@standardagents/vue
v0.15.3
Published
Vue SDK for Standard Agents
Downloads
1,940
Readme
@standardagents/vue
Vue 3 composables and components for Standard Agents - connect to AI agent threads with real-time updates, send messages, manage files, and listen for custom events.
Installation
npm install @standardagents/vue
# or
pnpm add @standardagents/vue
# or
yarn add @standardagents/vueRequirements: Vue 3.3+
Quick Start
// main.ts
import { createApp } from 'vue'
import { StandardAgentsPlugin } from '@standardagents/vue'
import App from './App.vue'
const app = createApp(App)
app.use(StandardAgentsPlugin, { endpoint: 'https://api.example.com' })
app.mount('#app')<!-- App.vue -->
<script setup lang="ts">
import { ThreadProvider, useThread } from '@standardagents/vue'
</script>
<template>
<ThreadProvider threadId="thread-123">
<ChatInterface />
</ThreadProvider>
</template><!-- ChatInterface.vue -->
<script setup lang="ts">
import { ref } from 'vue'
import { useThread } from '@standardagents/vue'
const { messages, sendMessage, status } = useThread()
const input = ref('')
const handleSend = async () => {
await sendMessage({ role: 'user', content: input.value })
input.value = ''
}
</script>
<template>
<div>
<p>Status: {{ status }}</p>
<div v-for="msg in messages" :key="msg.id">
<strong>{{ msg.role }}:</strong> {{ msg.content }}
</div>
<input v-model="input" @keyup.enter="handleSend" />
<button @click="handleSend">Send</button>
</div>
</template>Authentication
The package reads the authentication token from localStorage using the key agentbuilder_auth_token:
// Set the token before using the composables
localStorage.setItem('agentbuilder_auth_token', 'your-token-here')All API requests and WebSocket connections will automatically include this token.
API Reference
StandardAgentsPlugin
Vue plugin that configures the Standard Agents client for all components.
Options:
endpoint: string- The API endpoint URL (required)
import { createApp } from 'vue'
import { StandardAgentsPlugin } from '@standardagents/vue'
const app = createApp(App)
app.use(StandardAgentsPlugin, { endpoint: 'https://api.example.com' })ThreadProvider
Component that establishes a WebSocket connection to a specific thread and provides context to child components.
Props:
threadId: string- The thread ID to connect topreload?: boolean- Fetch existing messages on mount (default:true)live?: boolean- Enable WebSocket for real-time updates (default:true)useWorkblocks?: boolean- Group tool calls into workblocks (default:false)depth?: number- Message depth level (default:0)includeSilent?: boolean- Include silent messages (default:false)endpoint?: string- Override the endpoint from plugin config
<template>
<ThreadProvider threadId="thread-123" :live="true">
<YourComponents />
</ThreadProvider>
</template>
<script setup lang="ts">
import { ThreadProvider } from '@standardagents/vue'
</script>useThread()
Composable to access the full thread context. Must be used within a ThreadProvider.
Returns:
threadId: string- The thread IDmessages: Ref<Message[]>- Reactive array of messagesworkblocks: ComputedRef<ThreadMessage[]>- Messages transformed to workblocks (ifuseWorkblocksis true)status: Ref<ConnectionStatus>- Connection status ("connecting"|"connected"|"disconnected"|"reconnecting")loading: Ref<boolean>- Loading state (alias:isLoading)error: Ref<Error | null>- Error stateoptions: ThreadProviderOptions- Options passed to the providersendMessage: (payload: SendMessagePayload) => Promise<Message>- Send a messagestopExecution: () => Promise<void>- Stop current executiononEvent: <T>(eventType, callback) => () => void- Subscribe to custom events (alias:subscribeToEvent)files: ComputedRef<ThreadFile[]>- All files (pending + committed)addFiles: (files: File[] | FileList) => void- Upload filesremoveFile: (id: string) => void- Remove a pending filegetFileUrl: (file: ThreadFile) => string- Get file URLgetThumbnailUrl: (file: ThreadFile) => string- Get thumbnail URLgetPreviewUrl: (file: ThreadFile) => string | null- Get preview URL
Example:
<script setup lang="ts">
import { useThread } from '@standardagents/vue'
const {
messages,
sendMessage,
stopExecution,
status,
isLoading,
files,
addFiles,
onEvent,
} = useThread()
// Subscribe to custom events
onEvent<{ todos: string[] }>('todo-updated', (data) => {
console.log('Todos:', data.todos)
})
</script>
<template>
<div>
<p v-if="isLoading">Loading...</p>
<p>Status: {{ status }}</p>
<div v-for="msg in messages" :key="msg.id">
<strong>{{ msg.role }}:</strong> {{ msg.content }}
</div>
<input type="file" multiple @change="(e) => addFiles(e.target.files)" />
<div v-for="file in files" :key="file.id">
{{ file.name }} ({{ file.status }})
</div>
<button @click="sendMessage({ role: 'user', content: 'Hello!' })">Send</button>
<button @click="stopExecution">Stop</button>
</div>
</template>File Management
The useThread() composable provides file management capabilities:
<script setup lang="ts">
import { useThread } from '@standardagents/vue'
const { files, addFiles, removeFile, getPreviewUrl } = useThread()
const handleFileChange = (event: Event) => {
const input = event.target as HTMLInputElement
if (input.files) {
addFiles(input.files)
}
}
</script>
<template>
<div>
<input type="file" multiple accept="image/*,.pdf,.txt" @change="handleFileChange" />
<div v-for="file in files" :key="file.id">
<img
v-if="file.isImage && file.status !== 'uploading'"
:src="getPreviewUrl(file) || ''"
:alt="file.name"
width="50"
/>
<span>{{ file.name }}</span>
<span>{{ file.status }}</span>
<span v-if="file.status === 'uploading'">Uploading...</span>
<span v-if="file.status === 'error'">Error: {{ file.error }}</span>
<button v-if="file.status !== 'committed'" @click="removeFile(file.id)">
Remove
</button>
</div>
</div>
</template>File States
uploading- File is being uploadedready- Upload complete, file ready to attach to messagecommitted- File is attached to a sent messageerror- Upload failed
Types
interface Message {
id: string
role: 'user' | 'assistant' | 'system' | 'tool'
content: string | null
created_at: number
attachments?: string // JSON array of AttachmentRef
}
interface SendMessagePayload {
role: 'user' | 'assistant' | 'system'
content: string
silent?: boolean
attachments?: string[] // Paths of files to attach
}
interface ThreadFile {
id: string
name: string
mimeType: string
size: number
isImage: boolean
status: 'uploading' | 'ready' | 'committed' | 'error'
error?: string
path?: string
localPreviewUrl: string | null
}
type ConnectionStatus = 'connecting' | 'connected' | 'disconnected' | 'reconnecting'Complete Example
<script setup lang="ts">
import { onMounted } from 'vue'
import { ThreadProvider } from '@standardagents/vue'
onMounted(() => {
localStorage.setItem('agentbuilder_auth_token', 'your-token')
})
</script>
<template>
<ThreadProvider threadId="thread-123">
<AgentChat />
</ThreadProvider>
</template><!-- AgentChat.vue -->
<script setup lang="ts">
import { ref } from 'vue'
import { useThread } from '@standardagents/vue'
const input = ref('')
const {
messages,
sendMessage,
stopExecution,
status,
isLoading,
files,
addFiles,
removeFile,
getPreviewUrl,
} = useThread()
const handleSend = async () => {
if (!input.value.trim()) return
await sendMessage({ role: 'user', content: input.value })
input.value = ''
}
const handleFileChange = (event: Event) => {
const target = event.target as HTMLInputElement
if (target.files) addFiles(target.files)
}
</script>
<template>
<div>
<p v-if="isLoading">Loading messages...</p>
<div v-for="msg in messages" :key="msg.id">
<strong>{{ msg.role }}:</strong> {{ msg.content }}
</div>
<input type="file" multiple @change="handleFileChange" />
<div v-for="file in files.filter(f => f.status !== 'committed')" :key="file.id">
<img
v-if="file.isImage && getPreviewUrl(file)"
:src="getPreviewUrl(file)!"
:alt="file.name"
width="50"
/>
<span>{{ file.name }} ({{ file.status }})</span>
<button @click="removeFile(file.id)">x</button>
</div>
<div>
<input v-model="input" @keyup.enter="handleSend" />
<button @click="handleSend">Send</button>
<button @click="stopExecution">Stop</button>
<span>Status: {{ status }}</span>
</div>
</div>
</template>TypeScript Support
The package includes full TypeScript definitions:
import type {
Message,
SendMessagePayload,
ThreadFile,
ConnectionStatus,
ThreadContext,
} from '@standardagents/vue'