| 8 | export function useLlmStreamService() { |
| 9 | return { |
| 10 | async chatStream( |
| 11 | messages: Array<{ role: string; content: string }>, |
| 12 | options?: { temperature?: number; maxTokens?: number }, |
| 13 | onChunk?: (chunk: LlmStreamChunk) => void |
| 14 | ): Promise<{ success: boolean; error?: string }> { |
| 15 | let streamError: string | undefined |
| 16 | try { |
| 17 | await fetchSSE({ |
| 18 | url: '/_web/ai/llm/chat-stream', |
| 19 | body: { messages, options }, |
| 20 | onEvent: ({ data }) => { |
| 21 | try { |
| 22 | const parsed = JSON.parse(data) as LlmStreamChunk |
| 23 | if (parsed.finishReason === 'error' && parsed.error) { |
| 24 | streamError = parsed.error |
| 25 | } |
| 26 | onChunk?.(parsed) |
| 27 | } catch { |
| 28 | // skip malformed JSON |
| 29 | } |
| 30 | }, |
| 31 | }) |
| 32 | if (streamError) return { success: false, error: streamError } |
| 33 | return { success: true } |
| 34 | } catch (error) { |
| 35 | const msg = error instanceof Error ? error.message : String(error) |
| 36 | return { success: false, error: streamError ?? msg } |
| 37 | } |
| 38 | }, |
| 39 | } |
| 40 | } |
| 41 | |