@botbotgo/agent-harness 0.0.470 → 0.0.472

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.
@@ -1,2 +1,2 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.470";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.472";
2
2
  export declare const AGENT_HARNESS_RELEASE_DATE = "2026-05-04";
@@ -1,2 +1,2 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.470";
1
+ export const AGENT_HARNESS_VERSION = "0.0.472";
2
2
  export const AGENT_HARNESS_RELEASE_DATE = "2026-05-04";
@@ -16,16 +16,6 @@ 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
- }>;
29
19
  };
30
20
  resolveTools: (tools: CompiledTool[], binding?: CompiledAgentBinding) => unknown[];
31
21
  getToolNameMapping: (binding: CompiledAgentBinding) => ToolNameMapping;
@@ -329,8 +329,6 @@ export async function executeRequestInvocation(options) {
329
329
  callRuntimeWithToolParseRecovery: options.callRuntimeWithToolParseRecovery,
330
330
  toolRuntimeContext: invokeOptions.toolRuntimeContext,
331
331
  externalPlanEvidence: invokeOptions.externalPlanEvidence,
332
- externalPlanEvidenceTool: invokeOptions.externalPlanEvidenceTool,
333
- externalPlanEvidenceTools: invokeOptions.externalPlanEvidenceTools,
334
332
  });
335
333
  let localOrUpstreamInvocation = await invokeOnce(request);
336
334
  if (options.resumePayload === undefined
@@ -18,16 +18,6 @@ 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
- }>;
31
21
  }): Promise<{
32
22
  result: Record<string, unknown>;
33
23
  executedToolResults: ExecutedToolResult[];
@@ -16,7 +16,5 @@ 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,
21
19
  });
22
20
  }
@@ -23,16 +23,6 @@ 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
- }>;
36
26
  };
37
27
  primaryTools: CompiledTool[];
38
28
  toolNameMapping: ToolNameMapping;
@@ -61,16 +51,6 @@ export declare function streamRuntimeExecution(options: {
61
51
  toolRuntimeContext?: Record<string, unknown>;
62
52
  suppressInitialRequiredPlanInstruction?: boolean;
63
53
  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
- }>;
74
54
  }) => Promise<{
75
55
  output: string;
76
56
  metadata?: Record<string, unknown>;
@@ -45,12 +45,6 @@ function buildRunEvidenceAfterPlanInstruction(primaryTools) {
45
45
  `Available non-planning tool names: ${toolNames.join(", ")}.`,
46
46
  ].join("\n");
47
47
  }
48
- function resolveSingleConfiguredPlanEvidenceTool(primaryTools) {
49
- const toolNames = primaryTools
50
- .map(readPrimaryToolName)
51
- .filter((name) => name.length > 0 && !isPlanToolName(name));
52
- return toolNames.length === 1 ? [{ name: toolNames[0], args: {}, id: "stream-single-plan-evidence-tool-1" }] : [];
53
- }
54
48
  const INITIAL_REQUIRED_PLAN_INSTRUCTION = [
55
49
  "This agent has a required visible planning contract.",
56
50
  "Your first action for this request must be write_todos with concrete task steps and statuses.",
@@ -721,7 +715,6 @@ export async function* streamRuntimeExecution(options) {
721
715
  let sawCompletedPlanToolResult = false;
722
716
  let sawSuccessfulNonTodoToolResult = false;
723
717
  let earlyStreamRecoveryInstruction = null;
724
- let earlyStreamExternalPlanEvidenceTools;
725
718
  let earlyStreamRecoverySuppressInitialPlan = false;
726
719
  let completedPlanToolResultCount = 0;
727
720
  for await (const event of options.iterateWithTimeout(events, options.streamIdleTimeoutMs, "agent streamEvents", options.streamDeadlineAt, options.invokeTimeoutMs)) {
@@ -751,7 +744,6 @@ export async function* streamRuntimeExecution(options) {
751
744
  && hadPriorPlanToolResult
752
745
  && projectedChunks.some((chunk) => chunk.kind === "tool-result" && isPlanToolName(chunk.toolName));
753
746
  if (repeatedPlanToolResultBeforeEvidence) {
754
- earlyStreamExternalPlanEvidenceTools = resolveSingleConfiguredPlanEvidenceTool(options.primaryTools);
755
747
  earlyStreamRecoveryInstruction = buildRunEvidenceAfterPlanInstruction(options.primaryTools);
756
748
  earlyStreamRecoverySuppressInitialPlan = true;
757
749
  break;
@@ -797,7 +789,6 @@ export async function* streamRuntimeExecution(options) {
797
789
  && (hadPriorPlanToolResult
798
790
  || projectedChunks.some((chunk) => isCompletedPlanToolResultChunk(chunk)))
799
791
  && !sawSuccessfulNonTodoToolResult) {
800
- earlyStreamExternalPlanEvidenceTools = resolveSingleConfiguredPlanEvidenceTool(options.primaryTools);
801
792
  earlyStreamRecoveryInstruction = buildRunEvidenceAfterPlanInstruction(options.primaryTools);
802
793
  earlyStreamRecoverySuppressInitialPlan = true;
803
794
  break;
@@ -855,9 +846,6 @@ export async function* streamRuntimeExecution(options) {
855
846
  ?? terminalPrematurePlanCloseRecoveryInstruction
856
847
  ?? terminalDelegationOnlyRecoveryInstruction;
857
848
  earlyStreamRecoverySuppressInitialPlan = terminalPrematurePlanCloseRecoveryInstruction !== null;
858
- if (terminalPrematurePlanCloseRecoveryInstruction) {
859
- earlyStreamExternalPlanEvidenceTools = resolveSingleConfiguredPlanEvidenceTool(options.primaryTools);
860
- }
861
849
  break;
862
850
  }
863
851
  if (requiresPlanEvidence(options.binding) && hasCompletedPlanWithEvidence(terminalExecutionEvidence)) {
@@ -892,9 +880,6 @@ export async function* streamRuntimeExecution(options) {
892
880
  ? {
893
881
  ...withNonPlanningEvidenceToolPolicy(withSuppressedInitialRequiredPlanInstruction(options.runtimeOptions)),
894
882
  externalPlanEvidence: true,
895
- ...(earlyStreamExternalPlanEvidenceTools && earlyStreamExternalPlanEvidenceTools.length > 0
896
- ? { externalPlanEvidenceTools: earlyStreamExternalPlanEvidenceTools }
897
- : {}),
898
883
  }
899
884
  : options.runtimeOptions;
900
885
  const recovered = await options.invoke(options.applyToolRecoveryInstruction(options.binding, earlyStreamRecoveryInstruction), options.input, options.sessionId, options.runtimeOptions.requestId ?? options.sessionId, undefined, options.history, earlyRecoveryRuntimeOptions);
@@ -16,20 +16,10 @@ 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
- }>;
29
19
  };
30
20
  type LocalToolInvocationResult = {
31
21
  result: Record<string, unknown>;
32
22
  executedToolResults: ExecutedToolResult[];
33
23
  };
34
- export declare function runLocalToolInvocationLoop({ binding, request, primaryTools, toolNameMapping, executableTools, builtinExecutableTools, callRuntimeWithToolParseRecovery, toolRuntimeContext, externalPlanEvidence, externalPlanEvidenceTool, externalPlanEvidenceTools, }: LocalToolInvocationParams): Promise<LocalToolInvocationResult>;
24
+ export declare function runLocalToolInvocationLoop({ binding, request, primaryTools, toolNameMapping, executableTools, builtinExecutableTools, callRuntimeWithToolParseRecovery, toolRuntimeContext, externalPlanEvidence, }: LocalToolInvocationParams): Promise<LocalToolInvocationResult>;
35
25
  export {};
@@ -73,19 +73,6 @@ function buildBootstrapPlanToolResult(primaryTools) {
73
73
  })],
74
74
  };
75
75
  }
76
- function buildExternalPlanEvidenceToolResult(tools) {
77
- return {
78
- messages: [{
79
- content: "",
80
- tool_calls: tools.map((tool, index) => ({
81
- id: tool.id ?? `external-plan-evidence-${index + 1}-${Math.random().toString(36).slice(2, 10)}`,
82
- name: tool.name,
83
- args: tool.args ?? {},
84
- type: "tool_call",
85
- })),
86
- }],
87
- };
88
- }
89
76
  function stripSatisfiedInitialPlanInstruction(messages) {
90
77
  return messages.filter((message) => {
91
78
  const typed = typeof message === "object" && message !== null ? message : {};
@@ -204,6 +191,78 @@ function buildDeterministicFinalFromToolEvidence(executedToolResults) {
204
191
  function hasPlanStateEvidence(executedToolResults, externalPlanEvidence = false) {
205
192
  return externalPlanEvidence || executedToolResults.some((item) => isPlanToolName(item.toolName) || readPlanStateSummary(item.output) !== null);
206
193
  }
194
+ function isNonFunctionObject(value) {
195
+ return Object(value) === value && typeof value !== "function";
196
+ }
197
+ function readSerializedMessageType(value) {
198
+ if (!isNonFunctionObject(value)) {
199
+ return "";
200
+ }
201
+ const id = value.id;
202
+ if (!Array.isArray(id)) {
203
+ return "";
204
+ }
205
+ return id.map((item) => typeof item === "string" ? item : "").filter(Boolean).join(".");
206
+ }
207
+ function readUpstreamToolMessage(value) {
208
+ if (!isNonFunctionObject(value)) {
209
+ return null;
210
+ }
211
+ const typed = value;
212
+ const kwargs = isNonFunctionObject(typed.kwargs) ? typed.kwargs : {};
213
+ const lcKwargs = isNonFunctionObject(typed.lc_kwargs) ? typed.lc_kwargs : {};
214
+ const messageType = readSerializedMessageType(value);
215
+ const isToolMessage = typed.role === "tool"
216
+ || typed.type === "tool"
217
+ || messageType.endsWith("ToolMessage")
218
+ || typeof typed.tool_call_id === "string"
219
+ || typeof kwargs.tool_call_id === "string"
220
+ || typeof lcKwargs.tool_call_id === "string";
221
+ if (!isToolMessage) {
222
+ return null;
223
+ }
224
+ const toolNameCandidate = kwargs.name ?? lcKwargs.name ?? typed.name;
225
+ const toolName = typeof toolNameCandidate === "string" ? toolNameCandidate.trim() : "";
226
+ if (!toolName) {
227
+ return null;
228
+ }
229
+ const output = kwargs.content ?? lcKwargs.content ?? typed.content ?? "";
230
+ const status = kwargs.status ?? lcKwargs.status ?? typed.status;
231
+ return {
232
+ toolName,
233
+ output,
234
+ ...(status === "error" ? { isError: true } : {}),
235
+ };
236
+ }
237
+ function extractUpstreamToolMessages(value, seen = new Set()) {
238
+ if (typeof value !== "object" || value === null || seen.has(value)) {
239
+ return [];
240
+ }
241
+ seen.add(value);
242
+ if (Array.isArray(value)) {
243
+ return value.flatMap((item) => extractUpstreamToolMessages(item, seen));
244
+ }
245
+ const direct = readUpstreamToolMessage(value);
246
+ if (direct) {
247
+ return [direct];
248
+ }
249
+ const typed = value;
250
+ return [
251
+ ...extractUpstreamToolMessages(typed.messages, seen),
252
+ ...extractUpstreamToolMessages(typed.output, seen),
253
+ ];
254
+ }
255
+ function mergeUpstreamToolMessages(executedToolResults, result) {
256
+ const existing = new Set(executedToolResults.map((item) => `${item.toolName}\u0000${item.isError === true ? "error" : "ok"}\u0000${stringifyToolOutput(item.output)}`));
257
+ for (const upstream of extractUpstreamToolMessages(result)) {
258
+ const key = `${upstream.toolName}\u0000${upstream.isError === true ? "error" : "ok"}\u0000${stringifyToolOutput(upstream.output)}`;
259
+ if (existing.has(key)) {
260
+ continue;
261
+ }
262
+ existing.add(key);
263
+ executedToolResults.push(upstream);
264
+ }
265
+ }
207
266
  function latestToolErrorRecoveryInstruction(executedToolResults) {
208
267
  const latest = executedToolResults.at(-1);
209
268
  if (!latest || latest.isError !== true) {
@@ -285,7 +344,7 @@ function summarizeResultMessages(result) {
285
344
  };
286
345
  });
287
346
  }
288
- export async function runLocalToolInvocationLoop({ binding, request, primaryTools, toolNameMapping, executableTools, builtinExecutableTools, callRuntimeWithToolParseRecovery, toolRuntimeContext, externalPlanEvidence, externalPlanEvidenceTool, externalPlanEvidenceTools, }) {
347
+ export async function runLocalToolInvocationLoop({ binding, request, primaryTools, toolNameMapping, executableTools, builtinExecutableTools, callRuntimeWithToolParseRecovery, toolRuntimeContext, externalPlanEvidence, }) {
289
348
  const executedToolResults = [];
290
349
  let activeRequest = request;
291
350
  let currentMessages = Array.isArray(activeRequest.messages) ? [...activeRequest.messages] : [];
@@ -307,39 +366,11 @@ export async function runLocalToolInvocationLoop({ binding, request, primaryTool
307
366
  }
308
367
  for (let iteration = 0; iteration < maxToolIterations; iteration += 1) {
309
368
  const isFinalIteration = iteration + 1 === maxToolIterations;
310
- const externalPlanEvidenceToolCalls = externalPlanEvidenceTools && externalPlanEvidenceTools.length > 0
311
- ? externalPlanEvidenceTools
312
- : externalPlanEvidenceTool
313
- ? [externalPlanEvidenceTool]
314
- : [];
315
- const shouldRunExternalPlanEvidenceTool = pendingResult === undefined
316
- && requiresPlanEvidence(binding)
317
- && externalPlanEvidence === true
318
- && externalPlanEvidenceToolCalls.length > 0
319
- && !hasNonTodoToolEvidence(executedToolResults);
320
- const usedExternalPlanEvidenceToolThisIteration = shouldRunExternalPlanEvidenceTool;
321
369
  result = pendingResult
322
- ?? (shouldRunExternalPlanEvidenceTool
323
- ? buildExternalPlanEvidenceToolResult(externalPlanEvidenceToolCalls)
324
- : await callRuntimeWithToolParseRecovery(activeRequest));
370
+ ?? await callRuntimeWithToolParseRecovery(activeRequest);
325
371
  pendingResult = undefined;
372
+ mergeUpstreamToolMessages(executedToolResults, result);
326
373
  let toolCalls = extractToolCallsFromResult(result);
327
- const structuredExternalPlanEvidenceTool = requiresPlanEvidence(binding)
328
- && hasPlanStateEvidence(executedToolResults, externalPlanEvidence)
329
- && !hasNonTodoToolEvidence(executedToolResults)
330
- && (externalPlanEvidenceTool !== undefined || !hasIncompleteExecutedPlan(executedToolResults, externalPlanEvidence))
331
- && (toolCalls.length === 0 || toolCalls.every((toolCall) => isPlanToolName(toolCall.name)))
332
- ? externalPlanEvidenceTool
333
- ? {
334
- name: externalPlanEvidenceTool.name,
335
- args: externalPlanEvidenceTool.args ?? {},
336
- id: externalPlanEvidenceTool.id ?? "external-plan-evidence-tool",
337
- }
338
- : null
339
- : null;
340
- if (structuredExternalPlanEvidenceTool) {
341
- toolCalls = [structuredExternalPlanEvidenceTool];
342
- }
343
374
  if (toolCalls.length === 0) {
344
375
  const terminalText = sanitizeVisibleText(extractVisibleOutput(result) || "");
345
376
  const hasIncompletePlanState = hasIncompleteExecutedPlan(executedToolResults, externalPlanEvidence);
@@ -496,8 +527,7 @@ export async function runLocalToolInvocationLoop({ binding, request, primaryTool
496
527
  repeatedRecoveryWithoutProgress = 0;
497
528
  repeatedPlanOnlyAfterPlan = 0;
498
529
  repeatedInvalidExternalPlanEvidenceSelection = 0;
499
- const canReplayToolCalls = usedExternalPlanEvidenceToolThisIteration
500
- || canReplayToolCallsLocally(binding, toolCalls, primaryTools, toolNameMapping, executableTools, builtinExecutableTools);
530
+ const canReplayToolCalls = canReplayToolCallsLocally(binding, toolCalls, primaryTools, toolNameMapping, executableTools, builtinExecutableTools);
501
531
  debugLocalToolReplay({
502
532
  toolCalls,
503
533
  result,
@@ -583,12 +613,6 @@ export async function runLocalToolInvocationLoop({ binding, request, primaryTool
583
613
  content: stringifyToolOutput(safeToolResult),
584
614
  }));
585
615
  }
586
- if (usedExternalPlanEvidenceToolThisIteration && hasNonTodoToolEvidence(executedToolResults)) {
587
- return {
588
- result: buildDeterministicFinalFromToolEvidence(executedToolResults),
589
- executedToolResults,
590
- };
591
- }
592
616
  if (requiresPlanEvidence(binding)
593
617
  && toolCalls.length > 0
594
618
  && toolCalls.every((toolCall) => isPlanToolName(toolCall.name))
@@ -1,5 +1,5 @@
1
1
  import { salvageToolArgs } from "../../parsing/output-parsing.js";
2
- import { normalizeKnownToolArgs, salvageJsonToolCalls, salvageResultLabeledToolCall } from "../../parsing/output-tool-args.js";
2
+ import { normalizeKnownToolArgs, salvageJsonToolCalls, salvageMarkdownNamedToolCall, salvageResultLabeledToolCall } from "../../parsing/output-tool-args.js";
3
3
  import { isRecord } from "../../../utils/object.js";
4
4
  import { extractExplicitResourceReferences, hasExplicitResourceReference } from "../../harness/system/runtime-memory-policy.js";
5
5
  import { readCapturedPromptedJsonToolCalls } from "../model/prompted-json-tool-call-capture.js";
@@ -463,6 +463,15 @@ export function extractToolCallsFromResult(result) {
463
463
  rawArgsInput: content,
464
464
  }];
465
465
  }
466
+ const markdownNamedToolCall = salvageMarkdownNamedToolCall(content);
467
+ if (markdownNamedToolCall) {
468
+ return [{
469
+ id: "salvaged-markdown-label-1",
470
+ name: markdownNamedToolCall.name,
471
+ args: markdownNamedToolCall.args,
472
+ rawArgsInput: content,
473
+ }];
474
+ }
466
475
  const salvaged = salvageJsonToolCalls(content);
467
476
  if (salvaged.length > 0) {
468
477
  return salvaged.map((toolCall, salvageIndex) => ({
@@ -62,11 +62,6 @@ export declare class AgentRuntimeAdapter {
62
62
  toolRuntimeContext?: Record<string, unknown>;
63
63
  suppressInitialRequiredPlanInstruction?: boolean;
64
64
  externalPlanEvidence?: boolean;
65
- externalPlanEvidenceTools?: Array<{
66
- name: string;
67
- args?: Record<string, unknown>;
68
- id?: string;
69
- }>;
70
65
  }): Promise<RequestResult>;
71
66
  private tryDelegateWithCompactRouter;
72
67
  private buildCompactDelegationReport;
@@ -82,11 +77,6 @@ export declare class AgentRuntimeAdapter {
82
77
  toolRuntimeContext?: Record<string, unknown>;
83
78
  suppressInitialRequiredPlanInstruction?: boolean;
84
79
  externalPlanEvidence?: boolean;
85
- externalPlanEvidenceTools?: Array<{
86
- name: string;
87
- args?: Record<string, unknown>;
88
- id?: string;
89
- }>;
90
80
  }): AsyncGenerator<RuntimeStreamChunk | string>;
91
81
  }
92
82
  export { AgentRuntimeAdapter as RuntimeAdapter, AGENT_INTERRUPT_SENTINEL_PREFIX, AGENT_INTERRUPT_SENTINEL_PREFIX as INTERRUPT_SENTINEL_PREFIX, buildDeepAgentCreateParams, buildLangChainCreateParams, DEFAULT_DEEPAGENT_RECURSION_LIMIT, materializeModelExposedBuiltinMiddlewareTools, resolveLangChainInvocationConfig, resolveRunnableCheckpointer, resolveRunnableInterruptOn, RuntimeOperationTimeoutError, };
@@ -10,7 +10,6 @@ import { resolveDeepAgentSkillSourcePaths, resolveDeepAgentSkillSourceRootPaths,
10
10
  import { buildToolNameMapping, } from "./adapter/tool/tool-name-mapping.js";
11
11
  import { PROMPTED_JSON_TOOL_POLICY_KEY } from "./adapter/model/prompted-json-tool-policy.js";
12
12
  import { executeRequestInvocation } from "./adapter/flow/invocation-flow.js";
13
- import { extractExplicitResourceReferences } from "./harness/system/runtime-memory-policy.js";
14
13
  import { streamRuntimeExecution } from "./adapter/flow/stream-runtime.js";
15
14
  import { resolveDeterministicFinalOutput } from "./adapter/invocation-result.js";
16
15
  import { applyToolRecoveryInstruction as applyToolRecoveryInstructionHelper, applyStrictToolJsonInstruction as applyStrictToolJsonInstructionHelper, callRuntimeWithToolParseRecovery as callRuntimeWithToolParseRecoveryHelper, createModelFallbackRunnable as createModelFallbackRunnableHelper, invokeWithProviderRetry as invokeWithProviderRetryHelper, iterateWithTimeout as iterateWithTimeoutHelper, materializeModelStream as materializeModelStreamHelper, RuntimeOperationTimeoutError, withRuntimeTimeout, } from "./adapter/runtime-shell.js";
@@ -442,73 +441,17 @@ const DELEGATED_PLAN_EVIDENCE_FINAL_RETRY_INSTRUCTION = [
442
441
  "The next runtime event must be one available non-planning evidence tool call.",
443
442
  "After that tool returns, update or close the TODO board and provide the final answer required by the agent response format.",
444
443
  ].join("\n");
445
- function buildDelegatedPlanEvidenceRecoveryOptions(binding, baseOptions, requestText = "") {
446
- const nonPlanningTools = binding
447
- ? getBindingPrimaryTools(binding).filter((tool) => !isPlanToolName(tool.name))
448
- : [];
449
- const configuredRecoveryTool = resolveConfiguredRecoveryEvidenceTool(binding, nonPlanningTools, requestText);
450
- const externalPlanEvidenceTools = configuredRecoveryTool
451
- ? [configuredRecoveryTool]
452
- : nonPlanningTools.length === 1
453
- ? [{
454
- name: nonPlanningTools[0].name,
455
- args: buildExternalPlanEvidenceArgs(nonPlanningTools[0], requestText),
456
- id: "delegated-plan-evidence-tool-1",
457
- }]
458
- : undefined;
444
+ function buildDelegatedPlanEvidenceRecoveryOptions(_binding, baseOptions, _requestText = "") {
459
445
  return {
460
446
  ...baseOptions,
461
447
  suppressInitialRequiredPlanInstruction: true,
462
448
  externalPlanEvidence: true,
463
- ...(externalPlanEvidenceTools ? { externalPlanEvidenceTools } : {}),
464
449
  state: {
465
450
  ...(typeof baseOptions.state === "object" && baseOptions.state !== null ? baseOptions.state : {}),
466
451
  [PROMPTED_JSON_TOOL_POLICY_KEY]: "nonPlanningEvidence",
467
452
  },
468
453
  };
469
454
  }
470
- function resolveConfiguredRecoveryEvidenceTool(binding, nonPlanningTools, requestText) {
471
- const configured = binding?.harnessRuntime.executionContract?.recoveryEvidenceTool;
472
- const configuredName = typeof configured?.name === "string" ? configured.name.trim() : "";
473
- if (!configuredName) {
474
- return undefined;
475
- }
476
- const tool = nonPlanningTools.find((candidate) => candidate.name === configuredName);
477
- if (!tool) {
478
- return undefined;
479
- }
480
- return {
481
- name: tool.name,
482
- args: configured?.args ?? buildExternalPlanEvidenceArgs(tool, requestText),
483
- id: "delegated-plan-evidence-tool-1",
484
- };
485
- }
486
- function buildExternalPlanEvidenceArgs(tool, requestText) {
487
- const properties = tool?.modelSchema && typeof tool.modelSchema === "object"
488
- && tool.modelSchema !== null
489
- && typeof tool.modelSchema.properties === "object"
490
- && tool.modelSchema.properties !== null
491
- ? tool.modelSchema.properties
492
- : {};
493
- const refs = extractExplicitResourceReferences(requestText);
494
- const args = {};
495
- const firstUrl = refs.find((ref) => /^https?:\/\//iu.test(ref));
496
- if ("url" in properties && firstUrl) {
497
- args.url = firstUrl;
498
- }
499
- if ("sources" in properties && refs.length > 0) {
500
- args.sources = refs.map((ref) => /^https?:\/\//iu.test(ref)
501
- ? { type: "url", url: ref }
502
- : { type: "text", text: ref });
503
- }
504
- if ("question" in properties) {
505
- args.question = requestText;
506
- }
507
- else if ("query" in properties) {
508
- args.query = requestText;
509
- }
510
- return args;
511
- }
512
455
  function looksLikeRawCommandTranscript(value) {
513
456
  const normalized = value.trim();
514
457
  return /^(?:stdout|stderr)\s*:/iu.test(normalized)
@@ -1984,7 +1927,6 @@ export class AgentRuntimeAdapter {
1984
1927
  profiling: options.profiling,
1985
1928
  suppressInitialRequiredPlanInstruction: delegatedOptions.suppressInitialRequiredPlanInstruction,
1986
1929
  externalPlanEvidence: delegatedOptions.externalPlanEvidence,
1987
- externalPlanEvidenceTools: delegatedOptions.externalPlanEvidenceTools,
1988
1930
  })) {
1989
1931
  if (typeof chunk === "string") {
1990
1932
  output += chunk;
@@ -2209,7 +2151,6 @@ export class AgentRuntimeAdapter {
2209
2151
  profiling: options.profiling,
2210
2152
  suppressInitialRequiredPlanInstruction: delegatedOptions.suppressInitialRequiredPlanInstruction,
2211
2153
  externalPlanEvidence: delegatedOptions.externalPlanEvidence,
2212
- externalPlanEvidenceTools: delegatedOptions.externalPlanEvidenceTools,
2213
2154
  })) {
2214
2155
  if (typeof chunk === "string") {
2215
2156
  output += chunk;
@@ -11,6 +11,10 @@ export declare function salvageResultLabeledToolCall(value: unknown): {
11
11
  name: string;
12
12
  args: Record<string, unknown>;
13
13
  } | null;
14
+ export declare function salvageMarkdownNamedToolCall(value: unknown): {
15
+ name: string;
16
+ args: Record<string, unknown>;
17
+ } | null;
14
18
  export declare function salvageToolArgs(value: unknown): Record<string, unknown> | null;
15
19
  export declare function salvageJsonToolCalls(value: unknown): Array<{
16
20
  name: string;
@@ -195,6 +195,28 @@ export function salvageResultLabeledToolCall(value) {
195
195
  const args = salvageToolArgs(lines.slice(1).join("\n")) ?? {};
196
196
  return { name: match[1], args: normalizeKnownToolArgs(match[1], args) };
197
197
  }
198
+ export function salvageMarkdownNamedToolCall(value) {
199
+ if (typeof value !== "string") {
200
+ return null;
201
+ }
202
+ const lines = value
203
+ .split("\n")
204
+ .map((line) => line.trim())
205
+ .filter(Boolean);
206
+ if (lines.length < 2) {
207
+ return null;
208
+ }
209
+ const label = lines[0]?.replace(/[*`#]/gu, "").trim() ?? "";
210
+ if (!isToolName(label) || ["json", "javascript", "typescript", "python", "yaml", "text"].includes(label.toLowerCase())) {
211
+ return null;
212
+ }
213
+ const rest = lines.slice(1).join("\n").trim();
214
+ const args = salvageToolArgs(rest);
215
+ if (!args) {
216
+ return null;
217
+ }
218
+ return { name: label, args: normalizeKnownToolArgs(label, args) };
219
+ }
198
220
  function extractBalancedJsonValue(value, openChar, closeChar) {
199
221
  const start = value.indexOf(openChar);
200
222
  if (start < 0)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.470",
3
+ "version": "0.0.472",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1 +0,0 @@
1
- When first calling write_todos, use descriptive task content for each todo item. Do not use placeholders like '1', '2', '3', 'step 1', or 'todo 1'. Describe the real step, for example 'Create tmp-counter.txt' or 'Append digit 2 and read the file'.