@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.
@@ -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 summarizePlanStateTerminalTransitions(previousPlanState, nextPlanState) {
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 [`TODO ${label}: ${item.content}.`];
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
- for (const item of await emitPlanStateUpdate(options, currentAgentId, mergedPlanState)) {
660
- yield item;
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
- for (const commentary of summarizePlanStateTerminalTransitions(previousPlanState, mergedPlanState)) {
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
- for (const item of await emitPlanStateUpdate(options, currentAgentId, mergedPlanState)) {
822
- yield item;
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
- for (const commentary of summarizePlanStateTerminalTransitions(previousPlanState, mergedPlanState)) {
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
- ? readTerminalStructuredStatus(normalizedChunk.output)
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
- for (const item of await emitPlanStateUpdate(options, currentAgentId, reconciledPlanState)) {
845
- yield item;
846
- }
847
- for (const commentary of summarizePlanStateTerminalTransitions(previousPlanState, reconciledPlanState)) {
848
- yield* emitCommentary(commentary);
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(reconciledPlanState);
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
- for (const item of await emitPlanStateUpdate(options, currentAgentId, mergedPlanState)) {
923
- yield item;
924
- }
925
- for (const commentary of summarizePlanStateTerminalTransitions(previousPlanState, mergedPlanState)) {
926
- yield* emitCommentary(commentary);
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(mergedPlanState);
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 = readTerminalStructuredStatus(actual.structuredResponse);
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
- for (const item of await emitPlanStateUpdate(options, currentAgentId, reconciledPlanState)) {
945
- yield item;
946
- }
947
- for (const commentary of summarizePlanStateTerminalTransitions(previousPlanState, reconciledPlanState)) {
948
- yield* emitCommentary(commentary);
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(reconciledPlanState);
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
- for (const item of await emitPlanStateUpdate(options, currentAgentId, reconciledPlanState)) {
967
- yield item;
968
- }
969
- for (const commentary of summarizePlanStateTerminalTransitions(previousPlanState, reconciledPlanState)) {
970
- yield* emitCommentary(commentary);
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(reconciledPlanState);
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, "completed", {
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: "completed",
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 = readTerminalStructuredStatus(deterministicToolEvidenceOutput);
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
- for (const item of await emitPlanStateUpdate(options, currentAgentId, reconciledPlanState)) {
1035
- yield item;
1036
- }
1037
- for (const commentary of summarizePlanStateTerminalTransitions(previousPlanState, reconciledPlanState)) {
1038
- yield* emitCommentary(commentary);
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(reconciledPlanState);
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 completedEvent = await options.setRequestStateAndEmit(options.sessionId, options.requestId, 6, "completed", {
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: "completed",
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 (!shouldRequireVisibleTodoPlan(params.request) || hasPlanEvidence) {
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: {