@botbotgo/agent-harness 0.0.359 → 0.0.361
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.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.361";
|
|
2
2
|
export declare const AGENT_HARNESS_RELEASE_DATE = "2026-04-25";
|
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.361";
|
|
2
2
|
export const AGENT_HARNESS_RELEASE_DATE = "2026-04-25";
|
|
@@ -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 } from "../../prompts/runtime-prompts.js";
|
|
10
|
+
import { AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION, } from "../../prompts/runtime-prompts.js";
|
|
11
11
|
function readBindingExecutionParams(binding) {
|
|
12
12
|
const params = binding.execution?.params ?? binding.deepAgentParams ?? binding.langchainAgentParams;
|
|
13
13
|
return {
|
|
@@ -76,6 +76,17 @@ function hasNativeTaskDelegationIntent(value) {
|
|
|
76
76
|
}
|
|
77
77
|
return hasNativeTaskDelegationIntent(typed.tool_calls) || hasNativeTaskDelegationIntent(typed.messages);
|
|
78
78
|
}
|
|
79
|
+
function looksLikeCapabilityRefusalWithoutEvidence(value) {
|
|
80
|
+
const text = extractVisibleOutput(value).trim();
|
|
81
|
+
if (!text) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
const refusalSignal = /(?:cannot|can't|unable to|do not have|don't have|not support|does not support|missing capabilities|tool limitation|skill limitation|capability limitation|out of scope|无法|不能|不支持|缺少能力|能力不足|超出范围)/iu.test(text);
|
|
85
|
+
if (!refusalSignal) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
return /(?:tool|tools|skill|skills|capabilit|scope|工具|技能|能力|范围)/iu.test(text);
|
|
89
|
+
}
|
|
79
90
|
function readStructuredToolCall(value) {
|
|
80
91
|
const salvaged = salvageJsonToolCalls(value)[0];
|
|
81
92
|
if (salvaged) {
|
|
@@ -344,6 +355,20 @@ export async function executeRequestInvocation(options) {
|
|
|
344
355
|
result = recoveredInvocation.result;
|
|
345
356
|
executedToolResults.splice(0, executedToolResults.length, ...recoveredInvocation.executedToolResults);
|
|
346
357
|
}
|
|
358
|
+
if (options.resumePayload === undefined
|
|
359
|
+
&& primaryTools.length > 0
|
|
360
|
+
&& executedToolResults.length === 0
|
|
361
|
+
&& looksLikeCapabilityRefusalWithoutEvidence(result)) {
|
|
362
|
+
const messages = Array.isArray(result.messages)
|
|
363
|
+
? result.messages
|
|
364
|
+
: undefined;
|
|
365
|
+
const recoveryBase = messages ? { messages } : request;
|
|
366
|
+
const recoveredRequest = appendToolRecoveryInstruction(recoveryBase, EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION);
|
|
367
|
+
const recoveredInvocation = await invokeOnce(recoveredRequest);
|
|
368
|
+
localOrUpstreamInvocation = recoveredInvocation;
|
|
369
|
+
result = recoveredInvocation.result;
|
|
370
|
+
executedToolResults.splice(0, executedToolResults.length, ...recoveredInvocation.executedToolResults);
|
|
371
|
+
}
|
|
347
372
|
try {
|
|
348
373
|
return finalizeRequestResult({
|
|
349
374
|
bindingAgentId: options.binding.agent.id,
|
|
@@ -242,6 +242,17 @@ function looksLikeNonEvidenceApology(value) {
|
|
|
242
242
|
|| /(?:system limitation|technical limitation|internal limitation|recursion limit)/iu.test(normalized)
|
|
243
243
|
|| /(?:抱歉|对不起)[\s\S]*(?:无法|不能|未能)(?:完成|继续|处理)/u.test(normalized);
|
|
244
244
|
}
|
|
245
|
+
function looksLikeContradictedToolExecutionFailure(value) {
|
|
246
|
+
const normalized = sanitizeVisibleText(value).trim();
|
|
247
|
+
if (!normalized) {
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
const mentionsToolExecution = /(?:\btool\b|\bfunction\b|\bexecute\b|\binvoke\b|\bcall\b|工具|函数|调用|执行)/iu.test(normalized);
|
|
251
|
+
if (!mentionsToolExecution) {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
return /(?:cancelled|canceled|timeout|timed out|race condition|cannot execute|can't execute|unable to execute|could not execute|failed to execute|被取消|超时|无法执行|不能执行|未能执行)/iu.test(normalized);
|
|
255
|
+
}
|
|
245
256
|
function extractDeterministicToolFailureReport(executedToolResults) {
|
|
246
257
|
const hasSuccessfulSubstantiveTool = executedToolResults.some((toolResult) => (toolResult.isError !== true
|
|
247
258
|
&& toolResult.toolName !== "write_todos"
|
|
@@ -311,6 +322,9 @@ export function resolveDeterministicFinalOutput(params) {
|
|
|
311
322
|
&& (looksLikeClarificationQuestion(sanitizedVisibleOutput) || looksLikeNonEvidenceApology(sanitizedVisibleOutput))) {
|
|
312
323
|
return deterministicFailureReport || delegatedTaskOutput || successfulToolOutput || sanitizedVisibleOutput;
|
|
313
324
|
}
|
|
325
|
+
if (sanitizedVisibleOutput && successfulToolOutput && looksLikeContradictedToolExecutionFailure(sanitizedVisibleOutput)) {
|
|
326
|
+
return delegatedTaskOutput || successfulToolOutput;
|
|
327
|
+
}
|
|
314
328
|
if (sanitizedVisibleOutput && !isLowSignalStructuredCompletion(sanitizedVisibleOutput)) {
|
|
315
329
|
return sanitizedVisibleOutput;
|
|
316
330
|
}
|
|
@@ -383,6 +397,7 @@ export function finalizeRequestResult(params) {
|
|
|
383
397
|
const hasMissingRequiredFinalAnswer = binding?.harnessRuntime?.executionContract?.requiresPlan === true
|
|
384
398
|
&& !visibleOutput
|
|
385
399
|
&& !preliminaryTerminalStatus
|
|
400
|
+
&& !output.trim()
|
|
386
401
|
&& allExecutedToolResults.some((toolResult) => toolResult.isError !== true && toolResult.toolName !== "write_todos" && toolResult.toolName !== "read_todos");
|
|
387
402
|
if (hasMissingRequiredPlanEvidence) {
|
|
388
403
|
output = "runtime_error=Agent ended before producing required plan evidence.";
|
|
@@ -10,6 +10,7 @@ import { EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION } from "./prompts/runtim
|
|
|
10
10
|
import { buildToolNameMapping, } from "./adapter/tool/tool-name-mapping.js";
|
|
11
11
|
import { executeRequestInvocation } from "./adapter/flow/invocation-flow.js";
|
|
12
12
|
import { streamRuntimeExecution } from "./adapter/flow/stream-runtime.js";
|
|
13
|
+
import { resolveDeterministicFinalOutput } from "./adapter/invocation-result.js";
|
|
13
14
|
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";
|
|
14
15
|
import { extractSubagentRequestText, invokeBuiltinTaskTool as invokeBuiltinTaskToolHelper, materializeAutomaticSummarizationMiddleware as materializeAutomaticSummarizationMiddlewareHelper, resolveBuiltinMiddlewareBackend as resolveBuiltinMiddlewareBackendHelper, resolveBuiltinMiddlewareTools as resolveBuiltinMiddlewareToolsHelper, resolveLangChainRuntimeExtensionMiddleware as resolveLangChainRuntimeExtensionMiddlewareHelper, resolveMiddleware as resolveMiddlewareHelper, resolveSubagents as resolveSubagentsHelper, wrapRequestResultAsSubagentResponse, } from "./adapter/middleware-assembly.js";
|
|
15
16
|
import { isEmptyFinalAiMessageError, resolveBindingTimeout, resolveStreamIdleTimeout, } from "./adapter/resilience.js";
|
|
@@ -154,6 +155,29 @@ function hasDelegatedPlanEvidence(result) {
|
|
|
154
155
|
return Array.isArray(toolResults)
|
|
155
156
|
&& toolResults.some((item) => item.toolName === "write_todos" || item.toolName === "read_todos");
|
|
156
157
|
}
|
|
158
|
+
function resolveDelegatedResultOutput(result) {
|
|
159
|
+
const executedToolResults = Array.isArray(result.metadata?.executedToolResults)
|
|
160
|
+
? result.metadata.executedToolResults
|
|
161
|
+
: [];
|
|
162
|
+
const deterministicOutput = resolveDeterministicFinalOutput({
|
|
163
|
+
visibleOutput: typeof result.output === "string" ? result.output : "",
|
|
164
|
+
executedToolResults,
|
|
165
|
+
});
|
|
166
|
+
return deterministicOutput || result.output;
|
|
167
|
+
}
|
|
168
|
+
function selectDelegatedToolResultsForVisibleProgress(result) {
|
|
169
|
+
const executedToolResults = Array.isArray(result?.metadata?.executedToolResults)
|
|
170
|
+
? result.metadata.executedToolResults
|
|
171
|
+
: [];
|
|
172
|
+
const hasSuccessfulExecutionEvidence = executedToolResults.some((toolResult) => (toolResult.isError !== true
|
|
173
|
+
&& toolResult.toolName !== "write_todos"
|
|
174
|
+
&& toolResult.toolName !== "read_todos"));
|
|
175
|
+
return hasSuccessfulExecutionEvidence
|
|
176
|
+
? executedToolResults.filter((toolResult) => (toolResult.isError !== true
|
|
177
|
+
&& toolResult.toolName !== "write_todos"
|
|
178
|
+
&& toolResult.toolName !== "read_todos"))
|
|
179
|
+
: executedToolResults;
|
|
180
|
+
}
|
|
157
181
|
export class AgentRuntimeAdapter {
|
|
158
182
|
options;
|
|
159
183
|
modelCache = new Map();
|
|
@@ -806,7 +830,7 @@ export class AgentRuntimeAdapter {
|
|
|
806
830
|
if (typeof model.invoke !== "function") {
|
|
807
831
|
return null;
|
|
808
832
|
}
|
|
809
|
-
const
|
|
833
|
+
const invokeRouter = async (activePrompt, operationName) => this.invokeWithProviderRetry(binding, () => this.withTimeout(() => model.invoke(activePrompt, resolveLangChainInvocationConfig(binding, {
|
|
810
834
|
sessionId,
|
|
811
835
|
requestId,
|
|
812
836
|
context: options.context,
|
|
@@ -815,28 +839,44 @@ export class AgentRuntimeAdapter {
|
|
|
815
839
|
sessionId,
|
|
816
840
|
requestId,
|
|
817
841
|
}),
|
|
818
|
-
})), resolveBindingTimeout(binding),
|
|
819
|
-
const
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
const retryPrompt = [
|
|
842
|
+
})), resolveBindingTimeout(binding), operationName, "invoke"));
|
|
843
|
+
const routerPrompts = [
|
|
844
|
+
prompt,
|
|
845
|
+
[
|
|
823
846
|
prompt,
|
|
824
847
|
"Your previous router output was invalid.",
|
|
825
|
-
"Previous output:",
|
|
826
|
-
rawText,
|
|
827
848
|
"Return only one JSON object now. Do not include prose, markdown, labels, or tool-call wrappers.",
|
|
828
|
-
].join("\n\n")
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
849
|
+
].join("\n\n"),
|
|
850
|
+
[
|
|
851
|
+
primaryModel.init?.think === false ? "/no_think" : "",
|
|
852
|
+
"Select one subagent from this exact list:",
|
|
853
|
+
Array.from(subagentNames).join(", "),
|
|
854
|
+
"Return JSON only:",
|
|
855
|
+
"{\"subagent_type\":\"<one exact listed name>\"}",
|
|
856
|
+
"User request:",
|
|
857
|
+
requestText,
|
|
858
|
+
].filter(Boolean).join("\n\n"),
|
|
859
|
+
[
|
|
860
|
+
primaryModel.init?.think === false ? "/no_think" : "",
|
|
861
|
+
"JSON only. Pick a listed subagent or refuse.",
|
|
862
|
+
"Listed subagents:",
|
|
863
|
+
Array.from(subagentNames).join(", "),
|
|
864
|
+
"Allowed outputs:",
|
|
865
|
+
"{\"subagent_type\":\"<listed name>\"}",
|
|
866
|
+
"{\"status\":\"refused\",\"reason\":\"No configured subagent can handle the request.\"}",
|
|
867
|
+
"Request:",
|
|
868
|
+
requestText,
|
|
869
|
+
].filter(Boolean).join("\n\n"),
|
|
870
|
+
];
|
|
871
|
+
let selection = null;
|
|
872
|
+
let previousRawText = "";
|
|
873
|
+
for (let index = 0; index < routerPrompts.length && !selection; index += 1) {
|
|
874
|
+
const activePrompt = index <= 1 || !previousRawText
|
|
875
|
+
? routerPrompts[index]
|
|
876
|
+
: [routerPrompts[index], "Previous output:", previousRawText].join("\n\n");
|
|
877
|
+
const raw = await invokeRouter(activePrompt, index === 0 ? "delegation router invoke" : `delegation router retry invoke ${index}`);
|
|
878
|
+
previousRawText = readModelText(raw);
|
|
879
|
+
selection = parseCompactRouterSelection(previousRawText, subagentNames);
|
|
840
880
|
}
|
|
841
881
|
if (selection?.refusedReason) {
|
|
842
882
|
return {
|
|
@@ -896,7 +936,7 @@ export class AgentRuntimeAdapter {
|
|
|
896
936
|
},
|
|
897
937
|
};
|
|
898
938
|
}
|
|
899
|
-
return { toolOutput: delegatedResult
|
|
939
|
+
return { toolOutput: resolveDelegatedResultOutput(delegatedResult), delegatedResult };
|
|
900
940
|
}
|
|
901
941
|
async *stream(binding, input, sessionId, history = [], options = {}) {
|
|
902
942
|
const directListing = await this.tryHandleDirectWorkspaceListing(binding, input, {
|
|
@@ -916,17 +956,32 @@ export class AgentRuntimeAdapter {
|
|
|
916
956
|
};
|
|
917
957
|
return;
|
|
918
958
|
}
|
|
959
|
+
if (isDelegationOnlyDeepAgentBinding(binding)) {
|
|
960
|
+
yield {
|
|
961
|
+
kind: "commentary",
|
|
962
|
+
content: "Selecting a specialist for delegated execution.",
|
|
963
|
+
};
|
|
964
|
+
}
|
|
919
965
|
const compactDelegation = await this.tryDelegateWithCompactRouter(binding, input, sessionId, options.requestId ?? sessionId, {
|
|
920
966
|
...options,
|
|
921
967
|
sessionId,
|
|
922
968
|
requestId: options.requestId,
|
|
923
969
|
});
|
|
924
970
|
if (compactDelegation) {
|
|
971
|
+
const delegatedToolResults = selectDelegatedToolResultsForVisibleProgress(compactDelegation.delegatedResult);
|
|
925
972
|
yield {
|
|
926
973
|
kind: "tool-result",
|
|
927
974
|
toolName: "task",
|
|
928
975
|
output: compactDelegation.toolOutput,
|
|
929
976
|
};
|
|
977
|
+
for (const toolResult of delegatedToolResults) {
|
|
978
|
+
yield {
|
|
979
|
+
kind: "tool-result",
|
|
980
|
+
toolName: toolResult.toolName,
|
|
981
|
+
output: toolResult.output,
|
|
982
|
+
isError: toolResult.isError,
|
|
983
|
+
};
|
|
984
|
+
}
|
|
930
985
|
yield {
|
|
931
986
|
kind: "content",
|
|
932
987
|
content: typeof compactDelegation.toolOutput === "string"
|