@poncho-ai/harness 0.52.2 → 0.53.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/.turbo/turbo-build.log +5 -5
- package/CHANGELOG.md +32 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +30 -11
- package/package.json +2 -2
- package/src/harness.ts +3 -1
- package/src/orchestrator/orchestrator.ts +20 -2
- package/src/state.ts +3 -0
- package/src/subagent-manager.ts +4 -0
- package/src/subagent-tools.ts +1 -0
- package/src/tool-dispatcher.ts +4 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @poncho-ai/harness@0.
|
|
2
|
+
> @poncho-ai/harness@0.53.0 build /home/runner/work/poncho-ai/poncho-ai/packages/harness
|
|
3
3
|
> node scripts/embed-docs.js && tsup src/index.ts --format esm --dts
|
|
4
4
|
|
|
5
5
|
[embed-docs] Generated poncho-docs.ts with 4 topics
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
[34mCLI[39m tsup v8.5.1
|
|
9
9
|
[34mCLI[39m Target: es2022
|
|
10
10
|
[34mESM[39m Build start
|
|
11
|
-
[32mESM[39m [1mdist/index.js [22m[32m540.60 KB[39m
|
|
12
11
|
[32mESM[39m [1mdist/isolate-F2PPSUL6.js [22m[32m53.82 KB[39m
|
|
13
|
-
[32mESM[39m
|
|
12
|
+
[32mESM[39m [1mdist/index.js [22m[32m541.42 KB[39m
|
|
13
|
+
[32mESM[39m ⚡️ Build success in 239ms
|
|
14
14
|
[34mDTS[39m Build start
|
|
15
|
-
[32mDTS[39m ⚡️ Build success in
|
|
16
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[
|
|
15
|
+
[32mDTS[39m ⚡️ Build success in 7708ms
|
|
16
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m94.04 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @poncho-ai/harness
|
|
2
2
|
|
|
3
|
+
## 0.53.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#145](https://github.com/cesr/poncho-ai/pull/145) [`bfa4976`](https://github.com/cesr/poncho-ai/commit/bfa4976ac8b05a300e22271e23c3bae4aadae2a8) Thanks [@cesr](https://github.com/cesr)! - events: add stable identity so streaming clients match instead of guess
|
|
8
|
+
|
|
9
|
+
Additive fields that let a streaming client reconstruct view-state by
|
|
10
|
+
identity rather than inferring structure from event order (the source of a
|
|
11
|
+
class of reconnect/subagent rendering bugs):
|
|
12
|
+
- `tool:started` / `tool:completed` / `tool:error` now carry `toolCallId`
|
|
13
|
+
(already in scope as `call.id` / `result.callId`). Clients match tool
|
|
14
|
+
pills by id instead of by tool name.
|
|
15
|
+
- `subagent:spawned|completed|error|stopped` now carry `parentToolCallId`
|
|
16
|
+
(the `spawn_subagent` tool call's id) and `task`; `completed`/`error`
|
|
17
|
+
also carry `resultText`. Clients attach subagent state to the spawning
|
|
18
|
+
tool's pill and render the result inline — no header-regex or
|
|
19
|
+
sequential-cursor pairing needed.
|
|
20
|
+
- `ToolContext` gains `toolCallId` so the `spawn_subagent` handler can
|
|
21
|
+
record which call produced the subagent (plumbed: tool-dispatcher →
|
|
22
|
+
spawn handler → `SubagentSpawnOptions.parentToolCallId` →
|
|
23
|
+
`subagentMeta.parentToolCallId` → the events above).
|
|
24
|
+
- `run:started` gains an optional `cause` field in the type
|
|
25
|
+
(`user|continuation|subagent_callback|approval_resume`); emission is
|
|
26
|
+
deferred to a later pass.
|
|
27
|
+
|
|
28
|
+
All fields are additive; older clients ignore them.
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- Updated dependencies [[`bfa4976`](https://github.com/cesr/poncho-ai/commit/bfa4976ac8b05a300e22271e23c3bae4aadae2a8)]:
|
|
33
|
+
- @poncho-ai/sdk@1.15.0
|
|
34
|
+
|
|
3
35
|
## 0.52.2
|
|
4
36
|
|
|
5
37
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -199,6 +199,9 @@ interface Conversation {
|
|
|
199
199
|
* subagent's runs emit no telemetry (e.g. spawned from an incognito
|
|
200
200
|
* turn). Read by the orchestrator's runSubagent / continuation. */
|
|
201
201
|
suppressTelemetry?: boolean;
|
|
202
|
+
/** The parent's `spawn_subagent` tool call id — echoed onto subagent:*
|
|
203
|
+
* events so a client can attach subagent state to that tool's pill. */
|
|
204
|
+
parentToolCallId?: string;
|
|
202
205
|
};
|
|
203
206
|
channelMeta?: {
|
|
204
207
|
platform: string;
|
|
@@ -1190,6 +1193,10 @@ interface SubagentManager {
|
|
|
1190
1193
|
/** Inherit the parent run's telemetry choice — when true, the subagent
|
|
1191
1194
|
* run (and its re-runs) emit no telemetry. */
|
|
1192
1195
|
suppressTelemetry?: boolean;
|
|
1196
|
+
/** The id of the `spawn_subagent` tool call that produced this subagent,
|
|
1197
|
+
* so its events can carry `parentToolCallId` and a client can attach
|
|
1198
|
+
* subagent state to the spawning tool's pill. */
|
|
1199
|
+
parentToolCallId?: string;
|
|
1193
1200
|
}): Promise<SubagentSpawnResult>;
|
|
1194
1201
|
sendMessage(subagentId: string, message: string): Promise<SubagentSpawnResult>;
|
|
1195
1202
|
stop(subagentId: string): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -8323,7 +8323,8 @@ var createSubagentTools = (manager) => [
|
|
|
8323
8323
|
parentConversationId: conversationId,
|
|
8324
8324
|
ownerId,
|
|
8325
8325
|
tenantId: context.tenantId,
|
|
8326
|
-
suppressTelemetry: context.suppressTelemetry
|
|
8326
|
+
suppressTelemetry: context.suppressTelemetry,
|
|
8327
|
+
parentToolCallId: context.toolCallId
|
|
8327
8328
|
});
|
|
8328
8329
|
return { subagentId, status: "running" };
|
|
8329
8330
|
}
|
|
@@ -8585,7 +8586,7 @@ var ToolDispatcher = class {
|
|
|
8585
8586
|
};
|
|
8586
8587
|
}
|
|
8587
8588
|
try {
|
|
8588
|
-
const output = await definition.handler(call.input, context);
|
|
8589
|
+
const output = await definition.handler(call.input, { ...context, toolCallId: call.id });
|
|
8589
8590
|
if (context.abortSignal?.aborted) {
|
|
8590
8591
|
return {
|
|
8591
8592
|
callId: call.id,
|
|
@@ -11170,7 +11171,7 @@ ${textContent}` };
|
|
|
11170
11171
|
return;
|
|
11171
11172
|
}
|
|
11172
11173
|
const runtimeToolName = exposedToolNames.get(call.name) ?? call.name;
|
|
11173
|
-
yield pushEvent({ type: "tool:started", tool: runtimeToolName, input: call.input });
|
|
11174
|
+
yield pushEvent({ type: "tool:started", tool: runtimeToolName, toolCallId: call.id, input: call.input });
|
|
11174
11175
|
if (this.requiresApprovalForToolCall(runtimeToolName, call.input)) {
|
|
11175
11176
|
approvalNeeded.push({
|
|
11176
11177
|
approvalId: `approval_${randomUUID5()}`,
|
|
@@ -11363,6 +11364,7 @@ ${textContent}` };
|
|
|
11363
11364
|
yield pushEvent({
|
|
11364
11365
|
type: "tool:error",
|
|
11365
11366
|
tool: result2.tool,
|
|
11367
|
+
toolCallId: result2.callId,
|
|
11366
11368
|
error: result2.error,
|
|
11367
11369
|
recoverable: true
|
|
11368
11370
|
});
|
|
@@ -11404,6 +11406,7 @@ ${textContent}` };
|
|
|
11404
11406
|
yield pushEvent({
|
|
11405
11407
|
type: "tool:completed",
|
|
11406
11408
|
tool: result2.tool,
|
|
11409
|
+
toolCallId: result2.callId,
|
|
11407
11410
|
input: callInputMap.get(result2.callId),
|
|
11408
11411
|
output: result2.output,
|
|
11409
11412
|
duration: now() - batchStart,
|
|
@@ -12826,11 +12829,14 @@ var AgentOrchestrator = class {
|
|
|
12826
12829
|
result: { status: "completed", response: responseText, steps: 0, tokens: { input: 0, output: 0, cached: 0 }, duration: 0 },
|
|
12827
12830
|
timestamp: Date.now()
|
|
12828
12831
|
};
|
|
12829
|
-
await this.
|
|
12832
|
+
await this.appendSubagentResultReliable(conv.parentConversationId, pendingResult);
|
|
12830
12833
|
await this.eventSink(conv.parentConversationId, {
|
|
12831
12834
|
type: "subagent:completed",
|
|
12832
12835
|
subagentId,
|
|
12833
|
-
conversationId: subagentId
|
|
12836
|
+
conversationId: subagentId,
|
|
12837
|
+
task: conv.subagentMeta?.task ?? conv.title,
|
|
12838
|
+
parentToolCallId: conv.subagentMeta?.parentToolCallId,
|
|
12839
|
+
resultText: responseText
|
|
12834
12840
|
});
|
|
12835
12841
|
await this.triggerParentCallback(conv.parentConversationId);
|
|
12836
12842
|
}
|
|
@@ -12906,9 +12912,11 @@ var AgentOrchestrator = class {
|
|
|
12906
12912
|
let latestRunId = "";
|
|
12907
12913
|
let runResult;
|
|
12908
12914
|
let runError;
|
|
12915
|
+
let parentToolCallId;
|
|
12909
12916
|
try {
|
|
12910
12917
|
const conversation = await this.conversationStore.getWithArchive(childConversationId);
|
|
12911
12918
|
if (!conversation) throw new Error("Subagent conversation not found");
|
|
12919
|
+
parentToolCallId = conversation.subagentMeta?.parentToolCallId;
|
|
12912
12920
|
if (conversation.subagentMeta?.status === "stopped") return;
|
|
12913
12921
|
conversation.lastActivityAt = Date.now();
|
|
12914
12922
|
await this.conversationStore.update(conversation);
|
|
@@ -13126,7 +13134,10 @@ var AgentOrchestrator = class {
|
|
|
13126
13134
|
await this.eventSink(parentConversationId, {
|
|
13127
13135
|
type: "subagent:completed",
|
|
13128
13136
|
subagentId: childConversationId,
|
|
13129
|
-
conversationId: childConversationId
|
|
13137
|
+
conversationId: childConversationId,
|
|
13138
|
+
task,
|
|
13139
|
+
parentToolCallId,
|
|
13140
|
+
resultText: subagentResponse
|
|
13130
13141
|
});
|
|
13131
13142
|
this.triggerParentCallback(parentConversationId).catch(
|
|
13132
13143
|
(err) => console.error(`[poncho][subagent] Parent callback failed:`, err instanceof Error ? err.message : err)
|
|
@@ -13157,7 +13168,9 @@ var AgentOrchestrator = class {
|
|
|
13157
13168
|
type: "subagent:error",
|
|
13158
13169
|
subagentId: childConversationId,
|
|
13159
13170
|
conversationId: childConversationId,
|
|
13160
|
-
error: errMsg
|
|
13171
|
+
error: errMsg,
|
|
13172
|
+
task,
|
|
13173
|
+
parentToolCallId
|
|
13161
13174
|
});
|
|
13162
13175
|
this.triggerParentCallback(parentConversationId).catch(
|
|
13163
13176
|
(err2) => console.error(`[poncho][subagent] Parent callback failed:`, err2 instanceof Error ? err2.message : err2)
|
|
@@ -13486,7 +13499,10 @@ ${resultBody}`,
|
|
|
13486
13499
|
await this.eventSink(parentConversationId, {
|
|
13487
13500
|
type: "subagent:completed",
|
|
13488
13501
|
subagentId: conversationId,
|
|
13489
|
-
conversationId
|
|
13502
|
+
conversationId,
|
|
13503
|
+
task,
|
|
13504
|
+
parentToolCallId: conversation.subagentMeta?.parentToolCallId,
|
|
13505
|
+
resultText: subagentResponse
|
|
13490
13506
|
});
|
|
13491
13507
|
if (parentConv) {
|
|
13492
13508
|
if (this.isServerless) {
|
|
@@ -13530,7 +13546,9 @@ ${resultBody}`,
|
|
|
13530
13546
|
await this.eventSink(conversation.parentConversationId, {
|
|
13531
13547
|
type: "subagent:completed",
|
|
13532
13548
|
subagentId: conversationId,
|
|
13533
|
-
conversationId
|
|
13549
|
+
conversationId,
|
|
13550
|
+
task,
|
|
13551
|
+
parentToolCallId: conversation.subagentMeta?.parentToolCallId
|
|
13534
13552
|
});
|
|
13535
13553
|
if (parentConv) {
|
|
13536
13554
|
if (this.isServerless) {
|
|
@@ -13560,7 +13578,7 @@ ${resultBody}`,
|
|
|
13560
13578
|
opts.tenantId ?? null,
|
|
13561
13579
|
{
|
|
13562
13580
|
parentConversationId: opts.parentConversationId,
|
|
13563
|
-
subagentMeta: { task: opts.task, status: "running", suppressTelemetry: opts.suppressTelemetry },
|
|
13581
|
+
subagentMeta: { task: opts.task, status: "running", suppressTelemetry: opts.suppressTelemetry, parentToolCallId: opts.parentToolCallId },
|
|
13564
13582
|
messages: [{ role: "user", content: opts.task }]
|
|
13565
13583
|
}
|
|
13566
13584
|
);
|
|
@@ -13572,7 +13590,8 @@ ${resultBody}`,
|
|
|
13572
13590
|
type: "subagent:spawned",
|
|
13573
13591
|
subagentId: conversation.conversationId,
|
|
13574
13592
|
conversationId: conversation.conversationId,
|
|
13575
|
-
task: opts.task
|
|
13593
|
+
task: opts.task,
|
|
13594
|
+
parentToolCallId: opts.parentToolCallId
|
|
13576
13595
|
});
|
|
13577
13596
|
if (this.isServerless) {
|
|
13578
13597
|
this.hooks.dispatchBackground("subagent-run", conversation.conversationId);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poncho-ai/harness",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.53.0",
|
|
4
4
|
"description": "Agent execution runtime - conversation loop, tool dispatch, streaming",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"mustache": "^4.2.0",
|
|
35
35
|
"yaml": "^2.4.0",
|
|
36
36
|
"zod": "^3.22.0",
|
|
37
|
-
"@poncho-ai/sdk": "1.
|
|
37
|
+
"@poncho-ai/sdk": "1.15.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"esbuild": ">=0.17.0",
|
package/src/harness.ts
CHANGED
|
@@ -3344,7 +3344,7 @@ Code is wrapped in an async IIFE — use \`return\` to return a value to the too
|
|
|
3344
3344
|
return;
|
|
3345
3345
|
}
|
|
3346
3346
|
const runtimeToolName = exposedToolNames.get(call.name) ?? call.name;
|
|
3347
|
-
yield pushEvent({ type: "tool:started", tool: runtimeToolName, input: call.input });
|
|
3347
|
+
yield pushEvent({ type: "tool:started", tool: runtimeToolName, toolCallId: call.id, input: call.input });
|
|
3348
3348
|
if (this.requiresApprovalForToolCall(runtimeToolName, call.input)) {
|
|
3349
3349
|
approvalNeeded.push({
|
|
3350
3350
|
approvalId: `approval_${randomUUID()}`,
|
|
@@ -3563,6 +3563,7 @@ Code is wrapped in an async IIFE — use \`return\` to return a value to the too
|
|
|
3563
3563
|
yield pushEvent({
|
|
3564
3564
|
type: "tool:error",
|
|
3565
3565
|
tool: result.tool,
|
|
3566
|
+
toolCallId: result.callId,
|
|
3566
3567
|
error: result.error,
|
|
3567
3568
|
recoverable: true,
|
|
3568
3569
|
});
|
|
@@ -3604,6 +3605,7 @@ Code is wrapped in an async IIFE — use \`return\` to return a value to the too
|
|
|
3604
3605
|
yield pushEvent({
|
|
3605
3606
|
type: "tool:completed",
|
|
3606
3607
|
tool: result.tool,
|
|
3608
|
+
toolCallId: result.callId,
|
|
3607
3609
|
input: callInputMap.get(result.callId),
|
|
3608
3610
|
output: result.output,
|
|
3609
3611
|
duration: now() - batchStart,
|
|
@@ -693,12 +693,15 @@ export class AgentOrchestrator {
|
|
|
693
693
|
result: { status: "completed", response: responseText, steps: 0, tokens: { input: 0, output: 0, cached: 0 }, duration: 0 },
|
|
694
694
|
timestamp: Date.now(),
|
|
695
695
|
};
|
|
696
|
-
await this.
|
|
696
|
+
await this.appendSubagentResultReliable(conv.parentConversationId, pendingResult);
|
|
697
697
|
|
|
698
698
|
await this.eventSink(conv.parentConversationId, {
|
|
699
699
|
type: "subagent:completed",
|
|
700
700
|
subagentId,
|
|
701
701
|
conversationId: subagentId,
|
|
702
|
+
task: conv.subagentMeta?.task ?? conv.title,
|
|
703
|
+
parentToolCallId: conv.subagentMeta?.parentToolCallId,
|
|
704
|
+
resultText: responseText,
|
|
702
705
|
});
|
|
703
706
|
|
|
704
707
|
await this.triggerParentCallback(conv.parentConversationId);
|
|
@@ -796,10 +799,14 @@ export class AgentOrchestrator {
|
|
|
796
799
|
let latestRunId = "";
|
|
797
800
|
let runResult: { status: "completed" | "error" | "cancelled"; response?: string; steps: number; duration: number; continuation?: boolean; continuationMessages?: Message[] } | undefined;
|
|
798
801
|
let runError: { code?: string; message?: string } | undefined;
|
|
802
|
+
// The spawning tool call's id — echoed onto subagent:* events so the
|
|
803
|
+
// client can attach subagent state to that tool's pill.
|
|
804
|
+
let parentToolCallId: string | undefined;
|
|
799
805
|
|
|
800
806
|
try {
|
|
801
807
|
const conversation = await this.conversationStore.getWithArchive(childConversationId);
|
|
802
808
|
if (!conversation) throw new Error("Subagent conversation not found");
|
|
809
|
+
parentToolCallId = conversation.subagentMeta?.parentToolCallId;
|
|
803
810
|
|
|
804
811
|
if (conversation.subagentMeta?.status === "stopped") return;
|
|
805
812
|
|
|
@@ -1054,6 +1061,9 @@ export class AgentOrchestrator {
|
|
|
1054
1061
|
type: "subagent:completed",
|
|
1055
1062
|
subagentId: childConversationId,
|
|
1056
1063
|
conversationId: childConversationId,
|
|
1064
|
+
task,
|
|
1065
|
+
parentToolCallId,
|
|
1066
|
+
resultText: subagentResponse,
|
|
1057
1067
|
});
|
|
1058
1068
|
|
|
1059
1069
|
this.triggerParentCallback(parentConversationId).catch(err =>
|
|
@@ -1090,6 +1100,8 @@ export class AgentOrchestrator {
|
|
|
1090
1100
|
subagentId: childConversationId,
|
|
1091
1101
|
conversationId: childConversationId,
|
|
1092
1102
|
error: errMsg,
|
|
1103
|
+
task,
|
|
1104
|
+
parentToolCallId,
|
|
1093
1105
|
});
|
|
1094
1106
|
|
|
1095
1107
|
this.triggerParentCallback(parentConversationId).catch(err2 =>
|
|
@@ -1476,6 +1488,9 @@ export class AgentOrchestrator {
|
|
|
1476
1488
|
type: "subagent:completed",
|
|
1477
1489
|
subagentId: conversationId,
|
|
1478
1490
|
conversationId,
|
|
1491
|
+
task,
|
|
1492
|
+
parentToolCallId: conversation.subagentMeta?.parentToolCallId,
|
|
1493
|
+
resultText: subagentResponse,
|
|
1479
1494
|
});
|
|
1480
1495
|
|
|
1481
1496
|
if (parentConv) {
|
|
@@ -1520,6 +1535,8 @@ export class AgentOrchestrator {
|
|
|
1520
1535
|
type: "subagent:completed",
|
|
1521
1536
|
subagentId: conversationId,
|
|
1522
1537
|
conversationId,
|
|
1538
|
+
task,
|
|
1539
|
+
parentToolCallId: conversation.subagentMeta?.parentToolCallId,
|
|
1523
1540
|
});
|
|
1524
1541
|
|
|
1525
1542
|
if (parentConv) {
|
|
@@ -1553,7 +1570,7 @@ export class AgentOrchestrator {
|
|
|
1553
1570
|
opts.tenantId ?? null,
|
|
1554
1571
|
{
|
|
1555
1572
|
parentConversationId: opts.parentConversationId,
|
|
1556
|
-
subagentMeta: { task: opts.task, status: "running", suppressTelemetry: opts.suppressTelemetry },
|
|
1573
|
+
subagentMeta: { task: opts.task, status: "running", suppressTelemetry: opts.suppressTelemetry, parentToolCallId: opts.parentToolCallId },
|
|
1557
1574
|
messages: [{ role: "user", content: opts.task }],
|
|
1558
1575
|
},
|
|
1559
1576
|
);
|
|
@@ -1568,6 +1585,7 @@ export class AgentOrchestrator {
|
|
|
1568
1585
|
subagentId: conversation.conversationId,
|
|
1569
1586
|
conversationId: conversation.conversationId,
|
|
1570
1587
|
task: opts.task,
|
|
1588
|
+
parentToolCallId: opts.parentToolCallId,
|
|
1571
1589
|
});
|
|
1572
1590
|
|
|
1573
1591
|
if (this.isServerless) {
|
package/src/state.ts
CHANGED
|
@@ -79,6 +79,9 @@ export interface Conversation {
|
|
|
79
79
|
* subagent's runs emit no telemetry (e.g. spawned from an incognito
|
|
80
80
|
* turn). Read by the orchestrator's runSubagent / continuation. */
|
|
81
81
|
suppressTelemetry?: boolean;
|
|
82
|
+
/** The parent's `spawn_subagent` tool call id — echoed onto subagent:*
|
|
83
|
+
* events so a client can attach subagent state to that tool's pill. */
|
|
84
|
+
parentToolCallId?: string;
|
|
82
85
|
};
|
|
83
86
|
channelMeta?: {
|
|
84
87
|
platform: string;
|
package/src/subagent-manager.ts
CHANGED
|
@@ -40,6 +40,10 @@ export interface SubagentManager {
|
|
|
40
40
|
/** Inherit the parent run's telemetry choice — when true, the subagent
|
|
41
41
|
* run (and its re-runs) emit no telemetry. */
|
|
42
42
|
suppressTelemetry?: boolean;
|
|
43
|
+
/** The id of the `spawn_subagent` tool call that produced this subagent,
|
|
44
|
+
* so its events can carry `parentToolCallId` and a client can attach
|
|
45
|
+
* subagent state to the spawning tool's pill. */
|
|
46
|
+
parentToolCallId?: string;
|
|
43
47
|
}): Promise<SubagentSpawnResult>;
|
|
44
48
|
|
|
45
49
|
sendMessage(subagentId: string, message: string): Promise<SubagentSpawnResult>;
|
package/src/subagent-tools.ts
CHANGED
package/src/tool-dispatcher.ts
CHANGED
|
@@ -62,7 +62,10 @@ export class ToolDispatcher {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
try {
|
|
65
|
-
|
|
65
|
+
// Per-call context: stamp the current tool call's id so handlers that
|
|
66
|
+
// spawn further work (spawn_subagent) can record `parentToolCallId`.
|
|
67
|
+
// A fresh object — `context` is shared across a batch, don't mutate it.
|
|
68
|
+
const output = await definition.handler(call.input, { ...context, toolCallId: call.id });
|
|
66
69
|
if (context.abortSignal?.aborted) {
|
|
67
70
|
return {
|
|
68
71
|
callId: call.id,
|