@boostecom/provider 0.0.1

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.
Files changed (70) hide show
  1. package/README.md +90 -0
  2. package/dist/index.cjs +2522 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +848 -0
  5. package/dist/index.d.ts +848 -0
  6. package/dist/index.js +2484 -0
  7. package/dist/index.js.map +1 -0
  8. package/docs/content/README.md +337 -0
  9. package/docs/content/agent-teams.mdx +324 -0
  10. package/docs/content/api.mdx +757 -0
  11. package/docs/content/best-practices.mdx +624 -0
  12. package/docs/content/examples.mdx +675 -0
  13. package/docs/content/guide.mdx +516 -0
  14. package/docs/content/index.mdx +99 -0
  15. package/docs/content/installation.mdx +246 -0
  16. package/docs/content/skills.mdx +548 -0
  17. package/docs/content/troubleshooting.mdx +588 -0
  18. package/docs/examples/README.md +499 -0
  19. package/docs/examples/abort-signal.ts +125 -0
  20. package/docs/examples/agent-teams.ts +122 -0
  21. package/docs/examples/basic-usage.ts +73 -0
  22. package/docs/examples/check-cli.ts +51 -0
  23. package/docs/examples/conversation-history.ts +69 -0
  24. package/docs/examples/custom-config.ts +90 -0
  25. package/docs/examples/generate-object-constraints.ts +209 -0
  26. package/docs/examples/generate-object.ts +211 -0
  27. package/docs/examples/hooks-callbacks.ts +63 -0
  28. package/docs/examples/images.ts +76 -0
  29. package/docs/examples/integration-test.ts +241 -0
  30. package/docs/examples/limitations.ts +150 -0
  31. package/docs/examples/logging-custom-logger.ts +99 -0
  32. package/docs/examples/logging-default.ts +55 -0
  33. package/docs/examples/logging-disabled.ts +74 -0
  34. package/docs/examples/logging-verbose.ts +64 -0
  35. package/docs/examples/long-running-tasks.ts +179 -0
  36. package/docs/examples/message-injection.ts +210 -0
  37. package/docs/examples/mid-stream-injection.ts +126 -0
  38. package/docs/examples/run-all-examples.sh +48 -0
  39. package/docs/examples/sdk-tools-callbacks.ts +49 -0
  40. package/docs/examples/skills-discovery.ts +144 -0
  41. package/docs/examples/skills-management.ts +140 -0
  42. package/docs/examples/stream-object.ts +80 -0
  43. package/docs/examples/streaming.ts +52 -0
  44. package/docs/examples/structured-output-repro.ts +227 -0
  45. package/docs/examples/tool-management.ts +215 -0
  46. package/docs/examples/tool-streaming.ts +132 -0
  47. package/docs/examples/zod4-compatibility-test.ts +290 -0
  48. package/docs/src/claude-code-language-model.test.ts +3883 -0
  49. package/docs/src/claude-code-language-model.ts +2586 -0
  50. package/docs/src/claude-code-provider.test.ts +97 -0
  51. package/docs/src/claude-code-provider.ts +179 -0
  52. package/docs/src/convert-to-claude-code-messages.images.test.ts +104 -0
  53. package/docs/src/convert-to-claude-code-messages.test.ts +193 -0
  54. package/docs/src/convert-to-claude-code-messages.ts +419 -0
  55. package/docs/src/errors.test.ts +213 -0
  56. package/docs/src/errors.ts +216 -0
  57. package/docs/src/index.test.ts +49 -0
  58. package/docs/src/index.ts +98 -0
  59. package/docs/src/logger.integration.test.ts +164 -0
  60. package/docs/src/logger.test.ts +184 -0
  61. package/docs/src/logger.ts +65 -0
  62. package/docs/src/map-claude-code-finish-reason.test.ts +120 -0
  63. package/docs/src/map-claude-code-finish-reason.ts +60 -0
  64. package/docs/src/mcp-helpers.test.ts +71 -0
  65. package/docs/src/mcp-helpers.ts +123 -0
  66. package/docs/src/message-injection.test.ts +460 -0
  67. package/docs/src/types.ts +447 -0
  68. package/docs/src/validation.test.ts +558 -0
  69. package/docs/src/validation.ts +360 -0
  70. package/package.json +124 -0
package/dist/index.js ADDED
@@ -0,0 +1,2484 @@
1
+ // docs/src/claude-code-provider.ts
2
+ import { NoSuchModelError as NoSuchModelError2 } from "@ai-sdk/provider";
3
+
4
+ // docs/src/claude-code-language-model.ts
5
+ import { NoSuchModelError } from "@ai-sdk/provider";
6
+ import { generateId } from "@ai-sdk/provider-utils";
7
+
8
+ // docs/src/convert-to-claude-code-messages.ts
9
+ var IMAGE_URL_WARNING = "Image URLs are not supported by this provider; supply base64/data URLs.";
10
+ var IMAGE_CONVERSION_WARNING = "Unable to convert image content; supply base64/data URLs.";
11
+ function normalizeBase64(base64) {
12
+ return base64.replace(/\s+/g, "");
13
+ }
14
+ function isImageMimeType(mimeType) {
15
+ return typeof mimeType === "string" && mimeType.trim().toLowerCase().startsWith("image/");
16
+ }
17
+ function createImageContent(mediaType, data) {
18
+ const trimmedType = mediaType.trim();
19
+ const trimmedData = normalizeBase64(data.trim());
20
+ if (!trimmedType || !trimmedData) {
21
+ return void 0;
22
+ }
23
+ return {
24
+ type: "image",
25
+ source: {
26
+ type: "base64",
27
+ media_type: trimmedType,
28
+ data: trimmedData
29
+ }
30
+ };
31
+ }
32
+ function extractMimeType(candidate) {
33
+ if (typeof candidate === "string" && candidate.trim()) {
34
+ return candidate.trim();
35
+ }
36
+ return void 0;
37
+ }
38
+ function parseObjectImage(imageObj, fallbackMimeType) {
39
+ const data = typeof imageObj.data === "string" ? imageObj.data : void 0;
40
+ const mimeType = extractMimeType(
41
+ imageObj.mimeType ?? imageObj.mediaType ?? imageObj.media_type ?? fallbackMimeType
42
+ );
43
+ if (!data || !mimeType) {
44
+ return void 0;
45
+ }
46
+ return createImageContent(mimeType, data);
47
+ }
48
+ function parseStringImage(value, fallbackMimeType) {
49
+ const trimmed = value.trim();
50
+ if (/^https?:\/\//i.test(trimmed)) {
51
+ return { warning: IMAGE_URL_WARNING };
52
+ }
53
+ const dataUrlMatch = trimmed.match(/^data:([^;]+);base64,(.+)$/i);
54
+ if (dataUrlMatch) {
55
+ const [, mediaType, data] = dataUrlMatch;
56
+ const content = createImageContent(mediaType, data);
57
+ return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
58
+ }
59
+ const base64Match = trimmed.match(/^base64:([^,]+),(.+)$/i);
60
+ if (base64Match) {
61
+ const [, explicitMimeType, data] = base64Match;
62
+ const content = createImageContent(explicitMimeType, data);
63
+ return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
64
+ }
65
+ if (fallbackMimeType) {
66
+ const content = createImageContent(fallbackMimeType, trimmed);
67
+ if (content) {
68
+ return { content };
69
+ }
70
+ }
71
+ return { warning: IMAGE_CONVERSION_WARNING };
72
+ }
73
+ function parseImagePart(part) {
74
+ if (!part || typeof part !== "object") {
75
+ return { warning: IMAGE_CONVERSION_WARNING };
76
+ }
77
+ const imageValue = part.image;
78
+ const mimeType = extractMimeType(part.mimeType);
79
+ if (typeof imageValue === "string") {
80
+ return parseStringImage(imageValue, mimeType);
81
+ }
82
+ if (imageValue && typeof imageValue === "object") {
83
+ const content = parseObjectImage(imageValue, mimeType);
84
+ return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
85
+ }
86
+ return { warning: IMAGE_CONVERSION_WARNING };
87
+ }
88
+ function convertBinaryToBase64(data) {
89
+ if (typeof Buffer !== "undefined") {
90
+ const buffer = data instanceof Uint8Array ? Buffer.from(data) : Buffer.from(new Uint8Array(data));
91
+ return buffer.toString("base64");
92
+ }
93
+ if (typeof btoa === "function") {
94
+ const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
95
+ let binary = "";
96
+ const chunkSize = 32768;
97
+ for (let i = 0; i < bytes.length; i += chunkSize) {
98
+ const chunk = bytes.subarray(i, i + chunkSize);
99
+ binary += String.fromCharCode(...chunk);
100
+ }
101
+ return btoa(binary);
102
+ }
103
+ return void 0;
104
+ }
105
+ function parseFilePart(part) {
106
+ const mimeType = extractMimeType(part.mediaType ?? part.mimeType);
107
+ if (!mimeType || !isImageMimeType(mimeType)) {
108
+ return {};
109
+ }
110
+ const data = part.data;
111
+ if (typeof data === "string") {
112
+ const content = createImageContent(mimeType, data);
113
+ return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
114
+ }
115
+ if (data instanceof Uint8Array || typeof ArrayBuffer !== "undefined" && data instanceof ArrayBuffer) {
116
+ const base64 = convertBinaryToBase64(data);
117
+ if (!base64) {
118
+ return { warning: IMAGE_CONVERSION_WARNING };
119
+ }
120
+ const content = createImageContent(mimeType, base64);
121
+ return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
122
+ }
123
+ return { warning: IMAGE_CONVERSION_WARNING };
124
+ }
125
+ function convertToClaudeCodeMessages(prompt) {
126
+ const messages = [];
127
+ const warnings = [];
128
+ let systemPrompt;
129
+ const streamingSegments = [];
130
+ const imageMap = /* @__PURE__ */ new Map();
131
+ let hasImageParts = false;
132
+ const addSegment = (formatted) => {
133
+ streamingSegments.push({ formatted });
134
+ return streamingSegments.length - 1;
135
+ };
136
+ const addImageForSegment = (segmentIndex, content) => {
137
+ hasImageParts = true;
138
+ if (!imageMap.has(segmentIndex)) {
139
+ imageMap.set(segmentIndex, []);
140
+ }
141
+ imageMap.get(segmentIndex)?.push(content);
142
+ };
143
+ for (const message of prompt) {
144
+ switch (message.role) {
145
+ case "system":
146
+ systemPrompt = message.content;
147
+ if (typeof message.content === "string" && message.content.trim().length > 0) {
148
+ addSegment(message.content);
149
+ } else {
150
+ addSegment("");
151
+ }
152
+ break;
153
+ case "user":
154
+ if (typeof message.content === "string") {
155
+ messages.push(message.content);
156
+ addSegment(`Human: ${message.content}`);
157
+ } else {
158
+ const textParts = message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
159
+ const segmentIndex = addSegment(textParts ? `Human: ${textParts}` : "");
160
+ if (textParts) {
161
+ messages.push(textParts);
162
+ }
163
+ for (const part of message.content) {
164
+ if (part.type === "image") {
165
+ const { content, warning } = parseImagePart(part);
166
+ if (content) {
167
+ addImageForSegment(segmentIndex, content);
168
+ } else if (warning) {
169
+ warnings.push(warning);
170
+ }
171
+ } else if (part.type === "file") {
172
+ const { content, warning } = parseFilePart(part);
173
+ if (content) {
174
+ addImageForSegment(segmentIndex, content);
175
+ } else if (warning) {
176
+ warnings.push(warning);
177
+ }
178
+ }
179
+ }
180
+ }
181
+ break;
182
+ case "assistant": {
183
+ let assistantContent = "";
184
+ if (typeof message.content === "string") {
185
+ assistantContent = message.content;
186
+ } else {
187
+ const textParts = message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
188
+ if (textParts) {
189
+ assistantContent = textParts;
190
+ }
191
+ const toolCalls = message.content.filter((part) => part.type === "tool-call");
192
+ if (toolCalls.length > 0) {
193
+ assistantContent += `
194
+ [Tool calls made]`;
195
+ }
196
+ }
197
+ const formattedAssistant = `Assistant: ${assistantContent}`;
198
+ messages.push(formattedAssistant);
199
+ addSegment(formattedAssistant);
200
+ break;
201
+ }
202
+ case "tool":
203
+ for (const tool3 of message.content) {
204
+ if (tool3.type === "tool-approval-response") {
205
+ continue;
206
+ }
207
+ let resultText;
208
+ const output = tool3.output;
209
+ if (output.type === "text" || output.type === "error-text") {
210
+ resultText = output.value;
211
+ } else if (output.type === "json" || output.type === "error-json") {
212
+ resultText = JSON.stringify(output.value);
213
+ } else if (output.type === "execution-denied") {
214
+ resultText = `[Execution denied${output.reason ? `: ${output.reason}` : ""}]`;
215
+ } else if (output.type === "content") {
216
+ resultText = output.value.filter((part) => part.type === "text").map((part) => part.text).join("\n");
217
+ } else {
218
+ resultText = "[Unknown output type]";
219
+ }
220
+ const formattedToolResult = `Tool Result (${tool3.toolName}): ${resultText}`;
221
+ messages.push(formattedToolResult);
222
+ addSegment(formattedToolResult);
223
+ }
224
+ break;
225
+ }
226
+ }
227
+ let finalPrompt = "";
228
+ if (systemPrompt) {
229
+ finalPrompt = systemPrompt;
230
+ }
231
+ if (messages.length > 0) {
232
+ const formattedMessages = [];
233
+ for (let i = 0; i < messages.length; i++) {
234
+ const msg = messages[i];
235
+ if (msg.startsWith("Assistant:") || msg.startsWith("Tool Result")) {
236
+ formattedMessages.push(msg);
237
+ } else {
238
+ formattedMessages.push(`Human: ${msg}`);
239
+ }
240
+ }
241
+ if (finalPrompt) {
242
+ const joinedMessages = formattedMessages.join("\n\n");
243
+ finalPrompt = joinedMessages ? `${finalPrompt}
244
+
245
+ ${joinedMessages}` : finalPrompt;
246
+ } else {
247
+ finalPrompt = formattedMessages.join("\n\n");
248
+ }
249
+ }
250
+ const streamingParts = [];
251
+ const imagePartsInOrder = [];
252
+ const appendImagesForIndex = (index) => {
253
+ const images = imageMap.get(index);
254
+ if (!images) {
255
+ return;
256
+ }
257
+ images.forEach((image) => {
258
+ streamingParts.push(image);
259
+ imagePartsInOrder.push(image);
260
+ });
261
+ };
262
+ if (streamingSegments.length > 0) {
263
+ let accumulatedText = "";
264
+ let emittedText = false;
265
+ const flushText = () => {
266
+ if (!accumulatedText) {
267
+ return;
268
+ }
269
+ streamingParts.push({ type: "text", text: accumulatedText });
270
+ accumulatedText = "";
271
+ emittedText = true;
272
+ };
273
+ streamingSegments.forEach((segment, index) => {
274
+ const segmentText = segment.formatted;
275
+ if (segmentText) {
276
+ if (!accumulatedText) {
277
+ accumulatedText = emittedText ? `
278
+
279
+ ${segmentText}` : segmentText;
280
+ } else {
281
+ accumulatedText += `
282
+
283
+ ${segmentText}`;
284
+ }
285
+ }
286
+ if (imageMap.has(index)) {
287
+ flushText();
288
+ appendImagesForIndex(index);
289
+ }
290
+ });
291
+ flushText();
292
+ }
293
+ return {
294
+ messagesPrompt: finalPrompt,
295
+ systemPrompt,
296
+ ...warnings.length > 0 && { warnings },
297
+ streamingContentParts: streamingParts.length > 0 ? streamingParts : [
298
+ { type: "text", text: finalPrompt },
299
+ ...imagePartsInOrder
300
+ ],
301
+ hasImageParts
302
+ };
303
+ }
304
+
305
+ // docs/src/errors.ts
306
+ import { APICallError, LoadAPIKeyError } from "@ai-sdk/provider";
307
+ function createAPICallError({
308
+ message,
309
+ code,
310
+ exitCode,
311
+ stderr,
312
+ promptExcerpt,
313
+ isRetryable = false
314
+ }) {
315
+ const metadata = {
316
+ code,
317
+ exitCode,
318
+ stderr,
319
+ promptExcerpt
320
+ };
321
+ return new APICallError({
322
+ message,
323
+ isRetryable,
324
+ url: "claude-code-cli://command",
325
+ requestBodyValues: promptExcerpt ? { prompt: promptExcerpt } : void 0,
326
+ data: metadata
327
+ });
328
+ }
329
+ function createAuthenticationError({ message }) {
330
+ return new LoadAPIKeyError({
331
+ message: message || "Authentication failed. Please ensure Claude Code SDK is properly authenticated."
332
+ });
333
+ }
334
+ function createTimeoutError({
335
+ message,
336
+ promptExcerpt,
337
+ timeoutMs
338
+ }) {
339
+ const metadata = {
340
+ code: "TIMEOUT",
341
+ promptExcerpt
342
+ };
343
+ return new APICallError({
344
+ message,
345
+ isRetryable: true,
346
+ url: "claude-code-cli://command",
347
+ requestBodyValues: promptExcerpt ? { prompt: promptExcerpt } : void 0,
348
+ data: timeoutMs !== void 0 ? { ...metadata, timeoutMs } : metadata
349
+ });
350
+ }
351
+ function isAuthenticationError(error) {
352
+ if (error instanceof LoadAPIKeyError) return true;
353
+ if (error instanceof APICallError && error.data?.exitCode === 401)
354
+ return true;
355
+ return false;
356
+ }
357
+ function isTimeoutError(error) {
358
+ if (error instanceof APICallError && error.data?.code === "TIMEOUT")
359
+ return true;
360
+ return false;
361
+ }
362
+ function getErrorMetadata(error) {
363
+ if (error instanceof APICallError && error.data) {
364
+ return error.data;
365
+ }
366
+ return void 0;
367
+ }
368
+
369
+ // docs/src/map-claude-code-finish-reason.ts
370
+ function mapClaudeCodeFinishReason(subtype, stopReason) {
371
+ if (stopReason != null) {
372
+ switch (stopReason) {
373
+ case "end_turn":
374
+ return { unified: "stop", raw: "end_turn" };
375
+ case "max_tokens":
376
+ return { unified: "length", raw: "max_tokens" };
377
+ case "stop_sequence":
378
+ return { unified: "stop", raw: "stop_sequence" };
379
+ case "tool_use":
380
+ return { unified: "tool-calls", raw: "tool_use" };
381
+ default:
382
+ break;
383
+ }
384
+ }
385
+ const raw = stopReason ?? subtype;
386
+ switch (subtype) {
387
+ case "success":
388
+ return { unified: "stop", raw };
389
+ case "error_max_turns":
390
+ return { unified: "length", raw };
391
+ case "error_during_execution":
392
+ return { unified: "error", raw };
393
+ case void 0:
394
+ return { unified: "stop", raw };
395
+ default:
396
+ return { unified: "other", raw };
397
+ }
398
+ }
399
+
400
+ // docs/src/validation.ts
401
+ import { z } from "zod";
402
+ import { existsSync } from "fs";
403
+ var loggerFunctionSchema = z.object({
404
+ debug: z.any().refine((val) => typeof val === "function", {
405
+ message: "debug must be a function"
406
+ }),
407
+ info: z.any().refine((val) => typeof val === "function", {
408
+ message: "info must be a function"
409
+ }),
410
+ warn: z.any().refine((val) => typeof val === "function", {
411
+ message: "warn must be a function"
412
+ }),
413
+ error: z.any().refine((val) => typeof val === "function", {
414
+ message: "error must be a function"
415
+ })
416
+ });
417
+ var claudeCodeSettingsSchema = z.object({
418
+ pathToClaudeCodeExecutable: z.string().optional(),
419
+ customSystemPrompt: z.string().optional(),
420
+ appendSystemPrompt: z.string().optional(),
421
+ systemPrompt: z.union([
422
+ z.string(),
423
+ z.object({
424
+ type: z.literal("preset"),
425
+ preset: z.literal("claude_code"),
426
+ append: z.string().optional()
427
+ })
428
+ ]).optional(),
429
+ maxTurns: z.number().int().min(1).max(100).optional(),
430
+ maxThinkingTokens: z.number().int().positive().max(1e5).optional(),
431
+ cwd: z.string().refine(
432
+ (val) => {
433
+ if (typeof process === "undefined" || !process.versions?.node) {
434
+ return true;
435
+ }
436
+ return !val || existsSync(val);
437
+ },
438
+ { message: "Working directory must exist" }
439
+ ).optional(),
440
+ executable: z.enum(["bun", "deno", "node"]).optional(),
441
+ executableArgs: z.array(z.string()).optional(),
442
+ permissionMode: z.enum(["default", "acceptEdits", "bypassPermissions", "plan", "delegate", "dontAsk"]).optional(),
443
+ permissionPromptToolName: z.string().optional(),
444
+ continue: z.boolean().optional(),
445
+ resume: z.string().optional(),
446
+ sessionId: z.string().optional(),
447
+ allowedTools: z.array(z.string()).optional(),
448
+ disallowedTools: z.array(z.string()).optional(),
449
+ betas: z.array(z.string()).optional(),
450
+ allowDangerouslySkipPermissions: z.boolean().optional(),
451
+ enableFileCheckpointing: z.boolean().optional(),
452
+ maxBudgetUsd: z.number().min(0).optional(),
453
+ plugins: z.array(
454
+ z.object({
455
+ type: z.string(),
456
+ path: z.string()
457
+ }).passthrough()
458
+ ).optional(),
459
+ resumeSessionAt: z.string().optional(),
460
+ sandbox: z.any().refine((val) => val === void 0 || typeof val === "object", {
461
+ message: "sandbox must be an object"
462
+ }).optional(),
463
+ tools: z.union([
464
+ z.array(z.string()),
465
+ z.object({
466
+ type: z.literal("preset"),
467
+ preset: z.literal("claude_code")
468
+ })
469
+ ]).optional(),
470
+ settingSources: z.array(z.enum(["user", "project", "local"])).optional(),
471
+ streamingInput: z.enum(["auto", "always", "off"]).optional(),
472
+ // Hooks and tool-permission callback (permissive validation of shapes)
473
+ canUseTool: z.any().refine((v) => v === void 0 || typeof v === "function", {
474
+ message: "canUseTool must be a function"
475
+ }).optional(),
476
+ hooks: z.record(
477
+ z.string(),
478
+ z.array(
479
+ z.object({
480
+ matcher: z.string().optional(),
481
+ hooks: z.array(z.any()).nonempty()
482
+ })
483
+ )
484
+ ).optional(),
485
+ mcpServers: z.record(
486
+ z.string(),
487
+ z.union([
488
+ // McpStdioServerConfig
489
+ z.object({
490
+ type: z.literal("stdio").optional(),
491
+ command: z.string(),
492
+ args: z.array(z.string()).optional(),
493
+ env: z.record(z.string(), z.string()).optional()
494
+ }),
495
+ // McpSSEServerConfig
496
+ z.object({
497
+ type: z.literal("sse"),
498
+ url: z.string(),
499
+ headers: z.record(z.string(), z.string()).optional()
500
+ }),
501
+ // McpHttpServerConfig
502
+ z.object({
503
+ type: z.literal("http"),
504
+ url: z.string(),
505
+ headers: z.record(z.string(), z.string()).optional()
506
+ }),
507
+ // McpSdkServerConfig (in-process custom tools)
508
+ z.object({
509
+ type: z.literal("sdk"),
510
+ name: z.string(),
511
+ instance: z.any()
512
+ })
513
+ ])
514
+ ).optional(),
515
+ verbose: z.boolean().optional(),
516
+ debug: z.boolean().optional(),
517
+ debugFile: z.string().optional(),
518
+ logger: z.union([z.literal(false), loggerFunctionSchema]).optional(),
519
+ env: z.record(z.string(), z.string().optional()).optional(),
520
+ additionalDirectories: z.array(z.string()).optional(),
521
+ agents: z.record(
522
+ z.string(),
523
+ z.object({
524
+ description: z.string(),
525
+ tools: z.array(z.string()).optional(),
526
+ disallowedTools: z.array(z.string()).optional(),
527
+ prompt: z.string(),
528
+ model: z.enum(["sonnet", "opus", "haiku", "inherit"]).optional(),
529
+ mcpServers: z.array(
530
+ z.union([
531
+ z.string(),
532
+ z.record(z.string(), z.any())
533
+ // McpServerConfigForProcessTransport
534
+ ])
535
+ ).optional(),
536
+ criticalSystemReminder_EXPERIMENTAL: z.string().optional()
537
+ }).passthrough()
538
+ ).optional(),
539
+ includePartialMessages: z.boolean().optional(),
540
+ fallbackModel: z.string().optional(),
541
+ forkSession: z.boolean().optional(),
542
+ stderr: z.any().refine((val) => val === void 0 || typeof val === "function", {
543
+ message: "stderr must be a function"
544
+ }).optional(),
545
+ strictMcpConfig: z.boolean().optional(),
546
+ extraArgs: z.record(z.string(), z.union([z.string(), z.null()])).optional(),
547
+ persistSession: z.boolean().optional(),
548
+ spawnClaudeCodeProcess: z.any().refine((val) => val === void 0 || typeof val === "function", {
549
+ message: "spawnClaudeCodeProcess must be a function"
550
+ }).optional(),
551
+ sdkOptions: z.record(z.string(), z.any()).optional(),
552
+ maxToolResultSize: z.number().int().min(100).max(1e6).optional(),
553
+ // Callback invoked when Query object is created - for mid-stream injection via streamInput()
554
+ onQueryCreated: z.any().refine((val) => val === void 0 || typeof val === "function", {
555
+ message: "onQueryCreated must be a function"
556
+ }).optional(),
557
+ onStreamStart: z.any().refine((val) => val === void 0 || typeof val === "function", {
558
+ message: "onStreamStart must be a function"
559
+ }).optional()
560
+ }).strict();
561
+ function validateModelId(modelId) {
562
+ const knownModels = ["opus", "sonnet", "haiku"];
563
+ if (!modelId || modelId.trim() === "") {
564
+ throw new Error("Model ID cannot be empty");
565
+ }
566
+ if (!knownModels.includes(modelId)) {
567
+ return `Unknown model ID: '${modelId}'. Proceeding with custom model. Known models are: ${knownModels.join(", ")}`;
568
+ }
569
+ return void 0;
570
+ }
571
+ function validateSettings(settings) {
572
+ const warnings = [];
573
+ const errors = [];
574
+ try {
575
+ const result = claudeCodeSettingsSchema.safeParse(settings);
576
+ if (!result.success) {
577
+ const errorObject = result.error;
578
+ const issues = errorObject.errors || errorObject.issues || [];
579
+ issues.forEach((err) => {
580
+ const path = err.path.join(".");
581
+ errors.push(`${path ? `${path}: ` : ""}${err.message}`);
582
+ });
583
+ return { valid: false, warnings, errors };
584
+ }
585
+ const validSettings = result.data;
586
+ if (validSettings.maxTurns && validSettings.maxTurns > 20) {
587
+ warnings.push(
588
+ `High maxTurns value (${validSettings.maxTurns}) may lead to long-running conversations`
589
+ );
590
+ }
591
+ if (validSettings.maxThinkingTokens && validSettings.maxThinkingTokens > 5e4) {
592
+ warnings.push(
593
+ `Very high maxThinkingTokens (${validSettings.maxThinkingTokens}) may increase response time`
594
+ );
595
+ }
596
+ if (validSettings.allowedTools && validSettings.disallowedTools) {
597
+ warnings.push(
598
+ "Both allowedTools and disallowedTools are specified. Only allowedTools will be used."
599
+ );
600
+ }
601
+ const validateToolNames = (tools, type) => {
602
+ tools.forEach((tool3) => {
603
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*(\([^)]*\))?$/.test(tool3) && !tool3.startsWith("mcp__")) {
604
+ warnings.push(`Unusual ${type} tool name format: '${tool3}'`);
605
+ }
606
+ });
607
+ };
608
+ if (validSettings.allowedTools) {
609
+ validateToolNames(validSettings.allowedTools, "allowed");
610
+ }
611
+ if (validSettings.disallowedTools) {
612
+ validateToolNames(validSettings.disallowedTools, "disallowed");
613
+ }
614
+ if (validSettings.allowedTools?.includes("Skill") && !validSettings.settingSources) {
615
+ warnings.push(
616
+ "allowedTools includes 'Skill' but settingSources is not set. Skills require settingSources (e.g., ['user', 'project']) to load skill definitions."
617
+ );
618
+ }
619
+ return { valid: true, warnings, errors };
620
+ } catch (error) {
621
+ errors.push(`Validation error: ${error instanceof Error ? error.message : String(error)}`);
622
+ return { valid: false, warnings, errors };
623
+ }
624
+ }
625
+ function validatePrompt(prompt) {
626
+ const MAX_PROMPT_LENGTH = 1e5;
627
+ if (prompt.length > MAX_PROMPT_LENGTH) {
628
+ return `Very long prompt (${prompt.length} characters) may cause performance issues or timeouts`;
629
+ }
630
+ return void 0;
631
+ }
632
+ function validateSessionId(sessionId) {
633
+ if (sessionId && !/^[a-zA-Z0-9-_]+$/.test(sessionId)) {
634
+ return `Unusual session ID format. This may cause issues with session resumption.`;
635
+ }
636
+ return void 0;
637
+ }
638
+
639
+ // docs/src/logger.ts
640
+ var defaultLogger = {
641
+ // eslint-disable-next-line no-console
642
+ debug: (message) => console.debug(`[DEBUG] ${message}`),
643
+ // eslint-disable-next-line no-console
644
+ info: (message) => console.info(`[INFO] ${message}`),
645
+ warn: (message) => console.warn(`[WARN] ${message}`),
646
+ error: (message) => console.error(`[ERROR] ${message}`)
647
+ };
648
+ var noopLogger = {
649
+ debug: () => {
650
+ },
651
+ info: () => {
652
+ },
653
+ warn: () => {
654
+ },
655
+ error: () => {
656
+ }
657
+ };
658
+ function getLogger(logger) {
659
+ if (logger === false) {
660
+ return noopLogger;
661
+ }
662
+ if (logger === void 0) {
663
+ return defaultLogger;
664
+ }
665
+ return logger;
666
+ }
667
+ function createVerboseLogger(logger, verbose = false) {
668
+ if (verbose) {
669
+ return logger;
670
+ }
671
+ return {
672
+ debug: () => {
673
+ },
674
+ // No-op when not verbose
675
+ info: () => {
676
+ },
677
+ // No-op when not verbose
678
+ warn: logger.warn.bind(logger),
679
+ error: logger.error.bind(logger)
680
+ };
681
+ }
682
+
683
+ // docs/src/claude-code-language-model.ts
684
+ import { query } from "@anthropic-ai/claude-agent-sdk";
685
+ var CLAUDE_CODE_TRUNCATION_WARNING = "Claude Code SDK output ended unexpectedly; returning truncated response from buffered text. Await upstream fix to avoid data loss.";
686
+ var MIN_TRUNCATION_LENGTH = 512;
687
+ function isClaudeCodeTruncationError(error, bufferedText) {
688
+ const isSyntaxError = error instanceof SyntaxError || // eslint-disable-next-line @typescript-eslint/no-explicit-any
689
+ typeof error?.name === "string" && // eslint-disable-next-line @typescript-eslint/no-explicit-any
690
+ error.name.toLowerCase() === "syntaxerror";
691
+ if (!isSyntaxError) {
692
+ return false;
693
+ }
694
+ if (!bufferedText) {
695
+ return false;
696
+ }
697
+ const rawMessage = typeof error?.message === "string" ? error.message : "";
698
+ const message = rawMessage.toLowerCase();
699
+ const truncationIndicators = [
700
+ "unexpected end of json input",
701
+ "unexpected end of input",
702
+ "unexpected end of string",
703
+ "unexpected eof",
704
+ "end of file",
705
+ "unterminated string",
706
+ "unterminated string constant"
707
+ ];
708
+ if (!truncationIndicators.some((indicator) => message.includes(indicator))) {
709
+ return false;
710
+ }
711
+ if (bufferedText.length < MIN_TRUNCATION_LENGTH) {
712
+ return false;
713
+ }
714
+ return true;
715
+ }
716
+ function isAbortError(err) {
717
+ if (err && typeof err === "object") {
718
+ const e = err;
719
+ if (typeof e.name === "string" && e.name === "AbortError") return true;
720
+ if (typeof e.code === "string" && e.code.toUpperCase() === "ABORT_ERR") return true;
721
+ }
722
+ return false;
723
+ }
724
+ var DEFAULT_INHERITED_ENV_VARS = process.platform === "win32" ? [
725
+ "APPDATA",
726
+ "HOMEDRIVE",
727
+ "HOMEPATH",
728
+ "LOCALAPPDATA",
729
+ "PATH",
730
+ "PATHEXT",
731
+ "SYSTEMDRIVE",
732
+ "SYSTEMROOT",
733
+ "TEMP",
734
+ "TMP",
735
+ "USERNAME",
736
+ "USERPROFILE",
737
+ "WINDIR"
738
+ ] : ["HOME", "LOGNAME", "PATH", "SHELL", "TERM", "USER", "LANG", "LC_ALL", "TMPDIR"];
739
+ var CLAUDE_ENV_VARS = ["CLAUDE_CONFIG_DIR"];
740
+ function getBaseProcessEnv() {
741
+ const env = {};
742
+ const allowedKeys = /* @__PURE__ */ new Set([...DEFAULT_INHERITED_ENV_VARS, ...CLAUDE_ENV_VARS]);
743
+ for (const key of allowedKeys) {
744
+ const value = process.env[key];
745
+ if (typeof value !== "string") {
746
+ continue;
747
+ }
748
+ if (value.startsWith("()")) {
749
+ continue;
750
+ }
751
+ env[key] = value;
752
+ }
753
+ return env;
754
+ }
755
+ var STREAMING_FEATURE_WARNING = "Claude Agent SDK features (hooks/MCP/images) require streaming input. Set `streamingInput: 'always'` or provide `canUseTool` (auto streams only when canUseTool is set).";
756
+ var SDK_OPTIONS_BLOCKLIST = /* @__PURE__ */ new Set(["model", "abortController", "prompt", "outputFormat"]);
757
+ function createEmptyUsage() {
758
+ return {
759
+ inputTokens: {
760
+ total: 0,
761
+ noCache: 0,
762
+ cacheRead: 0,
763
+ cacheWrite: 0
764
+ },
765
+ outputTokens: {
766
+ total: 0,
767
+ text: void 0,
768
+ reasoning: void 0
769
+ },
770
+ raw: void 0
771
+ };
772
+ }
773
+ function convertClaudeCodeUsage(usage) {
774
+ const inputTokens = usage.input_tokens ?? 0;
775
+ const outputTokens = usage.output_tokens ?? 0;
776
+ const cacheWrite = usage.cache_creation_input_tokens ?? 0;
777
+ const cacheRead = usage.cache_read_input_tokens ?? 0;
778
+ return {
779
+ inputTokens: {
780
+ total: inputTokens + cacheWrite + cacheRead,
781
+ noCache: inputTokens,
782
+ cacheRead,
783
+ cacheWrite
784
+ },
785
+ outputTokens: {
786
+ total: outputTokens,
787
+ text: void 0,
788
+ reasoning: void 0
789
+ },
790
+ raw: usage
791
+ };
792
+ }
793
+ function createMessageInjector() {
794
+ const queue = [];
795
+ let closed = false;
796
+ let resolver = null;
797
+ const injector = {
798
+ inject(content, onResult) {
799
+ if (closed) {
800
+ onResult?.(false);
801
+ return;
802
+ }
803
+ const item = { content, onResult };
804
+ if (resolver) {
805
+ const r = resolver;
806
+ resolver = null;
807
+ r(item);
808
+ } else {
809
+ queue.push(item);
810
+ }
811
+ },
812
+ close() {
813
+ closed = true;
814
+ if (resolver && queue.length === 0) {
815
+ resolver(null);
816
+ resolver = null;
817
+ }
818
+ }
819
+ };
820
+ const getNextItem = () => {
821
+ if (queue.length > 0) {
822
+ const item = queue.shift();
823
+ if (!item) {
824
+ return Promise.resolve(null);
825
+ }
826
+ return Promise.resolve(item);
827
+ }
828
+ if (closed) {
829
+ return Promise.resolve(null);
830
+ }
831
+ return new Promise((resolve) => {
832
+ resolver = (item) => {
833
+ resolve(item);
834
+ };
835
+ });
836
+ };
837
+ const notifySessionEnded = () => {
838
+ for (const item of queue) {
839
+ item.onResult?.(false);
840
+ }
841
+ queue.length = 0;
842
+ closed = true;
843
+ if (resolver) {
844
+ resolver(null);
845
+ resolver = null;
846
+ }
847
+ };
848
+ return { injector, getNextItem, notifySessionEnded };
849
+ }
850
+ function toAsyncIterablePrompt(messagesPrompt, outputStreamEnded, sessionId, contentParts, onStreamStart) {
851
+ const content = contentParts && contentParts.length > 0 ? contentParts : [{ type: "text", text: messagesPrompt }];
852
+ const initialMsg = {
853
+ type: "user",
854
+ message: {
855
+ role: "user",
856
+ content
857
+ },
858
+ parent_tool_use_id: null,
859
+ session_id: sessionId ?? ""
860
+ };
861
+ if (!onStreamStart) {
862
+ return {
863
+ async *[Symbol.asyncIterator]() {
864
+ yield initialMsg;
865
+ await outputStreamEnded;
866
+ }
867
+ };
868
+ }
869
+ const { injector, getNextItem, notifySessionEnded } = createMessageInjector();
870
+ return {
871
+ async *[Symbol.asyncIterator]() {
872
+ yield initialMsg;
873
+ onStreamStart(injector);
874
+ let streamEnded = false;
875
+ void outputStreamEnded.then(() => {
876
+ streamEnded = true;
877
+ notifySessionEnded();
878
+ });
879
+ while (!streamEnded) {
880
+ const item = await Promise.race([getNextItem(), outputStreamEnded.then(() => null)]);
881
+ if (item === null) {
882
+ await outputStreamEnded;
883
+ break;
884
+ }
885
+ const sdkMsg = {
886
+ type: "user",
887
+ message: {
888
+ role: "user",
889
+ content: [{ type: "text", text: item.content }]
890
+ },
891
+ parent_tool_use_id: null,
892
+ session_id: sessionId ?? ""
893
+ };
894
+ yield sdkMsg;
895
+ item.onResult?.(true);
896
+ }
897
+ }
898
+ };
899
+ }
900
+ var modelMap = {
901
+ opus: "opus",
902
+ sonnet: "sonnet",
903
+ haiku: "haiku"
904
+ };
905
+ var MAX_TOOL_RESULT_SIZE = 1e4;
906
+ function truncateToolResultForStream(result, maxSize = MAX_TOOL_RESULT_SIZE) {
907
+ if (typeof result === "string") {
908
+ if (result.length <= maxSize) return result;
909
+ return result.slice(0, maxSize) + `
910
+ ...[truncated ${result.length - maxSize} chars]`;
911
+ }
912
+ if (typeof result !== "object" || result === null) return result;
913
+ if (Array.isArray(result)) {
914
+ let largestIndex = -1;
915
+ let largestSize2 = 0;
916
+ for (let i = 0; i < result.length; i++) {
917
+ const value = result[i];
918
+ if (typeof value === "string" && value.length > largestSize2) {
919
+ largestIndex = i;
920
+ largestSize2 = value.length;
921
+ }
922
+ }
923
+ if (largestIndex >= 0 && largestSize2 > maxSize) {
924
+ const truncatedValue = result[largestIndex].slice(0, maxSize) + `
925
+ ...[truncated ${largestSize2 - maxSize} chars]`;
926
+ const cloned = [...result];
927
+ cloned[largestIndex] = truncatedValue;
928
+ return cloned;
929
+ }
930
+ return result;
931
+ }
932
+ const obj = result;
933
+ let largestKey = null;
934
+ let largestSize = 0;
935
+ for (const [key, value] of Object.entries(obj)) {
936
+ if (typeof value === "string" && value.length > largestSize) {
937
+ largestKey = key;
938
+ largestSize = value.length;
939
+ }
940
+ }
941
+ if (largestKey && largestSize > maxSize) {
942
+ const truncatedValue = obj[largestKey].slice(0, maxSize) + `
943
+ ...[truncated ${largestSize - maxSize} chars]`;
944
+ return { ...obj, [largestKey]: truncatedValue };
945
+ }
946
+ return result;
947
+ }
948
+ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
949
+ specificationVersion = "v3";
950
+ defaultObjectGenerationMode = "json";
951
+ supportsImageUrls = false;
952
+ supportedUrls = {};
953
+ supportsStructuredOutputs = true;
954
+ // Fallback/magic string constants
955
+ static UNKNOWN_TOOL_NAME = "unknown-tool";
956
+ // Tool input safety limits
957
+ static MAX_TOOL_INPUT_SIZE = 1048576;
958
+ // 1MB hard limit
959
+ static MAX_TOOL_INPUT_WARN = 102400;
960
+ // 100KB warning threshold
961
+ static MAX_DELTA_CALC_SIZE = 1e4;
962
+ // 10KB delta computation threshold
963
+ modelId;
964
+ settings;
965
+ sessionId;
966
+ modelValidationWarning;
967
+ settingsValidationWarnings;
968
+ logger;
969
+ constructor(options) {
970
+ this.modelId = options.id;
971
+ this.settings = options.settings ?? {};
972
+ this.settingsValidationWarnings = options.settingsValidationWarnings ?? [];
973
+ const baseLogger = getLogger(this.settings.logger);
974
+ this.logger = createVerboseLogger(baseLogger, this.settings.verbose ?? false);
975
+ if (!this.modelId || typeof this.modelId !== "string" || this.modelId.trim() === "") {
976
+ throw new NoSuchModelError({
977
+ modelId: this.modelId,
978
+ modelType: "languageModel"
979
+ });
980
+ }
981
+ this.modelValidationWarning = validateModelId(this.modelId);
982
+ if (this.modelValidationWarning) {
983
+ this.logger.warn(`Claude Code Model: ${this.modelValidationWarning}`);
984
+ }
985
+ }
986
+ get provider() {
987
+ return "claude-code";
988
+ }
989
+ getModel() {
990
+ const mapped = modelMap[this.modelId];
991
+ return mapped ?? this.modelId;
992
+ }
993
+ getSanitizedSdkOptions() {
994
+ if (!this.settings.sdkOptions || typeof this.settings.sdkOptions !== "object") {
995
+ return void 0;
996
+ }
997
+ const sanitized = { ...this.settings.sdkOptions };
998
+ const blockedKeys = Array.from(SDK_OPTIONS_BLOCKLIST).filter((key) => key in sanitized);
999
+ if (blockedKeys.length > 0) {
1000
+ this.logger.warn(
1001
+ `[claude-code] sdkOptions includes provider-managed fields (${blockedKeys.join(
1002
+ ", "
1003
+ )}); these will be ignored.`
1004
+ );
1005
+ blockedKeys.forEach((key) => delete sanitized[key]);
1006
+ }
1007
+ return sanitized;
1008
+ }
1009
+ getEffectiveResume(sdkOptions) {
1010
+ return sdkOptions?.resume ?? this.settings.resume ?? this.sessionId;
1011
+ }
1012
+ extractToolUses(content) {
1013
+ if (!Array.isArray(content)) {
1014
+ return [];
1015
+ }
1016
+ return content.filter(
1017
+ (item) => typeof item === "object" && item !== null && "type" in item && item.type === "tool_use"
1018
+ ).map((item) => {
1019
+ const { id, name, input, parent_tool_use_id } = item;
1020
+ return {
1021
+ id: typeof id === "string" && id.length > 0 ? id : generateId(),
1022
+ name: typeof name === "string" && name.length > 0 ? name : _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME,
1023
+ input,
1024
+ parentToolUseId: typeof parent_tool_use_id === "string" ? parent_tool_use_id : null
1025
+ };
1026
+ });
1027
+ }
1028
+ extractToolResults(content) {
1029
+ if (!Array.isArray(content)) {
1030
+ return [];
1031
+ }
1032
+ return content.filter(
1033
+ (item) => typeof item === "object" && item !== null && "type" in item && item.type === "tool_result"
1034
+ ).map((item) => {
1035
+ const { tool_use_id, content: content2, is_error, name } = item;
1036
+ return {
1037
+ id: typeof tool_use_id === "string" && tool_use_id.length > 0 ? tool_use_id : generateId(),
1038
+ name: typeof name === "string" && name.length > 0 ? name : void 0,
1039
+ result: content2,
1040
+ isError: Boolean(is_error)
1041
+ };
1042
+ });
1043
+ }
1044
+ extractToolErrors(content) {
1045
+ if (!Array.isArray(content)) {
1046
+ return [];
1047
+ }
1048
+ return content.filter(
1049
+ (item) => typeof item === "object" && item !== null && "type" in item && item.type === "tool_error"
1050
+ ).map((item) => {
1051
+ const { tool_use_id, error, name } = item;
1052
+ return {
1053
+ id: typeof tool_use_id === "string" && tool_use_id.length > 0 ? tool_use_id : generateId(),
1054
+ name: typeof name === "string" && name.length > 0 ? name : void 0,
1055
+ error
1056
+ };
1057
+ });
1058
+ }
1059
+ serializeToolInput(input) {
1060
+ if (typeof input === "string") {
1061
+ return this.checkInputSize(input);
1062
+ }
1063
+ if (input === void 0) {
1064
+ return "";
1065
+ }
1066
+ try {
1067
+ const serialized = JSON.stringify(input);
1068
+ return this.checkInputSize(serialized);
1069
+ } catch {
1070
+ const fallback = String(input);
1071
+ return this.checkInputSize(fallback);
1072
+ }
1073
+ }
1074
+ checkInputSize(str) {
1075
+ const length = str.length;
1076
+ if (length > _ClaudeCodeLanguageModel.MAX_TOOL_INPUT_SIZE) {
1077
+ throw new Error(
1078
+ `Tool input exceeds maximum size of ${_ClaudeCodeLanguageModel.MAX_TOOL_INPUT_SIZE} bytes (got ${length} bytes). This may indicate a malformed request or an attempt to process excessively large data.`
1079
+ );
1080
+ }
1081
+ if (length > _ClaudeCodeLanguageModel.MAX_TOOL_INPUT_WARN) {
1082
+ this.logger.warn(
1083
+ `[claude-code] Large tool input detected: ${length} bytes. Performance may be impacted. Consider chunking or reducing input size.`
1084
+ );
1085
+ }
1086
+ return str;
1087
+ }
1088
+ normalizeToolResult(result) {
1089
+ if (typeof result === "string") {
1090
+ try {
1091
+ return JSON.parse(result);
1092
+ } catch {
1093
+ return result;
1094
+ }
1095
+ }
1096
+ if (Array.isArray(result) && result.length > 0) {
1097
+ const textBlocks = result.filter(
1098
+ (block) => block?.type === "text" && typeof block.text === "string"
1099
+ ).map((block) => block.text);
1100
+ if (textBlocks.length !== result.length) {
1101
+ return result;
1102
+ }
1103
+ if (textBlocks.length === 1) {
1104
+ try {
1105
+ return JSON.parse(textBlocks[0]);
1106
+ } catch {
1107
+ return textBlocks[0];
1108
+ }
1109
+ }
1110
+ const combined = textBlocks.join("\n");
1111
+ try {
1112
+ return JSON.parse(combined);
1113
+ } catch {
1114
+ return combined;
1115
+ }
1116
+ }
1117
+ return result;
1118
+ }
1119
+ generateAllWarnings(options, prompt) {
1120
+ const warnings = [];
1121
+ const unsupportedParams = [];
1122
+ if (options.temperature !== void 0) unsupportedParams.push("temperature");
1123
+ if (options.topP !== void 0) unsupportedParams.push("topP");
1124
+ if (options.topK !== void 0) unsupportedParams.push("topK");
1125
+ if (options.presencePenalty !== void 0) unsupportedParams.push("presencePenalty");
1126
+ if (options.frequencyPenalty !== void 0) unsupportedParams.push("frequencyPenalty");
1127
+ if (options.stopSequences !== void 0 && options.stopSequences.length > 0)
1128
+ unsupportedParams.push("stopSequences");
1129
+ if (options.seed !== void 0) unsupportedParams.push("seed");
1130
+ if (unsupportedParams.length > 0) {
1131
+ for (const param of unsupportedParams) {
1132
+ warnings.push({
1133
+ type: "unsupported",
1134
+ feature: param,
1135
+ details: `Claude Code SDK does not support the ${param} parameter. It will be ignored.`
1136
+ });
1137
+ }
1138
+ }
1139
+ if (this.modelValidationWarning) {
1140
+ warnings.push({
1141
+ type: "other",
1142
+ message: this.modelValidationWarning
1143
+ });
1144
+ }
1145
+ this.settingsValidationWarnings.forEach((warning) => {
1146
+ warnings.push({
1147
+ type: "other",
1148
+ message: warning
1149
+ });
1150
+ });
1151
+ if (options.responseFormat?.type === "json" && !options.responseFormat.schema) {
1152
+ warnings.push({
1153
+ type: "unsupported",
1154
+ feature: "responseFormat",
1155
+ details: "JSON response format requires a schema for the Claude Code provider. The JSON responseFormat is ignored and the call is treated as plain text."
1156
+ });
1157
+ }
1158
+ const promptWarning = validatePrompt(prompt);
1159
+ if (promptWarning) {
1160
+ warnings.push({
1161
+ type: "other",
1162
+ message: promptWarning
1163
+ });
1164
+ }
1165
+ return warnings;
1166
+ }
1167
+ createQueryOptions(abortController, responseFormat, stderrCollector, sdkOptions, effectiveResume) {
1168
+ const opts = {
1169
+ model: this.getModel(),
1170
+ abortController,
1171
+ resume: effectiveResume ?? this.settings.resume ?? this.sessionId,
1172
+ pathToClaudeCodeExecutable: this.settings.pathToClaudeCodeExecutable,
1173
+ maxTurns: this.settings.maxTurns,
1174
+ maxThinkingTokens: this.settings.maxThinkingTokens,
1175
+ cwd: this.settings.cwd,
1176
+ executable: this.settings.executable,
1177
+ executableArgs: this.settings.executableArgs,
1178
+ permissionMode: this.settings.permissionMode,
1179
+ permissionPromptToolName: this.settings.permissionPromptToolName,
1180
+ continue: this.settings.continue,
1181
+ allowedTools: this.settings.allowedTools,
1182
+ disallowedTools: this.settings.disallowedTools,
1183
+ betas: this.settings.betas,
1184
+ allowDangerouslySkipPermissions: this.settings.allowDangerouslySkipPermissions,
1185
+ enableFileCheckpointing: this.settings.enableFileCheckpointing,
1186
+ maxBudgetUsd: this.settings.maxBudgetUsd,
1187
+ plugins: this.settings.plugins,
1188
+ resumeSessionAt: this.settings.resumeSessionAt,
1189
+ sandbox: this.settings.sandbox,
1190
+ tools: this.settings.tools,
1191
+ mcpServers: this.settings.mcpServers,
1192
+ canUseTool: this.settings.canUseTool
1193
+ };
1194
+ if (this.settings.systemPrompt !== void 0) {
1195
+ opts.systemPrompt = this.settings.systemPrompt;
1196
+ } else if (this.settings.customSystemPrompt !== void 0) {
1197
+ this.logger.warn(
1198
+ "[claude-code] 'customSystemPrompt' is deprecated and will be removed in a future major release. Please use 'systemPrompt' instead (string or { type: 'preset', preset: 'claude_code', append? })."
1199
+ );
1200
+ opts.systemPrompt = this.settings.customSystemPrompt;
1201
+ } else if (this.settings.appendSystemPrompt !== void 0) {
1202
+ this.logger.warn(
1203
+ "[claude-code] 'appendSystemPrompt' is deprecated and will be removed in a future major release. Please use 'systemPrompt: { type: 'preset', preset: 'claude_code', append: <text> }' instead."
1204
+ );
1205
+ opts.systemPrompt = {
1206
+ type: "preset",
1207
+ preset: "claude_code",
1208
+ append: this.settings.appendSystemPrompt
1209
+ };
1210
+ }
1211
+ if (this.settings.settingSources !== void 0) {
1212
+ opts.settingSources = this.settings.settingSources;
1213
+ }
1214
+ if (this.settings.additionalDirectories !== void 0) {
1215
+ opts.additionalDirectories = this.settings.additionalDirectories;
1216
+ }
1217
+ if (this.settings.agents !== void 0) {
1218
+ opts.agents = this.settings.agents;
1219
+ }
1220
+ if (this.settings.includePartialMessages !== void 0) {
1221
+ opts.includePartialMessages = this.settings.includePartialMessages;
1222
+ }
1223
+ if (this.settings.fallbackModel !== void 0) {
1224
+ opts.fallbackModel = this.settings.fallbackModel;
1225
+ }
1226
+ if (this.settings.forkSession !== void 0) {
1227
+ opts.forkSession = this.settings.forkSession;
1228
+ }
1229
+ if (this.settings.strictMcpConfig !== void 0) {
1230
+ opts.strictMcpConfig = this.settings.strictMcpConfig;
1231
+ }
1232
+ if (this.settings.extraArgs !== void 0) {
1233
+ opts.extraArgs = this.settings.extraArgs;
1234
+ }
1235
+ if (this.settings.persistSession !== void 0) {
1236
+ opts.persistSession = this.settings.persistSession;
1237
+ }
1238
+ if (this.settings.spawnClaudeCodeProcess !== void 0) {
1239
+ opts.spawnClaudeCodeProcess = this.settings.spawnClaudeCodeProcess;
1240
+ }
1241
+ if (this.settings.hooks) {
1242
+ opts.hooks = this.settings.hooks;
1243
+ }
1244
+ if (this.settings.sessionId !== void 0) {
1245
+ opts.sessionId = this.settings.sessionId;
1246
+ }
1247
+ if (this.settings.debug !== void 0) {
1248
+ opts.debug = this.settings.debug;
1249
+ }
1250
+ if (this.settings.debugFile !== void 0) {
1251
+ opts.debugFile = this.settings.debugFile;
1252
+ }
1253
+ const sdkOverrides = sdkOptions ? sdkOptions : void 0;
1254
+ const sdkEnv = sdkOverrides && typeof sdkOverrides.env === "object" && sdkOverrides.env !== null ? sdkOverrides.env : void 0;
1255
+ const sdkStderr = sdkOverrides && typeof sdkOverrides.stderr === "function" ? sdkOverrides.stderr : void 0;
1256
+ if (sdkOverrides) {
1257
+ const rest = { ...sdkOverrides };
1258
+ delete rest.env;
1259
+ delete rest.stderr;
1260
+ Object.assign(opts, rest);
1261
+ }
1262
+ const userStderrCallback = sdkStderr ?? this.settings.stderr;
1263
+ if (stderrCollector || userStderrCallback) {
1264
+ opts.stderr = (data) => {
1265
+ if (stderrCollector) stderrCollector(data);
1266
+ if (userStderrCallback) userStderrCallback(data);
1267
+ };
1268
+ }
1269
+ if (this.settings.env !== void 0 || sdkEnv !== void 0) {
1270
+ const baseEnv = getBaseProcessEnv();
1271
+ opts.env = { ...baseEnv, ...this.settings.env, ...sdkEnv };
1272
+ }
1273
+ if (responseFormat?.type === "json" && responseFormat.schema) {
1274
+ opts.outputFormat = {
1275
+ type: "json_schema",
1276
+ schema: responseFormat.schema
1277
+ };
1278
+ }
1279
+ return opts;
1280
+ }
1281
+ handleClaudeCodeError(error, messagesPrompt, collectedStderr) {
1282
+ if (isAbortError(error)) {
1283
+ throw error;
1284
+ }
1285
+ const isErrorWithMessage = (err) => {
1286
+ return typeof err === "object" && err !== null && "message" in err;
1287
+ };
1288
+ const isErrorWithCode = (err) => {
1289
+ return typeof err === "object" && err !== null;
1290
+ };
1291
+ const authErrorPatterns = [
1292
+ "not logged in",
1293
+ "authentication",
1294
+ "unauthorized",
1295
+ "auth failed",
1296
+ "please login",
1297
+ "claude login",
1298
+ "/login",
1299
+ // CLI returns "Please run /login"
1300
+ "invalid api key"
1301
+ ];
1302
+ const errorMessage = isErrorWithMessage(error) && error.message ? error.message.toLowerCase() : "";
1303
+ const exitCode = isErrorWithCode(error) && typeof error.exitCode === "number" ? error.exitCode : void 0;
1304
+ const isAuthError = authErrorPatterns.some((pattern) => errorMessage.includes(pattern)) || exitCode === 401;
1305
+ if (isAuthError) {
1306
+ return createAuthenticationError({
1307
+ message: isErrorWithMessage(error) && error.message ? error.message : "Authentication failed. Please ensure Claude Code SDK is properly authenticated."
1308
+ });
1309
+ }
1310
+ const errorCode = isErrorWithCode(error) && typeof error.code === "string" ? error.code : "";
1311
+ if (errorCode === "ETIMEDOUT" || errorMessage.includes("timeout")) {
1312
+ return createTimeoutError({
1313
+ message: isErrorWithMessage(error) && error.message ? error.message : "Request timed out",
1314
+ promptExcerpt: messagesPrompt.substring(0, 200)
1315
+ // Don't specify timeoutMs since we don't know the actual timeout value
1316
+ // It's controlled by the consumer via AbortSignal
1317
+ });
1318
+ }
1319
+ const isRetryable = errorCode === "ENOENT" || errorCode === "ECONNREFUSED" || errorCode === "ETIMEDOUT" || errorCode === "ECONNRESET";
1320
+ const stderrFromError = isErrorWithCode(error) && typeof error.stderr === "string" ? error.stderr : void 0;
1321
+ const stderr = stderrFromError || collectedStderr || void 0;
1322
+ return createAPICallError({
1323
+ message: isErrorWithMessage(error) && error.message ? error.message : "Claude Code SDK error",
1324
+ code: errorCode || void 0,
1325
+ exitCode,
1326
+ stderr,
1327
+ promptExcerpt: messagesPrompt.substring(0, 200),
1328
+ isRetryable
1329
+ });
1330
+ }
1331
+ setSessionId(sessionId) {
1332
+ this.sessionId = sessionId;
1333
+ const warning = validateSessionId(sessionId);
1334
+ if (warning) {
1335
+ this.logger.warn(`Claude Code Session: ${warning}`);
1336
+ }
1337
+ }
1338
+ async doGenerate(options) {
1339
+ this.logger.debug(`[claude-code] Starting doGenerate request with model: ${this.modelId}`);
1340
+ this.logger.debug(`[claude-code] Response format: ${options.responseFormat?.type ?? "none"}`);
1341
+ const {
1342
+ messagesPrompt,
1343
+ warnings: messageWarnings,
1344
+ streamingContentParts,
1345
+ hasImageParts
1346
+ } = convertToClaudeCodeMessages(options.prompt);
1347
+ this.logger.debug(
1348
+ `[claude-code] Converted ${options.prompt.length} messages, hasImageParts: ${hasImageParts}`
1349
+ );
1350
+ const abortController = new AbortController();
1351
+ let abortListener;
1352
+ if (options.abortSignal?.aborted) {
1353
+ abortController.abort(options.abortSignal.reason);
1354
+ } else if (options.abortSignal) {
1355
+ abortListener = () => abortController.abort(options.abortSignal?.reason);
1356
+ options.abortSignal.addEventListener("abort", abortListener, { once: true });
1357
+ }
1358
+ let collectedStderr = "";
1359
+ const stderrCollector = (data) => {
1360
+ collectedStderr += data;
1361
+ };
1362
+ const sdkOptions = this.getSanitizedSdkOptions();
1363
+ const effectiveResume = this.getEffectiveResume(sdkOptions);
1364
+ const queryOptions = this.createQueryOptions(
1365
+ abortController,
1366
+ options.responseFormat,
1367
+ stderrCollector,
1368
+ sdkOptions,
1369
+ effectiveResume
1370
+ );
1371
+ let text = "";
1372
+ let structuredOutput;
1373
+ let usage = createEmptyUsage();
1374
+ let finishReason = { unified: "stop", raw: void 0 };
1375
+ let wasTruncated = false;
1376
+ let costUsd;
1377
+ let durationMs;
1378
+ let modelUsage;
1379
+ const warnings = this.generateAllWarnings(options, messagesPrompt);
1380
+ if (messageWarnings) {
1381
+ messageWarnings.forEach((warning) => {
1382
+ warnings.push({
1383
+ type: "other",
1384
+ message: warning
1385
+ });
1386
+ });
1387
+ }
1388
+ const modeSetting = this.settings.streamingInput ?? "auto";
1389
+ const effectiveCanUseTool = sdkOptions?.canUseTool ?? this.settings.canUseTool;
1390
+ const effectivePermissionPromptToolName = sdkOptions?.permissionPromptToolName ?? this.settings.permissionPromptToolName;
1391
+ const wantsStreamInput = modeSetting === "always" || modeSetting === "auto" && !!effectiveCanUseTool;
1392
+ if (!wantsStreamInput && hasImageParts) {
1393
+ warnings.push({
1394
+ type: "other",
1395
+ message: STREAMING_FEATURE_WARNING
1396
+ });
1397
+ }
1398
+ let done = () => {
1399
+ };
1400
+ const outputStreamEnded = new Promise((resolve) => {
1401
+ done = () => resolve(void 0);
1402
+ });
1403
+ try {
1404
+ if (effectiveCanUseTool && effectivePermissionPromptToolName) {
1405
+ throw new Error(
1406
+ "canUseTool requires streamingInput mode ('auto' or 'always') and cannot be used with permissionPromptToolName (SDK constraint). Set streamingInput: 'auto' (or 'always') and remove permissionPromptToolName, or remove canUseTool."
1407
+ );
1408
+ }
1409
+ const sdkPrompt = wantsStreamInput ? toAsyncIterablePrompt(
1410
+ messagesPrompt,
1411
+ outputStreamEnded,
1412
+ effectiveResume,
1413
+ streamingContentParts,
1414
+ this.settings.onStreamStart
1415
+ ) : messagesPrompt;
1416
+ this.logger.debug(
1417
+ `[claude-code] Executing query with streamingInput: ${wantsStreamInput}, session: ${effectiveResume ?? "new"}`
1418
+ );
1419
+ const response = query({
1420
+ prompt: sdkPrompt,
1421
+ options: queryOptions
1422
+ });
1423
+ this.settings.onQueryCreated?.(response);
1424
+ for await (const message of response) {
1425
+ this.logger.debug(`[claude-code] Received message type: ${message.type}`);
1426
+ if (message.type === "assistant") {
1427
+ text += message.message.content.map((c) => c.type === "text" ? c.text : "").join("");
1428
+ } else if (message.type === "result") {
1429
+ done();
1430
+ this.setSessionId(message.session_id);
1431
+ costUsd = message.total_cost_usd;
1432
+ durationMs = message.duration_ms;
1433
+ modelUsage = message.modelUsage;
1434
+ if ("is_error" in message && message.is_error === true) {
1435
+ const errorMessage = "result" in message && typeof message.result === "string" ? message.result : "Claude Code CLI returned an error";
1436
+ throw Object.assign(new Error(errorMessage), { exitCode: 1 });
1437
+ }
1438
+ if (message.subtype === "error_max_structured_output_retries") {
1439
+ throw new Error(
1440
+ "Failed to generate valid structured output after maximum retries. The model could not produce a response matching the required schema."
1441
+ );
1442
+ }
1443
+ if ("structured_output" in message && message.structured_output !== void 0) {
1444
+ structuredOutput = message.structured_output;
1445
+ this.logger.debug("[claude-code] Received structured output from SDK");
1446
+ }
1447
+ this.logger.info(
1448
+ `[claude-code] Request completed - Session: ${message.session_id}, Cost: $${costUsd?.toFixed(4) ?? "N/A"}, Duration: ${durationMs ?? "N/A"}ms`
1449
+ );
1450
+ if ("usage" in message) {
1451
+ usage = convertClaudeCodeUsage(message.usage);
1452
+ this.logger.debug(
1453
+ `[claude-code] Token usage - Input: ${usage.inputTokens.total}, Output: ${usage.outputTokens.total}`
1454
+ );
1455
+ }
1456
+ const stopReason = "stop_reason" in message ? message.stop_reason : void 0;
1457
+ finishReason = mapClaudeCodeFinishReason(message.subtype, stopReason);
1458
+ this.logger.debug(`[claude-code] Finish reason: ${finishReason.unified}`);
1459
+ } else if (message.type === "system" && message.subtype === "init") {
1460
+ this.setSessionId(message.session_id);
1461
+ this.logger.info(`[claude-code] Session initialized: ${message.session_id}`);
1462
+ }
1463
+ }
1464
+ } catch (error) {
1465
+ done();
1466
+ this.logger.debug(
1467
+ `[claude-code] Error during doGenerate: ${error instanceof Error ? error.message : String(error)}`
1468
+ );
1469
+ if (isAbortError(error)) {
1470
+ this.logger.debug("[claude-code] Request aborted by user");
1471
+ throw options.abortSignal?.aborted ? options.abortSignal.reason : error;
1472
+ }
1473
+ if (isClaudeCodeTruncationError(error, text)) {
1474
+ this.logger.warn(
1475
+ `[claude-code] Detected truncated response, returning ${text.length} characters of buffered text`
1476
+ );
1477
+ wasTruncated = true;
1478
+ finishReason = { unified: "length", raw: "truncation" };
1479
+ warnings.push({
1480
+ type: "other",
1481
+ message: CLAUDE_CODE_TRUNCATION_WARNING
1482
+ });
1483
+ } else {
1484
+ throw this.handleClaudeCodeError(error, messagesPrompt, collectedStderr);
1485
+ }
1486
+ } finally {
1487
+ if (options.abortSignal && abortListener) {
1488
+ options.abortSignal.removeEventListener("abort", abortListener);
1489
+ }
1490
+ }
1491
+ const finalText = structuredOutput !== void 0 ? JSON.stringify(structuredOutput) : text;
1492
+ return {
1493
+ content: [{ type: "text", text: finalText }],
1494
+ usage,
1495
+ finishReason,
1496
+ warnings,
1497
+ response: {
1498
+ id: generateId(),
1499
+ timestamp: /* @__PURE__ */ new Date(),
1500
+ modelId: this.modelId
1501
+ },
1502
+ request: {
1503
+ body: messagesPrompt
1504
+ },
1505
+ providerMetadata: {
1506
+ "claude-code": {
1507
+ ...this.sessionId !== void 0 && { sessionId: this.sessionId },
1508
+ ...costUsd !== void 0 && { costUsd },
1509
+ ...durationMs !== void 0 && { durationMs },
1510
+ ...modelUsage !== void 0 && { modelUsage },
1511
+ ...wasTruncated && { truncated: true }
1512
+ }
1513
+ }
1514
+ };
1515
+ }
1516
+ async doStream(options) {
1517
+ this.logger.debug(`[claude-code] Starting doStream request with model: ${this.modelId}`);
1518
+ this.logger.debug(`[claude-code] Response format: ${options.responseFormat?.type ?? "none"}`);
1519
+ const {
1520
+ messagesPrompt,
1521
+ warnings: messageWarnings,
1522
+ streamingContentParts,
1523
+ hasImageParts
1524
+ } = convertToClaudeCodeMessages(options.prompt);
1525
+ this.logger.debug(
1526
+ `[claude-code] Converted ${options.prompt.length} messages for streaming, hasImageParts: ${hasImageParts}`
1527
+ );
1528
+ const abortController = new AbortController();
1529
+ let abortListener;
1530
+ if (options.abortSignal?.aborted) {
1531
+ abortController.abort(options.abortSignal.reason);
1532
+ } else if (options.abortSignal) {
1533
+ abortListener = () => abortController.abort(options.abortSignal?.reason);
1534
+ options.abortSignal.addEventListener("abort", abortListener, { once: true });
1535
+ }
1536
+ let collectedStderr = "";
1537
+ const stderrCollector = (data) => {
1538
+ collectedStderr += data;
1539
+ };
1540
+ const sdkOptions = this.getSanitizedSdkOptions();
1541
+ const effectiveResume = this.getEffectiveResume(sdkOptions);
1542
+ const queryOptions = this.createQueryOptions(
1543
+ abortController,
1544
+ options.responseFormat,
1545
+ stderrCollector,
1546
+ sdkOptions,
1547
+ effectiveResume
1548
+ );
1549
+ if (queryOptions.includePartialMessages === void 0) {
1550
+ queryOptions.includePartialMessages = true;
1551
+ }
1552
+ const warnings = this.generateAllWarnings(options, messagesPrompt);
1553
+ if (messageWarnings) {
1554
+ messageWarnings.forEach((warning) => {
1555
+ warnings.push({
1556
+ type: "other",
1557
+ message: warning
1558
+ });
1559
+ });
1560
+ }
1561
+ const modeSetting = this.settings.streamingInput ?? "auto";
1562
+ const effectiveCanUseTool = sdkOptions?.canUseTool ?? this.settings.canUseTool;
1563
+ const effectivePermissionPromptToolName = sdkOptions?.permissionPromptToolName ?? this.settings.permissionPromptToolName;
1564
+ const wantsStreamInput = modeSetting === "always" || modeSetting === "auto" && !!effectiveCanUseTool;
1565
+ if (!wantsStreamInput && hasImageParts) {
1566
+ warnings.push({
1567
+ type: "other",
1568
+ message: STREAMING_FEATURE_WARNING
1569
+ });
1570
+ }
1571
+ const stream = new ReadableStream({
1572
+ start: async (controller) => {
1573
+ let done = () => {
1574
+ };
1575
+ const outputStreamEnded = new Promise((resolve) => {
1576
+ done = () => resolve(void 0);
1577
+ });
1578
+ const toolStates = /* @__PURE__ */ new Map();
1579
+ const activeTaskTools = /* @__PURE__ */ new Map();
1580
+ const getFallbackParentId = () => {
1581
+ if (activeTaskTools.size === 1) {
1582
+ return activeTaskTools.keys().next().value ?? null;
1583
+ }
1584
+ return null;
1585
+ };
1586
+ const streamWarnings = [];
1587
+ const closeToolInput = (toolId, state) => {
1588
+ if (!state.inputClosed && state.inputStarted) {
1589
+ controller.enqueue({
1590
+ type: "tool-input-end",
1591
+ id: toolId
1592
+ });
1593
+ state.inputClosed = true;
1594
+ }
1595
+ };
1596
+ const emitToolCall = (toolId, state) => {
1597
+ if (state.callEmitted) {
1598
+ return;
1599
+ }
1600
+ closeToolInput(toolId, state);
1601
+ controller.enqueue({
1602
+ type: "tool-call",
1603
+ toolCallId: toolId,
1604
+ toolName: state.name,
1605
+ input: state.lastSerializedInput ?? "",
1606
+ providerExecuted: true,
1607
+ dynamic: true,
1608
+ // V3 field: indicates tool is provider-defined (not in user's tools map)
1609
+ providerMetadata: {
1610
+ "claude-code": {
1611
+ // rawInput preserves the original serialized format before AI SDK normalization.
1612
+ // Use this if you need the exact string sent to the Claude CLI, which may differ
1613
+ // from the `input` field after AI SDK processing.
1614
+ rawInput: state.lastSerializedInput ?? "",
1615
+ parentToolCallId: state.parentToolCallId ?? null
1616
+ }
1617
+ }
1618
+ });
1619
+ state.callEmitted = true;
1620
+ };
1621
+ const finalizeToolCalls = () => {
1622
+ for (const [toolId, state] of toolStates) {
1623
+ emitToolCall(toolId, state);
1624
+ }
1625
+ toolStates.clear();
1626
+ };
1627
+ let usage = createEmptyUsage();
1628
+ let accumulatedText = "";
1629
+ let textPartId;
1630
+ let streamedTextLength = 0;
1631
+ let hasReceivedStreamEvents = false;
1632
+ let hasStreamedJson = false;
1633
+ const toolBlocksByIndex = /* @__PURE__ */ new Map();
1634
+ const toolInputAccumulators = /* @__PURE__ */ new Map();
1635
+ const textBlocksByIndex = /* @__PURE__ */ new Map();
1636
+ let textStreamedViaContentBlock = false;
1637
+ const reasoningBlocksByIndex = /* @__PURE__ */ new Map();
1638
+ let currentReasoningPartId;
1639
+ try {
1640
+ controller.enqueue({ type: "stream-start", warnings });
1641
+ if (effectiveCanUseTool && effectivePermissionPromptToolName) {
1642
+ throw new Error(
1643
+ "canUseTool requires streamingInput mode ('auto' or 'always') and cannot be used with permissionPromptToolName (SDK constraint). Set streamingInput: 'auto' (or 'always') and remove permissionPromptToolName, or remove canUseTool."
1644
+ );
1645
+ }
1646
+ const sdkPrompt = wantsStreamInput ? toAsyncIterablePrompt(
1647
+ messagesPrompt,
1648
+ outputStreamEnded,
1649
+ effectiveResume,
1650
+ streamingContentParts,
1651
+ this.settings.onStreamStart
1652
+ ) : messagesPrompt;
1653
+ this.logger.debug(
1654
+ `[claude-code] Starting stream query with streamingInput: ${wantsStreamInput}, session: ${effectiveResume ?? "new"}`
1655
+ );
1656
+ const response = query({
1657
+ prompt: sdkPrompt,
1658
+ options: queryOptions
1659
+ });
1660
+ this.settings.onQueryCreated?.(response);
1661
+ for await (const message of response) {
1662
+ this.logger.debug(`[claude-code] Stream received message type: ${message.type}`);
1663
+ if (message.type === "stream_event") {
1664
+ const streamEvent = message;
1665
+ const event = streamEvent.event;
1666
+ if (event.type === "content_block_delta" && event.delta.type === "text_delta" && "text" in event.delta && event.delta.text) {
1667
+ const deltaText = event.delta.text;
1668
+ hasReceivedStreamEvents = true;
1669
+ if (options.responseFormat?.type === "json") {
1670
+ accumulatedText += deltaText;
1671
+ streamedTextLength += deltaText.length;
1672
+ continue;
1673
+ }
1674
+ if (!textPartId) {
1675
+ textPartId = generateId();
1676
+ controller.enqueue({
1677
+ type: "text-start",
1678
+ id: textPartId
1679
+ });
1680
+ }
1681
+ controller.enqueue({
1682
+ type: "text-delta",
1683
+ id: textPartId,
1684
+ delta: deltaText
1685
+ });
1686
+ accumulatedText += deltaText;
1687
+ streamedTextLength += deltaText.length;
1688
+ }
1689
+ if (event.type === "content_block_delta" && event.delta.type === "input_json_delta" && "partial_json" in event.delta && event.delta.partial_json) {
1690
+ const jsonDelta = event.delta.partial_json;
1691
+ hasReceivedStreamEvents = true;
1692
+ const blockIndex = "index" in event ? event.index : -1;
1693
+ if (options.responseFormat?.type === "json") {
1694
+ if (!textPartId) {
1695
+ textPartId = generateId();
1696
+ controller.enqueue({
1697
+ type: "text-start",
1698
+ id: textPartId
1699
+ });
1700
+ }
1701
+ controller.enqueue({
1702
+ type: "text-delta",
1703
+ id: textPartId,
1704
+ delta: jsonDelta
1705
+ });
1706
+ accumulatedText += jsonDelta;
1707
+ streamedTextLength += jsonDelta.length;
1708
+ hasStreamedJson = true;
1709
+ continue;
1710
+ }
1711
+ const toolId = toolBlocksByIndex.get(blockIndex);
1712
+ if (toolId) {
1713
+ const accumulated = (toolInputAccumulators.get(toolId) ?? "") + jsonDelta;
1714
+ toolInputAccumulators.set(toolId, accumulated);
1715
+ controller.enqueue({
1716
+ type: "tool-input-delta",
1717
+ id: toolId,
1718
+ delta: jsonDelta
1719
+ });
1720
+ continue;
1721
+ }
1722
+ }
1723
+ if (event.type === "content_block_start" && "content_block" in event && event.content_block?.type === "tool_use") {
1724
+ const blockIndex = "index" in event ? event.index : -1;
1725
+ const toolBlock = event.content_block;
1726
+ const toolId = typeof toolBlock.id === "string" && toolBlock.id.length > 0 ? toolBlock.id : generateId();
1727
+ const toolName = typeof toolBlock.name === "string" && toolBlock.name.length > 0 ? toolBlock.name : _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
1728
+ hasReceivedStreamEvents = true;
1729
+ if (textPartId) {
1730
+ controller.enqueue({
1731
+ type: "text-end",
1732
+ id: textPartId
1733
+ });
1734
+ textPartId = void 0;
1735
+ }
1736
+ toolBlocksByIndex.set(blockIndex, toolId);
1737
+ toolInputAccumulators.set(toolId, "");
1738
+ let state = toolStates.get(toolId);
1739
+ if (!state) {
1740
+ const currentParentId = toolName === "Task" ? null : getFallbackParentId();
1741
+ state = {
1742
+ name: toolName,
1743
+ inputStarted: false,
1744
+ inputClosed: false,
1745
+ callEmitted: false,
1746
+ parentToolCallId: currentParentId
1747
+ };
1748
+ toolStates.set(toolId, state);
1749
+ }
1750
+ if (!state.inputStarted) {
1751
+ this.logger.debug(
1752
+ `[claude-code] Tool input started (content_block) - Tool: ${toolName}, ID: ${toolId}, parent: ${state.parentToolCallId}`
1753
+ );
1754
+ controller.enqueue({
1755
+ type: "tool-input-start",
1756
+ id: toolId,
1757
+ toolName,
1758
+ providerExecuted: true,
1759
+ dynamic: true,
1760
+ providerMetadata: {
1761
+ "claude-code": {
1762
+ parentToolCallId: state.parentToolCallId ?? null
1763
+ }
1764
+ }
1765
+ });
1766
+ if (toolName === "Task") {
1767
+ activeTaskTools.set(toolId, { startTime: Date.now() });
1768
+ }
1769
+ state.inputStarted = true;
1770
+ }
1771
+ continue;
1772
+ }
1773
+ if (event.type === "content_block_start" && "content_block" in event && event.content_block?.type === "text") {
1774
+ const blockIndex = "index" in event ? event.index : -1;
1775
+ hasReceivedStreamEvents = true;
1776
+ const partId = generateId();
1777
+ textBlocksByIndex.set(blockIndex, partId);
1778
+ textPartId = partId;
1779
+ this.logger.debug(
1780
+ `[claude-code] Text content block started - Index: ${blockIndex}, ID: ${partId}`
1781
+ );
1782
+ controller.enqueue({
1783
+ type: "text-start",
1784
+ id: partId
1785
+ });
1786
+ textStreamedViaContentBlock = true;
1787
+ continue;
1788
+ }
1789
+ if (event.type === "content_block_start" && "content_block" in event && event.content_block?.type === "thinking") {
1790
+ const blockIndex = "index" in event ? event.index : -1;
1791
+ hasReceivedStreamEvents = true;
1792
+ if (textPartId) {
1793
+ controller.enqueue({
1794
+ type: "text-end",
1795
+ id: textPartId
1796
+ });
1797
+ textPartId = void 0;
1798
+ }
1799
+ const reasoningPartId = generateId();
1800
+ reasoningBlocksByIndex.set(blockIndex, reasoningPartId);
1801
+ currentReasoningPartId = reasoningPartId;
1802
+ this.logger.debug(
1803
+ `[claude-code] Reasoning started (content_block) - ID: ${reasoningPartId}`
1804
+ );
1805
+ controller.enqueue({
1806
+ type: "reasoning-start",
1807
+ id: reasoningPartId
1808
+ });
1809
+ continue;
1810
+ }
1811
+ if (event.type === "content_block_delta" && event.delta.type === "thinking_delta" && "thinking" in event.delta && event.delta.thinking) {
1812
+ const blockIndex = "index" in event ? event.index : -1;
1813
+ const reasoningPartId = reasoningBlocksByIndex.get(blockIndex) ?? currentReasoningPartId;
1814
+ hasReceivedStreamEvents = true;
1815
+ if (reasoningPartId) {
1816
+ controller.enqueue({
1817
+ type: "reasoning-delta",
1818
+ id: reasoningPartId,
1819
+ delta: event.delta.thinking
1820
+ });
1821
+ }
1822
+ continue;
1823
+ }
1824
+ if (event.type === "content_block_stop") {
1825
+ const blockIndex = "index" in event ? event.index : -1;
1826
+ hasReceivedStreamEvents = true;
1827
+ const toolId = toolBlocksByIndex.get(blockIndex);
1828
+ if (toolId) {
1829
+ const state = toolStates.get(toolId);
1830
+ if (state && !state.inputClosed) {
1831
+ const accumulatedInput = toolInputAccumulators.get(toolId) ?? "";
1832
+ this.logger.debug(
1833
+ `[claude-code] Tool content block stopped - Index: ${blockIndex}, Tool: ${state.name}, ID: ${toolId}`
1834
+ );
1835
+ controller.enqueue({
1836
+ type: "tool-input-end",
1837
+ id: toolId
1838
+ });
1839
+ state.inputClosed = true;
1840
+ const effectiveInput = accumulatedInput || state.lastSerializedInput || "";
1841
+ state.lastSerializedInput = effectiveInput;
1842
+ if (!state.callEmitted) {
1843
+ controller.enqueue({
1844
+ type: "tool-call",
1845
+ toolCallId: toolId,
1846
+ toolName: state.name,
1847
+ input: effectiveInput,
1848
+ providerExecuted: true,
1849
+ dynamic: true,
1850
+ providerMetadata: {
1851
+ "claude-code": {
1852
+ rawInput: effectiveInput,
1853
+ parentToolCallId: state.parentToolCallId ?? null
1854
+ }
1855
+ }
1856
+ });
1857
+ state.callEmitted = true;
1858
+ }
1859
+ }
1860
+ toolBlocksByIndex.delete(blockIndex);
1861
+ toolInputAccumulators.delete(toolId);
1862
+ continue;
1863
+ }
1864
+ const textId = textBlocksByIndex.get(blockIndex);
1865
+ if (textId) {
1866
+ this.logger.debug(
1867
+ `[claude-code] Text content block stopped - Index: ${blockIndex}, ID: ${textId}`
1868
+ );
1869
+ controller.enqueue({
1870
+ type: "text-end",
1871
+ id: textId
1872
+ });
1873
+ textBlocksByIndex.delete(blockIndex);
1874
+ if (textPartId === textId) {
1875
+ textPartId = void 0;
1876
+ }
1877
+ continue;
1878
+ }
1879
+ const reasoningPartId = reasoningBlocksByIndex.get(blockIndex);
1880
+ if (reasoningPartId) {
1881
+ this.logger.debug(
1882
+ `[claude-code] Reasoning ended (content_block) - ID: ${reasoningPartId}`
1883
+ );
1884
+ controller.enqueue({
1885
+ type: "reasoning-end",
1886
+ id: reasoningPartId
1887
+ });
1888
+ reasoningBlocksByIndex.delete(blockIndex);
1889
+ if (currentReasoningPartId === reasoningPartId) {
1890
+ currentReasoningPartId = void 0;
1891
+ }
1892
+ continue;
1893
+ }
1894
+ }
1895
+ continue;
1896
+ }
1897
+ if (message.type === "assistant") {
1898
+ if (!message.message?.content) {
1899
+ this.logger.warn(
1900
+ `[claude-code] Unexpected assistant message structure: missing content field. Message type: ${message.type}. This may indicate an SDK protocol violation.`
1901
+ );
1902
+ continue;
1903
+ }
1904
+ const sdkParentToolUseId = message.parent_tool_use_id;
1905
+ const content = message.message.content;
1906
+ const tools = this.extractToolUses(content);
1907
+ if (textPartId && tools.length > 0) {
1908
+ controller.enqueue({
1909
+ type: "text-end",
1910
+ id: textPartId
1911
+ });
1912
+ textPartId = void 0;
1913
+ }
1914
+ for (const tool3 of tools) {
1915
+ const toolId = tool3.id;
1916
+ let state = toolStates.get(toolId);
1917
+ if (!state) {
1918
+ const currentParentId = tool3.name === "Task" ? null : sdkParentToolUseId ?? tool3.parentToolUseId ?? getFallbackParentId();
1919
+ state = {
1920
+ name: tool3.name,
1921
+ inputStarted: false,
1922
+ inputClosed: false,
1923
+ callEmitted: false,
1924
+ parentToolCallId: currentParentId
1925
+ };
1926
+ toolStates.set(toolId, state);
1927
+ this.logger.debug(
1928
+ `[claude-code] New tool use detected - Tool: ${tool3.name}, ID: ${toolId}, SDK parent: ${sdkParentToolUseId}, resolved parent: ${currentParentId}`
1929
+ );
1930
+ } else if (!state.parentToolCallId && sdkParentToolUseId && tool3.name !== "Task") {
1931
+ state.parentToolCallId = sdkParentToolUseId;
1932
+ this.logger.debug(
1933
+ `[claude-code] Retroactive parent context - Tool: ${tool3.name}, ID: ${toolId}, parent: ${sdkParentToolUseId}`
1934
+ );
1935
+ }
1936
+ state.name = tool3.name;
1937
+ if (!state.inputStarted) {
1938
+ this.logger.debug(
1939
+ `[claude-code] Tool input started - Tool: ${tool3.name}, ID: ${toolId}`
1940
+ );
1941
+ controller.enqueue({
1942
+ type: "tool-input-start",
1943
+ id: toolId,
1944
+ toolName: tool3.name,
1945
+ providerExecuted: true,
1946
+ dynamic: true,
1947
+ // V3 field: indicates tool is provider-defined
1948
+ providerMetadata: {
1949
+ "claude-code": {
1950
+ parentToolCallId: state.parentToolCallId ?? null
1951
+ }
1952
+ }
1953
+ });
1954
+ if (tool3.name === "Task") {
1955
+ activeTaskTools.set(toolId, { startTime: Date.now() });
1956
+ }
1957
+ state.inputStarted = true;
1958
+ }
1959
+ const serializedInput = this.serializeToolInput(tool3.input);
1960
+ if (serializedInput) {
1961
+ let deltaPayload = "";
1962
+ if (state.lastSerializedInput === void 0) {
1963
+ if (serializedInput.length <= _ClaudeCodeLanguageModel.MAX_DELTA_CALC_SIZE) {
1964
+ deltaPayload = serializedInput;
1965
+ }
1966
+ } else if (serializedInput.length <= _ClaudeCodeLanguageModel.MAX_DELTA_CALC_SIZE && state.lastSerializedInput.length <= _ClaudeCodeLanguageModel.MAX_DELTA_CALC_SIZE && serializedInput.startsWith(state.lastSerializedInput)) {
1967
+ deltaPayload = serializedInput.slice(state.lastSerializedInput.length);
1968
+ } else if (serializedInput !== state.lastSerializedInput) {
1969
+ deltaPayload = "";
1970
+ }
1971
+ if (deltaPayload) {
1972
+ controller.enqueue({
1973
+ type: "tool-input-delta",
1974
+ id: toolId,
1975
+ delta: deltaPayload
1976
+ });
1977
+ }
1978
+ state.lastSerializedInput = serializedInput;
1979
+ }
1980
+ }
1981
+ const text = content.map((c) => c.type === "text" ? c.text : "").join("");
1982
+ if (text) {
1983
+ if (hasReceivedStreamEvents) {
1984
+ const newTextStart = streamedTextLength;
1985
+ const deltaText = text.length > newTextStart ? text.slice(newTextStart) : "";
1986
+ accumulatedText = text;
1987
+ if (options.responseFormat?.type !== "json" && deltaText) {
1988
+ if (!textPartId) {
1989
+ textPartId = generateId();
1990
+ controller.enqueue({
1991
+ type: "text-start",
1992
+ id: textPartId
1993
+ });
1994
+ }
1995
+ controller.enqueue({
1996
+ type: "text-delta",
1997
+ id: textPartId,
1998
+ delta: deltaText
1999
+ });
2000
+ }
2001
+ streamedTextLength = text.length;
2002
+ } else {
2003
+ accumulatedText += text;
2004
+ if (options.responseFormat?.type !== "json") {
2005
+ if (!textPartId) {
2006
+ textPartId = generateId();
2007
+ controller.enqueue({
2008
+ type: "text-start",
2009
+ id: textPartId
2010
+ });
2011
+ }
2012
+ controller.enqueue({
2013
+ type: "text-delta",
2014
+ id: textPartId,
2015
+ delta: text
2016
+ });
2017
+ }
2018
+ }
2019
+ }
2020
+ } else if (message.type === "user") {
2021
+ if (!message.message?.content) {
2022
+ this.logger.warn(
2023
+ `[claude-code] Unexpected user message structure: missing content field. Message type: ${message.type}. This may indicate an SDK protocol violation.`
2024
+ );
2025
+ continue;
2026
+ }
2027
+ if (textPartId) {
2028
+ const closedTextId = textPartId;
2029
+ controller.enqueue({
2030
+ type: "text-end",
2031
+ id: closedTextId
2032
+ });
2033
+ textPartId = void 0;
2034
+ for (const [blockIndex, blockTextId] of textBlocksByIndex) {
2035
+ if (blockTextId === closedTextId) {
2036
+ textBlocksByIndex.delete(blockIndex);
2037
+ break;
2038
+ }
2039
+ }
2040
+ accumulatedText = "";
2041
+ streamedTextLength = 0;
2042
+ this.logger.debug("[claude-code] Closed text part due to user message");
2043
+ }
2044
+ const sdkParentToolUseIdForResults = message.parent_tool_use_id;
2045
+ const content = message.message.content;
2046
+ for (const result of this.extractToolResults(content)) {
2047
+ let state = toolStates.get(result.id);
2048
+ const toolName = result.name ?? state?.name ?? _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
2049
+ this.logger.debug(
2050
+ `[claude-code] Tool result received - Tool: ${toolName}, ID: ${result.id}`
2051
+ );
2052
+ if (!state) {
2053
+ this.logger.warn(
2054
+ `[claude-code] Received tool result for unknown tool ID: ${result.id}`
2055
+ );
2056
+ const resolvedParentId = toolName === "Task" ? null : sdkParentToolUseIdForResults ?? getFallbackParentId();
2057
+ state = {
2058
+ name: toolName,
2059
+ inputStarted: false,
2060
+ inputClosed: false,
2061
+ callEmitted: false,
2062
+ parentToolCallId: resolvedParentId
2063
+ };
2064
+ toolStates.set(result.id, state);
2065
+ if (!state.inputStarted) {
2066
+ controller.enqueue({
2067
+ type: "tool-input-start",
2068
+ id: result.id,
2069
+ toolName,
2070
+ providerExecuted: true,
2071
+ dynamic: true,
2072
+ // V3 field: indicates tool is provider-defined
2073
+ providerMetadata: {
2074
+ "claude-code": {
2075
+ parentToolCallId: state.parentToolCallId ?? null
2076
+ }
2077
+ }
2078
+ });
2079
+ state.inputStarted = true;
2080
+ }
2081
+ if (!state.inputClosed) {
2082
+ controller.enqueue({
2083
+ type: "tool-input-end",
2084
+ id: result.id
2085
+ });
2086
+ state.inputClosed = true;
2087
+ }
2088
+ }
2089
+ state.name = toolName;
2090
+ const normalizedResult = this.normalizeToolResult(result.result);
2091
+ const rawResult = typeof result.result === "string" ? result.result : (() => {
2092
+ try {
2093
+ return JSON.stringify(result.result);
2094
+ } catch {
2095
+ return String(result.result);
2096
+ }
2097
+ })();
2098
+ const maxToolResultSize = this.settings.maxToolResultSize;
2099
+ const truncatedResult = truncateToolResultForStream(
2100
+ normalizedResult,
2101
+ maxToolResultSize
2102
+ );
2103
+ const truncatedRawResult = truncateToolResultForStream(
2104
+ rawResult,
2105
+ maxToolResultSize
2106
+ );
2107
+ const rawResultTruncated = truncatedRawResult !== rawResult;
2108
+ emitToolCall(result.id, state);
2109
+ if (toolName === "Task") {
2110
+ activeTaskTools.delete(result.id);
2111
+ }
2112
+ controller.enqueue({
2113
+ type: "tool-result",
2114
+ toolCallId: result.id,
2115
+ toolName,
2116
+ result: truncatedResult,
2117
+ isError: result.isError,
2118
+ providerExecuted: true,
2119
+ dynamic: true,
2120
+ // V3 field: indicates tool is provider-defined
2121
+ providerMetadata: {
2122
+ "claude-code": {
2123
+ // rawResult preserves the original CLI output string before JSON parsing.
2124
+ // Use this when you need the exact string returned by the tool, especially
2125
+ // if the `result` field has been parsed/normalized and you need the original format.
2126
+ rawResult: truncatedRawResult,
2127
+ rawResultTruncated,
2128
+ parentToolCallId: state.parentToolCallId ?? null
2129
+ }
2130
+ }
2131
+ });
2132
+ }
2133
+ for (const error of this.extractToolErrors(content)) {
2134
+ let state = toolStates.get(error.id);
2135
+ const toolName = error.name ?? state?.name ?? _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
2136
+ this.logger.debug(
2137
+ `[claude-code] Tool error received - Tool: ${toolName}, ID: ${error.id}`
2138
+ );
2139
+ if (!state) {
2140
+ this.logger.warn(
2141
+ `[claude-code] Received tool error for unknown tool ID: ${error.id}`
2142
+ );
2143
+ const errorResolvedParentId = toolName === "Task" ? null : sdkParentToolUseIdForResults ?? getFallbackParentId();
2144
+ state = {
2145
+ name: toolName,
2146
+ inputStarted: true,
2147
+ inputClosed: true,
2148
+ callEmitted: false,
2149
+ parentToolCallId: errorResolvedParentId
2150
+ };
2151
+ toolStates.set(error.id, state);
2152
+ }
2153
+ emitToolCall(error.id, state);
2154
+ if (toolName === "Task") {
2155
+ activeTaskTools.delete(error.id);
2156
+ }
2157
+ const rawError = typeof error.error === "string" ? error.error : typeof error.error === "object" && error.error !== null ? (() => {
2158
+ try {
2159
+ return JSON.stringify(error.error);
2160
+ } catch {
2161
+ return String(error.error);
2162
+ }
2163
+ })() : String(error.error);
2164
+ controller.enqueue({
2165
+ type: "tool-error",
2166
+ toolCallId: error.id,
2167
+ toolName,
2168
+ error: rawError,
2169
+ providerExecuted: true,
2170
+ dynamic: true,
2171
+ // V3 field: indicates tool is provider-defined
2172
+ providerMetadata: {
2173
+ "claude-code": {
2174
+ rawError,
2175
+ parentToolCallId: state.parentToolCallId ?? null
2176
+ }
2177
+ }
2178
+ });
2179
+ }
2180
+ } else if (message.type === "result") {
2181
+ done();
2182
+ if ("is_error" in message && message.is_error === true) {
2183
+ const errorMessage = "result" in message && typeof message.result === "string" ? message.result : "Claude Code CLI returned an error";
2184
+ throw Object.assign(new Error(errorMessage), { exitCode: 1 });
2185
+ }
2186
+ if (message.subtype === "error_max_structured_output_retries") {
2187
+ throw new Error(
2188
+ "Failed to generate valid structured output after maximum retries. The model could not produce a response matching the required schema."
2189
+ );
2190
+ }
2191
+ this.logger.info(
2192
+ `[claude-code] Stream completed - Session: ${message.session_id}, Cost: $${message.total_cost_usd?.toFixed(4) ?? "N/A"}, Duration: ${message.duration_ms ?? "N/A"}ms`
2193
+ );
2194
+ if ("usage" in message) {
2195
+ usage = convertClaudeCodeUsage(message.usage);
2196
+ this.logger.debug(
2197
+ `[claude-code] Stream token usage - Input: ${usage.inputTokens.total}, Output: ${usage.outputTokens.total}`
2198
+ );
2199
+ }
2200
+ const stopReason = "stop_reason" in message ? message.stop_reason : void 0;
2201
+ const finishReason = mapClaudeCodeFinishReason(
2202
+ message.subtype,
2203
+ stopReason
2204
+ );
2205
+ this.logger.debug(`[claude-code] Stream finish reason: ${finishReason.unified}`);
2206
+ this.setSessionId(message.session_id);
2207
+ const structuredOutput = "structured_output" in message ? message.structured_output : void 0;
2208
+ const alreadyStreamedJson = hasStreamedJson && options.responseFormat?.type === "json" && hasReceivedStreamEvents;
2209
+ if (alreadyStreamedJson) {
2210
+ if (textPartId) {
2211
+ controller.enqueue({
2212
+ type: "text-end",
2213
+ id: textPartId
2214
+ });
2215
+ }
2216
+ } else if (structuredOutput !== void 0) {
2217
+ const jsonTextId = generateId();
2218
+ const jsonText = JSON.stringify(structuredOutput);
2219
+ controller.enqueue({
2220
+ type: "text-start",
2221
+ id: jsonTextId
2222
+ });
2223
+ controller.enqueue({
2224
+ type: "text-delta",
2225
+ id: jsonTextId,
2226
+ delta: jsonText
2227
+ });
2228
+ controller.enqueue({
2229
+ type: "text-end",
2230
+ id: jsonTextId
2231
+ });
2232
+ } else if (textPartId) {
2233
+ controller.enqueue({
2234
+ type: "text-end",
2235
+ id: textPartId
2236
+ });
2237
+ } else if (accumulatedText && !textStreamedViaContentBlock) {
2238
+ const fallbackTextId = generateId();
2239
+ controller.enqueue({
2240
+ type: "text-start",
2241
+ id: fallbackTextId
2242
+ });
2243
+ controller.enqueue({
2244
+ type: "text-delta",
2245
+ id: fallbackTextId,
2246
+ delta: accumulatedText
2247
+ });
2248
+ controller.enqueue({
2249
+ type: "text-end",
2250
+ id: fallbackTextId
2251
+ });
2252
+ }
2253
+ finalizeToolCalls();
2254
+ const warningsJson = this.serializeWarningsForMetadata(streamWarnings);
2255
+ controller.enqueue({
2256
+ type: "finish",
2257
+ finishReason,
2258
+ usage,
2259
+ providerMetadata: {
2260
+ "claude-code": {
2261
+ sessionId: message.session_id,
2262
+ ...message.total_cost_usd !== void 0 && {
2263
+ costUsd: message.total_cost_usd
2264
+ },
2265
+ ...message.duration_ms !== void 0 && { durationMs: message.duration_ms },
2266
+ ...message.modelUsage !== void 0 && {
2267
+ modelUsage: message.modelUsage
2268
+ },
2269
+ // JSON validation warnings are collected during streaming and included
2270
+ // in providerMetadata since the AI SDK's finish event doesn't support
2271
+ // a top-level warnings field (unlike stream-start which was already emitted)
2272
+ ...streamWarnings.length > 0 && {
2273
+ warnings: warningsJson
2274
+ }
2275
+ }
2276
+ }
2277
+ });
2278
+ controller.close();
2279
+ return;
2280
+ } else if (message.type === "system" && message.subtype === "init") {
2281
+ this.setSessionId(message.session_id);
2282
+ this.logger.info(`[claude-code] Stream session initialized: ${message.session_id}`);
2283
+ controller.enqueue({
2284
+ type: "response-metadata",
2285
+ id: message.session_id,
2286
+ timestamp: /* @__PURE__ */ new Date(),
2287
+ modelId: this.modelId
2288
+ });
2289
+ }
2290
+ }
2291
+ finalizeToolCalls();
2292
+ this.logger.debug("[claude-code] Stream finalized, closing stream");
2293
+ controller.close();
2294
+ } catch (error) {
2295
+ done();
2296
+ this.logger.debug(
2297
+ `[claude-code] Error during doStream: ${error instanceof Error ? error.message : String(error)}`
2298
+ );
2299
+ if (isClaudeCodeTruncationError(error, accumulatedText)) {
2300
+ this.logger.warn(
2301
+ `[claude-code] Detected truncated stream response, returning ${accumulatedText.length} characters of buffered text`
2302
+ );
2303
+ const truncationWarning = {
2304
+ type: "other",
2305
+ message: CLAUDE_CODE_TRUNCATION_WARNING
2306
+ };
2307
+ streamWarnings.push(truncationWarning);
2308
+ if (textPartId) {
2309
+ controller.enqueue({
2310
+ type: "text-end",
2311
+ id: textPartId
2312
+ });
2313
+ } else if (accumulatedText && !textStreamedViaContentBlock) {
2314
+ const fallbackTextId = generateId();
2315
+ controller.enqueue({
2316
+ type: "text-start",
2317
+ id: fallbackTextId
2318
+ });
2319
+ controller.enqueue({
2320
+ type: "text-delta",
2321
+ id: fallbackTextId,
2322
+ delta: accumulatedText
2323
+ });
2324
+ controller.enqueue({
2325
+ type: "text-end",
2326
+ id: fallbackTextId
2327
+ });
2328
+ }
2329
+ finalizeToolCalls();
2330
+ const warningsJson = this.serializeWarningsForMetadata(streamWarnings);
2331
+ controller.enqueue({
2332
+ type: "finish",
2333
+ finishReason: { unified: "length", raw: "truncation" },
2334
+ usage,
2335
+ providerMetadata: {
2336
+ "claude-code": {
2337
+ ...this.sessionId !== void 0 && { sessionId: this.sessionId },
2338
+ truncated: true,
2339
+ ...streamWarnings.length > 0 && {
2340
+ warnings: warningsJson
2341
+ }
2342
+ }
2343
+ }
2344
+ });
2345
+ controller.close();
2346
+ return;
2347
+ }
2348
+ finalizeToolCalls();
2349
+ let errorToEmit;
2350
+ if (isAbortError(error)) {
2351
+ errorToEmit = options.abortSignal?.aborted ? options.abortSignal.reason : error;
2352
+ } else {
2353
+ errorToEmit = this.handleClaudeCodeError(error, messagesPrompt, collectedStderr);
2354
+ }
2355
+ controller.enqueue({
2356
+ type: "error",
2357
+ error: errorToEmit
2358
+ });
2359
+ controller.close();
2360
+ } finally {
2361
+ if (options.abortSignal && abortListener) {
2362
+ options.abortSignal.removeEventListener("abort", abortListener);
2363
+ }
2364
+ }
2365
+ },
2366
+ cancel: () => {
2367
+ if (options.abortSignal && abortListener) {
2368
+ options.abortSignal.removeEventListener("abort", abortListener);
2369
+ }
2370
+ }
2371
+ });
2372
+ return {
2373
+ stream,
2374
+ request: {
2375
+ body: messagesPrompt
2376
+ }
2377
+ };
2378
+ }
2379
+ serializeWarningsForMetadata(warnings) {
2380
+ const result = warnings.map((w) => {
2381
+ const base = { type: w.type };
2382
+ if ("message" in w) {
2383
+ const m = w.message;
2384
+ if (m !== void 0) base.message = String(m);
2385
+ }
2386
+ if (w.type === "unsupported" || w.type === "compatibility") {
2387
+ const feature = w.feature;
2388
+ if (feature !== void 0) base.feature = String(feature);
2389
+ if ("details" in w) {
2390
+ const d = w.details;
2391
+ if (d !== void 0) base.details = String(d);
2392
+ }
2393
+ }
2394
+ return base;
2395
+ });
2396
+ return result;
2397
+ }
2398
+ };
2399
+
2400
+ // docs/src/claude-code-provider.ts
2401
+ function createClaudeCode(options = {}) {
2402
+ const logger = getLogger(options.defaultSettings?.logger);
2403
+ if (options.defaultSettings) {
2404
+ const validation = validateSettings(options.defaultSettings);
2405
+ if (!validation.valid) {
2406
+ throw new Error(`Invalid default settings: ${validation.errors.join(", ")}`);
2407
+ }
2408
+ if (validation.warnings.length > 0) {
2409
+ validation.warnings.forEach((warning) => logger.warn(`Claude Code Provider: ${warning}`));
2410
+ }
2411
+ }
2412
+ const createModel = (modelId, settings = {}) => {
2413
+ const mergedSettings = {
2414
+ ...options.defaultSettings,
2415
+ ...settings
2416
+ };
2417
+ const validation = validateSettings(mergedSettings);
2418
+ if (!validation.valid) {
2419
+ throw new Error(`Invalid settings: ${validation.errors.join(", ")}`);
2420
+ }
2421
+ return new ClaudeCodeLanguageModel({
2422
+ id: modelId,
2423
+ settings: mergedSettings,
2424
+ settingsValidationWarnings: validation.warnings
2425
+ });
2426
+ };
2427
+ const provider = function(modelId, settings) {
2428
+ if (new.target) {
2429
+ throw new Error("The Claude Code model function cannot be called with the new keyword.");
2430
+ }
2431
+ return createModel(modelId, settings);
2432
+ };
2433
+ provider.languageModel = createModel;
2434
+ provider.chat = createModel;
2435
+ provider.specificationVersion = "v3";
2436
+ provider.embeddingModel = (modelId) => {
2437
+ throw new NoSuchModelError2({
2438
+ modelId,
2439
+ modelType: "embeddingModel"
2440
+ });
2441
+ };
2442
+ provider.imageModel = (modelId) => {
2443
+ throw new NoSuchModelError2({
2444
+ modelId,
2445
+ modelType: "imageModel"
2446
+ });
2447
+ };
2448
+ return provider;
2449
+ }
2450
+ var claudeCode = createClaudeCode();
2451
+
2452
+ // docs/src/index.ts
2453
+ import { createSdkMcpServer as createSdkMcpServer2, tool as tool2 } from "@anthropic-ai/claude-agent-sdk";
2454
+
2455
+ // docs/src/mcp-helpers.ts
2456
+ import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
2457
+ import "zod";
2458
+ function createCustomMcpServer(config) {
2459
+ const defs = Object.entries(config.tools).map(
2460
+ ([name, def]) => tool(
2461
+ name,
2462
+ def.description,
2463
+ def.inputSchema.shape,
2464
+ (args, extra) => def.handler(args, extra),
2465
+ def.annotations ? { annotations: def.annotations } : void 0
2466
+ )
2467
+ );
2468
+ return createSdkMcpServer({ name: config.name, version: config.version, tools: defs });
2469
+ }
2470
+ export {
2471
+ ClaudeCodeLanguageModel,
2472
+ claudeCode,
2473
+ createAPICallError,
2474
+ createAuthenticationError,
2475
+ createClaudeCode,
2476
+ createCustomMcpServer,
2477
+ createSdkMcpServer2 as createSdkMcpServer,
2478
+ createTimeoutError,
2479
+ getErrorMetadata,
2480
+ isAuthenticationError,
2481
+ isTimeoutError,
2482
+ tool2 as tool
2483
+ };
2484
+ //# sourceMappingURL=index.js.map