@botbotgo/agent-harness 0.0.373 → 0.0.374

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.
@@ -16,21 +16,18 @@ export function renderChatRequestRunning(input) {
16
16
  return `\n${parts.join(" ")}\n`;
17
17
  }
18
18
  export function summarizeChatToolResult(output, isError) {
19
- if (!isError) {
20
- return "completed";
21
- }
22
- return summarizeChatToolError(output);
19
+ return isError ? summarizeChatToolOutput(output, "failed") : summarizeChatToolOutput(output, "completed");
23
20
  }
24
- function summarizeChatToolError(output) {
21
+ function summarizeChatToolOutput(output, fallback) {
25
22
  if (typeof output === "string") {
26
23
  const trimmed = output.trim();
27
- return trimmed.length > 0 ? truncateChatToolPreview(trimmed, 240) : "failed";
24
+ return trimmed.length > 0 ? truncateChatToolPreview(trimmed, 240) : fallback;
28
25
  }
29
26
  if (typeof output === "number" || typeof output === "boolean") {
30
27
  return String(output);
31
28
  }
32
29
  if (!output || typeof output !== "object") {
33
- return "failed";
30
+ return fallback;
34
31
  }
35
32
  const typed = output;
36
33
  const content = extractChatToolTextContent(output);
@@ -1,2 +1,2 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.373";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.374";
2
2
  export declare const AGENT_HARNESS_RELEASE_DATE = "2026-04-30";
@@ -1,2 +1,2 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.373";
1
+ export const AGENT_HARNESS_VERSION = "0.0.374";
2
2
  export const AGENT_HARNESS_RELEASE_DATE = "2026-04-30";
@@ -28,18 +28,19 @@ export function buildBindingToolExecutionContext(input) {
28
28
  export async function resolveLangChainStreamContext(input) {
29
29
  const primaryTools = getBindingPrimaryTools(input.binding);
30
30
  const primaryModel = getBindingPrimaryModel(input.binding);
31
- const forceInvokeFallback = isLangChainBinding(input.binding) &&
32
- primaryTools.length > 0 &&
33
- primaryModel?.provider === "openai-compatible";
34
31
  const resolvedLangChainModel = primaryModel
35
32
  ? (await input.resolveModel(primaryModel))
36
33
  : undefined;
37
34
  const resolvedLangChainTools = primaryTools.length > 0 ? input.resolveTools(primaryTools, input.binding) : [];
35
+ const modelSupportsToolBinding = typeof resolvedLangChainModel?.bindTools === "function";
36
+ const forceInvokeFallback = isLangChainBinding(input.binding) &&
37
+ primaryTools.length > 0 &&
38
+ primaryModel?.provider === "openai-compatible";
38
39
  const canUseDirectModelStream = !!resolvedLangChainModel &&
39
- (resolvedLangChainTools.length === 0 || typeof resolvedLangChainModel.bindTools !== "function");
40
+ primaryTools.length === 0;
40
41
  const langChainStreamModel = resolvedLangChainModel && canUseDirectModelStream
41
42
  ? resolvedLangChainModel
42
- : resolvedLangChainModel && typeof resolvedLangChainModel.bindTools === "function" && resolvedLangChainTools.length > 0
43
+ : resolvedLangChainModel && modelSupportsToolBinding && resolvedLangChainTools.length > 0
43
44
  ? resolvedLangChainModel.bindTools(resolvedLangChainTools)
44
45
  : undefined;
45
46
  return {
@@ -7,7 +7,7 @@ import { UPSTREAM_REQUEST_CONFIG_KEY, UPSTREAM_SESSION_CONFIG_KEY } from "../ups
7
7
  import { appendToolRecoveryInstruction, extractVisibleOutput, tryParseJson } from "../../parsing/output-parsing.js";
8
8
  import { salvageJsonToolCalls } from "../../parsing/output-tool-args.js";
9
9
  import { isEmptyFinalAiMessageError } from "../resilience.js";
10
- import { AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, } from "../../prompts/runtime-prompts.js";
10
+ import { AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, WRITE_TODOS_REQUIRED_PLAN_INSTRUCTION, } from "../../prompts/runtime-prompts.js";
11
11
  const CLOSE_REQUIRED_PLAN_RECOVERY_INSTRUCTION = [
12
12
  "The current required todo board still has unfinished work.",
13
13
  "Do not broaden the investigation, restart planning, or ask the user what to do next.",
@@ -352,7 +352,7 @@ export async function executeRequestInvocation(options) {
352
352
  ? result.messages
353
353
  : undefined;
354
354
  const recoveryBase = messages ? { messages } : request;
355
- const recoveredRequest = appendToolRecoveryInstruction(recoveryBase, CLOSE_REQUIRED_PLAN_RECOVERY_INSTRUCTION);
355
+ const recoveredRequest = appendToolRecoveryInstruction(recoveryBase, WRITE_TODOS_REQUIRED_PLAN_INSTRUCTION);
356
356
  const recoveredInvocation = await invokeOnce(recoveredRequest);
357
357
  localOrUpstreamInvocation = recoveredInvocation;
358
358
  result = recoveredInvocation.result;
@@ -1,4 +1,4 @@
1
- import { extractVisibleOutput, isToolCallRecoveryFailure, isRetrySafeInvalidToolSelectionError, resolveMissingPlanRecoveryInstruction, resolveExecutionWithoutToolEvidenceTextInstruction, shouldValidateExecutionWithoutToolEvidence, resolveToolCallRecoveryInstruction, sanitizeVisibleText, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, INVALID_TOOL_SELECTION_RECOVERY_INSTRUCTION, } from "../../parsing/output-parsing.js";
1
+ import { extractVisibleOutput, isToolCallRecoveryFailure, isRetrySafeInvalidToolSelectionError, appendToolRecoveryInstruction, resolveMissingPlanRecoveryInstruction, resolveExecutionWithoutToolEvidenceTextInstruction, shouldValidateExecutionWithoutToolEvidence, resolveToolCallRecoveryInstruction, sanitizeVisibleText, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, INVALID_TOOL_SELECTION_RECOVERY_INSTRUCTION, } from "../../parsing/output-parsing.js";
2
2
  import { DELEGATED_TASK_FAILURE_RECOVERY_INSTRUCTION, DELEGATION_ONLY_RECOVERY_INSTRUCTION, } from "../../prompts/runtime-prompts.js";
3
3
  import { buildInvocationRequest } from "../model/invocation-request.js";
4
4
  import { buildRawModelMessages } from "../model/message-assembly.js";
@@ -19,6 +19,13 @@ const CLOSE_REQUIRED_PLAN_RECOVERY_INSTRUCTION = [
19
19
  "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.",
20
20
  "After that write_todos call, provide the final answer required by the agent response format.",
21
21
  ].join("\n");
22
+ const INITIAL_REQUIRED_PLAN_INSTRUCTION = [
23
+ "This agent has a required visible planning contract.",
24
+ "Your first action for this request must be write_todos with concrete task steps and statuses.",
25
+ "Do not call any domain/evidence tool and do not provide a final answer before the initial write_todos call succeeds.",
26
+ "Do not use placeholders like '1', '2', '3', 'step 1', or generic labels. Each todo must name the concrete work it represents.",
27
+ "After each evidence step, update the todo board. Before the final answer, close every todo as completed or failed.",
28
+ ].join("\n");
22
29
  function toVisibleContent(value) {
23
30
  const extracted = extractVisibleOutput(value);
24
31
  return extracted ? sanitizeVisibleText(extracted) : "";
@@ -231,7 +238,10 @@ function finishProfileStep(input) {
231
238
  });
232
239
  }
233
240
  export async function* streamRuntimeExecution(options) {
234
- const request = buildInvocationRequest(options.binding, options.history, options.input, options.runtimeOptions);
241
+ let request = buildInvocationRequest(options.binding, options.history, options.input, options.runtimeOptions);
242
+ if (requiresPlanEvidence(options.binding)) {
243
+ request = appendToolRecoveryInstruction(request, INITIAL_REQUIRED_PLAN_INSTRUCTION);
244
+ }
235
245
  let emittedUnsafeStreamSideEffects = false;
236
246
  const shouldProfile = options.runtimeOptions.profiling === true;
237
247
  const shouldValidateStreamOutput = shouldValidateExecutionWithoutToolEvidence(request);
@@ -201,6 +201,30 @@ function hasPriorToolResultForToolName(input, toolName) {
201
201
  }
202
202
  return false;
203
203
  }
204
+ function readBoundToolName(tool) {
205
+ return typeof tool === "object" && tool !== null && typeof tool.name === "string"
206
+ ? tool.name.trim()
207
+ : "";
208
+ }
209
+ function isTodoPlanningToolName(name) {
210
+ return name === "write_todos"
211
+ || name === "read_todos"
212
+ || name === "tool_call_write_todos"
213
+ || name === "tool_call_read_todos";
214
+ }
215
+ function shouldLimitPromptedJsonToolsToPlanning(input) {
216
+ const text = stringifyNodeLlamaCppInput(input);
217
+ return text.includes("required visible planning contract")
218
+ && !hasPriorToolResultForToolName(input, "write_todos")
219
+ && !hasPriorToolResultForToolName(input, "tool_call_write_todos");
220
+ }
221
+ function selectPromptedJsonToolsForTurn(input, boundTools) {
222
+ if (!shouldLimitPromptedJsonToolsToPlanning(input)) {
223
+ return boundTools;
224
+ }
225
+ const planningTools = boundTools.filter((tool) => isTodoPlanningToolName(readBoundToolName(tool)));
226
+ return planningTools.length > 0 ? planningTools : boundTools;
227
+ }
204
228
  function normalizeReadFileToolContent(name, content) {
205
229
  if (name !== "read_file") {
206
230
  return content;
@@ -484,8 +508,9 @@ function createPromptedJsonToolBindableModel(model, boundTools = [], options = {
484
508
  }
485
509
  if (prop === "invoke") {
486
510
  return async (input, config) => {
487
- const rawResult = await target.invoke(boundTools.length > 0 ? withPromptedJsonToolPrompt(input, boundTools, options) : input, config);
488
- if (boundTools.length === 0) {
511
+ const effectiveBoundTools = selectPromptedJsonToolsForTurn(input, boundTools);
512
+ const rawResult = await target.invoke(effectiveBoundTools.length > 0 ? withPromptedJsonToolPrompt(input, effectiveBoundTools, options) : input, config);
513
+ if (effectiveBoundTools.length === 0) {
489
514
  return rawResult;
490
515
  }
491
516
  const text = readModelText(rawResult);
@@ -1,5 +1,6 @@
1
1
  import { extractToolFallbackContext, extractVisibleOutput, readTextContent, sanitizeVisibleText } from "../parsing/output-parsing.js";
2
2
  import { salvageFunctionLikeToolCall } from "../parsing/output-tool-args.js";
3
+ import { isLowSignalTodoContent, summarizeBuiltinWriteTodosArgs } from "./runtime-adapter-support.js";
3
4
  import { computeIncrementalOutput, extractInterruptPayload, extractReasoningStreamOutput, sanitizeRetainedUpstreamEvent, extractStateStreamOutput, extractTerminalStreamOutput, extractToolResult, extractVisibleStreamOutput, normalizeTerminalOutputKey, } from "../parsing/stream-event-parsing.js";
4
5
  import { resolveModelFacingToolName } from "./tool/tool-name-mapping.js";
5
6
  export function createStreamEventProjectionState() {
@@ -299,7 +300,17 @@ function extractTodoToolStart(event) {
299
300
  if (!isToolStart || (toolName !== "write_todos" && toolName !== "read_todos")) {
300
301
  return null;
301
302
  }
302
- return { toolName, input: unwrapPossibleToolInput(typed.data?.input) };
303
+ const input = unwrapPossibleToolInput(typed.data?.input);
304
+ if (toolName === "write_todos" && typeof input === "object" && input !== null && !Array.isArray(input)) {
305
+ const summary = summarizeBuiltinWriteTodosArgs(input);
306
+ if (summary.summary.total === 0) {
307
+ throw new Error("Error invoking tool 'write_todos' with kwargs {\"todos\":[]} with error: Error: Initial write_todos call cannot use an empty todo list. Send the concrete task steps with both content and status.");
308
+ }
309
+ if (summary.items.every((item) => isLowSignalTodoContent(item.content))) {
310
+ throw new Error("Error invoking tool 'write_todos' with placeholder todo content with error: Error: Initial write_todos call must use descriptive task content. Do not use placeholder entries like '1', '2', or 'step 1'.");
311
+ }
312
+ }
313
+ return { toolName, input };
303
314
  }
304
315
  export function projectRuntimeStreamEvent(params) {
305
316
  const { event, allowVisibleStreamDeltas, includeStateStreamOutput, rootAgentId, countConfiguredToolsForAgentId, toolNameMapping, primaryTools, state, } = params;
@@ -217,7 +217,7 @@ export function asStructuredExecutableTool(resolvedTool, modelFacingName, descri
217
217
  if (typeof handler !== "function") {
218
218
  return resolvedTool;
219
219
  }
220
- return createLangChainTool(async (input, config) => handler(input, config), {
220
+ return createLangChainTool(async (input, config) => handler.call(resolvedTool, input, config), {
221
221
  name: modelFacingName,
222
222
  description,
223
223
  schema: normalizeModelFacingToolSchema(resolvedTool),
@@ -2,6 +2,8 @@ export type ToolNameMapping = {
2
2
  originalToModelFacing: Map<string, string>;
3
3
  modelFacingToOriginal: Map<string, string>;
4
4
  };
5
+ export declare function stripProviderToolCallPrefix(toolName: string): string | null;
6
+ export declare function createProviderToolCallAliasName(toolName: string): string;
5
7
  export declare function sanitizeToolNameForModel(name: string): string;
6
8
  export declare function buildToolNameMapping(tools: Array<{
7
9
  name: string;
@@ -1,4 +1,17 @@
1
1
  const MODEL_SAFE_TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
2
+ const PROVIDER_TOOL_CALL_PREFIXES = ["tool_call_", "tool_call.", "tool_call-", "tool.call_", "tool.call.", "tool-call-"];
3
+ export function stripProviderToolCallPrefix(toolName) {
4
+ const trimmed = toolName.trim();
5
+ for (const prefix of PROVIDER_TOOL_CALL_PREFIXES) {
6
+ if (trimmed.startsWith(prefix)) {
7
+ return trimmed.substring(prefix.length);
8
+ }
9
+ }
10
+ return null;
11
+ }
12
+ export function createProviderToolCallAliasName(toolName) {
13
+ return `tool_call_${sanitizeToolNameForModel(toolName)}`;
14
+ }
2
15
  export function sanitizeToolNameForModel(name) {
3
16
  const withoutNamespace = name.includes(".") ? name.split(".").at(-1) ?? name : name;
4
17
  const sanitized = withoutNamespace
@@ -59,16 +72,26 @@ export function createModelFacingToolNameLookupCandidates(toolName) {
59
72
  add(stripped);
60
73
  }
61
74
  };
75
+ const addProviderPrefixStripped = (value) => {
76
+ const stripped = stripProviderToolCallPrefix(value);
77
+ if (stripped) {
78
+ add(stripped);
79
+ addSuffixStripped(stripped);
80
+ }
81
+ };
62
82
  add(trimmed);
83
+ addProviderPrefixStripped(trimmed);
63
84
  if (trimmed.startsWith("functions.")) {
64
85
  const stripped = trimmed.substring("functions.".length);
65
86
  add(stripped);
66
87
  addSuffixStripped(stripped);
88
+ addProviderPrefixStripped(stripped);
67
89
  }
68
90
  else if (trimmed.startsWith("function.")) {
69
91
  const stripped = trimmed.substring("function.".length);
70
92
  add(stripped);
71
93
  addSuffixStripped(stripped);
94
+ addProviderPrefixStripped(stripped);
72
95
  }
73
96
  else {
74
97
  addSuffixStripped(trimmed);
@@ -97,5 +120,9 @@ export function resolveModelFacingToolName(toolName, mapping, tools) {
97
120
  if (candidateMatches.length === 1) {
98
121
  return candidateMatches[0].name;
99
122
  }
123
+ const providerPrefixStripped = stripProviderToolCallPrefix(toolName);
124
+ if (providerPrefixStripped) {
125
+ return sanitizeToolNameForModel(providerPrefixStripped);
126
+ }
100
127
  return toolName;
101
128
  }
@@ -13,3 +13,4 @@ export declare function buildExecutableToolMap(input: {
13
13
  toolConfig?: Record<string, unknown>;
14
14
  context?: Record<string, unknown>;
15
15
  }): Map<string, ExecutableTool>;
16
+ export declare function appendProviderToolCallAliasTools(tools: unknown[]): unknown[];
@@ -1,6 +1,6 @@
1
1
  import { instantiateProviderTool } from "./tool/provider-tool.js";
2
2
  import { asStructuredExecutableTool, hasCallableToolHandler, normalizeResolvedToolSchema, wrapResolvedToolWithModelFacingName, } from "./tool/resolved-tool.js";
3
- import { buildToolNameMapping } from "./tool/tool-name-mapping.js";
3
+ import { buildToolNameMapping, createProviderToolCallAliasName } from "./tool/tool-name-mapping.js";
4
4
  import { wrapToolForExecution } from "./tool/tool-hitl.js";
5
5
  export function resolveAdapterTools(input) {
6
6
  const resolved = input.resolveToolValues ? input.resolveToolValues(input.tools.map((tool) => tool.id), input.binding) : [];
@@ -57,3 +57,30 @@ export function buildExecutableToolMap(input) {
57
57
  }
58
58
  return executableTools;
59
59
  }
60
+ function readResolvedToolName(tool) {
61
+ return typeof tool === "object" && tool !== null && typeof tool.name === "string"
62
+ ? tool.name
63
+ : undefined;
64
+ }
65
+ function readResolvedToolDescription(tool) {
66
+ return typeof tool === "object" && tool !== null && typeof tool.description === "string"
67
+ ? tool.description
68
+ : "";
69
+ }
70
+ export function appendProviderToolCallAliasTools(tools) {
71
+ const existingNames = new Set(tools.map(readResolvedToolName).filter((name) => !!name));
72
+ const aliases = [];
73
+ for (const tool of tools) {
74
+ const name = readResolvedToolName(tool);
75
+ if (!name || !hasCallableToolHandler(tool)) {
76
+ continue;
77
+ }
78
+ const aliasName = createProviderToolCallAliasName(name);
79
+ if (existingNames.has(aliasName)) {
80
+ continue;
81
+ }
82
+ existingNames.add(aliasName);
83
+ aliases.push(asStructuredExecutableTool(tool, aliasName, readResolvedToolDescription(tool) || name));
84
+ }
85
+ return [...tools, ...aliases];
86
+ }
@@ -37,6 +37,7 @@ export declare class AgentRuntimeAdapter {
37
37
  private createAssemblyResolvers;
38
38
  private invokeBuiltinTaskTool;
39
39
  private resolveBuiltinMiddlewareTools;
40
+ private materializeProviderAliasBuiltinTools;
40
41
  private materializeAutomaticSummarizationMiddleware;
41
42
  private resolveLangChainRuntimeExtensionMiddleware;
42
43
  private resolveMiddleware;
@@ -16,7 +16,7 @@ import { extractSubagentRequestText, invokeBuiltinTaskTool as invokeBuiltinTaskT
16
16
  import { isEmptyFinalAiMessageError, resolveBindingTimeout, resolveStreamIdleTimeout, } from "./adapter/resilience.js";
17
17
  import { createResolvedModel } from "./adapter/model/model-providers.js";
18
18
  import { renderDirectWorkspaceListing, shouldDirectlyListWorkspaceFiles } from "./adapter/direct-builtin-utility.js";
19
- import { resolveAdapterTools } from "./adapter/tool-resolution.js";
19
+ import { appendProviderToolCallAliasTools, resolveAdapterTools } from "./adapter/tool-resolution.js";
20
20
  import { resolveRuntimeStreamExecutionContext, } from "./adapter/flow/execution-context.js";
21
21
  import { isRetryableProviderError } from "./adapter/resilience.js";
22
22
  import { UPSTREAM_REQUEST_CONFIG_KEY, UPSTREAM_SESSION_CONFIG_KEY } from "./adapter/upstream-configurable-keys.js";
@@ -418,6 +418,12 @@ export class AgentRuntimeAdapter {
418
418
  invokeBuiltinTaskTool: assembly.invokeBuiltinTaskTool,
419
419
  });
420
420
  }
421
+ materializeProviderAliasBuiltinTools(builtinTools) {
422
+ const aliasableTools = ["write_todos", "read_todos", "task"]
423
+ .map((name) => builtinTools.get(name))
424
+ .filter((tool) => tool !== undefined);
425
+ return appendProviderToolCallAliasTools(aliasableTools).slice(aliasableTools.length);
426
+ }
421
427
  async materializeAutomaticSummarizationMiddleware(binding) {
422
428
  const assembly = this.createAssemblyResolvers(binding);
423
429
  return materializeAutomaticSummarizationMiddlewareHelper({
@@ -530,16 +536,18 @@ export class AgentRuntimeAdapter {
530
536
  const interruptOn = resolveRunnableInterruptOn(binding);
531
537
  const resolvedModel = await this.resolveModel(primaryModel);
532
538
  const resolvedTools = this.resolveTools(primaryTools, binding);
533
- const builtinMiddlewareTools = materializeModelExposedBuiltinMiddlewareTools({
534
- builtinTools: await this.resolveBuiltinMiddlewareTools(binding, {
539
+ const builtinExecutableTools = await this.resolveBuiltinMiddlewareTools(binding, {
540
+ sessionId: options.sessionId ?? options.legacySessionId,
541
+ toolRuntimeContext: this.buildFunctionToolRuntimeContext(binding, {
535
542
  sessionId: options.sessionId ?? options.legacySessionId,
536
- toolRuntimeContext: this.buildFunctionToolRuntimeContext(binding, {
537
- sessionId: options.sessionId ?? options.legacySessionId,
538
- }),
539
543
  }),
544
+ });
545
+ const builtinMiddlewareTools = materializeModelExposedBuiltinMiddlewareTools({
546
+ builtinTools: builtinExecutableTools,
540
547
  explicitToolNames: primaryTools.map((tool) => tool.name),
541
548
  modelExposed: getBindingBuiltinToolsConfig(binding)?.modelExposed,
542
549
  });
550
+ const providerAliasBuiltinTools = this.materializeProviderAliasBuiltinTools(builtinExecutableTools);
543
551
  const resolvedMiddleware = await this.resolveMiddleware(binding, interruptOn, { sessionId: options.sessionId ?? options.legacySessionId });
544
552
  const resolvedCheckpointer = resolveRunnableCheckpointer(this.options, binding);
545
553
  const resolvedStore = this.options.storeResolver?.(binding);
@@ -547,10 +555,14 @@ export class AgentRuntimeAdapter {
547
555
  if (resolvedTools.length + builtinMiddlewareTools.length > 0 && typeof model.bindTools !== "function") {
548
556
  throw new Error(`Agent ${binding.agent.id} configures ${resolvedTools.length + builtinMiddlewareTools.length} tool(s), but resolved model ${primaryModel.id} does not support tool binding.`);
549
557
  }
558
+ const modelTools = [
559
+ ...appendProviderToolCallAliasTools([...resolvedTools, ...builtinMiddlewareTools]),
560
+ ...providerAliasBuiltinTools,
561
+ ];
550
562
  return createAgent(buildLangChainCreateParams({
551
563
  binding,
552
564
  resolvedModel: model,
553
- resolvedTools: [...resolvedTools, ...builtinMiddlewareTools],
565
+ resolvedTools: modelTools,
554
566
  resolvedMiddleware,
555
567
  resolvedCheckpointer,
556
568
  resolvedStore,
@@ -576,16 +588,22 @@ export class AgentRuntimeAdapter {
576
588
  }
577
589
  const resolvedModel = await this.resolveModel(primaryModel);
578
590
  const resolvedTools = this.resolveTools(primaryTools, binding);
579
- const builtinMiddlewareTools = materializeModelExposedBuiltinMiddlewareTools({
580
- builtinTools: await this.resolveBuiltinMiddlewareTools(binding, {
591
+ const builtinExecutableTools = await this.resolveBuiltinMiddlewareTools(binding, {
592
+ sessionId: options.sessionId ?? options.legacySessionId,
593
+ toolRuntimeContext: this.buildFunctionToolRuntimeContext(binding, {
581
594
  sessionId: options.sessionId ?? options.legacySessionId,
582
- toolRuntimeContext: this.buildFunctionToolRuntimeContext(binding, {
583
- sessionId: options.sessionId ?? options.legacySessionId,
584
- }),
585
595
  }),
596
+ });
597
+ const builtinMiddlewareTools = materializeModelExposedBuiltinMiddlewareTools({
598
+ builtinTools: builtinExecutableTools,
586
599
  explicitToolNames: primaryTools.map((tool) => tool.name),
587
600
  modelExposed: getBindingBuiltinToolsConfig(binding)?.modelExposed,
588
601
  });
602
+ const providerAliasBuiltinTools = this.materializeProviderAliasBuiltinTools(builtinExecutableTools);
603
+ const modelTools = [
604
+ ...appendProviderToolCallAliasTools([...resolvedTools, ...builtinMiddlewareTools]),
605
+ ...providerAliasBuiltinTools,
606
+ ];
589
607
  const resolvedMiddleware = await this.resolveMiddleware(binding);
590
608
  const resolvedSubagents = await this.resolveDeepAgentSubagents(getBindingDeepAgentSubagents(binding), binding, { sessionId: options.sessionId ?? options.legacySessionId });
591
609
  const resolvedInterruptOn = resolveRunnableInterruptOn(binding);
@@ -607,7 +625,7 @@ export class AgentRuntimeAdapter {
607
625
  if (shouldUseConfigurableDeepAgentAssembly(binding)) {
608
626
  return this.createConfigurableDeepAgentRunnable(binding, {
609
627
  resolvedModel,
610
- resolvedTools: [...resolvedTools, ...builtinMiddlewareTools],
628
+ resolvedTools: modelTools,
611
629
  resolvedMiddleware,
612
630
  resolvedSubagents,
613
631
  resolvedInterruptOn,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.373",
3
+ "version": "0.0.374",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "license": "MIT",
6
6
  "type": "module",