/** * OpenAI-chat delta assembly, done once and correctly (WS5.1). * * Fed the {@link SseEvent}s of an OpenAI Chat Completions stream, this rebuilds * a single turn: content and reasoning text, tool calls (fragmented arguments * merged by `index`, falling back to `id`, with id/index-less fragments * appended to the last open call), the finish reason, and the top-level `usage` * and opaque top-level extensions. It replaces several ad-hoc assemblers that * dropped parallel tool calls, mis-attributed argument fragments, or silently * swallowed malformed JSON. */ import type { Reasoning, ToolCall, Usage } from "@velum-labs/routekit-contracts/protocol-ir"; import { type ResponsesReasoningState } from "../adapters/openai-chat-wire.js"; import { type SseEvent } from "./parse.js"; export type AssembledTurn = { content: string; reasoning: string; reasoningDetails: Reasoning[]; responsesReasoning?: ResponsesReasoningState; toolCalls: ToolCall[]; finishReason?: string; usage?: Usage; extensions: Readonly>; }; export declare class ChatStreamAssembler { #private; /** * Merge one event. Empty `data` (keepalive) is ignored; the `[DONE]` sentinel * marks stream end (it does not, on its own, clear truncation). Malformed JSON * surfaces as {@link SseParseError} rather than being swallowed. */ push(event: SseEvent): void; /** * Merge an already-parsed chunk. Lets buffered-scan callers that decode + JSON * parse an event once (for both assembly and, say, provider-cost extraction) * reuse this assembler without a second parse. */ pushParsed(json: unknown): void; result(): AssembledTurn; /** True until a `finish_reason` is seen; a `[DONE]` without one stays truncated. */ get truncated(): boolean; }