/** * Shared decoder for the `decision_resolved` leading frame the * `confirm-tool` route emits as the first chunk of its SSE response. * * Wire format (matches `use-embedded-chat.ts:270-394`): * - Frames are JSON objects separated by `\0` (NUL). * - `\x1E` (record separator) marks the transition from leading * metadata frames into the text body (chat path). * - For the tickets-UI path, the request body carries `messages: []` * which makes phase-2 (text body) structurally unreachable — * `confirm-tool/route.ts:569` skips the `runDocsChat` call. So the * stream contains exactly ONE frame (`decision_resolved`) followed * by EOF. * * This helper drains the stream defensively (reads all remaining bytes * after the leading frame so the server-side `composed.start()` doesn't * hang on a half-closed connection) and returns the first decoded * `decision_resolved` frame. Throws on: * - Empty body * - First frame is not `decision_resolved` * - Malformed JSON before the first `\0` * * Migration note: `use-embedded-chat.ts` still inlines the full decoder * including phase-2 text + trailing usage parsing. A future refactor * could move the leading-frame loop here and have the chat shell * compose with that — out of scope for this PR. */ export interface DecisionResolvedFrame { kind: 'decision_resolved'; ok: boolean; action: 'approved' | 'rejected'; toolName?: string; willAutoContinue?: boolean; proposalId?: string; /** Approve-path result envelope. `mirror_synced=false` means the * HubSpot REST call succeeded but the local mirror upsert lagged — * callers should optimistic-render and schedule a delayed refetch. */ result?: { ticket_id?: string; status?: string | null; mirror_synced?: boolean; } | null; receiptText?: string; } /** * Read the leading `decision_resolved` frame from a confirm-tool SSE * response. Drains the stream to end-of-file before resolving so the * server doesn't sit on a half-closed socket. * * @throws {Error} when the body is empty, the first frame is not * `decision_resolved`, or the leading JSON is malformed. */ export declare function readLeadingDecisionFrame(response: Response): Promise; //# sourceMappingURL=sse-decision-frame.d.ts.map