@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
@@ -0,0 +1,374 @@
1
+ /**
2
+ * Foreground children run as in-process pi sessions. These tests drive
3
+ * `runSync` against the scripted child session factory and check the seams
4
+ * the in-process launch owns: hook config, steering, interrupt, timeout,
5
+ * structured output capture, disposal, and detach.
6
+ */
7
+
8
+ import { describe, it, before, after, beforeEach } from "node:test";
9
+ import assert from "node:assert/strict";
10
+ import * as fs from "node:fs";
11
+ import * as path from "node:path";
12
+ import type { MockPi } from "../support/helpers.ts";
13
+ import { createMockPi, createTempDir, makeAgent, makeAgentConfigs, removeTempDir } from "../support/helpers.ts";
14
+ import { runSync } from "../../src/runs/foreground/execution.ts";
15
+ import { childSessionFactory, createDefaultChildSessionFactory, disposeChildSessions, type ChildSessionFactory, type ChildSessionLaunch, type PiCodingAgentModule } from "../../src/runs/shared/child-session.ts";
16
+ import { createNestedRoute } from "../../src/runs/shared/nested-events.ts";
17
+ import { createStructuredOutputRuntime } from "../../src/runs/shared/structured-output.ts";
18
+ import type { ForegroundChildSessionControls, SingleResult } from "../../src/shared/types.ts";
19
+
20
+ async function waitFor(read: () => boolean, timeoutMs = 5_000): Promise<void> {
21
+ const deadline = Date.now() + timeoutMs;
22
+ while (!read()) {
23
+ if (Date.now() > deadline) throw new Error("Timed out waiting for test condition.");
24
+ await new Promise((resolve) => setTimeout(resolve, 5));
25
+ }
26
+ }
27
+
28
+ describe("in-process foreground child", () => {
29
+ let tempDir: string;
30
+ let mockPi: MockPi;
31
+ const savedEnv = { ...process.env };
32
+
33
+ before(() => {
34
+ mockPi = createMockPi();
35
+ mockPi.install();
36
+ });
37
+
38
+ after(() => {
39
+ mockPi.uninstall();
40
+ });
41
+
42
+ beforeEach(() => {
43
+ tempDir = createTempDir();
44
+ mockPi.reset();
45
+ process.env.SELESAI_SUBAGENT_CHILD_AGENT = savedEnv.SELESAI_SUBAGENT_CHILD_AGENT ?? "";
46
+ delete process.env.SELESAI_SUBAGENT_CHILD_AGENT;
47
+ });
48
+
49
+ after(() => removeTempDir(tempDir));
50
+
51
+ it("passes the child hooks a typed config built without the environment", async () => {
52
+ process.env.SELESAI_SUBAGENT_CHILD_AGENT = "leaked-parent-value";
53
+ try {
54
+ mockPi.onCall({ output: "done" });
55
+ const result = await runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", { runId: "hooks-config", index: 3, waitToolEnabled: false });
56
+ assert.equal(result.exitCode, 0);
57
+ const [session] = mockPi.sessions;
58
+ assert.ok(session, "child session was created");
59
+ assert.equal(session.launch.runtime.agent, "echo");
60
+ assert.equal(session.launch.runtime.runId, "hooks-config");
61
+ assert.equal(session.launch.runtime.childIndex, 3);
62
+ assert.equal(session.launch.runtime.fanoutChild, false);
63
+ assert.equal(session.launch.runtime.waitTool.enabled, false);
64
+ assert.equal(session.launch.runtime.steerInbox, undefined, "in-process children have no steer inbox");
65
+ assert.equal(session.launch.runtime.depth, 1);
66
+ assert.equal(session.task?.startsWith("Task: Task"), true);
67
+ assert.equal(session.launch.systemPrompt?.startsWith('<active_agent name="echo"/>'), true);
68
+ assert.deepEqual(session.launch.storage, { kind: "memory" });
69
+ } finally {
70
+ delete process.env.SELESAI_SUBAGENT_CHILD_AGENT;
71
+ }
72
+ });
73
+
74
+ it("adds the fanout hook and nested route only for fanout-authorized children", async () => {
75
+ const route = createNestedRoute("hooks-fanout");
76
+ try {
77
+ mockPi.onCall({ output: "done" });
78
+ const result = await runSync(tempDir, [makeAgent("delegator", { tools: ["read", "subagent"] })], "delegator", "Task", {
79
+ runId: "hooks-fanout",
80
+ nestedRoute: route,
81
+ });
82
+ assert.equal(result.exitCode, 0);
83
+ const [session] = mockPi.sessions;
84
+ assert.equal(session?.launch.runtime.fanoutChild, true);
85
+ assert.deepEqual(session?.launch.runtime.nestedRoute, route);
86
+ assert.deepEqual(session?.launch.runtime.nestedParent, { parentRunId: "hooks-fanout", parentChildIndex: 0, depth: 1, path: [{ runId: "hooks-fanout", stepIndex: 0, agent: "delegator" }] });
87
+ assert.deepEqual(session?.launch.tools, ["read", "subagent"]);
88
+ } finally {
89
+ fs.rmSync(path.dirname(route.eventSink), { recursive: true, force: true });
90
+ }
91
+ });
92
+
93
+ it("routes steer and follow-up to the child session", async () => {
94
+ const release = path.join(tempDir, "release");
95
+ mockPi.onCall({ steps: [{ waitForPath: release, jsonl: [{ type: "message_end", message: { role: "assistant", content: [{ type: "text", text: "steered" }], model: "mock/test-model", stopReason: "stop", usage: { input: 1, output: 1, cacheRead: 0, cacheWrite: 0, cost: { total: 0 } } } }] }] });
96
+ let controls: ForegroundChildSessionControls | undefined;
97
+ const run = runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", {
98
+ runId: "steer-session",
99
+ onChildSession: (next) => { controls = next; },
100
+ });
101
+ await waitFor(() => controls !== undefined);
102
+ await controls!.steer("Focus on tests.");
103
+ await controls!.followUp("Then update docs.");
104
+ fs.writeFileSync(release, "go");
105
+ const result = await run;
106
+ assert.equal(result.exitCode, 0);
107
+ assert.deepEqual(mockPi.sessions[0]?.steers, [
108
+ { text: "Focus on tests.", mode: "steer" },
109
+ { text: "Then update docs.", mode: "followUp" },
110
+ ]);
111
+ });
112
+
113
+ it("aborts the child session on interrupt and disposes it", async () => {
114
+ mockPi.onCall({ hangUntilAbort: true });
115
+ const interrupt = new AbortController();
116
+ const run = runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", { runId: "interrupt-session", interruptSignal: interrupt.signal });
117
+ await waitFor(() => mockPi.sessions.length === 1);
118
+ await waitFor(() => mockPi.sessions[0]?.task !== undefined);
119
+ interrupt.abort();
120
+ const result = await run;
121
+ assert.equal(result.interrupted, true);
122
+ assert.equal(result.exitCode, 0);
123
+ assert.equal(mockPi.sessions[0]?.aborted, true);
124
+ assert.equal(mockPi.sessions[0]?.disposed, true);
125
+ });
126
+
127
+ it("aborts the child session on timeout and disposes it", async () => {
128
+ mockPi.onCall({ hangUntilAbort: true });
129
+ const result = await runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", { runId: "timeout-session", timeoutMs: 60 });
130
+ assert.equal(result.timedOut, true);
131
+ assert.equal(result.exitCode, 1);
132
+ assert.match(result.error ?? "", /timed out after 60ms/);
133
+ assert.equal(mockPi.sessions[0]?.aborted, true);
134
+ assert.equal(mockPi.sessions[0]?.disposed, true);
135
+ });
136
+
137
+ it("disposes the child session after a normal completion", async () => {
138
+ mockPi.onCall({ output: "finished" });
139
+ const result = await runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", { runId: "dispose-session" });
140
+ assert.equal(result.exitCode, 0);
141
+ assert.equal(result.finalOutput, "finished");
142
+ assert.equal(mockPi.sessions[0]?.settled, true);
143
+ assert.equal(mockPi.sessions[0]?.disposed, true);
144
+ });
145
+
146
+ it("reports the run only after the child session's shutdown work finished", async () => {
147
+ mockPi.onCall({ output: "done" });
148
+ let shutdownDone = false;
149
+ const inner = childSessionFactory();
150
+ const wrapped: ChildSessionFactory = {
151
+ ...inner,
152
+ create: async (launch) => {
153
+ const session = await inner.create(launch);
154
+ const dispose = session.dispose.bind(session);
155
+ session.dispose = () => dispose().then(() => new Promise<void>((resolve) => setTimeout(() => { shutdownDone = true; resolve(); }, 30)));
156
+ return session;
157
+ },
158
+ };
159
+ const result = await runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", { runId: "dispose-order", childSessionFactory: wrapped });
160
+ assert.equal(result.exitCode, 0);
161
+ assert.equal(shutdownDone, true);
162
+ });
163
+
164
+ it("captures structured output in memory", async () => {
165
+ const structured = createStructuredOutputRuntime({ type: "object", required: ["ok"], properties: { ok: { type: "boolean" } } }, tempDir);
166
+ mockPi.onCall({ structuredOutput: { ok: true } });
167
+ const result = await runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", { runId: "structured-memory", structuredOutput: structured });
168
+ assert.equal(result.exitCode, 0, result.error);
169
+ assert.deepEqual(result.structuredOutput, { ok: true });
170
+ assert.equal(mockPi.sessions[0]?.launch.runtime.structuredOutput?.schema.type, "object");
171
+ assert.deepEqual(JSON.parse(fs.readFileSync(structured.outputPath, "utf-8")), { ok: true });
172
+ });
173
+
174
+ it("fails when the child never calls structured_output", async () => {
175
+ const structured = createStructuredOutputRuntime({ type: "object" }, tempDir);
176
+ mockPi.onCall({ output: "prose only" });
177
+ const result = await runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", { runId: "structured-missing", structuredOutput: structured });
178
+ assert.equal(result.exitCode, 1);
179
+ assert.match(result.error ?? "", /Missing structured_output call/);
180
+ assert.equal(result.structuredOutputFailed, true);
181
+ });
182
+
183
+ it("keeps a detached child running in-process and delivers its terminal result", async () => {
184
+ const release = path.join(tempDir, "release-detach");
185
+ mockPi.onCall({ steps: [{ waitForPath: release, jsonl: [{ type: "message_end", message: { role: "assistant", content: [{ type: "text", text: "after detach" }], model: "mock/test-model", stopReason: "stop", usage: { input: 1, output: 1, cacheRead: 0, cacheWrite: 0, cost: { total: 0 } } } }] }] });
186
+ let detach: ((reason?: string) => boolean) | undefined;
187
+ let terminal: SingleResult | undefined;
188
+ const receipt = await new Promise<SingleResult>((resolve, reject) => {
189
+ runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", {
190
+ runId: "detach-session",
191
+ onDetachReady: (next) => { detach = next; },
192
+ onDetachReceipt: () => true,
193
+ onDetachedExit: (result) => { terminal = result; },
194
+ }).then(resolve, reject);
195
+ void waitFor(() => detach !== undefined && mockPi.sessions[0]?.task !== undefined).then(() => {
196
+ assert.equal(detach!("user request"), true);
197
+ }, reject);
198
+ });
199
+ assert.equal(receipt.detached, true);
200
+ assert.equal(receipt.detachedReason, "user request");
201
+ assert.equal(mockPi.sessions[0]?.aborted, false, "detach must not abort the session");
202
+ await disposeChildSessions();
203
+ assert.equal(mockPi.sessions[0]?.aborted, false, "parent session shutdown must not abort a detached child");
204
+ fs.writeFileSync(release, "go");
205
+ await waitFor(() => terminal !== undefined);
206
+ assert.equal(terminal?.exitCode, 0);
207
+ assert.equal(terminal?.finalOutput, "after detach");
208
+ assert.equal(terminal?.detachedReason, "user request");
209
+ assert.equal(mockPi.sessions[0]?.disposed, true);
210
+ });
211
+
212
+ it("reports a parent session shutdown as the reason an attached child stopped", async () => {
213
+ mockPi.onCall({ hangUntilAbort: true });
214
+ const run = runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", { runId: "shutdown-attached" });
215
+ await waitFor(() => mockPi.sessions[0]?.task !== undefined);
216
+ await disposeChildSessions();
217
+ const result = await run;
218
+ assert.equal(result.exitCode, 1);
219
+ assert.equal(result.error, "Subagent stopped because the parent session shut down.");
220
+ });
221
+ });
222
+
223
+ /** A pi module stub whose loader reads `process.env` after an await, the way a real extension load does. */
224
+ function stubPi(session: Record<string, unknown> = {}, onReload?: () => void): PiCodingAgentModule {
225
+ return {
226
+ ModelRuntime: { create: async () => ({}) },
227
+ SettingsManager: { create: () => ({}) },
228
+ DefaultResourceLoader: class { async reload() { await new Promise((resolve) => setTimeout(resolve, 10)); onReload?.(); } },
229
+ SessionManager: { inMemory: () => ({}) },
230
+ resolveCliModel: () => ({}),
231
+ createAgentSession: async () => ({ session: { bindExtensions: async () => {}, dispose() {}, extensionRunner: { hasHandlers: () => false }, subscribe: () => () => {}, prompt: async () => {}, abort: async () => {}, steer: async () => {}, followUp: async () => {}, messages: [], sessionId: "s", ...session } }),
232
+ } as unknown as PiCodingAgentModule;
233
+ }
234
+ const stubLaunch: ChildSessionLaunch = { cwd: process.cwd(), storage: { kind: "memory" }, extensionPaths: [], ambientExtensions: false, hooks: [], noSkills: true, noContextFiles: true, runtime: { fanoutChild: false, depth: 1, waitTool: { enabled: false }, fast: false } as ChildSessionLaunch["runtime"] };
235
+
236
+ describe("default child session factory", () => {
237
+ it("serializes process env through extension loading and session start across concurrent launches", async () => {
238
+ const seen: string[] = [];
239
+ const bound: string[] = [];
240
+ const bindExtensions = async () => { await new Promise((resolve) => setTimeout(resolve, 10)); bound.push(process.env.SELESAI_SUBAGENT_TEST_ENV ?? ""); };
241
+ const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => stubPi({ bindExtensions }, () => { seen.push(process.env.SELESAI_SUBAGENT_TEST_ENV ?? ""); }) });
242
+ await Promise.all([
243
+ factory.create({ ...stubLaunch, processEnv: { SELESAI_SUBAGENT_TEST_ENV: "a" } }),
244
+ factory.create({ ...stubLaunch, processEnv: { SELESAI_SUBAGENT_TEST_ENV: "b" } }),
245
+ ]);
246
+ delete process.env.SELESAI_SUBAGENT_TEST_ENV;
247
+ assert.deepEqual(seen, ["a", "b"]);
248
+ assert.deepEqual(bound, ["a", "b"]);
249
+ });
250
+
251
+ it("marks each child's loader as reloaded so pi resets its extension cache", async () => {
252
+ const flags: boolean[] = [];
253
+ const pi = stubPi();
254
+ pi.DefaultResourceLoader = class { loaded = false; async reload() { flags.push(this.loaded); } } as unknown as PiCodingAgentModule["DefaultResourceLoader"];
255
+ const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => pi });
256
+ await factory.create(stubLaunch);
257
+ await factory.create(stubLaunch);
258
+ assert.deepEqual(flags, [true, true]);
259
+ });
260
+
261
+ it("resolves models from providers queued during child extension loading", async () => {
262
+ const registeredProviders: string[] = [];
263
+ const registeredNativeProviders: string[] = [];
264
+ let refreshed = false;
265
+ let pendingRuntime: { pendingProviderRegistrations: unknown[]; pendingNativeProviderRegistrations: unknown[] } | undefined;
266
+ const pi = stubPi();
267
+ pi.ModelRuntime = { create: async () => ({ registerProvider: (name: string) => { registeredProviders.push(name); }, registerNativeProvider: (provider: { id: string }) => { registeredNativeProviders.push(provider.id); }, refresh: async () => { refreshed = true; } }) } as unknown as PiCodingAgentModule["ModelRuntime"];
268
+ pi.DefaultResourceLoader = class {
269
+ runtime = {
270
+ pendingProviderRegistrations: [{ name: "router", config: { models: [{ id: "mimo-v2.5" }] }, extensionPath: "/extensions/router.ts" }],
271
+ pendingNativeProviderRegistrations: [{ provider: { id: "native-router", models: [{ id: "native-model" }] }, extensionPath: "/extensions/native-router.ts" }],
272
+ };
273
+ async reload() { pendingRuntime = this.runtime; }
274
+ getExtensions() { return { extensions: [], errors: [], runtime: this.runtime }; }
275
+ } as unknown as PiCodingAgentModule["DefaultResourceLoader"];
276
+ pi.resolveCliModel = (({ cliModel }) => {
277
+ assert.equal(cliModel, "router/mimo-v2.5");
278
+ assert.deepEqual(registeredProviders, ["router"]);
279
+ assert.deepEqual(registeredNativeProviders, ["native-router"]);
280
+ assert.equal(refreshed, true);
281
+ return { model: { provider: "router", id: "mimo-v2.5" } };
282
+ }) as unknown as PiCodingAgentModule["resolveCliModel"];
283
+ pi.createAgentSession = (async ({ model }) => ({ session: { bindExtensions: async () => {}, dispose() {}, extensionRunner: { hasHandlers: () => false }, subscribe: () => () => {}, prompt: async () => {}, abort: async () => {}, steer: async () => {}, followUp: async () => {}, messages: [], sessionId: "s", model } })) as unknown as PiCodingAgentModule["createAgentSession"];
284
+
285
+ const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => pi });
286
+ const child = await factory.create({ ...stubLaunch, model: "router/mimo-v2.5" });
287
+
288
+ assert.equal(child.modelId, "router/mimo-v2.5");
289
+ assert.deepEqual(pendingRuntime?.pendingProviderRegistrations, []);
290
+ assert.deepEqual(pendingRuntime?.pendingNativeProviderRegistrations, []);
291
+ });
292
+
293
+ it("resolves queued providers when the loader has no native provider queue", async () => {
294
+ const registeredProviders: string[] = [];
295
+ let refreshed = false;
296
+ let pendingRuntime: { pendingProviderRegistrations?: unknown[] } | undefined;
297
+ const pi = stubPi();
298
+ pi.ModelRuntime = { create: async () => ({ registerProvider: (name: string) => { registeredProviders.push(name); }, registerNativeProvider: () => {}, refresh: async () => { refreshed = true; } }) } as unknown as PiCodingAgentModule["ModelRuntime"];
299
+ pi.DefaultResourceLoader = class {
300
+ runtime = {
301
+ pendingProviderRegistrations: [{ name: "router", config: { models: [{ id: "mimo-v2.5" }] }, extensionPath: "/extensions/router.ts" }],
302
+ };
303
+ async reload() { pendingRuntime = this.runtime; }
304
+ getExtensions() { return { extensions: [], errors: [], runtime: this.runtime }; }
305
+ } as unknown as PiCodingAgentModule["DefaultResourceLoader"];
306
+ pi.resolveCliModel = (({ cliModel }) => {
307
+ assert.equal(cliModel, "router/mimo-v2.5");
308
+ assert.deepEqual(registeredProviders, ["router"]);
309
+ assert.equal(refreshed, true);
310
+ return { model: { provider: "router", id: "mimo-v2.5" } };
311
+ }) as unknown as PiCodingAgentModule["resolveCliModel"];
312
+ pi.createAgentSession = (async ({ model }) => ({ session: { bindExtensions: async () => {}, dispose() {}, extensionRunner: { hasHandlers: () => false }, subscribe: () => () => {}, prompt: async () => {}, abort: async () => {}, steer: async () => {}, followUp: async () => {}, messages: [], sessionId: "s", model } })) as unknown as PiCodingAgentModule["createAgentSession"];
313
+
314
+ const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => pi });
315
+ const child = await factory.create({ ...stubLaunch, model: "router/mimo-v2.5" });
316
+
317
+ assert.equal(child.modelId, "router/mimo-v2.5");
318
+ assert.deepEqual(pendingRuntime?.pendingProviderRegistrations, []);
319
+ });
320
+
321
+ it("reports a missing extension cache reset when the child loads extension files", async () => {
322
+ const errors: string[] = [];
323
+ const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => stubPi() });
324
+ await factory.create({ ...stubLaunch, onExtensionError: (error) => errors.push(error.extensionPath) });
325
+ await factory.create({ ...stubLaunch, extensionPaths: ["/tmp/ext.ts"], onExtensionError: (error) => errors.push(error.extensionPath) });
326
+ assert.deepEqual(errors, ["<loader>"]);
327
+ });
328
+
329
+ it("initializes the theme from settings before each child session", async () => {
330
+ const themed: Array<string | undefined> = [];
331
+ const pi = stubPi();
332
+ pi.initTheme = ((themeName?: string) => { themed.push(themeName); }) as PiCodingAgentModule["initTheme"];
333
+ pi.SettingsManager = { create: () => ({ getTheme: () => "solarized-dark" }) } as unknown as PiCodingAgentModule["SettingsManager"];
334
+ const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => pi });
335
+ await factory.create(stubLaunch);
336
+ await factory.create(stubLaunch);
337
+ assert.deepEqual(themed, ["solarized-dark", "solarized-dark"]);
338
+ });
339
+
340
+ it("skips theme initialization when the pi module has no initTheme export", async () => {
341
+ const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => stubPi() });
342
+ await factory.create(stubLaunch);
343
+ // Reaching here without throwing is the assertion: `settingsManager.getTheme()`
344
+ // must not be evaluated when `initTheme` is unavailable.
345
+ });
346
+
347
+ it("disposes the session when bindExtensions rejects", async () => {
348
+ let disposed = 0;
349
+ const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => stubPi({ bindExtensions: async () => { throw new Error("bind failed"); }, dispose: () => { disposed += 1; } }) });
350
+ await assert.rejects(factory.create(stubLaunch), /bind failed/);
351
+ assert.equal(disposed, 1);
352
+ });
353
+
354
+ it("leaves detached children running on dispose and keeps the shared runtime", async () => {
355
+ let aborted = 0;
356
+ let runtimes = 0;
357
+ const pi = stubPi({ abort: async () => { aborted += 1; } });
358
+ pi.ModelRuntime = { create: async () => { runtimes += 1; return {}; } } as unknown as PiCodingAgentModule["ModelRuntime"];
359
+ const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => pi });
360
+ const child = await factory.create(stubLaunch);
361
+ child.detached = true;
362
+ await factory.dispose();
363
+ assert.equal(aborted, 0);
364
+ assert.equal(child.shutDown, undefined);
365
+ await factory.create(stubLaunch);
366
+ assert.equal(runtimes, 1, "runtime is kept while a detached child runs");
367
+ });
368
+
369
+ it("bounds the wait for a stuck session_shutdown handler", { timeout: 2_000 }, async () => {
370
+ const factory = createDefaultChildSessionFactory({ shutdownTimeoutMs: 50, loadPiCodingAgent: async () => stubPi({ extensionRunner: { hasHandlers: () => true, emit: () => new Promise(() => {}) } }) });
371
+ (await factory.create(stubLaunch)).dispose();
372
+ await factory.dispose();
373
+ });
374
+ });
@@ -359,7 +359,8 @@ describe("intercom result delivery cutover", { skip: !available ? "executor not
359
359
  assert.notEqual(revivedIds[1], revivedIds[0], "expected the latest revived run id from pass two");
360
360
  assert.equal(value?.firstOutput, "Completed retained follow-up one");
361
361
  assert.equal(value?.output, "Completed retained follow-up two");
362
- assert.equal(revivedIds.every((id) => !fs.existsSync(path.join(ASYNC_DIR, id, "workflow-result.json"))), true);
362
+ // Awaiting may consume a pending result before the runner promotes its public file.
363
+ assert.equal(mockPi.callCount(), 2, "each retained follow-up must execute once without replay or extra children");
363
364
  } finally {
364
365
  fs.rmSync(sourceAsyncDir, { recursive: true, force: true });
365
366
  for (const id of revivedIds) fs.rmSync(path.join(ASYNC_DIR, id), { recursive: true, force: true });
@@ -905,7 +906,7 @@ describe("intercom result delivery cutover", { skip: !available ? "executor not
905
906
  }
906
907
  });
907
908
 
908
- it("resume action revives completed multi-child async runs by index", async () => {
909
+ for (const workflow of [false, true]) it(`${workflow ? "workflow string resume" : "resume action"} revives completed multi-child async runs by index`, async () => {
909
910
  mockPi.onCall({ output: "revived async child b" });
910
911
  const runId = `resume-revive-multi-${Date.now()}`;
911
912
  const asyncDir = path.join(ASYNC_DIR, runId);
@@ -933,17 +934,26 @@ describe("intercom result delivery cutover", { skip: !available ? "executor not
933
934
 
934
935
  const result = await executor.execute(
935
936
  "resume-revive-multi",
936
- { action: "resume", id: runId, index: 1, message: "What did b find?" },
937
+ workflow
938
+ ? { async: false, workflowScript: `return runs.run("indexed", { resume: ${JSON.stringify(runId)}, index: 1, task: "What did b find?", output: false });` }
939
+ : { action: "resume", id: runId, index: 1, message: "What did b find?" },
937
940
  new AbortController().signal,
938
941
  undefined,
939
942
  makeMinimalCtx(tempDir),
940
943
  );
941
944
 
942
- assert.equal(result.isError, undefined);
943
- assert.match(result.content[0]?.text ?? "", /Revived async subagent from/);
944
- assert.match(result.details?.asyncId ?? "", /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
945
- assert.match(result.content[0]?.text ?? "", /Agent: b/);
946
- assert.match(result.content[0]?.text ?? "", new RegExp(secondSession.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")));
945
+ assert.equal(result.isError, undefined, result.content[0]?.text);
946
+ if (workflow) {
947
+ const child = result.details!.workflow!.value as { runId: string; agent: string; continuation: { runIds: string[] } };
948
+ assert.equal(child.agent, "b");
949
+ assert.deepEqual(child.continuation.runIds, [runId, child.runId]);
950
+ assert.deepEqual(result.details!.workflow!.receipt!.entries.indexed.continuation, child.continuation);
951
+ } else {
952
+ assert.match(result.content[0]?.text ?? "", /Revived async subagent from/);
953
+ assert.match(result.details?.asyncId ?? "", /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
954
+ assert.match(result.content[0]?.text ?? "", /Agent: b/);
955
+ assert.match(result.content[0]?.text ?? "", new RegExp(secondSession.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")));
956
+ }
947
957
  const args = await readMockCallArgs(0);
948
958
  assert.equal(args[args.indexOf("--session") + 1], secondSession);
949
959
  assert.equal(args[args.indexOf("--model") + 1], "anthropic/claude-sonnet-4:high");
@@ -1238,7 +1248,7 @@ describe("intercom result delivery cutover", { skip: !available ? "executor not
1238
1248
  {
1239
1249
  workflowScript: `return await runs.run("gated", { agent: "worker", task: "run", gate: "npm test" });`,
1240
1250
  async: true,
1241
- acceptance: false,
1251
+ acceptance: "checked",
1242
1252
  },
1243
1253
  new AbortController().signal,
1244
1254
  undefined,
@@ -1943,4 +1953,4 @@ describe("intercom result delivery cutover", { skip: !available ? "executor not
1943
1953
  assert.match(message, /process failed · output absent/);
1944
1954
  assert.doesNotMatch(message, /Inspect that output before retrying/);
1945
1955
  });
1946
- });
1956
+ });
@@ -31,6 +31,16 @@ afterEach(() => {
31
31
  }
32
32
  });
33
33
 
34
+ const RUNNER_CHILD_SESSION_FACTORY = path.resolve(import.meta.dirname, "../support/runner-child-session-factory.ts");
35
+
36
+ /** Queue one scripted response every child session the runner creates replays. */
37
+ function scriptChildSessions(dir: string, response: object): string {
38
+ const queueDir = path.join(dir, "child-sessions");
39
+ fs.mkdirSync(queueDir, { recursive: true });
40
+ fs.writeFileSync(path.join(queueDir, "default-response.json"), JSON.stringify(response), "utf-8");
41
+ return queueDir;
42
+ }
43
+
34
44
  function runProcess(command: string, args: string[], cwd: string, env: NodeJS.ProcessEnv): Promise<number | null> {
35
45
  return new Promise((resolve, reject) => {
36
46
  const child = spawn(command, args, { cwd, stdio: "inherit", shell: false, env });
@@ -56,7 +66,7 @@ async function waitForFileCount(dir: string, count: number): Promise<void> {
56
66
  }
57
67
 
58
68
  describe("Orca progress-tab observer", () => {
59
- it("mirrors a native Pi child without replacing its execution path", { skip: process.platform === "win32" ? "Orca progress tabs are not supported on Windows" : undefined }, async () => {
69
+ it("mirrors an in-process Pi child without replacing its execution path", { skip: process.platform === "win32" ? "Orca progress tabs are not supported on Windows" : undefined }, async () => {
60
70
  const dir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-orca-native-"));
61
71
  tempDirs.push(dir);
62
72
  const asyncDir = path.join(dir, "async");
@@ -72,7 +82,7 @@ describe("Orca progress-tab observer", () => {
72
82
  { type: "message_end", message: { role: "assistant", content: [{ type: "text", text: "native Pi result" }], stopReason: "stop", usage: { input: 1, output: 2, cacheRead: 0, cacheWrite: 0, cost: { total: 0 } } } },
73
83
  { type: "agent_settled" },
74
84
  ];
75
- const fakePi = writeNodeCommand(dir, "pi", `for (const event of ${JSON.stringify(childEvents)}) process.stdout.write(JSON.stringify(event)+'\\n')`);
85
+ const queueDir = scriptChildSessions(dir, { jsonl: childEvents });
76
86
 
77
87
  const resultPath = path.join(dir, "result.json");
78
88
  const configPath = path.join(dir, "config.json");
@@ -93,6 +103,7 @@ describe("Orca progress-tab observer", () => {
93
103
  artifactConfig: { enabled: false },
94
104
  asyncDir,
95
105
  resultMode: "single",
106
+ childSessionFactoryModule: RUNNER_CHILD_SESSION_FACTORY,
96
107
  }));
97
108
  const repo = path.resolve(import.meta.dirname, "../..");
98
109
  const exitCode = await runProcess(
@@ -103,7 +114,7 @@ describe("Orca progress-tab observer", () => {
103
114
  ...process.env,
104
115
  SELESAI_CODING_AGENT_DIR: agentDir,
105
116
  SELESAI_SUBAGENT_ORCA_BINARY: fakeOrca,
106
- SELESAI_SUBAGENT_SELESAI_BINARY: fakePi,
117
+ MOCK_PI_QUEUE_DIR: queueDir,
107
118
  ORCA_TEST_CAPTURE: capture,
108
119
  },
109
120
  );
@@ -132,7 +143,7 @@ describe("Orca progress-tab observer", () => {
132
143
  fs.mkdirSync(path.join(agentDir, "extensions", "subagent"), { recursive: true });
133
144
  fs.writeFileSync(path.join(agentDir, "extensions", "subagent", "config.json"), JSON.stringify({ orcaProgressTabs: { enabled: true } }));
134
145
  const fakeOrca = writeNodeCommand(dir, "orca", "const fs=require('fs'),path=require('path');const args=process.argv.slice(2);fs.writeFileSync(path.join(process.env.ORCA_TEST_CAPTURE_DIR, process.pid+'.json'),JSON.stringify(args))");
135
- const fakePi = writeNodeCommand(dir, "pi", "process.stdout.write(JSON.stringify({type:'message_end',message:{role:'assistant',content:[{type:'text',text:'parallel result'}]}})+'\\n')");
146
+ const queueDir = scriptChildSessions(dir, { output: "parallel result" });
136
147
 
137
148
  const resultPath = path.join(dir, "result.json");
138
149
  const configPath = path.join(dir, "config.json");
@@ -152,6 +163,7 @@ describe("Orca progress-tab observer", () => {
152
163
  artifactConfig: { enabled: false },
153
164
  asyncDir,
154
165
  resultMode: "parallel",
166
+ childSessionFactoryModule: RUNNER_CHILD_SESSION_FACTORY,
155
167
  }));
156
168
  const repo = path.resolve(import.meta.dirname, "../..");
157
169
  const exitCode = await runProcess(
@@ -162,7 +174,7 @@ describe("Orca progress-tab observer", () => {
162
174
  ...process.env,
163
175
  SELESAI_CODING_AGENT_DIR: agentDir,
164
176
  SELESAI_SUBAGENT_ORCA_BINARY: fakeOrca,
165
- SELESAI_SUBAGENT_SELESAI_BINARY: fakePi,
177
+ MOCK_PI_QUEUE_DIR: queueDir,
166
178
  ORCA_TEST_CAPTURE_DIR: captures,
167
179
  },
168
180
  );
@@ -211,4 +223,4 @@ describe("Orca progress-tab observer", () => {
211
223
  const createdOrder = fs.readFileSync(orderFile, "utf-8").trim().split("\n");
212
224
  assert.deepEqual(createdOrder, titles);
213
225
  });
214
- });
226
+ });