ai-sdk-provider-claude-code 3.5.2 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs DELETED
@@ -1,4025 +0,0 @@
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
- // src/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- AbortError: () => import_claude_agent_sdk3.AbortError,
24
- ClaudeCodeLanguageModel: () => ClaudeCodeLanguageModel,
25
- HOOK_EVENTS: () => import_claude_agent_sdk3.HOOK_EVENTS,
26
- InMemorySessionStore: () => import_claude_agent_sdk3.InMemorySessionStore,
27
- SYSTEM_PROMPT_DYNAMIC_BOUNDARY: () => import_claude_agent_sdk3.SYSTEM_PROMPT_DYNAMIC_BOUNDARY,
28
- claudeCode: () => claudeCode,
29
- createAPICallError: () => createAPICallError,
30
- createAiSdkMcpServer: () => createAiSdkMcpServer,
31
- createAuthenticationError: () => createAuthenticationError,
32
- createClaudeCode: () => createClaudeCode,
33
- createCustomMcpServer: () => createCustomMcpServer,
34
- createSdkMcpServer: () => import_claude_agent_sdk3.createSdkMcpServer,
35
- createTimeoutError: () => createTimeoutError,
36
- deleteSession: () => import_claude_agent_sdk4.deleteSession,
37
- foldSessionSummary: () => import_claude_agent_sdk4.foldSessionSummary,
38
- forkSession: () => import_claude_agent_sdk4.forkSession,
39
- getErrorMetadata: () => getErrorMetadata,
40
- getSessionInfo: () => import_claude_agent_sdk4.getSessionInfo,
41
- getSessionMessages: () => import_claude_agent_sdk4.getSessionMessages,
42
- getSubagentMessages: () => import_claude_agent_sdk4.getSubagentMessages,
43
- importSessionToStore: () => import_claude_agent_sdk4.importSessionToStore,
44
- isAuthenticationError: () => isAuthenticationError,
45
- isTimeoutError: () => isTimeoutError,
46
- listSessions: () => import_claude_agent_sdk4.listSessions,
47
- listSubagents: () => import_claude_agent_sdk4.listSubagents,
48
- renameSession: () => import_claude_agent_sdk4.renameSession,
49
- startup: () => import_claude_agent_sdk5.startup,
50
- tagSession: () => import_claude_agent_sdk4.tagSession,
51
- tool: () => import_claude_agent_sdk3.tool
52
- });
53
- module.exports = __toCommonJS(index_exports);
54
-
55
- // src/claude-code-provider.ts
56
- var import_provider3 = require("@ai-sdk/provider");
57
-
58
- // src/claude-code-language-model.ts
59
- var import_provider2 = require("@ai-sdk/provider");
60
- var import_provider_utils = require("@ai-sdk/provider-utils");
61
-
62
- // src/convert-to-claude-code-messages.ts
63
- var IMAGE_URL_WARNING = "Image URLs are not supported by this provider; supply base64/data URLs.";
64
- var IMAGE_CONVERSION_WARNING = "Unable to convert image content; supply base64/data URLs.";
65
- var MAX_TOOL_CALL_INPUT_LENGTH = 1e3;
66
- function serializeToolCallInput(input) {
67
- let serialized;
68
- if (input === void 0) {
69
- serialized = "";
70
- } else {
71
- try {
72
- serialized = JSON.stringify(input) ?? String(input);
73
- } catch {
74
- serialized = String(input);
75
- }
76
- }
77
- if (serialized.length > MAX_TOOL_CALL_INPUT_LENGTH) {
78
- return `${serialized.slice(0, MAX_TOOL_CALL_INPUT_LENGTH)}...[truncated]`;
79
- }
80
- return serialized;
81
- }
82
- function normalizeBase64(base64) {
83
- return base64.replace(/\s+/g, "");
84
- }
85
- function isImageMimeType(mimeType) {
86
- return typeof mimeType === "string" && mimeType.trim().toLowerCase().startsWith("image/");
87
- }
88
- function createImageContent(mediaType, data) {
89
- const trimmedType = mediaType.trim();
90
- const trimmedData = normalizeBase64(data.trim());
91
- if (!trimmedType || !trimmedData) {
92
- return void 0;
93
- }
94
- return {
95
- type: "image",
96
- source: {
97
- type: "base64",
98
- media_type: trimmedType,
99
- data: trimmedData
100
- }
101
- };
102
- }
103
- function extractMimeType(candidate) {
104
- if (typeof candidate === "string" && candidate.trim()) {
105
- return candidate.trim();
106
- }
107
- return void 0;
108
- }
109
- function parseObjectImage(imageObj, fallbackMimeType) {
110
- const data = typeof imageObj.data === "string" ? imageObj.data : void 0;
111
- const mimeType = extractMimeType(
112
- imageObj.mimeType ?? imageObj.mediaType ?? imageObj.media_type ?? fallbackMimeType
113
- );
114
- if (!data || !mimeType) {
115
- return void 0;
116
- }
117
- return createImageContent(mimeType, data);
118
- }
119
- function parseStringImage(value, fallbackMimeType) {
120
- const trimmed = value.trim();
121
- if (/^https?:\/\//i.test(trimmed)) {
122
- return { warning: IMAGE_URL_WARNING };
123
- }
124
- const dataUrlMatch = trimmed.match(/^data:([^;]+);base64,(.+)$/i);
125
- if (dataUrlMatch) {
126
- const [, mediaType, data] = dataUrlMatch;
127
- const content = createImageContent(mediaType, data);
128
- return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
129
- }
130
- const base64Match = trimmed.match(/^base64:([^,]+),(.+)$/i);
131
- if (base64Match) {
132
- const [, explicitMimeType, data] = base64Match;
133
- const content = createImageContent(explicitMimeType, data);
134
- return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
135
- }
136
- if (fallbackMimeType) {
137
- const content = createImageContent(fallbackMimeType, trimmed);
138
- if (content) {
139
- return { content };
140
- }
141
- }
142
- return { warning: IMAGE_CONVERSION_WARNING };
143
- }
144
- function parseImagePart(part) {
145
- if (!part || typeof part !== "object") {
146
- return { warning: IMAGE_CONVERSION_WARNING };
147
- }
148
- const imageValue = part.image;
149
- const mimeType = extractMimeType(part.mimeType);
150
- if (typeof imageValue === "string") {
151
- return parseStringImage(imageValue, mimeType);
152
- }
153
- if (imageValue && typeof imageValue === "object") {
154
- const content = parseObjectImage(imageValue, mimeType);
155
- return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
156
- }
157
- return { warning: IMAGE_CONVERSION_WARNING };
158
- }
159
- function convertBinaryToBase64(data) {
160
- if (typeof Buffer !== "undefined") {
161
- const buffer = data instanceof Uint8Array ? Buffer.from(data) : Buffer.from(new Uint8Array(data));
162
- return buffer.toString("base64");
163
- }
164
- if (typeof btoa === "function") {
165
- const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
166
- let binary = "";
167
- const chunkSize = 32768;
168
- for (let i = 0; i < bytes.length; i += chunkSize) {
169
- const chunk = bytes.subarray(i, i + chunkSize);
170
- binary += String.fromCharCode(...chunk);
171
- }
172
- return btoa(binary);
173
- }
174
- return void 0;
175
- }
176
- function parseFilePart(part) {
177
- const mimeType = extractMimeType(part.mediaType ?? part.mimeType);
178
- if (!mimeType || !isImageMimeType(mimeType)) {
179
- return {};
180
- }
181
- const data = part.data;
182
- if (typeof data === "string") {
183
- const content = createImageContent(mimeType, data);
184
- return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
185
- }
186
- if (data instanceof Uint8Array || typeof ArrayBuffer !== "undefined" && data instanceof ArrayBuffer) {
187
- const base64 = convertBinaryToBase64(data);
188
- if (!base64) {
189
- return { warning: IMAGE_CONVERSION_WARNING };
190
- }
191
- const content = createImageContent(mimeType, base64);
192
- return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
193
- }
194
- return { warning: IMAGE_CONVERSION_WARNING };
195
- }
196
- function convertToClaudeCodeMessages(prompt) {
197
- const messages = [];
198
- const warnings = [];
199
- let systemPrompt;
200
- const streamingSegments = [];
201
- const imageMap = /* @__PURE__ */ new Map();
202
- let hasImageParts = false;
203
- const addSegment = (formatted) => {
204
- streamingSegments.push({ formatted });
205
- return streamingSegments.length - 1;
206
- };
207
- const addImageForSegment = (segmentIndex, content) => {
208
- hasImageParts = true;
209
- if (!imageMap.has(segmentIndex)) {
210
- imageMap.set(segmentIndex, []);
211
- }
212
- imageMap.get(segmentIndex)?.push(content);
213
- };
214
- for (const message of prompt) {
215
- switch (message.role) {
216
- case "system":
217
- systemPrompt = message.content;
218
- if (typeof message.content === "string" && message.content.trim().length > 0) {
219
- addSegment(message.content);
220
- } else {
221
- addSegment("");
222
- }
223
- break;
224
- case "user":
225
- if (typeof message.content === "string") {
226
- messages.push(message.content);
227
- addSegment(`Human: ${message.content}`);
228
- } else {
229
- const textParts = message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
230
- const segmentIndex = addSegment(textParts ? `Human: ${textParts}` : "");
231
- if (textParts) {
232
- messages.push(textParts);
233
- }
234
- for (const part of message.content) {
235
- if (part.type === "image") {
236
- const { content, warning } = parseImagePart(part);
237
- if (content) {
238
- addImageForSegment(segmentIndex, content);
239
- } else if (warning) {
240
- warnings.push(warning);
241
- }
242
- } else if (part.type === "file") {
243
- const { content, warning } = parseFilePart(part);
244
- if (content) {
245
- addImageForSegment(segmentIndex, content);
246
- } else if (warning) {
247
- warnings.push(warning);
248
- }
249
- }
250
- }
251
- }
252
- break;
253
- case "assistant": {
254
- let assistantContent = "";
255
- if (typeof message.content === "string") {
256
- assistantContent = message.content;
257
- } else {
258
- const textParts = message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
259
- if (textParts) {
260
- assistantContent = textParts;
261
- }
262
- const toolCalls = message.content.filter((part) => part.type === "tool-call");
263
- if (toolCalls.length > 0) {
264
- const serializedCalls = toolCalls.map((call) => `[Tool call: ${call.toolName}(${serializeToolCallInput(call.input)})]`).join("\n");
265
- assistantContent += assistantContent ? `
266
- ${serializedCalls}` : serializedCalls;
267
- }
268
- }
269
- const formattedAssistant = `Assistant: ${assistantContent}`;
270
- messages.push(formattedAssistant);
271
- addSegment(formattedAssistant);
272
- break;
273
- }
274
- case "tool":
275
- for (const tool3 of message.content) {
276
- if (tool3.type === "tool-approval-response") {
277
- continue;
278
- }
279
- let resultText;
280
- const output = tool3.output;
281
- if (output.type === "text" || output.type === "error-text") {
282
- resultText = output.value;
283
- } else if (output.type === "json" || output.type === "error-json") {
284
- resultText = JSON.stringify(output.value);
285
- } else if (output.type === "execution-denied") {
286
- resultText = `[Execution denied${output.reason ? `: ${output.reason}` : ""}]`;
287
- } else if (output.type === "content") {
288
- resultText = output.value.filter((part) => part.type === "text").map((part) => part.text).join("\n");
289
- } else {
290
- resultText = "[Unknown output type]";
291
- }
292
- const formattedToolResult = `Tool Result (${tool3.toolName}): ${resultText}`;
293
- messages.push(formattedToolResult);
294
- addSegment(formattedToolResult);
295
- }
296
- break;
297
- }
298
- }
299
- let finalPrompt = "";
300
- if (systemPrompt) {
301
- finalPrompt = systemPrompt;
302
- }
303
- if (messages.length > 0) {
304
- const formattedMessages = [];
305
- for (let i = 0; i < messages.length; i++) {
306
- const msg = messages[i];
307
- if (msg.startsWith("Assistant:") || msg.startsWith("Tool Result")) {
308
- formattedMessages.push(msg);
309
- } else {
310
- formattedMessages.push(`Human: ${msg}`);
311
- }
312
- }
313
- if (finalPrompt) {
314
- const joinedMessages = formattedMessages.join("\n\n");
315
- finalPrompt = joinedMessages ? `${finalPrompt}
316
-
317
- ${joinedMessages}` : finalPrompt;
318
- } else {
319
- finalPrompt = formattedMessages.join("\n\n");
320
- }
321
- }
322
- const streamingParts = [];
323
- const imagePartsInOrder = [];
324
- const appendImagesForIndex = (index) => {
325
- const images = imageMap.get(index);
326
- if (!images) {
327
- return;
328
- }
329
- images.forEach((image) => {
330
- streamingParts.push(image);
331
- imagePartsInOrder.push(image);
332
- });
333
- };
334
- if (streamingSegments.length > 0) {
335
- let accumulatedText = "";
336
- let emittedText = false;
337
- const flushText = () => {
338
- if (!accumulatedText) {
339
- return;
340
- }
341
- streamingParts.push({ type: "text", text: accumulatedText });
342
- accumulatedText = "";
343
- emittedText = true;
344
- };
345
- streamingSegments.forEach((segment, index) => {
346
- const segmentText = segment.formatted;
347
- if (segmentText) {
348
- if (!accumulatedText) {
349
- accumulatedText = emittedText ? `
350
-
351
- ${segmentText}` : segmentText;
352
- } else {
353
- accumulatedText += `
354
-
355
- ${segmentText}`;
356
- }
357
- }
358
- if (imageMap.has(index)) {
359
- flushText();
360
- appendImagesForIndex(index);
361
- }
362
- });
363
- flushText();
364
- }
365
- return {
366
- messagesPrompt: finalPrompt,
367
- systemPrompt,
368
- ...warnings.length > 0 && { warnings },
369
- streamingContentParts: streamingParts.length > 0 ? streamingParts : [
370
- { type: "text", text: finalPrompt },
371
- ...imagePartsInOrder
372
- ],
373
- hasImageParts
374
- };
375
- }
376
-
377
- // src/errors.ts
378
- var import_provider = require("@ai-sdk/provider");
379
- function createAPICallError({
380
- message,
381
- code,
382
- exitCode,
383
- stderr,
384
- promptExcerpt,
385
- isRetryable = false
386
- }) {
387
- const metadata = {
388
- code,
389
- exitCode,
390
- stderr,
391
- promptExcerpt
392
- };
393
- return new import_provider.APICallError({
394
- message,
395
- isRetryable,
396
- url: "claude-code-cli://command",
397
- requestBodyValues: promptExcerpt ? { prompt: promptExcerpt } : void 0,
398
- data: metadata
399
- });
400
- }
401
- function createAuthenticationError({ message }) {
402
- return new import_provider.LoadAPIKeyError({
403
- message: message || "Authentication failed. Please ensure Claude Code SDK is properly authenticated."
404
- });
405
- }
406
- function createTimeoutError({
407
- message,
408
- promptExcerpt,
409
- timeoutMs
410
- }) {
411
- const metadata = {
412
- code: "TIMEOUT",
413
- promptExcerpt
414
- };
415
- return new import_provider.APICallError({
416
- message,
417
- isRetryable: true,
418
- url: "claude-code-cli://command",
419
- requestBodyValues: promptExcerpt ? { prompt: promptExcerpt } : void 0,
420
- data: timeoutMs !== void 0 ? { ...metadata, timeoutMs } : metadata
421
- });
422
- }
423
- function isAuthenticationError(error) {
424
- if (error instanceof import_provider.LoadAPIKeyError) return true;
425
- if (error instanceof import_provider.APICallError && error.data?.exitCode === 401)
426
- return true;
427
- return false;
428
- }
429
- function isTimeoutError(error) {
430
- if (error instanceof import_provider.APICallError && error.data?.code === "TIMEOUT")
431
- return true;
432
- return false;
433
- }
434
- function getErrorMetadata(error) {
435
- if (error instanceof import_provider.APICallError && error.data) {
436
- return error.data;
437
- }
438
- return void 0;
439
- }
440
-
441
- // src/map-claude-code-finish-reason.ts
442
- function mapClaudeCodeFinishReason(subtype, stopReason) {
443
- if (stopReason != null) {
444
- switch (stopReason) {
445
- case "end_turn":
446
- return { unified: "stop", raw: "end_turn" };
447
- case "max_tokens":
448
- return { unified: "length", raw: "max_tokens" };
449
- case "stop_sequence":
450
- return { unified: "stop", raw: "stop_sequence" };
451
- case "tool_use":
452
- return { unified: "tool-calls", raw: "tool_use" };
453
- default:
454
- break;
455
- }
456
- }
457
- const raw = stopReason ?? subtype;
458
- switch (subtype) {
459
- case "success":
460
- return { unified: "stop", raw };
461
- case "error_max_turns":
462
- return { unified: "length", raw };
463
- case "error_during_execution":
464
- return { unified: "error", raw };
465
- case void 0:
466
- return { unified: "stop", raw };
467
- default:
468
- return { unified: "other", raw };
469
- }
470
- }
471
-
472
- // src/validation.ts
473
- var import_zod = require("zod");
474
- var import_fs = require("fs");
475
- function isBlankResume(value) {
476
- return typeof value === "string" && value.trim() === "";
477
- }
478
- var loggerFunctionSchema = import_zod.z.object({
479
- debug: import_zod.z.any().refine((val) => typeof val === "function", {
480
- message: "debug must be a function"
481
- }),
482
- info: import_zod.z.any().refine((val) => typeof val === "function", {
483
- message: "info must be a function"
484
- }),
485
- warn: import_zod.z.any().refine((val) => typeof val === "function", {
486
- message: "warn must be a function"
487
- }),
488
- error: import_zod.z.any().refine((val) => typeof val === "function", {
489
- message: "error must be a function"
490
- })
491
- });
492
- var claudeCodeSettingsSchema = import_zod.z.object({
493
- pathToClaudeCodeExecutable: import_zod.z.string().optional(),
494
- customSystemPrompt: import_zod.z.string().optional(),
495
- appendSystemPrompt: import_zod.z.string().optional(),
496
- systemPrompt: import_zod.z.union([
497
- import_zod.z.string(),
498
- import_zod.z.array(import_zod.z.string()),
499
- import_zod.z.object({
500
- type: import_zod.z.literal("preset"),
501
- preset: import_zod.z.literal("claude_code"),
502
- append: import_zod.z.string().optional(),
503
- excludeDynamicSections: import_zod.z.boolean().optional()
504
- })
505
- ]).optional(),
506
- maxTurns: import_zod.z.number().int().min(1).max(100).optional(),
507
- maxThinkingTokens: import_zod.z.number().int().positive().max(1e5).optional(),
508
- thinking: import_zod.z.union([
509
- import_zod.z.object({
510
- type: import_zod.z.literal("adaptive"),
511
- display: import_zod.z.enum(["summarized", "omitted"]).optional()
512
- }).strict(),
513
- import_zod.z.object({
514
- type: import_zod.z.literal("enabled"),
515
- budgetTokens: import_zod.z.number().int().positive().optional(),
516
- display: import_zod.z.enum(["summarized", "omitted"]).optional()
517
- }).strict(),
518
- import_zod.z.object({ type: import_zod.z.literal("disabled") }).strict()
519
- ]).optional(),
520
- effort: import_zod.z.enum(["low", "medium", "high", "xhigh", "max"]).optional(),
521
- promptSuggestions: import_zod.z.boolean().optional(),
522
- cwd: import_zod.z.string().refine(
523
- (val) => {
524
- if (typeof process === "undefined" || !process.versions?.node) {
525
- return true;
526
- }
527
- return !val || (0, import_fs.existsSync)(val);
528
- },
529
- { message: "Working directory must exist" }
530
- ).optional(),
531
- executable: import_zod.z.enum(["bun", "deno", "node"]).optional(),
532
- executableArgs: import_zod.z.array(import_zod.z.string()).optional(),
533
- // Mirrors the SDK 0.3.x PermissionMode union ('auto' and 'dontAsk' were
534
- // added in 0.3.x; 'delegate' was dropped AND is rejected by the CLI's
535
- // --permission-mode flag parser, so it is rejected here too).
536
- permissionMode: import_zod.z.enum(["default", "acceptEdits", "bypassPermissions", "plan", "dontAsk", "auto"]).optional(),
537
- permissionPromptToolName: import_zod.z.string().optional(),
538
- continue: import_zod.z.boolean().optional(),
539
- resume: import_zod.z.string().optional(),
540
- // The CLI rejects --session-id values that are not valid UUIDs, so
541
- // enforce the UUID shape here instead of failing at query time.
542
- sessionId: import_zod.z.string().refine(
543
- (val) => /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(val),
544
- { message: "sessionId must be a valid UUID (the CLI rejects non-UUID session IDs)" }
545
- ).optional(),
546
- allowedTools: import_zod.z.array(import_zod.z.string()).optional(),
547
- disallowedTools: import_zod.z.array(import_zod.z.string()).optional(),
548
- betas: import_zod.z.array(import_zod.z.string()).optional(),
549
- allowDangerouslySkipPermissions: import_zod.z.boolean().optional(),
550
- enableFileCheckpointing: import_zod.z.boolean().optional(),
551
- maxBudgetUsd: import_zod.z.number().min(0).optional(),
552
- plugins: import_zod.z.array(
553
- import_zod.z.object({
554
- // SDK SdkPluginConfig: only 'local' is supported; the SDK throws
555
- // 'Unsupported plugin type' at query time for anything else.
556
- type: import_zod.z.literal("local"),
557
- path: import_zod.z.string()
558
- }).passthrough()
559
- ).optional(),
560
- resumeSessionAt: import_zod.z.string().optional(),
561
- sandbox: import_zod.z.any().refine((val) => val === void 0 || typeof val === "object", {
562
- message: "sandbox must be an object"
563
- }).optional(),
564
- tools: import_zod.z.union([
565
- import_zod.z.array(import_zod.z.string()),
566
- import_zod.z.object({
567
- type: import_zod.z.literal("preset"),
568
- preset: import_zod.z.literal("claude_code")
569
- })
570
- ]).optional(),
571
- skills: import_zod.z.union([import_zod.z.array(import_zod.z.string()), import_zod.z.literal("all")]).optional(),
572
- settings: import_zod.z.union([
573
- import_zod.z.string(),
574
- import_zod.z.record(import_zod.z.string(), import_zod.z.any())
575
- // inline Settings object
576
- ]).optional(),
577
- managedSettings: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional(),
578
- toolAliases: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional(),
579
- toolConfig: import_zod.z.object({
580
- askUserQuestion: import_zod.z.object({
581
- previewFormat: import_zod.z.enum(["markdown", "html"]).optional()
582
- }).passthrough().optional()
583
- }).passthrough().optional(),
584
- planModeInstructions: import_zod.z.string().optional(),
585
- title: import_zod.z.string().optional(),
586
- forwardSubagentText: import_zod.z.boolean().optional(),
587
- agentProgressSummaries: import_zod.z.boolean().optional(),
588
- includeHookEvents: import_zod.z.boolean().optional(),
589
- taskBudget: import_zod.z.object({ total: import_zod.z.number().positive() }).strict().optional(),
590
- sessionStore: import_zod.z.any().refine(
591
- (val) => val === void 0 || typeof val === "object" && val !== null && typeof val.append === "function" && typeof val.load === "function",
592
- { message: "sessionStore must be an object with append() and load() functions" }
593
- ).optional(),
594
- sessionStoreFlush: import_zod.z.enum(["batched", "eager"]).optional(),
595
- loadTimeoutMs: import_zod.z.number().int().positive().optional(),
596
- settingSources: import_zod.z.array(import_zod.z.enum(["user", "project", "local"])).optional(),
597
- streamingInput: import_zod.z.enum(["auto", "always", "off"]).optional(),
598
- // Hooks and tool-permission callback (permissive validation of shapes)
599
- canUseTool: import_zod.z.any().refine((v) => v === void 0 || typeof v === "function", {
600
- message: "canUseTool must be a function"
601
- }).optional(),
602
- onUserDialog: import_zod.z.any().refine((v) => v === void 0 || typeof v === "function", {
603
- message: "onUserDialog must be a function"
604
- }).optional(),
605
- supportedDialogKinds: import_zod.z.array(import_zod.z.string()).optional(),
606
- hooks: import_zod.z.record(
607
- import_zod.z.string(),
608
- import_zod.z.array(
609
- import_zod.z.object({
610
- matcher: import_zod.z.string().optional(),
611
- hooks: import_zod.z.array(import_zod.z.any()).nonempty()
612
- })
613
- )
614
- ).optional(),
615
- mcpServers: import_zod.z.record(
616
- import_zod.z.string(),
617
- import_zod.z.union([
618
- // McpStdioServerConfig
619
- import_zod.z.object({
620
- type: import_zod.z.literal("stdio").optional(),
621
- command: import_zod.z.string(),
622
- args: import_zod.z.array(import_zod.z.string()).optional(),
623
- env: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional()
624
- }),
625
- // McpSSEServerConfig
626
- import_zod.z.object({
627
- type: import_zod.z.literal("sse"),
628
- url: import_zod.z.string(),
629
- headers: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional()
630
- }),
631
- // McpHttpServerConfig
632
- import_zod.z.object({
633
- type: import_zod.z.literal("http"),
634
- url: import_zod.z.string(),
635
- headers: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional()
636
- }),
637
- // McpSdkServerConfig (in-process custom tools)
638
- import_zod.z.object({
639
- type: import_zod.z.literal("sdk"),
640
- name: import_zod.z.string(),
641
- instance: import_zod.z.any()
642
- })
643
- ])
644
- ).optional(),
645
- verbose: import_zod.z.boolean().optional(),
646
- debug: import_zod.z.boolean().optional(),
647
- debugFile: import_zod.z.string().optional(),
648
- logger: import_zod.z.union([import_zod.z.literal(false), loggerFunctionSchema]).optional(),
649
- env: import_zod.z.record(import_zod.z.string(), import_zod.z.string().optional()).optional(),
650
- additionalDirectories: import_zod.z.array(import_zod.z.string()).optional(),
651
- agents: import_zod.z.record(
652
- import_zod.z.string(),
653
- import_zod.z.object({
654
- description: import_zod.z.string(),
655
- tools: import_zod.z.array(import_zod.z.string()).optional(),
656
- disallowedTools: import_zod.z.array(import_zod.z.string()).optional(),
657
- prompt: import_zod.z.string(),
658
- // SDK 0.3.x AgentDefinition accepts any model alias or full model ID
659
- model: import_zod.z.string().optional(),
660
- mcpServers: import_zod.z.array(
661
- import_zod.z.union([
662
- import_zod.z.string(),
663
- import_zod.z.record(import_zod.z.string(), import_zod.z.any())
664
- // McpServerConfigForProcessTransport
665
- ])
666
- ).optional(),
667
- criticalSystemReminder_EXPERIMENTAL: import_zod.z.string().optional()
668
- }).passthrough()
669
- ).optional(),
670
- includePartialMessages: import_zod.z.boolean().optional(),
671
- fallbackModel: import_zod.z.string().optional(),
672
- forkSession: import_zod.z.boolean().optional(),
673
- stderr: import_zod.z.any().refine((val) => val === void 0 || typeof val === "function", {
674
- message: "stderr must be a function"
675
- }).optional(),
676
- strictMcpConfig: import_zod.z.boolean().optional(),
677
- extraArgs: import_zod.z.record(import_zod.z.string(), import_zod.z.union([import_zod.z.string(), import_zod.z.null()])).optional(),
678
- persistSession: import_zod.z.boolean().optional(),
679
- spawnClaudeCodeProcess: import_zod.z.any().refine((val) => val === void 0 || typeof val === "function", {
680
- message: "spawnClaudeCodeProcess must be a function"
681
- }).optional(),
682
- sdkOptions: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional(),
683
- maxToolResultSize: import_zod.z.number().int().min(100).max(1e6).optional(),
684
- // Callback invoked when Query object is created - for mid-stream injection via streamInput()
685
- onQueryCreated: import_zod.z.any().refine((val) => val === void 0 || typeof val === "function", {
686
- message: "onQueryCreated must be a function"
687
- }).optional(),
688
- onStreamStart: import_zod.z.any().refine((val) => val === void 0 || typeof val === "function", {
689
- message: "onStreamStart must be a function"
690
- }).optional(),
691
- // Callback invoked with the predicted next user prompt (active unless promptSuggestions: false)
692
- onPromptSuggestion: import_zod.z.any().refine((val) => val === void 0 || typeof val === "function", {
693
- message: "onPromptSuggestion must be a function"
694
- }).optional()
695
- }).strict();
696
- function validateModelId(modelId) {
697
- const knownModels = ["opus", "sonnet", "haiku", "fable"];
698
- if (!modelId || modelId.trim() === "") {
699
- throw new Error("Model ID cannot be empty");
700
- }
701
- if (!knownModels.includes(modelId)) {
702
- return `Unknown model ID: '${modelId}'. Proceeding with custom model. Known models are: ${knownModels.join(", ")}`;
703
- }
704
- return void 0;
705
- }
706
- function validateSettings(settings) {
707
- const warnings = [];
708
- const errors = [];
709
- try {
710
- const result = claudeCodeSettingsSchema.safeParse(settings);
711
- if (!result.success) {
712
- const errorObject = result.error;
713
- const issues = errorObject.errors || errorObject.issues || [];
714
- issues.forEach((err) => {
715
- const path = err.path.join(".");
716
- errors.push(`${path ? `${path}: ` : ""}${err.message}`);
717
- });
718
- return { valid: false, warnings, errors };
719
- }
720
- const validSettings = result.data;
721
- const sdkOptionsRecord = validSettings.sdkOptions;
722
- const effective = (key) => {
723
- const override = sdkOptionsRecord?.[key];
724
- return override !== void 0 ? override : validSettings[key];
725
- };
726
- const effSessionStore = effective("sessionStore");
727
- const effectiveResumeId = () => {
728
- for (const candidate of [sdkOptionsRecord?.resume, validSettings.resume]) {
729
- if (typeof candidate === "string" && !isBlankResume(candidate)) {
730
- return candidate;
731
- }
732
- }
733
- return void 0;
734
- };
735
- if (effSessionStore !== void 0 && effective("persistSession") === false) {
736
- errors.push(
737
- "sessionStore cannot be combined with persistSession: false. Transcript mirroring requires local session writes; remove persistSession: false or drop sessionStore."
738
- );
739
- return { valid: false, warnings, errors };
740
- }
741
- if (effSessionStore !== void 0 && effective("enableFileCheckpointing") === true) {
742
- errors.push(
743
- "sessionStore cannot be combined with enableFileCheckpointing: true. Checkpoint backup blobs are not mirrored to the store (rewindFiles() fails after a store-backed resume); remove enableFileCheckpointing or drop sessionStore."
744
- );
745
- return { valid: false, warnings, errors };
746
- }
747
- if (effective("continue") === true && effSessionStore !== void 0 && effectiveResumeId() === void 0 && typeof effSessionStore.listSessions !== "function") {
748
- errors.push(
749
- "continue: true with sessionStore requires the store to implement listSessions() (used to discover the most recent session). Implement listSessions(), pass resume with an explicit session ID, or drop continue."
750
- );
751
- return { valid: false, warnings, errors };
752
- }
753
- const effSettingsOption = effective("settings");
754
- if (effective("sandbox") !== void 0 && typeof effSettingsOption === "string" && !(effSettingsOption.trim().startsWith("{") && effSettingsOption.trim().endsWith("}"))) {
755
- errors.push(
756
- "sandbox cannot be combined with a settings file path. Pass settings as an inline Settings object, or move the sandbox configuration into the settings file and drop the sandbox option."
757
- );
758
- return { valid: false, warnings, errors };
759
- }
760
- if (effective("sessionId") !== void 0 && effective("forkSession") !== true && (effective("continue") === true || effectiveResumeId() !== void 0)) {
761
- errors.push(
762
- "sessionId cannot be combined with continue or resume unless forkSession: true is also set (it then names the forked session's ID). Remove sessionId, remove continue/resume, or add forkSession: true."
763
- );
764
- return { valid: false, warnings, errors };
765
- }
766
- if (validSettings.maxTurns && validSettings.maxTurns > 20) {
767
- warnings.push(
768
- `High maxTurns value (${validSettings.maxTurns}) may lead to long-running conversations`
769
- );
770
- }
771
- if (validSettings.maxThinkingTokens && validSettings.maxThinkingTokens > 5e4) {
772
- warnings.push(
773
- `Very high maxThinkingTokens (${validSettings.maxThinkingTokens}) may increase response time`
774
- );
775
- }
776
- if (validSettings.allowedTools && validSettings.disallowedTools) {
777
- warnings.push(
778
- "Both allowedTools and disallowedTools are specified. Only allowedTools will be used."
779
- );
780
- }
781
- const validateToolNames = (tools, type) => {
782
- tools.forEach((tool3) => {
783
- if (!/^[a-zA-Z_][a-zA-Z0-9_]*(\([^)]*\))?$/.test(tool3) && !tool3.startsWith("mcp__")) {
784
- warnings.push(`Unusual ${type} tool name format: '${tool3}'`);
785
- }
786
- });
787
- };
788
- if (validSettings.allowedTools) {
789
- validateToolNames(validSettings.allowedTools, "allowed");
790
- }
791
- if (validSettings.disallowedTools) {
792
- validateToolNames(validSettings.disallowedTools, "disallowed");
793
- }
794
- const effDialogKinds = effective("supportedDialogKinds");
795
- if (Array.isArray(effDialogKinds) && effDialogKinds.length > 0 && effective("onUserDialog") == null) {
796
- errors.push(
797
- "supportedDialogKinds is set without onUserDialog. The SDK requires the onUserDialog callback to render declared dialog kinds and throws when a non-empty list is passed without it; provide onUserDialog or remove supportedDialogKinds."
798
- );
799
- return { valid: false, warnings, errors };
800
- }
801
- const effAllowedTools = effective("allowedTools");
802
- if (Array.isArray(effAllowedTools) && effAllowedTools.includes("Skill") && !effective("settingSources")) {
803
- warnings.push(
804
- "allowedTools includes 'Skill' but settingSources is not set. Skills require settingSources (e.g., ['user', 'project']) to load skill definitions."
805
- );
806
- }
807
- if (validSettings.agents) {
808
- const knownAgentModelAliases = ["sonnet", "opus", "haiku", "fable", "inherit"];
809
- for (const [agentName, agent] of Object.entries(validSettings.agents)) {
810
- const agentModel = agent.model;
811
- if (agentModel !== void 0 && !knownAgentModelAliases.includes(agentModel) && !agentModel.includes("-")) {
812
- warnings.push(
813
- `Unknown model alias '${agentModel}' for agent '${agentName}'. Known aliases are: ${knownAgentModelAliases.join(", ")}; full model IDs (e.g. 'claude-sonnet-4-5') are also accepted.`
814
- );
815
- }
816
- }
817
- }
818
- return { valid: true, warnings, errors };
819
- } catch (error) {
820
- errors.push(`Validation error: ${error instanceof Error ? error.message : String(error)}`);
821
- return { valid: false, warnings, errors };
822
- }
823
- }
824
- function validatePrompt(prompt) {
825
- const MAX_PROMPT_LENGTH = 1e5;
826
- if (prompt.length > MAX_PROMPT_LENGTH) {
827
- return `Very long prompt (${prompt.length} characters) may cause performance issues or timeouts`;
828
- }
829
- return void 0;
830
- }
831
- function validateSessionId(sessionId) {
832
- if (sessionId && !/^[a-zA-Z0-9-_]+$/.test(sessionId)) {
833
- return `Unusual session ID format. This may cause issues with session resumption.`;
834
- }
835
- return void 0;
836
- }
837
-
838
- // src/sanitize-json-schema.ts
839
- var SUBSCHEMA_MAP_KEYWORDS = [
840
- "properties",
841
- "patternProperties",
842
- "$defs",
843
- "definitions",
844
- "dependentSchemas",
845
- // draft-07 `dependencies` values are either subschemas (schema form) or
846
- // arrays of property-name strings (array form); sanitizeNode passes
847
- // string arrays through untouched, so walking both forms is safe.
848
- "dependencies"
849
- ];
850
- var SUBSCHEMA_KEYWORDS = [
851
- "items",
852
- // may also be an array of subschemas (draft-07 tuple form)
853
- "additionalItems",
854
- "additionalProperties",
855
- "unevaluatedItems",
856
- "unevaluatedProperties",
857
- "not",
858
- "contains",
859
- "propertyNames",
860
- "contentSchema",
861
- "if",
862
- "then",
863
- "else"
864
- ];
865
- var SUBSCHEMA_LIST_KEYWORDS = ["prefixItems", "anyOf", "oneOf", "allOf"];
866
- function sanitizeJsonSchemaForOutputFormat(schema) {
867
- const strippedFormatPaths = [];
868
- const sanitized = sanitizeNode(schema, "#", /* @__PURE__ */ new WeakSet(), strippedFormatPaths);
869
- return {
870
- schema: sanitized ?? schema,
871
- strippedFormatPaths
872
- };
873
- }
874
- function sanitizeNode(node, path, visiting, strippedFormatPaths) {
875
- if (typeof node !== "object" || node === null) {
876
- return node;
877
- }
878
- if (visiting.has(node)) {
879
- return node;
880
- }
881
- visiting.add(node);
882
- try {
883
- if (Array.isArray(node)) {
884
- return sanitizeList(node, path, visiting, strippedFormatPaths);
885
- }
886
- const record = node;
887
- let result = record;
888
- const setKey = (key, value) => {
889
- if (result === record) {
890
- result = { ...record };
891
- }
892
- result[key] = value;
893
- };
894
- if (typeof record.format === "string") {
895
- const format = record.format;
896
- const existingDescription = record.description;
897
- result = { ...record };
898
- delete result.format;
899
- if (typeof existingDescription === "string" && existingDescription.length > 0) {
900
- result.description = `${existingDescription} (expected format: ${format})`;
901
- } else if (existingDescription === void 0 || existingDescription === "") {
902
- result.description = `Expected format: ${format}`;
903
- }
904
- strippedFormatPaths.push(path);
905
- }
906
- for (const keyword of SUBSCHEMA_MAP_KEYWORDS) {
907
- const map = record[keyword];
908
- if (typeof map !== "object" || map === null || Array.isArray(map)) continue;
909
- const mapRecord = map;
910
- let newMap = mapRecord;
911
- for (const [name, child] of Object.entries(mapRecord)) {
912
- const sanitizedChild = sanitizeNode(
913
- child,
914
- `${path}/${keyword}/${name}`,
915
- visiting,
916
- strippedFormatPaths
917
- );
918
- if (sanitizedChild !== child) {
919
- if (newMap === mapRecord) {
920
- newMap = { ...mapRecord };
921
- }
922
- newMap[name] = sanitizedChild;
923
- }
924
- }
925
- if (newMap !== mapRecord) {
926
- setKey(keyword, newMap);
927
- }
928
- }
929
- for (const keyword of SUBSCHEMA_KEYWORDS) {
930
- const child = record[keyword];
931
- if (typeof child !== "object" || child === null) continue;
932
- const sanitizedChild = sanitizeNode(
933
- child,
934
- `${path}/${keyword}`,
935
- visiting,
936
- strippedFormatPaths
937
- );
938
- if (sanitizedChild !== child) {
939
- setKey(keyword, sanitizedChild);
940
- }
941
- }
942
- for (const keyword of SUBSCHEMA_LIST_KEYWORDS) {
943
- const list = record[keyword];
944
- if (!Array.isArray(list)) continue;
945
- const sanitizedList = sanitizeList(list, `${path}/${keyword}`, visiting, strippedFormatPaths);
946
- if (sanitizedList !== list) {
947
- setKey(keyword, sanitizedList);
948
- }
949
- }
950
- return result;
951
- } finally {
952
- visiting.delete(node);
953
- }
954
- }
955
- function sanitizeList(list, path, visiting, strippedFormatPaths) {
956
- let result = list;
957
- for (let i = 0; i < list.length; i++) {
958
- const sanitizedChild = sanitizeNode(list[i], `${path}/${i}`, visiting, strippedFormatPaths);
959
- if (sanitizedChild !== list[i]) {
960
- if (result === list) {
961
- result = [...list];
962
- }
963
- result[i] = sanitizedChild;
964
- }
965
- }
966
- return result;
967
- }
968
-
969
- // src/logger.ts
970
- var defaultLogger = {
971
- // eslint-disable-next-line no-console
972
- debug: (message) => console.debug(`[DEBUG] ${message}`),
973
- // eslint-disable-next-line no-console
974
- info: (message) => console.info(`[INFO] ${message}`),
975
- warn: (message) => console.warn(`[WARN] ${message}`),
976
- error: (message) => console.error(`[ERROR] ${message}`)
977
- };
978
- var noopLogger = {
979
- debug: () => {
980
- },
981
- info: () => {
982
- },
983
- warn: () => {
984
- },
985
- error: () => {
986
- }
987
- };
988
- function getLogger(logger) {
989
- if (logger === false) {
990
- return noopLogger;
991
- }
992
- if (logger === void 0) {
993
- return defaultLogger;
994
- }
995
- return logger;
996
- }
997
- function createVerboseLogger(logger, verbose = false) {
998
- if (verbose) {
999
- return logger;
1000
- }
1001
- return {
1002
- debug: () => {
1003
- },
1004
- // No-op when not verbose
1005
- info: () => {
1006
- },
1007
- // No-op when not verbose
1008
- warn: logger.warn.bind(logger),
1009
- error: logger.error.bind(logger)
1010
- };
1011
- }
1012
-
1013
- // src/claude-code-language-model.ts
1014
- var import_claude_agent_sdk = require("@anthropic-ai/claude-agent-sdk");
1015
- var PROVIDER_VERSION = "3.5.2";
1016
- var DEFAULT_CLIENT_APP = `ai-sdk-provider-claude-code/${PROVIDER_VERSION}`;
1017
- var CLAUDE_CODE_TRUNCATION_WARNING = "Claude Code SDK output ended unexpectedly; returning truncated response from buffered text. Await upstream fix to avoid data loss.";
1018
- var MIN_TRUNCATION_LENGTH = 512;
1019
- function isClaudeCodeTruncationError(error, bufferedText) {
1020
- const isSyntaxError = error instanceof SyntaxError || // eslint-disable-next-line @typescript-eslint/no-explicit-any
1021
- typeof error?.name === "string" && // eslint-disable-next-line @typescript-eslint/no-explicit-any
1022
- error.name.toLowerCase() === "syntaxerror";
1023
- if (!isSyntaxError) {
1024
- return false;
1025
- }
1026
- if (!bufferedText) {
1027
- return false;
1028
- }
1029
- const rawMessage = typeof error?.message === "string" ? error.message : "";
1030
- const message = rawMessage.toLowerCase();
1031
- const truncationIndicators = [
1032
- "unexpected end of json input",
1033
- "unexpected end of input",
1034
- "unexpected end of string",
1035
- "unexpected eof",
1036
- "end of file",
1037
- "unterminated string",
1038
- "unterminated string constant"
1039
- ];
1040
- if (!truncationIndicators.some((indicator) => message.includes(indicator))) {
1041
- return false;
1042
- }
1043
- if (bufferedText.length < MIN_TRUNCATION_LENGTH) {
1044
- return false;
1045
- }
1046
- return true;
1047
- }
1048
- var MISSING_STRUCTURED_OUTPUT_ERROR_MESSAGE = "Structured output was requested (responseFormat with a JSON schema) but the Claude Code CLI returned no structured_output, and the prose response could not be parsed as JSON. This usually means the schema contains constructs the CLI cannot enforce (e.g. complex regex patterns with lookaheads/backreferences), causing it to silently fall back to prose. Simplify the generation schema and validate strictly client-side. See the 'Structured Outputs' section of the ai-sdk-provider-claude-code README for the list of known limitations.";
1049
- function extractJsonObjectText(text) {
1050
- const trimmed = text.trim();
1051
- if (!trimmed) {
1052
- return void 0;
1053
- }
1054
- const candidates = [trimmed];
1055
- const fencedBlocks = Array.from(trimmed.matchAll(/```(?:json)?\s*\n?([\s\S]*?)```/gi)).map((match) => match[1]?.trim()).filter((block) => block !== void 0 && block.length > 0);
1056
- candidates.push(...fencedBlocks.reverse());
1057
- for (const candidate of candidates) {
1058
- if (!candidate) continue;
1059
- try {
1060
- const parsed = JSON.parse(candidate);
1061
- if (typeof parsed === "object" && parsed !== null) {
1062
- return candidate;
1063
- }
1064
- } catch {
1065
- }
1066
- }
1067
- return void 0;
1068
- }
1069
- function getStructuredErrorKind(error) {
1070
- if (typeof error === "object" && error !== null && "errorKind" in error) {
1071
- const kind = error.errorKind;
1072
- if (typeof kind === "string") return kind;
1073
- }
1074
- return void 0;
1075
- }
1076
- function isAbortError(err) {
1077
- if (err && typeof err === "object") {
1078
- const e = err;
1079
- if (typeof e.name === "string" && e.name === "AbortError") return true;
1080
- if (typeof e.code === "string" && e.code.toUpperCase() === "ABORT_ERR") return true;
1081
- }
1082
- return false;
1083
- }
1084
- var DEFAULT_INHERITED_ENV_VARS = process.platform === "win32" ? [
1085
- "APPDATA",
1086
- "COMSPEC",
1087
- "HOMEDRIVE",
1088
- "HOMEPATH",
1089
- "LOCALAPPDATA",
1090
- "PATH",
1091
- "PATHEXT",
1092
- "SYSTEMDRIVE",
1093
- "SYSTEMROOT",
1094
- "TEMP",
1095
- "TMP",
1096
- "USERNAME",
1097
- "USERPROFILE",
1098
- "WINDIR"
1099
- ] : ["HOME", "LOGNAME", "PATH", "SHELL", "TERM", "USER", "LANG", "LC_ALL", "TMPDIR"];
1100
- var CLAUDE_ENV_VARS = ["CLAUDE_CONFIG_DIR"];
1101
- var NETWORK_ENV_VARS = [
1102
- "HTTP_PROXY",
1103
- "HTTPS_PROXY",
1104
- "NO_PROXY",
1105
- "http_proxy",
1106
- "https_proxy",
1107
- "no_proxy",
1108
- "NODE_EXTRA_CA_CERTS",
1109
- "SSL_CERT_FILE",
1110
- "SSL_CERT_DIR"
1111
- ];
1112
- var CLOUD_ENV_VARS = ["GCLOUD_PROJECT", "CLOUD_ML_REGION"];
1113
- var INHERITED_ENV_PREFIXES = ["ANTHROPIC_", "CLAUDE_", "AWS_", "GOOGLE_"];
1114
- function getBaseProcessEnv() {
1115
- const env = {};
1116
- const allowedKeys = /* @__PURE__ */ new Set([
1117
- ...DEFAULT_INHERITED_ENV_VARS,
1118
- ...CLAUDE_ENV_VARS,
1119
- ...NETWORK_ENV_VARS,
1120
- ...CLOUD_ENV_VARS
1121
- ]);
1122
- const addIfSafe = (key) => {
1123
- const value = process.env[key];
1124
- if (typeof value !== "string") {
1125
- return;
1126
- }
1127
- if (value.startsWith("()")) {
1128
- return;
1129
- }
1130
- env[key] = value;
1131
- };
1132
- for (const key of allowedKeys) {
1133
- addIfSafe(key);
1134
- }
1135
- for (const key of Object.keys(process.env)) {
1136
- if (INHERITED_ENV_PREFIXES.some((prefix) => key.startsWith(prefix))) {
1137
- addIfSafe(key);
1138
- }
1139
- }
1140
- return env;
1141
- }
1142
- 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).";
1143
- var SDK_OPTIONS_BLOCKLIST = /* @__PURE__ */ new Set(["model", "abortController", "prompt", "outputFormat"]);
1144
- var SUBAGENT_TOOL_NAMES = /* @__PURE__ */ new Set(["Task", "Agent"]);
1145
- function isSubagentToolName(name) {
1146
- return SUBAGENT_TOOL_NAMES.has(name);
1147
- }
1148
- function resolveToolParentId(messageLevel, blockLevel, inferFallback) {
1149
- if (messageLevel !== void 0) return messageLevel;
1150
- if (typeof blockLevel === "string") return blockLevel;
1151
- return inferFallback();
1152
- }
1153
- function computeRetractedToolCallIds(retracted, descriptors) {
1154
- const ids = /* @__PURE__ */ new Set();
1155
- for (const { toolCallId, uuid } of descriptors) {
1156
- if (uuid !== void 0 && retracted.has(uuid)) {
1157
- ids.add(toolCallId);
1158
- }
1159
- }
1160
- return ids;
1161
- }
1162
- function applySupersede(message, evict, logger, guard = "array") {
1163
- const supersedes = message.supersedes;
1164
- const triggered = guard === "truthy" ? Boolean(supersedes && supersedes.length > 0) : Array.isArray(supersedes) && supersedes.length > 0;
1165
- if (!triggered) {
1166
- return false;
1167
- }
1168
- logger.debug(`[claude-code] Assistant message supersedes ${supersedes.length} prior message(s)`);
1169
- evict(new Set(supersedes));
1170
- return true;
1171
- }
1172
- function buildRetractionEvictor(evict) {
1173
- return (uuids) => evict(new Set(uuids));
1174
- }
1175
- var INFORMATIONAL_SYSTEM_SUBTYPES = /* @__PURE__ */ new Set([
1176
- "notification",
1177
- "status",
1178
- "task_updated",
1179
- "session_state_changed",
1180
- "commands_changed",
1181
- "memory_recall",
1182
- "plugin_install"
1183
- ]);
1184
- function isContentBlock(item) {
1185
- return typeof item === "object" && item !== null && "type" in item;
1186
- }
1187
- function filterContentBlocks(content, type) {
1188
- if (!Array.isArray(content)) return [];
1189
- const blocks = content.filter(
1190
- (item) => isContentBlock(item) && item.type === type
1191
- );
1192
- const mismatch = blocks.find((b) => b.type !== type);
1193
- if (mismatch) {
1194
- throw new Error(
1195
- `filterContentBlocks: block type '${mismatch.type}' passed filter for '${type}'`
1196
- );
1197
- }
1198
- return blocks;
1199
- }
1200
- function createEmptyUsage() {
1201
- return {
1202
- inputTokens: {
1203
- total: 0,
1204
- noCache: 0,
1205
- cacheRead: 0,
1206
- cacheWrite: 0
1207
- },
1208
- outputTokens: {
1209
- total: 0,
1210
- text: void 0,
1211
- reasoning: void 0
1212
- },
1213
- raw: void 0
1214
- };
1215
- }
1216
- function convertClaudeCodeUsage(usage) {
1217
- const inputTokens = usage.input_tokens ?? 0;
1218
- const outputTokens = usage.output_tokens ?? 0;
1219
- const cacheWrite = usage.cache_creation_input_tokens ?? 0;
1220
- const cacheRead = usage.cache_read_input_tokens ?? 0;
1221
- return {
1222
- inputTokens: {
1223
- total: inputTokens + cacheWrite + cacheRead,
1224
- noCache: inputTokens,
1225
- cacheRead,
1226
- cacheWrite
1227
- },
1228
- outputTokens: {
1229
- total: outputTokens,
1230
- text: void 0,
1231
- reasoning: void 0
1232
- },
1233
- raw: usage
1234
- };
1235
- }
1236
- function createMessageInjector() {
1237
- const queue = [];
1238
- let closed = false;
1239
- let resolver = null;
1240
- const injector = {
1241
- inject(content, onResult) {
1242
- if (closed) {
1243
- onResult?.(false);
1244
- return;
1245
- }
1246
- const item = { content, onResult };
1247
- if (resolver) {
1248
- const r = resolver;
1249
- resolver = null;
1250
- r(item);
1251
- } else {
1252
- queue.push(item);
1253
- }
1254
- },
1255
- close() {
1256
- closed = true;
1257
- if (resolver && queue.length === 0) {
1258
- resolver(null);
1259
- resolver = null;
1260
- }
1261
- }
1262
- };
1263
- const getNextItem = () => {
1264
- if (queue.length > 0) {
1265
- const item = queue.shift();
1266
- if (!item) {
1267
- return Promise.resolve(null);
1268
- }
1269
- return Promise.resolve(item);
1270
- }
1271
- if (closed) {
1272
- return Promise.resolve(null);
1273
- }
1274
- return new Promise((resolve) => {
1275
- resolver = (item) => {
1276
- resolve(item);
1277
- };
1278
- });
1279
- };
1280
- const notifySessionEnded = () => {
1281
- for (const item of queue) {
1282
- item.onResult?.(false);
1283
- }
1284
- queue.length = 0;
1285
- closed = true;
1286
- if (resolver) {
1287
- resolver(null);
1288
- resolver = null;
1289
- }
1290
- };
1291
- return { injector, getNextItem, notifySessionEnded };
1292
- }
1293
- function toAsyncIterablePrompt(messagesPrompt, outputStreamEnded, sessionId, contentParts, onStreamStart) {
1294
- const content = contentParts && contentParts.length > 0 ? contentParts : [{ type: "text", text: messagesPrompt }];
1295
- const initialMsg = {
1296
- type: "user",
1297
- message: {
1298
- role: "user",
1299
- content
1300
- },
1301
- parent_tool_use_id: null,
1302
- session_id: sessionId ?? ""
1303
- };
1304
- if (!onStreamStart) {
1305
- return {
1306
- async *[Symbol.asyncIterator]() {
1307
- yield initialMsg;
1308
- await outputStreamEnded;
1309
- }
1310
- };
1311
- }
1312
- const { injector, getNextItem, notifySessionEnded } = createMessageInjector();
1313
- return {
1314
- async *[Symbol.asyncIterator]() {
1315
- yield initialMsg;
1316
- onStreamStart(injector);
1317
- let streamEnded = false;
1318
- void outputStreamEnded.then(() => {
1319
- streamEnded = true;
1320
- notifySessionEnded();
1321
- });
1322
- while (!streamEnded) {
1323
- const item = await Promise.race([getNextItem(), outputStreamEnded.then(() => null)]);
1324
- if (item === null) {
1325
- await outputStreamEnded;
1326
- break;
1327
- }
1328
- const sdkMsg = {
1329
- type: "user",
1330
- message: {
1331
- role: "user",
1332
- content: [{ type: "text", text: item.content }]
1333
- },
1334
- parent_tool_use_id: null,
1335
- session_id: sessionId ?? ""
1336
- };
1337
- yield sdkMsg;
1338
- item.onResult?.(true);
1339
- }
1340
- }
1341
- };
1342
- }
1343
- var modelMap = {
1344
- opus: "opus",
1345
- sonnet: "sonnet",
1346
- haiku: "haiku"
1347
- };
1348
- var MAX_TOOL_RESULT_SIZE = 1e4;
1349
- function truncateToolResultForStream(result, maxSize = MAX_TOOL_RESULT_SIZE) {
1350
- if (typeof result === "string") {
1351
- if (result.length <= maxSize) return result;
1352
- return result.slice(0, maxSize) + `
1353
- ...[truncated ${result.length - maxSize} chars]`;
1354
- }
1355
- if (typeof result !== "object" || result === null) return result;
1356
- if (Array.isArray(result)) {
1357
- let largestIndex = -1;
1358
- let largestSize2 = 0;
1359
- for (let i = 0; i < result.length; i++) {
1360
- const value = result[i];
1361
- if (typeof value === "string" && value.length > largestSize2) {
1362
- largestIndex = i;
1363
- largestSize2 = value.length;
1364
- }
1365
- }
1366
- if (largestIndex >= 0 && largestSize2 > maxSize) {
1367
- const truncatedValue = result[largestIndex].slice(0, maxSize) + `
1368
- ...[truncated ${largestSize2 - maxSize} chars]`;
1369
- const cloned = [...result];
1370
- cloned[largestIndex] = truncatedValue;
1371
- return cloned;
1372
- }
1373
- return result;
1374
- }
1375
- const obj = result;
1376
- let largestKey = null;
1377
- let largestSize = 0;
1378
- for (const [key, value] of Object.entries(obj)) {
1379
- if (typeof value === "string" && value.length > largestSize) {
1380
- largestKey = key;
1381
- largestSize = value.length;
1382
- }
1383
- }
1384
- if (largestKey && largestSize > maxSize) {
1385
- const truncatedValue = obj[largestKey].slice(0, maxSize) + `
1386
- ...[truncated ${largestSize - maxSize} chars]`;
1387
- return { ...obj, [largestKey]: truncatedValue };
1388
- }
1389
- return result;
1390
- }
1391
- var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
1392
- specificationVersion = "v3";
1393
- defaultObjectGenerationMode = "json";
1394
- supportsImageUrls = false;
1395
- supportedUrls = {};
1396
- supportsStructuredOutputs = true;
1397
- // Fallback/magic string constants
1398
- static UNKNOWN_TOOL_NAME = "unknown-tool";
1399
- // Tool input safety limits
1400
- static MAX_TOOL_INPUT_SIZE = 1048576;
1401
- // 1MB hard limit
1402
- static MAX_TOOL_INPUT_WARN = 102400;
1403
- // 100KB warning threshold
1404
- static MAX_DELTA_CALC_SIZE = 1e4;
1405
- // 10KB delta computation threshold
1406
- // Upper bound for draining post-result messages (prompt_suggestion) so a
1407
- // lingering CLI subprocess cannot be held open indefinitely after finish.
1408
- static PROMPT_SUGGESTION_DRAIN_TIMEOUT_MS = 1e4;
1409
- modelId;
1410
- settings;
1411
- sessionId;
1412
- modelValidationWarning;
1413
- settingsValidationWarnings;
1414
- logger;
1415
- constructor(options) {
1416
- this.modelId = options.id;
1417
- this.settings = options.settings ?? {};
1418
- this.settingsValidationWarnings = options.settingsValidationWarnings ?? [];
1419
- const baseLogger = getLogger(this.settings.logger);
1420
- this.logger = createVerboseLogger(baseLogger, this.settings.verbose ?? false);
1421
- if (!this.modelId || typeof this.modelId !== "string" || this.modelId.trim() === "") {
1422
- throw new import_provider2.NoSuchModelError({
1423
- modelId: this.modelId,
1424
- modelType: "languageModel"
1425
- });
1426
- }
1427
- this.modelValidationWarning = validateModelId(this.modelId);
1428
- if (this.modelValidationWarning) {
1429
- this.logger.warn(`Claude Code Model: ${this.modelValidationWarning}`);
1430
- }
1431
- }
1432
- get provider() {
1433
- return "claude-code";
1434
- }
1435
- getModel() {
1436
- const mapped = modelMap[this.modelId];
1437
- return mapped ?? this.modelId;
1438
- }
1439
- getSanitizedSdkOptions() {
1440
- if (!this.settings.sdkOptions || typeof this.settings.sdkOptions !== "object") {
1441
- return void 0;
1442
- }
1443
- const sanitized = { ...this.settings.sdkOptions };
1444
- const blockedKeys = Array.from(SDK_OPTIONS_BLOCKLIST).filter((key) => key in sanitized);
1445
- if (blockedKeys.length > 0) {
1446
- this.logger.warn(
1447
- `[claude-code] sdkOptions includes provider-managed fields (${blockedKeys.join(
1448
- ", "
1449
- )}); these will be ignored.`
1450
- );
1451
- blockedKeys.forEach((key) => delete sanitized[key]);
1452
- }
1453
- return sanitized;
1454
- }
1455
- getEffectiveResume(sdkOptions) {
1456
- for (const candidate of [sdkOptions?.resume, this.settings.resume, this.sessionId]) {
1457
- if (typeof candidate === "string" && !isBlankResume(candidate)) {
1458
- return candidate;
1459
- }
1460
- }
1461
- return void 0;
1462
- }
1463
- /**
1464
- * Single source of truth for the CLI's `--session-id` exclusivity rule.
1465
- *
1466
- * The CLI rejects `--session-id` together with `--resume`/`--continue`
1467
- * unless `--fork-session` is also set (forkSession then names the forked
1468
- * session's own ID). This predicate captures "there IS a resume/continue
1469
- * target AND we are not forking", i.e. the case where a session id must NOT
1470
- * coexist. It is referenced by both:
1471
- * - the pre-merge forwarding guard (via its inverse), which decides whether
1472
- * to forward `settings.sessionId` onto the base options, and
1473
- * - the post-merge exclusivity drop, which removes any session id that the
1474
- * generic sdkOptions overlay (or the auto-resume turn) re-introduced.
1475
- *
1476
- * Keeping one definition guarantees both sites agree on what "conflicts with
1477
- * a session id" means. The mirror in validation.ts (construction-time)
1478
- * intentionally stays separate: it reads settings+sdkOptions, not a built
1479
- * opts object.
1480
- */
1481
- static sessionIdConflictsWithResumeOrContinue(args) {
1482
- return (args.resumePresent || args.continue) && !args.forkSession;
1483
- }
1484
- /**
1485
- * Owns ALL session-id / resume cross-option resolution on the FINAL merged
1486
- * options, in the single correct order. Called once, immediately after the
1487
- * generic sdkOptions overlay in createQueryOptions.
1488
- *
1489
- * Two concerns, in this exact order (order matters: step 1 can change whether
1490
- * step 2 sees a resume target):
1491
- *
1492
- * 1. Blank-resume restoration. The overlay copies the raw `sdkOptions.resume`
1493
- * verbatim, which can re-introduce a blank/whitespace value over the
1494
- * base `resume` that getEffectiveResume already normalized. The SDK treats
1495
- * a blank resume as absent, so a blank must NOT clobber the computed
1496
- * fallback — restore `effectiveResume` (already blank-stripped; may itself
1497
- * be undefined for a genuinely new session) rather than leaving '' or
1498
- * forcing undefined, which would erase a real settings.resume / captured
1499
- * session id.
1500
- *
1501
- * 2. Session-id exclusivity. Drop `opts.sessionId` whenever it conflicts with
1502
- * a resume/continue target (see sessionIdConflictsWithResumeOrContinue).
1503
- * This runs on the merged opts so it catches a sessionId re-added by the
1504
- * sdkOptions overlay AND the auto-resumed second turn (where resume was
1505
- * populated from the captured session id). It complements — does not
1506
- * replace — the pre-merge forwarding guard, which governs whether
1507
- * settings.sessionId was forwarded BEFORE the overlay could mutate
1508
- * forkSession/continue/resume.
1509
- */
1510
- applySessionResolution(opts, effectiveResume) {
1511
- if (isBlankResume(opts.resume)) {
1512
- opts.resume = effectiveResume;
1513
- }
1514
- if (opts.sessionId !== void 0 && _ClaudeCodeLanguageModel.sessionIdConflictsWithResumeOrContinue({
1515
- resumePresent: opts.resume !== void 0,
1516
- continue: opts.continue === true,
1517
- forkSession: opts.forkSession === true
1518
- })) {
1519
- opts.sessionId = void 0;
1520
- }
1521
- }
1522
- extractToolUses(content) {
1523
- return filterContentBlocks(content, "tool_use").map((block) => {
1524
- const { id, name, input, parent_tool_use_id } = block;
1525
- return {
1526
- id: typeof id === "string" && id.length > 0 ? id : (0, import_provider_utils.generateId)(),
1527
- name: typeof name === "string" && name.length > 0 ? name : _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME,
1528
- input,
1529
- parentToolUseId: typeof parent_tool_use_id === "string" ? parent_tool_use_id : null
1530
- };
1531
- });
1532
- }
1533
- extractToolResults(content) {
1534
- return filterContentBlocks(content, "tool_result").map((block) => {
1535
- const { tool_use_id, content: content2, is_error, name } = block;
1536
- return {
1537
- id: typeof tool_use_id === "string" && tool_use_id.length > 0 ? tool_use_id : (0, import_provider_utils.generateId)(),
1538
- name: typeof name === "string" && name.length > 0 ? name : void 0,
1539
- result: content2,
1540
- isError: Boolean(is_error)
1541
- };
1542
- });
1543
- }
1544
- extractToolErrors(content) {
1545
- return filterContentBlocks(content, "tool_error").map((block) => {
1546
- const { tool_use_id, error, name } = block;
1547
- return {
1548
- id: typeof tool_use_id === "string" && tool_use_id.length > 0 ? tool_use_id : (0, import_provider_utils.generateId)(),
1549
- name: typeof name === "string" && name.length > 0 ? name : void 0,
1550
- error
1551
- };
1552
- });
1553
- }
1554
- serializeToolInput(input) {
1555
- if (typeof input === "string") {
1556
- return this.checkInputSize(input);
1557
- }
1558
- if (input === void 0) {
1559
- return "";
1560
- }
1561
- try {
1562
- const serialized = JSON.stringify(input);
1563
- return this.checkInputSize(serialized);
1564
- } catch {
1565
- const fallback = String(input);
1566
- return this.checkInputSize(fallback);
1567
- }
1568
- }
1569
- checkInputSize(str) {
1570
- const length = str.length;
1571
- if (length > _ClaudeCodeLanguageModel.MAX_TOOL_INPUT_SIZE) {
1572
- throw new Error(
1573
- `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.`
1574
- );
1575
- }
1576
- if (length > _ClaudeCodeLanguageModel.MAX_TOOL_INPUT_WARN) {
1577
- this.logger.warn(
1578
- `[claude-code] Large tool input detected: ${length} bytes. Performance may be impacted. Consider chunking or reducing input size.`
1579
- );
1580
- }
1581
- return str;
1582
- }
1583
- normalizeToolResult(result) {
1584
- if (typeof result === "string") {
1585
- try {
1586
- return JSON.parse(result);
1587
- } catch {
1588
- return result;
1589
- }
1590
- }
1591
- if (Array.isArray(result) && result.length > 0) {
1592
- const textBlocks = result.filter(
1593
- (block) => block?.type === "text" && typeof block.text === "string"
1594
- ).map((block) => block.text);
1595
- if (textBlocks.length !== result.length) {
1596
- return result;
1597
- }
1598
- if (textBlocks.length === 1) {
1599
- try {
1600
- return JSON.parse(textBlocks[0]);
1601
- } catch {
1602
- return textBlocks[0];
1603
- }
1604
- }
1605
- const combined = textBlocks.join("\n");
1606
- try {
1607
- return JSON.parse(combined);
1608
- } catch {
1609
- return combined;
1610
- }
1611
- }
1612
- return result;
1613
- }
1614
- /**
1615
- * Builds a provider-executed `tool-call` part from an assistant `tool_use`
1616
- * block. Shared by doGenerate (content part) and doStream (stream part) so
1617
- * the two paths cannot drift in field shape.
1618
- */
1619
- buildToolCallPart(toolCallId, toolName, input, parentToolCallId) {
1620
- return {
1621
- type: "tool-call",
1622
- toolCallId,
1623
- toolName,
1624
- input,
1625
- providerExecuted: true,
1626
- dynamic: true,
1627
- // V3 field: indicates tool is provider-defined (not in user's tools map)
1628
- providerMetadata: {
1629
- "claude-code": {
1630
- // rawInput preserves the original serialized format before AI SDK normalization.
1631
- // Use this if you need the exact string sent to the Claude CLI, which may differ
1632
- // from the `input` field after AI SDK processing.
1633
- rawInput: input,
1634
- parentToolCallId: parentToolCallId ?? null
1635
- }
1636
- }
1637
- };
1638
- }
1639
- /**
1640
- * Builds a provider-executed `tool-result` part from a user-message
1641
- * `tool_result` block, applying normalization and `maxToolResultSize`
1642
- * truncation. Shared by doGenerate and doStream.
1643
- */
1644
- buildToolResultPart(toolCallId, toolName, result, isError, parentToolCallId) {
1645
- const normalizedResult = this.normalizeToolResult(result);
1646
- const rawResult = typeof result === "string" ? result : result === void 0 ? (
1647
- // tool_result blocks may omit `content` entirely; '' keeps both
1648
- // `result` (NonNullable<JSONValue>) and rawResult (JSONValue) valid.
1649
- ""
1650
- ) : (() => {
1651
- try {
1652
- return JSON.stringify(result) ?? String(result);
1653
- } catch {
1654
- return String(result);
1655
- }
1656
- })();
1657
- const maxToolResultSize = this.settings.maxToolResultSize;
1658
- const truncatedResult = truncateToolResultForStream(normalizedResult, maxToolResultSize);
1659
- const truncatedRawResult = truncateToolResultForStream(rawResult, maxToolResultSize);
1660
- const rawResultTruncated = truncatedRawResult !== rawResult;
1661
- return {
1662
- type: "tool-result",
1663
- toolCallId,
1664
- toolName,
1665
- // `?? ''`: absent `content` (undefined) and string results that
1666
- // normalize to JSON null (e.g. the string "null") must not violate the
1667
- // NonNullable<JSONValue> contract of LanguageModelV3ToolResult.result.
1668
- result: truncatedResult ?? "",
1669
- isError,
1670
- providerExecuted: true,
1671
- dynamic: true,
1672
- // V3 field: indicates tool is provider-defined
1673
- providerMetadata: {
1674
- "claude-code": {
1675
- // rawResult preserves the original CLI output string before JSON parsing.
1676
- // Use this when you need the exact string returned by the tool, especially
1677
- // if the `result` field has been parsed/normalized and you need the original format.
1678
- rawResult: truncatedRawResult,
1679
- rawResultTruncated,
1680
- parentToolCallId: parentToolCallId ?? null
1681
- }
1682
- }
1683
- };
1684
- }
1685
- serializeToolError(error) {
1686
- return typeof error === "string" ? error : typeof error === "object" && error !== null ? (() => {
1687
- try {
1688
- return JSON.stringify(error) ?? String(error);
1689
- } catch {
1690
- return String(error);
1691
- }
1692
- })() : String(error);
1693
- }
1694
- /**
1695
- * Builds a provider-executed `tool-error` STREAM part from a user-message
1696
- * `tool_error` block (doStream only; AI SDK core handles tool-error stream
1697
- * parts natively).
1698
- */
1699
- buildToolErrorPart(toolCallId, toolName, error, parentToolCallId) {
1700
- const rawError = this.serializeToolError(error);
1701
- return {
1702
- type: "tool-error",
1703
- toolCallId,
1704
- toolName,
1705
- error: rawError,
1706
- providerExecuted: true,
1707
- dynamic: true,
1708
- // V3 field: indicates tool is provider-defined
1709
- providerMetadata: {
1710
- "claude-code": {
1711
- rawError,
1712
- parentToolCallId: parentToolCallId ?? null
1713
- }
1714
- }
1715
- };
1716
- }
1717
- /**
1718
- * Builds a V3 `tool-result` CONTENT part with `isError: true` from a
1719
- * user-message `tool_error` block (doGenerate only). The V3 content union
1720
- * has no `tool-error` member and AI SDK core's asContent() silently drops
1721
- * unknown content part types, so an extension tool-error part would never
1722
- * reach `generateText` users — an isError tool-result, by contrast,
1723
- * round-trips into a proper tool-error part in steps content.
1724
- */
1725
- buildToolErrorResultPart(toolCallId, toolName, error, parentToolCallId) {
1726
- const rawError = this.serializeToolError(error);
1727
- return {
1728
- type: "tool-result",
1729
- toolCallId,
1730
- toolName,
1731
- result: rawError,
1732
- isError: true,
1733
- providerExecuted: true,
1734
- dynamic: true,
1735
- // V3 field: indicates tool is provider-defined
1736
- providerMetadata: {
1737
- "claude-code": {
1738
- rawError,
1739
- parentToolCallId: parentToolCallId ?? null
1740
- }
1741
- }
1742
- };
1743
- }
1744
- /**
1745
- * Policy (P3): late-frame drop guard, shared by all four tool_result/tool_error
1746
- * sites (doGenerate result+error, doStream result+error). When a frame's tool
1747
- * id is tombstoned (its tool-call was retracted by a supersede/refusal-fallback
1748
- * signal), the frame must be DROPPED rather than re-synthesized into an orphan
1749
- * tool-call. Centralizing the predicate + debug message keeps the four sites in
1750
- * lockstep so a future tombstone change can't be applied to only some of them.
1751
- */
1752
- isRetractedToolFrame(id, tombstone, frameKind) {
1753
- if (!tombstone.has(id)) {
1754
- return false;
1755
- }
1756
- this.logger.debug(
1757
- `[claude-code] Dropping tool ${frameKind} for retracted (superseded) tool ID: ${id}`
1758
- );
1759
- return true;
1760
- }
1761
- generateAllWarnings(options, prompt) {
1762
- const warnings = [];
1763
- const unsupportedParams = [];
1764
- if (options.temperature !== void 0) unsupportedParams.push("temperature");
1765
- if (options.topP !== void 0) unsupportedParams.push("topP");
1766
- if (options.topK !== void 0) unsupportedParams.push("topK");
1767
- if (options.presencePenalty !== void 0) unsupportedParams.push("presencePenalty");
1768
- if (options.frequencyPenalty !== void 0) unsupportedParams.push("frequencyPenalty");
1769
- if (options.stopSequences !== void 0 && options.stopSequences.length > 0)
1770
- unsupportedParams.push("stopSequences");
1771
- if (options.seed !== void 0) unsupportedParams.push("seed");
1772
- if (unsupportedParams.length > 0) {
1773
- for (const param of unsupportedParams) {
1774
- warnings.push({
1775
- type: "unsupported",
1776
- feature: param,
1777
- details: `Claude Code SDK does not support the ${param} parameter. It will be ignored.`
1778
- });
1779
- }
1780
- }
1781
- if (options.tools !== void 0 && options.tools.length > 0) {
1782
- warnings.push({
1783
- type: "unsupported",
1784
- feature: "tools",
1785
- details: "The Claude Code CLI executes its own tools; AI SDK tools cannot be auto-bridged at the provider layer and will be ignored. To expose custom tools to the CLI, build an in-process MCP server with the createAiSdkMcpServer helper (exported by this package) and pass it via the mcpServers setting (plus allowedTools)."
1786
- });
1787
- }
1788
- if (options.toolChoice !== void 0 && options.toolChoice.type !== "auto") {
1789
- warnings.push({
1790
- type: "unsupported",
1791
- feature: "toolChoice",
1792
- details: `Claude Code CLI does not support toolChoice '${options.toolChoice.type}'. Only automatic tool selection is available; the toolChoice parameter will be ignored.`
1793
- });
1794
- }
1795
- if (options.maxOutputTokens !== void 0) {
1796
- warnings.push({
1797
- type: "unsupported",
1798
- feature: "maxOutputTokens",
1799
- details: "Claude Code CLI does not accept an output token cap. The maxOutputTokens parameter will be ignored."
1800
- });
1801
- }
1802
- if (this.modelValidationWarning) {
1803
- warnings.push({
1804
- type: "other",
1805
- message: this.modelValidationWarning
1806
- });
1807
- }
1808
- this.settingsValidationWarnings.forEach((warning) => {
1809
- warnings.push({
1810
- type: "other",
1811
- message: warning
1812
- });
1813
- });
1814
- if (options.responseFormat?.type === "json" && !options.responseFormat.schema) {
1815
- warnings.push({
1816
- type: "unsupported",
1817
- feature: "responseFormat",
1818
- 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."
1819
- });
1820
- }
1821
- const promptWarning = validatePrompt(prompt);
1822
- if (promptWarning) {
1823
- warnings.push({
1824
- type: "other",
1825
- message: promptWarning
1826
- });
1827
- }
1828
- return warnings;
1829
- }
1830
- createQueryOptions(abortController, responseFormat, stderrCollector, sdkOptions, effectiveResume) {
1831
- const opts = {
1832
- model: this.getModel(),
1833
- abortController,
1834
- resume: effectiveResume,
1835
- pathToClaudeCodeExecutable: this.settings.pathToClaudeCodeExecutable,
1836
- maxTurns: this.settings.maxTurns,
1837
- maxThinkingTokens: this.settings.maxThinkingTokens,
1838
- thinking: this.settings.thinking,
1839
- effort: this.settings.effort,
1840
- promptSuggestions: this.settings.promptSuggestions,
1841
- cwd: this.settings.cwd,
1842
- executable: this.settings.executable,
1843
- executableArgs: this.settings.executableArgs,
1844
- permissionMode: this.settings.permissionMode,
1845
- permissionPromptToolName: this.settings.permissionPromptToolName,
1846
- continue: this.settings.continue,
1847
- allowedTools: this.settings.allowedTools,
1848
- disallowedTools: this.settings.disallowedTools,
1849
- betas: this.settings.betas,
1850
- allowDangerouslySkipPermissions: this.settings.allowDangerouslySkipPermissions,
1851
- enableFileCheckpointing: this.settings.enableFileCheckpointing,
1852
- maxBudgetUsd: this.settings.maxBudgetUsd,
1853
- plugins: this.settings.plugins,
1854
- resumeSessionAt: this.settings.resumeSessionAt,
1855
- sandbox: this.settings.sandbox,
1856
- tools: this.settings.tools,
1857
- mcpServers: this.settings.mcpServers,
1858
- canUseTool: this.settings.canUseTool
1859
- };
1860
- if (this.settings.onUserDialog !== void 0) {
1861
- opts.onUserDialog = this.settings.onUserDialog;
1862
- }
1863
- if (this.settings.supportedDialogKinds !== void 0) {
1864
- opts.supportedDialogKinds = this.settings.supportedDialogKinds;
1865
- }
1866
- if (this.settings.systemPrompt !== void 0) {
1867
- opts.systemPrompt = this.settings.systemPrompt;
1868
- } else if (this.settings.customSystemPrompt !== void 0) {
1869
- this.logger.warn(
1870
- "[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? })."
1871
- );
1872
- opts.systemPrompt = this.settings.customSystemPrompt;
1873
- } else if (this.settings.appendSystemPrompt !== void 0) {
1874
- this.logger.warn(
1875
- "[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."
1876
- );
1877
- opts.systemPrompt = {
1878
- type: "preset",
1879
- preset: "claude_code",
1880
- append: this.settings.appendSystemPrompt
1881
- };
1882
- }
1883
- if (this.settings.settingSources !== void 0) {
1884
- opts.settingSources = this.settings.settingSources;
1885
- } else {
1886
- opts.settingSources = [];
1887
- }
1888
- if (this.settings.additionalDirectories !== void 0) {
1889
- opts.additionalDirectories = this.settings.additionalDirectories;
1890
- }
1891
- if (this.settings.agents !== void 0) {
1892
- opts.agents = this.settings.agents;
1893
- }
1894
- if (this.settings.skills !== void 0) {
1895
- opts.skills = this.settings.skills;
1896
- }
1897
- if (this.settings.settings !== void 0) {
1898
- opts.settings = this.settings.settings;
1899
- }
1900
- if (this.settings.managedSettings !== void 0) {
1901
- opts.managedSettings = this.settings.managedSettings;
1902
- }
1903
- if (this.settings.toolAliases !== void 0) {
1904
- opts.toolAliases = this.settings.toolAliases;
1905
- }
1906
- if (this.settings.toolConfig !== void 0) {
1907
- opts.toolConfig = this.settings.toolConfig;
1908
- }
1909
- if (this.settings.planModeInstructions !== void 0) {
1910
- opts.planModeInstructions = this.settings.planModeInstructions;
1911
- }
1912
- if (this.settings.title !== void 0) {
1913
- opts.title = this.settings.title;
1914
- }
1915
- if (this.settings.forwardSubagentText !== void 0) {
1916
- opts.forwardSubagentText = this.settings.forwardSubagentText;
1917
- }
1918
- if (this.settings.agentProgressSummaries !== void 0) {
1919
- opts.agentProgressSummaries = this.settings.agentProgressSummaries;
1920
- }
1921
- if (this.settings.includeHookEvents !== void 0) {
1922
- opts.includeHookEvents = this.settings.includeHookEvents;
1923
- }
1924
- if (this.settings.taskBudget !== void 0) {
1925
- opts.taskBudget = this.settings.taskBudget;
1926
- }
1927
- if (this.settings.sessionStore !== void 0) {
1928
- opts.sessionStore = this.settings.sessionStore;
1929
- }
1930
- if (this.settings.sessionStoreFlush !== void 0) {
1931
- opts.sessionStoreFlush = this.settings.sessionStoreFlush;
1932
- }
1933
- if (this.settings.loadTimeoutMs !== void 0) {
1934
- opts.loadTimeoutMs = this.settings.loadTimeoutMs;
1935
- }
1936
- if (this.settings.includePartialMessages !== void 0) {
1937
- opts.includePartialMessages = this.settings.includePartialMessages;
1938
- }
1939
- if (this.settings.fallbackModel !== void 0) {
1940
- opts.fallbackModel = this.settings.fallbackModel;
1941
- }
1942
- if (this.settings.forkSession !== void 0) {
1943
- opts.forkSession = this.settings.forkSession;
1944
- }
1945
- if (this.settings.strictMcpConfig !== void 0) {
1946
- opts.strictMcpConfig = this.settings.strictMcpConfig;
1947
- }
1948
- if (this.settings.extraArgs !== void 0) {
1949
- opts.extraArgs = this.settings.extraArgs;
1950
- }
1951
- if (this.settings.persistSession !== void 0) {
1952
- opts.persistSession = this.settings.persistSession;
1953
- }
1954
- if (this.settings.spawnClaudeCodeProcess !== void 0) {
1955
- opts.spawnClaudeCodeProcess = this.settings.spawnClaudeCodeProcess;
1956
- }
1957
- if (this.settings.hooks) {
1958
- opts.hooks = this.settings.hooks;
1959
- }
1960
- const effectiveForkSession = sdkOptions?.forkSession ?? this.settings.forkSession;
1961
- const effectiveContinue = sdkOptions?.continue ?? this.settings.continue;
1962
- if (this.settings.sessionId !== void 0 && !_ClaudeCodeLanguageModel.sessionIdConflictsWithResumeOrContinue({
1963
- resumePresent: opts.resume !== void 0,
1964
- continue: effectiveContinue === true,
1965
- forkSession: effectiveForkSession === true
1966
- })) {
1967
- opts.sessionId = this.settings.sessionId;
1968
- }
1969
- if (this.settings.debug !== void 0) {
1970
- opts.debug = this.settings.debug;
1971
- }
1972
- if (this.settings.debugFile !== void 0) {
1973
- opts.debugFile = this.settings.debugFile;
1974
- }
1975
- const sdkOverrides = sdkOptions ? sdkOptions : void 0;
1976
- const sdkEnv = sdkOverrides && typeof sdkOverrides.env === "object" && sdkOverrides.env !== null ? sdkOverrides.env : void 0;
1977
- const sdkStderr = sdkOverrides && typeof sdkOverrides.stderr === "function" ? sdkOverrides.stderr : void 0;
1978
- if (sdkOverrides) {
1979
- const rest = { ...sdkOverrides };
1980
- delete rest.env;
1981
- delete rest.stderr;
1982
- for (const [key, value] of Object.entries(rest)) {
1983
- if (value !== void 0) {
1984
- opts[key] = value;
1985
- }
1986
- }
1987
- }
1988
- this.applySessionResolution(opts, effectiveResume);
1989
- if (typeof opts.fallbackModel === "string" && opts.fallbackModel === opts.model) {
1990
- throw new Error(
1991
- `fallbackModel cannot be the same as the model ('${String(opts.model)}'). Specify a different model for fallbackModel, or remove it.`
1992
- );
1993
- }
1994
- const userStderrCallback = sdkStderr ?? this.settings.stderr;
1995
- if (stderrCollector || userStderrCallback) {
1996
- opts.stderr = (data) => {
1997
- if (stderrCollector) stderrCollector(data);
1998
- if (userStderrCallback) userStderrCallback(data);
1999
- };
2000
- }
2001
- const mergedEnv = {
2002
- ...getBaseProcessEnv(),
2003
- ...this.settings.env,
2004
- ...sdkEnv
2005
- };
2006
- if (!("CLAUDE_AGENT_SDK_CLIENT_APP" in mergedEnv)) {
2007
- mergedEnv.CLAUDE_AGENT_SDK_CLIENT_APP = DEFAULT_CLIENT_APP;
2008
- }
2009
- opts.env = mergedEnv;
2010
- if (responseFormat?.type === "json" && responseFormat.schema) {
2011
- const { schema: sanitizedSchema, strippedFormatPaths } = sanitizeJsonSchemaForOutputFormat(
2012
- responseFormat.schema
2013
- );
2014
- if (strippedFormatPaths.length > 0) {
2015
- this.logger.debug(
2016
- `[claude-code] Stripped unsupported 'format' keywords from outputFormat schema (hints folded into descriptions; client-side Zod validation still enforces them) at: ${strippedFormatPaths.join(", ")}`
2017
- );
2018
- }
2019
- opts.outputFormat = {
2020
- type: "json_schema",
2021
- schema: sanitizedSchema
2022
- };
2023
- }
2024
- return opts;
2025
- }
2026
- handleClaudeCodeError(error, messagesPrompt, collectedStderr) {
2027
- if (isAbortError(error)) {
2028
- throw error;
2029
- }
2030
- if (error instanceof import_provider2.APICallError || error instanceof import_provider2.LoadAPIKeyError) {
2031
- return error;
2032
- }
2033
- const isErrorWithMessage = (err) => {
2034
- return typeof err === "object" && err !== null && "message" in err;
2035
- };
2036
- const isErrorWithCode = (err) => {
2037
- return typeof err === "object" && err !== null;
2038
- };
2039
- const authErrorPatterns = [
2040
- "not logged in",
2041
- "authentication",
2042
- "unauthorized",
2043
- "auth failed",
2044
- "please login",
2045
- "claude login",
2046
- "claude auth login",
2047
- "/login",
2048
- // CLI returns "Please run /login"
2049
- "invalid api key",
2050
- "oauth_org_not_allowed"
2051
- // SDK 0.3.x assistant error kind: OAuth org not permitted
2052
- ];
2053
- const errorMessage = isErrorWithMessage(error) && error.message ? error.message.toLowerCase() : "";
2054
- const errorKind = getStructuredErrorKind(error);
2055
- const exitCode = isErrorWithCode(error) && typeof error.exitCode === "number" ? error.exitCode : void 0;
2056
- const isAuthError = errorKind === "authentication_failed" || errorKind === "oauth_org_not_allowed" || authErrorPatterns.some((pattern) => errorMessage.includes(pattern)) || exitCode === 401;
2057
- if (isAuthError) {
2058
- return createAuthenticationError({
2059
- message: isErrorWithMessage(error) && error.message ? error.message : "Authentication failed. Please ensure Claude Code SDK is properly authenticated."
2060
- });
2061
- }
2062
- const errorCode = isErrorWithCode(error) && typeof error.code === "string" ? error.code : "";
2063
- if (errorCode === "ETIMEDOUT" || errorMessage.includes("timeout")) {
2064
- return createTimeoutError({
2065
- message: isErrorWithMessage(error) && error.message ? error.message : "Request timed out",
2066
- promptExcerpt: messagesPrompt.substring(0, 200)
2067
- // Don't specify timeoutMs since we don't know the actual timeout value
2068
- // It's controlled by the consumer via AbortSignal
2069
- });
2070
- }
2071
- const stderrFromError = isErrorWithCode(error) && typeof error.stderr === "string" ? error.stderr : void 0;
2072
- const stderr = stderrFromError || collectedStderr || void 0;
2073
- if (errorKind === "overloaded" || errorKind === "rate_limit" || errorMessage.includes("overloaded")) {
2074
- return createAPICallError({
2075
- message: isErrorWithMessage(error) && error.message ? error.message : "Anthropic API is overloaded. Please retry.",
2076
- code: errorCode || void 0,
2077
- exitCode,
2078
- stderr,
2079
- promptExcerpt: messagesPrompt.substring(0, 200),
2080
- isRetryable: true
2081
- });
2082
- }
2083
- if (errorKind === "model_not_found" || errorMessage.includes("model_not_found") || errorMessage.includes("no such model")) {
2084
- const originalMessage = isErrorWithMessage(error) && error.message ? error.message : "Model not found";
2085
- return createAPICallError({
2086
- message: `${originalMessage}. The requested model was not found. Verify the model id passed to the provider (e.g. 'opus', 'sonnet', 'haiku', or a full model name) and that your account has access to it.`,
2087
- code: errorCode || void 0,
2088
- exitCode,
2089
- stderr,
2090
- promptExcerpt: messagesPrompt.substring(0, 200),
2091
- isRetryable: false
2092
- });
2093
- }
2094
- const isRetryable = errorCode === "ENOENT" || errorCode === "ECONNREFUSED" || errorCode === "ETIMEDOUT" || errorCode === "ECONNRESET";
2095
- return createAPICallError({
2096
- message: isErrorWithMessage(error) && error.message ? error.message : "Claude Code SDK error",
2097
- code: errorCode || void 0,
2098
- exitCode,
2099
- stderr,
2100
- promptExcerpt: messagesPrompt.substring(0, 200),
2101
- isRetryable
2102
- });
2103
- }
2104
- setSessionId(sessionId) {
2105
- this.sessionId = sessionId;
2106
- const warning = validateSessionId(sessionId);
2107
- if (warning) {
2108
- this.logger.warn(`Claude Code Session: ${warning}`);
2109
- }
2110
- }
2111
- logMcpConnectionIssues(mcpServers) {
2112
- if (!Array.isArray(mcpServers) || mcpServers.length === 0) {
2113
- return;
2114
- }
2115
- const serversNeedingAttention = mcpServers.filter((server) => {
2116
- const status = typeof server.status === "string" ? server.status.toLowerCase() : "";
2117
- return status === "failed" || status === "needs-auth";
2118
- });
2119
- if (serversNeedingAttention.length === 0) {
2120
- return;
2121
- }
2122
- const details = serversNeedingAttention.map((server) => {
2123
- const name = typeof server.name === "string" && server.name.trim().length > 0 ? server.name : "<unknown>";
2124
- const status = typeof server.status === "string" && server.status.trim().length > 0 ? server.status : "unknown";
2125
- const error = typeof server.error === "string" && server.error.trim().length > 0 ? ` (${server.error})` : "";
2126
- return `${name}:${status}${error}`;
2127
- }).join(", ");
2128
- this.logger.warn(`[claude-code] MCP servers not connected: ${details}`);
2129
- }
2130
- /**
2131
- * Handles SDK 0.3.x system messages other than 'init', shared by doGenerate
2132
- * and doStream:
2133
- * - 'api_retry' is counted into providerMetadata (`apiRetries`) and debug-logged.
2134
- * - 'permission_denied' is warn-logged and recorded into providerMetadata
2135
- * (`permissionDenials`); without this a denial is invisible until the
2136
- * model talks about it.
2137
- * - 'model_refusal_fallback' is debug-logged (the superseding assistant
2138
- * message is handled by the text-dedup guard in the message loops).
2139
- * - 'thinking_tokens' deltas are accumulated into providerMetadata
2140
- * (`estimatedThinkingTokens`); the estimate is explicitly not the
2141
- * authoritative billed output tokens, so it is surfaced as metadata
2142
- * instead of feeding `usage.outputTokens.reasoning`.
2143
- * - The subtypes in {@link INFORMATIONAL_SYSTEM_SUBTYPES} are intentionally
2144
- * informational and only debug-logged.
2145
- */
2146
- handleSystemMessage(message, tracking, onRetractedUuids) {
2147
- switch (message.subtype) {
2148
- case "api_retry":
2149
- tracking.apiRetries += 1;
2150
- this.logger.debug(
2151
- `[claude-code] API retry ${message.attempt}/${message.max_retries} in ${message.retry_delay_ms}ms - Status: ${message.error_status ?? "unknown"}, Error: ${message.error}`
2152
- );
2153
- break;
2154
- case "permission_denied": {
2155
- const reason = message.decision_reason ?? message.message;
2156
- tracking.permissionDenials.push({
2157
- toolName: message.tool_name,
2158
- toolUseId: message.tool_use_id,
2159
- ...reason !== void 0 && { reason }
2160
- });
2161
- this.logger.warn(
2162
- `[claude-code] Permission denied - Tool: ${message.tool_name}${reason ? `, Reason: ${reason}` : ""}`
2163
- );
2164
- break;
2165
- }
2166
- case "mirror_error": {
2167
- const mirrorError = message.error ?? "unknown error";
2168
- const mirrorSessionId = message.key?.sessionId ?? message.session_id ?? "unknown";
2169
- tracking.mirrorErrors.push({ error: mirrorError, sessionId: mirrorSessionId });
2170
- this.logger.warn(
2171
- `[claude-code] SessionStore mirror error (transcript batch dropped) - Session: ${mirrorSessionId}, Error: ${mirrorError}`
2172
- );
2173
- break;
2174
- }
2175
- case "model_refusal_fallback": {
2176
- this.logger.debug(
2177
- `[claude-code] Model refusal fallback - ${message.original_model} -> ${message.fallback_model} (direction: ${message.direction})`
2178
- );
2179
- const retractedUuids = message.retracted_message_uuids;
2180
- if (onRetractedUuids && retractedUuids && retractedUuids.length > 0) {
2181
- this.logger.debug(
2182
- `[claude-code] Refusal fallback retracts ${retractedUuids.length} message uuid(s)`
2183
- );
2184
- onRetractedUuids(retractedUuids);
2185
- }
2186
- break;
2187
- }
2188
- case "thinking_tokens":
2189
- tracking.estimatedThinkingTokens += message.estimated_tokens_delta;
2190
- this.logger.debug(
2191
- `[claude-code] Thinking tokens estimate - block total: ${message.estimated_tokens}, delta: ${message.estimated_tokens_delta}, accumulated: ${tracking.estimatedThinkingTokens}`
2192
- );
2193
- break;
2194
- default:
2195
- if (INFORMATIONAL_SYSTEM_SUBTYPES.has(message.subtype)) {
2196
- this.logger.debug(
2197
- `[claude-code] Ignoring informational system message: ${message.subtype}`
2198
- );
2199
- } else {
2200
- this.logger.debug(`[claude-code] Unhandled system message subtype: ${message.subtype}`);
2201
- }
2202
- break;
2203
- }
2204
- }
2205
- /**
2206
- * Merges the result message's `permission_denials` list into the tracked
2207
- * denials. PreToolUse-hook denies bypass canUseTool and emit no
2208
- * `permission_denied` system event (per the SDK docs on
2209
- * SDKPermissionDeniedMessage), so the result list is the only place they
2210
- * surface. Entries already recorded from stream-time events are deduped by
2211
- * `tool_use_id`.
2212
- */
2213
- mergeResultPermissionDenials(message, tracking) {
2214
- for (const denial of message.permission_denials ?? []) {
2215
- const alreadyTracked = tracking.permissionDenials.some(
2216
- (d) => d.toolUseId !== void 0 && d.toolUseId === denial.tool_use_id
2217
- );
2218
- if (!alreadyTracked) {
2219
- tracking.permissionDenials.push({
2220
- toolName: denial.tool_name,
2221
- toolUseId: denial.tool_use_id
2222
- });
2223
- }
2224
- }
2225
- }
2226
- /**
2227
- * Bounded post-result drain for the `prompt_suggestion` message
2228
- * (promptSuggestions: true), shared by doGenerate and doStream. The
2229
- * suggestion arrives AFTER the result message; the SDK emits at most one
2230
- * per turn, so stop once it is delivered, and a timeout closes the
2231
- * iterator (tearing down the subprocess) if the CLI lingers after the
2232
- * result without emitting one. Advances the response's own generator, so
2233
- * the caller's surrounding loop resumes to a finished iterator.
2234
- */
2235
- async drainPromptSuggestion(response, onPromptSuggestion) {
2236
- const iterator = response[Symbol.asyncIterator]();
2237
- let drainTimer;
2238
- const drainTimeout = new Promise((resolve) => {
2239
- drainTimer = setTimeout(
2240
- () => resolve("timeout"),
2241
- _ClaudeCodeLanguageModel.PROMPT_SUGGESTION_DRAIN_TIMEOUT_MS
2242
- );
2243
- drainTimer.unref?.();
2244
- });
2245
- try {
2246
- while (true) {
2247
- const winner = await Promise.race([iterator.next(), drainTimeout]);
2248
- if (winner === "timeout") {
2249
- this.logger.debug("[claude-code] Post-result drain timed out; closing SDK iterator");
2250
- void iterator.return?.().catch(() => {
2251
- });
2252
- break;
2253
- }
2254
- if (winner.done) {
2255
- break;
2256
- }
2257
- const trailingMessage = winner.value;
2258
- this.logger.debug(`[claude-code] Post-result message type: ${trailingMessage.type}`);
2259
- if (trailingMessage.type === "prompt_suggestion") {
2260
- onPromptSuggestion(trailingMessage.suggestion);
2261
- void iterator.return?.().catch(() => {
2262
- });
2263
- break;
2264
- }
2265
- }
2266
- } catch (drainError) {
2267
- this.logger.debug(
2268
- `[claude-code] Error draining post-result messages: ${drainError instanceof Error ? drainError.message : String(drainError)}`
2269
- );
2270
- } finally {
2271
- if (drainTimer !== void 0) {
2272
- clearTimeout(drainTimer);
2273
- }
2274
- }
2275
- }
2276
- async doGenerate(options) {
2277
- this.logger.debug(`[claude-code] Starting doGenerate request with model: ${this.modelId}`);
2278
- this.logger.debug(`[claude-code] Response format: ${options.responseFormat?.type ?? "none"}`);
2279
- const {
2280
- messagesPrompt,
2281
- warnings: messageWarnings,
2282
- streamingContentParts,
2283
- hasImageParts
2284
- } = convertToClaudeCodeMessages(options.prompt);
2285
- this.logger.debug(
2286
- `[claude-code] Converted ${options.prompt.length} messages, hasImageParts: ${hasImageParts}`
2287
- );
2288
- const abortController = new AbortController();
2289
- let abortListener;
2290
- if (options.abortSignal?.aborted) {
2291
- abortController.abort(options.abortSignal.reason);
2292
- }
2293
- let collectedStderr = "";
2294
- const stderrCollector = (data) => {
2295
- collectedStderr += data;
2296
- };
2297
- const sdkOptions = this.getSanitizedSdkOptions();
2298
- const effectiveResume = this.getEffectiveResume(sdkOptions);
2299
- const queryOptions = this.createQueryOptions(
2300
- abortController,
2301
- options.responseFormat,
2302
- stderrCollector,
2303
- sdkOptions,
2304
- effectiveResume
2305
- );
2306
- if (options.abortSignal && !options.abortSignal.aborted) {
2307
- abortListener = () => abortController.abort(options.abortSignal?.reason);
2308
- options.abortSignal.addEventListener("abort", abortListener, { once: true });
2309
- }
2310
- let text = "";
2311
- const contentSegments = [];
2312
- const joinTextSegments = () => contentSegments.filter((segment) => segment.kind === "text").map((segment) => segment.text).join("");
2313
- const joinFinalTurnTextSegments = () => {
2314
- let start = 0;
2315
- for (let i = 0; i < contentSegments.length; i++) {
2316
- const kind = contentSegments[i]?.kind;
2317
- if (kind === "tool-result" || kind === "tool-error") {
2318
- start = i + 1;
2319
- }
2320
- }
2321
- return contentSegments.slice(start).filter((segment) => segment.kind === "text").map((segment) => segment.text).join("");
2322
- };
2323
- const knownTools = /* @__PURE__ */ new Map();
2324
- const retractedToolIds = /* @__PURE__ */ new Set();
2325
- const evictBuffered = (retracted) => {
2326
- if (retracted.size === 0) return;
2327
- const retractedToolCallIds = computeRetractedToolCallIds(
2328
- retracted,
2329
- contentSegments.filter(
2330
- (segment) => segment.kind === "tool-call" || segment.kind === "tool-result" || segment.kind === "tool-error"
2331
- ).map((segment) => ({
2332
- toolCallId: segment.toolCallId,
2333
- uuid: segment.uuid
2334
- }))
2335
- );
2336
- for (const toolCallId of retractedToolCallIds) {
2337
- retractedToolIds.add(toolCallId);
2338
- knownTools.delete(toolCallId);
2339
- activeTaskTools.delete(toolCallId);
2340
- }
2341
- for (let i = contentSegments.length - 1; i >= 0; i--) {
2342
- const segment = contentSegments[i];
2343
- if (segment === void 0) continue;
2344
- const segmentUuid = "uuid" in segment ? segment.uuid : void 0;
2345
- const retractsSegment = segmentUuid !== void 0 && retracted.has(segmentUuid) || (segment.kind === "tool-result" || segment.kind === "tool-error") && retractedToolCallIds.has(segment.toolCallId);
2346
- if (retractsSegment) {
2347
- contentSegments.splice(i, 1);
2348
- }
2349
- }
2350
- };
2351
- const activeTaskTools = /* @__PURE__ */ new Map();
2352
- const getFallbackParentId = () => {
2353
- if (activeTaskTools.size === 1) {
2354
- return activeTaskTools.keys().next().value ?? null;
2355
- }
2356
- return null;
2357
- };
2358
- let structuredOutput;
2359
- let receivedResultMessage = false;
2360
- let usage = createEmptyUsage();
2361
- let finishReason = { unified: "stop", raw: void 0 };
2362
- let wasTruncated = false;
2363
- let costUsd;
2364
- let durationMs;
2365
- let modelUsage;
2366
- let ttftMs;
2367
- let ttftStreamMs;
2368
- let timeToRequestMs;
2369
- let warmSpareClaimed;
2370
- let terminalReason;
2371
- const metadataTracking = {
2372
- apiRetries: 0,
2373
- permissionDenials: [],
2374
- mirrorErrors: [],
2375
- estimatedThinkingTokens: 0
2376
- };
2377
- const warnings = this.generateAllWarnings(options, messagesPrompt);
2378
- if (messageWarnings) {
2379
- messageWarnings.forEach((warning) => {
2380
- warnings.push({
2381
- type: "other",
2382
- message: warning
2383
- });
2384
- });
2385
- }
2386
- const modeSetting = this.settings.streamingInput ?? "auto";
2387
- const effectiveCanUseTool = sdkOptions?.canUseTool ?? this.settings.canUseTool;
2388
- const effectivePermissionPromptToolName = sdkOptions?.permissionPromptToolName ?? this.settings.permissionPromptToolName;
2389
- const wantsStreamInput = modeSetting === "always" || modeSetting === "auto" && !!effectiveCanUseTool;
2390
- if (!wantsStreamInput && hasImageParts) {
2391
- warnings.push({
2392
- type: "other",
2393
- message: STREAMING_FEATURE_WARNING
2394
- });
2395
- }
2396
- let done = () => {
2397
- };
2398
- const outputStreamEnded = new Promise((resolve) => {
2399
- done = () => resolve(void 0);
2400
- });
2401
- try {
2402
- if (effectiveCanUseTool && effectivePermissionPromptToolName) {
2403
- throw new Error(
2404
- "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."
2405
- );
2406
- }
2407
- const sdkPrompt = wantsStreamInput ? toAsyncIterablePrompt(
2408
- messagesPrompt,
2409
- outputStreamEnded,
2410
- effectiveResume,
2411
- streamingContentParts,
2412
- this.settings.onStreamStart
2413
- ) : messagesPrompt;
2414
- this.logger.debug(
2415
- `[claude-code] Executing query with streamingInput: ${wantsStreamInput}, session: ${effectiveResume ?? "new"}`
2416
- );
2417
- const response = (0, import_claude_agent_sdk.query)({
2418
- prompt: sdkPrompt,
2419
- options: queryOptions
2420
- });
2421
- this.settings.onQueryCreated?.(response);
2422
- let lastAssistantErrorKind;
2423
- const sdkIterator = response[Symbol.asyncIterator]();
2424
- const detachableResponse = {
2425
- [Symbol.asyncIterator]: () => ({
2426
- next: () => sdkIterator.next(),
2427
- return: () => {
2428
- void sdkIterator.return?.().catch(() => {
2429
- });
2430
- return Promise.resolve({ done: true, value: void 0 });
2431
- }
2432
- })
2433
- };
2434
- for await (const message of detachableResponse) {
2435
- this.logger.debug(`[claude-code] Received message type: ${message.type}`);
2436
- if (message.type === "assistant") {
2437
- if (typeof message.error === "string") {
2438
- lastAssistantErrorKind = message.error;
2439
- }
2440
- applySupersede(message, evictBuffered, this.logger, "truthy");
2441
- const messageUuid = typeof message.uuid === "string" ? message.uuid : void 0;
2442
- const sdkParentToolUseId = message.parent_tool_use_id;
2443
- const content = message.message.content;
2444
- if (Array.isArray(content)) {
2445
- for (const block of content) {
2446
- if (!isContentBlock(block)) continue;
2447
- if (block.type === "text" && typeof block.text === "string") {
2448
- if (block.text.length > 0) {
2449
- contentSegments.push({
2450
- kind: "text",
2451
- ...messageUuid !== void 0 && { uuid: messageUuid },
2452
- text: block.text
2453
- });
2454
- }
2455
- } else if (block.type === "thinking" && typeof block.thinking === "string") {
2456
- contentSegments.push({
2457
- kind: "reasoning",
2458
- ...messageUuid !== void 0 && { uuid: messageUuid },
2459
- text: block.thinking
2460
- });
2461
- } else if (block.type === "tool_use") {
2462
- const [tool3] = this.extractToolUses([block]);
2463
- if (!tool3) continue;
2464
- const parentToolCallId = isSubagentToolName(tool3.name) ? null : resolveToolParentId(
2465
- sdkParentToolUseId,
2466
- tool3.parentToolUseId,
2467
- getFallbackParentId
2468
- );
2469
- this.logger.debug(
2470
- `[claude-code] Tool use detected - Tool: ${tool3.name}, ID: ${tool3.id}, SDK parent: ${sdkParentToolUseId}, resolved parent: ${parentToolCallId}`
2471
- );
2472
- knownTools.set(tool3.id, { name: tool3.name, parentToolCallId });
2473
- if (isSubagentToolName(tool3.name)) {
2474
- activeTaskTools.set(tool3.id, { startTime: Date.now() });
2475
- }
2476
- contentSegments.push({
2477
- kind: "tool-call",
2478
- ...messageUuid !== void 0 && { uuid: messageUuid },
2479
- toolCallId: tool3.id,
2480
- part: this.buildToolCallPart(
2481
- tool3.id,
2482
- tool3.name,
2483
- this.serializeToolInput(tool3.input),
2484
- parentToolCallId
2485
- )
2486
- });
2487
- }
2488
- }
2489
- }
2490
- text = joinTextSegments();
2491
- } else if (message.type === "user") {
2492
- if (!message.message?.content) {
2493
- this.logger.warn(
2494
- `[claude-code] Unexpected user message structure: missing content field. Message type: ${message.type}. This may indicate an SDK protocol violation.`
2495
- );
2496
- continue;
2497
- }
2498
- const sdkParentToolUseIdForResults = message.parent_tool_use_id;
2499
- const resultMessageUuid = typeof message.uuid === "string" ? message.uuid : void 0;
2500
- const content = message.message.content;
2501
- for (const result of this.extractToolResults(content)) {
2502
- if (this.isRetractedToolFrame(result.id, retractedToolIds, "result")) {
2503
- continue;
2504
- }
2505
- const known = knownTools.get(result.id);
2506
- const toolName = result.name ?? known?.name ?? _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
2507
- this.logger.debug(
2508
- `[claude-code] Tool result received - Tool: ${toolName}, ID: ${result.id}`
2509
- );
2510
- let parentToolCallId;
2511
- if (known) {
2512
- known.name = toolName;
2513
- parentToolCallId = known.parentToolCallId;
2514
- } else {
2515
- this.logger.warn(
2516
- `[claude-code] Received tool result for unknown tool ID: ${result.id}`
2517
- );
2518
- parentToolCallId = isSubagentToolName(toolName) ? null : resolveToolParentId(sdkParentToolUseIdForResults, void 0, getFallbackParentId);
2519
- knownTools.set(result.id, { name: toolName, parentToolCallId });
2520
- contentSegments.push({
2521
- kind: "tool-call",
2522
- toolCallId: result.id,
2523
- part: this.buildToolCallPart(result.id, toolName, "", parentToolCallId)
2524
- });
2525
- }
2526
- if (isSubagentToolName(toolName)) {
2527
- activeTaskTools.delete(result.id);
2528
- }
2529
- contentSegments.push({
2530
- kind: "tool-result",
2531
- ...resultMessageUuid !== void 0 && { uuid: resultMessageUuid },
2532
- toolCallId: result.id,
2533
- part: this.buildToolResultPart(
2534
- result.id,
2535
- toolName,
2536
- result.result,
2537
- result.isError,
2538
- parentToolCallId
2539
- )
2540
- });
2541
- }
2542
- for (const error of this.extractToolErrors(content)) {
2543
- if (this.isRetractedToolFrame(error.id, retractedToolIds, "error")) {
2544
- continue;
2545
- }
2546
- const known = knownTools.get(error.id);
2547
- const toolName = error.name ?? known?.name ?? _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
2548
- this.logger.debug(
2549
- `[claude-code] Tool error received - Tool: ${toolName}, ID: ${error.id}`
2550
- );
2551
- let parentToolCallId;
2552
- if (known) {
2553
- known.name = toolName;
2554
- parentToolCallId = known.parentToolCallId;
2555
- } else {
2556
- this.logger.warn(
2557
- `[claude-code] Received tool error for unknown tool ID: ${error.id}`
2558
- );
2559
- parentToolCallId = isSubagentToolName(toolName) ? null : resolveToolParentId(sdkParentToolUseIdForResults, void 0, getFallbackParentId);
2560
- knownTools.set(error.id, { name: toolName, parentToolCallId });
2561
- contentSegments.push({
2562
- kind: "tool-call",
2563
- toolCallId: error.id,
2564
- part: this.buildToolCallPart(error.id, toolName, "", parentToolCallId)
2565
- });
2566
- }
2567
- if (isSubagentToolName(toolName)) {
2568
- activeTaskTools.delete(error.id);
2569
- }
2570
- contentSegments.push({
2571
- kind: "tool-error",
2572
- ...resultMessageUuid !== void 0 && { uuid: resultMessageUuid },
2573
- toolCallId: error.id,
2574
- part: this.buildToolErrorResultPart(
2575
- error.id,
2576
- toolName,
2577
- error.error,
2578
- parentToolCallId
2579
- )
2580
- });
2581
- }
2582
- } else if (message.type === "result") {
2583
- done();
2584
- receivedResultMessage = true;
2585
- this.setSessionId(message.session_id);
2586
- costUsd = message.total_cost_usd;
2587
- durationMs = message.duration_ms;
2588
- modelUsage = message.modelUsage;
2589
- if ("ttft_ms" in message) {
2590
- ttftMs = message.ttft_ms;
2591
- }
2592
- if ("ttft_stream_ms" in message) {
2593
- ttftStreamMs = message.ttft_stream_ms;
2594
- }
2595
- if ("time_to_request_ms" in message) {
2596
- timeToRequestMs = message.time_to_request_ms;
2597
- }
2598
- if ("warm_spare_claimed" in message) {
2599
- warmSpareClaimed = message.warm_spare_claimed;
2600
- }
2601
- terminalReason = message.terminal_reason;
2602
- this.mergeResultPermissionDenials(message, metadataTracking);
2603
- if ("is_error" in message && message.is_error === true) {
2604
- const resultText = "result" in message && typeof message.result === "string" ? message.result : void 0;
2605
- const errorsText = "errors" in message && Array.isArray(message.errors) ? message.errors.filter((e) => typeof e === "string").join("; ") : "";
2606
- const errorMessage = resultText ?? (errorsText || "Claude Code CLI returned an error");
2607
- throw Object.assign(new Error(errorMessage), {
2608
- exitCode: 1,
2609
- errorKind: lastAssistantErrorKind
2610
- });
2611
- }
2612
- if (message.subtype === "error_max_structured_output_retries") {
2613
- throw new Error(
2614
- "Failed to generate valid structured output after maximum retries. The model could not produce a response matching the required schema."
2615
- );
2616
- }
2617
- if ("structured_output" in message && message.structured_output !== void 0) {
2618
- structuredOutput = message.structured_output;
2619
- this.logger.debug("[claude-code] Received structured output from SDK");
2620
- }
2621
- this.logger.info(
2622
- `[claude-code] Request completed - Session: ${message.session_id}, Cost: $${costUsd?.toFixed(4) ?? "N/A"}, Duration: ${durationMs ?? "N/A"}ms`
2623
- );
2624
- if ("usage" in message) {
2625
- usage = convertClaudeCodeUsage(message.usage);
2626
- this.logger.debug(
2627
- `[claude-code] Token usage - Input: ${usage.inputTokens.total}, Output: ${usage.outputTokens.total}`
2628
- );
2629
- }
2630
- const stopReason = "stop_reason" in message ? message.stop_reason : void 0;
2631
- finishReason = mapClaudeCodeFinishReason(message.subtype, stopReason);
2632
- this.logger.debug(`[claude-code] Finish reason: ${finishReason.unified}`);
2633
- const effectivePromptSuggestions = sdkOptions?.promptSuggestions ?? this.settings.promptSuggestions;
2634
- if (this.settings.onPromptSuggestion && effectivePromptSuggestions !== false) {
2635
- await this.drainPromptSuggestion(response, this.settings.onPromptSuggestion);
2636
- }
2637
- break;
2638
- } else if (message.type === "system" && message.subtype === "init") {
2639
- this.logMcpConnectionIssues(message.mcp_servers);
2640
- this.setSessionId(message.session_id);
2641
- this.logger.info(`[claude-code] Session initialized: ${message.session_id}`);
2642
- } else if (message.type === "system") {
2643
- this.handleSystemMessage(
2644
- message,
2645
- metadataTracking,
2646
- buildRetractionEvictor(evictBuffered)
2647
- );
2648
- }
2649
- }
2650
- } catch (error) {
2651
- done();
2652
- this.logger.debug(
2653
- `[claude-code] Error during doGenerate: ${error instanceof Error ? error.message : String(error)}`
2654
- );
2655
- if (isAbortError(error)) {
2656
- this.logger.debug("[claude-code] Request aborted by user");
2657
- throw options.abortSignal?.aborted ? options.abortSignal.reason : error;
2658
- }
2659
- if (isClaudeCodeTruncationError(error, text)) {
2660
- this.logger.warn(
2661
- `[claude-code] Detected truncated response, returning ${text.length} characters of buffered text`
2662
- );
2663
- wasTruncated = true;
2664
- finishReason = { unified: "length", raw: "truncation" };
2665
- warnings.push({
2666
- type: "other",
2667
- message: CLAUDE_CODE_TRUNCATION_WARNING
2668
- });
2669
- } else {
2670
- throw this.handleClaudeCodeError(error, messagesPrompt, collectedStderr);
2671
- }
2672
- } finally {
2673
- if (options.abortSignal && abortListener) {
2674
- options.abortSignal.removeEventListener("abort", abortListener);
2675
- }
2676
- }
2677
- if (options.responseFormat?.type === "json" && options.responseFormat.schema !== void 0 && receivedResultMessage && structuredOutput === void 0 && !wasTruncated && finishReason.unified === "stop") {
2678
- const recoveredJsonText = extractJsonObjectText(joinFinalTurnTextSegments()) ?? extractJsonObjectText(joinTextSegments());
2679
- if (recoveredJsonText !== void 0) {
2680
- this.logger.warn(
2681
- "[claude-code] outputFormat was requested but the CLI returned no structured_output; recovered JSON by parsing the prose response. The schema likely contains constructs the CLI cannot enforce - see the README structured-output limitations."
2682
- );
2683
- structuredOutput = JSON.parse(recoveredJsonText);
2684
- } else {
2685
- throw createAPICallError({
2686
- message: MISSING_STRUCTURED_OUTPUT_ERROR_MESSAGE,
2687
- promptExcerpt: messagesPrompt.substring(0, 200),
2688
- isRetryable: false
2689
- });
2690
- }
2691
- }
2692
- const thinkingTraces = contentSegments.filter((segment) => segment.kind === "reasoning").map((segment) => segment.text);
2693
- const contentParts = [];
2694
- for (const segment of contentSegments) {
2695
- if (segment.kind === "reasoning") {
2696
- contentParts.push({ type: "reasoning", text: segment.text });
2697
- } else if (segment.kind === "text") {
2698
- if (structuredOutput !== void 0) continue;
2699
- const last = contentParts[contentParts.length - 1];
2700
- if (last !== void 0 && last.type === "text") {
2701
- last.text += segment.text;
2702
- } else {
2703
- contentParts.push({ type: "text", text: segment.text });
2704
- }
2705
- } else {
2706
- contentParts.push(segment.part);
2707
- }
2708
- }
2709
- if (structuredOutput !== void 0) {
2710
- contentParts.push({ type: "text", text: JSON.stringify(structuredOutput) });
2711
- } else if (!contentParts.some((part) => part.type === "text")) {
2712
- contentParts.push({ type: "text", text: "" });
2713
- }
2714
- return {
2715
- content: contentParts,
2716
- usage,
2717
- finishReason,
2718
- warnings,
2719
- response: {
2720
- id: (0, import_provider_utils.generateId)(),
2721
- timestamp: /* @__PURE__ */ new Date(),
2722
- modelId: this.modelId
2723
- },
2724
- request: {
2725
- body: messagesPrompt
2726
- },
2727
- providerMetadata: {
2728
- "claude-code": {
2729
- ...this.sessionId !== void 0 && { sessionId: this.sessionId },
2730
- ...costUsd !== void 0 && { costUsd },
2731
- ...durationMs !== void 0 && { durationMs },
2732
- ...modelUsage !== void 0 && { modelUsage },
2733
- ...ttftMs !== void 0 && { ttftMs },
2734
- ...ttftStreamMs !== void 0 && { ttftStreamMs },
2735
- ...timeToRequestMs !== void 0 && { timeToRequestMs },
2736
- ...warmSpareClaimed !== void 0 && { warmSpareClaimed },
2737
- ...terminalReason !== void 0 && { terminalReason },
2738
- ...metadataTracking.apiRetries > 0 && { apiRetries: metadataTracking.apiRetries },
2739
- ...metadataTracking.permissionDenials.length > 0 && {
2740
- permissionDenials: metadataTracking.permissionDenials
2741
- },
2742
- ...metadataTracking.mirrorErrors.length > 0 && {
2743
- mirrorErrors: metadataTracking.mirrorErrors
2744
- },
2745
- ...metadataTracking.estimatedThinkingTokens > 0 && {
2746
- estimatedThinkingTokens: metadataTracking.estimatedThinkingTokens
2747
- },
2748
- ...wasTruncated && { truncated: true },
2749
- ...thinkingTraces.length > 0 && { thinkingTraces }
2750
- }
2751
- }
2752
- };
2753
- }
2754
- async doStream(options) {
2755
- this.logger.debug(`[claude-code] Starting doStream request with model: ${this.modelId}`);
2756
- this.logger.debug(`[claude-code] Response format: ${options.responseFormat?.type ?? "none"}`);
2757
- const {
2758
- messagesPrompt,
2759
- warnings: messageWarnings,
2760
- streamingContentParts,
2761
- hasImageParts
2762
- } = convertToClaudeCodeMessages(options.prompt);
2763
- this.logger.debug(
2764
- `[claude-code] Converted ${options.prompt.length} messages for streaming, hasImageParts: ${hasImageParts}`
2765
- );
2766
- const abortController = new AbortController();
2767
- let abortListener;
2768
- if (options.abortSignal?.aborted) {
2769
- abortController.abort(options.abortSignal.reason);
2770
- }
2771
- let collectedStderr = "";
2772
- const stderrCollector = (data) => {
2773
- collectedStderr += data;
2774
- };
2775
- const sdkOptions = this.getSanitizedSdkOptions();
2776
- const effectiveResume = this.getEffectiveResume(sdkOptions);
2777
- const queryOptions = this.createQueryOptions(
2778
- abortController,
2779
- options.responseFormat,
2780
- stderrCollector,
2781
- sdkOptions,
2782
- effectiveResume
2783
- );
2784
- if (options.abortSignal && !options.abortSignal.aborted) {
2785
- abortListener = () => abortController.abort(options.abortSignal?.reason);
2786
- options.abortSignal.addEventListener("abort", abortListener, { once: true });
2787
- }
2788
- if (queryOptions.includePartialMessages === void 0) {
2789
- queryOptions.includePartialMessages = true;
2790
- }
2791
- const warnings = this.generateAllWarnings(options, messagesPrompt);
2792
- if (messageWarnings) {
2793
- messageWarnings.forEach((warning) => {
2794
- warnings.push({
2795
- type: "other",
2796
- message: warning
2797
- });
2798
- });
2799
- }
2800
- const modeSetting = this.settings.streamingInput ?? "auto";
2801
- const effectiveCanUseTool = sdkOptions?.canUseTool ?? this.settings.canUseTool;
2802
- const effectivePermissionPromptToolName = sdkOptions?.permissionPromptToolName ?? this.settings.permissionPromptToolName;
2803
- const wantsStreamInput = modeSetting === "always" || modeSetting === "auto" && !!effectiveCanUseTool;
2804
- if (!wantsStreamInput && hasImageParts) {
2805
- warnings.push({
2806
- type: "other",
2807
- message: STREAMING_FEATURE_WARNING
2808
- });
2809
- }
2810
- const stream = new ReadableStream({
2811
- start: async (controller) => {
2812
- let done = () => {
2813
- };
2814
- const outputStreamEnded = new Promise((resolve) => {
2815
- done = () => resolve(void 0);
2816
- });
2817
- const toolStates = /* @__PURE__ */ new Map();
2818
- const retractedStreamToolIds = /* @__PURE__ */ new Set();
2819
- const activeTaskTools = /* @__PURE__ */ new Map();
2820
- const getFallbackParentId = () => {
2821
- if (activeTaskTools.size === 1) {
2822
- return activeTaskTools.keys().next().value ?? null;
2823
- }
2824
- return null;
2825
- };
2826
- const streamWarnings = [];
2827
- const closeToolInput = (toolId, state) => {
2828
- if (!state.inputClosed && state.inputStarted) {
2829
- controller.enqueue({
2830
- type: "tool-input-end",
2831
- id: toolId
2832
- });
2833
- state.inputClosed = true;
2834
- }
2835
- };
2836
- const emitToolCall = (toolId, state) => {
2837
- if (state.callEmitted) {
2838
- return;
2839
- }
2840
- closeToolInput(toolId, state);
2841
- controller.enqueue(
2842
- this.buildToolCallPart(
2843
- toolId,
2844
- state.name,
2845
- state.lastSerializedInput ?? "",
2846
- state.parentToolCallId
2847
- )
2848
- );
2849
- state.callEmitted = true;
2850
- };
2851
- const finalizeToolCalls = () => {
2852
- for (const [toolId, state] of toolStates) {
2853
- emitToolCall(toolId, state);
2854
- }
2855
- toolStates.clear();
2856
- };
2857
- let usage = createEmptyUsage();
2858
- let accumulatedText = "";
2859
- const textSegments = [];
2860
- let textPartId;
2861
- let streamedTextLength = 0;
2862
- let emittedTextSinceLastAssistant = "";
2863
- let hasReceivedStreamEvents = false;
2864
- let hasStreamedJson = false;
2865
- let lastAssistantErrorKind;
2866
- const metadataTracking = {
2867
- apiRetries: 0,
2868
- permissionDenials: [],
2869
- mirrorErrors: [],
2870
- estimatedThinkingTokens: 0
2871
- };
2872
- const toolBlocksByIndex = /* @__PURE__ */ new Map();
2873
- const toolInputAccumulators = /* @__PURE__ */ new Map();
2874
- const textBlocksByIndex = /* @__PURE__ */ new Map();
2875
- let textStreamedViaContentBlock = false;
2876
- const reasoningBlocksByIndex = /* @__PURE__ */ new Map();
2877
- let currentReasoningPartId;
2878
- const evictLive = (retracted) => {
2879
- if (retracted.size === 0) return;
2880
- for (let i = textSegments.length - 1; i >= 0; i--) {
2881
- const segmentUuid = textSegments[i]?.uuid;
2882
- if (segmentUuid !== void 0 && retracted.has(segmentUuid)) {
2883
- textSegments.splice(i, 1);
2884
- }
2885
- }
2886
- accumulatedText = textSegments.map((segment) => segment.text).join("");
2887
- const retractedToolCallIds = computeRetractedToolCallIds(
2888
- retracted,
2889
- [...toolStates].map(([toolId, state]) => ({
2890
- toolCallId: toolId,
2891
- uuid: state.messageUuid
2892
- }))
2893
- );
2894
- for (const toolId of retractedToolCallIds) {
2895
- const state = toolStates.get(toolId);
2896
- if (!state) continue;
2897
- activeTaskTools.delete(toolId);
2898
- if (!state.callEmitted) {
2899
- closeToolInput(toolId, state);
2900
- toolStates.delete(toolId);
2901
- retractedStreamToolIds.add(toolId);
2902
- toolInputAccumulators.delete(toolId);
2903
- for (const [blockIndex, mappedId] of toolBlocksByIndex) {
2904
- if (mappedId === toolId) {
2905
- toolBlocksByIndex.delete(blockIndex);
2906
- }
2907
- }
2908
- this.logger.debug(
2909
- `[claude-code] Retracted pending tool call from superseded message - ID: ${toolId}`
2910
- );
2911
- }
2912
- }
2913
- };
2914
- try {
2915
- controller.enqueue({ type: "stream-start", warnings });
2916
- if (effectiveCanUseTool && effectivePermissionPromptToolName) {
2917
- throw new Error(
2918
- "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."
2919
- );
2920
- }
2921
- const sdkPrompt = wantsStreamInput ? toAsyncIterablePrompt(
2922
- messagesPrompt,
2923
- outputStreamEnded,
2924
- effectiveResume,
2925
- streamingContentParts,
2926
- this.settings.onStreamStart
2927
- ) : messagesPrompt;
2928
- this.logger.debug(
2929
- `[claude-code] Starting stream query with streamingInput: ${wantsStreamInput}, session: ${effectiveResume ?? "new"}`
2930
- );
2931
- const response = (0, import_claude_agent_sdk.query)({
2932
- prompt: sdkPrompt,
2933
- options: queryOptions
2934
- });
2935
- this.settings.onQueryCreated?.(response);
2936
- for await (const message of response) {
2937
- this.logger.debug(`[claude-code] Stream received message type: ${message.type}`);
2938
- if (message.type === "stream_event") {
2939
- const streamEvent = message;
2940
- const event = streamEvent.event;
2941
- if (event.type === "content_block_delta" && event.delta.type === "text_delta" && "text" in event.delta && event.delta.text) {
2942
- const deltaText = event.delta.text;
2943
- hasReceivedStreamEvents = true;
2944
- if (options.responseFormat?.type === "json") {
2945
- accumulatedText += deltaText;
2946
- streamedTextLength += deltaText.length;
2947
- continue;
2948
- }
2949
- if (!textPartId) {
2950
- textPartId = (0, import_provider_utils.generateId)();
2951
- controller.enqueue({
2952
- type: "text-start",
2953
- id: textPartId
2954
- });
2955
- }
2956
- controller.enqueue({
2957
- type: "text-delta",
2958
- id: textPartId,
2959
- delta: deltaText
2960
- });
2961
- accumulatedText += deltaText;
2962
- streamedTextLength += deltaText.length;
2963
- emittedTextSinceLastAssistant += deltaText;
2964
- }
2965
- if (event.type === "content_block_delta" && event.delta.type === "input_json_delta" && "partial_json" in event.delta && event.delta.partial_json) {
2966
- const jsonDelta = event.delta.partial_json;
2967
- hasReceivedStreamEvents = true;
2968
- const blockIndex = "index" in event ? event.index : -1;
2969
- if (options.responseFormat?.type === "json") {
2970
- if (!textPartId) {
2971
- textPartId = (0, import_provider_utils.generateId)();
2972
- controller.enqueue({
2973
- type: "text-start",
2974
- id: textPartId
2975
- });
2976
- }
2977
- controller.enqueue({
2978
- type: "text-delta",
2979
- id: textPartId,
2980
- delta: jsonDelta
2981
- });
2982
- accumulatedText += jsonDelta;
2983
- streamedTextLength += jsonDelta.length;
2984
- hasStreamedJson = true;
2985
- continue;
2986
- }
2987
- const toolId = toolBlocksByIndex.get(blockIndex);
2988
- if (toolId) {
2989
- const accumulated = (toolInputAccumulators.get(toolId) ?? "") + jsonDelta;
2990
- toolInputAccumulators.set(toolId, accumulated);
2991
- controller.enqueue({
2992
- type: "tool-input-delta",
2993
- id: toolId,
2994
- delta: jsonDelta
2995
- });
2996
- continue;
2997
- }
2998
- }
2999
- if (event.type === "content_block_start" && "content_block" in event && event.content_block?.type === "tool_use") {
3000
- const blockIndex = "index" in event ? event.index : -1;
3001
- const toolBlock = event.content_block;
3002
- const toolId = typeof toolBlock.id === "string" && toolBlock.id.length > 0 ? toolBlock.id : (0, import_provider_utils.generateId)();
3003
- const toolName = typeof toolBlock.name === "string" && toolBlock.name.length > 0 ? toolBlock.name : _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
3004
- hasReceivedStreamEvents = true;
3005
- if (textPartId) {
3006
- const closedTextId = textPartId;
3007
- controller.enqueue({
3008
- type: "text-end",
3009
- id: closedTextId
3010
- });
3011
- textPartId = void 0;
3012
- for (const [idx, blockTextId] of textBlocksByIndex) {
3013
- if (blockTextId === closedTextId) {
3014
- textBlocksByIndex.delete(idx);
3015
- break;
3016
- }
3017
- }
3018
- }
3019
- toolBlocksByIndex.set(blockIndex, toolId);
3020
- toolInputAccumulators.set(toolId, "");
3021
- let state = toolStates.get(toolId);
3022
- if (!state) {
3023
- const partialParentId = message.parent_tool_use_id;
3024
- const currentParentId = isSubagentToolName(toolName) ? null : resolveToolParentId(partialParentId, void 0, getFallbackParentId);
3025
- const envelopeUuid = message.uuid;
3026
- state = {
3027
- name: toolName,
3028
- inputStarted: false,
3029
- inputClosed: false,
3030
- callEmitted: false,
3031
- parentToolCallId: currentParentId,
3032
- ...typeof envelopeUuid === "string" && { messageUuid: envelopeUuid }
3033
- };
3034
- toolStates.set(toolId, state);
3035
- }
3036
- if (!state.inputStarted) {
3037
- this.logger.debug(
3038
- `[claude-code] Tool input started (content_block) - Tool: ${toolName}, ID: ${toolId}, parent: ${state.parentToolCallId}`
3039
- );
3040
- controller.enqueue({
3041
- type: "tool-input-start",
3042
- id: toolId,
3043
- toolName,
3044
- providerExecuted: true,
3045
- dynamic: true,
3046
- providerMetadata: {
3047
- "claude-code": {
3048
- parentToolCallId: state.parentToolCallId ?? null
3049
- }
3050
- }
3051
- });
3052
- if (isSubagentToolName(toolName)) {
3053
- activeTaskTools.set(toolId, { startTime: Date.now() });
3054
- }
3055
- state.inputStarted = true;
3056
- }
3057
- continue;
3058
- }
3059
- if (event.type === "content_block_start" && "content_block" in event && event.content_block?.type === "text") {
3060
- const blockIndex = "index" in event ? event.index : -1;
3061
- hasReceivedStreamEvents = true;
3062
- const partId = (0, import_provider_utils.generateId)();
3063
- textBlocksByIndex.set(blockIndex, partId);
3064
- textPartId = partId;
3065
- this.logger.debug(
3066
- `[claude-code] Text content block started - Index: ${blockIndex}, ID: ${partId}`
3067
- );
3068
- controller.enqueue({
3069
- type: "text-start",
3070
- id: partId
3071
- });
3072
- textStreamedViaContentBlock = true;
3073
- continue;
3074
- }
3075
- if (event.type === "content_block_start" && "content_block" in event && event.content_block?.type === "thinking") {
3076
- const blockIndex = "index" in event ? event.index : -1;
3077
- hasReceivedStreamEvents = true;
3078
- if (textPartId) {
3079
- const closedTextId = textPartId;
3080
- controller.enqueue({
3081
- type: "text-end",
3082
- id: closedTextId
3083
- });
3084
- textPartId = void 0;
3085
- for (const [idx, blockTextId] of textBlocksByIndex) {
3086
- if (blockTextId === closedTextId) {
3087
- textBlocksByIndex.delete(idx);
3088
- break;
3089
- }
3090
- }
3091
- }
3092
- const reasoningPartId = (0, import_provider_utils.generateId)();
3093
- reasoningBlocksByIndex.set(blockIndex, reasoningPartId);
3094
- currentReasoningPartId = reasoningPartId;
3095
- this.logger.debug(
3096
- `[claude-code] Reasoning started (content_block) - ID: ${reasoningPartId}`
3097
- );
3098
- controller.enqueue({
3099
- type: "reasoning-start",
3100
- id: reasoningPartId
3101
- });
3102
- continue;
3103
- }
3104
- if (event.type === "content_block_delta" && event.delta.type === "thinking_delta" && "thinking" in event.delta && event.delta.thinking) {
3105
- const blockIndex = "index" in event ? event.index : -1;
3106
- const reasoningPartId = reasoningBlocksByIndex.get(blockIndex) ?? currentReasoningPartId;
3107
- hasReceivedStreamEvents = true;
3108
- if (reasoningPartId) {
3109
- controller.enqueue({
3110
- type: "reasoning-delta",
3111
- id: reasoningPartId,
3112
- delta: event.delta.thinking
3113
- });
3114
- }
3115
- continue;
3116
- }
3117
- if (event.type === "content_block_stop") {
3118
- const blockIndex = "index" in event ? event.index : -1;
3119
- hasReceivedStreamEvents = true;
3120
- const toolId = toolBlocksByIndex.get(blockIndex);
3121
- if (toolId) {
3122
- const state = toolStates.get(toolId);
3123
- if (state && !state.inputClosed) {
3124
- const accumulatedInput = toolInputAccumulators.get(toolId) ?? "";
3125
- this.logger.debug(
3126
- `[claude-code] Tool content block stopped - Index: ${blockIndex}, Tool: ${state.name}, ID: ${toolId}`
3127
- );
3128
- controller.enqueue({
3129
- type: "tool-input-end",
3130
- id: toolId
3131
- });
3132
- state.inputClosed = true;
3133
- const effectiveInput = accumulatedInput || state.lastSerializedInput || "";
3134
- state.lastSerializedInput = effectiveInput;
3135
- if (!state.callEmitted) {
3136
- controller.enqueue(
3137
- this.buildToolCallPart(
3138
- toolId,
3139
- state.name,
3140
- effectiveInput,
3141
- state.parentToolCallId
3142
- )
3143
- );
3144
- state.callEmitted = true;
3145
- }
3146
- }
3147
- toolBlocksByIndex.delete(blockIndex);
3148
- toolInputAccumulators.delete(toolId);
3149
- continue;
3150
- }
3151
- const textId = textBlocksByIndex.get(blockIndex);
3152
- if (textId) {
3153
- this.logger.debug(
3154
- `[claude-code] Text content block stopped - Index: ${blockIndex}, ID: ${textId}`
3155
- );
3156
- controller.enqueue({
3157
- type: "text-end",
3158
- id: textId
3159
- });
3160
- textBlocksByIndex.delete(blockIndex);
3161
- if (textPartId === textId) {
3162
- textPartId = void 0;
3163
- }
3164
- continue;
3165
- }
3166
- const reasoningPartId = reasoningBlocksByIndex.get(blockIndex);
3167
- if (reasoningPartId) {
3168
- this.logger.debug(
3169
- `[claude-code] Reasoning ended (content_block) - ID: ${reasoningPartId}`
3170
- );
3171
- controller.enqueue({
3172
- type: "reasoning-end",
3173
- id: reasoningPartId
3174
- });
3175
- reasoningBlocksByIndex.delete(blockIndex);
3176
- if (currentReasoningPartId === reasoningPartId) {
3177
- currentReasoningPartId = void 0;
3178
- }
3179
- continue;
3180
- }
3181
- }
3182
- continue;
3183
- }
3184
- if (message.type === "assistant") {
3185
- if (typeof message.error === "string") {
3186
- lastAssistantErrorKind = message.error;
3187
- }
3188
- const supersedesPriorMessages = applySupersede(message, evictLive, this.logger);
3189
- if (!message.message?.content) {
3190
- this.logger.warn(
3191
- `[claude-code] Unexpected assistant message structure: missing content field. Message type: ${message.type}. This may indicate an SDK protocol violation.`
3192
- );
3193
- continue;
3194
- }
3195
- const sdkParentToolUseId = message.parent_tool_use_id;
3196
- const content = message.message.content;
3197
- const tools = this.extractToolUses(content);
3198
- if (textPartId && tools.length > 0) {
3199
- const closedTextId = textPartId;
3200
- controller.enqueue({
3201
- type: "text-end",
3202
- id: closedTextId
3203
- });
3204
- textPartId = void 0;
3205
- for (const [idx, blockTextId] of textBlocksByIndex) {
3206
- if (blockTextId === closedTextId) {
3207
- textBlocksByIndex.delete(idx);
3208
- break;
3209
- }
3210
- }
3211
- }
3212
- for (const tool3 of tools) {
3213
- const toolId = tool3.id;
3214
- let state = toolStates.get(toolId);
3215
- if (!state) {
3216
- const currentParentId = isSubagentToolName(tool3.name) ? null : resolveToolParentId(
3217
- sdkParentToolUseId,
3218
- tool3.parentToolUseId,
3219
- getFallbackParentId
3220
- );
3221
- state = {
3222
- name: tool3.name,
3223
- inputStarted: false,
3224
- inputClosed: false,
3225
- callEmitted: false,
3226
- parentToolCallId: currentParentId,
3227
- ...typeof message.uuid === "string" && { messageUuid: message.uuid }
3228
- };
3229
- toolStates.set(toolId, state);
3230
- this.logger.debug(
3231
- `[claude-code] New tool use detected - Tool: ${tool3.name}, ID: ${toolId}, SDK parent: ${sdkParentToolUseId}, resolved parent: ${currentParentId}`
3232
- );
3233
- } else if (!state.parentToolCallId && sdkParentToolUseId && !isSubagentToolName(tool3.name)) {
3234
- state.parentToolCallId = sdkParentToolUseId;
3235
- this.logger.debug(
3236
- `[claude-code] Retroactive parent context - Tool: ${tool3.name}, ID: ${toolId}, parent: ${sdkParentToolUseId}`
3237
- );
3238
- }
3239
- state.name = tool3.name;
3240
- if (!state.inputStarted) {
3241
- this.logger.debug(
3242
- `[claude-code] Tool input started - Tool: ${tool3.name}, ID: ${toolId}`
3243
- );
3244
- controller.enqueue({
3245
- type: "tool-input-start",
3246
- id: toolId,
3247
- toolName: tool3.name,
3248
- providerExecuted: true,
3249
- dynamic: true,
3250
- // V3 field: indicates tool is provider-defined
3251
- providerMetadata: {
3252
- "claude-code": {
3253
- parentToolCallId: state.parentToolCallId ?? null
3254
- }
3255
- }
3256
- });
3257
- if (isSubagentToolName(tool3.name)) {
3258
- activeTaskTools.set(toolId, { startTime: Date.now() });
3259
- }
3260
- state.inputStarted = true;
3261
- }
3262
- const serializedInput = this.serializeToolInput(tool3.input);
3263
- if (serializedInput) {
3264
- let deltaPayload = "";
3265
- if (state.lastSerializedInput === void 0) {
3266
- if (serializedInput.length <= _ClaudeCodeLanguageModel.MAX_DELTA_CALC_SIZE) {
3267
- deltaPayload = serializedInput;
3268
- }
3269
- } else if (serializedInput.length <= _ClaudeCodeLanguageModel.MAX_DELTA_CALC_SIZE && state.lastSerializedInput.length <= _ClaudeCodeLanguageModel.MAX_DELTA_CALC_SIZE && serializedInput.startsWith(state.lastSerializedInput)) {
3270
- deltaPayload = serializedInput.slice(state.lastSerializedInput.length);
3271
- } else if (serializedInput !== state.lastSerializedInput) {
3272
- deltaPayload = "";
3273
- }
3274
- if (deltaPayload) {
3275
- controller.enqueue({
3276
- type: "tool-input-delta",
3277
- id: toolId,
3278
- delta: deltaPayload
3279
- });
3280
- }
3281
- state.lastSerializedInput = serializedInput;
3282
- }
3283
- }
3284
- const text = content.map((c) => c.type === "text" ? c.text : "").join("");
3285
- if (text) {
3286
- if (supersedesPriorMessages) {
3287
- textSegments.push({
3288
- ...typeof message.uuid === "string" && { uuid: message.uuid },
3289
- text
3290
- });
3291
- accumulatedText = textSegments.map((segment) => segment.text).join("");
3292
- if (emittedTextSinceLastAssistant === text) {
3293
- streamedTextLength = Math.max(streamedTextLength, text.length);
3294
- this.logger.debug(
3295
- "[claude-code] Skipping text emission for superseding assistant message (replacement already streamed)"
3296
- );
3297
- } else if (emittedTextSinceLastAssistant.length > 0 && text.startsWith(emittedTextSinceLastAssistant)) {
3298
- if (options.responseFormat?.type !== "json") {
3299
- const suffix = text.slice(emittedTextSinceLastAssistant.length);
3300
- if (suffix) {
3301
- if (!textPartId) {
3302
- textPartId = (0, import_provider_utils.generateId)();
3303
- controller.enqueue({ type: "text-start", id: textPartId });
3304
- }
3305
- controller.enqueue({
3306
- type: "text-delta",
3307
- id: textPartId,
3308
- delta: suffix
3309
- });
3310
- emittedTextSinceLastAssistant = text;
3311
- }
3312
- }
3313
- streamedTextLength = Math.max(streamedTextLength, text.length);
3314
- this.logger.debug(
3315
- "[claude-code] Emitted unstreamed suffix of superseding assistant message"
3316
- );
3317
- } else if (options.responseFormat?.type !== "json") {
3318
- if (textPartId) {
3319
- const closedTextId = textPartId;
3320
- controller.enqueue({
3321
- type: "text-end",
3322
- id: closedTextId
3323
- });
3324
- textPartId = void 0;
3325
- for (const [idx, blockTextId] of textBlocksByIndex) {
3326
- if (blockTextId === closedTextId) {
3327
- textBlocksByIndex.delete(idx);
3328
- break;
3329
- }
3330
- }
3331
- }
3332
- textPartId = (0, import_provider_utils.generateId)();
3333
- controller.enqueue({
3334
- type: "text-start",
3335
- id: textPartId
3336
- });
3337
- controller.enqueue({
3338
- type: "text-delta",
3339
- id: textPartId,
3340
- delta: text
3341
- });
3342
- streamedTextLength = Math.max(streamedTextLength, text.length);
3343
- this.logger.debug(
3344
- "[claude-code] Emitted superseding assistant message as a new text part (canonical replacement)"
3345
- );
3346
- }
3347
- } else if (hasReceivedStreamEvents) {
3348
- const newTextStart = streamedTextLength;
3349
- const deltaText = text.length > newTextStart ? text.slice(newTextStart) : "";
3350
- accumulatedText = text;
3351
- textSegments.length = 0;
3352
- textSegments.push({
3353
- ...typeof message.uuid === "string" && { uuid: message.uuid },
3354
- text
3355
- });
3356
- if (options.responseFormat?.type !== "json" && deltaText) {
3357
- if (!textPartId) {
3358
- textPartId = (0, import_provider_utils.generateId)();
3359
- controller.enqueue({
3360
- type: "text-start",
3361
- id: textPartId
3362
- });
3363
- }
3364
- controller.enqueue({
3365
- type: "text-delta",
3366
- id: textPartId,
3367
- delta: deltaText
3368
- });
3369
- }
3370
- streamedTextLength = text.length;
3371
- } else {
3372
- accumulatedText += text;
3373
- textSegments.push({
3374
- ...typeof message.uuid === "string" && { uuid: message.uuid },
3375
- text
3376
- });
3377
- if (options.responseFormat?.type !== "json") {
3378
- if (!textPartId) {
3379
- textPartId = (0, import_provider_utils.generateId)();
3380
- controller.enqueue({
3381
- type: "text-start",
3382
- id: textPartId
3383
- });
3384
- }
3385
- controller.enqueue({
3386
- type: "text-delta",
3387
- id: textPartId,
3388
- delta: text
3389
- });
3390
- }
3391
- }
3392
- }
3393
- emittedTextSinceLastAssistant = "";
3394
- } else if (message.type === "user") {
3395
- if (!message.message?.content) {
3396
- this.logger.warn(
3397
- `[claude-code] Unexpected user message structure: missing content field. Message type: ${message.type}. This may indicate an SDK protocol violation.`
3398
- );
3399
- continue;
3400
- }
3401
- if (textPartId) {
3402
- const closedTextId = textPartId;
3403
- controller.enqueue({
3404
- type: "text-end",
3405
- id: closedTextId
3406
- });
3407
- textPartId = void 0;
3408
- for (const [blockIndex, blockTextId] of textBlocksByIndex) {
3409
- if (blockTextId === closedTextId) {
3410
- textBlocksByIndex.delete(blockIndex);
3411
- break;
3412
- }
3413
- }
3414
- this.logger.debug("[claude-code] Closed text part due to user message");
3415
- }
3416
- accumulatedText = "";
3417
- textSegments.length = 0;
3418
- streamedTextLength = 0;
3419
- emittedTextSinceLastAssistant = "";
3420
- const sdkParentToolUseIdForResults = message.parent_tool_use_id;
3421
- const content = message.message.content;
3422
- for (const result of this.extractToolResults(content)) {
3423
- if (this.isRetractedToolFrame(result.id, retractedStreamToolIds, "result")) {
3424
- continue;
3425
- }
3426
- let state = toolStates.get(result.id);
3427
- const toolName = result.name ?? state?.name ?? _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
3428
- this.logger.debug(
3429
- `[claude-code] Tool result received - Tool: ${toolName}, ID: ${result.id}`
3430
- );
3431
- if (!state) {
3432
- this.logger.warn(
3433
- `[claude-code] Received tool result for unknown tool ID: ${result.id}`
3434
- );
3435
- const resolvedParentId = isSubagentToolName(toolName) ? null : resolveToolParentId(
3436
- sdkParentToolUseIdForResults,
3437
- void 0,
3438
- getFallbackParentId
3439
- );
3440
- state = {
3441
- name: toolName,
3442
- inputStarted: false,
3443
- inputClosed: false,
3444
- callEmitted: false,
3445
- parentToolCallId: resolvedParentId
3446
- };
3447
- toolStates.set(result.id, state);
3448
- if (!state.inputStarted) {
3449
- controller.enqueue({
3450
- type: "tool-input-start",
3451
- id: result.id,
3452
- toolName,
3453
- providerExecuted: true,
3454
- dynamic: true,
3455
- // V3 field: indicates tool is provider-defined
3456
- providerMetadata: {
3457
- "claude-code": {
3458
- parentToolCallId: state.parentToolCallId ?? null
3459
- }
3460
- }
3461
- });
3462
- state.inputStarted = true;
3463
- }
3464
- if (!state.inputClosed) {
3465
- controller.enqueue({
3466
- type: "tool-input-end",
3467
- id: result.id
3468
- });
3469
- state.inputClosed = true;
3470
- }
3471
- }
3472
- state.name = toolName;
3473
- emitToolCall(result.id, state);
3474
- if (isSubagentToolName(toolName)) {
3475
- activeTaskTools.delete(result.id);
3476
- }
3477
- controller.enqueue(
3478
- this.buildToolResultPart(
3479
- result.id,
3480
- toolName,
3481
- result.result,
3482
- result.isError,
3483
- state.parentToolCallId
3484
- )
3485
- );
3486
- }
3487
- for (const error of this.extractToolErrors(content)) {
3488
- if (this.isRetractedToolFrame(error.id, retractedStreamToolIds, "error")) {
3489
- continue;
3490
- }
3491
- let state = toolStates.get(error.id);
3492
- const toolName = error.name ?? state?.name ?? _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
3493
- this.logger.debug(
3494
- `[claude-code] Tool error received - Tool: ${toolName}, ID: ${error.id}`
3495
- );
3496
- if (!state) {
3497
- this.logger.warn(
3498
- `[claude-code] Received tool error for unknown tool ID: ${error.id}`
3499
- );
3500
- const errorResolvedParentId = isSubagentToolName(toolName) ? null : resolveToolParentId(
3501
- sdkParentToolUseIdForResults,
3502
- void 0,
3503
- getFallbackParentId
3504
- );
3505
- state = {
3506
- name: toolName,
3507
- inputStarted: true,
3508
- inputClosed: true,
3509
- callEmitted: false,
3510
- parentToolCallId: errorResolvedParentId
3511
- };
3512
- toolStates.set(error.id, state);
3513
- }
3514
- emitToolCall(error.id, state);
3515
- if (isSubagentToolName(toolName)) {
3516
- activeTaskTools.delete(error.id);
3517
- }
3518
- controller.enqueue(
3519
- this.buildToolErrorPart(error.id, toolName, error.error, state.parentToolCallId)
3520
- );
3521
- }
3522
- } else if (message.type === "result") {
3523
- done();
3524
- this.mergeResultPermissionDenials(message, metadataTracking);
3525
- if ("is_error" in message && message.is_error === true) {
3526
- const resultText = "result" in message && typeof message.result === "string" ? message.result : void 0;
3527
- const errorsText = "errors" in message && Array.isArray(message.errors) ? message.errors.filter((e) => typeof e === "string").join("; ") : "";
3528
- const errorMessage = resultText ?? (errorsText || "Claude Code CLI returned an error");
3529
- throw Object.assign(new Error(errorMessage), {
3530
- exitCode: 1,
3531
- errorKind: lastAssistantErrorKind
3532
- });
3533
- }
3534
- if (message.subtype === "error_max_structured_output_retries") {
3535
- throw new Error(
3536
- "Failed to generate valid structured output after maximum retries. The model could not produce a response matching the required schema."
3537
- );
3538
- }
3539
- this.logger.info(
3540
- `[claude-code] Stream completed - Session: ${message.session_id}, Cost: $${message.total_cost_usd?.toFixed(4) ?? "N/A"}, Duration: ${message.duration_ms ?? "N/A"}ms`
3541
- );
3542
- if ("usage" in message) {
3543
- usage = convertClaudeCodeUsage(message.usage);
3544
- this.logger.debug(
3545
- `[claude-code] Stream token usage - Input: ${usage.inputTokens.total}, Output: ${usage.outputTokens.total}`
3546
- );
3547
- }
3548
- const stopReason = "stop_reason" in message ? message.stop_reason : void 0;
3549
- const finishReason = mapClaudeCodeFinishReason(
3550
- message.subtype,
3551
- stopReason
3552
- );
3553
- this.logger.debug(`[claude-code] Stream finish reason: ${finishReason.unified}`);
3554
- this.setSessionId(message.session_id);
3555
- const structuredOutput = "structured_output" in message ? message.structured_output : void 0;
3556
- const alreadyStreamedJson = hasStreamedJson && options.responseFormat?.type === "json" && hasReceivedStreamEvents;
3557
- if (alreadyStreamedJson) {
3558
- if (textPartId) {
3559
- controller.enqueue({
3560
- type: "text-end",
3561
- id: textPartId
3562
- });
3563
- }
3564
- } else if (structuredOutput !== void 0) {
3565
- const jsonTextId = (0, import_provider_utils.generateId)();
3566
- const jsonText = JSON.stringify(structuredOutput);
3567
- controller.enqueue({
3568
- type: "text-start",
3569
- id: jsonTextId
3570
- });
3571
- controller.enqueue({
3572
- type: "text-delta",
3573
- id: jsonTextId,
3574
- delta: jsonText
3575
- });
3576
- controller.enqueue({
3577
- type: "text-end",
3578
- id: jsonTextId
3579
- });
3580
- } else if (options.responseFormat?.type === "json" && options.responseFormat.schema !== void 0 && finishReason.unified === "stop") {
3581
- const recoveredJsonText = extractJsonObjectText(accumulatedText);
3582
- if (recoveredJsonText === void 0) {
3583
- throw createAPICallError({
3584
- message: MISSING_STRUCTURED_OUTPUT_ERROR_MESSAGE,
3585
- promptExcerpt: messagesPrompt.substring(0, 200),
3586
- isRetryable: false
3587
- });
3588
- }
3589
- this.logger.warn(
3590
- "[claude-code] outputFormat was requested but the CLI returned no structured_output; recovered JSON by parsing the prose response. The schema likely contains constructs the CLI cannot enforce - see the README structured-output limitations."
3591
- );
3592
- if (textPartId) {
3593
- controller.enqueue({
3594
- type: "text-end",
3595
- id: textPartId
3596
- });
3597
- }
3598
- const recoveredTextId = (0, import_provider_utils.generateId)();
3599
- controller.enqueue({
3600
- type: "text-start",
3601
- id: recoveredTextId
3602
- });
3603
- controller.enqueue({
3604
- type: "text-delta",
3605
- id: recoveredTextId,
3606
- delta: recoveredJsonText
3607
- });
3608
- controller.enqueue({
3609
- type: "text-end",
3610
- id: recoveredTextId
3611
- });
3612
- } else if (textPartId) {
3613
- controller.enqueue({
3614
- type: "text-end",
3615
- id: textPartId
3616
- });
3617
- } else if (accumulatedText && !textStreamedViaContentBlock) {
3618
- const fallbackTextId = (0, import_provider_utils.generateId)();
3619
- controller.enqueue({
3620
- type: "text-start",
3621
- id: fallbackTextId
3622
- });
3623
- controller.enqueue({
3624
- type: "text-delta",
3625
- id: fallbackTextId,
3626
- delta: accumulatedText
3627
- });
3628
- controller.enqueue({
3629
- type: "text-end",
3630
- id: fallbackTextId
3631
- });
3632
- }
3633
- finalizeToolCalls();
3634
- const warningsJson = this.serializeWarningsForMetadata(streamWarnings);
3635
- controller.enqueue({
3636
- type: "finish",
3637
- finishReason,
3638
- usage,
3639
- providerMetadata: {
3640
- "claude-code": {
3641
- sessionId: message.session_id,
3642
- ...message.total_cost_usd !== void 0 && {
3643
- costUsd: message.total_cost_usd
3644
- },
3645
- ...message.duration_ms !== void 0 && { durationMs: message.duration_ms },
3646
- ...message.modelUsage !== void 0 && {
3647
- modelUsage: message.modelUsage
3648
- },
3649
- // SDK 0.3.x timing metadata (ttft_* only present on SDKResultSuccess)
3650
- ..."ttft_ms" in message && message.ttft_ms !== void 0 && { ttftMs: message.ttft_ms },
3651
- ..."ttft_stream_ms" in message && message.ttft_stream_ms !== void 0 && {
3652
- ttftStreamMs: message.ttft_stream_ms
3653
- },
3654
- ..."time_to_request_ms" in message && message.time_to_request_ms !== void 0 && {
3655
- timeToRequestMs: message.time_to_request_ms
3656
- },
3657
- ..."warm_spare_claimed" in message && message.warm_spare_claimed !== void 0 && {
3658
- warmSpareClaimed: message.warm_spare_claimed
3659
- },
3660
- ...message.terminal_reason !== void 0 && {
3661
- terminalReason: message.terminal_reason
3662
- },
3663
- ...metadataTracking.apiRetries > 0 && {
3664
- apiRetries: metadataTracking.apiRetries
3665
- },
3666
- ...metadataTracking.permissionDenials.length > 0 && {
3667
- permissionDenials: metadataTracking.permissionDenials
3668
- },
3669
- ...metadataTracking.mirrorErrors.length > 0 && {
3670
- mirrorErrors: metadataTracking.mirrorErrors
3671
- },
3672
- ...metadataTracking.estimatedThinkingTokens > 0 && {
3673
- estimatedThinkingTokens: metadataTracking.estimatedThinkingTokens
3674
- },
3675
- // JSON validation warnings are collected during streaming and included
3676
- // in providerMetadata since the AI SDK's finish event doesn't support
3677
- // a top-level warnings field (unlike stream-start which was already emitted)
3678
- ...streamWarnings.length > 0 && {
3679
- warnings: warningsJson
3680
- }
3681
- }
3682
- }
3683
- });
3684
- controller.close();
3685
- const effectivePromptSuggestions = sdkOptions?.promptSuggestions ?? this.settings.promptSuggestions;
3686
- if (this.settings.onPromptSuggestion && effectivePromptSuggestions !== false) {
3687
- await this.drainPromptSuggestion(response, this.settings.onPromptSuggestion);
3688
- }
3689
- return;
3690
- } else if (message.type === "system" && message.subtype === "init") {
3691
- this.logMcpConnectionIssues(message.mcp_servers);
3692
- this.setSessionId(message.session_id);
3693
- this.logger.info(`[claude-code] Stream session initialized: ${message.session_id}`);
3694
- controller.enqueue({
3695
- type: "response-metadata",
3696
- id: message.session_id,
3697
- timestamp: /* @__PURE__ */ new Date(),
3698
- modelId: this.modelId
3699
- });
3700
- } else if (message.type === "system") {
3701
- this.handleSystemMessage(
3702
- message,
3703
- metadataTracking,
3704
- buildRetractionEvictor(evictLive)
3705
- );
3706
- } else if (message.type === "prompt_suggestion") {
3707
- this.logger.debug("[claude-code] Received prompt suggestion");
3708
- this.settings.onPromptSuggestion?.(message.suggestion);
3709
- }
3710
- }
3711
- finalizeToolCalls();
3712
- this.logger.debug("[claude-code] Stream finalized, closing stream");
3713
- controller.close();
3714
- } catch (error) {
3715
- done();
3716
- this.logger.debug(
3717
- `[claude-code] Error during doStream: ${error instanceof Error ? error.message : String(error)}`
3718
- );
3719
- if (isClaudeCodeTruncationError(error, accumulatedText)) {
3720
- this.logger.warn(
3721
- `[claude-code] Detected truncated stream response, returning ${accumulatedText.length} characters of buffered text`
3722
- );
3723
- const truncationWarning = {
3724
- type: "other",
3725
- message: CLAUDE_CODE_TRUNCATION_WARNING
3726
- };
3727
- streamWarnings.push(truncationWarning);
3728
- if (textPartId) {
3729
- controller.enqueue({
3730
- type: "text-end",
3731
- id: textPartId
3732
- });
3733
- } else if (accumulatedText && !textStreamedViaContentBlock) {
3734
- const fallbackTextId = (0, import_provider_utils.generateId)();
3735
- controller.enqueue({
3736
- type: "text-start",
3737
- id: fallbackTextId
3738
- });
3739
- controller.enqueue({
3740
- type: "text-delta",
3741
- id: fallbackTextId,
3742
- delta: accumulatedText
3743
- });
3744
- controller.enqueue({
3745
- type: "text-end",
3746
- id: fallbackTextId
3747
- });
3748
- }
3749
- finalizeToolCalls();
3750
- const warningsJson = this.serializeWarningsForMetadata(streamWarnings);
3751
- controller.enqueue({
3752
- type: "finish",
3753
- finishReason: { unified: "length", raw: "truncation" },
3754
- usage,
3755
- providerMetadata: {
3756
- "claude-code": {
3757
- ...this.sessionId !== void 0 && { sessionId: this.sessionId },
3758
- truncated: true,
3759
- ...metadataTracking.apiRetries > 0 && {
3760
- apiRetries: metadataTracking.apiRetries
3761
- },
3762
- ...metadataTracking.permissionDenials.length > 0 && {
3763
- permissionDenials: metadataTracking.permissionDenials
3764
- },
3765
- ...metadataTracking.mirrorErrors.length > 0 && {
3766
- mirrorErrors: metadataTracking.mirrorErrors
3767
- },
3768
- ...metadataTracking.estimatedThinkingTokens > 0 && {
3769
- estimatedThinkingTokens: metadataTracking.estimatedThinkingTokens
3770
- },
3771
- ...streamWarnings.length > 0 && {
3772
- warnings: warningsJson
3773
- }
3774
- }
3775
- }
3776
- });
3777
- controller.close();
3778
- return;
3779
- }
3780
- finalizeToolCalls();
3781
- let errorToEmit;
3782
- if (isAbortError(error)) {
3783
- errorToEmit = options.abortSignal?.aborted ? options.abortSignal.reason : error;
3784
- } else {
3785
- errorToEmit = this.handleClaudeCodeError(error, messagesPrompt, collectedStderr);
3786
- }
3787
- controller.enqueue({
3788
- type: "error",
3789
- error: errorToEmit
3790
- });
3791
- controller.close();
3792
- } finally {
3793
- if (options.abortSignal && abortListener) {
3794
- options.abortSignal.removeEventListener("abort", abortListener);
3795
- }
3796
- }
3797
- },
3798
- cancel: () => {
3799
- if (options.abortSignal && abortListener) {
3800
- options.abortSignal.removeEventListener("abort", abortListener);
3801
- }
3802
- }
3803
- });
3804
- return {
3805
- stream,
3806
- request: {
3807
- body: messagesPrompt
3808
- }
3809
- };
3810
- }
3811
- serializeWarningsForMetadata(warnings) {
3812
- const result = warnings.map((w) => {
3813
- const base = { type: w.type };
3814
- if ("message" in w) {
3815
- const m = w.message;
3816
- if (m !== void 0) base.message = String(m);
3817
- }
3818
- if (w.type === "unsupported" || w.type === "compatibility") {
3819
- const feature = w.feature;
3820
- if (feature !== void 0) base.feature = String(feature);
3821
- if ("details" in w) {
3822
- const d = w.details;
3823
- if (d !== void 0) base.details = String(d);
3824
- }
3825
- }
3826
- return base;
3827
- });
3828
- return result;
3829
- }
3830
- };
3831
-
3832
- // src/claude-code-provider.ts
3833
- function createClaudeCode(options = {}) {
3834
- const logger = getLogger(options.defaultSettings?.logger);
3835
- if (options.defaultSettings) {
3836
- const validation = validateSettings(options.defaultSettings);
3837
- if (!validation.valid) {
3838
- throw new Error(`Invalid default settings: ${validation.errors.join(", ")}`);
3839
- }
3840
- if (validation.warnings.length > 0) {
3841
- validation.warnings.forEach((warning) => logger.warn(`Claude Code Provider: ${warning}`));
3842
- }
3843
- }
3844
- const createModel = (modelId, settings = {}) => {
3845
- const mergedSettings = {
3846
- ...options.defaultSettings,
3847
- ...settings
3848
- };
3849
- const validation = validateSettings(mergedSettings);
3850
- if (!validation.valid) {
3851
- throw new Error(`Invalid settings: ${validation.errors.join(", ")}`);
3852
- }
3853
- return new ClaudeCodeLanguageModel({
3854
- id: modelId,
3855
- settings: mergedSettings,
3856
- settingsValidationWarnings: validation.warnings
3857
- });
3858
- };
3859
- const provider = function(modelId, settings) {
3860
- if (new.target) {
3861
- throw new Error("The Claude Code model function cannot be called with the new keyword.");
3862
- }
3863
- return createModel(modelId, settings);
3864
- };
3865
- provider.languageModel = createModel;
3866
- provider.chat = createModel;
3867
- provider.specificationVersion = "v3";
3868
- provider.embeddingModel = (modelId) => {
3869
- throw new import_provider3.NoSuchModelError({
3870
- modelId,
3871
- modelType: "embeddingModel"
3872
- });
3873
- };
3874
- provider.imageModel = (modelId) => {
3875
- throw new import_provider3.NoSuchModelError({
3876
- modelId,
3877
- modelType: "imageModel"
3878
- });
3879
- };
3880
- return provider;
3881
- }
3882
- var claudeCode = createClaudeCode();
3883
-
3884
- // src/index.ts
3885
- var import_claude_agent_sdk3 = require("@anthropic-ai/claude-agent-sdk");
3886
- var import_claude_agent_sdk4 = require("@anthropic-ai/claude-agent-sdk");
3887
- var import_claude_agent_sdk5 = require("@anthropic-ai/claude-agent-sdk");
3888
-
3889
- // src/mcp-helpers.ts
3890
- var import_claude_agent_sdk2 = require("@anthropic-ai/claude-agent-sdk");
3891
- var import_zod2 = require("zod");
3892
- function buildIsErrorResult(text) {
3893
- return {
3894
- isError: true,
3895
- content: [{ type: "text", text }]
3896
- };
3897
- }
3898
- async function normalizeToolResultToText(toolName, result) {
3899
- if (result != null && typeof result[Symbol.asyncIterator] === "function") {
3900
- let last;
3901
- for await (const chunk of result) {
3902
- last = chunk;
3903
- }
3904
- result = last;
3905
- }
3906
- if (typeof result === "string") {
3907
- return { text: result };
3908
- }
3909
- try {
3910
- return { text: JSON.stringify(result) ?? "undefined" };
3911
- } catch (serializationError) {
3912
- const reason = serializationError instanceof Error ? serializationError.message : String(serializationError);
3913
- return {
3914
- isError: buildIsErrorResult(
3915
- `Tool "${toolName}" succeeded but its result could not be serialized to JSON: ${reason}`
3916
- )
3917
- };
3918
- }
3919
- }
3920
- function createCustomMcpServer(config) {
3921
- const defs = Object.entries(config.tools).map(
3922
- ([name, def]) => (0, import_claude_agent_sdk2.tool)(
3923
- name,
3924
- def.description,
3925
- def.inputSchema.shape,
3926
- (args, extra) => def.handler(args, extra),
3927
- def.annotations ? { annotations: def.annotations } : void 0
3928
- )
3929
- );
3930
- return (0, import_claude_agent_sdk2.createSdkMcpServer)({ name: config.name, version: config.version, tools: defs });
3931
- }
3932
- var AI_SDK_SCHEMA_SYMBOL = Symbol.for("vercel.ai.schema");
3933
- function isAiSdkJsonSchema(schema) {
3934
- return typeof schema === "object" && schema !== null && AI_SDK_SCHEMA_SYMBOL in schema;
3935
- }
3936
- function isZodObjectSchema(schema) {
3937
- if (typeof schema !== "object" || schema === null) {
3938
- return false;
3939
- }
3940
- const candidate = schema;
3941
- if (!("_zod" in candidate) && !("_def" in candidate)) {
3942
- return false;
3943
- }
3944
- const typeTag = candidate._zod?.def?.type ?? candidate._def?.typeName;
3945
- if (typeTag !== "object" && typeTag !== "ZodObject") {
3946
- return false;
3947
- }
3948
- return typeof candidate.shape === "object" && candidate.shape !== null;
3949
- }
3950
- function createAiSdkMcpServer(name, tools) {
3951
- const defs = Object.entries(tools).map(([toolName, def]) => {
3952
- const execute = def.execute;
3953
- if (typeof execute !== "function") {
3954
- throw new Error(
3955
- `createAiSdkMcpServer: tool "${toolName}" has no execute function. Only tools that execute locally can be bridged to the Claude Code CLI.`
3956
- );
3957
- }
3958
- if (isAiSdkJsonSchema(def.inputSchema)) {
3959
- throw new Error(
3960
- `createAiSdkMcpServer: tool "${toolName}" uses a JSON Schema-based inputSchema (e.g. the AI SDK's jsonSchema() helper). Only Zod object schemas are supported because the Agent SDK's tool() requires a Zod shape. Define inputSchema with z.object({...}) instead.`
3961
- );
3962
- }
3963
- if (!isZodObjectSchema(def.inputSchema)) {
3964
- throw new Error(
3965
- `createAiSdkMcpServer: tool "${toolName}" has an inputSchema that is not a Zod object schema. Pass the same z.object({...}) schema you would give to the AI SDK tool() helper.`
3966
- );
3967
- }
3968
- const zodSchema = def.inputSchema;
3969
- return (0, import_claude_agent_sdk2.tool)(
3970
- toolName,
3971
- def.description ?? "",
3972
- zodSchema.shape,
3973
- async (args, extra) => {
3974
- try {
3975
- const extraInfo = extra ?? {};
3976
- const result = await execute.call(def, args, {
3977
- toolCallId: extraInfo.requestId !== void 0 ? String(extraInfo.requestId) : void 0,
3978
- abortSignal: extraInfo.signal
3979
- });
3980
- const normalized = await normalizeToolResultToText(toolName, result);
3981
- if ("isError" in normalized) {
3982
- return normalized.isError;
3983
- }
3984
- return { content: [{ type: "text", text: normalized.text }] };
3985
- } catch (error) {
3986
- return buildIsErrorResult(error instanceof Error ? error.message : String(error));
3987
- }
3988
- }
3989
- );
3990
- });
3991
- return (0, import_claude_agent_sdk2.createSdkMcpServer)({ name, tools: defs });
3992
- }
3993
- // Annotate the CommonJS export names for ESM import in node:
3994
- 0 && (module.exports = {
3995
- AbortError,
3996
- ClaudeCodeLanguageModel,
3997
- HOOK_EVENTS,
3998
- InMemorySessionStore,
3999
- SYSTEM_PROMPT_DYNAMIC_BOUNDARY,
4000
- claudeCode,
4001
- createAPICallError,
4002
- createAiSdkMcpServer,
4003
- createAuthenticationError,
4004
- createClaudeCode,
4005
- createCustomMcpServer,
4006
- createSdkMcpServer,
4007
- createTimeoutError,
4008
- deleteSession,
4009
- foldSessionSummary,
4010
- forkSession,
4011
- getErrorMetadata,
4012
- getSessionInfo,
4013
- getSessionMessages,
4014
- getSubagentMessages,
4015
- importSessionToStore,
4016
- isAuthenticationError,
4017
- isTimeoutError,
4018
- listSessions,
4019
- listSubagents,
4020
- renameSession,
4021
- startup,
4022
- tagSession,
4023
- tool
4024
- });
4025
- //# sourceMappingURL=index.cjs.map