@botbotgo/agent-harness 0.0.372 → 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.
- package/dist/cli/chat-rendering.js +4 -7
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/runtime/adapter/flow/execution-context.js +6 -5
- package/dist/runtime/adapter/flow/invocation-flow.js +2 -2
- package/dist/runtime/adapter/flow/stream-runtime.js +12 -2
- package/dist/runtime/adapter/model/model-providers.js +27 -2
- package/dist/runtime/adapter/stream-event-projection.js +36 -0
- package/dist/runtime/adapter/tool/resolved-tool.js +1 -1
- package/dist/runtime/adapter/tool/tool-name-mapping.d.ts +2 -0
- package/dist/runtime/adapter/tool/tool-name-mapping.js +27 -0
- package/dist/runtime/adapter/tool-resolution.d.ts +1 -0
- package/dist/runtime/adapter/tool-resolution.js +28 -1
- package/dist/runtime/agent-runtime-adapter.d.ts +1 -0
- package/dist/runtime/agent-runtime-adapter.js +31 -13
- package/package.json +1 -1
|
@@ -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
|
-
|
|
20
|
-
return "completed";
|
|
21
|
-
}
|
|
22
|
-
return summarizeChatToolError(output);
|
|
19
|
+
return isError ? summarizeChatToolOutput(output, "failed") : summarizeChatToolOutput(output, "completed");
|
|
23
20
|
}
|
|
24
|
-
function
|
|
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) :
|
|
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
|
|
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.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.374";
|
|
2
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.
|
|
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
|
-
|
|
40
|
+
primaryTools.length === 0;
|
|
40
41
|
const langChainStreamModel = resolvedLangChainModel && canUseDirectModelStream
|
|
41
42
|
? resolvedLangChainModel
|
|
42
|
-
: resolvedLangChainModel &&
|
|
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,
|
|
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
|
-
|
|
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
|
|
488
|
-
|
|
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() {
|
|
@@ -287,6 +288,30 @@ function updateDelegationState(state, event, countConfiguredToolsForAgentId) {
|
|
|
287
288
|
}
|
|
288
289
|
}
|
|
289
290
|
}
|
|
291
|
+
function extractTodoToolStart(event) {
|
|
292
|
+
if (typeof event !== "object" || event === null) {
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
const typed = event;
|
|
296
|
+
const eventName = typeof typed.event === "string" ? typed.event : "";
|
|
297
|
+
const runType = typeof typed.run_type === "string" ? typed.run_type : "";
|
|
298
|
+
const toolName = typeof typed.name === "string" ? typed.name : "";
|
|
299
|
+
const isToolStart = eventName === "on_tool_start" || (eventName === "on_chain_start" && runType === "tool");
|
|
300
|
+
if (!isToolStart || (toolName !== "write_todos" && toolName !== "read_todos")) {
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
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 };
|
|
314
|
+
}
|
|
290
315
|
export function projectRuntimeStreamEvent(params) {
|
|
291
316
|
const { event, allowVisibleStreamDeltas, includeStateStreamOutput, rootAgentId, countConfiguredToolsForAgentId, toolNameMapping, primaryTools, state, } = params;
|
|
292
317
|
const chunks = [{
|
|
@@ -341,6 +366,17 @@ export function projectRuntimeStreamEvent(params) {
|
|
|
341
366
|
}
|
|
342
367
|
}
|
|
343
368
|
const toolResult = extractToolResult(event);
|
|
369
|
+
const todoToolStart = toolResult ? null : extractTodoToolStart(event);
|
|
370
|
+
if (todoToolStart) {
|
|
371
|
+
state.emittedToolResult = true;
|
|
372
|
+
state.emittedSuccessfulToolResult = true;
|
|
373
|
+
chunks.push({
|
|
374
|
+
kind: "tool-result",
|
|
375
|
+
toolName: resolveModelFacingToolName(todoToolStart.toolName, toolNameMapping, primaryTools),
|
|
376
|
+
output: todoToolStart.input,
|
|
377
|
+
isError: false,
|
|
378
|
+
});
|
|
379
|
+
}
|
|
344
380
|
if (toolResult) {
|
|
345
381
|
const isTodoTool = toolResult.toolName === "write_todos" || toolResult.toolName === "read_todos";
|
|
346
382
|
const salvagedTaskErrorFindings = toolResult.toolName === "task"
|
|
@@ -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
|
}
|
|
@@ -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
|
|
534
|
-
|
|
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:
|
|
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
|
|
580
|
-
|
|
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:
|
|
628
|
+
resolvedTools: modelTools,
|
|
611
629
|
resolvedMiddleware,
|
|
612
630
|
resolvedSubagents,
|
|
613
631
|
resolvedInterruptOn,
|