@botbotgo/agent-harness 0.0.354 → 0.0.357
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/package-version.d.ts +2 -2
- package/dist/package-version.js +2 -2
- package/dist/resources/prompts/runtime/autonomous-investigation-recovery.md +10 -1
- package/dist/runtime/adapter/compat/deepagent-compat.d.ts +6 -0
- package/dist/runtime/adapter/compat/deepagent-compat.js +16 -0
- package/dist/runtime/adapter/flow/invocation-flow.js +40 -2
- package/dist/runtime/adapter/invocation-result.js +28 -5
- package/dist/runtime/agent-runtime-adapter.d.ts +1 -1
- package/dist/runtime/agent-runtime-adapter.js +22 -10
- package/dist/runtime/agent-runtime-assembly.d.ts +1 -0
- package/dist/runtime/agent-runtime-assembly.js +17 -2
- package/dist/runtime/harness/run/stream-run.js +3 -2
- package/dist/runtime/parsing/output-content.js +4 -0
- package/dist/runtime/parsing/output-tool-args.js +44 -0
- package/package.json +3 -3
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
2
|
-
export declare const AGENT_HARNESS_RELEASE_DATE = "2026-04-
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.357";
|
|
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.
|
|
2
|
-
export const AGENT_HARNESS_RELEASE_DATE = "2026-04-
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.357";
|
|
2
|
+
export const AGENT_HARNESS_RELEASE_DATE = "2026-04-25";
|
|
@@ -1 +1,10 @@
|
|
|
1
|
-
Do not stop at a plan or ask the user to choose the next obvious diagnostic step when the request is for deep investigation, root-cause analysis, or step-by-step execution. Do not ask for more background, scope, logs, or environment details until you have first exhausted the context and tools already available in this runtime.
|
|
1
|
+
Do not stop at a plan or ask the user to choose the next obvious diagnostic step when the request is for deep investigation, root-cause analysis, or step-by-step execution. Do not ask for more background, scope, logs, or environment details until you have first exhausted the context and tools already available in this runtime.
|
|
2
|
+
|
|
3
|
+
If no concrete execution has happened yet, start from the current workspace, shell, and attached runtime/tool context by default, then continue the investigation yourself with the next concrete tool call. If the user explicitly asked for a plan, or if the task is clearly non-trivial and multi-step, call write_todos first with concrete investigation/execution steps before any other tool call or final answer.
|
|
4
|
+
|
|
5
|
+
If a todo board already exists, do not restart planning and do not repeat the same clarification request. Use the current todo board and prior tool results to choose one of these terminally useful actions:
|
|
6
|
+
- If more evidence is genuinely needed and an available tool can get it, make the next concrete tool call.
|
|
7
|
+
- If the existing evidence is enough to answer, update the todo board to completed or blocked as appropriate, then provide the final answer grounded in the tool results.
|
|
8
|
+
- If the available tools cannot resolve the remaining work, update the todo board to blocked or failed and provide a blocker report with the evidence.
|
|
9
|
+
|
|
10
|
+
Never print a tool-call JSON object, function call, or tool name as prose when you intend to use a tool. Actually call the tool. Ask a blocking clarification question only after the available evidence is genuinely insufficient to continue.
|
|
@@ -11,3 +11,9 @@ export declare function resolveDeepAgentSkillSourcePaths(options: {
|
|
|
11
11
|
ownerId: string;
|
|
12
12
|
skillPaths?: string[];
|
|
13
13
|
}): string[] | undefined;
|
|
14
|
+
export declare function resolveDeepAgentSkillSourceRootPaths(options: {
|
|
15
|
+
workspaceRoot?: string;
|
|
16
|
+
runtimeRoot?: string;
|
|
17
|
+
ownerId: string;
|
|
18
|
+
skillPaths?: string[];
|
|
19
|
+
}): string[] | undefined;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
2
3
|
export function relativizeDeepAgentSkillSourcePaths(workspaceRoot, skillPaths) {
|
|
3
4
|
if (!workspaceRoot || !skillPaths) {
|
|
4
5
|
return skillPaths;
|
|
@@ -24,3 +25,18 @@ export function resolveDeepAgentSkillSourcePaths(options) {
|
|
|
24
25
|
}
|
|
25
26
|
return relativizeDeepAgentSkillSourcePaths(workspaceRoot, skillPaths) ?? skillPaths;
|
|
26
27
|
}
|
|
28
|
+
export function resolveDeepAgentSkillSourceRootPaths(options) {
|
|
29
|
+
const { workspaceRoot, skillPaths } = options;
|
|
30
|
+
if (!skillPaths) {
|
|
31
|
+
return skillPaths;
|
|
32
|
+
}
|
|
33
|
+
const sourceRoots = Array.from(new Set(skillPaths.map((skillPath) => {
|
|
34
|
+
const absolutePath = path.isAbsolute(skillPath) || !workspaceRoot
|
|
35
|
+
? skillPath
|
|
36
|
+
: path.resolve(workspaceRoot, skillPath);
|
|
37
|
+
return existsSync(path.join(absolutePath, "SKILL.md"))
|
|
38
|
+
? path.dirname(absolutePath)
|
|
39
|
+
: absolutePath;
|
|
40
|
+
})));
|
|
41
|
+
return relativizeDeepAgentSkillSourcePaths(workspaceRoot, sourceRoots) ?? sourceRoots;
|
|
42
|
+
}
|
|
@@ -4,9 +4,10 @@ import { finalizeRequestResult } from "../invocation-result.js";
|
|
|
4
4
|
import { invokeRuntimeWithLocalTools } from "./invoke-runtime.js";
|
|
5
5
|
import { buildInvocationRequest } from "../model/invocation-request.js";
|
|
6
6
|
import { UPSTREAM_REQUEST_CONFIG_KEY, UPSTREAM_SESSION_CONFIG_KEY } from "../upstream-configurable-keys.js";
|
|
7
|
-
import { extractVisibleOutput, tryParseJson } from "../../parsing/output-parsing.js";
|
|
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
11
|
function readBindingExecutionParams(binding) {
|
|
11
12
|
const params = binding.execution?.params ?? binding.deepAgentParams ?? binding.langchainAgentParams;
|
|
12
13
|
return {
|
|
@@ -36,6 +37,29 @@ function isDelegationOnlyBinding(binding) {
|
|
|
36
37
|
function hasTaskDelegationEvidence(executedToolResults) {
|
|
37
38
|
return executedToolResults.some((item) => item.toolName === "task");
|
|
38
39
|
}
|
|
40
|
+
function hasIncompleteTodos(value) {
|
|
41
|
+
if (!Array.isArray(value)) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
return value.some((todo) => {
|
|
45
|
+
if (typeof todo !== "object" || todo === null) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const status = typeof todo.status === "string"
|
|
49
|
+
? todo.status.trim().toLowerCase()
|
|
50
|
+
: "";
|
|
51
|
+
return status === "pending" || status === "in_progress";
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function hasIncompleteUpstreamPlan(value) {
|
|
55
|
+
if (typeof value !== "object" || value === null) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
const typed = value;
|
|
59
|
+
return hasIncompleteTodos(typed.todos)
|
|
60
|
+
|| hasIncompleteTodos(typed.stateSnapshot?.todos)
|
|
61
|
+
|| hasIncompleteTodos(typed.metadata?.stateSnapshot?.todos);
|
|
62
|
+
}
|
|
39
63
|
function hasNativeTaskDelegationIntent(value) {
|
|
40
64
|
if (typeof value !== "object" || value === null) {
|
|
41
65
|
return false;
|
|
@@ -285,11 +309,25 @@ export async function executeRequestInvocation(options) {
|
|
|
285
309
|
toolRuntimeContext: invokeOptions.toolRuntimeContext,
|
|
286
310
|
});
|
|
287
311
|
}
|
|
288
|
-
|
|
312
|
+
let result = localOrUpstreamInvocation.result;
|
|
289
313
|
const executedToolResults = [...localOrUpstreamInvocation.executedToolResults];
|
|
290
314
|
if (!result) {
|
|
291
315
|
throw new Error("Agent invocation returned no result");
|
|
292
316
|
}
|
|
317
|
+
if (options.resumePayload === undefined
|
|
318
|
+
&& options.binding.harnessRuntime.executionContract?.requiresPlan === true
|
|
319
|
+
&& hasIncompleteUpstreamPlan(result)
|
|
320
|
+
&& !extractVisibleOutput(result).trim()) {
|
|
321
|
+
const messages = Array.isArray(result.messages)
|
|
322
|
+
? result.messages
|
|
323
|
+
: undefined;
|
|
324
|
+
const recoveryBase = messages ? { messages } : request;
|
|
325
|
+
const recoveredRequest = appendToolRecoveryInstruction(recoveryBase, AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION);
|
|
326
|
+
const recoveredInvocation = await invokeOnce(recoveredRequest);
|
|
327
|
+
localOrUpstreamInvocation = recoveredInvocation;
|
|
328
|
+
result = recoveredInvocation.result;
|
|
329
|
+
executedToolResults.splice(0, executedToolResults.length, ...recoveredInvocation.executedToolResults);
|
|
330
|
+
}
|
|
293
331
|
try {
|
|
294
332
|
return finalizeRequestResult({
|
|
295
333
|
bindingAgentId: options.binding.agent.id,
|
|
@@ -57,6 +57,17 @@ function looksLikeToolBlocker(value) {
|
|
|
57
57
|
|| /invalid tool call/iu.test(normalized)
|
|
58
58
|
|| /tool call.*schema/iu.test(normalized);
|
|
59
59
|
}
|
|
60
|
+
function isSubstantiveFinalOutput(value) {
|
|
61
|
+
const normalized = sanitizeVisibleText(value).trim();
|
|
62
|
+
if (normalized.length < 80) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
return !looksLikeLeakedToolCallText(normalized)
|
|
66
|
+
&& !looksLikeToolBlocker(normalized)
|
|
67
|
+
&& !looksLikeClarificationQuestion(normalized)
|
|
68
|
+
&& !looksLikeNonEvidenceApology(normalized)
|
|
69
|
+
&& !isLowSignalStructuredCompletion(normalized);
|
|
70
|
+
}
|
|
60
71
|
function normalizeToolOutputText(output) {
|
|
61
72
|
const directText = typeof output === "string"
|
|
62
73
|
? sanitizeVisibleText(output).trim()
|
|
@@ -343,18 +354,30 @@ export function finalizeRequestResult(params) {
|
|
|
343
354
|
&& !hasFinalMessageToolCalls(result)) {
|
|
344
355
|
throw new Error("empty_final_output");
|
|
345
356
|
}
|
|
357
|
+
const stateSnapshot = buildStateSnapshot(result);
|
|
358
|
+
const hasIncompleteRequiredPlan = binding?.harnessRuntime?.executionContract?.requiresPlan === true
|
|
359
|
+
&& hasIncompleteStateSnapshotPlan(stateSnapshot);
|
|
346
360
|
const serializedResult = JSON.stringify(result, null, 2);
|
|
347
|
-
|
|
361
|
+
let output = resolveDeterministicFinalOutput({
|
|
348
362
|
visibleOutput,
|
|
349
363
|
toolFallback,
|
|
350
364
|
executedToolResults: allExecutedToolResults,
|
|
351
365
|
})
|
|
352
366
|
|| (containsLikelySkillDocument(result) ? "" : serializedResult);
|
|
367
|
+
const preliminaryTerminalStatus = readTerminalExecutionStatus(output);
|
|
368
|
+
const hasMissingRequiredFinalAnswer = binding?.harnessRuntime?.executionContract?.requiresPlan === true
|
|
369
|
+
&& !visibleOutput
|
|
370
|
+
&& !preliminaryTerminalStatus
|
|
371
|
+
&& allExecutedToolResults.some((toolResult) => toolResult.isError !== true && toolResult.toolName !== "write_todos" && toolResult.toolName !== "read_todos");
|
|
372
|
+
if (hasIncompleteRequiredPlan && !visibleOutput) {
|
|
373
|
+
output = "runtime_error=Agent ended while required plan still had unfinished work.";
|
|
374
|
+
}
|
|
375
|
+
else if (hasMissingRequiredFinalAnswer) {
|
|
376
|
+
output = "runtime_error=Agent ended after tool execution without producing a final answer.";
|
|
377
|
+
}
|
|
353
378
|
const finalMessageText = sanitizeVisibleText(output);
|
|
354
379
|
const terminalStatus = structuredTerminalStatus ?? readTerminalExecutionStatus(finalMessageText);
|
|
355
|
-
const
|
|
356
|
-
const hasIncompleteRequiredPlan = binding?.harnessRuntime?.executionContract?.requiresPlan === true
|
|
357
|
-
&& hasIncompleteStateSnapshotPlan(stateSnapshot);
|
|
380
|
+
const hasSubstantiveFinalOutput = Boolean(visibleOutput) && isSubstantiveFinalOutput(finalMessageText);
|
|
358
381
|
const hasTerminalToolBlocker = looksLikeToolBlocker(finalMessageText);
|
|
359
382
|
const memoryCandidates = allExecutedToolResults.flatMap((toolResult) => toolResult.memoryCandidates ?? []);
|
|
360
383
|
return {
|
|
@@ -363,7 +386,7 @@ export function finalizeRequestResult(params) {
|
|
|
363
386
|
agentId: bindingAgentId,
|
|
364
387
|
state: Array.isArray(result.__interrupt__) && result.__interrupt__.length > 0
|
|
365
388
|
? "waiting_for_approval"
|
|
366
|
-
: hasIncompleteRequiredPlan
|
|
389
|
+
: (hasIncompleteRequiredPlan && !hasSubstantiveFinalOutput) || hasMissingRequiredFinalAnswer
|
|
367
390
|
? "failed"
|
|
368
391
|
: hasTerminalToolBlocker
|
|
369
392
|
? "failed"
|
|
@@ -2,7 +2,7 @@ import type { CompiledAgentBinding, MessageContent, RequestResult, RuntimeAdapte
|
|
|
2
2
|
import { type RuntimeStreamChunk } from "./parsing/stream-event-parsing.js";
|
|
3
3
|
import { AGENT_INTERRUPT_SENTINEL_PREFIX, buildDeepAgentCreateParams, buildLangChainCreateParams, DEFAULT_DEEPAGENT_RECURSION_LIMIT, materializeModelExposedBuiltinMiddlewareTools, resolveLangChainInvocationConfig, resolveRunnableCheckpointer, resolveRunnableInterruptOn } from "./agent-runtime-assembly.js";
|
|
4
4
|
import { RuntimeOperationTimeoutError } from "./adapter/runtime-shell.js";
|
|
5
|
-
export { materializeDeepAgentSkillSourcePaths, resolveDeepAgentSkillSourcePaths, relativizeDeepAgentSkillSourcePaths, } from "./adapter/compat/deepagent-compat.js";
|
|
5
|
+
export { materializeDeepAgentSkillSourcePaths, resolveDeepAgentSkillSourcePaths, resolveDeepAgentSkillSourceRootPaths, relativizeDeepAgentSkillSourcePaths, } from "./adapter/compat/deepagent-compat.js";
|
|
6
6
|
export { buildAuthOmittingFetch, normalizeOpenAICompatibleInit } from "./adapter/compat/openai-compatible.js";
|
|
7
7
|
export { buildToolNameMapping, createModelFacingToolNameCandidates, createModelFacingToolNameLookupCandidates, resolveModelFacingToolName, sanitizeToolNameForModel, } from "./adapter/tool/tool-name-mapping.js";
|
|
8
8
|
export { computeRemainingTimeoutMs, isRetryableProviderError, resolveBindingTimeout, resolveProviderRetryPolicy, resolveStreamIdleTimeout, resolveTimeoutMs, } from "./adapter/resilience.js";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { createAsyncSubAgentMiddleware, createFilesystemMiddleware, createMemoryMiddleware, createPatchToolCallsMiddleware, createSkillsMiddleware, createSummarizationMiddleware, createSubAgentMiddleware, FilesystemBackend, StateBackend, } from "deepagents";
|
|
3
3
|
import { createAgent, humanInTheLoopMiddleware, todoListMiddleware } from "langchain";
|
|
4
|
-
import { tryParseJson, wrapResolvedModel, } from "./parsing/output-parsing.js";
|
|
4
|
+
import { sanitizeVisibleText, tryParseJson, wrapResolvedModel, } from "./parsing/output-parsing.js";
|
|
5
5
|
import { extractMessageText } from "../utils/message-content.js";
|
|
6
6
|
import { AGENT_INTERRUPT_SENTINEL_PREFIX, buildDeepAgentCreateParams, buildDeepAgentSystemPromptWithCapabilityHierarchy, buildLangChainCreateParams, DEFAULT_DEEPAGENT_RECURSION_LIMIT, materializeModelExposedBuiltinMiddlewareTools, resolveLangChainInvocationConfig, resolveRunnableCheckpointer, resolveRunnableInterruptOn, shouldAttachDeepAgentBackend, shouldAttachDeepAgentCheckpointer, shouldAttachDeepAgentStore, } from "./agent-runtime-assembly.js";
|
|
7
|
-
import { resolveDeepAgentSkillSourcePaths, } from "./adapter/compat/deepagent-compat.js";
|
|
7
|
+
import { resolveDeepAgentSkillSourcePaths, resolveDeepAgentSkillSourceRootPaths, } from "./adapter/compat/deepagent-compat.js";
|
|
8
8
|
import { EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION } from "./prompts/runtime-prompts.js";
|
|
9
9
|
import { buildToolNameMapping, } from "./adapter/tool/tool-name-mapping.js";
|
|
10
10
|
import { executeRequestInvocation } from "./adapter/flow/invocation-flow.js";
|
|
@@ -18,7 +18,7 @@ import { resolveAdapterTools } from "./adapter/tool-resolution.js";
|
|
|
18
18
|
import { resolveRuntimeStreamExecutionContext, } from "./adapter/flow/execution-context.js";
|
|
19
19
|
import { isRetryableProviderError } from "./adapter/resilience.js";
|
|
20
20
|
import { UPSTREAM_REQUEST_CONFIG_KEY, UPSTREAM_SESSION_CONFIG_KEY } from "./adapter/upstream-configurable-keys.js";
|
|
21
|
-
export { materializeDeepAgentSkillSourcePaths, resolveDeepAgentSkillSourcePaths, relativizeDeepAgentSkillSourcePaths, } from "./adapter/compat/deepagent-compat.js";
|
|
21
|
+
export { materializeDeepAgentSkillSourcePaths, resolveDeepAgentSkillSourcePaths, resolveDeepAgentSkillSourceRootPaths, relativizeDeepAgentSkillSourcePaths, } from "./adapter/compat/deepagent-compat.js";
|
|
22
22
|
export { buildAuthOmittingFetch, normalizeOpenAICompatibleInit } from "./adapter/compat/openai-compatible.js";
|
|
23
23
|
export { buildToolNameMapping, createModelFacingToolNameCandidates, createModelFacingToolNameLookupCandidates, resolveModelFacingToolName, sanitizeToolNameForModel, } from "./adapter/tool/tool-name-mapping.js";
|
|
24
24
|
export { computeRemainingTimeoutMs, isRetryableProviderError, resolveBindingTimeout, resolveProviderRetryPolicy, resolveStreamIdleTimeout, resolveTimeoutMs, } from "./adapter/resilience.js";
|
|
@@ -509,13 +509,17 @@ export class AgentRuntimeAdapter {
|
|
|
509
509
|
? resolveRunnableCheckpointer(this.options, binding)
|
|
510
510
|
: undefined;
|
|
511
511
|
const resolvedStore = shouldAttachDeepAgentStore(binding) ? this.options.storeResolver?.(binding) : undefined;
|
|
512
|
-
const resolvedBackend = shouldAttachDeepAgentBackend(binding) ? this.options.backendResolver?.(binding) : undefined;
|
|
513
512
|
const resolvedSkills = resolveDeepAgentSkillSourcePaths({
|
|
514
513
|
workspaceRoot: binding.harnessRuntime.workspaceRoot,
|
|
515
514
|
runtimeRoot: binding.harnessRuntime.runtimeRoot,
|
|
516
515
|
ownerId: binding.agent.id,
|
|
517
516
|
skillPaths: getBindingSkills(binding),
|
|
518
517
|
}) ?? [];
|
|
518
|
+
const resolvedBackend = shouldAttachDeepAgentBackend(binding)
|
|
519
|
+
? (this.options.backendResolver?.(binding) ?? (resolvedSkills.length > 0 ? this.resolveFilesystemBackend(binding, {
|
|
520
|
+
sessionId: options.sessionId ?? options.legacySessionId,
|
|
521
|
+
}) : undefined))
|
|
522
|
+
: undefined;
|
|
519
523
|
if (shouldUseConfigurableDeepAgentAssembly(binding)) {
|
|
520
524
|
return this.createConfigurableDeepAgentRunnable(binding, {
|
|
521
525
|
resolvedModel,
|
|
@@ -539,7 +543,15 @@ export class AgentRuntimeAdapter {
|
|
|
539
543
|
const subagents = inlineSubagents;
|
|
540
544
|
const middleware = [
|
|
541
545
|
...(builtinTools.todos === false ? [] : [todoListMiddleware()]),
|
|
542
|
-
...(input.resolvedSkills.length > 0 ? [createSkillsMiddleware({
|
|
546
|
+
...(input.resolvedSkills.length > 0 ? [createSkillsMiddleware({
|
|
547
|
+
backend,
|
|
548
|
+
sources: resolveDeepAgentSkillSourceRootPaths({
|
|
549
|
+
workspaceRoot: binding.harnessRuntime.workspaceRoot,
|
|
550
|
+
runtimeRoot: binding.harnessRuntime.runtimeRoot,
|
|
551
|
+
ownerId: binding.agent.id,
|
|
552
|
+
skillPaths: input.resolvedSkills,
|
|
553
|
+
}) ?? input.resolvedSkills,
|
|
554
|
+
})] : []),
|
|
543
555
|
...(builtinTools.filesystem === false ? [] : [createFilesystemMiddleware({ backend })]),
|
|
544
556
|
...(subagents.length > 0
|
|
545
557
|
? [createSubAgentMiddleware({
|
|
@@ -645,9 +657,9 @@ export class AgentRuntimeAdapter {
|
|
|
645
657
|
sessionId,
|
|
646
658
|
requestId,
|
|
647
659
|
agentId: binding.agent.id,
|
|
648
|
-
state: "completed",
|
|
649
|
-
output,
|
|
650
|
-
finalMessageText: output,
|
|
660
|
+
state: compactDelegation.delegatedResult?.state ?? "completed",
|
|
661
|
+
output: sanitizeVisibleText(output),
|
|
662
|
+
finalMessageText: sanitizeVisibleText(output),
|
|
651
663
|
metadata: {
|
|
652
664
|
executedToolResults: [
|
|
653
665
|
{
|
|
@@ -750,7 +762,7 @@ export class AgentRuntimeAdapter {
|
|
|
750
762
|
if (typeof model.invoke !== "function") {
|
|
751
763
|
return null;
|
|
752
764
|
}
|
|
753
|
-
const raw = await this.withTimeout(() => model.invoke(prompt, resolveLangChainInvocationConfig(binding, {
|
|
765
|
+
const raw = await this.invokeWithProviderRetry(binding, () => this.withTimeout(() => model.invoke(prompt, resolveLangChainInvocationConfig(binding, {
|
|
754
766
|
sessionId,
|
|
755
767
|
requestId,
|
|
756
768
|
context: options.context,
|
|
@@ -759,7 +771,7 @@ export class AgentRuntimeAdapter {
|
|
|
759
771
|
sessionId,
|
|
760
772
|
requestId,
|
|
761
773
|
}),
|
|
762
|
-
})), resolveBindingTimeout(binding), "delegation router invoke", "invoke");
|
|
774
|
+
})), resolveBindingTimeout(binding), "delegation router invoke", "invoke"));
|
|
763
775
|
const parsed = parseFirstJsonObject(readModelText(raw));
|
|
764
776
|
if (typeof parsed !== "object" || parsed === null) {
|
|
765
777
|
return null;
|
|
@@ -8,6 +8,7 @@ export declare function materializeModelExposedBuiltinMiddlewareTools(input: {
|
|
|
8
8
|
explicitToolNames?: string[];
|
|
9
9
|
modelExposed?: boolean | string[];
|
|
10
10
|
}): unknown[];
|
|
11
|
+
export declare function buildRuntimeTemporalContext(now?: Date): string;
|
|
11
12
|
export declare function buildDeepAgentSystemPromptWithCapabilityHierarchy(input: {
|
|
12
13
|
systemPrompt?: unknown;
|
|
13
14
|
subagents: Array<Pick<UpstreamSubagentConfig, "name" | "description"> | Pick<CompiledAsyncSubAgent, "name" | "description">>;
|
|
@@ -53,6 +53,21 @@ function buildSkillCatalog(skillPaths) {
|
|
|
53
53
|
};
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
|
+
export function buildRuntimeTemporalContext(now = new Date()) {
|
|
57
|
+
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone || "system local time";
|
|
58
|
+
return [
|
|
59
|
+
"Runtime temporal context:",
|
|
60
|
+
`- Current date/time: ${now.toISOString()}`,
|
|
61
|
+
`- Local time zone: ${timeZone}`,
|
|
62
|
+
"Use the runtime date/time above as authoritative for interpreting current, latest, recent, today, tomorrow, yesterday, and tool-returned dates.",
|
|
63
|
+
"Do not reject tool evidence as future-dated solely because it is newer than the model's training data.",
|
|
64
|
+
].join("\n");
|
|
65
|
+
}
|
|
66
|
+
function appendRuntimeTemporalContext(systemPrompt) {
|
|
67
|
+
return [typeof systemPrompt === "string" ? systemPrompt : undefined, buildRuntimeTemporalContext()]
|
|
68
|
+
.filter((part) => typeof part === "string" && part.length > 0)
|
|
69
|
+
.join("\n\n");
|
|
70
|
+
}
|
|
56
71
|
export function buildDeepAgentSystemPromptWithCapabilityHierarchy(input) {
|
|
57
72
|
const basePrompt = typeof input.systemPrompt === "string" ? input.systemPrompt : undefined;
|
|
58
73
|
const skills = buildSkillCatalog(input.skills ?? []);
|
|
@@ -122,7 +137,7 @@ export function buildDeepAgentSystemPromptWithCapabilityHierarchy(input) {
|
|
|
122
137
|
: []),
|
|
123
138
|
"",
|
|
124
139
|
].join("\n");
|
|
125
|
-
return [basePrompt, catalogPrompt].filter((part) => typeof part === "string" && part.length > 0).join("\n\n");
|
|
140
|
+
return appendRuntimeTemporalContext([basePrompt, catalogPrompt].filter((part) => typeof part === "string" && part.length > 0).join("\n\n"));
|
|
126
141
|
}
|
|
127
142
|
export const buildDeepAgentSystemPromptWithSubagentCatalog = buildDeepAgentSystemPromptWithCapabilityHierarchy;
|
|
128
143
|
export function resolveRunnableCheckpointer(options, binding) {
|
|
@@ -175,7 +190,7 @@ export function buildLangChainCreateParams(input) {
|
|
|
175
190
|
...(legacyPassthrough ?? {}),
|
|
176
191
|
...(langchainPassthrough ?? {}),
|
|
177
192
|
...(input.passthroughOverride ?? {}),
|
|
178
|
-
systemPrompt: input.systemPromptOverride ?? executionParams.systemPrompt,
|
|
193
|
+
systemPrompt: appendRuntimeTemporalContext(input.systemPromptOverride ?? executionParams.systemPrompt),
|
|
179
194
|
model: input.resolvedModel,
|
|
180
195
|
tools: input.resolvedTools,
|
|
181
196
|
middleware: input.resolvedMiddleware,
|
|
@@ -1092,8 +1092,9 @@ export async function* streamHarnessRun(options) {
|
|
|
1092
1092
|
visibleOutput: assistantOutput,
|
|
1093
1093
|
executedToolResults,
|
|
1094
1094
|
});
|
|
1095
|
-
|
|
1096
|
-
|
|
1095
|
+
const terminalStructuredStatus = readTerminalExecutionStatus(deterministicToolEvidenceOutput);
|
|
1096
|
+
const canUseDeterministicToolEvidenceOutput = !currentPlanState || !planStateHasActiveItems(currentPlanState) || Boolean(terminalStructuredStatus);
|
|
1097
|
+
if (!assistantOutput && sawSuccessfulToolResult && deterministicToolEvidenceOutput && canUseDeterministicToolEvidenceOutput) {
|
|
1097
1098
|
if (terminalStructuredStatus && currentPlanState && planStateHasActiveItems(currentPlanState)) {
|
|
1098
1099
|
const reconciledPlanState = reconcilePlanStateToTerminalStatus(currentPlanState, mapTerminalStatusToPlanItemStatus(terminalStructuredStatus), new Date().toISOString());
|
|
1099
1100
|
const signature = buildPlanStateSignature(reconciledPlanState);
|
|
@@ -59,6 +59,9 @@ function consumeLeadingFunctionLikeToolCall(value) {
|
|
|
59
59
|
function stripVisibleFunctionLikeToolCallText(value) {
|
|
60
60
|
let remaining = value.trim();
|
|
61
61
|
let removedLeadingCall = false;
|
|
62
|
+
if (salvageJsonToolCalls(remaining).length > 0) {
|
|
63
|
+
return "";
|
|
64
|
+
}
|
|
62
65
|
while (remaining.length > 0) {
|
|
63
66
|
const consumed = consumeLeadingFunctionLikeToolCall(remaining);
|
|
64
67
|
if (!consumed) {
|
|
@@ -84,6 +87,7 @@ function stripVisibleFunctionLikeToolCallText(value) {
|
|
|
84
87
|
}
|
|
85
88
|
export function sanitizeVisibleText(value) {
|
|
86
89
|
return stripVisibleFunctionLikeToolCallText(value
|
|
90
|
+
.replace(/<agent_memory>[\s\S]*?<\/agent_memory>/giu, "")
|
|
87
91
|
.replace(/[A-Za-z0-9_]*Middleware\.after_model/g, "")
|
|
88
92
|
.replace(/todoListMiddleware\.after_model/g, "")
|
|
89
93
|
.replace(/__end__+/g, "")
|
|
@@ -205,6 +205,43 @@ function closeJsonContainerSuffix(value) {
|
|
|
205
205
|
}
|
|
206
206
|
return `${trimmed}${stack.reverse().join("")}`;
|
|
207
207
|
}
|
|
208
|
+
function normalizePythonLikeJson(value) {
|
|
209
|
+
const trimmed = value.trim();
|
|
210
|
+
if (!trimmed.includes("'")) {
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
let output = "";
|
|
214
|
+
let inSingle = false;
|
|
215
|
+
let inDouble = false;
|
|
216
|
+
let escaping = false;
|
|
217
|
+
for (const char of trimmed) {
|
|
218
|
+
if (escaping) {
|
|
219
|
+
output += char;
|
|
220
|
+
escaping = false;
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
if (char === "\\") {
|
|
224
|
+
output += char;
|
|
225
|
+
escaping = true;
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
if (char === "\"" && !inSingle) {
|
|
229
|
+
inDouble = !inDouble;
|
|
230
|
+
output += char;
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
if (char === "'" && !inDouble) {
|
|
234
|
+
inSingle = !inSingle;
|
|
235
|
+
output += "\"";
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
output += char;
|
|
239
|
+
}
|
|
240
|
+
if (inSingle || inDouble) {
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
return output;
|
|
244
|
+
}
|
|
208
245
|
export function salvageToolArgs(value) {
|
|
209
246
|
if (typeof value === "object" && value && !Array.isArray(value)) {
|
|
210
247
|
return value;
|
|
@@ -255,6 +292,13 @@ export function salvageJsonToolCalls(value) {
|
|
|
255
292
|
if (direct) {
|
|
256
293
|
return direct;
|
|
257
294
|
}
|
|
295
|
+
const pythonLike = normalizePythonLikeJson(trimmed);
|
|
296
|
+
if (pythonLike) {
|
|
297
|
+
const parsed = tryParseJson(pythonLike);
|
|
298
|
+
if (parsed) {
|
|
299
|
+
return parsed;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
258
302
|
const closed = closeJsonContainerSuffix(trimmed);
|
|
259
303
|
if (closed) {
|
|
260
304
|
const parsed = tryParseJson(closed);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botbotgo/agent-harness",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.357",
|
|
4
4
|
"description": "Workspace runtime for multi-agent applications",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
"main": "./dist/index.js",
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
10
10
|
"bin": {
|
|
11
|
-
"agent-harness": "
|
|
12
|
-
"botbotgo": "
|
|
11
|
+
"agent-harness": "dist/cli.js",
|
|
12
|
+
"botbotgo": "dist/cli.js"
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
15
15
|
"dist"
|