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