ai-sdk-provider-claude-code 3.2.1 → 3.3.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 +25 -0
- package/dist/index.cjs +359 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +359 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -361,6 +361,31 @@ See [examples/skills-management.ts](examples/skills-management.ts) for more exam
|
|
|
361
361
|
- For parity with other tool events, `tool-error` includes `providerExecuted: true` and `providerMetadata['claude-code']` (e.g., `rawError`). These fields are documented extensions; downstream consumers may safely ignore them if unused.
|
|
362
362
|
- See Tool Streaming Support for full event list, ordering guarantees, and performance considerations.
|
|
363
363
|
|
|
364
|
+
## Content Block Streaming
|
|
365
|
+
|
|
366
|
+
This provider handles Anthropic `content_block_*` stream events directly for more responsive UIs:
|
|
367
|
+
|
|
368
|
+
- **Tool input streaming** — `tool-input-delta` streams arguments incrementally; `tool-call` emits when the tool input block completes (before results), enabling “running” state in UIs.
|
|
369
|
+
- **Text streaming** — `text-start/delta/end` emitted from content blocks with proper lifecycle management.
|
|
370
|
+
- **Extended thinking** — `reasoning-start/delta/end` emitted from `thinking` content blocks (availability depends on model and request).
|
|
371
|
+
|
|
372
|
+
For subagent parent/child tracking, see **Subagent Hierarchy Tracking** in this README.
|
|
373
|
+
|
|
374
|
+
## Subagent Hierarchy Tracking
|
|
375
|
+
|
|
376
|
+
When Claude Code spawns subagents via the `Task` tool, this provider exposes parent-child relationships through `providerMetadata`:
|
|
377
|
+
|
|
378
|
+
```ts
|
|
379
|
+
// Available on tool-input-start, tool-call, tool-result, and tool-error events
|
|
380
|
+
providerMetadata['claude-code'].parentToolCallId: string | null;
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
- Task tools: Always null (top-level)
|
|
384
|
+
- Child tools: Reference their parent Task's ID
|
|
385
|
+
- Parallel Tasks: Child returns null if parent is ambiguous
|
|
386
|
+
|
|
387
|
+
This enables UIs to build hierarchical views of nested agent execution.
|
|
388
|
+
|
|
364
389
|
## Contributing
|
|
365
390
|
|
|
366
391
|
We welcome contributions, especially:
|
package/dist/index.cjs
CHANGED
|
@@ -567,7 +567,8 @@ var claudeCodeSettingsSchema = import_zod.z.object({
|
|
|
567
567
|
spawnClaudeCodeProcess: import_zod.z.any().refine((val) => val === void 0 || typeof val === "function", {
|
|
568
568
|
message: "spawnClaudeCodeProcess must be a function"
|
|
569
569
|
}).optional(),
|
|
570
|
-
sdkOptions: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional()
|
|
570
|
+
sdkOptions: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional(),
|
|
571
|
+
maxToolResultSize: import_zod.z.number().int().min(100).max(1e6).optional()
|
|
571
572
|
}).strict();
|
|
572
573
|
function validateModelId(modelId) {
|
|
573
574
|
const knownModels = ["opus", "sonnet", "haiku"];
|
|
@@ -732,6 +733,37 @@ function isAbortError(err) {
|
|
|
732
733
|
}
|
|
733
734
|
return false;
|
|
734
735
|
}
|
|
736
|
+
var DEFAULT_INHERITED_ENV_VARS = process.platform === "win32" ? [
|
|
737
|
+
"APPDATA",
|
|
738
|
+
"HOMEDRIVE",
|
|
739
|
+
"HOMEPATH",
|
|
740
|
+
"LOCALAPPDATA",
|
|
741
|
+
"PATH",
|
|
742
|
+
"PATHEXT",
|
|
743
|
+
"SYSTEMDRIVE",
|
|
744
|
+
"SYSTEMROOT",
|
|
745
|
+
"TEMP",
|
|
746
|
+
"TMP",
|
|
747
|
+
"USERNAME",
|
|
748
|
+
"USERPROFILE",
|
|
749
|
+
"WINDIR"
|
|
750
|
+
] : ["HOME", "LOGNAME", "PATH", "SHELL", "TERM", "USER", "LANG", "LC_ALL", "TMPDIR"];
|
|
751
|
+
var CLAUDE_ENV_VARS = ["CLAUDE_CONFIG_DIR"];
|
|
752
|
+
function getBaseProcessEnv() {
|
|
753
|
+
const env = {};
|
|
754
|
+
const allowedKeys = /* @__PURE__ */ new Set([...DEFAULT_INHERITED_ENV_VARS, ...CLAUDE_ENV_VARS]);
|
|
755
|
+
for (const key of allowedKeys) {
|
|
756
|
+
const value = process.env[key];
|
|
757
|
+
if (typeof value !== "string") {
|
|
758
|
+
continue;
|
|
759
|
+
}
|
|
760
|
+
if (value.startsWith("()")) {
|
|
761
|
+
continue;
|
|
762
|
+
}
|
|
763
|
+
env[key] = value;
|
|
764
|
+
}
|
|
765
|
+
return env;
|
|
766
|
+
}
|
|
735
767
|
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).";
|
|
736
768
|
var SDK_OPTIONS_BLOCKLIST = /* @__PURE__ */ new Set(["model", "abortController", "prompt", "outputFormat"]);
|
|
737
769
|
function createEmptyUsage() {
|
|
@@ -793,6 +825,49 @@ var modelMap = {
|
|
|
793
825
|
sonnet: "sonnet",
|
|
794
826
|
haiku: "haiku"
|
|
795
827
|
};
|
|
828
|
+
var MAX_TOOL_RESULT_SIZE = 1e4;
|
|
829
|
+
function truncateToolResultForStream(result, maxSize = MAX_TOOL_RESULT_SIZE) {
|
|
830
|
+
if (typeof result === "string") {
|
|
831
|
+
if (result.length <= maxSize) return result;
|
|
832
|
+
return result.slice(0, maxSize) + `
|
|
833
|
+
...[truncated ${result.length - maxSize} chars]`;
|
|
834
|
+
}
|
|
835
|
+
if (typeof result !== "object" || result === null) return result;
|
|
836
|
+
if (Array.isArray(result)) {
|
|
837
|
+
let largestIndex = -1;
|
|
838
|
+
let largestSize2 = 0;
|
|
839
|
+
for (let i = 0; i < result.length; i++) {
|
|
840
|
+
const value = result[i];
|
|
841
|
+
if (typeof value === "string" && value.length > largestSize2) {
|
|
842
|
+
largestIndex = i;
|
|
843
|
+
largestSize2 = value.length;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
if (largestIndex >= 0 && largestSize2 > maxSize) {
|
|
847
|
+
const truncatedValue = result[largestIndex].slice(0, maxSize) + `
|
|
848
|
+
...[truncated ${largestSize2 - maxSize} chars]`;
|
|
849
|
+
const cloned = [...result];
|
|
850
|
+
cloned[largestIndex] = truncatedValue;
|
|
851
|
+
return cloned;
|
|
852
|
+
}
|
|
853
|
+
return result;
|
|
854
|
+
}
|
|
855
|
+
const obj = result;
|
|
856
|
+
let largestKey = null;
|
|
857
|
+
let largestSize = 0;
|
|
858
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
859
|
+
if (typeof value === "string" && value.length > largestSize) {
|
|
860
|
+
largestKey = key;
|
|
861
|
+
largestSize = value.length;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
if (largestKey && largestSize > maxSize) {
|
|
865
|
+
const truncatedValue = obj[largestKey].slice(0, maxSize) + `
|
|
866
|
+
...[truncated ${largestSize - maxSize} chars]`;
|
|
867
|
+
return { ...obj, [largestKey]: truncatedValue };
|
|
868
|
+
}
|
|
869
|
+
return result;
|
|
870
|
+
}
|
|
796
871
|
var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
797
872
|
specificationVersion = "v3";
|
|
798
873
|
defaultObjectGenerationMode = "json";
|
|
@@ -864,11 +939,12 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
864
939
|
return content.filter(
|
|
865
940
|
(item) => typeof item === "object" && item !== null && "type" in item && item.type === "tool_use"
|
|
866
941
|
).map((item) => {
|
|
867
|
-
const { id, name, input } = item;
|
|
942
|
+
const { id, name, input, parent_tool_use_id } = item;
|
|
868
943
|
return {
|
|
869
944
|
id: typeof id === "string" && id.length > 0 ? id : (0, import_provider_utils.generateId)(),
|
|
870
945
|
name: typeof name === "string" && name.length > 0 ? name : _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME,
|
|
871
|
-
input
|
|
946
|
+
input,
|
|
947
|
+
parentToolUseId: typeof parent_tool_use_id === "string" ? parent_tool_use_id : null
|
|
872
948
|
};
|
|
873
949
|
});
|
|
874
950
|
}
|
|
@@ -940,6 +1016,27 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
940
1016
|
return result;
|
|
941
1017
|
}
|
|
942
1018
|
}
|
|
1019
|
+
if (Array.isArray(result) && result.length > 0) {
|
|
1020
|
+
const textBlocks = result.filter(
|
|
1021
|
+
(block) => block?.type === "text" && typeof block.text === "string"
|
|
1022
|
+
).map((block) => block.text);
|
|
1023
|
+
if (textBlocks.length !== result.length) {
|
|
1024
|
+
return result;
|
|
1025
|
+
}
|
|
1026
|
+
if (textBlocks.length === 1) {
|
|
1027
|
+
try {
|
|
1028
|
+
return JSON.parse(textBlocks[0]);
|
|
1029
|
+
} catch {
|
|
1030
|
+
return textBlocks[0];
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
const combined = textBlocks.join("\n");
|
|
1034
|
+
try {
|
|
1035
|
+
return JSON.parse(combined);
|
|
1036
|
+
} catch {
|
|
1037
|
+
return combined;
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
943
1040
|
return result;
|
|
944
1041
|
}
|
|
945
1042
|
generateAllWarnings(options, prompt) {
|
|
@@ -1084,7 +1181,8 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1084
1181
|
};
|
|
1085
1182
|
}
|
|
1086
1183
|
if (this.settings.env !== void 0 || sdkEnv !== void 0) {
|
|
1087
|
-
|
|
1184
|
+
const baseEnv = getBaseProcessEnv();
|
|
1185
|
+
opts.env = { ...baseEnv, ...this.settings.env, ...sdkEnv };
|
|
1088
1186
|
}
|
|
1089
1187
|
if (responseFormat?.type === "json" && responseFormat.schema) {
|
|
1090
1188
|
opts.outputFormat = {
|
|
@@ -1386,6 +1484,13 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1386
1484
|
done = () => resolve(void 0);
|
|
1387
1485
|
});
|
|
1388
1486
|
const toolStates = /* @__PURE__ */ new Map();
|
|
1487
|
+
const activeTaskTools = /* @__PURE__ */ new Map();
|
|
1488
|
+
const getFallbackParentId = () => {
|
|
1489
|
+
if (activeTaskTools.size === 1) {
|
|
1490
|
+
return activeTaskTools.keys().next().value ?? null;
|
|
1491
|
+
}
|
|
1492
|
+
return null;
|
|
1493
|
+
};
|
|
1389
1494
|
const streamWarnings = [];
|
|
1390
1495
|
const closeToolInput = (toolId, state) => {
|
|
1391
1496
|
if (!state.inputClosed && state.inputStarted) {
|
|
@@ -1414,7 +1519,8 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1414
1519
|
// rawInput preserves the original serialized format before AI SDK normalization.
|
|
1415
1520
|
// Use this if you need the exact string sent to the Claude CLI, which may differ
|
|
1416
1521
|
// from the `input` field after AI SDK processing.
|
|
1417
|
-
rawInput: state.lastSerializedInput ?? ""
|
|
1522
|
+
rawInput: state.lastSerializedInput ?? "",
|
|
1523
|
+
parentToolCallId: state.parentToolCallId ?? null
|
|
1418
1524
|
}
|
|
1419
1525
|
}
|
|
1420
1526
|
});
|
|
@@ -1432,6 +1538,12 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1432
1538
|
let streamedTextLength = 0;
|
|
1433
1539
|
let hasReceivedStreamEvents = false;
|
|
1434
1540
|
let hasStreamedJson = false;
|
|
1541
|
+
const toolBlocksByIndex = /* @__PURE__ */ new Map();
|
|
1542
|
+
const toolInputAccumulators = /* @__PURE__ */ new Map();
|
|
1543
|
+
const textBlocksByIndex = /* @__PURE__ */ new Map();
|
|
1544
|
+
let textStreamedViaContentBlock = false;
|
|
1545
|
+
const reasoningBlocksByIndex = /* @__PURE__ */ new Map();
|
|
1546
|
+
let currentReasoningPartId;
|
|
1435
1547
|
try {
|
|
1436
1548
|
controller.enqueue({ type: "stream-start", warnings });
|
|
1437
1549
|
if (effectiveCanUseTool && effectivePermissionPromptToolName) {
|
|
@@ -1483,6 +1595,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1483
1595
|
if (event.type === "content_block_delta" && event.delta.type === "input_json_delta" && "partial_json" in event.delta && event.delta.partial_json) {
|
|
1484
1596
|
const jsonDelta = event.delta.partial_json;
|
|
1485
1597
|
hasReceivedStreamEvents = true;
|
|
1598
|
+
const blockIndex = "index" in event ? event.index : -1;
|
|
1486
1599
|
if (options.responseFormat?.type === "json") {
|
|
1487
1600
|
if (!textPartId) {
|
|
1488
1601
|
textPartId = (0, import_provider_utils.generateId)();
|
|
@@ -1499,6 +1612,189 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1499
1612
|
accumulatedText += jsonDelta;
|
|
1500
1613
|
streamedTextLength += jsonDelta.length;
|
|
1501
1614
|
hasStreamedJson = true;
|
|
1615
|
+
continue;
|
|
1616
|
+
}
|
|
1617
|
+
const toolId = toolBlocksByIndex.get(blockIndex);
|
|
1618
|
+
if (toolId) {
|
|
1619
|
+
const accumulated = (toolInputAccumulators.get(toolId) ?? "") + jsonDelta;
|
|
1620
|
+
toolInputAccumulators.set(toolId, accumulated);
|
|
1621
|
+
controller.enqueue({
|
|
1622
|
+
type: "tool-input-delta",
|
|
1623
|
+
id: toolId,
|
|
1624
|
+
delta: jsonDelta
|
|
1625
|
+
});
|
|
1626
|
+
continue;
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
if (event.type === "content_block_start" && "content_block" in event && event.content_block?.type === "tool_use") {
|
|
1630
|
+
const blockIndex = "index" in event ? event.index : -1;
|
|
1631
|
+
const toolBlock = event.content_block;
|
|
1632
|
+
const toolId = typeof toolBlock.id === "string" && toolBlock.id.length > 0 ? toolBlock.id : (0, import_provider_utils.generateId)();
|
|
1633
|
+
const toolName = typeof toolBlock.name === "string" && toolBlock.name.length > 0 ? toolBlock.name : _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
|
|
1634
|
+
hasReceivedStreamEvents = true;
|
|
1635
|
+
if (textPartId) {
|
|
1636
|
+
controller.enqueue({
|
|
1637
|
+
type: "text-end",
|
|
1638
|
+
id: textPartId
|
|
1639
|
+
});
|
|
1640
|
+
textPartId = void 0;
|
|
1641
|
+
}
|
|
1642
|
+
toolBlocksByIndex.set(blockIndex, toolId);
|
|
1643
|
+
toolInputAccumulators.set(toolId, "");
|
|
1644
|
+
let state = toolStates.get(toolId);
|
|
1645
|
+
if (!state) {
|
|
1646
|
+
const currentParentId = toolName === "Task" ? null : getFallbackParentId();
|
|
1647
|
+
state = {
|
|
1648
|
+
name: toolName,
|
|
1649
|
+
inputStarted: false,
|
|
1650
|
+
inputClosed: false,
|
|
1651
|
+
callEmitted: false,
|
|
1652
|
+
parentToolCallId: currentParentId
|
|
1653
|
+
};
|
|
1654
|
+
toolStates.set(toolId, state);
|
|
1655
|
+
}
|
|
1656
|
+
if (!state.inputStarted) {
|
|
1657
|
+
this.logger.debug(
|
|
1658
|
+
`[claude-code] Tool input started (content_block) - Tool: ${toolName}, ID: ${toolId}, parent: ${state.parentToolCallId}`
|
|
1659
|
+
);
|
|
1660
|
+
controller.enqueue({
|
|
1661
|
+
type: "tool-input-start",
|
|
1662
|
+
id: toolId,
|
|
1663
|
+
toolName,
|
|
1664
|
+
providerExecuted: true,
|
|
1665
|
+
dynamic: true,
|
|
1666
|
+
providerMetadata: {
|
|
1667
|
+
"claude-code": {
|
|
1668
|
+
parentToolCallId: state.parentToolCallId ?? null
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
});
|
|
1672
|
+
if (toolName === "Task") {
|
|
1673
|
+
activeTaskTools.set(toolId, { startTime: Date.now() });
|
|
1674
|
+
}
|
|
1675
|
+
state.inputStarted = true;
|
|
1676
|
+
}
|
|
1677
|
+
continue;
|
|
1678
|
+
}
|
|
1679
|
+
if (event.type === "content_block_start" && "content_block" in event && event.content_block?.type === "text") {
|
|
1680
|
+
const blockIndex = "index" in event ? event.index : -1;
|
|
1681
|
+
hasReceivedStreamEvents = true;
|
|
1682
|
+
const partId = (0, import_provider_utils.generateId)();
|
|
1683
|
+
textBlocksByIndex.set(blockIndex, partId);
|
|
1684
|
+
textPartId = partId;
|
|
1685
|
+
this.logger.debug(
|
|
1686
|
+
`[claude-code] Text content block started - Index: ${blockIndex}, ID: ${partId}`
|
|
1687
|
+
);
|
|
1688
|
+
controller.enqueue({
|
|
1689
|
+
type: "text-start",
|
|
1690
|
+
id: partId
|
|
1691
|
+
});
|
|
1692
|
+
textStreamedViaContentBlock = true;
|
|
1693
|
+
continue;
|
|
1694
|
+
}
|
|
1695
|
+
if (event.type === "content_block_start" && "content_block" in event && event.content_block?.type === "thinking") {
|
|
1696
|
+
const blockIndex = "index" in event ? event.index : -1;
|
|
1697
|
+
hasReceivedStreamEvents = true;
|
|
1698
|
+
if (textPartId) {
|
|
1699
|
+
controller.enqueue({
|
|
1700
|
+
type: "text-end",
|
|
1701
|
+
id: textPartId
|
|
1702
|
+
});
|
|
1703
|
+
textPartId = void 0;
|
|
1704
|
+
}
|
|
1705
|
+
const reasoningPartId = (0, import_provider_utils.generateId)();
|
|
1706
|
+
reasoningBlocksByIndex.set(blockIndex, reasoningPartId);
|
|
1707
|
+
currentReasoningPartId = reasoningPartId;
|
|
1708
|
+
this.logger.debug(
|
|
1709
|
+
`[claude-code] Reasoning started (content_block) - ID: ${reasoningPartId}`
|
|
1710
|
+
);
|
|
1711
|
+
controller.enqueue({
|
|
1712
|
+
type: "reasoning-start",
|
|
1713
|
+
id: reasoningPartId
|
|
1714
|
+
});
|
|
1715
|
+
continue;
|
|
1716
|
+
}
|
|
1717
|
+
if (event.type === "content_block_delta" && event.delta.type === "thinking_delta" && "thinking" in event.delta && event.delta.thinking) {
|
|
1718
|
+
const blockIndex = "index" in event ? event.index : -1;
|
|
1719
|
+
const reasoningPartId = reasoningBlocksByIndex.get(blockIndex) ?? currentReasoningPartId;
|
|
1720
|
+
hasReceivedStreamEvents = true;
|
|
1721
|
+
if (reasoningPartId) {
|
|
1722
|
+
controller.enqueue({
|
|
1723
|
+
type: "reasoning-delta",
|
|
1724
|
+
id: reasoningPartId,
|
|
1725
|
+
delta: event.delta.thinking
|
|
1726
|
+
});
|
|
1727
|
+
}
|
|
1728
|
+
continue;
|
|
1729
|
+
}
|
|
1730
|
+
if (event.type === "content_block_stop") {
|
|
1731
|
+
const blockIndex = "index" in event ? event.index : -1;
|
|
1732
|
+
hasReceivedStreamEvents = true;
|
|
1733
|
+
const toolId = toolBlocksByIndex.get(blockIndex);
|
|
1734
|
+
if (toolId) {
|
|
1735
|
+
const state = toolStates.get(toolId);
|
|
1736
|
+
if (state && !state.inputClosed) {
|
|
1737
|
+
const accumulatedInput = toolInputAccumulators.get(toolId) ?? "";
|
|
1738
|
+
this.logger.debug(
|
|
1739
|
+
`[claude-code] Tool content block stopped - Index: ${blockIndex}, Tool: ${state.name}, ID: ${toolId}`
|
|
1740
|
+
);
|
|
1741
|
+
controller.enqueue({
|
|
1742
|
+
type: "tool-input-end",
|
|
1743
|
+
id: toolId
|
|
1744
|
+
});
|
|
1745
|
+
state.inputClosed = true;
|
|
1746
|
+
state.lastSerializedInput = accumulatedInput;
|
|
1747
|
+
if (!state.callEmitted) {
|
|
1748
|
+
controller.enqueue({
|
|
1749
|
+
type: "tool-call",
|
|
1750
|
+
toolCallId: toolId,
|
|
1751
|
+
toolName: state.name,
|
|
1752
|
+
input: accumulatedInput,
|
|
1753
|
+
providerExecuted: true,
|
|
1754
|
+
dynamic: true,
|
|
1755
|
+
providerMetadata: {
|
|
1756
|
+
"claude-code": {
|
|
1757
|
+
rawInput: accumulatedInput,
|
|
1758
|
+
parentToolCallId: state.parentToolCallId ?? null
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
});
|
|
1762
|
+
state.callEmitted = true;
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
toolBlocksByIndex.delete(blockIndex);
|
|
1766
|
+
toolInputAccumulators.delete(toolId);
|
|
1767
|
+
continue;
|
|
1768
|
+
}
|
|
1769
|
+
const textId = textBlocksByIndex.get(blockIndex);
|
|
1770
|
+
if (textId) {
|
|
1771
|
+
this.logger.debug(
|
|
1772
|
+
`[claude-code] Text content block stopped - Index: ${blockIndex}, ID: ${textId}`
|
|
1773
|
+
);
|
|
1774
|
+
controller.enqueue({
|
|
1775
|
+
type: "text-end",
|
|
1776
|
+
id: textId
|
|
1777
|
+
});
|
|
1778
|
+
textBlocksByIndex.delete(blockIndex);
|
|
1779
|
+
if (textPartId === textId) {
|
|
1780
|
+
textPartId = void 0;
|
|
1781
|
+
}
|
|
1782
|
+
continue;
|
|
1783
|
+
}
|
|
1784
|
+
const reasoningPartId = reasoningBlocksByIndex.get(blockIndex);
|
|
1785
|
+
if (reasoningPartId) {
|
|
1786
|
+
this.logger.debug(
|
|
1787
|
+
`[claude-code] Reasoning ended (content_block) - ID: ${reasoningPartId}`
|
|
1788
|
+
);
|
|
1789
|
+
controller.enqueue({
|
|
1790
|
+
type: "reasoning-end",
|
|
1791
|
+
id: reasoningPartId
|
|
1792
|
+
});
|
|
1793
|
+
reasoningBlocksByIndex.delete(blockIndex);
|
|
1794
|
+
if (currentReasoningPartId === reasoningPartId) {
|
|
1795
|
+
currentReasoningPartId = void 0;
|
|
1796
|
+
}
|
|
1797
|
+
continue;
|
|
1502
1798
|
}
|
|
1503
1799
|
}
|
|
1504
1800
|
continue;
|
|
@@ -1510,6 +1806,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1510
1806
|
);
|
|
1511
1807
|
continue;
|
|
1512
1808
|
}
|
|
1809
|
+
const sdkParentToolUseId = message.parent_tool_use_id;
|
|
1513
1810
|
const content = message.message.content;
|
|
1514
1811
|
const tools = this.extractToolUses(content);
|
|
1515
1812
|
if (textPartId && tools.length > 0) {
|
|
@@ -1523,15 +1820,22 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1523
1820
|
const toolId = tool3.id;
|
|
1524
1821
|
let state = toolStates.get(toolId);
|
|
1525
1822
|
if (!state) {
|
|
1823
|
+
const currentParentId = tool3.name === "Task" ? null : sdkParentToolUseId ?? tool3.parentToolUseId ?? getFallbackParentId();
|
|
1526
1824
|
state = {
|
|
1527
1825
|
name: tool3.name,
|
|
1528
1826
|
inputStarted: false,
|
|
1529
1827
|
inputClosed: false,
|
|
1530
|
-
callEmitted: false
|
|
1828
|
+
callEmitted: false,
|
|
1829
|
+
parentToolCallId: currentParentId
|
|
1531
1830
|
};
|
|
1532
1831
|
toolStates.set(toolId, state);
|
|
1533
1832
|
this.logger.debug(
|
|
1534
|
-
`[claude-code] New tool use detected - Tool: ${tool3.name}, ID: ${toolId}`
|
|
1833
|
+
`[claude-code] New tool use detected - Tool: ${tool3.name}, ID: ${toolId}, SDK parent: ${sdkParentToolUseId}, resolved parent: ${currentParentId}`
|
|
1834
|
+
);
|
|
1835
|
+
} else if (!state.parentToolCallId && sdkParentToolUseId && tool3.name !== "Task") {
|
|
1836
|
+
state.parentToolCallId = sdkParentToolUseId;
|
|
1837
|
+
this.logger.debug(
|
|
1838
|
+
`[claude-code] Retroactive parent context - Tool: ${tool3.name}, ID: ${toolId}, parent: ${sdkParentToolUseId}`
|
|
1535
1839
|
);
|
|
1536
1840
|
}
|
|
1537
1841
|
state.name = tool3.name;
|
|
@@ -1544,9 +1848,17 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1544
1848
|
id: toolId,
|
|
1545
1849
|
toolName: tool3.name,
|
|
1546
1850
|
providerExecuted: true,
|
|
1547
|
-
dynamic: true
|
|
1851
|
+
dynamic: true,
|
|
1548
1852
|
// V3 field: indicates tool is provider-defined
|
|
1853
|
+
providerMetadata: {
|
|
1854
|
+
"claude-code": {
|
|
1855
|
+
parentToolCallId: state.parentToolCallId ?? null
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1549
1858
|
});
|
|
1859
|
+
if (tool3.name === "Task") {
|
|
1860
|
+
activeTaskTools.set(toolId, { startTime: Date.now() });
|
|
1861
|
+
}
|
|
1550
1862
|
state.inputStarted = true;
|
|
1551
1863
|
}
|
|
1552
1864
|
const serializedInput = this.serializeToolInput(tool3.input);
|
|
@@ -1617,6 +1929,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1617
1929
|
);
|
|
1618
1930
|
continue;
|
|
1619
1931
|
}
|
|
1932
|
+
const sdkParentToolUseIdForResults = message.parent_tool_use_id;
|
|
1620
1933
|
const content = message.message.content;
|
|
1621
1934
|
for (const result of this.extractToolResults(content)) {
|
|
1622
1935
|
let state = toolStates.get(result.id);
|
|
@@ -1628,11 +1941,13 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1628
1941
|
this.logger.warn(
|
|
1629
1942
|
`[claude-code] Received tool result for unknown tool ID: ${result.id}`
|
|
1630
1943
|
);
|
|
1944
|
+
const resolvedParentId = toolName === "Task" ? null : sdkParentToolUseIdForResults ?? getFallbackParentId();
|
|
1631
1945
|
state = {
|
|
1632
1946
|
name: toolName,
|
|
1633
1947
|
inputStarted: false,
|
|
1634
1948
|
inputClosed: false,
|
|
1635
|
-
callEmitted: false
|
|
1949
|
+
callEmitted: false,
|
|
1950
|
+
parentToolCallId: resolvedParentId
|
|
1636
1951
|
};
|
|
1637
1952
|
toolStates.set(result.id, state);
|
|
1638
1953
|
if (!state.inputStarted) {
|
|
@@ -1641,8 +1956,13 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1641
1956
|
id: result.id,
|
|
1642
1957
|
toolName,
|
|
1643
1958
|
providerExecuted: true,
|
|
1644
|
-
dynamic: true
|
|
1959
|
+
dynamic: true,
|
|
1645
1960
|
// V3 field: indicates tool is provider-defined
|
|
1961
|
+
providerMetadata: {
|
|
1962
|
+
"claude-code": {
|
|
1963
|
+
parentToolCallId: state.parentToolCallId ?? null
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1646
1966
|
});
|
|
1647
1967
|
state.inputStarted = true;
|
|
1648
1968
|
}
|
|
@@ -1663,12 +1983,25 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1663
1983
|
return String(result.result);
|
|
1664
1984
|
}
|
|
1665
1985
|
})();
|
|
1986
|
+
const maxToolResultSize = this.settings.maxToolResultSize;
|
|
1987
|
+
const truncatedResult = truncateToolResultForStream(
|
|
1988
|
+
normalizedResult,
|
|
1989
|
+
maxToolResultSize
|
|
1990
|
+
);
|
|
1991
|
+
const truncatedRawResult = truncateToolResultForStream(
|
|
1992
|
+
rawResult,
|
|
1993
|
+
maxToolResultSize
|
|
1994
|
+
);
|
|
1995
|
+
const rawResultTruncated = truncatedRawResult !== rawResult;
|
|
1666
1996
|
emitToolCall(result.id, state);
|
|
1997
|
+
if (toolName === "Task") {
|
|
1998
|
+
activeTaskTools.delete(result.id);
|
|
1999
|
+
}
|
|
1667
2000
|
controller.enqueue({
|
|
1668
2001
|
type: "tool-result",
|
|
1669
2002
|
toolCallId: result.id,
|
|
1670
2003
|
toolName,
|
|
1671
|
-
result:
|
|
2004
|
+
result: truncatedResult,
|
|
1672
2005
|
isError: result.isError,
|
|
1673
2006
|
providerExecuted: true,
|
|
1674
2007
|
dynamic: true,
|
|
@@ -1678,7 +2011,9 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1678
2011
|
// rawResult preserves the original CLI output string before JSON parsing.
|
|
1679
2012
|
// Use this when you need the exact string returned by the tool, especially
|
|
1680
2013
|
// if the `result` field has been parsed/normalized and you need the original format.
|
|
1681
|
-
rawResult
|
|
2014
|
+
rawResult: truncatedRawResult,
|
|
2015
|
+
rawResultTruncated,
|
|
2016
|
+
parentToolCallId: state.parentToolCallId ?? null
|
|
1682
2017
|
}
|
|
1683
2018
|
}
|
|
1684
2019
|
});
|
|
@@ -1693,15 +2028,20 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1693
2028
|
this.logger.warn(
|
|
1694
2029
|
`[claude-code] Received tool error for unknown tool ID: ${error.id}`
|
|
1695
2030
|
);
|
|
2031
|
+
const errorResolvedParentId = toolName === "Task" ? null : sdkParentToolUseIdForResults ?? getFallbackParentId();
|
|
1696
2032
|
state = {
|
|
1697
2033
|
name: toolName,
|
|
1698
2034
|
inputStarted: true,
|
|
1699
2035
|
inputClosed: true,
|
|
1700
|
-
callEmitted: false
|
|
2036
|
+
callEmitted: false,
|
|
2037
|
+
parentToolCallId: errorResolvedParentId
|
|
1701
2038
|
};
|
|
1702
2039
|
toolStates.set(error.id, state);
|
|
1703
2040
|
}
|
|
1704
2041
|
emitToolCall(error.id, state);
|
|
2042
|
+
if (toolName === "Task") {
|
|
2043
|
+
activeTaskTools.delete(error.id);
|
|
2044
|
+
}
|
|
1705
2045
|
const rawError = typeof error.error === "string" ? error.error : typeof error.error === "object" && error.error !== null ? (() => {
|
|
1706
2046
|
try {
|
|
1707
2047
|
return JSON.stringify(error.error);
|
|
@@ -1719,7 +2059,8 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1719
2059
|
// V3 field: indicates tool is provider-defined
|
|
1720
2060
|
providerMetadata: {
|
|
1721
2061
|
"claude-code": {
|
|
1722
|
-
rawError
|
|
2062
|
+
rawError,
|
|
2063
|
+
parentToolCallId: state.parentToolCallId ?? null
|
|
1723
2064
|
}
|
|
1724
2065
|
}
|
|
1725
2066
|
});
|
|
@@ -1779,7 +2120,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1779
2120
|
type: "text-end",
|
|
1780
2121
|
id: textPartId
|
|
1781
2122
|
});
|
|
1782
|
-
} else if (accumulatedText) {
|
|
2123
|
+
} else if (accumulatedText && !textStreamedViaContentBlock) {
|
|
1783
2124
|
const fallbackTextId = (0, import_provider_utils.generateId)();
|
|
1784
2125
|
controller.enqueue({
|
|
1785
2126
|
type: "text-start",
|
|
@@ -1817,6 +2158,8 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1817
2158
|
}
|
|
1818
2159
|
}
|
|
1819
2160
|
});
|
|
2161
|
+
controller.close();
|
|
2162
|
+
return;
|
|
1820
2163
|
} else if (message.type === "system" && message.subtype === "init") {
|
|
1821
2164
|
this.setSessionId(message.session_id);
|
|
1822
2165
|
this.logger.info(`[claude-code] Stream session initialized: ${message.session_id}`);
|
|
@@ -1850,7 +2193,7 @@ var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
|
|
|
1850
2193
|
type: "text-end",
|
|
1851
2194
|
id: textPartId
|
|
1852
2195
|
});
|
|
1853
|
-
} else if (accumulatedText) {
|
|
2196
|
+
} else if (accumulatedText && !textStreamedViaContentBlock) {
|
|
1854
2197
|
const fallbackTextId = (0, import_provider_utils.generateId)();
|
|
1855
2198
|
controller.enqueue({
|
|
1856
2199
|
type: "text-start",
|