@duckmind/dm-windows-x64 0.61.4 → 0.61.9

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 (279) hide show
  1. package/dm.exe +0 -0
  2. package/extensions/.dm-extensions.json +211 -67
  3. package/extensions/dm-subagents/agents/claude-code-writer.md +15 -0
  4. package/extensions/dm-subagents/agents/claude-code.md +15 -0
  5. package/extensions/dm-subagents/agents/codex-exec-writer.md +15 -0
  6. package/extensions/dm-subagents/agents/codex-exec.md +15 -0
  7. package/extensions/dm-subagents/agents/cursor-agent-writer.md +14 -0
  8. package/extensions/dm-subagents/agents/cursor-agent.md +14 -0
  9. package/extensions/dm-subagents/agents/delegate.md +3 -2
  10. package/extensions/dm-subagents/agents/oracle.md +10 -5
  11. package/extensions/dm-subagents/agents/researcher.md +2 -2
  12. package/extensions/dm-subagents/agents/reviewer.md +17 -7
  13. package/extensions/dm-subagents/agents/scout.md +5 -5
  14. package/extensions/dm-subagents/agents/worker.md +6 -2
  15. package/extensions/dm-subagents/async-retention-discovery-worker.mjs +167 -0
  16. package/extensions/dm-subagents/index.js +4 -0
  17. package/extensions/dm-subagents/inspector-runner.mjs +10 -0
  18. package/extensions/dm-subagents/install.mjs +3 -2
  19. package/extensions/dm-subagents/package.json +2 -2
  20. package/extensions/dm-subagents/prompts/council.md +60 -0
  21. package/extensions/dm-subagents/prompts/parallel-review.md +5 -1
  22. package/extensions/dm-subagents/prompts/review-loop.md +13 -7
  23. package/extensions/dm-subagents/skills/council-mode/SKILL.md +59 -0
  24. package/extensions/dm-subagents/skills/council-mode/references/pass-contracts.md +150 -0
  25. package/extensions/dm-subagents/skills/dm-subagents/SKILL.md +96 -911
  26. package/extensions/dm-subagents/skills/dm-subagents/references/constraints-and-recipes.md +70 -0
  27. package/extensions/dm-subagents/skills/dm-subagents/references/execution-controls.md +539 -0
  28. package/extensions/dm-subagents/skills/dm-subagents/references/management-authoring-rpc.md +161 -0
  29. package/extensions/dm-subagents/skills/dm-subagents/references/multi-lane-orchestration.md +51 -0
  30. package/extensions/dm-subagents/skills/dm-subagents/references/prompting-and-roles.md +295 -0
  31. package/extensions/dm-subagents/skills/dm-subagents/references/review-and-validation.md +73 -0
  32. package/extensions/dm-subagents/src/agents/agent-management.js +716 -484
  33. package/extensions/dm-subagents/src/agents/agent-refinements.js +563 -0
  34. package/extensions/dm-subagents/src/agents/agent-serializer.js +70 -5
  35. package/extensions/dm-subagents/src/agents/agents.js +1447 -299
  36. package/extensions/dm-subagents/src/agents/builtin-names.js +15 -0
  37. package/extensions/dm-subagents/src/agents/chain-serializer.js +12 -7
  38. package/extensions/dm-subagents/src/agents/frontmatter.js +64 -14
  39. package/extensions/dm-subagents/src/agents/identity.js +1 -1
  40. package/extensions/dm-subagents/src/agents/proactive-skills.js +14 -11
  41. package/extensions/dm-subagents/src/agents/runtime-agent-events.js +49 -0
  42. package/extensions/dm-subagents/src/agents/runtime-agent-registry.js +412 -0
  43. package/extensions/dm-subagents/src/agents/skills.js +52 -35
  44. package/extensions/dm-subagents/src/api/agents.js +6 -0
  45. package/extensions/dm-subagents/src/api/background-work.js +151 -0
  46. package/extensions/dm-subagents/src/api/capability-ceiling.js +12 -0
  47. package/extensions/dm-subagents/src/api/control-channel.js +3 -0
  48. package/extensions/dm-subagents/src/api/delegation.js +5 -0
  49. package/extensions/dm-subagents/src/api/dm-args.js +3 -0
  50. package/extensions/dm-subagents/src/api/external-job-provider.js +137 -0
  51. package/extensions/dm-subagents/src/api/external-runs.js +233 -0
  52. package/extensions/dm-subagents/src/api/intercom-bridge.js +3 -0
  53. package/extensions/dm-subagents/src/api/preflight.js +322 -0
  54. package/extensions/dm-subagents/src/api/project-panes.js +11 -0
  55. package/extensions/dm-subagents/src/api/shared-types.js +4 -0
  56. package/extensions/dm-subagents/src/extension/config.js +175 -0
  57. package/extensions/dm-subagents/src/extension/control-notices.js +4 -43
  58. package/extensions/dm-subagents/src/extension/doctor.js +71 -17
  59. package/extensions/dm-subagents/src/extension/fanout-child.js +49 -32
  60. package/extensions/dm-subagents/src/extension/index.js +711 -265
  61. package/extensions/dm-subagents/src/extension/public-execution.js +114 -0
  62. package/extensions/dm-subagents/src/extension/rpc.js +427 -22
  63. package/extensions/dm-subagents/src/extension/schemas.js +158 -65
  64. package/extensions/dm-subagents/src/extension/steering-notices.js +23 -0
  65. package/extensions/dm-subagents/src/extension/subagent-guide.js +31 -0
  66. package/extensions/dm-subagents/src/extension/tool-description.js +92 -74
  67. package/extensions/dm-subagents/src/extension/tool-result.js +7 -0
  68. package/extensions/dm-subagents/src/inspectors/herdr/actions.js +218 -0
  69. package/extensions/dm-subagents/src/inspectors/herdr/client.js +123 -0
  70. package/extensions/dm-subagents/src/inspectors/herdr/focus.js +47 -0
  71. package/extensions/dm-subagents/src/inspectors/herdr/inspector-runner.js +160 -0
  72. package/extensions/dm-subagents/src/inspectors/herdr/project-panes.js +618 -0
  73. package/extensions/dm-subagents/src/inspectors/herdr/session-roots-codec.js +21 -0
  74. package/extensions/dm-subagents/src/inspectors/herdr/shell-command.js +15 -0
  75. package/extensions/dm-subagents/src/integrations/herdr-status.js +377 -0
  76. package/extensions/dm-subagents/src/intercom/intercom-bridge.js +17 -13
  77. package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +371 -79
  78. package/extensions/dm-subagents/src/intercom/result-intercom.js +47 -7
  79. package/extensions/dm-subagents/src/missions/actions.js +394 -0
  80. package/extensions/dm-subagents/src/missions/goal-driver.js +149 -0
  81. package/extensions/dm-subagents/src/missions/lifecycle.js +331 -0
  82. package/extensions/dm-subagents/src/missions/store.js +548 -0
  83. package/extensions/dm-subagents/src/missions/types.js +9 -0
  84. package/extensions/dm-subagents/src/missions/workflow-state.js +245 -0
  85. package/extensions/dm-subagents/src/policy/authority.js +37 -0
  86. package/extensions/dm-subagents/src/profiles/profiles.js +36 -18
  87. package/extensions/dm-subagents/src/runs/background/active-async-capacity.js +427 -0
  88. package/extensions/dm-subagents/src/runs/background/active-run-index.js +122 -0
  89. package/extensions/dm-subagents/src/runs/background/async-execution.js +925 -137
  90. package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +515 -148
  91. package/extensions/dm-subagents/src/runs/background/async-resume.js +378 -51
  92. package/extensions/dm-subagents/src/runs/background/async-retention.js +828 -0
  93. package/extensions/dm-subagents/src/runs/background/async-status-snapshot.js +31 -0
  94. package/extensions/dm-subagents/src/runs/background/async-status.js +259 -22
  95. package/extensions/dm-subagents/src/runs/background/auto-drain.js +46 -0
  96. package/extensions/dm-subagents/src/runs/background/chain-append.js +50 -15
  97. package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +67 -12
  98. package/extensions/dm-subagents/src/runs/background/completion-batcher.js +5 -1
  99. package/extensions/dm-subagents/src/runs/background/completion-dedupe.js +3 -11
  100. package/extensions/dm-subagents/src/runs/background/completion-replay.js +245 -0
  101. package/extensions/dm-subagents/src/runs/background/control-channel.js +423 -36
  102. package/extensions/dm-subagents/src/runs/background/fleet-view.js +132 -59
  103. package/extensions/dm-subagents/src/runs/background/index-segment.js +38 -0
  104. package/extensions/dm-subagents/src/runs/background/inspect-rpc.js +373 -0
  105. package/extensions/dm-subagents/src/runs/background/notify.js +357 -57
  106. package/extensions/dm-subagents/src/runs/background/owned-process-tree.js +86 -0
  107. package/extensions/dm-subagents/src/runs/background/process-terminal.js +269 -0
  108. package/extensions/dm-subagents/src/runs/background/result-delivery-ownership.js +34 -0
  109. package/extensions/dm-subagents/src/runs/background/result-files.js +469 -0
  110. package/extensions/dm-subagents/src/runs/background/result-watcher.js +540 -75
  111. package/extensions/dm-subagents/src/runs/background/resume-guidance.js +44 -0
  112. package/extensions/dm-subagents/src/runs/background/retained-children.js +119 -0
  113. package/extensions/dm-subagents/src/runs/background/run-id-query.js +5 -0
  114. package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +93 -9
  115. package/extensions/dm-subagents/src/runs/background/run-status.js +303 -32
  116. package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +784 -376
  117. package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +75 -34
  118. package/extensions/dm-subagents/src/runs/background/steering.js +221 -0
  119. package/extensions/dm-subagents/src/runs/background/subagent-runner.js +3106 -844
  120. package/extensions/dm-subagents/src/runs/background/subagent-wait.js +529 -0
  121. package/extensions/dm-subagents/src/runs/background/terminal-run-index.js +106 -0
  122. package/extensions/dm-subagents/src/runs/background/top-level-async.js +1 -1
  123. package/extensions/dm-subagents/src/runs/background/wait-completions.js +155 -0
  124. package/extensions/dm-subagents/src/runs/background/wait-config.js +46 -0
  125. package/extensions/dm-subagents/src/runs/background/wait-subscriptions.js +278 -0
  126. package/extensions/dm-subagents/src/runs/background/wait-tool.js +47 -0
  127. package/extensions/dm-subagents/src/runs/foreground/async-dismiss-action.js +81 -0
  128. package/extensions/dm-subagents/src/runs/foreground/async-steering-action.js +245 -0
  129. package/extensions/dm-subagents/src/runs/foreground/async-stop-action.js +74 -0
  130. package/extensions/dm-subagents/src/runs/foreground/execution.js +1401 -342
  131. package/extensions/dm-subagents/src/runs/foreground/foreground-control.js +133 -0
  132. package/extensions/dm-subagents/src/runs/foreground/foreground-history.js +148 -0
  133. package/extensions/dm-subagents/src/runs/foreground/prompt-audit.js +139 -0
  134. package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +4278 -1441
  135. package/extensions/dm-subagents/src/runs/foreground/workflow-detach-reconcile.js +278 -0
  136. package/extensions/dm-subagents/src/runs/foreground/workflow-foreground-steering.js +155 -0
  137. package/extensions/dm-subagents/src/runs/shared/abort-recovery.js +97 -0
  138. package/extensions/dm-subagents/src/runs/shared/acceptance.js +597 -148
  139. package/extensions/dm-subagents/src/runs/shared/agent-contract.js +35 -0
  140. package/extensions/dm-subagents/src/runs/shared/async-status-projection.js +472 -0
  141. package/extensions/dm-subagents/src/runs/shared/background-process-options.js +6 -0
  142. package/extensions/dm-subagents/src/runs/shared/capability-ceiling.js +175 -0
  143. package/extensions/dm-subagents/src/runs/shared/child-identity.js +32 -0
  144. package/extensions/dm-subagents/src/runs/shared/child-launch-plan.js +65 -0
  145. package/extensions/dm-subagents/src/runs/shared/child-protocol.js +447 -0
  146. package/extensions/dm-subagents/src/runs/shared/claude-code-adapter.js +120 -0
  147. package/extensions/dm-subagents/src/runs/shared/codex-exec-adapter.js +129 -0
  148. package/extensions/dm-subagents/src/runs/shared/completion-evidence.js +40 -0
  149. package/extensions/dm-subagents/src/runs/shared/completion-guard.js +140 -83
  150. package/extensions/dm-subagents/src/runs/shared/context-mode.js +38 -0
  151. package/extensions/dm-subagents/src/runs/shared/cursor-agent-adapter.js +101 -0
  152. package/extensions/dm-subagents/src/runs/shared/dm-args.js +445 -72
  153. package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +27 -16
  154. package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +19 -6
  155. package/extensions/dm-subagents/src/runs/shared/extension-bindings.js +81 -0
  156. package/extensions/dm-subagents/src/runs/shared/external-cli-contract.js +134 -0
  157. package/extensions/dm-subagents/src/runs/shared/external-cli-preflight.js +98 -0
  158. package/extensions/dm-subagents/src/runs/shared/external-cli-runner.js +419 -0
  159. package/extensions/dm-subagents/src/runs/shared/external-job-bridge.js +404 -0
  160. package/extensions/dm-subagents/src/runs/shared/external-job-runner.js +334 -0
  161. package/extensions/dm-subagents/src/runs/shared/fast-mode-extension.js +8 -0
  162. package/extensions/dm-subagents/src/runs/shared/host-step-status.js +228 -0
  163. package/extensions/dm-subagents/src/runs/shared/lane-metadata.js +104 -0
  164. package/extensions/dm-subagents/src/runs/shared/launch-cwd.js +17 -0
  165. package/extensions/dm-subagents/src/runs/shared/llm-intent-arbiter.js +190 -0
  166. package/extensions/dm-subagents/src/runs/shared/long-running-guard.js +48 -3
  167. package/extensions/dm-subagents/src/runs/shared/mcp-config-sources.js +387 -0
  168. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +212 -137
  169. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-grant.js +131 -0
  170. package/extensions/dm-subagents/src/runs/shared/model-exclusions.js +207 -0
  171. package/extensions/dm-subagents/src/runs/shared/model-fallback.js +225 -55
  172. package/extensions/dm-subagents/src/runs/shared/model-scope.js +85 -28
  173. package/extensions/dm-subagents/src/runs/shared/mutation-evidence.js +182 -0
  174. package/extensions/dm-subagents/src/runs/shared/nested-events.js +264 -102
  175. package/extensions/dm-subagents/src/runs/shared/nested-render.js +15 -5
  176. package/extensions/dm-subagents/src/runs/shared/orca-progress-tabs.js +505 -0
  177. package/extensions/dm-subagents/src/runs/shared/parallel-handoff.js +653 -0
  178. package/extensions/dm-subagents/src/runs/shared/parallel-utils.js +29 -12
  179. package/extensions/dm-subagents/src/runs/shared/permissions.js +108 -0
  180. package/extensions/dm-subagents/src/runs/shared/process-signal.js +13 -0
  181. package/extensions/dm-subagents/src/runs/shared/run-fanout-budget.js +257 -0
  182. package/extensions/dm-subagents/src/runs/shared/run-history.js +133 -13
  183. package/extensions/dm-subagents/src/runs/shared/runtime-acknowledged-extensions.js +62 -0
  184. package/extensions/dm-subagents/src/runs/shared/session-lease.js +225 -0
  185. package/extensions/dm-subagents/src/runs/shared/single-output.js +129 -27
  186. package/extensions/dm-subagents/src/runs/shared/spawn-budget.js +95 -0
  187. package/extensions/dm-subagents/src/runs/shared/structured-output.js +129 -10
  188. package/extensions/dm-subagents/src/runs/shared/subagent-control.js +66 -11
  189. package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +548 -70
  190. package/extensions/dm-subagents/src/runs/shared/subagent-startup-retry.js +50 -0
  191. package/extensions/dm-subagents/src/runs/shared/task-intent.js +130 -0
  192. package/extensions/dm-subagents/src/runs/shared/tool-availability.js +59 -0
  193. package/extensions/dm-subagents/src/runs/shared/tool-budget.js +7 -5
  194. package/extensions/dm-subagents/src/runs/shared/tool-timeout.js +64 -0
  195. package/extensions/dm-subagents/src/runs/shared/usage-budget.js +74 -0
  196. package/extensions/dm-subagents/src/runs/shared/workflow-graph.js +22 -0
  197. package/extensions/dm-subagents/src/runs/shared/worktree-cleanup-plan.js +721 -0
  198. package/extensions/dm-subagents/src/runs/shared/worktree.js +168 -19
  199. package/extensions/dm-subagents/src/shared/accessible-dir.js +35 -0
  200. package/extensions/dm-subagents/src/shared/agent-stream-options.js +3 -0
  201. package/extensions/dm-subagents/src/shared/artifacts.js +170 -11
  202. package/extensions/dm-subagents/src/shared/atomic-json.js +36 -38
  203. package/extensions/dm-subagents/src/shared/capacity-resilient-json.js +77 -0
  204. package/extensions/dm-subagents/src/shared/child-session-name.js +15 -0
  205. package/extensions/dm-subagents/src/shared/child-transcript.js +57 -2
  206. package/extensions/dm-subagents/src/shared/completion-owner.js +7 -0
  207. package/extensions/dm-subagents/src/shared/display-text.js +142 -0
  208. package/extensions/dm-subagents/src/shared/extension-context.js +17 -0
  209. package/extensions/dm-subagents/src/shared/file-coalescer.js +9 -0
  210. package/extensions/dm-subagents/src/shared/file-system-retry.js +56 -0
  211. package/extensions/dm-subagents/src/shared/fork-context.js +96 -33
  212. package/extensions/dm-subagents/src/shared/formatters.js +21 -7
  213. package/extensions/dm-subagents/src/shared/launch-contract.js +94 -0
  214. package/extensions/dm-subagents/src/shared/model-info.js +10 -5
  215. package/extensions/dm-subagents/src/shared/node-executable.js +19 -0
  216. package/extensions/dm-subagents/src/shared/prompt-resources.js +10 -0
  217. package/extensions/dm-subagents/src/shared/pruned-fork.js +427 -0
  218. package/extensions/dm-subagents/src/shared/session-file-trust.js +19 -0
  219. package/extensions/dm-subagents/src/shared/session-tokens.js +14 -3
  220. package/extensions/dm-subagents/src/shared/settings.js +39 -47
  221. package/extensions/dm-subagents/src/shared/shortcuts.js +16 -0
  222. package/extensions/dm-subagents/src/shared/status-format.js +9 -2
  223. package/extensions/dm-subagents/src/shared/thinking-ceiling.js +41 -0
  224. package/extensions/dm-subagents/src/shared/types.js +47 -7
  225. package/extensions/dm-subagents/src/shared/utf8.js +12 -0
  226. package/extensions/dm-subagents/src/shared/utils.js +151 -131
  227. package/extensions/dm-subagents/src/shared/watch-strategy.js +3 -0
  228. package/extensions/dm-subagents/src/shared/workflow-child-permit.js +84 -0
  229. package/extensions/dm-subagents/src/slash/delegation-adapters.js +274 -0
  230. package/extensions/dm-subagents/src/slash/delegation-json.js +113 -0
  231. package/extensions/dm-subagents/src/slash/delegation-request.js +152 -0
  232. package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +294 -243
  233. package/extensions/dm-subagents/src/slash/prompt-workflows.js +35 -73
  234. package/extensions/dm-subagents/src/slash/selector.js +101 -0
  235. package/extensions/dm-subagents/src/slash/slash-bridge.js +17 -1
  236. package/extensions/dm-subagents/src/slash/slash-commands.js +722 -732
  237. package/extensions/dm-subagents/src/slash/slash-live-state.js +37 -19
  238. package/extensions/dm-subagents/src/slash/subagents-admin.js +410 -0
  239. package/extensions/dm-subagents/src/tui/fleet-status.js +824 -0
  240. package/extensions/dm-subagents/src/tui/fleet-transcript.js +479 -0
  241. package/extensions/dm-subagents/src/tui/fleet.js +1326 -0
  242. package/extensions/dm-subagents/src/tui/render-helpers.js +22 -0
  243. package/extensions/dm-subagents/src/tui/render.js +1511 -261
  244. package/extensions/dm-subagents/src/watchdog/change-signature.js +220 -0
  245. package/extensions/dm-subagents/src/watchdog/child-status.js +151 -0
  246. package/extensions/dm-subagents/src/watchdog/emission-guard.js +90 -0
  247. package/extensions/dm-subagents/src/watchdog/lsp-diagnostics.js +484 -0
  248. package/extensions/dm-subagents/src/watchdog/model-selection.js +154 -0
  249. package/extensions/dm-subagents/src/watchdog/permission-arbiter.js +138 -0
  250. package/extensions/dm-subagents/src/watchdog/register-child.js +112 -0
  251. package/extensions/dm-subagents/src/watchdog/register-main.js +419 -0
  252. package/extensions/dm-subagents/src/watchdog/render.js +54 -0
  253. package/extensions/dm-subagents/src/watchdog/review.js +251 -0
  254. package/extensions/dm-subagents/src/watchdog/runtime.js +803 -0
  255. package/extensions/dm-subagents/src/watchdog/scope.js +56 -0
  256. package/extensions/dm-subagents/src/watchdog/settings.js +515 -0
  257. package/extensions/dm-subagents/src/watchdog/tool-actions.js +151 -0
  258. package/extensions/dm-subagents/src/watchdog/turn-delta.js +169 -0
  259. package/extensions/dm-subagents/src/watchdog/types.js +29 -0
  260. package/extensions/dm-subagents/src/watchdog/warning-format.js +58 -0
  261. package/extensions/dm-subagents/src/workflows/chat-progress.js +116 -0
  262. package/extensions/dm-subagents/src/workflows/host-command.js +227 -0
  263. package/extensions/dm-subagents/src/workflows/scripted-workflow.js +2011 -0
  264. package/extensions/dm-subagents/src/workflows/workflow-child-summary.js +116 -0
  265. package/extensions/dm-subagents/src/workflows/workflow-preflight.js +243 -0
  266. package/extensions/dm-subagents/src/workflows/workflow-receipt.js +387 -0
  267. package/extensions/dm-subagents/src/workflows/workflow-settlement.js +189 -0
  268. package/package.json +4 -3
  269. package/extensions/dm-fff/package.json +0 -21
  270. package/extensions/dm-fff/src/index.js +0 -691
  271. package/extensions/dm-fff/src/query.js +0 -60
  272. package/extensions/dm-subagents/agents/context-builder.md +0 -46
  273. package/extensions/dm-subagents/agents/planner.md +0 -55
  274. package/extensions/dm-subagents/prompts/parallel-context-build.md +0 -55
  275. package/extensions/dm-subagents/prompts/parallel-handoff-plan.md +0 -61
  276. package/extensions/dm-subagents/src/runs/background/wait.js +0 -206
  277. package/extensions/dm-subagents/src/runs/foreground/chain-clarify.js +0 -1013
  278. package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +0 -981
  279. package/extensions/dm-subagents/src/runs/shared/turn-budget.js +0 -50
@@ -1,16 +1,200 @@
1
1
  import * as path from "node:path";
2
2
  import { Compile } from "typebox/compile";
3
3
  import { resolveAsyncRunLocation } from "../runs/background/async-resume.js";
4
- import { deliverTimeoutRequest } from "../runs/background/control-channel.js";
4
+ import { deliverStopRequest } from "../runs/background/control-channel.js";
5
5
  import { reconcileAsyncRun } from "../runs/background/stale-run-reconciler.js";
6
- import { ASYNC_DIR, RESULTS_DIR } from "../shared/types.js";
6
+ import { resolveCurrentSessionId } from "../shared/session-identity.js";
7
+ import {
8
+ DIRS,
9
+ SUBAGENT_ASYNC_COMPLETE_EVENT,
10
+ SUBAGENT_CHILD_STATUS_EVENT,
11
+ SUBAGENT_PROCESS_TERMINAL_EVENT,
12
+ SUBAGENT_LIFECYCLE_ARTIFACT_VERSION
13
+ } from "../shared/types.js";
14
+ import { sanitizeDisplayText, truncateDisplayText } from "../shared/display-text.js";
7
15
  import { readStatus } from "../shared/utils.js";
8
16
  import { SubagentParams } from "./schemas.js";
17
+ import { normalizePublicSubagentExecution } from "./public-execution.js";
18
+ import { ASYNC_STATUS_SNAPSHOT_KIND, ASYNC_STATUS_SNAPSHOT_VERSION, buildAsyncStatusSnapshotForState } from "../runs/background/async-status-snapshot.js";
19
+ import { isStoppableAsyncStatusStep, resolveAsyncStatusChild } from "../runs/shared/child-identity.js";
9
20
  export const SUBAGENT_RPC_PROTOCOL_VERSION = 1;
10
21
  export const SUBAGENT_RPC_REQUEST_EVENT = "subagents:rpc:v1:request";
11
22
  export const SUBAGENT_RPC_READY_EVENT = "subagents:rpc:v1:ready";
12
23
  export const SUBAGENT_RPC_REPLY_EVENT_PREFIX = "subagents:rpc:v1:reply:";
13
- export const SUBAGENT_RPC_METHODS = ["ping", "status", "spawn", "interrupt", "stop"];
24
+ export const SUBAGENT_RPC_METHODS = ["ping", "status", "manage", "spawn", "steer", "interrupt", "stop", "resume"];
25
+ export const SUBAGENT_RPC_MANAGEMENT_ACTIONS = [
26
+ "schedule.list",
27
+ "schedule.show",
28
+ "schedule.history",
29
+ "schedule.pause",
30
+ "schedule.resume",
31
+ "schedule.run",
32
+ "schedule.delete"
33
+ ];
34
+ const MAX_FLEET_ENTRIES = 16;
35
+ const MAX_FLEET_CANDIDATES = 256;
36
+ const MAX_AGENT_LENGTH = 96;
37
+ const MAX_GOAL_LENGTH = 512;
38
+ const MAX_METADATA_LENGTH = 128;
39
+ function displayText(value, maxLength) {
40
+ if (typeof value !== "string")
41
+ return;
42
+ const normalized = sanitizeDisplayText(value.slice(0, 4096));
43
+ return normalized ? truncateDisplayText(normalized, maxLength) : undefined;
44
+ }
45
+ function publicTokens(value) {
46
+ const record = isRecord(value) ? value : {};
47
+ const count = (field) => {
48
+ const raw = record[field];
49
+ return typeof raw === "number" && Number.isFinite(raw) && raw >= 0 ? Math.min(Number.MAX_SAFE_INTEGER, Math.floor(raw)) : 0;
50
+ };
51
+ const input = count("input");
52
+ const output = count("output");
53
+ const sum = Math.min(Number.MAX_SAFE_INTEGER, input + output);
54
+ const optionalCount = (field) => {
55
+ const raw = record[field];
56
+ return typeof raw === "number" && Number.isFinite(raw) && raw >= 0 ? Math.min(Number.MAX_SAFE_INTEGER, Math.floor(raw)) : undefined;
57
+ };
58
+ const window = optionalCount("window");
59
+ const windowPeak = optionalCount("windowPeak");
60
+ return {
61
+ input,
62
+ output,
63
+ total: Math.max(sum, count("total")),
64
+ ...window !== undefined ? { window } : {},
65
+ ...windowPeak !== undefined ? { windowPeak } : {}
66
+ };
67
+ }
68
+ function activeState(value) {
69
+ return value === "running" || value === "queued" || value === "pending";
70
+ }
71
+ function buildFleetStatus(state, keyState, sessionId) {
72
+ const authoritativeSessionId = sessionId ?? null;
73
+ if (keyState.sessionId !== authoritativeSessionId) {
74
+ keyState.sessionId = authoritativeSessionId;
75
+ keyState.next = 0;
76
+ keyState.keys.clear();
77
+ }
78
+ if (!state || !authoritativeSessionId || state.currentSessionId !== authoritativeSessionId) {
79
+ keyState.keys.clear();
80
+ return { version: 1, entries: [], totalActive: 0, topLevelAsyncCapacity: { used: 0, limit: 0 }, omitted: 0 };
81
+ }
82
+ let totalActive = 0;
83
+ const candidates = [];
84
+ const addCandidate = (candidate) => {
85
+ totalActive += 1;
86
+ if (candidates.length < MAX_FLEET_CANDIDATES)
87
+ candidates.push(candidate);
88
+ };
89
+ for (const control of state.foregroundControls.values()) {
90
+ if (control.sessionId !== authoritativeSessionId)
91
+ continue;
92
+ if (control.activeChildren?.size) {
93
+ for (const child of control.activeChildren.values())
94
+ addCandidate({
95
+ internalKey: `foreground:${control.runId}:${child.index}`,
96
+ agent: child.agent,
97
+ model: child.model,
98
+ effort: child.thinking,
99
+ startedAt: child.startedAt,
100
+ tokens: { input: child.inputTokens ?? 0, output: child.outputTokens ?? 0, total: child.tokens ?? 0, ...child.window !== undefined ? { window: child.window } : {}, ...child.windowPeak !== undefined ? { windowPeak: child.windowPeak } : {} }
101
+ });
102
+ } else {
103
+ addCandidate({
104
+ internalKey: `foreground:${control.runId}:${control.currentIndex ?? 0}`,
105
+ agent: control.currentAgent ?? control.mode,
106
+ model: control.model,
107
+ effort: control.thinking,
108
+ startedAt: control.startedAt,
109
+ tokens: { input: control.inputTokens ?? 0, output: control.outputTokens ?? 0, total: control.tokens ?? 0, ...control.window !== undefined ? { window: control.window } : {}, ...control.windowPeak !== undefined ? { windowPeak: control.windowPeak } : {} }
110
+ });
111
+ }
112
+ }
113
+ for (const job of state.asyncJobs.values()) {
114
+ if (job.sessionId !== authoritativeSessionId || !activeState(job.status))
115
+ continue;
116
+ const startedAt = job.startedAt ?? job.updatedAt;
117
+ if (job.mode === "workflow") {
118
+ addCandidate({
119
+ internalKey: `async:${job.asyncId}`,
120
+ agent: "workflow",
121
+ startedAt,
122
+ tokens: job.totalTokens
123
+ });
124
+ continue;
125
+ }
126
+ const steps = job.steps?.length ? job.steps : job.agents?.map((agent, index) => ({
127
+ agent,
128
+ index,
129
+ status: job.status === "queued" ? "pending" : "running"
130
+ }));
131
+ if (!steps?.length) {
132
+ addCandidate({
133
+ internalKey: `async:${job.asyncId}`,
134
+ agent: job.mode ?? "subagent",
135
+ startedAt,
136
+ tokens: job.totalTokens
137
+ });
138
+ continue;
139
+ }
140
+ for (const [offset, step] of steps.entries()) {
141
+ if (!activeState(step.status))
142
+ continue;
143
+ const index = step.index ?? offset;
144
+ if (step.status === "pending" && job.mode === "chain" && !job.activeParallelGroup && index !== (job.currentStep ?? 0))
145
+ continue;
146
+ addCandidate({
147
+ internalKey: `async:${job.asyncId}:${index}`,
148
+ agent: step.agent,
149
+ role: step.label,
150
+ model: step.model,
151
+ effort: step.thinking,
152
+ startedAt: step.startedAt ?? startedAt,
153
+ tokens: step.tokens ?? (steps.length === 1 ? job.totalTokens : undefined)
154
+ });
155
+ }
156
+ }
157
+ candidates.sort((left, right) => {
158
+ const leftStarted = typeof left.startedAt === "number" ? left.startedAt : Number.MAX_SAFE_INTEGER;
159
+ const rightStarted = typeof right.startedAt === "number" ? right.startedAt : Number.MAX_SAFE_INTEGER;
160
+ return leftStarted - rightStarted || left.internalKey.localeCompare(right.internalKey);
161
+ });
162
+ const activeKeys = new Set(candidates.map((candidate) => candidate.internalKey));
163
+ const entries = [];
164
+ for (const candidate of candidates) {
165
+ if (entries.length >= MAX_FLEET_ENTRIES)
166
+ break;
167
+ const agent = displayText(candidate.agent, MAX_AGENT_LENGTH);
168
+ const startedAt = candidate.startedAt;
169
+ if (!agent || typeof startedAt !== "number" || !Number.isSafeInteger(startedAt) || startedAt < 0)
170
+ continue;
171
+ let key = keyState.keys.get(candidate.internalKey);
172
+ if (!key) {
173
+ key = `fleet-${++keyState.next}`;
174
+ keyState.keys.set(candidate.internalKey, key);
175
+ }
176
+ const role = displayText(candidate.role, MAX_AGENT_LENGTH);
177
+ const model = displayText(candidate.model, MAX_METADATA_LENGTH);
178
+ const effort = displayText(candidate.effort, MAX_METADATA_LENGTH);
179
+ const goal = displayText(candidate.goal, MAX_GOAL_LENGTH);
180
+ entries.push({
181
+ key,
182
+ agent,
183
+ ...role ? { role } : {},
184
+ ...model ? { model } : {},
185
+ ...effort ? { effort } : {},
186
+ startedAt,
187
+ tokens: publicTokens(candidate.tokens),
188
+ ...goal ? { goal } : {}
189
+ });
190
+ }
191
+ for (const internalKey of keyState.keys.keys()) {
192
+ if (!activeKeys.has(internalKey))
193
+ keyState.keys.delete(internalKey);
194
+ }
195
+ const omitted = Math.max(0, totalActive - entries.length);
196
+ return { version: 1, entries, totalActive, topLevelAsyncCapacity: state.activeAsyncCapacity ?? { used: 0, limit: 0 }, omitted };
197
+ }
14
198
 
15
199
  class SubagentRpcError extends Error {
16
200
  code;
@@ -62,8 +246,7 @@ function failIfToolError(result) {
62
246
  return;
63
247
  throw new SubagentRpcError("execution_failed", textFromToolResult(result) || "Subagent RPC execution failed.");
64
248
  }
65
- function normalizeTargetParams(params, method) {
66
- const input = assertRecordParams(params, method);
249
+ function normalizeTargetParamsFromRecord(input) {
67
250
  const output = {};
68
251
  if (input.id !== undefined)
69
252
  output.id = input.id;
@@ -75,6 +258,28 @@ function normalizeTargetParams(params, method) {
75
258
  output.index = input.index;
76
259
  return output;
77
260
  }
261
+ function normalizeTargetParams(params, method) {
262
+ return normalizeTargetParamsFromRecord(assertRecordParams(params, method));
263
+ }
264
+ function normalizeStatusParams(params) {
265
+ const input = assertRecordParams(params, "status");
266
+ const output = normalizeTargetParamsFromRecord(input);
267
+ if (input.view !== undefined)
268
+ output.view = input.view;
269
+ if (input.lines !== undefined)
270
+ output.lines = input.lines;
271
+ return output;
272
+ }
273
+ function hasStatusTarget(params) {
274
+ return params.id !== undefined || params.runId !== undefined || params.dir !== undefined || params.index !== undefined || params.view !== undefined || params.lines !== undefined;
275
+ }
276
+ function canUseInMemoryStatus(state, sessionId) {
277
+ return Boolean(state && sessionId && state.currentSessionId === sessionId && state.statusProjectionSessionId === sessionId && state.foregroundControls instanceof Map && state.asyncJobs instanceof Map);
278
+ }
279
+ function inMemoryStatusSummary(fleet) {
280
+ const noun = fleet.totalActive === 1 ? "child" : "children";
281
+ return `In-memory subagent status: ${fleet.totalActive} active ${noun}.`;
282
+ }
78
283
  function sessionData(ctx) {
79
284
  if (!ctx)
80
285
  return {};
@@ -90,14 +295,27 @@ function pingData(ctx) {
90
295
  methods: [...SUBAGENT_RPC_METHODS],
91
296
  capabilities: {
92
297
  status: true,
298
+ statusProjection: { version: 1, untargeted: "in-memory-when-ready", targeted: "executor" },
299
+ managementActions: [...SUBAGENT_RPC_MANAGEMENT_ACTIONS],
300
+ fleetStatus: { version: 1 },
301
+ asyncStatusSnapshot: { kind: ASYNC_STATUS_SNAPSHOT_KIND, version: ASYNC_STATUS_SNAPSHOT_VERSION },
93
302
  asyncSpawn: true,
303
+ steer: true,
304
+ nonRecoveringSteer: true,
94
305
  interrupt: true,
95
- stop: true
306
+ stop: true,
307
+ resume: true,
308
+ launchResolvedExtensions: { version: 1, source: "launch-resolved" },
309
+ runtimeAcknowledgedExtensions: { version: 1, source: "child-runtime", event: "subagent:acknowledge-extension" },
310
+ processTerminalProof: { version: 1, lifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION }
96
311
  },
97
312
  events: {
98
313
  ready: SUBAGENT_RPC_READY_EVENT,
99
314
  request: SUBAGENT_RPC_REQUEST_EVENT,
100
- replyPrefix: SUBAGENT_RPC_REPLY_EVENT_PREFIX
315
+ replyPrefix: SUBAGENT_RPC_REPLY_EVENT_PREFIX,
316
+ asyncComplete: SUBAGENT_ASYNC_COMPLETE_EVENT,
317
+ childStatus: SUBAGENT_CHILD_STATUS_EVENT,
318
+ processTerminal: SUBAGENT_PROCESS_TERMINAL_EVENT
101
319
  },
102
320
  session: sessionData(ctx)
103
321
  };
@@ -109,24 +327,85 @@ async function executeChecked(options, ctx, requestId, method, params) {
109
327
  failIfToolError(result);
110
328
  return dataFromToolResult(result);
111
329
  }
330
+ function manageParams(params) {
331
+ const input = assertRecordParams(params, "manage");
332
+ if (typeof input.action !== "string" || !SUBAGENT_RPC_MANAGEMENT_ACTIONS.includes(input.action)) {
333
+ throw new SubagentRpcError("invalid_params", `RPC manage action must be one of: ${SUBAGENT_RPC_MANAGEMENT_ACTIONS.join(", ")}.`);
334
+ }
335
+ if (input.id !== undefined && (typeof input.id !== "string" || !input.id.trim())) {
336
+ throw new SubagentRpcError("invalid_params", "RPC manage id must be a non-empty string.");
337
+ }
338
+ const action = input.action;
339
+ const requiresId = action !== "schedule.list";
340
+ if (requiresId && typeof input.id !== "string") {
341
+ throw new SubagentRpcError("invalid_params", `RPC manage ${action} requires id.`);
342
+ }
343
+ const output = {
344
+ action,
345
+ ...typeof input.id === "string" ? { id: input.id.trim() } : {}
346
+ };
347
+ assertSubagentParams(output, "RPC manage params");
348
+ return output;
349
+ }
112
350
  function spawnParams(params) {
113
351
  const input = assertRecordParams(params, "spawn");
114
- if (input.action !== undefined) {
352
+ const normalized = normalizePublicSubagentExecution(input);
353
+ if (!normalized.ok)
354
+ throw new SubagentRpcError("invalid_params", normalized.error);
355
+ if (normalized.params.action !== undefined) {
115
356
  throw new SubagentRpcError("invalid_params", "RPC spawn does not accept management/control actions. Use status or interrupt RPC methods instead.");
116
357
  }
117
358
  if (input.async === false) {
118
359
  throw new SubagentRpcError("invalid_params", "RPC spawn only supports detached async launches; omit async or set async: true.");
119
360
  }
120
- if (input.clarify === true) {
121
- throw new SubagentRpcError("invalid_params", "RPC spawn cannot open the clarify UI; omit clarify or set clarify: false.");
122
- }
123
- return { ...input, async: true, clarify: false };
361
+ return { ...normalized.params, async: true };
362
+ }
363
+ function steerParams(params) {
364
+ const input = assertRecordParams(params, "steer");
365
+ if (typeof input.message !== "string" || !input.message.trim())
366
+ throw new SubagentRpcError("invalid_params", "RPC steer requires a non-empty message.");
367
+ const target = normalizeTargetParams(input, "steer");
368
+ if (!target.id && !target.runId && !target.dir)
369
+ throw new SubagentRpcError("invalid_params", "RPC steer requires id, runId, or dir.");
370
+ if (input.mode !== undefined && input.mode !== "steer" && input.mode !== "follow_up" && input.mode !== "auto")
371
+ throw new SubagentRpcError("invalid_params", "RPC steer mode must be steer, follow_up, or auto.");
372
+ return {
373
+ action: "steer",
374
+ ...target,
375
+ message: input.message.trim(),
376
+ ...typeof input.mode === "string" ? { mode: input.mode } : {},
377
+ steeringRecovery: false
378
+ };
379
+ }
380
+ function resumeParams(params) {
381
+ const input = assertRecordParams(params, "resume");
382
+ if (typeof input.message !== "string" || !input.message.trim())
383
+ throw new SubagentRpcError("invalid_params", "RPC resume requires a non-empty message.");
384
+ const target = normalizeTargetParams(input, "resume");
385
+ if (!target.id && !target.runId && !target.dir)
386
+ throw new SubagentRpcError("invalid_params", "RPC resume requires id, runId, or dir.");
387
+ if (input.output !== undefined && (typeof input.output !== "string" || !input.output.trim()))
388
+ throw new SubagentRpcError("invalid_params", "RPC resume output must be a non-empty path.");
389
+ if (input.outputMode !== undefined && input.outputMode !== "file-only")
390
+ throw new SubagentRpcError("invalid_params", "RPC resume supports only file-only output mode.");
391
+ return {
392
+ action: "resume",
393
+ ...target,
394
+ message: input.message.trim(),
395
+ ...typeof input.output === "string" ? { output: input.output.trim(), outputMode: "file-only" } : {}
396
+ };
124
397
  }
125
398
  function stopAsyncRun(params, options, ctx) {
126
- const target = normalizeTargetParams(params, "stop");
399
+ const input = assertRecordParams(params, "stop");
400
+ const rawChildId = input.childId;
401
+ if (rawChildId !== undefined && (typeof rawChildId !== "string" || !rawChildId.trim() || /[\r\n]/.test(rawChildId) || rawChildId.length > 256)) {
402
+ throw new SubagentRpcError("invalid_params", "RPC stop childId must be a non-empty string without newlines and at most 256 characters.");
403
+ }
404
+ const childId = typeof rawChildId === "string" ? rawChildId : undefined;
405
+ const target = normalizeTargetParams(input, "stop");
127
406
  assertSubagentParams({ action: "status", ...target }, "RPC stop target params");
128
- const asyncDirRoot = options.asyncDirRoot ?? ASYNC_DIR;
129
- const resultsDir = options.resultsDir ?? RESULTS_DIR;
407
+ const asyncDirRoot = options.asyncDirRoot ?? DIRS.async;
408
+ const resultsDir = options.resultsDir ?? DIRS.results;
130
409
  let location;
131
410
  try {
132
411
  location = resolveAsyncRunLocation(target, asyncDirRoot, resultsDir);
@@ -136,7 +415,7 @@ function stopAsyncRun(params, options, ctx) {
136
415
  if (!location.asyncDir) {
137
416
  throw new SubagentRpcError("not_found", "Async run not found or already completed; stop requires a live async run directory.");
138
417
  }
139
- const currentSessionId = ctx.sessionManager.getSessionId();
418
+ const currentSessionId = resolveCurrentSessionId(ctx.sessionManager);
140
419
  const initialStatus = readStatus(location.asyncDir);
141
420
  const initialRunId = initialStatus?.runId ?? location.resolvedId ?? path.basename(location.asyncDir);
142
421
  if (!initialStatus)
@@ -144,6 +423,86 @@ function stopAsyncRun(params, options, ctx) {
144
423
  if (!currentSessionId || initialStatus.sessionId !== currentSessionId) {
145
424
  throw new SubagentRpcError("not_found", `Async run '${initialRunId}' was not found in the active session.`);
146
425
  }
426
+ let child;
427
+ const emitChildStopping = (runId, asyncDir, stoppedChild, ts = options.now?.() ?? Date.now()) => {
428
+ options.events.emit(SUBAGENT_CHILD_STATUS_EVENT, {
429
+ type: "subagent.child-status",
430
+ version: 1,
431
+ runId,
432
+ childId: stoppedChild.id,
433
+ status: "stopping",
434
+ ts,
435
+ reason: "rpc",
436
+ source: "rpc",
437
+ asyncDir,
438
+ stepIndex: stoppedChild.index,
439
+ agent: stoppedChild.step.agent,
440
+ ...stoppedChild.step.runId ? { childRunId: stoppedChild.step.runId } : {},
441
+ ...stoppedChild.step.workflowKey ? { workflowKey: stoppedChild.step.workflowKey } : {},
442
+ ...stoppedChild.step.phase ? { phase: stoppedChild.step.phase } : {},
443
+ ...stoppedChild.step.label ? { label: stoppedChild.step.label } : {}
444
+ });
445
+ };
446
+ if (childId !== undefined) {
447
+ const resolution = resolveAsyncStatusChild(initialStatus, childId);
448
+ if (!resolution.ok)
449
+ throw new SubagentRpcError(resolution.code === "not_found" ? "not_found" : "invalid_params", resolution.message);
450
+ child = resolution.child;
451
+ if (!isStoppableAsyncStatusStep(child.step)) {
452
+ throw new SubagentRpcError("invalid_state", `Child '${childId}' in async run '${initialRunId}' is ${child.step.status}; stop only supports pending or running children.`);
453
+ }
454
+ }
455
+ if (initialStatus.mode === "workflow" && initialStatus.state === "running") {
456
+ if (child) {
457
+ const stopChild = options.state?.workflowChildStops?.get(initialRunId);
458
+ if (stopChild) {
459
+ if (!stopChild(child.id, `Workflow child '${child.id}' stopped by RPC.`))
460
+ throw new SubagentRpcError("invalid_state", `Child '${childId}' in workflow ${initialRunId} is not available to stop.`);
461
+ emitChildStopping(initialRunId, location.asyncDir, child);
462
+ return {
463
+ runId: initialRunId,
464
+ asyncDir: location.asyncDir,
465
+ previousState: initialStatus.state,
466
+ state: "stopping",
467
+ childId: child.id,
468
+ message: `Stop requested for child ${child.id} in async run ${initialRunId}.`
469
+ };
470
+ }
471
+ }
472
+ const workflowController = options.state?.workflowControllers?.get(initialRunId);
473
+ if (workflowController && !child) {
474
+ workflowController.abort(new Error("Workflow stopped by RPC."));
475
+ return {
476
+ runId: initialRunId,
477
+ asyncDir: location.asyncDir,
478
+ previousState: initialStatus.state,
479
+ state: "stopping",
480
+ message: `Stop requested for async run ${initialRunId}.`
481
+ };
482
+ }
483
+ try {
484
+ deliverStopRequest({
485
+ asyncDir: location.asyncDir,
486
+ pid: initialStatus.pid,
487
+ kill: options.kill,
488
+ now: options.now,
489
+ source: "rpc-stop",
490
+ ...child ? { targetIndex: child.index, childId: child.id } : {}
491
+ });
492
+ } catch (error) {
493
+ throw new SubagentRpcError("execution_failed", error instanceof Error ? error.message : String(error));
494
+ }
495
+ if (child)
496
+ emitChildStopping(initialRunId, location.asyncDir, child);
497
+ return {
498
+ runId: initialRunId,
499
+ asyncDir: location.asyncDir,
500
+ previousState: initialStatus.state,
501
+ state: "stopping",
502
+ ...child ? { childId: child.id } : {},
503
+ message: child ? `Stop requested for child ${child.id} in async run ${initialRunId}.` : `Stop requested for async run ${initialRunId}.`
504
+ };
505
+ }
147
506
  let status;
148
507
  try {
149
508
  status = reconcileAsyncRun(location.asyncDir, { resultsDir, kill: options.kill, now: options.now }).status;
@@ -159,36 +518,78 @@ function stopAsyncRun(params, options, ctx) {
159
518
  if (status.state !== "running") {
160
519
  throw new SubagentRpcError("invalid_state", `Async run ${runId} is ${status.state}; stop only supports running async runs.`);
161
520
  }
521
+ if (childId !== undefined) {
522
+ const resolution = resolveAsyncStatusChild(status, childId);
523
+ if (!resolution.ok)
524
+ throw new SubagentRpcError(resolution.code === "not_found" ? "not_found" : "invalid_params", resolution.message);
525
+ child = resolution.child;
526
+ if (!isStoppableAsyncStatusStep(child.step)) {
527
+ throw new SubagentRpcError("invalid_state", `Child '${childId}' in async run '${runId}' is ${child.step.status}; stop only supports pending or running children.`);
528
+ }
529
+ }
162
530
  try {
163
- deliverTimeoutRequest({
531
+ deliverStopRequest({
164
532
  asyncDir: location.asyncDir,
165
533
  pid: status.pid,
166
534
  kill: options.kill,
167
535
  now: options.now,
168
- source: "rpc-stop"
536
+ source: "rpc-stop",
537
+ ...child ? { targetIndex: child.index, childId: child.id } : {}
169
538
  });
170
539
  } catch (error) {
171
540
  throw new SubagentRpcError("execution_failed", error instanceof Error ? error.message : String(error));
172
541
  }
542
+ if (child)
543
+ emitChildStopping(runId, location.asyncDir, child);
173
544
  return {
174
545
  runId,
175
546
  asyncDir: location.asyncDir,
176
547
  previousState: status.state,
177
548
  state: "stopping",
178
- message: `Stop requested for async run ${runId}.`
549
+ ...child ? { childId: child.id } : {},
550
+ message: child ? `Stop requested for child ${child.id} in async run ${runId}.` : `Stop requested for async run ${runId}.`
179
551
  };
180
552
  }
181
- async function handleRequest(request, options) {
553
+ async function handleRequest(request, options, fleetKeys) {
182
554
  const ctx = options.getContext();
183
555
  if (request.method === "ping")
184
556
  return pingData(ctx);
185
557
  if (!ctx)
186
558
  throw new SubagentRpcError("no_active_session", "No active extension context for subagent RPC.");
559
+ if (request.method === "manage") {
560
+ return executeChecked(options, ctx, request.requestId, request.method, manageParams(request.params));
561
+ }
187
562
  if (request.method === "spawn") {
188
563
  return executeChecked(options, ctx, request.requestId, request.method, spawnParams(request.params));
189
564
  }
190
565
  if (request.method === "status") {
191
- return executeChecked(options, ctx, request.requestId, request.method, { action: "status", ...normalizeTargetParams(request.params, "status") });
566
+ const statusParams = normalizeStatusParams(request.params);
567
+ let sessionId;
568
+ if (!hasStatusTarget(statusParams)) {
569
+ try {
570
+ sessionId = resolveCurrentSessionId(ctx.sessionManager);
571
+ } catch {}
572
+ if (canUseInMemoryStatus(options.state, sessionId)) {
573
+ const fleet = buildFleetStatus(options.state, fleetKeys, sessionId);
574
+ const asyncSnapshot = buildAsyncStatusSnapshotForState(options.state, sessionId);
575
+ return {
576
+ text: inMemoryStatusSummary(fleet),
577
+ details: { mode: "management", results: [] },
578
+ fleet,
579
+ asyncSnapshot
580
+ };
581
+ }
582
+ }
583
+ const status = await executeChecked(options, ctx, request.requestId, request.method, { action: "status", ...statusParams });
584
+ sessionId ??= resolveCurrentSessionId(ctx.sessionManager);
585
+ return {
586
+ ...status,
587
+ fleet: buildFleetStatus(options.state, fleetKeys, sessionId),
588
+ asyncSnapshot: buildAsyncStatusSnapshotForState(options.state, sessionId)
589
+ };
590
+ }
591
+ if (request.method === "steer") {
592
+ return executeChecked(options, ctx, request.requestId, request.method, steerParams(request.params));
192
593
  }
193
594
  if (request.method === "interrupt") {
194
595
  return executeChecked(options, ctx, request.requestId, request.method, { action: "interrupt", ...normalizeTargetParams(request.params, "interrupt") });
@@ -196,6 +597,9 @@ async function handleRequest(request, options) {
196
597
  if (request.method === "stop") {
197
598
  return stopAsyncRun(request.params, options, ctx);
198
599
  }
600
+ if (request.method === "resume") {
601
+ return executeChecked(options, ctx, request.requestId, request.method, resumeParams(request.params));
602
+ }
199
603
  throw new SubagentRpcError("unsupported_method", `Unsupported subagent RPC method: ${String(request.method)}`);
200
604
  }
201
605
  function parseRequest(raw) {
@@ -238,11 +642,12 @@ function errorReply(raw, error) {
238
642
  };
239
643
  }
240
644
  export function registerSubagentRpcBridge(options) {
645
+ const fleetKeys = { sessionId: null, next: 0, keys: new Map };
241
646
  const unsubscribe = options.events.on(SUBAGENT_RPC_REQUEST_EVENT, async (raw) => {
242
647
  let request;
243
648
  try {
244
649
  request = parseRequest(raw);
245
- const data = await handleRequest(request, options);
650
+ const data = await handleRequest(request, options, fleetKeys);
246
651
  options.events.emit(subagentRpcReplyEvent(request.requestId), {
247
652
  version: SUBAGENT_RPC_PROTOCOL_VERSION,
248
653
  requestId: request.requestId,