@langchain/langgraph-sdk 1.12.5 → 1.12.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/stream/messages.cjs +23 -2
- package/dist/client/stream/messages.cjs.map +1 -1
- package/dist/client/stream/messages.d.cts +6 -1
- package/dist/client/stream/messages.d.cts.map +1 -1
- package/dist/client/stream/messages.d.ts +6 -1
- package/dist/client/stream/messages.d.ts.map +1 -1
- package/dist/client/stream/messages.js +23 -2
- package/dist/client/stream/messages.js.map +1 -1
- package/dist/stream/controller.cjs +100 -4
- package/dist/stream/controller.cjs.map +1 -1
- package/dist/stream/controller.d.cts.map +1 -1
- package/dist/stream/controller.d.ts.map +1 -1
- package/dist/stream/controller.js +100 -4
- package/dist/stream/controller.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.js","names":["#events","#textPromise","#reasoningPromise","#resolveText","#resolveReasoning","#textChunks","#textWaiters","#textDone","#reasoningChunks","#reasoningWaiters","#reasoningDone","#usageIterator","#assembleMessage","#assembler","#activeStreaming"],"sources":["../../../src/client/stream/messages.ts"],"sourcesContent":["import {\n AIMessage,\n type ContentBlock as CoreContentBlock,\n type UsageMetadata,\n} from \"@langchain/core/messages\";\nimport type {\n ChatModelStreamEvent,\n ContentBlockDelta as CoreContentBlockDelta,\n} from \"@langchain/core/language_models/event\";\nimport type {\n ContentBlock,\n FinalizedContentBlock,\n MessageMetadata,\n MessagesEvent,\n UsageInfo,\n} from \"@langchain/protocol\";\n\nimport { MultiCursorBuffer } from \"./multi-cursor-buffer.js\";\n\ntype TextContentStream = AsyncIterable<string> &\n PromiseLike<string> & { full: AsyncIterable<string> };\n\ntype UsageMetadataStream = AsyncIterable<UsageMetadata> &\n PromiseLike<UsageMetadata | undefined>;\n\ntype ToolCallsStream = AsyncIterable<CoreContentBlock.Tools.ToolCall> &\n PromiseLike<Array<CoreContentBlock.Tools.ToolCall>> & {\n full: AsyncIterable<Array<CoreContentBlock.Tools.ToolCall>>;\n };\n\nfunction applyCoreContentDelta(\n target: CoreContentBlock,\n delta: CoreContentBlock\n): CoreContentBlock {\n if (target.type !== delta.type) {\n return structuredClone(delta);\n }\n\n switch (delta.type) {\n case \"text\":\n return {\n ...target,\n ...delta,\n text: `${\"text\" in target ? target.text : \"\"}${delta.text}`,\n } as CoreContentBlock;\n case \"reasoning\":\n return {\n ...target,\n ...delta,\n reasoning: `${\"reasoning\" in target ? target.reasoning : \"\"}${delta.reasoning}`,\n } as CoreContentBlock;\n case \"tool_call_chunk\":\n case \"server_tool_call_chunk\": {\n const merged = { ...target, ...delta } as Record<string, unknown>;\n if (delta.id == null && \"id\" in target && target.id != null) {\n merged.id = target.id;\n }\n if (delta.name == null && \"name\" in target && target.name != null) {\n merged.name = target.name;\n }\n merged.args = `${(\"args\" in target ? target.args : \"\") ?? \"\"}${delta.args ?? \"\"}`;\n return merged as unknown as CoreContentBlock;\n }\n default:\n return { ...target, ...delta } as CoreContentBlock;\n }\n}\n\nfunction coreContentBlockFromDelta(\n delta: CoreContentBlockDelta,\n current?: CoreContentBlock\n): CoreContentBlock {\n switch (delta.type) {\n case \"text-delta\":\n return { type: \"text\", text: delta.text } as CoreContentBlock;\n case \"reasoning-delta\":\n return {\n type: \"reasoning\",\n reasoning: delta.reasoning,\n } as CoreContentBlock;\n case \"data-delta\": {\n const merged = { ...(current ?? {}), data: delta.data } as Record<\n string,\n unknown\n >;\n if (delta.encoding) merged.encoding = delta.encoding;\n return merged as unknown as CoreContentBlock;\n }\n case \"block-delta\":\n return delta.fields as CoreContentBlock;\n }\n}\n\nfunction applyCoreEventDelta(\n current: CoreContentBlock | undefined,\n event: Extract<ChatModelStreamEvent, { event: \"content-block-delta\" }> & {\n content?: CoreContentBlock;\n }\n): CoreContentBlock {\n if (event.content) {\n return current\n ? applyCoreContentDelta(current, event.content)\n : event.content;\n }\n\n switch (event.delta.type) {\n case \"text-delta\":\n if (current?.type === \"text\") {\n return {\n ...current,\n text: `${\"text\" in current ? current.text : \"\"}${event.delta.text}`,\n } as CoreContentBlock;\n }\n return coreContentBlockFromDelta(event.delta, current);\n case \"reasoning-delta\":\n if (current?.type === \"reasoning\") {\n return {\n ...current,\n reasoning: `${\"reasoning\" in current ? current.reasoning : \"\"}${event.delta.reasoning}`,\n } as CoreContentBlock;\n }\n return coreContentBlockFromDelta(event.delta, current);\n case \"data-delta\": {\n const merged = { ...(current ?? {}) } as Record<string, unknown>;\n merged.data = `${(merged.data as string | undefined) ?? \"\"}${event.delta.data}`;\n if (event.delta.encoding) merged.encoding = event.delta.encoding;\n return merged as unknown as CoreContentBlock;\n }\n case \"block-delta\":\n return {\n ...(current ?? {}),\n ...event.delta.fields,\n } as CoreContentBlock;\n }\n}\n\nfunction normalizeUsage(\n usage: UsageInfo | Partial<UsageMetadata> | undefined\n): UsageMetadata | undefined {\n if (!usage) return undefined;\n return {\n ...usage,\n input_tokens: usage.input_tokens ?? 0,\n output_tokens: usage.output_tokens ?? 0,\n total_tokens: usage.total_tokens ?? 0,\n };\n}\n\nfunction readRunId(data: object): string | undefined {\n const record = data as Record<string, unknown>;\n return typeof record.run_id === \"string\" ? record.run_id : undefined;\n}\n\nfunction readUsage(data: object): UsageInfo | undefined {\n const usage = (data as Record<string, unknown>).usage;\n return usage != null && typeof usage === \"object\" && !Array.isArray(usage)\n ? (usage as UsageInfo)\n : undefined;\n}\n\nfunction readFinishMetadata(data: object): Record<string, unknown> | undefined {\n const record = data as Record<string, unknown>;\n const isRecord = (value: unknown): value is Record<string, unknown> =>\n value != null && typeof value === \"object\" && !Array.isArray(value);\n const merged = {\n ...(isRecord(record.responseMetadata) ? record.responseMetadata : {}),\n ...(isRecord(record.metadata) ? record.metadata : {}),\n };\n return Object.keys(merged).length > 0 ? merged : undefined;\n}\n\n/**\n * Mutable view of a streamed message as message and content-block events are\n * assembled into a single structure.\n */\nexport interface AssembledMessage {\n id: string;\n namespace: string[];\n blocks: ContentBlock[];\n node?: string;\n runId?: string;\n usage?: UsageInfo;\n metadata?: MessageMetadata;\n finishMetadata?: Record<string, any>;\n finishReason?: string;\n error?: {\n message: string;\n code?: string;\n };\n}\n\n/**\n * Symbol keys for assembler → StreamingMessage communication.\n * Module-private: invisible to external consumers, accessible to\n * {@link StreamingMessageAssembler} within this file.\n */\nconst PUSH_TEXT: unique symbol = Symbol(\"pushText\");\nconst PUSH_REASONING: unique symbol = Symbol(\"pushReasoning\");\nconst PUSH_EVENT: unique symbol = Symbol(\"pushEvent\");\nconst UPDATE_CONTEXT: unique symbol = Symbol(\"updateContext\");\nconst FINISH: unique symbol = Symbol(\"finish\");\nconst ERROR: unique symbol = Symbol(\"error\");\n\n/**\n * Live streaming view of a single message lifecycle, matching the\n * in-process `ChatModelStream` dual-interface pattern.\n *\n * - `text` / `reasoning`: iterate for streaming deltas, or await for\n * the full concatenated string after the message completes.\n * - `usage`: promise that resolves with token usage on message-finish.\n * - `blocks`: the assembled content blocks (updated as deltas arrive).\n *\n * Created by {@link StreamingMessageAssembler} and yielded by\n * the `session.messages` lazy getter.\n */\nexport class StreamingMessage\n implements AsyncIterable<ChatModelStreamEvent>, PromiseLike<AIMessage>\n{\n readonly id: string;\n readonly namespace: string[];\n node: string | undefined;\n readonly metadata: MessageMetadata | undefined;\n readonly assembled: AssembledMessage;\n readonly #events = new MultiCursorBuffer<ChatModelStreamEvent>();\n\n #textChunks: string[] = [];\n #reasoningChunks: string[] = [];\n #textWaiters: Array<() => void> = [];\n #reasoningWaiters: Array<() => void> = [];\n #textDone = false;\n #reasoningDone = false;\n\n #resolveText!: (v: string) => void;\n #resolveReasoning!: (v: string) => void;\n readonly #textPromise: Promise<string>;\n readonly #reasoningPromise: Promise<string>;\n\n constructor(assembled: AssembledMessage) {\n this.id = assembled.id;\n this.assembled = assembled;\n this.namespace = assembled.namespace;\n this.node = assembled.node;\n this.metadata = assembled.metadata;\n this.#textPromise = new Promise<string>((r) => {\n this.#resolveText = r;\n });\n this.#reasoningPromise = new Promise<string>((r) => {\n this.#resolveReasoning = r;\n });\n }\n\n get text(): TextContentStream {\n const chunks = this.#textChunks;\n const waiters = this.#textWaiters;\n const getDone = () => this.#textDone;\n let cursor = 0;\n return {\n [Symbol.asyncIterator]() {\n return {\n async next(): Promise<IteratorResult<string>> {\n while (true) {\n if (cursor < chunks.length) {\n return { done: false, value: chunks[cursor++] };\n }\n if (getDone()) {\n return { done: true, value: undefined };\n }\n await new Promise<void>((resolve) => {\n waiters.push(resolve);\n });\n }\n },\n };\n },\n then: this.#textPromise.then.bind(this.#textPromise),\n full: {\n async *[Symbol.asyncIterator]() {\n let accumulated = \"\";\n for await (const chunk of {\n [Symbol.asyncIterator]: () =>\n ({\n next: async (): Promise<IteratorResult<string>> => {\n while (true) {\n if (cursor < chunks.length) {\n return { done: false, value: chunks[cursor++] };\n }\n if (getDone()) {\n return { done: true, value: undefined };\n }\n await new Promise<void>((resolve) => {\n waiters.push(resolve);\n });\n }\n },\n }) satisfies AsyncIterator<string>,\n }) {\n accumulated += chunk;\n yield accumulated;\n }\n },\n },\n };\n }\n\n get reasoning(): TextContentStream {\n const chunks = this.#reasoningChunks;\n const waiters = this.#reasoningWaiters;\n const getDone = () => this.#reasoningDone;\n let cursor = 0;\n return {\n [Symbol.asyncIterator]() {\n return {\n async next(): Promise<IteratorResult<string>> {\n while (true) {\n if (cursor < chunks.length) {\n return { done: false, value: chunks[cursor++] };\n }\n if (getDone()) {\n return { done: true, value: undefined };\n }\n await new Promise<void>((resolve) => {\n waiters.push(resolve);\n });\n }\n },\n };\n },\n then: this.#reasoningPromise.then.bind(this.#reasoningPromise),\n full: {\n async *[Symbol.asyncIterator]() {\n let accumulated = \"\";\n for await (const chunk of {\n [Symbol.asyncIterator]: () =>\n ({\n next: async (): Promise<IteratorResult<string>> => {\n while (true) {\n if (cursor < chunks.length) {\n return { done: false, value: chunks[cursor++] };\n }\n if (getDone()) {\n return { done: true, value: undefined };\n }\n await new Promise<void>((resolve) => {\n waiters.push(resolve);\n });\n }\n },\n }) satisfies AsyncIterator<string>,\n }) {\n accumulated += chunk;\n yield accumulated;\n }\n },\n },\n };\n }\n\n get usage(): UsageMetadataStream {\n const promise = (async () => {\n let usage: UsageMetadata | undefined;\n for await (const snapshot of this.#usageIterator()) {\n usage = snapshot;\n }\n return usage;\n })();\n return {\n [Symbol.asyncIterator]: () => this.#usageIterator(),\n then: promise.then.bind(promise),\n };\n }\n\n get toolCalls(): ToolCallsStream {\n const events = this.#events;\n const iterator = async function* () {\n for await (const event of events) {\n if (\n event.event === \"content-block-finish\" &&\n event.content.type === \"tool_call\"\n ) {\n yield event.content as CoreContentBlock.Tools.ToolCall;\n }\n }\n };\n return {\n [Symbol.asyncIterator]: iterator,\n then: async (onfulfilled, onrejected) => {\n try {\n const calls: CoreContentBlock.Tools.ToolCall[] = [];\n for await (const call of iterator()) calls.push(call);\n return onfulfilled ? onfulfilled(calls) : (calls as never);\n } catch (err) {\n if (onrejected) return onrejected(err);\n throw err;\n }\n },\n full: {\n async *[Symbol.asyncIterator]() {\n const calls: CoreContentBlock.Tools.ToolCall[] = [];\n for await (const call of iterator()) {\n calls.push(call);\n yield [...calls];\n }\n },\n },\n };\n }\n\n get output(): PromiseLike<AIMessage> {\n return { then: (onf, onr) => this.#assembleMessage().then(onf, onr) };\n }\n\n get blocks(): ContentBlock[] {\n return this.assembled.blocks;\n }\n\n [Symbol.asyncIterator](): AsyncIterator<ChatModelStreamEvent> {\n return this.#events[Symbol.asyncIterator]();\n }\n\n then<TResult1 = AIMessage, TResult2 = never>(\n onfulfilled?:\n | ((value: AIMessage) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n return this.#assembleMessage().then(onfulfilled, onrejected);\n }\n\n async *#usageIterator(): AsyncGenerator<UsageMetadata> {\n for await (const event of this.#events) {\n if (event.event === \"message-start\" && event.usage) {\n yield normalizeUsage(event.usage)!;\n } else if (event.event === \"message-finish\" && event.usage) {\n yield normalizeUsage(event.usage)!;\n }\n }\n }\n\n async #assembleMessage(): Promise<AIMessage> {\n const contentBlocks: Array<CoreContentBlock | undefined> = [];\n let id: string | undefined = this.id;\n let usage = normalizeUsage(this.assembled.usage);\n let metadata: Record<string, unknown> = {\n ...(this.assembled.finishMetadata ?? {}),\n };\n let finishReason: string | undefined = this.assembled.finishReason;\n\n for await (const event of this.#events) {\n switch (event.event) {\n case \"message-start\":\n id = event.id ?? id;\n if (event.usage) usage = normalizeUsage(event.usage);\n break;\n case \"content-block-start\":\n contentBlocks[event.index] = event.content;\n break;\n case \"content-block-delta\": {\n const current = contentBlocks[event.index];\n contentBlocks[event.index] = applyCoreEventDelta(current, event);\n break;\n }\n case \"content-block-finish\":\n contentBlocks[event.index] = event.content;\n break;\n case \"message-finish\": {\n finishReason = event.reason;\n if (event.usage) usage = normalizeUsage(event.usage);\n const finishMetadata = readFinishMetadata(event);\n if (finishMetadata != null) {\n metadata = { ...metadata, ...finishMetadata };\n }\n break;\n }\n default:\n break;\n }\n }\n\n return new AIMessage({\n id,\n content: contentBlocks.filter(\n (block): block is CoreContentBlock => block != null\n ),\n usage_metadata: usage,\n additional_kwargs: {\n namespace: this.namespace,\n ...(this.node != null ? { node: this.node } : {}),\n ...(this.assembled.runId != null\n ? { run_id: this.assembled.runId }\n : {}),\n ...(this.metadata != null ? { metadata: this.metadata } : {}),\n ...(this.assembled.usage != null\n ? { usage: this.assembled.usage }\n : {}),\n },\n response_metadata: {\n ...(finishReason != null ? { finish_reason: finishReason } : {}),\n ...metadata,\n output_version: \"v1\" as const,\n },\n });\n }\n\n [PUSH_EVENT](event: ChatModelStreamEvent): void {\n this.#events.push(event);\n }\n\n [UPDATE_CONTEXT](event: MessagesEvent): void {\n this.node = event.params.node ?? this.node;\n }\n\n [PUSH_TEXT](delta: string): void {\n this.#textChunks.push(delta);\n // Wake every caught-up iterator so each one advances its own cursor.\n // Iterators re-check `chunks.length` before delivering, which keeps\n // the cursor the single source of truth for what a consumer has seen.\n const pending = this.#textWaiters.splice(0, this.#textWaiters.length);\n for (const waiter of pending) waiter();\n }\n\n [PUSH_REASONING](delta: string): void {\n this.#reasoningChunks.push(delta);\n const pending = this.#reasoningWaiters.splice(\n 0,\n this.#reasoningWaiters.length\n );\n for (const waiter of pending) waiter();\n }\n\n [FINISH](): void {\n this.#textDone = true;\n this.#reasoningDone = true;\n this.#resolveText(this.#textChunks.join(\"\"));\n this.#resolveReasoning(this.#reasoningChunks.join(\"\"));\n const textPending = this.#textWaiters.splice(0, this.#textWaiters.length);\n for (const waiter of textPending) waiter();\n const reasoningPending = this.#reasoningWaiters.splice(\n 0,\n this.#reasoningWaiters.length\n );\n for (const waiter of reasoningPending) waiter();\n this.#events.close();\n }\n\n [ERROR](): void {\n this[FINISH]();\n }\n}\n\n/**\n * Public view yielded by message projections.\n *\n * `StreamingMessage` is PromiseLike so callers can still `await` a message\n * object directly, but TypeScript applies `Awaited<T>` to values produced by\n * `for await`. Exposing a non-thenable view keeps loop variables typed as the\n * streaming handle instead of as the finalized `AIMessage`.\n */\nexport type StreamingMessageHandle = Omit<StreamingMessage, \"then\">;\n\nexport function toStreamingMessageHandle(\n message: StreamingMessage\n): StreamingMessageHandle {\n return new Proxy(message, {\n get(target, prop) {\n if (prop === \"then\") return undefined;\n const value = Reflect.get(target, prop, target);\n return typeof value === \"function\" ? value.bind(target) : value;\n },\n has(target, prop) {\n if (prop === \"then\") return false;\n return prop in target;\n },\n }) as StreamingMessageHandle;\n}\n\n/**\n * Emitted by `MessageAssembler.consume()` to describe how a message changed in\n * response to a single protocol event.\n */\nexport type MessageAssemblyUpdate =\n | {\n kind: \"message-start\";\n key: string;\n message: AssembledMessage;\n event: MessagesEvent;\n }\n | {\n kind: \"content-block-start\" | \"content-block-delta\";\n key: string;\n message: AssembledMessage;\n index: number;\n block: ContentBlock;\n event: MessagesEvent;\n }\n | {\n kind: \"content-block-finish\";\n key: string;\n message: AssembledMessage;\n index: number;\n block: FinalizedContentBlock;\n event: MessagesEvent;\n }\n | {\n kind: \"usage\";\n key: string;\n message: AssembledMessage;\n event: MessagesEvent;\n }\n | {\n kind: \"message-finish\";\n key: string;\n message: AssembledMessage;\n event: MessagesEvent;\n }\n | {\n kind: \"message-error\";\n key: string;\n message: AssembledMessage;\n event: MessagesEvent;\n };\n\nfunction cloneBlock<T extends ContentBlock>(block: T): T {\n return structuredClone(block);\n}\n\nfunction blockFromDelta(\n delta: CoreContentBlockDelta,\n current?: ContentBlock\n): ContentBlock {\n return coreContentBlockFromDelta(\n delta,\n current as unknown as CoreContentBlock | undefined\n ) as unknown as ContentBlock;\n}\n\nfunction applyContentDelta(\n target: ContentBlock,\n delta: ContentBlock\n): ContentBlock {\n if (target.type !== delta.type) {\n return cloneBlock(delta);\n }\n\n switch (delta.type) {\n case \"text\":\n return {\n ...target,\n ...delta,\n text: `${\"text\" in target ? target.text : \"\"}${delta.text}`,\n } as ContentBlock;\n case \"reasoning\":\n return {\n ...target,\n ...delta,\n reasoning: `${\"reasoning\" in target ? target.reasoning : \"\"}${delta.reasoning}`,\n } as ContentBlock;\n case \"tool_call_chunk\":\n case \"server_tool_call_chunk\": {\n // Spread target first, then delta — but preserve target's\n // ``id``/``name`` when the delta explicitly sets them to\n // null/undefined. Some providers (notably Anthropic via the\n // langchain-core compat bridge) only attach the tool-call\n // identifiers to the first ``content-block-start`` chunk; every\n // subsequent ``input_json_delta`` chunk carries ``id=null,\n // name=null``. A naive ``{...target, ...delta}`` spread\n // overwrites the captured identifiers with null, which in turn\n // makes downstream consumers (e.g. ``extractToolCallChunks`` in\n // ``assembled-to-message.ts``) drop the chunk on the floor until\n // the final ``content-block-finish`` event promotes it to a\n // finalized ``tool_call`` — causing tool-call cards to appear\n // all-at-once at the end of the turn instead of incrementally.\n const merged = { ...target, ...delta } as Record<string, unknown>;\n if (delta.id == null && \"id\" in target && target.id != null) {\n merged.id = target.id;\n }\n if (delta.name == null && \"name\" in target && target.name != null) {\n merged.name = target.name;\n }\n merged.args = `${(\"args\" in target ? target.args : \"\") ?? \"\"}${delta.args ?? \"\"}`;\n return merged as unknown as ContentBlock;\n }\n default:\n return {\n ...target,\n ...delta,\n } as ContentBlock;\n }\n}\n\nfunction messageKeyFor(event: MessagesEvent): string {\n const { namespace, node, data } = event.params;\n const namespaceKey = namespace.join(\"/\");\n const runId = readRunId(data);\n const messageId = data.event === \"message-start\" ? (data.id ?? \"\") : \"\";\n return `${namespaceKey}::${node ?? \"\"}::${runId ?? messageId}`;\n}\n\nfunction toChatModelStreamEvent(event: MessagesEvent): ChatModelStreamEvent {\n return event.params.data as unknown as ChatModelStreamEvent;\n}\n\n/**\n * Incrementally assembles `messages` events into complete message objects.\n */\nexport class MessageAssembler {\n private readonly activeMessages = new Map<string, AssembledMessage>();\n private readonly activeByNamespaceNode = new Map<string, string>();\n private readonly blockIndexByProtocolIndexAndType = new Map<string, number>();\n\n /**\n * Applies a single message event and returns the resulting assembly update.\n *\n * @param event - Incoming `messages` event to fold into the assembler state.\n */\n consume(event: MessagesEvent): MessageAssemblyUpdate {\n const data = event.params.data;\n const namespaceNodeKey = `${event.params.namespace.join(\"/\")}::${event.params.node ?? \"\"}`;\n const runId = readRunId(data);\n\n if (data.event === \"message-start\") {\n const key = messageKeyFor(event);\n this.activeByNamespaceNode.set(namespaceNodeKey, key);\n const message: AssembledMessage = {\n id: data.id,\n namespace: [...event.params.namespace],\n node: event.params.node,\n runId,\n usage: readUsage(data),\n metadata: data.metadata,\n blocks: [],\n };\n this.activeMessages.set(key, message);\n return { kind: \"message-start\", key, message, event };\n }\n\n const runKey = runId != null ? `${namespaceNodeKey}::${runId}` : undefined;\n const fallbackKey = this.activeByNamespaceNode.get(namespaceNodeKey);\n const fallbackMessage =\n fallbackKey != null ? this.activeMessages.get(fallbackKey) : undefined;\n const activeKey =\n (runKey != null && this.activeMessages.has(runKey)\n ? runKey\n : undefined) ??\n (runId == null || fallbackMessage?.runId == null\n ? fallbackKey\n : undefined);\n if (!activeKey) {\n // A continuation event (delta/finish/error) arrived without a\n // prior `message-start`. This can happen on late-attaching\n // subscriptions when the server has already trimmed the\n // `message-start` from its replay buffer. Synthesize a minimal\n // active message so the assembler can still fold subsequent\n // events instead of hard-failing the caller.\n const syntheticKey = runKey ?? `${namespaceNodeKey}::`;\n this.activeByNamespaceNode.set(namespaceNodeKey, syntheticKey);\n const synthetic: AssembledMessage = {\n id: data.id,\n namespace: [...event.params.namespace],\n node: event.params.node,\n runId,\n blocks: [],\n };\n this.activeMessages.set(syntheticKey, synthetic);\n return this.consume(event);\n }\n\n const message = this.activeMessages.get(activeKey);\n if (!message) {\n throw new Error(`No active message state found for key ${activeKey}`);\n }\n\n if ((data as { event?: string }).event === \"usage\") {\n message.usage = (data as { usage?: UsageInfo }).usage;\n return {\n kind: \"usage\",\n key: activeKey,\n message,\n event,\n };\n }\n\n switch (data.event) {\n case \"content-block-start\": {\n message.blocks[data.index] = cloneBlock(data.content);\n this.blockIndexByProtocolIndexAndType.set(\n blockIndexKey(activeKey, data.index, data.content.type),\n data.index\n );\n return {\n kind: \"content-block-start\",\n key: activeKey,\n message,\n index: data.index,\n block: data.content,\n event,\n };\n }\n case \"content-block-delta\": {\n const deltaEvent = data as typeof data & {\n content?: ContentBlock;\n delta?: CoreContentBlockDelta;\n };\n const deltaBlock =\n deltaEvent.content ??\n (deltaEvent.delta != null\n ? blockFromDelta(deltaEvent.delta, message.blocks[data.index])\n : undefined);\n if (deltaBlock == null) {\n throw new Error(\"Received content-block-delta without content\");\n }\n const targetIndex = this.resolveBlockIndex(\n activeKey,\n message.blocks,\n data.index,\n deltaBlock.type\n );\n const current = message.blocks[targetIndex];\n message.blocks[targetIndex] =\n deltaEvent.content != null\n ? current == null\n ? cloneBlock(deltaEvent.content)\n : applyContentDelta(current, deltaEvent.content)\n : (applyCoreEventDelta(\n current as CoreContentBlock | undefined,\n data as unknown as Extract<\n ChatModelStreamEvent,\n { event: \"content-block-delta\" }\n >\n ) as unknown as ContentBlock);\n return {\n kind: \"content-block-delta\",\n key: activeKey,\n message,\n index: targetIndex,\n block: deltaBlock,\n event,\n };\n }\n case \"content-block-finish\": {\n const targetIndex = this.resolveFinishBlockIndex(\n activeKey,\n data.index,\n data.content.type\n );\n message.blocks[targetIndex] = cloneBlock(data.content);\n return {\n kind: \"content-block-finish\",\n key: activeKey,\n message,\n index: targetIndex,\n block: data.content,\n event,\n };\n }\n case \"message-finish\": {\n message.usage = readUsage(data) ?? message.usage;\n message.finishMetadata = readFinishMetadata(data);\n message.finishReason = data.reason;\n this.clearActiveMessage(activeKey, namespaceNodeKey);\n this.clearBlockIndexAliases(activeKey);\n return {\n kind: \"message-finish\",\n key: activeKey,\n message: structuredClone(message),\n event,\n };\n }\n case \"error\": {\n message.error = { message: data.message, code: data.code };\n this.clearActiveMessage(activeKey, namespaceNodeKey);\n this.clearBlockIndexAliases(activeKey);\n return {\n kind: \"message-error\",\n key: activeKey,\n message: structuredClone(message),\n event,\n };\n }\n }\n }\n\n /**\n * Drop every message that started but never got `message-finish` or\n * `error`, e.g. because the run was cancelled mid-stream.\n *\n * @param namespace - Only abandon messages at or below this namespace.\n * @returns The abandoned messages.\n */\n abandonActive(namespace?: readonly string[]): AssembledMessage[] {\n const abandoned: AssembledMessage[] = [];\n for (const [key, message] of this.activeMessages) {\n if (\n namespace != null &&\n !hasNamespacePrefix(message.namespace, namespace)\n )\n continue;\n abandoned.push(message);\n this.activeMessages.delete(key);\n this.clearBlockIndexAliases(key);\n for (const [nsNode, activeKey] of this.activeByNamespaceNode) {\n if (activeKey === key) this.activeByNamespaceNode.delete(nsNode);\n }\n }\n return abandoned;\n }\n\n private clearActiveMessage(\n activeKey: string,\n namespaceNodeKey: string\n ): void {\n this.activeMessages.delete(activeKey);\n if (this.activeByNamespaceNode.get(namespaceNodeKey) === activeKey) {\n this.activeByNamespaceNode.delete(namespaceNodeKey);\n }\n }\n\n private resolveBlockIndex(\n activeKey: string,\n blocks: ContentBlock[],\n protocolIndex: number,\n blockType: string\n ): number {\n const current = blocks[protocolIndex];\n if (\n current == null ||\n current.type === blockType ||\n areCompatibleBlockTypes(current.type, blockType)\n ) {\n this.blockIndexByProtocolIndexAndType.set(\n blockIndexKey(activeKey, protocolIndex, blockType),\n protocolIndex\n );\n return protocolIndex;\n }\n\n const key = blockIndexKey(activeKey, protocolIndex, blockType);\n const existing = this.blockIndexByProtocolIndexAndType.get(key);\n if (existing != null) return existing;\n\n const nextIndex = blocks.length;\n this.blockIndexByProtocolIndexAndType.set(key, nextIndex);\n return nextIndex;\n }\n\n private resolveFinishBlockIndex(\n activeKey: string,\n protocolIndex: number,\n blockType: string\n ): number {\n const key = blockIndexKey(activeKey, protocolIndex, blockType);\n const existing = this.blockIndexByProtocolIndexAndType.get(key);\n if (existing != null) return existing;\n\n this.blockIndexByProtocolIndexAndType.set(key, protocolIndex);\n return protocolIndex;\n }\n\n private clearBlockIndexAliases(activeKey: string): void {\n const prefix = `${activeKey}::`;\n for (const key of this.blockIndexByProtocolIndexAndType.keys()) {\n if (key.startsWith(prefix))\n this.blockIndexByProtocolIndexAndType.delete(key);\n }\n }\n}\n\nfunction hasNamespacePrefix(\n namespace: readonly string[],\n prefix: readonly string[]\n): boolean {\n return prefix.every((segment, i) => namespace[i] === segment);\n}\n\nfunction blockIndexKey(\n activeKey: string,\n protocolIndex: number,\n blockType: string\n): string {\n return `${activeKey}::${protocolIndex}::${blockType}`;\n}\n\nfunction areCompatibleBlockTypes(\n currentType: string,\n nextType: string\n): boolean {\n const toolCallTypes = new Set([\n \"tool_call\",\n \"tool_call_chunk\",\n \"tool_use\",\n \"input_json_delta\",\n ]);\n const serverToolCallTypes = new Set([\n \"server_tool_call\",\n \"server_tool_call_chunk\",\n ]);\n\n return (\n (toolCallTypes.has(currentType) && toolCallTypes.has(nextType)) ||\n (serverToolCallTypes.has(currentType) && serverToolCallTypes.has(nextType))\n );\n}\n\n/**\n * Assembles `messages` events into {@link StreamingMessage} instances\n * with live text/reasoning delta streams, matching the in-process\n * `ChatModelStream` dual-interface pattern.\n */\nexport class StreamingMessageAssembler {\n readonly #assembler = new MessageAssembler();\n readonly #activeStreaming = new Map<string, StreamingMessage>();\n\n /**\n * Folds a single event and returns a new {@link StreamingMessage}\n * when a `message-start` is seen, or `undefined` for continuation\n * events (deltas, finish, error).\n */\n consume(event: MessagesEvent): StreamingMessage | undefined {\n const update = this.#assembler.consume(event);\n if (update == null) return undefined;\n\n switch (update.kind) {\n case \"message-start\": {\n const streaming = new StreamingMessage(update.message);\n streaming[UPDATE_CONTEXT](update.event);\n streaming[PUSH_EVENT](toChatModelStreamEvent(update.event));\n this.#activeStreaming.set(update.key, streaming);\n return streaming;\n }\n case \"content-block-start\": {\n const streaming = this.#activeStreaming.get(update.key);\n if (streaming) {\n streaming[UPDATE_CONTEXT](update.event);\n streaming[PUSH_EVENT](toChatModelStreamEvent(update.event));\n }\n if (\n streaming &&\n update.block.type === \"text\" &&\n \"text\" in update.block &&\n update.block.text\n ) {\n streaming[PUSH_TEXT](update.block.text);\n }\n if (\n streaming &&\n update.block.type === \"reasoning\" &&\n \"reasoning\" in update.block &&\n update.block.reasoning\n ) {\n streaming[PUSH_REASONING](update.block.reasoning);\n }\n return undefined;\n }\n case \"content-block-delta\": {\n const streaming = this.#activeStreaming.get(update.key);\n if (!streaming) return undefined;\n streaming[UPDATE_CONTEXT](update.event);\n streaming[PUSH_EVENT](toChatModelStreamEvent(update.event));\n if (update.block.type === \"text\" && \"text\" in update.block) {\n streaming[PUSH_TEXT](update.block.text);\n }\n if (update.block.type === \"reasoning\" && \"reasoning\" in update.block) {\n streaming[PUSH_REASONING](update.block.reasoning);\n }\n return undefined;\n }\n case \"content-block-finish\": {\n const streaming = this.#activeStreaming.get(update.key);\n if (streaming) {\n streaming[UPDATE_CONTEXT](update.event);\n streaming[PUSH_EVENT](toChatModelStreamEvent(update.event));\n }\n return undefined;\n }\n case \"usage\": {\n const streaming = this.#activeStreaming.get(update.key);\n if (streaming) {\n streaming[UPDATE_CONTEXT](update.event);\n streaming[PUSH_EVENT](toChatModelStreamEvent(update.event));\n }\n return undefined;\n }\n case \"message-finish\": {\n const streaming = this.#activeStreaming.get(update.key);\n if (streaming) {\n streaming[UPDATE_CONTEXT](update.event);\n streaming[PUSH_EVENT](toChatModelStreamEvent(update.event));\n streaming[FINISH]();\n this.#activeStreaming.delete(update.key);\n }\n return undefined;\n }\n case \"message-error\": {\n const streaming = this.#activeStreaming.get(update.key);\n if (streaming) {\n streaming[UPDATE_CONTEXT](update.event);\n streaming[PUSH_EVENT](toChatModelStreamEvent(update.event));\n streaming[ERROR]();\n this.#activeStreaming.delete(update.key);\n }\n return undefined;\n }\n }\n }\n\n /**\n * Settle every message that never finished, marking it with an\n * `aborted` error so awaiting consumers don't hang.\n *\n * @param namespace - Only abandon messages at or below this namespace.\n * @returns The abandoned messages.\n */\n abandonActive(namespace?: readonly string[]): StreamingMessage[] {\n this.#assembler.abandonActive(namespace);\n const abandoned: StreamingMessage[] = [];\n for (const [key, streaming] of this.#activeStreaming) {\n if (\n namespace != null &&\n !hasNamespacePrefix(streaming.namespace, namespace)\n )\n continue;\n streaming.assembled.error = {\n message: \"Message stream ended before message-finish\",\n code: \"aborted\",\n };\n streaming[ERROR]();\n this.#activeStreaming.delete(key);\n abandoned.push(streaming);\n }\n return abandoned;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"messages.js","names":["#events","#textPromise","#reasoningPromise","#resolveText","#resolveReasoning","#textChunks","#textWaiters","#textDone","#reasoningChunks","#reasoningWaiters","#reasoningDone","#usageIterator","#assembleMessage","#assembler","#activeStreaming"],"sources":["../../../src/client/stream/messages.ts"],"sourcesContent":["import {\n AIMessage,\n type ContentBlock as CoreContentBlock,\n type UsageMetadata,\n} from \"@langchain/core/messages\";\nimport type { ChatModelStreamEvent } from \"@langchain/core/language_models/event\";\nimport type {\n ContentBlock,\n ContentBlockDelta,\n FinalizedContentBlock,\n MessageMetadata,\n MessagesEvent,\n UsageInfo,\n} from \"@langchain/protocol\";\n\nimport { MultiCursorBuffer } from \"./multi-cursor-buffer.js\";\n\ntype TextContentStream = AsyncIterable<string> &\n PromiseLike<string> & { full: AsyncIterable<string> };\n\ntype UsageMetadataStream = AsyncIterable<UsageMetadata> &\n PromiseLike<UsageMetadata | undefined>;\n\ntype ToolCallsStream = AsyncIterable<CoreContentBlock.Tools.ToolCall> &\n PromiseLike<Array<CoreContentBlock.Tools.ToolCall>> & {\n full: AsyncIterable<Array<CoreContentBlock.Tools.ToolCall>>;\n };\n\n// Deltas are typed by the protocol, not `@langchain/core`, whose union\n// doesn't include `tool-call-delta` yet.\ntype ContentBlockDeltaEvent = Omit<\n Extract<ChatModelStreamEvent, { event: \"content-block-delta\" }>,\n \"delta\"\n> & { delta: ContentBlockDelta; content?: CoreContentBlock };\n\ntype ToolCallChunkBlock =\n | CoreContentBlock.Tools.ToolCallChunk\n | CoreContentBlock.Tools.ServerToolCallChunk;\n\nfunction isToolCallChunk(\n block: CoreContentBlock | undefined\n): block is ToolCallChunkBlock {\n return (\n block?.type === \"tool_call_chunk\" ||\n block?.type === \"server_tool_call_chunk\"\n );\n}\n\nfunction applyCoreContentDelta(\n target: CoreContentBlock,\n delta: CoreContentBlock\n): CoreContentBlock {\n if (target.type !== delta.type) {\n return structuredClone(delta);\n }\n\n switch (delta.type) {\n case \"text\":\n return {\n ...target,\n ...delta,\n text: `${\"text\" in target ? target.text : \"\"}${delta.text}`,\n } as CoreContentBlock;\n case \"reasoning\":\n return {\n ...target,\n ...delta,\n reasoning: `${\"reasoning\" in target ? target.reasoning : \"\"}${delta.reasoning}`,\n } as CoreContentBlock;\n case \"tool_call_chunk\":\n case \"server_tool_call_chunk\": {\n const merged = { ...target, ...delta } as Record<string, unknown>;\n if (delta.id == null && \"id\" in target && target.id != null) {\n merged.id = target.id;\n }\n if (delta.name == null && \"name\" in target && target.name != null) {\n merged.name = target.name;\n }\n merged.args = `${(\"args\" in target ? target.args : \"\") ?? \"\"}${delta.args ?? \"\"}`;\n return merged as unknown as CoreContentBlock;\n }\n default:\n return { ...target, ...delta } as CoreContentBlock;\n }\n}\n\nfunction coreContentBlockFromDelta(\n delta: ContentBlockDelta,\n current?: CoreContentBlock\n): CoreContentBlock | undefined {\n switch (delta.type) {\n case \"text-delta\":\n return { type: \"text\", text: delta.text } as CoreContentBlock;\n case \"reasoning-delta\":\n return {\n type: \"reasoning\",\n reasoning: delta.reasoning,\n } as CoreContentBlock;\n case \"data-delta\": {\n const merged = { ...(current ?? {}), data: delta.data } as Record<\n string,\n unknown\n >;\n if (delta.encoding) merged.encoding = delta.encoding;\n return merged as unknown as CoreContentBlock;\n }\n case \"block-delta\":\n return delta.fields as CoreContentBlock;\n case \"tool-call-delta\":\n // Without the block's start there's no id or name to attach the\n // slice to; `content-block-finish` delivers the complete call.\n return isToolCallChunk(current)\n ? { type: current.type, args: delta.args }\n : undefined;\n default:\n // Unknown variants are ignored.\n return undefined;\n }\n}\n\nfunction applyCoreEventDelta(\n current: CoreContentBlock | undefined,\n event: ContentBlockDeltaEvent\n): CoreContentBlock | undefined {\n if (event.content) {\n return current\n ? applyCoreContentDelta(current, event.content)\n : event.content;\n }\n\n switch (event.delta.type) {\n case \"text-delta\":\n if (current?.type === \"text\") {\n return {\n ...current,\n text: `${\"text\" in current ? current.text : \"\"}${event.delta.text}`,\n } as CoreContentBlock;\n }\n return coreContentBlockFromDelta(event.delta, current);\n case \"reasoning-delta\":\n if (current?.type === \"reasoning\") {\n return {\n ...current,\n reasoning: `${\"reasoning\" in current ? current.reasoning : \"\"}${event.delta.reasoning}`,\n } as CoreContentBlock;\n }\n return coreContentBlockFromDelta(event.delta, current);\n case \"data-delta\": {\n const merged = { ...(current ?? {}) } as Record<string, unknown>;\n merged.data = `${(merged.data as string | undefined) ?? \"\"}${event.delta.data}`;\n if (event.delta.encoding) merged.encoding = event.delta.encoding;\n return merged as unknown as CoreContentBlock;\n }\n case \"block-delta\":\n return {\n ...(current ?? {}),\n ...event.delta.fields,\n } as CoreContentBlock;\n case \"tool-call-delta\":\n if (!isToolCallChunk(current)) return current;\n return {\n ...current,\n args: `${current.args ?? \"\"}${event.delta.args}`,\n };\n default:\n return current;\n }\n}\n\nfunction normalizeUsage(\n usage: UsageInfo | Partial<UsageMetadata> | undefined\n): UsageMetadata | undefined {\n if (!usage) return undefined;\n return {\n ...usage,\n input_tokens: usage.input_tokens ?? 0,\n output_tokens: usage.output_tokens ?? 0,\n total_tokens: usage.total_tokens ?? 0,\n };\n}\n\nfunction readRunId(data: object): string | undefined {\n const record = data as Record<string, unknown>;\n return typeof record.run_id === \"string\" ? record.run_id : undefined;\n}\n\nfunction readUsage(data: object): UsageInfo | undefined {\n const usage = (data as Record<string, unknown>).usage;\n return usage != null && typeof usage === \"object\" && !Array.isArray(usage)\n ? (usage as UsageInfo)\n : undefined;\n}\n\nfunction readFinishMetadata(data: object): Record<string, unknown> | undefined {\n const record = data as Record<string, unknown>;\n const isRecord = (value: unknown): value is Record<string, unknown> =>\n value != null && typeof value === \"object\" && !Array.isArray(value);\n const merged = {\n ...(isRecord(record.responseMetadata) ? record.responseMetadata : {}),\n ...(isRecord(record.metadata) ? record.metadata : {}),\n };\n return Object.keys(merged).length > 0 ? merged : undefined;\n}\n\n/**\n * Mutable view of a streamed message as message and content-block events are\n * assembled into a single structure.\n */\nexport interface AssembledMessage {\n id: string;\n namespace: string[];\n blocks: ContentBlock[];\n node?: string;\n runId?: string;\n usage?: UsageInfo;\n metadata?: MessageMetadata;\n finishMetadata?: Record<string, any>;\n finishReason?: string;\n error?: {\n message: string;\n code?: string;\n };\n}\n\n/**\n * Symbol keys for assembler → StreamingMessage communication.\n * Module-private: invisible to external consumers, accessible to\n * {@link StreamingMessageAssembler} within this file.\n */\nconst PUSH_TEXT: unique symbol = Symbol(\"pushText\");\nconst PUSH_REASONING: unique symbol = Symbol(\"pushReasoning\");\nconst PUSH_EVENT: unique symbol = Symbol(\"pushEvent\");\nconst UPDATE_CONTEXT: unique symbol = Symbol(\"updateContext\");\nconst FINISH: unique symbol = Symbol(\"finish\");\nconst ERROR: unique symbol = Symbol(\"error\");\n\n/**\n * Live streaming view of a single message lifecycle, matching the\n * in-process `ChatModelStream` dual-interface pattern.\n *\n * - `text` / `reasoning`: iterate for streaming deltas, or await for\n * the full concatenated string after the message completes.\n * - `usage`: promise that resolves with token usage on message-finish.\n * - `blocks`: the assembled content blocks (updated as deltas arrive).\n *\n * Created by {@link StreamingMessageAssembler} and yielded by\n * the `session.messages` lazy getter.\n */\nexport class StreamingMessage\n implements AsyncIterable<ChatModelStreamEvent>, PromiseLike<AIMessage>\n{\n readonly id: string;\n readonly namespace: string[];\n node: string | undefined;\n readonly metadata: MessageMetadata | undefined;\n readonly assembled: AssembledMessage;\n readonly #events = new MultiCursorBuffer<ChatModelStreamEvent>();\n\n #textChunks: string[] = [];\n #reasoningChunks: string[] = [];\n #textWaiters: Array<() => void> = [];\n #reasoningWaiters: Array<() => void> = [];\n #textDone = false;\n #reasoningDone = false;\n\n #resolveText!: (v: string) => void;\n #resolveReasoning!: (v: string) => void;\n readonly #textPromise: Promise<string>;\n readonly #reasoningPromise: Promise<string>;\n\n constructor(assembled: AssembledMessage) {\n this.id = assembled.id;\n this.assembled = assembled;\n this.namespace = assembled.namespace;\n this.node = assembled.node;\n this.metadata = assembled.metadata;\n this.#textPromise = new Promise<string>((r) => {\n this.#resolveText = r;\n });\n this.#reasoningPromise = new Promise<string>((r) => {\n this.#resolveReasoning = r;\n });\n }\n\n get text(): TextContentStream {\n const chunks = this.#textChunks;\n const waiters = this.#textWaiters;\n const getDone = () => this.#textDone;\n let cursor = 0;\n return {\n [Symbol.asyncIterator]() {\n return {\n async next(): Promise<IteratorResult<string>> {\n while (true) {\n if (cursor < chunks.length) {\n return { done: false, value: chunks[cursor++] };\n }\n if (getDone()) {\n return { done: true, value: undefined };\n }\n await new Promise<void>((resolve) => {\n waiters.push(resolve);\n });\n }\n },\n };\n },\n then: this.#textPromise.then.bind(this.#textPromise),\n full: {\n async *[Symbol.asyncIterator]() {\n let accumulated = \"\";\n for await (const chunk of {\n [Symbol.asyncIterator]: () =>\n ({\n next: async (): Promise<IteratorResult<string>> => {\n while (true) {\n if (cursor < chunks.length) {\n return { done: false, value: chunks[cursor++] };\n }\n if (getDone()) {\n return { done: true, value: undefined };\n }\n await new Promise<void>((resolve) => {\n waiters.push(resolve);\n });\n }\n },\n }) satisfies AsyncIterator<string>,\n }) {\n accumulated += chunk;\n yield accumulated;\n }\n },\n },\n };\n }\n\n get reasoning(): TextContentStream {\n const chunks = this.#reasoningChunks;\n const waiters = this.#reasoningWaiters;\n const getDone = () => this.#reasoningDone;\n let cursor = 0;\n return {\n [Symbol.asyncIterator]() {\n return {\n async next(): Promise<IteratorResult<string>> {\n while (true) {\n if (cursor < chunks.length) {\n return { done: false, value: chunks[cursor++] };\n }\n if (getDone()) {\n return { done: true, value: undefined };\n }\n await new Promise<void>((resolve) => {\n waiters.push(resolve);\n });\n }\n },\n };\n },\n then: this.#reasoningPromise.then.bind(this.#reasoningPromise),\n full: {\n async *[Symbol.asyncIterator]() {\n let accumulated = \"\";\n for await (const chunk of {\n [Symbol.asyncIterator]: () =>\n ({\n next: async (): Promise<IteratorResult<string>> => {\n while (true) {\n if (cursor < chunks.length) {\n return { done: false, value: chunks[cursor++] };\n }\n if (getDone()) {\n return { done: true, value: undefined };\n }\n await new Promise<void>((resolve) => {\n waiters.push(resolve);\n });\n }\n },\n }) satisfies AsyncIterator<string>,\n }) {\n accumulated += chunk;\n yield accumulated;\n }\n },\n },\n };\n }\n\n get usage(): UsageMetadataStream {\n const promise = (async () => {\n let usage: UsageMetadata | undefined;\n for await (const snapshot of this.#usageIterator()) {\n usage = snapshot;\n }\n return usage;\n })();\n return {\n [Symbol.asyncIterator]: () => this.#usageIterator(),\n then: promise.then.bind(promise),\n };\n }\n\n get toolCalls(): ToolCallsStream {\n const events = this.#events;\n const iterator = async function* () {\n for await (const event of events) {\n if (\n event.event === \"content-block-finish\" &&\n event.content.type === \"tool_call\"\n ) {\n yield event.content as CoreContentBlock.Tools.ToolCall;\n }\n }\n };\n return {\n [Symbol.asyncIterator]: iterator,\n then: async (onfulfilled, onrejected) => {\n try {\n const calls: CoreContentBlock.Tools.ToolCall[] = [];\n for await (const call of iterator()) calls.push(call);\n return onfulfilled ? onfulfilled(calls) : (calls as never);\n } catch (err) {\n if (onrejected) return onrejected(err);\n throw err;\n }\n },\n full: {\n async *[Symbol.asyncIterator]() {\n const calls: CoreContentBlock.Tools.ToolCall[] = [];\n for await (const call of iterator()) {\n calls.push(call);\n yield [...calls];\n }\n },\n },\n };\n }\n\n get output(): PromiseLike<AIMessage> {\n return { then: (onf, onr) => this.#assembleMessage().then(onf, onr) };\n }\n\n get blocks(): ContentBlock[] {\n return this.assembled.blocks;\n }\n\n [Symbol.asyncIterator](): AsyncIterator<ChatModelStreamEvent> {\n return this.#events[Symbol.asyncIterator]();\n }\n\n then<TResult1 = AIMessage, TResult2 = never>(\n onfulfilled?:\n | ((value: AIMessage) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n return this.#assembleMessage().then(onfulfilled, onrejected);\n }\n\n async *#usageIterator(): AsyncGenerator<UsageMetadata> {\n for await (const event of this.#events) {\n if (event.event === \"message-start\" && event.usage) {\n yield normalizeUsage(event.usage)!;\n } else if (event.event === \"message-finish\" && event.usage) {\n yield normalizeUsage(event.usage)!;\n }\n }\n }\n\n async #assembleMessage(): Promise<AIMessage> {\n const contentBlocks: Array<CoreContentBlock | undefined> = [];\n let id: string | undefined = this.id;\n let usage = normalizeUsage(this.assembled.usage);\n let metadata: Record<string, unknown> = {\n ...(this.assembled.finishMetadata ?? {}),\n };\n let finishReason: string | undefined = this.assembled.finishReason;\n\n for await (const event of this.#events) {\n switch (event.event) {\n case \"message-start\":\n id = event.id ?? id;\n if (event.usage) usage = normalizeUsage(event.usage);\n break;\n case \"content-block-start\":\n contentBlocks[event.index] = event.content;\n break;\n case \"content-block-delta\": {\n const current = contentBlocks[event.index];\n contentBlocks[event.index] = applyCoreEventDelta(current, event);\n break;\n }\n case \"content-block-finish\":\n contentBlocks[event.index] = event.content;\n break;\n case \"message-finish\": {\n finishReason = event.reason;\n if (event.usage) usage = normalizeUsage(event.usage);\n const finishMetadata = readFinishMetadata(event);\n if (finishMetadata != null) {\n metadata = { ...metadata, ...finishMetadata };\n }\n break;\n }\n default:\n break;\n }\n }\n\n return new AIMessage({\n id,\n content: contentBlocks.filter(\n (block): block is CoreContentBlock => block != null\n ),\n usage_metadata: usage,\n additional_kwargs: {\n namespace: this.namespace,\n ...(this.node != null ? { node: this.node } : {}),\n ...(this.assembled.runId != null\n ? { run_id: this.assembled.runId }\n : {}),\n ...(this.metadata != null ? { metadata: this.metadata } : {}),\n ...(this.assembled.usage != null\n ? { usage: this.assembled.usage }\n : {}),\n },\n response_metadata: {\n ...(finishReason != null ? { finish_reason: finishReason } : {}),\n ...metadata,\n output_version: \"v1\" as const,\n },\n });\n }\n\n [PUSH_EVENT](event: ChatModelStreamEvent): void {\n this.#events.push(event);\n }\n\n [UPDATE_CONTEXT](event: MessagesEvent): void {\n this.node = event.params.node ?? this.node;\n }\n\n [PUSH_TEXT](delta: string): void {\n this.#textChunks.push(delta);\n // Wake every caught-up iterator so each one advances its own cursor.\n // Iterators re-check `chunks.length` before delivering, which keeps\n // the cursor the single source of truth for what a consumer has seen.\n const pending = this.#textWaiters.splice(0, this.#textWaiters.length);\n for (const waiter of pending) waiter();\n }\n\n [PUSH_REASONING](delta: string): void {\n this.#reasoningChunks.push(delta);\n const pending = this.#reasoningWaiters.splice(\n 0,\n this.#reasoningWaiters.length\n );\n for (const waiter of pending) waiter();\n }\n\n [FINISH](): void {\n this.#textDone = true;\n this.#reasoningDone = true;\n this.#resolveText(this.#textChunks.join(\"\"));\n this.#resolveReasoning(this.#reasoningChunks.join(\"\"));\n const textPending = this.#textWaiters.splice(0, this.#textWaiters.length);\n for (const waiter of textPending) waiter();\n const reasoningPending = this.#reasoningWaiters.splice(\n 0,\n this.#reasoningWaiters.length\n );\n for (const waiter of reasoningPending) waiter();\n this.#events.close();\n }\n\n [ERROR](): void {\n this[FINISH]();\n }\n}\n\n/**\n * Public view yielded by message projections.\n *\n * `StreamingMessage` is PromiseLike so callers can still `await` a message\n * object directly, but TypeScript applies `Awaited<T>` to values produced by\n * `for await`. Exposing a non-thenable view keeps loop variables typed as the\n * streaming handle instead of as the finalized `AIMessage`.\n */\nexport type StreamingMessageHandle = Omit<StreamingMessage, \"then\">;\n\nexport function toStreamingMessageHandle(\n message: StreamingMessage\n): StreamingMessageHandle {\n return new Proxy(message, {\n get(target, prop) {\n if (prop === \"then\") return undefined;\n const value = Reflect.get(target, prop, target);\n return typeof value === \"function\" ? value.bind(target) : value;\n },\n has(target, prop) {\n if (prop === \"then\") return false;\n return prop in target;\n },\n }) as StreamingMessageHandle;\n}\n\n/**\n * Emitted by `MessageAssembler.consume()` to describe how a message changed in\n * response to a single protocol event.\n */\nexport type MessageAssemblyUpdate =\n | {\n kind: \"message-start\";\n key: string;\n message: AssembledMessage;\n event: MessagesEvent;\n }\n | {\n kind: \"content-block-start\" | \"content-block-delta\";\n key: string;\n message: AssembledMessage;\n index: number;\n block: ContentBlock;\n event: MessagesEvent;\n }\n | {\n kind: \"content-block-finish\";\n key: string;\n message: AssembledMessage;\n index: number;\n block: FinalizedContentBlock;\n event: MessagesEvent;\n }\n | {\n kind: \"usage\";\n key: string;\n message: AssembledMessage;\n event: MessagesEvent;\n }\n | {\n kind: \"message-finish\";\n key: string;\n message: AssembledMessage;\n event: MessagesEvent;\n }\n | {\n kind: \"message-error\";\n key: string;\n message: AssembledMessage;\n event: MessagesEvent;\n };\n\nfunction cloneBlock<T extends ContentBlock>(block: T): T {\n return structuredClone(block);\n}\n\nfunction blockFromDelta(\n delta: ContentBlockDelta,\n current?: ContentBlock\n): ContentBlock | undefined {\n return coreContentBlockFromDelta(\n delta,\n current as unknown as CoreContentBlock | undefined\n ) as unknown as ContentBlock | undefined;\n}\n\nfunction applyContentDelta(\n target: ContentBlock,\n delta: ContentBlock\n): ContentBlock {\n if (target.type !== delta.type) {\n return cloneBlock(delta);\n }\n\n switch (delta.type) {\n case \"text\":\n return {\n ...target,\n ...delta,\n text: `${\"text\" in target ? target.text : \"\"}${delta.text}`,\n } as ContentBlock;\n case \"reasoning\":\n return {\n ...target,\n ...delta,\n reasoning: `${\"reasoning\" in target ? target.reasoning : \"\"}${delta.reasoning}`,\n } as ContentBlock;\n case \"tool_call_chunk\":\n case \"server_tool_call_chunk\": {\n // Spread target first, then delta — but preserve target's\n // ``id``/``name`` when the delta explicitly sets them to\n // null/undefined. Some providers (notably Anthropic via the\n // langchain-core compat bridge) only attach the tool-call\n // identifiers to the first ``content-block-start`` chunk; every\n // subsequent ``input_json_delta`` chunk carries ``id=null,\n // name=null``. A naive ``{...target, ...delta}`` spread\n // overwrites the captured identifiers with null, which in turn\n // makes downstream consumers (e.g. ``extractToolCallChunks`` in\n // ``assembled-to-message.ts``) drop the chunk on the floor until\n // the final ``content-block-finish`` event promotes it to a\n // finalized ``tool_call`` — causing tool-call cards to appear\n // all-at-once at the end of the turn instead of incrementally.\n const merged = { ...target, ...delta } as Record<string, unknown>;\n if (delta.id == null && \"id\" in target && target.id != null) {\n merged.id = target.id;\n }\n if (delta.name == null && \"name\" in target && target.name != null) {\n merged.name = target.name;\n }\n merged.args = `${(\"args\" in target ? target.args : \"\") ?? \"\"}${delta.args ?? \"\"}`;\n return merged as unknown as ContentBlock;\n }\n default:\n return {\n ...target,\n ...delta,\n } as ContentBlock;\n }\n}\n\nfunction messageKeyFor(event: MessagesEvent): string {\n const { namespace, node, data } = event.params;\n const namespaceKey = namespace.join(\"/\");\n const runId = readRunId(data);\n const messageId = data.event === \"message-start\" ? (data.id ?? \"\") : \"\";\n return `${namespaceKey}::${node ?? \"\"}::${runId ?? messageId}`;\n}\n\nfunction toChatModelStreamEvent(event: MessagesEvent): ChatModelStreamEvent {\n return event.params.data as unknown as ChatModelStreamEvent;\n}\n\n/**\n * Incrementally assembles `messages` events into complete message objects.\n */\nexport class MessageAssembler {\n private readonly activeMessages = new Map<string, AssembledMessage>();\n private readonly activeByNamespaceNode = new Map<string, string>();\n private readonly blockIndexByProtocolIndexAndType = new Map<string, number>();\n\n /**\n * Applies a single message event and returns the resulting assembly update.\n *\n * Returns `undefined` when the event changes nothing, such as a delta\n * variant this version doesn't recognise. Those are ignored so that a\n * newer producer can't break the stream; `content-block-finish` still\n * carries the complete block.\n *\n * @param event - Incoming `messages` event to fold into the assembler state.\n */\n consume(event: MessagesEvent): MessageAssemblyUpdate | undefined {\n const data = event.params.data;\n const namespaceNodeKey = `${event.params.namespace.join(\"/\")}::${event.params.node ?? \"\"}`;\n const runId = readRunId(data);\n\n if (data.event === \"message-start\") {\n const key = messageKeyFor(event);\n this.activeByNamespaceNode.set(namespaceNodeKey, key);\n const message: AssembledMessage = {\n id: data.id,\n namespace: [...event.params.namespace],\n node: event.params.node,\n runId,\n usage: readUsage(data),\n metadata: data.metadata,\n blocks: [],\n };\n this.activeMessages.set(key, message);\n return { kind: \"message-start\", key, message, event };\n }\n\n const runKey = runId != null ? `${namespaceNodeKey}::${runId}` : undefined;\n const fallbackKey = this.activeByNamespaceNode.get(namespaceNodeKey);\n const fallbackMessage =\n fallbackKey != null ? this.activeMessages.get(fallbackKey) : undefined;\n const activeKey =\n (runKey != null && this.activeMessages.has(runKey)\n ? runKey\n : undefined) ??\n (runId == null || fallbackMessage?.runId == null\n ? fallbackKey\n : undefined);\n if (!activeKey) {\n // A continuation event (delta/finish/error) arrived without a\n // prior `message-start`. This can happen on late-attaching\n // subscriptions when the server has already trimmed the\n // `message-start` from its replay buffer. Synthesize a minimal\n // active message so the assembler can still fold subsequent\n // events instead of hard-failing the caller.\n const syntheticKey = runKey ?? `${namespaceNodeKey}::`;\n this.activeByNamespaceNode.set(namespaceNodeKey, syntheticKey);\n const synthetic: AssembledMessage = {\n id: data.id,\n namespace: [...event.params.namespace],\n node: event.params.node,\n runId,\n blocks: [],\n };\n this.activeMessages.set(syntheticKey, synthetic);\n return this.consume(event);\n }\n\n const message = this.activeMessages.get(activeKey);\n if (!message) {\n throw new Error(`No active message state found for key ${activeKey}`);\n }\n\n if ((data as { event?: string }).event === \"usage\") {\n message.usage = (data as { usage?: UsageInfo }).usage;\n return {\n kind: \"usage\",\n key: activeKey,\n message,\n event,\n };\n }\n\n switch (data.event) {\n case \"content-block-start\": {\n message.blocks[data.index] = cloneBlock(data.content);\n this.blockIndexByProtocolIndexAndType.set(\n blockIndexKey(activeKey, data.index, data.content.type),\n data.index\n );\n return {\n kind: \"content-block-start\",\n key: activeKey,\n message,\n index: data.index,\n block: data.content,\n event,\n };\n }\n case \"content-block-delta\": {\n const deltaEvent = data as typeof data & {\n content?: ContentBlock;\n delta?: ContentBlockDelta;\n };\n if (deltaEvent.content == null && deltaEvent.delta == null) {\n throw new Error(\"Received content-block-delta without content\");\n }\n const deltaBlock =\n deltaEvent.content ??\n blockFromDelta(deltaEvent.delta!, message.blocks[data.index]);\n if (deltaBlock == null) return undefined;\n const targetIndex = this.resolveBlockIndex(\n activeKey,\n message.blocks,\n data.index,\n deltaBlock.type\n );\n const current = message.blocks[targetIndex];\n message.blocks[targetIndex] =\n deltaEvent.content != null\n ? current == null\n ? cloneBlock(deltaEvent.content)\n : applyContentDelta(current, deltaEvent.content)\n : (applyCoreEventDelta(\n current as CoreContentBlock | undefined,\n data as unknown as ContentBlockDeltaEvent\n ) as unknown as ContentBlock);\n return {\n kind: \"content-block-delta\",\n key: activeKey,\n message,\n index: targetIndex,\n block: deltaBlock,\n event,\n };\n }\n case \"content-block-finish\": {\n const targetIndex = this.resolveFinishBlockIndex(\n activeKey,\n data.index,\n data.content.type\n );\n message.blocks[targetIndex] = cloneBlock(data.content);\n return {\n kind: \"content-block-finish\",\n key: activeKey,\n message,\n index: targetIndex,\n block: data.content,\n event,\n };\n }\n case \"message-finish\": {\n message.usage = readUsage(data) ?? message.usage;\n message.finishMetadata = readFinishMetadata(data);\n message.finishReason = data.reason;\n this.clearActiveMessage(activeKey, namespaceNodeKey);\n this.clearBlockIndexAliases(activeKey);\n return {\n kind: \"message-finish\",\n key: activeKey,\n message: structuredClone(message),\n event,\n };\n }\n case \"error\": {\n message.error = { message: data.message, code: data.code };\n this.clearActiveMessage(activeKey, namespaceNodeKey);\n this.clearBlockIndexAliases(activeKey);\n return {\n kind: \"message-error\",\n key: activeKey,\n message: structuredClone(message),\n event,\n };\n }\n }\n }\n\n /**\n * Drop every message that started but never got `message-finish` or\n * `error`, e.g. because the run was cancelled mid-stream.\n *\n * @param namespace - Only abandon messages at or below this namespace.\n * @returns The abandoned messages.\n */\n abandonActive(namespace?: readonly string[]): AssembledMessage[] {\n const abandoned: AssembledMessage[] = [];\n for (const [key, message] of this.activeMessages) {\n if (\n namespace != null &&\n !hasNamespacePrefix(message.namespace, namespace)\n )\n continue;\n abandoned.push(message);\n this.activeMessages.delete(key);\n this.clearBlockIndexAliases(key);\n for (const [nsNode, activeKey] of this.activeByNamespaceNode) {\n if (activeKey === key) this.activeByNamespaceNode.delete(nsNode);\n }\n }\n return abandoned;\n }\n\n private clearActiveMessage(\n activeKey: string,\n namespaceNodeKey: string\n ): void {\n this.activeMessages.delete(activeKey);\n if (this.activeByNamespaceNode.get(namespaceNodeKey) === activeKey) {\n this.activeByNamespaceNode.delete(namespaceNodeKey);\n }\n }\n\n private resolveBlockIndex(\n activeKey: string,\n blocks: ContentBlock[],\n protocolIndex: number,\n blockType: string\n ): number {\n const current = blocks[protocolIndex];\n if (\n current == null ||\n current.type === blockType ||\n areCompatibleBlockTypes(current.type, blockType)\n ) {\n this.blockIndexByProtocolIndexAndType.set(\n blockIndexKey(activeKey, protocolIndex, blockType),\n protocolIndex\n );\n return protocolIndex;\n }\n\n const key = blockIndexKey(activeKey, protocolIndex, blockType);\n const existing = this.blockIndexByProtocolIndexAndType.get(key);\n if (existing != null) return existing;\n\n const nextIndex = blocks.length;\n this.blockIndexByProtocolIndexAndType.set(key, nextIndex);\n return nextIndex;\n }\n\n private resolveFinishBlockIndex(\n activeKey: string,\n protocolIndex: number,\n blockType: string\n ): number {\n const key = blockIndexKey(activeKey, protocolIndex, blockType);\n const existing = this.blockIndexByProtocolIndexAndType.get(key);\n if (existing != null) return existing;\n\n this.blockIndexByProtocolIndexAndType.set(key, protocolIndex);\n return protocolIndex;\n }\n\n private clearBlockIndexAliases(activeKey: string): void {\n const prefix = `${activeKey}::`;\n for (const key of this.blockIndexByProtocolIndexAndType.keys()) {\n if (key.startsWith(prefix))\n this.blockIndexByProtocolIndexAndType.delete(key);\n }\n }\n}\n\nfunction hasNamespacePrefix(\n namespace: readonly string[],\n prefix: readonly string[]\n): boolean {\n return prefix.every((segment, i) => namespace[i] === segment);\n}\n\nfunction blockIndexKey(\n activeKey: string,\n protocolIndex: number,\n blockType: string\n): string {\n return `${activeKey}::${protocolIndex}::${blockType}`;\n}\n\nfunction areCompatibleBlockTypes(\n currentType: string,\n nextType: string\n): boolean {\n const toolCallTypes = new Set([\n \"tool_call\",\n \"tool_call_chunk\",\n \"tool_use\",\n \"input_json_delta\",\n ]);\n const serverToolCallTypes = new Set([\n \"server_tool_call\",\n \"server_tool_call_chunk\",\n ]);\n\n return (\n (toolCallTypes.has(currentType) && toolCallTypes.has(nextType)) ||\n (serverToolCallTypes.has(currentType) && serverToolCallTypes.has(nextType))\n );\n}\n\n/**\n * Assembles `messages` events into {@link StreamingMessage} instances\n * with live text/reasoning delta streams, matching the in-process\n * `ChatModelStream` dual-interface pattern.\n */\nexport class StreamingMessageAssembler {\n readonly #assembler = new MessageAssembler();\n readonly #activeStreaming = new Map<string, StreamingMessage>();\n\n /**\n * Folds a single event and returns a new {@link StreamingMessage}\n * when a `message-start` is seen, or `undefined` for continuation\n * events (deltas, finish, error).\n */\n consume(event: MessagesEvent): StreamingMessage | undefined {\n const update = this.#assembler.consume(event);\n if (update == null) return undefined;\n\n switch (update.kind) {\n case \"message-start\": {\n const streaming = new StreamingMessage(update.message);\n streaming[UPDATE_CONTEXT](update.event);\n streaming[PUSH_EVENT](toChatModelStreamEvent(update.event));\n this.#activeStreaming.set(update.key, streaming);\n return streaming;\n }\n case \"content-block-start\": {\n const streaming = this.#activeStreaming.get(update.key);\n if (streaming) {\n streaming[UPDATE_CONTEXT](update.event);\n streaming[PUSH_EVENT](toChatModelStreamEvent(update.event));\n }\n if (\n streaming &&\n update.block.type === \"text\" &&\n \"text\" in update.block &&\n update.block.text\n ) {\n streaming[PUSH_TEXT](update.block.text);\n }\n if (\n streaming &&\n update.block.type === \"reasoning\" &&\n \"reasoning\" in update.block &&\n update.block.reasoning\n ) {\n streaming[PUSH_REASONING](update.block.reasoning);\n }\n return undefined;\n }\n case \"content-block-delta\": {\n const streaming = this.#activeStreaming.get(update.key);\n if (!streaming) return undefined;\n streaming[UPDATE_CONTEXT](update.event);\n streaming[PUSH_EVENT](toChatModelStreamEvent(update.event));\n if (update.block.type === \"text\" && \"text\" in update.block) {\n streaming[PUSH_TEXT](update.block.text);\n }\n if (update.block.type === \"reasoning\" && \"reasoning\" in update.block) {\n streaming[PUSH_REASONING](update.block.reasoning);\n }\n return undefined;\n }\n case \"content-block-finish\": {\n const streaming = this.#activeStreaming.get(update.key);\n if (streaming) {\n streaming[UPDATE_CONTEXT](update.event);\n streaming[PUSH_EVENT](toChatModelStreamEvent(update.event));\n }\n return undefined;\n }\n case \"usage\": {\n const streaming = this.#activeStreaming.get(update.key);\n if (streaming) {\n streaming[UPDATE_CONTEXT](update.event);\n streaming[PUSH_EVENT](toChatModelStreamEvent(update.event));\n }\n return undefined;\n }\n case \"message-finish\": {\n const streaming = this.#activeStreaming.get(update.key);\n if (streaming) {\n streaming[UPDATE_CONTEXT](update.event);\n streaming[PUSH_EVENT](toChatModelStreamEvent(update.event));\n streaming[FINISH]();\n this.#activeStreaming.delete(update.key);\n }\n return undefined;\n }\n case \"message-error\": {\n const streaming = this.#activeStreaming.get(update.key);\n if (streaming) {\n streaming[UPDATE_CONTEXT](update.event);\n streaming[PUSH_EVENT](toChatModelStreamEvent(update.event));\n streaming[ERROR]();\n this.#activeStreaming.delete(update.key);\n }\n return undefined;\n }\n }\n }\n\n /**\n * Settle every message that never finished, marking it with an\n * `aborted` error so awaiting consumers don't hang.\n *\n * @param namespace - Only abandon messages at or below this namespace.\n * @returns The abandoned messages.\n */\n abandonActive(namespace?: readonly string[]): StreamingMessage[] {\n this.#assembler.abandonActive(namespace);\n const abandoned: StreamingMessage[] = [];\n for (const [key, streaming] of this.#activeStreaming) {\n if (\n namespace != null &&\n !hasNamespacePrefix(streaming.namespace, namespace)\n )\n continue;\n streaming.assembled.error = {\n message: \"Message stream ended before message-finish\",\n code: \"aborted\",\n };\n streaming[ERROR]();\n this.#activeStreaming.delete(key);\n abandoned.push(streaming);\n }\n return abandoned;\n }\n}\n"],"mappings":"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"}
|
|
@@ -186,6 +186,21 @@ var StreamController = class {
|
|
|
186
186
|
* from the newly-started run and must be accepted.
|
|
187
187
|
*/
|
|
188
188
|
#interruptReplayThroughSeq;
|
|
189
|
+
/**
|
|
190
|
+
* Command whose barrier is still to be found on the thread stream. The
|
|
191
|
+
* agent server answers HTTP commands from a fresh per-request manager,
|
|
192
|
+
* so `applied_through_seq` is 0 while the stream replays the whole
|
|
193
|
+
* history with positive seqs. The barrier is then the event before the
|
|
194
|
+
* `running` event of the run the command started: `run.start` names that
|
|
195
|
+
* run, and a resume starts the first root run after the answered
|
|
196
|
+
* interrupts were last requested. Unknown interrupts stay buffered until
|
|
197
|
+
* it is found.
|
|
198
|
+
*/
|
|
199
|
+
#awaitingRunBoundary;
|
|
200
|
+
/** Seq of each root run's `running` event, keyed by run id. */
|
|
201
|
+
#rootRunStartSeqs = /* @__PURE__ */ new Map();
|
|
202
|
+
/** Highest seq at which each interrupt was requested. */
|
|
203
|
+
#interruptRequestSeqs = /* @__PURE__ */ new Map();
|
|
189
204
|
/** Unknown inputs waiting to be classified as live or replayed history. */
|
|
190
205
|
#pendingHydrationInterruptEvents = [];
|
|
191
206
|
#settleParkedInterruptsPromise;
|
|
@@ -351,6 +366,7 @@ var StreamController = class {
|
|
|
351
366
|
awaitResumedRunTerminal: (signal) => this.#awaitResumedRunTerminal(signal),
|
|
352
367
|
onSubmitStart: () => {
|
|
353
368
|
this.#submitGeneration += 1;
|
|
369
|
+
this.#awaitingRunBoundary = void 0;
|
|
354
370
|
this.#interruptCommandPending = this.#hydratedActiveInterruptIds != null;
|
|
355
371
|
this.#pendingInterruptEvents = this.#pendingHydrationInterruptEvents;
|
|
356
372
|
this.#pendingHydrationInterruptEvents = [];
|
|
@@ -362,11 +378,12 @@ var StreamController = class {
|
|
|
362
378
|
for (const release of [...this.#heldLifecycleReleases]) release();
|
|
363
379
|
},
|
|
364
380
|
onRunCreated: (runId) => {
|
|
365
|
-
this.#advanceInterruptReplayBarrier();
|
|
381
|
+
this.#advanceInterruptReplayBarrier({ runId });
|
|
366
382
|
this.#notifyCreated(runId);
|
|
367
383
|
},
|
|
368
384
|
onRunCompleted: (reason, runId) => this.#notifyCompleted(reason, runId),
|
|
369
385
|
onRunEnd: () => {
|
|
386
|
+
this.#abandonRunBoundary();
|
|
370
387
|
this.#interruptCommandPending = false;
|
|
371
388
|
this.#markLocalRunEnd();
|
|
372
389
|
},
|
|
@@ -1100,7 +1117,7 @@ var StreamController = class {
|
|
|
1100
1117
|
config: options?.config,
|
|
1101
1118
|
metadata: options?.metadata
|
|
1102
1119
|
});
|
|
1103
|
-
this.#advanceInterruptReplayBarrier();
|
|
1120
|
+
this.#advanceInterruptReplayBarrier({ answeredInterruptIds: [resolved.interruptId] });
|
|
1104
1121
|
this.#markInterruptResolvedInRootStore(resolved.interruptId);
|
|
1105
1122
|
}, prepared?.handle);
|
|
1106
1123
|
} catch (error) {
|
|
@@ -1171,7 +1188,7 @@ var StreamController = class {
|
|
|
1171
1188
|
config: options?.config,
|
|
1172
1189
|
metadata: options?.metadata
|
|
1173
1190
|
});
|
|
1174
|
-
this.#advanceInterruptReplayBarrier();
|
|
1191
|
+
this.#advanceInterruptReplayBarrier({ answeredInterruptIds: responses.map((r) => r.interrupt_id) });
|
|
1175
1192
|
for (const { interrupt_id: interruptId } of responses) this.#markInterruptResolvedInRootStore(interruptId);
|
|
1176
1193
|
}, prepared?.handle);
|
|
1177
1194
|
} catch (error) {
|
|
@@ -1391,6 +1408,9 @@ var StreamController = class {
|
|
|
1391
1408
|
this.#hydratedActiveInterruptIds = null;
|
|
1392
1409
|
this.#hydratedCheckpointTime = void 0;
|
|
1393
1410
|
this.#interruptReplayThroughSeq = void 0;
|
|
1411
|
+
this.#awaitingRunBoundary = void 0;
|
|
1412
|
+
this.#rootRunStartSeqs.clear();
|
|
1413
|
+
this.#interruptRequestSeqs.clear();
|
|
1394
1414
|
this.#pendingHydrationInterruptEvents = [];
|
|
1395
1415
|
this.#discardPendingInterruptEvents();
|
|
1396
1416
|
this.queueStore.setState(() => require_queue_adapter.EMPTY_QUEUE);
|
|
@@ -1607,10 +1627,70 @@ var StreamController = class {
|
|
|
1607
1627
|
* consumer. `ThreadStream.interrupts` is updated in parallel for
|
|
1608
1628
|
* resume targeting.
|
|
1609
1629
|
*/
|
|
1630
|
+
this.#observeRunBoundary(event);
|
|
1610
1631
|
this.#recordInterrupt(event);
|
|
1611
1632
|
this.#settleParkedInterruptsOnTerminal(event);
|
|
1612
1633
|
}
|
|
1613
1634
|
/**
|
|
1635
|
+
* Remember where each root run starts and where each interrupt was last
|
|
1636
|
+
* requested, then try to place a pending command barrier. Both the
|
|
1637
|
+
* content pump and the lifecycle watcher replay the same tape with the
|
|
1638
|
+
* same seqs, so recording either copy is enough.
|
|
1639
|
+
*/
|
|
1640
|
+
#observeRunBoundary(event) {
|
|
1641
|
+
const { seq } = event;
|
|
1642
|
+
if (typeof seq !== "number") return;
|
|
1643
|
+
if (event.method === "input.requested") {
|
|
1644
|
+
const id = event.params.data?.interrupt_id;
|
|
1645
|
+
if (typeof id !== "string") return;
|
|
1646
|
+
if (seq <= (this.#interruptRequestSeqs.get(id) ?? -1)) return;
|
|
1647
|
+
this.#interruptRequestSeqs.set(id, seq);
|
|
1648
|
+
} else if (event.method === "lifecycle" && require_namespace.isRootNamespace(event.params.namespace) && event.params.data?.event === "running") {
|
|
1649
|
+
const runId = synthesizedEventRunId(event.event_id);
|
|
1650
|
+
if (runId == null || this.#rootRunStartSeqs.has(runId)) return;
|
|
1651
|
+
this.#rootRunStartSeqs.set(runId, seq);
|
|
1652
|
+
} else return;
|
|
1653
|
+
this.#resolveRunBoundary();
|
|
1654
|
+
}
|
|
1655
|
+
/**
|
|
1656
|
+
* Place the barrier of a command that reported `applied_through_seq: 0`
|
|
1657
|
+
* once its run's `running` event has been seen, then classify the
|
|
1658
|
+
* interrupts buffered while it was unknown.
|
|
1659
|
+
*/
|
|
1660
|
+
#resolveRunBoundary() {
|
|
1661
|
+
const command = this.#awaitingRunBoundary;
|
|
1662
|
+
if (command == null) return;
|
|
1663
|
+
let runStartSeq;
|
|
1664
|
+
if ("runId" in command) runStartSeq = this.#rootRunStartSeqs.get(command.runId);
|
|
1665
|
+
else {
|
|
1666
|
+
let lastRequested = -1;
|
|
1667
|
+
for (const id of command.answeredInterruptIds) {
|
|
1668
|
+
const seq = this.#interruptRequestSeqs.get(id);
|
|
1669
|
+
if (seq == null) return;
|
|
1670
|
+
lastRequested = Math.max(lastRequested, seq);
|
|
1671
|
+
}
|
|
1672
|
+
for (const seq of this.#rootRunStartSeqs.values()) if (seq > lastRequested && (runStartSeq == null || seq < runStartSeq)) runStartSeq = seq;
|
|
1673
|
+
}
|
|
1674
|
+
if (runStartSeq == null) return;
|
|
1675
|
+
this.#awaitingRunBoundary = void 0;
|
|
1676
|
+
this.#interruptReplayThroughSeq = runStartSeq - 1;
|
|
1677
|
+
this.#interruptCommandPending = false;
|
|
1678
|
+
this.#flushPendingInterruptEvents();
|
|
1679
|
+
}
|
|
1680
|
+
/**
|
|
1681
|
+
* Give up on a barrier whose run never showed up on the stream: a run
|
|
1682
|
+
* cancelled before it started, or a resume whose answered interrupts
|
|
1683
|
+
* were trimmed from the tape. Stop buffering and let the parked
|
|
1684
|
+
* interrupt state check decide what was held.
|
|
1685
|
+
*/
|
|
1686
|
+
#abandonRunBoundary() {
|
|
1687
|
+
if (this.#awaitingRunBoundary == null) return;
|
|
1688
|
+
this.#awaitingRunBoundary = void 0;
|
|
1689
|
+
this.#interruptCommandPending = false;
|
|
1690
|
+
this.#flushPendingInterruptEvents();
|
|
1691
|
+
this.#settleParkedInterrupts();
|
|
1692
|
+
}
|
|
1693
|
+
/**
|
|
1614
1694
|
* Process one root-pump event and update all root projections.
|
|
1615
1695
|
*
|
|
1616
1696
|
* @param event - Event yielded by the root subscription.
|
|
@@ -1902,24 +1982,38 @@ var StreamController = class {
|
|
|
1902
1982
|
* Convert the hydrate-time allowlist into a replay barrier after a command
|
|
1903
1983
|
* is accepted. Built-in transports update `lastAppliedThroughSeq` from the
|
|
1904
1984
|
* command response before resolving `submitRun` / `respondInput`.
|
|
1985
|
+
*
|
|
1986
|
+
* @param command - The run the command started, used to find the barrier
|
|
1987
|
+
* on the thread stream when the response reports
|
|
1988
|
+
* `applied_through_seq: 0`.
|
|
1905
1989
|
*/
|
|
1906
|
-
#advanceInterruptReplayBarrier() {
|
|
1990
|
+
#advanceInterruptReplayBarrier(command) {
|
|
1907
1991
|
if (this.#hydratedActiveInterruptIds == null) {
|
|
1908
1992
|
this.#discardPendingInterruptEvents();
|
|
1909
1993
|
return;
|
|
1910
1994
|
}
|
|
1911
1995
|
const throughSeq = this.#thread?.ordering?.lastAppliedThroughSeq;
|
|
1996
|
+
if (throughSeq === 0 && command != null) {
|
|
1997
|
+
this.#awaitingRunBoundary = command;
|
|
1998
|
+
this.#resolveRunBoundary();
|
|
1999
|
+
return;
|
|
2000
|
+
}
|
|
1912
2001
|
if (typeof throughSeq === "number") this.#interruptReplayThroughSeq = throughSeq;
|
|
1913
2002
|
else {
|
|
1914
2003
|
this.#hydratedActiveInterruptIds = null;
|
|
1915
2004
|
this.#interruptReplayThroughSeq = void 0;
|
|
1916
2005
|
}
|
|
1917
2006
|
this.#interruptCommandPending = false;
|
|
2007
|
+
this.#flushPendingInterruptEvents();
|
|
2008
|
+
}
|
|
2009
|
+
/** Classify the interrupts buffered while a command was in flight. */
|
|
2010
|
+
#flushPendingInterruptEvents() {
|
|
1918
2011
|
const pendingEvents = this.#pendingInterruptEvents;
|
|
1919
2012
|
this.#pendingInterruptEvents = [];
|
|
1920
2013
|
for (const event of pendingEvents) this.#recordInterrupt(event);
|
|
1921
2014
|
}
|
|
1922
2015
|
#discardPendingInterruptEvents() {
|
|
2016
|
+
this.#awaitingRunBoundary = void 0;
|
|
1923
2017
|
this.#interruptCommandPending = false;
|
|
1924
2018
|
this.#pendingInterruptEvents = [];
|
|
1925
2019
|
}
|
|
@@ -2069,7 +2163,9 @@ var StreamController = class {
|
|
|
2069
2163
|
* `stream.interrupts` empty while the checkpoint still has siblings.
|
|
2070
2164
|
*/
|
|
2071
2165
|
async #awaitResumedRunTerminal(signal) {
|
|
2166
|
+
const generation = this.#submitGeneration;
|
|
2072
2167
|
const terminal = await this.#awaitRootTerminal(signal, { skipInterruptedUntilRunning: true });
|
|
2168
|
+
if (this.#submitGeneration === generation) this.#abandonRunBoundary();
|
|
2073
2169
|
if (!signal.aborted && !this.#disposed && (terminal.event === "interrupted" || terminal.event === "completed")) await this.#reconcilePendingInterruptsFromServer();
|
|
2074
2170
|
return terminal;
|
|
2075
2171
|
}
|