pi-subagents 0.76.1 → 0.78.0

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 (391) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/README.md +1 -1
  3. package/agents/evidence-auditor.md +1 -0
  4. package/agents/oracle.md +9 -19
  5. package/agents/researcher.md +0 -3
  6. package/agents/reviewer.md +18 -61
  7. package/agents/scout.md +1 -4
  8. package/agents/worker.md +8 -25
  9. package/docs/agents.md +71 -4
  10. package/docs/configuration.md +75 -10
  11. package/docs/extension-api.md +38 -9
  12. package/docs/missions.md +24 -17
  13. package/docs/models.md +1 -1
  14. package/docs/observability.md +12 -5
  15. package/docs/tool-reference.md +103 -85
  16. package/docs/watchdog.md +8 -6
  17. package/docs/workflows.md +17 -8
  18. package/package.json +1 -1
  19. package/prompts/council.md +1 -1
  20. package/skills/pi-subagents/SKILL.md +2 -2
  21. package/skills/pi-subagents/references/constraints-and-recipes.md +1 -1
  22. package/skills/pi-subagents/references/execution-controls.md +16 -16
  23. package/skills/pi-subagents/references/management-authoring-rpc.md +16 -12
  24. package/skills/pi-subagents/references/multi-lane-orchestration.md +1 -1
  25. package/skills/pi-subagents/references/prompting-and-roles.md +3 -3
  26. package/src/agents/advertised-agent-prompt.d.ts +5 -1
  27. package/src/agents/advertised-agent-prompt.d.ts.map +1 -1
  28. package/src/agents/advertised-agent-prompt.js +8 -2
  29. package/src/agents/advertised-agent-prompt.js.map +1 -1
  30. package/src/agents/agent-management.d.ts.map +1 -1
  31. package/src/agents/agent-management.js +5 -0
  32. package/src/agents/agent-management.js.map +1 -1
  33. package/src/agents/agent-scope.d.ts +1 -0
  34. package/src/agents/agent-scope.d.ts.map +1 -1
  35. package/src/agents/agent-scope.js +3 -0
  36. package/src/agents/agent-scope.js.map +1 -1
  37. package/src/agents/agent-serializer.d.ts.map +1 -1
  38. package/src/agents/agent-serializer.js +3 -0
  39. package/src/agents/agent-serializer.js.map +1 -1
  40. package/src/agents/agents.d.ts +14 -2
  41. package/src/agents/agents.d.ts.map +1 -1
  42. package/src/agents/agents.js +94 -36
  43. package/src/agents/agents.js.map +1 -1
  44. package/src/api/external-runs.d.ts.map +1 -1
  45. package/src/api/external-runs.js +5 -4
  46. package/src/api/external-runs.js.map +1 -1
  47. package/src/api/preflight.d.ts +2 -0
  48. package/src/api/preflight.d.ts.map +1 -1
  49. package/src/api/preflight.js +7 -3
  50. package/src/api/preflight.js.map +1 -1
  51. package/src/extension/active-runs-prompt.d.ts +8 -0
  52. package/src/extension/active-runs-prompt.d.ts.map +1 -0
  53. package/src/extension/active-runs-prompt.js +30 -0
  54. package/src/extension/active-runs-prompt.js.map +1 -0
  55. package/src/extension/config.d.ts.map +1 -1
  56. package/src/extension/config.js +29 -2
  57. package/src/extension/config.js.map +1 -1
  58. package/src/extension/control-notices.d.ts +0 -2
  59. package/src/extension/control-notices.d.ts.map +1 -1
  60. package/src/extension/control-notices.js +1 -7
  61. package/src/extension/control-notices.js.map +1 -1
  62. package/src/extension/declaration-pinning.d.ts +19 -0
  63. package/src/extension/declaration-pinning.d.ts.map +1 -0
  64. package/src/extension/declaration-pinning.js +154 -0
  65. package/src/extension/declaration-pinning.js.map +1 -0
  66. package/src/extension/fanout-child.d.ts.map +1 -1
  67. package/src/extension/fanout-child.js +6 -8
  68. package/src/extension/fanout-child.js.map +1 -1
  69. package/src/extension/index.d.ts +1 -2
  70. package/src/extension/index.d.ts.map +1 -1
  71. package/src/extension/index.js +104 -121
  72. package/src/extension/index.js.map +1 -1
  73. package/src/extension/rpc.d.ts.map +1 -1
  74. package/src/extension/rpc.js +12 -6
  75. package/src/extension/rpc.js.map +1 -1
  76. package/src/extension/schemas.d.ts +137 -1
  77. package/src/extension/schemas.d.ts.map +1 -1
  78. package/src/extension/schemas.js +22 -22
  79. package/src/extension/schemas.js.map +1 -1
  80. package/src/extension/subagent-guide.d.ts +1 -0
  81. package/src/extension/subagent-guide.d.ts.map +1 -1
  82. package/src/extension/subagent-guide.js +80 -6
  83. package/src/extension/subagent-guide.js.map +1 -1
  84. package/src/extension/subagent-options.d.ts +8 -0
  85. package/src/extension/subagent-options.d.ts.map +1 -0
  86. package/src/extension/subagent-options.js +52 -0
  87. package/src/extension/subagent-options.js.map +1 -0
  88. package/src/extension/tool-activation.d.ts.map +1 -1
  89. package/src/extension/tool-activation.js +7 -4
  90. package/src/extension/tool-activation.js.map +1 -1
  91. package/src/extension/tool-description.d.ts +4 -7
  92. package/src/extension/tool-description.d.ts.map +1 -1
  93. package/src/extension/tool-description.js +45 -59
  94. package/src/extension/tool-description.js.map +1 -1
  95. package/src/inspectors/actions.d.ts +2 -0
  96. package/src/inspectors/actions.d.ts.map +1 -1
  97. package/src/inspectors/actions.js +41 -13
  98. package/src/inspectors/actions.js.map +1 -1
  99. package/src/inspectors/plugins.d.ts.map +1 -1
  100. package/src/inspectors/plugins.js +3 -2
  101. package/src/inspectors/plugins.js.map +1 -1
  102. package/src/inspectors/tmux/actions.d.ts +26 -0
  103. package/src/inspectors/tmux/actions.d.ts.map +1 -0
  104. package/src/inspectors/tmux/actions.js +182 -0
  105. package/src/inspectors/tmux/actions.js.map +1 -0
  106. package/src/inspectors/tmux/client.d.ts +28 -0
  107. package/src/inspectors/tmux/client.d.ts.map +1 -0
  108. package/src/inspectors/tmux/client.js +65 -0
  109. package/src/inspectors/tmux/client.js.map +1 -0
  110. package/src/inspectors/tmux/plugin.d.ts +8 -0
  111. package/src/inspectors/tmux/plugin.d.ts.map +1 -0
  112. package/src/inspectors/tmux/plugin.js +15 -0
  113. package/src/inspectors/tmux/plugin.js.map +1 -0
  114. package/src/integrations/program-status.d.ts +31 -0
  115. package/src/integrations/program-status.d.ts.map +1 -0
  116. package/src/integrations/program-status.js +189 -0
  117. package/src/integrations/program-status.js.map +1 -0
  118. package/src/intercom/native-supervisor-channel.d.ts +16 -1
  119. package/src/intercom/native-supervisor-channel.d.ts.map +1 -1
  120. package/src/intercom/native-supervisor-channel.js +101 -8
  121. package/src/intercom/native-supervisor-channel.js.map +1 -1
  122. package/src/intercom/result-intercom.js +1 -1
  123. package/src/intercom/result-intercom.js.map +1 -1
  124. package/src/intercom/supervisor-ui.d.ts +2 -12
  125. package/src/intercom/supervisor-ui.d.ts.map +1 -1
  126. package/src/intercom/supervisor-ui.js +2 -154
  127. package/src/intercom/supervisor-ui.js.map +1 -1
  128. package/src/missions/store.d.ts.map +1 -1
  129. package/src/missions/store.js +27 -5
  130. package/src/missions/store.js.map +1 -1
  131. package/src/runs/background/active-async-capacity.d.ts +2 -1
  132. package/src/runs/background/active-async-capacity.d.ts.map +1 -1
  133. package/src/runs/background/active-async-capacity.js +10 -6
  134. package/src/runs/background/active-async-capacity.js.map +1 -1
  135. package/src/runs/background/async-execution.d.ts +9 -1
  136. package/src/runs/background/async-execution.d.ts.map +1 -1
  137. package/src/runs/background/async-execution.js +253 -144
  138. package/src/runs/background/async-execution.js.map +1 -1
  139. package/src/runs/background/async-job-tracker.d.ts +4 -1
  140. package/src/runs/background/async-job-tracker.d.ts.map +1 -1
  141. package/src/runs/background/async-job-tracker.js +3 -2
  142. package/src/runs/background/async-job-tracker.js.map +1 -1
  143. package/src/runs/background/async-resume.d.ts.map +1 -1
  144. package/src/runs/background/async-resume.js +9 -3
  145. package/src/runs/background/async-resume.js.map +1 -1
  146. package/src/runs/background/await-async-run.d.ts +8 -4
  147. package/src/runs/background/await-async-run.d.ts.map +1 -1
  148. package/src/runs/background/await-async-run.js +14 -8
  149. package/src/runs/background/await-async-run.js.map +1 -1
  150. package/src/runs/background/binary-bootstrap.d.ts.map +1 -1
  151. package/src/runs/background/binary-bootstrap.js +2 -1
  152. package/src/runs/background/binary-bootstrap.js.map +1 -1
  153. package/src/runs/background/chain-root-attachment.d.ts +2 -0
  154. package/src/runs/background/chain-root-attachment.d.ts.map +1 -1
  155. package/src/runs/background/chain-root-attachment.js +9 -6
  156. package/src/runs/background/chain-root-attachment.js.map +1 -1
  157. package/src/runs/background/control-channel.d.ts +1 -0
  158. package/src/runs/background/control-channel.d.ts.map +1 -1
  159. package/src/runs/background/control-channel.js +27 -3
  160. package/src/runs/background/control-channel.js.map +1 -1
  161. package/src/runs/background/fleet-view.js +5 -5
  162. package/src/runs/background/fleet-view.js.map +1 -1
  163. package/src/runs/background/notify.d.ts +6 -1
  164. package/src/runs/background/notify.d.ts.map +1 -1
  165. package/src/runs/background/notify.js +130 -14
  166. package/src/runs/background/notify.js.map +1 -1
  167. package/src/runs/background/result-files.d.ts +27 -0
  168. package/src/runs/background/result-files.d.ts.map +1 -1
  169. package/src/runs/background/result-files.js +100 -6
  170. package/src/runs/background/result-files.js.map +1 -1
  171. package/src/runs/background/result-watcher.d.ts.map +1 -1
  172. package/src/runs/background/result-watcher.js +60 -64
  173. package/src/runs/background/result-watcher.js.map +1 -1
  174. package/src/runs/background/resume-guidance.js +2 -2
  175. package/src/runs/background/resume-guidance.js.map +1 -1
  176. package/src/runs/background/run-child-session.d.ts.map +1 -1
  177. package/src/runs/background/run-child-session.js +9 -15
  178. package/src/runs/background/run-child-session.js.map +1 -1
  179. package/src/runs/background/run-id-resolver.d.ts.map +1 -1
  180. package/src/runs/background/run-id-resolver.js +9 -6
  181. package/src/runs/background/run-id-resolver.js.map +1 -1
  182. package/src/runs/background/run-status.d.ts.map +1 -1
  183. package/src/runs/background/run-status.js +19 -15
  184. package/src/runs/background/run-status.js.map +1 -1
  185. package/src/runs/background/runner-aliases.d.ts.map +1 -1
  186. package/src/runs/background/runner-aliases.js +11 -8
  187. package/src/runs/background/runner-aliases.js.map +1 -1
  188. package/src/runs/background/runner-child-launch.d.ts.map +1 -1
  189. package/src/runs/background/runner-child-launch.js +1 -0
  190. package/src/runs/background/runner-child-launch.js.map +1 -1
  191. package/src/runs/background/runner-http-dispatcher.d.ts +3 -0
  192. package/src/runs/background/runner-http-dispatcher.d.ts.map +1 -1
  193. package/src/runs/background/runner-http-dispatcher.js +2 -0
  194. package/src/runs/background/runner-http-dispatcher.js.map +1 -1
  195. package/src/runs/background/scheduled-runs.d.ts +9 -0
  196. package/src/runs/background/scheduled-runs.d.ts.map +1 -1
  197. package/src/runs/background/scheduled-runs.js +124 -36
  198. package/src/runs/background/scheduled-runs.js.map +1 -1
  199. package/src/runs/background/subagent-runner-bootstrap.d.ts.map +1 -1
  200. package/src/runs/background/subagent-runner-bootstrap.js +5 -1
  201. package/src/runs/background/subagent-runner-bootstrap.js.map +1 -1
  202. package/src/runs/background/subagent-runner.d.ts +3 -1
  203. package/src/runs/background/subagent-runner.d.ts.map +1 -1
  204. package/src/runs/background/subagent-runner.js +211 -283
  205. package/src/runs/background/subagent-runner.js.map +1 -1
  206. package/src/runs/background/subagent-wait.d.ts +2 -0
  207. package/src/runs/background/subagent-wait.d.ts.map +1 -1
  208. package/src/runs/background/subagent-wait.js +34 -20
  209. package/src/runs/background/subagent-wait.js.map +1 -1
  210. package/src/runs/background/terminal-run-index.d.ts +1 -0
  211. package/src/runs/background/terminal-run-index.d.ts.map +1 -1
  212. package/src/runs/background/terminal-run-index.js +47 -1
  213. package/src/runs/background/terminal-run-index.js.map +1 -1
  214. package/src/runs/background/wait-tool.d.ts.map +1 -1
  215. package/src/runs/background/wait-tool.js +36 -23
  216. package/src/runs/background/wait-tool.js.map +1 -1
  217. package/src/runs/background/workflow-terminal-proof.d.ts +1 -1
  218. package/src/runs/background/workflow-terminal-proof.d.ts.map +1 -1
  219. package/src/runs/background/workflow-terminal-proof.js +12 -3
  220. package/src/runs/background/workflow-terminal-proof.js.map +1 -1
  221. package/src/runs/foreground/async-stop-action.d.ts +7 -1
  222. package/src/runs/foreground/async-stop-action.d.ts.map +1 -1
  223. package/src/runs/foreground/async-stop-action.js +27 -23
  224. package/src/runs/foreground/async-stop-action.js.map +1 -1
  225. package/src/runs/foreground/execution.d.ts.map +1 -1
  226. package/src/runs/foreground/execution.js +91 -69
  227. package/src/runs/foreground/execution.js.map +1 -1
  228. package/src/runs/foreground/subagent-executor.d.ts +4 -1
  229. package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  230. package/src/runs/foreground/subagent-executor.js +174 -79
  231. package/src/runs/foreground/subagent-executor.js.map +1 -1
  232. package/src/runs/shared/child-hooks.js +6 -5
  233. package/src/runs/shared/child-hooks.js.map +1 -1
  234. package/src/runs/shared/child-launch.d.ts +2 -0
  235. package/src/runs/shared/child-launch.d.ts.map +1 -1
  236. package/src/runs/shared/child-launch.js +1 -0
  237. package/src/runs/shared/child-launch.js.map +1 -1
  238. package/src/runs/shared/child-session.d.ts +4 -0
  239. package/src/runs/shared/child-session.d.ts.map +1 -1
  240. package/src/runs/shared/child-session.js +28 -23
  241. package/src/runs/shared/child-session.js.map +1 -1
  242. package/src/runs/shared/child-tool-plan.d.ts.map +1 -1
  243. package/src/runs/shared/child-tool-plan.js +11 -10
  244. package/src/runs/shared/child-tool-plan.js.map +1 -1
  245. package/src/runs/shared/dynamic-fanout.js +1 -1
  246. package/src/runs/shared/dynamic-fanout.js.map +1 -1
  247. package/src/runs/shared/effective-system-prompt.d.ts +4 -4
  248. package/src/runs/shared/effective-system-prompt.d.ts.map +1 -1
  249. package/src/runs/shared/effective-system-prompt.js +5 -4
  250. package/src/runs/shared/effective-system-prompt.js.map +1 -1
  251. package/src/runs/shared/external-cli-runner.d.ts.map +1 -1
  252. package/src/runs/shared/external-cli-runner.js +3 -2
  253. package/src/runs/shared/external-cli-runner.js.map +1 -1
  254. package/src/runs/shared/herdr-placed-run.d.ts +1 -0
  255. package/src/runs/shared/herdr-placed-run.d.ts.map +1 -1
  256. package/src/runs/shared/herdr-placed-run.js +10 -6
  257. package/src/runs/shared/herdr-placed-run.js.map +1 -1
  258. package/src/runs/shared/model-resolution-diagnostic.d.ts +17 -5
  259. package/src/runs/shared/model-resolution-diagnostic.d.ts.map +1 -1
  260. package/src/runs/shared/model-resolution-diagnostic.js +37 -10
  261. package/src/runs/shared/model-resolution-diagnostic.js.map +1 -1
  262. package/src/runs/shared/model-resolution.d.ts.map +1 -1
  263. package/src/runs/shared/model-resolution.js +29 -1
  264. package/src/runs/shared/model-resolution.js.map +1 -1
  265. package/src/runs/shared/nested-events.d.ts +2 -0
  266. package/src/runs/shared/nested-events.d.ts.map +1 -1
  267. package/src/runs/shared/nested-events.js +4 -0
  268. package/src/runs/shared/nested-events.js.map +1 -1
  269. package/src/runs/shared/orca-progress-tabs.js +1 -1
  270. package/src/runs/shared/orca-progress-tabs.js.map +1 -1
  271. package/src/runs/shared/parallel-handoff.js +2 -2
  272. package/src/runs/shared/parallel-handoff.js.map +1 -1
  273. package/src/runs/shared/parallel-utils.d.ts +2 -0
  274. package/src/runs/shared/parallel-utils.d.ts.map +1 -1
  275. package/src/runs/shared/parallel-utils.js.map +1 -1
  276. package/src/runs/shared/partial-output.d.ts +7 -0
  277. package/src/runs/shared/partial-output.d.ts.map +1 -1
  278. package/src/runs/shared/partial-output.js +7 -0
  279. package/src/runs/shared/partial-output.js.map +1 -1
  280. package/src/runs/shared/runner-launcher.d.ts +12 -0
  281. package/src/runs/shared/runner-launcher.d.ts.map +1 -0
  282. package/src/runs/shared/runner-launcher.js +25 -0
  283. package/src/runs/shared/runner-launcher.js.map +1 -0
  284. package/src/runs/shared/single-output.d.ts +31 -1
  285. package/src/runs/shared/single-output.d.ts.map +1 -1
  286. package/src/runs/shared/single-output.js +100 -21
  287. package/src/runs/shared/single-output.js.map +1 -1
  288. package/src/runs/shared/structured-output.d.ts +2 -0
  289. package/src/runs/shared/structured-output.d.ts.map +1 -1
  290. package/src/runs/shared/structured-output.js +26 -8
  291. package/src/runs/shared/structured-output.js.map +1 -1
  292. package/src/runs/shared/subagent-control.js +3 -3
  293. package/src/runs/shared/subagent-control.js.map +1 -1
  294. package/src/runs/shared/subagent-prompt-runtime.d.ts +37 -2
  295. package/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
  296. package/src/runs/shared/subagent-prompt-runtime.js +127 -20
  297. package/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
  298. package/src/runs/shared/tool-budget.js +1 -1
  299. package/src/runs/shared/tool-budget.js.map +1 -1
  300. package/src/runs/shared/workflow-async-child-guidance.js +1 -1
  301. package/src/runs/shared/workflow-async-child-guidance.js.map +1 -1
  302. package/src/runs/shared/worktree-cleanup-plan.js +1 -1
  303. package/src/runs/shared/worktree-cleanup-plan.js.map +1 -1
  304. package/src/shared/atomic-json.d.ts +4 -3
  305. package/src/shared/atomic-json.d.ts.map +1 -1
  306. package/src/shared/atomic-json.js +3 -1
  307. package/src/shared/atomic-json.js.map +1 -1
  308. package/src/shared/child-transcript.js +1 -1
  309. package/src/shared/child-transcript.js.map +1 -1
  310. package/src/shared/edit-distance.d.ts +5 -0
  311. package/src/shared/edit-distance.d.ts.map +1 -0
  312. package/src/shared/edit-distance.js +33 -0
  313. package/src/shared/edit-distance.js.map +1 -0
  314. package/src/shared/extension-context.d.ts +5 -0
  315. package/src/shared/extension-context.d.ts.map +1 -1
  316. package/src/shared/extension-context.js +7 -0
  317. package/src/shared/extension-context.js.map +1 -1
  318. package/src/shared/formatters.d.ts.map +1 -1
  319. package/src/shared/formatters.js +1 -6
  320. package/src/shared/formatters.js.map +1 -1
  321. package/src/shared/model-info.d.ts +8 -0
  322. package/src/shared/model-info.d.ts.map +1 -1
  323. package/src/shared/model-info.js +22 -0
  324. package/src/shared/model-info.js.map +1 -1
  325. package/src/shared/parent-wake.d.ts +7 -1
  326. package/src/shared/parent-wake.d.ts.map +1 -1
  327. package/src/shared/parent-wake.js +36 -12
  328. package/src/shared/parent-wake.js.map +1 -1
  329. package/src/shared/pruned-fork.d.ts +1 -1
  330. package/src/shared/pruned-fork.d.ts.map +1 -1
  331. package/src/shared/pruned-fork.js +6 -0
  332. package/src/shared/pruned-fork.js.map +1 -1
  333. package/src/shared/runtime-module-path.d.ts +11 -0
  334. package/src/shared/runtime-module-path.d.ts.map +1 -0
  335. package/src/shared/runtime-module-path.js +17 -0
  336. package/src/shared/runtime-module-path.js.map +1 -0
  337. package/src/shared/types.d.ts +33 -10
  338. package/src/shared/types.d.ts.map +1 -1
  339. package/src/shared/types.js +7 -4
  340. package/src/shared/types.js.map +1 -1
  341. package/src/shared/utils.d.ts +2 -0
  342. package/src/shared/utils.d.ts.map +1 -1
  343. package/src/shared/utils.js +10 -7
  344. package/src/shared/utils.js.map +1 -1
  345. package/src/slash/slash-commands.d.ts.map +1 -1
  346. package/src/slash/slash-commands.js +21 -10
  347. package/src/slash/slash-commands.js.map +1 -1
  348. package/src/slash/subagents-admin.d.ts.map +1 -1
  349. package/src/slash/subagents-admin.js +3 -1
  350. package/src/slash/subagents-admin.js.map +1 -1
  351. package/src/tui/fleet-status.d.ts +5 -0
  352. package/src/tui/fleet-status.d.ts.map +1 -1
  353. package/src/tui/fleet-status.js +24 -3
  354. package/src/tui/fleet-status.js.map +1 -1
  355. package/src/tui/fleet-transcript.d.ts +2 -0
  356. package/src/tui/fleet-transcript.d.ts.map +1 -1
  357. package/src/tui/fleet-transcript.js +7 -2
  358. package/src/tui/fleet-transcript.js.map +1 -1
  359. package/src/tui/fleet.d.ts.map +1 -1
  360. package/src/tui/fleet.js +11 -6
  361. package/src/tui/fleet.js.map +1 -1
  362. package/src/tui/render.d.ts +2 -2
  363. package/src/tui/render.d.ts.map +1 -1
  364. package/src/tui/render.js +19 -17
  365. package/src/tui/render.js.map +1 -1
  366. package/src/tui/subagent-messages.d.ts +23 -0
  367. package/src/tui/subagent-messages.d.ts.map +1 -0
  368. package/src/tui/subagent-messages.js +270 -0
  369. package/src/tui/subagent-messages.js.map +1 -0
  370. package/src/watchdog/change-signature.d.ts.map +1 -1
  371. package/src/watchdog/change-signature.js +1 -3
  372. package/src/watchdog/change-signature.js.map +1 -1
  373. package/src/watchdog/register-main.d.ts.map +1 -1
  374. package/src/watchdog/register-main.js +1 -19
  375. package/src/watchdog/register-main.js.map +1 -1
  376. package/src/watchdog/render.d.ts +2 -10
  377. package/src/watchdog/render.d.ts.map +1 -1
  378. package/src/watchdog/render.js +1 -19
  379. package/src/watchdog/render.js.map +1 -1
  380. package/src/watchdog/tool-actions.js +2 -2
  381. package/src/watchdog/tool-actions.js.map +1 -1
  382. package/src/workflows/scripted-workflow.d.ts.map +1 -1
  383. package/src/workflows/scripted-workflow.js +33 -10
  384. package/src/workflows/scripted-workflow.js.map +1 -1
  385. package/src/workflows/workflow-resources.d.ts.map +1 -1
  386. package/src/workflows/workflow-resources.js +12 -0
  387. package/src/workflows/workflow-resources.js.map +1 -1
  388. package/src/runs/shared/run-history.d.ts +0 -67
  389. package/src/runs/shared/run-history.d.ts.map +0 -1
  390. package/src/runs/shared/run-history.js +0 -270
  391. package/src/runs/shared/run-history.js.map +0 -1
@@ -15,8 +15,7 @@ import { randomUUID } from "node:crypto";
15
15
  import * as fs from "node:fs";
16
16
  import * as os from "node:os";
17
17
  import * as path from "node:path";
18
- import { keyText } from "@earendil-works/pi-coding-agent";
19
- import { Box, Container, Spacer, Text, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui";
18
+ import { Box, Container, Spacer, Text } from "@earendil-works/pi-tui";
20
19
  import { clearAgentDiscoveryCache, discoverAgentSnapshot, discoverAgents, discoverAgentsAll } from "../agents/agents.js";
21
20
  import { resolveGlobalNpmRoot } from "../agents/global-npm-root.js";
22
21
  import { buildAdvertisedAgentCatalog, buildAdvertisedAgentPrompt } from "../agents/advertised-agent-prompt.js";
@@ -46,9 +45,10 @@ import { registerSlashCommands } from "../slash/slash-commands.js";
46
45
  import { registerPromptTemplateDelegationBridge } from "../slash/prompt-template-bridge.js";
47
46
  import { registerMainWatchdog } from "../watchdog/register-main.js";
48
47
  import { registerSlashSubagentBridge } from "../slash/slash-bridge.js";
49
- import { createNativeSupervisorChannel } from "../intercom/native-supervisor-channel.js";
50
- import { renderSupervisorReply, renderSupervisorRequest, SUPERVISOR_REPLY_ENTRY_TYPE, SUPERVISOR_REQUEST_MESSAGE_TYPE, } from "../intercom/supervisor-ui.js";
48
+ import { createNativeSupervisorChannel, topLevelSupervisorTool } from "../intercom/native-supervisor-channel.js";
49
+ import { renderSubagentEntry, renderSubagentMessage, SUBAGENT_ENTRY_TYPES, SUBAGENT_MESSAGE_TYPES } from "../tui/subagent-messages.js";
51
50
  import { registerHerdrStatusBridge } from "../integrations/herdr-status.js";
51
+ import { registerProgramStatusReporter } from "../integrations/program-status.js";
52
52
  import { hasLiveSubagentWork, registerPiWebSessionLiveness } from "../integrations/pi-web-session-liveness.js";
53
53
  import { createRetainedNestedRouteTracker } from "../runs/background/retained-nested-route-tracker.js";
54
54
  import { listHerdrProjectPaneRoots, restoreHerdrProjectPaneSnapshots } from "../inspectors/herdr/project-panes.js";
@@ -57,32 +57,34 @@ import { clearSlashSnapshots, getSlashRenderableSnapshot, resolveSlashMessageDet
57
57
  import { resolveWaitToolConfig } from "../runs/background/subagent-wait.js";
58
58
  import { registerWaitTool } from "../runs/background/wait-tool.js";
59
59
  import { registerSubagentToolActivation } from "./tool-activation.js";
60
+ import { recordedPromptSection, registerPinnedTool, setDeclarationPinning } from "./declaration-pinning.js";
61
+ import { buildActiveRunsSection } from "./active-runs-prompt.js";
60
62
  import { createWaitSubscriptionManager } from "../runs/background/wait-subscriptions.js";
61
63
  import { drainOutstandingWork } from "../runs/background/auto-drain.js";
62
- import registerSubagentNotify, { parseSubagentNotifyContent } from "../runs/background/notify.js";
64
+ import registerSubagentNotify from "../runs/background/notify.js";
63
65
  import { createParentWake } from "../shared/parent-wake.js";
64
- import { formatSteeringNotice, handleSubagentSteeringNotice, SUBAGENT_STEERING_MESSAGE_TYPE } from "./steering-notices.js";
66
+ import { handleSubagentSteeringNotice } from "./steering-notices.js";
65
67
  import { SUBAGENT_CHILD_ENV, SUBAGENT_PARENT_SESSION_ENV } from "../runs/shared/child-runtime-config.js";
66
68
  import { disposeChildSessions } from "../runs/shared/child-session.js";
67
69
  import { resolveCurrentSubagentCapabilityCeiling } from "../runs/shared/capability-ceiling.js";
68
- import { formatDuration, shortenPath } from "../shared/formatters.js";
69
70
  import { loadConfig, resolveAsyncByDefault, resolveScheduledStoreRoot } from "./config.js";
70
71
  import { buildSubagentToolDescription, buildSubagentToolPromptMetadata } from "./tool-description.js";
71
72
  import { formatWorkflowPreflightSummary, normalizeWorkflowPreflight } from "../workflows/workflow-preflight.js";
72
73
  import { runtimeReplacedAbortReason } from "../workflows/workflow-reuse.js";
73
74
  import { finalizeToolResult } from "./tool-result.js";
74
- import { removedModelWorkflowFieldError } from "./public-execution.js";
75
+ import { flattenSubagentToolOptions } from "./subagent-options.js";
75
76
  import { collectGoalContinuationNotices } from "../missions/goal-driver.js";
76
77
  import { restoreForegroundRunHistory } from "../runs/foreground/foreground-history.js";
77
78
  import { resolveMissionStoreLocation } from "../missions/store.js";
78
79
  import { listRetainedChildren } from "../runs/background/retained-children.js";
79
80
  import { DIRS, DEFAULT_ARTIFACT_CONFIG, SLASH_RESULT_TYPE, SLASH_TEXT_RESULT_TYPE, SUBAGENT_ASYNC_COMPLETE_EVENT, SUBAGENT_ASYNC_STARTED_EVENT, SUBAGENT_PROCESS_TERMINAL_EVENT, SUBAGENT_CONTROL_EVENT, SUBAGENT_STEERING_NOTICE_EVENT, WIDGET_KEY, resolveMaxSubagentSpawnsPerSession, } from "../shared/types.js";
80
- import { formatSubagentControlNotice, handleSubagentControlNotice, SUBAGENT_CONTROL_MESSAGE_TYPE, } from "./control-notices.js";
81
+ import { handleSubagentControlNotice, } from "./control-notices.js";
81
82
  import { showUpgradeNotice } from "./upgrade-notice.js";
82
- export { loadConfig, resolveAsyncByDefault } from "./config.js";
83
83
  const SLOW_RELOAD_PHASE_MS = 250;
84
84
  // Long enough for Pi to finish starting; loading the executor blocks the event loop for tens of ms.
85
85
  const MODULE_PRELOAD_DELAY_MS = 1_000;
86
+ const COMPACTION_RESUME_POLL_MS = 50;
87
+ const COMPACTION_RESUME_DEADLINE_MS = 10_000;
86
88
  const RUNTIME_REGISTRY_STORE_KEY = "__piSubagentRuntimeRegistry";
87
89
  function getRuntimeRegistry() {
88
90
  const globalStore = globalThis;
@@ -166,33 +168,6 @@ function createSlashResultComponent(details, options, theme, rendererConfig, for
166
168
  };
167
169
  return container;
168
170
  }
169
- class SubagentControlNoticeComponent {
170
- details;
171
- theme;
172
- constructor(details, theme) {
173
- this.details = details;
174
- this.theme = theme;
175
- }
176
- invalidate() { }
177
- render(width) {
178
- const eventLabel = this.details.event.type.replaceAll("_", " ");
179
- if (width < 3)
180
- return [truncateToWidth(`Subagent ${eventLabel}`, width)];
181
- const bodyWidth = Math.max(1, width - 2);
182
- const borderChar = "─";
183
- const header = ` ⚠ Subagent ${eventLabel}: ${this.details.event.agent} `;
184
- const headerText = truncateToWidth(header, bodyWidth, "");
185
- const headerPadding = Math.max(0, bodyWidth - visibleWidth(headerText));
186
- const lines = [this.theme.fg("accent", `╭${headerText}${borderChar.repeat(headerPadding)}╮`)];
187
- for (const line of wrapTextWithAnsi(formatSubagentControlNotice(this.details), bodyWidth)) {
188
- const text = truncateToWidth(line, bodyWidth, "");
189
- const padding = Math.max(0, bodyWidth - visibleWidth(text));
190
- lines.push(this.theme.fg("accent", `│${text}${" ".repeat(padding)}│`));
191
- }
192
- lines.push(this.theme.fg("accent", `╰${borderChar.repeat(bodyWidth)}╯`));
193
- return lines;
194
- }
195
- }
196
171
  export function projectActiveHerdrRuns(state) {
197
172
  const active = (status) => status === "queued" || status === "running";
198
173
  const foregroundChildrenByWorkflow = new Map();
@@ -250,12 +225,14 @@ export default function registerSubagentExtension(pi) {
250
225
  DIRS.async = ensureAccessibleDir(DIRS.async);
251
226
  cleanupOldChainDirs();
252
227
  const config = loadConfig();
228
+ setDeclarationPinning(pi, config.pinToolDeclarations !== false);
253
229
  const waitToolConfig = resolveWaitToolConfig(config.waitTool);
254
230
  const asyncByDefault = resolveAsyncByDefault(config);
255
231
  const fleetViewEnabled = config.fleetView !== false;
256
232
  const fleetViewPlacement = resolveFleetViewPlacement(config.fleetViewPlacement);
257
233
  const asyncWidgetEnabled = config.asyncWidget !== false;
258
234
  const asyncWidgetCollapsed = config.asyncWidgetCollapsed === true;
235
+ const asyncWidgetLayout = config.asyncWidgetLayout ?? "adaptive";
259
236
  const summaryInlineToolDisplay = config.inlineToolDisplay === "summary";
260
237
  const tempArtifactsDir = getArtifactsDir(null);
261
238
  const artifactCleanupDays = config.artifactConfig?.cleanupDays ?? DEFAULT_ARTIFACT_CONFIG.cleanupDays;
@@ -307,7 +284,7 @@ export default function registerSubagentExtension(pi) {
307
284
  };
308
285
  // Every notice that wakes the parent goes through parentWake; the watchdog wakes only inside a run.
309
286
  const parentWake = createParentWake(pi);
310
- const wakingPi = { events: pi.events, sendMessage: parentWake.sendMessage };
287
+ const wakingPi = { events: pi.events, sendMessage: parentWake.sendMessage, isHeld: parentWake.isHeld, on: pi.on };
311
288
  const supervisorChannel = createNativeSupervisorChannel(pi, state, {
312
289
  // Owner states are created only by scheduled execution, which loads the executor first.
313
290
  getCurrentOwnerStates: () => executor?.getCurrentSupervisorOwnerStates() ?? [],
@@ -381,7 +358,7 @@ export default function registerSubagentExtension(pi) {
381
358
  if (!advertisedContext)
382
359
  return;
383
360
  clearAgentDiscoveryCache();
384
- advertisedAgents = discoverAgents(advertisedContext.cwd, "both", advertisedContext.model?.provider, { globalNpmRoot: globalRoot }).agents
361
+ advertisedAgents = discoverAgents(advertisedContext.cwd, "both", advertisedContext.model?.provider, { globalNpmRoot: globalRoot, projectTrusted: advertisedContext.projectTrusted }).agents
385
362
  .filter((agent) => agent.advertise === true);
386
363
  };
387
364
  const beginAdvertisement = (ctx) => {
@@ -389,7 +366,7 @@ export default function registerSubagentExtension(pi) {
389
366
  notifySessionChange();
390
367
  sessionChanged = new Promise((resolve) => { notifySessionChange = resolve; });
391
368
  advertisedAgents = [];
392
- advertisedContext = { cwd: ctx.cwd, model: ctx.model };
369
+ advertisedContext = { cwd: ctx.cwd, model: ctx.model, projectTrusted: typeof ctx.isProjectTrusted === "function" ? ctx.isProjectTrusted() : undefined };
393
370
  globalRoot = null;
394
371
  advertisementReady = resolveGlobalNpmRoot().then((root) => {
395
372
  if (generation !== advertisementGeneration)
@@ -404,10 +381,11 @@ export default function registerSubagentExtension(pi) {
404
381
  return { error };
405
382
  });
406
383
  };
384
+ const activeAsyncJobCount = () => [...state.asyncJobs.values()].filter((job) => job.status === "queued" || job.status === "running").length;
407
385
  const hasResultDeliveryDemand = () => {
408
386
  if (owedResultRunIds.size > 0)
409
387
  return true;
410
- if ([...state.asyncJobs.values()].some((job) => job.status === "queued" || job.status === "running"))
388
+ if (activeAsyncJobCount() > 0)
411
389
  return true;
412
390
  if (state.foregroundControls.size > 0)
413
391
  return true;
@@ -415,10 +393,10 @@ export default function registerSubagentExtension(pi) {
415
393
  return true;
416
394
  return missionObserverResultCandidateFiles(DIRS.results).length > 0;
417
395
  };
418
- const discoverAgentsForRuntime = (cwd, scope, preferredModelProvider) => {
396
+ const discoverAgentsForRuntime = (cwd, scope, preferredModelProvider, options = {}) => {
419
397
  if (listRuntimeAgentConfigs(pi).length === 0)
420
- return discoverAgents(cwd, scope, preferredModelProvider, { globalNpmRoot: globalRoot });
421
- const snapshot = discoverAgentSnapshot(cwd, scope, preferredModelProvider, { includeChains: false, globalNpmRoot: globalRoot });
398
+ return discoverAgents(cwd, scope, preferredModelProvider, { globalNpmRoot: globalRoot, projectTrusted: options.projectTrusted });
399
+ const snapshot = discoverAgentSnapshot(cwd, scope, preferredModelProvider, { includeChains: false, globalNpmRoot: globalRoot, projectTrusted: options.projectTrusted });
422
400
  const discovered = snapshot.effective;
423
401
  const all = snapshot.all;
424
402
  const configuredAgents = [
@@ -427,7 +405,8 @@ export default function registerSubagentExtension(pi) {
427
405
  ...all.user,
428
406
  ...all.project,
429
407
  ];
430
- const merged = mergeRuntimeAgents(pi, discovered, configuredAgents, { cwd, scope, preferredModelProvider });
408
+ // Runtime agents take model settings from the scope discovery actually used.
409
+ const merged = mergeRuntimeAgents(pi, discovered, configuredAgents, { cwd, scope: discovered.scope, preferredModelProvider, projectTrusted: options.projectTrusted });
431
410
  if (discovered.maxThinking === undefined)
432
411
  return merged;
433
412
  return {
@@ -435,15 +414,23 @@ export default function registerSubagentExtension(pi) {
435
414
  agents: merged.agents.map((agent) => agent.maxThinking === discovered.maxThinking ? agent : { ...agent, maxThinking: discovered.maxThinking }),
436
415
  };
437
416
  };
417
+ const programStatus = registerProgramStatusReporter({
418
+ enabled: config.programStatus !== false,
419
+ // Fleet history keeps recent finished runs after the widget drops them.
420
+ getJobs: () => new Map([...(state.fleetJobs ?? []), ...state.asyncJobs]).values(),
421
+ getPendingRequests: () => supervisorChannel.pending.values(),
422
+ });
438
423
  const { ensurePoller, refreshWidget, handleStarted, handleComplete, resetJobs, restoreActiveJobs, dispose: disposeAsyncJobTracker } = createAsyncJobTracker(pi, state, DIRS.async, {
439
424
  widgetEnabled: asyncWidgetEnabled,
440
425
  widgetCollapsed: asyncWidgetCollapsed,
426
+ widgetLayout: asyncWidgetLayout,
441
427
  onJobTerminal: (job) => {
442
428
  holdOwedResult(job);
443
429
  refreshResultDelivery();
444
430
  },
445
431
  onJobCleanup: (asyncId) => deliveredRunIds.delete(asyncId),
446
432
  supervisorRequestState: supervisorChannel.getSupervisorRequestState,
433
+ onJobsChanged: programStatus.sync,
447
434
  });
448
435
  const resultWatcher = createResultWatcher(pi, state, DIRS.results, 10 * 60 * 1000, {
449
436
  notifier: completionNotifier,
@@ -553,10 +540,12 @@ export default function registerSubagentExtension(pi) {
553
540
  }, MODULE_PRELOAD_DELAY_MS);
554
541
  modulePreloadTimer.unref?.();
555
542
  };
556
- pi.registerMessageRenderer(SUPERVISOR_REQUEST_MESSAGE_TYPE, renderSupervisorRequest);
543
+ for (const customType of SUBAGENT_MESSAGE_TYPES)
544
+ pi.registerMessageRenderer(customType, renderSubagentMessage);
557
545
  const registerEntryRenderer = pi.registerEntryRenderer;
558
546
  if (typeof registerEntryRenderer === "function") {
559
- registerEntryRenderer.call(pi, SUPERVISOR_REPLY_ENTRY_TYPE, renderSupervisorReply);
547
+ for (const customType of SUBAGENT_ENTRY_TYPES)
548
+ registerEntryRenderer.call(pi, customType, renderSubagentEntry);
560
549
  }
561
550
  pi.registerMessageRenderer(SLASH_RESULT_TYPE, (message, options, theme) => {
562
551
  const details = resolveSlashMessageDetails(message.details);
@@ -573,62 +562,6 @@ export default function registerSubagentExtension(pi) {
573
562
  .join("\n");
574
563
  return new Text(content, 0, 0);
575
564
  });
576
- pi.registerMessageRenderer("subagent-notify", (message, options, theme) => {
577
- const content = typeof message.content === "string" ? message.content : "";
578
- const details = message.details ?? parseSubagentNotifyContent(content);
579
- if (!details)
580
- return new Text(content, 0, 0);
581
- const icon = details.status === "completed"
582
- ? theme.fg("success", "✓")
583
- : details.status === "paused"
584
- ? theme.fg("warning", "■")
585
- : theme.fg("error", "✗");
586
- const parts = [];
587
- if (details.taskInfo)
588
- parts.push(details.taskInfo);
589
- if (details.durationMs !== undefined)
590
- parts.push(formatDuration(details.durationMs));
591
- let text = `${icon} ${theme.bold(details.agent)} ${theme.fg("dim", details.status)}`;
592
- if (parts.length > 0)
593
- text += ` ${theme.fg("dim", "·")} ${parts.map((part) => theme.fg("dim", part)).join(` ${theme.fg("dim", "·")} `)}`;
594
- const trimmedPreview = details.resultPreview.trim();
595
- const previewLines = options.expanded
596
- ? trimmedPreview.split("\n").filter((line) => line.trim())
597
- : [trimmedPreview.split("\n", 1)[0] ?? ""].filter((line) => line.trim());
598
- for (const line of previewLines.length > 0 ? previewLines : ["(no output)"]) {
599
- text += `\n ${theme.fg("dim", `⎿ ${line}`)}`;
600
- }
601
- if (!options.expanded && trimmedPreview.includes("\n")) {
602
- const expandKey = keyText("app.tools.expand");
603
- text += `\n ${theme.fg("dim", `${expandKey} full notification`)}`;
604
- }
605
- if (details.workflowRunId) {
606
- text += `\n ${theme.fg("muted", `workflow: ${details.workflowRunId}`)}`;
607
- }
608
- if (details.childRuns?.length) {
609
- text += `\n ${theme.fg("muted", `children: ${details.childRuns.map((child) => `${child.workflowKey ?? child.agent ?? "child"}=${child.runId}`).join(", ")}`)}`;
610
- }
611
- if (details.reconciledFromDetachedChild) {
612
- text += `\n ${theme.fg("muted", `reconciled child: ${details.reconciledFromDetachedChild}`)}`;
613
- }
614
- if (details.sessionLabel && details.sessionValue) {
615
- text += `\n ${theme.fg("muted", `${details.sessionLabel}: ${shortenPath(details.sessionValue)}`)}`;
616
- }
617
- return new Text(text, 0, 0);
618
- });
619
- pi.registerMessageRenderer(SUBAGENT_STEERING_MESSAGE_TYPE, (message, _options, theme) => {
620
- const details = message.details;
621
- if (!details)
622
- return undefined;
623
- return new Text(theme.fg(details.state === "recovered" ? "warning" : "error", formatSteeringNotice(details)), 0, 0);
624
- });
625
- pi.registerMessageRenderer(SUBAGENT_CONTROL_MESSAGE_TYPE, (message, _options, theme) => {
626
- const details = message.details;
627
- if (!details?.event)
628
- return undefined;
629
- const content = typeof message.content === "string" ? message.content : undefined;
630
- return new SubagentControlNoticeComponent({ ...details, noticeText: formatSubagentControlNotice(details, content) }, theme);
631
- });
632
565
  const executeSubagentReady = async (id, params, signal, onUpdate, ctx) => {
633
566
  await waitForAdvertisement();
634
567
  return (await getExecutor()).executePublic(id, params, signal, onUpdate, ctx);
@@ -671,10 +604,7 @@ export default function registerSubagentExtension(pi) {
671
604
  ...buildSubagentToolPromptMetadata(config, disabledFeatures),
672
605
  parameters,
673
606
  async execute(id, params, signal, onUpdate, ctx) {
674
- const removedField = removedModelWorkflowFieldError(params);
675
- if (removedField)
676
- throw new Error(removedField);
677
- return finalizeToolResult(await executeSubagentCollapsed(id, params, signal ?? new AbortController().signal, onUpdate, ctx));
607
+ return finalizeToolResult(await executeSubagentCollapsed(id, flattenSubagentToolOptions(params, disabledFeatures), signal ?? new AbortController().signal, onUpdate, ctx));
678
608
  },
679
609
  renderCall(args, theme) {
680
610
  const gap = " ".repeat(config.mainWindowRenderer?.horizontalSpacing ?? 1);
@@ -683,8 +613,9 @@ export default function registerSubagentExtension(pi) {
683
613
  const target = args.agent || "";
684
614
  return new Text(`${title}${gap}${args.action}${target ? `${gap}${theme.fg("accent", target)}` : ""}`, 0, 0);
685
615
  }
616
+ const preflight = args.options?.preflight ?? args.preflight;
686
617
  if (args.workflow !== undefined)
687
- return new Text(`${title}${gap}${theme.fg("accent", args.workflow === true || args.workflow === "true" ? "workflow (reply block)" : `workflow ${String(args.workflow)}`)}${args.async === true ? `${gap}${theme.fg("warning", "[async]")}` : ""}${args.preflight !== undefined ? `${gap}${theme.fg("dim", formatWorkflowPreflightCall(args.preflight))}` : ""}`, 0, 0);
618
+ return new Text(`${title}${gap}${theme.fg("accent", args.workflow === true || args.workflow === "true" ? "workflow (reply block)" : `workflow ${String(args.workflow)}`)}${args.async === true ? `${gap}${theme.fg("warning", "[async]")}` : ""}${preflight !== undefined ? `${gap}${theme.fg("dim", formatWorkflowPreflightCall(preflight))}` : ""}`, 0, 0);
688
619
  const asyncLabel = args.async === true ? `${gap}${theme.fg("warning", "[async]")}` : "";
689
620
  return new Text(`${title}${gap}${theme.fg("accent", args.agent || "?")}${asyncLabel}`, 0, 0);
690
621
  },
@@ -696,22 +627,36 @@ export default function registerSubagentExtension(pi) {
696
627
  : renderSubagentResult(renderedResult, options, theme, undefined, config.mainWindowRenderer, config.foregroundDetachShortcut);
697
628
  },
698
629
  };
699
- pi.registerTool(tool);
630
+ registerPinnedTool(pi, tool);
631
+ // Declared with the same definition children use, so a fork's tool list equals this session's.
632
+ registerPinnedTool(pi, topLevelSupervisorTool());
700
633
  pi.on("before_agent_start", async (event, ctx) => {
701
634
  await waitForAdvertisement();
702
- if (!event.systemPromptOptions.selectedTools.includes("subagent"))
703
- return;
704
635
  const sessionId = state.currentSessionId ?? resolveCurrentSessionId(ctx.sessionManager);
705
636
  // Structured sections let Pi append a transcript delta instead of replacing the
706
637
  // cached system prompt. Set the section on every turn it applies: Pi rebuilds the
707
638
  // options each turn, and an unset turn records a removal.
708
- const catalog = buildAdvertisedAgentCatalog(advertisedAgents, resolveCurrentSubagentCapabilityCeiling(sessionId));
639
+ // Active runs are listed even when only subagents_enable is selected, e.g. runs re-adopted after a resume.
640
+ const activeRuns = config.activeRunsPrompt === true ? buildActiveRunsSection(state.asyncJobs.values(), sessionId) : undefined;
641
+ if (activeRuns)
642
+ event.systemPromptOptions.sections.active_subagents = activeRuns;
643
+ if (!event.systemPromptOptions.selectedTools.includes("subagent"))
644
+ return;
645
+ const catalog = buildAdvertisedAgentCatalog(advertisedAgents, resolveCurrentSubagentCapabilityCeiling(sessionId), recordedPromptSection(pi, "advertised_subagents"));
709
646
  if (catalog)
710
647
  event.systemPromptOptions.sections.advertised_subagents = catalog;
711
648
  });
712
649
  registerWaitTool(pi, state, waitToolConfig.enabled, waitSubscriptionManager, waitToolConfig.defaultTimeoutMs, undefined, supervisorChannel.hasPendingRequests);
713
650
  pi.on("agent_end", async (_event, ctx) => {
714
651
  try {
652
+ // The run is still active here, so its signal tells a user stop (Esc) apart from a finished or failed run.
653
+ // Pi skips agent_before_settle after an abort. Background runs keep going, but they must not restart the parent.
654
+ if (ctx.hasUI && ctx.signal?.aborted) {
655
+ parentWake.userAborted();
656
+ const active = activeAsyncJobCount();
657
+ if (active > 0)
658
+ ctx.ui.notify(`${active} background subagent run${active === 1 ? " is" : "s are"} still active · /subagents-stop`, "info");
659
+ }
715
660
  // A headless host may dispose the session as soon as this turn settles, so hand
716
661
  // finished results to Pi now; Pi runs the queued completion turn after agent_end.
717
662
  // A failed drain rejects without this step so its deadline stays exact.
@@ -922,12 +867,23 @@ export default function registerSubagentExtension(pi) {
922
867
  const runtimeEntry = {
923
868
  sessionManager: null,
924
869
  visibleControlNotices,
925
- cleanup() {
870
+ cleanup(shutdownReason) {
926
871
  if (runtimeCleaned)
927
872
  return;
928
873
  runtimeCleaned = true;
874
+ programStatus.dispose(shutdownReason);
929
875
  releaseHostSessionLiveness();
930
876
  releaseHostSessionLiveness = () => { };
877
+ // Detached foreground children run in this runtime's memory, and the next runtime
878
+ // cannot see or control them, so stop each one and record it as stopped.
879
+ for (const control of state.foregroundControls.values()) {
880
+ try {
881
+ control.stopForRuntimeReplacement?.();
882
+ }
883
+ catch (error) {
884
+ console.error(`Failed to stop detached foreground run ${control.runId}:`, error);
885
+ }
886
+ }
931
887
  // Workflow continuations retain their launch context; abort them before
932
888
  // teardown so a reload cannot launch through a stale context.
933
889
  for (const controller of state.workflowControllers?.values() ?? []) {
@@ -1028,30 +984,55 @@ export default function registerSubagentExtension(pi) {
1028
984
  }
1029
985
  }
1030
986
  };
987
+ let compactionResumeTimer;
988
+ const cancelCompactionResume = () => { clearTimeout(compactionResumeTimer); compactionResumeTimer = undefined; };
1031
989
  pi.on("agent_start", () => {
990
+ cancelCompactionResume();
1032
991
  parentWake.agentStarted();
1033
992
  resumeWidgetsAfterCompaction();
1034
993
  herdrStatusBridge.agentStarted();
994
+ programStatus.agentStarted();
1035
995
  });
1036
996
  pi.on("message_start", (event) => completionNotifier.messageStarted(event.message));
1037
997
  pi.on("agent_settled", () => {
1038
998
  resumeWidgetsAfterCompaction();
999
+ programStatus.agentSettled();
1039
1000
  });
1040
1001
  pi.on("session_before_compact", (event) => {
1041
1002
  if (event.reason !== "manual")
1042
1003
  suspendWidgetsForCompaction();
1043
1004
  });
1005
+ // Pi emits session_compact before it clears its compaction state, and a parent that is still
1006
+ // compacting can only be woken without before_agent_start (earendil-works/pi#5581). Wait for the
1007
+ // parent to go idle so the resume takes parentWake's prompt() path. A run that starts first cancels the pending resume.
1044
1008
  pi.on("session_compact", (event) => {
1045
1009
  if (event.reason !== "manual")
1046
1010
  return;
1047
- const hasActiveAsyncWork = [...state.asyncJobs.values()].some((job) => job.status === "queued" || job.status === "running");
1048
- if (!hasActiveAsyncWork || !withLastUiContext(() => true))
1011
+ if (activeAsyncJobCount() === 0 || !withLastUiContext(() => true))
1049
1012
  return;
1050
- parentWake.sendMessage({
1051
- customType: "subagent-compaction-resume",
1052
- content: "Compaction is complete. Resume the parent task now; background subagent results will arrive separately when ready.",
1053
- display: false,
1054
- }, { triggerTurn: true });
1013
+ cancelCompactionResume();
1014
+ const sessionId = state.currentSessionId;
1015
+ const deadline = Date.now() + COMPACTION_RESUME_DEADLINE_MS;
1016
+ const resumeWhenIdle = () => {
1017
+ if (state.currentSessionId !== sessionId || activeAsyncJobCount() === 0)
1018
+ return;
1019
+ const idle = withLastUiContext((ctx) => ctx.isIdle());
1020
+ if (idle === undefined)
1021
+ return;
1022
+ if (!idle) {
1023
+ if (Date.now() < deadline)
1024
+ compactionResumeTimer = setTimeout(resumeWhenIdle, COMPACTION_RESUME_POLL_MS);
1025
+ return;
1026
+ }
1027
+ // Pi's compact() aborts a live run first, which set the user-abort hold; this resume is deliberate.
1028
+ parentWake.releaseHold();
1029
+ parentWake.sendMessage({
1030
+ customType: "subagent-compaction-resume",
1031
+ content: "Compaction is complete. Resume the parent task now; background subagent results will arrive separately when ready.",
1032
+ display: false,
1033
+ }, { triggerTurn: true });
1034
+ };
1035
+ compactionResumeTimer = setTimeout(resumeWhenIdle, COMPACTION_RESUME_POLL_MS);
1055
1036
  });
1056
1037
  pi.on("session_start", (event, ctx) => {
1057
1038
  parentWake.bindSession(ctx);
@@ -1080,14 +1061,16 @@ export default function registerSubagentExtension(pi) {
1080
1061
  hasUI: ctx.hasUI === true,
1081
1062
  runs: activeHerdrRuns(),
1082
1063
  });
1064
+ programStatus.sessionStarted({ hasUI: ctx.hasUI === true, mode: ctx.mode });
1083
1065
  rpcBridge.emitReady(ctx);
1084
1066
  supervisorChannel.start();
1085
1067
  supervisorChannel.activateTransport();
1086
1068
  });
1087
1069
  pi.on("session_shutdown", async (event) => {
1070
+ cancelCompactionResume();
1088
1071
  completionNotifier.sessionShutdown(event?.reason);
1089
1072
  parentWake.sessionShutdown(event?.reason);
1090
- runtimeEntry.cleanup();
1073
+ runtimeEntry.cleanup(event?.reason);
1091
1074
  try {
1092
1075
  await disposeChildSessions();
1093
1076
  }