ai-sdk-provider-claude-code 3.4.4 → 3.5.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/README.md +312 -51
- package/dist/index.cjs +1589 -175
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +481 -31
- package/dist/index.d.ts +481 -31
- package/dist/index.js +1593 -177
- package/dist/index.js.map +1 -1
- package/docs/ai-sdk-v4/GUIDE.md +2 -0
- package/docs/ai-sdk-v4/README.md +7 -0
- package/docs/ai-sdk-v5/GUIDE.md +2 -0
- package/docs/ai-sdk-v5/README.md +10 -0
- package/docs/sessions.md +117 -0
- package/package.json +9 -2
package/dist/index.js
CHANGED
|
@@ -2,12 +2,29 @@
|
|
|
2
2
|
import { NoSuchModelError as NoSuchModelError2 } from "@ai-sdk/provider";
|
|
3
3
|
|
|
4
4
|
// src/claude-code-language-model.ts
|
|
5
|
-
import { NoSuchModelError } from "@ai-sdk/provider";
|
|
5
|
+
import { NoSuchModelError, APICallError as APICallError2, LoadAPIKeyError as LoadAPIKeyError2 } from "@ai-sdk/provider";
|
|
6
6
|
import { generateId } from "@ai-sdk/provider-utils";
|
|
7
7
|
|
|
8
8
|
// src/convert-to-claude-code-messages.ts
|
|
9
9
|
var IMAGE_URL_WARNING = "Image URLs are not supported by this provider; supply base64/data URLs.";
|
|
10
10
|
var IMAGE_CONVERSION_WARNING = "Unable to convert image content; supply base64/data URLs.";
|
|
11
|
+
var MAX_TOOL_CALL_INPUT_LENGTH = 1e3;
|
|
12
|
+
function serializeToolCallInput(input) {
|
|
13
|
+
let serialized;
|
|
14
|
+
if (input === void 0) {
|
|
15
|
+
serialized = "";
|
|
16
|
+
} else {
|
|
17
|
+
try {
|
|
18
|
+
serialized = JSON.stringify(input) ?? String(input);
|
|
19
|
+
} catch {
|
|
20
|
+
serialized = String(input);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (serialized.length > MAX_TOOL_CALL_INPUT_LENGTH) {
|
|
24
|
+
return `${serialized.slice(0, MAX_TOOL_CALL_INPUT_LENGTH)}...[truncated]`;
|
|
25
|
+
}
|
|
26
|
+
return serialized;
|
|
27
|
+
}
|
|
11
28
|
function normalizeBase64(base64) {
|
|
12
29
|
return base64.replace(/\s+/g, "");
|
|
13
30
|
}
|
|
@@ -190,8 +207,9 @@ function convertToClaudeCodeMessages(prompt) {
|
|
|
190
207
|
}
|
|
191
208
|
const toolCalls = message.content.filter((part) => part.type === "tool-call");
|
|
192
209
|
if (toolCalls.length > 0) {
|
|
193
|
-
|
|
194
|
-
|
|
210
|
+
const serializedCalls = toolCalls.map((call) => `[Tool call: ${call.toolName}(${serializeToolCallInput(call.input)})]`).join("\n");
|
|
211
|
+
assistantContent += assistantContent ? `
|
|
212
|
+
${serializedCalls}` : serializedCalls;
|
|
195
213
|
}
|
|
196
214
|
}
|
|
197
215
|
const formattedAssistant = `Assistant: ${assistantContent}`;
|
|
@@ -400,6 +418,9 @@ function mapClaudeCodeFinishReason(subtype, stopReason) {
|
|
|
400
418
|
// src/validation.ts
|
|
401
419
|
import { z } from "zod";
|
|
402
420
|
import { existsSync } from "fs";
|
|
421
|
+
function isBlankResume(value) {
|
|
422
|
+
return typeof value === "string" && value.trim() === "";
|
|
423
|
+
}
|
|
403
424
|
var loggerFunctionSchema = z.object({
|
|
404
425
|
debug: z.any().refine((val) => typeof val === "function", {
|
|
405
426
|
message: "debug must be a function"
|
|
@@ -420,23 +441,29 @@ var claudeCodeSettingsSchema = z.object({
|
|
|
420
441
|
appendSystemPrompt: z.string().optional(),
|
|
421
442
|
systemPrompt: z.union([
|
|
422
443
|
z.string(),
|
|
444
|
+
z.array(z.string()),
|
|
423
445
|
z.object({
|
|
424
446
|
type: z.literal("preset"),
|
|
425
447
|
preset: z.literal("claude_code"),
|
|
426
|
-
append: z.string().optional()
|
|
448
|
+
append: z.string().optional(),
|
|
449
|
+
excludeDynamicSections: z.boolean().optional()
|
|
427
450
|
})
|
|
428
451
|
]).optional(),
|
|
429
452
|
maxTurns: z.number().int().min(1).max(100).optional(),
|
|
430
453
|
maxThinkingTokens: z.number().int().positive().max(1e5).optional(),
|
|
431
454
|
thinking: z.union([
|
|
432
|
-
z.object({
|
|
455
|
+
z.object({
|
|
456
|
+
type: z.literal("adaptive"),
|
|
457
|
+
display: z.enum(["summarized", "omitted"]).optional()
|
|
458
|
+
}).strict(),
|
|
433
459
|
z.object({
|
|
434
460
|
type: z.literal("enabled"),
|
|
435
|
-
budgetTokens: z.number().int().positive().optional()
|
|
461
|
+
budgetTokens: z.number().int().positive().optional(),
|
|
462
|
+
display: z.enum(["summarized", "omitted"]).optional()
|
|
436
463
|
}).strict(),
|
|
437
464
|
z.object({ type: z.literal("disabled") }).strict()
|
|
438
465
|
]).optional(),
|
|
439
|
-
effort: z.enum(["low", "medium", "high", "max"]).optional(),
|
|
466
|
+
effort: z.enum(["low", "medium", "high", "xhigh", "max"]).optional(),
|
|
440
467
|
promptSuggestions: z.boolean().optional(),
|
|
441
468
|
cwd: z.string().refine(
|
|
442
469
|
(val) => {
|
|
@@ -449,11 +476,19 @@ var claudeCodeSettingsSchema = z.object({
|
|
|
449
476
|
).optional(),
|
|
450
477
|
executable: z.enum(["bun", "deno", "node"]).optional(),
|
|
451
478
|
executableArgs: z.array(z.string()).optional(),
|
|
452
|
-
|
|
479
|
+
// Mirrors the SDK 0.3.x PermissionMode union ('auto' and 'dontAsk' were
|
|
480
|
+
// added in 0.3.x; 'delegate' was dropped AND is rejected by the CLI's
|
|
481
|
+
// --permission-mode flag parser, so it is rejected here too).
|
|
482
|
+
permissionMode: z.enum(["default", "acceptEdits", "bypassPermissions", "plan", "dontAsk", "auto"]).optional(),
|
|
453
483
|
permissionPromptToolName: z.string().optional(),
|
|
454
484
|
continue: z.boolean().optional(),
|
|
455
485
|
resume: z.string().optional(),
|
|
456
|
-
|
|
486
|
+
// The CLI rejects --session-id values that are not valid UUIDs, so
|
|
487
|
+
// enforce the UUID shape here instead of failing at query time.
|
|
488
|
+
sessionId: z.string().refine(
|
|
489
|
+
(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),
|
|
490
|
+
{ message: "sessionId must be a valid UUID (the CLI rejects non-UUID session IDs)" }
|
|
491
|
+
).optional(),
|
|
457
492
|
allowedTools: z.array(z.string()).optional(),
|
|
458
493
|
disallowedTools: z.array(z.string()).optional(),
|
|
459
494
|
betas: z.array(z.string()).optional(),
|
|
@@ -462,7 +497,9 @@ var claudeCodeSettingsSchema = z.object({
|
|
|
462
497
|
maxBudgetUsd: z.number().min(0).optional(),
|
|
463
498
|
plugins: z.array(
|
|
464
499
|
z.object({
|
|
465
|
-
|
|
500
|
+
// SDK SdkPluginConfig: only 'local' is supported; the SDK throws
|
|
501
|
+
// 'Unsupported plugin type' at query time for anything else.
|
|
502
|
+
type: z.literal("local"),
|
|
466
503
|
path: z.string()
|
|
467
504
|
}).passthrough()
|
|
468
505
|
).optional(),
|
|
@@ -477,12 +514,41 @@ var claudeCodeSettingsSchema = z.object({
|
|
|
477
514
|
preset: z.literal("claude_code")
|
|
478
515
|
})
|
|
479
516
|
]).optional(),
|
|
517
|
+
skills: z.union([z.array(z.string()), z.literal("all")]).optional(),
|
|
518
|
+
settings: z.union([
|
|
519
|
+
z.string(),
|
|
520
|
+
z.record(z.string(), z.any())
|
|
521
|
+
// inline Settings object
|
|
522
|
+
]).optional(),
|
|
523
|
+
managedSettings: z.record(z.string(), z.any()).optional(),
|
|
524
|
+
toolAliases: z.record(z.string(), z.string()).optional(),
|
|
525
|
+
toolConfig: z.object({
|
|
526
|
+
askUserQuestion: z.object({
|
|
527
|
+
previewFormat: z.enum(["markdown", "html"]).optional()
|
|
528
|
+
}).passthrough().optional()
|
|
529
|
+
}).passthrough().optional(),
|
|
530
|
+
planModeInstructions: z.string().optional(),
|
|
531
|
+
title: z.string().optional(),
|
|
532
|
+
forwardSubagentText: z.boolean().optional(),
|
|
533
|
+
agentProgressSummaries: z.boolean().optional(),
|
|
534
|
+
includeHookEvents: z.boolean().optional(),
|
|
535
|
+
taskBudget: z.object({ total: z.number().positive() }).strict().optional(),
|
|
536
|
+
sessionStore: z.any().refine(
|
|
537
|
+
(val) => val === void 0 || typeof val === "object" && val !== null && typeof val.append === "function" && typeof val.load === "function",
|
|
538
|
+
{ message: "sessionStore must be an object with append() and load() functions" }
|
|
539
|
+
).optional(),
|
|
540
|
+
sessionStoreFlush: z.enum(["batched", "eager"]).optional(),
|
|
541
|
+
loadTimeoutMs: z.number().int().positive().optional(),
|
|
480
542
|
settingSources: z.array(z.enum(["user", "project", "local"])).optional(),
|
|
481
543
|
streamingInput: z.enum(["auto", "always", "off"]).optional(),
|
|
482
544
|
// Hooks and tool-permission callback (permissive validation of shapes)
|
|
483
545
|
canUseTool: z.any().refine((v) => v === void 0 || typeof v === "function", {
|
|
484
546
|
message: "canUseTool must be a function"
|
|
485
547
|
}).optional(),
|
|
548
|
+
onUserDialog: z.any().refine((v) => v === void 0 || typeof v === "function", {
|
|
549
|
+
message: "onUserDialog must be a function"
|
|
550
|
+
}).optional(),
|
|
551
|
+
supportedDialogKinds: z.array(z.string()).optional(),
|
|
486
552
|
hooks: z.record(
|
|
487
553
|
z.string(),
|
|
488
554
|
z.array(
|
|
@@ -535,7 +601,8 @@ var claudeCodeSettingsSchema = z.object({
|
|
|
535
601
|
tools: z.array(z.string()).optional(),
|
|
536
602
|
disallowedTools: z.array(z.string()).optional(),
|
|
537
603
|
prompt: z.string(),
|
|
538
|
-
|
|
604
|
+
// SDK 0.3.x AgentDefinition accepts any model alias or full model ID
|
|
605
|
+
model: z.string().optional(),
|
|
539
606
|
mcpServers: z.array(
|
|
540
607
|
z.union([
|
|
541
608
|
z.string(),
|
|
@@ -566,10 +633,14 @@ var claudeCodeSettingsSchema = z.object({
|
|
|
566
633
|
}).optional(),
|
|
567
634
|
onStreamStart: z.any().refine((val) => val === void 0 || typeof val === "function", {
|
|
568
635
|
message: "onStreamStart must be a function"
|
|
636
|
+
}).optional(),
|
|
637
|
+
// Callback invoked with the predicted next user prompt (active unless promptSuggestions: false)
|
|
638
|
+
onPromptSuggestion: z.any().refine((val) => val === void 0 || typeof val === "function", {
|
|
639
|
+
message: "onPromptSuggestion must be a function"
|
|
569
640
|
}).optional()
|
|
570
641
|
}).strict();
|
|
571
642
|
function validateModelId(modelId) {
|
|
572
|
-
const knownModels = ["opus", "sonnet", "haiku"];
|
|
643
|
+
const knownModels = ["opus", "sonnet", "haiku", "fable"];
|
|
573
644
|
if (!modelId || modelId.trim() === "") {
|
|
574
645
|
throw new Error("Model ID cannot be empty");
|
|
575
646
|
}
|
|
@@ -593,6 +664,51 @@ function validateSettings(settings) {
|
|
|
593
664
|
return { valid: false, warnings, errors };
|
|
594
665
|
}
|
|
595
666
|
const validSettings = result.data;
|
|
667
|
+
const sdkOptionsRecord = validSettings.sdkOptions;
|
|
668
|
+
const effective = (key) => {
|
|
669
|
+
const override = sdkOptionsRecord?.[key];
|
|
670
|
+
return override !== void 0 ? override : validSettings[key];
|
|
671
|
+
};
|
|
672
|
+
const effSessionStore = effective("sessionStore");
|
|
673
|
+
const effectiveResumeId = () => {
|
|
674
|
+
for (const candidate of [sdkOptionsRecord?.resume, validSettings.resume]) {
|
|
675
|
+
if (typeof candidate === "string" && !isBlankResume(candidate)) {
|
|
676
|
+
return candidate;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
return void 0;
|
|
680
|
+
};
|
|
681
|
+
if (effSessionStore !== void 0 && effective("persistSession") === false) {
|
|
682
|
+
errors.push(
|
|
683
|
+
"sessionStore cannot be combined with persistSession: false. Transcript mirroring requires local session writes; remove persistSession: false or drop sessionStore."
|
|
684
|
+
);
|
|
685
|
+
return { valid: false, warnings, errors };
|
|
686
|
+
}
|
|
687
|
+
if (effSessionStore !== void 0 && effective("enableFileCheckpointing") === true) {
|
|
688
|
+
errors.push(
|
|
689
|
+
"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."
|
|
690
|
+
);
|
|
691
|
+
return { valid: false, warnings, errors };
|
|
692
|
+
}
|
|
693
|
+
if (effective("continue") === true && effSessionStore !== void 0 && effectiveResumeId() === void 0 && typeof effSessionStore.listSessions !== "function") {
|
|
694
|
+
errors.push(
|
|
695
|
+
"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."
|
|
696
|
+
);
|
|
697
|
+
return { valid: false, warnings, errors };
|
|
698
|
+
}
|
|
699
|
+
const effSettingsOption = effective("settings");
|
|
700
|
+
if (effective("sandbox") !== void 0 && typeof effSettingsOption === "string" && !(effSettingsOption.trim().startsWith("{") && effSettingsOption.trim().endsWith("}"))) {
|
|
701
|
+
errors.push(
|
|
702
|
+
"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."
|
|
703
|
+
);
|
|
704
|
+
return { valid: false, warnings, errors };
|
|
705
|
+
}
|
|
706
|
+
if (effective("sessionId") !== void 0 && effective("forkSession") !== true && (effective("continue") === true || effectiveResumeId() !== void 0)) {
|
|
707
|
+
errors.push(
|
|
708
|
+
"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."
|
|
709
|
+
);
|
|
710
|
+
return { valid: false, warnings, errors };
|
|
711
|
+
}
|
|
596
712
|
if (validSettings.maxTurns && validSettings.maxTurns > 20) {
|
|
597
713
|
warnings.push(
|
|
598
714
|
`High maxTurns value (${validSettings.maxTurns}) may lead to long-running conversations`
|
|
@@ -621,11 +737,30 @@ function validateSettings(settings) {
|
|
|
621
737
|
if (validSettings.disallowedTools) {
|
|
622
738
|
validateToolNames(validSettings.disallowedTools, "disallowed");
|
|
623
739
|
}
|
|
624
|
-
|
|
740
|
+
const effDialogKinds = effective("supportedDialogKinds");
|
|
741
|
+
if (Array.isArray(effDialogKinds) && effDialogKinds.length > 0 && effective("onUserDialog") == null) {
|
|
742
|
+
errors.push(
|
|
743
|
+
"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."
|
|
744
|
+
);
|
|
745
|
+
return { valid: false, warnings, errors };
|
|
746
|
+
}
|
|
747
|
+
const effAllowedTools = effective("allowedTools");
|
|
748
|
+
if (Array.isArray(effAllowedTools) && effAllowedTools.includes("Skill") && !effective("settingSources")) {
|
|
625
749
|
warnings.push(
|
|
626
750
|
"allowedTools includes 'Skill' but settingSources is not set. Skills require settingSources (e.g., ['user', 'project']) to load skill definitions."
|
|
627
751
|
);
|
|
628
752
|
}
|
|
753
|
+
if (validSettings.agents) {
|
|
754
|
+
const knownAgentModelAliases = ["sonnet", "opus", "haiku", "fable", "inherit"];
|
|
755
|
+
for (const [agentName, agent] of Object.entries(validSettings.agents)) {
|
|
756
|
+
const agentModel = agent.model;
|
|
757
|
+
if (agentModel !== void 0 && !knownAgentModelAliases.includes(agentModel) && !agentModel.includes("-")) {
|
|
758
|
+
warnings.push(
|
|
759
|
+
`Unknown model alias '${agentModel}' for agent '${agentName}'. Known aliases are: ${knownAgentModelAliases.join(", ")}; full model IDs (e.g. 'claude-sonnet-4-5') are also accepted.`
|
|
760
|
+
);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
629
764
|
return { valid: true, warnings, errors };
|
|
630
765
|
} catch (error) {
|
|
631
766
|
errors.push(`Validation error: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -646,6 +781,137 @@ function validateSessionId(sessionId) {
|
|
|
646
781
|
return void 0;
|
|
647
782
|
}
|
|
648
783
|
|
|
784
|
+
// src/sanitize-json-schema.ts
|
|
785
|
+
var SUBSCHEMA_MAP_KEYWORDS = [
|
|
786
|
+
"properties",
|
|
787
|
+
"patternProperties",
|
|
788
|
+
"$defs",
|
|
789
|
+
"definitions",
|
|
790
|
+
"dependentSchemas",
|
|
791
|
+
// draft-07 `dependencies` values are either subschemas (schema form) or
|
|
792
|
+
// arrays of property-name strings (array form); sanitizeNode passes
|
|
793
|
+
// string arrays through untouched, so walking both forms is safe.
|
|
794
|
+
"dependencies"
|
|
795
|
+
];
|
|
796
|
+
var SUBSCHEMA_KEYWORDS = [
|
|
797
|
+
"items",
|
|
798
|
+
// may also be an array of subschemas (draft-07 tuple form)
|
|
799
|
+
"additionalItems",
|
|
800
|
+
"additionalProperties",
|
|
801
|
+
"unevaluatedItems",
|
|
802
|
+
"unevaluatedProperties",
|
|
803
|
+
"not",
|
|
804
|
+
"contains",
|
|
805
|
+
"propertyNames",
|
|
806
|
+
"contentSchema",
|
|
807
|
+
"if",
|
|
808
|
+
"then",
|
|
809
|
+
"else"
|
|
810
|
+
];
|
|
811
|
+
var SUBSCHEMA_LIST_KEYWORDS = ["prefixItems", "anyOf", "oneOf", "allOf"];
|
|
812
|
+
function sanitizeJsonSchemaForOutputFormat(schema) {
|
|
813
|
+
const strippedFormatPaths = [];
|
|
814
|
+
const sanitized = sanitizeNode(schema, "#", /* @__PURE__ */ new WeakSet(), strippedFormatPaths);
|
|
815
|
+
return {
|
|
816
|
+
schema: sanitized ?? schema,
|
|
817
|
+
strippedFormatPaths
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
function sanitizeNode(node, path, visiting, strippedFormatPaths) {
|
|
821
|
+
if (typeof node !== "object" || node === null) {
|
|
822
|
+
return node;
|
|
823
|
+
}
|
|
824
|
+
if (visiting.has(node)) {
|
|
825
|
+
return node;
|
|
826
|
+
}
|
|
827
|
+
visiting.add(node);
|
|
828
|
+
try {
|
|
829
|
+
if (Array.isArray(node)) {
|
|
830
|
+
return sanitizeList(node, path, visiting, strippedFormatPaths);
|
|
831
|
+
}
|
|
832
|
+
const record = node;
|
|
833
|
+
let result = record;
|
|
834
|
+
const setKey = (key, value) => {
|
|
835
|
+
if (result === record) {
|
|
836
|
+
result = { ...record };
|
|
837
|
+
}
|
|
838
|
+
result[key] = value;
|
|
839
|
+
};
|
|
840
|
+
if (typeof record.format === "string") {
|
|
841
|
+
const format = record.format;
|
|
842
|
+
const existingDescription = record.description;
|
|
843
|
+
result = { ...record };
|
|
844
|
+
delete result.format;
|
|
845
|
+
if (typeof existingDescription === "string" && existingDescription.length > 0) {
|
|
846
|
+
result.description = `${existingDescription} (expected format: ${format})`;
|
|
847
|
+
} else if (existingDescription === void 0 || existingDescription === "") {
|
|
848
|
+
result.description = `Expected format: ${format}`;
|
|
849
|
+
}
|
|
850
|
+
strippedFormatPaths.push(path);
|
|
851
|
+
}
|
|
852
|
+
for (const keyword of SUBSCHEMA_MAP_KEYWORDS) {
|
|
853
|
+
const map = record[keyword];
|
|
854
|
+
if (typeof map !== "object" || map === null || Array.isArray(map)) continue;
|
|
855
|
+
const mapRecord = map;
|
|
856
|
+
let newMap = mapRecord;
|
|
857
|
+
for (const [name, child] of Object.entries(mapRecord)) {
|
|
858
|
+
const sanitizedChild = sanitizeNode(
|
|
859
|
+
child,
|
|
860
|
+
`${path}/${keyword}/${name}`,
|
|
861
|
+
visiting,
|
|
862
|
+
strippedFormatPaths
|
|
863
|
+
);
|
|
864
|
+
if (sanitizedChild !== child) {
|
|
865
|
+
if (newMap === mapRecord) {
|
|
866
|
+
newMap = { ...mapRecord };
|
|
867
|
+
}
|
|
868
|
+
newMap[name] = sanitizedChild;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
if (newMap !== mapRecord) {
|
|
872
|
+
setKey(keyword, newMap);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
for (const keyword of SUBSCHEMA_KEYWORDS) {
|
|
876
|
+
const child = record[keyword];
|
|
877
|
+
if (typeof child !== "object" || child === null) continue;
|
|
878
|
+
const sanitizedChild = sanitizeNode(
|
|
879
|
+
child,
|
|
880
|
+
`${path}/${keyword}`,
|
|
881
|
+
visiting,
|
|
882
|
+
strippedFormatPaths
|
|
883
|
+
);
|
|
884
|
+
if (sanitizedChild !== child) {
|
|
885
|
+
setKey(keyword, sanitizedChild);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
for (const keyword of SUBSCHEMA_LIST_KEYWORDS) {
|
|
889
|
+
const list = record[keyword];
|
|
890
|
+
if (!Array.isArray(list)) continue;
|
|
891
|
+
const sanitizedList = sanitizeList(list, `${path}/${keyword}`, visiting, strippedFormatPaths);
|
|
892
|
+
if (sanitizedList !== list) {
|
|
893
|
+
setKey(keyword, sanitizedList);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
return result;
|
|
897
|
+
} finally {
|
|
898
|
+
visiting.delete(node);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
function sanitizeList(list, path, visiting, strippedFormatPaths) {
|
|
902
|
+
let result = list;
|
|
903
|
+
for (let i = 0; i < list.length; i++) {
|
|
904
|
+
const sanitizedChild = sanitizeNode(list[i], `${path}/${i}`, visiting, strippedFormatPaths);
|
|
905
|
+
if (sanitizedChild !== list[i]) {
|
|
906
|
+
if (result === list) {
|
|
907
|
+
result = [...list];
|
|
908
|
+
}
|
|
909
|
+
result[i] = sanitizedChild;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
return result;
|
|
913
|
+
}
|
|
914
|
+
|
|
649
915
|
// src/logger.ts
|
|
650
916
|
var defaultLogger = {
|
|
651
917
|
// eslint-disable-next-line no-console
|
|
@@ -692,6 +958,8 @@ function createVerboseLogger(logger, verbose = false) {
|
|
|
692
958
|
|
|
693
959
|
// src/claude-code-language-model.ts
|
|
694
960
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
961
|
+
var PROVIDER_VERSION = "3.5.0";
|
|
962
|
+
var DEFAULT_CLIENT_APP = `ai-sdk-provider-claude-code/${PROVIDER_VERSION}`;
|
|
695
963
|
var CLAUDE_CODE_TRUNCATION_WARNING = "Claude Code SDK output ended unexpectedly; returning truncated response from buffered text. Await upstream fix to avoid data loss.";
|
|
696
964
|
var MIN_TRUNCATION_LENGTH = 512;
|
|
697
965
|
function isClaudeCodeTruncationError(error, bufferedText) {
|
|
@@ -723,6 +991,34 @@ function isClaudeCodeTruncationError(error, bufferedText) {
|
|
|
723
991
|
}
|
|
724
992
|
return true;
|
|
725
993
|
}
|
|
994
|
+
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.";
|
|
995
|
+
function extractJsonObjectText(text) {
|
|
996
|
+
const trimmed = text.trim();
|
|
997
|
+
if (!trimmed) {
|
|
998
|
+
return void 0;
|
|
999
|
+
}
|
|
1000
|
+
const candidates = [trimmed];
|
|
1001
|
+
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);
|
|
1002
|
+
candidates.push(...fencedBlocks.reverse());
|
|
1003
|
+
for (const candidate of candidates) {
|
|
1004
|
+
if (!candidate) continue;
|
|
1005
|
+
try {
|
|
1006
|
+
const parsed = JSON.parse(candidate);
|
|
1007
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
1008
|
+
return candidate;
|
|
1009
|
+
}
|
|
1010
|
+
} catch {
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
return void 0;
|
|
1014
|
+
}
|
|
1015
|
+
function getStructuredErrorKind(error) {
|
|
1016
|
+
if (typeof error === "object" && error !== null && "errorKind" in error) {
|
|
1017
|
+
const kind = error.errorKind;
|
|
1018
|
+
if (typeof kind === "string") return kind;
|
|
1019
|
+
}
|
|
1020
|
+
return void 0;
|
|
1021
|
+
}
|
|
726
1022
|
function isAbortError(err) {
|
|
727
1023
|
if (err && typeof err === "object") {
|
|
728
1024
|
const e = err;
|
|
@@ -733,6 +1029,7 @@ function isAbortError(err) {
|
|
|
733
1029
|
}
|
|
734
1030
|
var DEFAULT_INHERITED_ENV_VARS = process.platform === "win32" ? [
|
|
735
1031
|
"APPDATA",
|
|
1032
|
+
"COMSPEC",
|
|
736
1033
|
"HOMEDRIVE",
|
|
737
1034
|
"HOMEPATH",
|
|
738
1035
|
"LOCALAPPDATA",
|
|
@@ -747,23 +1044,89 @@ var DEFAULT_INHERITED_ENV_VARS = process.platform === "win32" ? [
|
|
|
747
1044
|
"WINDIR"
|
|
748
1045
|
] : ["HOME", "LOGNAME", "PATH", "SHELL", "TERM", "USER", "LANG", "LC_ALL", "TMPDIR"];
|
|
749
1046
|
var CLAUDE_ENV_VARS = ["CLAUDE_CONFIG_DIR"];
|
|
1047
|
+
var NETWORK_ENV_VARS = [
|
|
1048
|
+
"HTTP_PROXY",
|
|
1049
|
+
"HTTPS_PROXY",
|
|
1050
|
+
"NO_PROXY",
|
|
1051
|
+
"http_proxy",
|
|
1052
|
+
"https_proxy",
|
|
1053
|
+
"no_proxy",
|
|
1054
|
+
"NODE_EXTRA_CA_CERTS",
|
|
1055
|
+
"SSL_CERT_FILE",
|
|
1056
|
+
"SSL_CERT_DIR"
|
|
1057
|
+
];
|
|
1058
|
+
var CLOUD_ENV_VARS = ["GCLOUD_PROJECT", "CLOUD_ML_REGION"];
|
|
1059
|
+
var INHERITED_ENV_PREFIXES = ["ANTHROPIC_", "CLAUDE_", "AWS_", "GOOGLE_"];
|
|
750
1060
|
function getBaseProcessEnv() {
|
|
751
1061
|
const env = {};
|
|
752
|
-
const allowedKeys = /* @__PURE__ */ new Set([
|
|
753
|
-
|
|
1062
|
+
const allowedKeys = /* @__PURE__ */ new Set([
|
|
1063
|
+
...DEFAULT_INHERITED_ENV_VARS,
|
|
1064
|
+
...CLAUDE_ENV_VARS,
|
|
1065
|
+
...NETWORK_ENV_VARS,
|
|
1066
|
+
...CLOUD_ENV_VARS
|
|
1067
|
+
]);
|
|
1068
|
+
const addIfSafe = (key) => {
|
|
754
1069
|
const value = process.env[key];
|
|
755
1070
|
if (typeof value !== "string") {
|
|
756
|
-
|
|
1071
|
+
return;
|
|
757
1072
|
}
|
|
758
1073
|
if (value.startsWith("()")) {
|
|
759
|
-
|
|
1074
|
+
return;
|
|
760
1075
|
}
|
|
761
1076
|
env[key] = value;
|
|
1077
|
+
};
|
|
1078
|
+
for (const key of allowedKeys) {
|
|
1079
|
+
addIfSafe(key);
|
|
1080
|
+
}
|
|
1081
|
+
for (const key of Object.keys(process.env)) {
|
|
1082
|
+
if (INHERITED_ENV_PREFIXES.some((prefix) => key.startsWith(prefix))) {
|
|
1083
|
+
addIfSafe(key);
|
|
1084
|
+
}
|
|
762
1085
|
}
|
|
763
1086
|
return env;
|
|
764
1087
|
}
|
|
765
1088
|
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).";
|
|
766
1089
|
var SDK_OPTIONS_BLOCKLIST = /* @__PURE__ */ new Set(["model", "abortController", "prompt", "outputFormat"]);
|
|
1090
|
+
var SUBAGENT_TOOL_NAMES = /* @__PURE__ */ new Set(["Task", "Agent"]);
|
|
1091
|
+
function isSubagentToolName(name) {
|
|
1092
|
+
return SUBAGENT_TOOL_NAMES.has(name);
|
|
1093
|
+
}
|
|
1094
|
+
function resolveToolParentId(messageLevel, blockLevel, inferFallback) {
|
|
1095
|
+
if (messageLevel !== void 0) return messageLevel;
|
|
1096
|
+
if (typeof blockLevel === "string") return blockLevel;
|
|
1097
|
+
return inferFallback();
|
|
1098
|
+
}
|
|
1099
|
+
function computeRetractedToolCallIds(retracted, descriptors) {
|
|
1100
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1101
|
+
for (const { toolCallId, uuid } of descriptors) {
|
|
1102
|
+
if (uuid !== void 0 && retracted.has(uuid)) {
|
|
1103
|
+
ids.add(toolCallId);
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
return ids;
|
|
1107
|
+
}
|
|
1108
|
+
function applySupersede(message, evict, logger, guard = "array") {
|
|
1109
|
+
const supersedes = message.supersedes;
|
|
1110
|
+
const triggered = guard === "truthy" ? Boolean(supersedes && supersedes.length > 0) : Array.isArray(supersedes) && supersedes.length > 0;
|
|
1111
|
+
if (!triggered) {
|
|
1112
|
+
return false;
|
|
1113
|
+
}
|
|
1114
|
+
logger.debug(`[claude-code] Assistant message supersedes ${supersedes.length} prior message(s)`);
|
|
1115
|
+
evict(new Set(supersedes));
|
|
1116
|
+
return true;
|
|
1117
|
+
}
|
|
1118
|
+
function buildRetractionEvictor(evict) {
|
|
1119
|
+
return (uuids) => evict(new Set(uuids));
|
|
1120
|
+
}
|
|
1121
|
+
var INFORMATIONAL_SYSTEM_SUBTYPES = /* @__PURE__ */ new Set([
|
|
1122
|
+
"notification",
|
|
1123
|
+
"status",
|
|
1124
|
+
"task_updated",
|
|
1125
|
+
"session_state_changed",
|
|
1126
|
+
"commands_changed",
|
|
1127
|
+
"memory_recall",
|
|
1128
|
+
"plugin_install"
|
|
1129
|
+
]);
|
|
767
1130
|
function isContentBlock(item) {
|
|
768
1131
|
return typeof item === "object" && item !== null && "type" in item;
|
|
769
1132
|
}
|
|
@@ -986,6 +1349,9 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
986
1349
|
// 100KB warning threshold
|
|
987
1350
|
static MAX_DELTA_CALC_SIZE = 1e4;
|
|
988
1351
|
// 10KB delta computation threshold
|
|
1352
|
+
// Upper bound for draining post-result messages (prompt_suggestion) so a
|
|
1353
|
+
// lingering CLI subprocess cannot be held open indefinitely after finish.
|
|
1354
|
+
static PROMPT_SUGGESTION_DRAIN_TIMEOUT_MS = 1e4;
|
|
989
1355
|
modelId;
|
|
990
1356
|
settings;
|
|
991
1357
|
sessionId;
|
|
@@ -1033,27 +1399,71 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1033
1399
|
return sanitized;
|
|
1034
1400
|
}
|
|
1035
1401
|
getEffectiveResume(sdkOptions) {
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
if (!Array.isArray(content)) return { text: "", thinking: [] };
|
|
1040
|
-
let text = "";
|
|
1041
|
-
const thinking = [];
|
|
1042
|
-
for (const part of content) {
|
|
1043
|
-
if (!isContentBlock(part)) continue;
|
|
1044
|
-
if (part.type === "text" && typeof part.text === "string") {
|
|
1045
|
-
text += part.text;
|
|
1046
|
-
} else if (part.type === "thinking" && typeof part.thinking === "string") {
|
|
1047
|
-
thinking.push(part.thinking);
|
|
1402
|
+
for (const candidate of [sdkOptions?.resume, this.settings.resume, this.sessionId]) {
|
|
1403
|
+
if (typeof candidate === "string" && !isBlankResume(candidate)) {
|
|
1404
|
+
return candidate;
|
|
1048
1405
|
}
|
|
1049
1406
|
}
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1407
|
+
return void 0;
|
|
1408
|
+
}
|
|
1409
|
+
/**
|
|
1410
|
+
* Single source of truth for the CLI's `--session-id` exclusivity rule.
|
|
1411
|
+
*
|
|
1412
|
+
* The CLI rejects `--session-id` together with `--resume`/`--continue`
|
|
1413
|
+
* unless `--fork-session` is also set (forkSession then names the forked
|
|
1414
|
+
* session's own ID). This predicate captures "there IS a resume/continue
|
|
1415
|
+
* target AND we are not forking", i.e. the case where a session id must NOT
|
|
1416
|
+
* coexist. It is referenced by both:
|
|
1417
|
+
* - the pre-merge forwarding guard (via its inverse), which decides whether
|
|
1418
|
+
* to forward `settings.sessionId` onto the base options, and
|
|
1419
|
+
* - the post-merge exclusivity drop, which removes any session id that the
|
|
1420
|
+
* generic sdkOptions overlay (or the auto-resume turn) re-introduced.
|
|
1421
|
+
*
|
|
1422
|
+
* Keeping one definition guarantees both sites agree on what "conflicts with
|
|
1423
|
+
* a session id" means. The mirror in validation.ts (construction-time)
|
|
1424
|
+
* intentionally stays separate: it reads settings+sdkOptions, not a built
|
|
1425
|
+
* opts object.
|
|
1426
|
+
*/
|
|
1427
|
+
static sessionIdConflictsWithResumeOrContinue(args) {
|
|
1428
|
+
return (args.resumePresent || args.continue) && !args.forkSession;
|
|
1429
|
+
}
|
|
1430
|
+
/**
|
|
1431
|
+
* Owns ALL session-id / resume cross-option resolution on the FINAL merged
|
|
1432
|
+
* options, in the single correct order. Called once, immediately after the
|
|
1433
|
+
* generic sdkOptions overlay in createQueryOptions.
|
|
1434
|
+
*
|
|
1435
|
+
* Two concerns, in this exact order (order matters: step 1 can change whether
|
|
1436
|
+
* step 2 sees a resume target):
|
|
1437
|
+
*
|
|
1438
|
+
* 1. Blank-resume restoration. The overlay copies the raw `sdkOptions.resume`
|
|
1439
|
+
* verbatim, which can re-introduce a blank/whitespace value over the
|
|
1440
|
+
* base `resume` that getEffectiveResume already normalized. The SDK treats
|
|
1441
|
+
* a blank resume as absent, so a blank must NOT clobber the computed
|
|
1442
|
+
* fallback — restore `effectiveResume` (already blank-stripped; may itself
|
|
1443
|
+
* be undefined for a genuinely new session) rather than leaving '' or
|
|
1444
|
+
* forcing undefined, which would erase a real settings.resume / captured
|
|
1445
|
+
* session id.
|
|
1446
|
+
*
|
|
1447
|
+
* 2. Session-id exclusivity. Drop `opts.sessionId` whenever it conflicts with
|
|
1448
|
+
* a resume/continue target (see sessionIdConflictsWithResumeOrContinue).
|
|
1449
|
+
* This runs on the merged opts so it catches a sessionId re-added by the
|
|
1450
|
+
* sdkOptions overlay AND the auto-resumed second turn (where resume was
|
|
1451
|
+
* populated from the captured session id). It complements — does not
|
|
1452
|
+
* replace — the pre-merge forwarding guard, which governs whether
|
|
1453
|
+
* settings.sessionId was forwarded BEFORE the overlay could mutate
|
|
1454
|
+
* forkSession/continue/resume.
|
|
1455
|
+
*/
|
|
1456
|
+
applySessionResolution(opts, effectiveResume) {
|
|
1457
|
+
if (isBlankResume(opts.resume)) {
|
|
1458
|
+
opts.resume = effectiveResume;
|
|
1459
|
+
}
|
|
1460
|
+
if (opts.sessionId !== void 0 && _ClaudeCodeLanguageModel.sessionIdConflictsWithResumeOrContinue({
|
|
1461
|
+
resumePresent: opts.resume !== void 0,
|
|
1462
|
+
continue: opts.continue === true,
|
|
1463
|
+
forkSession: opts.forkSession === true
|
|
1464
|
+
})) {
|
|
1465
|
+
opts.sessionId = void 0;
|
|
1055
1466
|
}
|
|
1056
|
-
return { text, thinking };
|
|
1057
1467
|
}
|
|
1058
1468
|
extractToolUses(content) {
|
|
1059
1469
|
return filterContentBlocks(content, "tool_use").map((block) => {
|
|
@@ -1147,6 +1557,153 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1147
1557
|
}
|
|
1148
1558
|
return result;
|
|
1149
1559
|
}
|
|
1560
|
+
/**
|
|
1561
|
+
* Builds a provider-executed `tool-call` part from an assistant `tool_use`
|
|
1562
|
+
* block. Shared by doGenerate (content part) and doStream (stream part) so
|
|
1563
|
+
* the two paths cannot drift in field shape.
|
|
1564
|
+
*/
|
|
1565
|
+
buildToolCallPart(toolCallId, toolName, input, parentToolCallId) {
|
|
1566
|
+
return {
|
|
1567
|
+
type: "tool-call",
|
|
1568
|
+
toolCallId,
|
|
1569
|
+
toolName,
|
|
1570
|
+
input,
|
|
1571
|
+
providerExecuted: true,
|
|
1572
|
+
dynamic: true,
|
|
1573
|
+
// V3 field: indicates tool is provider-defined (not in user's tools map)
|
|
1574
|
+
providerMetadata: {
|
|
1575
|
+
"claude-code": {
|
|
1576
|
+
// rawInput preserves the original serialized format before AI SDK normalization.
|
|
1577
|
+
// Use this if you need the exact string sent to the Claude CLI, which may differ
|
|
1578
|
+
// from the `input` field after AI SDK processing.
|
|
1579
|
+
rawInput: input,
|
|
1580
|
+
parentToolCallId: parentToolCallId ?? null
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
};
|
|
1584
|
+
}
|
|
1585
|
+
/**
|
|
1586
|
+
* Builds a provider-executed `tool-result` part from a user-message
|
|
1587
|
+
* `tool_result` block, applying normalization and `maxToolResultSize`
|
|
1588
|
+
* truncation. Shared by doGenerate and doStream.
|
|
1589
|
+
*/
|
|
1590
|
+
buildToolResultPart(toolCallId, toolName, result, isError, parentToolCallId) {
|
|
1591
|
+
const normalizedResult = this.normalizeToolResult(result);
|
|
1592
|
+
const rawResult = typeof result === "string" ? result : result === void 0 ? (
|
|
1593
|
+
// tool_result blocks may omit `content` entirely; '' keeps both
|
|
1594
|
+
// `result` (NonNullable<JSONValue>) and rawResult (JSONValue) valid.
|
|
1595
|
+
""
|
|
1596
|
+
) : (() => {
|
|
1597
|
+
try {
|
|
1598
|
+
return JSON.stringify(result) ?? String(result);
|
|
1599
|
+
} catch {
|
|
1600
|
+
return String(result);
|
|
1601
|
+
}
|
|
1602
|
+
})();
|
|
1603
|
+
const maxToolResultSize = this.settings.maxToolResultSize;
|
|
1604
|
+
const truncatedResult = truncateToolResultForStream(normalizedResult, maxToolResultSize);
|
|
1605
|
+
const truncatedRawResult = truncateToolResultForStream(rawResult, maxToolResultSize);
|
|
1606
|
+
const rawResultTruncated = truncatedRawResult !== rawResult;
|
|
1607
|
+
return {
|
|
1608
|
+
type: "tool-result",
|
|
1609
|
+
toolCallId,
|
|
1610
|
+
toolName,
|
|
1611
|
+
// `?? ''`: absent `content` (undefined) and string results that
|
|
1612
|
+
// normalize to JSON null (e.g. the string "null") must not violate the
|
|
1613
|
+
// NonNullable<JSONValue> contract of LanguageModelV3ToolResult.result.
|
|
1614
|
+
result: truncatedResult ?? "",
|
|
1615
|
+
isError,
|
|
1616
|
+
providerExecuted: true,
|
|
1617
|
+
dynamic: true,
|
|
1618
|
+
// V3 field: indicates tool is provider-defined
|
|
1619
|
+
providerMetadata: {
|
|
1620
|
+
"claude-code": {
|
|
1621
|
+
// rawResult preserves the original CLI output string before JSON parsing.
|
|
1622
|
+
// Use this when you need the exact string returned by the tool, especially
|
|
1623
|
+
// if the `result` field has been parsed/normalized and you need the original format.
|
|
1624
|
+
rawResult: truncatedRawResult,
|
|
1625
|
+
rawResultTruncated,
|
|
1626
|
+
parentToolCallId: parentToolCallId ?? null
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
};
|
|
1630
|
+
}
|
|
1631
|
+
serializeToolError(error) {
|
|
1632
|
+
return typeof error === "string" ? error : typeof error === "object" && error !== null ? (() => {
|
|
1633
|
+
try {
|
|
1634
|
+
return JSON.stringify(error) ?? String(error);
|
|
1635
|
+
} catch {
|
|
1636
|
+
return String(error);
|
|
1637
|
+
}
|
|
1638
|
+
})() : String(error);
|
|
1639
|
+
}
|
|
1640
|
+
/**
|
|
1641
|
+
* Builds a provider-executed `tool-error` STREAM part from a user-message
|
|
1642
|
+
* `tool_error` block (doStream only; AI SDK core handles tool-error stream
|
|
1643
|
+
* parts natively).
|
|
1644
|
+
*/
|
|
1645
|
+
buildToolErrorPart(toolCallId, toolName, error, parentToolCallId) {
|
|
1646
|
+
const rawError = this.serializeToolError(error);
|
|
1647
|
+
return {
|
|
1648
|
+
type: "tool-error",
|
|
1649
|
+
toolCallId,
|
|
1650
|
+
toolName,
|
|
1651
|
+
error: rawError,
|
|
1652
|
+
providerExecuted: true,
|
|
1653
|
+
dynamic: true,
|
|
1654
|
+
// V3 field: indicates tool is provider-defined
|
|
1655
|
+
providerMetadata: {
|
|
1656
|
+
"claude-code": {
|
|
1657
|
+
rawError,
|
|
1658
|
+
parentToolCallId: parentToolCallId ?? null
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
};
|
|
1662
|
+
}
|
|
1663
|
+
/**
|
|
1664
|
+
* Builds a V3 `tool-result` CONTENT part with `isError: true` from a
|
|
1665
|
+
* user-message `tool_error` block (doGenerate only). The V3 content union
|
|
1666
|
+
* has no `tool-error` member and AI SDK core's asContent() silently drops
|
|
1667
|
+
* unknown content part types, so an extension tool-error part would never
|
|
1668
|
+
* reach `generateText` users — an isError tool-result, by contrast,
|
|
1669
|
+
* round-trips into a proper tool-error part in steps content.
|
|
1670
|
+
*/
|
|
1671
|
+
buildToolErrorResultPart(toolCallId, toolName, error, parentToolCallId) {
|
|
1672
|
+
const rawError = this.serializeToolError(error);
|
|
1673
|
+
return {
|
|
1674
|
+
type: "tool-result",
|
|
1675
|
+
toolCallId,
|
|
1676
|
+
toolName,
|
|
1677
|
+
result: rawError,
|
|
1678
|
+
isError: true,
|
|
1679
|
+
providerExecuted: true,
|
|
1680
|
+
dynamic: true,
|
|
1681
|
+
// V3 field: indicates tool is provider-defined
|
|
1682
|
+
providerMetadata: {
|
|
1683
|
+
"claude-code": {
|
|
1684
|
+
rawError,
|
|
1685
|
+
parentToolCallId: parentToolCallId ?? null
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
};
|
|
1689
|
+
}
|
|
1690
|
+
/**
|
|
1691
|
+
* Policy (P3): late-frame drop guard, shared by all four tool_result/tool_error
|
|
1692
|
+
* sites (doGenerate result+error, doStream result+error). When a frame's tool
|
|
1693
|
+
* id is tombstoned (its tool-call was retracted by a supersede/refusal-fallback
|
|
1694
|
+
* signal), the frame must be DROPPED rather than re-synthesized into an orphan
|
|
1695
|
+
* tool-call. Centralizing the predicate + debug message keeps the four sites in
|
|
1696
|
+
* lockstep so a future tombstone change can't be applied to only some of them.
|
|
1697
|
+
*/
|
|
1698
|
+
isRetractedToolFrame(id, tombstone, frameKind) {
|
|
1699
|
+
if (!tombstone.has(id)) {
|
|
1700
|
+
return false;
|
|
1701
|
+
}
|
|
1702
|
+
this.logger.debug(
|
|
1703
|
+
`[claude-code] Dropping tool ${frameKind} for retracted (superseded) tool ID: ${id}`
|
|
1704
|
+
);
|
|
1705
|
+
return true;
|
|
1706
|
+
}
|
|
1150
1707
|
generateAllWarnings(options, prompt) {
|
|
1151
1708
|
const warnings = [];
|
|
1152
1709
|
const unsupportedParams = [];
|
|
@@ -1167,6 +1724,27 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1167
1724
|
});
|
|
1168
1725
|
}
|
|
1169
1726
|
}
|
|
1727
|
+
if (options.tools !== void 0 && options.tools.length > 0) {
|
|
1728
|
+
warnings.push({
|
|
1729
|
+
type: "unsupported",
|
|
1730
|
+
feature: "tools",
|
|
1731
|
+
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)."
|
|
1732
|
+
});
|
|
1733
|
+
}
|
|
1734
|
+
if (options.toolChoice !== void 0 && options.toolChoice.type !== "auto") {
|
|
1735
|
+
warnings.push({
|
|
1736
|
+
type: "unsupported",
|
|
1737
|
+
feature: "toolChoice",
|
|
1738
|
+
details: `Claude Code CLI does not support toolChoice '${options.toolChoice.type}'. Only automatic tool selection is available; the toolChoice parameter will be ignored.`
|
|
1739
|
+
});
|
|
1740
|
+
}
|
|
1741
|
+
if (options.maxOutputTokens !== void 0) {
|
|
1742
|
+
warnings.push({
|
|
1743
|
+
type: "unsupported",
|
|
1744
|
+
feature: "maxOutputTokens",
|
|
1745
|
+
details: "Claude Code CLI does not accept an output token cap. The maxOutputTokens parameter will be ignored."
|
|
1746
|
+
});
|
|
1747
|
+
}
|
|
1170
1748
|
if (this.modelValidationWarning) {
|
|
1171
1749
|
warnings.push({
|
|
1172
1750
|
type: "other",
|
|
@@ -1199,7 +1777,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1199
1777
|
const opts = {
|
|
1200
1778
|
model: this.getModel(),
|
|
1201
1779
|
abortController,
|
|
1202
|
-
resume: effectiveResume
|
|
1780
|
+
resume: effectiveResume,
|
|
1203
1781
|
pathToClaudeCodeExecutable: this.settings.pathToClaudeCodeExecutable,
|
|
1204
1782
|
maxTurns: this.settings.maxTurns,
|
|
1205
1783
|
maxThinkingTokens: this.settings.maxThinkingTokens,
|
|
@@ -1225,6 +1803,12 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1225
1803
|
mcpServers: this.settings.mcpServers,
|
|
1226
1804
|
canUseTool: this.settings.canUseTool
|
|
1227
1805
|
};
|
|
1806
|
+
if (this.settings.onUserDialog !== void 0) {
|
|
1807
|
+
opts.onUserDialog = this.settings.onUserDialog;
|
|
1808
|
+
}
|
|
1809
|
+
if (this.settings.supportedDialogKinds !== void 0) {
|
|
1810
|
+
opts.supportedDialogKinds = this.settings.supportedDialogKinds;
|
|
1811
|
+
}
|
|
1228
1812
|
if (this.settings.systemPrompt !== void 0) {
|
|
1229
1813
|
opts.systemPrompt = this.settings.systemPrompt;
|
|
1230
1814
|
} else if (this.settings.customSystemPrompt !== void 0) {
|
|
@@ -1244,6 +1828,8 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1244
1828
|
}
|
|
1245
1829
|
if (this.settings.settingSources !== void 0) {
|
|
1246
1830
|
opts.settingSources = this.settings.settingSources;
|
|
1831
|
+
} else {
|
|
1832
|
+
opts.settingSources = [];
|
|
1247
1833
|
}
|
|
1248
1834
|
if (this.settings.additionalDirectories !== void 0) {
|
|
1249
1835
|
opts.additionalDirectories = this.settings.additionalDirectories;
|
|
@@ -1251,6 +1837,48 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1251
1837
|
if (this.settings.agents !== void 0) {
|
|
1252
1838
|
opts.agents = this.settings.agents;
|
|
1253
1839
|
}
|
|
1840
|
+
if (this.settings.skills !== void 0) {
|
|
1841
|
+
opts.skills = this.settings.skills;
|
|
1842
|
+
}
|
|
1843
|
+
if (this.settings.settings !== void 0) {
|
|
1844
|
+
opts.settings = this.settings.settings;
|
|
1845
|
+
}
|
|
1846
|
+
if (this.settings.managedSettings !== void 0) {
|
|
1847
|
+
opts.managedSettings = this.settings.managedSettings;
|
|
1848
|
+
}
|
|
1849
|
+
if (this.settings.toolAliases !== void 0) {
|
|
1850
|
+
opts.toolAliases = this.settings.toolAliases;
|
|
1851
|
+
}
|
|
1852
|
+
if (this.settings.toolConfig !== void 0) {
|
|
1853
|
+
opts.toolConfig = this.settings.toolConfig;
|
|
1854
|
+
}
|
|
1855
|
+
if (this.settings.planModeInstructions !== void 0) {
|
|
1856
|
+
opts.planModeInstructions = this.settings.planModeInstructions;
|
|
1857
|
+
}
|
|
1858
|
+
if (this.settings.title !== void 0) {
|
|
1859
|
+
opts.title = this.settings.title;
|
|
1860
|
+
}
|
|
1861
|
+
if (this.settings.forwardSubagentText !== void 0) {
|
|
1862
|
+
opts.forwardSubagentText = this.settings.forwardSubagentText;
|
|
1863
|
+
}
|
|
1864
|
+
if (this.settings.agentProgressSummaries !== void 0) {
|
|
1865
|
+
opts.agentProgressSummaries = this.settings.agentProgressSummaries;
|
|
1866
|
+
}
|
|
1867
|
+
if (this.settings.includeHookEvents !== void 0) {
|
|
1868
|
+
opts.includeHookEvents = this.settings.includeHookEvents;
|
|
1869
|
+
}
|
|
1870
|
+
if (this.settings.taskBudget !== void 0) {
|
|
1871
|
+
opts.taskBudget = this.settings.taskBudget;
|
|
1872
|
+
}
|
|
1873
|
+
if (this.settings.sessionStore !== void 0) {
|
|
1874
|
+
opts.sessionStore = this.settings.sessionStore;
|
|
1875
|
+
}
|
|
1876
|
+
if (this.settings.sessionStoreFlush !== void 0) {
|
|
1877
|
+
opts.sessionStoreFlush = this.settings.sessionStoreFlush;
|
|
1878
|
+
}
|
|
1879
|
+
if (this.settings.loadTimeoutMs !== void 0) {
|
|
1880
|
+
opts.loadTimeoutMs = this.settings.loadTimeoutMs;
|
|
1881
|
+
}
|
|
1254
1882
|
if (this.settings.includePartialMessages !== void 0) {
|
|
1255
1883
|
opts.includePartialMessages = this.settings.includePartialMessages;
|
|
1256
1884
|
}
|
|
@@ -1275,7 +1903,13 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1275
1903
|
if (this.settings.hooks) {
|
|
1276
1904
|
opts.hooks = this.settings.hooks;
|
|
1277
1905
|
}
|
|
1278
|
-
|
|
1906
|
+
const effectiveForkSession = sdkOptions?.forkSession ?? this.settings.forkSession;
|
|
1907
|
+
const effectiveContinue = sdkOptions?.continue ?? this.settings.continue;
|
|
1908
|
+
if (this.settings.sessionId !== void 0 && !_ClaudeCodeLanguageModel.sessionIdConflictsWithResumeOrContinue({
|
|
1909
|
+
resumePresent: opts.resume !== void 0,
|
|
1910
|
+
continue: effectiveContinue === true,
|
|
1911
|
+
forkSession: effectiveForkSession === true
|
|
1912
|
+
})) {
|
|
1279
1913
|
opts.sessionId = this.settings.sessionId;
|
|
1280
1914
|
}
|
|
1281
1915
|
if (this.settings.debug !== void 0) {
|
|
@@ -1291,7 +1925,17 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1291
1925
|
const rest = { ...sdkOverrides };
|
|
1292
1926
|
delete rest.env;
|
|
1293
1927
|
delete rest.stderr;
|
|
1294
|
-
Object.
|
|
1928
|
+
for (const [key, value] of Object.entries(rest)) {
|
|
1929
|
+
if (value !== void 0) {
|
|
1930
|
+
opts[key] = value;
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
this.applySessionResolution(opts, effectiveResume);
|
|
1935
|
+
if (typeof opts.fallbackModel === "string" && opts.fallbackModel === opts.model) {
|
|
1936
|
+
throw new Error(
|
|
1937
|
+
`fallbackModel cannot be the same as the model ('${String(opts.model)}'). Specify a different model for fallbackModel, or remove it.`
|
|
1938
|
+
);
|
|
1295
1939
|
}
|
|
1296
1940
|
const userStderrCallback = sdkStderr ?? this.settings.stderr;
|
|
1297
1941
|
if (stderrCollector || userStderrCallback) {
|
|
@@ -1300,14 +1944,27 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1300
1944
|
if (userStderrCallback) userStderrCallback(data);
|
|
1301
1945
|
};
|
|
1302
1946
|
}
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1947
|
+
const mergedEnv = {
|
|
1948
|
+
...getBaseProcessEnv(),
|
|
1949
|
+
...this.settings.env,
|
|
1950
|
+
...sdkEnv
|
|
1951
|
+
};
|
|
1952
|
+
if (!("CLAUDE_AGENT_SDK_CLIENT_APP" in mergedEnv)) {
|
|
1953
|
+
mergedEnv.CLAUDE_AGENT_SDK_CLIENT_APP = DEFAULT_CLIENT_APP;
|
|
1306
1954
|
}
|
|
1955
|
+
opts.env = mergedEnv;
|
|
1307
1956
|
if (responseFormat?.type === "json" && responseFormat.schema) {
|
|
1957
|
+
const { schema: sanitizedSchema, strippedFormatPaths } = sanitizeJsonSchemaForOutputFormat(
|
|
1958
|
+
responseFormat.schema
|
|
1959
|
+
);
|
|
1960
|
+
if (strippedFormatPaths.length > 0) {
|
|
1961
|
+
this.logger.debug(
|
|
1962
|
+
`[claude-code] Stripped unsupported 'format' keywords from outputFormat schema (hints folded into descriptions; client-side Zod validation still enforces them) at: ${strippedFormatPaths.join(", ")}`
|
|
1963
|
+
);
|
|
1964
|
+
}
|
|
1308
1965
|
opts.outputFormat = {
|
|
1309
1966
|
type: "json_schema",
|
|
1310
|
-
schema:
|
|
1967
|
+
schema: sanitizedSchema
|
|
1311
1968
|
};
|
|
1312
1969
|
}
|
|
1313
1970
|
return opts;
|
|
@@ -1316,6 +1973,9 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1316
1973
|
if (isAbortError(error)) {
|
|
1317
1974
|
throw error;
|
|
1318
1975
|
}
|
|
1976
|
+
if (error instanceof APICallError2 || error instanceof LoadAPIKeyError2) {
|
|
1977
|
+
return error;
|
|
1978
|
+
}
|
|
1319
1979
|
const isErrorWithMessage = (err) => {
|
|
1320
1980
|
return typeof err === "object" && err !== null && "message" in err;
|
|
1321
1981
|
};
|
|
@@ -1332,11 +1992,14 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1332
1992
|
"claude auth login",
|
|
1333
1993
|
"/login",
|
|
1334
1994
|
// CLI returns "Please run /login"
|
|
1335
|
-
"invalid api key"
|
|
1995
|
+
"invalid api key",
|
|
1996
|
+
"oauth_org_not_allowed"
|
|
1997
|
+
// SDK 0.3.x assistant error kind: OAuth org not permitted
|
|
1336
1998
|
];
|
|
1337
1999
|
const errorMessage = isErrorWithMessage(error) && error.message ? error.message.toLowerCase() : "";
|
|
2000
|
+
const errorKind = getStructuredErrorKind(error);
|
|
1338
2001
|
const exitCode = isErrorWithCode(error) && typeof error.exitCode === "number" ? error.exitCode : void 0;
|
|
1339
|
-
const isAuthError = authErrorPatterns.some((pattern) => errorMessage.includes(pattern)) || exitCode === 401;
|
|
2002
|
+
const isAuthError = errorKind === "authentication_failed" || errorKind === "oauth_org_not_allowed" || authErrorPatterns.some((pattern) => errorMessage.includes(pattern)) || exitCode === 401;
|
|
1340
2003
|
if (isAuthError) {
|
|
1341
2004
|
return createAuthenticationError({
|
|
1342
2005
|
message: isErrorWithMessage(error) && error.message ? error.message : "Authentication failed. Please ensure Claude Code SDK is properly authenticated."
|
|
@@ -1351,9 +2014,30 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1351
2014
|
// It's controlled by the consumer via AbortSignal
|
|
1352
2015
|
});
|
|
1353
2016
|
}
|
|
1354
|
-
const isRetryable = errorCode === "ENOENT" || errorCode === "ECONNREFUSED" || errorCode === "ETIMEDOUT" || errorCode === "ECONNRESET";
|
|
1355
2017
|
const stderrFromError = isErrorWithCode(error) && typeof error.stderr === "string" ? error.stderr : void 0;
|
|
1356
2018
|
const stderr = stderrFromError || collectedStderr || void 0;
|
|
2019
|
+
if (errorKind === "overloaded" || errorKind === "rate_limit" || errorMessage.includes("overloaded")) {
|
|
2020
|
+
return createAPICallError({
|
|
2021
|
+
message: isErrorWithMessage(error) && error.message ? error.message : "Anthropic API is overloaded. Please retry.",
|
|
2022
|
+
code: errorCode || void 0,
|
|
2023
|
+
exitCode,
|
|
2024
|
+
stderr,
|
|
2025
|
+
promptExcerpt: messagesPrompt.substring(0, 200),
|
|
2026
|
+
isRetryable: true
|
|
2027
|
+
});
|
|
2028
|
+
}
|
|
2029
|
+
if (errorKind === "model_not_found" || errorMessage.includes("model_not_found") || errorMessage.includes("no such model")) {
|
|
2030
|
+
const originalMessage = isErrorWithMessage(error) && error.message ? error.message : "Model not found";
|
|
2031
|
+
return createAPICallError({
|
|
2032
|
+
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.`,
|
|
2033
|
+
code: errorCode || void 0,
|
|
2034
|
+
exitCode,
|
|
2035
|
+
stderr,
|
|
2036
|
+
promptExcerpt: messagesPrompt.substring(0, 200),
|
|
2037
|
+
isRetryable: false
|
|
2038
|
+
});
|
|
2039
|
+
}
|
|
2040
|
+
const isRetryable = errorCode === "ENOENT" || errorCode === "ECONNREFUSED" || errorCode === "ETIMEDOUT" || errorCode === "ECONNRESET";
|
|
1357
2041
|
return createAPICallError({
|
|
1358
2042
|
message: isErrorWithMessage(error) && error.message ? error.message : "Claude Code SDK error",
|
|
1359
2043
|
code: errorCode || void 0,
|
|
@@ -1389,6 +2073,152 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1389
2073
|
}).join(", ");
|
|
1390
2074
|
this.logger.warn(`[claude-code] MCP servers not connected: ${details}`);
|
|
1391
2075
|
}
|
|
2076
|
+
/**
|
|
2077
|
+
* Handles SDK 0.3.x system messages other than 'init', shared by doGenerate
|
|
2078
|
+
* and doStream:
|
|
2079
|
+
* - 'api_retry' is counted into providerMetadata (`apiRetries`) and debug-logged.
|
|
2080
|
+
* - 'permission_denied' is warn-logged and recorded into providerMetadata
|
|
2081
|
+
* (`permissionDenials`); without this a denial is invisible until the
|
|
2082
|
+
* model talks about it.
|
|
2083
|
+
* - 'model_refusal_fallback' is debug-logged (the superseding assistant
|
|
2084
|
+
* message is handled by the text-dedup guard in the message loops).
|
|
2085
|
+
* - 'thinking_tokens' deltas are accumulated into providerMetadata
|
|
2086
|
+
* (`estimatedThinkingTokens`); the estimate is explicitly not the
|
|
2087
|
+
* authoritative billed output tokens, so it is surfaced as metadata
|
|
2088
|
+
* instead of feeding `usage.outputTokens.reasoning`.
|
|
2089
|
+
* - The subtypes in {@link INFORMATIONAL_SYSTEM_SUBTYPES} are intentionally
|
|
2090
|
+
* informational and only debug-logged.
|
|
2091
|
+
*/
|
|
2092
|
+
handleSystemMessage(message, tracking, onRetractedUuids) {
|
|
2093
|
+
switch (message.subtype) {
|
|
2094
|
+
case "api_retry":
|
|
2095
|
+
tracking.apiRetries += 1;
|
|
2096
|
+
this.logger.debug(
|
|
2097
|
+
`[claude-code] API retry ${message.attempt}/${message.max_retries} in ${message.retry_delay_ms}ms - Status: ${message.error_status ?? "unknown"}, Error: ${message.error}`
|
|
2098
|
+
);
|
|
2099
|
+
break;
|
|
2100
|
+
case "permission_denied": {
|
|
2101
|
+
const reason = message.decision_reason ?? message.message;
|
|
2102
|
+
tracking.permissionDenials.push({
|
|
2103
|
+
toolName: message.tool_name,
|
|
2104
|
+
toolUseId: message.tool_use_id,
|
|
2105
|
+
...reason !== void 0 && { reason }
|
|
2106
|
+
});
|
|
2107
|
+
this.logger.warn(
|
|
2108
|
+
`[claude-code] Permission denied - Tool: ${message.tool_name}${reason ? `, Reason: ${reason}` : ""}`
|
|
2109
|
+
);
|
|
2110
|
+
break;
|
|
2111
|
+
}
|
|
2112
|
+
case "mirror_error": {
|
|
2113
|
+
const mirrorError = message.error ?? "unknown error";
|
|
2114
|
+
const mirrorSessionId = message.key?.sessionId ?? message.session_id ?? "unknown";
|
|
2115
|
+
tracking.mirrorErrors.push({ error: mirrorError, sessionId: mirrorSessionId });
|
|
2116
|
+
this.logger.warn(
|
|
2117
|
+
`[claude-code] SessionStore mirror error (transcript batch dropped) - Session: ${mirrorSessionId}, Error: ${mirrorError}`
|
|
2118
|
+
);
|
|
2119
|
+
break;
|
|
2120
|
+
}
|
|
2121
|
+
case "model_refusal_fallback": {
|
|
2122
|
+
this.logger.debug(
|
|
2123
|
+
`[claude-code] Model refusal fallback - ${message.original_model} -> ${message.fallback_model} (direction: ${message.direction})`
|
|
2124
|
+
);
|
|
2125
|
+
const retractedUuids = message.retracted_message_uuids;
|
|
2126
|
+
if (onRetractedUuids && retractedUuids && retractedUuids.length > 0) {
|
|
2127
|
+
this.logger.debug(
|
|
2128
|
+
`[claude-code] Refusal fallback retracts ${retractedUuids.length} message uuid(s)`
|
|
2129
|
+
);
|
|
2130
|
+
onRetractedUuids(retractedUuids);
|
|
2131
|
+
}
|
|
2132
|
+
break;
|
|
2133
|
+
}
|
|
2134
|
+
case "thinking_tokens":
|
|
2135
|
+
tracking.estimatedThinkingTokens += message.estimated_tokens_delta;
|
|
2136
|
+
this.logger.debug(
|
|
2137
|
+
`[claude-code] Thinking tokens estimate - block total: ${message.estimated_tokens}, delta: ${message.estimated_tokens_delta}, accumulated: ${tracking.estimatedThinkingTokens}`
|
|
2138
|
+
);
|
|
2139
|
+
break;
|
|
2140
|
+
default:
|
|
2141
|
+
if (INFORMATIONAL_SYSTEM_SUBTYPES.has(message.subtype)) {
|
|
2142
|
+
this.logger.debug(
|
|
2143
|
+
`[claude-code] Ignoring informational system message: ${message.subtype}`
|
|
2144
|
+
);
|
|
2145
|
+
} else {
|
|
2146
|
+
this.logger.debug(`[claude-code] Unhandled system message subtype: ${message.subtype}`);
|
|
2147
|
+
}
|
|
2148
|
+
break;
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
/**
|
|
2152
|
+
* Merges the result message's `permission_denials` list into the tracked
|
|
2153
|
+
* denials. PreToolUse-hook denies bypass canUseTool and emit no
|
|
2154
|
+
* `permission_denied` system event (per the SDK docs on
|
|
2155
|
+
* SDKPermissionDeniedMessage), so the result list is the only place they
|
|
2156
|
+
* surface. Entries already recorded from stream-time events are deduped by
|
|
2157
|
+
* `tool_use_id`.
|
|
2158
|
+
*/
|
|
2159
|
+
mergeResultPermissionDenials(message, tracking) {
|
|
2160
|
+
for (const denial of message.permission_denials ?? []) {
|
|
2161
|
+
const alreadyTracked = tracking.permissionDenials.some(
|
|
2162
|
+
(d) => d.toolUseId !== void 0 && d.toolUseId === denial.tool_use_id
|
|
2163
|
+
);
|
|
2164
|
+
if (!alreadyTracked) {
|
|
2165
|
+
tracking.permissionDenials.push({
|
|
2166
|
+
toolName: denial.tool_name,
|
|
2167
|
+
toolUseId: denial.tool_use_id
|
|
2168
|
+
});
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
/**
|
|
2173
|
+
* Bounded post-result drain for the `prompt_suggestion` message
|
|
2174
|
+
* (promptSuggestions: true), shared by doGenerate and doStream. The
|
|
2175
|
+
* suggestion arrives AFTER the result message; the SDK emits at most one
|
|
2176
|
+
* per turn, so stop once it is delivered, and a timeout closes the
|
|
2177
|
+
* iterator (tearing down the subprocess) if the CLI lingers after the
|
|
2178
|
+
* result without emitting one. Advances the response's own generator, so
|
|
2179
|
+
* the caller's surrounding loop resumes to a finished iterator.
|
|
2180
|
+
*/
|
|
2181
|
+
async drainPromptSuggestion(response, onPromptSuggestion) {
|
|
2182
|
+
const iterator = response[Symbol.asyncIterator]();
|
|
2183
|
+
let drainTimer;
|
|
2184
|
+
const drainTimeout = new Promise((resolve) => {
|
|
2185
|
+
drainTimer = setTimeout(
|
|
2186
|
+
() => resolve("timeout"),
|
|
2187
|
+
_ClaudeCodeLanguageModel.PROMPT_SUGGESTION_DRAIN_TIMEOUT_MS
|
|
2188
|
+
);
|
|
2189
|
+
drainTimer.unref?.();
|
|
2190
|
+
});
|
|
2191
|
+
try {
|
|
2192
|
+
while (true) {
|
|
2193
|
+
const winner = await Promise.race([iterator.next(), drainTimeout]);
|
|
2194
|
+
if (winner === "timeout") {
|
|
2195
|
+
this.logger.debug("[claude-code] Post-result drain timed out; closing SDK iterator");
|
|
2196
|
+
void iterator.return?.().catch(() => {
|
|
2197
|
+
});
|
|
2198
|
+
break;
|
|
2199
|
+
}
|
|
2200
|
+
if (winner.done) {
|
|
2201
|
+
break;
|
|
2202
|
+
}
|
|
2203
|
+
const trailingMessage = winner.value;
|
|
2204
|
+
this.logger.debug(`[claude-code] Post-result message type: ${trailingMessage.type}`);
|
|
2205
|
+
if (trailingMessage.type === "prompt_suggestion") {
|
|
2206
|
+
onPromptSuggestion(trailingMessage.suggestion);
|
|
2207
|
+
void iterator.return?.().catch(() => {
|
|
2208
|
+
});
|
|
2209
|
+
break;
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
} catch (drainError) {
|
|
2213
|
+
this.logger.debug(
|
|
2214
|
+
`[claude-code] Error draining post-result messages: ${drainError instanceof Error ? drainError.message : String(drainError)}`
|
|
2215
|
+
);
|
|
2216
|
+
} finally {
|
|
2217
|
+
if (drainTimer !== void 0) {
|
|
2218
|
+
clearTimeout(drainTimer);
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
1392
2222
|
async doGenerate(options) {
|
|
1393
2223
|
this.logger.debug(`[claude-code] Starting doGenerate request with model: ${this.modelId}`);
|
|
1394
2224
|
this.logger.debug(`[claude-code] Response format: ${options.responseFormat?.type ?? "none"}`);
|
|
@@ -1405,9 +2235,6 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1405
2235
|
let abortListener;
|
|
1406
2236
|
if (options.abortSignal?.aborted) {
|
|
1407
2237
|
abortController.abort(options.abortSignal.reason);
|
|
1408
|
-
} else if (options.abortSignal) {
|
|
1409
|
-
abortListener = () => abortController.abort(options.abortSignal?.reason);
|
|
1410
|
-
options.abortSignal.addEventListener("abort", abortListener, { once: true });
|
|
1411
2238
|
}
|
|
1412
2239
|
let collectedStderr = "";
|
|
1413
2240
|
const stderrCollector = (data) => {
|
|
@@ -1422,15 +2249,77 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1422
2249
|
sdkOptions,
|
|
1423
2250
|
effectiveResume
|
|
1424
2251
|
);
|
|
2252
|
+
if (options.abortSignal && !options.abortSignal.aborted) {
|
|
2253
|
+
abortListener = () => abortController.abort(options.abortSignal?.reason);
|
|
2254
|
+
options.abortSignal.addEventListener("abort", abortListener, { once: true });
|
|
2255
|
+
}
|
|
1425
2256
|
let text = "";
|
|
1426
|
-
const
|
|
2257
|
+
const contentSegments = [];
|
|
2258
|
+
const joinTextSegments = () => contentSegments.filter((segment) => segment.kind === "text").map((segment) => segment.text).join("");
|
|
2259
|
+
const joinFinalTurnTextSegments = () => {
|
|
2260
|
+
let start = 0;
|
|
2261
|
+
for (let i = 0; i < contentSegments.length; i++) {
|
|
2262
|
+
const kind = contentSegments[i]?.kind;
|
|
2263
|
+
if (kind === "tool-result" || kind === "tool-error") {
|
|
2264
|
+
start = i + 1;
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
return contentSegments.slice(start).filter((segment) => segment.kind === "text").map((segment) => segment.text).join("");
|
|
2268
|
+
};
|
|
2269
|
+
const knownTools = /* @__PURE__ */ new Map();
|
|
2270
|
+
const retractedToolIds = /* @__PURE__ */ new Set();
|
|
2271
|
+
const evictBuffered = (retracted) => {
|
|
2272
|
+
if (retracted.size === 0) return;
|
|
2273
|
+
const retractedToolCallIds = computeRetractedToolCallIds(
|
|
2274
|
+
retracted,
|
|
2275
|
+
contentSegments.filter(
|
|
2276
|
+
(segment) => segment.kind === "tool-call" || segment.kind === "tool-result" || segment.kind === "tool-error"
|
|
2277
|
+
).map((segment) => ({
|
|
2278
|
+
toolCallId: segment.toolCallId,
|
|
2279
|
+
uuid: segment.uuid
|
|
2280
|
+
}))
|
|
2281
|
+
);
|
|
2282
|
+
for (const toolCallId of retractedToolCallIds) {
|
|
2283
|
+
retractedToolIds.add(toolCallId);
|
|
2284
|
+
knownTools.delete(toolCallId);
|
|
2285
|
+
activeTaskTools.delete(toolCallId);
|
|
2286
|
+
}
|
|
2287
|
+
for (let i = contentSegments.length - 1; i >= 0; i--) {
|
|
2288
|
+
const segment = contentSegments[i];
|
|
2289
|
+
if (segment === void 0) continue;
|
|
2290
|
+
const segmentUuid = "uuid" in segment ? segment.uuid : void 0;
|
|
2291
|
+
const retractsSegment = segmentUuid !== void 0 && retracted.has(segmentUuid) || (segment.kind === "tool-result" || segment.kind === "tool-error") && retractedToolCallIds.has(segment.toolCallId);
|
|
2292
|
+
if (retractsSegment) {
|
|
2293
|
+
contentSegments.splice(i, 1);
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
};
|
|
2297
|
+
const activeTaskTools = /* @__PURE__ */ new Map();
|
|
2298
|
+
const getFallbackParentId = () => {
|
|
2299
|
+
if (activeTaskTools.size === 1) {
|
|
2300
|
+
return activeTaskTools.keys().next().value ?? null;
|
|
2301
|
+
}
|
|
2302
|
+
return null;
|
|
2303
|
+
};
|
|
1427
2304
|
let structuredOutput;
|
|
2305
|
+
let receivedResultMessage = false;
|
|
1428
2306
|
let usage = createEmptyUsage();
|
|
1429
2307
|
let finishReason = { unified: "stop", raw: void 0 };
|
|
1430
2308
|
let wasTruncated = false;
|
|
1431
2309
|
let costUsd;
|
|
1432
2310
|
let durationMs;
|
|
1433
2311
|
let modelUsage;
|
|
2312
|
+
let ttftMs;
|
|
2313
|
+
let ttftStreamMs;
|
|
2314
|
+
let timeToRequestMs;
|
|
2315
|
+
let warmSpareClaimed;
|
|
2316
|
+
let terminalReason;
|
|
2317
|
+
const metadataTracking = {
|
|
2318
|
+
apiRetries: 0,
|
|
2319
|
+
permissionDenials: [],
|
|
2320
|
+
mirrorErrors: [],
|
|
2321
|
+
estimatedThinkingTokens: 0
|
|
2322
|
+
};
|
|
1434
2323
|
const warnings = this.generateAllWarnings(options, messagesPrompt);
|
|
1435
2324
|
if (messageWarnings) {
|
|
1436
2325
|
messageWarnings.forEach((warning) => {
|
|
@@ -1476,23 +2365,195 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1476
2365
|
options: queryOptions
|
|
1477
2366
|
});
|
|
1478
2367
|
this.settings.onQueryCreated?.(response);
|
|
1479
|
-
|
|
2368
|
+
let lastAssistantErrorKind;
|
|
2369
|
+
const sdkIterator = response[Symbol.asyncIterator]();
|
|
2370
|
+
const detachableResponse = {
|
|
2371
|
+
[Symbol.asyncIterator]: () => ({
|
|
2372
|
+
next: () => sdkIterator.next(),
|
|
2373
|
+
return: () => {
|
|
2374
|
+
void sdkIterator.return?.().catch(() => {
|
|
2375
|
+
});
|
|
2376
|
+
return Promise.resolve({ done: true, value: void 0 });
|
|
2377
|
+
}
|
|
2378
|
+
})
|
|
2379
|
+
};
|
|
2380
|
+
for await (const message of detachableResponse) {
|
|
1480
2381
|
this.logger.debug(`[claude-code] Received message type: ${message.type}`);
|
|
1481
2382
|
if (message.type === "assistant") {
|
|
1482
|
-
|
|
1483
|
-
message.
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
2383
|
+
if (typeof message.error === "string") {
|
|
2384
|
+
lastAssistantErrorKind = message.error;
|
|
2385
|
+
}
|
|
2386
|
+
applySupersede(message, evictBuffered, this.logger, "truthy");
|
|
2387
|
+
const messageUuid = typeof message.uuid === "string" ? message.uuid : void 0;
|
|
2388
|
+
const sdkParentToolUseId = message.parent_tool_use_id;
|
|
2389
|
+
const content = message.message.content;
|
|
2390
|
+
if (Array.isArray(content)) {
|
|
2391
|
+
for (const block of content) {
|
|
2392
|
+
if (!isContentBlock(block)) continue;
|
|
2393
|
+
if (block.type === "text" && typeof block.text === "string") {
|
|
2394
|
+
if (block.text.length > 0) {
|
|
2395
|
+
contentSegments.push({
|
|
2396
|
+
kind: "text",
|
|
2397
|
+
...messageUuid !== void 0 && { uuid: messageUuid },
|
|
2398
|
+
text: block.text
|
|
2399
|
+
});
|
|
2400
|
+
}
|
|
2401
|
+
} else if (block.type === "thinking" && typeof block.thinking === "string") {
|
|
2402
|
+
contentSegments.push({
|
|
2403
|
+
kind: "reasoning",
|
|
2404
|
+
...messageUuid !== void 0 && { uuid: messageUuid },
|
|
2405
|
+
text: block.thinking
|
|
2406
|
+
});
|
|
2407
|
+
} else if (block.type === "tool_use") {
|
|
2408
|
+
const [tool3] = this.extractToolUses([block]);
|
|
2409
|
+
if (!tool3) continue;
|
|
2410
|
+
const parentToolCallId = isSubagentToolName(tool3.name) ? null : resolveToolParentId(
|
|
2411
|
+
sdkParentToolUseId,
|
|
2412
|
+
tool3.parentToolUseId,
|
|
2413
|
+
getFallbackParentId
|
|
2414
|
+
);
|
|
2415
|
+
this.logger.debug(
|
|
2416
|
+
`[claude-code] Tool use detected - Tool: ${tool3.name}, ID: ${tool3.id}, SDK parent: ${sdkParentToolUseId}, resolved parent: ${parentToolCallId}`
|
|
2417
|
+
);
|
|
2418
|
+
knownTools.set(tool3.id, { name: tool3.name, parentToolCallId });
|
|
2419
|
+
if (isSubagentToolName(tool3.name)) {
|
|
2420
|
+
activeTaskTools.set(tool3.id, { startTime: Date.now() });
|
|
2421
|
+
}
|
|
2422
|
+
contentSegments.push({
|
|
2423
|
+
kind: "tool-call",
|
|
2424
|
+
...messageUuid !== void 0 && { uuid: messageUuid },
|
|
2425
|
+
toolCallId: tool3.id,
|
|
2426
|
+
part: this.buildToolCallPart(
|
|
2427
|
+
tool3.id,
|
|
2428
|
+
tool3.name,
|
|
2429
|
+
this.serializeToolInput(tool3.input),
|
|
2430
|
+
parentToolCallId
|
|
2431
|
+
)
|
|
2432
|
+
});
|
|
2433
|
+
}
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
text = joinTextSegments();
|
|
2437
|
+
} else if (message.type === "user") {
|
|
2438
|
+
if (!message.message?.content) {
|
|
2439
|
+
this.logger.warn(
|
|
2440
|
+
`[claude-code] Unexpected user message structure: missing content field. Message type: ${message.type}. This may indicate an SDK protocol violation.`
|
|
2441
|
+
);
|
|
2442
|
+
continue;
|
|
2443
|
+
}
|
|
2444
|
+
const sdkParentToolUseIdForResults = message.parent_tool_use_id;
|
|
2445
|
+
const resultMessageUuid = typeof message.uuid === "string" ? message.uuid : void 0;
|
|
2446
|
+
const content = message.message.content;
|
|
2447
|
+
for (const result of this.extractToolResults(content)) {
|
|
2448
|
+
if (this.isRetractedToolFrame(result.id, retractedToolIds, "result")) {
|
|
2449
|
+
continue;
|
|
2450
|
+
}
|
|
2451
|
+
const known = knownTools.get(result.id);
|
|
2452
|
+
const toolName = result.name ?? known?.name ?? _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
|
|
2453
|
+
this.logger.debug(
|
|
2454
|
+
`[claude-code] Tool result received - Tool: ${toolName}, ID: ${result.id}`
|
|
2455
|
+
);
|
|
2456
|
+
let parentToolCallId;
|
|
2457
|
+
if (known) {
|
|
2458
|
+
known.name = toolName;
|
|
2459
|
+
parentToolCallId = known.parentToolCallId;
|
|
2460
|
+
} else {
|
|
2461
|
+
this.logger.warn(
|
|
2462
|
+
`[claude-code] Received tool result for unknown tool ID: ${result.id}`
|
|
2463
|
+
);
|
|
2464
|
+
parentToolCallId = isSubagentToolName(toolName) ? null : resolveToolParentId(sdkParentToolUseIdForResults, void 0, getFallbackParentId);
|
|
2465
|
+
knownTools.set(result.id, { name: toolName, parentToolCallId });
|
|
2466
|
+
contentSegments.push({
|
|
2467
|
+
kind: "tool-call",
|
|
2468
|
+
toolCallId: result.id,
|
|
2469
|
+
part: this.buildToolCallPart(result.id, toolName, "", parentToolCallId)
|
|
2470
|
+
});
|
|
2471
|
+
}
|
|
2472
|
+
if (isSubagentToolName(toolName)) {
|
|
2473
|
+
activeTaskTools.delete(result.id);
|
|
2474
|
+
}
|
|
2475
|
+
contentSegments.push({
|
|
2476
|
+
kind: "tool-result",
|
|
2477
|
+
...resultMessageUuid !== void 0 && { uuid: resultMessageUuid },
|
|
2478
|
+
toolCallId: result.id,
|
|
2479
|
+
part: this.buildToolResultPart(
|
|
2480
|
+
result.id,
|
|
2481
|
+
toolName,
|
|
2482
|
+
result.result,
|
|
2483
|
+
result.isError,
|
|
2484
|
+
parentToolCallId
|
|
2485
|
+
)
|
|
2486
|
+
});
|
|
2487
|
+
}
|
|
2488
|
+
for (const error of this.extractToolErrors(content)) {
|
|
2489
|
+
if (this.isRetractedToolFrame(error.id, retractedToolIds, "error")) {
|
|
2490
|
+
continue;
|
|
2491
|
+
}
|
|
2492
|
+
const known = knownTools.get(error.id);
|
|
2493
|
+
const toolName = error.name ?? known?.name ?? _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
|
|
2494
|
+
this.logger.debug(
|
|
2495
|
+
`[claude-code] Tool error received - Tool: ${toolName}, ID: ${error.id}`
|
|
2496
|
+
);
|
|
2497
|
+
let parentToolCallId;
|
|
2498
|
+
if (known) {
|
|
2499
|
+
known.name = toolName;
|
|
2500
|
+
parentToolCallId = known.parentToolCallId;
|
|
2501
|
+
} else {
|
|
2502
|
+
this.logger.warn(
|
|
2503
|
+
`[claude-code] Received tool error for unknown tool ID: ${error.id}`
|
|
2504
|
+
);
|
|
2505
|
+
parentToolCallId = isSubagentToolName(toolName) ? null : resolveToolParentId(sdkParentToolUseIdForResults, void 0, getFallbackParentId);
|
|
2506
|
+
knownTools.set(error.id, { name: toolName, parentToolCallId });
|
|
2507
|
+
contentSegments.push({
|
|
2508
|
+
kind: "tool-call",
|
|
2509
|
+
toolCallId: error.id,
|
|
2510
|
+
part: this.buildToolCallPart(error.id, toolName, "", parentToolCallId)
|
|
2511
|
+
});
|
|
2512
|
+
}
|
|
2513
|
+
if (isSubagentToolName(toolName)) {
|
|
2514
|
+
activeTaskTools.delete(error.id);
|
|
2515
|
+
}
|
|
2516
|
+
contentSegments.push({
|
|
2517
|
+
kind: "tool-error",
|
|
2518
|
+
...resultMessageUuid !== void 0 && { uuid: resultMessageUuid },
|
|
2519
|
+
toolCallId: error.id,
|
|
2520
|
+
part: this.buildToolErrorResultPart(
|
|
2521
|
+
error.id,
|
|
2522
|
+
toolName,
|
|
2523
|
+
error.error,
|
|
2524
|
+
parentToolCallId
|
|
2525
|
+
)
|
|
2526
|
+
});
|
|
2527
|
+
}
|
|
1487
2528
|
} else if (message.type === "result") {
|
|
1488
2529
|
done();
|
|
2530
|
+
receivedResultMessage = true;
|
|
1489
2531
|
this.setSessionId(message.session_id);
|
|
1490
2532
|
costUsd = message.total_cost_usd;
|
|
1491
2533
|
durationMs = message.duration_ms;
|
|
1492
2534
|
modelUsage = message.modelUsage;
|
|
2535
|
+
if ("ttft_ms" in message) {
|
|
2536
|
+
ttftMs = message.ttft_ms;
|
|
2537
|
+
}
|
|
2538
|
+
if ("ttft_stream_ms" in message) {
|
|
2539
|
+
ttftStreamMs = message.ttft_stream_ms;
|
|
2540
|
+
}
|
|
2541
|
+
if ("time_to_request_ms" in message) {
|
|
2542
|
+
timeToRequestMs = message.time_to_request_ms;
|
|
2543
|
+
}
|
|
2544
|
+
if ("warm_spare_claimed" in message) {
|
|
2545
|
+
warmSpareClaimed = message.warm_spare_claimed;
|
|
2546
|
+
}
|
|
2547
|
+
terminalReason = message.terminal_reason;
|
|
2548
|
+
this.mergeResultPermissionDenials(message, metadataTracking);
|
|
1493
2549
|
if ("is_error" in message && message.is_error === true) {
|
|
1494
|
-
const
|
|
1495
|
-
|
|
2550
|
+
const resultText = "result" in message && typeof message.result === "string" ? message.result : void 0;
|
|
2551
|
+
const errorsText = "errors" in message && Array.isArray(message.errors) ? message.errors.filter((e) => typeof e === "string").join("; ") : "";
|
|
2552
|
+
const errorMessage = resultText ?? (errorsText || "Claude Code CLI returned an error");
|
|
2553
|
+
throw Object.assign(new Error(errorMessage), {
|
|
2554
|
+
exitCode: 1,
|
|
2555
|
+
errorKind: lastAssistantErrorKind
|
|
2556
|
+
});
|
|
1496
2557
|
}
|
|
1497
2558
|
if (message.subtype === "error_max_structured_output_retries") {
|
|
1498
2559
|
throw new Error(
|
|
@@ -1515,10 +2576,21 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1515
2576
|
const stopReason = "stop_reason" in message ? message.stop_reason : void 0;
|
|
1516
2577
|
finishReason = mapClaudeCodeFinishReason(message.subtype, stopReason);
|
|
1517
2578
|
this.logger.debug(`[claude-code] Finish reason: ${finishReason.unified}`);
|
|
2579
|
+
const effectivePromptSuggestions = sdkOptions?.promptSuggestions ?? this.settings.promptSuggestions;
|
|
2580
|
+
if (this.settings.onPromptSuggestion && effectivePromptSuggestions !== false) {
|
|
2581
|
+
await this.drainPromptSuggestion(response, this.settings.onPromptSuggestion);
|
|
2582
|
+
}
|
|
2583
|
+
break;
|
|
1518
2584
|
} else if (message.type === "system" && message.subtype === "init") {
|
|
1519
2585
|
this.logMcpConnectionIssues(message.mcp_servers);
|
|
1520
2586
|
this.setSessionId(message.session_id);
|
|
1521
2587
|
this.logger.info(`[claude-code] Session initialized: ${message.session_id}`);
|
|
2588
|
+
} else if (message.type === "system") {
|
|
2589
|
+
this.handleSystemMessage(
|
|
2590
|
+
message,
|
|
2591
|
+
metadataTracking,
|
|
2592
|
+
buildRetractionEvictor(evictBuffered)
|
|
2593
|
+
);
|
|
1522
2594
|
}
|
|
1523
2595
|
}
|
|
1524
2596
|
} catch (error) {
|
|
@@ -1548,15 +2620,45 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1548
2620
|
options.abortSignal.removeEventListener("abort", abortListener);
|
|
1549
2621
|
}
|
|
1550
2622
|
}
|
|
1551
|
-
|
|
2623
|
+
if (options.responseFormat?.type === "json" && options.responseFormat.schema !== void 0 && receivedResultMessage && structuredOutput === void 0 && !wasTruncated && finishReason.unified === "stop") {
|
|
2624
|
+
const recoveredJsonText = extractJsonObjectText(joinFinalTurnTextSegments()) ?? extractJsonObjectText(joinTextSegments());
|
|
2625
|
+
if (recoveredJsonText !== void 0) {
|
|
2626
|
+
this.logger.warn(
|
|
2627
|
+
"[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."
|
|
2628
|
+
);
|
|
2629
|
+
structuredOutput = JSON.parse(recoveredJsonText);
|
|
2630
|
+
} else {
|
|
2631
|
+
throw createAPICallError({
|
|
2632
|
+
message: MISSING_STRUCTURED_OUTPUT_ERROR_MESSAGE,
|
|
2633
|
+
promptExcerpt: messagesPrompt.substring(0, 200),
|
|
2634
|
+
isRetryable: false
|
|
2635
|
+
});
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2638
|
+
const thinkingTraces = contentSegments.filter((segment) => segment.kind === "reasoning").map((segment) => segment.text);
|
|
2639
|
+
const contentParts = [];
|
|
2640
|
+
for (const segment of contentSegments) {
|
|
2641
|
+
if (segment.kind === "reasoning") {
|
|
2642
|
+
contentParts.push({ type: "reasoning", text: segment.text });
|
|
2643
|
+
} else if (segment.kind === "text") {
|
|
2644
|
+
if (structuredOutput !== void 0) continue;
|
|
2645
|
+
const last = contentParts[contentParts.length - 1];
|
|
2646
|
+
if (last !== void 0 && last.type === "text") {
|
|
2647
|
+
last.text += segment.text;
|
|
2648
|
+
} else {
|
|
2649
|
+
contentParts.push({ type: "text", text: segment.text });
|
|
2650
|
+
}
|
|
2651
|
+
} else {
|
|
2652
|
+
contentParts.push(segment.part);
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
if (structuredOutput !== void 0) {
|
|
2656
|
+
contentParts.push({ type: "text", text: JSON.stringify(structuredOutput) });
|
|
2657
|
+
} else if (!contentParts.some((part) => part.type === "text")) {
|
|
2658
|
+
contentParts.push({ type: "text", text: "" });
|
|
2659
|
+
}
|
|
1552
2660
|
return {
|
|
1553
|
-
content:
|
|
1554
|
-
...thinkingTraces.map((trace) => ({
|
|
1555
|
-
type: "reasoning",
|
|
1556
|
-
text: trace
|
|
1557
|
-
})),
|
|
1558
|
-
{ type: "text", text: finalText }
|
|
1559
|
-
],
|
|
2661
|
+
content: contentParts,
|
|
1560
2662
|
usage,
|
|
1561
2663
|
finishReason,
|
|
1562
2664
|
warnings,
|
|
@@ -1574,6 +2676,21 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1574
2676
|
...costUsd !== void 0 && { costUsd },
|
|
1575
2677
|
...durationMs !== void 0 && { durationMs },
|
|
1576
2678
|
...modelUsage !== void 0 && { modelUsage },
|
|
2679
|
+
...ttftMs !== void 0 && { ttftMs },
|
|
2680
|
+
...ttftStreamMs !== void 0 && { ttftStreamMs },
|
|
2681
|
+
...timeToRequestMs !== void 0 && { timeToRequestMs },
|
|
2682
|
+
...warmSpareClaimed !== void 0 && { warmSpareClaimed },
|
|
2683
|
+
...terminalReason !== void 0 && { terminalReason },
|
|
2684
|
+
...metadataTracking.apiRetries > 0 && { apiRetries: metadataTracking.apiRetries },
|
|
2685
|
+
...metadataTracking.permissionDenials.length > 0 && {
|
|
2686
|
+
permissionDenials: metadataTracking.permissionDenials
|
|
2687
|
+
},
|
|
2688
|
+
...metadataTracking.mirrorErrors.length > 0 && {
|
|
2689
|
+
mirrorErrors: metadataTracking.mirrorErrors
|
|
2690
|
+
},
|
|
2691
|
+
...metadataTracking.estimatedThinkingTokens > 0 && {
|
|
2692
|
+
estimatedThinkingTokens: metadataTracking.estimatedThinkingTokens
|
|
2693
|
+
},
|
|
1577
2694
|
...wasTruncated && { truncated: true },
|
|
1578
2695
|
...thinkingTraces.length > 0 && { thinkingTraces }
|
|
1579
2696
|
}
|
|
@@ -1596,9 +2713,6 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1596
2713
|
let abortListener;
|
|
1597
2714
|
if (options.abortSignal?.aborted) {
|
|
1598
2715
|
abortController.abort(options.abortSignal.reason);
|
|
1599
|
-
} else if (options.abortSignal) {
|
|
1600
|
-
abortListener = () => abortController.abort(options.abortSignal?.reason);
|
|
1601
|
-
options.abortSignal.addEventListener("abort", abortListener, { once: true });
|
|
1602
2716
|
}
|
|
1603
2717
|
let collectedStderr = "";
|
|
1604
2718
|
const stderrCollector = (data) => {
|
|
@@ -1613,6 +2727,10 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1613
2727
|
sdkOptions,
|
|
1614
2728
|
effectiveResume
|
|
1615
2729
|
);
|
|
2730
|
+
if (options.abortSignal && !options.abortSignal.aborted) {
|
|
2731
|
+
abortListener = () => abortController.abort(options.abortSignal?.reason);
|
|
2732
|
+
options.abortSignal.addEventListener("abort", abortListener, { once: true });
|
|
2733
|
+
}
|
|
1616
2734
|
if (queryOptions.includePartialMessages === void 0) {
|
|
1617
2735
|
queryOptions.includePartialMessages = true;
|
|
1618
2736
|
}
|
|
@@ -1643,6 +2761,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1643
2761
|
done = () => resolve(void 0);
|
|
1644
2762
|
});
|
|
1645
2763
|
const toolStates = /* @__PURE__ */ new Map();
|
|
2764
|
+
const retractedStreamToolIds = /* @__PURE__ */ new Set();
|
|
1646
2765
|
const activeTaskTools = /* @__PURE__ */ new Map();
|
|
1647
2766
|
const getFallbackParentId = () => {
|
|
1648
2767
|
if (activeTaskTools.size === 1) {
|
|
@@ -1665,24 +2784,14 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1665
2784
|
return;
|
|
1666
2785
|
}
|
|
1667
2786
|
closeToolInput(toolId, state);
|
|
1668
|
-
controller.enqueue(
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
providerMetadata: {
|
|
1677
|
-
"claude-code": {
|
|
1678
|
-
// rawInput preserves the original serialized format before AI SDK normalization.
|
|
1679
|
-
// Use this if you need the exact string sent to the Claude CLI, which may differ
|
|
1680
|
-
// from the `input` field after AI SDK processing.
|
|
1681
|
-
rawInput: state.lastSerializedInput ?? "",
|
|
1682
|
-
parentToolCallId: state.parentToolCallId ?? null
|
|
1683
|
-
}
|
|
1684
|
-
}
|
|
1685
|
-
});
|
|
2787
|
+
controller.enqueue(
|
|
2788
|
+
this.buildToolCallPart(
|
|
2789
|
+
toolId,
|
|
2790
|
+
state.name,
|
|
2791
|
+
state.lastSerializedInput ?? "",
|
|
2792
|
+
state.parentToolCallId
|
|
2793
|
+
)
|
|
2794
|
+
);
|
|
1686
2795
|
state.callEmitted = true;
|
|
1687
2796
|
};
|
|
1688
2797
|
const finalizeToolCalls = () => {
|
|
@@ -1693,16 +2802,61 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1693
2802
|
};
|
|
1694
2803
|
let usage = createEmptyUsage();
|
|
1695
2804
|
let accumulatedText = "";
|
|
2805
|
+
const textSegments = [];
|
|
1696
2806
|
let textPartId;
|
|
1697
2807
|
let streamedTextLength = 0;
|
|
2808
|
+
let emittedTextSinceLastAssistant = "";
|
|
1698
2809
|
let hasReceivedStreamEvents = false;
|
|
1699
2810
|
let hasStreamedJson = false;
|
|
2811
|
+
let lastAssistantErrorKind;
|
|
2812
|
+
const metadataTracking = {
|
|
2813
|
+
apiRetries: 0,
|
|
2814
|
+
permissionDenials: [],
|
|
2815
|
+
mirrorErrors: [],
|
|
2816
|
+
estimatedThinkingTokens: 0
|
|
2817
|
+
};
|
|
1700
2818
|
const toolBlocksByIndex = /* @__PURE__ */ new Map();
|
|
1701
2819
|
const toolInputAccumulators = /* @__PURE__ */ new Map();
|
|
1702
2820
|
const textBlocksByIndex = /* @__PURE__ */ new Map();
|
|
1703
2821
|
let textStreamedViaContentBlock = false;
|
|
1704
2822
|
const reasoningBlocksByIndex = /* @__PURE__ */ new Map();
|
|
1705
2823
|
let currentReasoningPartId;
|
|
2824
|
+
const evictLive = (retracted) => {
|
|
2825
|
+
if (retracted.size === 0) return;
|
|
2826
|
+
for (let i = textSegments.length - 1; i >= 0; i--) {
|
|
2827
|
+
const segmentUuid = textSegments[i]?.uuid;
|
|
2828
|
+
if (segmentUuid !== void 0 && retracted.has(segmentUuid)) {
|
|
2829
|
+
textSegments.splice(i, 1);
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
accumulatedText = textSegments.map((segment) => segment.text).join("");
|
|
2833
|
+
const retractedToolCallIds = computeRetractedToolCallIds(
|
|
2834
|
+
retracted,
|
|
2835
|
+
[...toolStates].map(([toolId, state]) => ({
|
|
2836
|
+
toolCallId: toolId,
|
|
2837
|
+
uuid: state.messageUuid
|
|
2838
|
+
}))
|
|
2839
|
+
);
|
|
2840
|
+
for (const toolId of retractedToolCallIds) {
|
|
2841
|
+
const state = toolStates.get(toolId);
|
|
2842
|
+
if (!state) continue;
|
|
2843
|
+
activeTaskTools.delete(toolId);
|
|
2844
|
+
if (!state.callEmitted) {
|
|
2845
|
+
closeToolInput(toolId, state);
|
|
2846
|
+
toolStates.delete(toolId);
|
|
2847
|
+
retractedStreamToolIds.add(toolId);
|
|
2848
|
+
toolInputAccumulators.delete(toolId);
|
|
2849
|
+
for (const [blockIndex, mappedId] of toolBlocksByIndex) {
|
|
2850
|
+
if (mappedId === toolId) {
|
|
2851
|
+
toolBlocksByIndex.delete(blockIndex);
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2854
|
+
this.logger.debug(
|
|
2855
|
+
`[claude-code] Retracted pending tool call from superseded message - ID: ${toolId}`
|
|
2856
|
+
);
|
|
2857
|
+
}
|
|
2858
|
+
}
|
|
2859
|
+
};
|
|
1706
2860
|
try {
|
|
1707
2861
|
controller.enqueue({ type: "stream-start", warnings });
|
|
1708
2862
|
if (effectiveCanUseTool && effectivePermissionPromptToolName) {
|
|
@@ -1752,6 +2906,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1752
2906
|
});
|
|
1753
2907
|
accumulatedText += deltaText;
|
|
1754
2908
|
streamedTextLength += deltaText.length;
|
|
2909
|
+
emittedTextSinceLastAssistant += deltaText;
|
|
1755
2910
|
}
|
|
1756
2911
|
if (event.type === "content_block_delta" && event.delta.type === "input_json_delta" && "partial_json" in event.delta && event.delta.partial_json) {
|
|
1757
2912
|
const jsonDelta = event.delta.partial_json;
|
|
@@ -1811,13 +2966,16 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1811
2966
|
toolInputAccumulators.set(toolId, "");
|
|
1812
2967
|
let state = toolStates.get(toolId);
|
|
1813
2968
|
if (!state) {
|
|
1814
|
-
const
|
|
2969
|
+
const partialParentId = message.parent_tool_use_id;
|
|
2970
|
+
const currentParentId = isSubagentToolName(toolName) ? null : resolveToolParentId(partialParentId, void 0, getFallbackParentId);
|
|
2971
|
+
const envelopeUuid = message.uuid;
|
|
1815
2972
|
state = {
|
|
1816
2973
|
name: toolName,
|
|
1817
2974
|
inputStarted: false,
|
|
1818
2975
|
inputClosed: false,
|
|
1819
2976
|
callEmitted: false,
|
|
1820
|
-
parentToolCallId: currentParentId
|
|
2977
|
+
parentToolCallId: currentParentId,
|
|
2978
|
+
...typeof envelopeUuid === "string" && { messageUuid: envelopeUuid }
|
|
1821
2979
|
};
|
|
1822
2980
|
toolStates.set(toolId, state);
|
|
1823
2981
|
}
|
|
@@ -1837,7 +2995,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1837
2995
|
}
|
|
1838
2996
|
}
|
|
1839
2997
|
});
|
|
1840
|
-
if (toolName
|
|
2998
|
+
if (isSubagentToolName(toolName)) {
|
|
1841
2999
|
activeTaskTools.set(toolId, { startTime: Date.now() });
|
|
1842
3000
|
}
|
|
1843
3001
|
state.inputStarted = true;
|
|
@@ -1921,20 +3079,14 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1921
3079
|
const effectiveInput = accumulatedInput || state.lastSerializedInput || "";
|
|
1922
3080
|
state.lastSerializedInput = effectiveInput;
|
|
1923
3081
|
if (!state.callEmitted) {
|
|
1924
|
-
controller.enqueue(
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
"claude-code": {
|
|
1933
|
-
rawInput: effectiveInput,
|
|
1934
|
-
parentToolCallId: state.parentToolCallId ?? null
|
|
1935
|
-
}
|
|
1936
|
-
}
|
|
1937
|
-
});
|
|
3082
|
+
controller.enqueue(
|
|
3083
|
+
this.buildToolCallPart(
|
|
3084
|
+
toolId,
|
|
3085
|
+
state.name,
|
|
3086
|
+
effectiveInput,
|
|
3087
|
+
state.parentToolCallId
|
|
3088
|
+
)
|
|
3089
|
+
);
|
|
1938
3090
|
state.callEmitted = true;
|
|
1939
3091
|
}
|
|
1940
3092
|
}
|
|
@@ -1976,6 +3128,10 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1976
3128
|
continue;
|
|
1977
3129
|
}
|
|
1978
3130
|
if (message.type === "assistant") {
|
|
3131
|
+
if (typeof message.error === "string") {
|
|
3132
|
+
lastAssistantErrorKind = message.error;
|
|
3133
|
+
}
|
|
3134
|
+
const supersedesPriorMessages = applySupersede(message, evictLive, this.logger);
|
|
1979
3135
|
if (!message.message?.content) {
|
|
1980
3136
|
this.logger.warn(
|
|
1981
3137
|
`[claude-code] Unexpected assistant message structure: missing content field. Message type: ${message.type}. This may indicate an SDK protocol violation.`
|
|
@@ -2003,19 +3159,24 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2003
3159
|
const toolId = tool3.id;
|
|
2004
3160
|
let state = toolStates.get(toolId);
|
|
2005
3161
|
if (!state) {
|
|
2006
|
-
const currentParentId = tool3.name
|
|
3162
|
+
const currentParentId = isSubagentToolName(tool3.name) ? null : resolveToolParentId(
|
|
3163
|
+
sdkParentToolUseId,
|
|
3164
|
+
tool3.parentToolUseId,
|
|
3165
|
+
getFallbackParentId
|
|
3166
|
+
);
|
|
2007
3167
|
state = {
|
|
2008
3168
|
name: tool3.name,
|
|
2009
3169
|
inputStarted: false,
|
|
2010
3170
|
inputClosed: false,
|
|
2011
3171
|
callEmitted: false,
|
|
2012
|
-
parentToolCallId: currentParentId
|
|
3172
|
+
parentToolCallId: currentParentId,
|
|
3173
|
+
...typeof message.uuid === "string" && { messageUuid: message.uuid }
|
|
2013
3174
|
};
|
|
2014
3175
|
toolStates.set(toolId, state);
|
|
2015
3176
|
this.logger.debug(
|
|
2016
3177
|
`[claude-code] New tool use detected - Tool: ${tool3.name}, ID: ${toolId}, SDK parent: ${sdkParentToolUseId}, resolved parent: ${currentParentId}`
|
|
2017
3178
|
);
|
|
2018
|
-
} else if (!state.parentToolCallId && sdkParentToolUseId && tool3.name
|
|
3179
|
+
} else if (!state.parentToolCallId && sdkParentToolUseId && !isSubagentToolName(tool3.name)) {
|
|
2019
3180
|
state.parentToolCallId = sdkParentToolUseId;
|
|
2020
3181
|
this.logger.debug(
|
|
2021
3182
|
`[claude-code] Retroactive parent context - Tool: ${tool3.name}, ID: ${toolId}, parent: ${sdkParentToolUseId}`
|
|
@@ -2039,7 +3200,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2039
3200
|
}
|
|
2040
3201
|
}
|
|
2041
3202
|
});
|
|
2042
|
-
if (tool3.name
|
|
3203
|
+
if (isSubagentToolName(tool3.name)) {
|
|
2043
3204
|
activeTaskTools.set(toolId, { startTime: Date.now() });
|
|
2044
3205
|
}
|
|
2045
3206
|
state.inputStarted = true;
|
|
@@ -2068,10 +3229,76 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2068
3229
|
}
|
|
2069
3230
|
const text = content.map((c) => c.type === "text" ? c.text : "").join("");
|
|
2070
3231
|
if (text) {
|
|
2071
|
-
if (
|
|
3232
|
+
if (supersedesPriorMessages) {
|
|
3233
|
+
textSegments.push({
|
|
3234
|
+
...typeof message.uuid === "string" && { uuid: message.uuid },
|
|
3235
|
+
text
|
|
3236
|
+
});
|
|
3237
|
+
accumulatedText = textSegments.map((segment) => segment.text).join("");
|
|
3238
|
+
if (emittedTextSinceLastAssistant === text) {
|
|
3239
|
+
streamedTextLength = Math.max(streamedTextLength, text.length);
|
|
3240
|
+
this.logger.debug(
|
|
3241
|
+
"[claude-code] Skipping text emission for superseding assistant message (replacement already streamed)"
|
|
3242
|
+
);
|
|
3243
|
+
} else if (emittedTextSinceLastAssistant.length > 0 && text.startsWith(emittedTextSinceLastAssistant)) {
|
|
3244
|
+
if (options.responseFormat?.type !== "json") {
|
|
3245
|
+
const suffix = text.slice(emittedTextSinceLastAssistant.length);
|
|
3246
|
+
if (suffix) {
|
|
3247
|
+
if (!textPartId) {
|
|
3248
|
+
textPartId = generateId();
|
|
3249
|
+
controller.enqueue({ type: "text-start", id: textPartId });
|
|
3250
|
+
}
|
|
3251
|
+
controller.enqueue({
|
|
3252
|
+
type: "text-delta",
|
|
3253
|
+
id: textPartId,
|
|
3254
|
+
delta: suffix
|
|
3255
|
+
});
|
|
3256
|
+
emittedTextSinceLastAssistant = text;
|
|
3257
|
+
}
|
|
3258
|
+
}
|
|
3259
|
+
streamedTextLength = Math.max(streamedTextLength, text.length);
|
|
3260
|
+
this.logger.debug(
|
|
3261
|
+
"[claude-code] Emitted unstreamed suffix of superseding assistant message"
|
|
3262
|
+
);
|
|
3263
|
+
} else if (options.responseFormat?.type !== "json") {
|
|
3264
|
+
if (textPartId) {
|
|
3265
|
+
const closedTextId = textPartId;
|
|
3266
|
+
controller.enqueue({
|
|
3267
|
+
type: "text-end",
|
|
3268
|
+
id: closedTextId
|
|
3269
|
+
});
|
|
3270
|
+
textPartId = void 0;
|
|
3271
|
+
for (const [idx, blockTextId] of textBlocksByIndex) {
|
|
3272
|
+
if (blockTextId === closedTextId) {
|
|
3273
|
+
textBlocksByIndex.delete(idx);
|
|
3274
|
+
break;
|
|
3275
|
+
}
|
|
3276
|
+
}
|
|
3277
|
+
}
|
|
3278
|
+
textPartId = generateId();
|
|
3279
|
+
controller.enqueue({
|
|
3280
|
+
type: "text-start",
|
|
3281
|
+
id: textPartId
|
|
3282
|
+
});
|
|
3283
|
+
controller.enqueue({
|
|
3284
|
+
type: "text-delta",
|
|
3285
|
+
id: textPartId,
|
|
3286
|
+
delta: text
|
|
3287
|
+
});
|
|
3288
|
+
streamedTextLength = Math.max(streamedTextLength, text.length);
|
|
3289
|
+
this.logger.debug(
|
|
3290
|
+
"[claude-code] Emitted superseding assistant message as a new text part (canonical replacement)"
|
|
3291
|
+
);
|
|
3292
|
+
}
|
|
3293
|
+
} else if (hasReceivedStreamEvents) {
|
|
2072
3294
|
const newTextStart = streamedTextLength;
|
|
2073
3295
|
const deltaText = text.length > newTextStart ? text.slice(newTextStart) : "";
|
|
2074
3296
|
accumulatedText = text;
|
|
3297
|
+
textSegments.length = 0;
|
|
3298
|
+
textSegments.push({
|
|
3299
|
+
...typeof message.uuid === "string" && { uuid: message.uuid },
|
|
3300
|
+
text
|
|
3301
|
+
});
|
|
2075
3302
|
if (options.responseFormat?.type !== "json" && deltaText) {
|
|
2076
3303
|
if (!textPartId) {
|
|
2077
3304
|
textPartId = generateId();
|
|
@@ -2089,6 +3316,10 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2089
3316
|
streamedTextLength = text.length;
|
|
2090
3317
|
} else {
|
|
2091
3318
|
accumulatedText += text;
|
|
3319
|
+
textSegments.push({
|
|
3320
|
+
...typeof message.uuid === "string" && { uuid: message.uuid },
|
|
3321
|
+
text
|
|
3322
|
+
});
|
|
2092
3323
|
if (options.responseFormat?.type !== "json") {
|
|
2093
3324
|
if (!textPartId) {
|
|
2094
3325
|
textPartId = generateId();
|
|
@@ -2105,6 +3336,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2105
3336
|
}
|
|
2106
3337
|
}
|
|
2107
3338
|
}
|
|
3339
|
+
emittedTextSinceLastAssistant = "";
|
|
2108
3340
|
} else if (message.type === "user") {
|
|
2109
3341
|
if (!message.message?.content) {
|
|
2110
3342
|
this.logger.warn(
|
|
@@ -2125,13 +3357,18 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2125
3357
|
break;
|
|
2126
3358
|
}
|
|
2127
3359
|
}
|
|
2128
|
-
accumulatedText = "";
|
|
2129
|
-
streamedTextLength = 0;
|
|
2130
3360
|
this.logger.debug("[claude-code] Closed text part due to user message");
|
|
2131
3361
|
}
|
|
3362
|
+
accumulatedText = "";
|
|
3363
|
+
textSegments.length = 0;
|
|
3364
|
+
streamedTextLength = 0;
|
|
3365
|
+
emittedTextSinceLastAssistant = "";
|
|
2132
3366
|
const sdkParentToolUseIdForResults = message.parent_tool_use_id;
|
|
2133
3367
|
const content = message.message.content;
|
|
2134
3368
|
for (const result of this.extractToolResults(content)) {
|
|
3369
|
+
if (this.isRetractedToolFrame(result.id, retractedStreamToolIds, "result")) {
|
|
3370
|
+
continue;
|
|
3371
|
+
}
|
|
2135
3372
|
let state = toolStates.get(result.id);
|
|
2136
3373
|
const toolName = result.name ?? state?.name ?? _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
|
|
2137
3374
|
this.logger.debug(
|
|
@@ -2141,7 +3378,11 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2141
3378
|
this.logger.warn(
|
|
2142
3379
|
`[claude-code] Received tool result for unknown tool ID: ${result.id}`
|
|
2143
3380
|
);
|
|
2144
|
-
const resolvedParentId = toolName
|
|
3381
|
+
const resolvedParentId = isSubagentToolName(toolName) ? null : resolveToolParentId(
|
|
3382
|
+
sdkParentToolUseIdForResults,
|
|
3383
|
+
void 0,
|
|
3384
|
+
getFallbackParentId
|
|
3385
|
+
);
|
|
2145
3386
|
state = {
|
|
2146
3387
|
name: toolName,
|
|
2147
3388
|
inputStarted: false,
|
|
@@ -2175,50 +3416,24 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2175
3416
|
}
|
|
2176
3417
|
}
|
|
2177
3418
|
state.name = toolName;
|
|
2178
|
-
const normalizedResult = this.normalizeToolResult(result.result);
|
|
2179
|
-
const rawResult = typeof result.result === "string" ? result.result : (() => {
|
|
2180
|
-
try {
|
|
2181
|
-
return JSON.stringify(result.result);
|
|
2182
|
-
} catch {
|
|
2183
|
-
return String(result.result);
|
|
2184
|
-
}
|
|
2185
|
-
})();
|
|
2186
|
-
const maxToolResultSize = this.settings.maxToolResultSize;
|
|
2187
|
-
const truncatedResult = truncateToolResultForStream(
|
|
2188
|
-
normalizedResult,
|
|
2189
|
-
maxToolResultSize
|
|
2190
|
-
);
|
|
2191
|
-
const truncatedRawResult = truncateToolResultForStream(
|
|
2192
|
-
rawResult,
|
|
2193
|
-
maxToolResultSize
|
|
2194
|
-
);
|
|
2195
|
-
const rawResultTruncated = truncatedRawResult !== rawResult;
|
|
2196
3419
|
emitToolCall(result.id, state);
|
|
2197
|
-
if (toolName
|
|
3420
|
+
if (isSubagentToolName(toolName)) {
|
|
2198
3421
|
activeTaskTools.delete(result.id);
|
|
2199
3422
|
}
|
|
2200
|
-
controller.enqueue(
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
providerMetadata: {
|
|
2210
|
-
"claude-code": {
|
|
2211
|
-
// rawResult preserves the original CLI output string before JSON parsing.
|
|
2212
|
-
// Use this when you need the exact string returned by the tool, especially
|
|
2213
|
-
// if the `result` field has been parsed/normalized and you need the original format.
|
|
2214
|
-
rawResult: truncatedRawResult,
|
|
2215
|
-
rawResultTruncated,
|
|
2216
|
-
parentToolCallId: state.parentToolCallId ?? null
|
|
2217
|
-
}
|
|
2218
|
-
}
|
|
2219
|
-
});
|
|
3423
|
+
controller.enqueue(
|
|
3424
|
+
this.buildToolResultPart(
|
|
3425
|
+
result.id,
|
|
3426
|
+
toolName,
|
|
3427
|
+
result.result,
|
|
3428
|
+
result.isError,
|
|
3429
|
+
state.parentToolCallId
|
|
3430
|
+
)
|
|
3431
|
+
);
|
|
2220
3432
|
}
|
|
2221
3433
|
for (const error of this.extractToolErrors(content)) {
|
|
3434
|
+
if (this.isRetractedToolFrame(error.id, retractedStreamToolIds, "error")) {
|
|
3435
|
+
continue;
|
|
3436
|
+
}
|
|
2222
3437
|
let state = toolStates.get(error.id);
|
|
2223
3438
|
const toolName = error.name ?? state?.name ?? _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
|
|
2224
3439
|
this.logger.debug(
|
|
@@ -2228,7 +3443,11 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2228
3443
|
this.logger.warn(
|
|
2229
3444
|
`[claude-code] Received tool error for unknown tool ID: ${error.id}`
|
|
2230
3445
|
);
|
|
2231
|
-
const errorResolvedParentId = toolName
|
|
3446
|
+
const errorResolvedParentId = isSubagentToolName(toolName) ? null : resolveToolParentId(
|
|
3447
|
+
sdkParentToolUseIdForResults,
|
|
3448
|
+
void 0,
|
|
3449
|
+
getFallbackParentId
|
|
3450
|
+
);
|
|
2232
3451
|
state = {
|
|
2233
3452
|
name: toolName,
|
|
2234
3453
|
inputStarted: true,
|
|
@@ -2239,37 +3458,24 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2239
3458
|
toolStates.set(error.id, state);
|
|
2240
3459
|
}
|
|
2241
3460
|
emitToolCall(error.id, state);
|
|
2242
|
-
if (toolName
|
|
3461
|
+
if (isSubagentToolName(toolName)) {
|
|
2243
3462
|
activeTaskTools.delete(error.id);
|
|
2244
3463
|
}
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
} catch {
|
|
2249
|
-
return String(error.error);
|
|
2250
|
-
}
|
|
2251
|
-
})() : String(error.error);
|
|
2252
|
-
controller.enqueue({
|
|
2253
|
-
type: "tool-error",
|
|
2254
|
-
toolCallId: error.id,
|
|
2255
|
-
toolName,
|
|
2256
|
-
error: rawError,
|
|
2257
|
-
providerExecuted: true,
|
|
2258
|
-
dynamic: true,
|
|
2259
|
-
// V3 field: indicates tool is provider-defined
|
|
2260
|
-
providerMetadata: {
|
|
2261
|
-
"claude-code": {
|
|
2262
|
-
rawError,
|
|
2263
|
-
parentToolCallId: state.parentToolCallId ?? null
|
|
2264
|
-
}
|
|
2265
|
-
}
|
|
2266
|
-
});
|
|
3464
|
+
controller.enqueue(
|
|
3465
|
+
this.buildToolErrorPart(error.id, toolName, error.error, state.parentToolCallId)
|
|
3466
|
+
);
|
|
2267
3467
|
}
|
|
2268
3468
|
} else if (message.type === "result") {
|
|
2269
3469
|
done();
|
|
3470
|
+
this.mergeResultPermissionDenials(message, metadataTracking);
|
|
2270
3471
|
if ("is_error" in message && message.is_error === true) {
|
|
2271
|
-
const
|
|
2272
|
-
|
|
3472
|
+
const resultText = "result" in message && typeof message.result === "string" ? message.result : void 0;
|
|
3473
|
+
const errorsText = "errors" in message && Array.isArray(message.errors) ? message.errors.filter((e) => typeof e === "string").join("; ") : "";
|
|
3474
|
+
const errorMessage = resultText ?? (errorsText || "Claude Code CLI returned an error");
|
|
3475
|
+
throw Object.assign(new Error(errorMessage), {
|
|
3476
|
+
exitCode: 1,
|
|
3477
|
+
errorKind: lastAssistantErrorKind
|
|
3478
|
+
});
|
|
2273
3479
|
}
|
|
2274
3480
|
if (message.subtype === "error_max_structured_output_retries") {
|
|
2275
3481
|
throw new Error(
|
|
@@ -2317,6 +3523,38 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2317
3523
|
type: "text-end",
|
|
2318
3524
|
id: jsonTextId
|
|
2319
3525
|
});
|
|
3526
|
+
} else if (options.responseFormat?.type === "json" && options.responseFormat.schema !== void 0 && finishReason.unified === "stop") {
|
|
3527
|
+
const recoveredJsonText = extractJsonObjectText(accumulatedText);
|
|
3528
|
+
if (recoveredJsonText === void 0) {
|
|
3529
|
+
throw createAPICallError({
|
|
3530
|
+
message: MISSING_STRUCTURED_OUTPUT_ERROR_MESSAGE,
|
|
3531
|
+
promptExcerpt: messagesPrompt.substring(0, 200),
|
|
3532
|
+
isRetryable: false
|
|
3533
|
+
});
|
|
3534
|
+
}
|
|
3535
|
+
this.logger.warn(
|
|
3536
|
+
"[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."
|
|
3537
|
+
);
|
|
3538
|
+
if (textPartId) {
|
|
3539
|
+
controller.enqueue({
|
|
3540
|
+
type: "text-end",
|
|
3541
|
+
id: textPartId
|
|
3542
|
+
});
|
|
3543
|
+
}
|
|
3544
|
+
const recoveredTextId = generateId();
|
|
3545
|
+
controller.enqueue({
|
|
3546
|
+
type: "text-start",
|
|
3547
|
+
id: recoveredTextId
|
|
3548
|
+
});
|
|
3549
|
+
controller.enqueue({
|
|
3550
|
+
type: "text-delta",
|
|
3551
|
+
id: recoveredTextId,
|
|
3552
|
+
delta: recoveredJsonText
|
|
3553
|
+
});
|
|
3554
|
+
controller.enqueue({
|
|
3555
|
+
type: "text-end",
|
|
3556
|
+
id: recoveredTextId
|
|
3557
|
+
});
|
|
2320
3558
|
} else if (textPartId) {
|
|
2321
3559
|
controller.enqueue({
|
|
2322
3560
|
type: "text-end",
|
|
@@ -2354,6 +3592,32 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2354
3592
|
...message.modelUsage !== void 0 && {
|
|
2355
3593
|
modelUsage: message.modelUsage
|
|
2356
3594
|
},
|
|
3595
|
+
// SDK 0.3.x timing metadata (ttft_* only present on SDKResultSuccess)
|
|
3596
|
+
..."ttft_ms" in message && message.ttft_ms !== void 0 && { ttftMs: message.ttft_ms },
|
|
3597
|
+
..."ttft_stream_ms" in message && message.ttft_stream_ms !== void 0 && {
|
|
3598
|
+
ttftStreamMs: message.ttft_stream_ms
|
|
3599
|
+
},
|
|
3600
|
+
..."time_to_request_ms" in message && message.time_to_request_ms !== void 0 && {
|
|
3601
|
+
timeToRequestMs: message.time_to_request_ms
|
|
3602
|
+
},
|
|
3603
|
+
..."warm_spare_claimed" in message && message.warm_spare_claimed !== void 0 && {
|
|
3604
|
+
warmSpareClaimed: message.warm_spare_claimed
|
|
3605
|
+
},
|
|
3606
|
+
...message.terminal_reason !== void 0 && {
|
|
3607
|
+
terminalReason: message.terminal_reason
|
|
3608
|
+
},
|
|
3609
|
+
...metadataTracking.apiRetries > 0 && {
|
|
3610
|
+
apiRetries: metadataTracking.apiRetries
|
|
3611
|
+
},
|
|
3612
|
+
...metadataTracking.permissionDenials.length > 0 && {
|
|
3613
|
+
permissionDenials: metadataTracking.permissionDenials
|
|
3614
|
+
},
|
|
3615
|
+
...metadataTracking.mirrorErrors.length > 0 && {
|
|
3616
|
+
mirrorErrors: metadataTracking.mirrorErrors
|
|
3617
|
+
},
|
|
3618
|
+
...metadataTracking.estimatedThinkingTokens > 0 && {
|
|
3619
|
+
estimatedThinkingTokens: metadataTracking.estimatedThinkingTokens
|
|
3620
|
+
},
|
|
2357
3621
|
// JSON validation warnings are collected during streaming and included
|
|
2358
3622
|
// in providerMetadata since the AI SDK's finish event doesn't support
|
|
2359
3623
|
// a top-level warnings field (unlike stream-start which was already emitted)
|
|
@@ -2364,6 +3628,10 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2364
3628
|
}
|
|
2365
3629
|
});
|
|
2366
3630
|
controller.close();
|
|
3631
|
+
const effectivePromptSuggestions = sdkOptions?.promptSuggestions ?? this.settings.promptSuggestions;
|
|
3632
|
+
if (this.settings.onPromptSuggestion && effectivePromptSuggestions !== false) {
|
|
3633
|
+
await this.drainPromptSuggestion(response, this.settings.onPromptSuggestion);
|
|
3634
|
+
}
|
|
2367
3635
|
return;
|
|
2368
3636
|
} else if (message.type === "system" && message.subtype === "init") {
|
|
2369
3637
|
this.logMcpConnectionIssues(message.mcp_servers);
|
|
@@ -2375,6 +3643,15 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2375
3643
|
timestamp: /* @__PURE__ */ new Date(),
|
|
2376
3644
|
modelId: this.modelId
|
|
2377
3645
|
});
|
|
3646
|
+
} else if (message.type === "system") {
|
|
3647
|
+
this.handleSystemMessage(
|
|
3648
|
+
message,
|
|
3649
|
+
metadataTracking,
|
|
3650
|
+
buildRetractionEvictor(evictLive)
|
|
3651
|
+
);
|
|
3652
|
+
} else if (message.type === "prompt_suggestion") {
|
|
3653
|
+
this.logger.debug("[claude-code] Received prompt suggestion");
|
|
3654
|
+
this.settings.onPromptSuggestion?.(message.suggestion);
|
|
2378
3655
|
}
|
|
2379
3656
|
}
|
|
2380
3657
|
finalizeToolCalls();
|
|
@@ -2425,6 +3702,18 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
2425
3702
|
"claude-code": {
|
|
2426
3703
|
...this.sessionId !== void 0 && { sessionId: this.sessionId },
|
|
2427
3704
|
truncated: true,
|
|
3705
|
+
...metadataTracking.apiRetries > 0 && {
|
|
3706
|
+
apiRetries: metadataTracking.apiRetries
|
|
3707
|
+
},
|
|
3708
|
+
...metadataTracking.permissionDenials.length > 0 && {
|
|
3709
|
+
permissionDenials: metadataTracking.permissionDenials
|
|
3710
|
+
},
|
|
3711
|
+
...metadataTracking.mirrorErrors.length > 0 && {
|
|
3712
|
+
mirrorErrors: metadataTracking.mirrorErrors
|
|
3713
|
+
},
|
|
3714
|
+
...metadataTracking.estimatedThinkingTokens > 0 && {
|
|
3715
|
+
estimatedThinkingTokens: metadataTracking.estimatedThinkingTokens
|
|
3716
|
+
},
|
|
2428
3717
|
...streamWarnings.length > 0 && {
|
|
2429
3718
|
warnings: warningsJson
|
|
2430
3719
|
}
|
|
@@ -2539,11 +3828,60 @@ function createClaudeCode(options = {}) {
|
|
|
2539
3828
|
var claudeCode = createClaudeCode();
|
|
2540
3829
|
|
|
2541
3830
|
// src/index.ts
|
|
2542
|
-
import {
|
|
3831
|
+
import {
|
|
3832
|
+
createSdkMcpServer as createSdkMcpServer2,
|
|
3833
|
+
tool as tool2,
|
|
3834
|
+
SYSTEM_PROMPT_DYNAMIC_BOUNDARY,
|
|
3835
|
+
InMemorySessionStore,
|
|
3836
|
+
HOOK_EVENTS,
|
|
3837
|
+
AbortError
|
|
3838
|
+
} from "@anthropic-ai/claude-agent-sdk";
|
|
3839
|
+
import {
|
|
3840
|
+
listSessions,
|
|
3841
|
+
forkSession,
|
|
3842
|
+
getSessionInfo,
|
|
3843
|
+
getSessionMessages,
|
|
3844
|
+
deleteSession,
|
|
3845
|
+
renameSession,
|
|
3846
|
+
tagSession,
|
|
3847
|
+
listSubagents,
|
|
3848
|
+
getSubagentMessages,
|
|
3849
|
+
foldSessionSummary,
|
|
3850
|
+
importSessionToStore
|
|
3851
|
+
} from "@anthropic-ai/claude-agent-sdk";
|
|
3852
|
+
import { startup } from "@anthropic-ai/claude-agent-sdk";
|
|
2543
3853
|
|
|
2544
3854
|
// src/mcp-helpers.ts
|
|
2545
3855
|
import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
2546
3856
|
import "zod";
|
|
3857
|
+
function buildIsErrorResult(text) {
|
|
3858
|
+
return {
|
|
3859
|
+
isError: true,
|
|
3860
|
+
content: [{ type: "text", text }]
|
|
3861
|
+
};
|
|
3862
|
+
}
|
|
3863
|
+
async function normalizeToolResultToText(toolName, result) {
|
|
3864
|
+
if (result != null && typeof result[Symbol.asyncIterator] === "function") {
|
|
3865
|
+
let last;
|
|
3866
|
+
for await (const chunk of result) {
|
|
3867
|
+
last = chunk;
|
|
3868
|
+
}
|
|
3869
|
+
result = last;
|
|
3870
|
+
}
|
|
3871
|
+
if (typeof result === "string") {
|
|
3872
|
+
return { text: result };
|
|
3873
|
+
}
|
|
3874
|
+
try {
|
|
3875
|
+
return { text: JSON.stringify(result) ?? "undefined" };
|
|
3876
|
+
} catch (serializationError) {
|
|
3877
|
+
const reason = serializationError instanceof Error ? serializationError.message : String(serializationError);
|
|
3878
|
+
return {
|
|
3879
|
+
isError: buildIsErrorResult(
|
|
3880
|
+
`Tool "${toolName}" succeeded but its result could not be serialized to JSON: ${reason}`
|
|
3881
|
+
)
|
|
3882
|
+
};
|
|
3883
|
+
}
|
|
3884
|
+
}
|
|
2547
3885
|
function createCustomMcpServer(config) {
|
|
2548
3886
|
const defs = Object.entries(config.tools).map(
|
|
2549
3887
|
([name, def]) => tool(
|
|
@@ -2556,18 +3894,96 @@ function createCustomMcpServer(config) {
|
|
|
2556
3894
|
);
|
|
2557
3895
|
return createSdkMcpServer({ name: config.name, version: config.version, tools: defs });
|
|
2558
3896
|
}
|
|
3897
|
+
var AI_SDK_SCHEMA_SYMBOL = Symbol.for("vercel.ai.schema");
|
|
3898
|
+
function isAiSdkJsonSchema(schema) {
|
|
3899
|
+
return typeof schema === "object" && schema !== null && AI_SDK_SCHEMA_SYMBOL in schema;
|
|
3900
|
+
}
|
|
3901
|
+
function isZodObjectSchema(schema) {
|
|
3902
|
+
if (typeof schema !== "object" || schema === null) {
|
|
3903
|
+
return false;
|
|
3904
|
+
}
|
|
3905
|
+
const candidate = schema;
|
|
3906
|
+
if (!("_zod" in candidate) && !("_def" in candidate)) {
|
|
3907
|
+
return false;
|
|
3908
|
+
}
|
|
3909
|
+
const typeTag = candidate._zod?.def?.type ?? candidate._def?.typeName;
|
|
3910
|
+
if (typeTag !== "object" && typeTag !== "ZodObject") {
|
|
3911
|
+
return false;
|
|
3912
|
+
}
|
|
3913
|
+
return typeof candidate.shape === "object" && candidate.shape !== null;
|
|
3914
|
+
}
|
|
3915
|
+
function createAiSdkMcpServer(name, tools) {
|
|
3916
|
+
const defs = Object.entries(tools).map(([toolName, def]) => {
|
|
3917
|
+
const execute = def.execute;
|
|
3918
|
+
if (typeof execute !== "function") {
|
|
3919
|
+
throw new Error(
|
|
3920
|
+
`createAiSdkMcpServer: tool "${toolName}" has no execute function. Only tools that execute locally can be bridged to the Claude Code CLI.`
|
|
3921
|
+
);
|
|
3922
|
+
}
|
|
3923
|
+
if (isAiSdkJsonSchema(def.inputSchema)) {
|
|
3924
|
+
throw new Error(
|
|
3925
|
+
`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.`
|
|
3926
|
+
);
|
|
3927
|
+
}
|
|
3928
|
+
if (!isZodObjectSchema(def.inputSchema)) {
|
|
3929
|
+
throw new Error(
|
|
3930
|
+
`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.`
|
|
3931
|
+
);
|
|
3932
|
+
}
|
|
3933
|
+
const zodSchema = def.inputSchema;
|
|
3934
|
+
return tool(
|
|
3935
|
+
toolName,
|
|
3936
|
+
def.description ?? "",
|
|
3937
|
+
zodSchema.shape,
|
|
3938
|
+
async (args, extra) => {
|
|
3939
|
+
try {
|
|
3940
|
+
const extraInfo = extra ?? {};
|
|
3941
|
+
const result = await execute.call(def, args, {
|
|
3942
|
+
toolCallId: extraInfo.requestId !== void 0 ? String(extraInfo.requestId) : void 0,
|
|
3943
|
+
abortSignal: extraInfo.signal
|
|
3944
|
+
});
|
|
3945
|
+
const normalized = await normalizeToolResultToText(toolName, result);
|
|
3946
|
+
if ("isError" in normalized) {
|
|
3947
|
+
return normalized.isError;
|
|
3948
|
+
}
|
|
3949
|
+
return { content: [{ type: "text", text: normalized.text }] };
|
|
3950
|
+
} catch (error) {
|
|
3951
|
+
return buildIsErrorResult(error instanceof Error ? error.message : String(error));
|
|
3952
|
+
}
|
|
3953
|
+
}
|
|
3954
|
+
);
|
|
3955
|
+
});
|
|
3956
|
+
return createSdkMcpServer({ name, tools: defs });
|
|
3957
|
+
}
|
|
2559
3958
|
export {
|
|
3959
|
+
AbortError,
|
|
2560
3960
|
ClaudeCodeLanguageModel,
|
|
3961
|
+
HOOK_EVENTS,
|
|
3962
|
+
InMemorySessionStore,
|
|
3963
|
+
SYSTEM_PROMPT_DYNAMIC_BOUNDARY,
|
|
2561
3964
|
claudeCode,
|
|
2562
3965
|
createAPICallError,
|
|
3966
|
+
createAiSdkMcpServer,
|
|
2563
3967
|
createAuthenticationError,
|
|
2564
3968
|
createClaudeCode,
|
|
2565
3969
|
createCustomMcpServer,
|
|
2566
3970
|
createSdkMcpServer2 as createSdkMcpServer,
|
|
2567
3971
|
createTimeoutError,
|
|
3972
|
+
deleteSession,
|
|
3973
|
+
foldSessionSummary,
|
|
3974
|
+
forkSession,
|
|
2568
3975
|
getErrorMetadata,
|
|
3976
|
+
getSessionInfo,
|
|
3977
|
+
getSessionMessages,
|
|
3978
|
+
getSubagentMessages,
|
|
3979
|
+
importSessionToStore,
|
|
2569
3980
|
isAuthenticationError,
|
|
2570
3981
|
isTimeoutError,
|
|
3982
|
+
listSessions,
|
|
3983
|
+
listSubagents,
|
|
3984
|
+
renameSession,
|
|
3985
|
+
startup,
|
|
3986
|
+
tagSession,
|
|
2571
3987
|
tool2 as tool
|
|
2572
3988
|
};
|
|
2573
3989
|
//# sourceMappingURL=index.js.map
|