@botbotgo/agent-harness 0.0.326 → 0.0.328

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.
Files changed (56) hide show
  1. package/dist/cli/chat-stream.js +33 -27
  2. package/dist/cli/main.js +30 -3
  3. package/dist/contracts/runtime-requests.d.ts +1 -2
  4. package/dist/contracts/runtime-scheduling.d.ts +1 -1
  5. package/dist/flow/flow-graph-upstream.js +3 -7
  6. package/dist/package-version.d.ts +1 -1
  7. package/dist/package-version.js +1 -1
  8. package/dist/projections/request-events.js +0 -1
  9. package/dist/resource/isolation.js +51 -10
  10. package/dist/resources/toolkit.mjs +183 -0
  11. package/dist/resources/tools/cancel_request.mjs +1 -1
  12. package/dist/resources/tools/fetch_url.mjs +1 -1
  13. package/dist/resources/tools/http_request.mjs +1 -1
  14. package/dist/resources/tools/inspect_approvals.mjs +1 -1
  15. package/dist/resources/tools/inspect_artifacts.mjs +1 -1
  16. package/dist/resources/tools/inspect_events.mjs +1 -1
  17. package/dist/resources/tools/inspect_requests.mjs +1 -1
  18. package/dist/resources/tools/inspect_sessions.mjs +1 -1
  19. package/dist/resources/tools/list_files.mjs +1 -1
  20. package/dist/resources/tools/read_artifact.mjs +1 -1
  21. package/dist/resources/tools/request_approval.mjs +1 -1
  22. package/dist/resources/tools/run_command.mjs +1 -1
  23. package/dist/resources/tools/schedule_task.mjs +1 -1
  24. package/dist/resources/tools/search_files.mjs +1 -1
  25. package/dist/resources/tools/send_message.mjs +1 -1
  26. package/dist/runtime/adapter/compat/deepagent-compat.d.ts +0 -9
  27. package/dist/runtime/adapter/compat/deepagent-compat.js +0 -22
  28. package/dist/runtime/adapter/flow/stream-runtime.d.ts +4 -0
  29. package/dist/runtime/adapter/flow/stream-runtime.js +239 -8
  30. package/dist/runtime/adapter/local-tool-invocation.js +53 -0
  31. package/dist/runtime/adapter/middleware-assembly.js +174 -29
  32. package/dist/runtime/adapter/runtime-adapter-support.js +1 -2
  33. package/dist/runtime/adapter/stream-event-projection.d.ts +17 -0
  34. package/dist/runtime/adapter/stream-event-projection.js +217 -4
  35. package/dist/runtime/adapter/tool/builtin-middleware-tools.d.ts +0 -3
  36. package/dist/runtime/adapter/tool/builtin-middleware-tools.js +37 -17
  37. package/dist/runtime/adapter/tool/resolved-tool.js +29 -3
  38. package/dist/runtime/agent-runtime-adapter.d.ts +3 -3
  39. package/dist/runtime/agent-runtime-adapter.js +12 -33
  40. package/dist/runtime/agent-runtime-assembly.d.ts +3 -21
  41. package/dist/runtime/agent-runtime-assembly.js +4 -56
  42. package/dist/runtime/harness/run/inspection.js +21 -5
  43. package/dist/runtime/harness/run/run-operations.js +2 -1
  44. package/dist/runtime/harness/run/stream-run.d.ts +3 -1
  45. package/dist/runtime/harness/run/stream-run.js +206 -30
  46. package/dist/runtime/harness.js +3 -0
  47. package/dist/runtime/parsing/output-content.js +11 -4
  48. package/dist/runtime/parsing/output-recovery.d.ts +3 -0
  49. package/dist/runtime/parsing/output-recovery.js +57 -11
  50. package/dist/runtime/parsing/output-tool-args.d.ts +4 -0
  51. package/dist/runtime/parsing/output-tool-args.js +122 -0
  52. package/dist/runtime/parsing/stream-event-parsing.js +37 -3
  53. package/dist/runtime/support/harness-support.d.ts +1 -0
  54. package/dist/runtime/support/harness-support.js +44 -2
  55. package/dist/tools.js +34 -4
  56. package/package.json +8 -8
@@ -1,4 +1,4 @@
1
- import { HumanMessage } from "@langchain/core/messages";
1
+ import { HumanMessage, SystemMessage } from "@langchain/core/messages";
2
2
  import { createMemoryMiddleware, createPatchToolCallsMiddleware, createSkillsMiddleware, createSubAgentMiddleware, createSummarizationMiddleware, StateBackend, } from "deepagents";
3
3
  import { createAgent, humanInTheLoopMiddleware } from "langchain";
4
4
  import { createBuiltinMiddlewareTools } from "./tool/builtin-middleware-tools.js";
@@ -7,9 +7,98 @@ import { extractToolFallbackContext, extractVisibleOutput } from "../parsing/out
7
7
  import { isRecord } from "../../utils/object.js";
8
8
  import { resolveDeclaredMiddleware } from "./tool/declared-middleware.js";
9
9
  import { UPSTREAM_SESSION_CONFIG_KEY } from "./upstream-configurable-keys.js";
10
- import { bindingHasLangChainSubagentSupport, bindingHasMiddlewareKind, getBindingExecutionKind, getBindingGeneralPurposeAgent, getBindingInterruptCompatibilityRules, getBindingMiddlewareConfigs, getBindingMemorySources, getBindingPrimaryModel, getBindingPrimaryTools, getBindingSkills, getBindingSubagents, getBindingTaskDescription, isDeepAgentBinding, isLangChainBinding, } from "../support/compiled-binding.js";
11
- import { applyDeepAgentDelegationPromptCompatibility, materializeDeepAgentSkillSourcePaths } from "./compat/deepagent-compat.js";
10
+ import { bindingHasLangChainSubagentSupport, bindingHasMiddlewareKind, getBindingExecutionKind, getBindingGeneralPurposeAgent, getBindingDeepAgentSubagents, getBindingInterruptCompatibilityRules, getBindingMiddlewareConfigs, getBindingMemorySources, getBindingPrimaryModel, getBindingPrimaryTools, getBindingSkills, getBindingSubagents, getBindingTaskDescription, isDeepAgentBinding, isLangChainBinding, } from "../support/compiled-binding.js";
11
+ import { materializeDeepAgentSkillSourcePaths } from "./compat/deepagent-compat.js";
12
12
  import { DEFAULT_SUBAGENT_PROMPT } from "../prompts/runtime-prompts.js";
13
+ import { AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION } from "../prompts/runtime-prompts.js";
14
+ import { createStreamEventProjectionState, projectRuntimeStreamEvent } from "./stream-event-projection.js";
15
+ const EMPTY_TOOL_NAME_MAPPING = {
16
+ originalToModelFacing: new Map(),
17
+ modelFacingToOriginal: new Map(),
18
+ };
19
+ function readPlanStateSummaryCounts(summary) {
20
+ if (typeof summary !== "object" || summary === null) {
21
+ return null;
22
+ }
23
+ const typed = summary;
24
+ const hasAny = typeof typed.pending === "number"
25
+ || typeof typed.inProgress === "number";
26
+ if (!hasAny) {
27
+ return null;
28
+ }
29
+ return {
30
+ pending: typeof typed.pending === "number" ? typed.pending : 0,
31
+ inProgress: typeof typed.inProgress === "number" ? typed.inProgress : 0,
32
+ };
33
+ }
34
+ function hasIncompletePlanTodos(value) {
35
+ if (!Array.isArray(value)) {
36
+ return null;
37
+ }
38
+ return value.some((item) => {
39
+ if (typeof item !== "object" || item === null) {
40
+ return false;
41
+ }
42
+ const status = item.status;
43
+ return status === "pending" || status === "in_progress";
44
+ });
45
+ }
46
+ function hasIncompletePlanStateInValue(value) {
47
+ if (Array.isArray(value)) {
48
+ return value.some((item) => hasIncompletePlanStateInValue(item));
49
+ }
50
+ if (typeof value !== "object" || value === null) {
51
+ return false;
52
+ }
53
+ const typed = value;
54
+ const summaryCounts = readPlanStateSummaryCounts(typed.summary);
55
+ if (summaryCounts) {
56
+ return summaryCounts.pending > 0 || summaryCounts.inProgress > 0;
57
+ }
58
+ const todoCompleteness = hasIncompletePlanTodos(typed.todos);
59
+ if (todoCompleteness !== null) {
60
+ return todoCompleteness;
61
+ }
62
+ const nestedCandidates = [
63
+ typed.summary,
64
+ typed.output,
65
+ typed.content,
66
+ typed.update,
67
+ typed.data,
68
+ typed.messages,
69
+ ];
70
+ return nestedCandidates.some((candidate) => hasIncompletePlanStateInValue(candidate));
71
+ }
72
+ function hasUnresolvedDelegatedExecution(state) {
73
+ return state.hasIncompletePlanState || state.openTaskDelegations > 0;
74
+ }
75
+ function hasMissingDelegatedToolExecutionEvidence(state, subagentHasTools) {
76
+ return subagentHasTools && !state.emittedToolResult && !state.emittedToolError;
77
+ }
78
+ function formatDelegatedExecutionBlocker(state) {
79
+ const summary = state.emittedOutput.trim();
80
+ if (summary) {
81
+ return summary;
82
+ }
83
+ if (state.emittedToolError) {
84
+ return "Delegated investigation encountered a tool failure before the plan completed.";
85
+ }
86
+ if (state.openTaskDelegations > 0) {
87
+ return "Delegated investigation did not finish before control returned to the parent agent.";
88
+ }
89
+ return "Delegated investigation ended before the plan was completed.";
90
+ }
91
+ function requiresDelegatedExecutionRecovery(state) {
92
+ return hasUnresolvedDelegatedExecution(state) || (state.emittedToolResult && !state.emittedOutput.trim());
93
+ }
94
+ const DELEGATED_FAILURE_PLAN_RECONCILIATION_INSTRUCTION = [
95
+ "Your previous attempt ended with a tool failure while the todo board still had unfinished work.",
96
+ "Do not continue broad investigation from here.",
97
+ "If the failed command had malformed arguments you can correct locally, retry that same command once.",
98
+ "Otherwise, if a todo board already exists, call write_todos again and keep only the tasks that were actually completed in this session.",
99
+ "Remove the unfinished tasks that cannot proceed until the blocker is resolved.",
100
+ "Then return a concise blocker report.",
101
+ ].join(" ");
13
102
  export function buildBuiltinTaskSubagentMiddleware(input) {
14
103
  const { selectedSubagent, builtinBackend, summarizationModel } = input;
15
104
  const defaultSubagentMiddleware = [
@@ -57,13 +146,6 @@ function buildLangChainContextMiddleware(params) {
57
146
  }
58
147
  return middleware;
59
148
  }
60
- function resolveLangChainDelegationCompatibility(params) {
61
- return applyDeepAgentDelegationPromptCompatibility(params.model, {
62
- subagents: params.subagents,
63
- generalPurposeAgent: params.generalPurposeAgent,
64
- taskDescription: params.taskDescription,
65
- });
66
- }
67
149
  export function planLangChainRuntimeExtensions(binding) {
68
150
  const primaryModel = getBindingPrimaryModel(binding);
69
151
  if (!isLangChainBinding(binding) || !primaryModel) {
@@ -71,12 +153,6 @@ export function planLangChainRuntimeExtensions(binding) {
71
153
  }
72
154
  const skills = getBindingSkills(binding);
73
155
  const memory = getBindingMemorySources(binding);
74
- const delegationCompatibility = resolveLangChainDelegationCompatibility({
75
- model: primaryModel,
76
- subagents: getBindingSubagents(binding),
77
- generalPurposeAgent: getBindingGeneralPurposeAgent(binding),
78
- taskDescription: getBindingTaskDescription(binding),
79
- });
80
156
  return {
81
157
  includePatchToolCalls: !bindingHasMiddlewareKind(binding, "patchToolCalls"),
82
158
  includeAutomaticSummarization: !bindingHasMiddlewareKind(binding, "summarization"),
@@ -86,9 +162,9 @@ export function planLangChainRuntimeExtensions(binding) {
86
162
  },
87
163
  delegation: bindingHasLangChainSubagentSupport(binding)
88
164
  ? {
89
- subagents: delegationCompatibility.subagents ?? [],
90
- generalPurposeAgent: delegationCompatibility.generalPurposeAgent,
91
- taskDescription: delegationCompatibility.taskDescription,
165
+ subagents: getBindingSubagents(binding),
166
+ generalPurposeAgent: getBindingGeneralPurposeAgent(binding),
167
+ taskDescription: getBindingTaskDescription(binding),
92
168
  interruptOn: getBindingInterruptCompatibilityRules(binding),
93
169
  }
94
170
  : undefined,
@@ -142,13 +218,18 @@ export async function invokeBuiltinTaskTool(input) {
142
218
  }
143
219
  const primaryModel = getBindingPrimaryModel(input.binding);
144
220
  const primaryTools = getBindingPrimaryTools(input.binding);
145
- const compiledSubagents = getBindingSubagents(input.binding);
221
+ const compiledSubagents = getBindingDeepAgentSubagents(input.binding)
222
+ .filter((subagent) => !("graphId" in subagent));
146
223
  if (!primaryModel) {
147
224
  throw new Error(`Agent ${input.binding.agent.id} has no deepagent params`);
148
225
  }
149
226
  const typedInput = isRecord(input.toolInput) ? input.toolInput : {};
150
- const description = typeof typedInput.description === "string" ? typedInput.description : "";
151
- const subagentType = typeof typedInput.subagent_type === "string" ? typedInput.subagent_type : "";
227
+ const description = typeof typedInput.description === "string"
228
+ ? typedInput.description
229
+ : "";
230
+ const subagentType = typeof typedInput.subagent_type === "string"
231
+ ? typedInput.subagent_type
232
+ : "";
152
233
  const builtinBackend = input.resolveBuiltinMiddlewareBackend(input.binding, input.options);
153
234
  const resolvedSubagents = await input.resolveSubagents(compiledSubagents, input.binding);
154
235
  const selectedSubagent = resolvedSubagents.find((subagent) => subagent.name === subagentType);
@@ -163,16 +244,82 @@ export async function invokeBuiltinTaskTool(input) {
163
244
  builtinBackend,
164
245
  summarizationModel,
165
246
  });
247
+ const resolvedSubagentTools = selectedSubagent.tools ?? input.resolveTools(primaryTools, input.binding);
248
+ const subagentHasTools = (resolvedSubagentTools?.length ?? 0) > 0;
166
249
  const runnable = createAgent({
167
250
  model: (selectedSubagent.model ?? resolvedHostModel),
168
- tools: (selectedSubagent.tools ?? input.resolveTools(primaryTools, input.binding)),
251
+ tools: resolvedSubagentTools,
169
252
  systemPrompt: selectedSubagent.systemPrompt ?? DEFAULT_SUBAGENT_PROMPT,
170
253
  middleware: middleware,
171
254
  responseFormat: selectedSubagent.responseFormat,
172
255
  name: selectedSubagent.name,
173
256
  description: selectedSubagent.description,
174
257
  });
175
- const result = await runnable.invoke({ messages: [new HumanMessage({ content: description })] }, { configurable: { [UPSTREAM_SESSION_CONFIG_KEY]: `${input.binding.agent.id}:builtin-task` }, ...(input.options?.context ? { context: input.options.context } : {}) });
258
+ const invokeConfig = {
259
+ configurable: { [UPSTREAM_SESSION_CONFIG_KEY]: `${input.binding.agent.id}:builtin-task` },
260
+ ...(input.options?.context ? { context: input.options.context } : {}),
261
+ };
262
+ const buildMessages = (recoveryInstruction) => ({
263
+ messages: [
264
+ ...(recoveryInstruction ? [new SystemMessage({ content: recoveryInstruction })] : []),
265
+ new HumanMessage({ content: description }),
266
+ ],
267
+ });
268
+ if (typeof runnable.streamEvents === "function") {
269
+ const runWithStreamInspection = async (recoveryInstruction) => {
270
+ const projectionState = createStreamEventProjectionState();
271
+ const events = await runnable.streamEvents(buildMessages(recoveryInstruction), invokeConfig);
272
+ for await (const event of events) {
273
+ projectRuntimeStreamEvent({
274
+ event,
275
+ allowVisibleStreamDeltas: false,
276
+ includeStateStreamOutput: false,
277
+ rootAgentId: input.binding.agent.id,
278
+ countConfiguredToolsForAgentId: (agentId) => agentId === selectedSubagent.name ? resolvedSubagentTools.length : 0,
279
+ toolNameMapping: EMPTY_TOOL_NAME_MAPPING,
280
+ primaryTools: [],
281
+ state: projectionState,
282
+ });
283
+ }
284
+ return projectionState;
285
+ };
286
+ let projectionState = await runWithStreamInspection();
287
+ if (requiresDelegatedExecutionRecovery(projectionState)) {
288
+ const recoveryInstruction = projectionState.hasIncompletePlanState && projectionState.emittedToolError
289
+ ? `${AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION}\n\n${DELEGATED_FAILURE_PLAN_RECONCILIATION_INSTRUCTION}`
290
+ : AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION;
291
+ projectionState = await runWithStreamInspection(recoveryInstruction);
292
+ }
293
+ if (requiresDelegatedExecutionRecovery(projectionState)) {
294
+ throw new Error(formatDelegatedExecutionBlocker(projectionState));
295
+ }
296
+ if (hasMissingDelegatedToolExecutionEvidence(projectionState, subagentHasTools)) {
297
+ throw new Error("Delegated investigation ended without any real tool execution evidence.");
298
+ }
299
+ if (projectionState.emittedToolError) {
300
+ const blockerMessage = projectionState.emittedOutput.trim()
301
+ || formatDelegatedExecutionBlocker(projectionState);
302
+ if (hasUnresolvedDelegatedExecution(projectionState) || !projectionState.emittedSuccessfulToolResult) {
303
+ throw new Error(blockerMessage);
304
+ }
305
+ }
306
+ if (projectionState.emittedOutput.trim()) {
307
+ return projectionState.emittedOutput.trim();
308
+ }
309
+ if (projectionState.emittedToolResult) {
310
+ throw new Error("Delegated investigation performed tool work but did not return surfaced findings.");
311
+ }
312
+ }
313
+ let result = await runnable.invoke(buildMessages(), invokeConfig);
314
+ if (hasIncompletePlanStateInValue(result)) {
315
+ result = await runnable.invoke(buildMessages(AUTONOMOUS_INVESTIGATION_RECOVERY_INSTRUCTION), invokeConfig);
316
+ }
317
+ if (hasIncompletePlanStateInValue(result)) {
318
+ throw new Error(extractVisibleOutput(result) || extractToolFallbackContext(result) || "Delegated investigation ended before the plan was completed.");
319
+ }
320
+ if (subagentHasTools) {
321
+ throw new Error("Delegated investigation ended without any real tool execution evidence.");
322
+ }
176
323
  const visibleOutput = extractVisibleOutput(result);
177
324
  const fallbackOutput = extractToolFallbackContext(result);
178
325
  return visibleOutput || fallbackOutput || JSON.stringify(result);
@@ -180,12 +327,10 @@ export async function invokeBuiltinTaskTool(input) {
180
327
  export async function resolveBuiltinMiddlewareTools(input) {
181
328
  const backend = input.resolveBuiltinMiddlewareBackend(input.binding, input.options);
182
329
  return createBuiltinMiddlewareTools(backend, {
183
- includeTaskTool: isDeepAgentBinding(input.binding),
330
+ includeTaskTool: false,
184
331
  workspaceRoot: input.binding.harnessRuntime.workspaceRoot,
185
332
  toolRuntimeContext: input.options?.toolRuntimeContext,
186
- invokeTaskTool: isDeepAgentBinding(input.binding)
187
- ? async (toolInput) => input.invokeBuiltinTaskTool(input.binding, toolInput, input.options)
188
- : undefined,
333
+ invokeTaskTool: undefined,
189
334
  });
190
335
  }
191
336
  export async function materializeAutomaticSummarizationMiddleware(input) {
@@ -214,7 +359,7 @@ export async function materializeLangChainRuntimeMiddleware(input) {
214
359
  memory: input.plan.context.memory,
215
360
  resolveFilesystemBackend: input.resolveFilesystemBackend,
216
361
  }));
217
- if (input.plan.delegation) {
362
+ if (input.plan.delegation && !isDeepAgentBinding(input.binding)) {
218
363
  runtimeMiddleware.push(createSubAgentMiddleware({
219
364
  defaultModel: (await input.resolveModel(primaryModel)),
220
365
  defaultTools: input.resolveTools(primaryTools, input.binding),
@@ -37,7 +37,6 @@ export function summarizeBuiltinWriteTodosArgs(args) {
37
37
  completed: items.filter((item) => item.status === "completed").length,
38
38
  failed: items.filter((item) => item.status === "failed").length,
39
39
  cancelled: items.filter((item) => item.status === "cancelled").length,
40
- blocked: items.filter((item) => item.status === "blocked").length,
41
40
  };
42
41
  return {
43
42
  items,
@@ -56,7 +55,7 @@ export function formatBuiltinTodoSnapshot(snapshot) {
56
55
  return "No todos tracked.";
57
56
  }
58
57
  const lines = [
59
- `Tracked ${snapshot.summary.total} todo item(s): ${snapshot.summary.pending + snapshot.summary.inProgress + snapshot.summary.blocked} pending, ${snapshot.summary.completed} completed.`,
58
+ `Tracked ${snapshot.summary.total} todo item(s): ${snapshot.summary.pending + snapshot.summary.inProgress} pending, ${snapshot.summary.completed} completed.`,
60
59
  ...snapshot.items.map((item, index) => `${index + 1}. [${item.status}] ${item.content}`),
61
60
  ];
62
61
  return truncateLines(lines);
@@ -5,6 +5,21 @@ export type StreamEventProjectionState = {
5
5
  emittedOutput: string;
6
6
  emittedToolError: boolean;
7
7
  emittedToolResult: boolean;
8
+ emittedSuccessfulToolResult: boolean;
9
+ emittedSuccessfulTaskResult: boolean;
10
+ emittedPlaceholderTaskResult: boolean;
11
+ hasFailedTaskDelegation: boolean;
12
+ emittedNonTodoToolResult: boolean;
13
+ emittedSuccessfulNonTodoToolResult: boolean;
14
+ sawDelegatedAgentWithConfiguredTools: boolean;
15
+ emittedDelegatedExecutionToolResult: boolean;
16
+ emittedSuccessfulDelegatedExecutionToolResult: boolean;
17
+ emittedDelegatedTerminalOutput: boolean;
18
+ sawPlanState: boolean;
19
+ hasIncompletePlanState: boolean;
20
+ openTaskDelegations: number;
21
+ openToolCapableTaskDelegations: number;
22
+ taskDelegationHasToolsStack: boolean[];
8
23
  seenTerminalOutputs: Set<string>;
9
24
  };
10
25
  export declare function createStreamEventProjectionState(): StreamEventProjectionState;
@@ -12,6 +27,8 @@ export declare function projectRuntimeStreamEvent(params: {
12
27
  event: unknown;
13
28
  allowVisibleStreamDeltas: boolean;
14
29
  includeStateStreamOutput: boolean;
30
+ rootAgentId?: string;
31
+ countConfiguredToolsForAgentId?: (agentId: string) => number;
15
32
  toolNameMapping: ToolNameMapping;
16
33
  primaryTools: CompiledTool[];
17
34
  state: StreamEventProjectionState;
@@ -6,15 +6,190 @@ export function createStreamEventProjectionState() {
6
6
  emittedOutput: "",
7
7
  emittedToolError: false,
8
8
  emittedToolResult: false,
9
+ emittedSuccessfulToolResult: false,
10
+ emittedSuccessfulTaskResult: false,
11
+ emittedPlaceholderTaskResult: false,
12
+ hasFailedTaskDelegation: false,
13
+ emittedNonTodoToolResult: false,
14
+ emittedSuccessfulNonTodoToolResult: false,
15
+ sawDelegatedAgentWithConfiguredTools: false,
16
+ emittedDelegatedExecutionToolResult: false,
17
+ emittedSuccessfulDelegatedExecutionToolResult: false,
18
+ emittedDelegatedTerminalOutput: false,
19
+ sawPlanState: false,
20
+ hasIncompletePlanState: false,
21
+ openTaskDelegations: 0,
22
+ openToolCapableTaskDelegations: 0,
23
+ taskDelegationHasToolsStack: [],
9
24
  seenTerminalOutputs: new Set(),
10
25
  };
11
26
  }
27
+ function readSummaryCounts(summary) {
28
+ if (typeof summary !== "object" || summary === null) {
29
+ return null;
30
+ }
31
+ const typed = summary;
32
+ const hasAnyCountField = typeof typed.pending === "number"
33
+ || typeof typed.inProgress === "number";
34
+ if (!hasAnyCountField) {
35
+ return null;
36
+ }
37
+ return {
38
+ pending: typeof typed.pending === "number" ? typed.pending : 0,
39
+ inProgress: typeof typed.inProgress === "number" ? typed.inProgress : 0,
40
+ };
41
+ }
42
+ function hasIncompleteTodosArray(value) {
43
+ if (!Array.isArray(value)) {
44
+ return null;
45
+ }
46
+ return value.some((item) => {
47
+ if (typeof item !== "object" || item === null) {
48
+ return false;
49
+ }
50
+ const status = item.status;
51
+ return status === "pending" || status === "in_progress";
52
+ });
53
+ }
54
+ function getPlanStateCompleteness(value) {
55
+ if (typeof value !== "object" || value === null) {
56
+ return null;
57
+ }
58
+ const typed = value;
59
+ const summaryCounts = readSummaryCounts(typed.summary);
60
+ if (summaryCounts) {
61
+ return summaryCounts.pending > 0 || summaryCounts.inProgress > 0;
62
+ }
63
+ if (typeof typed.summary === "object" && typed.summary !== null) {
64
+ const nestedSummary = getPlanStateCompleteness(typed.summary);
65
+ if (nestedSummary !== null) {
66
+ return nestedSummary;
67
+ }
68
+ }
69
+ const directTodos = hasIncompleteTodosArray(typed.todos);
70
+ if (directTodos !== null) {
71
+ return directTodos;
72
+ }
73
+ if (typeof typed.update === "object" && typed.update !== null) {
74
+ const nestedTodos = hasIncompleteTodosArray(typed.update.todos);
75
+ if (nestedTodos !== null) {
76
+ return nestedTodos;
77
+ }
78
+ }
79
+ if (typeof typed.output === "object" && typed.output !== null) {
80
+ const nestedOutput = getPlanStateCompleteness(typed.output);
81
+ if (nestedOutput !== null) {
82
+ return nestedOutput;
83
+ }
84
+ }
85
+ if (typeof typed.data === "object" && typed.data !== null) {
86
+ const nestedData = getPlanStateCompleteness(typed.data);
87
+ if (nestedData !== null) {
88
+ return nestedData;
89
+ }
90
+ }
91
+ return null;
92
+ }
93
+ function parseMaybeJsonString(value) {
94
+ const trimmed = value.trim();
95
+ if (!trimmed || (!trimmed.startsWith("{") && !trimmed.startsWith("["))) {
96
+ return value;
97
+ }
98
+ try {
99
+ return JSON.parse(trimmed);
100
+ }
101
+ catch {
102
+ return value;
103
+ }
104
+ }
105
+ function unwrapPossibleToolInput(value) {
106
+ if (typeof value === "string") {
107
+ return parseMaybeJsonString(value);
108
+ }
109
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
110
+ return value;
111
+ }
112
+ const typed = value;
113
+ if (typed.args !== undefined) {
114
+ return unwrapPossibleToolInput(typed.args);
115
+ }
116
+ if (typed.input !== undefined) {
117
+ return unwrapPossibleToolInput(typed.input);
118
+ }
119
+ return value;
120
+ }
121
+ function readTaskSubagentType(value) {
122
+ const unwrapped = unwrapPossibleToolInput(value);
123
+ if (typeof unwrapped !== "object" || unwrapped === null || Array.isArray(unwrapped)) {
124
+ return null;
125
+ }
126
+ const typed = unwrapped;
127
+ return typeof typed.subagent_type === "string" && typed.subagent_type.trim().length > 0
128
+ ? typed.subagent_type.trim()
129
+ : null;
130
+ }
131
+ function isUpstreamPlaceholderTaskResult(value) {
132
+ if (typeof value === "string") {
133
+ return value.trim() === "Task completed";
134
+ }
135
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
136
+ return false;
137
+ }
138
+ const typed = value;
139
+ const messages = Array.isArray(typed.update?.messages) ? typed.update.messages : [];
140
+ if (messages.length !== 1) {
141
+ return false;
142
+ }
143
+ const message = messages[0];
144
+ return typed.lg_name === "Command"
145
+ && typed.lc_direct_tool_output === true
146
+ && message?.name === "task"
147
+ && message?.type === "tool"
148
+ && typeof message?.tool_call_id === "string"
149
+ && message?.content === "Task completed";
150
+ }
151
+ function updateDelegationState(state, event, countConfiguredToolsForAgentId) {
152
+ if (typeof event !== "object" || event === null) {
153
+ return;
154
+ }
155
+ const typed = event;
156
+ const eventName = typeof typed.event === "string" ? typed.event : "";
157
+ const toolName = typeof typed.name === "string" ? typed.name : "";
158
+ const runType = typeof typed.run_type === "string" ? typed.run_type : "";
159
+ const isTaskStart = toolName === "task" && (eventName === "on_tool_start" || (eventName === "on_chain_start" && runType === "tool"));
160
+ const isTaskEnd = toolName === "task" && (eventName === "on_tool_end" || (eventName === "on_chain_end" && runType === "tool"));
161
+ const isTaskError = toolName === "task" && (eventName === "on_tool_error" || (eventName === "on_chain_error" && runType === "tool"));
162
+ if (isTaskStart) {
163
+ state.openTaskDelegations += 1;
164
+ const delegatedSubagentType = readTaskSubagentType(typed.data?.input);
165
+ const delegatedTaskHasTools = !!delegatedSubagentType
166
+ && !!countConfiguredToolsForAgentId
167
+ && countConfiguredToolsForAgentId(delegatedSubagentType) > 0;
168
+ state.taskDelegationHasToolsStack.push(delegatedTaskHasTools);
169
+ if (delegatedTaskHasTools) {
170
+ state.sawDelegatedAgentWithConfiguredTools = true;
171
+ state.openToolCapableTaskDelegations += 1;
172
+ }
173
+ return;
174
+ }
175
+ if (isTaskEnd || isTaskError) {
176
+ state.openTaskDelegations = Math.max(0, state.openTaskDelegations - 1);
177
+ const delegatedTaskHadTools = state.taskDelegationHasToolsStack.pop() === true;
178
+ if (delegatedTaskHadTools) {
179
+ state.openToolCapableTaskDelegations = Math.max(0, state.openToolCapableTaskDelegations - 1);
180
+ }
181
+ if (isTaskError) {
182
+ state.hasFailedTaskDelegation = true;
183
+ }
184
+ }
185
+ }
12
186
  export function projectRuntimeStreamEvent(params) {
13
- const { event, allowVisibleStreamDeltas, includeStateStreamOutput, toolNameMapping, primaryTools, state, } = params;
187
+ const { event, allowVisibleStreamDeltas, includeStateStreamOutput, rootAgentId, countConfiguredToolsForAgentId, toolNameMapping, primaryTools, state, } = params;
14
188
  const chunks = [{
15
189
  kind: "upstream-event",
16
190
  event: sanitizeRetainedUpstreamEvent(event),
17
191
  }];
192
+ updateDelegationState(state, event, countConfiguredToolsForAgentId);
18
193
  const interruptPayload = extractInterruptPayload(event);
19
194
  if (interruptPayload) {
20
195
  chunks.push({ kind: "interrupt", content: interruptPayload });
@@ -24,7 +199,24 @@ export function projectRuntimeStreamEvent(params) {
24
199
  if (reasoning) {
25
200
  chunks.push({ kind: "reasoning", content: reasoning });
26
201
  }
27
- if (allowVisibleStreamDeltas) {
202
+ const planStateCompleteness = getPlanStateCompleteness(event);
203
+ if (planStateCompleteness !== null) {
204
+ state.sawPlanState = true;
205
+ state.hasIncompletePlanState = planStateCompleteness;
206
+ }
207
+ const eventAgentId = typeof event === "object" && event !== null && typeof event.agentId === "string"
208
+ ? event.agentId.trim()
209
+ : "";
210
+ const isDelegatedAgentEvent = !!rootAgentId && !!eventAgentId && eventAgentId !== rootAgentId;
211
+ if (isDelegatedAgentEvent
212
+ && countConfiguredToolsForAgentId
213
+ && countConfiguredToolsForAgentId(eventAgentId) > 0) {
214
+ state.sawDelegatedAgentWithConfiguredTools = true;
215
+ }
216
+ const isRootVisibleEvent = !rootAgentId || !eventAgentId || eventAgentId === rootAgentId;
217
+ const allowVisibleContent = isRootVisibleEvent && state.openTaskDelegations === 0;
218
+ const allowStreamedVisibleContent = allowVisibleContent && !state.emittedToolResult && !state.emittedToolError;
219
+ if (allowVisibleStreamDeltas && allowStreamedVisibleContent) {
28
220
  const visibleStreamOutput = extractVisibleStreamOutput(event);
29
221
  if (visibleStreamOutput) {
30
222
  const nextOutput = computeIncrementalOutput(state.emittedOutput, visibleStreamOutput);
@@ -34,7 +226,7 @@ export function projectRuntimeStreamEvent(params) {
34
226
  }
35
227
  }
36
228
  }
37
- if (includeStateStreamOutput) {
229
+ if (includeStateStreamOutput && allowVisibleContent) {
38
230
  const stateStreamOutput = extractStateStreamOutput(event);
39
231
  if (stateStreamOutput) {
40
232
  const nextOutput = computeIncrementalOutput(state.emittedOutput, sanitizeVisibleText(stateStreamOutput));
@@ -46,8 +238,23 @@ export function projectRuntimeStreamEvent(params) {
46
238
  }
47
239
  const toolResult = extractToolResult(event);
48
240
  if (toolResult) {
241
+ const isTodoTool = toolResult.toolName === "write_todos" || toolResult.toolName === "read_todos";
242
+ const isSuccessfulTaskResult = toolResult.toolName === "task" && toolResult.isError !== true;
243
+ const isPlaceholderTaskResult = isSuccessfulTaskResult && isUpstreamPlaceholderTaskResult(toolResult.output);
244
+ const isDelegatedExecutionTool = (isDelegatedAgentEvent || state.openToolCapableTaskDelegations > 0)
245
+ && toolResult.toolName !== "write_todos"
246
+ && toolResult.toolName !== "read_todos"
247
+ && toolResult.toolName !== "task";
49
248
  state.emittedToolResult = true;
50
249
  state.emittedToolError = state.emittedToolError || toolResult.isError === true;
250
+ state.emittedSuccessfulToolResult = state.emittedSuccessfulToolResult || toolResult.isError !== true;
251
+ state.emittedSuccessfulTaskResult = state.emittedSuccessfulTaskResult || isSuccessfulTaskResult;
252
+ state.emittedPlaceholderTaskResult = state.emittedPlaceholderTaskResult || isPlaceholderTaskResult;
253
+ state.emittedNonTodoToolResult = state.emittedNonTodoToolResult || !isTodoTool;
254
+ state.emittedSuccessfulNonTodoToolResult = state.emittedSuccessfulNonTodoToolResult || (!isTodoTool && toolResult.isError !== true);
255
+ state.emittedDelegatedExecutionToolResult = state.emittedDelegatedExecutionToolResult || isDelegatedExecutionTool;
256
+ state.emittedSuccessfulDelegatedExecutionToolResult =
257
+ state.emittedSuccessfulDelegatedExecutionToolResult || (isDelegatedExecutionTool && toolResult.isError !== true);
51
258
  chunks.push({
52
259
  kind: "tool-result",
53
260
  toolName: resolveModelFacingToolName(toolResult.toolName, toolNameMapping, primaryTools),
@@ -55,7 +262,13 @@ export function projectRuntimeStreamEvent(params) {
55
262
  isError: toolResult.isError,
56
263
  });
57
264
  }
58
- const output = extractTerminalStreamOutput(event);
265
+ const output = allowVisibleContent ? extractTerminalStreamOutput(event) : "";
266
+ if (!allowVisibleContent) {
267
+ const delegatedTerminalOutput = extractTerminalStreamOutput(event);
268
+ if (delegatedTerminalOutput) {
269
+ state.emittedDelegatedTerminalOutput = true;
270
+ }
271
+ }
59
272
  if (output) {
60
273
  const outputKey = normalizeTerminalOutputKey(output);
61
274
  if (!outputKey || !state.seenTerminalOutputs.has(outputKey)) {
@@ -242,9 +242,6 @@ export declare const BUILTIN_MIDDLEWARE_TOOL_DESCRIPTORS: readonly [{
242
242
  }, {
243
243
  readonly name: "task";
244
244
  readonly description: "Delegate a bounded task to a subagent.";
245
- }, {
246
- readonly name: "delegate_task";
247
- readonly description: "Delegate a bounded task to a subagent.";
248
245
  }];
249
246
  export declare function createBuiltinMiddlewareTools(backend: BuiltinMiddlewareBackend, options: {
250
247
  includeTaskTool: boolean;