From e6721a0b72784461edfcfdbbb20c7af970826d14 Mon Sep 17 00:00:00 2001 From: mawkone Date: Wed, 10 Jun 2026 12:04:13 -0700 Subject: [PATCH] chore(telemetry): resolve loop crash caused by Temporal Dead Zone hoisting and fix conversational budget mapping --- vibn-frontend/app/api/chat/route.ts | 63 +++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/vibn-frontend/app/api/chat/route.ts b/vibn-frontend/app/api/chat/route.ts index f31f372..7750e26 100644 --- a/vibn-frontend/app/api/chat/route.ts +++ b/vibn-frontend/app/api/chat/route.ts @@ -830,6 +830,66 @@ export async function POST(request: Request) { function emit(chunk: object) { if (streamClosed) return; try { + if ( + "type" in chunk && + chunk.type !== "ping" && + chunk.type !== "turn_start" + ) { + if (chunk.type === "text" && "text" in chunk) { + assistantTimeline.push({ kind: "text", text: chunk.text }); + } else if (chunk.type === "thinking" && "text" in chunk) { + assistantTimeline.push({ kind: "thought", text: chunk.text }); + } else if (chunk.type === "tool_start" && "name" in chunk) { + assistantTimeline.push({ + kind: "tool", + name: chunk.name, + status: "running", + }); + } else if ( + chunk.type === "tool_result" && + "name" in chunk && + "result" in chunk + ) { + const lastRunning = [...assistantTimeline] + .reverse() + .find( + (t) => + t.kind === "tool" && + t.name === chunk.name && + t.status === "running", + ); + if (lastRunning) { + lastRunning.status = "done"; + lastRunning.result = chunk.result; + // Quick check if result indicates error + try { + const p = JSON.parse(chunk.result as string); + if (p && p.ok === false) lastRunning.status = "error"; + } catch {} + } + } else if ( + chunk.type === "phase" && + "phase" in chunk && + "label" in chunk + ) { + assistantTimeline.push({ + kind: "phase", + phase: chunk.phase, + label: chunk.label, + }); + } else if ( + chunk.type === "checkpoint" && + "goal" in chunk && + "findings" in chunk + ) { + assistantTimeline.push({ + kind: "checkpoint", + goal: chunk.goal, + findings: chunk.findings, + }); + } + } + controller.enqueue( encoder.encode(`data: ${JSON.stringify(chunk)}\n\n`), ); @@ -869,6 +929,7 @@ export async function POST(request: Request) { // restores the segmentation on reload. const assistantTextSegments: string[] = []; const assistantToolCalls: ToolCall[] = []; + const assistantTimeline: any[] = []; let aborted = clientSignal.aborted; const onAbort = () => { aborted = true; @@ -1339,6 +1400,7 @@ export async function POST(request: Request) { const finalMsg: ChatMessage & { textSegments?: string[]; + timeline?: any[]; _rawToolResults?: Array<{ name: string; args: Record; @@ -1356,6 +1418,7 @@ export async function POST(request: Request) { ), ) : undefined, + timeline: assistantTimeline.length ? assistantTimeline : undefined, _rawToolResults: assistantToolCalls.length ? [] : undefined, };