@selesai/code 0.9.10 → 0.9.12

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 (862) hide show
  1. package/CHANGELOG.md +271 -255
  2. package/dist/cli/args.js +13 -2
  3. package/dist/cli/args.test.js +8 -0
  4. package/dist/cli/credential-print.js +4 -4
  5. package/dist/cli.js +0 -0
  6. package/dist/config.d.ts +4 -6
  7. package/dist/config.js +10 -14
  8. package/dist/core/agent-session-auto-handoff.test.js +24 -1
  9. package/dist/core/agent-session.d.ts +10 -4
  10. package/dist/core/agent-session.js +61 -46
  11. package/dist/core/compaction/branch-summarization.js +30 -30
  12. package/dist/core/compaction/compaction.js +81 -81
  13. package/dist/core/compaction/utils.js +2 -2
  14. package/dist/core/defaults.d.ts +1 -0
  15. package/dist/core/defaults.js +9 -0
  16. package/dist/core/export-html/template.css +1066 -1066
  17. package/dist/core/export-html/template.html +55 -55
  18. package/dist/core/export-html/template.js +1864 -1864
  19. package/dist/core/export-html/vendor/highlight.min.js +1212 -1212
  20. package/dist/core/export-html/vendor/marked.min.js +78 -78
  21. package/dist/core/extensions/loader.js +108 -35
  22. package/dist/core/extensions/loader.test.js +21 -0
  23. package/dist/core/extensions/types.d.ts +12 -4
  24. package/dist/core/keybindings.d.ts +2 -2
  25. package/dist/core/messages.js +7 -7
  26. package/dist/core/model-resolver.d.ts +1 -0
  27. package/dist/core/model-resolver.js +10 -4
  28. package/dist/core/package-manager.js +4 -4
  29. package/dist/core/sdk.d.ts +5 -5
  30. package/dist/core/sdk.js +16 -4
  31. package/dist/core/settings-manager.d.ts +6 -2
  32. package/dist/core/settings-manager.js +22 -3
  33. package/dist/core/tools/bash.d.ts +18 -1
  34. package/dist/core/tools/bash.js +41 -23
  35. package/dist/core/tools/index.d.ts +4 -2
  36. package/dist/core/tools/index.js +9 -2
  37. package/dist/core/tools/powershell.d.ts +15 -0
  38. package/dist/core/tools/powershell.js +38 -0
  39. package/dist/core/tools/powershell.test.d.ts +1 -0
  40. package/dist/core/tools/powershell.test.js +20 -0
  41. package/dist/defaults/settings.json +0 -1
  42. package/dist/extensions/context-compaction-reminder.test.ts +82 -82
  43. package/dist/extensions/context-compaction-reminder.ts +28 -28
  44. package/dist/extensions/model-prompt-injector/index.test.ts +0 -10
  45. package/dist/extensions/model-prompt-injector/index.ts +0 -3
  46. package/dist/extensions/pi-intercom/CHANGELOG.md +53 -16
  47. package/dist/extensions/pi-intercom/LICENSE +21 -21
  48. package/dist/extensions/pi-intercom/README.md +41 -8
  49. package/dist/extensions/pi-intercom/banner.png +0 -0
  50. package/dist/extensions/pi-intercom/broker/broker.ts +498 -215
  51. package/dist/extensions/pi-intercom/broker/client.test.ts +83 -83
  52. package/dist/extensions/pi-intercom/broker/client.ts +39 -12
  53. package/dist/extensions/pi-intercom/broker/extension.test.ts +486 -387
  54. package/dist/extensions/pi-intercom/broker/framing.test.ts +114 -114
  55. package/dist/extensions/pi-intercom/broker/paths.test.ts +153 -153
  56. package/dist/extensions/pi-intercom/broker/paths.ts +134 -134
  57. package/dist/extensions/pi-intercom/broker/protocol.ts +26 -0
  58. package/dist/extensions/pi-intercom/broker/runtime-claim.test.ts +34 -34
  59. package/dist/extensions/pi-intercom/broker/runtime-claim.ts +21 -21
  60. package/dist/extensions/pi-intercom/broker/spawn.test.ts +5 -20
  61. package/dist/extensions/pi-intercom/config.test.ts +41 -0
  62. package/dist/extensions/pi-intercom/config.ts +21 -0
  63. package/dist/extensions/pi-intercom/cwd.test.ts +40 -40
  64. package/dist/extensions/pi-intercom/cwd.ts +31 -31
  65. package/dist/extensions/pi-intercom/extension-api.ts +84 -44
  66. package/dist/extensions/pi-intercom/format-context.test.ts +31 -31
  67. package/dist/extensions/pi-intercom/format-context.ts +32 -32
  68. package/dist/extensions/pi-intercom/index.ts +362 -26
  69. package/dist/extensions/pi-intercom/intercom.integration.test.ts +819 -13
  70. package/dist/extensions/pi-intercom/package.json +1 -1
  71. package/dist/extensions/pi-intercom/project-agent.ts +2 -2
  72. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +8 -110
  73. package/dist/extensions/pi-intercom/test/overlay-width.test.ts +66 -66
  74. package/dist/extensions/pi-intercom/types.ts +32 -5
  75. package/dist/extensions/pi-intercom/ui/compose.ts +143 -143
  76. package/dist/extensions/pi-intercom/ui/inline-message.ts +6 -0
  77. package/dist/extensions/pi-intercom/ui/session-list.ts +166 -166
  78. package/dist/extensions/pi-powerline-footer/bash-mode/shell-session.ts +286 -286
  79. package/dist/extensions/pi-powerline-footer/bash-mode/transcript.ts +108 -108
  80. package/dist/extensions/pi-powerline-footer/separators.ts +57 -57
  81. package/dist/extensions/pi-powerline-footer/tests/session-usage.test.ts +47 -47
  82. package/dist/extensions/pi-powerline-footer/tests/tps.test.ts +39 -39
  83. package/dist/extensions/pi-powerline-footer/theme.example.json +24 -24
  84. package/dist/extensions/pi-powerline-footer/theme.json +12 -12
  85. package/dist/extensions/pi-powerline-footer/tps.ts +345 -345
  86. package/dist/extensions/pi-rewind-hook/README.md +245 -245
  87. package/dist/extensions/pi-rewind-hook/index.ts +1445 -1445
  88. package/dist/extensions/pi-rewind-hook/package.json +29 -29
  89. package/dist/extensions/pi-subagents/.github/assets/subagent-fleet-inspector.png +0 -0
  90. package/dist/extensions/pi-subagents/.github/workflows/release.yml +28 -0
  91. package/dist/extensions/pi-subagents/.github/workflows/test.yml +51 -0
  92. package/dist/extensions/pi-subagents/.greptile/config.json +33 -0
  93. package/dist/extensions/pi-subagents/.greptile/files.json +8 -0
  94. package/dist/extensions/pi-subagents/.greptile/rules.md +16 -0
  95. package/dist/extensions/pi-subagents/CHANGELOG.md +309 -87
  96. package/dist/extensions/pi-subagents/README.md +15 -17
  97. package/dist/extensions/pi-subagents/agents/oracle.md +3 -1
  98. package/dist/extensions/pi-subagents/agents/researcher.md +32 -13
  99. package/dist/extensions/pi-subagents/agents/reviewer.md +13 -2
  100. package/dist/extensions/pi-subagents/agents/scout.md +2 -2
  101. package/dist/extensions/pi-subagents/agents/worker.md +2 -1
  102. package/dist/extensions/pi-subagents/async-retention-discovery-worker.mjs +180 -0
  103. package/dist/extensions/pi-subagents/docs/configuration.md +106 -27
  104. package/dist/extensions/pi-subagents/docs/extension-api.md +85 -21
  105. package/dist/extensions/pi-subagents/docs/missions.md +41 -4
  106. package/dist/extensions/pi-subagents/docs/models.md +52 -9
  107. package/dist/extensions/pi-subagents/docs/observability.md +103 -16
  108. package/dist/extensions/pi-subagents/docs/tool-reference.md +60 -45
  109. package/dist/extensions/pi-subagents/docs/watchdog.md +60 -3
  110. package/dist/extensions/pi-subagents/docs/workflows.md +181 -7
  111. package/dist/extensions/pi-subagents/index.ts +10 -1
  112. package/dist/extensions/pi-subagents/install.mjs +4 -4
  113. package/dist/extensions/pi-subagents/package-lock.json +1483 -1470
  114. package/dist/extensions/pi-subagents/package.json +6 -3
  115. package/dist/extensions/pi-subagents/prompts/council.md +60 -0
  116. package/dist/extensions/pi-subagents/prompts/parallel-review.md +5 -1
  117. package/dist/extensions/pi-subagents/prompts/review-loop.md +9 -5
  118. package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +254 -0
  119. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +18 -17
  120. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +31 -9
  121. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +107 -140
  122. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +9 -12
  123. package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +39 -0
  124. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +44 -92
  125. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +261 -368
  126. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +6 -2
  127. package/dist/extensions/pi-subagents/src/agents/agents.ts +388 -85
  128. package/dist/extensions/pi-subagents/src/agents/builtin-names.ts +14 -0
  129. package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +418 -0
  130. package/dist/extensions/pi-subagents/src/agents/skills.ts +1 -1
  131. package/dist/extensions/pi-subagents/src/api/agents.ts +7 -0
  132. package/dist/extensions/pi-subagents/src/api/external-job-provider.ts +195 -0
  133. package/dist/extensions/pi-subagents/src/api/preflight.ts +88 -27
  134. package/dist/extensions/pi-subagents/src/api/project-panes.ts +2 -0
  135. package/dist/extensions/pi-subagents/src/api/shared-types.ts +2 -0
  136. package/dist/extensions/pi-subagents/src/extension/config.ts +20 -11
  137. package/dist/extensions/pi-subagents/src/extension/doctor.ts +14 -6
  138. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +5 -4
  139. package/dist/extensions/pi-subagents/src/extension/index.ts +270 -187
  140. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +65 -28
  141. package/dist/extensions/pi-subagents/src/extension/rpc.ts +120 -11
  142. package/dist/extensions/pi-subagents/src/extension/schemas.ts +46 -64
  143. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +51 -37
  144. package/dist/extensions/pi-subagents/src/extension/tool-result.ts +19 -0
  145. package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +2 -2
  146. package/dist/extensions/pi-subagents/src/inspectors/herdr/client.ts +3 -3
  147. package/dist/extensions/pi-subagents/src/inspectors/herdr/focus.ts +55 -0
  148. package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +2 -1
  149. package/dist/extensions/pi-subagents/src/inspectors/herdr/project-panes.ts +230 -46
  150. package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +26 -4
  151. package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +32 -10
  152. package/dist/extensions/pi-subagents/src/missions/lifecycle.ts +6 -1
  153. package/dist/extensions/pi-subagents/src/missions/store.ts +4 -9
  154. package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +2 -2
  155. package/dist/extensions/pi-subagents/src/policy/authority.ts +2 -0
  156. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +3 -1
  157. package/dist/extensions/pi-subagents/src/runs/background/active-run-index.ts +31 -8
  158. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +210 -52
  159. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +63 -33
  160. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +71 -17
  161. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +886 -0
  162. package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +14 -5
  163. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +49 -56
  164. package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +1 -0
  165. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +3 -33
  166. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +5 -0
  167. package/dist/extensions/pi-subagents/src/runs/background/completion-dedupe.ts +5 -1
  168. package/dist/extensions/pi-subagents/src/runs/background/completion-replay.ts +22 -12
  169. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +105 -71
  170. package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +68 -19
  171. package/dist/extensions/pi-subagents/src/runs/background/index-segment.ts +59 -0
  172. package/dist/extensions/pi-subagents/src/runs/background/inspect-rpc.ts +443 -0
  173. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +94 -10
  174. package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +158 -90
  175. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +141 -53
  176. package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +8 -5
  177. package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +14 -4
  178. package/dist/extensions/pi-subagents/src/runs/background/run-id-query.ts +7 -0
  179. package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +13 -14
  180. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +46 -25
  181. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +823 -0
  182. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +9 -3
  183. package/dist/extensions/pi-subagents/src/runs/background/steering.ts +11 -1
  184. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +594 -216
  185. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +17 -13
  186. package/dist/extensions/pi-subagents/src/runs/background/terminal-run-index.ts +138 -0
  187. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +23 -4
  188. package/dist/extensions/pi-subagents/src/runs/background/wait-subscriptions.ts +82 -4
  189. package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +5 -3
  190. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +21 -14
  191. package/dist/extensions/pi-subagents/src/runs/foreground/async-stop-action.ts +23 -2
  192. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +153 -58
  193. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +7 -9
  194. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +1283 -1657
  195. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +274 -0
  196. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +6 -5
  197. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +59 -10
  198. package/dist/extensions/pi-subagents/src/runs/shared/agent-contract.ts +1 -1
  199. package/dist/extensions/pi-subagents/src/runs/shared/chain-outputs.ts +1 -3
  200. package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +36 -0
  201. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +52 -2
  202. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +1 -1
  203. package/dist/extensions/pi-subagents/src/runs/shared/extension-bindings.ts +78 -0
  204. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +2 -0
  205. package/dist/extensions/pi-subagents/src/runs/shared/external-job-bridge.ts +460 -0
  206. package/dist/extensions/pi-subagents/src/runs/shared/external-job-runner.ts +389 -0
  207. package/dist/extensions/pi-subagents/src/runs/shared/fast-mode-extension.ts +10 -0
  208. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +14 -0
  209. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +243 -0
  210. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +201 -85
  211. package/dist/extensions/pi-subagents/src/runs/shared/model-scope.ts +106 -39
  212. package/dist/extensions/pi-subagents/src/runs/shared/mutation-evidence.ts +145 -0
  213. package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +150 -27
  214. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +46 -4
  215. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +19 -15
  216. package/dist/extensions/pi-subagents/src/runs/shared/permissions.ts +5 -1
  217. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +86 -2
  218. package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +9 -9
  219. package/dist/extensions/pi-subagents/src/runs/shared/session-lease.ts +0 -6
  220. package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +18 -4
  221. package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +51 -7
  222. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +62 -21
  223. package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +1 -3
  224. package/dist/extensions/pi-subagents/src/runs/shared/tool-timeout.ts +1 -3
  225. package/dist/extensions/pi-subagents/src/runs/shared/workflow-graph.ts +1 -23
  226. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +14 -2
  227. package/dist/extensions/pi-subagents/src/shared/artifacts.ts +2 -2
  228. package/dist/extensions/pi-subagents/src/shared/atomic-json.ts +22 -2
  229. package/dist/extensions/pi-subagents/src/shared/capacity-resilient-json.ts +102 -0
  230. package/dist/extensions/pi-subagents/src/shared/completion-owner.ts +14 -0
  231. package/dist/extensions/pi-subagents/src/shared/file-system-retry.ts +49 -1
  232. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +59 -1
  233. package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +12 -5
  234. package/dist/extensions/pi-subagents/src/shared/model-info.ts +20 -0
  235. package/dist/extensions/pi-subagents/src/shared/prompt-resources.ts +0 -40
  236. package/dist/extensions/pi-subagents/src/shared/settings.ts +11 -30
  237. package/dist/extensions/pi-subagents/src/shared/thinking-ceiling.ts +52 -0
  238. package/dist/extensions/pi-subagents/src/shared/types.ts +228 -49
  239. package/dist/extensions/pi-subagents/src/shared/utils.ts +11 -3
  240. package/dist/extensions/pi-subagents/src/shared/watch-strategy.ts +10 -0
  241. package/dist/extensions/pi-subagents/src/slash/prompt-workflows.ts +0 -162
  242. package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +2 -5
  243. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +105 -13
  244. package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +6 -36
  245. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +829 -0
  246. package/dist/extensions/pi-subagents/src/tui/fleet.ts +1415 -0
  247. package/dist/extensions/pi-subagents/src/tui/render.ts +78 -7
  248. package/dist/extensions/pi-subagents/src/watchdog/change-signature.ts +1 -1
  249. package/dist/extensions/pi-subagents/src/watchdog/lsp-diagnostics.ts +1 -0
  250. package/dist/extensions/pi-subagents/src/watchdog/permission-arbiter.ts +59 -51
  251. package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +8 -2
  252. package/dist/extensions/pi-subagents/src/watchdog/tool-actions.ts +2 -1
  253. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +4 -4
  254. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +471 -86
  255. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +140 -0
  256. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
  257. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/cli.d.ts +3 -0
  258. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/register-bedrock.d.ts +2 -0
  259. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/restore-sandbox-env.d.ts +17 -0
  260. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/args.d.ts +57 -0
  261. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/config-selector.d.ts +16 -0
  262. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/file-processor.d.ts +15 -0
  263. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/initial-message.d.ts +18 -0
  264. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/list-models.d.ts +9 -0
  265. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/project-trust.d.ts +10 -0
  266. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/session-picker.d.ts +10 -0
  267. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/startup-ui.d.ts +20 -0
  268. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli.d.ts +3 -0
  269. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/config.d.ts +96 -0
  270. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-runtime.d.ts +119 -0
  271. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-services.d.ts +85 -0
  272. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session.d.ts +620 -0
  273. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-guidance.d.ts +5 -0
  274. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-storage.d.ts +56 -0
  275. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/bash-executor.d.ts +32 -0
  276. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/cache-stats.d.ts +49 -0
  277. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/branch-summarization.d.ts +93 -0
  278. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/compaction.d.ts +128 -0
  279. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/index.d.ts +7 -0
  280. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/utils.d.ts +38 -0
  281. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/defaults.d.ts +3 -0
  282. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/diagnostics.d.ts +15 -0
  283. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/event-bus.d.ts +9 -0
  284. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/exec.d.ts +29 -0
  285. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/experimental.d.ts +2 -0
  286. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/ansi-to-html.d.ts +22 -0
  287. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/index.d.ts +37 -0
  288. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/tool-renderer.d.ts +34 -0
  289. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/index.d.ts +12 -0
  290. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/loader.d.ts +23 -0
  291. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/runner.d.ts +171 -0
  292. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/types.d.ts +1261 -0
  293. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/wrapper.d.ts +20 -0
  294. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/footer-data-provider.d.ts +54 -0
  295. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/http-dispatcher.d.ts +22 -0
  296. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/index.d.ts +13 -0
  297. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/keybindings.d.ts +358 -0
  298. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/messages.d.ts +77 -0
  299. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-config.d.ts +512 -0
  300. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-registry.d.ts +43 -0
  301. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-resolver.d.ts +121 -0
  302. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-runtime.d.ts +82 -0
  303. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/models-store.d.ts +17 -0
  304. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/output-guard.d.ts +7 -0
  305. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/package-manager.d.ts +210 -0
  306. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/project-trust.d.ts +15 -0
  307. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/prompt-templates.d.ts +54 -0
  308. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-attribution.d.ts +4 -0
  309. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-composer.d.ts +55 -0
  310. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/radius.d.ts +2 -0
  311. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/remote-catalog-provider.d.ts +5 -0
  312. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resolve-config-value.d.ts +30 -0
  313. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resource-loader.d.ts +206 -0
  314. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/runtime-credentials.d.ts +15 -0
  315. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/sdk.d.ts +106 -0
  316. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-cwd.d.ts +19 -0
  317. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-manager.d.ts +356 -0
  318. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/settings-manager.d.ts +297 -0
  319. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/skills.d.ts +60 -0
  320. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/slash-commands.d.ts +15 -0
  321. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/source-info.d.ts +18 -0
  322. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/system-prompt.d.ts +28 -0
  323. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/telemetry.d.ts +3 -0
  324. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/timings.d.ts +10 -0
  325. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/bash.d.ts +68 -0
  326. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit-diff.d.ts +106 -0
  327. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit.d.ts +51 -0
  328. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/file-mutation-queue.d.ts +6 -0
  329. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/find.d.ts +35 -0
  330. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/grep.d.ts +37 -0
  331. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/index.d.ts +40 -0
  332. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/ls.d.ts +37 -0
  333. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/output-accumulator.d.ts +52 -0
  334. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/path-utils.d.ts +10 -0
  335. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/read.d.ts +35 -0
  336. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/render-utils.d.ts +24 -0
  337. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
  338. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/truncate.d.ts +70 -0
  339. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/write.d.ts +26 -0
  340. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/trust-manager.d.ts +36 -0
  341. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/usage-totals.d.ts +19 -0
  342. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/index.d.ts +3 -0
  343. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/client.d.ts +61 -0
  344. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/huggingface.d.ts +23 -0
  345. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/index.d.ts +3 -0
  346. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/provider.d.ts +10 -0
  347. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/ui.d.ts +42 -0
  348. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/index.d.ts +35 -0
  349. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/main.d.ts +12 -0
  350. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/migrations.d.ts +33 -0
  351. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/index.d.ts +9 -0
  352. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/armin.d.ts +34 -0
  353. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/assistant-message.d.ts +22 -0
  354. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bash-execution.d.ts +34 -0
  355. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
  356. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
  357. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
  358. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/config-selector.d.ts +102 -0
  359. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
  360. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-editor.d.ts +21 -0
  361. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-entry.d.ts +19 -0
  362. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-message.d.ts +20 -0
  363. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/daxnuts.d.ts +23 -0
  364. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/diff.d.ts +12 -0
  365. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
  366. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
  367. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-editor.d.ts +22 -0
  368. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-input.d.ts +23 -0
  369. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-selector.d.ts +26 -0
  370. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/first-time-setup.d.ts +25 -0
  371. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/footer.d.ts +32 -0
  372. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/index.d.ts +34 -0
  373. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/keybinding-hints.d.ts +13 -0
  374. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/login-dialog.d.ts +52 -0
  375. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/model-selector.d.ts +54 -0
  376. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/oauth-selector.d.ts +33 -0
  377. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/scoped-models-selector.d.ts +42 -0
  378. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
  379. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector.d.ts +95 -0
  380. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/settings-selector.d.ts +77 -0
  381. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
  382. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
  383. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/status-indicator.d.ts +28 -0
  384. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/theme-selector.d.ts +11 -0
  385. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
  386. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tool-execution.d.ts +63 -0
  387. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tree-selector.d.ts +94 -0
  388. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/trust-selector.d.ts +23 -0
  389. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
  390. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message.d.ts +14 -0
  391. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
  392. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/interactive-mode.d.ts +394 -0
  393. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/model-search.d.ts +12 -0
  394. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme-controller.d.ts +29 -0
  395. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme.d.ts +120 -0
  396. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/print-mode.d.ts +28 -0
  397. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/jsonl.d.ts +17 -0
  398. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-client.d.ts +246 -0
  399. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-mode.d.ts +20 -0
  400. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-types.d.ts +457 -0
  401. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/package-manager-cli.d.ts +8 -0
  402. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/rpc-entry.d.ts +3 -0
  403. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/ansi.d.ts +2 -0
  404. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/changelog.d.ts +22 -0
  405. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/child-process.d.ts +18 -0
  406. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-image.d.ts +11 -0
  407. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-native.d.ts +11 -0
  408. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard.d.ts +4 -0
  409. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/deprecation.d.ts +4 -0
  410. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/exif-orientation.d.ts +5 -0
  411. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/frontmatter.d.ts +8 -0
  412. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/fs-watch.d.ts +5 -0
  413. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/git.d.ts +26 -0
  414. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/html.d.ts +7 -0
  415. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-convert.d.ts +10 -0
  416. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-process.d.ts +18 -0
  417. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-core.d.ts +30 -0
  418. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-worker.d.ts +2 -0
  419. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize.d.ts +16 -0
  420. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/json.d.ts +3 -0
  421. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/mime.d.ts +3 -0
  422. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/open-browser.d.ts +9 -0
  423. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/paths.d.ts +31 -0
  424. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/photon.d.ts +21 -0
  425. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/pi-user-agent.d.ts +2 -0
  426. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/shell.d.ts +31 -0
  427. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/sleep.d.ts +5 -0
  428. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/syntax-highlight.d.ts +12 -0
  429. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/tools-manager.d.ts +3 -0
  430. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/version-check.d.ts +15 -0
  431. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/windows-self-update.d.ts +3 -0
  432. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/index.mjs +1 -1
  433. package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +0 -54
  434. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +1053 -414
  435. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +194 -4
  436. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +59 -4
  437. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +0 -77
  438. package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +107 -6
  439. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +211 -897
  440. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +265 -375
  441. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +77 -7
  442. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +1 -1
  443. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +10 -10
  444. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +547 -30
  445. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +2112 -310
  446. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +274 -34
  447. package/dist/extensions/pi-subagents/test/integration/slash-live-state.test.ts +1 -1
  448. package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +20 -3
  449. package/dist/extensions/pi-subagents/test/support/isolated-temp-root.mjs +9 -0
  450. package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +30 -5
  451. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +2 -0
  452. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +4 -2
  453. package/dist/extensions/pi-subagents/test/support/register-loader.mjs +1 -0
  454. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +197 -0
  455. package/dist/extensions/pi-subagents/test/unit/agent-contract.test.ts +14 -0
  456. package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +1 -1
  457. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +204 -27
  458. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +444 -145
  459. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +256 -4
  460. package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +9 -7
  461. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +152 -22
  462. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +29 -0
  463. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +205 -23
  464. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +579 -0
  465. package/dist/extensions/pi-subagents/test/unit/atomic-json.test.ts +24 -0
  466. package/dist/extensions/pi-subagents/test/unit/authority-policy.test.ts +1 -0
  467. package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +3 -3
  468. package/dist/extensions/pi-subagents/test/unit/capacity-resilient-json.test.ts +155 -0
  469. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +2 -2
  470. package/dist/extensions/pi-subagents/test/unit/completion-dedupe.test.ts +7 -0
  471. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +123 -0
  472. package/dist/extensions/pi-subagents/test/unit/completion-replay.test.ts +81 -3
  473. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +109 -7
  474. package/dist/extensions/pi-subagents/test/unit/default-extensions.test.ts +2 -2
  475. package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +5 -2
  476. package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +3 -2
  477. package/dist/extensions/pi-subagents/test/unit/extension-bindings.test.ts +79 -0
  478. package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +22 -0
  479. package/dist/extensions/pi-subagents/test/unit/external-job-runner.test.ts +961 -0
  480. package/dist/extensions/pi-subagents/test/unit/file-system-retry.test.ts +64 -0
  481. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +1110 -0
  482. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +1664 -0
  483. package/dist/extensions/pi-subagents/test/unit/fork-context.test.ts +81 -1
  484. package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +138 -11
  485. package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +41 -2
  486. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +210 -79
  487. package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +95 -0
  488. package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +596 -0
  489. package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +10 -1
  490. package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +3 -5
  491. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +167 -0
  492. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +319 -18
  493. package/dist/extensions/pi-subagents/test/unit/model-info.test.ts +78 -0
  494. package/dist/extensions/pi-subagents/test/unit/model-scope-settings.test.ts +19 -5
  495. package/dist/extensions/pi-subagents/test/unit/model-scope.test.ts +44 -0
  496. package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +129 -0
  497. package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +231 -2
  498. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +28 -1
  499. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +106 -2
  500. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +204 -7
  501. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +59 -4
  502. package/dist/extensions/pi-subagents/test/unit/path-handling.test.ts +2 -6
  503. package/dist/extensions/pi-subagents/test/unit/pi-args-permission-system.test.ts +34 -2
  504. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +116 -6
  505. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +12 -3
  506. package/dist/extensions/pi-subagents/test/unit/pi-spawn.test.ts +56 -61
  507. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +416 -1
  508. package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +9 -2
  509. package/dist/extensions/pi-subagents/test/unit/project-panes-public-api.test.ts +42 -0
  510. package/dist/extensions/pi-subagents/test/unit/prompt-workflows.test.ts +21 -30
  511. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +86 -11
  512. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +49 -1
  513. package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +233 -5
  514. package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +28 -5
  515. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +323 -20
  516. package/dist/extensions/pi-subagents/test/unit/run-id-resolver.test.ts +66 -10
  517. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +68 -5
  518. package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +174 -0
  519. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +679 -0
  520. package/dist/extensions/pi-subagents/test/unit/scheduled-store-root.test.ts +67 -0
  521. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +55 -44
  522. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +399 -84
  523. package/dist/extensions/pi-subagents/test/unit/session-lease.test.ts +13 -0
  524. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
  525. package/dist/extensions/pi-subagents/test/unit/slash-bridge.test.ts +15 -10
  526. package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +11 -7
  527. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +2 -0
  528. package/dist/extensions/pi-subagents/test/unit/steering.test.ts +40 -1
  529. package/dist/extensions/pi-subagents/test/unit/subagent-action-recovery.test.ts +10 -2
  530. package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +38 -3
  531. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +110 -12
  532. package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +204 -19
  533. package/dist/extensions/pi-subagents/test/unit/temp-paths.test.ts +25 -0
  534. package/dist/extensions/pi-subagents/test/unit/thinking-ceiling.test.ts +73 -0
  535. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +90 -50
  536. package/dist/extensions/pi-subagents/test/unit/tool-timeout.test.ts +1 -2
  537. package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +234 -7
  538. package/dist/extensions/pi-subagents/test/unit/watch-strategy.test.ts +24 -0
  539. package/dist/extensions/pi-subagents/test/unit/watchdog-permission-arbiter.test.ts +36 -0
  540. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +37 -9
  541. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +302 -0
  542. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +167 -7
  543. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +113 -0
  544. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +6 -6
  545. package/dist/extensions/pi-web-agent/package.json +31 -31
  546. package/dist/extensions/pi-web-agent/src/backends/config.ts +205 -205
  547. package/dist/extensions/pi-web-agent/src/backends/doctor.ts +136 -136
  548. package/dist/extensions/pi-web-agent/src/backends/factory.ts +152 -152
  549. package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +25 -25
  550. package/dist/extensions/pi-web-agent/src/cache/ttl-cache.ts +28 -28
  551. package/dist/extensions/pi-web-agent/src/changelog-notice.ts +136 -136
  552. package/dist/extensions/pi-web-agent/src/commands/web-agent-config.ts +946 -946
  553. package/dist/extensions/pi-web-agent/src/extension.ts +126 -126
  554. package/dist/extensions/pi-web-agent/src/extract/readability.ts +118 -118
  555. package/dist/extensions/pi-web-agent/src/fetch/browser-resolution.ts +199 -199
  556. package/dist/extensions/pi-web-agent/src/fetch/firecrawl-fetch.ts +100 -100
  557. package/dist/extensions/pi-web-agent/src/fetch/headless-fetch.ts +117 -117
  558. package/dist/extensions/pi-web-agent/src/fetch/http-fetch.ts +67 -67
  559. package/dist/extensions/pi-web-agent/src/orchestration/answer-synthesizer.ts +60 -60
  560. package/dist/extensions/pi-web-agent/src/orchestration/candidate-selector.ts +50 -50
  561. package/dist/extensions/pi-web-agent/src/orchestration/direct-url.ts +52 -52
  562. package/dist/extensions/pi-web-agent/src/orchestration/evidence-quality.ts +105 -105
  563. package/dist/extensions/pi-web-agent/src/orchestration/evidence-ranker.ts +45 -45
  564. package/dist/extensions/pi-web-agent/src/orchestration/index.ts +28 -28
  565. package/dist/extensions/pi-web-agent/src/orchestration/query-planner.ts +47 -47
  566. package/dist/extensions/pi-web-agent/src/orchestration/research-orchestrator.ts +376 -376
  567. package/dist/extensions/pi-web-agent/src/orchestration/research-types.ts +64 -64
  568. package/dist/extensions/pi-web-agent/src/orchestration/research-worker.ts +181 -181
  569. package/dist/extensions/pi-web-agent/src/orchestration/source-profile.ts +101 -101
  570. package/dist/extensions/pi-web-agent/src/orchestration/stop-decider.ts +81 -81
  571. package/dist/extensions/pi-web-agent/src/presentation/config-store.ts +210 -210
  572. package/dist/extensions/pi-web-agent/src/presentation/config.ts +75 -75
  573. package/dist/extensions/pi-web-agent/src/presentation/explore-presentation.ts +61 -61
  574. package/dist/extensions/pi-web-agent/src/presentation/fetch-presentation.ts +54 -54
  575. package/dist/extensions/pi-web-agent/src/presentation/search-presentation.ts +41 -41
  576. package/dist/extensions/pi-web-agent/src/presentation/select-view.ts +20 -20
  577. package/dist/extensions/pi-web-agent/src/presentation/types.ts +63 -63
  578. package/dist/extensions/pi-web-agent/src/search/brave.ts +114 -114
  579. package/dist/extensions/pi-web-agent/src/search/duckduckgo.ts +72 -72
  580. package/dist/extensions/pi-web-agent/src/search/searxng.ts +96 -96
  581. package/dist/extensions/pi-web-agent/src/tools/web-explore.ts +71 -71
  582. package/dist/extensions/pi-web-agent/src/tools/web-fetch-headless.ts +31 -31
  583. package/dist/extensions/pi-web-agent/src/tools/web-fetch.ts +31 -31
  584. package/dist/extensions/pi-web-agent/src/tools/web-search.ts +157 -157
  585. package/dist/extensions/pi-web-agent/src/types.ts +88 -88
  586. package/dist/extensions/ponytail/index.js +31 -25
  587. package/dist/extensions/ponytail/package.json +8 -8
  588. package/dist/extensions/ponytail/ponytail-config.cjs +34 -7
  589. package/dist/extensions/ponytail/ponytail-instructions.cjs +7 -9
  590. package/dist/extensions/ponytail/test/extension.test.js +7 -8
  591. package/dist/extensions/ponytail/test/helpers.test.js +1 -1
  592. package/dist/extensions/question/batch.ts +103 -103
  593. package/dist/extensions/question/constants.ts +30 -30
  594. package/dist/extensions/question/helpers.ts +58 -58
  595. package/dist/extensions/question/navigation.ts +14 -14
  596. package/dist/extensions/question/package.json +19 -19
  597. package/dist/extensions/question/schemas.ts +43 -43
  598. package/dist/extensions/question/selection-mode.ts +46 -46
  599. package/dist/extensions/question/shortcuts.ts +44 -44
  600. package/dist/extensions/question/types.ts +132 -132
  601. package/dist/extensions/test-resolve-hook-impl.mjs +6 -6
  602. package/dist/extensions/test-resolve-hook.mjs +6 -6
  603. package/dist/extensions/web-agent-onboarding.ts +222 -222
  604. package/dist/extensions/workflow/package.json +17 -17
  605. package/dist/package-manager-cli.js +71 -71
  606. package/dist/rpc-entry.js +0 -0
  607. package/dist/skills/agent-browser/SKILL.md +52 -52
  608. package/dist/skills/batch-grill-me/SKILL.md +19 -19
  609. package/dist/skills/brandkit/SKILL.md +799 -0
  610. package/dist/skills/design-taste-frontend/SKILL.md +1207 -0
  611. package/dist/skills/design-taste-frontend-v1/SKILL.md +227 -0
  612. package/dist/skills/full-output-enforcement/SKILL.md +50 -0
  613. package/dist/skills/gpt-taste/SKILL.md +75 -0
  614. package/dist/skills/grill-me/SKILL.md +10 -10
  615. package/dist/skills/handoff/SKILL.md +16 -16
  616. package/dist/skills/handoff-text/SKILL.md +14 -14
  617. package/dist/skills/high-end-visual-design/SKILL.md +99 -0
  618. package/dist/skills/image-to-code/SKILL.md +1229 -0
  619. package/dist/skills/imagegen-frontend-mobile/SKILL.md +1466 -0
  620. package/dist/skills/imagegen-frontend-web/SKILL.md +988 -0
  621. package/dist/skills/implanger/SKILL.md +69 -69
  622. package/dist/skills/improve-codebase/REFERENCE.md +78 -78
  623. package/dist/skills/improve-codebase/SKILL.md +178 -178
  624. package/dist/skills/industrial-brutalist-ui/SKILL.md +93 -0
  625. package/dist/skills/minimalist-ui/SKILL.md +86 -0
  626. package/dist/skills/pi-subagents/SKILL.md +18 -17
  627. package/dist/skills/pi-subagents/references/constraints-and-recipes.md +31 -9
  628. package/dist/skills/pi-subagents/references/execution-controls.md +95 -143
  629. package/dist/skills/pi-subagents/references/management-authoring-rpc.md +9 -12
  630. package/dist/skills/pi-subagents/references/multi-lane-orchestration.md +39 -0
  631. package/dist/skills/pi-subagents/references/prompting-and-roles.md +45 -94
  632. package/dist/skills/planger/SKILL.md +166 -166
  633. package/dist/skills/ponytail/SKILL.md +120 -116
  634. package/dist/skills/ponytail-audit/SKILL.md +41 -42
  635. package/dist/skills/ponytail-debt/SKILL.md +44 -45
  636. package/dist/skills/ponytail-gain/SKILL.md +50 -51
  637. package/dist/skills/ponytail-help/SKILL.md +71 -70
  638. package/dist/skills/ponytail-review/SKILL.md +57 -58
  639. package/dist/skills/redesign-existing-projects/SKILL.md +179 -0
  640. package/dist/skills/selesai-handoff/SKILL.md +20 -20
  641. package/dist/skills/stitch-design-taste/SKILL.md +185 -0
  642. package/dist/skills/unlazy/CHANGELOG.md +100 -0
  643. package/dist/skills/unlazy/CONTRIBUTING.md +66 -0
  644. package/dist/skills/unlazy/LICENSE +21 -0
  645. package/dist/skills/unlazy/README.md +242 -0
  646. package/dist/skills/unlazy/SECURITY.md +70 -0
  647. package/dist/skills/unlazy/SKILL.md +100 -0
  648. package/dist/skills/unlazy/package.json +13 -0
  649. package/dist/skills/unlazy/references/dispatch.md +82 -0
  650. package/dist/skills/unlazy/references/gates.md +132 -0
  651. package/dist/skills/unlazy/references/method.md +49 -0
  652. package/dist/skills/unlazy/references/orchestration.md +99 -0
  653. package/dist/skills/unlazy/references/parallel.md +123 -0
  654. package/dist/skills/unlazy/references/token-economy.md +39 -0
  655. package/dist/skills/unlazy/research/validation-protocol.md +81 -0
  656. package/dist/skills/unlazy/scripts/dispatch-check.mjs +108 -0
  657. package/dist/skills/unlazy/scripts/gate-check.mjs +894 -0
  658. package/dist/skills/unlazy/scripts/gate-lint.mjs +178 -0
  659. package/dist/skills/unlazy/scripts/install-hooks.mjs +206 -0
  660. package/dist/skills/unlazy/scripts/lib/check-supervisor.mjs +46 -0
  661. package/dist/skills/unlazy/scripts/lib/dispatch.mjs +283 -0
  662. package/dist/skills/unlazy/scripts/lib/gates.mjs +629 -0
  663. package/dist/skills/unlazy/scripts/lib/process-tree.mjs +161 -0
  664. package/dist/skills/unlazy/scripts/lib/regex-worker.mjs +9 -0
  665. package/dist/skills/unlazy/scripts/stop-hook.mjs +174 -0
  666. package/dist/skills/unlazy/templates/PLAN.md +65 -0
  667. package/dist/skills/unlazy/templates/gates-leaf.md +51 -0
  668. package/dist/skills/unlazy/templates/gates-node.md +50 -0
  669. package/dist/skills/unlazy/tests/contract-tests.mjs +127 -0
  670. package/dist/skills/unlazy/tests/dispatch-tests.mjs +481 -0
  671. package/dist/skills/unlazy/tests/hardening-tests.mjs +903 -0
  672. package/dist/skills/unlazy/tests/lint-tests.mjs +242 -0
  673. package/dist/skills/unlazy/tests/run-tests.mjs +554 -0
  674. package/dist/skills/unlazy/tests/self-check.mjs +165 -0
  675. package/dist/skills/unlazy/tests/stress-tests.mjs +356 -0
  676. package/dist/skills/web-design-guidelines/SKILL.md +40 -0
  677. package/dist/skills/workflow-creation/SKILL.md +73 -73
  678. package/dist/themes/powerline-footer/theme.json +33 -33
  679. package/dist/utils/shell.d.ts +3 -0
  680. package/dist/utils/shell.js +17 -5
  681. package/docs/compaction.md +396 -396
  682. package/docs/containerization.md +111 -111
  683. package/docs/development.md +71 -71
  684. package/docs/docs.json +164 -164
  685. package/docs/environment-variables.md +86 -86
  686. package/docs/index.md +83 -83
  687. package/docs/json.md +82 -82
  688. package/docs/models.md +502 -502
  689. package/docs/packages.md +227 -227
  690. package/docs/plans/subagent-delegation/phase-0-correctness.md +264 -264
  691. package/docs/plans/subagent-delegation/phase-1-behavioral-contract.md +485 -485
  692. package/docs/plans/subagent-delegation/phase-2-context-controls.md +281 -281
  693. package/docs/plans/subagent-delegation/phase-3-advisory-routing.md +361 -361
  694. package/docs/plans/subagent-delegation/phase-4-optional-enforcement.md +380 -380
  695. package/docs/prompt-templates.md +95 -95
  696. package/docs/providers.md +293 -293
  697. package/docs/sdk.md +1144 -1143
  698. package/docs/security.md +59 -59
  699. package/docs/session-format.md +414 -414
  700. package/docs/sessions.md +145 -145
  701. package/docs/settings.md +0 -5
  702. package/docs/shared-host-extensions.md +109 -109
  703. package/docs/shell-aliases.md +13 -13
  704. package/docs/skills.md +231 -231
  705. package/docs/terminal-setup.md +142 -142
  706. package/docs/termux.md +127 -127
  707. package/docs/themes.md +295 -295
  708. package/docs/tmux.md +63 -63
  709. package/docs/tui.md +927 -927
  710. package/docs/windows.md +17 -17
  711. package/examples/README.md +25 -25
  712. package/examples/extensions/README.md +211 -211
  713. package/examples/extensions/auto-commit-on-exit.ts +49 -49
  714. package/examples/extensions/bash-spawn-hook.ts +30 -30
  715. package/examples/extensions/bookmark.ts +50 -50
  716. package/examples/extensions/border-status-editor.ts +150 -150
  717. package/examples/extensions/built-in-tool-renderer.ts +249 -249
  718. package/examples/extensions/claude-rules.ts +86 -86
  719. package/examples/extensions/commands.ts +72 -72
  720. package/examples/extensions/confirm-destructive.ts +59 -59
  721. package/examples/extensions/custom-compaction.ts +130 -130
  722. package/examples/extensions/custom-footer.ts +64 -64
  723. package/examples/extensions/custom-header.ts +73 -73
  724. package/examples/extensions/custom-provider-anthropic/index.ts +610 -610
  725. package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -24
  726. package/examples/extensions/custom-provider-anthropic/package.json +19 -19
  727. package/examples/extensions/custom-provider-gitlab-duo/index.ts +404 -404
  728. package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -16
  729. package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -82
  730. package/examples/extensions/dirty-repo-guard.ts +56 -56
  731. package/examples/extensions/doom-overlay/README.md +46 -46
  732. package/examples/extensions/doom-overlay/doom/build/doom.js +21 -21
  733. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  734. package/examples/extensions/doom-overlay/doom/build.sh +152 -152
  735. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -72
  736. package/examples/extensions/doom-overlay/doom-component.ts +132 -132
  737. package/examples/extensions/doom-overlay/doom-engine.ts +173 -173
  738. package/examples/extensions/doom-overlay/doom-keys.ts +104 -104
  739. package/examples/extensions/doom-overlay/index.ts +74 -74
  740. package/examples/extensions/doom-overlay/wad-finder.ts +51 -51
  741. package/examples/extensions/dynamic-resources/SKILL.md +8 -8
  742. package/examples/extensions/dynamic-resources/dynamic.json +79 -79
  743. package/examples/extensions/dynamic-resources/dynamic.md +5 -5
  744. package/examples/extensions/dynamic-resources/index.ts +15 -15
  745. package/examples/extensions/dynamic-tools.ts +74 -74
  746. package/examples/extensions/event-bus.ts +43 -43
  747. package/examples/extensions/file-trigger.ts +41 -41
  748. package/examples/extensions/git-checkpoint.ts +53 -53
  749. package/examples/extensions/git-merge-and-resolve.ts +115 -115
  750. package/examples/extensions/github-issue-autocomplete.ts +185 -185
  751. package/examples/extensions/gondolin/index.ts +531 -531
  752. package/examples/extensions/gondolin/package-lock.json +185 -185
  753. package/examples/extensions/gondolin/package.json +19 -19
  754. package/examples/extensions/handoff.ts +199 -199
  755. package/examples/extensions/hello.ts +26 -26
  756. package/examples/extensions/hidden-thinking-label.ts +53 -53
  757. package/examples/extensions/inline-bash.ts +94 -94
  758. package/examples/extensions/input-transform-streaming.ts +39 -39
  759. package/examples/extensions/input-transform.ts +43 -43
  760. package/examples/extensions/interactive-shell.ts +196 -196
  761. package/examples/extensions/mac-system-theme.ts +47 -47
  762. package/examples/extensions/message-renderer.ts +59 -59
  763. package/examples/extensions/minimal-mode.ts +426 -426
  764. package/examples/extensions/modal-editor.ts +85 -85
  765. package/examples/extensions/model-status.ts +31 -31
  766. package/examples/extensions/notify.ts +55 -55
  767. package/examples/extensions/overlay-qa-tests.ts +1450 -1450
  768. package/examples/extensions/overlay-test.ts +153 -153
  769. package/examples/extensions/permission-gate.ts +34 -34
  770. package/examples/extensions/pirate.ts +47 -47
  771. package/examples/extensions/plan-mode/README.md +66 -66
  772. package/examples/extensions/plan-mode/index.ts +390 -390
  773. package/examples/extensions/plan-mode/utils.ts +168 -168
  774. package/examples/extensions/preset.ts +436 -436
  775. package/examples/extensions/project-trust.ts +64 -64
  776. package/examples/extensions/prompt-customizer.ts +97 -97
  777. package/examples/extensions/protected-paths.ts +30 -30
  778. package/examples/extensions/provider-payload.ts +18 -18
  779. package/examples/extensions/qna.ts +122 -122
  780. package/examples/extensions/question.ts +285 -285
  781. package/examples/extensions/questionnaire.ts +448 -448
  782. package/examples/extensions/rainbow-editor.ts +88 -88
  783. package/examples/extensions/reload-runtime.ts +37 -37
  784. package/examples/extensions/rpc-demo.ts +118 -118
  785. package/examples/extensions/sandbox/index.ts +321 -321
  786. package/examples/extensions/sandbox/package-lock.json +92 -92
  787. package/examples/extensions/sandbox/package.json +19 -19
  788. package/examples/extensions/send-user-message.ts +97 -97
  789. package/examples/extensions/session-name.ts +27 -27
  790. package/examples/extensions/shutdown-command.ts +63 -63
  791. package/examples/extensions/snake.ts +343 -343
  792. package/examples/extensions/space-invaders.ts +560 -560
  793. package/examples/extensions/ssh.ts +220 -220
  794. package/examples/extensions/status-line.ts +32 -32
  795. package/examples/extensions/structured-output.ts +65 -65
  796. package/examples/extensions/subagent/README.md +175 -175
  797. package/examples/extensions/subagent/agents/planner.md +37 -37
  798. package/examples/extensions/subagent/agents/reviewer.md +35 -35
  799. package/examples/extensions/subagent/agents/scout.md +50 -50
  800. package/examples/extensions/subagent/agents/worker.md +24 -24
  801. package/examples/extensions/subagent/agents.ts +126 -126
  802. package/examples/extensions/subagent/index.ts +1015 -1015
  803. package/examples/extensions/subagent/prompts/implement-and-review.md +10 -10
  804. package/examples/extensions/subagent/prompts/implement.md +10 -10
  805. package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -9
  806. package/examples/extensions/summarize.ts +209 -209
  807. package/examples/extensions/system-prompt-header.ts +17 -17
  808. package/examples/extensions/tic-tac-toe.ts +1008 -1008
  809. package/examples/extensions/timed-confirm.ts +70 -70
  810. package/examples/extensions/titlebar-spinner.ts +58 -58
  811. package/examples/extensions/todo.ts +297 -297
  812. package/examples/extensions/tool-override.ts +144 -144
  813. package/examples/extensions/tools.ts +146 -146
  814. package/examples/extensions/trigger-compact.ts +50 -50
  815. package/examples/extensions/truncated-tool.ts +195 -195
  816. package/examples/extensions/widget-placement.ts +9 -9
  817. package/examples/extensions/with-deps/index.ts +32 -32
  818. package/examples/extensions/with-deps/package-lock.json +31 -31
  819. package/examples/extensions/with-deps/package.json +22 -22
  820. package/examples/extensions/working-indicator.ts +123 -123
  821. package/examples/extensions/working-message-test.ts +25 -25
  822. package/examples/rpc-extension-ui.ts +632 -632
  823. package/examples/sdk/01-minimal.ts +26 -26
  824. package/examples/sdk/02-custom-model.ts +53 -53
  825. package/examples/sdk/03-custom-prompt.ts +75 -75
  826. package/examples/sdk/04-skills.ts +55 -55
  827. package/examples/sdk/05-tools.ts +48 -48
  828. package/examples/sdk/06-extensions.ts +99 -99
  829. package/examples/sdk/07-context-files.ts +47 -47
  830. package/examples/sdk/08-prompt-templates.ts +51 -51
  831. package/examples/sdk/09-api-keys-and-oauth.ts +52 -52
  832. package/examples/sdk/10-settings.ts +53 -53
  833. package/examples/sdk/11-sessions.ts +52 -52
  834. package/examples/sdk/12-full-control.ts +79 -79
  835. package/examples/sdk/13-session-runtime.ts +67 -67
  836. package/examples/sdk/README.md +144 -144
  837. package/package.json +4 -4
  838. package/dist/core/tools/schema-prune.d.ts +0 -16
  839. package/dist/core/tools/schema-prune.js +0 -39
  840. package/dist/core/tools/schema-prune.test.js +0 -111
  841. package/dist/extensions/pi-subagents/UPSTREAM-V0.50-MAPPING.md +0 -172
  842. package/dist/extensions/pi-subagents/prompts/parallel-context-build.md +0 -55
  843. package/dist/extensions/pi-subagents/prompts/parallel-handoff-plan.md +0 -61
  844. package/dist/extensions/pi-subagents/src/agents/task-aware-routing.ts +0 -132
  845. package/dist/extensions/pi-subagents/src/extension/chain-validation.ts +0 -181
  846. package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +0 -1354
  847. package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +0 -1581
  848. package/dist/extensions/pi-subagents/src/shared/env.ts +0 -16
  849. package/dist/extensions/pi-subagents/src/shared/session-lineage.ts +0 -71
  850. package/dist/extensions/pi-subagents/src/slash/inline-subagents.ts +0 -136
  851. package/dist/extensions/pi-subagents/src/workflows/workflow-auto-relaunch.ts +0 -41
  852. package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +0 -466
  853. package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +0 -1859
  854. package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +0 -733
  855. package/dist/extensions/pi-subagents/test/unit/builtin-agent-documentation.test.ts +0 -63
  856. package/dist/extensions/pi-subagents/test/unit/chain-validation.test.ts +0 -326
  857. package/dist/extensions/pi-subagents/test/unit/handoff-adoption.test.ts +0 -103
  858. package/dist/extensions/pi-subagents/test/unit/inline-subagents.test.ts +0 -127
  859. package/dist/extensions/pi-subagents/test/unit/session-lineage.test.ts +0 -73
  860. package/dist/extensions/pi-subagents/test/unit/task-aware-routing.test.ts +0 -213
  861. package/dist/extensions/pi-subagents/test/unit/workflow-auto-relaunch.test.ts +0 -65
  862. /package/dist/core/{tools/schema-prune.test.d.ts → extensions/loader.test.d.ts} +0 -0
@@ -1,13 +1,19 @@
1
1
  import test from "node:test";
2
2
  import assert from "node:assert/strict";
3
- import { mkdtempSync, rmSync } from "node:fs";
3
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
4
4
  import path from "node:path";
5
5
  import { tmpdir } from "node:os";
6
6
  import { EventEmitter, once } from "node:events";
7
7
  import { spawn, type ChildProcess } from "node:child_process";
8
8
  import { ReplyTracker } from "./reply-tracker.ts";
9
9
  import type { BrokerMessage, Message, SessionInfo } from "./types.ts";
10
- import { INTERCOM_EXTENSION_REGISTER_EVENT, type IntercomExtensionChannel } from "./extension-api.ts";
10
+ import {
11
+ INTERCOM_EXTENSION_REGISTER_EVENT,
12
+ INTERCOM_OUTBOX_REQUEST_EVENT,
13
+ INTERCOM_OUTBOX_RESULT_EVENT,
14
+ type IntercomExtensionChannel,
15
+ type IntercomOutboxResultV1,
16
+ } from "./extension-api.ts";
11
17
 
12
18
  const repoDir = process.cwd();
13
19
  const childEnvKeys = [
@@ -21,19 +27,45 @@ const childEnvKeys = [
21
27
  "SELESAI_SUBAGENT_INTERCOM_SESSION_NAME",
22
28
  "SELESAI_SUBAGENT_SUPERVISOR_CHANNEL_DIR",
23
29
  ] as const;
24
- const sharedHomeDir = mkdtempSync(path.join(tmpdir(), "pih-"));
30
+ const sharedHomeDir = mkdtempSync(path.join(tmpdir(), "pi-intercom-home-"));
25
31
  const previousHome = process.env.HOME;
26
32
  const previousUserProfile = process.env.USERPROFILE;
27
33
  process.env.HOME = sharedHomeDir;
28
34
  process.env.USERPROFILE = sharedHomeDir;
29
35
  const { IntercomClient } = await import("./broker/client.ts");
30
36
  const { getTsxCliPath } = await import("./broker/spawn.ts");
37
+ const { getAskTimeoutMs, getConfigPath } = await import("./config.ts");
31
38
  process.on("exit", () => {
32
39
  process.env.HOME = previousHome;
33
40
  process.env.USERPROFILE = previousUserProfile;
34
41
  rmSync(sharedHomeDir, { recursive: true, force: true });
35
42
  });
36
43
 
44
+ async function withIntercomConfig<T>(config: Record<string, unknown>, fn: () => T | Promise<T>): Promise<T> {
45
+ const configPath = getConfigPath();
46
+ const previous = existsSync(configPath) ? readFileSync(configPath, "utf-8") : undefined;
47
+ mkdirSync(path.dirname(configPath), { recursive: true });
48
+ writeFileSync(configPath, JSON.stringify(config));
49
+ try {
50
+ return await fn();
51
+ } finally {
52
+ if (previous === undefined) rmSync(configPath, { force: true });
53
+ else writeFileSync(configPath, previous);
54
+ }
55
+ }
56
+
57
+ async function withIntercomScope<T>(scopeId: string | undefined, fn: () => T | Promise<T>): Promise<T> {
58
+ const previous = process.env.PI_INTERCOM_SCOPE_ID;
59
+ if (scopeId === undefined) delete process.env.PI_INTERCOM_SCOPE_ID;
60
+ else process.env.PI_INTERCOM_SCOPE_ID = scopeId;
61
+ try {
62
+ return await fn();
63
+ } finally {
64
+ if (previous === undefined) delete process.env.PI_INTERCOM_SCOPE_ID;
65
+ else process.env.PI_INTERCOM_SCOPE_ID = previous;
66
+ }
67
+ }
68
+
37
69
  async function waitForBrokerReady(broker: ChildProcess): Promise<void> {
38
70
  const stdout = broker.stdout;
39
71
  if (!stdout) throw new Error("Broker stdout is unavailable");
@@ -145,13 +177,15 @@ function createExtensionHarness(sessionName: string | (() => string) = "child-wo
145
177
  mode?: "tui" | "rpc" | "json" | "print";
146
178
  ui?: unknown;
147
179
  sessionId?: string | (() => string);
180
+ activeTools?: string[];
148
181
  } = {}) {
149
182
  const events = new EventEmitter();
150
183
  const lifecycleHandlers = new Map<string, Array<(event: unknown, ctx: unknown) => unknown>>();
151
184
  const commands = new Map<string, (args: string, ctx: unknown) => unknown>();
152
185
  const tools: CapturedTool[] = [];
186
+ let activeToolNames = [...(options.activeTools ?? [])];
153
187
  const entries: Array<{ type: string; data: unknown }> = [];
154
- const sentMessages: Array<{ message: { customType?: string; content?: string; details?: unknown }; options?: { triggerTurn?: boolean; deliverAs?: string } }> = [];
188
+ const sentMessages: Array<{ message: { customType?: string; content?: string; details?: unknown }; options?: { triggerTurn?: boolean; deliverAs?: string }; activeTools: string[] }> = [];
155
189
  const pi = {
156
190
  getSessionName: () => typeof sessionName === "function" ? sessionName() : sessionName,
157
191
  events: {
@@ -169,13 +203,16 @@ function createExtensionHarness(sessionName: string | (() => string) = "child-wo
169
203
  registerMessageRenderer: () => undefined,
170
204
  registerTool: (tool: CapturedTool) => {
171
205
  tools.push(tool);
206
+ if (!activeToolNames.includes(tool.name)) activeToolNames.push(tool.name);
172
207
  },
208
+ getActiveTools: () => [...activeToolNames],
209
+ setActiveTools: (names: string[]) => { activeToolNames = [...names]; },
173
210
  registerCommand: (name: string, command: { handler: (args: string, ctx: unknown) => unknown }) => {
174
211
  commands.set(name, command.handler);
175
212
  },
176
213
  registerShortcut: () => undefined,
177
214
  sendMessage: (message: { customType?: string; content?: string; details?: unknown }, options?: { triggerTurn?: boolean; deliverAs?: string }) => {
178
- sentMessages.push({ message, options });
215
+ sentMessages.push({ message, options, activeTools: [...activeToolNames] });
179
216
  },
180
217
  appendEntry: (type: string, data: unknown) => entries.push({ type, data }),
181
218
  };
@@ -196,6 +233,7 @@ function createExtensionHarness(sessionName: string | (() => string) = "child-wo
196
233
  commands,
197
234
  entries,
198
235
  sentMessages,
236
+ getActiveTools: () => pi.getActiveTools(),
199
237
  async emitLifecycle(event: string, payload: unknown = {}, eventContext: unknown = ctx) {
200
238
  for (const handler of lifecycleHandlers.get(event) ?? []) {
201
239
  await handler(payload, eventContext);
@@ -353,7 +391,7 @@ test("opt-in TCP broker requires endpoint state for health and registration", {
353
391
  assert.deepEqual(registerMessages, [{
354
392
  type: "registered",
355
393
  sessionId: "authorized-tcp-client",
356
- features: ["extension-bus-v1"],
394
+ features: ["extension-bus-v1", "exact-send-v1"],
357
395
  }]);
358
396
  } finally {
359
397
  if (broker.exitCode === null && broker.signalCode === null) {
@@ -410,6 +448,17 @@ async function setupClients() {
410
448
  }
411
449
  }
412
450
 
451
+ async function connectClientWithScope(client: InstanceType<typeof IntercomClient>, scopeId: string | undefined, sessionId: string, name: string): Promise<void> {
452
+ await withIntercomScope(scopeId, () => client.connect({
453
+ name,
454
+ cwd: repoDir,
455
+ model: "test-model",
456
+ pid: process.pid,
457
+ startedAt: Date.now(),
458
+ lastActivity: Date.now(),
459
+ }, sessionId));
460
+ }
461
+
413
462
  function waitForReply(client: InstanceType<typeof IntercomClient>, replyTo: string, timeoutMs = 5000): Promise<{ from: SessionInfo; message: Message; }> {
414
463
  return new Promise((resolve, reject) => {
415
464
  const timeout = setTimeout(() => {
@@ -428,6 +477,54 @@ function waitForReply(client: InstanceType<typeof IntercomClient>, replyTo: stri
428
477
  });
429
478
  }
430
479
 
480
+ function waitForOutboxResults(results: IntercomOutboxResultV1[], count: number, timeoutMs = 3000): Promise<IntercomOutboxResultV1[]> {
481
+ return new Promise((resolve, reject) => {
482
+ const deadline = Date.now() + timeoutMs;
483
+ const check = () => {
484
+ if (results.length >= count) {
485
+ resolve(results.slice(0, count));
486
+ return;
487
+ }
488
+ if (Date.now() >= deadline) {
489
+ reject(new Error(`Timed out waiting for ${count} outbox result(s); saw ${JSON.stringify(results)}`));
490
+ return;
491
+ }
492
+ setTimeout(check, 10);
493
+ };
494
+ check();
495
+ });
496
+ }
497
+
498
+ async function waitForReplyMessage(messages: Message[], messageId: string, timeoutMs = 3000): Promise<Message> {
499
+ const deadline = Date.now() + timeoutMs;
500
+ while (Date.now() < deadline) {
501
+ const message = messages.find((candidate) => candidate.id === messageId);
502
+ if (message) return message;
503
+ await new Promise((resolve) => setTimeout(resolve, 10));
504
+ }
505
+ throw new Error(`Timed out waiting for message ${messageId}`);
506
+ }
507
+
508
+ function pendingAskRecordPath(messageId: string): string {
509
+ return path.join(sharedHomeDir, ".selesai", "agent", "intercom", "pending-asks", `${encodeURIComponent(messageId)}.json`);
510
+ }
511
+
512
+ function readPendingAskRecord(messageId: string): Record<string, unknown> {
513
+ return JSON.parse(readFileSync(pendingAskRecordPath(messageId), "utf-8")) as Record<string, unknown>;
514
+ }
515
+
516
+ async function waitForPendingAskRecordRemoved(messageId: string): Promise<void> {
517
+ const filePath = pendingAskRecordPath(messageId);
518
+ const deadline = Date.now() + 1000;
519
+ while (Date.now() < deadline) {
520
+ if (!existsSync(filePath)) {
521
+ return;
522
+ }
523
+ await new Promise((resolve) => setTimeout(resolve, 20));
524
+ }
525
+ assert.equal(existsSync(filePath), false);
526
+ }
527
+
431
528
  async function waitForSessionByName(client: InstanceType<typeof IntercomClient>, name: string): Promise<SessionInfo> {
432
529
  const deadline = Date.now() + 2000;
433
530
  while (Date.now() < deadline) {
@@ -558,6 +655,300 @@ test("broker accepts caller supplied stable IDs across reconnect", { concurrency
558
655
  }
559
656
  });
560
657
 
658
+ test("broker scopes discovery, routing, mailbox, and presence", { concurrency: false }, async () => {
659
+ const broker = spawn(process.execPath, [getTsxCliPath(), path.join(repoDir, "broker", "broker.ts")], {
660
+ cwd: repoDir,
661
+ env: { ...process.env, HOME: sharedHomeDir, USERPROFILE: sharedHomeDir },
662
+ stdio: ["ignore", "pipe", "pipe"],
663
+ });
664
+ const clients: Array<InstanceType<typeof IntercomClient>> = [];
665
+ try {
666
+ await waitForBrokerReady(broker);
667
+ const unscopedA = new IntercomClient();
668
+ const unscopedB = new IntercomClient();
669
+ const alphaSender = new IntercomClient();
670
+ const alphaTarget = new IntercomClient();
671
+ const betaTarget = new IntercomClient();
672
+ clients.push(unscopedA, unscopedB, alphaSender, alphaTarget, betaTarget);
673
+
674
+ const alphaEvents: BrokerMessage[] = [];
675
+ const alphaMessages: Message[] = [];
676
+ const betaMessages: Message[] = [];
677
+ alphaSender.onBrokerMessage((message) => alphaEvents.push(message));
678
+ alphaTarget.on("message", (_from: SessionInfo, message: Message) => alphaMessages.push(message));
679
+ betaTarget.on("message", (_from: SessionInfo, message: Message) => betaMessages.push(message));
680
+
681
+ await connectClientWithScope(unscopedA, undefined, "unscoped-a", "unscoped-a");
682
+ await connectClientWithScope(unscopedB, undefined, "unscoped-b", "unscoped-b");
683
+ await connectClientWithScope(alphaSender, " alpha-scope ", "alpha-sender", "alpha-sender");
684
+ await connectClientWithScope(betaTarget, "beta-scope", "shared-target-id", "shared-target");
685
+ await new Promise((resolve) => setTimeout(resolve, 50));
686
+ assert.equal(alphaEvents.some((message) => message.type === "session_joined" && message.session.id === "shared-target-id"), false);
687
+
688
+ await connectClientWithScope(alphaTarget, "alpha-scope", "shared-target-id", "shared-target");
689
+ await waitForSessionByName(alphaSender, "shared-target");
690
+ assert.equal((await unscopedA.listSessions()).some((session) => session.id === "shared-target-id"), false);
691
+ assert.equal((await alphaSender.listSessions()).some((session) => session.id === "unscoped-b"), false);
692
+ assert.equal((await unscopedA.listSessions()).some((session) => session.id === "unscoped-b"), true);
693
+ assert.equal((await alphaSender.listSessions()).filter((session) => session.cwd === repoDir && session.name === "shared-target").length, 1);
694
+
695
+ betaTarget.updatePresence({ status: "beta-only" });
696
+ await new Promise((resolve) => setTimeout(resolve, 50));
697
+ assert.equal(alphaEvents.some((message) => message.type === "presence_update" && message.session.status === "beta-only"), false);
698
+ alphaTarget.updatePresence({ status: "alpha-visible" });
699
+ await waitForSessionStatus(alphaSender, "shared-target", "alpha-visible");
700
+
701
+ assert.equal((await unscopedA.send("shared-target-id", { text: "full id must not cross" })).delivered, false);
702
+ assert.equal((await alphaSender.send("unscoped-b", { text: "unscoped id must not cross" })).delivered, false);
703
+ assert.equal((await alphaSender.send("shared-target", { messageId: "alpha-name-scope", text: "name stays in scope" })).delivered, true);
704
+ await new Promise((resolve) => setTimeout(resolve, 50));
705
+ assert.equal(alphaMessages.some((message) => message.id === "alpha-name-scope"), true);
706
+ assert.equal(betaMessages.some((message) => message.id === "alpha-name-scope"), false);
707
+
708
+ await alphaTarget.disconnect();
709
+ const crossScopeDisconnected = await unscopedA.send("shared-target-id", {
710
+ messageId: "unscoped-to-scoped-disconnected",
711
+ text: "must not queue across scope",
712
+ });
713
+ assert.equal(crossScopeDisconnected.delivered, false);
714
+ assert.match(crossScopeDisconnected.reason ?? "", /Session not found/);
715
+
716
+ const queued = await alphaSender.send("shared-target-id", {
717
+ messageId: "alpha-scoped-mailbox",
718
+ text: "queued only for alpha",
719
+ });
720
+ assert.equal(queued.delivery, "queued");
721
+ await new Promise((resolve) => setTimeout(resolve, 50));
722
+ assert.equal(betaMessages.some((message) => message.id === "alpha-scoped-mailbox"), false);
723
+
724
+ const alphaReplacement = new IntercomClient();
725
+ clients.push(alphaReplacement);
726
+ const recovered: Message[] = [];
727
+ alphaReplacement.on("message", (_from: SessionInfo, message: Message) => recovered.push(message));
728
+ await connectClientWithScope(alphaReplacement, "alpha-scope", "shared-target-id", "shared-target");
729
+ await waitForReplyMessage(recovered, "alpha-scoped-mailbox");
730
+ } finally {
731
+ await Promise.all(clients.map((client) => client.disconnect().catch(() => undefined)));
732
+ if (broker.exitCode === null && broker.signalCode === null) broker.kill("SIGTERM");
733
+ await once(broker, "exit").catch(() => undefined);
734
+ }
735
+ });
736
+
737
+ test("broker rotates endpoint epochs and replays same message ids without duplicate delivery", { concurrency: false }, async () => {
738
+ const { planner, orchestrator, cleanup } = await setupClients();
739
+ const replacement = new IntercomClient();
740
+ const received: Message[] = [];
741
+ orchestrator.on("message", (_from: SessionInfo, message: Message) => received.push(message));
742
+
743
+ try {
744
+ const firstEndpoint = await waitForSessionByName(planner, "orchestrator");
745
+ assert.equal(typeof firstEndpoint.endpointEpoch, "string");
746
+
747
+ const messageId = "endpoint-epoch-replay";
748
+ const first = await planner.send(orchestrator.sessionId!, { text: "deliver once", messageId });
749
+ const replay = await planner.send(orchestrator.sessionId!, { text: "deliver once", messageId });
750
+ assert.deepEqual([first.delivery, replay.delivery], ["socket_delivered", "socket_delivered"]);
751
+ await new Promise((resolve) => setTimeout(resolve, 50));
752
+ assert.equal(received.filter((message) => message.id === messageId).length, 1);
753
+
754
+ await replacement.connect({
755
+ name: "orchestrator-replacement",
756
+ cwd: repoDir,
757
+ model: "test-model",
758
+ pid: process.pid,
759
+ startedAt: Date.now(),
760
+ lastActivity: Date.now(),
761
+ }, orchestrator.sessionId!);
762
+ const replacedEndpoint = await waitForSessionId(planner, orchestrator.sessionId!);
763
+ assert.notEqual(replacedEndpoint.endpointEpoch, firstEndpoint.endpointEpoch);
764
+ } finally {
765
+ await replacement.disconnect().catch(() => undefined);
766
+ await cleanup();
767
+ }
768
+ });
769
+
770
+ test("delivery records keep colon-containing sender and message IDs distinct", { concurrency: false }, async () => {
771
+ const { orchestrator, cleanup } = await setupClients();
772
+ const first = new IntercomClient();
773
+ const second = new IntercomClient();
774
+ const received: Message[] = [];
775
+ orchestrator.on("message", (_from: SessionInfo, message: Message) => received.push(message));
776
+
777
+ try {
778
+ await first.connect({ name: "record-key-first", cwd: repoDir, model: "test-model", pid: process.pid, startedAt: Date.now(), lastActivity: Date.now() }, "a:b");
779
+ await second.connect({ name: "record-key-second", cwd: repoDir, model: "test-model", pid: process.pid, startedAt: Date.now(), lastActivity: Date.now() }, "a");
780
+
781
+ assert.equal((await first.send(orchestrator.sessionId!, { messageId: "c", text: "same fingerprint" })).delivered, true);
782
+ assert.equal((await second.send(orchestrator.sessionId!, { messageId: "b:c", text: "same fingerprint" })).delivered, true);
783
+ await new Promise((resolve) => setTimeout(resolve, 50));
784
+ assert.deepEqual(received.map((message) => message.id).sort(), ["b:c", "c"]);
785
+ } finally {
786
+ await first.disconnect().catch(() => undefined);
787
+ await second.disconnect().catch(() => undefined);
788
+ await cleanup();
789
+ }
790
+ });
791
+
792
+ test("client re-resolves a rebound exact target once with the same message id", { concurrency: false }, async () => {
793
+ const { planner, orchestrator, cleanup } = await setupClients();
794
+ const replacement = new IntercomClient();
795
+ const replacementReceived = once(replacement, "message") as Promise<[SessionInfo, Message]>;
796
+ const listSessions = planner.listSessions.bind(planner);
797
+ let listCalls = 0;
798
+
799
+ try {
800
+ (planner as unknown as { listSessions: () => Promise<SessionInfo[]> }).listSessions = async () => {
801
+ const sessions = await listSessions();
802
+ listCalls += 1;
803
+ if (listCalls === 1) {
804
+ await replacement.connect({
805
+ name: "orchestrator-replacement",
806
+ cwd: repoDir,
807
+ model: "test-model",
808
+ pid: process.pid,
809
+ startedAt: Date.now(),
810
+ lastActivity: Date.now(),
811
+ }, orchestrator.sessionId!);
812
+ }
813
+ return sessions;
814
+ };
815
+
816
+ const result = await planner.send(orchestrator.sessionId!, { text: "retry after rebound", messageId: "endpoint-rebound-retry" });
817
+ assert.equal(result.delivered, true);
818
+ assert.equal(result.delivery, "socket_delivered");
819
+ const [, message] = await replacementReceived;
820
+ assert.equal(message.id, "endpoint-rebound-retry");
821
+ assert.equal(listCalls, 2);
822
+ } finally {
823
+ await replacement.disconnect().catch(() => undefined);
824
+ await cleanup();
825
+ }
826
+ });
827
+
828
+ test("broker rejects malformed exact target fields instead of falling back to name routing", { concurrency: false }, async () => {
829
+ const { orchestrator, cleanup } = await setupClients();
830
+ const raw = await connectRawRegistered("malformed-exact-sender", "malformed-exact-sender");
831
+ const { createMessageReader } = await import("./broker/framing.ts");
832
+
833
+ try {
834
+ const delivery = new Promise<Record<string, unknown>>((resolve, reject) => {
835
+ const reader = createMessageReader((received) => {
836
+ if (typeof received === "object" && received !== null && "type" in received && received.type === "delivery_failed") {
837
+ raw.socket.off("data", reader);
838
+ resolve(received as Record<string, unknown>);
839
+ }
840
+ }, reject);
841
+ raw.socket.on("data", reader);
842
+ });
843
+ raw.writeMessage(raw.socket, {
844
+ type: "send",
845
+ to: orchestrator.sessionId,
846
+ targetId: "",
847
+ targetEpoch: "",
848
+ message: {
849
+ id: "malformed-exact-target",
850
+ timestamp: Date.now(),
851
+ content: { text: "must not reach orchestrator" },
852
+ },
853
+ });
854
+ const result = await delivery;
855
+ assert.equal(result.code, "E_INVALID_TARGET");
856
+ } finally {
857
+ raw.socket.destroy();
858
+ await cleanup();
859
+ }
860
+ });
861
+
862
+ test("broker rejects changed message content after a rebound exact-target failure", { concurrency: false }, async () => {
863
+ const { planner, orchestrator, cleanup } = await setupClients();
864
+ const raw = await connectRawRegistered("rebound-reuse-sender", "rebound-reuse-sender");
865
+ const replacement = new IntercomClient();
866
+ const { createMessageReader } = await import("./broker/framing.ts");
867
+
868
+ try {
869
+ const targetId = orchestrator.sessionId!;
870
+ const oldTarget = await waitForSessionId(planner, targetId);
871
+ await replacement.connect({
872
+ name: "rebound-reuse-replacement",
873
+ cwd: repoDir,
874
+ model: "test-model",
875
+ pid: process.pid,
876
+ startedAt: Date.now(),
877
+ lastActivity: Date.now(),
878
+ }, targetId);
879
+ const receiveDelivery = () => new Promise<Record<string, unknown>>((resolve, reject) => {
880
+ const reader = createMessageReader((received) => {
881
+ if (typeof received === "object" && received !== null && "type" in received && (received.type === "delivered" || received.type === "delivery_failed")) {
882
+ raw.socket.off("data", reader);
883
+ resolve(received as Record<string, unknown>);
884
+ }
885
+ }, reject);
886
+ raw.socket.on("data", reader);
887
+ });
888
+ const send = (text: string) => raw.writeMessage(raw.socket, {
889
+ type: "send",
890
+ to: targetId,
891
+ targetId,
892
+ targetEpoch: oldTarget.endpointEpoch,
893
+ message: { id: "rebound-id-reuse", timestamp: Date.now(), content: { text } },
894
+ });
895
+
896
+ const firstDelivery = receiveDelivery();
897
+ send("first content");
898
+ assert.equal((await firstDelivery).code, "E_TARGET_REBOUND");
899
+ const secondDelivery = receiveDelivery();
900
+ send("changed content");
901
+ assert.equal((await secondDelivery).code, "E_MESSAGE_ID_REUSE");
902
+ } finally {
903
+ raw.socket.destroy();
904
+ await replacement.disconnect().catch(() => undefined);
905
+ await cleanup();
906
+ }
907
+ });
908
+
909
+ test("broker propagates a session's tmux pane id into the roster", { concurrency: false }, async () => {
910
+ const { planner, cleanup } = await setupClients();
911
+ const worker = new IntercomClient();
912
+
913
+ try {
914
+ await worker.connect({
915
+ name: "tmux-worker",
916
+ cwd: repoDir,
917
+ model: "test-model",
918
+ pid: process.pid,
919
+ startedAt: Date.now(),
920
+ lastActivity: Date.now(),
921
+ tmuxPane: "%212",
922
+ });
923
+ const session = await waitForSessionByName(planner, "tmux-worker");
924
+ assert.equal(session.tmuxPane, "%212");
925
+ } finally {
926
+ await worker.disconnect().catch(() => undefined);
927
+ await cleanup();
928
+ }
929
+ });
930
+
931
+ test("broker omits tmux pane id for sessions outside tmux", { concurrency: false }, async () => {
932
+ const { planner, cleanup } = await setupClients();
933
+ const worker = new IntercomClient();
934
+
935
+ try {
936
+ await worker.connect({
937
+ name: "paneless-worker",
938
+ cwd: repoDir,
939
+ model: "test-model",
940
+ pid: process.pid,
941
+ startedAt: Date.now(),
942
+ lastActivity: Date.now(),
943
+ });
944
+ const session = await waitForSessionByName(planner, "paneless-worker");
945
+ assert.equal(session.tmuxPane, undefined);
946
+ } finally {
947
+ await worker.disconnect().catch(() => undefined);
948
+ await cleanup();
949
+ }
950
+ });
951
+
561
952
  test("broker owns local trust metadata instead of trusting registration payloads", { concurrency: false }, async () => {
562
953
  const { planner, cleanup } = await setupClients();
563
954
  const raw = await connectRawRegistered("trust-metadata-worker-id", "trust-metadata-worker", {
@@ -768,7 +1159,7 @@ test("old stable-ID socket cannot mutate the replacement session", { concurrency
768
1159
  }
769
1160
  });
770
1161
 
771
- test("stable-ID replacement clears old ask edges and ignores stale cancels", { concurrency: false }, async () => {
1162
+ test("stable-ID replacement preserves old ask edges and ignores stale cancels", { concurrency: false }, async () => {
772
1163
  const { orchestrator, cleanup } = await setupClients();
773
1164
  const first = await connectRawRegistered("replaceable-asker-id", "replaceable-asker-old");
774
1165
  const replacement = new IntercomClient();
@@ -790,6 +1181,13 @@ test("stable-ID replacement clears old ask edges and ignores stale cancels", { c
790
1181
  lastActivity: Date.now(),
791
1182
  }, "replaceable-asker-id");
792
1183
 
1184
+ const oldReply = once(replacement, "message") as Promise<[SessionInfo, Message]>;
1185
+ assert.equal((await orchestrator.send("replaceable-asker-id", {
1186
+ text: "Old ask answered after replacement.",
1187
+ replyTo: "old-ask-edge",
1188
+ })).delivered, true);
1189
+ assert.equal((await oldReply)[1].replyTo, "old-ask-edge");
1190
+
793
1191
  const reverseAfterReplace = await orchestrator.send("replaceable-asker-id", {
794
1192
  messageId: "reverse-after-replace",
795
1193
  text: "Can I ask the replacement?",
@@ -876,6 +1274,9 @@ test("intercom tool prefers exact names over ID prefixes", { concurrency: false
876
1274
  ]);
877
1275
  const result = await intercomTool.execute("send-exact-name", { action: "send", to: "orchestrator", message: "exact name wins" }, new AbortController().signal, undefined, harness.ctx);
878
1276
  assert.notEqual(result.details?.error, true);
1277
+ assert.equal(result.details?.delivery, "socket_delivered");
1278
+ assert.equal(result.details?.retryable, false);
1279
+ assert.equal(result.details?.outcomeKnown, true);
879
1280
 
880
1281
  const received = await exactNameReceived;
881
1282
  assert.notEqual(received, null);
@@ -929,7 +1330,7 @@ test("intercom-id inserts a stable handoff snippet into the editor", { concurren
929
1330
  piIntercomExtension(harness.pi as never);
930
1331
  await harness.emitLifecycle("session_start");
931
1332
  await harness.commands.get("intercom-id")!("", harness.ctx);
932
- assert.match(editorText, /Existing note\n\nUse pi-intercom: intercom\(\{ action: "send", to: "session-child-test", message: "\.\.\." \}\)/);
1333
+ assert.match(editorText, /Existing note\n\nUse pi-intercom: intercom\(\{ action: "send", to: "session-child-test", message: "\.\.\." \}\)/);
933
1334
  assert.match(notifications.at(-1) ?? "", /Inserted intercom contact target: session-child-test/);
934
1335
  await harness.emitLifecycle("session_shutdown");
935
1336
  } finally {
@@ -1062,6 +1463,161 @@ test("late extension registration advertises before an onReady publish", { concu
1062
1463
  }
1063
1464
  });
1064
1465
 
1466
+ test("extension outbox sends notify-only messages with trace and provenance", { concurrency: false }, async () => {
1467
+ const { planner, cleanup } = await setupClients();
1468
+ const { default: piIntercomExtension } = await import("./index.ts");
1469
+ const harness = createExtensionHarness("outbox-worker");
1470
+ const results: IntercomOutboxResultV1[] = [];
1471
+
1472
+ try {
1473
+ harness.pi.events.on(INTERCOM_OUTBOX_RESULT_EVENT, (payload) => results.push(payload as IntercomOutboxResultV1));
1474
+ piIntercomExtension(harness.pi as never);
1475
+ await harness.emitLifecycle("session_start");
1476
+ const delivered = once(planner, "message") as Promise<[SessionInfo, Message]>;
1477
+
1478
+ harness.pi.events.emit(INTERCOM_OUTBOX_REQUEST_EVENT, {
1479
+ version: 1,
1480
+ requestId: "outbox-success-1",
1481
+ extensionId: "example-extension",
1482
+ extensionName: "Example Extension",
1483
+ to: "planner",
1484
+ message: "Outbox hello.",
1485
+ });
1486
+
1487
+ const [result] = await waitForOutboxResults(results, 1);
1488
+ assert.equal(result?.status, "sent");
1489
+ assert.equal(result?.messageId, "outbox-success-1");
1490
+ const [, message] = await Promise.race([
1491
+ delivered,
1492
+ new Promise<never>((_resolve, reject) => setTimeout(() => reject(new Error("Timed out waiting for outbox delivery")), 3000)),
1493
+ ]);
1494
+ assert.equal(message.id, "outbox-success-1");
1495
+ assert.equal(message.content.text, "Outbox hello.");
1496
+ assert.deepEqual(message.provenance, {
1497
+ type: "extension_outbox",
1498
+ extensionId: "example-extension",
1499
+ extensionName: "Example Extension",
1500
+ requestId: "outbox-success-1",
1501
+ });
1502
+ assert.equal(harness.entries.some((entry) => entry.type === "intercom_sent"
1503
+ && (entry.data as { extension?: { requestId?: string } }).extension?.requestId === "outbox-success-1"), true);
1504
+ assert.equal(harness.entries.some((entry) => entry.type === "intercom_outbox_result"
1505
+ && (entry.data as { requestId?: string; status?: string }).requestId === "outbox-success-1"
1506
+ && (entry.data as { requestId?: string; status?: string }).status === "sent"), true);
1507
+ } finally {
1508
+ await harness.emitLifecycle("session_shutdown");
1509
+ await cleanup();
1510
+ }
1511
+ });
1512
+
1513
+ test("extension outbox rejects duplicate request ids without duplicate delivery", { concurrency: false }, async () => {
1514
+ const { planner, cleanup } = await setupClients();
1515
+ const { default: piIntercomExtension } = await import("./index.ts");
1516
+ const harness = createExtensionHarness("outbox-duplicate-worker");
1517
+ const results: IntercomOutboxResultV1[] = [];
1518
+ const deliveredMessages: Message[] = [];
1519
+
1520
+ try {
1521
+ planner.on("message", (_from: SessionInfo, message: Message) => deliveredMessages.push(message));
1522
+ harness.pi.events.on(INTERCOM_OUTBOX_RESULT_EVENT, (payload) => results.push(payload as IntercomOutboxResultV1));
1523
+ piIntercomExtension(harness.pi as never);
1524
+ await harness.emitLifecycle("session_start");
1525
+
1526
+ const request = {
1527
+ version: 1,
1528
+ requestId: "outbox-duplicate-1",
1529
+ extensionId: "example-extension",
1530
+ extensionName: "Example Extension",
1531
+ to: "planner",
1532
+ message: "Deliver once.",
1533
+ };
1534
+ harness.pi.events.emit(INTERCOM_OUTBOX_REQUEST_EVENT, request);
1535
+ await waitForOutboxResults(results, 1);
1536
+ harness.pi.events.emit(INTERCOM_OUTBOX_REQUEST_EVENT, request);
1537
+
1538
+ const [, duplicate] = await waitForOutboxResults(results, 2);
1539
+ await new Promise((resolve) => setTimeout(resolve, 50));
1540
+ assert.equal(duplicate?.status, "rejected");
1541
+ assert.equal(duplicate?.code, "duplicate_request");
1542
+ assert.equal(deliveredMessages.filter((message) => message.id === "outbox-duplicate-1").length, 1);
1543
+ } finally {
1544
+ await harness.emitLifecycle("session_shutdown");
1545
+ await cleanup();
1546
+ }
1547
+ });
1548
+
1549
+ test("extension outbox fails closed when confirmation needs unavailable UI", async () => {
1550
+ await withConfirmSendEnabled(async () => {
1551
+ const { default: piIntercomExtension } = await import("./index.ts");
1552
+ const harness = createExtensionHarness("outbox-no-ui", { hasUI: false });
1553
+ const results: IntercomOutboxResultV1[] = [];
1554
+
1555
+ harness.pi.events.on(INTERCOM_OUTBOX_RESULT_EVENT, (payload) => results.push(payload as IntercomOutboxResultV1));
1556
+ piIntercomExtension(harness.pi as never);
1557
+ await harness.emitLifecycle("session_start");
1558
+ harness.pi.events.emit(INTERCOM_OUTBOX_REQUEST_EVENT, {
1559
+ version: 1,
1560
+ requestId: "outbox-no-ui-1",
1561
+ extensionId: "example-extension",
1562
+ extensionName: "Example Extension",
1563
+ to: "planner",
1564
+ message: "Needs confirmation.",
1565
+ });
1566
+
1567
+ const [result] = await waitForOutboxResults(results, 1);
1568
+ assert.equal(result?.status, "blocked");
1569
+ assert.equal(result?.code, "confirmation_unavailable");
1570
+ assert.equal(harness.entries.some((entry) => entry.type === "intercom_outbox_result"
1571
+ && (entry.data as { code?: string }).code === "confirmation_unavailable"), true);
1572
+ await harness.emitLifecycle("session_shutdown");
1573
+ });
1574
+ });
1575
+
1576
+ test("extension outbox settles pending confirmation on session shutdown", async () => {
1577
+ await withConfirmSendEnabled(async () => {
1578
+ const { cleanup } = await setupClients();
1579
+ const { default: piIntercomExtension } = await import("./index.ts");
1580
+ const confirmCalls: string[] = [];
1581
+ const harness = createExtensionHarness("outbox-shutdown", {
1582
+ hasUI: true,
1583
+ ui: {
1584
+ confirm: (title: string) => {
1585
+ confirmCalls.push(title);
1586
+ return new Promise<boolean>(() => undefined);
1587
+ },
1588
+ },
1589
+ });
1590
+ const results: IntercomOutboxResultV1[] = [];
1591
+
1592
+ try {
1593
+ harness.pi.events.on(INTERCOM_OUTBOX_RESULT_EVENT, (payload) => results.push(payload as IntercomOutboxResultV1));
1594
+ piIntercomExtension(harness.pi as never);
1595
+ await harness.emitLifecycle("session_start");
1596
+ harness.pi.events.emit(INTERCOM_OUTBOX_REQUEST_EVENT, {
1597
+ version: 1,
1598
+ requestId: "outbox-shutdown-1",
1599
+ extensionId: "example-extension",
1600
+ extensionName: "Example Extension",
1601
+ to: "planner",
1602
+ message: "Will shut down.",
1603
+ });
1604
+ const deadline = Date.now() + 3000;
1605
+ while (confirmCalls.length === 0 && Date.now() < deadline) {
1606
+ await new Promise((resolve) => setTimeout(resolve, 10));
1607
+ }
1608
+ assert.equal(confirmCalls.length, 1);
1609
+ await harness.emitLifecycle("session_shutdown");
1610
+
1611
+ const [result] = await waitForOutboxResults(results, 1);
1612
+ assert.equal(result?.status, "failed");
1613
+ assert.equal(result?.code, "session_ended");
1614
+ } finally {
1615
+ await harness.emitLifecycle("session_shutdown");
1616
+ await cleanup();
1617
+ }
1618
+ });
1619
+ });
1620
+
1065
1621
  test("intercom tool renders compact call and result rows", async () => {
1066
1622
  const { default: piIntercomExtension } = await import("./index.ts");
1067
1623
  const harness = createExtensionHarness();
@@ -1116,6 +1672,115 @@ test("intercom tool result hook marks failed details as errors", async () => {
1116
1672
  assert.deepEqual(okResults.filter(Boolean), []);
1117
1673
  });
1118
1674
 
1675
+ test("lazy tool visibility reveals intercom on bundled skill use only", { concurrency: false }, async () => {
1676
+ const { default: piIntercomExtension } = await import("./index.ts");
1677
+
1678
+ await withIntercomConfig({ toolVisibility: "after-first-use" }, () => withChildOrchestratorEnv({
1679
+ orchestratorTarget: "orchestrator",
1680
+ runId: "78f659a3",
1681
+ agent: "worker",
1682
+ index: "0",
1683
+ }, async () => {
1684
+ const harness = createExtensionHarness("lazy-skill-worker", { activeTools: ["read", "bash"] });
1685
+ piIntercomExtension(harness.pi as never);
1686
+
1687
+ try {
1688
+ await harness.emitLifecycle("session_start");
1689
+ assert.deepEqual(harness.getActiveTools(), ["read", "bash", "contact_supervisor"]);
1690
+
1691
+ harness.pi.events.emit("subagent:control-intercom", {
1692
+ to: "session-child-test",
1693
+ message: "Local relay traffic should not reveal the generic tool.",
1694
+ });
1695
+ assert.equal(harness.sentMessages.at(-1)?.activeTools.includes("intercom"), false);
1696
+ assert.equal(harness.getActiveTools().includes("intercom"), false);
1697
+
1698
+ await harness.emitLifecycle("tool_result", {
1699
+ toolName: "read",
1700
+ input: { path: path.join(repoDir, "README.md") },
1701
+ isError: false,
1702
+ });
1703
+ await harness.emitLifecycle("tool_result", {
1704
+ toolName: "read",
1705
+ input: { path: path.join(repoDir, "skills", "pi-intercom", "SKILL.md") },
1706
+ isError: true,
1707
+ });
1708
+ assert.equal(harness.getActiveTools().includes("intercom"), false);
1709
+
1710
+ await harness.emitLifecycle("tool_result", {
1711
+ toolName: "read",
1712
+ input: { path: path.join(repoDir, "skills", "pi-intercom", "SKILL.md") },
1713
+ isError: false,
1714
+ });
1715
+ assert.deepEqual(harness.getActiveTools(), ["read", "bash", "contact_supervisor", "intercom"]);
1716
+
1717
+ await harness.emitLifecycle("session_start");
1718
+ assert.equal(harness.getActiveTools().includes("intercom"), false);
1719
+ await harness.emitLifecycle("input", { text: " /skill: pi-intercom", source: "user" });
1720
+ assert.equal(harness.getActiveTools().includes("intercom"), true);
1721
+ } finally {
1722
+ await harness.emitLifecycle("session_shutdown");
1723
+ }
1724
+ }));
1725
+ });
1726
+
1727
+ test("lazy tool visibility reveals intercom before broker injection and after an overlay send", { concurrency: false }, async () => {
1728
+ const { default: piIntercomExtension } = await import("./index.ts");
1729
+
1730
+ await withIntercomConfig({ toolVisibility: "after-first-use" }, async () => {
1731
+ const { planner, cleanup } = await setupClients();
1732
+ let selectedSession: SessionInfo | undefined;
1733
+ let overlayStep = 0;
1734
+ const overlayHarness = createExtensionHarness("lazy-overlay-worker", {
1735
+ hasUI: true,
1736
+ activeTools: ["read"],
1737
+ ui: {
1738
+ notify: () => undefined,
1739
+ custom: async () => {
1740
+ overlayStep += 1;
1741
+ return overlayStep === 1
1742
+ ? selectedSession
1743
+ : { sent: true, messageId: "overlay-message", text: "Hello from the overlay" };
1744
+ },
1745
+ },
1746
+ });
1747
+ const inboundHarness = createExtensionHarness("lazy-inbound-worker", {
1748
+ hasUI: true,
1749
+ activeTools: ["read"],
1750
+ });
1751
+
1752
+ try {
1753
+ piIntercomExtension(overlayHarness.pi as never);
1754
+ piIntercomExtension(inboundHarness.pi as never);
1755
+ await overlayHarness.emitLifecycle("session_start");
1756
+ await inboundHarness.emitLifecycle("session_start");
1757
+ assert.equal(overlayHarness.getActiveTools().includes("intercom"), false);
1758
+ assert.equal(inboundHarness.getActiveTools().includes("intercom"), false);
1759
+
1760
+ selectedSession = await waitForSessionByName(planner, "planner");
1761
+ const inboundSession = await waitForSessionByName(planner, "lazy-inbound-worker");
1762
+ const delivered = await planner.send(inboundSession.id, {
1763
+ messageId: "lazy-inbound-message",
1764
+ text: "Reveal intercom before injecting this message.",
1765
+ });
1766
+ assert.equal(delivered.delivered, true);
1767
+ const deadline = Date.now() + 1000;
1768
+ while (inboundHarness.sentMessages.length === 0 && Date.now() < deadline) {
1769
+ await new Promise((resolve) => setTimeout(resolve, 20));
1770
+ }
1771
+ assert.equal(inboundHarness.sentMessages[0]?.activeTools.includes("intercom"), true);
1772
+
1773
+ await overlayHarness.commands.get("intercom")!("", overlayHarness.ctx);
1774
+ assert.equal(overlayStep, 2);
1775
+ assert.equal(overlayHarness.getActiveTools().includes("intercom"), true);
1776
+ } finally {
1777
+ await overlayHarness.emitLifecycle("session_shutdown");
1778
+ await inboundHarness.emitLifecycle("session_shutdown");
1779
+ await cleanup();
1780
+ }
1781
+ });
1782
+ });
1783
+
1119
1784
  test("contact supervisor tool renders reason and reply state", async () => {
1120
1785
  const { default: piIntercomExtension } = await import("./index.ts");
1121
1786
 
@@ -1212,7 +1877,7 @@ test("idle name poll propagates /name changes without other activity", { concurr
1212
1877
  }
1213
1878
  });
1214
1879
 
1215
- test("turn_start re-registers when Pi replaces the session context", { concurrency: false }, async () => {
1880
+ test("turn_start re-registers when Selesai replaces the session context", { concurrency: false }, async () => {
1216
1881
  const { planner, cleanup } = await setupClients();
1217
1882
  let sessionName = "fork-before";
1218
1883
  let sessionId = "session-fork-before";
@@ -1307,7 +1972,7 @@ test("idle interactive sessions trigger a new turn immediately", { concurrency:
1307
1972
  }
1308
1973
  });
1309
1974
 
1310
- test("duplicate inbound message IDs inject once with visible delivery metadata", { concurrency: false }, async () => {
1975
+ test("broker rejects changed duplicate message IDs and replays identical sends without reinjection", { concurrency: false }, async () => {
1311
1976
  const { default: piIntercomExtension } = await import("./index.ts");
1312
1977
  const { planner, cleanup } = await setupClients();
1313
1978
  const harness = createExtensionHarness("dedupe-worker", { hasUI: true });
@@ -1322,8 +1987,13 @@ test("duplicate inbound message IDs inject once with visible delivery metadata",
1322
1987
  });
1323
1988
 
1324
1989
  try {
1325
- assert.equal((await planner.send(worker.id, { messageId: "duplicate-inbound", text: "First copy" })).delivered, true);
1326
- assert.equal((await planner.send(worker.id, { messageId: "duplicate-inbound", text: "Second copy" })).delivered, true);
1990
+ const first = await planner.send(worker.id, { messageId: "duplicate-inbound", text: "First copy" });
1991
+ const changed = await planner.send(worker.id, { messageId: "duplicate-inbound", text: "Second copy" });
1992
+ const replay = await planner.send(worker.id, { messageId: "duplicate-inbound", text: "First copy" });
1993
+ assert.equal(first.delivered, true);
1994
+ assert.equal(changed.delivered, false);
1995
+ assert.equal(changed.code, "E_MESSAGE_ID_REUSE");
1996
+ assert.equal(replay.delivered, true);
1327
1997
  await new Promise((resolve) => setTimeout(resolve, 100));
1328
1998
  } finally {
1329
1999
  unsubscribeReceipts();
@@ -1333,7 +2003,6 @@ test("duplicate inbound message IDs inject once with visible delivery metadata",
1333
2003
  assert.ok(receipts.includes("receiver_received"));
1334
2004
  assert.ok(receipts.includes("acknowledged:accepted by receiver"));
1335
2005
  assert.ok(receipts.includes("injected"));
1336
- assert.ok(receipts.includes("acknowledged:duplicate message id suppressed"));
1337
2006
  const sent = harness.sentMessages[0]!;
1338
2007
  assert.match(sent.message.content ?? "", /id duplicate-inbound/);
1339
2008
  assert.match(sent.message.content ?? "", /seq 1/);
@@ -2042,6 +2711,103 @@ test("regular intercom asks fail safely when started concurrently", { concurrenc
2042
2711
  }
2043
2712
  });
2044
2713
 
2714
+ test("broker writes a local pending ask record for delivered blocking asks", { concurrency: false }, async () => {
2715
+ const { planner, orchestrator, cleanup } = await setupClients();
2716
+ const askId = "pending-record-live-ask";
2717
+
2718
+ try {
2719
+ const result = await planner.send(orchestrator.sessionId!, {
2720
+ messageId: askId,
2721
+ text: "Can you decide?",
2722
+ expectsReply: true,
2723
+ });
2724
+
2725
+ assert.equal(result.delivered, true);
2726
+ const record = readPendingAskRecord(askId);
2727
+ assert.equal(record.askId, askId);
2728
+ assert.equal(record.messageId, askId);
2729
+ assert.deepEqual(record.asker, { sessionId: planner.sessionId, name: "planner" });
2730
+ assert.deepEqual(record.target, { sessionId: orchestrator.sessionId, name: "orchestrator" });
2731
+ assert.equal(record.question, "Can you decide?");
2732
+ assert.equal(Number(record.expiresAt) - Number(record.createdAt), getAskTimeoutMs());
2733
+ if (process.platform !== "win32") {
2734
+ assert.equal(statSync(pendingAskRecordPath(askId)).mode & 0o777, 0o600);
2735
+ }
2736
+ } finally {
2737
+ await cleanup();
2738
+ }
2739
+ });
2740
+
2741
+ test("broker removes a pending ask record after a delivered reply", { concurrency: false }, async () => {
2742
+ const { planner, orchestrator, cleanup } = await setupClients();
2743
+ const askId = "pending-record-replied-ask";
2744
+
2745
+ try {
2746
+ assert.equal((await planner.send(orchestrator.sessionId!, {
2747
+ messageId: askId,
2748
+ text: "Can you answer?",
2749
+ expectsReply: true,
2750
+ })).delivered, true);
2751
+ assert.equal(existsSync(pendingAskRecordPath(askId)), true);
2752
+
2753
+ assert.equal((await orchestrator.send(planner.sessionId!, {
2754
+ text: "Answered.",
2755
+ replyTo: askId,
2756
+ })).delivered, true);
2757
+
2758
+ assert.equal(existsSync(pendingAskRecordPath(askId)), false);
2759
+ } finally {
2760
+ await cleanup();
2761
+ }
2762
+ });
2763
+
2764
+ test("broker removes a pending ask record after asker cancellation", { concurrency: false }, async () => {
2765
+ const { planner, orchestrator, cleanup } = await setupClients();
2766
+ const askId = "pending-record-cancelled-ask";
2767
+
2768
+ try {
2769
+ assert.equal((await planner.send(orchestrator.sessionId!, {
2770
+ messageId: askId,
2771
+ text: "Should I stop?",
2772
+ expectsReply: true,
2773
+ })).delivered, true);
2774
+ assert.equal(existsSync(pendingAskRecordPath(askId)), true);
2775
+
2776
+ planner.cancelAsk(askId);
2777
+ await waitForPendingAskRecordRemoved(askId);
2778
+ } finally {
2779
+ await cleanup();
2780
+ }
2781
+ });
2782
+
2783
+ test("broker removes a pending ask record during timeout pruning", { concurrency: false }, async () => {
2784
+ const previousTimeout = process.env.PI_INTERCOM_ASK_TIMEOUT_MS;
2785
+ process.env.PI_INTERCOM_ASK_TIMEOUT_MS = "50";
2786
+ const { planner, orchestrator, cleanup } = await setupClients();
2787
+ const askId = "pending-record-timeout-ask";
2788
+
2789
+ try {
2790
+ assert.equal((await planner.send(orchestrator.sessionId!, {
2791
+ messageId: askId,
2792
+ text: "Will this expire?",
2793
+ expectsReply: true,
2794
+ })).delivered, true);
2795
+ assert.equal(existsSync(pendingAskRecordPath(askId)), true);
2796
+
2797
+ await new Promise((resolve) => setTimeout(resolve, 80));
2798
+ assert.equal((await planner.send(orchestrator.sessionId!, { text: "Prune asks." })).delivered, true);
2799
+
2800
+ assert.equal(existsSync(pendingAskRecordPath(askId)), false);
2801
+ } finally {
2802
+ if (previousTimeout === undefined) {
2803
+ delete process.env.PI_INTERCOM_ASK_TIMEOUT_MS;
2804
+ } else {
2805
+ process.env.PI_INTERCOM_ASK_TIMEOUT_MS = previousTimeout;
2806
+ }
2807
+ await cleanup();
2808
+ }
2809
+ });
2810
+
2045
2811
  test("broker refuses reverse mutual asks until the original ask is answered", { concurrency: false }, async () => {
2046
2812
  const { planner, orchestrator, cleanup } = await setupClients();
2047
2813
 
@@ -2346,6 +3112,42 @@ test("intercom reply targets exact replyTo when multiple asks are pending", { co
2346
3112
  }
2347
3113
  });
2348
3114
 
3115
+ test("intercom reply sends attachments", { concurrency: false }, async () => {
3116
+ const { planner, cleanup } = await setupClients();
3117
+ const { default: piIntercomExtension } = await import("./index.ts");
3118
+ const harness = createExtensionHarness("reply-attachment-worker");
3119
+
3120
+ try {
3121
+ piIntercomExtension(harness.pi as never);
3122
+ await harness.emitLifecycle("session_start");
3123
+ const worker = await waitForSessionByName(planner, "reply-attachment-worker");
3124
+
3125
+ const askId = "reply-attachment-ask";
3126
+ assert.equal((await planner.send(worker.id, { messageId: askId, text: "Send details?", expectsReply: true })).delivered, true);
3127
+ await new Promise((resolve) => setTimeout(resolve, 50));
3128
+
3129
+ const intercomTool = harness.tools.find((tool) => tool.name === "intercom")!;
3130
+ const attachments = [{ type: "snippet" as const, name: "details.md", content: "attached details", language: "md" }];
3131
+ const replyReceived = waitForReply(planner, askId);
3132
+ const result = await intercomTool.execute("reply-with-attachment", {
3133
+ action: "reply",
3134
+ message: "Here are details.",
3135
+ attachments,
3136
+ }, new AbortController().signal, undefined, harness.ctx);
3137
+
3138
+ assert.equal(result.details?.delivered, true);
3139
+ const reply = await replyReceived;
3140
+ assert.equal(reply.message.content.text, "Here are details.");
3141
+ assert.deepEqual(reply.message.content.attachments, attachments);
3142
+
3143
+ const sentEntry = harness.entries.find((entry) => entry.type === "intercom_sent");
3144
+ assert.deepEqual((sentEntry?.data as { message?: { attachments?: unknown } }).message?.attachments, attachments);
3145
+ } finally {
3146
+ await harness.emitLifecycle("session_shutdown");
3147
+ await cleanup();
3148
+ }
3149
+ });
3150
+
2349
3151
  test("intercom reply targets one of multiple pending asks by short session ID", { concurrency: false }, async () => {
2350
3152
  const { planner, orchestrator, cleanup } = await setupClients();
2351
3153
  const { default: piIntercomExtension } = await import("./index.ts");
@@ -3423,6 +4225,10 @@ test("failed delivery from an inferred reply preserves the pending ask", { concu
3423
4225
  }, new AbortController().signal, undefined, harness.ctx);
3424
4226
 
3425
4227
  assert.equal(result.details?.delivered, false);
4228
+ assert.equal(result.details?.delivery, "failed");
4229
+ assert.equal(result.details?.code, "E_AMBIGUOUS_TARGET");
4230
+ assert.equal(result.details?.retryable, false);
4231
+ assert.equal(result.details?.outcomeKnown, true);
3426
4232
  assert.match(result.content[0]?.text ?? "", /Multiple disconnected sessions named/);
3427
4233
 
3428
4234
  const pending = await intercomTool.execute("pending-after-failure", { action: "pending" }, new AbortController().signal, undefined, harness.ctx);