initial_commit

This commit is contained in:
2026-06-01 20:16:53 +09:00
commit 903d34761c
31 changed files with 1123 additions and 0 deletions
+69
View File
@@ -0,0 +1,69 @@
export interface SessionInfo {
id: string
title: string
model: string
updated_at: string
}
export interface SSEChunk {
type: 'session_id' | 'chunk' | 'done'
value?: string
}
const BASE = ''
export async function fetchSessions(): Promise<SessionInfo[]> {
const res = await fetch(`${BASE}/chat/sessions`)
if (!res.ok) throw new Error('Failed to fetch sessions')
return res.json()
}
export async function deleteSession(sessionId: string): Promise<void> {
await fetch(`${BASE}/chat/sessions/${sessionId}`, { method: 'DELETE' })
}
export function streamChat(
message: string,
sessionId: string | null,
model: string,
onChunk: (chunk: SSEChunk) => void,
onError: (err: Error) => void,
): () => void {
const controller = new AbortController()
fetch(`${BASE}/chat/stream`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message, session_id: sessionId, model }),
signal: controller.signal,
})
.then(async (res) => {
if (!res.body) throw new Error('No response body')
const reader = res.body.getReader()
const decoder = new TextDecoder()
let buffer = ''
while (true) {
const { done, value } = await reader.read()
if (done) break
buffer += decoder.decode(value, { stream: true })
const lines = buffer.split('\n\n')
buffer = lines.pop() ?? ''
for (const line of lines) {
if (line.startsWith('data: ')) {
try {
const parsed: SSEChunk = JSON.parse(line.slice(6))
onChunk(parsed)
} catch {
// ignore malformed
}
}
}
}
})
.catch((err) => {
if (err.name !== 'AbortError') onError(err)
})
return () => controller.abort()
}