@tashiscool/vue 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +170 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/useStreaming.d.ts +141 -0
- package/dist/useStreaming.d.ts.map +1 -0
- package/dist/useStreaming.js +306 -0
- package/dist/useStreaming.js.map +1 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# @llm-utils/vue
|
|
2
|
+
|
|
3
|
+
Vue 3 composables for LLM streaming. Reactive state management for chat interfaces.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @llm-utils/vue
|
|
9
|
+
# or
|
|
10
|
+
npm install @llm-utils/vue
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **useStreaming** - Full streaming state management
|
|
16
|
+
- **useChunkBuffer** - Aggregate streaming chunks
|
|
17
|
+
- **useTypingIndicator** - Typing indicator state
|
|
18
|
+
- **useMessageHistory** - Persistent message history
|
|
19
|
+
- **SSE Support** - Parse Server-Sent Events
|
|
20
|
+
- **TypeScript** - Full type safety
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
### Basic Streaming
|
|
25
|
+
|
|
26
|
+
```vue
|
|
27
|
+
<script setup lang="ts">
|
|
28
|
+
import { useStreaming } from '@llm-utils/vue';
|
|
29
|
+
|
|
30
|
+
const { messages, status, send, isStreaming, abort } = useStreaming({
|
|
31
|
+
endpoint: '/api/chat',
|
|
32
|
+
onChunk: (chunk) => console.log('Received:', chunk),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
async function handleSend(input: string) {
|
|
36
|
+
await send(input);
|
|
37
|
+
}
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<template>
|
|
41
|
+
<div>
|
|
42
|
+
<div v-for="msg in messages" :key="msg.id">
|
|
43
|
+
<strong>{{ msg.role }}:</strong>
|
|
44
|
+
<span>{{ msg.content }}</span>
|
|
45
|
+
<span v-if="msg.isStreaming">▌</span>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<div v-if="status === 'connecting'">Connecting...</div>
|
|
49
|
+
|
|
50
|
+
<button @click="abort" v-if="isStreaming">Stop</button>
|
|
51
|
+
</div>
|
|
52
|
+
</template>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Stream from URL
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
const { streamFrom, messages } = useStreaming();
|
|
59
|
+
|
|
60
|
+
// Stream from any URL
|
|
61
|
+
await streamFrom('/api/stream', {
|
|
62
|
+
method: 'POST',
|
|
63
|
+
body: JSON.stringify({ prompt: 'Hello' }),
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Chunk Buffer
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { useChunkBuffer } from '@llm-utils/vue';
|
|
71
|
+
|
|
72
|
+
const { content, append, flush } = useChunkBuffer();
|
|
73
|
+
|
|
74
|
+
// Append chunks
|
|
75
|
+
append('Hello ');
|
|
76
|
+
append('World');
|
|
77
|
+
|
|
78
|
+
console.log(content.value); // 'Hello World'
|
|
79
|
+
console.log(flush()); // 'Hello World' (also clears)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Typing Indicator
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { useTypingIndicator } from '@llm-utils/vue';
|
|
86
|
+
|
|
87
|
+
const { isTyping, start, stop, startWithTimeout } = useTypingIndicator();
|
|
88
|
+
|
|
89
|
+
// Manual control
|
|
90
|
+
start();
|
|
91
|
+
// ... do work
|
|
92
|
+
stop();
|
|
93
|
+
|
|
94
|
+
// Auto-stop after 3 seconds
|
|
95
|
+
startWithTimeout(3000);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Message History with Persistence
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { useMessageHistory } from '@llm-utils/vue';
|
|
102
|
+
|
|
103
|
+
const { messages, add, remove, clear } = useMessageHistory({
|
|
104
|
+
storageKey: 'my-chat-history',
|
|
105
|
+
maxMessages: 50,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Add message
|
|
109
|
+
add({
|
|
110
|
+
role: 'user',
|
|
111
|
+
content: 'Hello!',
|
|
112
|
+
isStreaming: false,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Messages persist across page reloads
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## API Reference
|
|
119
|
+
|
|
120
|
+
### useStreaming
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
interface UseStreamingReturn {
|
|
124
|
+
// State
|
|
125
|
+
status: Ref<StreamingStatus>;
|
|
126
|
+
messages: Ref<StreamingMessage[]>;
|
|
127
|
+
currentMessage: ComputedRef<StreamingMessage | null>;
|
|
128
|
+
isStreaming: ComputedRef<boolean>;
|
|
129
|
+
error: Ref<Error | null>;
|
|
130
|
+
|
|
131
|
+
// Actions
|
|
132
|
+
send: (content: string, options?) => Promise<void>;
|
|
133
|
+
streamFrom: (url: string, options?) => Promise<void>;
|
|
134
|
+
abort: () => void;
|
|
135
|
+
clear: () => void;
|
|
136
|
+
addMessage: (message) => void;
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### StreamingMessage
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
interface StreamingMessage {
|
|
144
|
+
id: string;
|
|
145
|
+
role: 'user' | 'assistant' | 'system';
|
|
146
|
+
content: string;
|
|
147
|
+
isStreaming: boolean;
|
|
148
|
+
error?: string;
|
|
149
|
+
startedAt: Date;
|
|
150
|
+
completedAt?: Date;
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### StreamingOptions
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
interface StreamingOptions {
|
|
158
|
+
endpoint?: string;
|
|
159
|
+
headers?: Record<string, string>;
|
|
160
|
+
transformChunk?: (chunk: string) => string;
|
|
161
|
+
onStart?: (message: StreamingMessage) => void;
|
|
162
|
+
onChunk?: (chunk: string, message: StreamingMessage) => void;
|
|
163
|
+
onComplete?: (message: StreamingMessage) => void;
|
|
164
|
+
onError?: (error: Error) => void;
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## License
|
|
169
|
+
|
|
170
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @llm-utils/vue
|
|
3
|
+
* Vue 3 composables for LLM streaming
|
|
4
|
+
*/
|
|
5
|
+
export { useStreaming, useChunkBuffer, useTypingIndicator, useMessageHistory, } from './useStreaming.js';
|
|
6
|
+
export type { StreamingStatus, StreamingMessage, StreamingOptions, StreamingState, StreamingActions, UseStreamingReturn, UseChunkBufferReturn, UseTypingIndicatorReturn, UseMessageHistoryOptions, UseMessageHistoryReturn, } from './useStreaming.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vue Streaming Composables
|
|
3
|
+
* Reactive state management for LLM streaming
|
|
4
|
+
*/
|
|
5
|
+
import { type Ref, type ComputedRef } from 'vue';
|
|
6
|
+
/**
|
|
7
|
+
* Streaming status
|
|
8
|
+
*/
|
|
9
|
+
export type StreamingStatus = 'idle' | 'connecting' | 'streaming' | 'complete' | 'error';
|
|
10
|
+
/**
|
|
11
|
+
* Streaming message
|
|
12
|
+
*/
|
|
13
|
+
export interface StreamingMessage {
|
|
14
|
+
/** Unique message ID */
|
|
15
|
+
id: string;
|
|
16
|
+
/** Message role */
|
|
17
|
+
role: 'user' | 'assistant' | 'system';
|
|
18
|
+
/** Current content (incrementally updated) */
|
|
19
|
+
content: string;
|
|
20
|
+
/** Is message still streaming */
|
|
21
|
+
isStreaming: boolean;
|
|
22
|
+
/** Error if any */
|
|
23
|
+
error?: string;
|
|
24
|
+
/** Timestamp when started */
|
|
25
|
+
startedAt: Date;
|
|
26
|
+
/** Timestamp when completed */
|
|
27
|
+
completedAt?: Date;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Streaming options
|
|
31
|
+
*/
|
|
32
|
+
export interface StreamingOptions {
|
|
33
|
+
/** API endpoint */
|
|
34
|
+
endpoint?: string;
|
|
35
|
+
/** Request headers */
|
|
36
|
+
headers?: Record<string, string>;
|
|
37
|
+
/** Transform response chunks */
|
|
38
|
+
transformChunk?: (chunk: string) => string;
|
|
39
|
+
/** On message start */
|
|
40
|
+
onStart?: (message: StreamingMessage) => void;
|
|
41
|
+
/** On chunk received */
|
|
42
|
+
onChunk?: (chunk: string, message: StreamingMessage) => void;
|
|
43
|
+
/** On message complete */
|
|
44
|
+
onComplete?: (message: StreamingMessage) => void;
|
|
45
|
+
/** On error */
|
|
46
|
+
onError?: (error: Error) => void;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Streaming state
|
|
50
|
+
*/
|
|
51
|
+
export interface StreamingState {
|
|
52
|
+
/** Current status */
|
|
53
|
+
status: Ref<StreamingStatus>;
|
|
54
|
+
/** All messages */
|
|
55
|
+
messages: Ref<StreamingMessage[]>;
|
|
56
|
+
/** Current streaming message */
|
|
57
|
+
currentMessage: ComputedRef<StreamingMessage | null>;
|
|
58
|
+
/** Is currently streaming */
|
|
59
|
+
isStreaming: ComputedRef<boolean>;
|
|
60
|
+
/** Latest error */
|
|
61
|
+
error: Ref<Error | null>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Streaming actions
|
|
65
|
+
*/
|
|
66
|
+
export interface StreamingActions {
|
|
67
|
+
/** Send a message and stream response */
|
|
68
|
+
send: (content: string, options?: Partial<StreamingOptions>) => Promise<void>;
|
|
69
|
+
/** Stream from a URL */
|
|
70
|
+
streamFrom: (url: string, options?: RequestInit) => Promise<void>;
|
|
71
|
+
/** Abort current stream */
|
|
72
|
+
abort: () => void;
|
|
73
|
+
/** Clear all messages */
|
|
74
|
+
clear: () => void;
|
|
75
|
+
/** Add a message manually */
|
|
76
|
+
addMessage: (message: Omit<StreamingMessage, 'id' | 'startedAt'>) => void;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Use streaming composable return type
|
|
80
|
+
*/
|
|
81
|
+
export interface UseStreamingReturn extends StreamingState, StreamingActions {
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Vue composable for LLM streaming
|
|
85
|
+
*/
|
|
86
|
+
export declare function useStreaming(defaultOptions?: StreamingOptions): UseStreamingReturn;
|
|
87
|
+
/**
|
|
88
|
+
* Chunk buffer composable for aggregating streaming chunks
|
|
89
|
+
*/
|
|
90
|
+
export interface UseChunkBufferReturn {
|
|
91
|
+
/** Current buffered content */
|
|
92
|
+
content: Ref<string>;
|
|
93
|
+
/** Append a chunk */
|
|
94
|
+
append: (chunk: string) => void;
|
|
95
|
+
/** Clear buffer */
|
|
96
|
+
clear: () => void;
|
|
97
|
+
/** Get content and clear */
|
|
98
|
+
flush: () => string;
|
|
99
|
+
}
|
|
100
|
+
export declare function useChunkBuffer(): UseChunkBufferReturn;
|
|
101
|
+
/**
|
|
102
|
+
* Typing indicator composable
|
|
103
|
+
*/
|
|
104
|
+
export interface UseTypingIndicatorReturn {
|
|
105
|
+
/** Is typing */
|
|
106
|
+
isTyping: Ref<boolean>;
|
|
107
|
+
/** Start typing */
|
|
108
|
+
start: () => void;
|
|
109
|
+
/** Stop typing */
|
|
110
|
+
stop: () => void;
|
|
111
|
+
/** Auto-stop after delay */
|
|
112
|
+
startWithTimeout: (ms: number) => void;
|
|
113
|
+
}
|
|
114
|
+
export declare function useTypingIndicator(): UseTypingIndicatorReturn;
|
|
115
|
+
/**
|
|
116
|
+
* Message history composable with persistence
|
|
117
|
+
*/
|
|
118
|
+
export interface UseMessageHistoryOptions {
|
|
119
|
+
/** Storage key */
|
|
120
|
+
storageKey?: string;
|
|
121
|
+
/** Max messages to keep */
|
|
122
|
+
maxMessages?: number;
|
|
123
|
+
/** Use session storage instead of local */
|
|
124
|
+
sessionStorage?: boolean;
|
|
125
|
+
}
|
|
126
|
+
export interface UseMessageHistoryReturn {
|
|
127
|
+
/** Messages */
|
|
128
|
+
messages: Ref<StreamingMessage[]>;
|
|
129
|
+
/** Add message */
|
|
130
|
+
add: (message: Omit<StreamingMessage, 'id' | 'startedAt'>) => void;
|
|
131
|
+
/** Remove message */
|
|
132
|
+
remove: (id: string) => void;
|
|
133
|
+
/** Clear all */
|
|
134
|
+
clear: () => void;
|
|
135
|
+
/** Load from storage */
|
|
136
|
+
load: () => void;
|
|
137
|
+
/** Save to storage */
|
|
138
|
+
save: () => void;
|
|
139
|
+
}
|
|
140
|
+
export declare function useMessageHistory(options?: UseMessageHistoryOptions): UseMessageHistoryReturn;
|
|
141
|
+
//# sourceMappingURL=useStreaming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStreaming.d.ts","sourceRoot":"","sources":["../src/useStreaming.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vue Streaming Composables
|
|
3
|
+
* Reactive state management for LLM streaming
|
|
4
|
+
*/
|
|
5
|
+
import { ref, computed } from 'vue';
|
|
6
|
+
/**
|
|
7
|
+
* Generate message ID
|
|
8
|
+
*/
|
|
9
|
+
function generateId() {
|
|
10
|
+
return `msg_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Vue composable for LLM streaming
|
|
14
|
+
*/
|
|
15
|
+
export function useStreaming(defaultOptions = {}) {
|
|
16
|
+
// State
|
|
17
|
+
const status = ref('idle');
|
|
18
|
+
const messages = ref([]);
|
|
19
|
+
const error = ref(null);
|
|
20
|
+
let abortController = null;
|
|
21
|
+
// Computed
|
|
22
|
+
const currentMessage = computed(() => {
|
|
23
|
+
const streaming = messages.value.filter((m) => m.isStreaming);
|
|
24
|
+
return streaming.length > 0 ? streaming[streaming.length - 1] ?? null : null;
|
|
25
|
+
});
|
|
26
|
+
const isStreaming = computed(() => status.value === 'streaming');
|
|
27
|
+
/**
|
|
28
|
+
* Parse SSE data
|
|
29
|
+
*/
|
|
30
|
+
function parseSSE(line) {
|
|
31
|
+
if (line.startsWith('data: ')) {
|
|
32
|
+
const data = line.slice(6);
|
|
33
|
+
if (data === '[DONE]')
|
|
34
|
+
return null;
|
|
35
|
+
try {
|
|
36
|
+
const parsed = JSON.parse(data);
|
|
37
|
+
// Handle various response formats
|
|
38
|
+
return (parsed.content ||
|
|
39
|
+
parsed.delta?.content ||
|
|
40
|
+
parsed.choices?.[0]?.delta?.content ||
|
|
41
|
+
parsed.text ||
|
|
42
|
+
'');
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return data;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Stream from a URL
|
|
52
|
+
*/
|
|
53
|
+
async function streamFrom(url, options = {}) {
|
|
54
|
+
abortController = new AbortController();
|
|
55
|
+
status.value = 'connecting';
|
|
56
|
+
error.value = null;
|
|
57
|
+
const message = {
|
|
58
|
+
id: generateId(),
|
|
59
|
+
role: 'assistant',
|
|
60
|
+
content: '',
|
|
61
|
+
isStreaming: true,
|
|
62
|
+
startedAt: new Date(),
|
|
63
|
+
};
|
|
64
|
+
messages.value.push(message);
|
|
65
|
+
defaultOptions.onStart?.(message);
|
|
66
|
+
try {
|
|
67
|
+
const response = await fetch(url, {
|
|
68
|
+
...options,
|
|
69
|
+
signal: abortController.signal,
|
|
70
|
+
headers: {
|
|
71
|
+
...defaultOptions.headers,
|
|
72
|
+
...options.headers,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
if (!response.ok) {
|
|
76
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
77
|
+
}
|
|
78
|
+
if (!response.body) {
|
|
79
|
+
throw new Error('Response body is null');
|
|
80
|
+
}
|
|
81
|
+
status.value = 'streaming';
|
|
82
|
+
const reader = response.body.getReader();
|
|
83
|
+
const decoder = new TextDecoder();
|
|
84
|
+
let buffer = '';
|
|
85
|
+
while (true) {
|
|
86
|
+
const { done, value } = await reader.read();
|
|
87
|
+
if (done)
|
|
88
|
+
break;
|
|
89
|
+
buffer += decoder.decode(value, { stream: true });
|
|
90
|
+
const lines = buffer.split('\n');
|
|
91
|
+
buffer = lines.pop() || '';
|
|
92
|
+
for (const line of lines) {
|
|
93
|
+
const trimmed = line.trim();
|
|
94
|
+
if (!trimmed)
|
|
95
|
+
continue;
|
|
96
|
+
let chunk = parseSSE(trimmed);
|
|
97
|
+
if (chunk === null)
|
|
98
|
+
continue;
|
|
99
|
+
if (defaultOptions.transformChunk) {
|
|
100
|
+
chunk = defaultOptions.transformChunk(chunk);
|
|
101
|
+
}
|
|
102
|
+
// Update message content
|
|
103
|
+
const msgIndex = messages.value.findIndex((m) => m.id === message.id);
|
|
104
|
+
if (msgIndex !== -1 && messages.value[msgIndex]) {
|
|
105
|
+
messages.value[msgIndex].content += chunk;
|
|
106
|
+
defaultOptions.onChunk?.(chunk, messages.value[msgIndex]);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Complete message
|
|
111
|
+
const msgIndex = messages.value.findIndex((m) => m.id === message.id);
|
|
112
|
+
if (msgIndex !== -1 && messages.value[msgIndex]) {
|
|
113
|
+
messages.value[msgIndex].isStreaming = false;
|
|
114
|
+
messages.value[msgIndex].completedAt = new Date();
|
|
115
|
+
defaultOptions.onComplete?.(messages.value[msgIndex]);
|
|
116
|
+
}
|
|
117
|
+
status.value = 'complete';
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
if (err.name === 'AbortError') {
|
|
121
|
+
status.value = 'idle';
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
125
|
+
error.value = errorObj;
|
|
126
|
+
status.value = 'error';
|
|
127
|
+
// Mark message as error
|
|
128
|
+
const msgIndex = messages.value.findIndex((m) => m.id === message.id);
|
|
129
|
+
if (msgIndex !== -1 && messages.value[msgIndex]) {
|
|
130
|
+
messages.value[msgIndex].isStreaming = false;
|
|
131
|
+
messages.value[msgIndex].error = errorObj.message;
|
|
132
|
+
}
|
|
133
|
+
defaultOptions.onError?.(errorObj);
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
abortController = null;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Send a message and stream response
|
|
141
|
+
*/
|
|
142
|
+
async function send(content, options = {}) {
|
|
143
|
+
const endpoint = options.endpoint || defaultOptions.endpoint;
|
|
144
|
+
if (!endpoint) {
|
|
145
|
+
throw new Error('No endpoint configured');
|
|
146
|
+
}
|
|
147
|
+
// Add user message
|
|
148
|
+
messages.value.push({
|
|
149
|
+
id: generateId(),
|
|
150
|
+
role: 'user',
|
|
151
|
+
content,
|
|
152
|
+
isStreaming: false,
|
|
153
|
+
startedAt: new Date(),
|
|
154
|
+
completedAt: new Date(),
|
|
155
|
+
});
|
|
156
|
+
// Stream response
|
|
157
|
+
await streamFrom(endpoint, {
|
|
158
|
+
method: 'POST',
|
|
159
|
+
headers: {
|
|
160
|
+
'Content-Type': 'application/json',
|
|
161
|
+
...defaultOptions.headers,
|
|
162
|
+
...options.headers,
|
|
163
|
+
},
|
|
164
|
+
body: JSON.stringify({
|
|
165
|
+
messages: messages.value.map((m) => ({
|
|
166
|
+
role: m.role,
|
|
167
|
+
content: m.content,
|
|
168
|
+
})),
|
|
169
|
+
}),
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Abort current stream
|
|
174
|
+
*/
|
|
175
|
+
function abort() {
|
|
176
|
+
abortController?.abort();
|
|
177
|
+
status.value = 'idle';
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Clear all messages
|
|
181
|
+
*/
|
|
182
|
+
function clear() {
|
|
183
|
+
messages.value = [];
|
|
184
|
+
status.value = 'idle';
|
|
185
|
+
error.value = null;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Add message manually
|
|
189
|
+
*/
|
|
190
|
+
function addMessage(msg) {
|
|
191
|
+
messages.value.push({
|
|
192
|
+
...msg,
|
|
193
|
+
id: generateId(),
|
|
194
|
+
startedAt: new Date(),
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
// State
|
|
199
|
+
status,
|
|
200
|
+
messages,
|
|
201
|
+
currentMessage,
|
|
202
|
+
isStreaming,
|
|
203
|
+
error,
|
|
204
|
+
// Actions
|
|
205
|
+
send,
|
|
206
|
+
streamFrom,
|
|
207
|
+
abort,
|
|
208
|
+
clear,
|
|
209
|
+
addMessage,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
export function useChunkBuffer() {
|
|
213
|
+
const content = ref('');
|
|
214
|
+
function append(chunk) {
|
|
215
|
+
content.value += chunk;
|
|
216
|
+
}
|
|
217
|
+
function clear() {
|
|
218
|
+
content.value = '';
|
|
219
|
+
}
|
|
220
|
+
function flush() {
|
|
221
|
+
const result = content.value;
|
|
222
|
+
content.value = '';
|
|
223
|
+
return result;
|
|
224
|
+
}
|
|
225
|
+
return { content, append, clear, flush };
|
|
226
|
+
}
|
|
227
|
+
export function useTypingIndicator() {
|
|
228
|
+
const isTyping = ref(false);
|
|
229
|
+
let timeoutId = null;
|
|
230
|
+
function start() {
|
|
231
|
+
isTyping.value = true;
|
|
232
|
+
}
|
|
233
|
+
function stop() {
|
|
234
|
+
isTyping.value = false;
|
|
235
|
+
if (timeoutId) {
|
|
236
|
+
clearTimeout(timeoutId);
|
|
237
|
+
timeoutId = null;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
function startWithTimeout(ms) {
|
|
241
|
+
start();
|
|
242
|
+
timeoutId = setTimeout(stop, ms);
|
|
243
|
+
}
|
|
244
|
+
return { isTyping, start, stop, startWithTimeout };
|
|
245
|
+
}
|
|
246
|
+
export function useMessageHistory(options = {}) {
|
|
247
|
+
const { storageKey = 'llm-utils-messages', maxMessages = 100, sessionStorage: useSession = false, } = options;
|
|
248
|
+
const messages = ref([]);
|
|
249
|
+
const storage = typeof window !== 'undefined'
|
|
250
|
+
? useSession
|
|
251
|
+
? window.sessionStorage
|
|
252
|
+
: window.localStorage
|
|
253
|
+
: null;
|
|
254
|
+
function add(msg) {
|
|
255
|
+
messages.value.push({
|
|
256
|
+
...msg,
|
|
257
|
+
id: generateId(),
|
|
258
|
+
startedAt: new Date(),
|
|
259
|
+
});
|
|
260
|
+
// Trim if needed
|
|
261
|
+
if (messages.value.length > maxMessages) {
|
|
262
|
+
messages.value = messages.value.slice(-maxMessages);
|
|
263
|
+
}
|
|
264
|
+
save();
|
|
265
|
+
}
|
|
266
|
+
function remove(id) {
|
|
267
|
+
messages.value = messages.value.filter((m) => m.id !== id);
|
|
268
|
+
save();
|
|
269
|
+
}
|
|
270
|
+
function clear() {
|
|
271
|
+
messages.value = [];
|
|
272
|
+
save();
|
|
273
|
+
}
|
|
274
|
+
function load() {
|
|
275
|
+
if (!storage)
|
|
276
|
+
return;
|
|
277
|
+
try {
|
|
278
|
+
const stored = storage.getItem(storageKey);
|
|
279
|
+
if (stored) {
|
|
280
|
+
const parsed = JSON.parse(stored);
|
|
281
|
+
messages.value = parsed.map((m) => ({
|
|
282
|
+
...m,
|
|
283
|
+
startedAt: new Date(m.startedAt),
|
|
284
|
+
completedAt: m.completedAt ? new Date(m.completedAt) : undefined,
|
|
285
|
+
}));
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
// Ignore parse errors
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function save() {
|
|
293
|
+
if (!storage)
|
|
294
|
+
return;
|
|
295
|
+
try {
|
|
296
|
+
storage.setItem(storageKey, JSON.stringify(messages.value));
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
// Ignore storage errors
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
// Auto-load on init
|
|
303
|
+
load();
|
|
304
|
+
return { messages, add, remove, clear, load, save };
|
|
305
|
+
}
|
|
306
|
+
//# sourceMappingURL=useStreaming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStreaming.js","sourceRoot":"","sources":["../src/useStreaming.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tashiscool/vue",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Vue 3 composables for LLM streaming",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"test": "vitest run",
|
|
20
|
+
"test:watch": "vitest"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"llm",
|
|
24
|
+
"ai",
|
|
25
|
+
"vue",
|
|
26
|
+
"vue3",
|
|
27
|
+
"composables",
|
|
28
|
+
"streaming",
|
|
29
|
+
"reactive"
|
|
30
|
+
],
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"vue": "^3.3.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"typescript": "^5.4.0",
|
|
37
|
+
"vitest": "^1.6.0",
|
|
38
|
+
"vue": "^3.4.0"
|
|
39
|
+
},
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "https://github.com/tashiscool/llm-utils.git",
|
|
43
|
+
"directory": "packages/vue"
|
|
44
|
+
}
|
|
45
|
+
}
|