@selesai/code 0.13.15 → 0.13.18

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 (473) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +2 -14
  3. package/dist/bun/cli.d.ts +3 -1
  4. package/dist/bun/cli.js +3 -9
  5. package/dist/bun/{register-bedrock.js → runtime-setup.js} +5 -0
  6. package/dist/bun/sandbox-env-setup.d.ts +1 -0
  7. package/dist/bun/sandbox-env-setup.js +3 -0
  8. package/dist/cli/auth-command.d.ts +23 -0
  9. package/dist/cli/auth-command.js +102 -0
  10. package/dist/cli/config-selector.js +2 -1
  11. package/dist/cli/setup.d.ts +1 -0
  12. package/dist/cli/setup.js +11 -0
  13. package/dist/cli.js +2 -14
  14. package/dist/config.d.ts +3 -2
  15. package/dist/config.js +9 -4
  16. package/dist/core/agent-session-runtime.js +15 -7
  17. package/dist/core/agent-session.d.ts +2 -6
  18. package/dist/core/agent-session.js +15 -4
  19. package/dist/core/compaction/branch-summarization.d.ts +1 -1
  20. package/dist/core/compaction/branch-summarization.js +2 -1
  21. package/dist/core/extensions/loader.js +3 -0
  22. package/dist/core/extensions/types.d.ts +16 -2
  23. package/dist/core/http-dispatcher.js +2 -0
  24. package/dist/core/keybindings.d.ts +5 -0
  25. package/dist/core/keybindings.js +4 -0
  26. package/dist/core/messages.d.ts +1 -1
  27. package/dist/core/model-config.d.ts +15 -0
  28. package/dist/core/model-config.js +3 -0
  29. package/dist/core/model-runtime.d.ts +1 -0
  30. package/dist/core/model-runtime.js +5 -2
  31. package/dist/core/provider-composer.js +8 -2
  32. package/dist/core/session-export.d.ts +3 -0
  33. package/dist/core/session-export.js +31 -0
  34. package/dist/core/session-manager.d.ts +3 -2
  35. package/dist/core/session-manager.js +40 -13
  36. package/dist/core/skills.d.ts +1 -1
  37. package/dist/core/skills.js +4 -2
  38. package/dist/core/system-prompt.js +10 -10
  39. package/dist/core/tools/bash.js +3 -117
  40. package/dist/core/tools/edit.d.ts +1 -12
  41. package/dist/core/tools/edit.js +5 -163
  42. package/dist/core/tools/find.js +4 -55
  43. package/dist/core/tools/grep.js +4 -60
  44. package/dist/core/tools/ls.js +4 -49
  45. package/dist/core/tools/read.d.ts +4 -0
  46. package/dist/core/tools/read.js +10 -122
  47. package/dist/core/tools/renderers/bash.d.ts +11 -0
  48. package/dist/core/tools/renderers/bash.js +129 -0
  49. package/dist/core/tools/renderers/edit.d.ts +22 -0
  50. package/dist/core/tools/renderers/edit.js +166 -0
  51. package/dist/core/tools/renderers/find.d.ts +9 -0
  52. package/dist/core/tools/renderers/find.js +63 -0
  53. package/dist/core/tools/renderers/grep.d.ts +9 -0
  54. package/dist/core/tools/renderers/grep.js +68 -0
  55. package/dist/core/tools/renderers/index.d.ts +27 -0
  56. package/dist/core/tools/renderers/index.js +46 -0
  57. package/dist/core/tools/renderers/ls.d.ts +9 -0
  58. package/dist/core/tools/renderers/ls.js +57 -0
  59. package/dist/core/tools/renderers/read.d.ts +10 -0
  60. package/dist/core/tools/renderers/read.js +128 -0
  61. package/dist/core/tools/renderers/write.d.ts +9 -0
  62. package/dist/core/tools/renderers/write.js +152 -0
  63. package/dist/core/tools/write.js +5 -146
  64. package/dist/extensions/capability-gateway/index.ts +12 -1
  65. package/dist/extensions/capability-gateway/integration.test.ts +23 -0
  66. package/dist/extensions/pi-hermes-memory/CHANGELOG.md +18 -0
  67. package/dist/extensions/pi-hermes-memory/README.md +16 -12
  68. package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +1 -1
  69. package/dist/extensions/pi-hermes-memory/package-lock.json +587 -62
  70. package/dist/extensions/pi-hermes-memory/package.json +4 -4
  71. package/dist/extensions/pi-hermes-memory/src/config.ts +32 -0
  72. package/dist/extensions/pi-hermes-memory/src/constants.ts +12 -2
  73. package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +109 -51
  74. package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +9 -3
  75. package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +257 -98
  76. package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +9 -2
  77. package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +5 -0
  78. package/dist/extensions/pi-hermes-memory/src/index.ts +22 -2
  79. package/dist/extensions/pi-hermes-memory/src/paths.ts +1 -1
  80. package/dist/extensions/pi-hermes-memory/src/store/db.ts +6 -0
  81. package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +58 -1
  82. package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +60 -8
  83. package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +169 -7
  84. package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +7 -21
  85. package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +134 -15
  86. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +4 -2
  87. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +24 -9
  88. package/dist/extensions/pi-hermes-memory/src/types.ts +11 -0
  89. package/dist/extensions/pi-hermes-memory/tests/config.test.ts +42 -0
  90. package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +159 -3
  91. package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +452 -0
  92. package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +39 -0
  93. package/dist/extensions/pi-hermes-memory/tests/integration/corruption-recovery-integration.test.ts +91 -0
  94. package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +29 -0
  95. package/dist/extensions/pi-hermes-memory/tests/store/fts-query.test.ts +116 -0
  96. package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +163 -0
  97. package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +233 -0
  98. package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +12 -0
  99. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +175 -0
  100. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +2 -2
  101. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +22 -0
  102. package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +37 -1
  103. package/dist/extensions/pi-intercom/CHANGELOG.md +13 -0
  104. package/dist/extensions/pi-intercom/README.md +16 -2
  105. package/dist/extensions/pi-intercom/broker/spawn.test.ts +19 -2
  106. package/dist/extensions/pi-intercom/broker/spawn.ts +4 -4
  107. package/dist/extensions/pi-intercom/index.ts +1 -1
  108. package/dist/extensions/pi-intercom/intercom.integration.test.ts +121 -2
  109. package/dist/extensions/pi-intercom/package.json +1 -1
  110. package/dist/extensions/pi-intercom/project-agent.test.ts +1 -1
  111. package/dist/extensions/pi-intercom/project-agent.ts +1 -6
  112. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +7 -6
  113. package/dist/extensions/pi-rewind-hook/index.test.ts +7 -0
  114. package/dist/extensions/pi-subagents/.github/workflows/test.yml +36 -4
  115. package/dist/extensions/pi-subagents/CHANGELOG.md +120 -0
  116. package/dist/extensions/pi-subagents/README.md +3 -3
  117. package/dist/extensions/pi-subagents/agents/researcher.md +23 -13
  118. package/dist/extensions/pi-subagents/agents/reviewer.md +1 -1
  119. package/dist/extensions/pi-subagents/agents/scout.md +1 -1
  120. package/dist/extensions/pi-subagents/docs/agents.md +32 -16
  121. package/dist/extensions/pi-subagents/docs/configuration.md +41 -15
  122. package/dist/extensions/pi-subagents/docs/extension-api.md +109 -6
  123. package/dist/extensions/pi-subagents/docs/missions.md +2 -0
  124. package/dist/extensions/pi-subagents/docs/models.md +58 -1
  125. package/dist/extensions/pi-subagents/docs/observability.md +50 -12
  126. package/dist/extensions/pi-subagents/docs/tool-reference.md +17 -10
  127. package/dist/extensions/pi-subagents/docs/watchdog.md +1 -1
  128. package/dist/extensions/pi-subagents/docs/workflows.md +26 -9
  129. package/dist/extensions/pi-subagents/package-lock.json +747 -177
  130. package/dist/extensions/pi-subagents/package.json +6 -4
  131. package/dist/extensions/pi-subagents/runner-server-preload.mjs +13 -0
  132. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +2 -1
  133. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +1 -1
  134. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +21 -4
  135. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -1
  136. package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +2 -0
  137. package/dist/extensions/pi-subagents/src/agents/advertised-agent-prompt.ts +63 -0
  138. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +61 -16
  139. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +2 -0
  140. package/dist/extensions/pi-subagents/src/agents/agents.ts +8 -0
  141. package/dist/extensions/pi-subagents/src/api/capability-ceiling.ts +0 -1
  142. package/dist/extensions/pi-subagents/src/api/{pi-args.ts → child-tool-plan.ts} +1 -1
  143. package/dist/extensions/pi-subagents/src/api/preflight.ts +7 -4
  144. package/dist/extensions/pi-subagents/src/api/shared-types.ts +2 -2
  145. package/dist/extensions/pi-subagents/src/api/workflow-resources.ts +6 -0
  146. package/dist/extensions/pi-subagents/src/extension/config.ts +4 -2
  147. package/dist/extensions/pi-subagents/src/extension/doctor.ts +2 -10
  148. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +9 -11
  149. package/dist/extensions/pi-subagents/src/extension/index.ts +99 -10
  150. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +13 -0
  151. package/dist/extensions/pi-subagents/src/extension/rpc.ts +7 -23
  152. package/dist/extensions/pi-subagents/src/extension/schemas.ts +11 -8
  153. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +25 -7
  154. package/dist/extensions/pi-subagents/src/integrations/pi-web-session-liveness.ts +73 -0
  155. package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +228 -136
  156. package/dist/extensions/pi-subagents/src/intercom/supervisor-ui.ts +244 -0
  157. package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +37 -16
  158. package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +18 -18
  159. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +51 -25
  160. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +46 -3
  161. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +14 -3
  162. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +9 -0
  163. package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +10 -12
  164. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -15
  165. package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +40 -29
  166. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +8 -0
  167. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +79 -247
  168. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +88 -12
  169. package/dist/extensions/pi-subagents/src/runs/background/owned-process-tree.ts +6 -6
  170. package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +24 -24
  171. package/dist/extensions/pi-subagents/src/runs/background/retained-nested-route-tracker.ts +96 -0
  172. package/dist/extensions/pi-subagents/src/runs/background/run-child-session.ts +642 -0
  173. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +75 -6
  174. package/dist/extensions/pi-subagents/src/runs/background/runner-aliases.ts +163 -0
  175. package/dist/extensions/pi-subagents/src/runs/background/runner-child-launch.ts +86 -0
  176. package/dist/extensions/pi-subagents/src/runs/background/runner-child-sessions.ts +31 -0
  177. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +18 -4
  178. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +3 -1
  179. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +597 -1092
  180. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +3 -0
  181. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +4 -0
  182. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +20 -17
  183. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +296 -394
  184. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +4 -0
  185. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +3 -1
  186. package/dist/extensions/pi-subagents/src/runs/foreground/prompt-audit.ts +9 -5
  187. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +630 -283
  188. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +8 -5
  189. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +78 -98
  190. package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +3 -3
  191. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +16 -3
  192. package/dist/extensions/pi-subagents/src/runs/shared/agent-contract.ts +1 -1
  193. package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +47 -47
  194. package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +1 -2
  195. package/dist/extensions/pi-subagents/src/runs/shared/child-hooks.ts +174 -0
  196. package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +14 -3
  197. package/dist/extensions/pi-subagents/src/runs/shared/child-launch.ts +319 -0
  198. package/dist/extensions/pi-subagents/src/runs/shared/child-lifecycle.ts +25 -0
  199. package/dist/extensions/pi-subagents/src/runs/shared/child-runtime-config.ts +126 -0
  200. package/dist/extensions/pi-subagents/src/runs/shared/child-session.ts +373 -0
  201. package/dist/extensions/pi-subagents/src/runs/shared/child-tool-plan.ts +530 -0
  202. package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +2 -2
  203. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +2 -1
  204. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +16 -0
  205. package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +11 -11
  206. package/dist/extensions/pi-subagents/src/runs/shared/llm-intent-arbiter.ts +30 -20
  207. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +5 -4
  208. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +84 -15
  209. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +88 -12
  210. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +37 -53
  211. package/dist/extensions/pi-subagents/src/runs/shared/nested-path.ts +1 -1
  212. package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +18 -7
  213. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +57 -12
  214. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +3 -4
  215. package/dist/extensions/pi-subagents/src/runs/shared/permissions.ts +0 -11
  216. package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +4 -1
  217. package/dist/extensions/pi-subagents/src/runs/shared/readonly-drain-observation.ts +42 -0
  218. package/dist/extensions/pi-subagents/src/runs/shared/readonly-model-continuation.ts +69 -0
  219. package/dist/extensions/pi-subagents/src/runs/shared/readonly-session-evidence.ts +307 -0
  220. package/dist/extensions/pi-subagents/src/runs/shared/run-fanout-budget.ts +8 -21
  221. package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +3 -30
  222. package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +17 -4
  223. package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +2 -0
  224. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +99 -386
  225. package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +18 -62
  226. package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +0 -14
  227. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +31 -9
  228. package/dist/extensions/pi-subagents/src/runs/shared/worktree-setup-command.ts +190 -0
  229. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +506 -226
  230. package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +1 -1
  231. package/dist/extensions/pi-subagents/src/shared/jsonl-writer.ts +11 -0
  232. package/dist/extensions/pi-subagents/src/shared/model-response-aliases.ts +13 -0
  233. package/dist/extensions/pi-subagents/src/shared/thinking-ceiling.ts +0 -6
  234. package/dist/extensions/pi-subagents/src/shared/types.ts +145 -89
  235. package/dist/extensions/pi-subagents/src/shared/utils.ts +13 -6
  236. package/dist/extensions/pi-subagents/src/shared/watch-strategy.ts +2 -0
  237. package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +18 -13
  238. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +0 -6
  239. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +1 -1
  240. package/dist/extensions/pi-subagents/src/tui/fleet.ts +11 -6
  241. package/dist/extensions/pi-subagents/src/tui/render.ts +277 -46
  242. package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +0 -1
  243. package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +12 -12
  244. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +3 -3
  245. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +116 -15
  246. package/dist/extensions/pi-subagents/src/workflows/workflow-checklist.ts +15 -18
  247. package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +57 -8
  248. package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +19 -19
  249. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +3 -3
  250. package/dist/extensions/pi-subagents/src/workflows/workflow-resources.ts +97 -22
  251. package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +3 -0
  252. package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +336 -21
  253. package/dist/extensions/pi-subagents/test/integration/async-execution.part-1.test.ts +1181 -0
  254. package/dist/extensions/pi-subagents/test/integration/async-execution.part-2.test.ts +2240 -0
  255. package/dist/extensions/pi-subagents/test/integration/async-execution.part-3.test.ts +2268 -0
  256. package/dist/extensions/pi-subagents/test/integration/async-execution.part-4.test.ts +1512 -0
  257. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +231 -16
  258. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +4 -18
  259. package/dist/extensions/pi-subagents/test/integration/foreign-workflow-steering.test.ts +95 -0
  260. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +9 -15
  261. package/dist/extensions/pi-subagents/test/integration/in-process-child.test.ts +374 -0
  262. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +20 -10
  263. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +18 -6
  264. package/dist/extensions/pi-subagents/test/integration/recovered-assistant-error.test.ts +151 -0
  265. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +42 -1
  266. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +150 -25
  267. package/dist/extensions/pi-subagents/test/integration/result-publication.test.ts +354 -0
  268. package/dist/extensions/pi-subagents/test/integration/shared-cwd-terminal-evidence.test.ts +117 -0
  269. package/dist/extensions/pi-subagents/test/integration/single-execution.part-1.test.ts +3678 -0
  270. package/dist/extensions/pi-subagents/test/integration/{single-execution.test.ts → single-execution.part-2.test.ts} +500 -4207
  271. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +1 -2
  272. package/dist/extensions/pi-subagents/test/integration/workflow-result-publication.test.ts +127 -0
  273. package/dist/extensions/pi-subagents/test/integration/workflow-steer-inbox.test.ts +365 -0
  274. package/dist/extensions/pi-subagents/test/smoke/pi085-child.ts +31 -0
  275. package/dist/extensions/pi-subagents/test/smoke/pi085-clean-install.mjs +74 -0
  276. package/dist/extensions/pi-subagents/test/smoke/pi085-extension.ts +16 -0
  277. package/dist/extensions/pi-subagents/test/support/async-execution-fixture.ts +699 -0
  278. package/dist/extensions/pi-subagents/test/support/fake-child-session.ts +418 -0
  279. package/dist/extensions/pi-subagents/test/support/foreign-workflow-steer-host.mjs +13 -0
  280. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +30 -76
  281. package/dist/extensions/pi-subagents/test/support/notify-diagnostics-fixture.ts +84 -0
  282. package/dist/extensions/pi-subagents/test/support/result-publication-capacity-preload.mjs +70 -0
  283. package/dist/extensions/pi-subagents/test/support/runner-child-session-factory.ts +17 -0
  284. package/dist/extensions/pi-subagents/test/support/single-execution-fixture.ts +390 -0
  285. package/dist/extensions/pi-subagents/test/unit/acceptance-compaction.test.ts +120 -0
  286. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +24 -3
  287. package/dist/extensions/pi-subagents/test/unit/advertised-agent-prompt.test.ts +87 -0
  288. package/dist/extensions/pi-subagents/test/unit/advertised-agent-refresh.test.ts +163 -0
  289. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +70 -31
  290. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +78 -3
  291. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +2 -8
  292. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +1 -1
  293. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +73 -66
  294. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +51 -1
  295. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +49 -1
  296. package/dist/extensions/pi-subagents/test/unit/async-spawn-preload.test.ts +103 -0
  297. package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +3 -3
  298. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +9 -8
  299. package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +10 -7
  300. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +48 -6
  301. package/dist/extensions/pi-subagents/test/unit/child-runtime-config.test.ts +90 -0
  302. package/dist/extensions/pi-subagents/test/unit/{pi-args-permission-system.test.ts → child-tool-plan-permission-system.test.ts} +48 -86
  303. package/dist/extensions/pi-subagents/test/unit/child-tool-plan.test.ts +33 -0
  304. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +18 -18
  305. package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +9 -9
  306. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +8 -7
  307. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +225 -65
  308. package/dist/extensions/pi-subagents/test/unit/extension-bindings.test.ts +17 -22
  309. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +11 -1
  310. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +47 -3
  311. package/dist/extensions/pi-subagents/test/unit/foreign-workflow-steering.test.ts +74 -0
  312. package/dist/extensions/pi-subagents/test/unit/fork-cache-key.test.ts +23 -29
  313. package/dist/extensions/pi-subagents/test/unit/host-peer-runtime-imports.test.ts +96 -4
  314. package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +4 -4
  315. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +116 -55
  316. package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +58 -1
  317. package/dist/extensions/pi-subagents/test/unit/llm-intent-arbiter.test.ts +104 -3
  318. package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +10 -1
  319. package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +31 -1
  320. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +102 -51
  321. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +196 -6
  322. package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +181 -38
  323. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +62 -70
  324. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +58 -53
  325. package/dist/extensions/pi-subagents/test/unit/notify-diagnostics.test.ts +42 -0
  326. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +84 -0
  327. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +13 -5
  328. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +21 -5
  329. package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +5 -4
  330. package/dist/extensions/pi-subagents/test/unit/permissions.test.ts +2 -6
  331. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +28 -2
  332. package/dist/extensions/pi-subagents/test/unit/pi-web-session-liveness.test.ts +209 -0
  333. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +38 -1
  334. package/dist/extensions/pi-subagents/test/unit/prompt-audit-optional-peers.test.ts +43 -0
  335. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +24 -2
  336. package/dist/extensions/pi-subagents/test/unit/readonly-drain-observation.test.ts +174 -0
  337. package/dist/extensions/pi-subagents/test/unit/readonly-model-continuation.test.ts +94 -0
  338. package/dist/extensions/pi-subagents/test/unit/readonly-session-evidence.test.ts +1329 -0
  339. package/dist/extensions/pi-subagents/test/unit/recursion-guard.test.ts +29 -80
  340. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +11 -8
  341. package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +2 -2
  342. package/dist/extensions/pi-subagents/test/unit/retained-nested-route-tracker.test.ts +175 -0
  343. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +38 -12
  344. package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +2 -5
  345. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +89 -1
  346. package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +2 -16
  347. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +27 -3
  348. package/dist/extensions/pi-subagents/test/unit/scheduled-supervisor-demand.test.ts +215 -0
  349. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +15 -11
  350. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +237 -1
  351. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +2 -5
  352. package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +2 -2
  353. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +14 -1
  354. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +130 -739
  355. package/dist/extensions/pi-subagents/test/unit/supervisor-ask-registration.test.ts +682 -0
  356. package/dist/extensions/pi-subagents/test/unit/supervisor-ui.test.ts +137 -0
  357. package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +1 -11
  358. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +23 -3
  359. package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +8 -1
  360. package/dist/extensions/pi-subagents/test/unit/watchdog-tool-actions.test.ts +19 -1
  361. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +72 -4
  362. package/dist/extensions/pi-subagents/test/unit/workflow-checklist.test.ts +17 -3
  363. package/dist/extensions/pi-subagents/test/unit/workflow-child-summary.test.ts +34 -0
  364. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +12 -2
  365. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +46 -6
  366. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +3 -3
  367. package/dist/extensions/pi-subagents/test/unit/workflow-resources.test.ts +133 -1
  368. package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +53 -2
  369. package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +222 -14
  370. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +526 -85
  371. package/dist/extensions/pi-web-agent/src/backends/config.ts +1 -0
  372. package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +5 -3
  373. package/dist/extensions/pi-web-agent/src/search/tokenin.ts +7 -3
  374. package/dist/extensions/pi-web-agent/src/types.ts +1 -1
  375. package/dist/extensions/pi-zentui/README.md +17 -0
  376. package/dist/extensions/pi-zentui/assets/screenshots/footer-status-hyperlink.png +0 -0
  377. package/dist/extensions/pi-zentui/docs/configuration.md +71 -2
  378. package/dist/extensions/pi-zentui/extensions/zentui/config.ts +11 -0
  379. package/dist/extensions/pi-zentui/extensions/zentui/editor-transfer.ts +14 -0
  380. package/dist/extensions/pi-zentui/extensions/zentui/extension-status.ts +29 -13
  381. package/dist/extensions/pi-zentui/extensions/zentui/footer-layout.ts +5 -4
  382. package/dist/extensions/pi-zentui/extensions/zentui/footer-text.ts +11 -0
  383. package/dist/extensions/pi-zentui/extensions/zentui/footer.ts +11 -10
  384. package/dist/extensions/pi-zentui/extensions/zentui/index.ts +77 -3
  385. package/dist/extensions/pi-zentui/extensions/zentui/presets.ts +77 -0
  386. package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +103 -2
  387. package/dist/extensions/pi-zentui/extensions/zentui/working-line-extension-segments.ts +115 -0
  388. package/dist/extensions/pi-zentui/extensions/zentui/working-line.ts +87 -5
  389. package/dist/extensions/pi-zentui/package-lock.json +277 -517
  390. package/dist/extensions/pi-zentui/package.json +7 -4
  391. package/dist/extensions/pi-zentui/test/config-presets.test.ts +238 -0
  392. package/dist/extensions/pi-zentui/test/editor-transfer.test.ts +24 -1
  393. package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +570 -2
  394. package/dist/extensions/pi-zentui/test/extension-status.test.ts +90 -0
  395. package/dist/extensions/pi-zentui/test/footer-hyperlink.test.ts +243 -0
  396. package/dist/extensions/pi-zentui/test/package-contents.mjs +1 -0
  397. package/dist/extensions/pi-zentui/test/presets.test.ts +121 -0
  398. package/dist/extensions/pi-zentui/test/settings-command.test.ts +205 -1
  399. package/dist/extensions/pi-zentui/test/working-line-extension-segments.test.ts +139 -0
  400. package/dist/extensions/pi-zentui/test/working-line-lifecycle.integration.test.ts +237 -3
  401. package/dist/extensions/pi-zentui/test/working-line.test.ts +94 -2
  402. package/dist/index.d.ts +1 -1
  403. package/dist/main.js +4 -1
  404. package/dist/modes/interactive/chat-viewport.d.ts +19 -0
  405. package/dist/modes/interactive/chat-viewport.js +27 -0
  406. package/dist/modes/interactive/components/assistant-message.d.ts +6 -2
  407. package/dist/modes/interactive/components/assistant-message.js +30 -13
  408. package/dist/modes/interactive/components/custom-editor.d.ts +10 -1
  409. package/dist/modes/interactive/components/custom-editor.js +39 -1
  410. package/dist/modes/interactive/components/first-time-setup.js +1 -1
  411. package/dist/modes/interactive/components/index.d.ts +1 -1
  412. package/dist/modes/interactive/components/markdown-transform.d.ts +2 -0
  413. package/dist/modes/interactive/components/markdown-transform.js +18 -0
  414. package/dist/modes/interactive/components/model-selector.js +19 -17
  415. package/dist/modes/interactive/components/scoped-models-selector.js +21 -23
  416. package/dist/modes/interactive/components/settings-selector.d.ts +7 -1
  417. package/dist/modes/interactive/components/settings-selector.js +128 -20
  418. package/dist/modes/interactive/components/settings-submenu.d.ts +71 -0
  419. package/dist/modes/interactive/components/settings-submenu.js +164 -0
  420. package/dist/modes/interactive/components/status-indicator.d.ts +3 -1
  421. package/dist/modes/interactive/components/status-indicator.js +10 -3
  422. package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
  423. package/dist/modes/interactive/components/thinking-selector.js +75 -18
  424. package/dist/modes/interactive/components/tool-execution.d.ts +21 -4
  425. package/dist/modes/interactive/components/tool-execution.js +35 -33
  426. package/dist/modes/interactive/components/trust-selector.js +2 -2
  427. package/dist/modes/interactive/interactive-mode.d.ts +13 -15
  428. package/dist/modes/interactive/interactive-mode.js +144 -80
  429. package/dist/modes/interactive/session-share.d.ts +15 -0
  430. package/dist/modes/interactive/session-share.js +183 -0
  431. package/dist/modes/interactive/theme/dark.json +2 -1
  432. package/dist/modes/interactive/theme/light.json +2 -1
  433. package/dist/modes/interactive/theme/theme-controller.d.ts +1 -0
  434. package/dist/modes/interactive/theme/theme-controller.js +5 -0
  435. package/dist/modes/interactive/theme/theme-json.d.ts +83 -0
  436. package/dist/modes/interactive/theme/theme-json.js +129 -0
  437. package/dist/modes/interactive/theme/theme-schema.json +9 -1
  438. package/dist/modes/interactive/theme/theme.d.ts +14 -5
  439. package/dist/modes/interactive/theme/theme.js +18 -119
  440. package/dist/modes/interactive/tui-renderer.d.ts +20 -0
  441. package/dist/modes/interactive/tui-renderer.js +65 -0
  442. package/dist/utils/exif-orientation.js +2 -3
  443. package/dist/utils/management-http.d.ts +24 -0
  444. package/dist/utils/management-http.js +53 -0
  445. package/dist/utils/text.d.ts +7 -0
  446. package/dist/utils/text.js +8 -0
  447. package/dist/utils/tools-manager.d.ts +1 -0
  448. package/dist/utils/tools-manager.js +43 -21
  449. package/docs/docs.json +0 -4
  450. package/package.json +4 -4
  451. package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +0 -415
  452. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +0 -1059
  453. package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +0 -116
  454. package/dist/extensions/pi-subagents/src/shared/post-exit-stdio-guard.ts +0 -85
  455. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +0 -224
  456. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +0 -6986
  457. package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +0 -447
  458. package/dist/extensions/pi-subagents/test/support/real-session-child-cli.mjs +0 -185
  459. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +0 -311
  460. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-pi-args.test.ts +0 -84
  461. package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +0 -202
  462. package/dist/extensions/pi-subagents/test/unit/close-grace-timer.test.ts +0 -101
  463. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +0 -2347
  464. package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +0 -104
  465. package/dist/extensions/pi-subagents/test/unit/windows-hide-spawn.test.ts +0 -49
  466. package/dist/skills/imagegen-frontend-mobile/SKILL.md +0 -1465
  467. package/dist/skills/imagegen-frontend-web/SKILL.md +0 -987
  468. package/dist/skills/implanger/SKILL.md +0 -70
  469. package/dist/skills/output/SKILL.md +0 -49
  470. package/dist/skills/planger/SKILL.md +0 -167
  471. package/dist/skills/workflow/SKILL.md +0 -95
  472. package/docs/workflows.md +0 -18
  473. /package/dist/bun/{register-bedrock.d.ts → runtime-setup.d.ts} +0 -0
@@ -2,19 +2,19 @@ import { randomUUID } from "node:crypto";
2
2
  import * as fs from "node:fs";
3
3
  import * as path from "node:path";
4
4
  import type { AgentToolResult } from "@earendil-works/pi-agent-core";
5
- import type { ExtensionAPI, ExtensionContext, ToolDefinition } from "@selesai/code";
5
+ import type { ExtensionAPI, ToolDefinition } from "@selesai/code";
6
6
  import { Type } from "typebox";
7
- import {
8
- SUBAGENT_CHILD_AGENT_ENV,
9
- SUBAGENT_CHILD_INDEX_ENV,
10
- SUBAGENT_ORCHESTRATOR_SESSION_ID_ENV,
11
- SUBAGENT_ORCHESTRATOR_TARGET_ENV,
12
- SUBAGENT_RUN_ID_ENV,
13
- SUBAGENT_SUPERVISOR_CHANNEL_DIR_ENV,
14
- } from "../runs/shared/pi-args.ts";
15
- import { INTERCOM_DETACH_REQUEST_EVENT, POLL_INTERVAL_MS, TEMP_ROOT_DIR, type IntercomEventBus, type SubagentState } from "../shared/types.ts";
7
+ import type { ChildSupervisorMetadata } from "../runs/shared/child-runtime-config.ts";
8
+ import { INTERCOM_DETACH_REQUEST_EVENT, POLL_INTERVAL_MS, TEMP_ROOT_DIR, type ControlEvent, type IntercomEventBus, type SubagentState } from "../shared/types.ts";
16
9
  import { writeAtomicJson } from "../shared/atomic-json.ts";
17
10
  import { shouldUseNativeFsWatch } from "../shared/watch-strategy.ts";
11
+ import {
12
+ SUPERVISOR_REQUEST_MESSAGE_TYPE,
13
+ SUPERVISOR_REPLY_ENTRY_TYPE,
14
+ supervisorReplyHint,
15
+ type SupervisorReason,
16
+ type SupervisorReplyEntryData,
17
+ } from "./supervisor-ui.ts";
18
18
 
19
19
  const SUPERVISOR_CHANNEL_ROOT = path.join(TEMP_ROOT_DIR, "supervisor-channels");
20
20
  const REQUESTS_DIR = "requests";
@@ -26,8 +26,10 @@ const CHANNEL_POLL_MS = Math.min(POLL_INTERVAL_MS, 500);
26
26
  const CHANNEL_SAFETY_POLL_MS = 5000;
27
27
  const STALE_EMPTY_CHANNEL_AGE_MS = 60 * 1000;
28
28
  const STALE_EMPTY_CHANNEL_CLEANUP_INTERVAL_MS = 60 * 1000;
29
+ const MAX_SUPERVISOR_REQUEST_CORRELATIONS = 256;
30
+ const SUPERVISOR_REQUEST_CORRELATION_RETENTION_MS = 10 * 60 * 1000;
29
31
 
30
- type SupervisorReason = "need_decision" | "interview_request" | "progress_update";
32
+ export type SupervisorRequestState = "pending" | "resolved" | "unknown";
31
33
 
32
34
  interface SupervisorRequest {
33
35
  type: "subagent.supervisor.request";
@@ -42,6 +44,7 @@ interface SupervisorRequest {
42
44
  runId: string;
43
45
  agent: string;
44
46
  childIndex: number;
47
+ toolCallId?: string;
45
48
  childTarget?: string;
46
49
  interview?: unknown;
47
50
  }
@@ -51,6 +54,12 @@ interface PendingSupervisorRequest extends SupervisorRequest {
51
54
  requestFile: string;
52
55
  }
53
56
 
57
+ interface SupervisorRequestCorrelation {
58
+ request: PendingSupervisorRequest;
59
+ state: Exclude<SupervisorRequestState, "unknown">;
60
+ updatedAt: number;
61
+ }
62
+
54
63
  interface SupervisorReply {
55
64
  type: "subagent.supervisor.reply";
56
65
  requestId: string;
@@ -65,7 +74,7 @@ interface ContactSupervisorParams {
65
74
  }
66
75
 
67
76
  interface IntercomParams {
68
- action: "list" | "send" | "ask" | "reply" | "pending" | "status";
77
+ action: "list" | "pending" | "status" | "reply";
69
78
  to?: string;
70
79
  message?: string;
71
80
  replyTo?: string;
@@ -74,6 +83,8 @@ interface IntercomParams {
74
83
  type SupervisorWatch = (filename: fs.PathLike, listener: fs.WatchListener<string>) => fs.FSWatcher;
75
84
 
76
85
  interface NativeSupervisorChannelDeps {
86
+ /** Retained scheduled states for the current runtime owner, never foreign owners. */
87
+ getCurrentOwnerStates?: () => Iterable<SubagentState>;
77
88
  platform?: NodeJS.Platform;
78
89
  watch?: SupervisorWatch;
79
90
  timers?: Pick<typeof globalThis, "setInterval" | "clearInterval" | "setImmediate" | "clearImmediate">;
@@ -86,7 +97,7 @@ const ContactSupervisorParamsSchema = Type.Object({
86
97
  }, { additionalProperties: false });
87
98
 
88
99
  const IntercomParamsSchema = Type.Object({
89
- action: Type.String({ enum: ["list", "send", "ask", "reply", "pending", "status"] }),
100
+ action: Type.String({ enum: ["list", "pending", "status", "reply"] }),
90
101
  to: Type.Optional(Type.String()),
91
102
  message: Type.Optional(Type.String()),
92
103
  replyTo: Type.Optional(Type.String()),
@@ -113,71 +124,12 @@ function replyPath(channelDir: string, requestId: string): string {
113
124
  return path.join(channelDir, REPLIES_DIR, `${safeSegment(requestId)}.json`);
114
125
  }
115
126
 
116
- function readTextEnv(name: string): string | undefined {
117
- const value = process.env[name]?.trim();
118
- return value ? value : undefined;
119
- }
120
-
121
- function readChildMetadata(): {
122
- channelDir: string;
123
- runId: string;
124
- agent: string;
125
- childIndex: number;
126
- orchestratorTarget?: string;
127
- orchestratorSessionId?: string;
128
- childTarget?: string;
129
- } | undefined {
130
- const channelDir = readTextEnv(SUBAGENT_SUPERVISOR_CHANNEL_DIR_ENV);
131
- const runId = readTextEnv(SUBAGENT_RUN_ID_ENV);
132
- const agent = readTextEnv(SUBAGENT_CHILD_AGENT_ENV);
133
- const rawIndex = readTextEnv(SUBAGENT_CHILD_INDEX_ENV);
134
- const orchestratorSessionId = readTextEnv(SUBAGENT_ORCHESTRATOR_SESSION_ID_ENV);
135
- if (!channelDir || !runId || !agent || !orchestratorSessionId || rawIndex === undefined || !/^\d+$/.test(rawIndex)) return undefined;
136
- return {
137
- channelDir,
138
- runId,
139
- agent,
140
- childIndex: Number(rawIndex),
141
- orchestratorTarget: readTextEnv(SUBAGENT_ORCHESTRATOR_TARGET_ENV),
142
- orchestratorSessionId,
143
- childTarget: readTextEnv("SELESAI_SUBAGENT_INTERCOM_SESSION_NAME"),
144
- };
145
- }
146
-
147
127
  function reasonHeading(reason: SupervisorReason): string {
148
128
  if (reason === "interview_request") return "Subagent requests a structured supervisor interview.";
149
129
  if (reason === "progress_update") return "Subagent progress update.";
150
130
  return "Subagent needs a supervisor decision.";
151
131
  }
152
132
 
153
- function formatChildMessage(input: {
154
- reason: SupervisorReason;
155
- message?: string;
156
- interview?: unknown;
157
- runId: string;
158
- agent: string;
159
- childIndex: number;
160
- childTarget?: string;
161
- }): string {
162
- const lines = [
163
- reasonHeading(input.reason),
164
- `Run: ${input.runId}`,
165
- `Agent: ${input.agent}`,
166
- `Child index: ${input.childIndex}`,
167
- ];
168
- if (input.childTarget) lines.push(`Child intercom target: ${input.childTarget}`);
169
- lines.push("");
170
- if (input.message?.trim()) lines.push(input.message.trim());
171
- if (input.reason === "interview_request") {
172
- lines.push(
173
- "",
174
- "Structured response requested. Reply with JSON, optionally fenced in ```json, matching the requested interview shape.",
175
- );
176
- if (input.interview !== undefined) lines.push(JSON.stringify(input.interview, null, "\t"));
177
- }
178
- return lines.join("\n").trimEnd();
179
- }
180
-
181
133
  function parseStructuredReply(message: string): { value?: unknown; error?: string } {
182
134
  const trimmed = message.trim();
183
135
  const fenced = trimmed.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i)?.[1]?.trim();
@@ -231,11 +183,9 @@ async function waitForReply(channelDir: string, requestId: string, deadline: num
231
183
  throw new Error("Timed out waiting for supervisor reply.");
232
184
  }
233
185
 
234
- async function sendSupervisorRequest(params: ContactSupervisorParams, signal?: AbortSignal): Promise<AgentToolResult<Record<string, unknown>>> {
235
- const metadata = readChildMetadata();
236
- if (!metadata) throw new Error("Native supervisor channel is not available for this subagent.");
237
- if (params.reason !== "progress_update" && !params.message?.trim() && params.reason !== "interview_request") {
238
- throw new Error("message is required for supervisor decisions.");
186
+ async function sendSupervisorRequest(params: ContactSupervisorParams, metadata: ChildSupervisorMetadata, signal?: AbortSignal, toolCallId?: string): Promise<AgentToolResult<Record<string, unknown>>> {
187
+ if (!params.message?.trim() && params.reason !== "interview_request") {
188
+ throw new Error("message is required for supervisor decisions and progress updates.");
239
189
  }
240
190
  ensureSupervisorChannelDir(metadata.channelDir);
241
191
  const requestId = randomUUID();
@@ -243,7 +193,8 @@ async function sendSupervisorRequest(params: ContactSupervisorParams, signal?: A
243
193
  const createdAt = Date.now();
244
194
  const replyDeadline = createdAt + askTimeoutMs();
245
195
  const expiresAt = expectsReply ? replyDeadline : undefined;
246
- const message = formatChildMessage({ ...metadata, reason: params.reason, message: params.message, interview: params.interview });
196
+ const message = params.message?.trim() ?? "";
197
+ const requestToolCallId = typeof toolCallId === "string" && toolCallId.length > 0 ? toolCallId : undefined;
247
198
  const request: SupervisorRequest = {
248
199
  type: "subagent.supervisor.request",
249
200
  id: requestId,
@@ -257,6 +208,7 @@ async function sendSupervisorRequest(params: ContactSupervisorParams, signal?: A
257
208
  runId: metadata.runId,
258
209
  agent: metadata.agent,
259
210
  childIndex: metadata.childIndex,
211
+ ...(requestToolCallId ? { toolCallId: requestToolCallId } : {}),
260
212
  ...(metadata.childTarget ? { childTarget: metadata.childTarget } : {}),
261
213
  ...(params.interview !== undefined ? { interview: params.interview } : {}),
262
214
  };
@@ -297,15 +249,19 @@ function hasTool(pi: ExtensionAPI, name: string): boolean {
297
249
  }
298
250
  }
299
251
 
300
- export function registerNativeSupervisorClient(pi: ExtensionAPI): void {
301
- if (!readChildMetadata() || hasTool(pi, "contact_supervisor")) return;
252
+ /**
253
+ * Register the child-side `contact_supervisor` tool. The host passes the
254
+ * channel metadata in the child runtime config.
255
+ */
256
+ export function registerNativeSupervisorClient(pi: ExtensionAPI, metadata: ChildSupervisorMetadata | undefined): void {
257
+ if (!metadata || hasTool(pi, "contact_supervisor")) return;
302
258
  const tool: ToolDefinition<typeof ContactSupervisorParamsSchema, Record<string, unknown>> = {
303
259
  name: "contact_supervisor",
304
260
  label: "Contact Supervisor",
305
261
  description: "Contact the parent/supervisor session for a blocking decision, structured interview, or progress update.",
306
262
  parameters: ContactSupervisorParamsSchema,
307
- execute(_id, params, signal) {
308
- return sendSupervisorRequest(params as ContactSupervisorParams, signal);
263
+ execute(id, params, signal) {
264
+ return sendSupervisorRequest(params as ContactSupervisorParams, metadata, signal, id);
309
265
  },
310
266
  };
311
267
  pi.registerTool(tool);
@@ -317,9 +273,14 @@ function parseRequestFile(file: string, channelDir: string): PendingSupervisorRe
317
273
  if (parsed.type !== "subagent.supervisor.request") return undefined;
318
274
  if (typeof parsed.id !== "string" || !parsed.id) return undefined;
319
275
  if (parsed.reason !== "need_decision" && parsed.reason !== "interview_request" && parsed.reason !== "progress_update") return undefined;
320
- if (typeof parsed.message !== "string" || !parsed.message) return undefined;
276
+ if (typeof parsed.message !== "string" || (!parsed.message.trim() && parsed.reason !== "interview_request")) return undefined;
321
277
  if (typeof parsed.runId !== "string" || typeof parsed.agent !== "string" || typeof parsed.childIndex !== "number") return undefined;
322
- return { ...parsed as SupervisorRequest, channelDir, requestFile: file };
278
+ return {
279
+ ...parsed as SupervisorRequest,
280
+ ...(typeof parsed.toolCallId === "string" && parsed.toolCallId.length > 0 ? { toolCallId: parsed.toolCallId } : { toolCallId: undefined }),
281
+ channelDir,
282
+ requestFile: file,
283
+ };
323
284
  } catch {
324
285
  return undefined;
325
286
  }
@@ -422,18 +383,8 @@ function cleanupStaleEmptySupervisorChannels(nowMs = Date.now()): number {
422
383
  return removed;
423
384
  }
424
385
 
425
- function currentContextSessionId(state: Pick<SubagentState, "currentSessionId">, ctx: ExtensionContext): string | undefined {
426
- try {
427
- const sessionId = ctx.sessionManager.getSessionId();
428
- if (sessionId) return sessionId;
429
- } catch {
430
- // Fall through to the last known identity.
431
- }
432
- return state.currentSessionId ?? undefined;
433
- }
434
-
435
- function requestMatchesContext(request: SupervisorRequest, state: Pick<SubagentState, "currentSessionId">, ctx: ExtensionContext): boolean {
436
- const currentSessionId = currentContextSessionId(state, ctx);
386
+ function requestMatchesOwner(request: SupervisorRequest, state: Pick<SubagentState, "supervisorOwnerSessionId">): boolean {
387
+ const currentSessionId = state.supervisorOwnerSessionId;
437
388
  return Boolean(currentSessionId && request.orchestratorSessionId === currentSessionId);
438
389
  }
439
390
 
@@ -483,6 +434,7 @@ function removeRequestFile(file: string): void {
483
434
  }
484
435
 
485
436
  type SupervisorRequestLifecycle = "pending" | "resolved" | "expired" | "inactive" | "missing" | "wrong-session";
437
+ type SupervisorRequestLifecycleObserver = (request: PendingSupervisorRequest, lifecycle: SupervisorRequestLifecycle) => void;
486
438
 
487
439
  function requestExpiresAt(request: SupervisorRequest, now: number): number {
488
440
  const expiresAt = (request as { expiresAt?: unknown }).expiresAt;
@@ -502,12 +454,12 @@ function requestRunInactive(request: SupervisorRequest, state: SubagentState): b
502
454
  return stepStatus === "complete" || stepStatus === "completed" || stepStatus === "failed" || stepStatus === "paused";
503
455
  }
504
456
 
505
- function requestLifecycle(request: PendingSupervisorRequest, state: SubagentState, ctx: ExtensionContext | undefined, now: number): SupervisorRequestLifecycle {
506
- if (ctx && !requestMatchesContext(request, state, ctx)) return "wrong-session";
457
+ function requestLifecycle(request: PendingSupervisorRequest, state: SubagentState, now: number, runState: SubagentState): SupervisorRequestLifecycle {
458
+ if (!requestMatchesOwner(request, state)) return "wrong-session";
507
459
  if (!fs.existsSync(request.requestFile)) return "missing";
508
460
  if (request.expectsReply && fs.existsSync(replyPath(request.channelDir, request.id))) return "resolved";
509
461
  if (request.expectsReply && now > requestExpiresAt(request, now)) return "expired";
510
- if (request.expectsReply && requestRunInactive(request, state)) return "inactive";
462
+ if (request.expectsReply && requestRunInactive(request, runState)) return "inactive";
511
463
  return "pending";
512
464
  }
513
465
 
@@ -515,30 +467,44 @@ function cleanupRequestLifecycle(request: PendingSupervisorRequest, lifecycle: S
515
467
  if (lifecycle === "resolved" || lifecycle === "expired" || lifecycle === "inactive") removeRequestFile(request.requestFile);
516
468
  }
517
469
 
518
- function refreshPendingRequests(pending: Map<string, PendingSupervisorRequest>, state: SubagentState, ctx: ExtensionContext | undefined): void {
470
+ function refreshPendingRequests(pending: Map<string, PendingSupervisorRequest>, state: SubagentState, onLifecycle: SupervisorRequestLifecycleObserver, runState: (request: SupervisorRequest) => SubagentState): void {
519
471
  const now = Date.now();
520
472
  for (const request of pending.values()) {
521
- const lifecycle = requestLifecycle(request, state, ctx, now);
473
+ const lifecycle = requestLifecycle(request, state, now, runState(request));
522
474
  if (lifecycle === "pending") continue;
523
475
  pending.delete(request.id);
476
+ onLifecycle(request, lifecycle);
524
477
  cleanupRequestLifecycle(request, lifecycle);
525
478
  }
526
479
  }
527
480
 
528
481
  function formatPendingLine(request: PendingSupervisorRequest): string {
529
- const replyHint = request.expectsReply ? ` Reply: ${NATIVE_SUPERVISOR_TOOL_NAME}({ action: "reply", replyTo: "${request.id}", message: "..." })` : "";
482
+ const replyHint = request.expectsReply ? ` Reply: ${supervisorReplyHint(request.id)}` : "";
530
483
  return `- ${request.id}: ${request.agent} [${request.runId}#${request.childIndex}] ${request.reason}.${replyHint}`;
531
484
  }
532
485
 
533
486
  function requestVisibleText(request: PendingSupervisorRequest): string {
534
- const lines = [request.message];
535
- if (request.expectsReply) {
536
- lines.push("", `Reply with: ${NATIVE_SUPERVISOR_TOOL_NAME}({ action: "reply", replyTo: "${request.id}", message: "..." })`);
487
+ const lines = [
488
+ reasonHeading(request.reason),
489
+ `Run: ${request.runId}`,
490
+ `Agent: ${request.agent}`,
491
+ `Child index: ${request.childIndex}`,
492
+ ];
493
+ lines.push("");
494
+ if (request.message) lines.push(request.message);
495
+ if (request.reason === "interview_request") {
496
+ lines.push(
497
+ "",
498
+ "Structured response requested. Reply with JSON, optionally fenced in ```json, matching the requested interview shape.",
499
+ );
500
+ if (request.interview !== undefined) lines.push(JSON.stringify(request.interview, null, "\t"));
537
501
  }
538
- return lines.join("\n");
502
+ if (request.expectsReply) lines.push("", `Reply with: ${supervisorReplyHint(request.id)}`);
503
+ lines.push("", `Live guidance: subagent({ action: "steer", id: ${JSON.stringify(request.runId)}, index: ${request.childIndex}, message: "..." })${request.expectsReply ? " (Reply to the pending request first.)" : ""}`);
504
+ return lines.join("\n").trimEnd();
539
505
  }
540
506
 
541
- function writeReply(request: PendingSupervisorRequest, message: string): void {
507
+ function writeReply(request: PendingSupervisorRequest, message: string): SupervisorReply {
542
508
  if (!message.trim()) throw new Error("message is required for supervisor replies.");
543
509
  const reply: SupervisorReply = {
544
510
  type: "subagent.supervisor.reply",
@@ -548,6 +514,29 @@ function writeReply(request: PendingSupervisorRequest, message: string): void {
548
514
  };
549
515
  writeAtomicJson(replyPath(request.channelDir, request.id), reply);
550
516
  removeRequestFile(request.requestFile);
517
+ return reply;
518
+ }
519
+
520
+ function appendSupervisorReplyEntry(pi: ExtensionAPI, request: PendingSupervisorRequest, reply: SupervisorReply): void {
521
+ const appendEntry = (pi as unknown as {
522
+ appendEntry?: (customType: string, data?: SupervisorReplyEntryData) => void;
523
+ }).appendEntry;
524
+ if (typeof appendEntry !== "function") return;
525
+ try {
526
+ appendEntry.call(pi, SUPERVISOR_REPLY_ENTRY_TYPE, {
527
+ requestId: request.id,
528
+ reason: request.reason,
529
+ runId: request.runId,
530
+ agent: request.agent,
531
+ childIndex: request.childIndex,
532
+ ...(request.childTarget ? { childTarget: request.childTarget } : {}),
533
+ message: reply.message,
534
+ createdAt: reply.createdAt,
535
+ });
536
+ } catch (error) {
537
+ // The reply file is authoritative; a UI journal failure must not undo a delivered reply.
538
+ console.error("Failed to journal native supervisor reply:", error);
539
+ }
551
540
  }
552
541
 
553
542
  function resolvePendingRequest(pending: Map<string, PendingSupervisorRequest>, params: IntercomParams): PendingSupervisorRequest {
@@ -566,6 +555,7 @@ function resolvePendingRequest(pending: Map<string, PendingSupervisorRequest>, p
566
555
  );
567
556
  if (matches.length === 1) return matches[0]!;
568
557
  if (matches.length > 1) throw new Error(`Multiple pending supervisor requests match '${params.to}'. Use replyTo.`);
558
+ throw new Error(`No pending supervisor request matches '${params.to}'. Use replyTo.`);
569
559
  }
570
560
  if (requests.length === 1) return requests[0]!;
571
561
  if (requests.length === 0) throw new Error("No pending supervisor requests need a reply.");
@@ -583,14 +573,16 @@ function publicPendingRequests(pending: Map<string, PendingSupervisorRequest>):
583
573
  }));
584
574
  }
585
575
 
586
- function buildParentSupervisorTool(pending: Map<string, PendingSupervisorRequest>, state: SubagentState): ToolDefinition<typeof IntercomParamsSchema, Record<string, unknown>> {
576
+ function buildParentSupervisorTool(pi: ExtensionAPI, pending: Map<string, PendingSupervisorRequest>, state: SubagentState, onLifecycle: SupervisorRequestLifecycleObserver, discover: () => void, runState: (request: SupervisorRequest) => SubagentState): ToolDefinition<typeof IntercomParamsSchema, Record<string, unknown>> {
587
577
  return {
588
578
  name: NATIVE_SUPERVISOR_TOOL_NAME,
589
579
  label: "Subagent Supervisor",
590
580
  description: "Native pi-subagents supervisor channel. Use reply/pending/status to answer child subagent requests without overriding pi-intercom.",
591
581
  parameters: IntercomParamsSchema,
592
582
  async execute(_id, params) {
593
- refreshPendingRequests(pending, state, state.lastUiContext ?? undefined);
583
+ // Discover new request files even when demand-gated polling is idle.
584
+ discover();
585
+ refreshPendingRequests(pending, state, onLifecycle, runState);
594
586
  const input = params as IntercomParams;
595
587
  if (input.action === "status") {
596
588
  return { content: [{ type: "text", text: `Native supervisor channel active. Pending replies: ${pending.size}.` }], details: { active: true, pending: pending.size, root: SUPERVISOR_CHANNEL_ROOT } };
@@ -601,23 +593,85 @@ function buildParentSupervisorTool(pending: Map<string, PendingSupervisorRequest
601
593
  }
602
594
  if (input.action === "reply") {
603
595
  const request = resolvePendingRequest(pending, input);
604
- writeReply(request, input.message ?? "");
596
+ const reply = writeReply(request, input.message ?? "");
597
+ appendSupervisorReplyEntry(pi, request, reply);
598
+ onLifecycle(request, "resolved");
605
599
  pending.delete(request.id);
606
600
  clearForegroundSupervisorAttention(request, pending, state);
607
601
  return { content: [{ type: "text", text: `Replied to supervisor request ${request.id}.` }], details: { replyTo: request.id, runId: request.runId, agent: request.agent } };
608
602
  }
609
- if (input.action === "send" || input.action === "ask") {
610
- throw new Error("The native subagent supervisor handles replies only. Child agents initiate asks with contact_supervisor.");
611
- }
612
603
  throw new Error(`Unsupported supervisor action: ${input.action}`);
613
604
  },
614
605
  };
615
606
  }
616
607
 
617
- export function createNativeSupervisorChannel(pi: ExtensionAPI, state: SubagentState, deps: NativeSupervisorChannelDeps = {}): { start: () => void; activateTransport: () => void; dispose: () => void; pending: Map<string, PendingSupervisorRequest> } {
608
+ export function createNativeSupervisorChannel(pi: ExtensionAPI, state: SubagentState, deps: NativeSupervisorChannelDeps = {}): {
609
+ start: () => void;
610
+ activateTransport: () => void;
611
+ findPendingAsks: (target: { runId: string; agent: string; childIndex: number }) => string[];
612
+ dispose: () => void;
613
+ pending: Map<string, PendingSupervisorRequest>;
614
+ getSupervisorRequestState: (event: ControlEvent) => SupervisorRequestState;
615
+ } {
618
616
  const watch = deps.watch ?? fs.watch;
619
617
  const timers = deps.timers ?? globalThis;
618
+ const runState = (request: SupervisorRequest): SubagentState => {
619
+ for (const ownerState of deps.getCurrentOwnerStates?.() ?? []) {
620
+ if (ownerState.asyncJobs.has(request.runId)) return ownerState;
621
+ }
622
+ return state;
623
+ };
620
624
  const pending = new Map<string, PendingSupervisorRequest>();
625
+ const requestCorrelations = new Map<string, SupervisorRequestCorrelation>();
626
+ const correlationKey = (request: { runId: string; agent: string; childIndex: number; toolCallId?: string }): string | undefined => {
627
+ if (!request.toolCallId) return undefined;
628
+ return JSON.stringify([request.runId, request.agent, request.childIndex, request.toolCallId]);
629
+ };
630
+ const pruneRequestCorrelations = (now = Date.now()): void => {
631
+ for (const [key, correlation] of requestCorrelations) {
632
+ if (correlation.state === "resolved" && now - correlation.updatedAt > SUPERVISOR_REQUEST_CORRELATION_RETENTION_MS) requestCorrelations.delete(key);
633
+ }
634
+ while (requestCorrelations.size > MAX_SUPERVISOR_REQUEST_CORRELATIONS) {
635
+ const oldest = requestCorrelations.keys().next().value;
636
+ if (oldest === undefined) break;
637
+ requestCorrelations.delete(oldest);
638
+ }
639
+ };
640
+ const rememberPendingRequest = (request: PendingSupervisorRequest): void => {
641
+ const key = correlationKey(request);
642
+ if (!key || !request.expectsReply) return;
643
+ requestCorrelations.set(key, { request, state: "pending", updatedAt: Date.now() });
644
+ pruneRequestCorrelations();
645
+ };
646
+ const rememberResolvedRequest = (request: PendingSupervisorRequest): void => {
647
+ const key = correlationKey(request);
648
+ if (!key || !request.expectsReply) return;
649
+ requestCorrelations.set(key, { request, state: "resolved", updatedAt: Date.now() });
650
+ pruneRequestCorrelations();
651
+ };
652
+ const observeRequestLifecycle: SupervisorRequestLifecycleObserver = (request, lifecycle) => {
653
+ if (lifecycle !== "wrong-session") rememberResolvedRequest(request);
654
+ };
655
+ const getSupervisorRequestState = (event: ControlEvent): SupervisorRequestState => {
656
+ if (event.currentTool === "intercom" || event.index === undefined) return "unknown";
657
+ const toolCallId = typeof event.toolCallId === "string" && event.toolCallId.length > 0 ? event.toolCallId : undefined;
658
+ if (!toolCallId) return "unknown";
659
+ pruneRequestCorrelations();
660
+ const key = correlationKey({ runId: event.runId, agent: event.agent, childIndex: event.index, toolCallId });
661
+ if (!key) return "unknown";
662
+ const correlation = requestCorrelations.get(key);
663
+ if (!correlation) return "unknown";
664
+ if (correlation.state === "resolved") return "resolved";
665
+ const now = Date.now();
666
+ if (!fs.existsSync(correlation.request.requestFile)
667
+ || fs.existsSync(replyPath(correlation.request.channelDir, correlation.request.id))
668
+ || now > requestExpiresAt(correlation.request, now)
669
+ || requestRunInactive(correlation.request, runState(correlation.request))) {
670
+ rememberResolvedRequest(correlation.request);
671
+ return "resolved";
672
+ }
673
+ return "pending";
674
+ };
621
675
  const seenFiles = new Set<string>();
622
676
  const requestWatchers = new Map<string, fs.FSWatcher>();
623
677
  let rootWatcher: fs.FSWatcher | undefined;
@@ -631,11 +685,17 @@ export function createNativeSupervisorChannel(pi: ExtensionAPI, state: SubagentS
631
685
  const hasTransportDemand = () => {
632
686
  if (pending.size > 0) return true;
633
687
  if (state.foregroundControls.size > 0) return true;
634
- return [...state.asyncJobs.values()].some((job) => job.status === "queued" || job.status === "running");
688
+ if ([...state.asyncJobs.values()].some((job) => job.status === "queued" || job.status === "running")) return true;
689
+ for (const ownerState of deps.getCurrentOwnerStates?.() ?? []) {
690
+ for (const job of ownerState.asyncJobs.values()) {
691
+ if (job.status === "queued" || job.status === "running") return true;
692
+ }
693
+ }
694
+ return false;
635
695
  };
636
696
 
637
697
  const registerParentTools = (): void => {
638
- if (!hasTool(pi, NATIVE_SUPERVISOR_TOOL_NAME)) pi.registerTool(buildParentSupervisorTool(pending, state));
698
+ if (!hasTool(pi, NATIVE_SUPERVISOR_TOOL_NAME)) pi.registerTool(buildParentSupervisorTool(pi, pending, state, observeRequestLifecycle, () => poll(), runState));
639
699
  };
640
700
 
641
701
  const cleanupStaleChannelsIfDue = (): void => {
@@ -651,41 +711,54 @@ export function createNativeSupervisorChannel(pi: ExtensionAPI, state: SubagentS
651
711
 
652
712
  const poll = (): void => {
653
713
  cleanupStaleChannelsIfDue();
654
- const ctx = state.lastUiContext;
655
- if (!ctx) return;
656
- refreshPendingRequests(pending, state, ctx);
714
+ // Only display notifications require a live UI context, not request registration.
715
+ refreshPendingRequests(pending, state, observeRequestLifecycle, runState);
657
716
  const now = Date.now();
658
717
  for (const { channelDir, file } of listRequestFiles()) {
659
718
  if (seenFiles.has(file)) continue;
660
719
  const request = parseRequestFile(file, channelDir);
661
- if (!request || !requestMatchesContext(request, state, ctx)) continue;
662
- const lifecycle = requestLifecycle(request, state, undefined, now);
720
+ if (!request || !requestMatchesOwner(request, state)) continue;
721
+ const lifecycle = requestLifecycle(request, state, now, runState(request));
663
722
  if (lifecycle !== "pending") {
664
723
  seenFiles.add(file);
724
+ observeRequestLifecycle(request, lifecycle);
665
725
  cleanupRequestLifecycle(request, lifecycle);
666
726
  continue;
667
727
  }
668
728
  seenFiles.add(file);
669
729
  if (request.expectsReply) {
730
+ rememberPendingRequest(request);
670
731
  pending.set(request.id, request);
671
732
  markForegroundSupervisorAttention(request, state);
672
733
  }
673
- else {
674
- removeRequestFile(request.requestFile);
734
+ // The ask is already queued above. A sendMessage failure (no UI, stale context) must not
735
+ // lose it, and must not abort the loop before the remaining asks register.
736
+ try {
737
+ pi.sendMessage({
738
+ customType: SUPERVISOR_REQUEST_MESSAGE_TYPE,
739
+ content: requestVisibleText(request),
740
+ display: true,
741
+ details: {
742
+ id: request.id,
743
+ requestId: request.id,
744
+ reason: request.reason,
745
+ expectsReply: request.expectsReply,
746
+ runId: request.runId,
747
+ agent: request.agent,
748
+ childIndex: request.childIndex,
749
+ ...(request.childTarget ? { childTarget: request.childTarget } : {}),
750
+ ...(request.interview !== undefined ? { interview: request.interview } : {}),
751
+ requestBody: request.message,
752
+ ...(request.expectsReply ? { replyHint: supervisorReplyHint(request.id) } : {}),
753
+ },
754
+ }, { triggerTurn: true });
755
+ // sendMessage accepts synchronously; one-way updates stay on disk until it returns.
756
+ if (!request.expectsReply) removeRequestFile(request.requestFile);
757
+ } catch (error) {
758
+ // Allow an existing later scan to retry an unaccepted one-way update.
759
+ if (!request.expectsReply) seenFiles.delete(file);
760
+ console.error(`Failed to surface supervisor request ${request.id} as a user turn:`, error);
675
761
  }
676
- pi.sendMessage({
677
- customType: "subagent_supervisor_request",
678
- content: requestVisibleText(request),
679
- display: true,
680
- details: {
681
- id: request.id,
682
- reason: request.reason,
683
- expectsReply: request.expectsReply,
684
- runId: request.runId,
685
- agent: request.agent,
686
- childIndex: request.childIndex,
687
- },
688
- }, { triggerTurn: true });
689
762
  if (request.expectsReply) {
690
763
  (pi as { events?: IntercomEventBus }).events?.emit(INTERCOM_DETACH_REQUEST_EVENT, {
691
764
  requestId: request.id,
@@ -762,6 +835,23 @@ export function createNativeSupervisorChannel(pi: ExtensionAPI, state: SubagentS
762
835
  poll();
763
836
  if (!useNativeWatcher() && hasTransportDemand()) startPolling();
764
837
  },
838
+ findPendingAsks: (target) => {
839
+ // Receipt-only discovery: no registration, notification, cleanup or reply writes.
840
+ const channelDir = resolveSupervisorChannelDir(target.runId, target.agent, target.childIndex);
841
+ let files: string[];
842
+ try { files = fs.readdirSync(path.join(channelDir, REQUESTS_DIR)); }
843
+ catch (error) {
844
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return [];
845
+ throw error;
846
+ }
847
+ const now = Date.now();
848
+ return files.filter(file => file.endsWith(".json")).flatMap(file => {
849
+ const request = parseRequestFile(path.join(channelDir, REQUESTS_DIR, file), channelDir);
850
+ return request?.expectsReply && request.runId === target.runId
851
+ && request.agent === target.agent && request.childIndex === target.childIndex
852
+ && requestLifecycle(request, state, now, runState(request)) === "pending" ? [request.id] : [];
853
+ }).sort();
854
+ },
765
855
  start: () => {
766
856
  if (started) return;
767
857
  started = true;
@@ -805,8 +895,10 @@ export function createNativeSupervisorChannel(pi: ExtensionAPI, state: SubagentS
805
895
  if (deferredWatcherRefresh) timers.clearImmediate(deferredWatcherRefresh);
806
896
  deferredWatcherRefresh = undefined;
807
897
  pending.clear();
898
+ requestCorrelations.clear();
808
899
  seenFiles.clear();
809
900
  },
810
901
  pending,
902
+ getSupervisorRequestState,
811
903
  };
812
904
  }