@co0ontty/wand 1.29.6 → 1.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/process-manager.js +5 -2
- package/dist/structured-session-manager.js +132 -24
- package/dist/types.d.ts +19 -0
- package/dist/web-ui/content/scripts.js +640 -131
- package/dist/web-ui/content/styles.css +259 -16
- package/dist/web-ui/content/vendor/wterm/wterm.bundle.js +1 -1
- package/package.json +1 -1
package/dist/process-manager.js
CHANGED
|
@@ -634,7 +634,10 @@ export class ProcessManager extends EventEmitter {
|
|
|
634
634
|
knownClaudeProjectMtimes: knownClaudeProjectMtimes ?? undefined,
|
|
635
635
|
approvalStats: { tool: 0, command: 0, file: 0, total: 0 },
|
|
636
636
|
selectedModel: selectedModel ?? null,
|
|
637
|
-
|
|
637
|
+
// cols 上限 256:与 @wterm/dom WASM grid 的 maxCols 硬编码一致,
|
|
638
|
+
// 防止服务端按 >256 cols 让 Claude 用 CSI 绝对列定位写到 wterm 实际
|
|
639
|
+
// 渲染不到的列上(表现为"内容神奇复制下行")。
|
|
640
|
+
ptyCols: opts?.cols !== undefined ? clampDimension(opts.cols, 20, 256) : 120,
|
|
638
641
|
ptyRows: opts?.rows !== undefined ? clampDimension(opts.rows, 10, 160) : 36,
|
|
639
642
|
};
|
|
640
643
|
if (isClaudeProvider) {
|
|
@@ -986,7 +989,7 @@ export class ProcessManager extends EventEmitter {
|
|
|
986
989
|
if (!record.ptyProcess || record.status !== "running") {
|
|
987
990
|
return this.snapshot(record);
|
|
988
991
|
}
|
|
989
|
-
const safeCols = clampDimension(cols, 20,
|
|
992
|
+
const safeCols = clampDimension(cols, 20, 256);
|
|
990
993
|
const safeRows = clampDimension(rows, 10, 160);
|
|
991
994
|
const changed = safeCols !== record.ptyCols || safeRows !== record.ptyRows;
|
|
992
995
|
record.ptyProcess.resize(safeCols, safeRows);
|
|
@@ -83,6 +83,40 @@ export function thinkingEffortToCodexFlag(effort) {
|
|
|
83
83
|
default: return null;
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
|
+
function captureTaskMeta(blocks, registry) {
|
|
87
|
+
for (const b of blocks) {
|
|
88
|
+
if (b.type !== "tool_use")
|
|
89
|
+
continue;
|
|
90
|
+
if (registry.has(b.id))
|
|
91
|
+
continue;
|
|
92
|
+
const input = b.input ?? {};
|
|
93
|
+
// Claude SDK 把这类"派 subagent 干活"的内置工具叫做 "Agent",CLI/旧版本里
|
|
94
|
+
// 也叫过 "Task"。判定不靠工具名(容易随版本变),而是看 input 是否含有
|
|
95
|
+
// `subagent_type` 字段——这是 Agent/Task 系列的唯一标志。
|
|
96
|
+
const agentType = typeof input.subagent_type === "string" ? input.subagent_type : undefined;
|
|
97
|
+
if (!agentType && b.name !== "Task" && b.name !== "Agent")
|
|
98
|
+
continue;
|
|
99
|
+
const description = typeof input.description === "string" ? input.description : undefined;
|
|
100
|
+
registry.set(b.id, { agentType, description });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Stamp every block with `__subagent` meta keyed to `parentToolUseId`. When
|
|
105
|
+
* the id has no entry yet (rare race: subagent emits before we see the parent
|
|
106
|
+
* Task tool_use), we still stamp the bare taskId so the UI can group blocks;
|
|
107
|
+
* agentType / description backfill on later updates.
|
|
108
|
+
*/
|
|
109
|
+
function tagSubagentBlocks(blocks, parentToolUseId, registry) {
|
|
110
|
+
if (!parentToolUseId)
|
|
111
|
+
return blocks;
|
|
112
|
+
const meta = registry.get(parentToolUseId);
|
|
113
|
+
const stamp = {
|
|
114
|
+
taskId: parentToolUseId,
|
|
115
|
+
...(meta?.agentType ? { agentType: meta.agentType } : {}),
|
|
116
|
+
...(meta?.description ? { taskDescription: meta.description } : {}),
|
|
117
|
+
};
|
|
118
|
+
return blocks.map((block) => ({ ...block, __subagent: stamp }));
|
|
119
|
+
}
|
|
86
120
|
const STREAM_EMIT_DEBOUNCE_MS = 16;
|
|
87
121
|
/** Min interval between full saveSession() calls for an in-progress streaming turn.
|
|
88
122
|
* saveSession serializes the entire messages array, so doing it on every NDJSON
|
|
@@ -1342,6 +1376,9 @@ export class StructuredSessionManager {
|
|
|
1342
1376
|
const blocksByKey = new Map();
|
|
1343
1377
|
const keyOrder = [];
|
|
1344
1378
|
let toolResultSeq = 0;
|
|
1379
|
+
// 本轮 Task tool_use_id → meta map,由父 assistant 消息里的 Task tool_use
|
|
1380
|
+
// 填充;子 agent message(parent_tool_use_id 非空)来时用它给每个 block 盖章。
|
|
1381
|
+
const taskMetaRegistry = new Map();
|
|
1345
1382
|
// 估算单个 ContentBlock 的"信息体积"——文字 / thinking / tool input 长度之和。
|
|
1346
1383
|
// 用于 upsertBlocks 的防御性合并:同一 message.id 重发时,按位置取信息量更大的
|
|
1347
1384
|
// 那个版本,保证已经吐出的文字 / tool_use input 不会被一条更短的同 id 事件
|
|
@@ -1372,22 +1409,25 @@ export class StructuredSessionManager {
|
|
|
1372
1409
|
blocksByKey.set(key, blocks);
|
|
1373
1410
|
return;
|
|
1374
1411
|
}
|
|
1375
|
-
// claude -p 在同一 message.id 的多次 assistant
|
|
1376
|
-
//
|
|
1377
|
-
//
|
|
1412
|
+
// claude -p 在同一 message.id 的多次 assistant 事件有两种观察到的协议:
|
|
1413
|
+
// a) **累积模式**:每次 event 的 content = 之前所有 blocks + 0~N 新 block,
|
|
1414
|
+
// 同位置类型一致。流式 text/thinking 的逐字增量属于这种。
|
|
1415
|
+
// b) **拼接模式**:SDK 把 thinking 和后续的 tool_use 拆成两条 event 给同
|
|
1416
|
+
// 一 msg.id 发出,第二条只带 tool_use,**不包含**之前的 thinking。
|
|
1417
|
+
// Opus 4.7 + claude-agent-sdk 实际跑下来就是这种。
|
|
1378
1418
|
//
|
|
1379
|
-
//
|
|
1380
|
-
//
|
|
1419
|
+
// 老逻辑("同 index 类型不一致 → 保留 prev")只对 a) 友好,碰上 b) 会让第
|
|
1420
|
+
// 二条事件里的 tool_use 直接被丢掉——表现是 Agent / Read 等 tool_use 永远
|
|
1421
|
+
// 不出现在 messages 里,subagent 多角色无法关联 agentType 到父 Task。
|
|
1381
1422
|
//
|
|
1382
|
-
//
|
|
1383
|
-
//
|
|
1384
|
-
//
|
|
1385
|
-
//
|
|
1386
|
-
// event 给出最终 turnState.result,compactContentBlocks 的 fallback
|
|
1387
|
-
// 才补回 text。用户反馈"文字消失,回复完成后又出现"就是这条路径。
|
|
1423
|
+
// 新规则:当类型不一致时,把新 block **追加**到 merged 末尾而非覆盖 prev。
|
|
1424
|
+
// 既兼容 a)(同位置同类型仍按累积取大),又兼容 b)(拼接的新类型 block
|
|
1425
|
+
// 进入末尾),还能挡住 b 早期版本里"短回退"的异常 frame(blocks.length
|
|
1426
|
+
// < prev.length 时直接拒绝)。
|
|
1388
1427
|
if (blocks.length < prev.length)
|
|
1389
1428
|
return;
|
|
1390
1429
|
const merged = [];
|
|
1430
|
+
const appendix = [];
|
|
1391
1431
|
for (let i = 0; i < blocks.length; i++) {
|
|
1392
1432
|
const a = prev[i];
|
|
1393
1433
|
const b = blocks[i];
|
|
@@ -1405,11 +1445,14 @@ export class StructuredSessionManager {
|
|
|
1405
1445
|
merged.push(blockVolume(b) >= blockVolume(a) ? b : a);
|
|
1406
1446
|
}
|
|
1407
1447
|
else {
|
|
1408
|
-
// 类型变了:保留 prev
|
|
1448
|
+
// 类型变了:保留 prev[i],把 incoming block 追加到末尾。
|
|
1409
1449
|
merged.push(a);
|
|
1450
|
+
appendix.push(b);
|
|
1410
1451
|
}
|
|
1411
1452
|
}
|
|
1412
1453
|
}
|
|
1454
|
+
for (const b of appendix)
|
|
1455
|
+
merged.push(b);
|
|
1413
1456
|
blocksByKey.set(key, merged);
|
|
1414
1457
|
};
|
|
1415
1458
|
const rebuildTurnBlocks = () => {
|
|
@@ -1503,8 +1546,19 @@ export class StructuredSessionManager {
|
|
|
1503
1546
|
const msgId = typeof parsed.message.id === "string" && parsed.message.id
|
|
1504
1547
|
? `assistant:${parsed.message.id}`
|
|
1505
1548
|
: `assistant:anon:${keyOrder.length}`;
|
|
1506
|
-
|
|
1507
|
-
|
|
1549
|
+
// parent_tool_use_id 决定父/子 agent。父 message 里的 Task tool_use 登记
|
|
1550
|
+
// 到 taskMetaRegistry;子 message 的每个 block 用 __subagent 盖章。
|
|
1551
|
+
const parentToolUseId = typeof parsed.parent_tool_use_id === "string" && parsed.parent_tool_use_id
|
|
1552
|
+
? parsed.parent_tool_use_id
|
|
1553
|
+
: null;
|
|
1554
|
+
if (parentToolUseId === null) {
|
|
1555
|
+
captureTaskMeta(extracted.content, taskMetaRegistry);
|
|
1556
|
+
}
|
|
1557
|
+
const stamped = parentToolUseId === null
|
|
1558
|
+
? extracted.content
|
|
1559
|
+
: tagSubagentBlocks(extracted.content, parentToolUseId, taskMetaRegistry);
|
|
1560
|
+
if (stamped.length > 0) {
|
|
1561
|
+
upsertBlocks(msgId, stamped);
|
|
1508
1562
|
rebuildTurnBlocks();
|
|
1509
1563
|
}
|
|
1510
1564
|
// NOTE: usage from streaming "assistant" events contains partial/incremental
|
|
@@ -1541,8 +1595,14 @@ export class StructuredSessionManager {
|
|
|
1541
1595
|
});
|
|
1542
1596
|
}
|
|
1543
1597
|
}
|
|
1544
|
-
|
|
1545
|
-
|
|
1598
|
+
const parentToolUseId = typeof parsed.parent_tool_use_id === "string" && parsed.parent_tool_use_id
|
|
1599
|
+
? parsed.parent_tool_use_id
|
|
1600
|
+
: null;
|
|
1601
|
+
const stamped = parentToolUseId === null
|
|
1602
|
+
? collected
|
|
1603
|
+
: tagSubagentBlocks(collected, parentToolUseId, taskMetaRegistry);
|
|
1604
|
+
if (stamped.length > 0) {
|
|
1605
|
+
upsertBlocks(`tool_result:${toolResultSeq++}`, stamped);
|
|
1546
1606
|
rebuildTurnBlocks();
|
|
1547
1607
|
}
|
|
1548
1608
|
syncSnapshot();
|
|
@@ -1794,6 +1854,10 @@ export class StructuredSessionManager {
|
|
|
1794
1854
|
...(permPolicy.allowedTools ? { allowedTools: permPolicy.allowedTools } : {}),
|
|
1795
1855
|
...(isManaged ? { disallowedTools: ["AskUserQuestion"] } : {}),
|
|
1796
1856
|
includePartialMessages: true,
|
|
1857
|
+
// 把子 agent 的 text/thinking 也转发回来,UI 才能把"被 Task 召唤来的协作者"
|
|
1858
|
+
// 渲染成独立角色的群聊消息。关掉这个开关时只会收到子 agent 的 tool_use/tool_result,
|
|
1859
|
+
// text/thinking 被 SDK 吞掉。
|
|
1860
|
+
forwardSubagentText: true,
|
|
1797
1861
|
...(systemPromptParts.length > 0 ? { appendSystemPrompt: systemPromptParts.join("\n\n") } : {}),
|
|
1798
1862
|
...(sdkClaudeBinary ? { pathToClaudeCodeExecutable: sdkClaudeBinary } : {}),
|
|
1799
1863
|
};
|
|
@@ -1855,6 +1919,11 @@ export class StructuredSessionManager {
|
|
|
1855
1919
|
// Tracks in-progress streaming blocks keyed by content_block index from stream_event.
|
|
1856
1920
|
// The map is cleared whenever a complete `assistant` message arrives — its blocks
|
|
1857
1921
|
// are then promoted into `finalizedBlocks` below.
|
|
1922
|
+
//
|
|
1923
|
+
// `parentToolUseId` carries through from SDKPartialAssistantMessage so we can
|
|
1924
|
+
// stamp streaming blocks with subagent persona *during* streaming, not only
|
|
1925
|
+
// after the completion event. Without it, subagent text shows up under the
|
|
1926
|
+
// parent's avatar for tens of ms then snaps to the subagent — visible flicker.
|
|
1858
1927
|
const streamingBlockByIndex = new Map();
|
|
1859
1928
|
// Blocks from messages that have already completed within this turn — including
|
|
1860
1929
|
// the parent assistant's prior messages, every subagent assistant message, and
|
|
@@ -1862,6 +1931,9 @@ export class StructuredSessionManager {
|
|
|
1862
1931
|
// back-to-back; without this list, each new streaming message would visually
|
|
1863
1932
|
// erase everything that came before it in the same turn.
|
|
1864
1933
|
const finalizedBlocks = [];
|
|
1934
|
+
// Per-turn Task tool_use_id → meta map; populated from the parent assistant's
|
|
1935
|
+
// Task tool_use blocks and consulted when subagent messages arrive.
|
|
1936
|
+
const taskMetaRegistry = new Map();
|
|
1865
1937
|
let emitTimer = null;
|
|
1866
1938
|
const flushEmit = () => {
|
|
1867
1939
|
if (emitTimer) {
|
|
@@ -1884,11 +1956,12 @@ export class StructuredSessionManager {
|
|
|
1884
1956
|
const sorted = [...streamingBlockByIndex.entries()].sort((a, b) => a[0] - b[0]);
|
|
1885
1957
|
const streaming = [];
|
|
1886
1958
|
for (const [, sb] of sorted) {
|
|
1959
|
+
let block = null;
|
|
1887
1960
|
if (sb.type === "text") {
|
|
1888
|
-
|
|
1961
|
+
block = { type: "text", text: sb.text };
|
|
1889
1962
|
}
|
|
1890
1963
|
else if (sb.type === "thinking") {
|
|
1891
|
-
|
|
1964
|
+
block = { type: "thinking", thinking: sb.thinking };
|
|
1892
1965
|
}
|
|
1893
1966
|
else if (sb.type === "tool_use" && sb.id && sb.name) {
|
|
1894
1967
|
let input = {};
|
|
@@ -1898,7 +1971,16 @@ export class StructuredSessionManager {
|
|
|
1898
1971
|
}
|
|
1899
1972
|
catch { /* partial json */ }
|
|
1900
1973
|
}
|
|
1901
|
-
|
|
1974
|
+
block = { type: "tool_use", id: sb.id, name: sb.name, input };
|
|
1975
|
+
}
|
|
1976
|
+
if (!block)
|
|
1977
|
+
continue;
|
|
1978
|
+
if (sb.parentToolUseId) {
|
|
1979
|
+
const [stamped] = tagSubagentBlocks([block], sb.parentToolUseId, taskMetaRegistry);
|
|
1980
|
+
streaming.push(stamped);
|
|
1981
|
+
}
|
|
1982
|
+
else {
|
|
1983
|
+
streaming.push(block);
|
|
1902
1984
|
}
|
|
1903
1985
|
}
|
|
1904
1986
|
return [...finalizedBlocks, ...streaming];
|
|
@@ -1950,7 +2032,9 @@ export class StructuredSessionManager {
|
|
|
1950
2032
|
break;
|
|
1951
2033
|
// Incremental streaming events (opt-in via includePartialMessages: true)
|
|
1952
2034
|
if (msg.type === "stream_event") {
|
|
1953
|
-
const
|
|
2035
|
+
const partial = msg;
|
|
2036
|
+
const ev = partial.event;
|
|
2037
|
+
const partialParentId = partial.parent_tool_use_id ?? null;
|
|
1954
2038
|
if (ev.type === "content_block_start") {
|
|
1955
2039
|
const cb = ev.content_block;
|
|
1956
2040
|
const blockType = cb.type;
|
|
@@ -1963,6 +2047,7 @@ export class StructuredSessionManager {
|
|
|
1963
2047
|
thinking: typeof cb.thinking === "string" ? cb.thinking : "",
|
|
1964
2048
|
partialInput: "",
|
|
1965
2049
|
finalized: false,
|
|
2050
|
+
parentToolUseId: partialParentId,
|
|
1966
2051
|
});
|
|
1967
2052
|
turnState.blocks = rebuildStreamingBlocks();
|
|
1968
2053
|
syncSnapshot();
|
|
@@ -2005,7 +2090,16 @@ export class StructuredSessionManager {
|
|
|
2005
2090
|
if (msg.type === "assistant") {
|
|
2006
2091
|
const assistantMsg = msg;
|
|
2007
2092
|
const extracted = this.extractAssistantMessage(assistantMsg.message);
|
|
2008
|
-
|
|
2093
|
+
// 父 assistant 的 Task tool_use → 注册到本轮 taskMeta map;
|
|
2094
|
+
// 子 agent 的 message(parent_tool_use_id 非空)→ 给每个 block 盖章。
|
|
2095
|
+
const parentToolUseId = assistantMsg.parent_tool_use_id ?? null;
|
|
2096
|
+
if (parentToolUseId === null) {
|
|
2097
|
+
captureTaskMeta(extracted.content, taskMetaRegistry);
|
|
2098
|
+
finalizedBlocks.push(...extracted.content);
|
|
2099
|
+
}
|
|
2100
|
+
else {
|
|
2101
|
+
finalizedBlocks.push(...tagSubagentBlocks(extracted.content, parentToolUseId, taskMetaRegistry));
|
|
2102
|
+
}
|
|
2009
2103
|
streamingBlockByIndex.clear();
|
|
2010
2104
|
turnState.blocks = rebuildStreamingBlocks();
|
|
2011
2105
|
if (assistantMsg.session_id)
|
|
@@ -2041,11 +2135,13 @@ export class StructuredSessionManager {
|
|
|
2041
2135
|
// tool call, or a subagent's tool_result during Task execution).
|
|
2042
2136
|
if (msg.type === "user") {
|
|
2043
2137
|
const userMsg = msg;
|
|
2138
|
+
const parentToolUseId = userMsg.parent_tool_use_id ?? null;
|
|
2044
2139
|
const content = Array.isArray(userMsg.message?.content) ? userMsg.message.content : [];
|
|
2140
|
+
const collected = [];
|
|
2045
2141
|
for (const block of content) {
|
|
2046
2142
|
const b = block;
|
|
2047
2143
|
if (b?.type === "tool_result") {
|
|
2048
|
-
|
|
2144
|
+
collected.push({
|
|
2049
2145
|
type: "tool_result",
|
|
2050
2146
|
tool_use_id: typeof b.tool_use_id === "string" ? b.tool_use_id : "",
|
|
2051
2147
|
content: this.normalizeToolResultContent(b.content),
|
|
@@ -2053,6 +2149,12 @@ export class StructuredSessionManager {
|
|
|
2053
2149
|
});
|
|
2054
2150
|
}
|
|
2055
2151
|
}
|
|
2152
|
+
if (parentToolUseId === null) {
|
|
2153
|
+
finalizedBlocks.push(...collected);
|
|
2154
|
+
}
|
|
2155
|
+
else {
|
|
2156
|
+
finalizedBlocks.push(...tagSubagentBlocks(collected, parentToolUseId, taskMetaRegistry));
|
|
2157
|
+
}
|
|
2056
2158
|
turnState.blocks = rebuildStreamingBlocks();
|
|
2057
2159
|
syncSnapshot();
|
|
2058
2160
|
scheduleEmit();
|
|
@@ -2227,11 +2329,17 @@ export class StructuredSessionManager {
|
|
|
2227
2329
|
const previous = compacted[compacted.length - 1];
|
|
2228
2330
|
if (previous
|
|
2229
2331
|
&& previous.type === "text"
|
|
2230
|
-
&& block.type === "text"
|
|
2332
|
+
&& block.type === "text"
|
|
2333
|
+
// 子 agent 边界不合并:父 assistant 的 text 与子 agent 的 text 必须保持独立,
|
|
2334
|
+
// 渲染层才能切段并给子 agent 单独发头像。同一 subagent 内部允许合并。
|
|
2335
|
+
&& (previous.__subagent?.taskId ?? null) === (block.__subagent?.taskId ?? null)) {
|
|
2231
2336
|
// 用新对象替换 compacted 末尾,**不要**就地改 previous.text —— previous
|
|
2232
2337
|
// 通常和调用方持有的 turnState.blocks 共享引用,原地 mutate 会让下次
|
|
2233
2338
|
// syncSnapshot 把已合并的内容再合并一次,呈指数级复制。
|
|
2234
|
-
|
|
2339
|
+
const merged = { type: "text", text: `${previous.text}${block.text}` };
|
|
2340
|
+
if (previous.__subagent)
|
|
2341
|
+
merged.__subagent = previous.__subagent;
|
|
2342
|
+
compacted[compacted.length - 1] = merged;
|
|
2235
2343
|
continue;
|
|
2236
2344
|
}
|
|
2237
2345
|
compacted.push(block);
|
package/dist/types.d.ts
CHANGED
|
@@ -299,13 +299,30 @@ export interface ChatMessage {
|
|
|
299
299
|
role: "user" | "assistant";
|
|
300
300
|
content: string;
|
|
301
301
|
}
|
|
302
|
+
/**
|
|
303
|
+
* Meta marker attached to blocks emitted by a Task-spawned subagent. Present
|
|
304
|
+
* on every block (text / thinking / tool_use / tool_result) whose origin is a
|
|
305
|
+
* subagent's stream rather than the main assistant. Drives the multi-persona
|
|
306
|
+
* chat rendering ("third cat joining the conversation").
|
|
307
|
+
*
|
|
308
|
+
* `taskId` is the parent Task tool_use id (= SDK's `parent_tool_use_id`).
|
|
309
|
+
* The parent Task tool_use block itself is NOT marked — it lives in the
|
|
310
|
+
* main assistant's stream.
|
|
311
|
+
*/
|
|
312
|
+
export interface SubagentMeta {
|
|
313
|
+
taskId: string;
|
|
314
|
+
agentType?: string;
|
|
315
|
+
taskDescription?: string;
|
|
316
|
+
}
|
|
302
317
|
export interface TextBlock {
|
|
303
318
|
type: "text";
|
|
304
319
|
text: string;
|
|
320
|
+
__subagent?: SubagentMeta;
|
|
305
321
|
}
|
|
306
322
|
export interface ThinkingBlock {
|
|
307
323
|
type: "thinking";
|
|
308
324
|
thinking: string;
|
|
325
|
+
__subagent?: SubagentMeta;
|
|
309
326
|
}
|
|
310
327
|
export interface ToolUseBlock {
|
|
311
328
|
type: "tool_use";
|
|
@@ -313,6 +330,7 @@ export interface ToolUseBlock {
|
|
|
313
330
|
name: string;
|
|
314
331
|
description?: string;
|
|
315
332
|
input: Record<string, unknown>;
|
|
333
|
+
__subagent?: SubagentMeta;
|
|
316
334
|
}
|
|
317
335
|
export interface ToolResultBlock {
|
|
318
336
|
type: "tool_result";
|
|
@@ -324,6 +342,7 @@ export interface ToolResultBlock {
|
|
|
324
342
|
is_error?: boolean;
|
|
325
343
|
/** When true, content has been truncated for transport. Client should fetch full content via API. */
|
|
326
344
|
_truncated?: boolean;
|
|
345
|
+
__subagent?: SubagentMeta;
|
|
327
346
|
}
|
|
328
347
|
export type ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock;
|
|
329
348
|
export interface ConversationTurn {
|