feat: task lane persistence + sidebar cleanup #121

Merged
chihlasm merged 49 commits from feat/task-lane-persistence into main 2026-03-29 16:59:41 +00:00
Showing only changes of commit bcab8158ab - Show all commits

View File

@@ -99,6 +99,69 @@ export const aiSessionsApi = {
return response.data
},
async streamDocumentation(
sessionId: string,
onChunk: (text: string) => void,
onDone: () => void,
onError: (error: string) => void,
): Promise<void> {
const token = localStorage.getItem('access_token')
const baseUrl = import.meta.env.VITE_API_URL || ''
try {
const response = await fetch(
`${baseUrl}/api/ai-sessions/${sessionId}/documentation/stream`,
{
headers: {
Authorization: `Bearer ${token}`,
},
},
)
if (!response.ok) {
onError(`HTTP ${response.status}`)
return
}
const reader = response.body?.getReader()
if (!reader) {
onError('No response body')
return
}
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')
buffer = lines.pop() || ''
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6)
if (data === '[DONE]') {
onDone()
return
}
if (data.startsWith('[ERROR]')) {
onError(data.slice(8))
return
}
onChunk(data)
}
}
}
// Stream ended without [DONE]
onDone()
} catch (err) {
onError(err instanceof Error ? err.message : 'Stream failed')
}
},
async rateSession(sessionId: string, data: { rating: number; feedback?: string }): Promise<void> {
await apiClient.post(`/ai-sessions/${sessionId}/rate`, data)
},