@botbotgo/agent-harness 0.0.366 → 0.0.368
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/cli/chat-stream.js +10 -0
- package/dist/package-version.d.ts +2 -2
- package/dist/package-version.js +2 -2
- package/dist/runtime/adapter/flow/invocation-flow.js +20 -4
- package/dist/runtime/agent-runtime-adapter.d.ts +1 -0
- package/dist/runtime/agent-runtime-adapter.js +235 -24
- package/dist/runtime/harness/run/stream-run.d.ts +3 -0
- package/dist/runtime/harness/run/stream-run.js +18 -15
- package/dist/runtime/parsing/stream-event-parsing.d.ts +7 -0
- package/package.json +1 -1
package/dist/cli/chat-stream.js
CHANGED
|
@@ -371,6 +371,16 @@ export async function streamChatMessage(input) {
|
|
|
371
371
|
renderContentBlocks(delta.contentBlocks, delta.agentId);
|
|
372
372
|
return;
|
|
373
373
|
}
|
|
374
|
+
if (delta.type === "plan.step") {
|
|
375
|
+
latestAgentId = delta.agentId || latestAgentId;
|
|
376
|
+
const item = delta.item;
|
|
377
|
+
const status = typeof item?.status === "string" ? item.status : "unknown";
|
|
378
|
+
const content = typeof item?.content === "string" ? item.content : "";
|
|
379
|
+
if ((input.showToolResults ?? true) && !input.requestEvents && content.trim().length > 0) {
|
|
380
|
+
writeChatStderr(`\n[${formatPerfClock(Date.now())} +${formatElapsed(Date.now())}]${formatAgentProgressLabel(delta.agentId)} [todo:${status}] ${content}\n`);
|
|
381
|
+
}
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
374
384
|
if (delta.type === "tool.result") {
|
|
375
385
|
latestAgentId = delta.agentId || latestAgentId;
|
|
376
386
|
if ((input.showToolResults ?? true) && !input.requestEvents) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
2
|
-
export declare const AGENT_HARNESS_RELEASE_DATE = "2026-04-
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.368";
|
|
2
|
+
export declare const AGENT_HARNESS_RELEASE_DATE = "2026-04-30";
|
package/dist/package-version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
2
|
-
export const AGENT_HARNESS_RELEASE_DATE = "2026-04-
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.368";
|
|
2
|
+
export const AGENT_HARNESS_RELEASE_DATE = "2026-04-30";
|
|
@@ -8,6 +8,19 @@ import { appendToolRecoveryInstruction, extractVisibleOutput, tryParseJson } fro
|
|
|
8
8
|
import { salvageJsonToolCalls } from "../../parsing/output-tool-args.js";
|
|
9
9
|
import { isEmptyFinalAiMessageError } from "../resilience.js";
|
|
10
10
|
import { AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, } from "../../prompts/runtime-prompts.js";
|
|
11
|
+
const CLOSE_REQUIRED_PLAN_RECOVERY_INSTRUCTION = [
|
|
12
|
+
"The current required todo board still has unfinished work.",
|
|
13
|
+
"Do not broaden the investigation, restart planning, or ask the user what to do next.",
|
|
14
|
+
"Use the existing tool evidence already available in this run.",
|
|
15
|
+
"Your next action must be write_todos: update every remaining pending or in_progress item to completed if evidence was gathered, or failed if it cannot be completed with the available tools.",
|
|
16
|
+
"After that write_todos call, provide the final answer required by the agent response format.",
|
|
17
|
+
].join("\n");
|
|
18
|
+
const INITIAL_REQUIRED_PLAN_INSTRUCTION = [
|
|
19
|
+
"This agent has a required visible planning contract.",
|
|
20
|
+
"Your first action for this request must be write_todos with concrete task steps and statuses.",
|
|
21
|
+
"Do not call any domain/evidence tool and do not provide a final answer before the initial write_todos call succeeds.",
|
|
22
|
+
"After each evidence step, update the todo board. Before the final answer, close every todo as completed or failed.",
|
|
23
|
+
].join("\n");
|
|
11
24
|
function readBindingExecutionParams(binding) {
|
|
12
25
|
const params = binding.execution?.params ?? binding.deepAgentParams ?? binding.langchainAgentParams;
|
|
13
26
|
return {
|
|
@@ -280,9 +293,13 @@ function appendUserRecoveryInstruction(input, instruction) {
|
|
|
280
293
|
export async function executeRequestInvocation(options) {
|
|
281
294
|
const history = options.history ?? [];
|
|
282
295
|
const invokeOptions = options.invokeOptions ?? {};
|
|
283
|
-
|
|
296
|
+
let request = options.resumePayload === undefined
|
|
284
297
|
? buildInvocationRequest(options.binding, history, options.input, invokeOptions)
|
|
285
298
|
: new Command({ resume: options.resumePayload });
|
|
299
|
+
if (options.resumePayload === undefined
|
|
300
|
+
&& options.binding.harnessRuntime.executionContract?.requiresPlan === true) {
|
|
301
|
+
request = appendToolRecoveryInstruction(request, INITIAL_REQUIRED_PLAN_INSTRUCTION);
|
|
302
|
+
}
|
|
286
303
|
const { primaryTools, toolNameMapping, executableTools, defersToUpstreamHitlExecution, } = buildBindingToolExecutionContext({
|
|
287
304
|
binding: options.binding,
|
|
288
305
|
resolveTools: options.resolveTools,
|
|
@@ -335,7 +352,7 @@ export async function executeRequestInvocation(options) {
|
|
|
335
352
|
? result.messages
|
|
336
353
|
: undefined;
|
|
337
354
|
const recoveryBase = messages ? { messages } : request;
|
|
338
|
-
const recoveredRequest = appendToolRecoveryInstruction(recoveryBase,
|
|
355
|
+
const recoveredRequest = appendToolRecoveryInstruction(recoveryBase, CLOSE_REQUIRED_PLAN_RECOVERY_INSTRUCTION);
|
|
339
356
|
const recoveredInvocation = await invokeOnce(recoveredRequest);
|
|
340
357
|
localOrUpstreamInvocation = recoveredInvocation;
|
|
341
358
|
result = recoveredInvocation.result;
|
|
@@ -343,8 +360,7 @@ export async function executeRequestInvocation(options) {
|
|
|
343
360
|
}
|
|
344
361
|
if (options.resumePayload === undefined
|
|
345
362
|
&& options.binding.harnessRuntime.executionContract?.requiresPlan === true
|
|
346
|
-
&& hasIncompleteUpstreamPlan(result)
|
|
347
|
-
&& !extractVisibleOutput(result).trim()) {
|
|
363
|
+
&& hasIncompleteUpstreamPlan(result)) {
|
|
348
364
|
const messages = Array.isArray(result.messages)
|
|
349
365
|
? result.messages
|
|
350
366
|
: undefined;
|
|
@@ -59,6 +59,7 @@ export declare class AgentRuntimeAdapter {
|
|
|
59
59
|
}): Promise<RequestResult>;
|
|
60
60
|
private tryDelegateWithCompactRouter;
|
|
61
61
|
private buildCompactDelegationReport;
|
|
62
|
+
private streamDelegateWithCompactRouter;
|
|
62
63
|
stream(binding: CompiledAgentBinding, input: MessageContent, sessionId: string, history?: TranscriptMessage[], options?: {
|
|
63
64
|
context?: Record<string, unknown>;
|
|
64
65
|
state?: Record<string, unknown>;
|
|
@@ -164,6 +164,11 @@ function hasDelegatedPlanEvidence(result) {
|
|
|
164
164
|
return Array.isArray(toolResults)
|
|
165
165
|
&& toolResults.some((item) => item.toolName === "write_todos" || item.toolName === "read_todos");
|
|
166
166
|
}
|
|
167
|
+
const DELEGATED_PLAN_EVIDENCE_RETRY_INSTRUCTION = [
|
|
168
|
+
"The delegated task requires visible TODO planning evidence.",
|
|
169
|
+
"Before any other tool call or final answer, call write_todos with concrete task steps and statuses.",
|
|
170
|
+
"Then continue the task to completion, update TODO statuses after evidence steps, and close every TODO as completed or failed before the final answer.",
|
|
171
|
+
].join("\n");
|
|
167
172
|
function resolveDelegatedResultOutput(result) {
|
|
168
173
|
const executedToolResults = Array.isArray(result.metadata?.executedToolResults)
|
|
169
174
|
? result.metadata.executedToolResults
|
|
@@ -936,21 +941,62 @@ export class AgentRuntimeAdapter {
|
|
|
936
941
|
delegatedResult = await runDelegatedRequest(requestText);
|
|
937
942
|
}
|
|
938
943
|
catch (error) {
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
944
|
+
if (selectedBinding.harnessRuntime.executionContract?.requiresPlan === true) {
|
|
945
|
+
try {
|
|
946
|
+
delegatedResult = await runDelegatedRequest([requestText, DELEGATED_PLAN_EVIDENCE_RETRY_INSTRUCTION].filter(Boolean).join("\n\n"), ":plan-evidence-retry");
|
|
947
|
+
}
|
|
948
|
+
catch (recoveryError) {
|
|
949
|
+
const output = recoveryError instanceof Error ? recoveryError.message : String(recoveryError);
|
|
950
|
+
return {
|
|
951
|
+
toolOutput: output,
|
|
952
|
+
delegatedSubagentType: subagentType,
|
|
953
|
+
delegatedResult: {
|
|
954
|
+
sessionId,
|
|
955
|
+
requestId,
|
|
956
|
+
agentId: selectedBinding.agent.id,
|
|
957
|
+
state: "failed",
|
|
958
|
+
output,
|
|
959
|
+
finalMessageText: output,
|
|
960
|
+
},
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
else {
|
|
965
|
+
const output = error instanceof Error ? error.message : String(error);
|
|
966
|
+
return {
|
|
967
|
+
toolOutput: output,
|
|
968
|
+
delegatedSubagentType: subagentType,
|
|
969
|
+
delegatedResult: {
|
|
970
|
+
sessionId,
|
|
971
|
+
requestId,
|
|
972
|
+
agentId: selectedBinding.agent.id,
|
|
973
|
+
state: "failed",
|
|
974
|
+
output,
|
|
975
|
+
finalMessageText: output,
|
|
976
|
+
},
|
|
977
|
+
};
|
|
978
|
+
}
|
|
952
979
|
}
|
|
953
980
|
const targetRequiresExecutionToolEvidence = getBindingPrimaryTools(selectedBinding).length > 0;
|
|
981
|
+
if (selectedBinding.harnessRuntime.executionContract?.requiresPlan === true
|
|
982
|
+
&& !hasDelegatedPlanEvidence(delegatedResult)) {
|
|
983
|
+
try {
|
|
984
|
+
delegatedResult = await runDelegatedRequest([requestText, DELEGATED_PLAN_EVIDENCE_RETRY_INSTRUCTION].filter(Boolean).join("\n\n"), ":plan-evidence-retry");
|
|
985
|
+
}
|
|
986
|
+
catch (error) {
|
|
987
|
+
const output = error instanceof Error ? error.message : String(error);
|
|
988
|
+
return {
|
|
989
|
+
toolOutput: output,
|
|
990
|
+
delegatedSubagentType: subagentType,
|
|
991
|
+
delegatedResult: {
|
|
992
|
+
...delegatedResult,
|
|
993
|
+
state: "failed",
|
|
994
|
+
output,
|
|
995
|
+
finalMessageText: output,
|
|
996
|
+
},
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
}
|
|
954
1000
|
if (targetRequiresExecutionToolEvidence && !hasDelegatedExecutionToolEvidence(delegatedResult)) {
|
|
955
1001
|
try {
|
|
956
1002
|
delegatedResult = await runDelegatedRequest([requestText, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION].filter(Boolean).join("\n\n"), ":tool-evidence-retry");
|
|
@@ -969,8 +1015,9 @@ export class AgentRuntimeAdapter {
|
|
|
969
1015
|
};
|
|
970
1016
|
}
|
|
971
1017
|
}
|
|
972
|
-
if (
|
|
973
|
-
|
|
1018
|
+
if (selectedBinding.harnessRuntime.executionContract?.requiresPlan === true
|
|
1019
|
+
&& !hasDelegatedPlanEvidence(delegatedResult)) {
|
|
1020
|
+
const output = "runtime_error=Delegated agent ended before producing required plan evidence.";
|
|
974
1021
|
return {
|
|
975
1022
|
toolOutput: output,
|
|
976
1023
|
delegatedSubagentType: subagentType,
|
|
@@ -982,10 +1029,8 @@ export class AgentRuntimeAdapter {
|
|
|
982
1029
|
},
|
|
983
1030
|
};
|
|
984
1031
|
}
|
|
985
|
-
if (
|
|
986
|
-
|
|
987
|
-
&& !hasDelegatedExecutionToolEvidence(delegatedResult)) {
|
|
988
|
-
const output = "runtime_error=Delegated agent ended before producing required plan evidence.";
|
|
1032
|
+
if (targetRequiresExecutionToolEvidence && !hasDelegatedExecutionToolEvidence(delegatedResult)) {
|
|
1033
|
+
const output = `runtime_error=Delegated agent ${selectedBinding.agent.id} completed without tool execution evidence.`;
|
|
989
1034
|
return {
|
|
990
1035
|
toolOutput: output,
|
|
991
1036
|
delegatedSubagentType: subagentType,
|
|
@@ -1094,6 +1139,176 @@ export class AgentRuntimeAdapter {
|
|
|
1094
1139
|
report,
|
|
1095
1140
|
};
|
|
1096
1141
|
}
|
|
1142
|
+
async *streamDelegateWithCompactRouter(binding, input, sessionId, requestId, options = {}) {
|
|
1143
|
+
if (!isDelegationOnlyDeepAgentBinding(binding) || !this.options.bindingResolver) {
|
|
1144
|
+
return null;
|
|
1145
|
+
}
|
|
1146
|
+
const primaryModel = getBindingPrimaryModel(binding);
|
|
1147
|
+
if (!primaryModel) {
|
|
1148
|
+
return null;
|
|
1149
|
+
}
|
|
1150
|
+
const requestText = extractMessageText(input).trim();
|
|
1151
|
+
if (!requestText) {
|
|
1152
|
+
return null;
|
|
1153
|
+
}
|
|
1154
|
+
const subagents = getBindingSubagents(binding);
|
|
1155
|
+
const subagentNames = new Set(subagents.map((subagent) => subagent.name));
|
|
1156
|
+
const subagentCatalog = subagents
|
|
1157
|
+
.map((subagent) => `- ${subagent.name}: ${subagent.description}`)
|
|
1158
|
+
.join("\n");
|
|
1159
|
+
const routingPolicy = getBindingSystemPrompt(binding);
|
|
1160
|
+
const prompt = [
|
|
1161
|
+
primaryModel.init?.think === false ? "/no_think" : "",
|
|
1162
|
+
"You are selecting a subagent for a delegation-only agent.",
|
|
1163
|
+
"Choose exactly one listed subagent when it can responsibly handle the request.",
|
|
1164
|
+
routingPolicy ? "Agent routing policy:" : "",
|
|
1165
|
+
routingPolicy ?? "",
|
|
1166
|
+
"Return only JSON with this shape:",
|
|
1167
|
+
"{\"subagent_type\":\"<listed subagent name>\"}",
|
|
1168
|
+
"If no listed subagent can handle the request, return only:",
|
|
1169
|
+
"{\"status\":\"refused\",\"reason\":\"No configured subagent can handle the request.\"}",
|
|
1170
|
+
"Available subagents:",
|
|
1171
|
+
subagentCatalog,
|
|
1172
|
+
"User request:",
|
|
1173
|
+
requestText,
|
|
1174
|
+
].filter(Boolean).join("\n\n");
|
|
1175
|
+
const model = await this.resolveModel(primaryModel);
|
|
1176
|
+
if (typeof model.invoke !== "function") {
|
|
1177
|
+
return null;
|
|
1178
|
+
}
|
|
1179
|
+
const invokeRouter = async (activePrompt, operationName) => this.invokeWithProviderRetry(binding, () => this.withTimeout(() => model.invoke(activePrompt, resolveLangChainInvocationConfig(binding, {
|
|
1180
|
+
sessionId,
|
|
1181
|
+
requestId,
|
|
1182
|
+
context: options.context,
|
|
1183
|
+
toolRuntimeContext: this.buildFunctionToolRuntimeContext(binding, {
|
|
1184
|
+
...options,
|
|
1185
|
+
sessionId,
|
|
1186
|
+
requestId,
|
|
1187
|
+
}),
|
|
1188
|
+
})), resolveBindingTimeout(binding), operationName, "invoke"));
|
|
1189
|
+
const routerPrompts = [
|
|
1190
|
+
prompt,
|
|
1191
|
+
[
|
|
1192
|
+
prompt,
|
|
1193
|
+
"Your previous router output was invalid.",
|
|
1194
|
+
"Return only one JSON object now. Do not include prose, markdown, labels, or tool-call wrappers.",
|
|
1195
|
+
].join("\n\n"),
|
|
1196
|
+
[
|
|
1197
|
+
primaryModel.init?.think === false ? "/no_think" : "",
|
|
1198
|
+
"Select one subagent from this exact list:",
|
|
1199
|
+
Array.from(subagentNames).join(", "),
|
|
1200
|
+
"Return JSON only:",
|
|
1201
|
+
"{\"subagent_type\":\"<one exact listed name>\"}",
|
|
1202
|
+
"User request:",
|
|
1203
|
+
requestText,
|
|
1204
|
+
].filter(Boolean).join("\n\n"),
|
|
1205
|
+
[
|
|
1206
|
+
primaryModel.init?.think === false ? "/no_think" : "",
|
|
1207
|
+
"JSON only. Pick a listed subagent or refuse.",
|
|
1208
|
+
"Listed subagents:",
|
|
1209
|
+
Array.from(subagentNames).join(", "),
|
|
1210
|
+
"Allowed outputs:",
|
|
1211
|
+
"{\"subagent_type\":\"<listed name>\"}",
|
|
1212
|
+
"{\"status\":\"refused\",\"reason\":\"No configured subagent can handle the request.\"}",
|
|
1213
|
+
"Request:",
|
|
1214
|
+
requestText,
|
|
1215
|
+
].filter(Boolean).join("\n\n"),
|
|
1216
|
+
];
|
|
1217
|
+
let selection = null;
|
|
1218
|
+
let previousRawText = "";
|
|
1219
|
+
for (let index = 0; index < routerPrompts.length && !selection; index += 1) {
|
|
1220
|
+
const activePrompt = index <= 1 || !previousRawText
|
|
1221
|
+
? routerPrompts[index]
|
|
1222
|
+
: [routerPrompts[index], "Previous output:", previousRawText].join("\n\n");
|
|
1223
|
+
const raw = await invokeRouter(activePrompt, index === 0 ? "delegation router invoke" : `delegation router retry invoke ${index}`);
|
|
1224
|
+
previousRawText = readModelText(raw);
|
|
1225
|
+
selection = parseCompactRouterSelection(previousRawText, subagentNames);
|
|
1226
|
+
}
|
|
1227
|
+
if (selection?.refusedReason) {
|
|
1228
|
+
return {
|
|
1229
|
+
toolOutput: selection.refusedReason,
|
|
1230
|
+
delegatedSubagentType: null,
|
|
1231
|
+
delegatedResult: {
|
|
1232
|
+
sessionId,
|
|
1233
|
+
requestId,
|
|
1234
|
+
agentId: binding.agent.id,
|
|
1235
|
+
state: "failed",
|
|
1236
|
+
output: selection.refusedReason,
|
|
1237
|
+
finalMessageText: selection.refusedReason,
|
|
1238
|
+
},
|
|
1239
|
+
};
|
|
1240
|
+
}
|
|
1241
|
+
let subagentType = selection?.subagentType ?? "";
|
|
1242
|
+
if (!subagentNames.has(subagentType)) {
|
|
1243
|
+
const fallbackSubagent = subagentNames.values().next().value;
|
|
1244
|
+
if (typeof fallbackSubagent === "string" && fallbackSubagent) {
|
|
1245
|
+
subagentType = fallbackSubagent;
|
|
1246
|
+
}
|
|
1247
|
+
else {
|
|
1248
|
+
return null;
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
const selectedBinding = this.options.bindingResolver(subagentType);
|
|
1252
|
+
if (!selectedBinding) {
|
|
1253
|
+
return null;
|
|
1254
|
+
}
|
|
1255
|
+
yield {
|
|
1256
|
+
kind: "commentary",
|
|
1257
|
+
content: `Delegating to ${subagentType}.`,
|
|
1258
|
+
agentId: binding.agent.id,
|
|
1259
|
+
};
|
|
1260
|
+
yield {
|
|
1261
|
+
kind: "commentary",
|
|
1262
|
+
content: "Starting delegated execution.",
|
|
1263
|
+
agentId: selectedBinding.agent.id,
|
|
1264
|
+
};
|
|
1265
|
+
const childRequestId = `${requestId}:${subagentType}`;
|
|
1266
|
+
let delegatedResult;
|
|
1267
|
+
const runDelegatedRequest = (text, requestSuffix = "") => this.invoke(selectedBinding, text, sessionId, `${childRequestId}${requestSuffix}`, undefined, [], {
|
|
1268
|
+
context: options.context,
|
|
1269
|
+
state: options.state,
|
|
1270
|
+
files: options.files,
|
|
1271
|
+
memoryContext: options.memoryContext,
|
|
1272
|
+
});
|
|
1273
|
+
try {
|
|
1274
|
+
delegatedResult = await runDelegatedRequest(requestText);
|
|
1275
|
+
}
|
|
1276
|
+
catch (error) {
|
|
1277
|
+
const output = error instanceof Error ? error.message : String(error);
|
|
1278
|
+
return {
|
|
1279
|
+
toolOutput: output,
|
|
1280
|
+
delegatedSubagentType: subagentType,
|
|
1281
|
+
delegatedResult: {
|
|
1282
|
+
sessionId,
|
|
1283
|
+
requestId: childRequestId,
|
|
1284
|
+
agentId: selectedBinding.agent.id,
|
|
1285
|
+
state: "failed",
|
|
1286
|
+
output,
|
|
1287
|
+
finalMessageText: output,
|
|
1288
|
+
},
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
const delegatedToolResults = Array.isArray(delegatedResult.metadata?.executedToolResults)
|
|
1292
|
+
? delegatedResult.metadata.executedToolResults
|
|
1293
|
+
: [];
|
|
1294
|
+
for (const toolResult of delegatedToolResults) {
|
|
1295
|
+
if (!toolResult?.toolName) {
|
|
1296
|
+
continue;
|
|
1297
|
+
}
|
|
1298
|
+
yield {
|
|
1299
|
+
kind: "tool-result",
|
|
1300
|
+
toolName: toolResult.toolName,
|
|
1301
|
+
output: toolResult.output,
|
|
1302
|
+
...(toolResult.isError !== undefined ? { isError: toolResult.isError } : {}),
|
|
1303
|
+
agentId: selectedBinding.agent.id,
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
return {
|
|
1307
|
+
toolOutput: resolveDelegatedResultOutput(delegatedResult),
|
|
1308
|
+
delegatedSubagentType: subagentType,
|
|
1309
|
+
delegatedResult,
|
|
1310
|
+
};
|
|
1311
|
+
}
|
|
1097
1312
|
async *stream(binding, input, sessionId, history = [], options = {}) {
|
|
1098
1313
|
const directListing = await this.tryHandleDirectWorkspaceListing(binding, input, {
|
|
1099
1314
|
...options,
|
|
@@ -1118,11 +1333,7 @@ export class AgentRuntimeAdapter {
|
|
|
1118
1333
|
content: "Selecting a specialist for delegated execution.",
|
|
1119
1334
|
};
|
|
1120
1335
|
}
|
|
1121
|
-
const compactDelegation =
|
|
1122
|
-
...options,
|
|
1123
|
-
sessionId,
|
|
1124
|
-
requestId: options.requestId,
|
|
1125
|
-
});
|
|
1336
|
+
const compactDelegation = yield* this.streamDelegateWithCompactRouter(binding, input, sessionId, options.requestId ?? sessionId, options);
|
|
1126
1337
|
if (compactDelegation) {
|
|
1127
1338
|
const compactReport = this.buildCompactDelegationReport(compactDelegation);
|
|
1128
1339
|
yield {
|
|
@@ -3,6 +3,7 @@ import { type InternalHarnessStreamItem } from "../events/streaming.js";
|
|
|
3
3
|
type RuntimeStreamChunk = {
|
|
4
4
|
kind: "commentary";
|
|
5
5
|
content: string;
|
|
6
|
+
agentId?: string;
|
|
6
7
|
} | string | {
|
|
7
8
|
kind: "content" | "interrupt" | "reasoning" | "tool-result" | "upstream-event";
|
|
8
9
|
content?: string;
|
|
@@ -10,9 +11,11 @@ type RuntimeStreamChunk = {
|
|
|
10
11
|
output?: unknown;
|
|
11
12
|
isError?: boolean;
|
|
12
13
|
event?: unknown;
|
|
14
|
+
agentId?: string;
|
|
13
15
|
} | {
|
|
14
16
|
kind: "profile";
|
|
15
17
|
step: RequestExecutionStep;
|
|
18
|
+
agentId?: string;
|
|
16
19
|
};
|
|
17
20
|
type StreamRunOptions = {
|
|
18
21
|
binding: CompiledAgentBinding;
|
|
@@ -284,16 +284,16 @@ function normalizeStreamChunk(chunk) {
|
|
|
284
284
|
return { kind: "content", content: chunk };
|
|
285
285
|
}
|
|
286
286
|
if (chunk.kind === "commentary") {
|
|
287
|
-
return { kind: "commentary", content: chunk.content ?? "" };
|
|
287
|
+
return { kind: "commentary", content: chunk.content ?? "", agentId: chunk.agentId };
|
|
288
288
|
}
|
|
289
289
|
if (chunk.kind === "upstream-event") {
|
|
290
|
-
return { kind: "upstream-event", event: (chunk.event ?? {}) };
|
|
290
|
+
return { kind: "upstream-event", event: (chunk.event ?? {}), agentId: chunk.agentId };
|
|
291
291
|
}
|
|
292
292
|
if (chunk.kind === "interrupt") {
|
|
293
|
-
return { kind: "interrupt", content: chunk.content };
|
|
293
|
+
return { kind: "interrupt", content: chunk.content, agentId: chunk.agentId };
|
|
294
294
|
}
|
|
295
295
|
if (chunk.kind === "reasoning") {
|
|
296
|
-
return { kind: "reasoning", content: chunk.content ?? "" };
|
|
296
|
+
return { kind: "reasoning", content: chunk.content ?? "", agentId: chunk.agentId };
|
|
297
297
|
}
|
|
298
298
|
if (chunk.kind === "tool-result") {
|
|
299
299
|
return {
|
|
@@ -301,15 +301,17 @@ function normalizeStreamChunk(chunk) {
|
|
|
301
301
|
toolName: chunk.toolName ?? "unknown_tool",
|
|
302
302
|
output: chunk.output,
|
|
303
303
|
isError: chunk.isError,
|
|
304
|
+
agentId: chunk.agentId,
|
|
304
305
|
};
|
|
305
306
|
}
|
|
306
307
|
if (chunk.kind === "profile") {
|
|
307
308
|
return {
|
|
308
309
|
kind: "profile",
|
|
309
310
|
step: chunk.step,
|
|
311
|
+
agentId: chunk.agentId,
|
|
310
312
|
};
|
|
311
313
|
}
|
|
312
|
-
return { kind: "content", content: chunk.content ?? "" };
|
|
314
|
+
return { kind: "content", content: chunk.content ?? "", agentId: chunk.agentId };
|
|
313
315
|
}
|
|
314
316
|
function normalizeCommentaryText(value) {
|
|
315
317
|
return value
|
|
@@ -645,7 +647,7 @@ export async function* streamHarnessRun(options) {
|
|
|
645
647
|
let lastToolResultKey = null;
|
|
646
648
|
const executedToolResults = [];
|
|
647
649
|
const emittedCommentary = new Set();
|
|
648
|
-
const emitCommentary = function* (content) {
|
|
650
|
+
const emitCommentary = function* (content, agentIdOverride) {
|
|
649
651
|
const normalized = normalizeCommentaryText(content);
|
|
650
652
|
if (!normalized || emittedCommentary.has(normalized)) {
|
|
651
653
|
return;
|
|
@@ -655,7 +657,7 @@ export async function* streamHarnessRun(options) {
|
|
|
655
657
|
type: "commentary",
|
|
656
658
|
sessionId: options.sessionId,
|
|
657
659
|
requestId: options.requestId,
|
|
658
|
-
agentId: currentAgentId,
|
|
660
|
+
agentId: agentIdOverride ?? currentAgentId,
|
|
659
661
|
content: normalized,
|
|
660
662
|
};
|
|
661
663
|
};
|
|
@@ -804,7 +806,7 @@ export async function* streamHarnessRun(options) {
|
|
|
804
806
|
return;
|
|
805
807
|
}
|
|
806
808
|
if (normalizedChunk.kind === "commentary") {
|
|
807
|
-
yield* emitCommentary(normalizedChunk.content);
|
|
809
|
+
yield* emitCommentary(normalizedChunk.content, normalizedChunk.agentId);
|
|
808
810
|
continue;
|
|
809
811
|
}
|
|
810
812
|
if (normalizedChunk.kind === "reasoning") {
|
|
@@ -824,6 +826,7 @@ export async function* streamHarnessRun(options) {
|
|
|
824
826
|
continue;
|
|
825
827
|
}
|
|
826
828
|
if (normalizedChunk.kind === "tool-result") {
|
|
829
|
+
const chunkAgentId = normalizedChunk.agentId ?? currentAgentId;
|
|
827
830
|
const toolResultKey = createToolResultKey(normalizedChunk.toolName, normalizedChunk.output, normalizedChunk.isError);
|
|
828
831
|
if (toolResultKey === lastToolResultKey) {
|
|
829
832
|
continue;
|
|
@@ -844,7 +847,7 @@ export async function* streamHarnessRun(options) {
|
|
|
844
847
|
type: "tool-result",
|
|
845
848
|
sessionId: options.sessionId,
|
|
846
849
|
requestId: options.requestId,
|
|
847
|
-
agentId:
|
|
850
|
+
agentId: chunkAgentId,
|
|
848
851
|
toolName: normalizedChunk.toolName,
|
|
849
852
|
output: normalizedChunk.output,
|
|
850
853
|
isError: normalizedChunk.isError,
|
|
@@ -873,16 +876,16 @@ export async function* streamHarnessRun(options) {
|
|
|
873
876
|
currentPlanState = mergedPlanState;
|
|
874
877
|
const progression = buildPlanStateProgression(previousPlanState, currentPlanState);
|
|
875
878
|
for (const progressionStep of progression) {
|
|
876
|
-
for (const item of await emitPlanStateUpdate(options,
|
|
879
|
+
for (const item of await emitPlanStateUpdate(options, chunkAgentId, progressionStep.planState)) {
|
|
877
880
|
yield item;
|
|
878
881
|
}
|
|
879
882
|
if (progressionStep.commentary) {
|
|
880
|
-
yield* emitCommentary(progressionStep.commentary);
|
|
883
|
+
yield* emitCommentary(progressionStep.commentary, chunkAgentId);
|
|
881
884
|
}
|
|
882
885
|
}
|
|
883
886
|
const commentary = summarizePlanState(currentPlanState);
|
|
884
887
|
if (commentary) {
|
|
885
|
-
yield* emitCommentary(commentary);
|
|
888
|
+
yield* emitCommentary(commentary, chunkAgentId);
|
|
886
889
|
}
|
|
887
890
|
}
|
|
888
891
|
}
|
|
@@ -899,16 +902,16 @@ export async function* streamHarnessRun(options) {
|
|
|
899
902
|
currentPlanState = reconciledPlanState;
|
|
900
903
|
const progression = buildPlanStateProgression(previousPlanState, currentPlanState);
|
|
901
904
|
for (const progressionStep of progression) {
|
|
902
|
-
for (const item of await emitPlanStateUpdate(options,
|
|
905
|
+
for (const item of await emitPlanStateUpdate(options, chunkAgentId, progressionStep.planState)) {
|
|
903
906
|
yield item;
|
|
904
907
|
}
|
|
905
908
|
if (progressionStep.commentary) {
|
|
906
|
-
yield* emitCommentary(progressionStep.commentary);
|
|
909
|
+
yield* emitCommentary(progressionStep.commentary, chunkAgentId);
|
|
907
910
|
}
|
|
908
911
|
}
|
|
909
912
|
const commentary = summarizePlanState(currentPlanState);
|
|
910
913
|
if (commentary) {
|
|
911
|
-
yield* emitCommentary(commentary);
|
|
914
|
+
yield* emitCommentary(commentary, chunkAgentId);
|
|
912
915
|
}
|
|
913
916
|
}
|
|
914
917
|
}
|
|
@@ -2,26 +2,33 @@ import type { RequestExecutionStep } from "../../contracts/types.js";
|
|
|
2
2
|
export type RuntimeStreamChunk = {
|
|
3
3
|
kind: "upstream-event";
|
|
4
4
|
event: unknown;
|
|
5
|
+
agentId?: string;
|
|
5
6
|
} | {
|
|
6
7
|
kind: "commentary";
|
|
7
8
|
content: string;
|
|
9
|
+
agentId?: string;
|
|
8
10
|
} | {
|
|
9
11
|
kind: "content";
|
|
10
12
|
content: string;
|
|
13
|
+
agentId?: string;
|
|
11
14
|
} | {
|
|
12
15
|
kind: "reasoning";
|
|
13
16
|
content: string;
|
|
17
|
+
agentId?: string;
|
|
14
18
|
} | {
|
|
15
19
|
kind: "interrupt";
|
|
16
20
|
content: string;
|
|
21
|
+
agentId?: string;
|
|
17
22
|
} | {
|
|
18
23
|
kind: "tool-result";
|
|
19
24
|
toolName: string;
|
|
20
25
|
output: unknown;
|
|
21
26
|
isError?: boolean;
|
|
27
|
+
agentId?: string;
|
|
22
28
|
} | {
|
|
23
29
|
kind: "profile";
|
|
24
30
|
step: RequestExecutionStep;
|
|
31
|
+
agentId?: string;
|
|
25
32
|
};
|
|
26
33
|
export declare function sanitizeStreamPayload(value: unknown): unknown;
|
|
27
34
|
export declare function sanitizeRetainedUpstreamEvent(event: unknown): unknown;
|