@selesai/code 0.13.0 → 0.13.1

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 (461) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/core/agent-session.d.ts +1 -1
  3. package/dist/core/agent-session.js +1 -1
  4. package/dist/core/sdk.d.ts +2 -2
  5. package/dist/core/sdk.js +1 -1
  6. package/dist/core/system-prompt.d.ts +1 -1
  7. package/dist/core/system-prompt.js +1 -1
  8. package/dist/extensions/ascii.txt +9 -0
  9. package/dist/extensions/package.json +1 -2
  10. package/dist/extensions/pi-hermes-memory/CHANGELOG.md +371 -0
  11. package/dist/extensions/pi-hermes-memory/LICENSE +21 -0
  12. package/dist/extensions/pi-hermes-memory/README.md +643 -0
  13. package/dist/extensions/pi-hermes-memory/docs/0.1/TASKS.md +197 -0
  14. package/dist/extensions/pi-hermes-memory/docs/0.2/PLAN.md +290 -0
  15. package/dist/extensions/pi-hermes-memory/docs/0.2/TASKS.md +134 -0
  16. package/dist/extensions/pi-hermes-memory/docs/0.2/TEST-PLAN.md +216 -0
  17. package/dist/extensions/pi-hermes-memory/docs/0.3/PLAN.md +330 -0
  18. package/dist/extensions/pi-hermes-memory/docs/0.3/TASKS.md +125 -0
  19. package/dist/extensions/pi-hermes-memory/docs/0.4/PLAN.md +160 -0
  20. package/dist/extensions/pi-hermes-memory/docs/0.4/TASKS.md +113 -0
  21. package/dist/extensions/pi-hermes-memory/docs/0.6/CHANGELOG.md +57 -0
  22. package/dist/extensions/pi-hermes-memory/docs/0.6/PLAN.md +202 -0
  23. package/dist/extensions/pi-hermes-memory/docs/0.6/TASKS.md +144 -0
  24. package/dist/extensions/pi-hermes-memory/docs/0.7/PLAN.md +349 -0
  25. package/dist/extensions/pi-hermes-memory/docs/0.7/TASKS.md +110 -0
  26. package/dist/extensions/pi-hermes-memory/docs/PUBLISHING.md +149 -0
  27. package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +468 -0
  28. package/dist/extensions/pi-hermes-memory/docs/images/memory-architecture.svg +1 -0
  29. package/dist/extensions/pi-hermes-memory/docs/images/pi-logo.svg +22 -0
  30. package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.png +0 -0
  31. package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.svg +19 -0
  32. package/dist/extensions/pi-hermes-memory/docs/images/security-flow.svg +1 -0
  33. package/dist/extensions/pi-hermes-memory/docs/images/session-lifecycle.svg +1 -0
  34. package/dist/extensions/pi-hermes-memory/docs/images/source-architecture.svg +1 -0
  35. package/dist/extensions/pi-hermes-memory/docs/mermaid/memory-architecture.mmd +49 -0
  36. package/dist/extensions/pi-hermes-memory/docs/mermaid/security-flow.mmd +40 -0
  37. package/dist/extensions/pi-hermes-memory/docs/mermaid/session-lifecycle.mmd +56 -0
  38. package/dist/extensions/pi-hermes-memory/docs/mermaid/source-architecture.mmd +54 -0
  39. package/dist/extensions/pi-hermes-memory/package-lock.json +3799 -0
  40. package/dist/extensions/pi-hermes-memory/package.json +66 -0
  41. package/dist/extensions/pi-hermes-memory/scripts/check-min-sdk.mjs +99 -0
  42. package/dist/extensions/pi-hermes-memory/scripts/ensure-dev.mjs +57 -0
  43. package/dist/extensions/pi-hermes-memory/src/auto-consolidation-warning.ts +6 -0
  44. package/dist/extensions/pi-hermes-memory/src/config.ts +178 -0
  45. package/dist/extensions/pi-hermes-memory/src/constants.ts +424 -0
  46. package/dist/extensions/pi-hermes-memory/src/extension-root-migration.ts +639 -0
  47. package/dist/extensions/pi-hermes-memory/src/handlers/auto-consolidate.ts +401 -0
  48. package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +297 -0
  49. package/dist/extensions/pi-hermes-memory/src/handlers/child-process-watchdog.mjs +90 -0
  50. package/dist/extensions/pi-hermes-memory/src/handlers/correction-detector.ts +300 -0
  51. package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +86 -0
  52. package/dist/extensions/pi-hermes-memory/src/handlers/insights.ts +78 -0
  53. package/dist/extensions/pi-hermes-memory/src/handlers/interview.ts +37 -0
  54. package/dist/extensions/pi-hermes-memory/src/handlers/learn-memory.ts +186 -0
  55. package/dist/extensions/pi-hermes-memory/src/handlers/message-parts.ts +27 -0
  56. package/dist/extensions/pi-hermes-memory/src/handlers/pi-child-process.ts +485 -0
  57. package/dist/extensions/pi-hermes-memory/src/handlers/preview-context.ts +105 -0
  58. package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +506 -0
  59. package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +145 -0
  60. package/dist/extensions/pi-hermes-memory/src/handlers/session-flush.ts +151 -0
  61. package/dist/extensions/pi-hermes-memory/src/handlers/session-live-index.ts +94 -0
  62. package/dist/extensions/pi-hermes-memory/src/handlers/skills-command.ts +1334 -0
  63. package/dist/extensions/pi-hermes-memory/src/handlers/standing-pin.ts +111 -0
  64. package/dist/extensions/pi-hermes-memory/src/handlers/switch-project.ts +75 -0
  65. package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +266 -0
  66. package/dist/extensions/pi-hermes-memory/src/index.ts +378 -0
  67. package/dist/extensions/pi-hermes-memory/src/lifecycle-timing.ts +54 -0
  68. package/dist/extensions/pi-hermes-memory/src/paths.ts +61 -0
  69. package/dist/extensions/pi-hermes-memory/src/project-context.ts +13 -0
  70. package/dist/extensions/pi-hermes-memory/src/project-memory-migration.ts +93 -0
  71. package/dist/extensions/pi-hermes-memory/src/project.ts +157 -0
  72. package/dist/extensions/pi-hermes-memory/src/prompt-context.ts +55 -0
  73. package/dist/extensions/pi-hermes-memory/src/store/atomic-lock-coordinator.ts +375 -0
  74. package/dist/extensions/pi-hermes-memory/src/store/canonical-storage-path.ts +54 -0
  75. package/dist/extensions/pi-hermes-memory/src/store/content-scanner.ts +101 -0
  76. package/dist/extensions/pi-hermes-memory/src/store/db.ts +1180 -0
  77. package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +101 -0
  78. package/dist/extensions/pi-hermes-memory/src/store/markdown-mutation-lock.ts +38 -0
  79. package/dist/extensions/pi-hermes-memory/src/store/memory-lookup.ts +24 -0
  80. package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +1191 -0
  81. package/dist/extensions/pi-hermes-memory/src/store/recovery-maintenance.ts +66 -0
  82. package/dist/extensions/pi-hermes-memory/src/store/schema.ts +118 -0
  83. package/dist/extensions/pi-hermes-memory/src/store/session-anchor-search.ts +472 -0
  84. package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +511 -0
  85. package/dist/extensions/pi-hermes-memory/src/store/session-parser.ts +213 -0
  86. package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +234 -0
  87. package/dist/extensions/pi-hermes-memory/src/store/skill-store.ts +950 -0
  88. package/dist/extensions/pi-hermes-memory/src/store/skill-utils.ts +133 -0
  89. package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +1002 -0
  90. package/dist/extensions/pi-hermes-memory/src/store/sqlite-native.ts +241 -0
  91. package/dist/extensions/pi-hermes-memory/src/store/standing-instructions.ts +247 -0
  92. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +95 -0
  93. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +469 -0
  94. package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +246 -0
  95. package/dist/extensions/pi-hermes-memory/src/tools/shared-output-view.ts +170 -0
  96. package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +333 -0
  97. package/dist/extensions/pi-hermes-memory/src/tools/tool-result-views.ts +105 -0
  98. package/dist/extensions/pi-hermes-memory/src/types.ts +214 -0
  99. package/dist/extensions/pi-hermes-memory/tests/config.test.ts +434 -0
  100. package/dist/extensions/pi-hermes-memory/tests/extension-root-migration.test.ts +368 -0
  101. package/dist/extensions/pi-hermes-memory/tests/handlers/auto-consolidate.test.ts +984 -0
  102. package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +950 -0
  103. package/dist/extensions/pi-hermes-memory/tests/handlers/correction-detector.test.ts +671 -0
  104. package/dist/extensions/pi-hermes-memory/tests/handlers/insights.test.ts +157 -0
  105. package/dist/extensions/pi-hermes-memory/tests/handlers/interview.test.ts +127 -0
  106. package/dist/extensions/pi-hermes-memory/tests/handlers/pi-child-process.test.ts +905 -0
  107. package/dist/extensions/pi-hermes-memory/tests/handlers/preview-context.test.ts +152 -0
  108. package/dist/extensions/pi-hermes-memory/tests/handlers/prompt-context.test.ts +166 -0
  109. package/dist/extensions/pi-hermes-memory/tests/handlers/resources-discover.test.ts +71 -0
  110. package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +614 -0
  111. package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +192 -0
  112. package/dist/extensions/pi-hermes-memory/tests/handlers/session-flush.test.ts +677 -0
  113. package/dist/extensions/pi-hermes-memory/tests/handlers/session-live-index.test.ts +225 -0
  114. package/dist/extensions/pi-hermes-memory/tests/handlers/skills-command.test.ts +827 -0
  115. package/dist/extensions/pi-hermes-memory/tests/handlers/standing-pin.test.ts +134 -0
  116. package/dist/extensions/pi-hermes-memory/tests/handlers/sync-markdown-memories.test.ts +491 -0
  117. package/dist/extensions/pi-hermes-memory/tests/handlers/system-prompt.test.ts +199 -0
  118. package/dist/extensions/pi-hermes-memory/tests/handlers/thinking-max.test.ts +64 -0
  119. package/dist/extensions/pi-hermes-memory/tests/index.test.ts +30 -0
  120. package/dist/extensions/pi-hermes-memory/tests/integration/flow.test.ts +126 -0
  121. package/dist/extensions/pi-hermes-memory/tests/lifecycle-timing.test.ts +76 -0
  122. package/dist/extensions/pi-hermes-memory/tests/paths.test.ts +23 -0
  123. package/dist/extensions/pi-hermes-memory/tests/project-memory-migration.test.ts +80 -0
  124. package/dist/extensions/pi-hermes-memory/tests/project-rebinding.test.ts +115 -0
  125. package/dist/extensions/pi-hermes-memory/tests/project.test.ts +120 -0
  126. package/dist/extensions/pi-hermes-memory/tests/run-all-timeout.test.ts +107 -0
  127. package/dist/extensions/pi-hermes-memory/tests/run-all.sh +45 -0
  128. package/dist/extensions/pi-hermes-memory/tests/store/atomic-lock-coordinator.test.ts +381 -0
  129. package/dist/extensions/pi-hermes-memory/tests/store/content-scanner.test.ts +388 -0
  130. package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +1046 -0
  131. package/dist/extensions/pi-hermes-memory/tests/store/markdown-mutation-lock.test.ts +34 -0
  132. package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +2150 -0
  133. package/dist/extensions/pi-hermes-memory/tests/store/recovery-maintenance.test.ts +170 -0
  134. package/dist/extensions/pi-hermes-memory/tests/store/session-anchor-search.test.ts +210 -0
  135. package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +643 -0
  136. package/dist/extensions/pi-hermes-memory/tests/store/session-parser.test.ts +282 -0
  137. package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +287 -0
  138. package/dist/extensions/pi-hermes-memory/tests/store/skill-store.test.ts +678 -0
  139. package/dist/extensions/pi-hermes-memory/tests/store/skill-utils.test.ts +21 -0
  140. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-lazy-load.test.ts +78 -0
  141. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +543 -0
  142. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +164 -0
  143. package/dist/extensions/pi-hermes-memory/tests/store/standing-instructions.test.ts +171 -0
  144. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +84 -0
  145. package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +709 -0
  146. package/dist/extensions/pi-hermes-memory/tests/tools/session-search-tool.test.ts +345 -0
  147. package/dist/extensions/pi-hermes-memory/tests/tools/shared-output-view.test.ts +362 -0
  148. package/dist/extensions/pi-hermes-memory/tests/tools/skill-tool.test.ts +478 -0
  149. package/dist/extensions/pi-hermes-memory/tests/tools/tool-result-renderer-wiring.test.ts +40 -0
  150. package/dist/extensions/pi-hermes-memory/tsconfig.json +19 -0
  151. package/dist/extensions/pi-subagents/.oxlintrc.json +43 -0
  152. package/dist/extensions/pi-subagents/AGENTS.md +5 -0
  153. package/dist/extensions/pi-subagents/CHANGELOG.md +157 -0
  154. package/dist/extensions/pi-subagents/README.md +12 -6
  155. package/dist/extensions/pi-subagents/VISION.md +81 -0
  156. package/dist/extensions/pi-subagents/agents/claude-code-writer.md +15 -0
  157. package/dist/extensions/pi-subagents/agents/claude-code.md +15 -0
  158. package/dist/extensions/pi-subagents/agents/codex-exec-writer.md +15 -0
  159. package/dist/extensions/pi-subagents/agents/codex-exec.md +15 -0
  160. package/dist/extensions/pi-subagents/agents/cursor-agent-writer.md +14 -0
  161. package/dist/extensions/pi-subagents/agents/cursor-agent.md +14 -0
  162. package/dist/extensions/pi-subagents/agents/reviewer.md +1 -3
  163. package/dist/extensions/pi-subagents/docs/agents.md +488 -0
  164. package/dist/extensions/pi-subagents/docs/configuration.md +46 -9
  165. package/dist/extensions/pi-subagents/docs/extension-api.md +42 -3
  166. package/dist/extensions/pi-subagents/docs/models.md +27 -4
  167. package/dist/extensions/pi-subagents/docs/observability.md +10 -9
  168. package/dist/extensions/pi-subagents/docs/tool-reference.md +102 -6
  169. package/dist/extensions/pi-subagents/docs/workflows.md +135 -0
  170. package/dist/extensions/pi-subagents/package-lock.json +389 -2
  171. package/dist/extensions/pi-subagents/package.json +3 -1
  172. package/dist/extensions/pi-subagents/prompts/review-loop.md +2 -2
  173. package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +1 -1
  174. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +3 -1
  175. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +7 -3
  176. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
  177. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +26 -5
  178. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +41 -22
  179. package/dist/extensions/pi-subagents/src/agents/agent-refinements.ts +4 -4
  180. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +9 -2
  181. package/dist/extensions/pi-subagents/src/agents/agents.ts +322 -75
  182. package/dist/extensions/pi-subagents/src/agents/builtin-names.ts +6 -0
  183. package/dist/extensions/pi-subagents/src/agents/runtime-agent-events.ts +70 -0
  184. package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +27 -20
  185. package/dist/extensions/pi-subagents/src/api/agents.ts +10 -5
  186. package/dist/extensions/pi-subagents/src/api/background-work.ts +5 -1
  187. package/dist/extensions/pi-subagents/src/api/delegation.ts +0 -7
  188. package/dist/extensions/pi-subagents/src/api/preflight.ts +34 -12
  189. package/dist/extensions/pi-subagents/src/extension/config.ts +70 -0
  190. package/dist/extensions/pi-subagents/src/extension/doctor.ts +3 -3
  191. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +5 -3
  192. package/dist/extensions/pi-subagents/src/extension/index.ts +83 -30
  193. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +44 -15
  194. package/dist/extensions/pi-subagents/src/extension/rpc.ts +55 -19
  195. package/dist/extensions/pi-subagents/src/extension/schemas.ts +41 -15
  196. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +28 -31
  197. package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +2 -1
  198. package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +2 -10
  199. package/dist/extensions/pi-subagents/src/inspectors/herdr/session-roots-codec.ts +42 -0
  200. package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +51 -3
  201. package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +2 -0
  202. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +5 -6
  203. package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +77 -10
  204. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +176 -53
  205. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +19 -12
  206. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +29 -27
  207. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +20 -3
  208. package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +23 -261
  209. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +73 -7
  210. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +8 -3
  211. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +74 -8
  212. package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +37 -21
  213. package/dist/extensions/pi-subagents/src/runs/background/inspect-rpc.ts +8 -8
  214. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +184 -9
  215. package/dist/extensions/pi-subagents/src/runs/background/result-delivery-ownership.ts +45 -0
  216. package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +28 -14
  217. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +38 -15
  218. package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +1 -1
  219. package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +1 -1
  220. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +50 -13
  221. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +93 -8
  222. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +10 -4
  223. package/dist/extensions/pi-subagents/src/runs/background/steering.ts +4 -14
  224. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +549 -377
  225. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +58 -10
  226. package/dist/extensions/pi-subagents/src/runs/background/terminal-run-index.ts +1 -1
  227. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +26 -1
  228. package/dist/extensions/pi-subagents/src/runs/background/wait-config.ts +23 -9
  229. package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +9 -2
  230. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +2 -2
  231. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +204 -129
  232. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +9 -0
  233. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +23 -1
  234. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +773 -311
  235. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +140 -115
  236. package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +119 -0
  237. package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +463 -0
  238. package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +19 -4
  239. package/dist/extensions/pi-subagents/src/runs/shared/child-launch-plan.ts +151 -0
  240. package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +21 -7
  241. package/dist/extensions/pi-subagents/src/runs/shared/claude-code-adapter.ts +129 -0
  242. package/dist/extensions/pi-subagents/src/runs/shared/codex-exec-adapter.ts +129 -0
  243. package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +89 -0
  244. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +5 -4
  245. package/dist/extensions/pi-subagents/src/runs/shared/cursor-agent-adapter.ts +114 -0
  246. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +3 -3
  247. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-contract.ts +167 -0
  248. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +122 -0
  249. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +348 -55
  250. package/dist/extensions/pi-subagents/src/runs/shared/fast-mode-extension.ts +5 -5
  251. package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +230 -0
  252. package/dist/extensions/pi-subagents/src/runs/shared/lane-metadata.ts +105 -0
  253. package/dist/extensions/pi-subagents/src/runs/shared/launch-cwd.ts +16 -0
  254. package/dist/extensions/pi-subagents/src/runs/shared/long-running-guard.ts +2 -1
  255. package/dist/extensions/pi-subagents/src/runs/shared/mcp-config-sources.ts +422 -0
  256. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +221 -158
  257. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-grant.ts +197 -0
  258. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +69 -7
  259. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +47 -6
  260. package/dist/extensions/pi-subagents/src/runs/shared/mutation-evidence.ts +7 -2
  261. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +9 -3
  262. package/dist/extensions/pi-subagents/src/runs/shared/nested-render.ts +9 -5
  263. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +419 -7
  264. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +15 -1
  265. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +81 -8
  266. package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +13 -0
  267. package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +21 -1
  268. package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +44 -4
  269. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +98 -13
  270. package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +1 -1
  271. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +847 -0
  272. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +18 -0
  273. package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +46 -0
  274. package/dist/extensions/pi-subagents/src/shared/extension-context.ts +24 -0
  275. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +21 -0
  276. package/dist/extensions/pi-subagents/src/shared/formatters.ts +18 -3
  277. package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +5 -1
  278. package/dist/extensions/pi-subagents/src/shared/pruned-fork.ts +450 -0
  279. package/dist/extensions/pi-subagents/src/shared/session-file-trust.ts +19 -0
  280. package/dist/extensions/pi-subagents/src/shared/session-tokens.ts +14 -3
  281. package/dist/extensions/pi-subagents/src/shared/settings.ts +19 -105
  282. package/dist/extensions/pi-subagents/src/shared/shortcuts.ts +17 -0
  283. package/dist/extensions/pi-subagents/src/shared/types.ts +359 -40
  284. package/dist/extensions/pi-subagents/src/shared/utils.ts +41 -84
  285. package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +116 -0
  286. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +1 -9
  287. package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +0 -4
  288. package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +1 -2
  289. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +378 -88
  290. package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +22 -11
  291. package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +3 -0
  292. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +147 -79
  293. package/dist/extensions/pi-subagents/src/tui/fleet-transcript.ts +11 -5
  294. package/dist/extensions/pi-subagents/src/tui/fleet.ts +39 -18
  295. package/dist/extensions/pi-subagents/src/tui/render.ts +369 -46
  296. package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +1 -1
  297. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +6 -3
  298. package/dist/extensions/pi-subagents/src/workflows/host-command.ts +230 -0
  299. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +740 -58
  300. package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +121 -0
  301. package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +270 -0
  302. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +195 -6
  303. package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +246 -0
  304. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
  305. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +1114 -260
  306. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +34 -0
  307. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +150 -3
  308. package/dist/extensions/pi-subagents/test/integration/claude-code-smoke.test.ts +52 -0
  309. package/dist/extensions/pi-subagents/test/integration/claude-code-writer-smoke.test.ts +55 -0
  310. package/dist/extensions/pi-subagents/test/integration/codex-exec-smoke.test.ts +53 -0
  311. package/dist/extensions/pi-subagents/test/integration/codex-exec-writer-smoke.test.ts +57 -0
  312. package/dist/extensions/pi-subagents/test/integration/cursor-agent-smoke.test.ts +59 -0
  313. package/dist/extensions/pi-subagents/test/integration/cursor-agent-writer-smoke.test.ts +62 -0
  314. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +57 -1
  315. package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +1 -0
  316. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +20 -0
  317. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +4 -3
  318. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +2 -2
  319. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +54 -4
  320. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +482 -4
  321. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +157 -9
  322. package/dist/extensions/pi-subagents/test/integration/session-tokens.test.ts +5 -5
  323. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +1508 -291
  324. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +423 -1
  325. package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +8 -0
  326. package/dist/extensions/pi-subagents/test/support/cursor-smoke-inputs.ts +51 -0
  327. package/dist/extensions/pi-subagents/test/support/helpers.ts +2 -0
  328. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +5 -5
  329. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +6 -6
  330. package/dist/extensions/pi-subagents/test/unit/abort-recovery.test.ts +152 -0
  331. package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +48 -0
  332. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +184 -6
  333. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +66 -6
  334. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +77 -0
  335. package/dist/extensions/pi-subagents/test/unit/agent-refinements.test.ts +18 -0
  336. package/dist/extensions/pi-subagents/test/unit/anti-slop-oxlint.test.ts +86 -0
  337. package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +1 -1
  338. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +101 -1
  339. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +121 -0
  340. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +28 -0
  341. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +14 -7
  342. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +53 -0
  343. package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +190 -0
  344. package/dist/extensions/pi-subagents/test/unit/async-status-snapshot.test.ts +42 -0
  345. package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +8 -4
  346. package/dist/extensions/pi-subagents/test/unit/background-work.test.ts +23 -0
  347. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +78 -1
  348. package/dist/extensions/pi-subagents/test/unit/child-launch-plan.test.ts +94 -0
  349. package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +21 -0
  350. package/dist/extensions/pi-subagents/test/unit/child-session-name.test.ts +50 -0
  351. package/dist/extensions/pi-subagents/test/unit/claude-code-adapter.test.ts +245 -0
  352. package/dist/extensions/pi-subagents/test/unit/codex-exec-adapter.test.ts +192 -0
  353. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +27 -0
  354. package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +150 -0
  355. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +21 -0
  356. package/dist/extensions/pi-subagents/test/unit/cursor-agent-adapter.test.ts +259 -0
  357. package/dist/extensions/pi-subagents/test/unit/cursor-smoke-inputs.test.ts +77 -0
  358. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +1 -4
  359. package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +1 -1
  360. package/dist/extensions/pi-subagents/test/unit/extension-context.test.ts +27 -0
  361. package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +223 -0
  362. package/dist/extensions/pi-subagents/test/unit/fast-mode-extension.test.ts +27 -0
  363. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +208 -2
  364. package/dist/extensions/pi-subagents/test/unit/fleet-transcript.test.ts +29 -1
  365. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +110 -1
  366. package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +10 -0
  367. package/dist/extensions/pi-subagents/test/unit/formatters.test.ts +14 -0
  368. package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +18 -9
  369. package/dist/extensions/pi-subagents/test/unit/herdr-session-roots-codec.test.ts +63 -0
  370. package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +2 -2
  371. package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +132 -0
  372. package/dist/extensions/pi-subagents/test/unit/host-command.test.ts +156 -0
  373. package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +98 -0
  374. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +178 -26
  375. package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +2 -1
  376. package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +21 -0
  377. package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-grant.test.ts +138 -0
  378. package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +1 -1
  379. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +91 -0
  380. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +72 -7
  381. package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +21 -0
  382. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +1 -0
  383. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +20 -2
  384. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +129 -1
  385. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +2 -2
  386. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +4 -0
  387. package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +358 -0
  388. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +574 -21
  389. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +109 -1
  390. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +71 -1
  391. package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +7 -7
  392. package/dist/extensions/pi-subagents/test/unit/pruned-fork.test.ts +214 -0
  393. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +29 -8
  394. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +53 -0
  395. package/dist/extensions/pi-subagents/test/unit/result-delivery-ownership.test.ts +34 -0
  396. package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +101 -3
  397. package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +1 -0
  398. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +10 -8
  399. package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +71 -1
  400. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +41 -7
  401. package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +136 -2
  402. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +137 -0
  403. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +33 -12
  404. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +504 -1
  405. package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +8 -0
  406. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
  407. package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +12 -1
  408. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +3 -5
  409. package/dist/extensions/pi-subagents/test/unit/steering.test.ts +5 -6
  410. package/dist/extensions/pi-subagents/test/unit/subagent-action-recovery.test.ts +0 -8
  411. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +5 -0
  412. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +157 -2
  413. package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +1 -1
  414. package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +63 -4
  415. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +27 -23
  416. package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +44 -0
  417. package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +1 -0
  418. package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +7 -5
  419. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +106 -0
  420. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +484 -9
  421. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +38 -4
  422. package/dist/extensions/pi-subagents/test/unit/workflow-preflight.test.ts +155 -0
  423. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +318 -0
  424. package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +365 -0
  425. package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +349 -0
  426. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +21 -0
  427. package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +2 -7
  428. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/index.ts +13 -0
  429. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/rules/no-service-constructor-imports.ts +52 -0
  430. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/index.ts +41 -0
  431. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-chained-type-assertions.ts +77 -0
  432. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-conditional-empty-object-spread.ts +49 -0
  433. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-known-value-widening.ts +247 -0
  434. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-module-mocking.ts +91 -0
  435. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-object-parameters.ts +126 -0
  436. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-apply.ts +28 -0
  437. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-get.ts +28 -0
  438. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-runtime-typeof.ts +67 -0
  439. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-shape-in-symbol-names.ts +39 -0
  440. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-parameters.ts +83 -0
  441. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-returns.ts +115 -0
  442. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-type-aliases.ts +72 -0
  443. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unsafe-dictionary-type.ts +134 -0
  444. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-widen-then-assert.ts +366 -0
  445. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/require-safety-comment-for-type-assertion.ts +62 -0
  446. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/dictionary-types.ts +502 -0
  447. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/lexical-type-parameters.ts +60 -0
  448. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/reflect-method.ts +35 -0
  449. package/dist/extensions/pi-tool-display/tests/capabilities.test.ts +1 -1
  450. package/dist/extensions/pi-tool-display/tests/settings-inspector.test.ts +2 -2
  451. package/dist/extensions/pi-tool-display/tests/tool-overrides-mcp.test.ts +1 -1
  452. package/dist/modes/interactive/interactive-mode.js +7 -7
  453. package/dist/skills/workflow/SKILL.md +65 -50
  454. package/package.json +112 -110
  455. package/dist/extensions/enable-readonly-tools.test.ts +0 -63
  456. package/dist/extensions/enable-readonly-tools.ts +0 -24
  457. package/dist/extensions/model-prompt-injector/config.json +0 -16
  458. package/dist/extensions/model-prompt-injector/index.test.ts +0 -102
  459. package/dist/extensions/model-prompt-injector/index.ts +0 -148
  460. package/dist/extensions/pi-subagents/src/runs/shared/turn-budget.ts +0 -98
  461. package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +0 -250
@@ -3,7 +3,7 @@ import * as fs from "node:fs";
3
3
  import * as path from "node:path";
4
4
  import { keyText, type ExtensionAPI, type ExtensionContext } from "@selesai/code";
5
5
  import { Key, matchesKey, truncateToWidth, type Component, type KeyId, type TUI } from "@earendil-works/pi-tui";
6
- import { BUILTIN_AGENT_NAMES, discoverAgents, discoverAgentsAll, findBlockingAgentDiagnostic, resolveAgentName, type AgentConfig, type AgentDiscoveryDiagnostic, type AgentScope } from "../agents/agents.ts";
6
+ import { BUILTIN_AGENT_NAMES, discoverAgents, discoverAgentsAll, findBlockingAgentDiagnostic, formatUnknownAgentError, resolveAgentName, unknownAgentDiagnosticContext, type AgentConfig, type AgentDiscoveryDiagnostic, type AgentScope, type UnknownAgentDiagnosticContext } from "../agents/agents.ts";
7
7
  import { listRuntimeAgentConfigs, mergeRuntimeAgents } from "../agents/runtime-agent-registry.ts";
8
8
  import { resolveExistingReadPaths } from "../shared/settings.ts";
9
9
  import {
@@ -22,6 +22,11 @@ import { listAsyncRuns, formatAsyncRunProgressLabel, type AsyncRunSummary } from
22
22
  import { encodeInspectReply, handleInspectRpcArgs, INSPECT_WIDGET_KEY } from "../runs/background/inspect-rpc.ts";
23
23
  import { listScheduledRunSummaries } from "../runs/background/scheduled-runs.ts";
24
24
  import { SUBAGENT_FANOUT_CHILD_ENV } from "../runs/shared/pi-args.ts";
25
+ import { resolveAsyncStatusChild } from "../runs/shared/child-identity.ts";
26
+ import { readStatus } from "../shared/utils.ts";
27
+ import { getArtifactPaths, getArtifactsDir } from "../shared/artifacts.ts";
28
+ import { readWorkflowReceipt } from "../workflows/workflow-receipt.ts";
29
+ import { FLEET_OPEN_SHORTCUT } from "../shared/shortcuts.ts";
25
30
  import type { SlashSubagentResponse, SlashSubagentUpdate } from "./slash-bridge.ts";
26
31
  import { registerPromptWorkflowCommands } from "./prompt-workflows.ts";
27
32
  import { openSubagentsAdmin } from "./subagents-admin.ts";
@@ -45,7 +50,6 @@ import {
45
50
  DIRS,
46
51
  type Details,
47
52
  type FleetKeybindingsConfig,
48
- type JsonSchemaObject,
49
53
  type SingleResult,
50
54
  type SubagentState,
51
55
  type Usage,
@@ -108,9 +112,9 @@ const extractExecutionFlags = (rawArgs: string): { args: string; bg: boolean; fo
108
112
  return { args, bg, fork };
109
113
  };
110
114
 
111
- function discoverSlashAgents(pi: ExtensionAPI, cwd: string, scope: AgentScope): { agents: AgentConfig[]; agentDiagnostics?: AgentDiscoveryDiagnostic[] } {
115
+ function discoverSlashAgents(pi: ExtensionAPI, cwd: string, scope: AgentScope): { agents: AgentConfig[]; agentDiagnostics?: AgentDiscoveryDiagnostic[]; unknownAgentDiagnosticContext: UnknownAgentDiagnosticContext } {
112
116
  const discovered = discoverAgents(cwd, scope);
113
- if (listRuntimeAgentConfigs(pi).length === 0) return discovered;
117
+ if (listRuntimeAgentConfigs(pi).length === 0) return { ...discovered, unknownAgentDiagnosticContext: unknownAgentDiagnosticContext(discovered) };
114
118
  const all = discoverAgentsAll(cwd);
115
119
  const configuredAgents: AgentConfig[] = [
116
120
  ...all.builtin,
@@ -118,7 +122,8 @@ function discoverSlashAgents(pi: ExtensionAPI, cwd: string, scope: AgentScope):
118
122
  ...(scope !== "project" ? all.user : []),
119
123
  ...(scope !== "user" ? all.project : []),
120
124
  ];
121
- return mergeRuntimeAgents(pi, discovered, configuredAgents);
125
+ const merged = mergeRuntimeAgents(pi, discovered, configuredAgents);
126
+ return { ...merged, unknownAgentDiagnosticContext: { ...unknownAgentDiagnosticContext(discovered), agents: merged.agents } };
122
127
  }
123
128
 
124
129
  const makeAgentCompletions = (pi: ExtensionAPI, state: SubagentState) => (prefix: string) => {
@@ -344,25 +349,60 @@ function usageHasValue(usage: Usage): boolean {
344
349
  return usage.input !== 0 || usage.output !== 0 || usage.cacheRead !== 0 || usage.cacheWrite !== 0 || usage.cost !== 0 || usage.turns !== 0;
345
350
  }
346
351
 
352
+ function nonNegativeNumber(value: unknown): number | undefined {
353
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined;
354
+ }
355
+
356
+ function usageFromValue(value: unknown, turnsOverride?: number): Usage | undefined {
357
+ if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
358
+ const record = value as Record<string, unknown>;
359
+ const costValue = typeof record.cost === "object" && record.cost !== null && !Array.isArray(record.cost)
360
+ ? (record.cost as Record<string, unknown>).total
361
+ : record.cost;
362
+ const turnsValue = turnsOverride ?? record.turns;
363
+ const usage = {
364
+ input: nonNegativeNumber(record.input) ?? 0,
365
+ output: nonNegativeNumber(record.output) ?? 0,
366
+ cacheRead: nonNegativeNumber(record.cacheRead) ?? 0,
367
+ cacheWrite: nonNegativeNumber(record.cacheWrite) ?? 0,
368
+ cost: nonNegativeNumber(costValue) ?? 0,
369
+ turns: nonNegativeNumber(turnsValue) ?? 0,
370
+ };
371
+ return Number.isSafeInteger(usage.turns) ? usage : undefined;
372
+ }
373
+
347
374
  function assistantUsageFromMessage(message: unknown): Usage | undefined {
348
375
  if (!message || typeof message !== "object") return undefined;
349
376
  const msg = message as { role?: unknown; usage?: unknown };
350
- if (msg.role !== "assistant" || !msg.usage || typeof msg.usage !== "object") return undefined;
351
- const usage = msg.usage as {
352
- input?: unknown;
353
- output?: unknown;
354
- cacheRead?: unknown;
355
- cacheWrite?: unknown;
356
- cost?: { total?: unknown };
357
- };
358
- return {
359
- input: typeof usage.input === "number" ? usage.input : 0,
360
- output: typeof usage.output === "number" ? usage.output : 0,
361
- cacheRead: typeof usage.cacheRead === "number" ? usage.cacheRead : 0,
362
- cacheWrite: typeof usage.cacheWrite === "number" ? usage.cacheWrite : 0,
363
- cost: typeof usage.cost?.total === "number" ? usage.cost.total : 0,
364
- turns: 1,
365
- };
377
+ return msg.role === "assistant" ? usageFromValue(msg.usage, 1) : undefined;
378
+ }
379
+
380
+ function compactionUsageFromEntry(entry: unknown): Usage | undefined {
381
+ if (!entry || typeof entry !== "object") return undefined;
382
+ const record = entry as { type?: unknown; usage?: unknown };
383
+ return record.type === "compaction" ? usageFromValue(record.usage, 0) : undefined;
384
+ }
385
+
386
+ const MAX_USAGE_METADATA_BYTES = 2 * 1024 * 1024;
387
+
388
+ function readUsageMetadata(metadataPath: string): Record<string, unknown> | undefined {
389
+ let fd: number | undefined;
390
+ try {
391
+ fd = fs.openSync(metadataPath, "r");
392
+ const stat = fs.fstatSync(fd);
393
+ if (!stat.isFile() || stat.size > MAX_USAGE_METADATA_BYTES) return undefined;
394
+ const buffer = Buffer.allocUnsafe(stat.size);
395
+ let offset = 0;
396
+ while (offset < buffer.length) {
397
+ const bytesRead = fs.readSync(fd, buffer, offset, buffer.length - offset, null);
398
+ if (bytesRead <= 0) return undefined;
399
+ offset += bytesRead;
400
+ }
401
+ const value: unknown = JSON.parse(buffer.toString("utf-8"));
402
+ return value && typeof value === "object" && !Array.isArray(value) ? value as Record<string, unknown> : undefined;
403
+ } finally {
404
+ if (fd !== undefined) fs.closeSync(fd);
405
+ }
366
406
  }
367
407
 
368
408
  function isSubagentDetails(value: unknown): value is Details {
@@ -380,10 +420,32 @@ function detailsFromSessionEntry(entry: unknown): Details | undefined {
380
420
  }
381
421
  if (record.type !== "message" || !record.message || typeof record.message !== "object") return undefined;
382
422
  const message = record.message as { role?: unknown; toolName?: unknown; details?: unknown };
383
- if (message.role !== "toolResult" || message.toolName !== "subagent") return undefined;
423
+ if (message.role !== "toolResult" || (message.toolName !== "subagent" && message.toolName !== "subagent_wait")) return undefined;
384
424
  return isSubagentDetails(message.details) ? message.details : undefined;
385
425
  }
386
426
 
427
+ function metadataUsage(
428
+ artifactsDirs: string[],
429
+ input: { runId: string; agent: string },
430
+ ): Usage | undefined {
431
+ if (!/^[A-Za-z0-9._-]+$/.test(input.runId)) return undefined;
432
+ for (const artifactsDir of artifactsDirs) {
433
+ for (const index of [0, undefined] as const) {
434
+ const metadataPath = getArtifactPaths(artifactsDir, input.runId, input.agent, index).metadataPath;
435
+ try {
436
+ const metadata = readUsageMetadata(metadataPath);
437
+ if (!metadata) continue;
438
+ if (metadata.runId !== input.runId || metadata.agent !== input.agent) continue;
439
+ const usage = usageFromValue(metadata.usage);
440
+ if (usage && usageHasValue(usage)) return usage;
441
+ } catch (error) {
442
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") console.error(`Failed to read subagent usage metadata '${metadataPath}':`, error);
443
+ }
444
+ }
445
+ }
446
+ return undefined;
447
+ }
448
+
387
449
  function formatCostUsage(label: string, usage: Usage): string {
388
450
  const extras = [
389
451
  usage.cacheRead ? `cache read ${formatTokens(usage.cacheRead)}` : "",
@@ -393,28 +455,94 @@ function formatCostUsage(label: string, usage: Usage): string {
393
455
  return `${label}: ↑${formatTokens(usage.input)} ↓${formatTokens(usage.output)} $${usage.cost.toFixed(4)}${extras.length ? ` (${extras.join(", ")})` : ""}`;
394
456
  }
395
457
 
396
- function buildSubagentCostReport(ctx: ExtensionContext): string {
458
+ function buildSubagentCostReport(ctx: ExtensionContext, state: SubagentState): string {
397
459
  const parent = emptyUsage();
398
460
  const childTotal = emptyUsage();
399
461
  const total = emptyUsage();
400
462
  const children: Array<{ label: string; usage: Usage; sessionFile?: string }> = [];
463
+ const seenChildren = new Set<string>();
464
+ const workflowRunIds = new Set<string>();
465
+ let unresolvedAsyncChildren = 0;
466
+
467
+ const addChild = (input: { agent?: string; runId?: string; usage?: Usage; sessionFile?: string }): boolean => {
468
+ if (!input.usage || !usageHasValue(input.usage)) return false;
469
+ const identity = input.runId ? `run:${input.runId}` : input.sessionFile ? `session:${input.sessionFile}` : undefined;
470
+ if (identity && seenChildren.has(identity)) return true;
471
+ if (identity) seenChildren.add(identity);
472
+ const usage = { ...input.usage };
473
+ children.push({
474
+ label: `Child ${children.length + 1} (${input.agent ?? "unknown"})`,
475
+ usage,
476
+ ...(input.sessionFile ? { sessionFile: input.sessionFile } : {}),
477
+ });
478
+ addUsage(childTotal, usage);
479
+ return true;
480
+ };
481
+
401
482
  for (const entry of ctx.sessionManager.getBranch()) {
402
483
  const message = entry.type === "message" ? (entry as { message?: unknown }).message : undefined;
403
- const parentUsage = assistantUsageFromMessage(message);
484
+ const parentUsage = assistantUsageFromMessage(message) ?? compactionUsageFromEntry(entry);
404
485
  if (parentUsage) addUsage(parent, parentUsage);
405
486
  const details = detailsFromSessionEntry(entry);
406
487
  if (!details) continue;
488
+ if (details.mode === "workflow" && details.runId) workflowRunIds.add(details.runId);
407
489
  for (const result of details.results) {
408
- if (!usageHasValue(result.usage)) continue;
409
- const usage = { ...result.usage };
410
- children.push({
411
- label: `Child ${children.length + 1} (${result.agent})`,
412
- usage,
413
- ...(result.sessionFile ? { sessionFile: result.sessionFile } : {}),
414
- });
415
- addUsage(childTotal, usage);
490
+ const resultRunId = (result as SingleResult & { runId?: unknown }).runId;
491
+ addChild({ agent: result.agent, runId: typeof resultRunId === "string" ? resultRunId : undefined, usage: usageFromValue(result.usage), sessionFile: result.sessionFile });
492
+ }
493
+ for (const completion of details.completions ?? []) {
494
+ if (completion.mode === "workflow") workflowRunIds.add(completion.runId);
495
+ for (const result of completion.results ?? []) {
496
+ addChild({ agent: result.agent, runId: result.runId, usage: usageFromValue(result.usage), sessionFile: result.sessionFile });
497
+ }
416
498
  }
417
499
  }
500
+
501
+ let sessionFile: string | null = null;
502
+ try {
503
+ sessionFile = ctx.sessionManager.getSessionFile() ?? null;
504
+ } catch { /* an unpersisted session can still report direct child usage */ }
505
+ const artifactsDirs = new Set<string>();
506
+ const addArtifactsDir = (cwd: string | undefined): void => {
507
+ try {
508
+ artifactsDirs.add(getArtifactsDir(sessionFile, cwd, state.artifactDirPreference));
509
+ } catch { /* invalid or unavailable project roots are ignored */ }
510
+ };
511
+ addArtifactsDir(ctx.cwd);
512
+ addArtifactsDir(state.baseCwd);
513
+
514
+ for (const workflowRunId of workflowRunIds) {
515
+ try {
516
+ const status = readStatus(path.join(DIRS.async, workflowRunId));
517
+ addArtifactsDir(status?.cwd);
518
+ const receipt = readWorkflowReceipt(DIRS.async, workflowRunId);
519
+ const summaryChildren = new Map((receipt.workflowChildren?.children ?? []).map((child) => [child.childId, child]));
520
+ const refsByRunId = new Map<string, { runId: string; agent: string }>();
521
+ const addRef = (runId: string | undefined, agent: string | undefined): void => {
522
+ if (!runId || !agent || refsByRunId.has(runId)) return;
523
+ refsByRunId.set(runId, { runId, agent });
524
+ };
525
+ for (const [key, entry] of Object.entries(receipt.entries)) {
526
+ const summaryChild = summaryChildren.get(key);
527
+ const runIds = entry.continuation?.runIds?.length
528
+ ? entry.continuation.runIds
529
+ : entry.latestRunId ? [entry.latestRunId] : summaryChild?.runId ? [summaryChild.runId] : [];
530
+ for (const runId of runIds) addRef(runId, entry.agent ?? summaryChild?.agent);
531
+ }
532
+ for (const child of receipt.workflowChildren?.children ?? []) {
533
+ if (!Object.hasOwn(receipt.entries, child.childId)) addRef(child.runId, child.agent);
534
+ }
535
+ const refs = [...refsByRunId.values()];
536
+ for (const ref of refs) {
537
+ if (seenChildren.has(`run:${ref.runId}`)) continue;
538
+ const usage = metadataUsage([...artifactsDirs], ref);
539
+ if (!usage || !addChild({ ...ref, usage })) unresolvedAsyncChildren += 1;
540
+ }
541
+ } catch (error) {
542
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") console.error(`Failed to resolve async subagent usage for '${workflowRunId}':`, error);
543
+ }
544
+ }
545
+
418
546
  addUsage(total, parent);
419
547
  addUsage(total, childTotal);
420
548
  const lines = [
@@ -430,6 +558,7 @@ function buildSubagentCostReport(ctx: ExtensionContext): string {
430
558
  if (child.sessionFile) lines.push(` Session: ${child.sessionFile}`);
431
559
  }
432
560
  }
561
+ if (unresolvedAsyncChildren > 0) lines.push(`Async child usage unavailable: ${unresolvedAsyncChildren}.`);
433
562
  lines.push("────────────────────────────", formatCostUsage("Children", childTotal), formatCostUsage("Total", total));
434
563
  return lines.join("\n");
435
564
  }
@@ -445,50 +574,76 @@ function getProfileWorkerModel(profile: { subagents?: { agentOverrides?: Record<
445
574
  return typeof model === "string" && model.trim() ? model.trim() : undefined;
446
575
  }
447
576
 
577
+ function isStaleExtensionContextError(error: unknown): boolean {
578
+ return error instanceof Error
579
+ && (error.message.includes("This extension ctx is stale")
580
+ || error.message.includes("Extension context no longer active"));
581
+ }
582
+
583
+ function slashHasUI(ctx: ExtensionContext): boolean | undefined {
584
+ try {
585
+ return ctx.hasUI;
586
+ } catch (error) {
587
+ if (isStaleExtensionContextError(error)) return undefined;
588
+ throw error;
589
+ }
590
+ }
591
+
448
592
 
449
593
  async function requestSlashRun(
450
594
  pi: ExtensionAPI,
451
595
  ctx: ExtensionContext,
452
596
  requestId: string,
453
597
  params: SubagentParamsLike,
598
+ signal?: AbortSignal,
454
599
  ): Promise<SlashSubagentResponse> {
455
600
  return new Promise((resolve, reject) => {
456
601
  let done = false;
457
602
  let started = false;
458
-
459
- const startTimeoutMs = 15_000;
460
- const startTimeout = setTimeout(() => {
461
- finish(() => reject(new Error(
462
- "Slash subagent bridge did not start within 15s. Ensure the extension is loaded correctly.",
463
- )));
464
- }, startTimeoutMs);
603
+ let startTimeout: ReturnType<typeof setTimeout> | undefined;
465
604
 
466
605
  const onStarted = (data: unknown) => {
467
- if (done || !data || typeof data !== "object") return;
606
+ if (done || signal?.aborted || !data || typeof data !== "object") return;
468
607
  if ((data as { requestId?: unknown }).requestId !== requestId) return;
469
608
  started = true;
470
- clearTimeout(startTimeout);
471
- if (ctx.hasUI) ctx.ui.setStatus("subagent-slash", "running...");
609
+ if (startTimeout) clearTimeout(startTimeout);
610
+ try {
611
+ if (ctx.hasUI) ctx.ui.setStatus("subagent-slash", "running...");
612
+ } catch (error) {
613
+ if (isStaleExtensionContextError(error)) {
614
+ finish(() => reject(error));
615
+ return;
616
+ }
617
+ throw error;
618
+ }
472
619
  };
473
620
 
474
621
  const onResponse = (data: unknown) => {
475
- if (done || !data || typeof data !== "object") return;
622
+ if (done || signal?.aborted || !data || typeof data !== "object") return;
476
623
  const response = data as Partial<SlashSubagentResponse>;
477
624
  if (response.requestId !== requestId) return;
478
- clearTimeout(startTimeout);
625
+ if (startTimeout) clearTimeout(startTimeout);
479
626
  finish(() => resolve(response as SlashSubagentResponse));
480
627
  };
481
628
 
482
629
  const onUpdate = (data: unknown) => {
483
- if (done || !data || typeof data !== "object") return;
630
+ if (done || signal?.aborted || !data || typeof data !== "object") return;
484
631
  const update = data as SlashSubagentUpdate;
485
632
  if (update.requestId !== requestId) return;
486
633
  applySlashUpdate(requestId, update);
487
- if (!ctx.hasUI) return;
488
- const tool = update.currentTool ? ` ${update.currentTool}` : "";
489
- const count = update.toolCount ?? 0;
490
- const liveDetailKey = keyText("app.tools.expand");
491
- ctx.ui.setStatus("subagent-slash", `${count} tools${tool} | ${liveDetailKey} live detail`);
634
+ try {
635
+ if (!ctx.hasUI) return;
636
+ const tool = update.currentTool ? ` ${update.currentTool}` : "";
637
+ const count = update.toolCount ?? 0;
638
+ const liveDetailKey = keyText("app.tools.expand");
639
+ ctx.ui.setStatus("subagent-slash", `${count} tools${tool} | ${liveDetailKey} live detail`);
640
+ } catch (error) {
641
+ if (isStaleExtensionContextError(error)) {
642
+ finish(() => reject(error));
643
+ return;
644
+ }
645
+ throw error;
646
+ }
492
647
  };
493
648
 
494
649
  const onTerminalInput = ctx.hasUI
@@ -504,18 +659,43 @@ async function requestSlashRun(
504
659
  const unsubResponse = pi.events.on(SLASH_SUBAGENT_RESPONSE_EVENT, onResponse);
505
660
  const unsubUpdate = pi.events.on(SLASH_SUBAGENT_UPDATE_EVENT, onUpdate);
506
661
 
662
+ let onAbort: () => void;
507
663
  const finish = (next: () => void) => {
508
664
  if (done) return;
509
665
  done = true;
510
- clearTimeout(startTimeout);
666
+ if (startTimeout) clearTimeout(startTimeout);
511
667
  unsubStarted();
512
668
  unsubResponse();
513
669
  unsubUpdate();
514
- onTerminalInput?.();
670
+ try {
671
+ onTerminalInput?.();
672
+ } catch (error) {
673
+ if (!isStaleExtensionContextError(error)) throw error;
674
+ }
675
+ signal?.removeEventListener("abort", onAbort);
515
676
  next();
516
677
  };
678
+ onAbort = () => finish(() => reject(new Error("Slash subagent request canceled during session replacement or reload.")));
679
+ startTimeout = setTimeout(() => {
680
+ finish(() => reject(new Error(
681
+ "Slash subagent bridge did not start within 15s. Ensure the extension is loaded correctly.",
682
+ )));
683
+ }, 15_000);
517
684
 
518
- pi.events.emit(SLASH_SUBAGENT_REQUEST_EVENT, { requestId, params, ctx });
685
+ if (signal?.aborted) {
686
+ onAbort();
687
+ return;
688
+ }
689
+ signal?.addEventListener("abort", onAbort, { once: true });
690
+ try {
691
+ pi.events.emit(SLASH_SUBAGENT_REQUEST_EVENT, { requestId, params, ctx });
692
+ } catch (error) {
693
+ if (isStaleExtensionContextError(error)) {
694
+ finish(() => reject(error));
695
+ return;
696
+ }
697
+ throw error;
698
+ }
519
699
 
520
700
  // Bridge emits STARTED synchronously during REQUEST emit.
521
701
  // If not started, no bridge received the request.
@@ -581,53 +761,73 @@ async function runSlashSubagent(
581
761
  pi: ExtensionAPI,
582
762
  ctx: ExtensionContext,
583
763
  params: SubagentParamsLike,
764
+ signal?: AbortSignal,
584
765
  ): Promise<void> {
585
- if (ctx.hasUI) ctx.ui.setToolsExpanded(false);
766
+ if (signal?.aborted) return;
767
+ const initialHasUI = slashHasUI(ctx);
768
+ if (initialHasUI === undefined) return;
769
+ try {
770
+ if (initialHasUI) ctx.ui.setToolsExpanded(false);
771
+ } catch (error) {
772
+ if (isStaleExtensionContextError(error)) return;
773
+ throw error;
774
+ }
586
775
  const requestId = randomUUID();
587
776
  const initialDetails = buildSlashInitialResult(requestId, params);
588
777
  const initialText = extractSlashMessageText(initialDetails.result.content) || "Running subagent...";
589
- pi.sendMessage({
590
- customType: SLASH_RESULT_TYPE,
591
- content: initialText,
592
- display: true,
593
- details: initialDetails,
594
- });
778
+ try {
779
+ pi.sendMessage({
780
+ customType: SLASH_RESULT_TYPE,
781
+ content: initialText,
782
+ display: true,
783
+ details: initialDetails,
784
+ });
785
+ } catch (error) {
786
+ if (isStaleExtensionContextError(error)) return;
787
+ throw error;
788
+ }
595
789
  persistSlashSessionSnapshot(ctx);
596
790
 
597
791
  try {
598
- const response = await requestSlashRun(pi, ctx, requestId, params);
792
+ const response = await requestSlashRun(pi, ctx, requestId, params, signal);
793
+ if (signal?.aborted) return;
794
+ const hasUI = slashHasUI(ctx);
795
+ if (hasUI === undefined) return;
599
796
  const finalDetails = finalizeSlashResult(response);
600
797
  pi.sendMessage({
601
798
  customType: SLASH_RESULT_TYPE,
602
799
  content: buildSlashExportText(response),
603
- display: !ctx.hasUI,
800
+ display: !hasUI,
604
801
  details: finalDetails,
605
802
  });
606
803
  persistSlashSessionSnapshot(ctx);
607
- if (ctx.hasUI) {
804
+ if (hasUI) {
608
805
  ctx.ui.setStatus("subagent-slash", undefined);
609
806
  }
610
- if (response.isError && ctx.hasUI) {
807
+ if (response.isError && hasUI) {
611
808
  ctx.ui.notify(response.errorText || "Subagent failed", "error");
612
809
  }
613
810
  } catch (error) {
811
+ if (signal?.aborted || isStaleExtensionContextError(error)) return;
614
812
  const message = error instanceof Error ? error.message : String(error);
813
+ const hasUI = slashHasUI(ctx);
814
+ if (hasUI === undefined) return;
615
815
  const failedDetails = failSlashResult(requestId, params, message);
616
816
  pi.sendMessage({
617
817
  customType: SLASH_RESULT_TYPE,
618
818
  content: `## Subagent result\n\n${message}`,
619
- display: !ctx.hasUI,
819
+ display: !hasUI,
620
820
  details: failedDetails,
621
821
  });
622
822
  persistSlashSessionSnapshot(ctx);
623
- if (ctx.hasUI) {
823
+ if (hasUI) {
624
824
  ctx.ui.setStatus("subagent-slash", undefined);
625
825
  }
626
826
  if (message === "Cancelled") {
627
- if (ctx.hasUI) ctx.ui.notify("Cancelled", "warning");
827
+ if (hasUI) ctx.ui.notify("Cancelled", "warning");
628
828
  return;
629
829
  }
630
- if (ctx.hasUI) ctx.ui.notify(message, "error");
830
+ if (hasUI) ctx.ui.notify(message, "error");
631
831
  }
632
832
  }
633
833
 
@@ -639,6 +839,7 @@ export function launchSlashSubagent(
639
839
  void runSlashSubagent(pi, ctx, params);
640
840
  }
641
841
 
842
+
642
843
  function slashRunWorkflowScript(key: string, child: Record<string, unknown>): string {
643
844
  return `return runs.run(${JSON.stringify(key)}, ${JSON.stringify(child)})`;
644
845
  }
@@ -647,12 +848,23 @@ export function registerSlashCommands(
647
848
  pi: ExtensionAPI,
648
849
  state: SubagentState,
649
850
  options: { fleetKeybindings?: FleetKeybindingsConfig; foregroundDetachShortcut?: string } = {},
650
- ): void {
851
+ ): { dispose: () => void } {
651
852
  let fleetOpen = false;
853
+ let disposed = false;
854
+ const pendingRequests = new Set<AbortController>();
855
+ const runCommand = (ctx: ExtensionContext, params: SubagentParamsLike): Promise<void> => {
856
+ if (disposed) return Promise.resolve();
857
+ const controller = new AbortController();
858
+ pendingRequests.add(controller);
859
+ return runSlashSubagent(pi, ctx, params, controller.signal).finally(() => pendingRequests.delete(controller));
860
+ };
861
+ const launchCommand = (ctx: ExtensionContext, params: SubagentParamsLike): void => {
862
+ void runCommand(ctx, params);
863
+ };
652
864
  const showFleet = async (ctx: ExtensionContext) => {
653
865
  state.lastUiContext = ctx;
654
866
  if (!ctx.hasUI) {
655
- await runSlashSubagent(pi, ctx, { action: "status", view: "fleet" });
867
+ await runCommand(ctx, { action: "status", view: "fleet" });
656
868
  return;
657
869
  }
658
870
  if (fleetOpen) {
@@ -693,7 +905,7 @@ export function registerSlashCommands(
693
905
  : resolvedAgent.agent;
694
906
  const diagnostic = findBlockingAgentDiagnostic(agentName, candidates, discovered.agentDiagnostics);
695
907
  if (diagnostic || resolvedAgent.error || !resolvedAgent.agent) {
696
- ctx.ui.notify(diagnostic ? `Agent '${agentName}' has invalid configuration: ${diagnostic.error}` : resolvedAgent.error ?? `Unknown agent: ${agentName}`, "error");
908
+ ctx.ui.notify(diagnostic ? `Agent '${agentName}' has invalid configuration: ${diagnostic.error}` : resolvedAgent.error ?? formatUnknownAgentError(agentName, discovered.unknownAgentDiagnosticContext), "error");
697
909
  return;
698
910
  }
699
911
 
@@ -708,21 +920,21 @@ export function registerSlashCommands(
708
920
  if (inline.skill !== undefined) child.skill = inline.skill;
709
921
  if (inline.model) child.model = inline.model;
710
922
  if (fork) child.context = "fork";
711
- launchSlashSubagent(pi, ctx, { workflowScript: slashRunWorkflowScript("run", child), async: bg ? true : false });
923
+ launchCommand(ctx, { workflowScript: slashRunWorkflowScript("run", child), async: bg ? true : false });
712
924
  },
713
925
  });
714
926
 
715
927
  pi.registerCommand("subagent-cost", {
716
928
  description: "Show parent and subagent child usage cost for this session",
717
929
  handler: async (_args, ctx) => {
718
- sendSlashText(pi, buildSubagentCostReport(ctx));
930
+ sendSlashText(pi, buildSubagentCostReport(ctx, state));
719
931
  },
720
932
  });
721
933
 
722
934
  pi.registerCommand("subagents-doctor", {
723
935
  description: "Show subagent diagnostics",
724
936
  handler: async (_args, ctx) => {
725
- await runSlashSubagent(pi, ctx, { action: "doctor" });
937
+ await runCommand(ctx, { action: "doctor" });
726
938
  },
727
939
  });
728
940
 
@@ -754,7 +966,7 @@ export function registerSlashCommands(
754
966
  ctx.ui.notify("Usage: /subagents-guide [topic]", "error");
755
967
  return;
756
968
  }
757
- await runSlashSubagent(pi, ctx, { action: "guide", ...(topic ? { topic } : {}) });
969
+ await runCommand(ctx, { action: "guide", ...(topic ? { topic } : {}) });
758
970
  },
759
971
  });
760
972
 
@@ -767,7 +979,7 @@ export function registerSlashCommands(
767
979
  ctx.ui.notify("Usage: /subagents-refine <agent>", "error");
768
980
  return;
769
981
  }
770
- await runSlashSubagent(pi, ctx, { action: "refine", agent: parts[0] });
982
+ await runCommand(ctx, { action: "refine", agent: parts[0] });
771
983
  },
772
984
  });
773
985
 
@@ -776,7 +988,7 @@ export function registerSlashCommands(
776
988
  handler: async (_args, ctx) => showFleet(ctx),
777
989
  });
778
990
 
779
- pi.registerShortcut(Key.ctrlAlt("f"), {
991
+ pi.registerShortcut(FLEET_OPEN_SHORTCUT, {
780
992
  description: "Open subagent fleet inspector",
781
993
  handler: async (ctx) => showFleet(ctx),
782
994
  });
@@ -818,11 +1030,15 @@ export function registerSlashCommands(
818
1030
  }
819
1031
 
820
1032
  pi.registerCommand("subagents-stop", {
821
- description: "Stop a current-session async subagent run",
1033
+ description: "Stop a current-session async subagent run, or one child of it with /subagents-stop <run-id> <child-id>",
822
1034
  handler: async (args, ctx) => {
823
- const id = args.trim();
1035
+ const [id, childId, ...extra] = args.trim().split(/\s+/).filter(Boolean);
1036
+ if (extra.length > 0) {
1037
+ sendSlashText(pi, "Usage: /subagents-stop [run-id] [child-id]");
1038
+ return;
1039
+ }
824
1040
  if (id) {
825
- await runSlashSubagent(pi, ctx, { action: "stop", id });
1041
+ await runCommand(ctx, childId ? { action: "stop", id, childId } : { action: "stop", id });
826
1042
  return;
827
1043
  }
828
1044
 
@@ -854,27 +1070,91 @@ export function registerSlashCommands(
854
1070
  );
855
1071
  if (!result?.confirmed || !result.target) return;
856
1072
  if (result.target.kind === "scheduled") {
857
- await runSlashSubagent(pi, ctx, { action: "schedule.pause", id: result.target.id });
1073
+ await runCommand(ctx, { action: "schedule.pause", id: result.target.id });
1074
+ return;
1075
+ }
1076
+ await runCommand(ctx, { action: "stop", id: result.target.id });
1077
+ },
1078
+ });
1079
+
1080
+ pi.registerCommand("subagents-steer", {
1081
+ description: "Steer a live async subagent run with a message, or one child of it with --child <child-id>",
1082
+ handler: async (args, ctx) => {
1083
+ const tokens = args.trim().split(/\s+/).filter(Boolean);
1084
+ const usage = "Usage: /subagents-steer <run-id> [--child <child-id>] <message>";
1085
+ const [id, ...rest] = tokens;
1086
+ if (!id || id.startsWith("--")) {
1087
+ sendSlashText(pi, usage);
858
1088
  return;
859
1089
  }
860
- await runSlashSubagent(pi, ctx, { action: "stop", id: result.target.id });
1090
+ // Only the optional child selector is parsed as a flag. Everything
1091
+ // after the run id (or selector) is free-form message text, including
1092
+ // a leading token such as `--verbose`.
1093
+ let childId: string | undefined;
1094
+ let messageStart = 0;
1095
+ if (rest[0] === "--child" && rest[1] && !rest[1].startsWith("--")) {
1096
+ childId = rest[1];
1097
+ messageStart = 2;
1098
+ }
1099
+ const message = rest.slice(messageStart).join(" ").trim();
1100
+ if (!message) {
1101
+ sendSlashText(pi, usage);
1102
+ return;
1103
+ }
1104
+ let targetId = id;
1105
+ let childIndex: number | undefined;
1106
+ if (childId !== undefined) {
1107
+ const sessionId = state.currentSessionId ?? ctx.sessionManager.getSessionId() ?? undefined;
1108
+ const run = listAsyncRuns(DIRS.async, {
1109
+ runId: id,
1110
+ states: ["queued", "running", "paused"],
1111
+ ...(sessionId ? { sessionId } : {}),
1112
+ })[0];
1113
+ const status = run ? readStatus(run.asyncDir) : null;
1114
+ if (!run || !status) {
1115
+ sendSlashText(pi, `No current-session async run found for '${id}'.`);
1116
+ return;
1117
+ }
1118
+ const resolutionStatus = {
1119
+ ...status,
1120
+ steps: status.steps?.map((step, index) => ({ ...step, children: run.steps[index]?.children ?? step.children })),
1121
+ };
1122
+ const resolution = resolveAsyncStatusChild(resolutionStatus, childId, { includeNested: true });
1123
+ if (!resolution.ok) {
1124
+ sendSlashText(pi, resolution.message);
1125
+ return;
1126
+ }
1127
+ if (resolution.child.nested) targetId = resolution.child.nested.id;
1128
+ else if (resolution.child.step.runId) targetId = resolution.child.step.runId;
1129
+ else childIndex = resolution.child.index;
1130
+ }
1131
+ await runCommand(ctx, {
1132
+ action: "steer",
1133
+ id: targetId,
1134
+ message,
1135
+ ...(childIndex !== undefined ? { index: childIndex } : {}),
1136
+ // Host-style exact-child authority, matching the extension RPC
1137
+ // nonRecoveringSteer guarantee: never swap the addressed child for
1138
+ // a pause-and-revive replacement after a missed acknowledgment.
1139
+ steeringRecovery: false,
1140
+ });
861
1141
  },
862
1142
  });
863
1143
 
864
1144
  registerPromptWorkflowCommands({
865
1145
  pi,
866
1146
  run: async (params, ctx) => {
867
- launchSlashSubagent(pi, ctx, params);
1147
+ launchCommand(ctx, params);
868
1148
  },
869
1149
  });
870
1150
 
871
1151
  pi.registerCommand("subagents-models", {
872
1152
  description: "Show runtime-loaded builtin subagent models",
873
1153
  getArgumentCompletions: makeBuiltinAgentNameCompletions(),
874
- handler: async (args, ctx) => {
875
- const trimmed = args.trim();
876
- if (!trimmed) {
877
- await runSlashSubagent(pi, ctx, { action: "models" });
1154
+ handler: async (args, ctx) => {
1155
+ const trimmed = args.trim();
1156
+ if (!trimmed) {
1157
+ await runCommand(ctx, { action: "models" });
878
1158
  return;
879
1159
  }
880
1160
  const parts = trimmed.split(/\s+/).filter(Boolean);
@@ -887,7 +1167,7 @@ export function registerSlashCommands(
887
1167
  ctx.ui.notify(`Unknown builtin agent: ${agent}`, "error");
888
1168
  return;
889
1169
  }
890
- await runSlashSubagent(pi, ctx, { action: "models", agent });
1170
+ await runCommand(ctx, { action: "models", agent });
891
1171
  },
892
1172
  });
893
1173
 
@@ -1060,4 +1340,14 @@ export function registerSlashCommands(
1060
1340
  },
1061
1341
  });
1062
1342
 
1343
+ return {
1344
+ dispose: () => {
1345
+ if (disposed) return;
1346
+ disposed = true;
1347
+ // A reload revokes the command context; do not let delayed responses
1348
+ // resume a command against the old Pi context.
1349
+ for (const controller of pendingRequests) controller.abort();
1350
+ pendingRequests.clear();
1351
+ },
1352
+ };
1063
1353
  }