@ashx-j/lunr-dev 0.2.19-dev.10.1 → 0.2.21-dev.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) 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-computer-use.d.ts.map +1 -1
  7. package/dist/builtin-extensions/lunr-computer-use.js +15 -14
  8. package/dist/builtin-extensions/lunr-computer-use.js.map +1 -1
  9. package/dist/builtin-extensions/lunr-todos.d.ts +6 -5
  10. package/dist/builtin-extensions/lunr-todos.d.ts.map +1 -1
  11. package/dist/builtin-extensions/lunr-todos.js +9 -7
  12. package/dist/builtin-extensions/lunr-todos.js.map +1 -1
  13. package/dist/builtin-extensions/pi-intercom/broker/spawn.d.ts +6 -4
  14. package/dist/builtin-extensions/pi-intercom/broker/spawn.d.ts.map +1 -1
  15. package/dist/builtin-extensions/pi-intercom/broker/spawn.js +114 -61
  16. package/dist/builtin-extensions/pi-intercom/broker/spawn.js.map +1 -1
  17. package/dist/builtin-extensions/pi-intercom/index.d.ts.map +1 -1
  18. package/dist/builtin-extensions/pi-intercom/index.js +360 -351
  19. package/dist/builtin-extensions/pi-intercom/index.js.map +1 -1
  20. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.d.ts.map +1 -1
  21. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js +2 -2
  22. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js.map +1 -1
  23. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +8 -6
  24. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  25. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +128 -57
  26. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  27. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts +18 -8
  28. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
  29. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +38 -13
  30. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
  31. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +4 -3
  32. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
  33. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +24 -14
  34. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
  35. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts +8 -1
  36. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts.map +1 -1
  37. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js +247 -18
  38. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js.map +1 -1
  39. package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.d.ts +1 -0
  40. package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.d.ts.map +1 -1
  41. package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.js +1 -1
  42. package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.js.map +1 -1
  43. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.d.ts +29 -0
  44. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.d.ts.map +1 -0
  45. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js +179 -0
  46. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js.map +1 -0
  47. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts +89 -0
  48. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts.map +1 -0
  49. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js +541 -0
  50. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js.map +1 -0
  51. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts +11 -1
  52. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts.map +1 -1
  53. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js +38 -12
  54. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js.map +1 -1
  55. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.d.ts.map +1 -1
  56. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js +3 -2
  57. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js.map +1 -1
  58. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts +2 -1
  59. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts.map +1 -1
  60. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js +35 -8
  61. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js.map +1 -1
  62. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts +7 -3
  63. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts.map +1 -1
  64. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js +26 -4
  65. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js.map +1 -1
  66. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.d.ts +1 -0
  67. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.d.ts.map +1 -1
  68. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js +55 -38
  69. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js.map +1 -1
  70. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts +100 -0
  71. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts.map +1 -1
  72. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js +46 -31
  73. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js.map +1 -1
  74. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts +3 -6
  75. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts.map +1 -1
  76. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js +64 -5
  77. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js.map +1 -1
  78. package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.d.ts +15 -2
  79. package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.d.ts.map +1 -1
  80. package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.js +14 -4
  81. package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.js.map +1 -1
  82. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.d.ts.map +1 -1
  83. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js +2 -1
  84. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js.map +1 -1
  85. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
  86. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +21 -8
  87. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
  88. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
  89. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +1 -1
  90. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
  91. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts +0 -1
  92. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  93. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +71 -25
  94. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
  95. package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.d.ts +2 -0
  96. package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.d.ts.map +1 -1
  97. package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.js +75 -18
  98. package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.js.map +1 -1
  99. package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.d.ts +1 -1
  100. package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.d.ts.map +1 -1
  101. package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.js +1 -1
  102. package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.js.map +1 -1
  103. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts +13 -1
  104. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts.map +1 -1
  105. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js +67 -11
  106. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js.map +1 -1
  107. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +1 -0
  108. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
  109. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
  110. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts +3 -0
  111. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts.map +1 -1
  112. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js +7 -2
  113. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js.map +1 -1
  114. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
  115. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js +13 -3
  116. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
  117. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.d.ts +2 -2
  118. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.d.ts.map +1 -1
  119. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.js +5 -10
  120. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.js.map +1 -1
  121. package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.d.ts +2 -0
  122. package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.d.ts.map +1 -0
  123. package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.js +3 -0
  124. package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.js.map +1 -0
  125. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts +3 -0
  126. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts.map +1 -1
  127. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js +68 -11
  128. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js.map +1 -1
  129. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts +12 -1
  130. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts.map +1 -1
  131. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js +21 -2
  132. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js.map +1 -1
  133. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +21 -4
  134. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
  135. package/dist/builtin-extensions/pi-subagents/src/shared/types.js +1 -1
  136. package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
  137. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.d.ts.map +1 -1
  138. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.js.map +1 -1
  139. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts +7 -0
  140. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts.map +1 -1
  141. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js +11 -7
  142. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js.map +1 -1
  143. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +6 -0
  144. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
  145. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +46 -29
  146. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
  147. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +46 -4
  148. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  149. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +407 -450
  150. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  151. package/dist/builtin-extensions/pi-subagents/src/watchdog/register-main.d.ts.map +1 -1
  152. package/dist/builtin-extensions/pi-subagents/src/watchdog/register-main.js +1 -1
  153. package/dist/builtin-extensions/pi-subagents/src/watchdog/register-main.js.map +1 -1
  154. package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.d.ts +2 -13
  155. package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.d.ts.map +1 -1
  156. package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.js +5 -91
  157. package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.js.map +1 -1
  158. package/dist/core/computer-use/image.d.ts +26 -0
  159. package/dist/core/computer-use/image.d.ts.map +1 -0
  160. package/dist/core/computer-use/image.js +64 -0
  161. package/dist/core/computer-use/image.js.map +1 -0
  162. package/dist/core/computer-use/policy.d.ts.map +1 -1
  163. package/dist/core/computer-use/policy.js +2 -6
  164. package/dist/core/computer-use/policy.js.map +1 -1
  165. package/dist/core/computer-use/schemas.d.ts +13 -10
  166. package/dist/core/computer-use/schemas.d.ts.map +1 -1
  167. package/dist/core/computer-use/schemas.js +26 -35
  168. package/dist/core/computer-use/schemas.js.map +1 -1
  169. package/dist/core/computer-use/workflow.d.ts +16 -8
  170. package/dist/core/computer-use/workflow.d.ts.map +1 -1
  171. package/dist/core/computer-use/workflow.js +271 -260
  172. package/dist/core/computer-use/workflow.js.map +1 -1
  173. package/dist/core/customize.d.ts +2 -0
  174. package/dist/core/customize.d.ts.map +1 -1
  175. package/dist/core/customize.js +3 -0
  176. package/dist/core/customize.js.map +1 -1
  177. package/dist/core/permissions.d.ts +1 -0
  178. package/dist/core/permissions.d.ts.map +1 -1
  179. package/dist/core/permissions.js +8 -4
  180. package/dist/core/permissions.js.map +1 -1
  181. package/dist/core/plan-mode.d.ts.map +1 -1
  182. package/dist/core/plan-mode.js +0 -5
  183. package/dist/core/plan-mode.js.map +1 -1
  184. package/dist/core/runtime-bridges.d.ts.map +1 -1
  185. package/dist/core/runtime-bridges.js +0 -2
  186. package/dist/core/runtime-bridges.js.map +1 -1
  187. package/dist/core/settings-manager.d.ts +4 -0
  188. package/dist/core/settings-manager.d.ts.map +1 -1
  189. package/dist/core/settings-manager.js +11 -0
  190. package/dist/core/settings-manager.js.map +1 -1
  191. package/dist/core/subagent-cancellation.d.ts +21 -0
  192. package/dist/core/subagent-cancellation.d.ts.map +1 -0
  193. package/dist/core/subagent-cancellation.js +53 -0
  194. package/dist/core/subagent-cancellation.js.map +1 -0
  195. package/dist/core/subagent-spinner-setting.d.ts +6 -0
  196. package/dist/core/subagent-spinner-setting.d.ts.map +1 -0
  197. package/dist/core/subagent-spinner-setting.js +12 -0
  198. package/dist/core/subagent-spinner-setting.js.map +1 -0
  199. package/dist/core/subagent-spinner.d.ts +4 -0
  200. package/dist/core/subagent-spinner.d.ts.map +1 -0
  201. package/dist/core/subagent-spinner.js +6 -0
  202. package/dist/core/subagent-spinner.js.map +1 -0
  203. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  204. package/dist/modes/interactive/components/assistant-message.js +12 -18
  205. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  206. package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
  207. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  208. package/dist/modes/interactive/components/settings-selector.js +73 -1
  209. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  210. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  211. package/dist/modes/interactive/components/tool-execution.js +12 -0
  212. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  213. package/dist/modes/interactive/extension-widget-order.d.ts +8 -0
  214. package/dist/modes/interactive/extension-widget-order.d.ts.map +1 -0
  215. package/dist/modes/interactive/extension-widget-order.js +37 -0
  216. package/dist/modes/interactive/extension-widget-order.js.map +1 -0
  217. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  218. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  219. package/dist/modes/interactive/interactive-mode.js +44 -22
  220. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  221. package/dist/node-runtime/{agent-session-services-RSGP5GDN.js → agent-session-services-QANFGM2V.js} +14 -13
  222. package/dist/node-runtime/{builtin-extensions-7STLFW3A.js → builtin-extensions-SRCYQPZ6.js} +4 -3
  223. package/dist/node-runtime/{chunk-5OLJGVCB.js → chunk-3ONQTOMR.js} +2 -2
  224. package/dist/node-runtime/chunk-5ZH3ZFIZ.js +308 -0
  225. package/dist/node-runtime/{chunk-4SJWFTUP.js → chunk-7NBZ5P7I.js} +1 -1
  226. package/dist/node-runtime/chunk-A3KMVBZV.js +60 -0
  227. package/dist/node-runtime/{chunk-FLYMHKCS.js → chunk-BJ6H7DPI.js} +25 -25
  228. package/dist/node-runtime/{chunk-T5GM5BFH.js → chunk-BYQ2MOFI.js} +6 -6
  229. package/dist/node-runtime/{chunk-W7S2REEG.js → chunk-CZUBYPFP.js} +157 -74
  230. package/dist/node-runtime/{chunk-ZRDIMBEQ.js → chunk-D466UAID.js} +9 -6
  231. package/dist/node-runtime/{chunk-K72NVGUB.js → chunk-GT5F3OKM.js} +1 -1
  232. package/dist/node-runtime/chunk-H2BI7G7T.js +73 -0
  233. package/dist/node-runtime/{chunk-ISQDQIZN.js → chunk-HXJS2PJM.js} +2 -2
  234. package/dist/node-runtime/chunk-LISUTZS3.js +19 -0
  235. package/dist/node-runtime/{chunk-BKAZ6BKX.js → chunk-LOYUC2ID.js} +7 -7
  236. package/dist/node-runtime/{chunk-OTT6JMPU.js → chunk-LTYWTR3V.js} +1 -369
  237. package/dist/node-runtime/{chunk-5Q45AVQG.js → chunk-MW2XJZIK.js} +1 -1
  238. package/dist/node-runtime/{chunk-MUMMMTW4.js → chunk-N3PNL74S.js} +536 -265
  239. package/dist/node-runtime/{chunk-HQCKFM2O.js → chunk-VGYZ3APQ.js} +3 -0
  240. package/dist/node-runtime/{chunk-5NWQCSKR.js → chunk-VQ4UBWSA.js} +11 -1
  241. package/dist/node-runtime/{chunk-6SPPH4FY.js → chunk-VTGEKB7R.js} +4 -4
  242. package/dist/node-runtime/chunk-W3SILANP.js +24 -0
  243. package/dist/node-runtime/{chunk-J7QGQD45.js → chunk-WJVFOIB5.js} +1 -1
  244. package/dist/node-runtime/{chunk-JT6YCS5B.js → chunk-XAUQOKYK.js} +408 -45
  245. package/dist/node-runtime/{chunk-LCACDWHJ.js → chunk-XSRCAQK2.js} +13 -13
  246. package/dist/node-runtime/{chunk-TAP7QTUT.js → chunk-ZOIIMEN6.js} +24 -425
  247. package/dist/node-runtime/{chunk-MGSB2C3M.js → chunk-ZVSORYRM.js} +1 -1
  248. package/dist/node-runtime/{command-6UXQ6XZN.js → command-ZURZJDXF.js} +1 -1
  249. package/dist/node-runtime/{commands-LGR5VT5X.js → commands-BZGSLIP7.js} +3 -3
  250. package/dist/node-runtime/{customize-XEXL2DGQ.js → customize-LF5VST47.js} +1 -1
  251. package/dist/node-runtime/{direct-tool-executor-TDJS7TBD.js → direct-tool-executor-BSZDHIYR.js} +4 -4
  252. package/dist/node-runtime/{extract-IUCVZCWC.js → extract-XLQSJN4V.js} +2 -2
  253. package/dist/node-runtime/{gateway-3OLC4GQN.js → gateway-FWHRIBK5.js} +9 -9
  254. package/dist/node-runtime/{gemini-search-NCIDF7NE.js → gemini-search-U7SUMPQA.js} +1 -1
  255. package/dist/node-runtime/{gemini-url-context-OKIN7AIP.js → gemini-url-context-PXWCBQHK.js} +2 -2
  256. package/dist/node-runtime/index.js +34 -31
  257. package/dist/node-runtime/{init-EKE277AG.js → init-DVJUAOUO.js} +3 -3
  258. package/dist/node-runtime/{interactive-mode-S5M26CQ7.js → interactive-mode-BBASNWHN.js} +18 -15
  259. package/dist/node-runtime/lunr-computer-use-TJNDAMWM.js +135 -0
  260. package/dist/node-runtime/{lunr-cron-KKBOGAEF.js → lunr-cron-J64I72C6.js} +5 -5
  261. package/dist/node-runtime/main.js +22 -20
  262. package/dist/node-runtime/{package-manager-cli-C4EJOO5Q.js → package-manager-cli-VMYX4Y2S.js} +8 -7
  263. package/dist/node-runtime/{pi-intercom-EEMBGQID.js → pi-intercom-NV2LW6X7.js} +108 -87
  264. package/dist/node-runtime/{pi-mcp-adapter-DPTJGAAL.js → pi-mcp-adapter-JLB5YL2F.js} +6 -6
  265. package/dist/node-runtime/{pi-subagents-VKCLYIBY.js → pi-subagents-WEHV3W7H.js} +1267 -604
  266. package/dist/node-runtime/{pi-web-access-BV6DSZOP.js → pi-web-access-FN5YC5T6.js} +5 -5
  267. package/dist/node-runtime/{proxy-modes-R64LU6WZ.js → proxy-modes-OR7ISBXK.js} +7 -7
  268. package/dist/node-runtime/rpc-entry.js +22 -20
  269. package/dist/node-runtime/{runtime-bridges-UJ5WJJLN.js → runtime-bridges-2VQTLPOZ.js} +3 -5
  270. package/dist/node-runtime/{settings-manager-K6IPIQTI.js → settings-manager-3CCU326G.js} +3 -2
  271. package/dist/node-runtime/{subagent-executor-EFLTO32A.js → subagent-executor-CXKXQDHH.js} +186 -299
  272. package/dist/node-runtime/{update-cli-I6OVDRPL.js → update-cli-NM7B4CKL.js} +3 -2
  273. package/dist/node-runtime/{video-extract-ETA5RA7U.js → video-extract-OYT5WKS5.js} +2 -2
  274. package/dist/node-runtime/workflow-C26QCUTW.js +468 -0
  275. package/dist/node-runtime/{youtube-extract-SRVGNN26.js → youtube-extract-TQYKGFGS.js} +2 -2
  276. package/docs/computer-use.md +233 -268
  277. package/docs/features.md +22 -4
  278. package/docs/keybindings.md +3 -1
  279. package/docs/settings.md +3 -2
  280. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  281. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  282. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  283. package/examples/extensions/gondolin/package-lock.json +2 -2
  284. package/examples/extensions/gondolin/package.json +1 -1
  285. package/examples/extensions/sandbox/package-lock.json +2 -2
  286. package/examples/extensions/sandbox/package.json +1 -1
  287. package/examples/extensions/with-deps/package-lock.json +2 -2
  288. package/examples/extensions/with-deps/package.json +1 -1
  289. package/install-lock/package-lock.json +24 -24
  290. package/install-lock/package.json +2 -2
  291. package/npm-shrinkwrap.json +21 -21
  292. package/package.json +7 -7
  293. package/dist/builtin-extensions/lunr-settings-tools.d.ts +0 -4
  294. package/dist/builtin-extensions/lunr-settings-tools.d.ts.map +0 -1
  295. package/dist/builtin-extensions/lunr-settings-tools.js +0 -120
  296. package/dist/builtin-extensions/lunr-settings-tools.js.map +0 -1
  297. package/dist/core/settings-tools-bridge.d.ts +0 -35
  298. package/dist/core/settings-tools-bridge.d.ts.map +0 -1
  299. package/dist/core/settings-tools-bridge.js +0 -56
  300. package/dist/core/settings-tools-bridge.js.map +0 -1
  301. package/dist/node-runtime/chunk-EH2LJQPM.js +0 -64
  302. package/dist/node-runtime/image-resize-6ZPBFMWW.js +0 -11
  303. package/dist/node-runtime/lunr-computer-use-4X3KUNF4.js +0 -206
  304. package/dist/node-runtime/workflow-SA34S4VX.js +0 -325
  305. package/dist/node-runtime/{chunk-EHMBW7FA.js → chunk-VSELYKWU.js} +3 -3
  306. package/dist/node-runtime/{chunk-ZSEZY3II.js → chunk-VTPM5V35.js} +0 -0
  307. package/dist/node-runtime/{src-GPFAU3N6.js → src-BPQFJR76.js} +3 -3
@@ -0,0 +1,29 @@
1
+ import type { AgentToolResult } from "@ashx-j/lunr-agent";
2
+ import type { AsyncStatus, SubagentState } from "../shared/types.ts";
3
+ import { type SupervisorQuestion } from "./supervisor-questions.ts";
4
+ export interface ParentAskParams {
5
+ id?: string;
6
+ index?: number;
7
+ childId?: string;
8
+ reason?: string;
9
+ message?: string;
10
+ }
11
+ export interface ParentAskRequestFile {
12
+ expectsReply?: boolean;
13
+ runId?: string;
14
+ childIndex?: number;
15
+ agent?: string;
16
+ childTarget?: string;
17
+ }
18
+ export declare function resolveAskChild(status: AsyncStatus, params: Pick<ParentAskParams, "index" | "childId">): {
19
+ index: number;
20
+ childId: string;
21
+ agent: string;
22
+ };
23
+ export declare function reconcileAsyncQuestion(channelDir: string, question: SupervisorQuestion, state: SubagentState): SupervisorQuestion;
24
+ export declare function askRunningAsyncChild(input: {
25
+ params: ParentAskParams;
26
+ state: SubagentState;
27
+ childRequests?: Iterable<ParentAskRequestFile>;
28
+ }): AgentToolResult<Record<string, unknown>>;
29
+ //# sourceMappingURL=supervisor-ask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supervisor-ask.d.ts","sourceRoot":"","sources":["../../../../../src/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAIrE,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAYN,KAAK,kBAAkB,EACvB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,eAAe;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACpC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAcD,wBAAgB,eAAe,CAC9B,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,SAAS,CAAC,GAChD;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CA+BnD;AAYD,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,EAAE,KAAK,EAAE,aAAa,GAAG,kBAAkB,CAmBjI;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC3C,MAAM,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,aAAa,CAAC;IACrB,aAAa,CAAC,EAAE,QAAQ,CAAC,oBAAoB,CAAC,CAAC;CAC/C,GAAG,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA8E3C","sourcesContent":["import type { AgentToolResult } from \"@ashx-j/lunr-agent\";\nimport { readSteerCapability, requestAsyncSteer } from \"../runs/background/control-channel.ts\";\nimport { resolveSubagentRunId } from \"../runs/background/run-id-resolver.ts\";\nimport { readStatus } from \"../shared/utils.ts\";\nimport type { AsyncStatus, SubagentState } from \"../shared/types.ts\";\nimport {\n\tcancelSupervisorQuestion,\n\tcreateSupervisorQuestion,\n\tformatParentQuestionForChild,\n\texpireSupervisorQuestion,\n\thasOutstandingQuestionForChild,\n\thasBlockingSupervisorRequest,\n\tincarnationMatches,\n\treadSupervisorQuestion,\n\tsupervisorQuestionIsTerminal,\n\tresolveSupervisorChannelDir,\n\ttype SupervisorChildIncarnation,\n\ttype SupervisorQuestion,\n} from \"./supervisor-questions.ts\";\n\nexport interface ParentAskParams {\n\tid?: string;\n\tindex?: number;\n\tchildId?: string;\n\treason?: string;\n\tmessage?: string;\n}\n\nexport interface ParentAskRequestFile {\n\texpectsReply?: boolean;\n\trunId?: string;\n\tchildIndex?: number;\n\tagent?: string;\n\tchildTarget?: string;\n}\n\nfunction runningSteps(status: AsyncStatus): Array<{ index: number; childId: string; agent: string }> {\n\treturn (status.steps ?? [])\n\t\t.map((step, index) => ({\n\t\t\tindex,\n\t\t\tchildId: step.childId ?? step.agent,\n\t\t\tagent: step.agent,\n\t\t\tstatus: step.status,\n\t\t}))\n\t\t.filter((step) => step.status === \"running\")\n\t\t.map((step) => ({ index: step.index, childId: step.childId, agent: step.agent }));\n}\n\nexport function resolveAskChild(\n\tstatus: AsyncStatus,\n\tparams: Pick<ParentAskParams, \"index\" | \"childId\">,\n): { index: number; childId: string; agent: string } {\n\tif (params.index !== undefined && (!Number.isInteger(params.index) || params.index < 0)) {\n\t\tthrow new Error(\"index must be a non-negative integer.\");\n\t}\n\tconst running = runningSteps(status);\n\tif (params.childId?.trim()) {\n\t\tconst childId = params.childId.trim();\n\t\tconst matches = (status.steps ?? [])\n\t\t\t.map((step, index) => ({ index, childId: step.childId ?? step.agent, agent: step.agent, status: step.status }))\n\t\t\t.filter((step) => step.childId === childId);\n\t\tif (matches.length === 0) throw new Error(`Async run '${status.runId}' has no child '${childId}'.`);\n\t\tif (matches.length > 1) throw new Error(`Async run '${status.runId}' has multiple children named '${childId}'. Pass index.`);\n\t\tconst match = matches[0]!;\n\t\tif (params.index !== undefined && params.index !== match.index) {\n\t\t\tthrow new Error(`Child '${childId}' is index ${match.index}, not ${params.index}.`);\n\t\t}\n\t\tif (match.status !== \"running\") throw new Error(`Async run '${status.runId}' child ${match.index} is ${match.status} and cannot be asked.`);\n\t\treturn { index: match.index, childId: match.childId, agent: match.agent };\n\t}\n\tif (params.index !== undefined) {\n\t\tconst steps = status.steps ?? [];\n\t\tif (params.index >= steps.length) {\n\t\t\tthrow new Error(`Async run '${status.runId}' has ${steps.length} children. Index ${params.index} is out of range.`);\n\t\t}\n\t\tconst step = steps[params.index]!;\n\t\tif (step.status !== \"running\") throw new Error(`Async run '${status.runId}' child ${params.index} is ${step.status} and cannot be asked.`);\n\t\treturn { index: params.index, childId: step.childId ?? step.agent, agent: step.agent };\n\t}\n\tif (running.length === 1) return running[0]!;\n\tif (running.length === 0) throw new Error(`Async run '${status.runId}' has no running child to ask.`);\n\tthrow new Error(`Async run '${status.runId}' has ${running.length} running children. Pass index or childId; broadcast asks are not supported.`);\n}\n\nfunction requestMatchesChild(request: ParentAskRequestFile, runId: string, child: { index: number; childId: string; agent: string }): boolean {\n\tif (!request.expectsReply) return false;\n\tif (typeof request.runId !== \"string\" || request.runId !== runId) return false;\n\tconst indexMatches = Number.isInteger(request.childIndex) && request.childIndex === child.index;\n\tconst idMatches = request.agent === child.childId\n\t\t|| request.agent === child.agent\n\t\t|| request.childTarget === child.childId;\n\treturn indexMatches && idMatches;\n}\n\nexport function reconcileAsyncQuestion(channelDir: string, question: SupervisorQuestion, state: SubagentState): SupervisorQuestion {\n\texpireSupervisorQuestion(channelDir, question.id);\n\tconst current = readSupervisorQuestion(channelDir, question.id) ?? question;\n\tif (supervisorQuestionIsTerminal(current)) return current;\n\tconst resolved = resolveSubagentRunId(current.runId, { state });\n\tif (resolved?.kind !== \"async\" || !resolved.location.asyncDir) return current;\n\tconst status = readStatus(resolved.location.asyncDir);\n\tif (!status) return current;\n\tconst step = status.steps?.[current.childIndex];\n\tconst capability = readSteerCapability(resolved.location.asyncDir, current.childIndex);\n\tlet reason: string | undefined;\n\tif (status.sessionId !== current.parentSessionId) reason = \"async run ownership changed\";\n\telse if (status.state !== \"running\" || !step || step.status !== \"running\") reason = \"target child is no longer running\";\n\telse if ((step.childId ?? step.agent) !== current.childId) reason = \"target child identity changed\";\n\telse if (capability && !incarnationMatches(current.childIncarnation, capability)) reason = \"target child process changed\";\n\telse if (capability && !capability.supported) reason = \"target child no longer accepts questions\";\n\tconst delivery = status.steering?.recent.find((request) => request.id === current.id)?.targets.find((target) => target.index === current.childIndex);\n\tif (delivery?.state === \"failed\" || delivery?.state === \"late\") reason = delivery.reason ?? \"question delivery failed\";\n\treturn reason ? cancelSupervisorQuestion(channelDir, current.id, reason) ?? current : current;\n}\n\nexport function askRunningAsyncChild(input: {\n\tparams: ParentAskParams;\n\tstate: SubagentState;\n\tchildRequests?: Iterable<ParentAskRequestFile>;\n}): AgentToolResult<Record<string, unknown>> {\n\tconst runId = input.params.id?.trim();\n\tif (!runId) throw new Error(\"action='ask' requires id for the async run.\");\n\tconst reason = input.params.reason?.trim();\n\tconst message = input.params.message?.trim();\n\tif (!reason) throw new Error(\"action='ask' requires reason naming the concrete decision the child's answer will change.\");\n\tif (!message) throw new Error(\"action='ask' requires message.\");\n\tconst sessionId = input.state.currentSessionId;\n\tif (!sessionId) throw new Error(\"action='ask' requires an active session identity.\");\n\n\tconst resolved = resolveSubagentRunId(runId, { state: input.state });\n\tif (!resolved) throw new Error(`No async run matched '${runId}'.`);\n\tif (resolved.kind !== \"async\") throw new Error(\"action='ask' targets a running async child only. It does not revive, reassign, or broadcast.\");\n\tif (!resolved.location.asyncDir) throw new Error(`Async run '${resolved.id}' has no live run directory.`);\n\n\tconst status = readStatus(resolved.location.asyncDir);\n\tif (!status) throw new Error(`Async run '${resolved.id}' has no status.`);\n\tif (!status.sessionId || status.sessionId !== sessionId) {\n\t\tthrow new Error(`Async run '${resolved.id}' was not found in the active session.`);\n\t}\n\tif (status.state !== \"running\") throw new Error(`Async run '${resolved.id}' is ${status.state} and cannot be asked.`);\n\n\tconst child = resolveAskChild(status, input.params);\n\tconst channelDir = resolveSupervisorChannelDir(status.runId, child.childId, child.index);\n\tif (hasOutstandingQuestionForChild(channelDir, child.index, child.childId)) {\n\t\tthrow new Error(`A question is already outstanding for async run '${status.runId}' child ${child.index}. Wait for that answer or expiry before asking again.`);\n\t}\n\tfor (const request of input.childRequests ?? []) {\n\t\tif (requestMatchesChild(request, status.runId, child)) {\n\t\t\tthrow new Error(`Child ${child.index} is waiting for a supervisor reply. Asking now would deadlock. Reply to the child request first.`);\n\t\t}\n\t}\n\n\tif (hasBlockingSupervisorRequest(channelDir, status.runId, child.index)) {\n\t\tthrow new Error(\"Child is waiting for a supervisor reply. Reply to its request before asking a question.\");\n\t}\n\tconst capability = readSteerCapability(resolved.location.asyncDir, child.index);\n\tif (!capability?.supported) {\n\t\tthrow new Error(\"This child is not ready to receive questions. Continue other work until it is ready; no question was queued.\");\n\t}\n\tconst incarnation: SupervisorChildIncarnation = { pid: capability.pid, readyAt: capability.readyAt };\n\tconst question: SupervisorQuestion = createSupervisorQuestion({\n\t\tchannelDir,\n\t\treason,\n\t\tmessage,\n\t\trunId: status.runId,\n\t\tchildIndex: child.index,\n\t\tchildId: child.childId,\n\t\tparentSessionId: sessionId,\n\t\tparentGeneration: input.state.sessionGeneration ?? 0,\n\t\tchildIncarnation: incarnation,\n\t});\n\ttry {\n\t\tif (hasBlockingSupervisorRequest(channelDir, status.runId, child.index)) {\n\t\t\tthrow new Error(\"Child is waiting for a supervisor reply. Reply to its request before asking a question.\");\n\t\t}\n\t\trequestAsyncSteer(resolved.location.asyncDir, {\n\t\t\tmessage: formatParentQuestionForChild(question),\n\t\t\ttargetIndex: child.index,\n\t\t\tsource: \"supervisor-question\",\n\t\t\tid: question.id,\n\t\t});\n\t} catch (error) {\n\t\tcancelSupervisorQuestion(channelDir, question.id, \"failed to queue delivery to child\");\n\t\tthrow error instanceof Error ? error : new Error(String(error));\n\t}\n\treturn {\n\t\tcontent: [{ type: \"text\", text: `Question ${question.id} queued for async run ${status.runId} child ${child.index}. The child's answer is delivered separately from the run result.` }],\n\t\tdetails: {\n\t\t\tquestionId: question.id,\n\t\t\tstate: \"pending\",\n\t\t\trunId: status.runId,\n\t\t\tchildIndex: child.index,\n\t\t\tchildId: child.childId,\n\t\t\tdelivered: false,\n\t\t\tanswered: false,\n\t\t},\n\t};\n}\n"]}
@@ -0,0 +1,179 @@
1
+ import { readSteerCapability, requestAsyncSteer } from "../runs/background/control-channel.js";
2
+ import { resolveSubagentRunId } from "../runs/background/run-id-resolver.js";
3
+ import { readStatus } from "../shared/utils.js";
4
+ import { cancelSupervisorQuestion, createSupervisorQuestion, formatParentQuestionForChild, expireSupervisorQuestion, hasOutstandingQuestionForChild, hasBlockingSupervisorRequest, incarnationMatches, readSupervisorQuestion, supervisorQuestionIsTerminal, resolveSupervisorChannelDir, } from "./supervisor-questions.js";
5
+ function runningSteps(status) {
6
+ return (status.steps ?? [])
7
+ .map((step, index) => ({
8
+ index,
9
+ childId: step.childId ?? step.agent,
10
+ agent: step.agent,
11
+ status: step.status,
12
+ }))
13
+ .filter((step) => step.status === "running")
14
+ .map((step) => ({ index: step.index, childId: step.childId, agent: step.agent }));
15
+ }
16
+ export function resolveAskChild(status, params) {
17
+ if (params.index !== undefined && (!Number.isInteger(params.index) || params.index < 0)) {
18
+ throw new Error("index must be a non-negative integer.");
19
+ }
20
+ const running = runningSteps(status);
21
+ if (params.childId?.trim()) {
22
+ const childId = params.childId.trim();
23
+ const matches = (status.steps ?? [])
24
+ .map((step, index) => ({ index, childId: step.childId ?? step.agent, agent: step.agent, status: step.status }))
25
+ .filter((step) => step.childId === childId);
26
+ if (matches.length === 0)
27
+ throw new Error(`Async run '${status.runId}' has no child '${childId}'.`);
28
+ if (matches.length > 1)
29
+ throw new Error(`Async run '${status.runId}' has multiple children named '${childId}'. Pass index.`);
30
+ const match = matches[0];
31
+ if (params.index !== undefined && params.index !== match.index) {
32
+ throw new Error(`Child '${childId}' is index ${match.index}, not ${params.index}.`);
33
+ }
34
+ if (match.status !== "running")
35
+ throw new Error(`Async run '${status.runId}' child ${match.index} is ${match.status} and cannot be asked.`);
36
+ return { index: match.index, childId: match.childId, agent: match.agent };
37
+ }
38
+ if (params.index !== undefined) {
39
+ const steps = status.steps ?? [];
40
+ if (params.index >= steps.length) {
41
+ throw new Error(`Async run '${status.runId}' has ${steps.length} children. Index ${params.index} is out of range.`);
42
+ }
43
+ const step = steps[params.index];
44
+ if (step.status !== "running")
45
+ throw new Error(`Async run '${status.runId}' child ${params.index} is ${step.status} and cannot be asked.`);
46
+ return { index: params.index, childId: step.childId ?? step.agent, agent: step.agent };
47
+ }
48
+ if (running.length === 1)
49
+ return running[0];
50
+ if (running.length === 0)
51
+ throw new Error(`Async run '${status.runId}' has no running child to ask.`);
52
+ throw new Error(`Async run '${status.runId}' has ${running.length} running children. Pass index or childId; broadcast asks are not supported.`);
53
+ }
54
+ function requestMatchesChild(request, runId, child) {
55
+ if (!request.expectsReply)
56
+ return false;
57
+ if (typeof request.runId !== "string" || request.runId !== runId)
58
+ return false;
59
+ const indexMatches = Number.isInteger(request.childIndex) && request.childIndex === child.index;
60
+ const idMatches = request.agent === child.childId
61
+ || request.agent === child.agent
62
+ || request.childTarget === child.childId;
63
+ return indexMatches && idMatches;
64
+ }
65
+ export function reconcileAsyncQuestion(channelDir, question, state) {
66
+ expireSupervisorQuestion(channelDir, question.id);
67
+ const current = readSupervisorQuestion(channelDir, question.id) ?? question;
68
+ if (supervisorQuestionIsTerminal(current))
69
+ return current;
70
+ const resolved = resolveSubagentRunId(current.runId, { state });
71
+ if (resolved?.kind !== "async" || !resolved.location.asyncDir)
72
+ return current;
73
+ const status = readStatus(resolved.location.asyncDir);
74
+ if (!status)
75
+ return current;
76
+ const step = status.steps?.[current.childIndex];
77
+ const capability = readSteerCapability(resolved.location.asyncDir, current.childIndex);
78
+ let reason;
79
+ if (status.sessionId !== current.parentSessionId)
80
+ reason = "async run ownership changed";
81
+ else if (status.state !== "running" || !step || step.status !== "running")
82
+ reason = "target child is no longer running";
83
+ else if ((step.childId ?? step.agent) !== current.childId)
84
+ reason = "target child identity changed";
85
+ else if (capability && !incarnationMatches(current.childIncarnation, capability))
86
+ reason = "target child process changed";
87
+ else if (capability && !capability.supported)
88
+ reason = "target child no longer accepts questions";
89
+ const delivery = status.steering?.recent.find((request) => request.id === current.id)?.targets.find((target) => target.index === current.childIndex);
90
+ if (delivery?.state === "failed" || delivery?.state === "late")
91
+ reason = delivery.reason ?? "question delivery failed";
92
+ return reason ? cancelSupervisorQuestion(channelDir, current.id, reason) ?? current : current;
93
+ }
94
+ export function askRunningAsyncChild(input) {
95
+ const runId = input.params.id?.trim();
96
+ if (!runId)
97
+ throw new Error("action='ask' requires id for the async run.");
98
+ const reason = input.params.reason?.trim();
99
+ const message = input.params.message?.trim();
100
+ if (!reason)
101
+ throw new Error("action='ask' requires reason naming the concrete decision the child's answer will change.");
102
+ if (!message)
103
+ throw new Error("action='ask' requires message.");
104
+ const sessionId = input.state.currentSessionId;
105
+ if (!sessionId)
106
+ throw new Error("action='ask' requires an active session identity.");
107
+ const resolved = resolveSubagentRunId(runId, { state: input.state });
108
+ if (!resolved)
109
+ throw new Error(`No async run matched '${runId}'.`);
110
+ if (resolved.kind !== "async")
111
+ throw new Error("action='ask' targets a running async child only. It does not revive, reassign, or broadcast.");
112
+ if (!resolved.location.asyncDir)
113
+ throw new Error(`Async run '${resolved.id}' has no live run directory.`);
114
+ const status = readStatus(resolved.location.asyncDir);
115
+ if (!status)
116
+ throw new Error(`Async run '${resolved.id}' has no status.`);
117
+ if (!status.sessionId || status.sessionId !== sessionId) {
118
+ throw new Error(`Async run '${resolved.id}' was not found in the active session.`);
119
+ }
120
+ if (status.state !== "running")
121
+ throw new Error(`Async run '${resolved.id}' is ${status.state} and cannot be asked.`);
122
+ const child = resolveAskChild(status, input.params);
123
+ const channelDir = resolveSupervisorChannelDir(status.runId, child.childId, child.index);
124
+ if (hasOutstandingQuestionForChild(channelDir, child.index, child.childId)) {
125
+ throw new Error(`A question is already outstanding for async run '${status.runId}' child ${child.index}. Wait for that answer or expiry before asking again.`);
126
+ }
127
+ for (const request of input.childRequests ?? []) {
128
+ if (requestMatchesChild(request, status.runId, child)) {
129
+ throw new Error(`Child ${child.index} is waiting for a supervisor reply. Asking now would deadlock. Reply to the child request first.`);
130
+ }
131
+ }
132
+ if (hasBlockingSupervisorRequest(channelDir, status.runId, child.index)) {
133
+ throw new Error("Child is waiting for a supervisor reply. Reply to its request before asking a question.");
134
+ }
135
+ const capability = readSteerCapability(resolved.location.asyncDir, child.index);
136
+ if (!capability?.supported) {
137
+ throw new Error("This child is not ready to receive questions. Continue other work until it is ready; no question was queued.");
138
+ }
139
+ const incarnation = { pid: capability.pid, readyAt: capability.readyAt };
140
+ const question = createSupervisorQuestion({
141
+ channelDir,
142
+ reason,
143
+ message,
144
+ runId: status.runId,
145
+ childIndex: child.index,
146
+ childId: child.childId,
147
+ parentSessionId: sessionId,
148
+ parentGeneration: input.state.sessionGeneration ?? 0,
149
+ childIncarnation: incarnation,
150
+ });
151
+ try {
152
+ if (hasBlockingSupervisorRequest(channelDir, status.runId, child.index)) {
153
+ throw new Error("Child is waiting for a supervisor reply. Reply to its request before asking a question.");
154
+ }
155
+ requestAsyncSteer(resolved.location.asyncDir, {
156
+ message: formatParentQuestionForChild(question),
157
+ targetIndex: child.index,
158
+ source: "supervisor-question",
159
+ id: question.id,
160
+ });
161
+ }
162
+ catch (error) {
163
+ cancelSupervisorQuestion(channelDir, question.id, "failed to queue delivery to child");
164
+ throw error instanceof Error ? error : new Error(String(error));
165
+ }
166
+ return {
167
+ content: [{ type: "text", text: `Question ${question.id} queued for async run ${status.runId} child ${child.index}. The child's answer is delivered separately from the run result.` }],
168
+ details: {
169
+ questionId: question.id,
170
+ state: "pending",
171
+ runId: status.runId,
172
+ childIndex: child.index,
173
+ childId: child.childId,
174
+ delivered: false,
175
+ answered: false,
176
+ },
177
+ };
178
+ }
179
+ //# sourceMappingURL=supervisor-ask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supervisor-ask.js","sourceRoot":"","sources":["../../../../../src/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentToolResult } from \"@ashx-j/lunr-agent\";\nimport { readSteerCapability, requestAsyncSteer } from \"../runs/background/control-channel.ts\";\nimport { resolveSubagentRunId } from \"../runs/background/run-id-resolver.ts\";\nimport { readStatus } from \"../shared/utils.ts\";\nimport type { AsyncStatus, SubagentState } from \"../shared/types.ts\";\nimport {\n\tcancelSupervisorQuestion,\n\tcreateSupervisorQuestion,\n\tformatParentQuestionForChild,\n\texpireSupervisorQuestion,\n\thasOutstandingQuestionForChild,\n\thasBlockingSupervisorRequest,\n\tincarnationMatches,\n\treadSupervisorQuestion,\n\tsupervisorQuestionIsTerminal,\n\tresolveSupervisorChannelDir,\n\ttype SupervisorChildIncarnation,\n\ttype SupervisorQuestion,\n} from \"./supervisor-questions.ts\";\n\nexport interface ParentAskParams {\n\tid?: string;\n\tindex?: number;\n\tchildId?: string;\n\treason?: string;\n\tmessage?: string;\n}\n\nexport interface ParentAskRequestFile {\n\texpectsReply?: boolean;\n\trunId?: string;\n\tchildIndex?: number;\n\tagent?: string;\n\tchildTarget?: string;\n}\n\nfunction runningSteps(status: AsyncStatus): Array<{ index: number; childId: string; agent: string }> {\n\treturn (status.steps ?? [])\n\t\t.map((step, index) => ({\n\t\t\tindex,\n\t\t\tchildId: step.childId ?? step.agent,\n\t\t\tagent: step.agent,\n\t\t\tstatus: step.status,\n\t\t}))\n\t\t.filter((step) => step.status === \"running\")\n\t\t.map((step) => ({ index: step.index, childId: step.childId, agent: step.agent }));\n}\n\nexport function resolveAskChild(\n\tstatus: AsyncStatus,\n\tparams: Pick<ParentAskParams, \"index\" | \"childId\">,\n): { index: number; childId: string; agent: string } {\n\tif (params.index !== undefined && (!Number.isInteger(params.index) || params.index < 0)) {\n\t\tthrow new Error(\"index must be a non-negative integer.\");\n\t}\n\tconst running = runningSteps(status);\n\tif (params.childId?.trim()) {\n\t\tconst childId = params.childId.trim();\n\t\tconst matches = (status.steps ?? [])\n\t\t\t.map((step, index) => ({ index, childId: step.childId ?? step.agent, agent: step.agent, status: step.status }))\n\t\t\t.filter((step) => step.childId === childId);\n\t\tif (matches.length === 0) throw new Error(`Async run '${status.runId}' has no child '${childId}'.`);\n\t\tif (matches.length > 1) throw new Error(`Async run '${status.runId}' has multiple children named '${childId}'. Pass index.`);\n\t\tconst match = matches[0]!;\n\t\tif (params.index !== undefined && params.index !== match.index) {\n\t\t\tthrow new Error(`Child '${childId}' is index ${match.index}, not ${params.index}.`);\n\t\t}\n\t\tif (match.status !== \"running\") throw new Error(`Async run '${status.runId}' child ${match.index} is ${match.status} and cannot be asked.`);\n\t\treturn { index: match.index, childId: match.childId, agent: match.agent };\n\t}\n\tif (params.index !== undefined) {\n\t\tconst steps = status.steps ?? [];\n\t\tif (params.index >= steps.length) {\n\t\t\tthrow new Error(`Async run '${status.runId}' has ${steps.length} children. Index ${params.index} is out of range.`);\n\t\t}\n\t\tconst step = steps[params.index]!;\n\t\tif (step.status !== \"running\") throw new Error(`Async run '${status.runId}' child ${params.index} is ${step.status} and cannot be asked.`);\n\t\treturn { index: params.index, childId: step.childId ?? step.agent, agent: step.agent };\n\t}\n\tif (running.length === 1) return running[0]!;\n\tif (running.length === 0) throw new Error(`Async run '${status.runId}' has no running child to ask.`);\n\tthrow new Error(`Async run '${status.runId}' has ${running.length} running children. Pass index or childId; broadcast asks are not supported.`);\n}\n\nfunction requestMatchesChild(request: ParentAskRequestFile, runId: string, child: { index: number; childId: string; agent: string }): boolean {\n\tif (!request.expectsReply) return false;\n\tif (typeof request.runId !== \"string\" || request.runId !== runId) return false;\n\tconst indexMatches = Number.isInteger(request.childIndex) && request.childIndex === child.index;\n\tconst idMatches = request.agent === child.childId\n\t\t|| request.agent === child.agent\n\t\t|| request.childTarget === child.childId;\n\treturn indexMatches && idMatches;\n}\n\nexport function reconcileAsyncQuestion(channelDir: string, question: SupervisorQuestion, state: SubagentState): SupervisorQuestion {\n\texpireSupervisorQuestion(channelDir, question.id);\n\tconst current = readSupervisorQuestion(channelDir, question.id) ?? question;\n\tif (supervisorQuestionIsTerminal(current)) return current;\n\tconst resolved = resolveSubagentRunId(current.runId, { state });\n\tif (resolved?.kind !== \"async\" || !resolved.location.asyncDir) return current;\n\tconst status = readStatus(resolved.location.asyncDir);\n\tif (!status) return current;\n\tconst step = status.steps?.[current.childIndex];\n\tconst capability = readSteerCapability(resolved.location.asyncDir, current.childIndex);\n\tlet reason: string | undefined;\n\tif (status.sessionId !== current.parentSessionId) reason = \"async run ownership changed\";\n\telse if (status.state !== \"running\" || !step || step.status !== \"running\") reason = \"target child is no longer running\";\n\telse if ((step.childId ?? step.agent) !== current.childId) reason = \"target child identity changed\";\n\telse if (capability && !incarnationMatches(current.childIncarnation, capability)) reason = \"target child process changed\";\n\telse if (capability && !capability.supported) reason = \"target child no longer accepts questions\";\n\tconst delivery = status.steering?.recent.find((request) => request.id === current.id)?.targets.find((target) => target.index === current.childIndex);\n\tif (delivery?.state === \"failed\" || delivery?.state === \"late\") reason = delivery.reason ?? \"question delivery failed\";\n\treturn reason ? cancelSupervisorQuestion(channelDir, current.id, reason) ?? current : current;\n}\n\nexport function askRunningAsyncChild(input: {\n\tparams: ParentAskParams;\n\tstate: SubagentState;\n\tchildRequests?: Iterable<ParentAskRequestFile>;\n}): AgentToolResult<Record<string, unknown>> {\n\tconst runId = input.params.id?.trim();\n\tif (!runId) throw new Error(\"action='ask' requires id for the async run.\");\n\tconst reason = input.params.reason?.trim();\n\tconst message = input.params.message?.trim();\n\tif (!reason) throw new Error(\"action='ask' requires reason naming the concrete decision the child's answer will change.\");\n\tif (!message) throw new Error(\"action='ask' requires message.\");\n\tconst sessionId = input.state.currentSessionId;\n\tif (!sessionId) throw new Error(\"action='ask' requires an active session identity.\");\n\n\tconst resolved = resolveSubagentRunId(runId, { state: input.state });\n\tif (!resolved) throw new Error(`No async run matched '${runId}'.`);\n\tif (resolved.kind !== \"async\") throw new Error(\"action='ask' targets a running async child only. It does not revive, reassign, or broadcast.\");\n\tif (!resolved.location.asyncDir) throw new Error(`Async run '${resolved.id}' has no live run directory.`);\n\n\tconst status = readStatus(resolved.location.asyncDir);\n\tif (!status) throw new Error(`Async run '${resolved.id}' has no status.`);\n\tif (!status.sessionId || status.sessionId !== sessionId) {\n\t\tthrow new Error(`Async run '${resolved.id}' was not found in the active session.`);\n\t}\n\tif (status.state !== \"running\") throw new Error(`Async run '${resolved.id}' is ${status.state} and cannot be asked.`);\n\n\tconst child = resolveAskChild(status, input.params);\n\tconst channelDir = resolveSupervisorChannelDir(status.runId, child.childId, child.index);\n\tif (hasOutstandingQuestionForChild(channelDir, child.index, child.childId)) {\n\t\tthrow new Error(`A question is already outstanding for async run '${status.runId}' child ${child.index}. Wait for that answer or expiry before asking again.`);\n\t}\n\tfor (const request of input.childRequests ?? []) {\n\t\tif (requestMatchesChild(request, status.runId, child)) {\n\t\t\tthrow new Error(`Child ${child.index} is waiting for a supervisor reply. Asking now would deadlock. Reply to the child request first.`);\n\t\t}\n\t}\n\n\tif (hasBlockingSupervisorRequest(channelDir, status.runId, child.index)) {\n\t\tthrow new Error(\"Child is waiting for a supervisor reply. Reply to its request before asking a question.\");\n\t}\n\tconst capability = readSteerCapability(resolved.location.asyncDir, child.index);\n\tif (!capability?.supported) {\n\t\tthrow new Error(\"This child is not ready to receive questions. Continue other work until it is ready; no question was queued.\");\n\t}\n\tconst incarnation: SupervisorChildIncarnation = { pid: capability.pid, readyAt: capability.readyAt };\n\tconst question: SupervisorQuestion = createSupervisorQuestion({\n\t\tchannelDir,\n\t\treason,\n\t\tmessage,\n\t\trunId: status.runId,\n\t\tchildIndex: child.index,\n\t\tchildId: child.childId,\n\t\tparentSessionId: sessionId,\n\t\tparentGeneration: input.state.sessionGeneration ?? 0,\n\t\tchildIncarnation: incarnation,\n\t});\n\ttry {\n\t\tif (hasBlockingSupervisorRequest(channelDir, status.runId, child.index)) {\n\t\t\tthrow new Error(\"Child is waiting for a supervisor reply. Reply to its request before asking a question.\");\n\t\t}\n\t\trequestAsyncSteer(resolved.location.asyncDir, {\n\t\t\tmessage: formatParentQuestionForChild(question),\n\t\t\ttargetIndex: child.index,\n\t\t\tsource: \"supervisor-question\",\n\t\t\tid: question.id,\n\t\t});\n\t} catch (error) {\n\t\tcancelSupervisorQuestion(channelDir, question.id, \"failed to queue delivery to child\");\n\t\tthrow error instanceof Error ? error : new Error(String(error));\n\t}\n\treturn {\n\t\tcontent: [{ type: \"text\", text: `Question ${question.id} queued for async run ${status.runId} child ${child.index}. The child's answer is delivered separately from the run result.` }],\n\t\tdetails: {\n\t\t\tquestionId: question.id,\n\t\t\tstate: \"pending\",\n\t\t\trunId: status.runId,\n\t\t\tchildIndex: child.index,\n\t\t\tchildId: child.childId,\n\t\t\tdelivered: false,\n\t\t\tanswered: false,\n\t\t},\n\t};\n}\n"]}
@@ -0,0 +1,89 @@
1
+ export declare const QUESTIONS_DIR = "questions";
2
+ export declare const SUPERVISOR_CHANNEL_ROOT: string;
3
+ export declare const SUBAGENT_SUPERVISOR_ANSWER_TYPE = "subagent_supervisor_answer";
4
+ export declare const SUBAGENT_QUESTION_EVENT = "subagent:supervisor-question";
5
+ export type SupervisorQuestionPublicState = "pending" | "answered" | "expired" | "cancelled";
6
+ export interface SupervisorChildIncarnation {
7
+ pid: number;
8
+ readyAt: number;
9
+ }
10
+ export interface SupervisorQuestion {
11
+ type: "subagent.supervisor.question";
12
+ id: string;
13
+ createdAt: number;
14
+ expiresAt: number;
15
+ reason: string;
16
+ message: string;
17
+ runId: string;
18
+ childIndex: number;
19
+ childId: string;
20
+ parentSessionId: string;
21
+ parentGeneration: number;
22
+ childIncarnation?: SupervisorChildIncarnation;
23
+ deliveredAt?: number;
24
+ answeredAt?: number;
25
+ expiredAt?: number;
26
+ cancelledAt?: number;
27
+ cancelReason?: string;
28
+ notifiedAt?: number;
29
+ lateAnswerAt?: number;
30
+ answer?: string;
31
+ }
32
+ export interface SupervisorQuestionOwner {
33
+ runId: string;
34
+ childIndex: number;
35
+ childId: string;
36
+ pid: number;
37
+ readyAt: number;
38
+ }
39
+ export declare function resolveSupervisorChannelDir(runId: string, agent: string, childIndex: number): string;
40
+ export declare function questionsDir(channelDir: string): string;
41
+ export declare function ensureQuestionsDir(channelDir: string): void;
42
+ export declare function supervisorQuestionPublicState(question: SupervisorQuestion): SupervisorQuestionPublicState;
43
+ export declare function supervisorQuestionIsTerminal(question: SupervisorQuestion): boolean;
44
+ export declare function readSupervisorQuestion(channelDir: string, questionId: string): SupervisorQuestion | undefined;
45
+ export declare function listSupervisorQuestions(channelDir: string): SupervisorQuestion[];
46
+ export declare function createSupervisorQuestion(input: {
47
+ channelDir: string;
48
+ reason: string;
49
+ message: string;
50
+ runId: string;
51
+ childIndex: number;
52
+ childId: string;
53
+ parentSessionId: string;
54
+ parentGeneration: number;
55
+ childIncarnation?: SupervisorChildIncarnation;
56
+ now?: number;
57
+ timeoutMs?: number;
58
+ id?: string;
59
+ }): SupervisorQuestion;
60
+ export declare function outstandingQuestionsForChild(channelDir: string, childIndex: number, childId?: string): SupervisorQuestion[];
61
+ export declare function hasBlockingSupervisorRequest(channelDir: string, runId: string, childIndex: number): boolean;
62
+ export declare function hasOutstandingQuestionForChild(channelDir: string, childIndex: number, childId?: string): boolean;
63
+ export declare function incarnationMatches(expected: SupervisorChildIncarnation | undefined, actual: SupervisorChildIncarnation): boolean;
64
+ export declare function markSupervisorQuestionDelivered(channelDir: string, questionId: string, owner: SupervisorQuestionOwner, now?: number): SupervisorQuestion | undefined;
65
+ export declare function answerSupervisorQuestion(channelDir: string, questionId: string, answer: string, owner: SupervisorQuestionOwner, now?: number): SupervisorQuestion;
66
+ export declare function expireSupervisorQuestion(channelDir: string, questionId: string, now?: number): SupervisorQuestion | undefined;
67
+ export declare function cancelSupervisorQuestion(channelDir: string, questionId: string, reason: string, now?: number): SupervisorQuestion | undefined;
68
+ export declare function refreshSupervisorQuestionLifecycle(channelDir: string, now?: number): SupervisorQuestion[];
69
+ export declare function formatParentQuestionForChild(question: SupervisorQuestion): string;
70
+ export declare function formatSupervisorQuestionAnswer(question: SupervisorQuestion): string;
71
+ export declare function registerQuestionWait(questionIds: Iterable<string>): () => void;
72
+ export declare function isQuestionWaitActive(questionId: string): boolean;
73
+ export declare function claimQuestionNotification(channelDir: string, questionId: string, now?: number): boolean;
74
+ export declare function markSupervisorQuestionNotified(channelDir: string, questionId: string, now?: number): SupervisorQuestion | undefined;
75
+ export declare function resetSupervisorQuestionTestState(): void;
76
+ export declare function listSupervisorChannelDirs(): string[];
77
+ export declare function findSupervisorQuestion(questionId: string): {
78
+ channelDir: string;
79
+ question: SupervisorQuestion;
80
+ } | undefined;
81
+ export declare function cancelPendingSupervisorQuestionsForOwner(input: {
82
+ parentSessionId: string;
83
+ parentGeneration?: number;
84
+ runId?: string;
85
+ reason: string;
86
+ now?: number;
87
+ }): SupervisorQuestion[];
88
+ export declare function pendingSupervisorQuestionsForDelivery(channelDir: string, owner: SupervisorQuestionOwner, now?: number): SupervisorQuestion[];
89
+ //# sourceMappingURL=supervisor-questions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supervisor-questions.d.ts","sourceRoot":"","sources":["../../../../../src/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { TEMP_ROOT_DIR } from \"../shared/types.ts\";\n\nexport const QUESTIONS_DIR = \"questions\";\nexport const SUPERVISOR_CHANNEL_ROOT = path.join(TEMP_ROOT_DIR, \"supervisor-channels\");\nexport const SUBAGENT_SUPERVISOR_ANSWER_TYPE = \"subagent_supervisor_answer\";\nexport const SUBAGENT_QUESTION_EVENT = \"subagent:supervisor-question\";\n\nexport type SupervisorQuestionPublicState = \"pending\" | \"answered\" | \"expired\" | \"cancelled\";\n\nexport interface SupervisorChildIncarnation {\n\tpid: number;\n\treadyAt: number;\n}\n\nexport interface SupervisorQuestion {\n\ttype: \"subagent.supervisor.question\";\n\tid: string;\n\tcreatedAt: number;\n\texpiresAt: number;\n\treason: string;\n\tmessage: string;\n\trunId: string;\n\tchildIndex: number;\n\tchildId: string;\n\tparentSessionId: string;\n\tparentGeneration: number;\n\tchildIncarnation?: SupervisorChildIncarnation;\n\tdeliveredAt?: number;\n\tansweredAt?: number;\n\texpiredAt?: number;\n\tcancelledAt?: number;\n\tcancelReason?: string;\n\tnotifiedAt?: number;\n\tlateAnswerAt?: number;\n\tanswer?: string;\n}\n\nexport interface SupervisorQuestionOwner {\n\trunId: string;\n\tchildIndex: number;\n\tchildId: string;\n\tpid: number;\n\treadyAt: number;\n}\n\ninterface QuestionRecord {\n\ttype: \"subagent.supervisor.question\";\n\tid: string;\n\tcreatedAt: number;\n\texpiresAt: number;\n\treason: string;\n\tmessage: string;\n\trunId: string;\n\tchildIndex: number;\n\tchildId: string;\n\tparentSessionId: string;\n\tparentGeneration: number;\n\tchildIncarnation?: SupervisorChildIncarnation;\n}\n\ninterface DeliveredRecord {\n\ttype: \"subagent.supervisor.delivered\";\n\tid: string;\n\tat: number;\n\tpid: number;\n\treadyAt: number;\n}\n\ntype TerminalRecord =\n\t| { type: \"subagent.supervisor.terminal\"; id: string; state: \"answered\"; at: number; message: string }\n\t| { type: \"subagent.supervisor.terminal\"; id: string; state: \"expired\"; at: number }\n\t| { type: \"subagent.supervisor.terminal\"; id: string; state: \"cancelled\"; at: number; reason: string };\n\ninterface NotifiedRecord {\n\ttype: \"subagent.supervisor.notified\";\n\tid: string;\n\tat: number;\n}\n\ninterface LateAnswerRecord {\n\ttype: \"subagent.supervisor.late-answer\";\n\tid: string;\n\tat: number;\n\tmessage: string;\n}\n\nconst MAX_MESSAGE_BYTES = 64 * 1024;\nconst DEFAULT_ASK_TIMEOUT_MS = 10 * 60 * 1000;\nconst activeQuestionWaits = new Set<string>();\n\nfunction askTimeoutMs(): number {\n\tconst parsed = Number(process.env.PI_INTERCOM_ASK_TIMEOUT_MS);\n\treturn Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_ASK_TIMEOUT_MS;\n}\n\nfunction safeSegment(value: string): string {\n\treturn value.trim().replace(/[^A-Za-z0-9._-]+/g, \"-\").replace(/^-+|-+$/g, \"\") || \"unknown\";\n}\n\nexport function resolveSupervisorChannelDir(runId: string, agent: string, childIndex: number): string {\n\treturn path.join(SUPERVISOR_CHANNEL_ROOT, `${safeSegment(runId)}-${safeSegment(agent)}-${childIndex}`);\n}\n\nexport function questionsDir(channelDir: string): string {\n\treturn path.join(channelDir, QUESTIONS_DIR);\n}\n\nfunction questionFile(channelDir: string, questionId: string): string {\n\treturn path.join(questionsDir(channelDir), `${safeSegment(questionId)}.json`);\n}\n\nfunction deliveredFile(channelDir: string, questionId: string): string {\n\treturn path.join(questionsDir(channelDir), `${safeSegment(questionId)}.delivered.json`);\n}\n\nfunction terminalFile(channelDir: string, questionId: string): string {\n\treturn path.join(questionsDir(channelDir), `${safeSegment(questionId)}.terminal.json`);\n}\n\nfunction notifiedFile(channelDir: string, questionId: string): string {\n\treturn path.join(questionsDir(channelDir), `${safeSegment(questionId)}.notified.json`);\n}\n\nfunction lateFile(channelDir: string, questionId: string): string {\n\treturn path.join(questionsDir(channelDir), `${safeSegment(questionId)}.late.json`);\n}\n\nfunction writeExclusiveJson(filePath: string, payload: object): boolean {\n\tfs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });\n\tconst temporary = `${filePath}.${randomUUID()}.tmp`;\n\ttry {\n\t\tfs.writeFileSync(temporary, JSON.stringify(payload), { encoding: \"utf-8\", flag: \"wx\", mode: 0o600 });\n\t\t// Publish a complete record without overwriting a competing terminal outcome.\n\t\tfs.linkSync(temporary, filePath);\n\t\treturn true;\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"EEXIST\") return false;\n\t\tthrow error;\n\t} finally {\n\t\tfs.rmSync(temporary, { force: true });\n\t}\n}\n\nfunction readJsonFile(filePath: string): unknown {\n\treturn JSON.parse(fs.readFileSync(filePath, \"utf-8\"));\n}\n\nfunction tryReadJson(filePath: string): unknown | undefined {\n\ttry {\n\t\treturn readJsonFile(filePath);\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n\t\treturn undefined;\n\t}\n}\n\nfunction parseIncarnation(raw: unknown): SupervisorChildIncarnation | undefined {\n\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n\tconst input = raw as Partial<SupervisorChildIncarnation>;\n\tconst pid = input.pid;\n\tconst readyAt = input.readyAt;\n\tif (!Number.isInteger(pid) || pid === undefined || pid <= 0) return undefined;\n\tif (typeof readyAt !== \"number\" || !Number.isFinite(readyAt) || readyAt <= 0) return undefined;\n\treturn { pid, readyAt };\n}\n\nfunction parseQuestionRecord(raw: unknown): QuestionRecord | undefined {\n\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n\tconst input = raw as Partial<QuestionRecord>;\n\tif (input.type !== \"subagent.supervisor.question\") return undefined;\n\tif (typeof input.id !== \"string\" || !input.id.trim()) return undefined;\n\tif (typeof input.createdAt !== \"number\" || !Number.isFinite(input.createdAt)) return undefined;\n\tif (typeof input.expiresAt !== \"number\" || !Number.isFinite(input.expiresAt)) return undefined;\n\tif (typeof input.reason !== \"string\" || !input.reason.trim()) return undefined;\n\tif (typeof input.message !== \"string\" || !input.message.trim()) return undefined;\n\tif (typeof input.runId !== \"string\" || !input.runId.trim()) return undefined;\n\tconst childIndex = input.childIndex;\n\tif (!Number.isInteger(childIndex) || childIndex === undefined || childIndex < 0) return undefined;\n\tif (typeof input.childId !== \"string\" || !input.childId.trim()) return undefined;\n\tif (typeof input.parentSessionId !== \"string\" || !input.parentSessionId.trim()) return undefined;\n\tconst parentGeneration = input.parentGeneration;\n\tif (!Number.isInteger(parentGeneration) || parentGeneration === undefined || parentGeneration < 0) return undefined;\n\tconst incarnation = parseIncarnation(input.childIncarnation);\n\treturn {\n\t\ttype: \"subagent.supervisor.question\",\n\t\tid: input.id.trim(),\n\t\tcreatedAt: input.createdAt,\n\t\texpiresAt: input.expiresAt,\n\t\treason: input.reason.trim(),\n\t\tmessage: input.message.trim(),\n\t\trunId: input.runId.trim(),\n\t\tchildIndex,\n\t\tchildId: input.childId.trim(),\n\t\tparentSessionId: input.parentSessionId.trim(),\n\t\tparentGeneration,\n\t\t...(incarnation ? { childIncarnation: incarnation } : {}),\n\t};\n}\n\nfunction parseDeliveredRecord(raw: unknown): DeliveredRecord | undefined {\n\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n\tconst input = raw as Partial<DeliveredRecord>;\n\tif (input.type !== \"subagent.supervisor.delivered\" || typeof input.id !== \"string\" || !input.id.trim()) return undefined;\n\tif (typeof input.at !== \"number\" || !Number.isFinite(input.at)) return undefined;\n\tconst incarnation = parseIncarnation(input);\n\tif (!incarnation) return undefined;\n\treturn { type: \"subagent.supervisor.delivered\", id: input.id.trim(), at: input.at, pid: incarnation.pid, readyAt: incarnation.readyAt };\n}\n\nfunction parseTerminalRecord(raw: unknown): TerminalRecord | undefined {\n\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n\tconst input = raw as Partial<TerminalRecord> & { message?: unknown; reason?: unknown };\n\tif (input.type !== \"subagent.supervisor.terminal\" || typeof input.id !== \"string\" || !input.id.trim()) return undefined;\n\tif (typeof input.at !== \"number\" || !Number.isFinite(input.at)) return undefined;\n\tif (input.state === \"answered\") {\n\t\tif (typeof input.message !== \"string\" || !input.message.trim()) return undefined;\n\t\treturn { type: \"subagent.supervisor.terminal\", id: input.id.trim(), state: \"answered\", at: input.at, message: input.message };\n\t}\n\tif (input.state === \"expired\") {\n\t\treturn { type: \"subagent.supervisor.terminal\", id: input.id.trim(), state: \"expired\", at: input.at };\n\t}\n\tif (input.state === \"cancelled\") {\n\t\tif (typeof input.reason !== \"string\" || !input.reason.trim()) return undefined;\n\t\treturn { type: \"subagent.supervisor.terminal\", id: input.id.trim(), state: \"cancelled\", at: input.at, reason: input.reason.trim() };\n\t}\n\treturn undefined;\n}\n\nfunction parseNotifiedRecord(raw: unknown): NotifiedRecord | undefined {\n\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n\tconst input = raw as Partial<NotifiedRecord>;\n\tif (input.type !== \"subagent.supervisor.notified\" || typeof input.id !== \"string\" || !input.id.trim()) return undefined;\n\tif (typeof input.at !== \"number\" || !Number.isFinite(input.at)) return undefined;\n\treturn { type: \"subagent.supervisor.notified\", id: input.id.trim(), at: input.at };\n}\n\nfunction parseLateRecord(raw: unknown): LateAnswerRecord | undefined {\n\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n\tconst input = raw as Partial<LateAnswerRecord>;\n\tif (input.type !== \"subagent.supervisor.late-answer\" || typeof input.id !== \"string\" || !input.id.trim()) return undefined;\n\tif (typeof input.at !== \"number\" || !Number.isFinite(input.at) || typeof input.message !== \"string\") return undefined;\n\treturn { type: \"subagent.supervisor.late-answer\", id: input.id.trim(), at: input.at, message: input.message };\n}\n\nfunction composeQuestion(record: QuestionRecord, channelDir: string): SupervisorQuestion {\n\tconst delivered = parseDeliveredRecord(tryReadJson(deliveredFile(channelDir, record.id)));\n\tconst terminal = parseTerminalRecord(tryReadJson(terminalFile(channelDir, record.id)));\n\tconst notified = parseNotifiedRecord(tryReadJson(notifiedFile(channelDir, record.id)));\n\tconst late = parseLateRecord(tryReadJson(lateFile(channelDir, record.id)));\n\treturn {\n\t\t...record,\n\t\t...(delivered ? { deliveredAt: delivered.at, childIncarnation: record.childIncarnation ?? { pid: delivered.pid, readyAt: delivered.readyAt } } : {}),\n\t\t...(terminal?.state === \"answered\" ? { answeredAt: terminal.at, answer: terminal.message } : {}),\n\t\t...(terminal?.state === \"expired\" ? { expiredAt: terminal.at } : {}),\n\t\t...(terminal?.state === \"cancelled\" ? { cancelledAt: terminal.at, cancelReason: terminal.reason } : {}),\n\t\t...(notified ? { notifiedAt: notified.at } : {}),\n\t\t...(late ? { lateAnswerAt: late.at, ...(terminal?.state === \"answered\" ? {} : { answer: late.message }) } : {}),\n\t};\n}\n\nfunction assertMessageSize(value: string, label: string): void {\n\tif (Buffer.byteLength(value, \"utf-8\") > MAX_MESSAGE_BYTES) throw new Error(`${label} is too large.`);\n}\n\nexport function ensureQuestionsDir(channelDir: string): void {\n\tfs.mkdirSync(questionsDir(channelDir), { recursive: true, mode: 0o700 });\n}\n\nexport function supervisorQuestionPublicState(question: SupervisorQuestion): SupervisorQuestionPublicState {\n\tif (question.answeredAt) return \"answered\";\n\tif (question.expiredAt) return \"expired\";\n\tif (question.cancelledAt) return \"cancelled\";\n\treturn \"pending\";\n}\n\nexport function supervisorQuestionIsTerminal(question: SupervisorQuestion): boolean {\n\treturn supervisorQuestionPublicState(question) !== \"pending\";\n}\n\nexport function readSupervisorQuestion(channelDir: string, questionId: string): SupervisorQuestion | undefined {\n\tconst record = parseQuestionRecord(tryReadJson(questionFile(channelDir, questionId)));\n\tif (!record || record.id !== questionId) return undefined;\n\treturn composeQuestion(record, channelDir);\n}\n\nexport function listSupervisorQuestions(channelDir: string): SupervisorQuestion[] {\n\tconst dir = questionsDir(channelDir);\n\tlet entries: string[];\n\ttry {\n\t\tentries = fs.readdirSync(dir).filter((name) => name.endsWith(\".json\") && !name.endsWith(\".delivered.json\") && !name.endsWith(\".terminal.json\") && !name.endsWith(\".notified.json\") && !name.endsWith(\".late.json\"));\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n\t\tthrow error;\n\t}\n\tconst questions: SupervisorQuestion[] = [];\n\tfor (const entry of entries.sort()) {\n\t\tconst record = parseQuestionRecord(tryReadJson(path.join(dir, entry)));\n\t\tif (record) questions.push(composeQuestion(record, channelDir));\n\t}\n\treturn questions;\n}\n\nfunction writeTerminal(channelDir: string, record: TerminalRecord): boolean {\n\treturn writeExclusiveJson(terminalFile(channelDir, record.id), record);\n}\n\nfunction readTerminal(channelDir: string, questionId: string): TerminalRecord | undefined {\n\treturn parseTerminalRecord(tryReadJson(terminalFile(channelDir, questionId)));\n}\n\nexport function createSupervisorQuestion(input: {\n\tchannelDir: string;\n\treason: string;\n\tmessage: string;\n\trunId: string;\n\tchildIndex: number;\n\tchildId: string;\n\tparentSessionId: string;\n\tparentGeneration: number;\n\tchildIncarnation?: SupervisorChildIncarnation;\n\tnow?: number;\n\ttimeoutMs?: number;\n\tid?: string;\n}): SupervisorQuestion {\n\tconst reason = input.reason.trim();\n\tconst message = input.message.trim();\n\tif (!reason) throw new Error(\"reason is required and must name the concrete decision the child's answer will change.\");\n\tif (!message) throw new Error(\"message is required for supervisor questions.\");\n\tassertMessageSize(reason, \"reason\");\n\tassertMessageSize(message, \"message\");\n\tconst createdAt = input.now ?? Date.now();\n\tconst timeoutMs = input.timeoutMs && input.timeoutMs > 0 ? input.timeoutMs : askTimeoutMs();\n\tconst record: QuestionRecord = {\n\t\ttype: \"subagent.supervisor.question\",\n\t\tid: input.id ?? randomUUID(),\n\t\tcreatedAt,\n\t\texpiresAt: createdAt + timeoutMs,\n\t\treason,\n\t\tmessage,\n\t\trunId: input.runId,\n\t\tchildIndex: input.childIndex,\n\t\tchildId: input.childId,\n\t\tparentSessionId: input.parentSessionId,\n\t\tparentGeneration: input.parentGeneration,\n\t\t...(input.childIncarnation ? { childIncarnation: input.childIncarnation } : {}),\n\t};\n\tassertMessageSize(JSON.stringify(record), \"Supervisor question\");\n\tensureQuestionsDir(input.channelDir);\n\tif (!writeExclusiveJson(questionFile(input.channelDir, record.id), record)) {\n\t\tthrow new Error(`Supervisor question '${record.id}' already exists.`);\n\t}\n\treturn composeQuestion(record, input.channelDir);\n}\n\nexport function outstandingQuestionsForChild(channelDir: string, childIndex: number, childId?: string): SupervisorQuestion[] {\n\trefreshSupervisorQuestionLifecycle(channelDir);\n\treturn listSupervisorQuestions(channelDir).filter((question) => {\n\t\tif (supervisorQuestionIsTerminal(question)) return false;\n\t\tif (question.childIndex !== childIndex) return false;\n\t\tif (childId && question.childId !== childId) return false;\n\t\treturn true;\n\t});\n}\n\nexport function hasBlockingSupervisorRequest(channelDir: string, runId: string, childIndex: number): boolean {\n\tconst directory = path.join(channelDir, \"requests\");\n\tif (!fs.existsSync(directory)) return false;\n\tfor (const name of fs.readdirSync(directory)) {\n\t\tif (!name.endsWith(\".json\")) continue;\n\t\tconst raw = tryReadJson(path.join(directory, name));\n\t\tif (!raw || typeof raw !== \"object\") continue;\n\t\tconst request = raw as { type?: unknown; id?: unknown; expectsReply?: unknown; runId?: unknown; childIndex?: unknown; expiresAt?: unknown };\n\t\tif (request.type !== \"subagent.supervisor.request\" || request.expectsReply !== true) continue;\n\t\tif (request.runId !== runId || request.childIndex !== childIndex || typeof request.id !== \"string\") continue;\n\t\tif (typeof request.expiresAt === \"number\" && request.expiresAt <= Date.now()) continue;\n\t\tif (!fs.existsSync(path.join(channelDir, \"replies\", `${safeSegment(request.id)}.json`))) return true;\n\t}\n\treturn false;\n}\n\nexport function hasOutstandingQuestionForChild(channelDir: string, childIndex: number, childId?: string): boolean {\n\treturn outstandingQuestionsForChild(channelDir, childIndex, childId).length > 0;\n}\n\nexport function incarnationMatches(expected: SupervisorChildIncarnation | undefined, actual: SupervisorChildIncarnation): boolean {\n\tif (!expected) return true;\n\treturn expected.pid === actual.pid && expected.readyAt === actual.readyAt;\n}\n\nfunction assertOwner(question: SupervisorQuestion, owner: SupervisorQuestionOwner): void {\n\tif (owner.runId !== question.runId || owner.childIndex !== question.childIndex || owner.childId !== question.childId) {\n\t\tthrow new Error(`Supervisor question '${question.id}' is not owned by this child.`);\n\t}\n\tif (!incarnationMatches(question.childIncarnation, { pid: owner.pid, readyAt: owner.readyAt })) {\n\t\tthrow new Error(`Supervisor question '${question.id}' was bound to a different child incarnation.`);\n\t}\n}\n\nfunction ownerMatchesDelivered(channelDir: string, questionId: string, owner: SupervisorQuestionOwner): boolean {\n\tconst delivered = parseDeliveredRecord(tryReadJson(deliveredFile(channelDir, questionId)));\n\tif (!delivered) return true;\n\treturn delivered.pid === owner.pid && delivered.readyAt === owner.readyAt;\n}\n\nexport function markSupervisorQuestionDelivered(\n\tchannelDir: string,\n\tquestionId: string,\n\towner: SupervisorQuestionOwner,\n\tnow = Date.now(),\n): SupervisorQuestion | undefined {\n\tconst current = readSupervisorQuestion(channelDir, questionId);\n\tif (!current || supervisorQuestionIsTerminal(current)) return current;\n\tassertOwner(current, owner);\n\twriteExclusiveJson(deliveredFile(channelDir, questionId), {\n\t\ttype: \"subagent.supervisor.delivered\",\n\t\tid: questionId,\n\t\tat: now,\n\t\tpid: owner.pid,\n\t\treadyAt: owner.readyAt,\n\t} satisfies DeliveredRecord);\n\treturn readSupervisorQuestion(channelDir, questionId);\n}\n\nfunction rejectLateOrDuplicate(channelDir: string, questionId: string, answer: string, now: number, terminal: TerminalRecord): never {\n\twriteExclusiveJson(lateFile(channelDir, questionId), {\n\t\ttype: \"subagent.supervisor.late-answer\",\n\t\tid: questionId,\n\t\tat: now,\n\t\tmessage: answer,\n\t} satisfies LateAnswerRecord);\n\tif (terminal.state === \"answered\") throw new Error(`Supervisor question '${questionId}' was already answered.`);\n\tthrow new Error(`Supervisor question '${questionId}' is ${terminal.state} and no longer accepts an answer.`);\n}\n\nexport function answerSupervisorQuestion(\n\tchannelDir: string,\n\tquestionId: string,\n\tanswer: string,\n\towner: SupervisorQuestionOwner,\n\tnow = Date.now(),\n): SupervisorQuestion {\n\tconst trimmed = answer.trim();\n\tif (!trimmed) throw new Error(\"message is required for supervisor question replies.\");\n\tassertMessageSize(trimmed, \"answer\");\n\tconst current = readSupervisorQuestion(channelDir, questionId);\n\tif (!current) throw new Error(`No supervisor question found for replyTo '${questionId}'.`);\n\tassertOwner(current, owner);\n\tif (!ownerMatchesDelivered(channelDir, questionId, owner)) {\n\t\tthrow new Error(`Supervisor question '${questionId}' was bound to a different child incarnation.`);\n\t}\n\tif (now > current.expiresAt) {\n\t\twriteTerminal(channelDir, { type: \"subagent.supervisor.terminal\", id: questionId, state: \"expired\", at: now });\n\t\tconst terminal = readTerminal(channelDir, questionId);\n\t\tif (terminal && terminal.state !== \"answered\") {\n\t\t\trejectLateOrDuplicate(channelDir, questionId, trimmed, now, terminal);\n\t\t}\n\t\tif (terminal?.state === \"answered\") throw new Error(`Supervisor question '${questionId}' was already answered.`);\n\t}\n\tconst existing = readTerminal(channelDir, questionId);\n\tif (existing) rejectLateOrDuplicate(channelDir, questionId, trimmed, now, existing);\n\tif (!writeTerminal(channelDir, { type: \"subagent.supervisor.terminal\", id: questionId, state: \"answered\", at: now, message: trimmed })) {\n\t\tconst terminal = readTerminal(channelDir, questionId);\n\t\tif (terminal) rejectLateOrDuplicate(channelDir, questionId, trimmed, now, terminal);\n\t\tthrow new Error(`Supervisor question '${questionId}' is no longer pending.`);\n\t}\n\tconst answered = readSupervisorQuestion(channelDir, questionId);\n\tif (!answered) throw new Error(`Supervisor question '${questionId}' is no longer pending.`);\n\treturn answered;\n}\n\nexport function expireSupervisorQuestion(channelDir: string, questionId: string, now = Date.now()): SupervisorQuestion | undefined {\n\tconst current = readSupervisorQuestion(channelDir, questionId);\n\tif (!current || supervisorQuestionIsTerminal(current) || now <= current.expiresAt) return current && supervisorQuestionIsTerminal(current) ? current : undefined;\n\tif (!writeTerminal(channelDir, { type: \"subagent.supervisor.terminal\", id: questionId, state: \"expired\", at: now })) return readSupervisorQuestion(channelDir, questionId);\n\treturn readSupervisorQuestion(channelDir, questionId);\n}\n\nexport function cancelSupervisorQuestion(\n\tchannelDir: string,\n\tquestionId: string,\n\treason: string,\n\tnow = Date.now(),\n): SupervisorQuestion | undefined {\n\tconst current = readSupervisorQuestion(channelDir, questionId);\n\tif (!current || supervisorQuestionIsTerminal(current)) return current;\n\tif (!writeTerminal(channelDir, { type: \"subagent.supervisor.terminal\", id: questionId, state: \"cancelled\", at: now, reason: reason.trim() || \"cancelled\" })) {\n\t\treturn readSupervisorQuestion(channelDir, questionId);\n\t}\n\treturn readSupervisorQuestion(channelDir, questionId);\n}\n\nexport function refreshSupervisorQuestionLifecycle(channelDir: string, now = Date.now()): SupervisorQuestion[] {\n\tconst changed: SupervisorQuestion[] = [];\n\tfor (const question of listSupervisorQuestions(channelDir)) {\n\t\tif (supervisorQuestionIsTerminal(question)) continue;\n\t\tif (now > question.expiresAt) {\n\t\t\tconst expired = expireSupervisorQuestion(channelDir, question.id, now);\n\t\t\tif (expired && expired.expiredAt) changed.push(expired);\n\t\t}\n\t}\n\treturn changed;\n}\n\nexport function formatParentQuestionForChild(question: SupervisorQuestion): string {\n\treturn [\n\t\t`Parent question (${question.id})`,\n\t\t`Decision needed: ${question.reason}`,\n\t\t\"\",\n\t\tquestion.message,\n\t\t\"\",\n\t\t`Reply with: contact_supervisor({ action: \"reply\", replyTo: \"${question.id}\", message: \"...\" })`,\n\t\t\"Answer from current findings and uncertainty. Do not silently start extra investigation. Continue the assigned task after replying.\",\n\t].join(\"\\n\");\n}\n\nexport function formatSupervisorQuestionAnswer(question: SupervisorQuestion): string {\n\tconst state = supervisorQuestionPublicState(question);\n\tconst header = state === \"answered\"\n\t\t? `Subagent answer (${question.id})`\n\t\t: `Subagent question ${state} (${question.id})`;\n\tconst lines = [\n\t\theader,\n\t\t`Run: ${question.runId}`,\n\t\t`Child: ${question.childId} [#${question.childIndex}]`,\n\t\t`Decision: ${question.reason}`,\n\t];\n\tif (state === \"answered\" && question.answer?.trim()) {\n\t\tlines.push(\"\", question.answer.trim());\n\t} else if (question.cancelReason) {\n\t\tlines.push(\"\", question.cancelReason);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nexport function registerQuestionWait(questionIds: Iterable<string>): () => void {\n\tconst ids = [...questionIds];\n\tfor (const id of ids) activeQuestionWaits.add(id);\n\treturn () => {\n\t\tfor (const id of ids) activeQuestionWaits.delete(id);\n\t};\n}\n\nexport function isQuestionWaitActive(questionId: string): boolean {\n\treturn activeQuestionWaits.has(questionId);\n}\n\nexport function claimQuestionNotification(channelDir: string, questionId: string, now = Date.now()): boolean {\n\treturn writeExclusiveJson(notifiedFile(channelDir, questionId), {\n\t\ttype: \"subagent.supervisor.notified\",\n\t\tid: questionId,\n\t\tat: now,\n\t} satisfies NotifiedRecord);\n}\n\nexport function markSupervisorQuestionNotified(channelDir: string, questionId: string, now = Date.now()): SupervisorQuestion | undefined {\n\tclaimQuestionNotification(channelDir, questionId, now);\n\treturn readSupervisorQuestion(channelDir, questionId);\n}\n\nexport function resetSupervisorQuestionTestState(): void {\n\tactiveQuestionWaits.clear();\n}\n\nexport function listSupervisorChannelDirs(): string[] {\n\tlet entries: fs.Dirent[];\n\ttry {\n\t\tentries = fs.readdirSync(SUPERVISOR_CHANNEL_ROOT, { withFileTypes: true });\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n\t\tthrow error;\n\t}\n\treturn entries.filter((entry) => entry.isDirectory()).map((entry) => path.join(SUPERVISOR_CHANNEL_ROOT, entry.name));\n}\n\nexport function findSupervisorQuestion(questionId: string): { channelDir: string; question: SupervisorQuestion } | undefined {\n\tconst id = questionId.trim();\n\tif (!id) return undefined;\n\tfor (const channelDir of listSupervisorChannelDirs()) {\n\t\tconst question = readSupervisorQuestion(channelDir, id);\n\t\tif (question) return { channelDir, question };\n\t}\n\treturn undefined;\n}\n\nexport function cancelPendingSupervisorQuestionsForOwner(input: {\n\tparentSessionId: string;\n\tparentGeneration?: number;\n\trunId?: string;\n\treason: string;\n\tnow?: number;\n}): SupervisorQuestion[] {\n\tif (!input.parentSessionId?.trim()) return [];\n\tconst now = input.now ?? Date.now();\n\tconst cancelled: SupervisorQuestion[] = [];\n\tfor (const channelDir of listSupervisorChannelDirs()) {\n\t\tfor (const question of listSupervisorQuestions(channelDir)) {\n\t\t\tif (supervisorQuestionIsTerminal(question)) continue;\n\t\t\tif (question.parentSessionId !== input.parentSessionId) continue;\n\t\t\tif (input.parentGeneration !== undefined && question.parentGeneration !== input.parentGeneration) continue;\n\t\t\tif (input.runId && question.runId !== input.runId) continue;\n\t\t\tconst next = cancelSupervisorQuestion(channelDir, question.id, input.reason, now);\n\t\t\tif (next?.cancelledAt) cancelled.push(next);\n\t\t}\n\t}\n\treturn cancelled;\n}\n\nexport function pendingSupervisorQuestionsForDelivery(channelDir: string, owner: SupervisorQuestionOwner, now = Date.now()): SupervisorQuestion[] {\n\trefreshSupervisorQuestionLifecycle(channelDir, now);\n\treturn listSupervisorQuestions(channelDir).filter((question) => {\n\t\tif (supervisorQuestionIsTerminal(question)) return false;\n\t\tif (question.deliveredAt) return false;\n\t\tif (question.runId !== owner.runId || question.childIndex !== owner.childIndex || question.childId !== owner.childId) return false;\n\t\tif (!incarnationMatches(question.childIncarnation, { pid: owner.pid, readyAt: owner.readyAt })) return false;\n\t\treturn now <= question.expiresAt;\n\t});\n}\n"]}