@langchain/anthropic 1.3.27 → 1.3.29

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.
@@ -0,0 +1,301 @@
1
+ //#region src/utils/stream_events.ts
2
+ /**
3
+ * Convert an async iterable of raw Anthropic stream events into
4
+ * LangChain `ChatModelStreamEvent`s with typed deltas.
5
+ */
6
+ async function* convertAnthropicStream(source, options = {}) {
7
+ const shouldStreamUsage = options.streamUsage ?? true;
8
+ const blockAccumulators = /* @__PURE__ */ new Map();
9
+ let usageSnapshot;
10
+ let stopReason = null;
11
+ for await (const data of source) switch (data.type) {
12
+ case "message_start": {
13
+ const { usage, id, model } = data.message;
14
+ if (usage && shouldStreamUsage) usageSnapshot = buildUsageSnapshot(usage);
15
+ yield {
16
+ event: "message-start",
17
+ id,
18
+ ...usageSnapshot ? { usage: usageSnapshot } : {}
19
+ };
20
+ yield {
21
+ event: "provider",
22
+ provider: "anthropic",
23
+ name: "message_start",
24
+ payload: {
25
+ model,
26
+ id
27
+ }
28
+ };
29
+ break;
30
+ }
31
+ case "message_delta":
32
+ stopReason = data.delta.stop_reason;
33
+ if (shouldStreamUsage && data.usage) {
34
+ if (!usageSnapshot) usageSnapshot = {
35
+ input_tokens: 0,
36
+ output_tokens: data.usage.output_tokens,
37
+ total_tokens: data.usage.output_tokens
38
+ };
39
+ else usageSnapshot = {
40
+ ...usageSnapshot,
41
+ output_tokens: usageSnapshot.output_tokens + data.usage.output_tokens,
42
+ total_tokens: usageSnapshot.input_tokens + usageSnapshot.output_tokens + data.usage.output_tokens
43
+ };
44
+ yield {
45
+ event: "usage",
46
+ usage: usageSnapshot
47
+ };
48
+ }
49
+ if ("context_management" in data.delta && data.delta.context_management) yield {
50
+ event: "provider",
51
+ provider: "anthropic",
52
+ name: "context_management",
53
+ payload: data.delta.context_management
54
+ };
55
+ break;
56
+ case "message_stop":
57
+ yield {
58
+ event: "message-finish",
59
+ reason: mapStopReason(stopReason),
60
+ ...usageSnapshot ? { usage: usageSnapshot } : {},
61
+ metadata: { model_provider: "anthropic" }
62
+ };
63
+ break;
64
+ case "content_block_start": {
65
+ const { index, content_block } = data;
66
+ const mapped = mapBlockToContentBlock(content_block, index);
67
+ blockAccumulators.set(index, { ...mapped });
68
+ yield {
69
+ event: "content-block-start",
70
+ index,
71
+ content: mapped
72
+ };
73
+ break;
74
+ }
75
+ case "content_block_delta": {
76
+ const { index, delta } = data;
77
+ const acc = blockAccumulators.get(index);
78
+ if (!acc) break;
79
+ const { contentDelta, accumulated } = applyAnthropicDelta(acc, delta);
80
+ blockAccumulators.set(index, accumulated);
81
+ yield {
82
+ event: "content-block-delta",
83
+ index,
84
+ delta: contentDelta
85
+ };
86
+ break;
87
+ }
88
+ case "content_block_stop": {
89
+ const { index } = data;
90
+ const acc = blockAccumulators.get(index);
91
+ if (!acc) break;
92
+ yield {
93
+ event: "content-block-finish",
94
+ index,
95
+ content: finalizeBlock(acc)
96
+ };
97
+ blockAccumulators.delete(index);
98
+ break;
99
+ }
100
+ default:
101
+ yield {
102
+ event: "provider",
103
+ provider: "anthropic",
104
+ name: data.type,
105
+ payload: data
106
+ };
107
+ break;
108
+ }
109
+ }
110
+ function mapStopReason(stopReason) {
111
+ switch (stopReason) {
112
+ case "end_turn":
113
+ case "stop_sequence": return "stop";
114
+ case "tool_use": return "tool_use";
115
+ case "max_tokens": return "length";
116
+ default: return "stop";
117
+ }
118
+ }
119
+ function buildUsageSnapshot(usage) {
120
+ const cacheCreation = usage.cache_creation_input_tokens ?? 0;
121
+ const cacheRead = usage.cache_read_input_tokens ?? 0;
122
+ const totalInput = usage.input_tokens + cacheCreation + cacheRead;
123
+ return {
124
+ input_tokens: totalInput,
125
+ output_tokens: usage.output_tokens,
126
+ total_tokens: totalInput + usage.output_tokens,
127
+ input_token_details: {
128
+ cache_creation: cacheCreation,
129
+ cache_read: cacheRead
130
+ }
131
+ };
132
+ }
133
+ function mapBlockToContentBlock(block, index) {
134
+ switch (block.type) {
135
+ case "text": return {
136
+ type: "text",
137
+ text: block.text ?? "",
138
+ index
139
+ };
140
+ case "thinking": return {
141
+ type: "reasoning",
142
+ reasoning: block.thinking ?? "",
143
+ index
144
+ };
145
+ case "redacted_thinking": return {
146
+ type: "non_standard",
147
+ value: { ...block },
148
+ index
149
+ };
150
+ case "tool_use": return {
151
+ type: "tool_call_chunk",
152
+ id: block.id,
153
+ name: block.name,
154
+ args: "",
155
+ index
156
+ };
157
+ case "server_tool_use": return {
158
+ type: "server_tool_call_chunk",
159
+ id: block.id,
160
+ name: block.name,
161
+ args: "",
162
+ index
163
+ };
164
+ default: return {
165
+ type: "non_standard",
166
+ value: { ...block },
167
+ index
168
+ };
169
+ }
170
+ }
171
+ /**
172
+ * Map an Anthropic content_block_delta to a content block delta
173
+ * and update the accumulated state.
174
+ */
175
+ function applyAnthropicDelta(accumulated, delta) {
176
+ switch (delta.type) {
177
+ case "text_delta": return {
178
+ contentDelta: {
179
+ type: "text-delta",
180
+ text: delta.text
181
+ },
182
+ accumulated: {
183
+ ...accumulated,
184
+ text: (accumulated.text ?? "") + delta.text
185
+ }
186
+ };
187
+ case "thinking_delta": return {
188
+ contentDelta: {
189
+ type: "reasoning-delta",
190
+ reasoning: delta.thinking
191
+ },
192
+ accumulated: {
193
+ ...accumulated,
194
+ reasoning: (accumulated.reasoning ?? "") + delta.thinking
195
+ }
196
+ };
197
+ case "input_json_delta": {
198
+ const newArgs = (accumulated.args ?? "") + delta.partial_json;
199
+ return {
200
+ contentDelta: {
201
+ type: "block-delta",
202
+ fields: {
203
+ type: accumulated.type,
204
+ args: newArgs
205
+ }
206
+ },
207
+ accumulated: {
208
+ ...accumulated,
209
+ args: newArgs
210
+ }
211
+ };
212
+ }
213
+ case "citations_delta": {
214
+ const annotations = [...accumulated.annotations ?? [], delta.citation];
215
+ return {
216
+ contentDelta: {
217
+ type: "block-delta",
218
+ fields: {
219
+ type: accumulated.type,
220
+ annotations
221
+ }
222
+ },
223
+ accumulated: {
224
+ ...accumulated,
225
+ annotations
226
+ }
227
+ };
228
+ }
229
+ case "signature_delta": return {
230
+ contentDelta: {
231
+ type: "block-delta",
232
+ fields: {
233
+ type: accumulated.type,
234
+ signature: delta.signature
235
+ }
236
+ },
237
+ accumulated: {
238
+ ...accumulated,
239
+ signature: delta.signature
240
+ }
241
+ };
242
+ case "compaction_delta": return {
243
+ contentDelta: {
244
+ type: "block-delta",
245
+ fields: {
246
+ type: "non_standard",
247
+ value: {
248
+ ...accumulated.value ?? {},
249
+ compaction: delta
250
+ }
251
+ }
252
+ },
253
+ accumulated: {
254
+ ...accumulated,
255
+ value: {
256
+ ...accumulated.value ?? {},
257
+ compaction: delta
258
+ }
259
+ }
260
+ };
261
+ default: return {
262
+ contentDelta: {
263
+ type: "block-delta",
264
+ fields: {
265
+ type: accumulated.type,
266
+ ...delta
267
+ }
268
+ },
269
+ accumulated
270
+ };
271
+ }
272
+ }
273
+ function finalizeBlock(accumulated) {
274
+ if (accumulated.type === "tool_call_chunk" || accumulated.type === "server_tool_call_chunk") {
275
+ const finalType = accumulated.type === "tool_call_chunk" ? "tool_call" : "server_tool_call";
276
+ let parsedArgs;
277
+ try {
278
+ parsedArgs = JSON.parse(accumulated.args || "{}");
279
+ } catch {
280
+ return {
281
+ type: "invalid_tool_call",
282
+ id: accumulated.id,
283
+ name: accumulated.name,
284
+ args: accumulated.args,
285
+ error: "Failed to parse tool call arguments as JSON"
286
+ };
287
+ }
288
+ return {
289
+ type: finalType,
290
+ id: accumulated.id,
291
+ name: accumulated.name,
292
+ args: parsedArgs
293
+ };
294
+ }
295
+ const { index: _index, ...rest } = accumulated;
296
+ return rest;
297
+ }
298
+ //#endregion
299
+ exports.convertAnthropicStream = convertAnthropicStream;
300
+
301
+ //# sourceMappingURL=stream_events.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream_events.cjs","names":[],"sources":["../../src/utils/stream_events.ts"],"sourcesContent":["/**\n * Converts a raw Anthropic SSE event stream into LangChain ChatModelStreamEvents.\n *\n * @module\n */\n\nimport type Anthropic from \"@anthropic-ai/sdk\";\nimport type {\n ChatModelStreamEvent,\n ContentBlockDelta,\n FinishReason,\n} from \"@langchain/core/language_models/event\";\nimport type { ContentBlock } from \"@langchain/core/messages/content\";\nimport type { UsageMetadata } from \"@langchain/core/messages/metadata\";\nimport type { AnthropicMessageStreamEvent } from \"../types.js\";\n\n// ─── Public API ─────────────────────────────────────────────────\n\nexport interface ConvertAnthropicStreamOptions {\n streamUsage?: boolean;\n}\n\n/**\n * Convert an async iterable of raw Anthropic stream events into\n * LangChain `ChatModelStreamEvent`s with typed deltas.\n */\nexport async function* convertAnthropicStream(\n source: AsyncIterable<AnthropicMessageStreamEvent>,\n options: ConvertAnthropicStreamOptions = {}\n): AsyncGenerator<ChatModelStreamEvent> {\n const shouldStreamUsage = options.streamUsage ?? true;\n\n // Track accumulated state per content block (for finalization)\n const blockAccumulators = new Map<\n number,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n Record<string, any>\n >();\n let usageSnapshot: UsageMetadata | undefined;\n let stopReason: string | null = null;\n\n for await (const data of source) {\n switch (data.type) {\n // ── Message lifecycle ──────────────────────────────────\n case \"message_start\": {\n const { usage, id, model } = data.message;\n if (usage && shouldStreamUsage) {\n usageSnapshot = buildUsageSnapshot(usage);\n }\n yield {\n event: \"message-start\" as const,\n id,\n ...(usageSnapshot ? { usage: usageSnapshot } : {}),\n };\n yield {\n event: \"provider\" as const,\n provider: \"anthropic\",\n name: \"message_start\",\n payload: { model, id },\n };\n break;\n }\n\n case \"message_delta\": {\n stopReason = data.delta.stop_reason;\n if (shouldStreamUsage && data.usage) {\n if (!usageSnapshot) {\n usageSnapshot = {\n input_tokens: 0,\n output_tokens: data.usage.output_tokens,\n total_tokens: data.usage.output_tokens,\n };\n } else {\n usageSnapshot = {\n ...usageSnapshot,\n output_tokens:\n usageSnapshot.output_tokens + data.usage.output_tokens,\n total_tokens:\n usageSnapshot.input_tokens +\n usageSnapshot.output_tokens +\n data.usage.output_tokens,\n };\n }\n yield { event: \"usage\" as const, usage: usageSnapshot };\n }\n if (\n \"context_management\" in data.delta &&\n data.delta.context_management\n ) {\n yield {\n event: \"provider\" as const,\n provider: \"anthropic\",\n name: \"context_management\",\n payload: data.delta.context_management,\n };\n }\n break;\n }\n\n case \"message_stop\": {\n yield {\n event: \"message-finish\" as const,\n reason: mapStopReason(stopReason),\n ...(usageSnapshot ? { usage: usageSnapshot } : {}),\n metadata: { model_provider: \"anthropic\" },\n };\n break;\n }\n\n // ── Content block lifecycle ───────────────────────────\n case \"content_block_start\": {\n const { index, content_block } = data;\n const mapped = mapBlockToContentBlock(content_block, index);\n blockAccumulators.set(index, { ...mapped });\n yield {\n event: \"content-block-start\" as const,\n index,\n content: mapped,\n };\n break;\n }\n\n case \"content_block_delta\": {\n const { index, delta } = data;\n const acc = blockAccumulators.get(index);\n if (!acc) break;\n\n const { contentDelta, accumulated } = applyAnthropicDelta(acc, delta);\n blockAccumulators.set(index, accumulated);\n\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: contentDelta,\n };\n break;\n }\n\n case \"content_block_stop\": {\n const { index } = data;\n const acc = blockAccumulators.get(index);\n if (!acc) break;\n\n const finalized = finalizeBlock(acc);\n yield {\n event: \"content-block-finish\" as const,\n index,\n content: finalized,\n };\n blockAccumulators.delete(index);\n break;\n }\n\n // ── Unhandled → provider passthrough ───────────────────\n default: {\n yield {\n event: \"provider\" as const,\n provider: \"anthropic\",\n name: data.type,\n payload: data,\n };\n break;\n }\n }\n }\n}\n\n// ─── Internal helpers ───────────────────────────────────────────\n\nfunction mapStopReason(stopReason: string | null | undefined): FinishReason {\n switch (stopReason) {\n case \"end_turn\":\n case \"stop_sequence\":\n return \"stop\";\n case \"tool_use\":\n return \"tool_use\";\n case \"max_tokens\":\n return \"length\";\n default:\n return \"stop\";\n }\n}\n\nfunction buildUsageSnapshot(\n usage: Anthropic.Messages.Usage | Record<string, number>\n): UsageMetadata {\n const cacheCreation =\n (usage as Record<string, number>).cache_creation_input_tokens ?? 0;\n const cacheRead =\n (usage as Record<string, number>).cache_read_input_tokens ?? 0;\n const totalInput = usage.input_tokens + cacheCreation + cacheRead;\n return {\n input_tokens: totalInput,\n output_tokens: usage.output_tokens,\n total_tokens: totalInput + usage.output_tokens,\n input_token_details: {\n cache_creation: cacheCreation,\n cache_read: cacheRead,\n },\n };\n}\n\nfunction mapBlockToContentBlock(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n block: any,\n index: number\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n): Record<string, any> {\n switch (block.type) {\n case \"text\":\n return { type: \"text\" as const, text: block.text ?? \"\", index };\n case \"thinking\":\n return {\n type: \"reasoning\" as const,\n reasoning: block.thinking ?? \"\",\n index,\n };\n case \"redacted_thinking\":\n return { type: \"non_standard\" as const, value: { ...block }, index };\n case \"tool_use\":\n return {\n type: \"tool_call_chunk\" as const,\n id: block.id,\n name: block.name,\n args: \"\",\n index,\n };\n case \"server_tool_use\":\n return {\n type: \"server_tool_call_chunk\" as const,\n id: block.id,\n name: block.name,\n args: \"\",\n index,\n };\n default:\n return { type: \"non_standard\" as const, value: { ...block }, index };\n }\n}\n\n/**\n * Map an Anthropic content_block_delta to a content block delta\n * and update the accumulated state.\n */\nfunction applyAnthropicDelta(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n accumulated: Record<string, any>,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n delta: any\n): {\n contentDelta: ContentBlockDelta;\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n accumulated: Record<string, any>;\n} {\n switch (delta.type) {\n case \"text_delta\":\n return {\n contentDelta: { type: \"text-delta\" as const, text: delta.text },\n accumulated: {\n ...accumulated,\n text: (accumulated.text ?? \"\") + delta.text,\n },\n };\n\n case \"thinking_delta\":\n return {\n contentDelta: {\n type: \"reasoning-delta\" as const,\n reasoning: delta.thinking,\n },\n accumulated: {\n ...accumulated,\n reasoning: (accumulated.reasoning ?? \"\") + delta.thinking,\n },\n };\n\n case \"input_json_delta\": {\n const newArgs = (accumulated.args ?? \"\") + delta.partial_json;\n return {\n contentDelta: {\n type: \"block-delta\" as const,\n fields: { type: accumulated.type, args: newArgs },\n },\n accumulated: { ...accumulated, args: newArgs },\n };\n }\n\n case \"citations_delta\": {\n const annotations = [...(accumulated.annotations ?? []), delta.citation];\n return {\n contentDelta: {\n type: \"block-delta\" as const,\n fields: {\n type: accumulated.type,\n annotations,\n },\n },\n accumulated: {\n ...accumulated,\n annotations,\n },\n };\n }\n\n case \"signature_delta\":\n return {\n contentDelta: {\n type: \"block-delta\" as const,\n fields: { type: accumulated.type, signature: delta.signature },\n },\n accumulated: { ...accumulated, signature: delta.signature },\n };\n\n case \"compaction_delta\":\n return {\n contentDelta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"non_standard\",\n value: { ...(accumulated.value ?? {}), compaction: delta },\n },\n },\n accumulated: {\n ...accumulated,\n value: { ...(accumulated.value ?? {}), compaction: delta },\n },\n };\n\n default:\n return {\n contentDelta: {\n type: \"block-delta\" as const,\n fields: { type: accumulated.type, ...delta },\n },\n accumulated,\n };\n }\n}\n\nfunction finalizeBlock(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n accumulated: Record<string, any>\n): ContentBlock {\n if (\n accumulated.type === \"tool_call_chunk\" ||\n accumulated.type === \"server_tool_call_chunk\"\n ) {\n const finalType =\n accumulated.type === \"tool_call_chunk\"\n ? (\"tool_call\" as const)\n : (\"server_tool_call\" as const);\n let parsedArgs: unknown;\n try {\n parsedArgs = JSON.parse(accumulated.args || \"{}\");\n } catch {\n return {\n type: \"invalid_tool_call\" as const,\n id: accumulated.id,\n name: accumulated.name,\n args: accumulated.args,\n error: \"Failed to parse tool call arguments as JSON\",\n } as ContentBlock.Tools.InvalidToolCall;\n }\n return {\n type: finalType,\n id: accumulated.id,\n name: accumulated.name,\n args: parsedArgs,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n } as any;\n }\n\n const { index: _index, ...rest } = accumulated;\n return rest as ContentBlock;\n}\n"],"mappings":"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"}
@@ -0,0 +1,301 @@
1
+ //#region src/utils/stream_events.ts
2
+ /**
3
+ * Convert an async iterable of raw Anthropic stream events into
4
+ * LangChain `ChatModelStreamEvent`s with typed deltas.
5
+ */
6
+ async function* convertAnthropicStream(source, options = {}) {
7
+ const shouldStreamUsage = options.streamUsage ?? true;
8
+ const blockAccumulators = /* @__PURE__ */ new Map();
9
+ let usageSnapshot;
10
+ let stopReason = null;
11
+ for await (const data of source) switch (data.type) {
12
+ case "message_start": {
13
+ const { usage, id, model } = data.message;
14
+ if (usage && shouldStreamUsage) usageSnapshot = buildUsageSnapshot(usage);
15
+ yield {
16
+ event: "message-start",
17
+ id,
18
+ ...usageSnapshot ? { usage: usageSnapshot } : {}
19
+ };
20
+ yield {
21
+ event: "provider",
22
+ provider: "anthropic",
23
+ name: "message_start",
24
+ payload: {
25
+ model,
26
+ id
27
+ }
28
+ };
29
+ break;
30
+ }
31
+ case "message_delta":
32
+ stopReason = data.delta.stop_reason;
33
+ if (shouldStreamUsage && data.usage) {
34
+ if (!usageSnapshot) usageSnapshot = {
35
+ input_tokens: 0,
36
+ output_tokens: data.usage.output_tokens,
37
+ total_tokens: data.usage.output_tokens
38
+ };
39
+ else usageSnapshot = {
40
+ ...usageSnapshot,
41
+ output_tokens: usageSnapshot.output_tokens + data.usage.output_tokens,
42
+ total_tokens: usageSnapshot.input_tokens + usageSnapshot.output_tokens + data.usage.output_tokens
43
+ };
44
+ yield {
45
+ event: "usage",
46
+ usage: usageSnapshot
47
+ };
48
+ }
49
+ if ("context_management" in data.delta && data.delta.context_management) yield {
50
+ event: "provider",
51
+ provider: "anthropic",
52
+ name: "context_management",
53
+ payload: data.delta.context_management
54
+ };
55
+ break;
56
+ case "message_stop":
57
+ yield {
58
+ event: "message-finish",
59
+ reason: mapStopReason(stopReason),
60
+ ...usageSnapshot ? { usage: usageSnapshot } : {},
61
+ metadata: { model_provider: "anthropic" }
62
+ };
63
+ break;
64
+ case "content_block_start": {
65
+ const { index, content_block } = data;
66
+ const mapped = mapBlockToContentBlock(content_block, index);
67
+ blockAccumulators.set(index, { ...mapped });
68
+ yield {
69
+ event: "content-block-start",
70
+ index,
71
+ content: mapped
72
+ };
73
+ break;
74
+ }
75
+ case "content_block_delta": {
76
+ const { index, delta } = data;
77
+ const acc = blockAccumulators.get(index);
78
+ if (!acc) break;
79
+ const { contentDelta, accumulated } = applyAnthropicDelta(acc, delta);
80
+ blockAccumulators.set(index, accumulated);
81
+ yield {
82
+ event: "content-block-delta",
83
+ index,
84
+ delta: contentDelta
85
+ };
86
+ break;
87
+ }
88
+ case "content_block_stop": {
89
+ const { index } = data;
90
+ const acc = blockAccumulators.get(index);
91
+ if (!acc) break;
92
+ yield {
93
+ event: "content-block-finish",
94
+ index,
95
+ content: finalizeBlock(acc)
96
+ };
97
+ blockAccumulators.delete(index);
98
+ break;
99
+ }
100
+ default:
101
+ yield {
102
+ event: "provider",
103
+ provider: "anthropic",
104
+ name: data.type,
105
+ payload: data
106
+ };
107
+ break;
108
+ }
109
+ }
110
+ function mapStopReason(stopReason) {
111
+ switch (stopReason) {
112
+ case "end_turn":
113
+ case "stop_sequence": return "stop";
114
+ case "tool_use": return "tool_use";
115
+ case "max_tokens": return "length";
116
+ default: return "stop";
117
+ }
118
+ }
119
+ function buildUsageSnapshot(usage) {
120
+ const cacheCreation = usage.cache_creation_input_tokens ?? 0;
121
+ const cacheRead = usage.cache_read_input_tokens ?? 0;
122
+ const totalInput = usage.input_tokens + cacheCreation + cacheRead;
123
+ return {
124
+ input_tokens: totalInput,
125
+ output_tokens: usage.output_tokens,
126
+ total_tokens: totalInput + usage.output_tokens,
127
+ input_token_details: {
128
+ cache_creation: cacheCreation,
129
+ cache_read: cacheRead
130
+ }
131
+ };
132
+ }
133
+ function mapBlockToContentBlock(block, index) {
134
+ switch (block.type) {
135
+ case "text": return {
136
+ type: "text",
137
+ text: block.text ?? "",
138
+ index
139
+ };
140
+ case "thinking": return {
141
+ type: "reasoning",
142
+ reasoning: block.thinking ?? "",
143
+ index
144
+ };
145
+ case "redacted_thinking": return {
146
+ type: "non_standard",
147
+ value: { ...block },
148
+ index
149
+ };
150
+ case "tool_use": return {
151
+ type: "tool_call_chunk",
152
+ id: block.id,
153
+ name: block.name,
154
+ args: "",
155
+ index
156
+ };
157
+ case "server_tool_use": return {
158
+ type: "server_tool_call_chunk",
159
+ id: block.id,
160
+ name: block.name,
161
+ args: "",
162
+ index
163
+ };
164
+ default: return {
165
+ type: "non_standard",
166
+ value: { ...block },
167
+ index
168
+ };
169
+ }
170
+ }
171
+ /**
172
+ * Map an Anthropic content_block_delta to a content block delta
173
+ * and update the accumulated state.
174
+ */
175
+ function applyAnthropicDelta(accumulated, delta) {
176
+ switch (delta.type) {
177
+ case "text_delta": return {
178
+ contentDelta: {
179
+ type: "text-delta",
180
+ text: delta.text
181
+ },
182
+ accumulated: {
183
+ ...accumulated,
184
+ text: (accumulated.text ?? "") + delta.text
185
+ }
186
+ };
187
+ case "thinking_delta": return {
188
+ contentDelta: {
189
+ type: "reasoning-delta",
190
+ reasoning: delta.thinking
191
+ },
192
+ accumulated: {
193
+ ...accumulated,
194
+ reasoning: (accumulated.reasoning ?? "") + delta.thinking
195
+ }
196
+ };
197
+ case "input_json_delta": {
198
+ const newArgs = (accumulated.args ?? "") + delta.partial_json;
199
+ return {
200
+ contentDelta: {
201
+ type: "block-delta",
202
+ fields: {
203
+ type: accumulated.type,
204
+ args: newArgs
205
+ }
206
+ },
207
+ accumulated: {
208
+ ...accumulated,
209
+ args: newArgs
210
+ }
211
+ };
212
+ }
213
+ case "citations_delta": {
214
+ const annotations = [...accumulated.annotations ?? [], delta.citation];
215
+ return {
216
+ contentDelta: {
217
+ type: "block-delta",
218
+ fields: {
219
+ type: accumulated.type,
220
+ annotations
221
+ }
222
+ },
223
+ accumulated: {
224
+ ...accumulated,
225
+ annotations
226
+ }
227
+ };
228
+ }
229
+ case "signature_delta": return {
230
+ contentDelta: {
231
+ type: "block-delta",
232
+ fields: {
233
+ type: accumulated.type,
234
+ signature: delta.signature
235
+ }
236
+ },
237
+ accumulated: {
238
+ ...accumulated,
239
+ signature: delta.signature
240
+ }
241
+ };
242
+ case "compaction_delta": return {
243
+ contentDelta: {
244
+ type: "block-delta",
245
+ fields: {
246
+ type: "non_standard",
247
+ value: {
248
+ ...accumulated.value ?? {},
249
+ compaction: delta
250
+ }
251
+ }
252
+ },
253
+ accumulated: {
254
+ ...accumulated,
255
+ value: {
256
+ ...accumulated.value ?? {},
257
+ compaction: delta
258
+ }
259
+ }
260
+ };
261
+ default: return {
262
+ contentDelta: {
263
+ type: "block-delta",
264
+ fields: {
265
+ type: accumulated.type,
266
+ ...delta
267
+ }
268
+ },
269
+ accumulated
270
+ };
271
+ }
272
+ }
273
+ function finalizeBlock(accumulated) {
274
+ if (accumulated.type === "tool_call_chunk" || accumulated.type === "server_tool_call_chunk") {
275
+ const finalType = accumulated.type === "tool_call_chunk" ? "tool_call" : "server_tool_call";
276
+ let parsedArgs;
277
+ try {
278
+ parsedArgs = JSON.parse(accumulated.args || "{}");
279
+ } catch {
280
+ return {
281
+ type: "invalid_tool_call",
282
+ id: accumulated.id,
283
+ name: accumulated.name,
284
+ args: accumulated.args,
285
+ error: "Failed to parse tool call arguments as JSON"
286
+ };
287
+ }
288
+ return {
289
+ type: finalType,
290
+ id: accumulated.id,
291
+ name: accumulated.name,
292
+ args: parsedArgs
293
+ };
294
+ }
295
+ const { index: _index, ...rest } = accumulated;
296
+ return rest;
297
+ }
298
+ //#endregion
299
+ export { convertAnthropicStream };
300
+
301
+ //# sourceMappingURL=stream_events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream_events.js","names":[],"sources":["../../src/utils/stream_events.ts"],"sourcesContent":["/**\n * Converts a raw Anthropic SSE event stream into LangChain ChatModelStreamEvents.\n *\n * @module\n */\n\nimport type Anthropic from \"@anthropic-ai/sdk\";\nimport type {\n ChatModelStreamEvent,\n ContentBlockDelta,\n FinishReason,\n} from \"@langchain/core/language_models/event\";\nimport type { ContentBlock } from \"@langchain/core/messages/content\";\nimport type { UsageMetadata } from \"@langchain/core/messages/metadata\";\nimport type { AnthropicMessageStreamEvent } from \"../types.js\";\n\n// ─── Public API ─────────────────────────────────────────────────\n\nexport interface ConvertAnthropicStreamOptions {\n streamUsage?: boolean;\n}\n\n/**\n * Convert an async iterable of raw Anthropic stream events into\n * LangChain `ChatModelStreamEvent`s with typed deltas.\n */\nexport async function* convertAnthropicStream(\n source: AsyncIterable<AnthropicMessageStreamEvent>,\n options: ConvertAnthropicStreamOptions = {}\n): AsyncGenerator<ChatModelStreamEvent> {\n const shouldStreamUsage = options.streamUsage ?? true;\n\n // Track accumulated state per content block (for finalization)\n const blockAccumulators = new Map<\n number,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n Record<string, any>\n >();\n let usageSnapshot: UsageMetadata | undefined;\n let stopReason: string | null = null;\n\n for await (const data of source) {\n switch (data.type) {\n // ── Message lifecycle ──────────────────────────────────\n case \"message_start\": {\n const { usage, id, model } = data.message;\n if (usage && shouldStreamUsage) {\n usageSnapshot = buildUsageSnapshot(usage);\n }\n yield {\n event: \"message-start\" as const,\n id,\n ...(usageSnapshot ? { usage: usageSnapshot } : {}),\n };\n yield {\n event: \"provider\" as const,\n provider: \"anthropic\",\n name: \"message_start\",\n payload: { model, id },\n };\n break;\n }\n\n case \"message_delta\": {\n stopReason = data.delta.stop_reason;\n if (shouldStreamUsage && data.usage) {\n if (!usageSnapshot) {\n usageSnapshot = {\n input_tokens: 0,\n output_tokens: data.usage.output_tokens,\n total_tokens: data.usage.output_tokens,\n };\n } else {\n usageSnapshot = {\n ...usageSnapshot,\n output_tokens:\n usageSnapshot.output_tokens + data.usage.output_tokens,\n total_tokens:\n usageSnapshot.input_tokens +\n usageSnapshot.output_tokens +\n data.usage.output_tokens,\n };\n }\n yield { event: \"usage\" as const, usage: usageSnapshot };\n }\n if (\n \"context_management\" in data.delta &&\n data.delta.context_management\n ) {\n yield {\n event: \"provider\" as const,\n provider: \"anthropic\",\n name: \"context_management\",\n payload: data.delta.context_management,\n };\n }\n break;\n }\n\n case \"message_stop\": {\n yield {\n event: \"message-finish\" as const,\n reason: mapStopReason(stopReason),\n ...(usageSnapshot ? { usage: usageSnapshot } : {}),\n metadata: { model_provider: \"anthropic\" },\n };\n break;\n }\n\n // ── Content block lifecycle ───────────────────────────\n case \"content_block_start\": {\n const { index, content_block } = data;\n const mapped = mapBlockToContentBlock(content_block, index);\n blockAccumulators.set(index, { ...mapped });\n yield {\n event: \"content-block-start\" as const,\n index,\n content: mapped,\n };\n break;\n }\n\n case \"content_block_delta\": {\n const { index, delta } = data;\n const acc = blockAccumulators.get(index);\n if (!acc) break;\n\n const { contentDelta, accumulated } = applyAnthropicDelta(acc, delta);\n blockAccumulators.set(index, accumulated);\n\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: contentDelta,\n };\n break;\n }\n\n case \"content_block_stop\": {\n const { index } = data;\n const acc = blockAccumulators.get(index);\n if (!acc) break;\n\n const finalized = finalizeBlock(acc);\n yield {\n event: \"content-block-finish\" as const,\n index,\n content: finalized,\n };\n blockAccumulators.delete(index);\n break;\n }\n\n // ── Unhandled → provider passthrough ───────────────────\n default: {\n yield {\n event: \"provider\" as const,\n provider: \"anthropic\",\n name: data.type,\n payload: data,\n };\n break;\n }\n }\n }\n}\n\n// ─── Internal helpers ───────────────────────────────────────────\n\nfunction mapStopReason(stopReason: string | null | undefined): FinishReason {\n switch (stopReason) {\n case \"end_turn\":\n case \"stop_sequence\":\n return \"stop\";\n case \"tool_use\":\n return \"tool_use\";\n case \"max_tokens\":\n return \"length\";\n default:\n return \"stop\";\n }\n}\n\nfunction buildUsageSnapshot(\n usage: Anthropic.Messages.Usage | Record<string, number>\n): UsageMetadata {\n const cacheCreation =\n (usage as Record<string, number>).cache_creation_input_tokens ?? 0;\n const cacheRead =\n (usage as Record<string, number>).cache_read_input_tokens ?? 0;\n const totalInput = usage.input_tokens + cacheCreation + cacheRead;\n return {\n input_tokens: totalInput,\n output_tokens: usage.output_tokens,\n total_tokens: totalInput + usage.output_tokens,\n input_token_details: {\n cache_creation: cacheCreation,\n cache_read: cacheRead,\n },\n };\n}\n\nfunction mapBlockToContentBlock(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n block: any,\n index: number\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n): Record<string, any> {\n switch (block.type) {\n case \"text\":\n return { type: \"text\" as const, text: block.text ?? \"\", index };\n case \"thinking\":\n return {\n type: \"reasoning\" as const,\n reasoning: block.thinking ?? \"\",\n index,\n };\n case \"redacted_thinking\":\n return { type: \"non_standard\" as const, value: { ...block }, index };\n case \"tool_use\":\n return {\n type: \"tool_call_chunk\" as const,\n id: block.id,\n name: block.name,\n args: \"\",\n index,\n };\n case \"server_tool_use\":\n return {\n type: \"server_tool_call_chunk\" as const,\n id: block.id,\n name: block.name,\n args: \"\",\n index,\n };\n default:\n return { type: \"non_standard\" as const, value: { ...block }, index };\n }\n}\n\n/**\n * Map an Anthropic content_block_delta to a content block delta\n * and update the accumulated state.\n */\nfunction applyAnthropicDelta(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n accumulated: Record<string, any>,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n delta: any\n): {\n contentDelta: ContentBlockDelta;\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n accumulated: Record<string, any>;\n} {\n switch (delta.type) {\n case \"text_delta\":\n return {\n contentDelta: { type: \"text-delta\" as const, text: delta.text },\n accumulated: {\n ...accumulated,\n text: (accumulated.text ?? \"\") + delta.text,\n },\n };\n\n case \"thinking_delta\":\n return {\n contentDelta: {\n type: \"reasoning-delta\" as const,\n reasoning: delta.thinking,\n },\n accumulated: {\n ...accumulated,\n reasoning: (accumulated.reasoning ?? \"\") + delta.thinking,\n },\n };\n\n case \"input_json_delta\": {\n const newArgs = (accumulated.args ?? \"\") + delta.partial_json;\n return {\n contentDelta: {\n type: \"block-delta\" as const,\n fields: { type: accumulated.type, args: newArgs },\n },\n accumulated: { ...accumulated, args: newArgs },\n };\n }\n\n case \"citations_delta\": {\n const annotations = [...(accumulated.annotations ?? []), delta.citation];\n return {\n contentDelta: {\n type: \"block-delta\" as const,\n fields: {\n type: accumulated.type,\n annotations,\n },\n },\n accumulated: {\n ...accumulated,\n annotations,\n },\n };\n }\n\n case \"signature_delta\":\n return {\n contentDelta: {\n type: \"block-delta\" as const,\n fields: { type: accumulated.type, signature: delta.signature },\n },\n accumulated: { ...accumulated, signature: delta.signature },\n };\n\n case \"compaction_delta\":\n return {\n contentDelta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"non_standard\",\n value: { ...(accumulated.value ?? {}), compaction: delta },\n },\n },\n accumulated: {\n ...accumulated,\n value: { ...(accumulated.value ?? {}), compaction: delta },\n },\n };\n\n default:\n return {\n contentDelta: {\n type: \"block-delta\" as const,\n fields: { type: accumulated.type, ...delta },\n },\n accumulated,\n };\n }\n}\n\nfunction finalizeBlock(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n accumulated: Record<string, any>\n): ContentBlock {\n if (\n accumulated.type === \"tool_call_chunk\" ||\n accumulated.type === \"server_tool_call_chunk\"\n ) {\n const finalType =\n accumulated.type === \"tool_call_chunk\"\n ? (\"tool_call\" as const)\n : (\"server_tool_call\" as const);\n let parsedArgs: unknown;\n try {\n parsedArgs = JSON.parse(accumulated.args || \"{}\");\n } catch {\n return {\n type: \"invalid_tool_call\" as const,\n id: accumulated.id,\n name: accumulated.name,\n args: accumulated.args,\n error: \"Failed to parse tool call arguments as JSON\",\n } as ContentBlock.Tools.InvalidToolCall;\n }\n return {\n type: finalType,\n id: accumulated.id,\n name: accumulated.name,\n args: parsedArgs,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n } as any;\n }\n\n const { index: _index, ...rest } = accumulated;\n return rest as ContentBlock;\n}\n"],"mappings":";;;;;AA0BA,gBAAuB,uBACrB,QACA,UAAyC,EAAE,EACL;CACtC,MAAM,oBAAoB,QAAQ,eAAe;CAGjD,MAAM,oCAAoB,IAAI,KAI3B;CACH,IAAI;CACJ,IAAI,aAA4B;AAEhC,YAAW,MAAM,QAAQ,OACvB,SAAQ,KAAK,MAAb;EAEE,KAAK,iBAAiB;GACpB,MAAM,EAAE,OAAO,IAAI,UAAU,KAAK;AAClC,OAAI,SAAS,kBACX,iBAAgB,mBAAmB,MAAM;AAE3C,SAAM;IACJ,OAAO;IACP;IACA,GAAI,gBAAgB,EAAE,OAAO,eAAe,GAAG,EAAE;IAClD;AACD,SAAM;IACJ,OAAO;IACP,UAAU;IACV,MAAM;IACN,SAAS;KAAE;KAAO;KAAI;IACvB;AACD;;EAGF,KAAK;AACH,gBAAa,KAAK,MAAM;AACxB,OAAI,qBAAqB,KAAK,OAAO;AACnC,QAAI,CAAC,cACH,iBAAgB;KACd,cAAc;KACd,eAAe,KAAK,MAAM;KAC1B,cAAc,KAAK,MAAM;KAC1B;QAED,iBAAgB;KACd,GAAG;KACH,eACE,cAAc,gBAAgB,KAAK,MAAM;KAC3C,cACE,cAAc,eACd,cAAc,gBACd,KAAK,MAAM;KACd;AAEH,UAAM;KAAE,OAAO;KAAkB,OAAO;KAAe;;AAEzD,OACE,wBAAwB,KAAK,SAC7B,KAAK,MAAM,mBAEX,OAAM;IACJ,OAAO;IACP,UAAU;IACV,MAAM;IACN,SAAS,KAAK,MAAM;IACrB;AAEH;EAGF,KAAK;AACH,SAAM;IACJ,OAAO;IACP,QAAQ,cAAc,WAAW;IACjC,GAAI,gBAAgB,EAAE,OAAO,eAAe,GAAG,EAAE;IACjD,UAAU,EAAE,gBAAgB,aAAa;IAC1C;AACD;EAIF,KAAK,uBAAuB;GAC1B,MAAM,EAAE,OAAO,kBAAkB;GACjC,MAAM,SAAS,uBAAuB,eAAe,MAAM;AAC3D,qBAAkB,IAAI,OAAO,EAAE,GAAG,QAAQ,CAAC;AAC3C,SAAM;IACJ,OAAO;IACP;IACA,SAAS;IACV;AACD;;EAGF,KAAK,uBAAuB;GAC1B,MAAM,EAAE,OAAO,UAAU;GACzB,MAAM,MAAM,kBAAkB,IAAI,MAAM;AACxC,OAAI,CAAC,IAAK;GAEV,MAAM,EAAE,cAAc,gBAAgB,oBAAoB,KAAK,MAAM;AACrE,qBAAkB,IAAI,OAAO,YAAY;AAEzC,SAAM;IACJ,OAAO;IACP;IACA,OAAO;IACR;AACD;;EAGF,KAAK,sBAAsB;GACzB,MAAM,EAAE,UAAU;GAClB,MAAM,MAAM,kBAAkB,IAAI,MAAM;AACxC,OAAI,CAAC,IAAK;AAGV,SAAM;IACJ,OAAO;IACP;IACA,SAJgB,cAAc,IAAI;IAKnC;AACD,qBAAkB,OAAO,MAAM;AAC/B;;EAIF;AACE,SAAM;IACJ,OAAO;IACP,UAAU;IACV,MAAM,KAAK;IACX,SAAS;IACV;AACD;;;AAQR,SAAS,cAAc,YAAqD;AAC1E,SAAQ,YAAR;EACE,KAAK;EACL,KAAK,gBACH,QAAO;EACT,KAAK,WACH,QAAO;EACT,KAAK,aACH,QAAO;EACT,QACE,QAAO;;;AAIb,SAAS,mBACP,OACe;CACf,MAAM,gBACH,MAAiC,+BAA+B;CACnE,MAAM,YACH,MAAiC,2BAA2B;CAC/D,MAAM,aAAa,MAAM,eAAe,gBAAgB;AACxD,QAAO;EACL,cAAc;EACd,eAAe,MAAM;EACrB,cAAc,aAAa,MAAM;EACjC,qBAAqB;GACnB,gBAAgB;GAChB,YAAY;GACb;EACF;;AAGH,SAAS,uBAEP,OACA,OAEqB;AACrB,SAAQ,MAAM,MAAd;EACE,KAAK,OACH,QAAO;GAAE,MAAM;GAAiB,MAAM,MAAM,QAAQ;GAAI;GAAO;EACjE,KAAK,WACH,QAAO;GACL,MAAM;GACN,WAAW,MAAM,YAAY;GAC7B;GACD;EACH,KAAK,oBACH,QAAO;GAAE,MAAM;GAAyB,OAAO,EAAE,GAAG,OAAO;GAAE;GAAO;EACtE,KAAK,WACH,QAAO;GACL,MAAM;GACN,IAAI,MAAM;GACV,MAAM,MAAM;GACZ,MAAM;GACN;GACD;EACH,KAAK,kBACH,QAAO;GACL,MAAM;GACN,IAAI,MAAM;GACV,MAAM,MAAM;GACZ,MAAM;GACN;GACD;EACH,QACE,QAAO;GAAE,MAAM;GAAyB,OAAO,EAAE,GAAG,OAAO;GAAE;GAAO;;;;;;;AAQ1E,SAAS,oBAEP,aAEA,OAKA;AACA,SAAQ,MAAM,MAAd;EACE,KAAK,aACH,QAAO;GACL,cAAc;IAAE,MAAM;IAAuB,MAAM,MAAM;IAAM;GAC/D,aAAa;IACX,GAAG;IACH,OAAO,YAAY,QAAQ,MAAM,MAAM;IACxC;GACF;EAEH,KAAK,iBACH,QAAO;GACL,cAAc;IACZ,MAAM;IACN,WAAW,MAAM;IAClB;GACD,aAAa;IACX,GAAG;IACH,YAAY,YAAY,aAAa,MAAM,MAAM;IAClD;GACF;EAEH,KAAK,oBAAoB;GACvB,MAAM,WAAW,YAAY,QAAQ,MAAM,MAAM;AACjD,UAAO;IACL,cAAc;KACZ,MAAM;KACN,QAAQ;MAAE,MAAM,YAAY;MAAM,MAAM;MAAS;KAClD;IACD,aAAa;KAAE,GAAG;KAAa,MAAM;KAAS;IAC/C;;EAGH,KAAK,mBAAmB;GACtB,MAAM,cAAc,CAAC,GAAI,YAAY,eAAe,EAAE,EAAG,MAAM,SAAS;AACxE,UAAO;IACL,cAAc;KACZ,MAAM;KACN,QAAQ;MACN,MAAM,YAAY;MAClB;MACD;KACF;IACD,aAAa;KACX,GAAG;KACH;KACD;IACF;;EAGH,KAAK,kBACH,QAAO;GACL,cAAc;IACZ,MAAM;IACN,QAAQ;KAAE,MAAM,YAAY;KAAM,WAAW,MAAM;KAAW;IAC/D;GACD,aAAa;IAAE,GAAG;IAAa,WAAW,MAAM;IAAW;GAC5D;EAEH,KAAK,mBACH,QAAO;GACL,cAAc;IACZ,MAAM;IACN,QAAQ;KACN,MAAM;KACN,OAAO;MAAE,GAAI,YAAY,SAAS,EAAE;MAAG,YAAY;MAAO;KAC3D;IACF;GACD,aAAa;IACX,GAAG;IACH,OAAO;KAAE,GAAI,YAAY,SAAS,EAAE;KAAG,YAAY;KAAO;IAC3D;GACF;EAEH,QACE,QAAO;GACL,cAAc;IACZ,MAAM;IACN,QAAQ;KAAE,MAAM,YAAY;KAAM,GAAG;KAAO;IAC7C;GACD;GACD;;;AAIP,SAAS,cAEP,aACc;AACd,KACE,YAAY,SAAS,qBACrB,YAAY,SAAS,0BACrB;EACA,MAAM,YACJ,YAAY,SAAS,oBAChB,cACA;EACP,IAAI;AACJ,MAAI;AACF,gBAAa,KAAK,MAAM,YAAY,QAAQ,KAAK;UAC3C;AACN,UAAO;IACL,MAAM;IACN,IAAI,YAAY;IAChB,MAAM,YAAY;IAClB,MAAM,YAAY;IAClB,OAAO;IACR;;AAEH,SAAO;GACL,MAAM;GACN,IAAI,YAAY;GAChB,MAAM,YAAY;GAClB,MAAM;GAEP;;CAGH,MAAM,EAAE,OAAO,QAAQ,GAAG,SAAS;AACnC,QAAO"}
@@ -1,6 +1,6 @@
1
1
  const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
2
  let zod_v4 = require("zod/v4");
3
- zod_v4 = require_runtime.__toESM(zod_v4);
3
+ zod_v4 = require_runtime.__toESM(zod_v4, 1);
4
4
  //#region src/utils/tools.ts
5
5
  function handleToolChoice(toolChoice) {
6
6
  if (!toolChoice) return;