@langchain/core 1.1.40-dev-1777576880340 → 1.1.40-dev-1777587649451
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/language_models/base.cjs +1 -1
- package/dist/language_models/base.js +1 -1
- package/dist/language_models/compat.cjs +147 -0
- package/dist/language_models/compat.cjs.map +1 -1
- package/dist/language_models/compat.d.cts.map +1 -1
- package/dist/language_models/compat.d.ts.map +1 -1
- package/dist/language_models/compat.js +147 -0
- package/dist/language_models/compat.js.map +1 -1
- package/dist/language_models/stream.cjs +25 -1
- package/dist/language_models/stream.cjs.map +1 -1
- package/dist/language_models/stream.d.cts.map +1 -1
- package/dist/language_models/stream.d.ts.map +1 -1
- package/dist/language_models/stream.js +25 -1
- package/dist/language_models/stream.js.map +1 -1
- package/package.json +1 -1
|
@@ -139,7 +139,7 @@ var BaseLangChain = class extends require_base.Runnable {
|
|
|
139
139
|
this.callbacks = params.callbacks;
|
|
140
140
|
this.tags = params.tags ?? [];
|
|
141
141
|
this.metadata = params.metadata ?? {};
|
|
142
|
-
this._addVersion("@langchain/core", "1.1.40-dev-
|
|
142
|
+
this._addVersion("@langchain/core", "1.1.40-dev-1777587649451");
|
|
143
143
|
}
|
|
144
144
|
_addVersion(pkg, version) {
|
|
145
145
|
const existing = this.metadata?.versions;
|
|
@@ -138,7 +138,7 @@ var BaseLangChain = class extends Runnable {
|
|
|
138
138
|
this.callbacks = params.callbacks;
|
|
139
139
|
this.tags = params.tags ?? [];
|
|
140
140
|
this.metadata = params.metadata ?? {};
|
|
141
|
-
this._addVersion("@langchain/core", "1.1.40-dev-
|
|
141
|
+
this._addVersion("@langchain/core", "1.1.40-dev-1777587649451");
|
|
142
142
|
}
|
|
143
143
|
_addVersion(pkg, version) {
|
|
144
144
|
const existing = this.metadata?.versions;
|
|
@@ -13,6 +13,72 @@ var compat_exports = /* @__PURE__ */ require_runtime.__exportAll({
|
|
|
13
13
|
convertChunksToEvents: () => convertChunksToEvents,
|
|
14
14
|
finalizeContentBlock: () => finalizeContentBlock
|
|
15
15
|
});
|
|
16
|
+
const MIME_TYPE_BY_AUDIO_FORMAT = {
|
|
17
|
+
wav: "audio/wav",
|
|
18
|
+
mp3: "audio/mpeg",
|
|
19
|
+
flac: "audio/flac",
|
|
20
|
+
opus: "audio/opus",
|
|
21
|
+
aac: "audio/aac",
|
|
22
|
+
pcm16: "audio/pcm"
|
|
23
|
+
};
|
|
24
|
+
const MIME_TYPE_BY_IMAGE_FORMAT = {
|
|
25
|
+
png: "image/png",
|
|
26
|
+
jpeg: "image/jpeg",
|
|
27
|
+
jpg: "image/jpeg",
|
|
28
|
+
webp: "image/webp",
|
|
29
|
+
gif: "image/gif"
|
|
30
|
+
};
|
|
31
|
+
function nextBlockIndex(activeBlocks) {
|
|
32
|
+
let next = 0;
|
|
33
|
+
for (const index of activeBlocks.keys()) if (index >= next) next = index + 1;
|
|
34
|
+
return next;
|
|
35
|
+
}
|
|
36
|
+
function getAdditionalKwargs(message) {
|
|
37
|
+
const additional = message.additional_kwargs;
|
|
38
|
+
return additional != null && typeof additional === "object" ? additional : {};
|
|
39
|
+
}
|
|
40
|
+
function extractImageBlocksFromToolOutputs(message) {
|
|
41
|
+
const toolOutputs = getAdditionalKwargs(message).tool_outputs;
|
|
42
|
+
if (!Array.isArray(toolOutputs)) return [];
|
|
43
|
+
const blocks = [];
|
|
44
|
+
for (const entry of toolOutputs) {
|
|
45
|
+
if (entry == null || typeof entry !== "object") continue;
|
|
46
|
+
const record = entry;
|
|
47
|
+
if (record.type !== "image_generation_call") continue;
|
|
48
|
+
const data = typeof record.result === "string" ? record.result : void 0;
|
|
49
|
+
const url = typeof record.url === "string" ? record.url : void 0;
|
|
50
|
+
if (data == null && url == null) continue;
|
|
51
|
+
const outputFormat = typeof record.output_format === "string" ? record.output_format.toLowerCase() : void 0;
|
|
52
|
+
const mimeType = (outputFormat != null ? MIME_TYPE_BY_IMAGE_FORMAT[outputFormat] : void 0) ?? "image/png";
|
|
53
|
+
blocks.push({
|
|
54
|
+
type: "image",
|
|
55
|
+
...typeof record.id === "string" ? { id: record.id } : {},
|
|
56
|
+
...url != null ? { url } : {},
|
|
57
|
+
...data != null ? { data } : {},
|
|
58
|
+
mimeType
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return blocks;
|
|
62
|
+
}
|
|
63
|
+
function getAudioPayload(message) {
|
|
64
|
+
const audio = getAdditionalKwargs(message).audio;
|
|
65
|
+
if (audio == null || typeof audio !== "object") return void 0;
|
|
66
|
+
const record = audio;
|
|
67
|
+
const data = typeof record.data === "string" ? record.data : void 0;
|
|
68
|
+
const url = typeof record.url === "string" ? record.url : void 0;
|
|
69
|
+
const transcript = typeof record.transcript === "string" ? record.transcript : void 0;
|
|
70
|
+
if (data == null && url == null && transcript == null) return void 0;
|
|
71
|
+
const explicitMimeType = typeof record.mime_type === "string" ? record.mime_type : typeof record.mimeType === "string" ? record.mimeType : void 0;
|
|
72
|
+
const format = typeof record.format === "string" ? record.format.toLowerCase() : void 0;
|
|
73
|
+
const mimeType = explicitMimeType ?? (format != null ? MIME_TYPE_BY_AUDIO_FORMAT[format] : void 0) ?? (data != null ? "audio/wav" : "audio/pcm");
|
|
74
|
+
return {
|
|
75
|
+
...typeof record.id === "string" ? { id: record.id } : {},
|
|
76
|
+
...data != null ? { data } : {},
|
|
77
|
+
...url != null ? { url } : {},
|
|
78
|
+
...transcript != null ? { transcript } : {},
|
|
79
|
+
mimeType
|
|
80
|
+
};
|
|
81
|
+
}
|
|
16
82
|
/**
|
|
17
83
|
* Convert an async iterable of legacy `ChatGenerationChunk`s into
|
|
18
84
|
* `ChatModelStreamEvent`s with typed deltas.
|
|
@@ -21,6 +87,8 @@ async function* convertChunksToEvents(chunks, options) {
|
|
|
21
87
|
const activeBlocks = /* @__PURE__ */ new Map();
|
|
22
88
|
let messageStarted = false;
|
|
23
89
|
let lastUsage;
|
|
90
|
+
let audioStream;
|
|
91
|
+
const emittedImageKeys = /* @__PURE__ */ new Set();
|
|
24
92
|
for await (const chunk of chunks) {
|
|
25
93
|
options?.signal?.throwIfAborted();
|
|
26
94
|
const msg = chunk.message;
|
|
@@ -132,6 +200,85 @@ async function* convertChunksToEvents(chunks, options) {
|
|
|
132
200
|
}
|
|
133
201
|
};
|
|
134
202
|
}
|
|
203
|
+
const audioPayload = getAudioPayload(msg);
|
|
204
|
+
if (audioPayload != null) {
|
|
205
|
+
if (audioStream == null) {
|
|
206
|
+
const index = nextBlockIndex(activeBlocks);
|
|
207
|
+
audioStream = {
|
|
208
|
+
index,
|
|
209
|
+
id: audioPayload.id,
|
|
210
|
+
mimeType: audioPayload.mimeType,
|
|
211
|
+
transcript: ""
|
|
212
|
+
};
|
|
213
|
+
const initial = {
|
|
214
|
+
type: "audio",
|
|
215
|
+
...audioPayload.id != null ? { id: audioPayload.id } : {},
|
|
216
|
+
...audioPayload.url != null ? { url: audioPayload.url } : {},
|
|
217
|
+
data: "",
|
|
218
|
+
mimeType: audioPayload.mimeType
|
|
219
|
+
};
|
|
220
|
+
activeBlocks.set(index, {
|
|
221
|
+
type: "audio",
|
|
222
|
+
accumulated: initial
|
|
223
|
+
});
|
|
224
|
+
yield {
|
|
225
|
+
event: "content-block-start",
|
|
226
|
+
index,
|
|
227
|
+
content: initial
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
const activeAudio = activeBlocks.get(audioStream.index);
|
|
231
|
+
if (activeAudio != null) {
|
|
232
|
+
const accumulated = activeAudio.accumulated;
|
|
233
|
+
if (audioPayload.id != null && audioStream.id == null) {
|
|
234
|
+
audioStream.id = audioPayload.id;
|
|
235
|
+
accumulated.id = audioPayload.id;
|
|
236
|
+
}
|
|
237
|
+
if (audioPayload.transcript != null) {
|
|
238
|
+
audioStream.transcript += audioPayload.transcript;
|
|
239
|
+
accumulated.transcript = audioStream.transcript;
|
|
240
|
+
yield {
|
|
241
|
+
event: "content-block-delta",
|
|
242
|
+
index: audioStream.index,
|
|
243
|
+
delta: {
|
|
244
|
+
type: "block-delta",
|
|
245
|
+
fields: {
|
|
246
|
+
type: "audio",
|
|
247
|
+
transcript: audioStream.transcript
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
if (audioPayload.data != null && audioPayload.data.length > 0) {
|
|
253
|
+
accumulated.data = (accumulated.data ?? "") + audioPayload.data;
|
|
254
|
+
yield {
|
|
255
|
+
event: "content-block-delta",
|
|
256
|
+
index: audioStream.index,
|
|
257
|
+
delta: {
|
|
258
|
+
type: "data-delta",
|
|
259
|
+
data: audioPayload.data,
|
|
260
|
+
encoding: "base64"
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
for (const imageBlock of extractImageBlocksFromToolOutputs(msg)) {
|
|
267
|
+
const imageRecord = imageBlock;
|
|
268
|
+
const imageKey = imageRecord.id ?? imageRecord.url ?? (imageRecord.data != null ? `${imageRecord.data.length}:${imageRecord.data.slice(0, 32)}` : void 0);
|
|
269
|
+
if (imageKey != null && emittedImageKeys.has(imageKey)) continue;
|
|
270
|
+
if (imageKey != null) emittedImageKeys.add(imageKey);
|
|
271
|
+
const index = nextBlockIndex(activeBlocks);
|
|
272
|
+
activeBlocks.set(index, {
|
|
273
|
+
type: "image",
|
|
274
|
+
accumulated: imageBlock
|
|
275
|
+
});
|
|
276
|
+
yield {
|
|
277
|
+
event: "content-block-start",
|
|
278
|
+
index,
|
|
279
|
+
content: imageBlock
|
|
280
|
+
};
|
|
281
|
+
}
|
|
135
282
|
if (!usageHandledInStart && require_ai.isAIMessageChunk(msg) && msg.usage_metadata) {
|
|
136
283
|
const chunkUsage = msg.usage_metadata;
|
|
137
284
|
if (!lastUsage) lastUsage = { ...chunkUsage };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compat.cjs","names":["isAIMessageChunk"],"sources":["../../src/language_models/compat.ts"],"sourcesContent":["/**\n * Compatibility bridge: converts legacy `_streamResponseChunks`\n * (`ChatGenerationChunk` / `AIMessageChunk`) output to the new\n * `ChatModelStreamEvent` protocol.\n *\n * @module\n */\n\nimport { isAIMessageChunk } from \"../messages/ai.js\";\nimport type { ContentBlock } from \"../messages/content/index.js\";\nimport type { ChatGenerationChunk } from \"../outputs.js\";\nimport type { ChatModelStreamEvent, ContentBlockDelta } from \"./event.js\";\n\n/**\n * Convert an async iterable of legacy `ChatGenerationChunk`s into\n * `ChatModelStreamEvent`s with typed deltas.\n */\nexport async function* convertChunksToEvents(\n chunks: AsyncIterable<ChatGenerationChunk>,\n options?: { signal?: AbortSignal }\n): AsyncGenerator<ChatModelStreamEvent> {\n const activeBlocks = new Map<\n number,\n { type: string; accumulated: ContentBlock }\n >();\n let messageStarted = false;\n let lastUsage:\n | { input_tokens: number; output_tokens: number; total_tokens: number }\n | undefined;\n\n for await (const chunk of chunks) {\n options?.signal?.throwIfAborted();\n\n const msg = chunk.message;\n\n // Message start\n let usageHandledInStart = false;\n if (!messageStarted) {\n messageStarted = true;\n const startEvent: ChatModelStreamEvent = {\n event: \"message-start\" as const,\n id: msg.id ?? undefined,\n };\n if (isAIMessageChunk(msg) && msg.usage_metadata) {\n (startEvent as { usage?: unknown }).usage = msg.usage_metadata;\n lastUsage = { ...msg.usage_metadata };\n usageHandledInStart = true;\n }\n yield startEvent;\n }\n\n // Process content\n const content = msg.content;\n if (typeof content === \"string\") {\n if (content !== \"\") {\n const blockIndex = 0;\n if (!activeBlocks.has(blockIndex)) {\n const initial: ContentBlock.Text = { type: \"text\", text: \"\" };\n activeBlocks.set(blockIndex, {\n type: \"text\",\n accumulated: initial,\n });\n yield {\n event: \"content-block-start\" as const,\n index: blockIndex,\n content: initial,\n };\n }\n const block = activeBlocks.get(blockIndex)!;\n block.accumulated = {\n ...block.accumulated,\n text: ((block.accumulated as { text?: string }).text ?? \"\") + content,\n };\n yield {\n event: \"content-block-delta\" as const,\n index: blockIndex,\n delta: { type: \"text-delta\" as const, text: content },\n };\n }\n } else if (Array.isArray(content)) {\n for (const part of content) {\n const blockIndex =\n typeof part.index === \"number\" ? part.index : activeBlocks.size;\n\n if (!activeBlocks.has(blockIndex)) {\n activeBlocks.set(blockIndex, {\n type: part.type,\n accumulated: { ...part },\n });\n yield {\n event: \"content-block-start\" as const,\n index: blockIndex,\n content: { ...part },\n };\n } else {\n const block = activeBlocks.get(blockIndex)!;\n const delta = contentBlockToDelta(part);\n block.accumulated = applyDeltaToBlock(block.accumulated, delta);\n yield {\n event: \"content-block-delta\" as const,\n index: blockIndex,\n delta,\n };\n }\n }\n }\n\n // Tool call chunks\n if (\n isAIMessageChunk(msg) &&\n msg.tool_call_chunks &&\n msg.tool_call_chunks.length > 0\n ) {\n for (const toolChunk of msg.tool_call_chunks) {\n const blockIndex =\n typeof toolChunk.index === \"number\"\n ? toolChunk.index\n : activeBlocks.size;\n\n if (!activeBlocks.has(blockIndex)) {\n const initial: ContentBlock = {\n type: \"tool_call_chunk\" as const,\n id: toolChunk.id,\n name: toolChunk.name,\n args: \"\",\n index: blockIndex,\n };\n activeBlocks.set(blockIndex, {\n type: \"tool_call_chunk\",\n accumulated: initial,\n });\n yield {\n event: \"content-block-start\" as const,\n index: blockIndex,\n content: initial,\n };\n }\n\n // Accumulate tool call args internally, emit incremental content chunks.\n const block = activeBlocks.get(blockIndex)!;\n const acc = block.accumulated as {\n args?: string;\n id?: string;\n name?: string;\n };\n if (toolChunk.id != null) acc.id = toolChunk.id;\n if (toolChunk.name != null) acc.name = toolChunk.name;\n acc.args = (acc.args ?? \"\") + (toolChunk.args ?? \"\");\n yield {\n event: \"content-block-delta\" as const,\n index: blockIndex,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(\"id\" in acc && acc.id != null ? { id: acc.id } : {}),\n ...(\"name\" in acc && acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n }\n }\n\n // Usage\n if (!usageHandledInStart && isAIMessageChunk(msg) && msg.usage_metadata) {\n const chunkUsage = msg.usage_metadata;\n if (!lastUsage) {\n lastUsage = { ...chunkUsage };\n } else {\n lastUsage = {\n input_tokens: lastUsage.input_tokens + chunkUsage.input_tokens,\n output_tokens: lastUsage.output_tokens + chunkUsage.output_tokens,\n total_tokens: lastUsage.total_tokens + chunkUsage.total_tokens,\n };\n }\n yield { event: \"usage\" as const, usage: { ...lastUsage } };\n }\n }\n\n // Finish all blocks\n for (const [index, block] of activeBlocks) {\n const finalized = finalizeContentBlock(block.accumulated);\n yield {\n event: \"content-block-finish\" as const,\n index,\n content: finalized,\n };\n }\n\n yield {\n event: \"message-finish\" as const,\n reason: \"stop\" as const,\n ...(lastUsage ? { usage: lastUsage } : {}),\n };\n}\n\n/**\n * Apply a typed delta to an accumulated content block.\n * @internal\n */\nfunction applyDeltaToBlock(\n block: ContentBlock,\n delta: ContentBlockDelta\n): ContentBlock {\n switch (delta.type) {\n case \"text-delta\":\n return {\n ...block,\n text: ((block as { text?: string }).text ?? \"\") + delta.text,\n } as ContentBlock;\n case \"reasoning-delta\":\n if ((block as { type?: string }).type === \"thinking\") {\n return {\n ...block,\n thinking:\n ((block as { thinking?: string }).thinking ?? \"\") + delta.reasoning,\n } as unknown as ContentBlock;\n }\n return {\n ...block,\n reasoning:\n ((block as { reasoning?: string }).reasoning ?? \"\") + delta.reasoning,\n } as ContentBlock;\n case \"data-delta\":\n return {\n ...block,\n data: ((block as { data?: string }).data ?? \"\") + delta.data,\n } as ContentBlock;\n case \"block-delta\":\n return { ...block, ...delta.fields } as ContentBlock;\n default:\n throw new Error(`Unknown delta type: ${JSON.stringify(delta)}`);\n }\n}\n\nfunction contentBlockToDelta(block: ContentBlock): ContentBlockDelta {\n if (block.type === \"text\") {\n return { type: \"text-delta\", text: (block as ContentBlock.Text).text };\n }\n if (block.type === \"reasoning\") {\n return {\n type: \"reasoning-delta\",\n reasoning: (block as ContentBlock.Reasoning).reasoning,\n };\n }\n if (\n (block as { type?: string }).type === \"thinking\" &&\n typeof (block as { thinking?: unknown }).thinking === \"string\"\n ) {\n return {\n type: \"reasoning-delta\",\n reasoning: (block as unknown as { thinking: string }).thinking,\n };\n }\n if (typeof (block as { data?: unknown }).data === \"string\") {\n return {\n type: \"data-delta\",\n data: (block as unknown as { data: string }).data,\n encoding: \"base64\",\n };\n }\n if (typeof (block as { type?: unknown }).type === \"string\") {\n return {\n type: \"block-delta\",\n fields: {\n ...(block as unknown as { type: string } & Record<string, unknown>),\n },\n };\n }\n\n throw new Error(`Unsupported content block delta: ${JSON.stringify(block)}`);\n}\n\n/**\n * Finalize a content block for the finish event.\n * For tool calls, parse the accumulated JSON args string.\n */\nexport function finalizeContentBlock(block: ContentBlock): ContentBlock {\n if (block.type === \"tool_call_chunk\") {\n const chunk = block as ContentBlock.Tools.ToolCallChunk;\n let parsedArgs: unknown;\n try {\n parsedArgs = JSON.parse(chunk.args ?? \"{}\");\n } catch {\n return {\n type: \"invalid_tool_call\" as const,\n id: chunk.id,\n name: chunk.name,\n args: chunk.args,\n error: \"Failed to parse tool call arguments as JSON\",\n } as ContentBlock.Tools.InvalidToolCall;\n }\n return {\n type: \"tool_call\" as const,\n id: chunk.id,\n name: chunk.name!,\n args: parsedArgs,\n } as ContentBlock.Tools.ToolCall;\n }\n\n return block;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compat.cjs","names":["isAIMessageChunk"],"sources":["../../src/language_models/compat.ts"],"sourcesContent":["/**\n * Compatibility bridge: converts legacy `_streamResponseChunks`\n * (`ChatGenerationChunk` / `AIMessageChunk`) output to the new\n * `ChatModelStreamEvent` protocol.\n *\n * @module\n */\n\nimport { isAIMessageChunk } from \"../messages/ai.js\";\nimport type { ContentBlock } from \"../messages/content/index.js\";\nimport type { ChatGenerationChunk } from \"../outputs.js\";\nimport type { ChatModelStreamEvent, ContentBlockDelta } from \"./event.js\";\n\nconst MIME_TYPE_BY_AUDIO_FORMAT: Record<string, string> = {\n wav: \"audio/wav\",\n mp3: \"audio/mpeg\",\n flac: \"audio/flac\",\n opus: \"audio/opus\",\n aac: \"audio/aac\",\n pcm16: \"audio/pcm\",\n};\n\nconst MIME_TYPE_BY_IMAGE_FORMAT: Record<string, string> = {\n png: \"image/png\",\n jpeg: \"image/jpeg\",\n jpg: \"image/jpeg\",\n webp: \"image/webp\",\n gif: \"image/gif\",\n};\n\ntype AudioStreamState = {\n index: number;\n id?: string;\n mimeType: string;\n transcript: string;\n};\n\nfunction nextBlockIndex(activeBlocks: Map<number, unknown>): number {\n let next = 0;\n for (const index of activeBlocks.keys()) {\n if (index >= next) next = index + 1;\n }\n return next;\n}\n\nfunction getAdditionalKwargs(message: unknown): Record<string, unknown> {\n const additional = (message as { additional_kwargs?: unknown })\n .additional_kwargs;\n return additional != null && typeof additional === \"object\"\n ? (additional as Record<string, unknown>)\n : {};\n}\n\nfunction extractImageBlocksFromToolOutputs(message: unknown): ContentBlock[] {\n const toolOutputs = getAdditionalKwargs(message).tool_outputs;\n if (!Array.isArray(toolOutputs)) return [];\n\n const blocks: ContentBlock[] = [];\n for (const entry of toolOutputs) {\n if (entry == null || typeof entry !== \"object\") continue;\n const record = entry as Record<string, unknown>;\n if (record.type !== \"image_generation_call\") continue;\n\n const data = typeof record.result === \"string\" ? record.result : undefined;\n const url = typeof record.url === \"string\" ? record.url : undefined;\n if (data == null && url == null) continue;\n\n const outputFormat =\n typeof record.output_format === \"string\"\n ? record.output_format.toLowerCase()\n : undefined;\n const mimeType =\n (outputFormat != null\n ? MIME_TYPE_BY_IMAGE_FORMAT[outputFormat]\n : undefined) ?? \"image/png\";\n\n blocks.push({\n type: \"image\",\n ...(typeof record.id === \"string\" ? { id: record.id } : {}),\n ...(url != null ? { url } : {}),\n ...(data != null ? { data } : {}),\n mimeType,\n } as ContentBlock);\n }\n return blocks;\n}\n\nfunction getAudioPayload(message: unknown):\n | {\n id?: string;\n data?: string;\n url?: string;\n transcript?: string;\n mimeType: string;\n }\n | undefined {\n const audio = getAdditionalKwargs(message).audio;\n if (audio == null || typeof audio !== \"object\") return undefined;\n const record = audio as Record<string, unknown>;\n\n const data = typeof record.data === \"string\" ? record.data : undefined;\n const url = typeof record.url === \"string\" ? record.url : undefined;\n const transcript =\n typeof record.transcript === \"string\" ? record.transcript : undefined;\n if (data == null && url == null && transcript == null) return undefined;\n\n const explicitMimeType =\n typeof record.mime_type === \"string\"\n ? record.mime_type\n : typeof record.mimeType === \"string\"\n ? record.mimeType\n : undefined;\n const format =\n typeof record.format === \"string\" ? record.format.toLowerCase() : undefined;\n const mimeType =\n explicitMimeType ??\n (format != null ? MIME_TYPE_BY_AUDIO_FORMAT[format] : undefined) ??\n (data != null ? \"audio/wav\" : \"audio/pcm\");\n\n return {\n ...(typeof record.id === \"string\" ? { id: record.id } : {}),\n ...(data != null ? { data } : {}),\n ...(url != null ? { url } : {}),\n ...(transcript != null ? { transcript } : {}),\n mimeType,\n };\n}\n\n/**\n * Convert an async iterable of legacy `ChatGenerationChunk`s into\n * `ChatModelStreamEvent`s with typed deltas.\n */\nexport async function* convertChunksToEvents(\n chunks: AsyncIterable<ChatGenerationChunk>,\n options?: { signal?: AbortSignal }\n): AsyncGenerator<ChatModelStreamEvent> {\n const activeBlocks = new Map<\n number,\n { type: string; accumulated: ContentBlock }\n >();\n let messageStarted = false;\n let lastUsage:\n | { input_tokens: number; output_tokens: number; total_tokens: number }\n | undefined;\n let audioStream: AudioStreamState | undefined;\n const emittedImageKeys = new Set<string>();\n\n for await (const chunk of chunks) {\n options?.signal?.throwIfAborted();\n\n const msg = chunk.message;\n\n // Message start\n let usageHandledInStart = false;\n if (!messageStarted) {\n messageStarted = true;\n const startEvent: ChatModelStreamEvent = {\n event: \"message-start\" as const,\n id: msg.id ?? undefined,\n };\n if (isAIMessageChunk(msg) && msg.usage_metadata) {\n (startEvent as { usage?: unknown }).usage = msg.usage_metadata;\n lastUsage = { ...msg.usage_metadata };\n usageHandledInStart = true;\n }\n yield startEvent;\n }\n\n // Process content\n const content = msg.content;\n if (typeof content === \"string\") {\n if (content !== \"\") {\n const blockIndex = 0;\n if (!activeBlocks.has(blockIndex)) {\n const initial: ContentBlock.Text = { type: \"text\", text: \"\" };\n activeBlocks.set(blockIndex, {\n type: \"text\",\n accumulated: initial,\n });\n yield {\n event: \"content-block-start\" as const,\n index: blockIndex,\n content: initial,\n };\n }\n const block = activeBlocks.get(blockIndex)!;\n block.accumulated = {\n ...block.accumulated,\n text: ((block.accumulated as { text?: string }).text ?? \"\") + content,\n };\n yield {\n event: \"content-block-delta\" as const,\n index: blockIndex,\n delta: { type: \"text-delta\" as const, text: content },\n };\n }\n } else if (Array.isArray(content)) {\n for (const part of content) {\n const blockIndex =\n typeof part.index === \"number\" ? part.index : activeBlocks.size;\n\n if (!activeBlocks.has(blockIndex)) {\n activeBlocks.set(blockIndex, {\n type: part.type,\n accumulated: { ...part },\n });\n yield {\n event: \"content-block-start\" as const,\n index: blockIndex,\n content: { ...part },\n };\n } else {\n const block = activeBlocks.get(blockIndex)!;\n const delta = contentBlockToDelta(part);\n block.accumulated = applyDeltaToBlock(block.accumulated, delta);\n yield {\n event: \"content-block-delta\" as const,\n index: blockIndex,\n delta,\n };\n }\n }\n }\n\n // Tool call chunks\n if (\n isAIMessageChunk(msg) &&\n msg.tool_call_chunks &&\n msg.tool_call_chunks.length > 0\n ) {\n for (const toolChunk of msg.tool_call_chunks) {\n const blockIndex =\n typeof toolChunk.index === \"number\"\n ? toolChunk.index\n : activeBlocks.size;\n\n if (!activeBlocks.has(blockIndex)) {\n const initial: ContentBlock = {\n type: \"tool_call_chunk\" as const,\n id: toolChunk.id,\n name: toolChunk.name,\n args: \"\",\n index: blockIndex,\n };\n activeBlocks.set(blockIndex, {\n type: \"tool_call_chunk\",\n accumulated: initial,\n });\n yield {\n event: \"content-block-start\" as const,\n index: blockIndex,\n content: initial,\n };\n }\n\n // Accumulate tool call args internally, emit incremental content chunks.\n const block = activeBlocks.get(blockIndex)!;\n const acc = block.accumulated as {\n args?: string;\n id?: string;\n name?: string;\n };\n if (toolChunk.id != null) acc.id = toolChunk.id;\n if (toolChunk.name != null) acc.name = toolChunk.name;\n acc.args = (acc.args ?? \"\") + (toolChunk.args ?? \"\");\n yield {\n event: \"content-block-delta\" as const,\n index: blockIndex,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(\"id\" in acc && acc.id != null ? { id: acc.id } : {}),\n ...(\"name\" in acc && acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n }\n }\n\n const audioPayload = getAudioPayload(msg);\n if (audioPayload != null) {\n if (audioStream == null) {\n const index = nextBlockIndex(activeBlocks);\n audioStream = {\n index,\n id: audioPayload.id,\n mimeType: audioPayload.mimeType,\n transcript: \"\",\n };\n const initial = {\n type: \"audio\",\n ...(audioPayload.id != null ? { id: audioPayload.id } : {}),\n ...(audioPayload.url != null ? { url: audioPayload.url } : {}),\n data: \"\",\n mimeType: audioPayload.mimeType,\n } as ContentBlock;\n activeBlocks.set(index, {\n type: \"audio\",\n accumulated: initial,\n });\n yield {\n event: \"content-block-start\" as const,\n index,\n content: initial,\n };\n }\n\n const activeAudio = activeBlocks.get(audioStream.index);\n if (activeAudio != null) {\n const accumulated = activeAudio.accumulated as ContentBlock & {\n data?: string;\n transcript?: string;\n };\n if (audioPayload.id != null && audioStream.id == null) {\n audioStream.id = audioPayload.id;\n (accumulated as { id?: string }).id = audioPayload.id;\n }\n if (audioPayload.transcript != null) {\n audioStream.transcript += audioPayload.transcript;\n accumulated.transcript = audioStream.transcript;\n yield {\n event: \"content-block-delta\" as const,\n index: audioStream.index,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"audio\",\n transcript: audioStream.transcript,\n },\n },\n };\n }\n if (audioPayload.data != null && audioPayload.data.length > 0) {\n accumulated.data = (accumulated.data ?? \"\") + audioPayload.data;\n yield {\n event: \"content-block-delta\" as const,\n index: audioStream.index,\n delta: {\n type: \"data-delta\" as const,\n data: audioPayload.data,\n encoding: \"base64\" as const,\n },\n };\n }\n }\n }\n\n for (const imageBlock of extractImageBlocksFromToolOutputs(msg)) {\n const imageRecord = imageBlock as ContentBlock & {\n id?: string;\n url?: string;\n data?: string;\n };\n const imageKey =\n imageRecord.id ??\n imageRecord.url ??\n (imageRecord.data != null\n ? `${imageRecord.data.length}:${imageRecord.data.slice(0, 32)}`\n : undefined);\n if (imageKey != null && emittedImageKeys.has(imageKey)) continue;\n if (imageKey != null) emittedImageKeys.add(imageKey);\n\n const index = nextBlockIndex(activeBlocks);\n activeBlocks.set(index, {\n type: \"image\",\n accumulated: imageBlock,\n });\n yield {\n event: \"content-block-start\" as const,\n index,\n content: imageBlock,\n };\n }\n\n // Usage\n if (!usageHandledInStart && isAIMessageChunk(msg) && msg.usage_metadata) {\n const chunkUsage = msg.usage_metadata;\n if (!lastUsage) {\n lastUsage = { ...chunkUsage };\n } else {\n lastUsage = {\n input_tokens: lastUsage.input_tokens + chunkUsage.input_tokens,\n output_tokens: lastUsage.output_tokens + chunkUsage.output_tokens,\n total_tokens: lastUsage.total_tokens + chunkUsage.total_tokens,\n };\n }\n yield { event: \"usage\" as const, usage: { ...lastUsage } };\n }\n }\n\n // Finish all blocks\n for (const [index, block] of activeBlocks) {\n const finalized = finalizeContentBlock(block.accumulated);\n yield {\n event: \"content-block-finish\" as const,\n index,\n content: finalized,\n };\n }\n\n yield {\n event: \"message-finish\" as const,\n reason: \"stop\" as const,\n ...(lastUsage ? { usage: lastUsage } : {}),\n };\n}\n\n/**\n * Apply a typed delta to an accumulated content block.\n * @internal\n */\nfunction applyDeltaToBlock(\n block: ContentBlock,\n delta: ContentBlockDelta\n): ContentBlock {\n switch (delta.type) {\n case \"text-delta\":\n return {\n ...block,\n text: ((block as { text?: string }).text ?? \"\") + delta.text,\n } as ContentBlock;\n case \"reasoning-delta\":\n if ((block as { type?: string }).type === \"thinking\") {\n return {\n ...block,\n thinking:\n ((block as { thinking?: string }).thinking ?? \"\") + delta.reasoning,\n } as unknown as ContentBlock;\n }\n return {\n ...block,\n reasoning:\n ((block as { reasoning?: string }).reasoning ?? \"\") + delta.reasoning,\n } as ContentBlock;\n case \"data-delta\":\n return {\n ...block,\n data: ((block as { data?: string }).data ?? \"\") + delta.data,\n } as ContentBlock;\n case \"block-delta\":\n return { ...block, ...delta.fields } as ContentBlock;\n default:\n throw new Error(`Unknown delta type: ${JSON.stringify(delta)}`);\n }\n}\n\nfunction contentBlockToDelta(block: ContentBlock): ContentBlockDelta {\n if (block.type === \"text\") {\n return { type: \"text-delta\", text: (block as ContentBlock.Text).text };\n }\n if (block.type === \"reasoning\") {\n return {\n type: \"reasoning-delta\",\n reasoning: (block as ContentBlock.Reasoning).reasoning,\n };\n }\n if (\n (block as { type?: string }).type === \"thinking\" &&\n typeof (block as { thinking?: unknown }).thinking === \"string\"\n ) {\n return {\n type: \"reasoning-delta\",\n reasoning: (block as unknown as { thinking: string }).thinking,\n };\n }\n if (typeof (block as { data?: unknown }).data === \"string\") {\n return {\n type: \"data-delta\",\n data: (block as unknown as { data: string }).data,\n encoding: \"base64\",\n };\n }\n if (typeof (block as { type?: unknown }).type === \"string\") {\n return {\n type: \"block-delta\",\n fields: {\n ...(block as unknown as { type: string } & Record<string, unknown>),\n },\n };\n }\n\n throw new Error(`Unsupported content block delta: ${JSON.stringify(block)}`);\n}\n\n/**\n * Finalize a content block for the finish event.\n * For tool calls, parse the accumulated JSON args string.\n */\nexport function finalizeContentBlock(block: ContentBlock): ContentBlock {\n if (block.type === \"tool_call_chunk\") {\n const chunk = block as ContentBlock.Tools.ToolCallChunk;\n let parsedArgs: unknown;\n try {\n parsedArgs = JSON.parse(chunk.args ?? \"{}\");\n } catch {\n return {\n type: \"invalid_tool_call\" as const,\n id: chunk.id,\n name: chunk.name,\n args: chunk.args,\n error: \"Failed to parse tool call arguments as JSON\",\n } as ContentBlock.Tools.InvalidToolCall;\n }\n return {\n type: \"tool_call\" as const,\n id: chunk.id,\n name: chunk.name!,\n args: parsedArgs,\n } as ContentBlock.Tools.ToolCall;\n }\n\n return block;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAaA,MAAM,4BAAoD;CACxD,KAAK;CACL,KAAK;CACL,MAAM;CACN,MAAM;CACN,KAAK;CACL,OAAO;CACR;AAED,MAAM,4BAAoD;CACxD,KAAK;CACL,MAAM;CACN,KAAK;CACL,MAAM;CACN,KAAK;CACN;AASD,SAAS,eAAe,cAA4C;CAClE,IAAI,OAAO;AACX,MAAK,MAAM,SAAS,aAAa,MAAM,CACrC,KAAI,SAAS,KAAM,QAAO,QAAQ;AAEpC,QAAO;;AAGT,SAAS,oBAAoB,SAA2C;CACtE,MAAM,aAAc,QACjB;AACH,QAAO,cAAc,QAAQ,OAAO,eAAe,WAC9C,aACD,EAAE;;AAGR,SAAS,kCAAkC,SAAkC;CAC3E,MAAM,cAAc,oBAAoB,QAAQ,CAAC;AACjD,KAAI,CAAC,MAAM,QAAQ,YAAY,CAAE,QAAO,EAAE;CAE1C,MAAM,SAAyB,EAAE;AACjC,MAAK,MAAM,SAAS,aAAa;AAC/B,MAAI,SAAS,QAAQ,OAAO,UAAU,SAAU;EAChD,MAAM,SAAS;AACf,MAAI,OAAO,SAAS,wBAAyB;EAE7C,MAAM,OAAO,OAAO,OAAO,WAAW,WAAW,OAAO,SAAS,KAAA;EACjE,MAAM,MAAM,OAAO,OAAO,QAAQ,WAAW,OAAO,MAAM,KAAA;AAC1D,MAAI,QAAQ,QAAQ,OAAO,KAAM;EAEjC,MAAM,eACJ,OAAO,OAAO,kBAAkB,WAC5B,OAAO,cAAc,aAAa,GAClC,KAAA;EACN,MAAM,YACH,gBAAgB,OACb,0BAA0B,gBAC1B,KAAA,MAAc;AAEpB,SAAO,KAAK;GACV,MAAM;GACN,GAAI,OAAO,OAAO,OAAO,WAAW,EAAE,IAAI,OAAO,IAAI,GAAG,EAAE;GAC1D,GAAI,OAAO,OAAO,EAAE,KAAK,GAAG,EAAE;GAC9B,GAAI,QAAQ,OAAO,EAAE,MAAM,GAAG,EAAE;GAChC;GACD,CAAiB;;AAEpB,QAAO;;AAGT,SAAS,gBAAgB,SAQX;CACZ,MAAM,QAAQ,oBAAoB,QAAQ,CAAC;AAC3C,KAAI,SAAS,QAAQ,OAAO,UAAU,SAAU,QAAO,KAAA;CACvD,MAAM,SAAS;CAEf,MAAM,OAAO,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO,KAAA;CAC7D,MAAM,MAAM,OAAO,OAAO,QAAQ,WAAW,OAAO,MAAM,KAAA;CAC1D,MAAM,aACJ,OAAO,OAAO,eAAe,WAAW,OAAO,aAAa,KAAA;AAC9D,KAAI,QAAQ,QAAQ,OAAO,QAAQ,cAAc,KAAM,QAAO,KAAA;CAE9D,MAAM,mBACJ,OAAO,OAAO,cAAc,WACxB,OAAO,YACP,OAAO,OAAO,aAAa,WACzB,OAAO,WACP,KAAA;CACR,MAAM,SACJ,OAAO,OAAO,WAAW,WAAW,OAAO,OAAO,aAAa,GAAG,KAAA;CACpE,MAAM,WACJ,qBACC,UAAU,OAAO,0BAA0B,UAAU,KAAA,OACrD,QAAQ,OAAO,cAAc;AAEhC,QAAO;EACL,GAAI,OAAO,OAAO,OAAO,WAAW,EAAE,IAAI,OAAO,IAAI,GAAG,EAAE;EAC1D,GAAI,QAAQ,OAAO,EAAE,MAAM,GAAG,EAAE;EAChC,GAAI,OAAO,OAAO,EAAE,KAAK,GAAG,EAAE;EAC9B,GAAI,cAAc,OAAO,EAAE,YAAY,GAAG,EAAE;EAC5C;EACD;;;;;;AAOH,gBAAuB,sBACrB,QACA,SACsC;CACtC,MAAM,+BAAe,IAAI,KAGtB;CACH,IAAI,iBAAiB;CACrB,IAAI;CAGJ,IAAI;CACJ,MAAM,mCAAmB,IAAI,KAAa;AAE1C,YAAW,MAAM,SAAS,QAAQ;AAChC,WAAS,QAAQ,gBAAgB;EAEjC,MAAM,MAAM,MAAM;EAGlB,IAAI,sBAAsB;AAC1B,MAAI,CAAC,gBAAgB;AACnB,oBAAiB;GACjB,MAAM,aAAmC;IACvC,OAAO;IACP,IAAI,IAAI,MAAM,KAAA;IACf;AACD,OAAIA,WAAAA,iBAAiB,IAAI,IAAI,IAAI,gBAAgB;AAC9C,eAAmC,QAAQ,IAAI;AAChD,gBAAY,EAAE,GAAG,IAAI,gBAAgB;AACrC,0BAAsB;;AAExB,SAAM;;EAIR,MAAM,UAAU,IAAI;AACpB,MAAI,OAAO,YAAY;OACjB,YAAY,IAAI;IAClB,MAAM,aAAa;AACnB,QAAI,CAAC,aAAa,IAAI,WAAW,EAAE;KACjC,MAAM,UAA6B;MAAE,MAAM;MAAQ,MAAM;MAAI;AAC7D,kBAAa,IAAI,YAAY;MAC3B,MAAM;MACN,aAAa;MACd,CAAC;AACF,WAAM;MACJ,OAAO;MACP,OAAO;MACP,SAAS;MACV;;IAEH,MAAM,QAAQ,aAAa,IAAI,WAAW;AAC1C,UAAM,cAAc;KAClB,GAAG,MAAM;KACT,OAAQ,MAAM,YAAkC,QAAQ,MAAM;KAC/D;AACD,UAAM;KACJ,OAAO;KACP,OAAO;KACP,OAAO;MAAE,MAAM;MAAuB,MAAM;MAAS;KACtD;;aAEM,MAAM,QAAQ,QAAQ,CAC/B,MAAK,MAAM,QAAQ,SAAS;GAC1B,MAAM,aACJ,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,aAAa;AAE7D,OAAI,CAAC,aAAa,IAAI,WAAW,EAAE;AACjC,iBAAa,IAAI,YAAY;KAC3B,MAAM,KAAK;KACX,aAAa,EAAE,GAAG,MAAM;KACzB,CAAC;AACF,UAAM;KACJ,OAAO;KACP,OAAO;KACP,SAAS,EAAE,GAAG,MAAM;KACrB;UACI;IACL,MAAM,QAAQ,aAAa,IAAI,WAAW;IAC1C,MAAM,QAAQ,oBAAoB,KAAK;AACvC,UAAM,cAAc,kBAAkB,MAAM,aAAa,MAAM;AAC/D,UAAM;KACJ,OAAO;KACP,OAAO;KACP;KACD;;;AAMP,MACEA,WAAAA,iBAAiB,IAAI,IACrB,IAAI,oBACJ,IAAI,iBAAiB,SAAS,EAE9B,MAAK,MAAM,aAAa,IAAI,kBAAkB;GAC5C,MAAM,aACJ,OAAO,UAAU,UAAU,WACvB,UAAU,QACV,aAAa;AAEnB,OAAI,CAAC,aAAa,IAAI,WAAW,EAAE;IACjC,MAAM,UAAwB;KAC5B,MAAM;KACN,IAAI,UAAU;KACd,MAAM,UAAU;KAChB,MAAM;KACN,OAAO;KACR;AACD,iBAAa,IAAI,YAAY;KAC3B,MAAM;KACN,aAAa;KACd,CAAC;AACF,UAAM;KACJ,OAAO;KACP,OAAO;KACP,SAAS;KACV;;GAKH,MAAM,MADQ,aAAa,IAAI,WAAW,CACxB;AAKlB,OAAI,UAAU,MAAM,KAAM,KAAI,KAAK,UAAU;AAC7C,OAAI,UAAU,QAAQ,KAAM,KAAI,OAAO,UAAU;AACjD,OAAI,QAAQ,IAAI,QAAQ,OAAO,UAAU,QAAQ;AACjD,SAAM;IACJ,OAAO;IACP,OAAO;IACP,OAAO;KACL,MAAM;KACN,QAAQ;MACN,MAAM;MACN,GAAI,QAAQ,OAAO,IAAI,MAAM,OAAO,EAAE,IAAI,IAAI,IAAI,GAAG,EAAE;MACvD,GAAI,UAAU,OAAO,IAAI,QAAQ,OAAO,EAAE,MAAM,IAAI,MAAM,GAAG,EAAE;MAC/D,MAAM,IAAI;MACX;KACF;IACF;;EAIL,MAAM,eAAe,gBAAgB,IAAI;AACzC,MAAI,gBAAgB,MAAM;AACxB,OAAI,eAAe,MAAM;IACvB,MAAM,QAAQ,eAAe,aAAa;AAC1C,kBAAc;KACZ;KACA,IAAI,aAAa;KACjB,UAAU,aAAa;KACvB,YAAY;KACb;IACD,MAAM,UAAU;KACd,MAAM;KACN,GAAI,aAAa,MAAM,OAAO,EAAE,IAAI,aAAa,IAAI,GAAG,EAAE;KAC1D,GAAI,aAAa,OAAO,OAAO,EAAE,KAAK,aAAa,KAAK,GAAG,EAAE;KAC7D,MAAM;KACN,UAAU,aAAa;KACxB;AACD,iBAAa,IAAI,OAAO;KACtB,MAAM;KACN,aAAa;KACd,CAAC;AACF,UAAM;KACJ,OAAO;KACP;KACA,SAAS;KACV;;GAGH,MAAM,cAAc,aAAa,IAAI,YAAY,MAAM;AACvD,OAAI,eAAe,MAAM;IACvB,MAAM,cAAc,YAAY;AAIhC,QAAI,aAAa,MAAM,QAAQ,YAAY,MAAM,MAAM;AACrD,iBAAY,KAAK,aAAa;AAC7B,iBAAgC,KAAK,aAAa;;AAErD,QAAI,aAAa,cAAc,MAAM;AACnC,iBAAY,cAAc,aAAa;AACvC,iBAAY,aAAa,YAAY;AACrC,WAAM;MACJ,OAAO;MACP,OAAO,YAAY;MACnB,OAAO;OACL,MAAM;OACN,QAAQ;QACN,MAAM;QACN,YAAY,YAAY;QACzB;OACF;MACF;;AAEH,QAAI,aAAa,QAAQ,QAAQ,aAAa,KAAK,SAAS,GAAG;AAC7D,iBAAY,QAAQ,YAAY,QAAQ,MAAM,aAAa;AAC3D,WAAM;MACJ,OAAO;MACP,OAAO,YAAY;MACnB,OAAO;OACL,MAAM;OACN,MAAM,aAAa;OACnB,UAAU;OACX;MACF;;;;AAKP,OAAK,MAAM,cAAc,kCAAkC,IAAI,EAAE;GAC/D,MAAM,cAAc;GAKpB,MAAM,WACJ,YAAY,MACZ,YAAY,QACX,YAAY,QAAQ,OACjB,GAAG,YAAY,KAAK,OAAO,GAAG,YAAY,KAAK,MAAM,GAAG,GAAG,KAC3D,KAAA;AACN,OAAI,YAAY,QAAQ,iBAAiB,IAAI,SAAS,CAAE;AACxD,OAAI,YAAY,KAAM,kBAAiB,IAAI,SAAS;GAEpD,MAAM,QAAQ,eAAe,aAAa;AAC1C,gBAAa,IAAI,OAAO;IACtB,MAAM;IACN,aAAa;IACd,CAAC;AACF,SAAM;IACJ,OAAO;IACP;IACA,SAAS;IACV;;AAIH,MAAI,CAAC,uBAAuBA,WAAAA,iBAAiB,IAAI,IAAI,IAAI,gBAAgB;GACvE,MAAM,aAAa,IAAI;AACvB,OAAI,CAAC,UACH,aAAY,EAAE,GAAG,YAAY;OAE7B,aAAY;IACV,cAAc,UAAU,eAAe,WAAW;IAClD,eAAe,UAAU,gBAAgB,WAAW;IACpD,cAAc,UAAU,eAAe,WAAW;IACnD;AAEH,SAAM;IAAE,OAAO;IAAkB,OAAO,EAAE,GAAG,WAAW;IAAE;;;AAK9D,MAAK,MAAM,CAAC,OAAO,UAAU,aAE3B,OAAM;EACJ,OAAO;EACP;EACA,SAJgB,qBAAqB,MAAM,YAAY;EAKxD;AAGH,OAAM;EACJ,OAAO;EACP,QAAQ;EACR,GAAI,YAAY,EAAE,OAAO,WAAW,GAAG,EAAE;EAC1C;;;;;;AAOH,SAAS,kBACP,OACA,OACc;AACd,SAAQ,MAAM,MAAd;EACE,KAAK,aACH,QAAO;GACL,GAAG;GACH,OAAQ,MAA4B,QAAQ,MAAM,MAAM;GACzD;EACH,KAAK;AACH,OAAK,MAA4B,SAAS,WACxC,QAAO;IACL,GAAG;IACH,WACI,MAAgC,YAAY,MAAM,MAAM;IAC7D;AAEH,UAAO;IACL,GAAG;IACH,YACI,MAAiC,aAAa,MAAM,MAAM;IAC/D;EACH,KAAK,aACH,QAAO;GACL,GAAG;GACH,OAAQ,MAA4B,QAAQ,MAAM,MAAM;GACzD;EACH,KAAK,cACH,QAAO;GAAE,GAAG;GAAO,GAAG,MAAM;GAAQ;EACtC,QACE,OAAM,IAAI,MAAM,uBAAuB,KAAK,UAAU,MAAM,GAAG;;;AAIrE,SAAS,oBAAoB,OAAwC;AACnE,KAAI,MAAM,SAAS,OACjB,QAAO;EAAE,MAAM;EAAc,MAAO,MAA4B;EAAM;AAExE,KAAI,MAAM,SAAS,YACjB,QAAO;EACL,MAAM;EACN,WAAY,MAAiC;EAC9C;AAEH,KACG,MAA4B,SAAS,cACtC,OAAQ,MAAiC,aAAa,SAEtD,QAAO;EACL,MAAM;EACN,WAAY,MAA0C;EACvD;AAEH,KAAI,OAAQ,MAA6B,SAAS,SAChD,QAAO;EACL,MAAM;EACN,MAAO,MAAsC;EAC7C,UAAU;EACX;AAEH,KAAI,OAAQ,MAA6B,SAAS,SAChD,QAAO;EACL,MAAM;EACN,QAAQ,EACN,GAAI,OACL;EACF;AAGH,OAAM,IAAI,MAAM,oCAAoC,KAAK,UAAU,MAAM,GAAG;;;;;;AAO9E,SAAgB,qBAAqB,OAAmC;AACtE,KAAI,MAAM,SAAS,mBAAmB;EACpC,MAAM,QAAQ;EACd,IAAI;AACJ,MAAI;AACF,gBAAa,KAAK,MAAM,MAAM,QAAQ,KAAK;UACrC;AACN,UAAO;IACL,MAAM;IACN,IAAI,MAAM;IACV,MAAM,MAAM;IACZ,MAAM,MAAM;IACZ,OAAO;IACR;;AAEH,SAAO;GACL,MAAM;GACN,IAAI,MAAM;GACV,MAAM,MAAM;GACZ,MAAM;GACP;;AAGH,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compat.d.cts","names":[],"sources":["../../src/language_models/compat.ts"],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"compat.d.cts","names":[],"sources":["../../src/language_models/compat.ts"],"mappings":";;;;;;;;;iBAoIuB,qBAAA,CACrB,MAAA,EAAQ,aAAA,CAAc,mBAAA,GACtB,OAAA;EAAY,MAAA,GAAS,WAAA;AAAA,IACpB,cAAA,CAAe,oBAAA;;;;;iBAmWF,oBAAA,CAAqB,KAAA,EAAO,YAAA,GAAe,YAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compat.d.ts","names":[],"sources":["../../src/language_models/compat.ts"],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"compat.d.ts","names":[],"sources":["../../src/language_models/compat.ts"],"mappings":";;;;;;;;;iBAoIuB,qBAAA,CACrB,MAAA,EAAQ,aAAA,CAAc,mBAAA,GACtB,OAAA;EAAY,MAAA,GAAS,WAAA;AAAA,IACpB,cAAA,CAAe,oBAAA;;;;;iBAmWF,oBAAA,CAAqB,KAAA,EAAO,YAAA,GAAe,YAAA"}
|
|
@@ -12,6 +12,72 @@ var compat_exports = /* @__PURE__ */ __exportAll({
|
|
|
12
12
|
convertChunksToEvents: () => convertChunksToEvents,
|
|
13
13
|
finalizeContentBlock: () => finalizeContentBlock
|
|
14
14
|
});
|
|
15
|
+
const MIME_TYPE_BY_AUDIO_FORMAT = {
|
|
16
|
+
wav: "audio/wav",
|
|
17
|
+
mp3: "audio/mpeg",
|
|
18
|
+
flac: "audio/flac",
|
|
19
|
+
opus: "audio/opus",
|
|
20
|
+
aac: "audio/aac",
|
|
21
|
+
pcm16: "audio/pcm"
|
|
22
|
+
};
|
|
23
|
+
const MIME_TYPE_BY_IMAGE_FORMAT = {
|
|
24
|
+
png: "image/png",
|
|
25
|
+
jpeg: "image/jpeg",
|
|
26
|
+
jpg: "image/jpeg",
|
|
27
|
+
webp: "image/webp",
|
|
28
|
+
gif: "image/gif"
|
|
29
|
+
};
|
|
30
|
+
function nextBlockIndex(activeBlocks) {
|
|
31
|
+
let next = 0;
|
|
32
|
+
for (const index of activeBlocks.keys()) if (index >= next) next = index + 1;
|
|
33
|
+
return next;
|
|
34
|
+
}
|
|
35
|
+
function getAdditionalKwargs(message) {
|
|
36
|
+
const additional = message.additional_kwargs;
|
|
37
|
+
return additional != null && typeof additional === "object" ? additional : {};
|
|
38
|
+
}
|
|
39
|
+
function extractImageBlocksFromToolOutputs(message) {
|
|
40
|
+
const toolOutputs = getAdditionalKwargs(message).tool_outputs;
|
|
41
|
+
if (!Array.isArray(toolOutputs)) return [];
|
|
42
|
+
const blocks = [];
|
|
43
|
+
for (const entry of toolOutputs) {
|
|
44
|
+
if (entry == null || typeof entry !== "object") continue;
|
|
45
|
+
const record = entry;
|
|
46
|
+
if (record.type !== "image_generation_call") continue;
|
|
47
|
+
const data = typeof record.result === "string" ? record.result : void 0;
|
|
48
|
+
const url = typeof record.url === "string" ? record.url : void 0;
|
|
49
|
+
if (data == null && url == null) continue;
|
|
50
|
+
const outputFormat = typeof record.output_format === "string" ? record.output_format.toLowerCase() : void 0;
|
|
51
|
+
const mimeType = (outputFormat != null ? MIME_TYPE_BY_IMAGE_FORMAT[outputFormat] : void 0) ?? "image/png";
|
|
52
|
+
blocks.push({
|
|
53
|
+
type: "image",
|
|
54
|
+
...typeof record.id === "string" ? { id: record.id } : {},
|
|
55
|
+
...url != null ? { url } : {},
|
|
56
|
+
...data != null ? { data } : {},
|
|
57
|
+
mimeType
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return blocks;
|
|
61
|
+
}
|
|
62
|
+
function getAudioPayload(message) {
|
|
63
|
+
const audio = getAdditionalKwargs(message).audio;
|
|
64
|
+
if (audio == null || typeof audio !== "object") return void 0;
|
|
65
|
+
const record = audio;
|
|
66
|
+
const data = typeof record.data === "string" ? record.data : void 0;
|
|
67
|
+
const url = typeof record.url === "string" ? record.url : void 0;
|
|
68
|
+
const transcript = typeof record.transcript === "string" ? record.transcript : void 0;
|
|
69
|
+
if (data == null && url == null && transcript == null) return void 0;
|
|
70
|
+
const explicitMimeType = typeof record.mime_type === "string" ? record.mime_type : typeof record.mimeType === "string" ? record.mimeType : void 0;
|
|
71
|
+
const format = typeof record.format === "string" ? record.format.toLowerCase() : void 0;
|
|
72
|
+
const mimeType = explicitMimeType ?? (format != null ? MIME_TYPE_BY_AUDIO_FORMAT[format] : void 0) ?? (data != null ? "audio/wav" : "audio/pcm");
|
|
73
|
+
return {
|
|
74
|
+
...typeof record.id === "string" ? { id: record.id } : {},
|
|
75
|
+
...data != null ? { data } : {},
|
|
76
|
+
...url != null ? { url } : {},
|
|
77
|
+
...transcript != null ? { transcript } : {},
|
|
78
|
+
mimeType
|
|
79
|
+
};
|
|
80
|
+
}
|
|
15
81
|
/**
|
|
16
82
|
* Convert an async iterable of legacy `ChatGenerationChunk`s into
|
|
17
83
|
* `ChatModelStreamEvent`s with typed deltas.
|
|
@@ -20,6 +86,8 @@ async function* convertChunksToEvents(chunks, options) {
|
|
|
20
86
|
const activeBlocks = /* @__PURE__ */ new Map();
|
|
21
87
|
let messageStarted = false;
|
|
22
88
|
let lastUsage;
|
|
89
|
+
let audioStream;
|
|
90
|
+
const emittedImageKeys = /* @__PURE__ */ new Set();
|
|
23
91
|
for await (const chunk of chunks) {
|
|
24
92
|
options?.signal?.throwIfAborted();
|
|
25
93
|
const msg = chunk.message;
|
|
@@ -131,6 +199,85 @@ async function* convertChunksToEvents(chunks, options) {
|
|
|
131
199
|
}
|
|
132
200
|
};
|
|
133
201
|
}
|
|
202
|
+
const audioPayload = getAudioPayload(msg);
|
|
203
|
+
if (audioPayload != null) {
|
|
204
|
+
if (audioStream == null) {
|
|
205
|
+
const index = nextBlockIndex(activeBlocks);
|
|
206
|
+
audioStream = {
|
|
207
|
+
index,
|
|
208
|
+
id: audioPayload.id,
|
|
209
|
+
mimeType: audioPayload.mimeType,
|
|
210
|
+
transcript: ""
|
|
211
|
+
};
|
|
212
|
+
const initial = {
|
|
213
|
+
type: "audio",
|
|
214
|
+
...audioPayload.id != null ? { id: audioPayload.id } : {},
|
|
215
|
+
...audioPayload.url != null ? { url: audioPayload.url } : {},
|
|
216
|
+
data: "",
|
|
217
|
+
mimeType: audioPayload.mimeType
|
|
218
|
+
};
|
|
219
|
+
activeBlocks.set(index, {
|
|
220
|
+
type: "audio",
|
|
221
|
+
accumulated: initial
|
|
222
|
+
});
|
|
223
|
+
yield {
|
|
224
|
+
event: "content-block-start",
|
|
225
|
+
index,
|
|
226
|
+
content: initial
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
const activeAudio = activeBlocks.get(audioStream.index);
|
|
230
|
+
if (activeAudio != null) {
|
|
231
|
+
const accumulated = activeAudio.accumulated;
|
|
232
|
+
if (audioPayload.id != null && audioStream.id == null) {
|
|
233
|
+
audioStream.id = audioPayload.id;
|
|
234
|
+
accumulated.id = audioPayload.id;
|
|
235
|
+
}
|
|
236
|
+
if (audioPayload.transcript != null) {
|
|
237
|
+
audioStream.transcript += audioPayload.transcript;
|
|
238
|
+
accumulated.transcript = audioStream.transcript;
|
|
239
|
+
yield {
|
|
240
|
+
event: "content-block-delta",
|
|
241
|
+
index: audioStream.index,
|
|
242
|
+
delta: {
|
|
243
|
+
type: "block-delta",
|
|
244
|
+
fields: {
|
|
245
|
+
type: "audio",
|
|
246
|
+
transcript: audioStream.transcript
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
if (audioPayload.data != null && audioPayload.data.length > 0) {
|
|
252
|
+
accumulated.data = (accumulated.data ?? "") + audioPayload.data;
|
|
253
|
+
yield {
|
|
254
|
+
event: "content-block-delta",
|
|
255
|
+
index: audioStream.index,
|
|
256
|
+
delta: {
|
|
257
|
+
type: "data-delta",
|
|
258
|
+
data: audioPayload.data,
|
|
259
|
+
encoding: "base64"
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
for (const imageBlock of extractImageBlocksFromToolOutputs(msg)) {
|
|
266
|
+
const imageRecord = imageBlock;
|
|
267
|
+
const imageKey = imageRecord.id ?? imageRecord.url ?? (imageRecord.data != null ? `${imageRecord.data.length}:${imageRecord.data.slice(0, 32)}` : void 0);
|
|
268
|
+
if (imageKey != null && emittedImageKeys.has(imageKey)) continue;
|
|
269
|
+
if (imageKey != null) emittedImageKeys.add(imageKey);
|
|
270
|
+
const index = nextBlockIndex(activeBlocks);
|
|
271
|
+
activeBlocks.set(index, {
|
|
272
|
+
type: "image",
|
|
273
|
+
accumulated: imageBlock
|
|
274
|
+
});
|
|
275
|
+
yield {
|
|
276
|
+
event: "content-block-start",
|
|
277
|
+
index,
|
|
278
|
+
content: imageBlock
|
|
279
|
+
};
|
|
280
|
+
}
|
|
134
281
|
if (!usageHandledInStart && isAIMessageChunk(msg) && msg.usage_metadata) {
|
|
135
282
|
const chunkUsage = msg.usage_metadata;
|
|
136
283
|
if (!lastUsage) lastUsage = { ...chunkUsage };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compat.js","names":[],"sources":["../../src/language_models/compat.ts"],"sourcesContent":["/**\n * Compatibility bridge: converts legacy `_streamResponseChunks`\n * (`ChatGenerationChunk` / `AIMessageChunk`) output to the new\n * `ChatModelStreamEvent` protocol.\n *\n * @module\n */\n\nimport { isAIMessageChunk } from \"../messages/ai.js\";\nimport type { ContentBlock } from \"../messages/content/index.js\";\nimport type { ChatGenerationChunk } from \"../outputs.js\";\nimport type { ChatModelStreamEvent, ContentBlockDelta } from \"./event.js\";\n\n/**\n * Convert an async iterable of legacy `ChatGenerationChunk`s into\n * `ChatModelStreamEvent`s with typed deltas.\n */\nexport async function* convertChunksToEvents(\n chunks: AsyncIterable<ChatGenerationChunk>,\n options?: { signal?: AbortSignal }\n): AsyncGenerator<ChatModelStreamEvent> {\n const activeBlocks = new Map<\n number,\n { type: string; accumulated: ContentBlock }\n >();\n let messageStarted = false;\n let lastUsage:\n | { input_tokens: number; output_tokens: number; total_tokens: number }\n | undefined;\n\n for await (const chunk of chunks) {\n options?.signal?.throwIfAborted();\n\n const msg = chunk.message;\n\n // Message start\n let usageHandledInStart = false;\n if (!messageStarted) {\n messageStarted = true;\n const startEvent: ChatModelStreamEvent = {\n event: \"message-start\" as const,\n id: msg.id ?? undefined,\n };\n if (isAIMessageChunk(msg) && msg.usage_metadata) {\n (startEvent as { usage?: unknown }).usage = msg.usage_metadata;\n lastUsage = { ...msg.usage_metadata };\n usageHandledInStart = true;\n }\n yield startEvent;\n }\n\n // Process content\n const content = msg.content;\n if (typeof content === \"string\") {\n if (content !== \"\") {\n const blockIndex = 0;\n if (!activeBlocks.has(blockIndex)) {\n const initial: ContentBlock.Text = { type: \"text\", text: \"\" };\n activeBlocks.set(blockIndex, {\n type: \"text\",\n accumulated: initial,\n });\n yield {\n event: \"content-block-start\" as const,\n index: blockIndex,\n content: initial,\n };\n }\n const block = activeBlocks.get(blockIndex)!;\n block.accumulated = {\n ...block.accumulated,\n text: ((block.accumulated as { text?: string }).text ?? \"\") + content,\n };\n yield {\n event: \"content-block-delta\" as const,\n index: blockIndex,\n delta: { type: \"text-delta\" as const, text: content },\n };\n }\n } else if (Array.isArray(content)) {\n for (const part of content) {\n const blockIndex =\n typeof part.index === \"number\" ? part.index : activeBlocks.size;\n\n if (!activeBlocks.has(blockIndex)) {\n activeBlocks.set(blockIndex, {\n type: part.type,\n accumulated: { ...part },\n });\n yield {\n event: \"content-block-start\" as const,\n index: blockIndex,\n content: { ...part },\n };\n } else {\n const block = activeBlocks.get(blockIndex)!;\n const delta = contentBlockToDelta(part);\n block.accumulated = applyDeltaToBlock(block.accumulated, delta);\n yield {\n event: \"content-block-delta\" as const,\n index: blockIndex,\n delta,\n };\n }\n }\n }\n\n // Tool call chunks\n if (\n isAIMessageChunk(msg) &&\n msg.tool_call_chunks &&\n msg.tool_call_chunks.length > 0\n ) {\n for (const toolChunk of msg.tool_call_chunks) {\n const blockIndex =\n typeof toolChunk.index === \"number\"\n ? toolChunk.index\n : activeBlocks.size;\n\n if (!activeBlocks.has(blockIndex)) {\n const initial: ContentBlock = {\n type: \"tool_call_chunk\" as const,\n id: toolChunk.id,\n name: toolChunk.name,\n args: \"\",\n index: blockIndex,\n };\n activeBlocks.set(blockIndex, {\n type: \"tool_call_chunk\",\n accumulated: initial,\n });\n yield {\n event: \"content-block-start\" as const,\n index: blockIndex,\n content: initial,\n };\n }\n\n // Accumulate tool call args internally, emit incremental content chunks.\n const block = activeBlocks.get(blockIndex)!;\n const acc = block.accumulated as {\n args?: string;\n id?: string;\n name?: string;\n };\n if (toolChunk.id != null) acc.id = toolChunk.id;\n if (toolChunk.name != null) acc.name = toolChunk.name;\n acc.args = (acc.args ?? \"\") + (toolChunk.args ?? \"\");\n yield {\n event: \"content-block-delta\" as const,\n index: blockIndex,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(\"id\" in acc && acc.id != null ? { id: acc.id } : {}),\n ...(\"name\" in acc && acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n }\n }\n\n // Usage\n if (!usageHandledInStart && isAIMessageChunk(msg) && msg.usage_metadata) {\n const chunkUsage = msg.usage_metadata;\n if (!lastUsage) {\n lastUsage = { ...chunkUsage };\n } else {\n lastUsage = {\n input_tokens: lastUsage.input_tokens + chunkUsage.input_tokens,\n output_tokens: lastUsage.output_tokens + chunkUsage.output_tokens,\n total_tokens: lastUsage.total_tokens + chunkUsage.total_tokens,\n };\n }\n yield { event: \"usage\" as const, usage: { ...lastUsage } };\n }\n }\n\n // Finish all blocks\n for (const [index, block] of activeBlocks) {\n const finalized = finalizeContentBlock(block.accumulated);\n yield {\n event: \"content-block-finish\" as const,\n index,\n content: finalized,\n };\n }\n\n yield {\n event: \"message-finish\" as const,\n reason: \"stop\" as const,\n ...(lastUsage ? { usage: lastUsage } : {}),\n };\n}\n\n/**\n * Apply a typed delta to an accumulated content block.\n * @internal\n */\nfunction applyDeltaToBlock(\n block: ContentBlock,\n delta: ContentBlockDelta\n): ContentBlock {\n switch (delta.type) {\n case \"text-delta\":\n return {\n ...block,\n text: ((block as { text?: string }).text ?? \"\") + delta.text,\n } as ContentBlock;\n case \"reasoning-delta\":\n if ((block as { type?: string }).type === \"thinking\") {\n return {\n ...block,\n thinking:\n ((block as { thinking?: string }).thinking ?? \"\") + delta.reasoning,\n } as unknown as ContentBlock;\n }\n return {\n ...block,\n reasoning:\n ((block as { reasoning?: string }).reasoning ?? \"\") + delta.reasoning,\n } as ContentBlock;\n case \"data-delta\":\n return {\n ...block,\n data: ((block as { data?: string }).data ?? \"\") + delta.data,\n } as ContentBlock;\n case \"block-delta\":\n return { ...block, ...delta.fields } as ContentBlock;\n default:\n throw new Error(`Unknown delta type: ${JSON.stringify(delta)}`);\n }\n}\n\nfunction contentBlockToDelta(block: ContentBlock): ContentBlockDelta {\n if (block.type === \"text\") {\n return { type: \"text-delta\", text: (block as ContentBlock.Text).text };\n }\n if (block.type === \"reasoning\") {\n return {\n type: \"reasoning-delta\",\n reasoning: (block as ContentBlock.Reasoning).reasoning,\n };\n }\n if (\n (block as { type?: string }).type === \"thinking\" &&\n typeof (block as { thinking?: unknown }).thinking === \"string\"\n ) {\n return {\n type: \"reasoning-delta\",\n reasoning: (block as unknown as { thinking: string }).thinking,\n };\n }\n if (typeof (block as { data?: unknown }).data === \"string\") {\n return {\n type: \"data-delta\",\n data: (block as unknown as { data: string }).data,\n encoding: \"base64\",\n };\n }\n if (typeof (block as { type?: unknown }).type === \"string\") {\n return {\n type: \"block-delta\",\n fields: {\n ...(block as unknown as { type: string } & Record<string, unknown>),\n },\n };\n }\n\n throw new Error(`Unsupported content block delta: ${JSON.stringify(block)}`);\n}\n\n/**\n * Finalize a content block for the finish event.\n * For tool calls, parse the accumulated JSON args string.\n */\nexport function finalizeContentBlock(block: ContentBlock): ContentBlock {\n if (block.type === \"tool_call_chunk\") {\n const chunk = block as ContentBlock.Tools.ToolCallChunk;\n let parsedArgs: unknown;\n try {\n parsedArgs = JSON.parse(chunk.args ?? \"{}\");\n } catch {\n return {\n type: \"invalid_tool_call\" as const,\n id: chunk.id,\n name: chunk.name,\n args: chunk.args,\n error: \"Failed to parse tool call arguments as JSON\",\n } as ContentBlock.Tools.InvalidToolCall;\n }\n return {\n type: \"tool_call\" as const,\n id: chunk.id,\n name: chunk.name!,\n args: parsedArgs,\n } as ContentBlock.Tools.ToolCall;\n }\n\n return block;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compat.js","names":[],"sources":["../../src/language_models/compat.ts"],"sourcesContent":["/**\n * Compatibility bridge: converts legacy `_streamResponseChunks`\n * (`ChatGenerationChunk` / `AIMessageChunk`) output to the new\n * `ChatModelStreamEvent` protocol.\n *\n * @module\n */\n\nimport { isAIMessageChunk } from \"../messages/ai.js\";\nimport type { ContentBlock } from \"../messages/content/index.js\";\nimport type { ChatGenerationChunk } from \"../outputs.js\";\nimport type { ChatModelStreamEvent, ContentBlockDelta } from \"./event.js\";\n\nconst MIME_TYPE_BY_AUDIO_FORMAT: Record<string, string> = {\n wav: \"audio/wav\",\n mp3: \"audio/mpeg\",\n flac: \"audio/flac\",\n opus: \"audio/opus\",\n aac: \"audio/aac\",\n pcm16: \"audio/pcm\",\n};\n\nconst MIME_TYPE_BY_IMAGE_FORMAT: Record<string, string> = {\n png: \"image/png\",\n jpeg: \"image/jpeg\",\n jpg: \"image/jpeg\",\n webp: \"image/webp\",\n gif: \"image/gif\",\n};\n\ntype AudioStreamState = {\n index: number;\n id?: string;\n mimeType: string;\n transcript: string;\n};\n\nfunction nextBlockIndex(activeBlocks: Map<number, unknown>): number {\n let next = 0;\n for (const index of activeBlocks.keys()) {\n if (index >= next) next = index + 1;\n }\n return next;\n}\n\nfunction getAdditionalKwargs(message: unknown): Record<string, unknown> {\n const additional = (message as { additional_kwargs?: unknown })\n .additional_kwargs;\n return additional != null && typeof additional === \"object\"\n ? (additional as Record<string, unknown>)\n : {};\n}\n\nfunction extractImageBlocksFromToolOutputs(message: unknown): ContentBlock[] {\n const toolOutputs = getAdditionalKwargs(message).tool_outputs;\n if (!Array.isArray(toolOutputs)) return [];\n\n const blocks: ContentBlock[] = [];\n for (const entry of toolOutputs) {\n if (entry == null || typeof entry !== \"object\") continue;\n const record = entry as Record<string, unknown>;\n if (record.type !== \"image_generation_call\") continue;\n\n const data = typeof record.result === \"string\" ? record.result : undefined;\n const url = typeof record.url === \"string\" ? record.url : undefined;\n if (data == null && url == null) continue;\n\n const outputFormat =\n typeof record.output_format === \"string\"\n ? record.output_format.toLowerCase()\n : undefined;\n const mimeType =\n (outputFormat != null\n ? MIME_TYPE_BY_IMAGE_FORMAT[outputFormat]\n : undefined) ?? \"image/png\";\n\n blocks.push({\n type: \"image\",\n ...(typeof record.id === \"string\" ? { id: record.id } : {}),\n ...(url != null ? { url } : {}),\n ...(data != null ? { data } : {}),\n mimeType,\n } as ContentBlock);\n }\n return blocks;\n}\n\nfunction getAudioPayload(message: unknown):\n | {\n id?: string;\n data?: string;\n url?: string;\n transcript?: string;\n mimeType: string;\n }\n | undefined {\n const audio = getAdditionalKwargs(message).audio;\n if (audio == null || typeof audio !== \"object\") return undefined;\n const record = audio as Record<string, unknown>;\n\n const data = typeof record.data === \"string\" ? record.data : undefined;\n const url = typeof record.url === \"string\" ? record.url : undefined;\n const transcript =\n typeof record.transcript === \"string\" ? record.transcript : undefined;\n if (data == null && url == null && transcript == null) return undefined;\n\n const explicitMimeType =\n typeof record.mime_type === \"string\"\n ? record.mime_type\n : typeof record.mimeType === \"string\"\n ? record.mimeType\n : undefined;\n const format =\n typeof record.format === \"string\" ? record.format.toLowerCase() : undefined;\n const mimeType =\n explicitMimeType ??\n (format != null ? MIME_TYPE_BY_AUDIO_FORMAT[format] : undefined) ??\n (data != null ? \"audio/wav\" : \"audio/pcm\");\n\n return {\n ...(typeof record.id === \"string\" ? { id: record.id } : {}),\n ...(data != null ? { data } : {}),\n ...(url != null ? { url } : {}),\n ...(transcript != null ? { transcript } : {}),\n mimeType,\n };\n}\n\n/**\n * Convert an async iterable of legacy `ChatGenerationChunk`s into\n * `ChatModelStreamEvent`s with typed deltas.\n */\nexport async function* convertChunksToEvents(\n chunks: AsyncIterable<ChatGenerationChunk>,\n options?: { signal?: AbortSignal }\n): AsyncGenerator<ChatModelStreamEvent> {\n const activeBlocks = new Map<\n number,\n { type: string; accumulated: ContentBlock }\n >();\n let messageStarted = false;\n let lastUsage:\n | { input_tokens: number; output_tokens: number; total_tokens: number }\n | undefined;\n let audioStream: AudioStreamState | undefined;\n const emittedImageKeys = new Set<string>();\n\n for await (const chunk of chunks) {\n options?.signal?.throwIfAborted();\n\n const msg = chunk.message;\n\n // Message start\n let usageHandledInStart = false;\n if (!messageStarted) {\n messageStarted = true;\n const startEvent: ChatModelStreamEvent = {\n event: \"message-start\" as const,\n id: msg.id ?? undefined,\n };\n if (isAIMessageChunk(msg) && msg.usage_metadata) {\n (startEvent as { usage?: unknown }).usage = msg.usage_metadata;\n lastUsage = { ...msg.usage_metadata };\n usageHandledInStart = true;\n }\n yield startEvent;\n }\n\n // Process content\n const content = msg.content;\n if (typeof content === \"string\") {\n if (content !== \"\") {\n const blockIndex = 0;\n if (!activeBlocks.has(blockIndex)) {\n const initial: ContentBlock.Text = { type: \"text\", text: \"\" };\n activeBlocks.set(blockIndex, {\n type: \"text\",\n accumulated: initial,\n });\n yield {\n event: \"content-block-start\" as const,\n index: blockIndex,\n content: initial,\n };\n }\n const block = activeBlocks.get(blockIndex)!;\n block.accumulated = {\n ...block.accumulated,\n text: ((block.accumulated as { text?: string }).text ?? \"\") + content,\n };\n yield {\n event: \"content-block-delta\" as const,\n index: blockIndex,\n delta: { type: \"text-delta\" as const, text: content },\n };\n }\n } else if (Array.isArray(content)) {\n for (const part of content) {\n const blockIndex =\n typeof part.index === \"number\" ? part.index : activeBlocks.size;\n\n if (!activeBlocks.has(blockIndex)) {\n activeBlocks.set(blockIndex, {\n type: part.type,\n accumulated: { ...part },\n });\n yield {\n event: \"content-block-start\" as const,\n index: blockIndex,\n content: { ...part },\n };\n } else {\n const block = activeBlocks.get(blockIndex)!;\n const delta = contentBlockToDelta(part);\n block.accumulated = applyDeltaToBlock(block.accumulated, delta);\n yield {\n event: \"content-block-delta\" as const,\n index: blockIndex,\n delta,\n };\n }\n }\n }\n\n // Tool call chunks\n if (\n isAIMessageChunk(msg) &&\n msg.tool_call_chunks &&\n msg.tool_call_chunks.length > 0\n ) {\n for (const toolChunk of msg.tool_call_chunks) {\n const blockIndex =\n typeof toolChunk.index === \"number\"\n ? toolChunk.index\n : activeBlocks.size;\n\n if (!activeBlocks.has(blockIndex)) {\n const initial: ContentBlock = {\n type: \"tool_call_chunk\" as const,\n id: toolChunk.id,\n name: toolChunk.name,\n args: \"\",\n index: blockIndex,\n };\n activeBlocks.set(blockIndex, {\n type: \"tool_call_chunk\",\n accumulated: initial,\n });\n yield {\n event: \"content-block-start\" as const,\n index: blockIndex,\n content: initial,\n };\n }\n\n // Accumulate tool call args internally, emit incremental content chunks.\n const block = activeBlocks.get(blockIndex)!;\n const acc = block.accumulated as {\n args?: string;\n id?: string;\n name?: string;\n };\n if (toolChunk.id != null) acc.id = toolChunk.id;\n if (toolChunk.name != null) acc.name = toolChunk.name;\n acc.args = (acc.args ?? \"\") + (toolChunk.args ?? \"\");\n yield {\n event: \"content-block-delta\" as const,\n index: blockIndex,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(\"id\" in acc && acc.id != null ? { id: acc.id } : {}),\n ...(\"name\" in acc && acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n }\n }\n\n const audioPayload = getAudioPayload(msg);\n if (audioPayload != null) {\n if (audioStream == null) {\n const index = nextBlockIndex(activeBlocks);\n audioStream = {\n index,\n id: audioPayload.id,\n mimeType: audioPayload.mimeType,\n transcript: \"\",\n };\n const initial = {\n type: \"audio\",\n ...(audioPayload.id != null ? { id: audioPayload.id } : {}),\n ...(audioPayload.url != null ? { url: audioPayload.url } : {}),\n data: \"\",\n mimeType: audioPayload.mimeType,\n } as ContentBlock;\n activeBlocks.set(index, {\n type: \"audio\",\n accumulated: initial,\n });\n yield {\n event: \"content-block-start\" as const,\n index,\n content: initial,\n };\n }\n\n const activeAudio = activeBlocks.get(audioStream.index);\n if (activeAudio != null) {\n const accumulated = activeAudio.accumulated as ContentBlock & {\n data?: string;\n transcript?: string;\n };\n if (audioPayload.id != null && audioStream.id == null) {\n audioStream.id = audioPayload.id;\n (accumulated as { id?: string }).id = audioPayload.id;\n }\n if (audioPayload.transcript != null) {\n audioStream.transcript += audioPayload.transcript;\n accumulated.transcript = audioStream.transcript;\n yield {\n event: \"content-block-delta\" as const,\n index: audioStream.index,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"audio\",\n transcript: audioStream.transcript,\n },\n },\n };\n }\n if (audioPayload.data != null && audioPayload.data.length > 0) {\n accumulated.data = (accumulated.data ?? \"\") + audioPayload.data;\n yield {\n event: \"content-block-delta\" as const,\n index: audioStream.index,\n delta: {\n type: \"data-delta\" as const,\n data: audioPayload.data,\n encoding: \"base64\" as const,\n },\n };\n }\n }\n }\n\n for (const imageBlock of extractImageBlocksFromToolOutputs(msg)) {\n const imageRecord = imageBlock as ContentBlock & {\n id?: string;\n url?: string;\n data?: string;\n };\n const imageKey =\n imageRecord.id ??\n imageRecord.url ??\n (imageRecord.data != null\n ? `${imageRecord.data.length}:${imageRecord.data.slice(0, 32)}`\n : undefined);\n if (imageKey != null && emittedImageKeys.has(imageKey)) continue;\n if (imageKey != null) emittedImageKeys.add(imageKey);\n\n const index = nextBlockIndex(activeBlocks);\n activeBlocks.set(index, {\n type: \"image\",\n accumulated: imageBlock,\n });\n yield {\n event: \"content-block-start\" as const,\n index,\n content: imageBlock,\n };\n }\n\n // Usage\n if (!usageHandledInStart && isAIMessageChunk(msg) && msg.usage_metadata) {\n const chunkUsage = msg.usage_metadata;\n if (!lastUsage) {\n lastUsage = { ...chunkUsage };\n } else {\n lastUsage = {\n input_tokens: lastUsage.input_tokens + chunkUsage.input_tokens,\n output_tokens: lastUsage.output_tokens + chunkUsage.output_tokens,\n total_tokens: lastUsage.total_tokens + chunkUsage.total_tokens,\n };\n }\n yield { event: \"usage\" as const, usage: { ...lastUsage } };\n }\n }\n\n // Finish all blocks\n for (const [index, block] of activeBlocks) {\n const finalized = finalizeContentBlock(block.accumulated);\n yield {\n event: \"content-block-finish\" as const,\n index,\n content: finalized,\n };\n }\n\n yield {\n event: \"message-finish\" as const,\n reason: \"stop\" as const,\n ...(lastUsage ? { usage: lastUsage } : {}),\n };\n}\n\n/**\n * Apply a typed delta to an accumulated content block.\n * @internal\n */\nfunction applyDeltaToBlock(\n block: ContentBlock,\n delta: ContentBlockDelta\n): ContentBlock {\n switch (delta.type) {\n case \"text-delta\":\n return {\n ...block,\n text: ((block as { text?: string }).text ?? \"\") + delta.text,\n } as ContentBlock;\n case \"reasoning-delta\":\n if ((block as { type?: string }).type === \"thinking\") {\n return {\n ...block,\n thinking:\n ((block as { thinking?: string }).thinking ?? \"\") + delta.reasoning,\n } as unknown as ContentBlock;\n }\n return {\n ...block,\n reasoning:\n ((block as { reasoning?: string }).reasoning ?? \"\") + delta.reasoning,\n } as ContentBlock;\n case \"data-delta\":\n return {\n ...block,\n data: ((block as { data?: string }).data ?? \"\") + delta.data,\n } as ContentBlock;\n case \"block-delta\":\n return { ...block, ...delta.fields } as ContentBlock;\n default:\n throw new Error(`Unknown delta type: ${JSON.stringify(delta)}`);\n }\n}\n\nfunction contentBlockToDelta(block: ContentBlock): ContentBlockDelta {\n if (block.type === \"text\") {\n return { type: \"text-delta\", text: (block as ContentBlock.Text).text };\n }\n if (block.type === \"reasoning\") {\n return {\n type: \"reasoning-delta\",\n reasoning: (block as ContentBlock.Reasoning).reasoning,\n };\n }\n if (\n (block as { type?: string }).type === \"thinking\" &&\n typeof (block as { thinking?: unknown }).thinking === \"string\"\n ) {\n return {\n type: \"reasoning-delta\",\n reasoning: (block as unknown as { thinking: string }).thinking,\n };\n }\n if (typeof (block as { data?: unknown }).data === \"string\") {\n return {\n type: \"data-delta\",\n data: (block as unknown as { data: string }).data,\n encoding: \"base64\",\n };\n }\n if (typeof (block as { type?: unknown }).type === \"string\") {\n return {\n type: \"block-delta\",\n fields: {\n ...(block as unknown as { type: string } & Record<string, unknown>),\n },\n };\n }\n\n throw new Error(`Unsupported content block delta: ${JSON.stringify(block)}`);\n}\n\n/**\n * Finalize a content block for the finish event.\n * For tool calls, parse the accumulated JSON args string.\n */\nexport function finalizeContentBlock(block: ContentBlock): ContentBlock {\n if (block.type === \"tool_call_chunk\") {\n const chunk = block as ContentBlock.Tools.ToolCallChunk;\n let parsedArgs: unknown;\n try {\n parsedArgs = JSON.parse(chunk.args ?? \"{}\");\n } catch {\n return {\n type: \"invalid_tool_call\" as const,\n id: chunk.id,\n name: chunk.name,\n args: chunk.args,\n error: \"Failed to parse tool call arguments as JSON\",\n } as ContentBlock.Tools.InvalidToolCall;\n }\n return {\n type: \"tool_call\" as const,\n id: chunk.id,\n name: chunk.name!,\n args: parsedArgs,\n } as ContentBlock.Tools.ToolCall;\n }\n\n return block;\n}\n"],"mappings":"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"}
|
|
@@ -163,6 +163,30 @@ function normalizeUsage(usage) {
|
|
|
163
163
|
total_tokens: usage.total_tokens ?? 0
|
|
164
164
|
};
|
|
165
165
|
}
|
|
166
|
+
function parseToolArgs(value) {
|
|
167
|
+
if (value != null && typeof value === "object" && !Array.isArray(value)) return value;
|
|
168
|
+
if (typeof value !== "string" || value.length === 0) return {};
|
|
169
|
+
try {
|
|
170
|
+
const parsed = JSON.parse(value);
|
|
171
|
+
return parsed != null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
172
|
+
} catch {
|
|
173
|
+
return {};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function standardizeToolBlock(block) {
|
|
177
|
+
const record = block;
|
|
178
|
+
if (block.type === "tool_call") return block;
|
|
179
|
+
if (block.type !== "tool_call_chunk" && block.type !== "tool_use" && block.type !== "input_json_delta") return block;
|
|
180
|
+
const name = typeof record.name === "string" ? record.name : void 0;
|
|
181
|
+
if (name == null) return block;
|
|
182
|
+
const args = record.args ?? record.input;
|
|
183
|
+
return {
|
|
184
|
+
...record,
|
|
185
|
+
type: "tool_call",
|
|
186
|
+
name,
|
|
187
|
+
args: parseToolArgs(args)
|
|
188
|
+
};
|
|
189
|
+
}
|
|
166
190
|
/**
|
|
167
191
|
* Typed stream for text content.
|
|
168
192
|
*
|
|
@@ -435,7 +459,7 @@ var ChatModelStream = class {
|
|
|
435
459
|
break;
|
|
436
460
|
default: break;
|
|
437
461
|
}
|
|
438
|
-
const filteredBlocks = contentBlocks.filter((b) => b != null);
|
|
462
|
+
const filteredBlocks = contentBlocks.filter((b) => b != null).map(standardizeToolBlock);
|
|
439
463
|
return new require_ai.AIMessage({
|
|
440
464
|
id,
|
|
441
465
|
content: filteredBlocks,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.cjs","names":["AIMessage"],"sources":["../../src/language_models/stream.ts"],"sourcesContent":["/**\n * Typed stream classes for chat model streaming.\n *\n * @module\n */\n\nimport { AIMessage } from \"../messages/ai.js\";\nimport type { ContentBlock } from \"../messages/content/index.js\";\nimport type { UsageMetadata } from \"../messages/metadata.js\";\nimport type { ChatModelStreamEvent, ContentBlockDelta } from \"./event.js\";\n\ntype UsageMetadataLike = Partial<UsageMetadata>;\n\n// ─── Replay Buffer ──────────────────────────────────────────────\n\n/**\n * A buffer that caches emitted events for replay.\n *\n * Multiple consumers can independently iterate the same buffer —\n * each gets its own cursor. Events are never consumed or removed.\n *\n * @internal\n */\nclass ReplayBuffer {\n private events: ChatModelStreamEvent[] = [];\n private finished = false;\n private waiters: Array<() => void> = [];\n private error: Error | null = null;\n\n push(event: ChatModelStreamEvent): void {\n this.events.push(event);\n const toWake = this.waiters.splice(0);\n for (const waiter of toWake) {\n waiter();\n }\n }\n\n finish(): void {\n this.finished = true;\n const toWake = this.waiters.splice(0);\n for (const waiter of toWake) {\n waiter();\n }\n }\n\n setError(err: Error): void {\n this.error = err;\n this.finished = true;\n const toWake = this.waiters.splice(0);\n for (const waiter of toWake) {\n waiter();\n }\n }\n\n async *iterate(): AsyncGenerator<ChatModelStreamEvent> {\n if (this.finished) {\n if (this.error) throw this.error;\n yield* this.events;\n return;\n }\n\n let cursor = 0;\n while (true) {\n while (cursor < this.events.length) {\n yield this.events[cursor]!;\n cursor++;\n }\n if (this.finished) {\n if (this.error) throw this.error;\n return;\n }\n await new Promise<void>((resolve) => {\n if (cursor < this.events.length || this.finished) {\n resolve();\n return;\n }\n this.waiters.push(resolve);\n });\n }\n }\n}\n\n// ─── Accumulator ────────────────────────────────────────────────\n\n/**\n * Apply a typed delta to an accumulated content block.\n *\n * - `text-delta` → append text\n * - `reasoning-delta` → append reasoning text\n * - `data-delta` → append encoded data to `data`\n * - `block-delta` → shallow merge fields\n *\n * @internal\n */\nfunction applyDelta(\n block: ContentBlock,\n delta: ContentBlockDelta\n): ContentBlock {\n switch (delta.type) {\n case \"text-delta\":\n return {\n ...block,\n text: ((block as { text?: string }).text ?? \"\") + delta.text,\n } as ContentBlock;\n case \"reasoning-delta\":\n if ((block as { type?: string }).type === \"thinking\") {\n return {\n ...block,\n thinking:\n ((block as { thinking?: string }).thinking ?? \"\") + delta.reasoning,\n } as unknown as ContentBlock;\n }\n return {\n ...block,\n reasoning:\n ((block as { reasoning?: string }).reasoning ?? \"\") + delta.reasoning,\n } as ContentBlock;\n case \"data-delta\":\n return {\n ...block,\n data: ((block as { data?: string }).data ?? \"\") + delta.data,\n } as ContentBlock;\n case \"block-delta\":\n return { ...block, ...delta.fields } as ContentBlock;\n default:\n throw new Error(`Unknown delta type: ${JSON.stringify(delta)}`);\n }\n}\n\nfunction getEventDelta(\n event: ChatModelStreamEvent\n): ContentBlockDelta | undefined {\n if (event.event !== \"content-block-delta\") return undefined;\n if (\"delta\" in event && event.delta) return event.delta;\n\n // Transitional tolerance for any stream sources still emitting the previous\n // content-shaped delta object.\n const content = (event as { content?: unknown }).content;\n if (content == null || typeof content !== \"object\") return undefined;\n const block = content as { type?: string } & Record<string, unknown>;\n if (block.type === \"text\" && typeof block.text === \"string\") {\n return { type: \"text-delta\", text: block.text };\n }\n if (block.type === \"reasoning\" && typeof block.reasoning === \"string\") {\n return { type: \"reasoning-delta\", reasoning: block.reasoning };\n }\n if (block.type === \"thinking\" && typeof block.thinking === \"string\") {\n return { type: \"reasoning-delta\", reasoning: block.thinking };\n }\n if (typeof block.data === \"string\") {\n return { type: \"data-delta\", data: block.data, encoding: \"base64\" };\n }\n if (typeof block.type === \"string\") {\n return { type: \"block-delta\", fields: { ...block, type: block.type } };\n }\n return undefined;\n}\n\nfunction getReasoningDelta(content: unknown): string | undefined {\n if (content == null || typeof content !== \"object\") return undefined;\n const block = content as {\n type?: string;\n reasoning?: unknown;\n thinking?: unknown;\n };\n if (block.type === \"reasoning\" && typeof block.reasoning === \"string\") {\n return block.reasoning;\n }\n if (block.type === \"thinking\" && typeof block.thinking === \"string\") {\n return block.thinking;\n }\n return undefined;\n}\n\nfunction isReasoningContent(content: unknown): boolean {\n if (content == null || typeof content !== \"object\") return false;\n const type = (content as { type?: unknown }).type;\n return type === \"reasoning\" || type === \"thinking\";\n}\n\n/**\n * Normalize protocol-compatible partial usage into Core's concrete usage shape.\n *\n * Some stream sources emit usage snapshots without every aggregate token field.\n * Keep the stream event input permissive, then normalize at read time so\n * high-level Core consumers always receive a complete {@link UsageMetadata}.\n */\nfunction normalizeUsage(\n usage: UsageMetadataLike | 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\n// ─── Sub-Stream: Text ───────────────────────────────────────────\n\n/**\n * Typed stream for text content.\n *\n * - **Iterate**: yields incremental text deltas.\n * - **Await**: resolves to the complete concatenated text.\n * - **`.full`**: yields the running accumulated text after each delta.\n */\nexport class TextContentStream\n implements AsyncIterable<string>, PromiseLike<string>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(buffer: ReplayBuffer) {\n this._buffer = buffer;\n }\n\n /** Yields the accumulated text so far after each delta. */\n get full(): AsyncIterable<string> {\n const buffer = this._buffer;\n return {\n async *[Symbol.asyncIterator]() {\n let accumulated = \"\";\n for await (const event of buffer.iterate()) {\n const delta = getEventDelta(event);\n if (delta?.type === \"text-delta\") {\n accumulated += delta.text;\n yield accumulated;\n }\n }\n },\n };\n }\n\n /** Yields incremental text deltas. */\n [Symbol.asyncIterator](): AsyncIterator<string> {\n const buffer = this._buffer;\n async function* gen() {\n for await (const event of buffer.iterate()) {\n const delta = getEventDelta(event);\n if (delta?.type === \"text-delta\") {\n yield delta.text;\n }\n }\n }\n return gen();\n }\n\n then<TResult1 = string, TResult2 = never>(\n onfulfilled?: ((value: string) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n const promise = (async () => {\n let text = \"\";\n for await (const delta of this) {\n text += delta;\n }\n return text;\n })();\n return promise.then(onfulfilled, onrejected);\n }\n}\n\n// ─── Sub-Stream: Tool Calls ─────────────────────────────────────\n\n/**\n * Typed stream for tool calls.\n *\n * - **Iterate**: yields individual `ToolCall` objects as each completes.\n * - **Await**: resolves to the full array.\n * - **`.full`**: yields the accumulated array after each new tool call.\n */\nexport class ToolCallsStream\n implements\n AsyncIterable<ContentBlock.Tools.ToolCall>,\n PromiseLike<Array<ContentBlock.Tools.ToolCall>>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(buffer: ReplayBuffer) {\n this._buffer = buffer;\n }\n\n get full(): AsyncIterable<Array<ContentBlock.Tools.ToolCall>> {\n const buffer = this._buffer;\n return {\n async *[Symbol.asyncIterator]() {\n const calls: Array<ContentBlock.Tools.ToolCall> = [];\n for await (const event of buffer.iterate()) {\n if (\n event.event === \"content-block-finish\" &&\n event.content.type === \"tool_call\"\n ) {\n calls.push(event.content as ContentBlock.Tools.ToolCall);\n yield [...calls];\n }\n }\n },\n };\n }\n\n [Symbol.asyncIterator](): AsyncIterator<ContentBlock.Tools.ToolCall> {\n const buffer = this._buffer;\n async function* gen() {\n for await (const event of buffer.iterate()) {\n if (\n event.event === \"content-block-finish\" &&\n event.content.type === \"tool_call\"\n ) {\n yield event.content as ContentBlock.Tools.ToolCall;\n }\n }\n }\n return gen();\n }\n\n then<TResult1 = Array<ContentBlock.Tools.ToolCall>, TResult2 = never>(\n onfulfilled?:\n | ((\n value: Array<ContentBlock.Tools.ToolCall>\n ) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n const promise = (async () => {\n const calls: Array<ContentBlock.Tools.ToolCall> = [];\n for await (const call of this) {\n calls.push(call);\n }\n return calls;\n })();\n return promise.then(onfulfilled, onrejected);\n }\n}\n\n// ─── Sub-Stream: Reasoning ──────────────────────────────────────\n\n/**\n * Typed stream for reasoning content (chain-of-thought).\n * Same interface as {@link TextContentStream} but for reasoning blocks.\n */\nexport class ReasoningContentStream\n implements AsyncIterable<string>, PromiseLike<string>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(buffer: ReplayBuffer) {\n this._buffer = buffer;\n }\n\n get full(): AsyncIterable<string> {\n const buffer = this._buffer;\n return {\n async *[Symbol.asyncIterator]() {\n let accumulated = \"\";\n let seenReasoning = false;\n for await (const event of buffer.iterate()) {\n if (event.event === \"content-block-start\") {\n if (!isReasoningContent(event.content)) {\n if (seenReasoning) return;\n continue;\n }\n seenReasoning = true;\n const delta = getReasoningDelta(event.content);\n if (delta == null || delta.length === 0) continue;\n accumulated += delta;\n yield accumulated;\n } else if (event.event === \"content-block-delta\") {\n const eventDelta = getEventDelta(event);\n if (eventDelta?.type !== \"reasoning-delta\") continue;\n seenReasoning = true;\n const delta = eventDelta.reasoning;\n if (delta == null || delta.length === 0) continue;\n accumulated += delta;\n yield accumulated;\n } else if (\n event.event === \"content-block-finish\" &&\n isReasoningContent(event.content)\n ) {\n return;\n } else if (event.event === \"message-finish\") {\n return;\n }\n }\n },\n };\n }\n\n [Symbol.asyncIterator](): AsyncIterator<string> {\n const buffer = this._buffer;\n async function* gen() {\n let seenReasoning = false;\n for await (const event of buffer.iterate()) {\n if (event.event === \"content-block-start\") {\n if (!isReasoningContent(event.content)) {\n if (seenReasoning) return;\n continue;\n }\n seenReasoning = true;\n const delta = getReasoningDelta(event.content);\n if (delta != null && delta.length > 0) yield delta;\n } else if (event.event === \"content-block-delta\") {\n const eventDelta = getEventDelta(event);\n if (eventDelta?.type !== \"reasoning-delta\") continue;\n seenReasoning = true;\n const delta = eventDelta.reasoning;\n if (delta != null && delta.length > 0) yield delta;\n } else if (\n event.event === \"content-block-finish\" &&\n isReasoningContent(event.content)\n ) {\n return;\n } else if (event.event === \"message-finish\") {\n return;\n }\n }\n }\n return gen();\n }\n\n then<TResult1 = string, TResult2 = never>(\n onfulfilled?: ((value: string) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n const promise = (async () => {\n let text = \"\";\n for await (const delta of this) {\n text += delta;\n }\n return text;\n })();\n return promise.then(onfulfilled, onrejected);\n }\n}\n\n// ─── Sub-Stream: Usage ──────────────────────────────────────────\n\n/**\n * Typed stream for usage metadata.\n */\nexport class UsageMetadataStream\n implements\n AsyncIterable<UsageMetadata>,\n PromiseLike<UsageMetadata | undefined>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(buffer: ReplayBuffer) {\n this._buffer = buffer;\n }\n\n [Symbol.asyncIterator](): AsyncIterator<UsageMetadata> {\n const buffer = this._buffer;\n async function* gen() {\n for await (const event of buffer.iterate()) {\n if (event.event === \"usage\") {\n const usage = normalizeUsage(event.usage);\n if (usage) yield usage;\n } else if (event.event === \"message-start\" && event.usage) {\n const usage = normalizeUsage(event.usage);\n if (usage) yield usage;\n } else if (event.event === \"message-finish\" && event.usage) {\n const usage = normalizeUsage(event.usage);\n if (usage) yield usage;\n }\n }\n }\n return gen();\n }\n\n then<TResult1 = UsageMetadata | undefined, TResult2 = never>(\n onfulfilled?:\n | ((value: UsageMetadata | undefined) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n const promise = (async () => {\n let latest: UsageMetadata | undefined;\n for await (const usage of this) {\n latest = usage;\n }\n return latest;\n })();\n return promise.then(onfulfilled, onrejected);\n }\n}\n\n// ─── ChatModelStream ────────────────────────────────────────────\n\n/**\n * The main stream object returned by chat model streaming.\n *\n * Implements `AsyncIterable<ChatModelStreamEvent>` for raw event access\n * and `PromiseLike<AIMessage>` for simple `await` usage.\n */\nexport class ChatModelStream\n implements AsyncIterable<ChatModelStreamEvent>, PromiseLike<AIMessage>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(source: AsyncIterable<ChatModelStreamEvent>) {\n this._buffer = new ReplayBuffer();\n this._consume(source);\n }\n\n /** @internal */\n private async _consume(\n source: AsyncIterable<ChatModelStreamEvent>\n ): Promise<void> {\n try {\n for await (const event of source) {\n this._buffer.push(event);\n }\n this._buffer.finish();\n } catch (err) {\n this._buffer.setError(\n err instanceof Error ? err : new Error(String(err))\n );\n }\n }\n\n [Symbol.asyncIterator](): AsyncIterator<ChatModelStreamEvent> {\n return this._buffer.iterate();\n }\n\n get text(): TextContentStream {\n return new TextContentStream(this._buffer);\n }\n\n get toolCalls(): ToolCallsStream {\n return new ToolCallsStream(this._buffer);\n }\n\n get reasoning(): ReasoningContentStream {\n return new ReasoningContentStream(this._buffer);\n }\n\n get usage(): UsageMetadataStream {\n return new UsageMetadataStream(this._buffer);\n }\n\n get output(): PromiseLike<AIMessage> {\n return { then: (onf, onr) => this._assembleMessage().then(onf, onr) };\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 /** @internal */\n private async _assembleMessage(): Promise<AIMessage> {\n const contentBlocks: Array<ContentBlock | undefined> = [];\n let id: string | undefined;\n let usage: UsageMetadata | undefined;\n let metadata: Record<string, unknown> = {};\n let finishReason: string | undefined;\n\n for await (const event of this._buffer.iterate()) {\n switch (event.event) {\n case \"message-start\":\n id = event.id ?? id;\n if (event.usage) usage = normalizeUsage(event.usage);\n break;\n\n case \"content-block-start\":\n contentBlocks[event.index] = event.content;\n break;\n\n case \"content-block-delta\": {\n const current = contentBlocks[event.index];\n const delta = getEventDelta(event);\n if (current) {\n if (delta) contentBlocks[event.index] = applyDelta(current, delta);\n }\n break;\n }\n\n case \"content-block-finish\":\n contentBlocks[event.index] = event.content;\n break;\n\n case \"usage\":\n usage = normalizeUsage(event.usage);\n break;\n\n case \"message-finish\":\n finishReason = event.reason;\n if (event.usage) usage = normalizeUsage(event.usage);\n if (event.responseMetadata) {\n metadata = {\n ...metadata,\n ...event.responseMetadata,\n };\n }\n break;\n\n default:\n break;\n }\n }\n\n const filteredBlocks = contentBlocks.filter(\n (b): b is ContentBlock => b != null\n );\n\n return new AIMessage({\n id,\n content: filteredBlocks,\n usage_metadata: usage,\n response_metadata: {\n ...metadata,\n ...(finishReason ? { finish_reason: finishReason } : {}),\n output_version: \"v1\" as const,\n },\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stream.cjs","names":["AIMessage"],"sources":["../../src/language_models/stream.ts"],"sourcesContent":["/**\n * Typed stream classes for chat model streaming.\n *\n * @module\n */\n\nimport { AIMessage } from \"../messages/ai.js\";\nimport type { ContentBlock } from \"../messages/content/index.js\";\nimport type { UsageMetadata } from \"../messages/metadata.js\";\nimport type { ChatModelStreamEvent, ContentBlockDelta } from \"./event.js\";\n\ntype UsageMetadataLike = Partial<UsageMetadata>;\n\n// ─── Replay Buffer ──────────────────────────────────────────────\n\n/**\n * A buffer that caches emitted events for replay.\n *\n * Multiple consumers can independently iterate the same buffer —\n * each gets its own cursor. Events are never consumed or removed.\n *\n * @internal\n */\nclass ReplayBuffer {\n private events: ChatModelStreamEvent[] = [];\n private finished = false;\n private waiters: Array<() => void> = [];\n private error: Error | null = null;\n\n push(event: ChatModelStreamEvent): void {\n this.events.push(event);\n const toWake = this.waiters.splice(0);\n for (const waiter of toWake) {\n waiter();\n }\n }\n\n finish(): void {\n this.finished = true;\n const toWake = this.waiters.splice(0);\n for (const waiter of toWake) {\n waiter();\n }\n }\n\n setError(err: Error): void {\n this.error = err;\n this.finished = true;\n const toWake = this.waiters.splice(0);\n for (const waiter of toWake) {\n waiter();\n }\n }\n\n async *iterate(): AsyncGenerator<ChatModelStreamEvent> {\n if (this.finished) {\n if (this.error) throw this.error;\n yield* this.events;\n return;\n }\n\n let cursor = 0;\n while (true) {\n while (cursor < this.events.length) {\n yield this.events[cursor]!;\n cursor++;\n }\n if (this.finished) {\n if (this.error) throw this.error;\n return;\n }\n await new Promise<void>((resolve) => {\n if (cursor < this.events.length || this.finished) {\n resolve();\n return;\n }\n this.waiters.push(resolve);\n });\n }\n }\n}\n\n// ─── Accumulator ────────────────────────────────────────────────\n\n/**\n * Apply a typed delta to an accumulated content block.\n *\n * - `text-delta` → append text\n * - `reasoning-delta` → append reasoning text\n * - `data-delta` → append encoded data to `data`\n * - `block-delta` → shallow merge fields\n *\n * @internal\n */\nfunction applyDelta(\n block: ContentBlock,\n delta: ContentBlockDelta\n): ContentBlock {\n switch (delta.type) {\n case \"text-delta\":\n return {\n ...block,\n text: ((block as { text?: string }).text ?? \"\") + delta.text,\n } as ContentBlock;\n case \"reasoning-delta\":\n if ((block as { type?: string }).type === \"thinking\") {\n return {\n ...block,\n thinking:\n ((block as { thinking?: string }).thinking ?? \"\") + delta.reasoning,\n } as unknown as ContentBlock;\n }\n return {\n ...block,\n reasoning:\n ((block as { reasoning?: string }).reasoning ?? \"\") + delta.reasoning,\n } as ContentBlock;\n case \"data-delta\":\n return {\n ...block,\n data: ((block as { data?: string }).data ?? \"\") + delta.data,\n } as ContentBlock;\n case \"block-delta\":\n return { ...block, ...delta.fields } as ContentBlock;\n default:\n throw new Error(`Unknown delta type: ${JSON.stringify(delta)}`);\n }\n}\n\nfunction getEventDelta(\n event: ChatModelStreamEvent\n): ContentBlockDelta | undefined {\n if (event.event !== \"content-block-delta\") return undefined;\n if (\"delta\" in event && event.delta) return event.delta;\n\n // Transitional tolerance for any stream sources still emitting the previous\n // content-shaped delta object.\n const content = (event as { content?: unknown }).content;\n if (content == null || typeof content !== \"object\") return undefined;\n const block = content as { type?: string } & Record<string, unknown>;\n if (block.type === \"text\" && typeof block.text === \"string\") {\n return { type: \"text-delta\", text: block.text };\n }\n if (block.type === \"reasoning\" && typeof block.reasoning === \"string\") {\n return { type: \"reasoning-delta\", reasoning: block.reasoning };\n }\n if (block.type === \"thinking\" && typeof block.thinking === \"string\") {\n return { type: \"reasoning-delta\", reasoning: block.thinking };\n }\n if (typeof block.data === \"string\") {\n return { type: \"data-delta\", data: block.data, encoding: \"base64\" };\n }\n if (typeof block.type === \"string\") {\n return { type: \"block-delta\", fields: { ...block, type: block.type } };\n }\n return undefined;\n}\n\nfunction getReasoningDelta(content: unknown): string | undefined {\n if (content == null || typeof content !== \"object\") return undefined;\n const block = content as {\n type?: string;\n reasoning?: unknown;\n thinking?: unknown;\n };\n if (block.type === \"reasoning\" && typeof block.reasoning === \"string\") {\n return block.reasoning;\n }\n if (block.type === \"thinking\" && typeof block.thinking === \"string\") {\n return block.thinking;\n }\n return undefined;\n}\n\nfunction isReasoningContent(content: unknown): boolean {\n if (content == null || typeof content !== \"object\") return false;\n const type = (content as { type?: unknown }).type;\n return type === \"reasoning\" || type === \"thinking\";\n}\n\n/**\n * Normalize protocol-compatible partial usage into Core's concrete usage shape.\n *\n * Some stream sources emit usage snapshots without every aggregate token field.\n * Keep the stream event input permissive, then normalize at read time so\n * high-level Core consumers always receive a complete {@link UsageMetadata}.\n */\nfunction normalizeUsage(\n usage: UsageMetadataLike | 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 parseToolArgs(value: unknown): Record<string, unknown> {\n if (value != null && typeof value === \"object\" && !Array.isArray(value)) {\n return value as Record<string, unknown>;\n }\n if (typeof value !== \"string\" || value.length === 0) return {};\n try {\n const parsed = JSON.parse(value);\n return parsed != null &&\n typeof parsed === \"object\" &&\n !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n return {};\n }\n}\n\nfunction standardizeToolBlock(block: ContentBlock): ContentBlock {\n const record = block as Record<string, unknown>;\n if (block.type === \"tool_call\") return block;\n if (\n block.type !== \"tool_call_chunk\" &&\n block.type !== \"tool_use\" &&\n block.type !== \"input_json_delta\"\n ) {\n return block;\n }\n\n const name = typeof record.name === \"string\" ? record.name : undefined;\n if (name == null) return block;\n\n const args = record.args ?? record.input;\n return {\n ...record,\n type: \"tool_call\",\n name,\n args: parseToolArgs(args),\n } as unknown as ContentBlock;\n}\n\n// ─── Sub-Stream: Text ───────────────────────────────────────────\n\n/**\n * Typed stream for text content.\n *\n * - **Iterate**: yields incremental text deltas.\n * - **Await**: resolves to the complete concatenated text.\n * - **`.full`**: yields the running accumulated text after each delta.\n */\nexport class TextContentStream\n implements AsyncIterable<string>, PromiseLike<string>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(buffer: ReplayBuffer) {\n this._buffer = buffer;\n }\n\n /** Yields the accumulated text so far after each delta. */\n get full(): AsyncIterable<string> {\n const buffer = this._buffer;\n return {\n async *[Symbol.asyncIterator]() {\n let accumulated = \"\";\n for await (const event of buffer.iterate()) {\n const delta = getEventDelta(event);\n if (delta?.type === \"text-delta\") {\n accumulated += delta.text;\n yield accumulated;\n }\n }\n },\n };\n }\n\n /** Yields incremental text deltas. */\n [Symbol.asyncIterator](): AsyncIterator<string> {\n const buffer = this._buffer;\n async function* gen() {\n for await (const event of buffer.iterate()) {\n const delta = getEventDelta(event);\n if (delta?.type === \"text-delta\") {\n yield delta.text;\n }\n }\n }\n return gen();\n }\n\n then<TResult1 = string, TResult2 = never>(\n onfulfilled?: ((value: string) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n const promise = (async () => {\n let text = \"\";\n for await (const delta of this) {\n text += delta;\n }\n return text;\n })();\n return promise.then(onfulfilled, onrejected);\n }\n}\n\n// ─── Sub-Stream: Tool Calls ─────────────────────────────────────\n\n/**\n * Typed stream for tool calls.\n *\n * - **Iterate**: yields individual `ToolCall` objects as each completes.\n * - **Await**: resolves to the full array.\n * - **`.full`**: yields the accumulated array after each new tool call.\n */\nexport class ToolCallsStream\n implements\n AsyncIterable<ContentBlock.Tools.ToolCall>,\n PromiseLike<Array<ContentBlock.Tools.ToolCall>>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(buffer: ReplayBuffer) {\n this._buffer = buffer;\n }\n\n get full(): AsyncIterable<Array<ContentBlock.Tools.ToolCall>> {\n const buffer = this._buffer;\n return {\n async *[Symbol.asyncIterator]() {\n const calls: Array<ContentBlock.Tools.ToolCall> = [];\n for await (const event of buffer.iterate()) {\n if (\n event.event === \"content-block-finish\" &&\n event.content.type === \"tool_call\"\n ) {\n calls.push(event.content as ContentBlock.Tools.ToolCall);\n yield [...calls];\n }\n }\n },\n };\n }\n\n [Symbol.asyncIterator](): AsyncIterator<ContentBlock.Tools.ToolCall> {\n const buffer = this._buffer;\n async function* gen() {\n for await (const event of buffer.iterate()) {\n if (\n event.event === \"content-block-finish\" &&\n event.content.type === \"tool_call\"\n ) {\n yield event.content as ContentBlock.Tools.ToolCall;\n }\n }\n }\n return gen();\n }\n\n then<TResult1 = Array<ContentBlock.Tools.ToolCall>, TResult2 = never>(\n onfulfilled?:\n | ((\n value: Array<ContentBlock.Tools.ToolCall>\n ) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n const promise = (async () => {\n const calls: Array<ContentBlock.Tools.ToolCall> = [];\n for await (const call of this) {\n calls.push(call);\n }\n return calls;\n })();\n return promise.then(onfulfilled, onrejected);\n }\n}\n\n// ─── Sub-Stream: Reasoning ──────────────────────────────────────\n\n/**\n * Typed stream for reasoning content (chain-of-thought).\n * Same interface as {@link TextContentStream} but for reasoning blocks.\n */\nexport class ReasoningContentStream\n implements AsyncIterable<string>, PromiseLike<string>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(buffer: ReplayBuffer) {\n this._buffer = buffer;\n }\n\n get full(): AsyncIterable<string> {\n const buffer = this._buffer;\n return {\n async *[Symbol.asyncIterator]() {\n let accumulated = \"\";\n let seenReasoning = false;\n for await (const event of buffer.iterate()) {\n if (event.event === \"content-block-start\") {\n if (!isReasoningContent(event.content)) {\n if (seenReasoning) return;\n continue;\n }\n seenReasoning = true;\n const delta = getReasoningDelta(event.content);\n if (delta == null || delta.length === 0) continue;\n accumulated += delta;\n yield accumulated;\n } else if (event.event === \"content-block-delta\") {\n const eventDelta = getEventDelta(event);\n if (eventDelta?.type !== \"reasoning-delta\") continue;\n seenReasoning = true;\n const delta = eventDelta.reasoning;\n if (delta == null || delta.length === 0) continue;\n accumulated += delta;\n yield accumulated;\n } else if (\n event.event === \"content-block-finish\" &&\n isReasoningContent(event.content)\n ) {\n return;\n } else if (event.event === \"message-finish\") {\n return;\n }\n }\n },\n };\n }\n\n [Symbol.asyncIterator](): AsyncIterator<string> {\n const buffer = this._buffer;\n async function* gen() {\n let seenReasoning = false;\n for await (const event of buffer.iterate()) {\n if (event.event === \"content-block-start\") {\n if (!isReasoningContent(event.content)) {\n if (seenReasoning) return;\n continue;\n }\n seenReasoning = true;\n const delta = getReasoningDelta(event.content);\n if (delta != null && delta.length > 0) yield delta;\n } else if (event.event === \"content-block-delta\") {\n const eventDelta = getEventDelta(event);\n if (eventDelta?.type !== \"reasoning-delta\") continue;\n seenReasoning = true;\n const delta = eventDelta.reasoning;\n if (delta != null && delta.length > 0) yield delta;\n } else if (\n event.event === \"content-block-finish\" &&\n isReasoningContent(event.content)\n ) {\n return;\n } else if (event.event === \"message-finish\") {\n return;\n }\n }\n }\n return gen();\n }\n\n then<TResult1 = string, TResult2 = never>(\n onfulfilled?: ((value: string) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n const promise = (async () => {\n let text = \"\";\n for await (const delta of this) {\n text += delta;\n }\n return text;\n })();\n return promise.then(onfulfilled, onrejected);\n }\n}\n\n// ─── Sub-Stream: Usage ──────────────────────────────────────────\n\n/**\n * Typed stream for usage metadata.\n */\nexport class UsageMetadataStream\n implements\n AsyncIterable<UsageMetadata>,\n PromiseLike<UsageMetadata | undefined>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(buffer: ReplayBuffer) {\n this._buffer = buffer;\n }\n\n [Symbol.asyncIterator](): AsyncIterator<UsageMetadata> {\n const buffer = this._buffer;\n async function* gen() {\n for await (const event of buffer.iterate()) {\n if (event.event === \"usage\") {\n const usage = normalizeUsage(event.usage);\n if (usage) yield usage;\n } else if (event.event === \"message-start\" && event.usage) {\n const usage = normalizeUsage(event.usage);\n if (usage) yield usage;\n } else if (event.event === \"message-finish\" && event.usage) {\n const usage = normalizeUsage(event.usage);\n if (usage) yield usage;\n }\n }\n }\n return gen();\n }\n\n then<TResult1 = UsageMetadata | undefined, TResult2 = never>(\n onfulfilled?:\n | ((value: UsageMetadata | undefined) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n const promise = (async () => {\n let latest: UsageMetadata | undefined;\n for await (const usage of this) {\n latest = usage;\n }\n return latest;\n })();\n return promise.then(onfulfilled, onrejected);\n }\n}\n\n// ─── ChatModelStream ────────────────────────────────────────────\n\n/**\n * The main stream object returned by chat model streaming.\n *\n * Implements `AsyncIterable<ChatModelStreamEvent>` for raw event access\n * and `PromiseLike<AIMessage>` for simple `await` usage.\n */\nexport class ChatModelStream\n implements AsyncIterable<ChatModelStreamEvent>, PromiseLike<AIMessage>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(source: AsyncIterable<ChatModelStreamEvent>) {\n this._buffer = new ReplayBuffer();\n this._consume(source);\n }\n\n /** @internal */\n private async _consume(\n source: AsyncIterable<ChatModelStreamEvent>\n ): Promise<void> {\n try {\n for await (const event of source) {\n this._buffer.push(event);\n }\n this._buffer.finish();\n } catch (err) {\n this._buffer.setError(\n err instanceof Error ? err : new Error(String(err))\n );\n }\n }\n\n [Symbol.asyncIterator](): AsyncIterator<ChatModelStreamEvent> {\n return this._buffer.iterate();\n }\n\n get text(): TextContentStream {\n return new TextContentStream(this._buffer);\n }\n\n get toolCalls(): ToolCallsStream {\n return new ToolCallsStream(this._buffer);\n }\n\n get reasoning(): ReasoningContentStream {\n return new ReasoningContentStream(this._buffer);\n }\n\n get usage(): UsageMetadataStream {\n return new UsageMetadataStream(this._buffer);\n }\n\n get output(): PromiseLike<AIMessage> {\n return { then: (onf, onr) => this._assembleMessage().then(onf, onr) };\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 /** @internal */\n private async _assembleMessage(): Promise<AIMessage> {\n const contentBlocks: Array<ContentBlock | undefined> = [];\n let id: string | undefined;\n let usage: UsageMetadata | undefined;\n let metadata: Record<string, unknown> = {};\n let finishReason: string | undefined;\n\n for await (const event of this._buffer.iterate()) {\n switch (event.event) {\n case \"message-start\":\n id = event.id ?? id;\n if (event.usage) usage = normalizeUsage(event.usage);\n break;\n\n case \"content-block-start\":\n contentBlocks[event.index] = event.content;\n break;\n\n case \"content-block-delta\": {\n const current = contentBlocks[event.index];\n const delta = getEventDelta(event);\n if (current) {\n if (delta) contentBlocks[event.index] = applyDelta(current, delta);\n }\n break;\n }\n\n case \"content-block-finish\":\n contentBlocks[event.index] = event.content;\n break;\n\n case \"usage\":\n usage = normalizeUsage(event.usage);\n break;\n\n case \"message-finish\":\n finishReason = event.reason;\n if (event.usage) usage = normalizeUsage(event.usage);\n if (event.responseMetadata) {\n metadata = {\n ...metadata,\n ...event.responseMetadata,\n };\n }\n break;\n\n default:\n break;\n }\n }\n\n const filteredBlocks = contentBlocks\n .filter((b): b is ContentBlock => b != null)\n .map(standardizeToolBlock);\n\n return new AIMessage({\n id,\n content: filteredBlocks,\n usage_metadata: usage,\n response_metadata: {\n ...metadata,\n ...(finishReason ? { finish_reason: finishReason } : {}),\n output_version: \"v1\" as const,\n },\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.cts","names":[],"sources":["../../src/language_models/stream.ts"],"mappings":";;;;;;;;;;;;;;cAuBM,YAAA;EAAA,QACI,MAAA;EAAA,QACA,QAAA;EAAA,QACA,OAAA;EAAA,QACA,KAAA;EAER,IAAA,CAAK,KAAA,EAAO,oBAAA;EAQZ,MAAA,CAAA;EAQA,QAAA,CAAS,GAAA,EAAK,KAAA;EASP,OAAA,CAAA,GAAW,cAAA,CAAe,oBAAA;AAAA;;;;;
|
|
1
|
+
{"version":3,"file":"stream.d.cts","names":[],"sources":["../../src/language_models/stream.ts"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.ts","names":[],"sources":["../../src/language_models/stream.ts"],"mappings":";;;;;;;;;;;;;;cAuBM,YAAA;EAAA,QACI,MAAA;EAAA,QACA,QAAA;EAAA,QACA,OAAA;EAAA,QACA,KAAA;EAER,IAAA,CAAK,KAAA,EAAO,oBAAA;EAQZ,MAAA,CAAA;EAQA,QAAA,CAAS,GAAA,EAAK,KAAA;EASP,OAAA,CAAA,GAAW,cAAA,CAAe,oBAAA;AAAA;;;;;
|
|
1
|
+
{"version":3,"file":"stream.d.ts","names":[],"sources":["../../src/language_models/stream.ts"],"mappings":"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"}
|
|
@@ -162,6 +162,30 @@ function normalizeUsage(usage) {
|
|
|
162
162
|
total_tokens: usage.total_tokens ?? 0
|
|
163
163
|
};
|
|
164
164
|
}
|
|
165
|
+
function parseToolArgs(value) {
|
|
166
|
+
if (value != null && typeof value === "object" && !Array.isArray(value)) return value;
|
|
167
|
+
if (typeof value !== "string" || value.length === 0) return {};
|
|
168
|
+
try {
|
|
169
|
+
const parsed = JSON.parse(value);
|
|
170
|
+
return parsed != null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
171
|
+
} catch {
|
|
172
|
+
return {};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function standardizeToolBlock(block) {
|
|
176
|
+
const record = block;
|
|
177
|
+
if (block.type === "tool_call") return block;
|
|
178
|
+
if (block.type !== "tool_call_chunk" && block.type !== "tool_use" && block.type !== "input_json_delta") return block;
|
|
179
|
+
const name = typeof record.name === "string" ? record.name : void 0;
|
|
180
|
+
if (name == null) return block;
|
|
181
|
+
const args = record.args ?? record.input;
|
|
182
|
+
return {
|
|
183
|
+
...record,
|
|
184
|
+
type: "tool_call",
|
|
185
|
+
name,
|
|
186
|
+
args: parseToolArgs(args)
|
|
187
|
+
};
|
|
188
|
+
}
|
|
165
189
|
/**
|
|
166
190
|
* Typed stream for text content.
|
|
167
191
|
*
|
|
@@ -434,7 +458,7 @@ var ChatModelStream = class {
|
|
|
434
458
|
break;
|
|
435
459
|
default: break;
|
|
436
460
|
}
|
|
437
|
-
const filteredBlocks = contentBlocks.filter((b) => b != null);
|
|
461
|
+
const filteredBlocks = contentBlocks.filter((b) => b != null).map(standardizeToolBlock);
|
|
438
462
|
return new AIMessage({
|
|
439
463
|
id,
|
|
440
464
|
content: filteredBlocks,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.js","names":[],"sources":["../../src/language_models/stream.ts"],"sourcesContent":["/**\n * Typed stream classes for chat model streaming.\n *\n * @module\n */\n\nimport { AIMessage } from \"../messages/ai.js\";\nimport type { ContentBlock } from \"../messages/content/index.js\";\nimport type { UsageMetadata } from \"../messages/metadata.js\";\nimport type { ChatModelStreamEvent, ContentBlockDelta } from \"./event.js\";\n\ntype UsageMetadataLike = Partial<UsageMetadata>;\n\n// ─── Replay Buffer ──────────────────────────────────────────────\n\n/**\n * A buffer that caches emitted events for replay.\n *\n * Multiple consumers can independently iterate the same buffer —\n * each gets its own cursor. Events are never consumed or removed.\n *\n * @internal\n */\nclass ReplayBuffer {\n private events: ChatModelStreamEvent[] = [];\n private finished = false;\n private waiters: Array<() => void> = [];\n private error: Error | null = null;\n\n push(event: ChatModelStreamEvent): void {\n this.events.push(event);\n const toWake = this.waiters.splice(0);\n for (const waiter of toWake) {\n waiter();\n }\n }\n\n finish(): void {\n this.finished = true;\n const toWake = this.waiters.splice(0);\n for (const waiter of toWake) {\n waiter();\n }\n }\n\n setError(err: Error): void {\n this.error = err;\n this.finished = true;\n const toWake = this.waiters.splice(0);\n for (const waiter of toWake) {\n waiter();\n }\n }\n\n async *iterate(): AsyncGenerator<ChatModelStreamEvent> {\n if (this.finished) {\n if (this.error) throw this.error;\n yield* this.events;\n return;\n }\n\n let cursor = 0;\n while (true) {\n while (cursor < this.events.length) {\n yield this.events[cursor]!;\n cursor++;\n }\n if (this.finished) {\n if (this.error) throw this.error;\n return;\n }\n await new Promise<void>((resolve) => {\n if (cursor < this.events.length || this.finished) {\n resolve();\n return;\n }\n this.waiters.push(resolve);\n });\n }\n }\n}\n\n// ─── Accumulator ────────────────────────────────────────────────\n\n/**\n * Apply a typed delta to an accumulated content block.\n *\n * - `text-delta` → append text\n * - `reasoning-delta` → append reasoning text\n * - `data-delta` → append encoded data to `data`\n * - `block-delta` → shallow merge fields\n *\n * @internal\n */\nfunction applyDelta(\n block: ContentBlock,\n delta: ContentBlockDelta\n): ContentBlock {\n switch (delta.type) {\n case \"text-delta\":\n return {\n ...block,\n text: ((block as { text?: string }).text ?? \"\") + delta.text,\n } as ContentBlock;\n case \"reasoning-delta\":\n if ((block as { type?: string }).type === \"thinking\") {\n return {\n ...block,\n thinking:\n ((block as { thinking?: string }).thinking ?? \"\") + delta.reasoning,\n } as unknown as ContentBlock;\n }\n return {\n ...block,\n reasoning:\n ((block as { reasoning?: string }).reasoning ?? \"\") + delta.reasoning,\n } as ContentBlock;\n case \"data-delta\":\n return {\n ...block,\n data: ((block as { data?: string }).data ?? \"\") + delta.data,\n } as ContentBlock;\n case \"block-delta\":\n return { ...block, ...delta.fields } as ContentBlock;\n default:\n throw new Error(`Unknown delta type: ${JSON.stringify(delta)}`);\n }\n}\n\nfunction getEventDelta(\n event: ChatModelStreamEvent\n): ContentBlockDelta | undefined {\n if (event.event !== \"content-block-delta\") return undefined;\n if (\"delta\" in event && event.delta) return event.delta;\n\n // Transitional tolerance for any stream sources still emitting the previous\n // content-shaped delta object.\n const content = (event as { content?: unknown }).content;\n if (content == null || typeof content !== \"object\") return undefined;\n const block = content as { type?: string } & Record<string, unknown>;\n if (block.type === \"text\" && typeof block.text === \"string\") {\n return { type: \"text-delta\", text: block.text };\n }\n if (block.type === \"reasoning\" && typeof block.reasoning === \"string\") {\n return { type: \"reasoning-delta\", reasoning: block.reasoning };\n }\n if (block.type === \"thinking\" && typeof block.thinking === \"string\") {\n return { type: \"reasoning-delta\", reasoning: block.thinking };\n }\n if (typeof block.data === \"string\") {\n return { type: \"data-delta\", data: block.data, encoding: \"base64\" };\n }\n if (typeof block.type === \"string\") {\n return { type: \"block-delta\", fields: { ...block, type: block.type } };\n }\n return undefined;\n}\n\nfunction getReasoningDelta(content: unknown): string | undefined {\n if (content == null || typeof content !== \"object\") return undefined;\n const block = content as {\n type?: string;\n reasoning?: unknown;\n thinking?: unknown;\n };\n if (block.type === \"reasoning\" && typeof block.reasoning === \"string\") {\n return block.reasoning;\n }\n if (block.type === \"thinking\" && typeof block.thinking === \"string\") {\n return block.thinking;\n }\n return undefined;\n}\n\nfunction isReasoningContent(content: unknown): boolean {\n if (content == null || typeof content !== \"object\") return false;\n const type = (content as { type?: unknown }).type;\n return type === \"reasoning\" || type === \"thinking\";\n}\n\n/**\n * Normalize protocol-compatible partial usage into Core's concrete usage shape.\n *\n * Some stream sources emit usage snapshots without every aggregate token field.\n * Keep the stream event input permissive, then normalize at read time so\n * high-level Core consumers always receive a complete {@link UsageMetadata}.\n */\nfunction normalizeUsage(\n usage: UsageMetadataLike | 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\n// ─── Sub-Stream: Text ───────────────────────────────────────────\n\n/**\n * Typed stream for text content.\n *\n * - **Iterate**: yields incremental text deltas.\n * - **Await**: resolves to the complete concatenated text.\n * - **`.full`**: yields the running accumulated text after each delta.\n */\nexport class TextContentStream\n implements AsyncIterable<string>, PromiseLike<string>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(buffer: ReplayBuffer) {\n this._buffer = buffer;\n }\n\n /** Yields the accumulated text so far after each delta. */\n get full(): AsyncIterable<string> {\n const buffer = this._buffer;\n return {\n async *[Symbol.asyncIterator]() {\n let accumulated = \"\";\n for await (const event of buffer.iterate()) {\n const delta = getEventDelta(event);\n if (delta?.type === \"text-delta\") {\n accumulated += delta.text;\n yield accumulated;\n }\n }\n },\n };\n }\n\n /** Yields incremental text deltas. */\n [Symbol.asyncIterator](): AsyncIterator<string> {\n const buffer = this._buffer;\n async function* gen() {\n for await (const event of buffer.iterate()) {\n const delta = getEventDelta(event);\n if (delta?.type === \"text-delta\") {\n yield delta.text;\n }\n }\n }\n return gen();\n }\n\n then<TResult1 = string, TResult2 = never>(\n onfulfilled?: ((value: string) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n const promise = (async () => {\n let text = \"\";\n for await (const delta of this) {\n text += delta;\n }\n return text;\n })();\n return promise.then(onfulfilled, onrejected);\n }\n}\n\n// ─── Sub-Stream: Tool Calls ─────────────────────────────────────\n\n/**\n * Typed stream for tool calls.\n *\n * - **Iterate**: yields individual `ToolCall` objects as each completes.\n * - **Await**: resolves to the full array.\n * - **`.full`**: yields the accumulated array after each new tool call.\n */\nexport class ToolCallsStream\n implements\n AsyncIterable<ContentBlock.Tools.ToolCall>,\n PromiseLike<Array<ContentBlock.Tools.ToolCall>>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(buffer: ReplayBuffer) {\n this._buffer = buffer;\n }\n\n get full(): AsyncIterable<Array<ContentBlock.Tools.ToolCall>> {\n const buffer = this._buffer;\n return {\n async *[Symbol.asyncIterator]() {\n const calls: Array<ContentBlock.Tools.ToolCall> = [];\n for await (const event of buffer.iterate()) {\n if (\n event.event === \"content-block-finish\" &&\n event.content.type === \"tool_call\"\n ) {\n calls.push(event.content as ContentBlock.Tools.ToolCall);\n yield [...calls];\n }\n }\n },\n };\n }\n\n [Symbol.asyncIterator](): AsyncIterator<ContentBlock.Tools.ToolCall> {\n const buffer = this._buffer;\n async function* gen() {\n for await (const event of buffer.iterate()) {\n if (\n event.event === \"content-block-finish\" &&\n event.content.type === \"tool_call\"\n ) {\n yield event.content as ContentBlock.Tools.ToolCall;\n }\n }\n }\n return gen();\n }\n\n then<TResult1 = Array<ContentBlock.Tools.ToolCall>, TResult2 = never>(\n onfulfilled?:\n | ((\n value: Array<ContentBlock.Tools.ToolCall>\n ) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n const promise = (async () => {\n const calls: Array<ContentBlock.Tools.ToolCall> = [];\n for await (const call of this) {\n calls.push(call);\n }\n return calls;\n })();\n return promise.then(onfulfilled, onrejected);\n }\n}\n\n// ─── Sub-Stream: Reasoning ──────────────────────────────────────\n\n/**\n * Typed stream for reasoning content (chain-of-thought).\n * Same interface as {@link TextContentStream} but for reasoning blocks.\n */\nexport class ReasoningContentStream\n implements AsyncIterable<string>, PromiseLike<string>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(buffer: ReplayBuffer) {\n this._buffer = buffer;\n }\n\n get full(): AsyncIterable<string> {\n const buffer = this._buffer;\n return {\n async *[Symbol.asyncIterator]() {\n let accumulated = \"\";\n let seenReasoning = false;\n for await (const event of buffer.iterate()) {\n if (event.event === \"content-block-start\") {\n if (!isReasoningContent(event.content)) {\n if (seenReasoning) return;\n continue;\n }\n seenReasoning = true;\n const delta = getReasoningDelta(event.content);\n if (delta == null || delta.length === 0) continue;\n accumulated += delta;\n yield accumulated;\n } else if (event.event === \"content-block-delta\") {\n const eventDelta = getEventDelta(event);\n if (eventDelta?.type !== \"reasoning-delta\") continue;\n seenReasoning = true;\n const delta = eventDelta.reasoning;\n if (delta == null || delta.length === 0) continue;\n accumulated += delta;\n yield accumulated;\n } else if (\n event.event === \"content-block-finish\" &&\n isReasoningContent(event.content)\n ) {\n return;\n } else if (event.event === \"message-finish\") {\n return;\n }\n }\n },\n };\n }\n\n [Symbol.asyncIterator](): AsyncIterator<string> {\n const buffer = this._buffer;\n async function* gen() {\n let seenReasoning = false;\n for await (const event of buffer.iterate()) {\n if (event.event === \"content-block-start\") {\n if (!isReasoningContent(event.content)) {\n if (seenReasoning) return;\n continue;\n }\n seenReasoning = true;\n const delta = getReasoningDelta(event.content);\n if (delta != null && delta.length > 0) yield delta;\n } else if (event.event === \"content-block-delta\") {\n const eventDelta = getEventDelta(event);\n if (eventDelta?.type !== \"reasoning-delta\") continue;\n seenReasoning = true;\n const delta = eventDelta.reasoning;\n if (delta != null && delta.length > 0) yield delta;\n } else if (\n event.event === \"content-block-finish\" &&\n isReasoningContent(event.content)\n ) {\n return;\n } else if (event.event === \"message-finish\") {\n return;\n }\n }\n }\n return gen();\n }\n\n then<TResult1 = string, TResult2 = never>(\n onfulfilled?: ((value: string) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n const promise = (async () => {\n let text = \"\";\n for await (const delta of this) {\n text += delta;\n }\n return text;\n })();\n return promise.then(onfulfilled, onrejected);\n }\n}\n\n// ─── Sub-Stream: Usage ──────────────────────────────────────────\n\n/**\n * Typed stream for usage metadata.\n */\nexport class UsageMetadataStream\n implements\n AsyncIterable<UsageMetadata>,\n PromiseLike<UsageMetadata | undefined>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(buffer: ReplayBuffer) {\n this._buffer = buffer;\n }\n\n [Symbol.asyncIterator](): AsyncIterator<UsageMetadata> {\n const buffer = this._buffer;\n async function* gen() {\n for await (const event of buffer.iterate()) {\n if (event.event === \"usage\") {\n const usage = normalizeUsage(event.usage);\n if (usage) yield usage;\n } else if (event.event === \"message-start\" && event.usage) {\n const usage = normalizeUsage(event.usage);\n if (usage) yield usage;\n } else if (event.event === \"message-finish\" && event.usage) {\n const usage = normalizeUsage(event.usage);\n if (usage) yield usage;\n }\n }\n }\n return gen();\n }\n\n then<TResult1 = UsageMetadata | undefined, TResult2 = never>(\n onfulfilled?:\n | ((value: UsageMetadata | undefined) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n const promise = (async () => {\n let latest: UsageMetadata | undefined;\n for await (const usage of this) {\n latest = usage;\n }\n return latest;\n })();\n return promise.then(onfulfilled, onrejected);\n }\n}\n\n// ─── ChatModelStream ────────────────────────────────────────────\n\n/**\n * The main stream object returned by chat model streaming.\n *\n * Implements `AsyncIterable<ChatModelStreamEvent>` for raw event access\n * and `PromiseLike<AIMessage>` for simple `await` usage.\n */\nexport class ChatModelStream\n implements AsyncIterable<ChatModelStreamEvent>, PromiseLike<AIMessage>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(source: AsyncIterable<ChatModelStreamEvent>) {\n this._buffer = new ReplayBuffer();\n this._consume(source);\n }\n\n /** @internal */\n private async _consume(\n source: AsyncIterable<ChatModelStreamEvent>\n ): Promise<void> {\n try {\n for await (const event of source) {\n this._buffer.push(event);\n }\n this._buffer.finish();\n } catch (err) {\n this._buffer.setError(\n err instanceof Error ? err : new Error(String(err))\n );\n }\n }\n\n [Symbol.asyncIterator](): AsyncIterator<ChatModelStreamEvent> {\n return this._buffer.iterate();\n }\n\n get text(): TextContentStream {\n return new TextContentStream(this._buffer);\n }\n\n get toolCalls(): ToolCallsStream {\n return new ToolCallsStream(this._buffer);\n }\n\n get reasoning(): ReasoningContentStream {\n return new ReasoningContentStream(this._buffer);\n }\n\n get usage(): UsageMetadataStream {\n return new UsageMetadataStream(this._buffer);\n }\n\n get output(): PromiseLike<AIMessage> {\n return { then: (onf, onr) => this._assembleMessage().then(onf, onr) };\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 /** @internal */\n private async _assembleMessage(): Promise<AIMessage> {\n const contentBlocks: Array<ContentBlock | undefined> = [];\n let id: string | undefined;\n let usage: UsageMetadata | undefined;\n let metadata: Record<string, unknown> = {};\n let finishReason: string | undefined;\n\n for await (const event of this._buffer.iterate()) {\n switch (event.event) {\n case \"message-start\":\n id = event.id ?? id;\n if (event.usage) usage = normalizeUsage(event.usage);\n break;\n\n case \"content-block-start\":\n contentBlocks[event.index] = event.content;\n break;\n\n case \"content-block-delta\": {\n const current = contentBlocks[event.index];\n const delta = getEventDelta(event);\n if (current) {\n if (delta) contentBlocks[event.index] = applyDelta(current, delta);\n }\n break;\n }\n\n case \"content-block-finish\":\n contentBlocks[event.index] = event.content;\n break;\n\n case \"usage\":\n usage = normalizeUsage(event.usage);\n break;\n\n case \"message-finish\":\n finishReason = event.reason;\n if (event.usage) usage = normalizeUsage(event.usage);\n if (event.responseMetadata) {\n metadata = {\n ...metadata,\n ...event.responseMetadata,\n };\n }\n break;\n\n default:\n break;\n }\n }\n\n const filteredBlocks = contentBlocks.filter(\n (b): b is ContentBlock => b != null\n );\n\n return new AIMessage({\n id,\n content: filteredBlocks,\n usage_metadata: usage,\n response_metadata: {\n ...metadata,\n ...(finishReason ? { finish_reason: finishReason } : {}),\n output_version: \"v1\" as const,\n },\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stream.js","names":[],"sources":["../../src/language_models/stream.ts"],"sourcesContent":["/**\n * Typed stream classes for chat model streaming.\n *\n * @module\n */\n\nimport { AIMessage } from \"../messages/ai.js\";\nimport type { ContentBlock } from \"../messages/content/index.js\";\nimport type { UsageMetadata } from \"../messages/metadata.js\";\nimport type { ChatModelStreamEvent, ContentBlockDelta } from \"./event.js\";\n\ntype UsageMetadataLike = Partial<UsageMetadata>;\n\n// ─── Replay Buffer ──────────────────────────────────────────────\n\n/**\n * A buffer that caches emitted events for replay.\n *\n * Multiple consumers can independently iterate the same buffer —\n * each gets its own cursor. Events are never consumed or removed.\n *\n * @internal\n */\nclass ReplayBuffer {\n private events: ChatModelStreamEvent[] = [];\n private finished = false;\n private waiters: Array<() => void> = [];\n private error: Error | null = null;\n\n push(event: ChatModelStreamEvent): void {\n this.events.push(event);\n const toWake = this.waiters.splice(0);\n for (const waiter of toWake) {\n waiter();\n }\n }\n\n finish(): void {\n this.finished = true;\n const toWake = this.waiters.splice(0);\n for (const waiter of toWake) {\n waiter();\n }\n }\n\n setError(err: Error): void {\n this.error = err;\n this.finished = true;\n const toWake = this.waiters.splice(0);\n for (const waiter of toWake) {\n waiter();\n }\n }\n\n async *iterate(): AsyncGenerator<ChatModelStreamEvent> {\n if (this.finished) {\n if (this.error) throw this.error;\n yield* this.events;\n return;\n }\n\n let cursor = 0;\n while (true) {\n while (cursor < this.events.length) {\n yield this.events[cursor]!;\n cursor++;\n }\n if (this.finished) {\n if (this.error) throw this.error;\n return;\n }\n await new Promise<void>((resolve) => {\n if (cursor < this.events.length || this.finished) {\n resolve();\n return;\n }\n this.waiters.push(resolve);\n });\n }\n }\n}\n\n// ─── Accumulator ────────────────────────────────────────────────\n\n/**\n * Apply a typed delta to an accumulated content block.\n *\n * - `text-delta` → append text\n * - `reasoning-delta` → append reasoning text\n * - `data-delta` → append encoded data to `data`\n * - `block-delta` → shallow merge fields\n *\n * @internal\n */\nfunction applyDelta(\n block: ContentBlock,\n delta: ContentBlockDelta\n): ContentBlock {\n switch (delta.type) {\n case \"text-delta\":\n return {\n ...block,\n text: ((block as { text?: string }).text ?? \"\") + delta.text,\n } as ContentBlock;\n case \"reasoning-delta\":\n if ((block as { type?: string }).type === \"thinking\") {\n return {\n ...block,\n thinking:\n ((block as { thinking?: string }).thinking ?? \"\") + delta.reasoning,\n } as unknown as ContentBlock;\n }\n return {\n ...block,\n reasoning:\n ((block as { reasoning?: string }).reasoning ?? \"\") + delta.reasoning,\n } as ContentBlock;\n case \"data-delta\":\n return {\n ...block,\n data: ((block as { data?: string }).data ?? \"\") + delta.data,\n } as ContentBlock;\n case \"block-delta\":\n return { ...block, ...delta.fields } as ContentBlock;\n default:\n throw new Error(`Unknown delta type: ${JSON.stringify(delta)}`);\n }\n}\n\nfunction getEventDelta(\n event: ChatModelStreamEvent\n): ContentBlockDelta | undefined {\n if (event.event !== \"content-block-delta\") return undefined;\n if (\"delta\" in event && event.delta) return event.delta;\n\n // Transitional tolerance for any stream sources still emitting the previous\n // content-shaped delta object.\n const content = (event as { content?: unknown }).content;\n if (content == null || typeof content !== \"object\") return undefined;\n const block = content as { type?: string } & Record<string, unknown>;\n if (block.type === \"text\" && typeof block.text === \"string\") {\n return { type: \"text-delta\", text: block.text };\n }\n if (block.type === \"reasoning\" && typeof block.reasoning === \"string\") {\n return { type: \"reasoning-delta\", reasoning: block.reasoning };\n }\n if (block.type === \"thinking\" && typeof block.thinking === \"string\") {\n return { type: \"reasoning-delta\", reasoning: block.thinking };\n }\n if (typeof block.data === \"string\") {\n return { type: \"data-delta\", data: block.data, encoding: \"base64\" };\n }\n if (typeof block.type === \"string\") {\n return { type: \"block-delta\", fields: { ...block, type: block.type } };\n }\n return undefined;\n}\n\nfunction getReasoningDelta(content: unknown): string | undefined {\n if (content == null || typeof content !== \"object\") return undefined;\n const block = content as {\n type?: string;\n reasoning?: unknown;\n thinking?: unknown;\n };\n if (block.type === \"reasoning\" && typeof block.reasoning === \"string\") {\n return block.reasoning;\n }\n if (block.type === \"thinking\" && typeof block.thinking === \"string\") {\n return block.thinking;\n }\n return undefined;\n}\n\nfunction isReasoningContent(content: unknown): boolean {\n if (content == null || typeof content !== \"object\") return false;\n const type = (content as { type?: unknown }).type;\n return type === \"reasoning\" || type === \"thinking\";\n}\n\n/**\n * Normalize protocol-compatible partial usage into Core's concrete usage shape.\n *\n * Some stream sources emit usage snapshots without every aggregate token field.\n * Keep the stream event input permissive, then normalize at read time so\n * high-level Core consumers always receive a complete {@link UsageMetadata}.\n */\nfunction normalizeUsage(\n usage: UsageMetadataLike | 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 parseToolArgs(value: unknown): Record<string, unknown> {\n if (value != null && typeof value === \"object\" && !Array.isArray(value)) {\n return value as Record<string, unknown>;\n }\n if (typeof value !== \"string\" || value.length === 0) return {};\n try {\n const parsed = JSON.parse(value);\n return parsed != null &&\n typeof parsed === \"object\" &&\n !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n return {};\n }\n}\n\nfunction standardizeToolBlock(block: ContentBlock): ContentBlock {\n const record = block as Record<string, unknown>;\n if (block.type === \"tool_call\") return block;\n if (\n block.type !== \"tool_call_chunk\" &&\n block.type !== \"tool_use\" &&\n block.type !== \"input_json_delta\"\n ) {\n return block;\n }\n\n const name = typeof record.name === \"string\" ? record.name : undefined;\n if (name == null) return block;\n\n const args = record.args ?? record.input;\n return {\n ...record,\n type: \"tool_call\",\n name,\n args: parseToolArgs(args),\n } as unknown as ContentBlock;\n}\n\n// ─── Sub-Stream: Text ───────────────────────────────────────────\n\n/**\n * Typed stream for text content.\n *\n * - **Iterate**: yields incremental text deltas.\n * - **Await**: resolves to the complete concatenated text.\n * - **`.full`**: yields the running accumulated text after each delta.\n */\nexport class TextContentStream\n implements AsyncIterable<string>, PromiseLike<string>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(buffer: ReplayBuffer) {\n this._buffer = buffer;\n }\n\n /** Yields the accumulated text so far after each delta. */\n get full(): AsyncIterable<string> {\n const buffer = this._buffer;\n return {\n async *[Symbol.asyncIterator]() {\n let accumulated = \"\";\n for await (const event of buffer.iterate()) {\n const delta = getEventDelta(event);\n if (delta?.type === \"text-delta\") {\n accumulated += delta.text;\n yield accumulated;\n }\n }\n },\n };\n }\n\n /** Yields incremental text deltas. */\n [Symbol.asyncIterator](): AsyncIterator<string> {\n const buffer = this._buffer;\n async function* gen() {\n for await (const event of buffer.iterate()) {\n const delta = getEventDelta(event);\n if (delta?.type === \"text-delta\") {\n yield delta.text;\n }\n }\n }\n return gen();\n }\n\n then<TResult1 = string, TResult2 = never>(\n onfulfilled?: ((value: string) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n const promise = (async () => {\n let text = \"\";\n for await (const delta of this) {\n text += delta;\n }\n return text;\n })();\n return promise.then(onfulfilled, onrejected);\n }\n}\n\n// ─── Sub-Stream: Tool Calls ─────────────────────────────────────\n\n/**\n * Typed stream for tool calls.\n *\n * - **Iterate**: yields individual `ToolCall` objects as each completes.\n * - **Await**: resolves to the full array.\n * - **`.full`**: yields the accumulated array after each new tool call.\n */\nexport class ToolCallsStream\n implements\n AsyncIterable<ContentBlock.Tools.ToolCall>,\n PromiseLike<Array<ContentBlock.Tools.ToolCall>>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(buffer: ReplayBuffer) {\n this._buffer = buffer;\n }\n\n get full(): AsyncIterable<Array<ContentBlock.Tools.ToolCall>> {\n const buffer = this._buffer;\n return {\n async *[Symbol.asyncIterator]() {\n const calls: Array<ContentBlock.Tools.ToolCall> = [];\n for await (const event of buffer.iterate()) {\n if (\n event.event === \"content-block-finish\" &&\n event.content.type === \"tool_call\"\n ) {\n calls.push(event.content as ContentBlock.Tools.ToolCall);\n yield [...calls];\n }\n }\n },\n };\n }\n\n [Symbol.asyncIterator](): AsyncIterator<ContentBlock.Tools.ToolCall> {\n const buffer = this._buffer;\n async function* gen() {\n for await (const event of buffer.iterate()) {\n if (\n event.event === \"content-block-finish\" &&\n event.content.type === \"tool_call\"\n ) {\n yield event.content as ContentBlock.Tools.ToolCall;\n }\n }\n }\n return gen();\n }\n\n then<TResult1 = Array<ContentBlock.Tools.ToolCall>, TResult2 = never>(\n onfulfilled?:\n | ((\n value: Array<ContentBlock.Tools.ToolCall>\n ) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n const promise = (async () => {\n const calls: Array<ContentBlock.Tools.ToolCall> = [];\n for await (const call of this) {\n calls.push(call);\n }\n return calls;\n })();\n return promise.then(onfulfilled, onrejected);\n }\n}\n\n// ─── Sub-Stream: Reasoning ──────────────────────────────────────\n\n/**\n * Typed stream for reasoning content (chain-of-thought).\n * Same interface as {@link TextContentStream} but for reasoning blocks.\n */\nexport class ReasoningContentStream\n implements AsyncIterable<string>, PromiseLike<string>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(buffer: ReplayBuffer) {\n this._buffer = buffer;\n }\n\n get full(): AsyncIterable<string> {\n const buffer = this._buffer;\n return {\n async *[Symbol.asyncIterator]() {\n let accumulated = \"\";\n let seenReasoning = false;\n for await (const event of buffer.iterate()) {\n if (event.event === \"content-block-start\") {\n if (!isReasoningContent(event.content)) {\n if (seenReasoning) return;\n continue;\n }\n seenReasoning = true;\n const delta = getReasoningDelta(event.content);\n if (delta == null || delta.length === 0) continue;\n accumulated += delta;\n yield accumulated;\n } else if (event.event === \"content-block-delta\") {\n const eventDelta = getEventDelta(event);\n if (eventDelta?.type !== \"reasoning-delta\") continue;\n seenReasoning = true;\n const delta = eventDelta.reasoning;\n if (delta == null || delta.length === 0) continue;\n accumulated += delta;\n yield accumulated;\n } else if (\n event.event === \"content-block-finish\" &&\n isReasoningContent(event.content)\n ) {\n return;\n } else if (event.event === \"message-finish\") {\n return;\n }\n }\n },\n };\n }\n\n [Symbol.asyncIterator](): AsyncIterator<string> {\n const buffer = this._buffer;\n async function* gen() {\n let seenReasoning = false;\n for await (const event of buffer.iterate()) {\n if (event.event === \"content-block-start\") {\n if (!isReasoningContent(event.content)) {\n if (seenReasoning) return;\n continue;\n }\n seenReasoning = true;\n const delta = getReasoningDelta(event.content);\n if (delta != null && delta.length > 0) yield delta;\n } else if (event.event === \"content-block-delta\") {\n const eventDelta = getEventDelta(event);\n if (eventDelta?.type !== \"reasoning-delta\") continue;\n seenReasoning = true;\n const delta = eventDelta.reasoning;\n if (delta != null && delta.length > 0) yield delta;\n } else if (\n event.event === \"content-block-finish\" &&\n isReasoningContent(event.content)\n ) {\n return;\n } else if (event.event === \"message-finish\") {\n return;\n }\n }\n }\n return gen();\n }\n\n then<TResult1 = string, TResult2 = never>(\n onfulfilled?: ((value: string) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n const promise = (async () => {\n let text = \"\";\n for await (const delta of this) {\n text += delta;\n }\n return text;\n })();\n return promise.then(onfulfilled, onrejected);\n }\n}\n\n// ─── Sub-Stream: Usage ──────────────────────────────────────────\n\n/**\n * Typed stream for usage metadata.\n */\nexport class UsageMetadataStream\n implements\n AsyncIterable<UsageMetadata>,\n PromiseLike<UsageMetadata | undefined>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(buffer: ReplayBuffer) {\n this._buffer = buffer;\n }\n\n [Symbol.asyncIterator](): AsyncIterator<UsageMetadata> {\n const buffer = this._buffer;\n async function* gen() {\n for await (const event of buffer.iterate()) {\n if (event.event === \"usage\") {\n const usage = normalizeUsage(event.usage);\n if (usage) yield usage;\n } else if (event.event === \"message-start\" && event.usage) {\n const usage = normalizeUsage(event.usage);\n if (usage) yield usage;\n } else if (event.event === \"message-finish\" && event.usage) {\n const usage = normalizeUsage(event.usage);\n if (usage) yield usage;\n }\n }\n }\n return gen();\n }\n\n then<TResult1 = UsageMetadata | undefined, TResult2 = never>(\n onfulfilled?:\n | ((value: UsageMetadata | undefined) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null\n ): PromiseLike<TResult1 | TResult2> {\n const promise = (async () => {\n let latest: UsageMetadata | undefined;\n for await (const usage of this) {\n latest = usage;\n }\n return latest;\n })();\n return promise.then(onfulfilled, onrejected);\n }\n}\n\n// ─── ChatModelStream ────────────────────────────────────────────\n\n/**\n * The main stream object returned by chat model streaming.\n *\n * Implements `AsyncIterable<ChatModelStreamEvent>` for raw event access\n * and `PromiseLike<AIMessage>` for simple `await` usage.\n */\nexport class ChatModelStream\n implements AsyncIterable<ChatModelStreamEvent>, PromiseLike<AIMessage>\n{\n /** @internal */\n private _buffer: ReplayBuffer;\n\n /** @internal */\n constructor(source: AsyncIterable<ChatModelStreamEvent>) {\n this._buffer = new ReplayBuffer();\n this._consume(source);\n }\n\n /** @internal */\n private async _consume(\n source: AsyncIterable<ChatModelStreamEvent>\n ): Promise<void> {\n try {\n for await (const event of source) {\n this._buffer.push(event);\n }\n this._buffer.finish();\n } catch (err) {\n this._buffer.setError(\n err instanceof Error ? err : new Error(String(err))\n );\n }\n }\n\n [Symbol.asyncIterator](): AsyncIterator<ChatModelStreamEvent> {\n return this._buffer.iterate();\n }\n\n get text(): TextContentStream {\n return new TextContentStream(this._buffer);\n }\n\n get toolCalls(): ToolCallsStream {\n return new ToolCallsStream(this._buffer);\n }\n\n get reasoning(): ReasoningContentStream {\n return new ReasoningContentStream(this._buffer);\n }\n\n get usage(): UsageMetadataStream {\n return new UsageMetadataStream(this._buffer);\n }\n\n get output(): PromiseLike<AIMessage> {\n return { then: (onf, onr) => this._assembleMessage().then(onf, onr) };\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 /** @internal */\n private async _assembleMessage(): Promise<AIMessage> {\n const contentBlocks: Array<ContentBlock | undefined> = [];\n let id: string | undefined;\n let usage: UsageMetadata | undefined;\n let metadata: Record<string, unknown> = {};\n let finishReason: string | undefined;\n\n for await (const event of this._buffer.iterate()) {\n switch (event.event) {\n case \"message-start\":\n id = event.id ?? id;\n if (event.usage) usage = normalizeUsage(event.usage);\n break;\n\n case \"content-block-start\":\n contentBlocks[event.index] = event.content;\n break;\n\n case \"content-block-delta\": {\n const current = contentBlocks[event.index];\n const delta = getEventDelta(event);\n if (current) {\n if (delta) contentBlocks[event.index] = applyDelta(current, delta);\n }\n break;\n }\n\n case \"content-block-finish\":\n contentBlocks[event.index] = event.content;\n break;\n\n case \"usage\":\n usage = normalizeUsage(event.usage);\n break;\n\n case \"message-finish\":\n finishReason = event.reason;\n if (event.usage) usage = normalizeUsage(event.usage);\n if (event.responseMetadata) {\n metadata = {\n ...metadata,\n ...event.responseMetadata,\n };\n }\n break;\n\n default:\n break;\n }\n }\n\n const filteredBlocks = contentBlocks\n .filter((b): b is ContentBlock => b != null)\n .map(standardizeToolBlock);\n\n return new AIMessage({\n id,\n content: filteredBlocks,\n usage_metadata: usage,\n response_metadata: {\n ...metadata,\n ...(finishReason ? { finish_reason: finishReason } : {}),\n output_version: \"v1\" as const,\n },\n });\n }\n}\n"],"mappings":"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"}
|