@tashiscool/vue
v0.1.0
Published
Vue 3 composables for LLM streaming
Maintainers
Readme
@llm-utils/vue
Vue 3 composables for LLM streaming. Reactive state management for chat interfaces.
Installation
pnpm add @llm-utils/vue
# or
npm install @llm-utils/vueFeatures
- useStreaming - Full streaming state management
- useChunkBuffer - Aggregate streaming chunks
- useTypingIndicator - Typing indicator state
- useMessageHistory - Persistent message history
- SSE Support - Parse Server-Sent Events
- TypeScript - Full type safety
Usage
Basic Streaming
<script setup lang="ts">
import { useStreaming } from '@llm-utils/vue';
const { messages, status, send, isStreaming, abort } = useStreaming({
endpoint: '/api/chat',
onChunk: (chunk) => console.log('Received:', chunk),
});
async function handleSend(input: string) {
await send(input);
}
</script>
<template>
<div>
<div v-for="msg in messages" :key="msg.id">
<strong>{{ msg.role }}:</strong>
<span>{{ msg.content }}</span>
<span v-if="msg.isStreaming">▌</span>
</div>
<div v-if="status === 'connecting'">Connecting...</div>
<button @click="abort" v-if="isStreaming">Stop</button>
</div>
</template>Stream from URL
const { streamFrom, messages } = useStreaming();
// Stream from any URL
await streamFrom('/api/stream', {
method: 'POST',
body: JSON.stringify({ prompt: 'Hello' }),
});Chunk Buffer
import { useChunkBuffer } from '@llm-utils/vue';
const { content, append, flush } = useChunkBuffer();
// Append chunks
append('Hello ');
append('World');
console.log(content.value); // 'Hello World'
console.log(flush()); // 'Hello World' (also clears)Typing Indicator
import { useTypingIndicator } from '@llm-utils/vue';
const { isTyping, start, stop, startWithTimeout } = useTypingIndicator();
// Manual control
start();
// ... do work
stop();
// Auto-stop after 3 seconds
startWithTimeout(3000);Message History with Persistence
import { useMessageHistory } from '@llm-utils/vue';
const { messages, add, remove, clear } = useMessageHistory({
storageKey: 'my-chat-history',
maxMessages: 50,
});
// Add message
add({
role: 'user',
content: 'Hello!',
isStreaming: false,
});
// Messages persist across page reloadsAPI Reference
useStreaming
interface UseStreamingReturn {
// State
status: Ref<StreamingStatus>;
messages: Ref<StreamingMessage[]>;
currentMessage: ComputedRef<StreamingMessage | null>;
isStreaming: ComputedRef<boolean>;
error: Ref<Error | null>;
// Actions
send: (content: string, options?) => Promise<void>;
streamFrom: (url: string, options?) => Promise<void>;
abort: () => void;
clear: () => void;
addMessage: (message) => void;
}StreamingMessage
interface StreamingMessage {
id: string;
role: 'user' | 'assistant' | 'system';
content: string;
isStreaming: boolean;
error?: string;
startedAt: Date;
completedAt?: Date;
}StreamingOptions
interface StreamingOptions {
endpoint?: string;
headers?: Record<string, string>;
transformChunk?: (chunk: string) => string;
onStart?: (message: StreamingMessage) => void;
onChunk?: (chunk: string, message: StreamingMessage) => void;
onComplete?: (message: StreamingMessage) => void;
onError?: (error: Error) => void;
}License
MIT
