@ashx-j/lunr 0.2.19 → 0.2.21

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 (259) hide show
  1. package/CHANGELOG.md +36 -1
  2. package/README.md +2 -2
  3. package/dist/builtin-extensions/index.d.ts.map +1 -1
  4. package/dist/builtin-extensions/index.js +0 -2
  5. package/dist/builtin-extensions/index.js.map +1 -1
  6. package/dist/builtin-extensions/lunr-todos.d.ts +6 -5
  7. package/dist/builtin-extensions/lunr-todos.d.ts.map +1 -1
  8. package/dist/builtin-extensions/lunr-todos.js +9 -7
  9. package/dist/builtin-extensions/lunr-todos.js.map +1 -1
  10. package/dist/builtin-extensions/pi-intercom/broker/spawn.d.ts +6 -4
  11. package/dist/builtin-extensions/pi-intercom/broker/spawn.d.ts.map +1 -1
  12. package/dist/builtin-extensions/pi-intercom/broker/spawn.js +114 -61
  13. package/dist/builtin-extensions/pi-intercom/broker/spawn.js.map +1 -1
  14. package/dist/builtin-extensions/pi-intercom/index.d.ts.map +1 -1
  15. package/dist/builtin-extensions/pi-intercom/index.js +360 -351
  16. package/dist/builtin-extensions/pi-intercom/index.js.map +1 -1
  17. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.d.ts.map +1 -1
  18. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js +2 -2
  19. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js.map +1 -1
  20. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +8 -6
  21. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  22. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +128 -57
  23. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  24. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts +18 -8
  25. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
  26. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +38 -13
  27. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
  28. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +4 -3
  29. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
  30. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +24 -14
  31. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
  32. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts +8 -1
  33. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts.map +1 -1
  34. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js +247 -18
  35. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js.map +1 -1
  36. package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.d.ts +1 -0
  37. package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.d.ts.map +1 -1
  38. package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.js +1 -1
  39. package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.js.map +1 -1
  40. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.d.ts +29 -0
  41. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.d.ts.map +1 -0
  42. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js +179 -0
  43. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js.map +1 -0
  44. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts +89 -0
  45. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts.map +1 -0
  46. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js +541 -0
  47. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js.map +1 -0
  48. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts +11 -1
  49. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts.map +1 -1
  50. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js +38 -12
  51. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js.map +1 -1
  52. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.d.ts.map +1 -1
  53. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js +3 -2
  54. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js.map +1 -1
  55. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts +2 -1
  56. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts.map +1 -1
  57. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js +35 -8
  58. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js.map +1 -1
  59. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts +7 -3
  60. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts.map +1 -1
  61. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js +26 -4
  62. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js.map +1 -1
  63. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.d.ts +1 -0
  64. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.d.ts.map +1 -1
  65. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js +55 -38
  66. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js.map +1 -1
  67. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts +100 -0
  68. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts.map +1 -1
  69. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js +46 -31
  70. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js.map +1 -1
  71. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts +3 -6
  72. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts.map +1 -1
  73. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js +64 -5
  74. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js.map +1 -1
  75. package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.d.ts +15 -2
  76. package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.d.ts.map +1 -1
  77. package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.js +14 -4
  78. package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.js.map +1 -1
  79. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.d.ts.map +1 -1
  80. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js +2 -1
  81. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js.map +1 -1
  82. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
  83. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +21 -8
  84. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
  85. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
  86. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +1 -1
  87. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
  88. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts +0 -1
  89. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  90. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +71 -25
  91. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
  92. package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.d.ts +2 -0
  93. package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.d.ts.map +1 -1
  94. package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.js +75 -18
  95. package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.js.map +1 -1
  96. package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.d.ts +1 -1
  97. package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.d.ts.map +1 -1
  98. package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.js +1 -1
  99. package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.js.map +1 -1
  100. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts +13 -1
  101. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts.map +1 -1
  102. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js +67 -11
  103. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js.map +1 -1
  104. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +1 -0
  105. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
  106. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
  107. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts +3 -0
  108. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts.map +1 -1
  109. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js +7 -2
  110. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js.map +1 -1
  111. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
  112. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js +13 -3
  113. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
  114. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.d.ts +2 -2
  115. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.d.ts.map +1 -1
  116. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.js +5 -10
  117. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.js.map +1 -1
  118. package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.d.ts +2 -0
  119. package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.d.ts.map +1 -0
  120. package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.js +3 -0
  121. package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.js.map +1 -0
  122. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts +3 -0
  123. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts.map +1 -1
  124. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js +68 -11
  125. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js.map +1 -1
  126. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts +12 -1
  127. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts.map +1 -1
  128. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js +21 -2
  129. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js.map +1 -1
  130. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +21 -4
  131. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
  132. package/dist/builtin-extensions/pi-subagents/src/shared/types.js +1 -1
  133. package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
  134. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.d.ts.map +1 -1
  135. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.js.map +1 -1
  136. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts +7 -0
  137. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts.map +1 -1
  138. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js +11 -7
  139. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js.map +1 -1
  140. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +6 -0
  141. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
  142. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +46 -29
  143. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
  144. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +46 -4
  145. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  146. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +407 -450
  147. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  148. package/dist/builtin-extensions/pi-subagents/src/watchdog/register-main.d.ts.map +1 -1
  149. package/dist/builtin-extensions/pi-subagents/src/watchdog/register-main.js +1 -1
  150. package/dist/builtin-extensions/pi-subagents/src/watchdog/register-main.js.map +1 -1
  151. package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.d.ts +2 -13
  152. package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.d.ts.map +1 -1
  153. package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.js +5 -91
  154. package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.js.map +1 -1
  155. package/dist/core/customize.d.ts +2 -0
  156. package/dist/core/customize.d.ts.map +1 -1
  157. package/dist/core/customize.js +3 -0
  158. package/dist/core/customize.js.map +1 -1
  159. package/dist/core/permissions.d.ts +1 -0
  160. package/dist/core/permissions.d.ts.map +1 -1
  161. package/dist/core/permissions.js +8 -4
  162. package/dist/core/permissions.js.map +1 -1
  163. package/dist/core/plan-mode.d.ts.map +1 -1
  164. package/dist/core/plan-mode.js +0 -5
  165. package/dist/core/plan-mode.js.map +1 -1
  166. package/dist/core/runtime-bridges.d.ts.map +1 -1
  167. package/dist/core/runtime-bridges.js +0 -2
  168. package/dist/core/runtime-bridges.js.map +1 -1
  169. package/dist/core/settings-manager.d.ts +4 -0
  170. package/dist/core/settings-manager.d.ts.map +1 -1
  171. package/dist/core/settings-manager.js +11 -0
  172. package/dist/core/settings-manager.js.map +1 -1
  173. package/dist/core/subagent-cancellation.d.ts +21 -0
  174. package/dist/core/subagent-cancellation.d.ts.map +1 -0
  175. package/dist/core/subagent-cancellation.js +53 -0
  176. package/dist/core/subagent-cancellation.js.map +1 -0
  177. package/dist/core/subagent-spinner-setting.d.ts +6 -0
  178. package/dist/core/subagent-spinner-setting.d.ts.map +1 -0
  179. package/dist/core/subagent-spinner-setting.js +12 -0
  180. package/dist/core/subagent-spinner-setting.js.map +1 -0
  181. package/dist/core/subagent-spinner.d.ts +4 -0
  182. package/dist/core/subagent-spinner.d.ts.map +1 -0
  183. package/dist/core/subagent-spinner.js +6 -0
  184. package/dist/core/subagent-spinner.js.map +1 -0
  185. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  186. package/dist/modes/interactive/components/assistant-message.js +12 -18
  187. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  188. package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
  189. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  190. package/dist/modes/interactive/components/settings-selector.js +73 -1
  191. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  192. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  193. package/dist/modes/interactive/components/tool-execution.js +12 -0
  194. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  195. package/dist/modes/interactive/extension-widget-order.d.ts +8 -0
  196. package/dist/modes/interactive/extension-widget-order.d.ts.map +1 -0
  197. package/dist/modes/interactive/extension-widget-order.js +37 -0
  198. package/dist/modes/interactive/extension-widget-order.js.map +1 -0
  199. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  200. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  201. package/dist/modes/interactive/interactive-mode.js +44 -22
  202. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  203. package/dist/node-runtime/{agent-session-services-35WNVGMR.js → agent-session-services-C743TYQE.js} +6 -5
  204. package/dist/node-runtime/{builtin-extensions-322XDDEM.js → builtin-extensions-JCOPAAB5.js} +3 -2
  205. package/dist/node-runtime/{chunk-XATUM2HK.js → chunk-25I2BHAA.js} +1 -1
  206. package/dist/node-runtime/{chunk-TXHKBRHZ.js → chunk-2BUAYZ7K.js} +136 -53
  207. package/dist/node-runtime/chunk-5ZH3ZFIZ.js +308 -0
  208. package/dist/node-runtime/{chunk-J26TSGDL.js → chunk-6N22HULO.js} +8 -5
  209. package/dist/node-runtime/chunk-A3KMVBZV.js +60 -0
  210. package/dist/node-runtime/{chunk-4FX25LWP.js → chunk-AWVD5IEY.js} +20 -421
  211. package/dist/node-runtime/{chunk-ZRCBN365.js → chunk-GB2MGFLI.js} +12 -12
  212. package/dist/node-runtime/chunk-LISUTZS3.js +19 -0
  213. package/dist/node-runtime/{chunk-PNJSG3IZ.js → chunk-LTYWTR3V.js} +1 -369
  214. package/dist/node-runtime/{chunk-TFBIJTM3.js → chunk-PDNXVXMD.js} +13 -13
  215. package/dist/node-runtime/{chunk-MCUNIRD5.js → chunk-SY2TFMLO.js} +532 -261
  216. package/dist/node-runtime/{chunk-HQCKFM2O.js → chunk-VGYZ3APQ.js} +3 -0
  217. package/dist/node-runtime/{chunk-4DJ6HEGH.js → chunk-VZR3NCM7.js} +3 -3
  218. package/dist/node-runtime/chunk-W3SILANP.js +24 -0
  219. package/dist/node-runtime/{chunk-CBGB57XT.js → chunk-WLLDXJRT.js} +10 -0
  220. package/dist/node-runtime/{chunk-ATGA2WLC.js → chunk-XI77KVKA.js} +399 -36
  221. package/dist/node-runtime/{chunk-4CSFRBCN.js → chunk-Y5KOEMBH.js} +1 -1
  222. package/dist/node-runtime/{chunk-AROOY4BB.js → chunk-YMEAYRBE.js} +1 -1
  223. package/dist/node-runtime/{command-DWUM5X3U.js → command-P4NYCJ2M.js} +1 -1
  224. package/dist/node-runtime/{customize-XEXL2DGQ.js → customize-LF5VST47.js} +1 -1
  225. package/dist/node-runtime/{gateway-UZXMFGWY.js → gateway-BM6NLOH4.js} +2 -2
  226. package/dist/node-runtime/index.js +16 -13
  227. package/dist/node-runtime/{interactive-mode-QT5IKGQ5.js → interactive-mode-EVVBA64D.js} +11 -8
  228. package/dist/node-runtime/{lunr-cron-QPBTKBGI.js → lunr-cron-4VHP4E4B.js} +2 -2
  229. package/dist/node-runtime/main.js +14 -12
  230. package/dist/node-runtime/{package-manager-cli-7RKSZGEN.js → package-manager-cli-N37546V5.js} +5 -4
  231. package/dist/node-runtime/{pi-intercom-EEMBGQID.js → pi-intercom-NV2LW6X7.js} +108 -87
  232. package/dist/node-runtime/{pi-subagents-7YJ3I4VE.js → pi-subagents-6MUIFNDM.js} +1262 -599
  233. package/dist/node-runtime/rpc-entry.js +14 -12
  234. package/dist/node-runtime/{runtime-bridges-3RKBDLNA.js → runtime-bridges-2VQTLPOZ.js} +3 -5
  235. package/dist/node-runtime/{settings-manager-GHPTUN7R.js → settings-manager-CUGAZWAB.js} +2 -1
  236. package/dist/node-runtime/{subagent-executor-5Q5A4HJ2.js → subagent-executor-MH4A7CCF.js} +181 -294
  237. package/dist/node-runtime/{update-cli-L3JIBH2U.js → update-cli-XTZMZGOL.js} +2 -1
  238. package/docs/features.md +22 -4
  239. package/docs/keybindings.md +3 -1
  240. package/docs/settings.md +3 -2
  241. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  242. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  243. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  244. package/examples/extensions/gondolin/package-lock.json +2 -2
  245. package/examples/extensions/gondolin/package.json +1 -1
  246. package/examples/extensions/sandbox/package-lock.json +2 -2
  247. package/examples/extensions/sandbox/package.json +1 -1
  248. package/examples/extensions/with-deps/package-lock.json +2 -2
  249. package/examples/extensions/with-deps/package.json +1 -1
  250. package/package.json +4 -4
  251. package/dist/builtin-extensions/lunr-settings-tools.d.ts +0 -4
  252. package/dist/builtin-extensions/lunr-settings-tools.d.ts.map +0 -1
  253. package/dist/builtin-extensions/lunr-settings-tools.js +0 -120
  254. package/dist/builtin-extensions/lunr-settings-tools.js.map +0 -1
  255. package/dist/core/settings-tools-bridge.d.ts +0 -35
  256. package/dist/core/settings-tools-bridge.d.ts.map +0 -1
  257. package/dist/core/settings-tools-bridge.js +0 -56
  258. package/dist/core/settings-tools-bridge.js.map +0 -1
  259. package/dist/node-runtime/chunk-3NMWLTPV.js +0 -64
@@ -44,11 +44,13 @@ export { WAIT_TOOL_ENABLED_ENV, resolveWaitToolConfig, type ResolvedWaitToolConf
44
44
  export interface SubagentWaitParams {
45
45
  /** Optional run id/prefix to wait for. When omitted, waits across every active run in this session. */
46
46
  id?: string;
47
+ /** Optional supervisor question id from subagent_supervisor action='ask'. */
48
+ questionId?: string;
47
49
  /**
48
50
  * When true, block until EVERY active run in this session (or matching `id`)
49
51
  * is terminal. Default false: return as soon as the first run finishes, so a
50
52
  * fleet manager can spawn a replacement and wait again. Ignored when `id`
51
- * targets a single run.
53
+ * or `questionId` targets a single item.
52
54
  */
53
55
  all?: boolean;
54
56
  /** Give up after this many milliseconds. Defaults to 30 minutes. */
@@ -86,10 +88,5 @@ export interface SubagentWaitDeps {
86
88
  */
87
89
  events?: WaitEventBus;
88
90
  }
89
- /**
90
- * Block until the targeted async or remembered detached foreground run finishes,
91
- * the timeout elapses, or the turn is aborted. Resolves with a short
92
- * human-readable summary either way.
93
- */
94
91
  export declare function waitForSubagents(params: SubagentWaitParams, signal: AbortSignal | undefined, deps: SubagentWaitDeps): Promise<AgentToolResult<Details>>;
95
92
  //# sourceMappingURL=subagent-wait.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"subagent-wait.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAGN,KAAK,sBAAsB,EAE3B,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAQN,KAAK,OAAO,EAEZ,KAAK,aAAa,EAClB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,KAAK,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAS7G,MAAM,WAAW,kBAAkB;IAClC,uGAAuG;IACvG,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wEAAwE;AACxE,MAAM,WAAW,YAAY;IAC5B,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAClE;AAED,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,aAAa,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,OAAO,CAAC;IAC7D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kCAAkC;IAClC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,qEAAqE;IACrE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,qEAAqE;IACrE,cAAc,CAAC,EAAE;QAChB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,sBAAsB,CAAC;QACnE,YAAY,IAAI,SAAS,MAAM,EAAE,CAAC;KAClC,CAAC;IACF;;;;;OAKG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;CACtB;AA+MD;;;;GAIG;AACH,wBAAsB,gBAAgB,CACrC,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,IAAI,EAAE,gBAAgB,GACpB,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAuJnC","sourcesContent":["// @ts-nocheck\n/**\n * `subagent_wait` tool: block the current turn until outstanding async runs\n * or a named remembered detached foreground run finishes.\n *\n * Background subagent runs are detached. In an interactive session the parent\n * can end its turn and Pi will wake it with a completion notification. That\n * does not work when the parent is a skill that must run to completion, and it\n * cannot work at all non-interactively (`pi -p ...`), where the run is a single\n * turn: once the turn ends there is nothing left to receive the notification.\n *\n * `subagent_wait` closes that gap. It keeps the turn alive until a tracked async\n * run for this session reaches a terminal state (complete / failed / paused),\n * the caller-supplied timeout elapses, or the turn is aborted. Because it awaits\n * inside the turn, the completion the model was told to wait for is actually\n * observed before the tool returns.\n *\n * By default `subagent_wait` returns as soon as ONE run finishes, so a fleet\n * manager can use it in a rolling-replacement loop: launch N workers, wait for\n * the next one to finish, spawn its replacement, then call `subagent_wait`\n * again — keeping N in flight instead of draining to zero between batches.\n * Pass `all: true` to block until every tracked async run is terminal, or `id`\n * to block on one specific async or remembered detached foreground run.\n *\n * `subagent_wait` also returns when a run needs attention — not just on\n * completion. A child that goes idle or blocks for a decision surfaces\n * `needs_attention` (the same signal Pi shows as a control notice and,\n * interactively, wakes the parent with). Since `subagent_wait` is used exactly\n * where there is no next turn to receive that notice, it must break on it too,\n * or a stuck child would stall the loop until the timeout. Attention runs are\n * reported so the caller can inspect / nudge / resume / interrupt them.\n *\n * Wake mechanism: when given Pi's event bus (`deps.events`), `subagent_wait`\n * subscribes to the subagent completion/control channels and wakes the instant\n * any fires, rather than waiting out a fixed poll interval. A poll still runs\n * on the interval as a reconciliation fallback (crashed runners, missed\n * events), and the poll is the source of truth for what actually changed — the\n * event only ends the sleep early. With no bus, `subagent_wait` degrades to pure\n * polling.\n */\n\nimport type { AgentToolResult } from \"@ashx-j/lunr-agent\";\nimport {\n\tlistBackgroundWorkWakeChannels,\n\tsnapshotBackgroundWork,\n\ttype BackgroundWorkSnapshot,\n\ttype RegisteredBackgroundWorkItem,\n} from \"../../api/background-work.ts\";\nimport { listAsyncRuns, type AsyncRunSummary } from \"./async-status.ts\";\nimport {\n\tASYNC_DIR,\n\tRESULTS_DIR,\n\tSUBAGENT_ASYNC_COMPLETE_EVENT,\n\tSUBAGENT_FOREGROUND_COMPLETE_EVENT,\n\tSUBAGENT_CONTROL_EVENT,\n\tSUBAGENT_CONTROL_INTERCOM_EVENT,\n\tSUBAGENT_RESULT_INTERCOM_EVENT,\n\ttype Details,\n\ttype ForegroundResumeRun,\n\ttype SubagentState,\n} from \"../../shared/types.ts\";\nimport { formatDuration } from \"../../shared/formatters.ts\";\nexport { WAIT_TOOL_ENABLED_ENV, resolveWaitToolConfig, type ResolvedWaitToolConfig } from \"./wait-config.ts\";\n\n/** States that mean a run is still in flight (not yet resolved). */\nconst ACTIVE_STATES: ReadonlyArray<AsyncRunSummary[\"state\"]> = [\"queued\", \"running\"];\n\nconst DEFAULT_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes\nconst MIN_POLL_INTERVAL_MS = 250;\nconst DEFAULT_POLL_INTERVAL_MS = 1000;\n\nexport interface SubagentWaitParams {\n\t/** Optional run id/prefix to wait for. When omitted, waits across every active run in this session. */\n\tid?: string;\n\t/**\n\t * When true, block until EVERY active run in this session (or matching `id`)\n\t * is terminal. Default false: return as soon as the first run finishes, so a\n\t * fleet manager can spawn a replacement and wait again. Ignored when `id`\n\t * targets a single run.\n\t */\n\tall?: boolean;\n\t/** Give up after this many milliseconds. Defaults to 30 minutes. */\n\ttimeoutMs?: number;\n}\n\n/** Minimal event-bus surface wait subscribes to (matches pi.events). */\nexport interface WaitEventBus {\n\ton(channel: string, handler: (data: unknown) => void): () => void;\n}\n\nexport interface SubagentWaitDeps {\n\tstate: SubagentState;\n\tasyncDirRoot?: string;\n\tresultsDir?: string;\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean;\n\tnow?: () => number;\n\tpollIntervalMs?: number;\n\t/** False makes the tool return immediately without blocking active async runs. */\n\tenabled?: boolean;\n\t/** Injectable sleep for tests. */\n\tsleep?: (ms: number, signal?: AbortSignal) => Promise<void>;\n\t/** Internal auto-drain mode waits through needs-attention states. */\n\tstopOnAttention?: boolean;\n\t/** Internal auto-drain mode surfaces failed terminal subagent runs as errors. */\n\tfailOnFailedRuns?: boolean;\n\t/** Injectable provider protocol surfaces for deterministic tests. */\n\tbackgroundWork?: {\n\t\tsnapshot(sessionId: string, nowMs: number): BackgroundWorkSnapshot;\n\t\twakeChannels(): readonly string[];\n\t};\n\t/**\n\t * Optional event bus (pi.events). When provided, wait wakes immediately on a\n\t * subagent completion/control event instead of waiting out the poll interval;\n\t * the poll then remains as a reconciliation fallback (crashed runners, missed\n\t * events). Omit in tests that want pure poll behavior.\n\t */\n\tevents?: WaitEventBus;\n}\n\n/** Bus channels that indicate a run changed state or needs attention. */\nconst WAKE_CHANNELS = [\n\tSUBAGENT_ASYNC_COMPLETE_EVENT,\n\tSUBAGENT_FOREGROUND_COMPLETE_EVENT,\n\tSUBAGENT_CONTROL_EVENT,\n\tSUBAGENT_CONTROL_INTERCOM_EVENT,\n\tSUBAGENT_RESULT_INTERCOM_EVENT,\n];\n\nfunction defaultSleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve) => {\n\t\tif (signal?.aborted) {\n\t\t\tresolve();\n\t\t\treturn;\n\t\t}\n\t\tconst timer = setTimeout(() => {\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve();\n\t\t}, ms);\n\t\tconst onAbort = () => {\n\t\t\tclearTimeout(timer);\n\t\t\tresolve();\n\t\t};\n\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t});\n}\n\n/**\n * Sleep up to `ms`, but wake early if a subagent event fires on the bus (or the\n * turn aborts). Returns when the first of those happens. With no bus this is a\n * plain sleep, so the poll interval alone drives progress.\n */\nfunction waitForWake(ms: number, signal: AbortSignal | undefined, deps: SubagentWaitDeps): Promise<void> {\n\tconst sleep = deps.sleep ?? defaultSleep;\n\tconst events = deps.events;\n\tif (!events) return sleep(ms, signal);\n\tconst providerChannels = deps.backgroundWork?.wakeChannels() ?? listBackgroundWorkWakeChannels();\n\treturn new Promise((resolve, reject) => {\n\t\tlet settled = false;\n\t\tconst unsubs: Array<() => void> = [];\n\t\tconst wakeController = new AbortController();\n\t\tconst done = () => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\twakeController.abort();\n\t\t\tsignal?.removeEventListener(\"abort\", done);\n\t\t\tfor (const u of unsubs) {\n\t\t\t\ttry { u(); } catch { /* best effort */ }\n\t\t\t}\n\t\t\tresolve();\n\t\t};\n\t\tif (signal?.aborted) {\n\t\t\tdone();\n\t\t\treturn;\n\t\t}\n\t\tsignal?.addEventListener(\"abort\", done, { once: true });\n\t\ttry {\n\t\t\tfor (const channel of [...new Set([...WAKE_CHANNELS, ...providerChannels])]) {\n\t\t\t\tunsubs.push(events.on(channel, done));\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tsignal?.removeEventListener(\"abort\", done);\n\t\t\tfor (const unsubscribe of unsubs) {\n\t\t\t\ttry { unsubscribe(); } catch { /* best effort cleanup */ }\n\t\t\t}\n\t\t\treject(error);\n\t\t\treturn;\n\t\t}\n\t\t// Poll-interval fallback so we still reconcile even if no event arrives.\n\t\t// The local signal cancels that fallback timer when an event wakes us first.\n\t\tvoid sleep(ms, wakeController.signal).then(done);\n\t});\n}\n\nfunction matchesId(run: AsyncRunSummary, id: string): boolean {\n\treturn run.id === id || run.id.startsWith(id);\n}\n\nfunction activeDetachedForegroundRuns(params: SubagentWaitParams, deps: SubagentWaitDeps): ForegroundResumeRun[] {\n\tif (!params.id || !deps.state.foregroundRuns) return [];\n\tconst sessionId = deps.state.currentSessionId;\n\tif (!sessionId) return [];\n\treturn [...deps.state.foregroundRuns.values()].filter((run) =>\n\t\t(run.runId === params.id || run.runId.startsWith(params.id!))\n\t\t&& run.sessionId === sessionId\n\t\t&& run.children.some((child) => child.status === \"detached\")\n\t);\n}\n\nfunction summarizeForegroundChildren(run: ForegroundResumeRun, indices: Set<number>): string {\n\tconst counts = new Map<string, number>();\n\tfor (const child of run.children) {\n\t\tif (!indices.has(child.index) || child.status === \"detached\") continue;\n\t\tcounts.set(child.status, (counts.get(child.status) ?? 0) + 1);\n\t}\n\treturn [...counts.entries()].map(([status, count]) => `${count} ${status}`).join(\", \");\n}\n\n/** A running run that has flagged it needs the parent's attention. */\nfunction needsAttention(run: AsyncRunSummary): boolean {\n\treturn run.activityState === \"needs_attention\";\n}\n\nfunction backgroundWorkIdentity(item: RegisteredBackgroundWorkItem): string {\n\treturn `${item.provider}\\0${item.sessionId}\\0${item.id}`;\n}\n\nfunction backgroundWorkForSession(deps: SubagentWaitDeps, nowMs: number): BackgroundWorkSnapshot {\n\tconst sessionId = deps.state.currentSessionId;\n\tif (!sessionId) throw new Error(\"subagent_wait requires an active session identity to scope background work safely.\");\n\treturn deps.backgroundWork?.snapshot(sessionId, nowMs) ?? snapshotBackgroundWork(sessionId, nowMs);\n}\n\n/** Queued/running runs from this session, including runs that need attention. */\nfunction activeRunsForSession(params: SubagentWaitParams, deps: SubagentWaitDeps): AsyncRunSummary[] {\n\tconst asyncDirRoot = deps.asyncDirRoot ?? ASYNC_DIR;\n\tconst resultsDir = deps.resultsDir ?? RESULTS_DIR;\n\tconst runs = listAsyncRuns(asyncDirRoot, {\n\t\tstates: [...ACTIVE_STATES],\n\t\tsessionId: deps.state.currentSessionId ?? undefined,\n\t\tresultsDir,\n\t\tkill: deps.kill,\n\t\tnow: deps.now,\n\t});\n\treturn params.id ? runs.filter((run) => matchesId(run, params.id!)) : runs;\n}\n\n/** Runs (from the initial set) currently flagged needs_attention, for reporting. */\nfunction attentionRunsForSession(params: SubagentWaitParams, deps: SubagentWaitDeps, initialIds: Set<string>): AsyncRunSummary[] {\n\treturn activeRunsForSession(params, deps).filter((run) => needsAttention(run) && initialIds.has(run.id));\n}\n\n/** All runs (any state) for this session, for the final summary. */\nfunction allRunsForSession(params: SubagentWaitParams, deps: SubagentWaitDeps): AsyncRunSummary[] {\n\tconst asyncDirRoot = deps.asyncDirRoot ?? ASYNC_DIR;\n\tconst resultsDir = deps.resultsDir ?? RESULTS_DIR;\n\tconst runs = listAsyncRuns(asyncDirRoot, {\n\t\tsessionId: deps.state.currentSessionId ?? undefined,\n\t\tresultsDir,\n\t\tkill: deps.kill,\n\t\tnow: deps.now,\n\t});\n\treturn params.id ? runs.filter((run) => matchesId(run, params.id!)) : runs;\n}\n\nfunction summarizeTerminalRuns(runs: AsyncRunSummary[], providerFinishedCount = 0): string {\n\tif (runs.length === 0 && providerFinishedCount === 0) return \"\";\n\tconst counts = { complete: 0, failed: 0, paused: 0 } as Record<string, number>;\n\tfor (const run of runs) {\n\t\tif (run.state in counts) counts[run.state] += 1;\n\t}\n\tconst parts: string[] = [];\n\tif (counts.complete) parts.push(`${counts.complete} complete`);\n\tif (counts.failed) parts.push(`${counts.failed} failed`);\n\tif (counts.paused) parts.push(`${counts.paused} paused`);\n\tif (providerFinishedCount > 0) parts.push(`${providerFinishedCount} provider item(s) finished`);\n\treturn parts.join(\", \");\n}\n\nfunction result(text: string, isError = false): AgentToolResult<Details> {\n\treturn {\n\t\tcontent: [{ type: \"text\", text }],\n\t\t...(isError ? { isError: true } : {}),\n\t\tdetails: { mode: \"management\", results: [] },\n\t};\n}\n\nasync function waitForDetachedForegroundRun(\n\trun: ForegroundResumeRun,\n\tsignal: AbortSignal | undefined,\n\tdeps: SubagentWaitDeps,\n\tstartedAt: number,\n\tnow: () => number,\n\tpollIntervalMs: number,\n\ttimeoutMs: number,\n): Promise<AgentToolResult<Details>> {\n\tconst initialDetachedIndices = new Set(run.children.filter((child) => child.status === \"detached\").map((child) => child.index));\n\twhile (true) {\n\t\tif (deps.state.currentSessionId !== run.sessionId) {\n\t\t\treturn result(`Wait stopped because the active session changed while remembered foreground run \"${run.runId}\" was still detached. Return to the originating session to inspect or wait for it.`, true);\n\t\t}\n\t\tconst current = deps.state.foregroundRuns?.get(run.runId);\n\t\tif (!current || current.sessionId !== run.sessionId) {\n\t\t\treturn result(`Remembered foreground run \"${run.runId}\" disappeared before a terminal child result was recorded. Completion cannot be confirmed; do not launch a replacement without checking the originating child session.`, true);\n\t\t}\n\t\tconst pending = current.children.filter((child) => initialDetachedIndices.has(child.index) && child.status === \"detached\");\n\t\tif (pending.length === 0) {\n\t\t\tconst outcome = summarizeForegroundChildren(current, initialDetachedIndices);\n\t\t\treturn result(\n\t\t\t\t`Waited ${formatDuration(now() - startedAt)} for remembered detached foreground run \"${run.runId}\"; done. Outcome: ${outcome || \"no recovered child status\"}. Completion event observed; inspect with subagent({ action: \"status\", id: \"${run.runId}\" }) for recovered output.`,\n\t\t\t);\n\t\t}\n\t\tif (signal?.aborted) {\n\t\t\treturn result(`Wait aborted after ${formatDuration(now() - startedAt)}. Remembered foreground run \"${run.runId}\" remains detached.`, true);\n\t\t}\n\t\tif (now() - startedAt >= timeoutMs) {\n\t\t\treturn result(\n\t\t\t\t`Wait timed out after ${formatDuration(timeoutMs)} with remembered foreground run \"${run.runId}\" still detached. Reply to any pending supervisor request, then call subagent_wait({ id: \"${run.runId}\" }) again or inspect status; do not resume or launch a replacement while it remains detached.`,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\t\tawait waitForWake(pollIntervalMs, signal, deps);\n\t}\n}\n\n/**\n * Block until the targeted async or remembered detached foreground run finishes,\n * the timeout elapses, or the turn is aborted. Resolves with a short\n * human-readable summary either way.\n */\nexport async function waitForSubagents(\n\tparams: SubagentWaitParams,\n\tsignal: AbortSignal | undefined,\n\tdeps: SubagentWaitDeps,\n): Promise<AgentToolResult<Details>> {\n\tif (deps.enabled === false) {\n\t\treturn result(\"subagent_wait is disabled by config.waitTool or PI_SUBAGENT_WAIT_TOOL_ENABLED; returning immediately without blocking background work. Active work keeps going, and you can inspect subagents with subagent({ action: \\\"status\\\" }) or rely on completion notifications.\");\n\t}\n\tif (!deps.state.currentSessionId) {\n\t\treturn result(\"subagent_wait requires an active session identity to scope background work safely.\", true);\n\t}\n\n\tconst now = deps.now ?? Date.now;\n\tconst pollIntervalMs = Math.max(MIN_POLL_INTERVAL_MS, deps.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);\n\tconst timeoutMs = params.timeoutMs !== undefined && params.timeoutMs > 0 ? params.timeoutMs : DEFAULT_TIMEOUT_MS;\n\tconst startedAt = now();\n\tconst waitForAll = params.id ? true : params.all === true;\n\n\tlet active: AsyncRunSummary[];\n\tlet foreground: ForegroundResumeRun[];\n\tlet providerSnapshot: BackgroundWorkSnapshot;\n\ttry {\n\t\tactive = activeRunsForSession(params, deps);\n\t\tforeground = activeDetachedForegroundRuns(params, deps);\n\t\tproviderSnapshot = params.id ? { providers: [], items: [] } : backgroundWorkForSession(deps, startedAt);\n\t} catch (error) {\n\t\treturn result(error instanceof Error ? error.message : String(error), true);\n\t}\n\n\tif (params.id) {\n\t\tconst candidates = [\n\t\t\t...active.map((run) => ({ kind: \"async\" as const, id: run.id, run })),\n\t\t\t...foreground.map((run) => ({ kind: \"foreground\" as const, id: run.runId, run })),\n\t\t];\n\t\tconst exact = candidates.filter((candidate) => candidate.id === params.id);\n\t\tconst matches = exact.length > 0 ? exact : candidates;\n\t\tif (matches.length > 1) {\n\t\t\treturn result(`Ambiguous subagent run id prefix \"${params.id}\" matched ${matches.length} active runs: ${matches.map((candidate) => candidate.id).join(\", \")}. Pass a longer id.`, true);\n\t\t}\n\t\tconst selected = matches[0];\n\t\tif (selected?.kind === \"foreground\") {\n\t\t\treturn waitForDetachedForegroundRun(selected.run, signal, deps, startedAt, now, pollIntervalMs, timeoutMs);\n\t\t}\n\t\tactive = selected?.kind === \"async\" ? [selected.run] : [];\n\t}\n\n\tlet providerActive = providerSnapshot.items;\n\tif (active.length === 0 && providerActive.length === 0) {\n\t\treturn result(params.id\n\t\t\t? `No active run matched \"${params.id}\". Nothing to wait for.`\n\t\t\t: \"No active async runs or registered provider work in this session. Nothing to wait for.\");\n\t}\n\tconst waitParams = params.id ? { ...params, id: active[0]!.id } : params;\n\tconst initialAsyncIds = new Set(active.map((run) => run.id));\n\tconst initialProviderIds = new Set(providerActive.map(backgroundWorkIdentity));\n\tconst initialProviderNames = new Set(providerActive.map((item) => item.provider));\n\tconst initialCount = initialAsyncIds.size + initialProviderIds.size;\n\tconst stopOnAttention = deps.stopOnAttention !== false;\n\tlet attention = active.filter((run) => needsAttention(run));\n\n\tconst isDone = (): boolean => {\n\t\tif (stopOnAttention && attention.some((run) => initialAsyncIds.has(run.id))) return true;\n\t\tconst activeAsyncIds = new Set(active.map((run) => run.id));\n\t\tconst activeProviderIds = new Set(providerActive.map(backgroundWorkIdentity));\n\t\tif (waitForAll) {\n\t\t\treturn [...initialAsyncIds].every((id) => !activeAsyncIds.has(id))\n\t\t\t\t&& [...initialProviderIds].every((id) => !activeProviderIds.has(id));\n\t\t}\n\t\treturn [...initialAsyncIds].some((id) => !activeAsyncIds.has(id))\n\t\t\t|| [...initialProviderIds].some((id) => !activeProviderIds.has(id));\n\t};\n\n\twhile (!isDone()) {\n\t\tconst activeInitialRuns = active.filter((run) => initialAsyncIds.has(run.id));\n\t\tconst activeInitialProviderItems = providerActive.filter((item) => initialProviderIds.has(backgroundWorkIdentity(item)));\n\t\tconst stillActive = [\n\t\t\t...activeInitialRuns.map((run) => `${run.id} (${run.state})`),\n\t\t\t...activeInitialProviderItems.map((item) => `${item.provider}/${item.id}`),\n\t\t].join(\", \");\n\t\tif (signal?.aborted) {\n\t\t\treturn result(`Wait aborted after ${formatDuration(now() - startedAt)}. Still active: ${stillActive}.`, true);\n\t\t}\n\t\tif (now() - startedAt >= timeoutMs) {\n\t\t\treturn result(\n\t\t\t\t`Wait timed out after ${formatDuration(timeoutMs)} with ${activeInitialRuns.length} async run(s) and ${activeInitialProviderItems.length} provider item(s) still active: ${stillActive}. The work keeps going; call subagent_wait again or inspect subagent status.`,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\tawait waitForWake(pollIntervalMs, signal, deps);\n\t\t\tactive = activeRunsForSession(waitParams, deps);\n\t\t\tattention = attentionRunsForSession(waitParams, deps, initialAsyncIds);\n\t\t\tproviderSnapshot = params.id ? providerSnapshot : backgroundWorkForSession(deps, now());\n\t\t\tfor (const provider of initialProviderNames) {\n\t\t\t\tif (!providerSnapshot.providers.includes(provider)) {\n\t\t\t\t\treturn result(`Background-work provider '${provider}' disappeared while subagent_wait was tracking its active work; completion cannot be confirmed.`, true);\n\t\t\t\t}\n\t\t\t}\n\t\t\tproviderActive = providerSnapshot.items;\n\t\t} catch (error) {\n\t\t\treturn result(error instanceof Error ? error.message : String(error), true);\n\t\t}\n\t}\n\n\tlet terminalSummary: string;\n\tlet finishedAsyncCount: number;\n\tlet failedAsyncCount: number;\n\tconst activeProviderIds = new Set(providerActive.map(backgroundWorkIdentity));\n\tconst providerFinishedCount = [...initialProviderIds].filter((id) => !activeProviderIds.has(id)).length;\n\ttry {\n\t\tconst allNow = allRunsForSession(waitParams, deps);\n\t\tconst terminal = allNow.filter((run) => !ACTIVE_STATES.includes(run.state) && initialAsyncIds.has(run.id));\n\t\tfinishedAsyncCount = terminal.length;\n\t\tfailedAsyncCount = terminal.filter((run) => run.state === \"failed\").length;\n\t\tterminalSummary = summarizeTerminalRuns(terminal, providerFinishedCount);\n\t} catch (error) {\n\t\treturn result(error instanceof Error ? error.message : String(error), true);\n\t}\n\n\tconst relevantAttention = attention.filter((run) => initialAsyncIds.has(run.id));\n\tconst attentionNote = relevantAttention.length > 0\n\t\t? ` ${relevantAttention.length} run(s) need attention: ${relevantAttention.map((run) => run.id).join(\", \")} — inspect with subagent({ action: \"status\" }) then nudge/resume/interrupt.`\n\t\t: \"\";\n\tconst stillRunning = active.filter((run) => initialAsyncIds.has(run.id)).length\n\t\t+ providerActive.filter((item) => initialProviderIds.has(backgroundWorkIdentity(item))).length;\n\tconst elapsed = formatDuration(now() - startedAt);\n\tconst outcome = terminalSummary ? ` Outcome: ${terminalSummary}.` : \"\";\n\n\tif (waitForAll) {\n\t\tconst scope = params.id\n\t\t\t? `run \"${params.id}\"`\n\t\t\t: initialProviderIds.size === 0\n\t\t\t\t? `${initialAsyncIds.size} async run(s)`\n\t\t\t\t: `${initialAsyncIds.size} async run(s) and ${initialProviderIds.size} provider item(s)`;\n\t\tconst status = relevantAttention.length > 0 ? \"attention required\" : \"done\";\n\t\treturn result(\n\t\t\t`Waited ${elapsed} for ${scope}; ${status}.${outcome}${attentionNote} Completion/control events have been observed; inspect status if a notification is not visible yet.`,\n\t\t\tdeps.failOnFailedRuns === true && failedAsyncCount > 0,\n\t\t);\n\t}\n\n\tconst finishedCount = finishedAsyncCount + providerFinishedCount;\n\tconst subject = initialProviderIds.size === 0 ? \"run(s)\" : \"item(s)\";\n\tconst remainder = stillRunning > 0\n\t\t? ` ${stillRunning} ${subject} still in flight — call subagent_wait again to catch the next one.`\n\t\t: relevantAttention.length > 0\n\t\t\t? \" No other work is waitable until attention is handled.\"\n\t\t\t: initialProviderIds.size === 0 ? \" No runs remain in flight.\" : \" No work remains in flight.\";\n\tconst progress = relevantAttention.length > 0 && finishedCount === 0\n\t\t? `${relevantAttention.length} of ${initialCount} ${subject} need attention`\n\t\t: `${finishedCount} of ${initialCount} ${subject} finished`;\n\treturn result(\n\t\t`Waited ${elapsed}; ${progress}.${outcome}${attentionNote}${remainder} Relevant completion/control events have been observed; inspect status if a notification is not visible yet.`,\n\t\tdeps.failOnFailedRuns === true && failedAsyncCount > 0,\n\t);\n}\n"]}
1
+ {"version":3,"file":"subagent-wait.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAGN,KAAK,sBAAsB,EAE3B,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EASN,KAAK,OAAO,EAEZ,KAAK,aAAa,EAClB,MAAM,uBAAuB,CAAC;AAY/B,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,KAAK,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAS7G,MAAM,WAAW,kBAAkB;IAClC,uGAAuG;IACvG,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wEAAwE;AACxE,MAAM,WAAW,YAAY;IAC5B,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAClE;AAED,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,aAAa,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,OAAO,CAAC;IAC7D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kCAAkC;IAClC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,qEAAqE;IACrE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,qEAAqE;IACrE,cAAc,CAAC,EAAE;QAChB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,sBAAsB,CAAC;QACnE,YAAY,IAAI,SAAS,MAAM,EAAE,CAAC;KAClC,CAAC;IACF;;;;;OAKG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;CACtB;AAgRD,wBAAsB,gBAAgB,CACrC,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,IAAI,EAAE,gBAAgB,GACpB,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CA0JnC","sourcesContent":["// @ts-nocheck\n/**\n * `subagent_wait` tool: block the current turn until outstanding async runs\n * or a named remembered detached foreground run finishes.\n *\n * Background subagent runs are detached. In an interactive session the parent\n * can end its turn and Pi will wake it with a completion notification. That\n * does not work when the parent is a skill that must run to completion, and it\n * cannot work at all non-interactively (`pi -p ...`), where the run is a single\n * turn: once the turn ends there is nothing left to receive the notification.\n *\n * `subagent_wait` closes that gap. It keeps the turn alive until a tracked async\n * run for this session reaches a terminal state (complete / failed / paused),\n * the caller-supplied timeout elapses, or the turn is aborted. Because it awaits\n * inside the turn, the completion the model was told to wait for is actually\n * observed before the tool returns.\n *\n * By default `subagent_wait` returns as soon as ONE run finishes, so a fleet\n * manager can use it in a rolling-replacement loop: launch N workers, wait for\n * the next one to finish, spawn its replacement, then call `subagent_wait`\n * again — keeping N in flight instead of draining to zero between batches.\n * Pass `all: true` to block until every tracked async run is terminal, or `id`\n * to block on one specific async or remembered detached foreground run.\n *\n * `subagent_wait` also returns when a run needs attention — not just on\n * completion. A child that goes idle or blocks for a decision surfaces\n * `needs_attention` (the same signal Pi shows as a control notice and,\n * interactively, wakes the parent with). Since `subagent_wait` is used exactly\n * where there is no next turn to receive that notice, it must break on it too,\n * or a stuck child would stall the loop until the timeout. Attention runs are\n * reported so the caller can inspect / nudge / resume / interrupt them.\n *\n * Wake mechanism: when given Pi's event bus (`deps.events`), `subagent_wait`\n * subscribes to the subagent completion/control channels and wakes the instant\n * any fires, rather than waiting out a fixed poll interval. A poll still runs\n * on the interval as a reconciliation fallback (crashed runners, missed\n * events), and the poll is the source of truth for what actually changed — the\n * event only ends the sleep early. With no bus, `subagent_wait` degrades to pure\n * polling.\n */\n\nimport type { AgentToolResult } from \"@ashx-j/lunr-agent\";\nimport {\n\tlistBackgroundWorkWakeChannels,\n\tsnapshotBackgroundWork,\n\ttype BackgroundWorkSnapshot,\n\ttype RegisteredBackgroundWorkItem,\n} from \"../../api/background-work.ts\";\nimport { listAsyncRuns, type AsyncRunSummary } from \"./async-status.ts\";\nimport { hasPendingBlockingSupervisorRequest } from \"../../intercom/native-supervisor-channel.ts\";\nimport {\n\tASYNC_DIR,\n\tINTERCOM_DETACH_REQUEST_EVENT,\n\tRESULTS_DIR,\n\tSUBAGENT_ASYNC_COMPLETE_EVENT,\n\tSUBAGENT_FOREGROUND_COMPLETE_EVENT,\n\tSUBAGENT_CONTROL_EVENT,\n\tSUBAGENT_CONTROL_INTERCOM_EVENT,\n\tSUBAGENT_RESULT_INTERCOM_EVENT,\n\ttype Details,\n\ttype ForegroundResumeRun,\n\ttype SubagentState,\n} from \"../../shared/types.ts\";\nimport { formatDuration } from \"../../shared/formatters.ts\";\nimport { reconcileAsyncQuestion } from \"../../intercom/supervisor-ask.ts\";\nimport {\n\tclaimQuestionNotification,\n\tfindSupervisorQuestion,\n\tformatSupervisorQuestionAnswer,\n\tregisterQuestionWait,\n\tsupervisorQuestionIsTerminal,\n\tsupervisorQuestionPublicState,\n\tSUBAGENT_QUESTION_EVENT,\n} from \"../../intercom/supervisor-questions.ts\";\nexport { WAIT_TOOL_ENABLED_ENV, resolveWaitToolConfig, type ResolvedWaitToolConfig } from \"./wait-config.ts\";\n\n/** States that mean a run is still in flight (not yet resolved). */\nconst ACTIVE_STATES: ReadonlyArray<AsyncRunSummary[\"state\"]> = [\"queued\", \"running\"];\n\nconst DEFAULT_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes\nconst MIN_POLL_INTERVAL_MS = 250;\nconst DEFAULT_POLL_INTERVAL_MS = 1000;\n\nexport interface SubagentWaitParams {\n\t/** Optional run id/prefix to wait for. When omitted, waits across every active run in this session. */\n\tid?: string;\n\t/** Optional supervisor question id from subagent_supervisor action='ask'. */\n\tquestionId?: string;\n\t/**\n\t * When true, block until EVERY active run in this session (or matching `id`)\n\t * is terminal. Default false: return as soon as the first run finishes, so a\n\t * fleet manager can spawn a replacement and wait again. Ignored when `id`\n\t * or `questionId` targets a single item.\n\t */\n\tall?: boolean;\n\t/** Give up after this many milliseconds. Defaults to 30 minutes. */\n\ttimeoutMs?: number;\n}\n\n/** Minimal event-bus surface wait subscribes to (matches pi.events). */\nexport interface WaitEventBus {\n\ton(channel: string, handler: (data: unknown) => void): () => void;\n}\n\nexport interface SubagentWaitDeps {\n\tstate: SubagentState;\n\tasyncDirRoot?: string;\n\tresultsDir?: string;\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean;\n\tnow?: () => number;\n\tpollIntervalMs?: number;\n\t/** False makes the tool return immediately without blocking active async runs. */\n\tenabled?: boolean;\n\t/** Injectable sleep for tests. */\n\tsleep?: (ms: number, signal?: AbortSignal) => Promise<void>;\n\t/** Internal auto-drain mode waits through needs-attention states. */\n\tstopOnAttention?: boolean;\n\t/** Internal auto-drain mode surfaces failed terminal subagent runs as errors. */\n\tfailOnFailedRuns?: boolean;\n\t/** Injectable provider protocol surfaces for deterministic tests. */\n\tbackgroundWork?: {\n\t\tsnapshot(sessionId: string, nowMs: number): BackgroundWorkSnapshot;\n\t\twakeChannels(): readonly string[];\n\t};\n\t/**\n\t * Optional event bus (pi.events). When provided, wait wakes immediately on a\n\t * subagent completion/control event instead of waiting out the poll interval;\n\t * the poll then remains as a reconciliation fallback (crashed runners, missed\n\t * events). Omit in tests that want pure poll behavior.\n\t */\n\tevents?: WaitEventBus;\n}\n\n/** Bus channels that indicate a run changed state or needs attention. */\nconst WAKE_CHANNELS = [\n\tSUBAGENT_ASYNC_COMPLETE_EVENT,\n\tSUBAGENT_FOREGROUND_COMPLETE_EVENT,\n\tSUBAGENT_CONTROL_EVENT,\n\tSUBAGENT_CONTROL_INTERCOM_EVENT,\n\tSUBAGENT_RESULT_INTERCOM_EVENT,\n\tINTERCOM_DETACH_REQUEST_EVENT,\n\tSUBAGENT_QUESTION_EVENT,\n];\n\nfunction defaultSleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve) => {\n\t\tif (signal?.aborted) {\n\t\t\tresolve();\n\t\t\treturn;\n\t\t}\n\t\tconst timer = setTimeout(() => {\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve();\n\t\t}, ms);\n\t\tconst onAbort = () => {\n\t\t\tclearTimeout(timer);\n\t\t\tresolve();\n\t\t};\n\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t});\n}\n\n/**\n * Sleep up to `ms`, but wake early if a subagent event fires on the bus (or the\n * turn aborts). Returns when the first of those happens. With no bus this is a\n * plain sleep, so the poll interval alone drives progress.\n */\nfunction waitForWake(ms: number, signal: AbortSignal | undefined, deps: SubagentWaitDeps): Promise<void> {\n\tconst sleep = deps.sleep ?? defaultSleep;\n\tconst events = deps.events;\n\tif (!events) return sleep(ms, signal);\n\tconst providerChannels = deps.backgroundWork?.wakeChannels() ?? listBackgroundWorkWakeChannels();\n\treturn new Promise((resolve, reject) => {\n\t\tlet settled = false;\n\t\tconst unsubs: Array<() => void> = [];\n\t\tconst wakeController = new AbortController();\n\t\tconst done = () => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\twakeController.abort();\n\t\t\tsignal?.removeEventListener(\"abort\", done);\n\t\t\tfor (const u of unsubs) {\n\t\t\t\ttry { u(); } catch { /* best effort */ }\n\t\t\t}\n\t\t\tresolve();\n\t\t};\n\t\tif (signal?.aborted) {\n\t\t\tdone();\n\t\t\treturn;\n\t\t}\n\t\tsignal?.addEventListener(\"abort\", done, { once: true });\n\t\ttry {\n\t\t\tfor (const channel of [...new Set([...WAKE_CHANNELS, ...providerChannels])]) {\n\t\t\t\tunsubs.push(events.on(channel, done));\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tsignal?.removeEventListener(\"abort\", done);\n\t\t\tfor (const unsubscribe of unsubs) {\n\t\t\t\ttry { unsubscribe(); } catch { /* best effort cleanup */ }\n\t\t\t}\n\t\t\treject(error);\n\t\t\treturn;\n\t\t}\n\t\t// Poll-interval fallback so we still reconcile even if no event arrives.\n\t\t// The local signal cancels that fallback timer when an event wakes us first.\n\t\tvoid sleep(ms, wakeController.signal).then(done);\n\t});\n}\n\nfunction matchesId(run: AsyncRunSummary, id: string): boolean {\n\treturn run.id === id || run.id.startsWith(id);\n}\n\nfunction activeDetachedForegroundRuns(params: SubagentWaitParams, deps: SubagentWaitDeps): ForegroundResumeRun[] {\n\tif (!params.id || !deps.state.foregroundRuns) return [];\n\tconst sessionId = deps.state.currentSessionId;\n\tif (!sessionId) return [];\n\treturn [...deps.state.foregroundRuns.values()].filter((run) =>\n\t\t(run.runId === params.id || run.runId.startsWith(params.id!))\n\t\t&& run.sessionId === sessionId\n\t\t&& run.children.some((child) => child.status === \"detached\")\n\t);\n}\n\nfunction summarizeForegroundChildren(run: ForegroundResumeRun, indices: Set<number>): string {\n\tconst counts = new Map<string, number>();\n\tfor (const child of run.children) {\n\t\tif (!indices.has(child.index) || child.status === \"detached\") continue;\n\t\tcounts.set(child.status, (counts.get(child.status) ?? 0) + 1);\n\t}\n\treturn [...counts.entries()].map(([status, count]) => `${count} ${status}`).join(\", \");\n}\n\n/** A running run that has flagged it needs the parent's attention. */\nfunction needsAttention(run: AsyncRunSummary, sessionId?: string | null): boolean {\n\treturn run.activityState === \"needs_attention\"\n\t\t|| hasPendingBlockingSupervisorRequest(run.id, sessionId);\n}\n\nfunction backgroundWorkIdentity(item: RegisteredBackgroundWorkItem): string {\n\treturn `${item.provider}\\0${item.sessionId}\\0${item.id}`;\n}\n\nfunction backgroundWorkForSession(deps: SubagentWaitDeps, nowMs: number): BackgroundWorkSnapshot {\n\tconst sessionId = deps.state.currentSessionId;\n\tif (!sessionId) throw new Error(\"subagent_wait requires an active session identity to scope background work safely.\");\n\treturn deps.backgroundWork?.snapshot(sessionId, nowMs) ?? snapshotBackgroundWork(sessionId, nowMs);\n}\n\n/** Queued/running runs from this session, including runs that need attention. */\nfunction activeRunsForSession(params: SubagentWaitParams, deps: SubagentWaitDeps): AsyncRunSummary[] {\n\tconst asyncDirRoot = deps.asyncDirRoot ?? ASYNC_DIR;\n\tconst resultsDir = deps.resultsDir ?? RESULTS_DIR;\n\tconst runs = listAsyncRuns(asyncDirRoot, {\n\t\tstates: [...ACTIVE_STATES],\n\t\tsessionId: deps.state.currentSessionId ?? undefined,\n\t\tresultsDir,\n\t\tkill: deps.kill,\n\t\tnow: deps.now,\n\t});\n\treturn params.id ? runs.filter((run) => matchesId(run, params.id!)) : runs;\n}\n\n/** Runs (from the initial set) currently flagged needs_attention, for reporting. */\nfunction attentionRunsForSession(params: SubagentWaitParams, deps: SubagentWaitDeps, initialIds: Set<string>): AsyncRunSummary[] {\n\treturn activeRunsForSession(params, deps).filter((run) => needsAttention(run, deps.state.currentSessionId) && initialIds.has(run.id));\n}\n\n/** All runs (any state) for this session, for the final summary. */\nfunction allRunsForSession(params: SubagentWaitParams, deps: SubagentWaitDeps): AsyncRunSummary[] {\n\tconst asyncDirRoot = deps.asyncDirRoot ?? ASYNC_DIR;\n\tconst resultsDir = deps.resultsDir ?? RESULTS_DIR;\n\tconst runs = listAsyncRuns(asyncDirRoot, {\n\t\tsessionId: deps.state.currentSessionId ?? undefined,\n\t\tresultsDir,\n\t\tkill: deps.kill,\n\t\tnow: deps.now,\n\t});\n\treturn params.id ? runs.filter((run) => matchesId(run, params.id!)) : runs;\n}\n\nfunction summarizeTerminalRuns(runs: AsyncRunSummary[], providerFinishedCount = 0): string {\n\tif (runs.length === 0 && providerFinishedCount === 0) return \"\";\n\tconst counts = { complete: 0, failed: 0, paused: 0 } as Record<string, number>;\n\tfor (const run of runs) {\n\t\tif (run.state in counts) counts[run.state] += 1;\n\t}\n\tconst parts: string[] = [];\n\tif (counts.complete) parts.push(`${counts.complete} complete`);\n\tif (counts.failed) parts.push(`${counts.failed} failed`);\n\tif (counts.paused) parts.push(`${counts.paused} paused`);\n\tif (providerFinishedCount > 0) parts.push(`${providerFinishedCount} provider item(s) finished`);\n\treturn parts.join(\", \");\n}\n\nfunction result(text: string, isError = false): AgentToolResult<Details> {\n\treturn {\n\t\tcontent: [{ type: \"text\", text }],\n\t\t...(isError ? { isError: true } : {}),\n\t\tdetails: { mode: \"management\", results: [] },\n\t};\n}\n\nasync function waitForDetachedForegroundRun(\n\trun: ForegroundResumeRun,\n\tsignal: AbortSignal | undefined,\n\tdeps: SubagentWaitDeps,\n\tstartedAt: number,\n\tnow: () => number,\n\tpollIntervalMs: number,\n\ttimeoutMs: number,\n): Promise<AgentToolResult<Details>> {\n\tconst initialDetachedIndices = new Set(run.children.filter((child) => child.status === \"detached\").map((child) => child.index));\n\twhile (true) {\n\t\tif (deps.state.currentSessionId !== run.sessionId) {\n\t\t\treturn result(`Wait stopped because the active session changed while remembered foreground run \"${run.runId}\" was still detached. Return to the originating session to inspect or wait for it.`, true);\n\t\t}\n\t\tconst current = deps.state.foregroundRuns?.get(run.runId);\n\t\tif (!current || current.sessionId !== run.sessionId) {\n\t\t\treturn result(`Remembered foreground run \"${run.runId}\" disappeared before a terminal child result was recorded. Completion cannot be confirmed; do not launch a replacement without checking the originating child session.`, true);\n\t\t}\n\t\tconst pending = current.children.filter((child) => initialDetachedIndices.has(child.index) && child.status === \"detached\");\n\t\tif (pending.length === 0) {\n\t\t\tconst outcome = summarizeForegroundChildren(current, initialDetachedIndices);\n\t\t\treturn result(\n\t\t\t\t`Waited ${formatDuration(now() - startedAt)} for remembered detached foreground run \"${run.runId}\"; done. Outcome: ${outcome || \"no recovered child status\"}. Completion event observed; inspect with subagent({ action: \"status\", id: \"${run.runId}\" }) for recovered output.`,\n\t\t\t);\n\t\t}\n\t\tif (signal?.aborted) {\n\t\t\treturn result(`Wait aborted after ${formatDuration(now() - startedAt)}. Remembered foreground run \"${run.runId}\" remains detached.`, true);\n\t\t}\n\t\tif (now() - startedAt >= timeoutMs) {\n\t\t\treturn result(\n\t\t\t\t`Wait timed out after ${formatDuration(timeoutMs)} with remembered foreground run \"${run.runId}\" still detached. Reply to any pending supervisor request, then call subagent_wait({ id: \"${run.runId}\" }) again or inspect status; do not resume or launch a replacement while it remains detached.`,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\t\tawait waitForWake(pollIntervalMs, signal, deps);\n\t}\n}\n\n/**\n * Block until the targeted async or remembered detached foreground run finishes,\n * the timeout elapses, or the turn is aborted. Resolves with a short\n * human-readable summary either way.\n */\nasync function waitForSupervisorQuestion(\n\tquestionId: string,\n\tsignal: AbortSignal | undefined,\n\tdeps: SubagentWaitDeps,\n\tstartedAt: number,\n\tnow: () => number,\n\tpollIntervalMs: number,\n\ttimeoutMs: number,\n): Promise<AgentToolResult<Details>> {\n\tconst sessionId = deps.state.currentSessionId;\n\tif (!sessionId) return result(\"subagent_wait requires an active session identity to scope background work safely.\", true);\n\tconst releaseWait = registerQuestionWait([questionId]);\n\ttry {\n\t\twhile (true) {\n\t\t\tconst found = findSupervisorQuestion(questionId);\n\t\t\tif (!found) {\n\t\t\t\treturn result(`No supervisor question matched \"${questionId}\".`, true);\n\t\t\t}\n\t\t\tconst { channelDir } = found;\n\t\t\tlet { question } = found;\n\t\t\tif (question.parentSessionId !== sessionId || deps.state.currentSessionId !== sessionId) {\n\t\t\t\treturn result(`Supervisor question \"${questionId}\" belongs to another session.`, true);\n\t\t\t}\n\t\t\tif ((deps.state.sessionGeneration ?? 0) !== question.parentGeneration) {\n\t\t\t\treturn result(`Supervisor question \"${questionId}\" was cancelled by a session replacement.`, true);\n\t\t\t}\n\t\t\tquestion = reconcileAsyncQuestion(channelDir, question, deps.state);\n\t\t\tif (supervisorQuestionIsTerminal(question)) {\n\t\t\t\tclaimQuestionNotification(channelDir, question.id);\n\t\t\t\tconst state = supervisorQuestionPublicState(question);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: formatSupervisorQuestionAnswer(question) }],\n\t\t\t\t\t...(state === \"answered\" ? {} : { isError: true }),\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tmode: \"management\",\n\t\t\t\t\t\tresults: [],\n\t\t\t\t\t\tquestionId: question.id,\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\trunId: question.runId,\n\t\t\t\t\t\tanswered: state === \"answered\",\n\t\t\t\t\t\tdelivered: Boolean(question.deliveredAt),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (signal?.aborted) {\n\t\t\t\treturn result(`Wait aborted after ${formatDuration(now() - startedAt)} for supervisor question \"${questionId}\".`, true);\n\t\t\t}\n\t\t\tif (now() - startedAt >= timeoutMs) {\n\t\t\t\treturn result(`Wait timed out after ${formatDuration(timeoutMs)} for supervisor question \"${questionId}\". The question remains pending until answered, expired, or cancelled.`, true);\n\t\t\t}\n\t\t\tawait waitForWake(pollIntervalMs, signal, deps);\n\t\t}\n\t} finally {\n\t\treleaseWait();\n\t}\n}\n\nexport async function waitForSubagents(\n\tparams: SubagentWaitParams,\n\tsignal: AbortSignal | undefined,\n\tdeps: SubagentWaitDeps,\n): Promise<AgentToolResult<Details>> {\n\tif (deps.enabled === false) {\n\t\treturn result(\"subagent_wait is disabled by config.waitTool or PI_SUBAGENT_WAIT_TOOL_ENABLED; returning immediately without blocking background work. Active work keeps going, and you can inspect subagents with subagent({ action: \\\"status\\\" }) or rely on completion notifications.\");\n\t}\n\tif (!deps.state.currentSessionId) {\n\t\treturn result(\"subagent_wait requires an active session identity to scope background work safely.\", true);\n\t}\n\n\tconst now = deps.now ?? Date.now;\n\tconst pollIntervalMs = Math.max(MIN_POLL_INTERVAL_MS, deps.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);\n\tconst timeoutMs = params.timeoutMs !== undefined && params.timeoutMs > 0 ? params.timeoutMs : DEFAULT_TIMEOUT_MS;\n\tconst startedAt = now();\n\tif (params.questionId?.trim()) {\n\t\treturn waitForSupervisorQuestion(params.questionId.trim(), signal, deps, startedAt, now, pollIntervalMs, timeoutMs);\n\t}\n\tconst waitForAll = params.id ? true : params.all === true;\n\n\tlet active: AsyncRunSummary[];\n\tlet foreground: ForegroundResumeRun[];\n\tlet providerSnapshot: BackgroundWorkSnapshot;\n\ttry {\n\t\tactive = activeRunsForSession(params, deps);\n\t\tforeground = activeDetachedForegroundRuns(params, deps);\n\t\tproviderSnapshot = params.id ? { providers: [], items: [] } : backgroundWorkForSession(deps, startedAt);\n\t} catch (error) {\n\t\treturn result(error instanceof Error ? error.message : String(error), true);\n\t}\n\n\tif (params.id) {\n\t\tconst candidates = [\n\t\t\t...active.map((run) => ({ kind: \"async\" as const, id: run.id, run })),\n\t\t\t...foreground.map((run) => ({ kind: \"foreground\" as const, id: run.runId, run })),\n\t\t];\n\t\tconst exact = candidates.filter((candidate) => candidate.id === params.id);\n\t\tconst matches = exact.length > 0 ? exact : candidates;\n\t\tif (matches.length > 1) {\n\t\t\treturn result(`Ambiguous subagent run id prefix \"${params.id}\" matched ${matches.length} active runs: ${matches.map((candidate) => candidate.id).join(\", \")}. Pass a longer id.`, true);\n\t\t}\n\t\tconst selected = matches[0];\n\t\tif (selected?.kind === \"foreground\") {\n\t\t\treturn waitForDetachedForegroundRun(selected.run, signal, deps, startedAt, now, pollIntervalMs, timeoutMs);\n\t\t}\n\t\tactive = selected?.kind === \"async\" ? [selected.run] : [];\n\t}\n\n\tlet providerActive = providerSnapshot.items;\n\tif (active.length === 0 && providerActive.length === 0) {\n\t\treturn result(params.id\n\t\t\t? `No active run matched \"${params.id}\". Nothing to wait for.`\n\t\t\t: \"No active async runs or registered provider work in this session. Nothing to wait for.\");\n\t}\n\tconst waitParams = params.id ? { ...params, id: active[0]!.id } : params;\n\tconst initialAsyncIds = new Set(active.map((run) => run.id));\n\tconst initialProviderIds = new Set(providerActive.map(backgroundWorkIdentity));\n\tconst initialProviderNames = new Set(providerActive.map((item) => item.provider));\n\tconst initialCount = initialAsyncIds.size + initialProviderIds.size;\n\tconst stopOnAttention = deps.stopOnAttention !== false;\n\tlet attention = active.filter((run) => needsAttention(run, deps.state.currentSessionId));\n\n\tconst isDone = (): boolean => {\n\t\tif (stopOnAttention && attention.some((run) => initialAsyncIds.has(run.id))) return true;\n\t\tconst activeAsyncIds = new Set(active.map((run) => run.id));\n\t\tconst activeProviderIds = new Set(providerActive.map(backgroundWorkIdentity));\n\t\tif (waitForAll) {\n\t\t\treturn [...initialAsyncIds].every((id) => !activeAsyncIds.has(id))\n\t\t\t\t&& [...initialProviderIds].every((id) => !activeProviderIds.has(id));\n\t\t}\n\t\treturn [...initialAsyncIds].some((id) => !activeAsyncIds.has(id))\n\t\t\t|| [...initialProviderIds].some((id) => !activeProviderIds.has(id));\n\t};\n\n\twhile (!isDone()) {\n\t\tconst activeInitialRuns = active.filter((run) => initialAsyncIds.has(run.id));\n\t\tconst activeInitialProviderItems = providerActive.filter((item) => initialProviderIds.has(backgroundWorkIdentity(item)));\n\t\tconst stillActive = [\n\t\t\t...activeInitialRuns.map((run) => `${run.id} (${run.state})`),\n\t\t\t...activeInitialProviderItems.map((item) => `${item.provider}/${item.id}`),\n\t\t].join(\", \");\n\t\tif (signal?.aborted) {\n\t\t\treturn result(`Wait aborted after ${formatDuration(now() - startedAt)}. Still active: ${stillActive}.`, true);\n\t\t}\n\t\tif (now() - startedAt >= timeoutMs) {\n\t\t\treturn result(\n\t\t\t\t`Wait timed out after ${formatDuration(timeoutMs)} with ${activeInitialRuns.length} async run(s) and ${activeInitialProviderItems.length} provider item(s) still active: ${stillActive}. The work keeps going; call subagent_wait again or inspect subagent status.`,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\tawait waitForWake(pollIntervalMs, signal, deps);\n\t\t\tactive = activeRunsForSession(waitParams, deps);\n\t\t\tattention = attentionRunsForSession(waitParams, deps, initialAsyncIds);\n\t\t\tproviderSnapshot = params.id ? providerSnapshot : backgroundWorkForSession(deps, now());\n\t\t\tfor (const provider of initialProviderNames) {\n\t\t\t\tif (!providerSnapshot.providers.includes(provider)) {\n\t\t\t\t\treturn result(`Background-work provider '${provider}' disappeared while subagent_wait was tracking its active work; completion cannot be confirmed.`, true);\n\t\t\t\t}\n\t\t\t}\n\t\t\tproviderActive = providerSnapshot.items;\n\t\t} catch (error) {\n\t\t\treturn result(error instanceof Error ? error.message : String(error), true);\n\t\t}\n\t}\n\n\tlet terminalSummary: string;\n\tlet finishedAsyncCount: number;\n\tlet failedAsyncCount: number;\n\tconst activeProviderIds = new Set(providerActive.map(backgroundWorkIdentity));\n\tconst providerFinishedCount = [...initialProviderIds].filter((id) => !activeProviderIds.has(id)).length;\n\ttry {\n\t\tconst allNow = allRunsForSession(waitParams, deps);\n\t\tconst terminal = allNow.filter((run) => !ACTIVE_STATES.includes(run.state) && initialAsyncIds.has(run.id));\n\t\tfinishedAsyncCount = terminal.length;\n\t\tfailedAsyncCount = terminal.filter((run) => run.state === \"failed\").length;\n\t\tterminalSummary = summarizeTerminalRuns(terminal, providerFinishedCount);\n\t} catch (error) {\n\t\treturn result(error instanceof Error ? error.message : String(error), true);\n\t}\n\n\tconst relevantAttention = attention.filter((run) => initialAsyncIds.has(run.id));\n\tconst attentionNote = relevantAttention.length > 0\n\t\t? ` ${relevantAttention.length} run(s) need attention: ${relevantAttention.map((run) => run.id).join(\", \")} — inspect with subagent({ action: \"status\" }) then nudge/resume/interrupt.`\n\t\t: \"\";\n\tconst stillRunning = active.filter((run) => initialAsyncIds.has(run.id)).length\n\t\t+ providerActive.filter((item) => initialProviderIds.has(backgroundWorkIdentity(item))).length;\n\tconst elapsed = formatDuration(now() - startedAt);\n\tconst outcome = terminalSummary ? ` Outcome: ${terminalSummary}.` : \"\";\n\n\tif (waitForAll) {\n\t\tconst scope = params.id\n\t\t\t? `run \"${params.id}\"`\n\t\t\t: initialProviderIds.size === 0\n\t\t\t\t? `${initialAsyncIds.size} async run(s)`\n\t\t\t\t: `${initialAsyncIds.size} async run(s) and ${initialProviderIds.size} provider item(s)`;\n\t\tconst status = relevantAttention.length > 0 ? \"attention required\" : \"done\";\n\t\treturn result(\n\t\t\t`Waited ${elapsed} for ${scope}; ${status}.${outcome}${attentionNote} Completion/control events have been observed; inspect status if a notification is not visible yet.`,\n\t\t\tdeps.failOnFailedRuns === true && failedAsyncCount > 0,\n\t\t);\n\t}\n\n\tconst finishedCount = finishedAsyncCount + providerFinishedCount;\n\tconst subject = initialProviderIds.size === 0 ? \"run(s)\" : \"item(s)\";\n\tconst remainder = stillRunning > 0\n\t\t? ` ${stillRunning} ${subject} still in flight — call subagent_wait again to catch the next one.`\n\t\t: relevantAttention.length > 0\n\t\t\t? \" No other work is waitable until attention is handled.\"\n\t\t\t: initialProviderIds.size === 0 ? \" No runs remain in flight.\" : \" No work remains in flight.\";\n\tconst progress = relevantAttention.length > 0 && finishedCount === 0\n\t\t? `${relevantAttention.length} of ${initialCount} ${subject} need attention`\n\t\t: `${finishedCount} of ${initialCount} ${subject} finished`;\n\treturn result(\n\t\t`Waited ${elapsed}; ${progress}.${outcome}${attentionNote}${remainder} Relevant completion/control events have been observed; inspect status if a notification is not visible yet.`,\n\t\tdeps.failOnFailedRuns === true && failedAsyncCount > 0,\n\t);\n}\n"]}
@@ -40,8 +40,11 @@
40
40
  */
41
41
  import { listBackgroundWorkWakeChannels, snapshotBackgroundWork, } from "../../api/background-work.js";
42
42
  import { listAsyncRuns } from "./async-status.js";
43
- import { ASYNC_DIR, RESULTS_DIR, SUBAGENT_ASYNC_COMPLETE_EVENT, SUBAGENT_FOREGROUND_COMPLETE_EVENT, SUBAGENT_CONTROL_EVENT, SUBAGENT_CONTROL_INTERCOM_EVENT, SUBAGENT_RESULT_INTERCOM_EVENT, } from "../../shared/types.js";
43
+ import { hasPendingBlockingSupervisorRequest } from "../../intercom/native-supervisor-channel.js";
44
+ import { ASYNC_DIR, INTERCOM_DETACH_REQUEST_EVENT, RESULTS_DIR, SUBAGENT_ASYNC_COMPLETE_EVENT, SUBAGENT_FOREGROUND_COMPLETE_EVENT, SUBAGENT_CONTROL_EVENT, SUBAGENT_CONTROL_INTERCOM_EVENT, SUBAGENT_RESULT_INTERCOM_EVENT, } from "../../shared/types.js";
44
45
  import { formatDuration } from "../../shared/formatters.js";
46
+ import { reconcileAsyncQuestion } from "../../intercom/supervisor-ask.js";
47
+ import { claimQuestionNotification, findSupervisorQuestion, formatSupervisorQuestionAnswer, registerQuestionWait, supervisorQuestionIsTerminal, supervisorQuestionPublicState, SUBAGENT_QUESTION_EVENT, } from "../../intercom/supervisor-questions.js";
45
48
  export { WAIT_TOOL_ENABLED_ENV, resolveWaitToolConfig } from "./wait-config.js";
46
49
  /** States that mean a run is still in flight (not yet resolved). */
47
50
  const ACTIVE_STATES = ["queued", "running"];
@@ -55,6 +58,8 @@ const WAKE_CHANNELS = [
55
58
  SUBAGENT_CONTROL_EVENT,
56
59
  SUBAGENT_CONTROL_INTERCOM_EVENT,
57
60
  SUBAGENT_RESULT_INTERCOM_EVENT,
61
+ INTERCOM_DETACH_REQUEST_EVENT,
62
+ SUBAGENT_QUESTION_EVENT,
58
63
  ];
59
64
  function defaultSleep(ms, signal) {
60
65
  return new Promise((resolve) => {
@@ -151,8 +156,9 @@ function summarizeForegroundChildren(run, indices) {
151
156
  return [...counts.entries()].map(([status, count]) => `${count} ${status}`).join(", ");
152
157
  }
153
158
  /** A running run that has flagged it needs the parent's attention. */
154
- function needsAttention(run) {
155
- return run.activityState === "needs_attention";
159
+ function needsAttention(run, sessionId) {
160
+ return run.activityState === "needs_attention"
161
+ || hasPendingBlockingSupervisorRequest(run.id, sessionId);
156
162
  }
157
163
  function backgroundWorkIdentity(item) {
158
164
  return `${item.provider}\0${item.sessionId}\0${item.id}`;
@@ -178,7 +184,7 @@ function activeRunsForSession(params, deps) {
178
184
  }
179
185
  /** Runs (from the initial set) currently flagged needs_attention, for reporting. */
180
186
  function attentionRunsForSession(params, deps, initialIds) {
181
- return activeRunsForSession(params, deps).filter((run) => needsAttention(run) && initialIds.has(run.id));
187
+ return activeRunsForSession(params, deps).filter((run) => needsAttention(run, deps.state.currentSessionId) && initialIds.has(run.id));
182
188
  }
183
189
  /** All runs (any state) for this session, for the final summary. */
184
190
  function allRunsForSession(params, deps) {
@@ -247,6 +253,56 @@ async function waitForDetachedForegroundRun(run, signal, deps, startedAt, now, p
247
253
  * the timeout elapses, or the turn is aborted. Resolves with a short
248
254
  * human-readable summary either way.
249
255
  */
256
+ async function waitForSupervisorQuestion(questionId, signal, deps, startedAt, now, pollIntervalMs, timeoutMs) {
257
+ const sessionId = deps.state.currentSessionId;
258
+ if (!sessionId)
259
+ return result("subagent_wait requires an active session identity to scope background work safely.", true);
260
+ const releaseWait = registerQuestionWait([questionId]);
261
+ try {
262
+ while (true) {
263
+ const found = findSupervisorQuestion(questionId);
264
+ if (!found) {
265
+ return result(`No supervisor question matched "${questionId}".`, true);
266
+ }
267
+ const { channelDir } = found;
268
+ let { question } = found;
269
+ if (question.parentSessionId !== sessionId || deps.state.currentSessionId !== sessionId) {
270
+ return result(`Supervisor question "${questionId}" belongs to another session.`, true);
271
+ }
272
+ if ((deps.state.sessionGeneration ?? 0) !== question.parentGeneration) {
273
+ return result(`Supervisor question "${questionId}" was cancelled by a session replacement.`, true);
274
+ }
275
+ question = reconcileAsyncQuestion(channelDir, question, deps.state);
276
+ if (supervisorQuestionIsTerminal(question)) {
277
+ claimQuestionNotification(channelDir, question.id);
278
+ const state = supervisorQuestionPublicState(question);
279
+ return {
280
+ content: [{ type: "text", text: formatSupervisorQuestionAnswer(question) }],
281
+ ...(state === "answered" ? {} : { isError: true }),
282
+ details: {
283
+ mode: "management",
284
+ results: [],
285
+ questionId: question.id,
286
+ state,
287
+ runId: question.runId,
288
+ answered: state === "answered",
289
+ delivered: Boolean(question.deliveredAt),
290
+ },
291
+ };
292
+ }
293
+ if (signal?.aborted) {
294
+ return result(`Wait aborted after ${formatDuration(now() - startedAt)} for supervisor question "${questionId}".`, true);
295
+ }
296
+ if (now() - startedAt >= timeoutMs) {
297
+ return result(`Wait timed out after ${formatDuration(timeoutMs)} for supervisor question "${questionId}". The question remains pending until answered, expired, or cancelled.`, true);
298
+ }
299
+ await waitForWake(pollIntervalMs, signal, deps);
300
+ }
301
+ }
302
+ finally {
303
+ releaseWait();
304
+ }
305
+ }
250
306
  export async function waitForSubagents(params, signal, deps) {
251
307
  if (deps.enabled === false) {
252
308
  return result("subagent_wait is disabled by config.waitTool or PI_SUBAGENT_WAIT_TOOL_ENABLED; returning immediately without blocking background work. Active work keeps going, and you can inspect subagents with subagent({ action: \"status\" }) or rely on completion notifications.");
@@ -258,6 +314,9 @@ export async function waitForSubagents(params, signal, deps) {
258
314
  const pollIntervalMs = Math.max(MIN_POLL_INTERVAL_MS, deps.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);
259
315
  const timeoutMs = params.timeoutMs !== undefined && params.timeoutMs > 0 ? params.timeoutMs : DEFAULT_TIMEOUT_MS;
260
316
  const startedAt = now();
317
+ if (params.questionId?.trim()) {
318
+ return waitForSupervisorQuestion(params.questionId.trim(), signal, deps, startedAt, now, pollIntervalMs, timeoutMs);
319
+ }
261
320
  const waitForAll = params.id ? true : params.all === true;
262
321
  let active;
263
322
  let foreground;
@@ -298,7 +357,7 @@ export async function waitForSubagents(params, signal, deps) {
298
357
  const initialProviderNames = new Set(providerActive.map((item) => item.provider));
299
358
  const initialCount = initialAsyncIds.size + initialProviderIds.size;
300
359
  const stopOnAttention = deps.stopOnAttention !== false;
301
- let attention = active.filter((run) => needsAttention(run));
360
+ let attention = active.filter((run) => needsAttention(run, deps.state.currentSessionId));
302
361
  const isDone = () => {
303
362
  if (stopOnAttention && attention.some((run) => initialAsyncIds.has(run.id)))
304
363
  return true;
@@ -1 +1 @@
1
- {"version":3,"file":"subagent-wait.js","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\n/**\n * `subagent_wait` tool: block the current turn until outstanding async runs\n * or a named remembered detached foreground run finishes.\n *\n * Background subagent runs are detached. In an interactive session the parent\n * can end its turn and Pi will wake it with a completion notification. That\n * does not work when the parent is a skill that must run to completion, and it\n * cannot work at all non-interactively (`pi -p ...`), where the run is a single\n * turn: once the turn ends there is nothing left to receive the notification.\n *\n * `subagent_wait` closes that gap. It keeps the turn alive until a tracked async\n * run for this session reaches a terminal state (complete / failed / paused),\n * the caller-supplied timeout elapses, or the turn is aborted. Because it awaits\n * inside the turn, the completion the model was told to wait for is actually\n * observed before the tool returns.\n *\n * By default `subagent_wait` returns as soon as ONE run finishes, so a fleet\n * manager can use it in a rolling-replacement loop: launch N workers, wait for\n * the next one to finish, spawn its replacement, then call `subagent_wait`\n * again — keeping N in flight instead of draining to zero between batches.\n * Pass `all: true` to block until every tracked async run is terminal, or `id`\n * to block on one specific async or remembered detached foreground run.\n *\n * `subagent_wait` also returns when a run needs attention — not just on\n * completion. A child that goes idle or blocks for a decision surfaces\n * `needs_attention` (the same signal Pi shows as a control notice and,\n * interactively, wakes the parent with). Since `subagent_wait` is used exactly\n * where there is no next turn to receive that notice, it must break on it too,\n * or a stuck child would stall the loop until the timeout. Attention runs are\n * reported so the caller can inspect / nudge / resume / interrupt them.\n *\n * Wake mechanism: when given Pi's event bus (`deps.events`), `subagent_wait`\n * subscribes to the subagent completion/control channels and wakes the instant\n * any fires, rather than waiting out a fixed poll interval. A poll still runs\n * on the interval as a reconciliation fallback (crashed runners, missed\n * events), and the poll is the source of truth for what actually changed — the\n * event only ends the sleep early. With no bus, `subagent_wait` degrades to pure\n * polling.\n */\n\nimport type { AgentToolResult } from \"@ashx-j/lunr-agent\";\nimport {\n\tlistBackgroundWorkWakeChannels,\n\tsnapshotBackgroundWork,\n\ttype BackgroundWorkSnapshot,\n\ttype RegisteredBackgroundWorkItem,\n} from \"../../api/background-work.ts\";\nimport { listAsyncRuns, type AsyncRunSummary } from \"./async-status.ts\";\nimport {\n\tASYNC_DIR,\n\tRESULTS_DIR,\n\tSUBAGENT_ASYNC_COMPLETE_EVENT,\n\tSUBAGENT_FOREGROUND_COMPLETE_EVENT,\n\tSUBAGENT_CONTROL_EVENT,\n\tSUBAGENT_CONTROL_INTERCOM_EVENT,\n\tSUBAGENT_RESULT_INTERCOM_EVENT,\n\ttype Details,\n\ttype ForegroundResumeRun,\n\ttype SubagentState,\n} from \"../../shared/types.ts\";\nimport { formatDuration } from \"../../shared/formatters.ts\";\nexport { WAIT_TOOL_ENABLED_ENV, resolveWaitToolConfig, type ResolvedWaitToolConfig } from \"./wait-config.ts\";\n\n/** States that mean a run is still in flight (not yet resolved). */\nconst ACTIVE_STATES: ReadonlyArray<AsyncRunSummary[\"state\"]> = [\"queued\", \"running\"];\n\nconst DEFAULT_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes\nconst MIN_POLL_INTERVAL_MS = 250;\nconst DEFAULT_POLL_INTERVAL_MS = 1000;\n\nexport interface SubagentWaitParams {\n\t/** Optional run id/prefix to wait for. When omitted, waits across every active run in this session. */\n\tid?: string;\n\t/**\n\t * When true, block until EVERY active run in this session (or matching `id`)\n\t * is terminal. Default false: return as soon as the first run finishes, so a\n\t * fleet manager can spawn a replacement and wait again. Ignored when `id`\n\t * targets a single run.\n\t */\n\tall?: boolean;\n\t/** Give up after this many milliseconds. Defaults to 30 minutes. */\n\ttimeoutMs?: number;\n}\n\n/** Minimal event-bus surface wait subscribes to (matches pi.events). */\nexport interface WaitEventBus {\n\ton(channel: string, handler: (data: unknown) => void): () => void;\n}\n\nexport interface SubagentWaitDeps {\n\tstate: SubagentState;\n\tasyncDirRoot?: string;\n\tresultsDir?: string;\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean;\n\tnow?: () => number;\n\tpollIntervalMs?: number;\n\t/** False makes the tool return immediately without blocking active async runs. */\n\tenabled?: boolean;\n\t/** Injectable sleep for tests. */\n\tsleep?: (ms: number, signal?: AbortSignal) => Promise<void>;\n\t/** Internal auto-drain mode waits through needs-attention states. */\n\tstopOnAttention?: boolean;\n\t/** Internal auto-drain mode surfaces failed terminal subagent runs as errors. */\n\tfailOnFailedRuns?: boolean;\n\t/** Injectable provider protocol surfaces for deterministic tests. */\n\tbackgroundWork?: {\n\t\tsnapshot(sessionId: string, nowMs: number): BackgroundWorkSnapshot;\n\t\twakeChannels(): readonly string[];\n\t};\n\t/**\n\t * Optional event bus (pi.events). When provided, wait wakes immediately on a\n\t * subagent completion/control event instead of waiting out the poll interval;\n\t * the poll then remains as a reconciliation fallback (crashed runners, missed\n\t * events). Omit in tests that want pure poll behavior.\n\t */\n\tevents?: WaitEventBus;\n}\n\n/** Bus channels that indicate a run changed state or needs attention. */\nconst WAKE_CHANNELS = [\n\tSUBAGENT_ASYNC_COMPLETE_EVENT,\n\tSUBAGENT_FOREGROUND_COMPLETE_EVENT,\n\tSUBAGENT_CONTROL_EVENT,\n\tSUBAGENT_CONTROL_INTERCOM_EVENT,\n\tSUBAGENT_RESULT_INTERCOM_EVENT,\n];\n\nfunction defaultSleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve) => {\n\t\tif (signal?.aborted) {\n\t\t\tresolve();\n\t\t\treturn;\n\t\t}\n\t\tconst timer = setTimeout(() => {\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve();\n\t\t}, ms);\n\t\tconst onAbort = () => {\n\t\t\tclearTimeout(timer);\n\t\t\tresolve();\n\t\t};\n\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t});\n}\n\n/**\n * Sleep up to `ms`, but wake early if a subagent event fires on the bus (or the\n * turn aborts). Returns when the first of those happens. With no bus this is a\n * plain sleep, so the poll interval alone drives progress.\n */\nfunction waitForWake(ms: number, signal: AbortSignal | undefined, deps: SubagentWaitDeps): Promise<void> {\n\tconst sleep = deps.sleep ?? defaultSleep;\n\tconst events = deps.events;\n\tif (!events) return sleep(ms, signal);\n\tconst providerChannels = deps.backgroundWork?.wakeChannels() ?? listBackgroundWorkWakeChannels();\n\treturn new Promise((resolve, reject) => {\n\t\tlet settled = false;\n\t\tconst unsubs: Array<() => void> = [];\n\t\tconst wakeController = new AbortController();\n\t\tconst done = () => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\twakeController.abort();\n\t\t\tsignal?.removeEventListener(\"abort\", done);\n\t\t\tfor (const u of unsubs) {\n\t\t\t\ttry { u(); } catch { /* best effort */ }\n\t\t\t}\n\t\t\tresolve();\n\t\t};\n\t\tif (signal?.aborted) {\n\t\t\tdone();\n\t\t\treturn;\n\t\t}\n\t\tsignal?.addEventListener(\"abort\", done, { once: true });\n\t\ttry {\n\t\t\tfor (const channel of [...new Set([...WAKE_CHANNELS, ...providerChannels])]) {\n\t\t\t\tunsubs.push(events.on(channel, done));\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tsignal?.removeEventListener(\"abort\", done);\n\t\t\tfor (const unsubscribe of unsubs) {\n\t\t\t\ttry { unsubscribe(); } catch { /* best effort cleanup */ }\n\t\t\t}\n\t\t\treject(error);\n\t\t\treturn;\n\t\t}\n\t\t// Poll-interval fallback so we still reconcile even if no event arrives.\n\t\t// The local signal cancels that fallback timer when an event wakes us first.\n\t\tvoid sleep(ms, wakeController.signal).then(done);\n\t});\n}\n\nfunction matchesId(run: AsyncRunSummary, id: string): boolean {\n\treturn run.id === id || run.id.startsWith(id);\n}\n\nfunction activeDetachedForegroundRuns(params: SubagentWaitParams, deps: SubagentWaitDeps): ForegroundResumeRun[] {\n\tif (!params.id || !deps.state.foregroundRuns) return [];\n\tconst sessionId = deps.state.currentSessionId;\n\tif (!sessionId) return [];\n\treturn [...deps.state.foregroundRuns.values()].filter((run) =>\n\t\t(run.runId === params.id || run.runId.startsWith(params.id!))\n\t\t&& run.sessionId === sessionId\n\t\t&& run.children.some((child) => child.status === \"detached\")\n\t);\n}\n\nfunction summarizeForegroundChildren(run: ForegroundResumeRun, indices: Set<number>): string {\n\tconst counts = new Map<string, number>();\n\tfor (const child of run.children) {\n\t\tif (!indices.has(child.index) || child.status === \"detached\") continue;\n\t\tcounts.set(child.status, (counts.get(child.status) ?? 0) + 1);\n\t}\n\treturn [...counts.entries()].map(([status, count]) => `${count} ${status}`).join(\", \");\n}\n\n/** A running run that has flagged it needs the parent's attention. */\nfunction needsAttention(run: AsyncRunSummary): boolean {\n\treturn run.activityState === \"needs_attention\";\n}\n\nfunction backgroundWorkIdentity(item: RegisteredBackgroundWorkItem): string {\n\treturn `${item.provider}\\0${item.sessionId}\\0${item.id}`;\n}\n\nfunction backgroundWorkForSession(deps: SubagentWaitDeps, nowMs: number): BackgroundWorkSnapshot {\n\tconst sessionId = deps.state.currentSessionId;\n\tif (!sessionId) throw new Error(\"subagent_wait requires an active session identity to scope background work safely.\");\n\treturn deps.backgroundWork?.snapshot(sessionId, nowMs) ?? snapshotBackgroundWork(sessionId, nowMs);\n}\n\n/** Queued/running runs from this session, including runs that need attention. */\nfunction activeRunsForSession(params: SubagentWaitParams, deps: SubagentWaitDeps): AsyncRunSummary[] {\n\tconst asyncDirRoot = deps.asyncDirRoot ?? ASYNC_DIR;\n\tconst resultsDir = deps.resultsDir ?? RESULTS_DIR;\n\tconst runs = listAsyncRuns(asyncDirRoot, {\n\t\tstates: [...ACTIVE_STATES],\n\t\tsessionId: deps.state.currentSessionId ?? undefined,\n\t\tresultsDir,\n\t\tkill: deps.kill,\n\t\tnow: deps.now,\n\t});\n\treturn params.id ? runs.filter((run) => matchesId(run, params.id!)) : runs;\n}\n\n/** Runs (from the initial set) currently flagged needs_attention, for reporting. */\nfunction attentionRunsForSession(params: SubagentWaitParams, deps: SubagentWaitDeps, initialIds: Set<string>): AsyncRunSummary[] {\n\treturn activeRunsForSession(params, deps).filter((run) => needsAttention(run) && initialIds.has(run.id));\n}\n\n/** All runs (any state) for this session, for the final summary. */\nfunction allRunsForSession(params: SubagentWaitParams, deps: SubagentWaitDeps): AsyncRunSummary[] {\n\tconst asyncDirRoot = deps.asyncDirRoot ?? ASYNC_DIR;\n\tconst resultsDir = deps.resultsDir ?? RESULTS_DIR;\n\tconst runs = listAsyncRuns(asyncDirRoot, {\n\t\tsessionId: deps.state.currentSessionId ?? undefined,\n\t\tresultsDir,\n\t\tkill: deps.kill,\n\t\tnow: deps.now,\n\t});\n\treturn params.id ? runs.filter((run) => matchesId(run, params.id!)) : runs;\n}\n\nfunction summarizeTerminalRuns(runs: AsyncRunSummary[], providerFinishedCount = 0): string {\n\tif (runs.length === 0 && providerFinishedCount === 0) return \"\";\n\tconst counts = { complete: 0, failed: 0, paused: 0 } as Record<string, number>;\n\tfor (const run of runs) {\n\t\tif (run.state in counts) counts[run.state] += 1;\n\t}\n\tconst parts: string[] = [];\n\tif (counts.complete) parts.push(`${counts.complete} complete`);\n\tif (counts.failed) parts.push(`${counts.failed} failed`);\n\tif (counts.paused) parts.push(`${counts.paused} paused`);\n\tif (providerFinishedCount > 0) parts.push(`${providerFinishedCount} provider item(s) finished`);\n\treturn parts.join(\", \");\n}\n\nfunction result(text: string, isError = false): AgentToolResult<Details> {\n\treturn {\n\t\tcontent: [{ type: \"text\", text }],\n\t\t...(isError ? { isError: true } : {}),\n\t\tdetails: { mode: \"management\", results: [] },\n\t};\n}\n\nasync function waitForDetachedForegroundRun(\n\trun: ForegroundResumeRun,\n\tsignal: AbortSignal | undefined,\n\tdeps: SubagentWaitDeps,\n\tstartedAt: number,\n\tnow: () => number,\n\tpollIntervalMs: number,\n\ttimeoutMs: number,\n): Promise<AgentToolResult<Details>> {\n\tconst initialDetachedIndices = new Set(run.children.filter((child) => child.status === \"detached\").map((child) => child.index));\n\twhile (true) {\n\t\tif (deps.state.currentSessionId !== run.sessionId) {\n\t\t\treturn result(`Wait stopped because the active session changed while remembered foreground run \"${run.runId}\" was still detached. Return to the originating session to inspect or wait for it.`, true);\n\t\t}\n\t\tconst current = deps.state.foregroundRuns?.get(run.runId);\n\t\tif (!current || current.sessionId !== run.sessionId) {\n\t\t\treturn result(`Remembered foreground run \"${run.runId}\" disappeared before a terminal child result was recorded. Completion cannot be confirmed; do not launch a replacement without checking the originating child session.`, true);\n\t\t}\n\t\tconst pending = current.children.filter((child) => initialDetachedIndices.has(child.index) && child.status === \"detached\");\n\t\tif (pending.length === 0) {\n\t\t\tconst outcome = summarizeForegroundChildren(current, initialDetachedIndices);\n\t\t\treturn result(\n\t\t\t\t`Waited ${formatDuration(now() - startedAt)} for remembered detached foreground run \"${run.runId}\"; done. Outcome: ${outcome || \"no recovered child status\"}. Completion event observed; inspect with subagent({ action: \"status\", id: \"${run.runId}\" }) for recovered output.`,\n\t\t\t);\n\t\t}\n\t\tif (signal?.aborted) {\n\t\t\treturn result(`Wait aborted after ${formatDuration(now() - startedAt)}. Remembered foreground run \"${run.runId}\" remains detached.`, true);\n\t\t}\n\t\tif (now() - startedAt >= timeoutMs) {\n\t\t\treturn result(\n\t\t\t\t`Wait timed out after ${formatDuration(timeoutMs)} with remembered foreground run \"${run.runId}\" still detached. Reply to any pending supervisor request, then call subagent_wait({ id: \"${run.runId}\" }) again or inspect status; do not resume or launch a replacement while it remains detached.`,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\t\tawait waitForWake(pollIntervalMs, signal, deps);\n\t}\n}\n\n/**\n * Block until the targeted async or remembered detached foreground run finishes,\n * the timeout elapses, or the turn is aborted. Resolves with a short\n * human-readable summary either way.\n */\nexport async function waitForSubagents(\n\tparams: SubagentWaitParams,\n\tsignal: AbortSignal | undefined,\n\tdeps: SubagentWaitDeps,\n): Promise<AgentToolResult<Details>> {\n\tif (deps.enabled === false) {\n\t\treturn result(\"subagent_wait is disabled by config.waitTool or PI_SUBAGENT_WAIT_TOOL_ENABLED; returning immediately without blocking background work. Active work keeps going, and you can inspect subagents with subagent({ action: \\\"status\\\" }) or rely on completion notifications.\");\n\t}\n\tif (!deps.state.currentSessionId) {\n\t\treturn result(\"subagent_wait requires an active session identity to scope background work safely.\", true);\n\t}\n\n\tconst now = deps.now ?? Date.now;\n\tconst pollIntervalMs = Math.max(MIN_POLL_INTERVAL_MS, deps.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);\n\tconst timeoutMs = params.timeoutMs !== undefined && params.timeoutMs > 0 ? params.timeoutMs : DEFAULT_TIMEOUT_MS;\n\tconst startedAt = now();\n\tconst waitForAll = params.id ? true : params.all === true;\n\n\tlet active: AsyncRunSummary[];\n\tlet foreground: ForegroundResumeRun[];\n\tlet providerSnapshot: BackgroundWorkSnapshot;\n\ttry {\n\t\tactive = activeRunsForSession(params, deps);\n\t\tforeground = activeDetachedForegroundRuns(params, deps);\n\t\tproviderSnapshot = params.id ? { providers: [], items: [] } : backgroundWorkForSession(deps, startedAt);\n\t} catch (error) {\n\t\treturn result(error instanceof Error ? error.message : String(error), true);\n\t}\n\n\tif (params.id) {\n\t\tconst candidates = [\n\t\t\t...active.map((run) => ({ kind: \"async\" as const, id: run.id, run })),\n\t\t\t...foreground.map((run) => ({ kind: \"foreground\" as const, id: run.runId, run })),\n\t\t];\n\t\tconst exact = candidates.filter((candidate) => candidate.id === params.id);\n\t\tconst matches = exact.length > 0 ? exact : candidates;\n\t\tif (matches.length > 1) {\n\t\t\treturn result(`Ambiguous subagent run id prefix \"${params.id}\" matched ${matches.length} active runs: ${matches.map((candidate) => candidate.id).join(\", \")}. Pass a longer id.`, true);\n\t\t}\n\t\tconst selected = matches[0];\n\t\tif (selected?.kind === \"foreground\") {\n\t\t\treturn waitForDetachedForegroundRun(selected.run, signal, deps, startedAt, now, pollIntervalMs, timeoutMs);\n\t\t}\n\t\tactive = selected?.kind === \"async\" ? [selected.run] : [];\n\t}\n\n\tlet providerActive = providerSnapshot.items;\n\tif (active.length === 0 && providerActive.length === 0) {\n\t\treturn result(params.id\n\t\t\t? `No active run matched \"${params.id}\". Nothing to wait for.`\n\t\t\t: \"No active async runs or registered provider work in this session. Nothing to wait for.\");\n\t}\n\tconst waitParams = params.id ? { ...params, id: active[0]!.id } : params;\n\tconst initialAsyncIds = new Set(active.map((run) => run.id));\n\tconst initialProviderIds = new Set(providerActive.map(backgroundWorkIdentity));\n\tconst initialProviderNames = new Set(providerActive.map((item) => item.provider));\n\tconst initialCount = initialAsyncIds.size + initialProviderIds.size;\n\tconst stopOnAttention = deps.stopOnAttention !== false;\n\tlet attention = active.filter((run) => needsAttention(run));\n\n\tconst isDone = (): boolean => {\n\t\tif (stopOnAttention && attention.some((run) => initialAsyncIds.has(run.id))) return true;\n\t\tconst activeAsyncIds = new Set(active.map((run) => run.id));\n\t\tconst activeProviderIds = new Set(providerActive.map(backgroundWorkIdentity));\n\t\tif (waitForAll) {\n\t\t\treturn [...initialAsyncIds].every((id) => !activeAsyncIds.has(id))\n\t\t\t\t&& [...initialProviderIds].every((id) => !activeProviderIds.has(id));\n\t\t}\n\t\treturn [...initialAsyncIds].some((id) => !activeAsyncIds.has(id))\n\t\t\t|| [...initialProviderIds].some((id) => !activeProviderIds.has(id));\n\t};\n\n\twhile (!isDone()) {\n\t\tconst activeInitialRuns = active.filter((run) => initialAsyncIds.has(run.id));\n\t\tconst activeInitialProviderItems = providerActive.filter((item) => initialProviderIds.has(backgroundWorkIdentity(item)));\n\t\tconst stillActive = [\n\t\t\t...activeInitialRuns.map((run) => `${run.id} (${run.state})`),\n\t\t\t...activeInitialProviderItems.map((item) => `${item.provider}/${item.id}`),\n\t\t].join(\", \");\n\t\tif (signal?.aborted) {\n\t\t\treturn result(`Wait aborted after ${formatDuration(now() - startedAt)}. Still active: ${stillActive}.`, true);\n\t\t}\n\t\tif (now() - startedAt >= timeoutMs) {\n\t\t\treturn result(\n\t\t\t\t`Wait timed out after ${formatDuration(timeoutMs)} with ${activeInitialRuns.length} async run(s) and ${activeInitialProviderItems.length} provider item(s) still active: ${stillActive}. The work keeps going; call subagent_wait again or inspect subagent status.`,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\tawait waitForWake(pollIntervalMs, signal, deps);\n\t\t\tactive = activeRunsForSession(waitParams, deps);\n\t\t\tattention = attentionRunsForSession(waitParams, deps, initialAsyncIds);\n\t\t\tproviderSnapshot = params.id ? providerSnapshot : backgroundWorkForSession(deps, now());\n\t\t\tfor (const provider of initialProviderNames) {\n\t\t\t\tif (!providerSnapshot.providers.includes(provider)) {\n\t\t\t\t\treturn result(`Background-work provider '${provider}' disappeared while subagent_wait was tracking its active work; completion cannot be confirmed.`, true);\n\t\t\t\t}\n\t\t\t}\n\t\t\tproviderActive = providerSnapshot.items;\n\t\t} catch (error) {\n\t\t\treturn result(error instanceof Error ? error.message : String(error), true);\n\t\t}\n\t}\n\n\tlet terminalSummary: string;\n\tlet finishedAsyncCount: number;\n\tlet failedAsyncCount: number;\n\tconst activeProviderIds = new Set(providerActive.map(backgroundWorkIdentity));\n\tconst providerFinishedCount = [...initialProviderIds].filter((id) => !activeProviderIds.has(id)).length;\n\ttry {\n\t\tconst allNow = allRunsForSession(waitParams, deps);\n\t\tconst terminal = allNow.filter((run) => !ACTIVE_STATES.includes(run.state) && initialAsyncIds.has(run.id));\n\t\tfinishedAsyncCount = terminal.length;\n\t\tfailedAsyncCount = terminal.filter((run) => run.state === \"failed\").length;\n\t\tterminalSummary = summarizeTerminalRuns(terminal, providerFinishedCount);\n\t} catch (error) {\n\t\treturn result(error instanceof Error ? error.message : String(error), true);\n\t}\n\n\tconst relevantAttention = attention.filter((run) => initialAsyncIds.has(run.id));\n\tconst attentionNote = relevantAttention.length > 0\n\t\t? ` ${relevantAttention.length} run(s) need attention: ${relevantAttention.map((run) => run.id).join(\", \")} — inspect with subagent({ action: \"status\" }) then nudge/resume/interrupt.`\n\t\t: \"\";\n\tconst stillRunning = active.filter((run) => initialAsyncIds.has(run.id)).length\n\t\t+ providerActive.filter((item) => initialProviderIds.has(backgroundWorkIdentity(item))).length;\n\tconst elapsed = formatDuration(now() - startedAt);\n\tconst outcome = terminalSummary ? ` Outcome: ${terminalSummary}.` : \"\";\n\n\tif (waitForAll) {\n\t\tconst scope = params.id\n\t\t\t? `run \"${params.id}\"`\n\t\t\t: initialProviderIds.size === 0\n\t\t\t\t? `${initialAsyncIds.size} async run(s)`\n\t\t\t\t: `${initialAsyncIds.size} async run(s) and ${initialProviderIds.size} provider item(s)`;\n\t\tconst status = relevantAttention.length > 0 ? \"attention required\" : \"done\";\n\t\treturn result(\n\t\t\t`Waited ${elapsed} for ${scope}; ${status}.${outcome}${attentionNote} Completion/control events have been observed; inspect status if a notification is not visible yet.`,\n\t\t\tdeps.failOnFailedRuns === true && failedAsyncCount > 0,\n\t\t);\n\t}\n\n\tconst finishedCount = finishedAsyncCount + providerFinishedCount;\n\tconst subject = initialProviderIds.size === 0 ? \"run(s)\" : \"item(s)\";\n\tconst remainder = stillRunning > 0\n\t\t? ` ${stillRunning} ${subject} still in flight — call subagent_wait again to catch the next one.`\n\t\t: relevantAttention.length > 0\n\t\t\t? \" No other work is waitable until attention is handled.\"\n\t\t\t: initialProviderIds.size === 0 ? \" No runs remain in flight.\" : \" No work remains in flight.\";\n\tconst progress = relevantAttention.length > 0 && finishedCount === 0\n\t\t? `${relevantAttention.length} of ${initialCount} ${subject} need attention`\n\t\t: `${finishedCount} of ${initialCount} ${subject} finished`;\n\treturn result(\n\t\t`Waited ${elapsed}; ${progress}.${outcome}${attentionNote}${remainder} Relevant completion/control events have been observed; inspect status if a notification is not visible yet.`,\n\t\tdeps.failOnFailedRuns === true && failedAsyncCount > 0,\n\t);\n}\n"]}
1
+ {"version":3,"file":"subagent-wait.js","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\n/**\n * `subagent_wait` tool: block the current turn until outstanding async runs\n * or a named remembered detached foreground run finishes.\n *\n * Background subagent runs are detached. In an interactive session the parent\n * can end its turn and Pi will wake it with a completion notification. That\n * does not work when the parent is a skill that must run to completion, and it\n * cannot work at all non-interactively (`pi -p ...`), where the run is a single\n * turn: once the turn ends there is nothing left to receive the notification.\n *\n * `subagent_wait` closes that gap. It keeps the turn alive until a tracked async\n * run for this session reaches a terminal state (complete / failed / paused),\n * the caller-supplied timeout elapses, or the turn is aborted. Because it awaits\n * inside the turn, the completion the model was told to wait for is actually\n * observed before the tool returns.\n *\n * By default `subagent_wait` returns as soon as ONE run finishes, so a fleet\n * manager can use it in a rolling-replacement loop: launch N workers, wait for\n * the next one to finish, spawn its replacement, then call `subagent_wait`\n * again — keeping N in flight instead of draining to zero between batches.\n * Pass `all: true` to block until every tracked async run is terminal, or `id`\n * to block on one specific async or remembered detached foreground run.\n *\n * `subagent_wait` also returns when a run needs attention — not just on\n * completion. A child that goes idle or blocks for a decision surfaces\n * `needs_attention` (the same signal Pi shows as a control notice and,\n * interactively, wakes the parent with). Since `subagent_wait` is used exactly\n * where there is no next turn to receive that notice, it must break on it too,\n * or a stuck child would stall the loop until the timeout. Attention runs are\n * reported so the caller can inspect / nudge / resume / interrupt them.\n *\n * Wake mechanism: when given Pi's event bus (`deps.events`), `subagent_wait`\n * subscribes to the subagent completion/control channels and wakes the instant\n * any fires, rather than waiting out a fixed poll interval. A poll still runs\n * on the interval as a reconciliation fallback (crashed runners, missed\n * events), and the poll is the source of truth for what actually changed — the\n * event only ends the sleep early. With no bus, `subagent_wait` degrades to pure\n * polling.\n */\n\nimport type { AgentToolResult } from \"@ashx-j/lunr-agent\";\nimport {\n\tlistBackgroundWorkWakeChannels,\n\tsnapshotBackgroundWork,\n\ttype BackgroundWorkSnapshot,\n\ttype RegisteredBackgroundWorkItem,\n} from \"../../api/background-work.ts\";\nimport { listAsyncRuns, type AsyncRunSummary } from \"./async-status.ts\";\nimport { hasPendingBlockingSupervisorRequest } from \"../../intercom/native-supervisor-channel.ts\";\nimport {\n\tASYNC_DIR,\n\tINTERCOM_DETACH_REQUEST_EVENT,\n\tRESULTS_DIR,\n\tSUBAGENT_ASYNC_COMPLETE_EVENT,\n\tSUBAGENT_FOREGROUND_COMPLETE_EVENT,\n\tSUBAGENT_CONTROL_EVENT,\n\tSUBAGENT_CONTROL_INTERCOM_EVENT,\n\tSUBAGENT_RESULT_INTERCOM_EVENT,\n\ttype Details,\n\ttype ForegroundResumeRun,\n\ttype SubagentState,\n} from \"../../shared/types.ts\";\nimport { formatDuration } from \"../../shared/formatters.ts\";\nimport { reconcileAsyncQuestion } from \"../../intercom/supervisor-ask.ts\";\nimport {\n\tclaimQuestionNotification,\n\tfindSupervisorQuestion,\n\tformatSupervisorQuestionAnswer,\n\tregisterQuestionWait,\n\tsupervisorQuestionIsTerminal,\n\tsupervisorQuestionPublicState,\n\tSUBAGENT_QUESTION_EVENT,\n} from \"../../intercom/supervisor-questions.ts\";\nexport { WAIT_TOOL_ENABLED_ENV, resolveWaitToolConfig, type ResolvedWaitToolConfig } from \"./wait-config.ts\";\n\n/** States that mean a run is still in flight (not yet resolved). */\nconst ACTIVE_STATES: ReadonlyArray<AsyncRunSummary[\"state\"]> = [\"queued\", \"running\"];\n\nconst DEFAULT_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes\nconst MIN_POLL_INTERVAL_MS = 250;\nconst DEFAULT_POLL_INTERVAL_MS = 1000;\n\nexport interface SubagentWaitParams {\n\t/** Optional run id/prefix to wait for. When omitted, waits across every active run in this session. */\n\tid?: string;\n\t/** Optional supervisor question id from subagent_supervisor action='ask'. */\n\tquestionId?: string;\n\t/**\n\t * When true, block until EVERY active run in this session (or matching `id`)\n\t * is terminal. Default false: return as soon as the first run finishes, so a\n\t * fleet manager can spawn a replacement and wait again. Ignored when `id`\n\t * or `questionId` targets a single item.\n\t */\n\tall?: boolean;\n\t/** Give up after this many milliseconds. Defaults to 30 minutes. */\n\ttimeoutMs?: number;\n}\n\n/** Minimal event-bus surface wait subscribes to (matches pi.events). */\nexport interface WaitEventBus {\n\ton(channel: string, handler: (data: unknown) => void): () => void;\n}\n\nexport interface SubagentWaitDeps {\n\tstate: SubagentState;\n\tasyncDirRoot?: string;\n\tresultsDir?: string;\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean;\n\tnow?: () => number;\n\tpollIntervalMs?: number;\n\t/** False makes the tool return immediately without blocking active async runs. */\n\tenabled?: boolean;\n\t/** Injectable sleep for tests. */\n\tsleep?: (ms: number, signal?: AbortSignal) => Promise<void>;\n\t/** Internal auto-drain mode waits through needs-attention states. */\n\tstopOnAttention?: boolean;\n\t/** Internal auto-drain mode surfaces failed terminal subagent runs as errors. */\n\tfailOnFailedRuns?: boolean;\n\t/** Injectable provider protocol surfaces for deterministic tests. */\n\tbackgroundWork?: {\n\t\tsnapshot(sessionId: string, nowMs: number): BackgroundWorkSnapshot;\n\t\twakeChannels(): readonly string[];\n\t};\n\t/**\n\t * Optional event bus (pi.events). When provided, wait wakes immediately on a\n\t * subagent completion/control event instead of waiting out the poll interval;\n\t * the poll then remains as a reconciliation fallback (crashed runners, missed\n\t * events). Omit in tests that want pure poll behavior.\n\t */\n\tevents?: WaitEventBus;\n}\n\n/** Bus channels that indicate a run changed state or needs attention. */\nconst WAKE_CHANNELS = [\n\tSUBAGENT_ASYNC_COMPLETE_EVENT,\n\tSUBAGENT_FOREGROUND_COMPLETE_EVENT,\n\tSUBAGENT_CONTROL_EVENT,\n\tSUBAGENT_CONTROL_INTERCOM_EVENT,\n\tSUBAGENT_RESULT_INTERCOM_EVENT,\n\tINTERCOM_DETACH_REQUEST_EVENT,\n\tSUBAGENT_QUESTION_EVENT,\n];\n\nfunction defaultSleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve) => {\n\t\tif (signal?.aborted) {\n\t\t\tresolve();\n\t\t\treturn;\n\t\t}\n\t\tconst timer = setTimeout(() => {\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve();\n\t\t}, ms);\n\t\tconst onAbort = () => {\n\t\t\tclearTimeout(timer);\n\t\t\tresolve();\n\t\t};\n\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t});\n}\n\n/**\n * Sleep up to `ms`, but wake early if a subagent event fires on the bus (or the\n * turn aborts). Returns when the first of those happens. With no bus this is a\n * plain sleep, so the poll interval alone drives progress.\n */\nfunction waitForWake(ms: number, signal: AbortSignal | undefined, deps: SubagentWaitDeps): Promise<void> {\n\tconst sleep = deps.sleep ?? defaultSleep;\n\tconst events = deps.events;\n\tif (!events) return sleep(ms, signal);\n\tconst providerChannels = deps.backgroundWork?.wakeChannels() ?? listBackgroundWorkWakeChannels();\n\treturn new Promise((resolve, reject) => {\n\t\tlet settled = false;\n\t\tconst unsubs: Array<() => void> = [];\n\t\tconst wakeController = new AbortController();\n\t\tconst done = () => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\twakeController.abort();\n\t\t\tsignal?.removeEventListener(\"abort\", done);\n\t\t\tfor (const u of unsubs) {\n\t\t\t\ttry { u(); } catch { /* best effort */ }\n\t\t\t}\n\t\t\tresolve();\n\t\t};\n\t\tif (signal?.aborted) {\n\t\t\tdone();\n\t\t\treturn;\n\t\t}\n\t\tsignal?.addEventListener(\"abort\", done, { once: true });\n\t\ttry {\n\t\t\tfor (const channel of [...new Set([...WAKE_CHANNELS, ...providerChannels])]) {\n\t\t\t\tunsubs.push(events.on(channel, done));\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tsignal?.removeEventListener(\"abort\", done);\n\t\t\tfor (const unsubscribe of unsubs) {\n\t\t\t\ttry { unsubscribe(); } catch { /* best effort cleanup */ }\n\t\t\t}\n\t\t\treject(error);\n\t\t\treturn;\n\t\t}\n\t\t// Poll-interval fallback so we still reconcile even if no event arrives.\n\t\t// The local signal cancels that fallback timer when an event wakes us first.\n\t\tvoid sleep(ms, wakeController.signal).then(done);\n\t});\n}\n\nfunction matchesId(run: AsyncRunSummary, id: string): boolean {\n\treturn run.id === id || run.id.startsWith(id);\n}\n\nfunction activeDetachedForegroundRuns(params: SubagentWaitParams, deps: SubagentWaitDeps): ForegroundResumeRun[] {\n\tif (!params.id || !deps.state.foregroundRuns) return [];\n\tconst sessionId = deps.state.currentSessionId;\n\tif (!sessionId) return [];\n\treturn [...deps.state.foregroundRuns.values()].filter((run) =>\n\t\t(run.runId === params.id || run.runId.startsWith(params.id!))\n\t\t&& run.sessionId === sessionId\n\t\t&& run.children.some((child) => child.status === \"detached\")\n\t);\n}\n\nfunction summarizeForegroundChildren(run: ForegroundResumeRun, indices: Set<number>): string {\n\tconst counts = new Map<string, number>();\n\tfor (const child of run.children) {\n\t\tif (!indices.has(child.index) || child.status === \"detached\") continue;\n\t\tcounts.set(child.status, (counts.get(child.status) ?? 0) + 1);\n\t}\n\treturn [...counts.entries()].map(([status, count]) => `${count} ${status}`).join(\", \");\n}\n\n/** A running run that has flagged it needs the parent's attention. */\nfunction needsAttention(run: AsyncRunSummary, sessionId?: string | null): boolean {\n\treturn run.activityState === \"needs_attention\"\n\t\t|| hasPendingBlockingSupervisorRequest(run.id, sessionId);\n}\n\nfunction backgroundWorkIdentity(item: RegisteredBackgroundWorkItem): string {\n\treturn `${item.provider}\\0${item.sessionId}\\0${item.id}`;\n}\n\nfunction backgroundWorkForSession(deps: SubagentWaitDeps, nowMs: number): BackgroundWorkSnapshot {\n\tconst sessionId = deps.state.currentSessionId;\n\tif (!sessionId) throw new Error(\"subagent_wait requires an active session identity to scope background work safely.\");\n\treturn deps.backgroundWork?.snapshot(sessionId, nowMs) ?? snapshotBackgroundWork(sessionId, nowMs);\n}\n\n/** Queued/running runs from this session, including runs that need attention. */\nfunction activeRunsForSession(params: SubagentWaitParams, deps: SubagentWaitDeps): AsyncRunSummary[] {\n\tconst asyncDirRoot = deps.asyncDirRoot ?? ASYNC_DIR;\n\tconst resultsDir = deps.resultsDir ?? RESULTS_DIR;\n\tconst runs = listAsyncRuns(asyncDirRoot, {\n\t\tstates: [...ACTIVE_STATES],\n\t\tsessionId: deps.state.currentSessionId ?? undefined,\n\t\tresultsDir,\n\t\tkill: deps.kill,\n\t\tnow: deps.now,\n\t});\n\treturn params.id ? runs.filter((run) => matchesId(run, params.id!)) : runs;\n}\n\n/** Runs (from the initial set) currently flagged needs_attention, for reporting. */\nfunction attentionRunsForSession(params: SubagentWaitParams, deps: SubagentWaitDeps, initialIds: Set<string>): AsyncRunSummary[] {\n\treturn activeRunsForSession(params, deps).filter((run) => needsAttention(run, deps.state.currentSessionId) && initialIds.has(run.id));\n}\n\n/** All runs (any state) for this session, for the final summary. */\nfunction allRunsForSession(params: SubagentWaitParams, deps: SubagentWaitDeps): AsyncRunSummary[] {\n\tconst asyncDirRoot = deps.asyncDirRoot ?? ASYNC_DIR;\n\tconst resultsDir = deps.resultsDir ?? RESULTS_DIR;\n\tconst runs = listAsyncRuns(asyncDirRoot, {\n\t\tsessionId: deps.state.currentSessionId ?? undefined,\n\t\tresultsDir,\n\t\tkill: deps.kill,\n\t\tnow: deps.now,\n\t});\n\treturn params.id ? runs.filter((run) => matchesId(run, params.id!)) : runs;\n}\n\nfunction summarizeTerminalRuns(runs: AsyncRunSummary[], providerFinishedCount = 0): string {\n\tif (runs.length === 0 && providerFinishedCount === 0) return \"\";\n\tconst counts = { complete: 0, failed: 0, paused: 0 } as Record<string, number>;\n\tfor (const run of runs) {\n\t\tif (run.state in counts) counts[run.state] += 1;\n\t}\n\tconst parts: string[] = [];\n\tif (counts.complete) parts.push(`${counts.complete} complete`);\n\tif (counts.failed) parts.push(`${counts.failed} failed`);\n\tif (counts.paused) parts.push(`${counts.paused} paused`);\n\tif (providerFinishedCount > 0) parts.push(`${providerFinishedCount} provider item(s) finished`);\n\treturn parts.join(\", \");\n}\n\nfunction result(text: string, isError = false): AgentToolResult<Details> {\n\treturn {\n\t\tcontent: [{ type: \"text\", text }],\n\t\t...(isError ? { isError: true } : {}),\n\t\tdetails: { mode: \"management\", results: [] },\n\t};\n}\n\nasync function waitForDetachedForegroundRun(\n\trun: ForegroundResumeRun,\n\tsignal: AbortSignal | undefined,\n\tdeps: SubagentWaitDeps,\n\tstartedAt: number,\n\tnow: () => number,\n\tpollIntervalMs: number,\n\ttimeoutMs: number,\n): Promise<AgentToolResult<Details>> {\n\tconst initialDetachedIndices = new Set(run.children.filter((child) => child.status === \"detached\").map((child) => child.index));\n\twhile (true) {\n\t\tif (deps.state.currentSessionId !== run.sessionId) {\n\t\t\treturn result(`Wait stopped because the active session changed while remembered foreground run \"${run.runId}\" was still detached. Return to the originating session to inspect or wait for it.`, true);\n\t\t}\n\t\tconst current = deps.state.foregroundRuns?.get(run.runId);\n\t\tif (!current || current.sessionId !== run.sessionId) {\n\t\t\treturn result(`Remembered foreground run \"${run.runId}\" disappeared before a terminal child result was recorded. Completion cannot be confirmed; do not launch a replacement without checking the originating child session.`, true);\n\t\t}\n\t\tconst pending = current.children.filter((child) => initialDetachedIndices.has(child.index) && child.status === \"detached\");\n\t\tif (pending.length === 0) {\n\t\t\tconst outcome = summarizeForegroundChildren(current, initialDetachedIndices);\n\t\t\treturn result(\n\t\t\t\t`Waited ${formatDuration(now() - startedAt)} for remembered detached foreground run \"${run.runId}\"; done. Outcome: ${outcome || \"no recovered child status\"}. Completion event observed; inspect with subagent({ action: \"status\", id: \"${run.runId}\" }) for recovered output.`,\n\t\t\t);\n\t\t}\n\t\tif (signal?.aborted) {\n\t\t\treturn result(`Wait aborted after ${formatDuration(now() - startedAt)}. Remembered foreground run \"${run.runId}\" remains detached.`, true);\n\t\t}\n\t\tif (now() - startedAt >= timeoutMs) {\n\t\t\treturn result(\n\t\t\t\t`Wait timed out after ${formatDuration(timeoutMs)} with remembered foreground run \"${run.runId}\" still detached. Reply to any pending supervisor request, then call subagent_wait({ id: \"${run.runId}\" }) again or inspect status; do not resume or launch a replacement while it remains detached.`,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\t\tawait waitForWake(pollIntervalMs, signal, deps);\n\t}\n}\n\n/**\n * Block until the targeted async or remembered detached foreground run finishes,\n * the timeout elapses, or the turn is aborted. Resolves with a short\n * human-readable summary either way.\n */\nasync function waitForSupervisorQuestion(\n\tquestionId: string,\n\tsignal: AbortSignal | undefined,\n\tdeps: SubagentWaitDeps,\n\tstartedAt: number,\n\tnow: () => number,\n\tpollIntervalMs: number,\n\ttimeoutMs: number,\n): Promise<AgentToolResult<Details>> {\n\tconst sessionId = deps.state.currentSessionId;\n\tif (!sessionId) return result(\"subagent_wait requires an active session identity to scope background work safely.\", true);\n\tconst releaseWait = registerQuestionWait([questionId]);\n\ttry {\n\t\twhile (true) {\n\t\t\tconst found = findSupervisorQuestion(questionId);\n\t\t\tif (!found) {\n\t\t\t\treturn result(`No supervisor question matched \"${questionId}\".`, true);\n\t\t\t}\n\t\t\tconst { channelDir } = found;\n\t\t\tlet { question } = found;\n\t\t\tif (question.parentSessionId !== sessionId || deps.state.currentSessionId !== sessionId) {\n\t\t\t\treturn result(`Supervisor question \"${questionId}\" belongs to another session.`, true);\n\t\t\t}\n\t\t\tif ((deps.state.sessionGeneration ?? 0) !== question.parentGeneration) {\n\t\t\t\treturn result(`Supervisor question \"${questionId}\" was cancelled by a session replacement.`, true);\n\t\t\t}\n\t\t\tquestion = reconcileAsyncQuestion(channelDir, question, deps.state);\n\t\t\tif (supervisorQuestionIsTerminal(question)) {\n\t\t\t\tclaimQuestionNotification(channelDir, question.id);\n\t\t\t\tconst state = supervisorQuestionPublicState(question);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: formatSupervisorQuestionAnswer(question) }],\n\t\t\t\t\t...(state === \"answered\" ? {} : { isError: true }),\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tmode: \"management\",\n\t\t\t\t\t\tresults: [],\n\t\t\t\t\t\tquestionId: question.id,\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\trunId: question.runId,\n\t\t\t\t\t\tanswered: state === \"answered\",\n\t\t\t\t\t\tdelivered: Boolean(question.deliveredAt),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (signal?.aborted) {\n\t\t\t\treturn result(`Wait aborted after ${formatDuration(now() - startedAt)} for supervisor question \"${questionId}\".`, true);\n\t\t\t}\n\t\t\tif (now() - startedAt >= timeoutMs) {\n\t\t\t\treturn result(`Wait timed out after ${formatDuration(timeoutMs)} for supervisor question \"${questionId}\". The question remains pending until answered, expired, or cancelled.`, true);\n\t\t\t}\n\t\t\tawait waitForWake(pollIntervalMs, signal, deps);\n\t\t}\n\t} finally {\n\t\treleaseWait();\n\t}\n}\n\nexport async function waitForSubagents(\n\tparams: SubagentWaitParams,\n\tsignal: AbortSignal | undefined,\n\tdeps: SubagentWaitDeps,\n): Promise<AgentToolResult<Details>> {\n\tif (deps.enabled === false) {\n\t\treturn result(\"subagent_wait is disabled by config.waitTool or PI_SUBAGENT_WAIT_TOOL_ENABLED; returning immediately without blocking background work. Active work keeps going, and you can inspect subagents with subagent({ action: \\\"status\\\" }) or rely on completion notifications.\");\n\t}\n\tif (!deps.state.currentSessionId) {\n\t\treturn result(\"subagent_wait requires an active session identity to scope background work safely.\", true);\n\t}\n\n\tconst now = deps.now ?? Date.now;\n\tconst pollIntervalMs = Math.max(MIN_POLL_INTERVAL_MS, deps.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);\n\tconst timeoutMs = params.timeoutMs !== undefined && params.timeoutMs > 0 ? params.timeoutMs : DEFAULT_TIMEOUT_MS;\n\tconst startedAt = now();\n\tif (params.questionId?.trim()) {\n\t\treturn waitForSupervisorQuestion(params.questionId.trim(), signal, deps, startedAt, now, pollIntervalMs, timeoutMs);\n\t}\n\tconst waitForAll = params.id ? true : params.all === true;\n\n\tlet active: AsyncRunSummary[];\n\tlet foreground: ForegroundResumeRun[];\n\tlet providerSnapshot: BackgroundWorkSnapshot;\n\ttry {\n\t\tactive = activeRunsForSession(params, deps);\n\t\tforeground = activeDetachedForegroundRuns(params, deps);\n\t\tproviderSnapshot = params.id ? { providers: [], items: [] } : backgroundWorkForSession(deps, startedAt);\n\t} catch (error) {\n\t\treturn result(error instanceof Error ? error.message : String(error), true);\n\t}\n\n\tif (params.id) {\n\t\tconst candidates = [\n\t\t\t...active.map((run) => ({ kind: \"async\" as const, id: run.id, run })),\n\t\t\t...foreground.map((run) => ({ kind: \"foreground\" as const, id: run.runId, run })),\n\t\t];\n\t\tconst exact = candidates.filter((candidate) => candidate.id === params.id);\n\t\tconst matches = exact.length > 0 ? exact : candidates;\n\t\tif (matches.length > 1) {\n\t\t\treturn result(`Ambiguous subagent run id prefix \"${params.id}\" matched ${matches.length} active runs: ${matches.map((candidate) => candidate.id).join(\", \")}. Pass a longer id.`, true);\n\t\t}\n\t\tconst selected = matches[0];\n\t\tif (selected?.kind === \"foreground\") {\n\t\t\treturn waitForDetachedForegroundRun(selected.run, signal, deps, startedAt, now, pollIntervalMs, timeoutMs);\n\t\t}\n\t\tactive = selected?.kind === \"async\" ? [selected.run] : [];\n\t}\n\n\tlet providerActive = providerSnapshot.items;\n\tif (active.length === 0 && providerActive.length === 0) {\n\t\treturn result(params.id\n\t\t\t? `No active run matched \"${params.id}\". Nothing to wait for.`\n\t\t\t: \"No active async runs or registered provider work in this session. Nothing to wait for.\");\n\t}\n\tconst waitParams = params.id ? { ...params, id: active[0]!.id } : params;\n\tconst initialAsyncIds = new Set(active.map((run) => run.id));\n\tconst initialProviderIds = new Set(providerActive.map(backgroundWorkIdentity));\n\tconst initialProviderNames = new Set(providerActive.map((item) => item.provider));\n\tconst initialCount = initialAsyncIds.size + initialProviderIds.size;\n\tconst stopOnAttention = deps.stopOnAttention !== false;\n\tlet attention = active.filter((run) => needsAttention(run, deps.state.currentSessionId));\n\n\tconst isDone = (): boolean => {\n\t\tif (stopOnAttention && attention.some((run) => initialAsyncIds.has(run.id))) return true;\n\t\tconst activeAsyncIds = new Set(active.map((run) => run.id));\n\t\tconst activeProviderIds = new Set(providerActive.map(backgroundWorkIdentity));\n\t\tif (waitForAll) {\n\t\t\treturn [...initialAsyncIds].every((id) => !activeAsyncIds.has(id))\n\t\t\t\t&& [...initialProviderIds].every((id) => !activeProviderIds.has(id));\n\t\t}\n\t\treturn [...initialAsyncIds].some((id) => !activeAsyncIds.has(id))\n\t\t\t|| [...initialProviderIds].some((id) => !activeProviderIds.has(id));\n\t};\n\n\twhile (!isDone()) {\n\t\tconst activeInitialRuns = active.filter((run) => initialAsyncIds.has(run.id));\n\t\tconst activeInitialProviderItems = providerActive.filter((item) => initialProviderIds.has(backgroundWorkIdentity(item)));\n\t\tconst stillActive = [\n\t\t\t...activeInitialRuns.map((run) => `${run.id} (${run.state})`),\n\t\t\t...activeInitialProviderItems.map((item) => `${item.provider}/${item.id}`),\n\t\t].join(\", \");\n\t\tif (signal?.aborted) {\n\t\t\treturn result(`Wait aborted after ${formatDuration(now() - startedAt)}. Still active: ${stillActive}.`, true);\n\t\t}\n\t\tif (now() - startedAt >= timeoutMs) {\n\t\t\treturn result(\n\t\t\t\t`Wait timed out after ${formatDuration(timeoutMs)} with ${activeInitialRuns.length} async run(s) and ${activeInitialProviderItems.length} provider item(s) still active: ${stillActive}. The work keeps going; call subagent_wait again or inspect subagent status.`,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\tawait waitForWake(pollIntervalMs, signal, deps);\n\t\t\tactive = activeRunsForSession(waitParams, deps);\n\t\t\tattention = attentionRunsForSession(waitParams, deps, initialAsyncIds);\n\t\t\tproviderSnapshot = params.id ? providerSnapshot : backgroundWorkForSession(deps, now());\n\t\t\tfor (const provider of initialProviderNames) {\n\t\t\t\tif (!providerSnapshot.providers.includes(provider)) {\n\t\t\t\t\treturn result(`Background-work provider '${provider}' disappeared while subagent_wait was tracking its active work; completion cannot be confirmed.`, true);\n\t\t\t\t}\n\t\t\t}\n\t\t\tproviderActive = providerSnapshot.items;\n\t\t} catch (error) {\n\t\t\treturn result(error instanceof Error ? error.message : String(error), true);\n\t\t}\n\t}\n\n\tlet terminalSummary: string;\n\tlet finishedAsyncCount: number;\n\tlet failedAsyncCount: number;\n\tconst activeProviderIds = new Set(providerActive.map(backgroundWorkIdentity));\n\tconst providerFinishedCount = [...initialProviderIds].filter((id) => !activeProviderIds.has(id)).length;\n\ttry {\n\t\tconst allNow = allRunsForSession(waitParams, deps);\n\t\tconst terminal = allNow.filter((run) => !ACTIVE_STATES.includes(run.state) && initialAsyncIds.has(run.id));\n\t\tfinishedAsyncCount = terminal.length;\n\t\tfailedAsyncCount = terminal.filter((run) => run.state === \"failed\").length;\n\t\tterminalSummary = summarizeTerminalRuns(terminal, providerFinishedCount);\n\t} catch (error) {\n\t\treturn result(error instanceof Error ? error.message : String(error), true);\n\t}\n\n\tconst relevantAttention = attention.filter((run) => initialAsyncIds.has(run.id));\n\tconst attentionNote = relevantAttention.length > 0\n\t\t? ` ${relevantAttention.length} run(s) need attention: ${relevantAttention.map((run) => run.id).join(\", \")} — inspect with subagent({ action: \"status\" }) then nudge/resume/interrupt.`\n\t\t: \"\";\n\tconst stillRunning = active.filter((run) => initialAsyncIds.has(run.id)).length\n\t\t+ providerActive.filter((item) => initialProviderIds.has(backgroundWorkIdentity(item))).length;\n\tconst elapsed = formatDuration(now() - startedAt);\n\tconst outcome = terminalSummary ? ` Outcome: ${terminalSummary}.` : \"\";\n\n\tif (waitForAll) {\n\t\tconst scope = params.id\n\t\t\t? `run \"${params.id}\"`\n\t\t\t: initialProviderIds.size === 0\n\t\t\t\t? `${initialAsyncIds.size} async run(s)`\n\t\t\t\t: `${initialAsyncIds.size} async run(s) and ${initialProviderIds.size} provider item(s)`;\n\t\tconst status = relevantAttention.length > 0 ? \"attention required\" : \"done\";\n\t\treturn result(\n\t\t\t`Waited ${elapsed} for ${scope}; ${status}.${outcome}${attentionNote} Completion/control events have been observed; inspect status if a notification is not visible yet.`,\n\t\t\tdeps.failOnFailedRuns === true && failedAsyncCount > 0,\n\t\t);\n\t}\n\n\tconst finishedCount = finishedAsyncCount + providerFinishedCount;\n\tconst subject = initialProviderIds.size === 0 ? \"run(s)\" : \"item(s)\";\n\tconst remainder = stillRunning > 0\n\t\t? ` ${stillRunning} ${subject} still in flight — call subagent_wait again to catch the next one.`\n\t\t: relevantAttention.length > 0\n\t\t\t? \" No other work is waitable until attention is handled.\"\n\t\t\t: initialProviderIds.size === 0 ? \" No runs remain in flight.\" : \" No work remains in flight.\";\n\tconst progress = relevantAttention.length > 0 && finishedCount === 0\n\t\t? `${relevantAttention.length} of ${initialCount} ${subject} need attention`\n\t\t: `${finishedCount} of ${initialCount} ${subject} finished`;\n\treturn result(\n\t\t`Waited ${elapsed}; ${progress}.${outcome}${attentionNote}${remainder} Relevant completion/control events have been observed; inspect status if a notification is not visible yet.`,\n\t\tdeps.failOnFailedRuns === true && failedAsyncCount > 0,\n\t);\n}\n"]}
@@ -1,8 +1,21 @@
1
- interface AsyncOverrideParams {
1
+ interface AsyncLaunchParams {
2
+ task?: unknown;
3
+ tasks?: unknown[];
4
+ chain?: unknown[];
5
+ action?: unknown;
2
6
  async?: boolean;
3
7
  clarify?: boolean;
4
8
  foregroundOnly?: boolean;
5
9
  }
6
- export declare function applyForceTopLevelAsyncOverride<T extends AsyncOverrideParams>(params: T, depth: number, forceTopLevelAsync: boolean): T;
10
+ interface LegacyAsyncLaunchConfig {
11
+ asyncByDefault?: boolean;
12
+ forceTopLevelAsync?: boolean;
13
+ }
14
+ export declare function normalizeAsyncLaunchConfig<T extends LegacyAsyncLaunchConfig>(config: T): T & {
15
+ asyncByDefault: true;
16
+ forceTopLevelAsync: false;
17
+ };
18
+ export declare function subagentLaunchRunsAsync(params: AsyncLaunchParams): boolean;
19
+ export declare function isAsyncSubagentExecution(params: AsyncLaunchParams): boolean;
7
20
  export {};
8
21
  //# sourceMappingURL=top-level-async.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"top-level-async.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/top-level-async.ts"],"names":[],"mappings":"AACA,UAAU,mBAAmB;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,+BAA+B,CAAC,CAAC,SAAS,mBAAmB,EAC5E,MAAM,EAAE,CAAC,EACT,KAAK,EAAE,MAAM,EACb,kBAAkB,EAAE,OAAO,GACzB,CAAC,CAGH","sourcesContent":["// @ts-nocheck\ninterface AsyncOverrideParams {\n\tasync?: boolean;\n\tclarify?: boolean;\n\tforegroundOnly?: boolean;\n}\n\nexport function applyForceTopLevelAsyncOverride<T extends AsyncOverrideParams>(\n\tparams: T,\n\tdepth: number,\n\tforceTopLevelAsync: boolean,\n): T {\n\tif (params.foregroundOnly || !(depth === 0 && forceTopLevelAsync)) return params;\n\treturn { ...params, async: true, clarify: false };\n}\n"]}
1
+ {"version":3,"file":"top-level-async.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/top-level-async.ts"],"names":[],"mappings":"AACA,UAAU,iBAAiB;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,UAAU,uBAAuB;IAChC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,uBAAuB,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG;IAC7F,cAAc,EAAE,IAAI,CAAC;IACrB,kBAAkB,EAAE,KAAK,CAAC;CAC1B,CAEA;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAG1E;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAI3E","sourcesContent":["// @ts-nocheck\ninterface AsyncLaunchParams {\n\ttask?: unknown;\n\ttasks?: unknown[];\n\tchain?: unknown[];\n\taction?: unknown;\n\tasync?: boolean;\n\tclarify?: boolean;\n\tforegroundOnly?: boolean;\n}\n\ninterface LegacyAsyncLaunchConfig {\n\tasyncByDefault?: boolean;\n\tforceTopLevelAsync?: boolean;\n}\n\nexport function normalizeAsyncLaunchConfig<T extends LegacyAsyncLaunchConfig>(config: T): T & {\n\tasyncByDefault: true;\n\tforceTopLevelAsync: false;\n} {\n\treturn { ...config, asyncByDefault: true, forceTopLevelAsync: false };\n}\n\nexport function subagentLaunchRunsAsync(params: AsyncLaunchParams): boolean {\n\tif (params.foregroundOnly === true || params.clarify === true || params.async === false) return false;\n\treturn true;\n}\n\nexport function isAsyncSubagentExecution(params: AsyncLaunchParams): boolean {\n\tif (params.action) return false;\n\tif (!params.task && !params.tasks?.length && !params.chain?.length) return false;\n\treturn subagentLaunchRunsAsync(params);\n}\n"]}
@@ -1,6 +1,16 @@
1
- export function applyForceTopLevelAsyncOverride(params, depth, forceTopLevelAsync) {
2
- if (params.foregroundOnly || !(depth === 0 && forceTopLevelAsync))
3
- return params;
4
- return { ...params, async: true, clarify: false };
1
+ export function normalizeAsyncLaunchConfig(config) {
2
+ return { ...config, asyncByDefault: true, forceTopLevelAsync: false };
3
+ }
4
+ export function subagentLaunchRunsAsync(params) {
5
+ if (params.foregroundOnly === true || params.clarify === true || params.async === false)
6
+ return false;
7
+ return true;
8
+ }
9
+ export function isAsyncSubagentExecution(params) {
10
+ if (params.action)
11
+ return false;
12
+ if (!params.task && !params.tasks?.length && !params.chain?.length)
13
+ return false;
14
+ return subagentLaunchRunsAsync(params);
5
15
  }
6
16
  //# sourceMappingURL=top-level-async.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"top-level-async.js","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/top-level-async.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,+BAA+B,CAC9C,MAAS,EACT,KAAa,EACb,kBAA2B,EACvB;IACJ,IAAI,MAAM,CAAC,cAAc,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,kBAAkB,CAAC;QAAE,OAAO,MAAM,CAAC;IACjF,OAAO,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAAA,CAClD","sourcesContent":["// @ts-nocheck\ninterface AsyncOverrideParams {\n\tasync?: boolean;\n\tclarify?: boolean;\n\tforegroundOnly?: boolean;\n}\n\nexport function applyForceTopLevelAsyncOverride<T extends AsyncOverrideParams>(\n\tparams: T,\n\tdepth: number,\n\tforceTopLevelAsync: boolean,\n): T {\n\tif (params.foregroundOnly || !(depth === 0 && forceTopLevelAsync)) return params;\n\treturn { ...params, async: true, clarify: false };\n}\n"]}
1
+ {"version":3,"file":"top-level-async.js","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/top-level-async.ts"],"names":[],"mappings":"AAgBA,MAAM,UAAU,0BAA0B,CAAoC,MAAS,EAGrF;IACD,OAAO,EAAE,GAAG,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC;AAAA,CACtE;AAED,MAAM,UAAU,uBAAuB,CAAC,MAAyB,EAAW;IAC3E,IAAI,MAAM,CAAC,cAAc,KAAK,IAAI,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IACtG,OAAO,IAAI,CAAC;AAAA,CACZ;AAED,MAAM,UAAU,wBAAwB,CAAC,MAAyB,EAAW;IAC5E,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAChC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM;QAAE,OAAO,KAAK,CAAC;IACjF,OAAO,uBAAuB,CAAC,MAAM,CAAC,CAAC;AAAA,CACvC","sourcesContent":["// @ts-nocheck\ninterface AsyncLaunchParams {\n\ttask?: unknown;\n\ttasks?: unknown[];\n\tchain?: unknown[];\n\taction?: unknown;\n\tasync?: boolean;\n\tclarify?: boolean;\n\tforegroundOnly?: boolean;\n}\n\ninterface LegacyAsyncLaunchConfig {\n\tasyncByDefault?: boolean;\n\tforceTopLevelAsync?: boolean;\n}\n\nexport function normalizeAsyncLaunchConfig<T extends LegacyAsyncLaunchConfig>(config: T): T & {\n\tasyncByDefault: true;\n\tforceTopLevelAsync: false;\n} {\n\treturn { ...config, asyncByDefault: true, forceTopLevelAsync: false };\n}\n\nexport function subagentLaunchRunsAsync(params: AsyncLaunchParams): boolean {\n\tif (params.foregroundOnly === true || params.clarify === true || params.async === false) return false;\n\treturn true;\n}\n\nexport function isAsyncSubagentExecution(params: AsyncLaunchParams): boolean {\n\tif (params.action) return false;\n\tif (!params.task && !params.tasks?.length && !params.chain?.length) return false;\n\treturn subagentLaunchRunsAsync(params);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"wait-tool.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/wait-tool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,iCAAiC,CAAC;AAEpF,OAAO,KAAK,EAAW,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGpE,wBAAgB,gBAAgB,CAC/B,EAAE,EAAE,YAAY,EAChB,KAAK,EAAE,aAAa,EACpB,OAAO,UAAkC,EACzC,sBAAsB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GAC9D,IAAI,CAuBN","sourcesContent":["// @ts-nocheck\nimport type { ExtensionAPI, ToolDefinition } from \"@ashx-j/lunr\";\nimport { SubagentWaitParams } from \"../../extension/schemas.ts\";\nimport type { Details, SubagentState } from \"../../shared/types.ts\";\nimport { resolveWaitToolConfig, waitForSubagents } from \"./subagent-wait.ts\";\n\nexport function registerWaitTool(\n\tpi: ExtensionAPI,\n\tstate: SubagentState,\n\tenabled = resolveWaitToolConfig().enabled,\n\twaitForPendingLaunches?: (signal?: AbortSignal) => Promise<void>,\n): void {\n\tconst tool: ToolDefinition<typeof SubagentWaitParams, Details> = {\n\t\tname: \"subagent_wait\",\n\t\tlabel: \"Subagent Wait\",\n\t\tdescription: `Block until background work owned by this session changes, then return.\n\nIn an interactive chat, do not call this merely to wait: return control to the user and let Pi wake the session on completion. Call it when the current request must run to completion in this turn, when a skill cannot return before its work finishes, or in a non-interactive run where there is no next turn.\n\n• { } — return when the first initially active async run or registered provider item finishes, or when a subagent needs attention.\n• { all: true } — wait for every async run and provider item that was active when the call began.\n• { id: \"...\" } — wait for one async or remembered detached foreground subagent run (id or prefix).\n• { timeoutMs: 600000 } — stop waiting after N ms; active work keeps running.\n\nProvider jobs are session-scoped and identified exactly, so replacing one job with another cannot hide a completion. Provider extensions must be explicitly loaded in this process. In a child agent, keep \\`subagent_wait\\` in the child tool allowlist and load each provider through the agent's extensions or subagentOnlyExtensions; this tool never loads providers or grants tools itself.${enabled ? \"\" : \"\\n\\nConfigured behavior: subagent_wait is disabled by config.waitTool or PI_SUBAGENT_WAIT_TOOL_ENABLED and returns immediately without blocking.\"}`,\n\t\tparameters: SubagentWaitParams,\n\t\tasync execute(_id, params, signal) {\n\t\t\tawait Promise.resolve();\n\t\t\tawait waitForPendingLaunches?.(signal);\n\t\t\tsignal?.throwIfAborted();\n\t\t\treturn waitForSubagents(params, signal, { state, events: pi.events, enabled });\n\t\t},\n\t};\n\tpi.registerTool(tool);\n}\n"]}
1
+ {"version":3,"file":"wait-tool.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/wait-tool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,iCAAiC,CAAC;AAEpF,OAAO,KAAK,EAAW,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGpE,wBAAgB,gBAAgB,CAC/B,EAAE,EAAE,YAAY,EAChB,KAAK,EAAE,aAAa,EACpB,OAAO,UAAkC,EACzC,sBAAsB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GAC9D,IAAI,CAwBN","sourcesContent":["// @ts-nocheck\nimport type { ExtensionAPI, ToolDefinition } from \"@ashx-j/lunr\";\nimport { SubagentWaitParams } from \"../../extension/schemas.ts\";\nimport type { Details, SubagentState } from \"../../shared/types.ts\";\nimport { resolveWaitToolConfig, waitForSubagents } from \"./subagent-wait.ts\";\n\nexport function registerWaitTool(\n\tpi: ExtensionAPI,\n\tstate: SubagentState,\n\tenabled = resolveWaitToolConfig().enabled,\n\twaitForPendingLaunches?: (signal?: AbortSignal) => Promise<void>,\n): void {\n\tconst tool: ToolDefinition<typeof SubagentWaitParams, Details> = {\n\t\tname: \"subagent_wait\",\n\t\tlabel: \"Subagent Wait\",\n\t\tdescription: `Block until background work owned by this session changes, then return.\n\nCall this when the current turn or skill must finish after its children. For normal interactive completion, yield and let lunR wake the session. Headless sessions auto-drain current-session work after the agent turn.\n\n• { } — return when the first initially active async run or registered provider item finishes, or when a subagent needs attention.\n• { all: true } — wait for every async run and provider item that was active when the call began.\n• { id: \"...\" } — wait for one async or remembered detached foreground subagent run (id or prefix).\n• { questionId: \"...\" } — wait for one supervisor question from subagent_supervisor action='ask' (answered/expired/cancelled). Separate from final run results.\n• { timeoutMs: 600000 } — stop waiting after N ms; active work keeps running.\n\nProvider jobs are session-scoped and identified exactly, so replacing one job with another cannot hide a completion. Provider extensions must be explicitly loaded in this process. In a child agent, keep \\`subagent_wait\\` in the child tool allowlist and load each provider through the agent's extensions or subagentOnlyExtensions; this tool never loads providers or grants tools itself.${enabled ? \"\" : \"\\n\\nConfigured behavior: subagent_wait is disabled by config.waitTool or PI_SUBAGENT_WAIT_TOOL_ENABLED and returns immediately without blocking.\"}`,\n\t\tparameters: SubagentWaitParams,\n\t\tasync execute(_id, params, signal) {\n\t\t\tawait Promise.resolve();\n\t\t\tawait waitForPendingLaunches?.(signal);\n\t\t\tsignal?.throwIfAborted();\n\t\t\treturn waitForSubagents(params, signal, { state, events: pi.events, enabled });\n\t\t},\n\t};\n\tpi.registerTool(tool);\n}\n"]}
@@ -6,11 +6,12 @@ export function registerWaitTool(pi, state, enabled = resolveWaitToolConfig().en
6
6
  label: "Subagent Wait",
7
7
  description: `Block until background work owned by this session changes, then return.
8
8
 
9
- In an interactive chat, do not call this merely to wait: return control to the user and let Pi wake the session on completion. Call it when the current request must run to completion in this turn, when a skill cannot return before its work finishes, or in a non-interactive run where there is no next turn.
9
+ Call this when the current turn or skill must finish after its children. For normal interactive completion, yield and let lunR wake the session. Headless sessions auto-drain current-session work after the agent turn.
10
10
 
11
11
  • { } — return when the first initially active async run or registered provider item finishes, or when a subagent needs attention.
12
12
  • { all: true } — wait for every async run and provider item that was active when the call began.
13
13
  • { id: "..." } — wait for one async or remembered detached foreground subagent run (id or prefix).
14
+ • { questionId: "..." } — wait for one supervisor question from subagent_supervisor action='ask' (answered/expired/cancelled). Separate from final run results.
14
15
  • { timeoutMs: 600000 } — stop waiting after N ms; active work keeps running.
15
16
 
16
17
  Provider jobs are session-scoped and identified exactly, so replacing one job with another cannot hide a completion. Provider extensions must be explicitly loaded in this process. In a child agent, keep \`subagent_wait\` in the child tool allowlist and load each provider through the agent's extensions or subagentOnlyExtensions; this tool never loads providers or grants tools itself.${enabled ? "" : "\n\nConfigured behavior: subagent_wait is disabled by config.waitTool or PI_SUBAGENT_WAIT_TOOL_ENABLED and returns immediately without blocking."}`,