@botbotgo/agent-harness 0.0.419 → 0.0.421
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-interactive.js +1 -1
- package/dist/cli/chat-stream.js +9 -1
- package/dist/package-version.d.ts +2 -2
- package/dist/package-version.js +2 -2
- package/dist/runtime/adapter/flow/invocation-flow.d.ts +10 -0
- package/dist/runtime/adapter/flow/invocation-flow.js +2 -0
- package/dist/runtime/adapter/flow/invoke-runtime.d.ts +10 -0
- package/dist/runtime/adapter/flow/invoke-runtime.js +2 -0
- package/dist/runtime/adapter/flow/stream-runtime.d.ts +20 -0
- package/dist/runtime/adapter/flow/stream-runtime.js +201 -3
- package/dist/runtime/adapter/local-tool-invocation.d.ts +11 -1
- package/dist/runtime/adapter/local-tool-invocation.js +250 -11
- package/dist/runtime/adapter/middleware-assembly.js +294 -20
- package/dist/runtime/adapter/model/model-providers.js +8 -0
- package/dist/runtime/agent-runtime-adapter.js +657 -48
- package/dist/runtime/agent-runtime-assembly.js +1 -1
- package/dist/runtime/harness/run/inspection.js +9 -1
- package/dist/runtime/harness/run/stream-run.js +11 -2
- package/dist/runtime/parsing/output-tool-args.js +108 -0
- package/package.json +1 -1
|
@@ -166,7 +166,7 @@ export async function runInteractiveChatLoop(input) {
|
|
|
166
166
|
}
|
|
167
167
|
activeSessionId = chatCommand.arg;
|
|
168
168
|
latestRequestId = session.latestRequestId;
|
|
169
|
-
activeAgentId = session.
|
|
169
|
+
activeAgentId = session.entryAgentId ?? session.currentAgentId ?? activeAgentId;
|
|
170
170
|
input.stdout(`session=${activeSessionId}\n`);
|
|
171
171
|
continue;
|
|
172
172
|
}
|
package/dist/cli/chat-stream.js
CHANGED
|
@@ -10,6 +10,7 @@ export async function streamChatMessage(input) {
|
|
|
10
10
|
let latestSessionId = input.sessionId;
|
|
11
11
|
let latestRequestId;
|
|
12
12
|
let latestAgentId = input.agentId;
|
|
13
|
+
let entryAgentId = input.agentId;
|
|
13
14
|
let wroteContent = false;
|
|
14
15
|
let wroteRenderableBlocks = false;
|
|
15
16
|
let renderedAssistantOutput = "";
|
|
@@ -348,6 +349,7 @@ export async function streamChatMessage(input) {
|
|
|
348
349
|
writeChatStderr(lines.join(""));
|
|
349
350
|
};
|
|
350
351
|
const renderContentBlocks = (contentBlocks, agentId) => {
|
|
352
|
+
entryAgentId ??= agentId;
|
|
351
353
|
latestAgentId = agentId || latestAgentId;
|
|
352
354
|
const rendered = contentBlocks
|
|
353
355
|
.map((block) => {
|
|
@@ -373,6 +375,7 @@ export async function streamChatMessage(input) {
|
|
|
373
375
|
markRuntimeProgress();
|
|
374
376
|
latestSessionId = snapshot.sessionId || latestSessionId;
|
|
375
377
|
latestRequestId = snapshot.requestId || latestRequestId;
|
|
378
|
+
entryAgentId ??= snapshot.agentId;
|
|
376
379
|
latestAgentId = snapshot.agentId || latestAgentId;
|
|
377
380
|
latestSnapshot = snapshot;
|
|
378
381
|
firstSnapshotAt ??= Date.now();
|
|
@@ -421,16 +424,19 @@ export async function streamChatMessage(input) {
|
|
|
421
424
|
latestRequestId = delta.requestId || latestRequestId;
|
|
422
425
|
firstDataAt ??= Date.now();
|
|
423
426
|
if (delta.type === "output.text.delta") {
|
|
427
|
+
entryAgentId ??= delta.agentId;
|
|
424
428
|
latestAgentId = delta.agentId || latestAgentId;
|
|
425
429
|
writeAssistantOutput(delta.text);
|
|
426
430
|
return;
|
|
427
431
|
}
|
|
428
432
|
if (delta.type === "output.content-blocks") {
|
|
433
|
+
entryAgentId ??= delta.agentId;
|
|
429
434
|
suspendRequestTreeRendering();
|
|
430
435
|
renderContentBlocks(delta.contentBlocks, delta.agentId);
|
|
431
436
|
return;
|
|
432
437
|
}
|
|
433
438
|
if (delta.type === "plan.step") {
|
|
439
|
+
entryAgentId ??= delta.agentId;
|
|
434
440
|
latestAgentId = delta.agentId || latestAgentId;
|
|
435
441
|
const item = delta.item;
|
|
436
442
|
const status = typeof item?.status === "string" ? item.status : "unknown";
|
|
@@ -441,6 +447,7 @@ export async function streamChatMessage(input) {
|
|
|
441
447
|
return;
|
|
442
448
|
}
|
|
443
449
|
if (delta.type === "tool.result") {
|
|
450
|
+
entryAgentId ??= delta.agentId;
|
|
444
451
|
latestAgentId = delta.agentId || latestAgentId;
|
|
445
452
|
if ((input.showToolResults ?? true) && !input.requestEvents) {
|
|
446
453
|
writeChatStderr(`\n[${formatPerfClock(Date.now())} +${formatElapsed(Date.now())}]${formatAgentProgressLabel(delta.agentId)} [tool:${delta.toolName}] ${summarizeChatToolResult(delta.output, delta.isError === true)}${delta.isError ? " (error)" : ""}\n`);
|
|
@@ -448,6 +455,7 @@ export async function streamChatMessage(input) {
|
|
|
448
455
|
return;
|
|
449
456
|
}
|
|
450
457
|
if (delta.type === "progress.commentary") {
|
|
458
|
+
entryAgentId ??= delta.agentId;
|
|
451
459
|
latestAgentId = delta.agentId || latestAgentId;
|
|
452
460
|
if (wroteContent || wroteRenderableBlocks) {
|
|
453
461
|
return;
|
|
@@ -500,5 +508,5 @@ export async function streamChatMessage(input) {
|
|
|
500
508
|
writeChatStdout("\n");
|
|
501
509
|
}
|
|
502
510
|
await Promise.allSettled([stdoutWriteChain, stderrWriteChain]);
|
|
503
|
-
return { sessionId: latestSessionId, requestId: latestRequestId, agentId: latestAgentId };
|
|
511
|
+
return { sessionId: latestSessionId, requestId: latestRequestId, agentId: entryAgentId ?? latestAgentId };
|
|
504
512
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
2
|
-
export declare const AGENT_HARNESS_RELEASE_DATE = "2026-05-
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.421";
|
|
2
|
+
export declare const AGENT_HARNESS_RELEASE_DATE = "2026-05-03";
|
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-05-
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.421";
|
|
2
|
+
export const AGENT_HARNESS_RELEASE_DATE = "2026-05-03";
|
|
@@ -16,6 +16,16 @@ export declare function executeRequestInvocation(options: {
|
|
|
16
16
|
toolRuntimeContext?: Record<string, unknown>;
|
|
17
17
|
suppressInitialRequiredPlanInstruction?: boolean;
|
|
18
18
|
externalPlanEvidence?: boolean;
|
|
19
|
+
externalPlanEvidenceTool?: {
|
|
20
|
+
name: string;
|
|
21
|
+
args?: Record<string, unknown>;
|
|
22
|
+
id?: string;
|
|
23
|
+
};
|
|
24
|
+
externalPlanEvidenceTools?: Array<{
|
|
25
|
+
name: string;
|
|
26
|
+
args?: Record<string, unknown>;
|
|
27
|
+
id?: string;
|
|
28
|
+
}>;
|
|
19
29
|
};
|
|
20
30
|
resolveTools: (tools: CompiledTool[], binding?: CompiledAgentBinding) => unknown[];
|
|
21
31
|
getToolNameMapping: (binding: CompiledAgentBinding) => ToolNameMapping;
|
|
@@ -339,6 +339,8 @@ export async function executeRequestInvocation(options) {
|
|
|
339
339
|
callRuntimeWithToolParseRecovery: options.callRuntimeWithToolParseRecovery,
|
|
340
340
|
toolRuntimeContext: invokeOptions.toolRuntimeContext,
|
|
341
341
|
externalPlanEvidence: invokeOptions.externalPlanEvidence,
|
|
342
|
+
externalPlanEvidenceTool: invokeOptions.externalPlanEvidenceTool,
|
|
343
|
+
externalPlanEvidenceTools: invokeOptions.externalPlanEvidenceTools,
|
|
342
344
|
});
|
|
343
345
|
let localOrUpstreamInvocation = await invokeOnce(request);
|
|
344
346
|
if (options.resumePayload === undefined
|
|
@@ -18,6 +18,16 @@ export declare function invokeRuntimeWithLocalTools(options: {
|
|
|
18
18
|
callRuntimeWithToolParseRecovery: (request: unknown) => Promise<Record<string, unknown>>;
|
|
19
19
|
toolRuntimeContext?: Record<string, unknown>;
|
|
20
20
|
externalPlanEvidence?: boolean;
|
|
21
|
+
externalPlanEvidenceTool?: {
|
|
22
|
+
name: string;
|
|
23
|
+
args?: Record<string, unknown>;
|
|
24
|
+
id?: string;
|
|
25
|
+
};
|
|
26
|
+
externalPlanEvidenceTools?: Array<{
|
|
27
|
+
name: string;
|
|
28
|
+
args?: Record<string, unknown>;
|
|
29
|
+
id?: string;
|
|
30
|
+
}>;
|
|
21
31
|
}): Promise<{
|
|
22
32
|
result: Record<string, unknown>;
|
|
23
33
|
executedToolResults: ExecutedToolResult[];
|
|
@@ -16,5 +16,7 @@ export async function invokeRuntimeWithLocalTools(options) {
|
|
|
16
16
|
callRuntimeWithToolParseRecovery: options.callRuntimeWithToolParseRecovery,
|
|
17
17
|
toolRuntimeContext: options.toolRuntimeContext,
|
|
18
18
|
externalPlanEvidence: options.externalPlanEvidence,
|
|
19
|
+
externalPlanEvidenceTool: options.externalPlanEvidenceTool,
|
|
20
|
+
externalPlanEvidenceTools: options.externalPlanEvidenceTools,
|
|
19
21
|
});
|
|
20
22
|
}
|
|
@@ -23,6 +23,16 @@ export declare function streamRuntimeExecution(options: {
|
|
|
23
23
|
toolRuntimeContext?: Record<string, unknown>;
|
|
24
24
|
suppressInitialRequiredPlanInstruction?: boolean;
|
|
25
25
|
externalPlanEvidence?: boolean;
|
|
26
|
+
externalPlanEvidenceTool?: {
|
|
27
|
+
name: string;
|
|
28
|
+
args?: Record<string, unknown>;
|
|
29
|
+
id?: string;
|
|
30
|
+
};
|
|
31
|
+
externalPlanEvidenceTools?: Array<{
|
|
32
|
+
name: string;
|
|
33
|
+
args?: Record<string, unknown>;
|
|
34
|
+
id?: string;
|
|
35
|
+
}>;
|
|
26
36
|
};
|
|
27
37
|
primaryTools: CompiledTool[];
|
|
28
38
|
toolNameMapping: ToolNameMapping;
|
|
@@ -51,6 +61,16 @@ export declare function streamRuntimeExecution(options: {
|
|
|
51
61
|
toolRuntimeContext?: Record<string, unknown>;
|
|
52
62
|
suppressInitialRequiredPlanInstruction?: boolean;
|
|
53
63
|
externalPlanEvidence?: boolean;
|
|
64
|
+
externalPlanEvidenceTool?: {
|
|
65
|
+
name: string;
|
|
66
|
+
args?: Record<string, unknown>;
|
|
67
|
+
id?: string;
|
|
68
|
+
};
|
|
69
|
+
externalPlanEvidenceTools?: Array<{
|
|
70
|
+
name: string;
|
|
71
|
+
args?: Record<string, unknown>;
|
|
72
|
+
id?: string;
|
|
73
|
+
}>;
|
|
54
74
|
}) => Promise<{
|
|
55
75
|
output: string;
|
|
56
76
|
metadata?: Record<string, unknown>;
|
|
@@ -128,6 +128,182 @@ function hasIncompletePlanOutput(value) {
|
|
|
128
128
|
}
|
|
129
129
|
return null;
|
|
130
130
|
}
|
|
131
|
+
function extractInProgressTodoContents(value) {
|
|
132
|
+
if (typeof value !== "object" || value === null) {
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
const typed = value;
|
|
136
|
+
const arrays = [typed.todos, typed.items];
|
|
137
|
+
const contents = [];
|
|
138
|
+
for (const candidate of arrays) {
|
|
139
|
+
if (!Array.isArray(candidate)) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
for (const todo of candidate) {
|
|
143
|
+
if (typeof todo !== "object" || todo === null) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
const item = todo;
|
|
147
|
+
if (item.status !== "in_progress") {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const content = [item.content, item.description, item.title, item.name, item.text]
|
|
151
|
+
.find((value) => typeof value === "string" && value.trim().length > 0);
|
|
152
|
+
if (content) {
|
|
153
|
+
contents.push(content.trim());
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
for (const nested of [typed.summary, typed.update, typed.data, typed.output]) {
|
|
158
|
+
contents.push(...extractInProgressTodoContents(nested));
|
|
159
|
+
}
|
|
160
|
+
return [...new Set(contents)];
|
|
161
|
+
}
|
|
162
|
+
function extractTodoContentsForEvidenceResolution(value) {
|
|
163
|
+
const inProgress = extractTodoContentsByStatus(value, "in_progress");
|
|
164
|
+
if (inProgress.length > 0) {
|
|
165
|
+
return inProgress;
|
|
166
|
+
}
|
|
167
|
+
return extractTodoContentsByStatus(value, "pending");
|
|
168
|
+
}
|
|
169
|
+
function extractTodoContentsByStatus(value, status) {
|
|
170
|
+
if (Array.isArray(value)) {
|
|
171
|
+
return value.flatMap((item) => extractTodoContentsByStatus(item, status));
|
|
172
|
+
}
|
|
173
|
+
if (typeof value !== "object" || value === null) {
|
|
174
|
+
return [];
|
|
175
|
+
}
|
|
176
|
+
const typed = value;
|
|
177
|
+
const arrays = [typed.todos, typed.items];
|
|
178
|
+
const contents = [];
|
|
179
|
+
for (const array of arrays) {
|
|
180
|
+
if (!Array.isArray(array)) {
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
for (const item of array) {
|
|
184
|
+
if (typeof item !== "object" || item === null) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
const typedItem = item;
|
|
188
|
+
if (typedItem.status !== status) {
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
const content = [
|
|
192
|
+
typedItem.content,
|
|
193
|
+
typedItem.description,
|
|
194
|
+
typedItem.title,
|
|
195
|
+
typedItem.name,
|
|
196
|
+
typedItem.text,
|
|
197
|
+
].find((value) => typeof value === "string" && value.trim().length > 0);
|
|
198
|
+
if (content) {
|
|
199
|
+
contents.push(content.trim());
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
for (const nested of [typed.summary, typed.update, typed.data, typed.output]) {
|
|
204
|
+
contents.push(...extractTodoContentsByStatus(nested, status));
|
|
205
|
+
}
|
|
206
|
+
return [...new Set(contents)];
|
|
207
|
+
}
|
|
208
|
+
function buildRunCommittedTodoEvidenceInstruction(primaryTools, planToolOutput) {
|
|
209
|
+
const todoContents = extractInProgressTodoContents(planToolOutput);
|
|
210
|
+
const todoText = todoContents.length > 0
|
|
211
|
+
? todoContents.map((content, index) => `${index + 1}. ${content}`).join("\n")
|
|
212
|
+
: "(no in-progress todo content was readable)";
|
|
213
|
+
return [
|
|
214
|
+
buildRunEvidenceAfterPlanInstruction(primaryTools),
|
|
215
|
+
"",
|
|
216
|
+
"The completed write_todos result contains these in-progress evidence commitments:",
|
|
217
|
+
todoText,
|
|
218
|
+
"",
|
|
219
|
+
"Your next action must execute the non-planning tool named by the in-progress TODO. If every TODO is pending, execute the non-planning tool named by the first pending TODO. Do not call write_todos or read_todos again before that evidence tool returns.",
|
|
220
|
+
].join("\n");
|
|
221
|
+
}
|
|
222
|
+
function resolveCommittedPlanEvidenceTool(primaryTools, planToolOutput) {
|
|
223
|
+
return resolveCommittedPlanEvidenceTools(primaryTools, planToolOutput)[0];
|
|
224
|
+
}
|
|
225
|
+
function resolveCommittedPlanEvidenceTools(primaryTools, planToolOutput) {
|
|
226
|
+
const availableToolNames = primaryTools
|
|
227
|
+
.map(readPrimaryToolName)
|
|
228
|
+
.filter((name) => name.length > 0 && !isPlanToolName(name));
|
|
229
|
+
const todoContents = extractTodoContentsForEvidenceResolution(planToolOutput);
|
|
230
|
+
if (todoContents.length === 0) {
|
|
231
|
+
return [];
|
|
232
|
+
}
|
|
233
|
+
const toolsByName = new Map(primaryTools.map((tool) => [tool.name, tool]));
|
|
234
|
+
const resolved = [];
|
|
235
|
+
const seen = new Set();
|
|
236
|
+
for (const content of todoContents) {
|
|
237
|
+
const todoText = content.toLowerCase();
|
|
238
|
+
const matches = availableToolNames.filter((name) => todoText.includes(name.toLowerCase()));
|
|
239
|
+
const selectedNames = matches.length === 1
|
|
240
|
+
? [matches[0]]
|
|
241
|
+
: resolveBestScoredToolNames(availableToolNames, toolsByName, todoText);
|
|
242
|
+
for (const selectedName of selectedNames) {
|
|
243
|
+
if (seen.has(selectedName)) {
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
seen.add(selectedName);
|
|
247
|
+
const matchedTool = toolsByName.get(selectedName);
|
|
248
|
+
const args = buildCommittedPlanEvidenceToolArgs(matchedTool, content);
|
|
249
|
+
resolved.push({
|
|
250
|
+
name: selectedName,
|
|
251
|
+
args,
|
|
252
|
+
id: `stream-committed-plan-evidence-tool-${resolved.length + 1}`,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return resolved;
|
|
257
|
+
}
|
|
258
|
+
function extractSelectionTokens(value) {
|
|
259
|
+
const tokens = new Set();
|
|
260
|
+
for (const match of value.matchAll(/[\p{L}\p{N}_-]+/gu)) {
|
|
261
|
+
const token = match[0].toLowerCase();
|
|
262
|
+
if (token.length >= 2) {
|
|
263
|
+
tokens.add(token);
|
|
264
|
+
}
|
|
265
|
+
for (const part of token.split(/[_-]+/u)) {
|
|
266
|
+
if (part.length >= 2) {
|
|
267
|
+
tokens.add(part);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return tokens;
|
|
272
|
+
}
|
|
273
|
+
function resolveBestScoredToolNames(availableToolNames, toolsByName, todoText) {
|
|
274
|
+
const requestTokens = extractSelectionTokens(todoText);
|
|
275
|
+
const scored = availableToolNames
|
|
276
|
+
.map((name) => {
|
|
277
|
+
const tool = toolsByName.get(name);
|
|
278
|
+
const toolTokens = extractSelectionTokens(`${name} ${tool?.description ?? ""}`);
|
|
279
|
+
const toolNameTokens = extractSelectionTokens(name);
|
|
280
|
+
let score = 0;
|
|
281
|
+
for (const token of requestTokens) {
|
|
282
|
+
if (toolNameTokens.has(token)) {
|
|
283
|
+
score += 10;
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
if (toolTokens.has(token)) {
|
|
287
|
+
score += token.length > 3 ? 2 : 1;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return { name, score };
|
|
291
|
+
})
|
|
292
|
+
.filter((item) => item.score > 0)
|
|
293
|
+
.sort((left, right) => right.score - left.score);
|
|
294
|
+
const topScore = scored[0]?.score ?? 0;
|
|
295
|
+
return topScore > 0 ? scored.filter((item) => item.score === topScore).map((item) => item.name) : [];
|
|
296
|
+
}
|
|
297
|
+
function buildCommittedPlanEvidenceToolArgs(tool, todoText) {
|
|
298
|
+
const properties = typeof tool?.modelSchema === "object" && tool.modelSchema !== null
|
|
299
|
+
? tool.modelSchema.properties
|
|
300
|
+
: undefined;
|
|
301
|
+
if (typeof properties !== "object" || properties === null) {
|
|
302
|
+
return {};
|
|
303
|
+
}
|
|
304
|
+
const queryLikeField = ["query", "question", "prompt", "input", "text"].find((field) => Object.prototype.hasOwnProperty.call(properties, field));
|
|
305
|
+
return queryLikeField ? { [queryLikeField]: todoText } : {};
|
|
306
|
+
}
|
|
131
307
|
function normalizePlanToolName(toolName) {
|
|
132
308
|
return typeof toolName === "string" ? toolName.trim().toLowerCase().replace(/[\s-]+/gu, "_") : "";
|
|
133
309
|
}
|
|
@@ -655,6 +831,7 @@ export async function* streamRuntimeExecution(options) {
|
|
|
655
831
|
let sawCompletedPlanToolResult = false;
|
|
656
832
|
let sawSuccessfulNonTodoToolResult = false;
|
|
657
833
|
let earlyStreamRecoveryInstruction = null;
|
|
834
|
+
let earlyStreamExternalPlanEvidenceTools;
|
|
658
835
|
let earlyStreamRecoverySuppressInitialPlan = false;
|
|
659
836
|
let completedPlanToolResultCount = 0;
|
|
660
837
|
for await (const event of options.iterateWithTimeout(events, options.streamIdleTimeoutMs, "agent streamEvents", options.streamDeadlineAt, options.invokeTimeoutMs)) {
|
|
@@ -677,12 +854,15 @@ export async function* streamRuntimeExecution(options) {
|
|
|
677
854
|
&& chunk.kind !== "content"
|
|
678
855
|
&& !(chunk.kind === "tool-result" && isPlanToolName(chunk.toolName))
|
|
679
856
|
&& !(chunk.kind === "tool-result" && chunk.isError === true && isRetrySafeInvalidToolSelectionError(chunk.output)));
|
|
857
|
+
const hadPriorPlanToolResult = completedPlanToolResultCount > 0;
|
|
680
858
|
const repeatedPlanToolResultBeforeEvidence = requiresPlanEvidence(options.binding)
|
|
681
859
|
&& !sawSuccessfulNonTodoToolResult
|
|
682
|
-
&&
|
|
860
|
+
&& hadPriorPlanToolResult
|
|
683
861
|
&& projectedChunks.some((chunk) => chunk.kind === "tool-result" && isPlanToolName(chunk.toolName));
|
|
684
862
|
if (repeatedPlanToolResultBeforeEvidence) {
|
|
685
|
-
|
|
863
|
+
const planToolResult = projectedChunks.find((chunk) => chunk.kind === "tool-result" && isPlanToolName(chunk.toolName) && chunk.isError !== true);
|
|
864
|
+
earlyStreamExternalPlanEvidenceTools = resolveCommittedPlanEvidenceTools(options.primaryTools, planToolResult?.kind === "tool-result" ? planToolResult.output : undefined);
|
|
865
|
+
earlyStreamRecoveryInstruction = buildRunCommittedTodoEvidenceInstruction(options.primaryTools, planToolResult?.kind === "tool-result" ? planToolResult.output : undefined);
|
|
686
866
|
earlyStreamRecoverySuppressInitialPlan = true;
|
|
687
867
|
break;
|
|
688
868
|
}
|
|
@@ -721,6 +901,18 @@ export async function* streamRuntimeExecution(options) {
|
|
|
721
901
|
}
|
|
722
902
|
yield chunk;
|
|
723
903
|
}
|
|
904
|
+
const eventContainsPlanToolResult = projectedChunks.some((chunk) => chunk.kind === "tool-result" && isPlanToolName(chunk.toolName) && chunk.isError !== true);
|
|
905
|
+
if (requiresPlanEvidence(options.binding)
|
|
906
|
+
&& eventContainsPlanToolResult
|
|
907
|
+
&& (hadPriorPlanToolResult
|
|
908
|
+
|| projectedChunks.some((chunk) => isCompletedPlanToolResultChunk(chunk)))
|
|
909
|
+
&& !sawSuccessfulNonTodoToolResult) {
|
|
910
|
+
const planToolResult = projectedChunks.find((chunk) => chunk.kind === "tool-result" && isPlanToolName(chunk.toolName) && chunk.isError !== true);
|
|
911
|
+
earlyStreamExternalPlanEvidenceTools = resolveCommittedPlanEvidenceTools(options.primaryTools, planToolResult?.kind === "tool-result" ? planToolResult.output : undefined);
|
|
912
|
+
earlyStreamRecoveryInstruction = buildRunCommittedTodoEvidenceInstruction(options.primaryTools, planToolResult?.kind === "tool-result" ? planToolResult.output : undefined);
|
|
913
|
+
earlyStreamRecoverySuppressInitialPlan = true;
|
|
914
|
+
break;
|
|
915
|
+
}
|
|
724
916
|
if (requiresPlanEvidence(options.binding) && sawCompletedPlanToolResult && sawSuccessfulNonTodoToolResult) {
|
|
725
917
|
if (hasUsefulVisibleSynthesis(projectionState.emittedOutput)) {
|
|
726
918
|
if (deferredStreamContent.length > 0) {
|
|
@@ -794,7 +986,13 @@ export async function* streamRuntimeExecution(options) {
|
|
|
794
986
|
}
|
|
795
987
|
if (earlyStreamRecoveryInstruction) {
|
|
796
988
|
const earlyRecoveryRuntimeOptions = earlyStreamRecoverySuppressInitialPlan
|
|
797
|
-
?
|
|
989
|
+
? {
|
|
990
|
+
...withSuppressedInitialRequiredPlanInstruction(options.runtimeOptions),
|
|
991
|
+
externalPlanEvidence: true,
|
|
992
|
+
...(earlyStreamExternalPlanEvidenceTools && earlyStreamExternalPlanEvidenceTools.length > 0
|
|
993
|
+
? { externalPlanEvidenceTools: earlyStreamExternalPlanEvidenceTools }
|
|
994
|
+
: {}),
|
|
995
|
+
}
|
|
798
996
|
: options.runtimeOptions;
|
|
799
997
|
const recovered = await options.invoke(options.applyToolRecoveryInstruction(options.binding, earlyStreamRecoveryInstruction), options.input, options.sessionId, options.runtimeOptions.requestId ?? options.sessionId, undefined, options.history, earlyRecoveryRuntimeOptions);
|
|
800
998
|
const recoveredToolResults = Array.isArray(recovered.metadata?.executedToolResults)
|
|
@@ -16,10 +16,20 @@ type LocalToolInvocationParams = {
|
|
|
16
16
|
callRuntimeWithToolParseRecovery: (request: unknown) => Promise<Record<string, unknown>>;
|
|
17
17
|
toolRuntimeContext?: Record<string, unknown>;
|
|
18
18
|
externalPlanEvidence?: boolean;
|
|
19
|
+
externalPlanEvidenceTool?: {
|
|
20
|
+
name: string;
|
|
21
|
+
args?: Record<string, unknown>;
|
|
22
|
+
id?: string;
|
|
23
|
+
};
|
|
24
|
+
externalPlanEvidenceTools?: Array<{
|
|
25
|
+
name: string;
|
|
26
|
+
args?: Record<string, unknown>;
|
|
27
|
+
id?: string;
|
|
28
|
+
}>;
|
|
19
29
|
};
|
|
20
30
|
type LocalToolInvocationResult = {
|
|
21
31
|
result: Record<string, unknown>;
|
|
22
32
|
executedToolResults: ExecutedToolResult[];
|
|
23
33
|
};
|
|
24
|
-
export declare function runLocalToolInvocationLoop({ binding, request, primaryTools, toolNameMapping, executableTools, builtinExecutableTools, callRuntimeWithToolParseRecovery, toolRuntimeContext, externalPlanEvidence, }: LocalToolInvocationParams): Promise<LocalToolInvocationResult>;
|
|
34
|
+
export declare function runLocalToolInvocationLoop({ binding, request, primaryTools, toolNameMapping, executableTools, builtinExecutableTools, callRuntimeWithToolParseRecovery, toolRuntimeContext, externalPlanEvidence, externalPlanEvidenceTool, externalPlanEvidenceTools, }: LocalToolInvocationParams): Promise<LocalToolInvocationResult>;
|
|
25
35
|
export {};
|