@botbotgo/agent-harness 0.0.345 → 0.0.347
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/contracts/runtime-requests.d.ts +1 -0
- package/dist/contracts/workspace.d.ts +4 -0
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/resources/prompts/runtime/delegated-task-failure-recovery.md +8 -0
- package/dist/runtime/adapter/flow/stream-runtime.js +50 -17
- package/dist/runtime/adapter/invocation-result.js +49 -5
- package/dist/runtime/adapter/local-tool-invocation.js +5 -0
- package/dist/runtime/adapter/stream-event-projection.js +3 -1
- package/dist/runtime/adapter/terminal-status.d.ts +4 -0
- package/dist/runtime/adapter/terminal-status.js +67 -0
- package/dist/runtime/agent-runtime-adapter.js +51 -37
- package/dist/runtime/agent-runtime-assembly.d.ts +10 -0
- package/dist/runtime/agent-runtime-assembly.js +68 -0
- package/dist/runtime/harness/run/stream-run.js +143 -75
- package/dist/runtime/parsing/output-recovery.d.ts +2 -1
- package/dist/runtime/parsing/output-recovery.js +2 -25
- package/dist/runtime/prompts/runtime-prompts.d.ts +1 -0
- package/dist/runtime/prompts/runtime-prompts.js +1 -0
- package/dist/workspace/agent-binding-compiler.js +11 -0
- package/dist/workspace/framework-contract-validation.js +122 -26
- package/dist/workspace/object-loader.js +3 -0
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ import { MemorySaver } from "@langchain/langgraph";
|
|
|
2
2
|
import { UPSTREAM_REQUEST_CONFIG_KEY, UPSTREAM_SESSION_CONFIG_KEY } from "./adapter/upstream-configurable-keys.js";
|
|
3
3
|
import { asStructuredExecutableTool } from "./adapter/tool/resolved-tool.js";
|
|
4
4
|
import { compileInterruptOn } from "./adapter/tool/interrupt-policy.js";
|
|
5
|
+
import { readSkillMetadata } from "./skills/skill-metadata.js";
|
|
5
6
|
import { getBindingBackendConfig, getBindingExecutionKind, getBindingExecutionParams, getBindingInterruptCompatibilityRules, getBindingMemorySources, getBindingMiddlewareConfigs, getBindingPrimaryTools, getBindingSkills, getBindingStoreConfig, } from "./support/compiled-binding.js";
|
|
6
7
|
export const AGENT_INTERRUPT_SENTINEL_PREFIX = "__agent_harness_interrupt__:";
|
|
7
8
|
export const DEFAULT_DEEPAGENT_RECURSION_LIMIT = 100;
|
|
@@ -37,6 +38,67 @@ export function materializeModelExposedBuiltinMiddlewareTools(input) {
|
|
|
37
38
|
}
|
|
38
39
|
return tools;
|
|
39
40
|
}
|
|
41
|
+
function formatCapabilityLine(item) {
|
|
42
|
+
const description = typeof item.description === "string" && item.description.length > 0
|
|
43
|
+
? `: ${item.description}`
|
|
44
|
+
: "";
|
|
45
|
+
return `- ${JSON.stringify(item.name)}${description}`;
|
|
46
|
+
}
|
|
47
|
+
function buildSkillCatalog(skillPaths) {
|
|
48
|
+
return skillPaths.map((skillPath) => {
|
|
49
|
+
const metadata = readSkillMetadata(skillPath);
|
|
50
|
+
return {
|
|
51
|
+
name: metadata.name,
|
|
52
|
+
...(metadata.description ? { description: metadata.description } : {}),
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
export function buildDeepAgentSystemPromptWithCapabilityHierarchy(input) {
|
|
57
|
+
const basePrompt = typeof input.systemPrompt === "string" ? input.systemPrompt : undefined;
|
|
58
|
+
const skills = buildSkillCatalog(input.skills ?? []);
|
|
59
|
+
const tools = input.tools ?? [];
|
|
60
|
+
if (input.subagents.length === 0 && skills.length === 0 && tools.length === 0) {
|
|
61
|
+
return input.systemPrompt;
|
|
62
|
+
}
|
|
63
|
+
const catalogPrompt = [
|
|
64
|
+
"Capability selection hierarchy:",
|
|
65
|
+
"1. If the current request fits an available subagent, delegate with the task tool before using local skills or raw tools.",
|
|
66
|
+
"2. If you are the selected agent and an available skill fits the request, read and follow that skill before calling raw tools.",
|
|
67
|
+
"3. Use raw tools as execution primitives for the selected agent or skill, or when no listed skill applies.",
|
|
68
|
+
"Keep each selection inside the selected capability's described responsibility boundary.",
|
|
69
|
+
"If no listed subagent, skill, or tool can responsibly handle the request, do not invent a path. Return a terminal response with status \"refused\" and explain the missing capability.",
|
|
70
|
+
"If a selected capability cannot complete after using its available tools, return a terminal response with status \"blocked\" or \"failed\" and include the blocker evidence.",
|
|
71
|
+
...(input.subagents.length > 0
|
|
72
|
+
? [
|
|
73
|
+
"",
|
|
74
|
+
"Available subagents for task delegation:",
|
|
75
|
+
...input.subagents.map(formatCapabilityLine),
|
|
76
|
+
"",
|
|
77
|
+
"When using the task tool, set subagent_type to exactly one of the listed subagent names. Do not create, translate, alias, or modify subagent names.",
|
|
78
|
+
]
|
|
79
|
+
: [
|
|
80
|
+
"",
|
|
81
|
+
"No configured specialist subagents are available for this agent. Do not use task delegation for role-internal work; select a skill first, then tools.",
|
|
82
|
+
]),
|
|
83
|
+
...(skills.length > 0
|
|
84
|
+
? [
|
|
85
|
+
"",
|
|
86
|
+
"Available skills for this agent:",
|
|
87
|
+
...skills.map(formatCapabilityLine),
|
|
88
|
+
]
|
|
89
|
+
: []),
|
|
90
|
+
...(tools.length > 0
|
|
91
|
+
? [
|
|
92
|
+
"",
|
|
93
|
+
"Raw tools available to this agent:",
|
|
94
|
+
...tools.map(formatCapabilityLine),
|
|
95
|
+
]
|
|
96
|
+
: []),
|
|
97
|
+
"",
|
|
98
|
+
].join("\n");
|
|
99
|
+
return [basePrompt, catalogPrompt].filter((part) => typeof part === "string" && part.length > 0).join("\n\n");
|
|
100
|
+
}
|
|
101
|
+
export const buildDeepAgentSystemPromptWithSubagentCatalog = buildDeepAgentSystemPromptWithCapabilityHierarchy;
|
|
40
102
|
export function resolveRunnableCheckpointer(options, binding) {
|
|
41
103
|
return options.checkpointerResolver ? options.checkpointerResolver(binding) : new MemorySaver();
|
|
42
104
|
}
|
|
@@ -146,6 +208,12 @@ export function buildDeepAgentCreateParams(input) {
|
|
|
146
208
|
]);
|
|
147
209
|
return {
|
|
148
210
|
...upstreamParams,
|
|
211
|
+
systemPrompt: buildDeepAgentSystemPromptWithSubagentCatalog({
|
|
212
|
+
systemPrompt: upstreamParams.systemPrompt,
|
|
213
|
+
subagents: input.resolvedSubagents,
|
|
214
|
+
skills: input.resolvedSkills,
|
|
215
|
+
tools: getBindingPrimaryTools(input.binding),
|
|
216
|
+
}),
|
|
149
217
|
skills: input.resolvedSkills,
|
|
150
218
|
model: input.resolvedModel,
|
|
151
219
|
tools: input.resolvedTools,
|
|
@@ -2,6 +2,7 @@ import { resolveDeterministicFinalOutput, } from "../../adapter/invocation-resul
|
|
|
2
2
|
import { AGENT_INTERRUPT_SENTINEL_PREFIX, RuntimeOperationTimeoutError } from "../../agent-runtime-adapter.js";
|
|
3
3
|
import { ExecutionReconciliationError } from "../../adapter/flow/stream-runtime.js";
|
|
4
4
|
import { buildRequestPlanState, summarizeBuiltinWriteTodosArgs } from "../../adapter/runtime-adapter-support.js";
|
|
5
|
+
import { mapTerminalStatusToPlanItemStatus, mapTerminalStatusToRequestState, readTerminalExecutionStatus, } from "../../adapter/terminal-status.js";
|
|
5
6
|
import { sanitizeVisibleText } from "../../parsing/output-parsing.js";
|
|
6
7
|
import { describeRuntimeError, renderRuntimeFailure, renderToolFailure } from "../../support/harness-support.js";
|
|
7
8
|
import { getBindingPrimaryModel } from "../../support/compiled-binding.js";
|
|
@@ -37,27 +38,6 @@ function planStateHasActiveItems(planState) {
|
|
|
37
38
|
}
|
|
38
39
|
return planState.summary.pending > 0 || planState.summary.inProgress > 0;
|
|
39
40
|
}
|
|
40
|
-
function readTerminalStructuredStatus(value) {
|
|
41
|
-
if (typeof value === "string") {
|
|
42
|
-
try {
|
|
43
|
-
return readTerminalStructuredStatus(JSON.parse(value));
|
|
44
|
-
}
|
|
45
|
-
catch {
|
|
46
|
-
return /^\s*Status:\s*completed\b/im.test(value) ? "completed" : null;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
if (typeof value !== "object" || value === null) {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
const typed = value;
|
|
53
|
-
if (typed.status === "completed") {
|
|
54
|
-
return typed.status;
|
|
55
|
-
}
|
|
56
|
-
return (readTerminalStructuredStatus(typed.structuredResponse)
|
|
57
|
-
?? readTerminalStructuredStatus(typed.content)
|
|
58
|
-
?? readTerminalStructuredStatus(typed.output)
|
|
59
|
-
?? readTerminalStructuredStatus(typed.data));
|
|
60
|
-
}
|
|
61
41
|
function isSubstantiveTerminalAssistantOutput(value) {
|
|
62
42
|
const normalized = sanitizeVisibleText(value).trim();
|
|
63
43
|
if (normalized.length < 80) {
|
|
@@ -372,7 +352,7 @@ function summarizePlanState(planState) {
|
|
|
372
352
|
const suffix = planState.items.length > items.length ? [` ... ${planState.items.length - items.length} more`] : [];
|
|
373
353
|
return ["TODO", ...items, ...suffix].join("\n");
|
|
374
354
|
}
|
|
375
|
-
function
|
|
355
|
+
function summarizePlanStateTerminalTransitionEntries(previousPlanState, nextPlanState) {
|
|
376
356
|
const previousByKey = new Map((previousPlanState?.items ?? []).map((item) => [normalizePlanItemKey(item), item]));
|
|
377
357
|
const terminalLabel = (status) => {
|
|
378
358
|
switch (status) {
|
|
@@ -395,9 +375,70 @@ function summarizePlanStateTerminalTransitions(previousPlanState, nextPlanState)
|
|
|
395
375
|
if (previousStatus === item.status) {
|
|
396
376
|
return [];
|
|
397
377
|
}
|
|
398
|
-
return [
|
|
378
|
+
return [{
|
|
379
|
+
key: normalizePlanItemKey(item),
|
|
380
|
+
text: `TODO ${label}: ${item.content}.`,
|
|
381
|
+
item,
|
|
382
|
+
}];
|
|
399
383
|
});
|
|
400
384
|
}
|
|
385
|
+
function buildPlanStateProgression(previousPlanState, nextPlanState) {
|
|
386
|
+
if (!previousPlanState) {
|
|
387
|
+
return [{ planState: nextPlanState }];
|
|
388
|
+
}
|
|
389
|
+
const terminalEntries = summarizePlanStateTerminalTransitionEntries(previousPlanState, nextPlanState);
|
|
390
|
+
if (terminalEntries.length === 0) {
|
|
391
|
+
return [{ planState: nextPlanState }];
|
|
392
|
+
}
|
|
393
|
+
const mergedPlanState = mergePartialPlanState(previousPlanState, nextPlanState);
|
|
394
|
+
const workingItems = [];
|
|
395
|
+
const workingItemByKey = new Map();
|
|
396
|
+
const previousItems = previousPlanState?.items ?? [];
|
|
397
|
+
const nextItems = mergedPlanState?.items ?? [];
|
|
398
|
+
for (const item of previousItems) {
|
|
399
|
+
workingItemByKey.set(normalizePlanItemKey(item), workingItems.length);
|
|
400
|
+
workingItems.push({ ...item });
|
|
401
|
+
}
|
|
402
|
+
for (const item of nextItems) {
|
|
403
|
+
const key = normalizePlanItemKey(item);
|
|
404
|
+
const index = workingItemByKey.get(key);
|
|
405
|
+
if (index === undefined) {
|
|
406
|
+
workingItemByKey.set(key, workingItems.length);
|
|
407
|
+
workingItems.push({ ...item });
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
const seenTransitionKeys = new Set();
|
|
411
|
+
const result = [];
|
|
412
|
+
for (const entry of terminalEntries) {
|
|
413
|
+
if (!entry.item || seenTransitionKeys.has(entry.key)) {
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
seenTransitionKeys.add(entry.key);
|
|
417
|
+
const index = workingItems.findIndex((item) => normalizePlanItemKey(item) === entry.key);
|
|
418
|
+
const nextItem = nextPlanState.items.find((item) => normalizePlanItemKey(item) === entry.key);
|
|
419
|
+
if (!nextItem) {
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
if (index >= 0) {
|
|
423
|
+
workingItems[index] = { ...workingItems[index], ...nextItem };
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
workingItems.push({ ...nextItem });
|
|
427
|
+
}
|
|
428
|
+
result.push({
|
|
429
|
+
planState: {
|
|
430
|
+
...nextPlanState,
|
|
431
|
+
items: workingItems.map((item) => ({ ...item })),
|
|
432
|
+
summary: recomputePlanSummary(workingItems),
|
|
433
|
+
},
|
|
434
|
+
commentary: entry.text,
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
if (result.length === 0) {
|
|
438
|
+
return [{ planState: nextPlanState }];
|
|
439
|
+
}
|
|
440
|
+
return result;
|
|
441
|
+
}
|
|
401
442
|
function createSurfaceCommentary(surfaceItem) {
|
|
402
443
|
const name = normalizeCommentaryText(surfaceItem.name);
|
|
403
444
|
if (!name) {
|
|
@@ -656,13 +697,16 @@ export async function* streamHarnessRun(options) {
|
|
|
656
697
|
planStateVersion = mergedPlanState.version;
|
|
657
698
|
lastPlanStateSignature = signature;
|
|
658
699
|
currentPlanState = mergedPlanState;
|
|
659
|
-
|
|
660
|
-
|
|
700
|
+
const progression = buildPlanStateProgression(previousPlanState, currentPlanState);
|
|
701
|
+
for (const progressionStep of progression) {
|
|
702
|
+
for (const item of await emitPlanStateUpdate(options, currentAgentId, progressionStep.planState)) {
|
|
703
|
+
yield item;
|
|
704
|
+
}
|
|
705
|
+
if (progressionStep.commentary) {
|
|
706
|
+
yield* emitCommentary(progressionStep.commentary);
|
|
707
|
+
}
|
|
661
708
|
}
|
|
662
|
-
|
|
663
|
-
yield* emitCommentary(commentary);
|
|
664
|
-
}
|
|
665
|
-
const commentary = summarizePlanState(mergedPlanState);
|
|
709
|
+
const commentary = summarizePlanState(currentPlanState);
|
|
666
710
|
if (commentary) {
|
|
667
711
|
yield* emitCommentary(commentary);
|
|
668
712
|
}
|
|
@@ -818,36 +862,42 @@ export async function* streamHarnessRun(options) {
|
|
|
818
862
|
const previousPlanState = currentPlanState;
|
|
819
863
|
lastPlanStateSignature = signature;
|
|
820
864
|
currentPlanState = mergedPlanState;
|
|
821
|
-
|
|
822
|
-
|
|
865
|
+
const progression = buildPlanStateProgression(previousPlanState, currentPlanState);
|
|
866
|
+
for (const progressionStep of progression) {
|
|
867
|
+
for (const item of await emitPlanStateUpdate(options, currentAgentId, progressionStep.planState)) {
|
|
868
|
+
yield item;
|
|
869
|
+
}
|
|
870
|
+
if (progressionStep.commentary) {
|
|
871
|
+
yield* emitCommentary(progressionStep.commentary);
|
|
872
|
+
}
|
|
823
873
|
}
|
|
824
|
-
|
|
825
|
-
yield* emitCommentary(commentary);
|
|
826
|
-
}
|
|
827
|
-
const commentary = summarizePlanState(mergedPlanState);
|
|
874
|
+
const commentary = summarizePlanState(currentPlanState);
|
|
828
875
|
if (commentary) {
|
|
829
876
|
yield* emitCommentary(commentary);
|
|
830
877
|
}
|
|
831
878
|
}
|
|
832
879
|
}
|
|
833
880
|
const terminalStructuredStatus = normalizedChunk.toolName === "task"
|
|
834
|
-
?
|
|
881
|
+
? readTerminalExecutionStatus(normalizedChunk.output)
|
|
835
882
|
: null;
|
|
836
883
|
if (terminalStructuredStatus && currentPlanState && planStateHasActiveItems(currentPlanState)) {
|
|
837
|
-
const reconciledPlanState = reconcilePlanStateToTerminalStatus(currentPlanState, terminalStructuredStatus, new Date().toISOString());
|
|
884
|
+
const reconciledPlanState = reconcilePlanStateToTerminalStatus(currentPlanState, mapTerminalStatusToPlanItemStatus(terminalStructuredStatus), new Date().toISOString());
|
|
838
885
|
const signature = buildPlanStateSignature(reconciledPlanState);
|
|
839
886
|
if (signature !== lastPlanStateSignature) {
|
|
840
887
|
const previousPlanState = currentPlanState;
|
|
841
888
|
planStateVersion = reconciledPlanState.version;
|
|
842
889
|
lastPlanStateSignature = signature;
|
|
843
890
|
currentPlanState = reconciledPlanState;
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
891
|
+
const progression = buildPlanStateProgression(previousPlanState, currentPlanState);
|
|
892
|
+
for (const progressionStep of progression) {
|
|
893
|
+
for (const item of await emitPlanStateUpdate(options, currentAgentId, progressionStep.planState)) {
|
|
894
|
+
yield item;
|
|
895
|
+
}
|
|
896
|
+
if (progressionStep.commentary) {
|
|
897
|
+
yield* emitCommentary(progressionStep.commentary);
|
|
898
|
+
}
|
|
849
899
|
}
|
|
850
|
-
const commentary = summarizePlanState(
|
|
900
|
+
const commentary = summarizePlanState(currentPlanState);
|
|
851
901
|
if (commentary) {
|
|
852
902
|
yield* emitCommentary(commentary);
|
|
853
903
|
}
|
|
@@ -919,35 +969,41 @@ export async function* streamHarnessRun(options) {
|
|
|
919
969
|
planStateVersion = mergedPlanState.version;
|
|
920
970
|
lastPlanStateSignature = signature;
|
|
921
971
|
currentPlanState = mergedPlanState;
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
972
|
+
const progression = buildPlanStateProgression(previousPlanState, currentPlanState);
|
|
973
|
+
for (const progressionStep of progression) {
|
|
974
|
+
for (const item of await emitPlanStateUpdate(options, currentAgentId, progressionStep.planState)) {
|
|
975
|
+
yield item;
|
|
976
|
+
}
|
|
977
|
+
if (progressionStep.commentary) {
|
|
978
|
+
yield* emitCommentary(progressionStep.commentary);
|
|
979
|
+
}
|
|
927
980
|
}
|
|
928
|
-
const commentary = summarizePlanState(
|
|
981
|
+
const commentary = summarizePlanState(currentPlanState);
|
|
929
982
|
if (commentary) {
|
|
930
983
|
yield* emitCommentary(commentary);
|
|
931
984
|
}
|
|
932
985
|
}
|
|
933
986
|
}
|
|
934
987
|
currentPlanState = await refreshPlanStateFromPersistence(options, currentPlanState);
|
|
935
|
-
const terminalStructuredStatus =
|
|
988
|
+
const terminalStructuredStatus = readTerminalExecutionStatus(actual.structuredResponse);
|
|
936
989
|
if (terminalStructuredStatus && currentPlanState && planStateHasActiveItems(currentPlanState)) {
|
|
937
|
-
const reconciledPlanState = reconcilePlanStateToTerminalStatus(currentPlanState, terminalStructuredStatus, new Date().toISOString());
|
|
990
|
+
const reconciledPlanState = reconcilePlanStateToTerminalStatus(currentPlanState, mapTerminalStatusToPlanItemStatus(terminalStructuredStatus), new Date().toISOString());
|
|
938
991
|
const signature = buildPlanStateSignature(reconciledPlanState);
|
|
939
992
|
if (signature !== lastPlanStateSignature) {
|
|
940
993
|
const previousPlanState = currentPlanState;
|
|
941
994
|
planStateVersion = reconciledPlanState.version;
|
|
942
995
|
lastPlanStateSignature = signature;
|
|
943
996
|
currentPlanState = reconciledPlanState;
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
997
|
+
const progression = buildPlanStateProgression(previousPlanState, currentPlanState);
|
|
998
|
+
for (const progressionStep of progression) {
|
|
999
|
+
for (const item of await emitPlanStateUpdate(options, currentAgentId, progressionStep.planState)) {
|
|
1000
|
+
yield item;
|
|
1001
|
+
}
|
|
1002
|
+
if (progressionStep.commentary) {
|
|
1003
|
+
yield* emitCommentary(progressionStep.commentary);
|
|
1004
|
+
}
|
|
949
1005
|
}
|
|
950
|
-
const commentary = summarizePlanState(
|
|
1006
|
+
const commentary = summarizePlanState(currentPlanState);
|
|
951
1007
|
if (commentary) {
|
|
952
1008
|
yield* emitCommentary(commentary);
|
|
953
1009
|
}
|
|
@@ -963,13 +1019,16 @@ export async function* streamHarnessRun(options) {
|
|
|
963
1019
|
planStateVersion = reconciledPlanState.version;
|
|
964
1020
|
lastPlanStateSignature = signature;
|
|
965
1021
|
currentPlanState = reconciledPlanState;
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
1022
|
+
const progression = buildPlanStateProgression(previousPlanState, currentPlanState);
|
|
1023
|
+
for (const progressionStep of progression) {
|
|
1024
|
+
for (const item of await emitPlanStateUpdate(options, currentAgentId, progressionStep.planState)) {
|
|
1025
|
+
yield item;
|
|
1026
|
+
}
|
|
1027
|
+
if (progressionStep.commentary) {
|
|
1028
|
+
yield* emitCommentary(progressionStep.commentary);
|
|
1029
|
+
}
|
|
971
1030
|
}
|
|
972
|
-
const commentary = summarizePlanState(
|
|
1031
|
+
const commentary = summarizePlanState(currentPlanState);
|
|
973
1032
|
if (commentary) {
|
|
974
1033
|
yield* emitCommentary(commentary);
|
|
975
1034
|
}
|
|
@@ -996,8 +1055,10 @@ export async function* streamHarnessRun(options) {
|
|
|
996
1055
|
content: assistantOutput,
|
|
997
1056
|
};
|
|
998
1057
|
}
|
|
1058
|
+
const terminalStatus = readTerminalExecutionStatus(assistantOutput);
|
|
1059
|
+
const terminalRequestState = mapTerminalStatusToRequestState(terminalStatus);
|
|
999
1060
|
await options.appendAssistantMessage(options.sessionId, options.requestId, assistantOutput);
|
|
1000
|
-
const completedEvent = await options.setRequestStateAndEmit(options.sessionId, options.requestId, 6,
|
|
1061
|
+
const completedEvent = await options.setRequestStateAndEmit(options.sessionId, options.requestId, 6, terminalRequestState, {
|
|
1001
1062
|
previousState: "running",
|
|
1002
1063
|
});
|
|
1003
1064
|
yield {
|
|
@@ -1010,9 +1071,10 @@ export async function* streamHarnessRun(options) {
|
|
|
1010
1071
|
sessionId: options.sessionId,
|
|
1011
1072
|
requestId: options.requestId,
|
|
1012
1073
|
agentId: currentAgentId,
|
|
1013
|
-
state:
|
|
1074
|
+
state: terminalRequestState,
|
|
1014
1075
|
output: assistantOutput,
|
|
1015
1076
|
finalMessageText: assistantOutput,
|
|
1077
|
+
...(terminalStatus ? { metadata: { terminalStatus } } : {}),
|
|
1016
1078
|
},
|
|
1017
1079
|
};
|
|
1018
1080
|
}
|
|
@@ -1022,22 +1084,25 @@ export async function* streamHarnessRun(options) {
|
|
|
1022
1084
|
executedToolResults,
|
|
1023
1085
|
});
|
|
1024
1086
|
if (!assistantOutput && sawSuccessfulToolResult && deterministicToolEvidenceOutput) {
|
|
1025
|
-
const terminalStructuredStatus =
|
|
1087
|
+
const terminalStructuredStatus = readTerminalExecutionStatus(deterministicToolEvidenceOutput);
|
|
1026
1088
|
if (terminalStructuredStatus && currentPlanState && planStateHasActiveItems(currentPlanState)) {
|
|
1027
|
-
const reconciledPlanState = reconcilePlanStateToTerminalStatus(currentPlanState, terminalStructuredStatus, new Date().toISOString());
|
|
1089
|
+
const reconciledPlanState = reconcilePlanStateToTerminalStatus(currentPlanState, mapTerminalStatusToPlanItemStatus(terminalStructuredStatus), new Date().toISOString());
|
|
1028
1090
|
const signature = buildPlanStateSignature(reconciledPlanState);
|
|
1029
1091
|
if (signature !== lastPlanStateSignature) {
|
|
1030
1092
|
const previousPlanState = currentPlanState;
|
|
1031
1093
|
planStateVersion = reconciledPlanState.version;
|
|
1032
1094
|
lastPlanStateSignature = signature;
|
|
1033
1095
|
currentPlanState = reconciledPlanState;
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1096
|
+
const progression = buildPlanStateProgression(previousPlanState, currentPlanState);
|
|
1097
|
+
for (const progressionStep of progression) {
|
|
1098
|
+
for (const item of await emitPlanStateUpdate(options, currentAgentId, progressionStep.planState)) {
|
|
1099
|
+
yield item;
|
|
1100
|
+
}
|
|
1101
|
+
if (progressionStep.commentary) {
|
|
1102
|
+
yield* emitCommentary(progressionStep.commentary);
|
|
1103
|
+
}
|
|
1039
1104
|
}
|
|
1040
|
-
const commentary = summarizePlanState(
|
|
1105
|
+
const commentary = summarizePlanState(currentPlanState);
|
|
1041
1106
|
if (commentary) {
|
|
1042
1107
|
yield* emitCommentary(commentary);
|
|
1043
1108
|
}
|
|
@@ -1055,7 +1120,9 @@ export async function* streamHarnessRun(options) {
|
|
|
1055
1120
|
agentId: currentAgentId,
|
|
1056
1121
|
content: deterministicToolEvidenceOutput,
|
|
1057
1122
|
};
|
|
1058
|
-
const
|
|
1123
|
+
const terminalStatus = readTerminalExecutionStatus(deterministicToolEvidenceOutput);
|
|
1124
|
+
const terminalRequestState = mapTerminalStatusToRequestState(terminalStatus);
|
|
1125
|
+
const completedEvent = await options.setRequestStateAndEmit(options.sessionId, options.requestId, 6, terminalRequestState, {
|
|
1059
1126
|
previousState: "running",
|
|
1060
1127
|
});
|
|
1061
1128
|
yield {
|
|
@@ -1068,11 +1135,12 @@ export async function* streamHarnessRun(options) {
|
|
|
1068
1135
|
sessionId: options.sessionId,
|
|
1069
1136
|
requestId: options.requestId,
|
|
1070
1137
|
agentId: currentAgentId,
|
|
1071
|
-
state:
|
|
1138
|
+
state: terminalRequestState,
|
|
1072
1139
|
output: deterministicToolEvidenceOutput,
|
|
1073
1140
|
finalMessageText: deterministicToolEvidenceOutput,
|
|
1074
1141
|
metadata: {
|
|
1075
1142
|
executedToolResults,
|
|
1143
|
+
...(terminalStatus ? { terminalStatus } : {}),
|
|
1076
1144
|
},
|
|
1077
1145
|
},
|
|
1078
1146
|
};
|
|
@@ -7,10 +7,10 @@ export declare function isRepairableWriteTodosEmptyFailure(error: unknown): bool
|
|
|
7
7
|
export declare function isToolCallRecoveryFailure(error: unknown): boolean;
|
|
8
8
|
export declare function isRetrySafeInvalidToolSelectionError(value: unknown): boolean;
|
|
9
9
|
export declare function shouldValidateExecutionWithoutToolEvidence(request: unknown): boolean;
|
|
10
|
-
export declare function shouldRequireVisibleTodoPlan(request: unknown): boolean;
|
|
11
10
|
export declare function resolveMissingPlanRecoveryInstruction(params: {
|
|
12
11
|
request: unknown;
|
|
13
12
|
assistantText?: string;
|
|
13
|
+
requiresPlan?: boolean;
|
|
14
14
|
hasPlanStateEvidence?: boolean;
|
|
15
15
|
hasWriteTodosEvidence?: boolean;
|
|
16
16
|
hasToolResultEvidence?: boolean;
|
|
@@ -23,6 +23,7 @@ export declare function resolveExecutionWithoutToolEvidenceTextInstruction(reque
|
|
|
23
23
|
hasPlanStateEvidence?: boolean;
|
|
24
24
|
hasOpenTaskDelegation?: boolean;
|
|
25
25
|
hasMissingDelegatedExecutionEvidence?: boolean;
|
|
26
|
+
requiresPlan?: boolean;
|
|
26
27
|
}): string | null;
|
|
27
28
|
export declare function resolveToolCallRecoveryInstruction(error: unknown): string | null;
|
|
28
29
|
export declare function appendToolRecoveryInstruction(input: unknown, instruction: string): unknown;
|
|
@@ -111,34 +111,10 @@ export function shouldValidateExecutionWithoutToolEvidence(request) {
|
|
|
111
111
|
}
|
|
112
112
|
return readSystemInstructionText(request).length > 0;
|
|
113
113
|
}
|
|
114
|
-
export function shouldRequireVisibleTodoPlan(request) {
|
|
115
|
-
const userText = readLatestUserRequestText(request).toLowerCase();
|
|
116
|
-
if (!userText) {
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
return [
|
|
120
|
-
"investigate",
|
|
121
|
-
"investigation",
|
|
122
|
-
"issue",
|
|
123
|
-
"issues",
|
|
124
|
-
"rca",
|
|
125
|
-
"root cause",
|
|
126
|
-
"go deeper",
|
|
127
|
-
"deep research",
|
|
128
|
-
"debug",
|
|
129
|
-
"排查",
|
|
130
|
-
"调查",
|
|
131
|
-
"问题",
|
|
132
|
-
"根因",
|
|
133
|
-
"故障",
|
|
134
|
-
"集群",
|
|
135
|
-
"cluster",
|
|
136
|
-
].some((keyword) => userText.includes(keyword));
|
|
137
|
-
}
|
|
138
114
|
export function resolveMissingPlanRecoveryInstruction(params) {
|
|
139
115
|
const hasPlanEvidence = params.hasWriteTodosEvidence === true
|
|
140
116
|
|| params.hasPlanStateEvidence === true;
|
|
141
|
-
if (
|
|
117
|
+
if (params.requiresPlan !== true || hasPlanEvidence) {
|
|
142
118
|
return null;
|
|
143
119
|
}
|
|
144
120
|
if (params.hasToolResultEvidence === true) {
|
|
@@ -158,6 +134,7 @@ export function resolveExecutionWithoutToolEvidenceTextInstruction(request, assi
|
|
|
158
134
|
const missingPlanRecoveryInstruction = resolveMissingPlanRecoveryInstruction({
|
|
159
135
|
request,
|
|
160
136
|
assistantText: normalizedText,
|
|
137
|
+
requiresPlan: resultEvidence.requiresPlan,
|
|
161
138
|
hasWriteTodosEvidence: resultEvidence.hasWriteTodosEvidence,
|
|
162
139
|
hasPlanStateEvidence: resultEvidence.hasIncompletePlanState === true || resultEvidence.hasPlanStateEvidence === true,
|
|
163
140
|
hasToolResultEvidence: resultEvidence.hasToolResultEvidence,
|
|
@@ -11,6 +11,7 @@ export declare const WRITE_TODOS_REQUIRED_PLAN_INSTRUCTION: string;
|
|
|
11
11
|
export declare const EXECUTION_WITH_TOOL_EVIDENCE_INSTRUCTION: string;
|
|
12
12
|
export declare const EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION: string;
|
|
13
13
|
export declare const AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION: string;
|
|
14
|
+
export declare const DELEGATED_TASK_FAILURE_RECOVERY_INSTRUCTION: string;
|
|
14
15
|
export declare const INTERNAL_RUNTIME_SPILL_PATH_INSTRUCTION: string;
|
|
15
16
|
export declare const WORKSPACE_RELATIVE_PATH_INSTRUCTION: string;
|
|
16
17
|
export declare function renderDurableMemoryContextPrompt(memoryContext: string): string;
|
|
@@ -14,6 +14,7 @@ export const WRITE_TODOS_REQUIRED_PLAN_INSTRUCTION = readRuntimePrompt("write-to
|
|
|
14
14
|
export const EXECUTION_WITH_TOOL_EVIDENCE_INSTRUCTION = readRuntimePrompt("execution-with-tool-evidence");
|
|
15
15
|
export const EXECUTION_WITH_TOOL_EVIDENCE_RETRY_INSTRUCTION = readRuntimePrompt("execution-with-tool-evidence-retry");
|
|
16
16
|
export const AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION = readRuntimePrompt("autonomous-investigation-recovery");
|
|
17
|
+
export const DELEGATED_TASK_FAILURE_RECOVERY_INSTRUCTION = readRuntimePrompt("delegated-task-failure-recovery");
|
|
17
18
|
export const INTERNAL_RUNTIME_SPILL_PATH_INSTRUCTION = readRuntimePrompt("internal-runtime-spill-path");
|
|
18
19
|
export const WORKSPACE_RELATIVE_PATH_INSTRUCTION = readRuntimePrompt("workspace-relative-path");
|
|
19
20
|
export function renderDurableMemoryContextPrompt(memoryContext) {
|
|
@@ -199,6 +199,15 @@ function resolveResponseFormat(agent) {
|
|
|
199
199
|
function resolveContextSchema(agent) {
|
|
200
200
|
return getAgentExecutionConfigValue(agent, "contextSchema");
|
|
201
201
|
}
|
|
202
|
+
function resolveExecutionContract(agent) {
|
|
203
|
+
const value = getAgentExecutionObject(agent, "executionContract");
|
|
204
|
+
if (!value) {
|
|
205
|
+
return undefined;
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
...(value.requiresPlan === true ? { requiresPlan: true } : {}),
|
|
209
|
+
};
|
|
210
|
+
}
|
|
202
211
|
function resolveCompiledMiddleware(agent, models) {
|
|
203
212
|
const middleware = getAgentExecutionConfigValue(agent, "middleware");
|
|
204
213
|
return compileMiddlewareConfigs(middleware, models, agent.id);
|
|
@@ -399,6 +408,7 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
|
|
|
399
408
|
: undefined;
|
|
400
409
|
const runtimeGovernanceDefaults = asObject(runtimeDefaults?.governance);
|
|
401
410
|
const runtimeObservabilityDefaults = asObject(runtimeDefaults?.observability);
|
|
411
|
+
const executionContract = resolveExecutionContract(agent);
|
|
402
412
|
const compiledFilesystemConfig = agent.executionMode === "langchain-v1"
|
|
403
413
|
? mergeConfigObjects(runtimeFilesystemDefaults, getAgentExecutionObject(agent, "filesystem", { executionMode: "langchain-v1" }))
|
|
404
414
|
: undefined;
|
|
@@ -417,6 +427,7 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
|
|
|
417
427
|
resilience,
|
|
418
428
|
...(runtimeGovernanceDefaults ? { governance: runtimeGovernanceDefaults } : {}),
|
|
419
429
|
...(runtimeObservabilityDefaults ? { observability: runtimeObservabilityDefaults } : {}),
|
|
430
|
+
...(executionContract ? { executionContract } : {}),
|
|
420
431
|
...(agent.executionMode === "deepagent"
|
|
421
432
|
? {
|
|
422
433
|
deepagent: {
|