@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
@@ -0,0 +1,1415 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import type { AgentToolResult } from "@earendil-works/pi-agent-core";
4
+ import { getMarkdownTheme, type ExtensionContext } from "@selesai/code";
5
+ import { matchesKey, truncateToWidth, visibleWidth, wrapTextWithAnsi, type Component, type MarkdownTheme } from "@earendil-works/pi-tui";
6
+ import { snapshotExternalRuns, type ExternalRun } from "../api/external-runs.ts";
7
+ import { getArtifactPaths, getArtifactsDir } from "../shared/artifacts.ts";
8
+ import { formatDuration, formatModelThinking, formatTokens, shortenPath } from "../shared/formatters.ts";
9
+ import { DIRS, type AsyncJobState, type AsyncJobStep, type Details, type FleetKeybindingAction, type FleetKeybindingsConfig, type ForegroundChildControl, type ForegroundResumeChild, type ForegroundResumeRun, type ForegroundRunControl, type SubagentState } from "../shared/types.ts";
10
+ import { decodeUtf8Tail } from "../shared/utf8.ts";
11
+ import { readStatus } from "../shared/utils.ts";
12
+ import { formatAsyncRunTranscript } from "../runs/background/fleet-view.ts";
13
+ import { listAsyncRuns, type AsyncRunSummary } from "../runs/background/async-status.ts";
14
+ import { steerAsyncRun } from "../runs/foreground/async-steering-action.ts";
15
+ import type { SteerDeliveryMode } from "../runs/background/control-channel.ts";
16
+ import { stopAsyncRun } from "../runs/foreground/async-stop-action.ts";
17
+ import { resolveWorkflowForegroundSteeringTarget, steerWorkflowForegroundTarget } from "../runs/foreground/workflow-foreground-steering.ts";
18
+ import { contextModeBadge, contextModeLabel } from "../runs/shared/context-mode.ts";
19
+ import { FLEET_STATUS_WIDGET_KEY } from "./fleet-status.ts";
20
+ import { readFleetTranscript, renderFleetTranscript, type FleetTranscript } from "./fleet-transcript.ts";
21
+ import { handleHerdrInspectorAction } from "../inspectors/herdr/actions.ts";
22
+ import type { HerdrClient } from "../inspectors/herdr/client.ts";
23
+ import { getLivePromptAudit, type LivePromptAudit, type PromptAuditView } from "../runs/foreground/prompt-audit.ts";
24
+
25
+ const REFRESH_MS = 750;
26
+ const MIN_REFRESH_MS = 250;
27
+ const MAX_RECENT_ASYNC_RUNS = 20;
28
+ const MAX_FLEET_HISTORY_CANDIDATES = 100;
29
+ const TRANSCRIPT_LINES = 200;
30
+ const OUTPUT_TAIL_BYTES = 64 * 1024;
31
+ const PROMPT_AUDIT_SUMMARY_WIDTH = 160;
32
+
33
+ export const DEFAULT_FLEET_KEYBINDINGS: Record<FleetKeybindingAction, string[]> = {
34
+ close: ["escape", "ctrl+c", "q"],
35
+ scrollUp: ["K"],
36
+ scrollDown: ["J"],
37
+ selectUp: ["up", "k"],
38
+ selectDown: ["down", "j"],
39
+ selectFirst: ["home"],
40
+ selectLast: ["end"],
41
+ pageUp: ["pageUp"],
42
+ pageDown: ["pageDown"],
43
+ refresh: ["r", "R"],
44
+ steer: ["s"],
45
+ inspect: ["H"],
46
+ stop: ["D"],
47
+ toggleTools: ["x", "X", "ctrl+o"],
48
+ };
49
+
50
+ type ResolvedFleetKeybindings = Record<FleetKeybindingAction, string[]>;
51
+
52
+ export function resolveFleetKeybindings(config: FleetKeybindingsConfig | undefined): ResolvedFleetKeybindings {
53
+ return Object.fromEntries(
54
+ Object.entries(DEFAULT_FLEET_KEYBINDINGS).map(([action, defaults]) => [action, config?.[action as FleetKeybindingAction] ?? defaults]),
55
+ ) as ResolvedFleetKeybindings;
56
+ }
57
+
58
+ function matchesFleetBinding(data: string, binding: string): boolean {
59
+ const key = /^[A-Z]$/.test(binding) ? `shift+${binding.toLowerCase()}` : binding;
60
+ return matchesKey(data, key as Parameters<typeof matchesKey>[1]);
61
+ }
62
+
63
+ function matchesFleetAction(data: string, bindings: ResolvedFleetKeybindings, action: FleetKeybindingAction): boolean {
64
+ return bindings[action].some((binding) => matchesFleetBinding(data, binding));
65
+ }
66
+
67
+ function bindingLabel(bindings: ResolvedFleetKeybindings, action: FleetKeybindingAction): string {
68
+ return bindings[action]
69
+ .map((binding) => binding === "up" ? "↑" : binding === "down" ? "↓" : binding === "escape" ? "Esc" : binding === "return" ? "Enter" : binding)
70
+ .join("/");
71
+ }
72
+
73
+ type Theme = ExtensionContext["ui"]["theme"];
74
+ type FleetTui = {
75
+ terminal?: { rows: number };
76
+ requestRender(): void;
77
+ };
78
+ type AsyncStep = AsyncRunSummary["steps"][number];
79
+
80
+ export type FleetItem = (
81
+ | { key: string; kind: "foreground-active"; runId: string; index?: number; agent: string; state: "running"; updatedAt: number; control: ForegroundRunControl; activeChild?: ForegroundChildControl }
82
+ | { key: string; kind: "foreground-recent"; runId: string; index: number; agent: string; state: ForegroundResumeChild["status"]; updatedAt: number; run: ForegroundResumeRun; child: ForegroundResumeChild }
83
+ | { key: string; kind: "async"; runId: string; index?: number; agent: string; state: string; updatedAt: number; run: AsyncRunSummary; step?: AsyncStep }
84
+ | { key: string; kind: "external"; runId: string; agent: string; state: ExternalRun["state"]; updatedAt: number; run: ExternalRun }
85
+ ) & { description?: string };
86
+
87
+ export interface FleetSnapshot {
88
+ items: FleetItem[];
89
+ error?: string;
90
+ }
91
+
92
+ export interface FleetActionResult {
93
+ text: string;
94
+ isError?: boolean;
95
+ }
96
+
97
+ export interface FleetActionHandlers {
98
+ steer(input: { runId: string; asyncDir: string; index?: number; message: string; mode: SteerDeliveryMode }): Promise<FleetActionResult>;
99
+ stop(input: { runId: string; asyncDir: string; index?: number }): Promise<FleetActionResult> | FleetActionResult;
100
+ inspect?(input: { runId: string; asyncDir: string; index?: number }): Promise<FleetActionResult>;
101
+ redoPrompt?(input: { runId: string; index: number; guidance: string; control?: ForegroundRunControl }): Promise<FleetActionResult>;
102
+ }
103
+
104
+ export interface FleetViewOptions {
105
+ asyncDirRoot?: string;
106
+ resultsDir?: string;
107
+ refreshMs?: number;
108
+ initialKey?: string;
109
+ markdownTheme?: MarkdownTheme;
110
+ fleetKeybindings?: FleetKeybindingsConfig;
111
+ actions?: FleetActionHandlers;
112
+ copyText?: (text: string) => Promise<void> | void;
113
+ herdrClient?: HerdrClient;
114
+ }
115
+
116
+ function belongsToCurrentSession(sessionId: string | undefined, currentSessionId: string | null): boolean {
117
+ return !currentSessionId || sessionId === currentSessionId;
118
+ }
119
+
120
+ function trackedJobSummary(job: AsyncJobState): AsyncRunSummary {
121
+ const startedAt = job.startedAt ?? job.updatedAt ?? Date.now();
122
+ return {
123
+ id: job.asyncId,
124
+ asyncDir: job.asyncDir,
125
+ ...(job.sessionId ? { sessionId: job.sessionId } : {}),
126
+ state: job.status,
127
+ activityState: job.activityState,
128
+ lastActivityAt: job.lastActivityAt,
129
+ currentTool: job.currentTool,
130
+ currentToolStartedAt: job.currentToolStartedAt,
131
+ currentPath: job.currentPath,
132
+ turnCount: job.turnCount,
133
+ toolCount: job.toolCount,
134
+ steering: job.steering,
135
+ mode: job.mode ?? "single",
136
+ ...(job.context ? { context: job.context } : {}),
137
+ ...(job.cwd ? { cwd: job.cwd } : {}),
138
+ startedAt,
139
+ ...(job.updatedAt !== undefined ? { lastUpdate: job.updatedAt } : {}),
140
+ ...(job.timeoutMs !== undefined ? { timeoutMs: job.timeoutMs } : {}),
141
+ ...(job.deadlineAt !== undefined ? { deadlineAt: job.deadlineAt } : {}),
142
+ ...(job.timedOut !== undefined ? { timedOut: job.timedOut } : {}),
143
+ ...(job.stopped !== undefined ? { stopped: job.stopped } : {}),
144
+ ...(job.turnBudget ? { turnBudget: job.turnBudget } : {}),
145
+ ...(job.turnBudgetExceeded !== undefined ? { turnBudgetExceeded: job.turnBudgetExceeded } : {}),
146
+ ...(job.wrapUpRequested !== undefined ? { wrapUpRequested: job.wrapUpRequested } : {}),
147
+ ...(job.currentStep !== undefined ? { currentStep: job.currentStep } : {}),
148
+ ...(job.chainStepCount !== undefined ? { chainStepCount: job.chainStepCount } : {}),
149
+ ...(job.parallelGroups?.length ? { parallelGroups: job.parallelGroups } : {}),
150
+ steps: (job.steps ?? job.agents?.map((agent, index) => ({ agent, index, status: job.status === "queued" ? "pending" as const : job.status })) ?? []).map((step, index) => ({
151
+ ...step,
152
+ index: step.index ?? index,
153
+ })),
154
+ ...(job.sessionDir ? { sessionDir: job.sessionDir } : {}),
155
+ ...(job.outputFile ? { outputFile: job.outputFile } : {}),
156
+ ...(job.totalTokens ? { totalTokens: job.totalTokens } : {}),
157
+ ...(job.sessionFile ? { sessionFile: job.sessionFile } : {}),
158
+ ...(job.nestedChildren?.length ? { nestedChildren: job.nestedChildren } : {}),
159
+ };
160
+ }
161
+
162
+ function asyncItems(run: AsyncRunSummary, description?: string): FleetItem[] {
163
+ const updatedAt = run.lastUpdate ?? run.endedAt ?? run.startedAt;
164
+ if (run.steps.length === 0 || run.mode === "workflow") {
165
+ return [{ key: `async:${run.id}`, kind: "async", runId: run.id, agent: run.mode, state: run.state, updatedAt, run, ...(description ? { description } : {}) }];
166
+ }
167
+ return run.steps.map((step) => ({
168
+ key: `async:${run.id}:${step.index}`,
169
+ kind: "async" as const,
170
+ runId: run.id,
171
+ index: step.index,
172
+ agent: step.label ? `${step.label} (${step.agent})` : step.agent,
173
+ state: step.status,
174
+ updatedAt: step.lastActivityAt ?? updatedAt,
175
+ run,
176
+ step,
177
+ ...(description ? { description } : {}),
178
+ }));
179
+ }
180
+
181
+ function orderFleetAsyncRuns(runs: AsyncRunSummary[], terminalLimit: number): AsyncRunSummary[] {
182
+ const updatedAt = (run: AsyncRunSummary) => run.lastUpdate ?? run.endedAt ?? run.startedAt;
183
+ const byNewest = (left: AsyncRunSummary, right: AsyncRunSummary) => updatedAt(right) - updatedAt(left);
184
+ const active = runs.filter((run) => run.state === "queued" || run.state === "running").sort(byNewest);
185
+ const terminal = runs.filter((run) => run.state !== "queued" && run.state !== "running").sort(byNewest);
186
+ return [...active, ...terminal.slice(0, terminalLimit)];
187
+ }
188
+
189
+ export function collectFleetSnapshot(
190
+ state: SubagentState,
191
+ options: { asyncDirRoot?: string; resultsDir?: string; limit?: number } = {},
192
+ ): FleetSnapshot {
193
+ const items: FleetItem[] = [];
194
+ const activeForegroundIds = new Set<string>();
195
+ const trackedJobs = state.fleetJobs ?? state.asyncJobs;
196
+ const workflowParentIds = new Set([...trackedJobs.values()]
197
+ .filter((job) => job.mode === "workflow" && belongsToCurrentSession(job.sessionId, state.currentSessionId))
198
+ .map((job) => job.asyncId));
199
+ const workflowForegroundChildCounts = new Map<string, number>();
200
+ const liveWorkflowForegroundControls = new Set<ForegroundRunControl>();
201
+ for (const control of state.foregroundControls.values()) {
202
+ const activeChildCount = control.activeChildren?.size ?? 0;
203
+ if (!control.parentWorkflowRunId
204
+ || !workflowParentIds.has(control.parentWorkflowRunId)
205
+ || !belongsToCurrentSession(control.sessionId, state.currentSessionId)
206
+ || !control.workflowSteeringDir
207
+ || activeChildCount === 0) continue;
208
+ liveWorkflowForegroundControls.add(control);
209
+ workflowForegroundChildCounts.set(control.parentWorkflowRunId, (workflowForegroundChildCounts.get(control.parentWorkflowRunId) ?? 0) + activeChildCount);
210
+ }
211
+ for (const control of [...state.foregroundControls.values()].sort((left, right) => right.updatedAt - left.updatedAt)) {
212
+ activeForegroundIds.add(control.runId);
213
+ if (control.parentWorkflowRunId && workflowParentIds.has(control.parentWorkflowRunId)
214
+ && ((workflowForegroundChildCounts.get(control.parentWorkflowRunId) ?? 0) <= 1 || !liveWorkflowForegroundControls.has(control))) continue;
215
+ if (control.activeChildren) {
216
+ for (const child of [...control.activeChildren.values()].sort((left, right) => left.index - right.index)) {
217
+ items.push({
218
+ key: `foreground-active:${control.runId}:${child.index}`,
219
+ kind: "foreground-active",
220
+ runId: control.runId,
221
+ index: child.index,
222
+ agent: child.agent,
223
+ state: "running",
224
+ updatedAt: child.updatedAt,
225
+ control,
226
+ activeChild: child,
227
+ ...(child.description ? { description: child.description } : {}),
228
+ });
229
+ }
230
+ continue;
231
+ }
232
+ items.push({
233
+ key: `foreground-active:${control.runId}:${control.currentIndex ?? 0}`,
234
+ kind: "foreground-active",
235
+ runId: control.runId,
236
+ ...(control.currentIndex !== undefined ? { index: control.currentIndex } : {}),
237
+ agent: control.currentAgent ?? control.mode,
238
+ state: "running",
239
+ updatedAt: control.updatedAt,
240
+ control,
241
+ ...(control.description ? { description: control.description } : {}),
242
+ });
243
+ }
244
+
245
+ let error: string | undefined;
246
+ try {
247
+ let runs: AsyncRunSummary[];
248
+ const descriptions = new Map<string, string>();
249
+ const tracked = [...trackedJobs.values()]
250
+ .filter((job) => belongsToCurrentSession(job.sessionId, state.currentSessionId));
251
+ const byUpdate = (left: AsyncJobState, right: AsyncJobState) => (right.updatedAt ?? right.startedAt ?? 0) - (left.updatedAt ?? left.startedAt ?? 0);
252
+ const active = tracked.filter((job) => job.status === "queued" || job.status === "running").sort(byUpdate);
253
+ const recent = tracked.filter((job) => job.status !== "queued" && job.status !== "running").sort(byUpdate).slice(0, options.limit ?? MAX_RECENT_ASYNC_RUNS);
254
+ const trackedRuns: AsyncRunSummary[] = [];
255
+ for (const job of [...active, ...recent]) {
256
+ try {
257
+ trackedRuns.push(trackedJobSummary(job));
258
+ if (job.description) descriptions.set(job.asyncId, job.description);
259
+ } catch (cause) {
260
+ error = `Failed to inspect async run '${job.asyncId}': ${cause instanceof Error ? cause.message : String(cause)}`;
261
+ }
262
+ }
263
+ if (options.asyncDirRoot !== undefined) {
264
+ const trackedIds = new Set(trackedRuns.map((run) => run.id));
265
+ const history = listAsyncRuns(options.asyncDirRoot, {
266
+ ...(state.currentSessionId ? { sessionId: state.currentSessionId } : {}),
267
+ entryLimit: MAX_FLEET_HISTORY_CANDIDATES,
268
+ resultsDir: options.resultsDir ?? DIRS.results,
269
+ reconcile: false,
270
+ }).filter((run) => !trackedIds.has(run.id));
271
+ runs = [...trackedRuns, ...history];
272
+ } else {
273
+ runs = trackedRuns;
274
+ }
275
+ for (const run of orderFleetAsyncRuns(runs, options.limit ?? MAX_RECENT_ASYNC_RUNS)) {
276
+ items.push(...asyncItems(run, descriptions.get(run.id)));
277
+ }
278
+ } catch (cause) {
279
+ error = cause instanceof Error ? cause.message : String(cause);
280
+ }
281
+
282
+ if (state.currentSessionId) {
283
+ try {
284
+ for (const run of snapshotExternalRuns(state.currentSessionId, { ignoreMalformed: true, onMalformedRecord: (message) => console.warn(`[pi-subagents] Removed ${message}`) })) {
285
+ items.push({
286
+ key: `external:${run.id}`,
287
+ kind: "external",
288
+ runId: run.id,
289
+ agent: run.label,
290
+ state: run.state,
291
+ updatedAt: run.updatedAt ?? run.endedAt ?? run.startedAt,
292
+ run,
293
+ ...(run.currentAction ? { description: run.currentAction } : {}),
294
+ });
295
+ }
296
+ } catch (cause) {
297
+ const message = `Failed to inspect external jobs: ${cause instanceof Error ? cause.message : String(cause)}`;
298
+ error = error ? `${error}; ${message}` : message;
299
+ }
300
+ }
301
+
302
+ const recentForeground = [...(state.foregroundRuns?.values() ?? [])]
303
+ .filter((run) => belongsToCurrentSession(run.sessionId, state.currentSessionId) && !activeForegroundIds.has(run.runId))
304
+ .sort((left, right) => right.updatedAt - left.updatedAt);
305
+ for (const run of recentForeground) {
306
+ for (const child of run.children) {
307
+ items.push({
308
+ key: `foreground-recent:${run.runId}:${child.index}`,
309
+ kind: "foreground-recent",
310
+ runId: run.runId,
311
+ index: child.index,
312
+ agent: child.agent,
313
+ state: child.status,
314
+ updatedAt: child.updatedAt ?? run.updatedAt,
315
+ run,
316
+ child,
317
+ });
318
+ }
319
+ }
320
+ return { items, ...(error ? { error } : {}) };
321
+ }
322
+
323
+ function visibleWorkflowParentKeyForForegroundKey(state: SubagentState, key: string, items: FleetItem[]): string | undefined {
324
+ for (const control of state.foregroundControls.values()) {
325
+ if (!control.parentWorkflowRunId) continue;
326
+ let matches = false;
327
+ if (control.activeChildren) {
328
+ for (const child of control.activeChildren.values()) {
329
+ if (`foreground-active:${control.runId}:${child.index}` === key) {
330
+ matches = true;
331
+ break;
332
+ }
333
+ }
334
+ } else {
335
+ matches = `foreground-active:${control.runId}:${control.currentIndex ?? 0}` === key;
336
+ }
337
+ if (!matches) continue;
338
+ const parentKey = `async:${control.parentWorkflowRunId}`;
339
+ return items.some((item) => item.key === parentKey) ? parentKey : undefined;
340
+ }
341
+ return undefined;
342
+ }
343
+
344
+ function statusGlyph(item: FleetItem, theme: Theme): string {
345
+ if (item.state === "running") return theme.fg("accent", "●");
346
+ if (item.state === "queued" || item.state === "pending") return theme.fg("muted", "◦");
347
+ if (item.state === "complete" || item.state === "completed") return theme.fg("success", "✓");
348
+ if (item.state === "paused" || item.state === "stopped" || item.state === "detached") return theme.fg("warning", "■");
349
+ return theme.fg("error", "✗");
350
+ }
351
+
352
+ function foregroundPromptAuditCount(item: Extract<FleetItem, { kind: "foreground-active" }>, state: SubagentState): number {
353
+ if (!state.currentSessionId || item.control.sessionId !== state.currentSessionId) return 0;
354
+ if (!item.control.activeChildren) return getLivePromptAudit(item.control, item.index ?? 0) ? 1 : 0;
355
+ return [...item.control.activeChildren.keys()].filter((index) => getLivePromptAudit(item.control, index)).length;
356
+ }
357
+
358
+ function authoredPromptSummary(text: string): string | undefined {
359
+ const summary = text.replace(/\s+/g, " ").trim();
360
+ return summary ? truncateToWidth(summary, PROMPT_AUDIT_SUMMARY_WIDTH, "…") : undefined;
361
+ }
362
+
363
+ function foregroundAuthoredPromptSummary(item: Extract<FleetItem, { kind: "foreground-active" }>, state: SubagentState): string | undefined {
364
+ if (!state.currentSessionId || item.control.sessionId !== state.currentSessionId) return undefined;
365
+ const prompt = getLivePromptAudit(item.control, item.index ?? 0);
366
+ return prompt ? authoredPromptSummary(prompt.authoredTask) : undefined;
367
+ }
368
+
369
+ function promptAuditText(prompt: LivePromptAudit, view: PromptAuditView): string {
370
+ switch (view) {
371
+ case "authored": return prompt.authoredTask;
372
+ case "runtime": return prompt.runtimeAdditions;
373
+ case "effective": return prompt.finalEffectivePrompt;
374
+ }
375
+ }
376
+
377
+ function promptAuditViewLabel(view: PromptAuditView): string {
378
+ switch (view) {
379
+ case "authored": return "[1] Authored task";
380
+ case "runtime": return "[2] Runtime additions";
381
+ case "effective": return "[3] Final effective prompt";
382
+ }
383
+ }
384
+
385
+ function foregroundActiveDetail(item: Extract<FleetItem, { kind: "foreground-active" }>, state: SubagentState): string[] {
386
+ const { control } = item;
387
+ const live = item.activeChild ?? control;
388
+ const modelThinking = formatModelThinking(live.model, live.thinking);
389
+ const promptAuditCount = foregroundPromptAuditCount(item, state);
390
+ const promptSummary = foregroundAuthoredPromptSummary(item, state);
391
+ const lines = [
392
+ `Run: ${item.runId}`,
393
+ "Source: foreground",
394
+ `State: running`,
395
+ `Mode: ${control.mode}`,
396
+ control.parentWorkflowRunId ? `Workflow child of: ${control.parentWorkflowRunId}${control.workflowKey ? ` (${control.workflowKey})` : ""}` : undefined,
397
+ control.sourceRunId ? `Redo source: ${control.sourceRunId}` : undefined,
398
+ control.supersededByRunId ? `Superseded by: ${control.supersededByRunId}` : undefined,
399
+ item.index !== undefined ? `Child: ${item.index} (${item.agent})` : `Agent: ${item.agent}`,
400
+ modelThinking ? `Model: ${modelThinking}` : undefined,
401
+ promptSummary ? `Task: ${promptSummary}` : undefined,
402
+ `Started: ${new Date(live.startedAt).toISOString()}`,
403
+ live.currentTool ? `Current tool: ${live.currentTool}${live.currentPath ? ` · ${shortenPath(live.currentPath)}` : ""}` : undefined,
404
+ live.turnCount !== undefined ? `Turns: ${live.turnCount}` : undefined,
405
+ live.toolCount !== undefined ? `Tools: ${live.toolCount}` : undefined,
406
+ live.tokens !== undefined ? `Tokens: ${formatTokens(live.tokens)}` : undefined,
407
+ promptAuditCount > 0 ? `Prompt audit: ${promptAuditCount} live · 3 views · p opens` : undefined,
408
+ "",
409
+ "Transcript",
410
+ "Live foreground output remains in the expanded subagent tool result. Persisted output and session paths appear here after the child settles.",
411
+ ];
412
+ return lines.filter((line): line is string => line !== undefined);
413
+ }
414
+
415
+ function pathWithin(base: string, candidate: string): boolean {
416
+ const resolvedBase = path.resolve(base);
417
+ const resolvedCandidate = path.resolve(candidate);
418
+ return resolvedCandidate === resolvedBase || resolvedCandidate.startsWith(`${resolvedBase}${path.sep}`);
419
+ }
420
+
421
+ function trustedFileTail(filePath: string, trustedRoots: string[]): { text?: string; warning?: string; unavailable?: string } {
422
+ const resolvedPath = path.resolve(filePath);
423
+ if (trustedRoots.length === 0 || !trustedRoots.some((root) => pathWithin(root, resolvedPath))) return { warning: `output artifact is outside trusted roots: ${filePath}` };
424
+ let stat: fs.Stats;
425
+ try {
426
+ stat = fs.lstatSync(resolvedPath);
427
+ } catch (error) {
428
+ if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") return { unavailable: `output artifact unavailable: ${filePath}` };
429
+ return { warning: `output artifact could not be inspected: ${error instanceof Error ? error.message : String(error)}` };
430
+ }
431
+ if (stat.isSymbolicLink()) return { warning: `output artifact refused a symlink: ${filePath}` };
432
+ if (!stat.isFile()) return { warning: `output artifact is not a file: ${filePath}` };
433
+ try {
434
+ const realPath = fs.realpathSync(resolvedPath);
435
+ const realRoots = trustedRoots.filter((root) => fs.existsSync(root)).map((root) => fs.realpathSync(root));
436
+ if (!realRoots.some((root) => pathWithin(root, realPath))) return { warning: `output artifact resolves outside trusted roots: ${filePath}` };
437
+ const fd = fs.openSync(realPath, "r");
438
+ try {
439
+ const bytes = Math.min(stat.size, OUTPUT_TAIL_BYTES);
440
+ const buffer = Buffer.alloc(bytes);
441
+ fs.readSync(fd, buffer, 0, bytes, stat.size - bytes);
442
+ return { text: decodeUtf8Tail(buffer) };
443
+ } finally {
444
+ fs.closeSync(fd);
445
+ }
446
+ } catch (error) {
447
+ return { warning: `output artifact could not be read: ${error instanceof Error ? error.message : String(error)}` };
448
+ }
449
+ }
450
+
451
+ function foregroundRecentOutputLines(item: Extract<FleetItem, { kind: "foreground-recent" }>, state: SubagentState): string[] {
452
+ const outputPath = item.child.artifactPaths?.outputPath ?? item.child.savedOutputPath;
453
+ const output = item.child.finalOutput
454
+ ? { text: item.child.finalOutput }
455
+ : outputPath
456
+ ? trustedFileTail(path.isAbsolute(outputPath) ? outputPath : path.resolve(item.run.cwd, outputPath), uniquePaths([
457
+ fleetArtifactsRoot(state, item.run.cwd),
458
+ fleetArtifactsRoot(state, state.baseCwd),
459
+ ]))
460
+ : undefined;
461
+ if (output?.warning) return [`(${output.warning})`];
462
+ if (output?.unavailable) return [`(${output.unavailable})`];
463
+ const outputLines = (output?.text ?? "").split(/\r?\n/).filter((line) => line.trim()).slice(-TRANSCRIPT_LINES);
464
+ return outputLines.length ? outputLines : ["(no recovered output available)"];
465
+ }
466
+
467
+ function foregroundRecentDetail(item: Extract<FleetItem, { kind: "foreground-recent" }>, state: SubagentState): string[] {
468
+ const { child, run } = item;
469
+ const outputPath = child.artifactPaths?.outputPath ?? child.savedOutputPath;
470
+ const modelThinking = formatModelThinking(child.model, child.thinking);
471
+ const lines = [
472
+ `Run: ${item.runId}`,
473
+ "Source: foreground",
474
+ `State: ${child.status}`,
475
+ `Mode: ${run.mode}`,
476
+ `Child: ${child.index} (${child.agent})${contextModeLabel(child.context) ? ` ${contextModeLabel(child.context)}` : ""}`,
477
+ modelThinking ? `Model: ${modelThinking}` : undefined,
478
+ `Updated: ${new Date(child.updatedAt ?? run.updatedAt).toISOString()}`,
479
+ outputPath ? `Output: ${outputPath}` : undefined,
480
+ child.sessionFile ? `Session: ${child.sessionFile}` : undefined,
481
+ child.transcriptPath ? `Transcript file: ${child.transcriptPath}` : undefined,
482
+ child.error ? `Error: ${child.error}` : undefined,
483
+ child.outputSaveError ? `Output warning: ${child.outputSaveError}` : undefined,
484
+ child.transcriptError ? `Transcript warning: ${child.transcriptError}` : undefined,
485
+ "",
486
+ "Result transcript tail",
487
+ ];
488
+ lines.push(...foregroundRecentOutputLines(item, state));
489
+ return lines.filter((line): line is string => line !== undefined);
490
+ }
491
+
492
+ function externalElapsedEnd(run: ExternalRun): number {
493
+ const terminal = run.state !== "queued" && run.state !== "running";
494
+ return terminal ? (run.endedAt ?? run.updatedAt ?? Date.now()) : Date.now();
495
+ }
496
+
497
+ function workflowStepLabel(step: AsyncJobStep, index: number): string {
498
+ const key = step.workflowKey ?? `step ${index + 1}`;
499
+ const label = step.label && step.label !== key ? ` · ${step.label}` : "";
500
+ const phase = step.phase ? `${step.phase}: ` : "";
501
+ return `${phase}${key}${label} (${step.agent})`;
502
+ }
503
+
504
+ function workflowStepActivity(step: AsyncJobStep): string | undefined {
505
+ if (step.currentTool) return `tool ${step.currentTool}`;
506
+ if (step.currentPath) return shortenPath(step.currentPath);
507
+ if (step.activityState === "needs_attention") return "needs attention";
508
+ if (step.activityState === "active_long_running") return "long-running";
509
+ if (step.turnCount !== undefined) return `${step.turnCount} turns`;
510
+ if (step.toolCount !== undefined) return `${step.toolCount} tools`;
511
+ return undefined;
512
+ }
513
+
514
+ function visibleWorkflowProgressSteps(steps: AsyncJobStep[], visibleLimit: number): Array<{ step: AsyncJobStep; index: number } | { hidden: number }> {
515
+ if (steps.length <= visibleLimit) return steps.map((step, index) => ({ step, index }));
516
+ const selected = new Set<number>();
517
+ for (const [index, step] of steps.entries()) {
518
+ if (step.status !== "complete" && step.status !== "completed") selected.add(index);
519
+ if (selected.size >= visibleLimit) break;
520
+ }
521
+ for (let index = steps.length - 1; index >= 0 && selected.size < visibleLimit; index--) selected.add(index);
522
+ const visible = [...selected].sort((left, right) => left - right).map((index) => ({ step: steps[index]!, index }));
523
+ return [{ hidden: steps.length - visible.length }, ...visible];
524
+ }
525
+
526
+ function workflowProgressLines(steps: AsyncJobStep[] | undefined): string[] {
527
+ if (!steps?.length) return [];
528
+ const lines = ["Workflow progress:"];
529
+ for (const row of visibleWorkflowProgressSteps(steps, 8)) {
530
+ if ("hidden" in row) {
531
+ lines.push(` +${row.hidden} hidden workflow steps`);
532
+ continue;
533
+ }
534
+ const activity = workflowStepActivity(row.step);
535
+ const context = contextModeLabel(row.step.context);
536
+ const details = [row.step.status, activity, context, row.step.tokens?.total !== undefined ? formatTokens(row.step.tokens.total) : undefined].filter(Boolean).join(" · ");
537
+ lines.push(` ${row.index + 1}. ${workflowStepLabel(row.step, row.index)}${details ? ` — ${details}` : ""}`);
538
+ }
539
+ return lines;
540
+ }
541
+
542
+ function asyncDetail(item: Extract<FleetItem, { kind: "async" }>, state: SubagentState): string[] {
543
+ const status = readStatus(item.run.asyncDir);
544
+ if (status) {
545
+ const trackedJob = state.fleetJobs?.get(item.runId) ?? state.asyncJobs.get(item.runId);
546
+ const lines = formatAsyncRunTranscript(status, item.run.asyncDir, {
547
+ index: item.index,
548
+ lines: TRANSCRIPT_LINES,
549
+ sessionRoots: uniquePaths([...(state.trustedSessionRoots ?? []), trackedJob?.sessionRoot]),
550
+ }).split("\n");
551
+ if (status.mode === "workflow" && item.index === undefined) {
552
+ const progress = workflowProgressLines((status.steps ?? item.run.steps) as AsyncJobStep[]);
553
+ if (progress.length) {
554
+ const modeIndex = lines.findIndex((line) => line.startsWith("Mode:"));
555
+ lines.splice(modeIndex >= 0 ? modeIndex + 1 : 0, 0, "", ...progress);
556
+ }
557
+ }
558
+ return lines;
559
+ }
560
+ const outputPath = item.index !== undefined ? path.join(item.run.asyncDir, `output-${item.index}.log`) : undefined;
561
+ return [
562
+ `Run: ${item.runId}`,
563
+ "Source: async",
564
+ `State: ${item.state}`,
565
+ `Mode: ${item.run.mode}${contextModeLabel(item.run.context) ? ` ${contextModeLabel(item.run.context)}` : ""}`,
566
+ item.index !== undefined ? `Child: ${item.index} (${item.agent})${contextModeLabel(item.step?.context) ? ` ${contextModeLabel(item.step?.context)}` : ""}` : `Agent: ${item.agent}${contextModeLabel(item.run.context) ? ` ${contextModeLabel(item.run.context)}` : ""}`,
567
+ outputPath ? `Output: ${outputPath}` : undefined,
568
+ item.step?.sessionFile ? `Session: ${item.step.sessionFile}` : item.run.sessionFile ? `Session: ${item.run.sessionFile}` : undefined,
569
+ "",
570
+ "Transcript",
571
+ "(status is no longer available)",
572
+ ].filter((line): line is string => line !== undefined);
573
+ }
574
+
575
+ function externalDetail(item: Extract<FleetItem, { kind: "external" }>): string[] {
576
+ return [
577
+ `Run: ${item.runId}`,
578
+ "Source: external · display-only",
579
+ `Owner: ${item.run.source}`,
580
+ `State: ${item.state}`,
581
+ `Started: ${new Date(item.run.startedAt).toISOString()}`,
582
+ item.run.updatedAt !== undefined ? `Updated: ${new Date(item.run.updatedAt).toISOString()}` : undefined,
583
+ item.run.endedAt !== undefined ? `Ended: ${new Date(item.run.endedAt).toISOString()}` : undefined,
584
+ `Elapsed: ${formatDuration(Math.max(0, externalElapsedEnd(item.run) - item.run.startedAt))}`,
585
+ item.run.currentAction ? `Current action: ${item.run.currentAction}` : undefined,
586
+ item.run.reportPath ? `Report path: ${item.run.reportPath}` : undefined,
587
+ item.run.transcriptPath ? `Transcript path: ${item.run.transcriptPath}` : undefined,
588
+ "",
589
+ "Preview",
590
+ item.run.preview ?? "(no preview supplied)",
591
+ "",
592
+ "The owning extension controls execution, persistence, cancellation, and results.",
593
+ ].filter((line): line is string => line !== undefined);
594
+ }
595
+
596
+ function detailLines(item: FleetItem | undefined, error: string | undefined, state: SubagentState): string[] {
597
+ if (!item) return [error ? `Fleet scan failed: ${error}` : "No current-session Fleet jobs.", "", "New jobs appear here automatically while this inspector remains open."];
598
+ const lines = item.kind === "foreground-active"
599
+ ? foregroundActiveDetail(item, state)
600
+ : item.kind === "foreground-recent"
601
+ ? foregroundRecentDetail(item, state)
602
+ : item.kind === "external"
603
+ ? externalDetail(item)
604
+ : asyncDetail(item, state);
605
+ if (error) lines.unshift(`Fleet scan warning: ${error}`, "");
606
+ return lines;
607
+ }
608
+
609
+ function isActionableAsyncState(state: string): boolean {
610
+ return state === "running" || state === "queued" || state === "pending";
611
+ }
612
+
613
+ function firstToolResultText(result: AgentToolResult<Details> | null, fallback: string): FleetActionResult {
614
+ if (!result) return { text: fallback, isError: true };
615
+ const text = result.content.find((item) => item.type === "text")?.text ?? fallback;
616
+ return { text, ...(result.isError ? { isError: true } : {}) };
617
+ }
618
+
619
+ function uniquePaths(values: Array<string | undefined>): string[] {
620
+ return [...new Set(values.filter((value): value is string => Boolean(value)).map((value) => path.resolve(value)))];
621
+ }
622
+
623
+ function fleetArtifactsRoot(state: SubagentState, cwd: string): string {
624
+ return getArtifactsDir(
625
+ state.parentSessionFile ?? null,
626
+ cwd,
627
+ state.artifactDirPreference,
628
+ );
629
+ }
630
+
631
+ function transcriptTarget(item: FleetItem, state: SubagentState): { path: string; trustedRoots: string[] } | undefined {
632
+ if (item.kind === "external") return undefined;
633
+ if (item.kind === "foreground-active") {
634
+ const artifactsRoot = fleetArtifactsRoot(state, item.control.cwd ?? state.baseCwd);
635
+ return {
636
+ path: getArtifactPaths(artifactsRoot, item.runId, item.agent, item.index ?? 0).transcriptPath,
637
+ trustedRoots: [artifactsRoot],
638
+ };
639
+ }
640
+ if (item.kind === "foreground-recent") {
641
+ if (!item.child.transcriptPath) return undefined;
642
+ const transcriptPath = path.isAbsolute(item.child.transcriptPath)
643
+ ? item.child.transcriptPath
644
+ : path.resolve(item.run.cwd, item.child.transcriptPath);
645
+ return {
646
+ path: transcriptPath,
647
+ trustedRoots: uniquePaths([
648
+ fleetArtifactsRoot(state, item.run.cwd),
649
+ fleetArtifactsRoot(state, state.baseCwd),
650
+ ]),
651
+ };
652
+ }
653
+ const step = item.step ?? (item.run.steps.length === 1 ? item.run.steps[0] : undefined);
654
+ if (!step?.transcriptPath) return undefined;
655
+ const transcriptPath = path.isAbsolute(step.transcriptPath)
656
+ ? step.transcriptPath
657
+ : path.resolve(item.run.asyncDir, step.transcriptPath);
658
+ const trackedJob = state.fleetJobs?.get(item.runId) ?? state.asyncJobs.get(item.runId);
659
+ return {
660
+ path: transcriptPath,
661
+ trustedRoots: uniquePaths([
662
+ item.run.asyncDir,
663
+ fleetArtifactsRoot(state, state.baseCwd),
664
+ trackedJob?.cwd ? fleetArtifactsRoot(state, trackedJob.cwd) : undefined,
665
+ item.run.sessionFile ? getArtifactsDir(item.run.sessionFile, item.run.cwd ?? state.baseCwd, state.artifactDirPreference) : undefined,
666
+ ]),
667
+ };
668
+ }
669
+
670
+ function itemContext(item: FleetItem): string | undefined {
671
+ if (item.kind === "async") return contextModeLabel(item.step?.context ?? item.run.context);
672
+ if (item.kind === "foreground-recent") return contextModeLabel(item.child.context);
673
+ return undefined;
674
+ }
675
+
676
+ function itemMode(item: FleetItem): string {
677
+ if (item.kind === "external") return "display-only";
678
+ return item.kind === "foreground-active" ? item.control.mode : item.run.mode;
679
+ }
680
+
681
+ function itemSource(item: FleetItem): string {
682
+ if (item.kind === "external") return `external · ${item.run.source}`;
683
+ if (item.kind === "async") return "background";
684
+ return item.kind === "foreground-active" ? "foreground · live" : "foreground · recent";
685
+ }
686
+
687
+ function itemStats(item: FleetItem): string[] {
688
+ let model: string | undefined;
689
+ let tokens: number | undefined;
690
+ let tools: number | undefined;
691
+ let durationMs: number | undefined;
692
+ if (item.kind === "foreground-active") {
693
+ const live = item.activeChild ?? item.control;
694
+ model = formatModelThinking(live.model, live.thinking) || undefined;
695
+ tokens = live.tokens;
696
+ tools = live.toolCount;
697
+ durationMs = Math.max(0, Date.now() - live.startedAt);
698
+ } else if (item.kind === "foreground-recent") {
699
+ model = formatModelThinking(item.child.model, item.child.thinking) || undefined;
700
+ tokens = item.child.tokens;
701
+ tools = item.child.toolCount;
702
+ } else if (item.kind === "external") {
703
+ durationMs = Math.max(0, externalElapsedEnd(item.run) - item.run.startedAt);
704
+ } else {
705
+ model = formatModelThinking(item.step?.model, item.step?.thinking) || undefined;
706
+ tokens = item.step?.tokens?.total ?? (item.index === undefined ? item.run.totalTokens?.total : undefined);
707
+ tools = item.step?.toolCount ?? (item.index === undefined ? item.run.toolCount : undefined);
708
+ const terminalRun = item.state !== "queued" && item.state !== "running" && item.state !== "pending";
709
+ const endTime = item.run.endedAt ?? (terminalRun ? item.run.lastUpdate : undefined) ?? Date.now();
710
+ durationMs = item.step?.durationMs ?? Math.max(0, endTime - item.run.startedAt);
711
+ }
712
+ return [
713
+ model,
714
+ tokens !== undefined ? `${formatTokens(tokens)} tok` : undefined,
715
+ tools !== undefined ? `${tools} tool${tools === 1 ? "" : "s"}` : undefined,
716
+ durationMs !== undefined ? formatDuration(durationMs) : undefined,
717
+ ].filter((value): value is string => Boolean(value));
718
+ }
719
+
720
+ function structuredHeader(item: FleetItem, width: number, theme: Theme, conversationState: string, promptSummary?: string): string[] {
721
+ const lines: string[] = [];
722
+ lines.push(rightAligned(` ${statusGlyph(item, theme)} ${theme.bold(item.agent)}`, theme.fg("dim", item.state), width));
723
+ const child = "index" in item && item.index !== undefined ? ` · child ${item.index + 1}` : "";
724
+ const context = itemContext(item);
725
+ const identity = `${itemSource(item)} · ${item.runId.slice(0, 8)}${child} · ${itemMode(item)}${context ? ` ${context}` : ""}`;
726
+ lines.push(` ${theme.fg("dim", identity)}`);
727
+ const stats = itemStats(item);
728
+ if (stats.length) lines.push(` ${theme.fg("muted", stats.join(" · "))}`);
729
+ if (promptSummary) lines.push(` ${theme.fg("muted", `Task: ${promptSummary}`)}`);
730
+ lines.push(`${theme.fg("accent", "Conversation")} ${theme.fg("dim", `· ${conversationState}`)}`);
731
+ return lines.map((line) => truncateToWidth(line, width));
732
+ }
733
+
734
+ function fit(text: string, width: number): string {
735
+ const clipped = truncateToWidth(text, Math.max(0, width));
736
+ return clipped + " ".repeat(Math.max(0, width - visibleWidth(clipped)));
737
+ }
738
+
739
+ function rightAligned(left: string, right: string, width: number): string {
740
+ const rightWidth = visibleWidth(right);
741
+ const leftWidth = Math.max(0, width - rightWidth - 1);
742
+ return fit(left, leftWidth) + " ".repeat(Math.max(1, width - leftWidth - rightWidth)) + fit(right, rightWidth);
743
+ }
744
+
745
+ interface FleetDetailSections {
746
+ header: string[];
747
+ body: string[];
748
+ }
749
+
750
+ interface FleetTranscriptCache {
751
+ path: string;
752
+ fingerprint: string;
753
+ width: number;
754
+ expandedTools: boolean;
755
+ transcript: FleetTranscript;
756
+ body: string[];
757
+ }
758
+
759
+ function transcriptFingerprint(filePath: string): string {
760
+ try {
761
+ const stat = fs.statSync(filePath);
762
+ return `${stat.size}:${stat.mtimeMs}`;
763
+ } catch {
764
+ return "missing";
765
+ }
766
+ }
767
+
768
+ export class SubagentFleetComponent implements Component {
769
+ private snapshot: FleetSnapshot = { items: [] };
770
+ private selected = 0;
771
+ private selectedKey: string | undefined;
772
+ private detailScroll = 0;
773
+ private detailAutoFollow = true;
774
+ private detailLineCount = 0;
775
+ private detailViewportHeight = 8;
776
+ private bodyHeight = 8;
777
+ private expandedTools = false;
778
+ private promptAuditOpen = false;
779
+ private promptAuditView: PromptAuditView = "authored";
780
+ private actionNotice: FleetActionResult | undefined;
781
+ private steerDraft: string | undefined;
782
+ private redoGuidanceDraft: string | undefined;
783
+ private steerMode: SteerDeliveryMode = "steer";
784
+ private stopConfirming = false;
785
+ private actionBusy = false;
786
+ private transcriptCache: FleetTranscriptCache | undefined;
787
+ private disposed = false;
788
+ private refreshTimer: ReturnType<typeof setTimeout> | undefined;
789
+ private readonly refreshMs: number;
790
+ private readonly tui: FleetTui;
791
+ private readonly theme: Theme;
792
+ private readonly markdownTheme: MarkdownTheme;
793
+ private readonly state: SubagentState;
794
+ private readonly done: (result: undefined) => void;
795
+ private readonly options: FleetViewOptions;
796
+ private readonly keybindings: ResolvedFleetKeybindings;
797
+
798
+ constructor(
799
+ tui: FleetTui,
800
+ theme: Theme,
801
+ state: SubagentState,
802
+ done: (result: undefined) => void,
803
+ options: FleetViewOptions = {},
804
+ ) {
805
+ this.tui = tui;
806
+ this.theme = theme;
807
+ this.markdownTheme = options.markdownTheme ?? getMarkdownTheme();
808
+ this.state = state;
809
+ this.done = done;
810
+ this.options = options;
811
+ this.keybindings = resolveFleetKeybindings(options.fleetKeybindings);
812
+ this.refreshMs = Math.max(MIN_REFRESH_MS, options.refreshMs ?? REFRESH_MS);
813
+ this.selectedKey = options.initialKey;
814
+ this.refresh();
815
+ this.scheduleRefresh();
816
+ }
817
+
818
+ private scheduleRefresh(): void {
819
+ if (this.disposed || this.refreshTimer) return;
820
+ this.refreshTimer = setTimeout(() => {
821
+ this.refreshTimer = undefined;
822
+ if (this.disposed) return;
823
+ try {
824
+ this.invalidate();
825
+ this.tui.requestRender();
826
+ } finally {
827
+ this.scheduleRefresh();
828
+ }
829
+ }, this.refreshMs);
830
+ this.refreshTimer.unref?.();
831
+ }
832
+
833
+ private stopRefresh(): void {
834
+ this.disposed = true;
835
+ if (this.refreshTimer) clearTimeout(this.refreshTimer);
836
+ this.refreshTimer = undefined;
837
+ }
838
+
839
+ private refresh(): void {
840
+ const previousKey = this.snapshot.items[this.selected]?.key ?? this.selectedKey;
841
+ this.snapshot = collectFleetSnapshot(this.state, this.options);
842
+ let preserved = previousKey ? this.snapshot.items.findIndex((item) => item.key === previousKey) : -1;
843
+ if (preserved < 0 && previousKey) {
844
+ const parentKey = visibleWorkflowParentKeyForForegroundKey(this.state, previousKey, this.snapshot.items);
845
+ if (parentKey) preserved = this.snapshot.items.findIndex((item) => item.key === parentKey);
846
+ }
847
+ this.selected = preserved >= 0 ? preserved : Math.min(this.selected, Math.max(0, this.snapshot.items.length - 1));
848
+ this.selectedKey = this.snapshot.items[this.selected]?.key;
849
+ }
850
+
851
+ private moveSelection(delta: number): void {
852
+ if (this.snapshot.items.length === 0) return;
853
+ this.selected = Math.max(0, Math.min(this.snapshot.items.length - 1, this.selected + delta));
854
+ this.selectedKey = this.snapshot.items[this.selected]?.key;
855
+ this.detailAutoFollow = true;
856
+ this.resetActionInput();
857
+ this.tui.requestRender();
858
+ }
859
+
860
+ private selectedPromptAudit(): LivePromptAudit | undefined {
861
+ const item = this.snapshot.items[this.selected];
862
+ if (item?.kind !== "foreground-active") return undefined;
863
+ if (!this.state.currentSessionId || item.control.sessionId !== this.state.currentSessionId) return undefined;
864
+ return getLivePromptAudit(item.control, item.index ?? 0);
865
+ }
866
+
867
+ private promptAuditItems(): Array<{ item: Extract<FleetItem, { kind: "foreground-active" }>; prompt: LivePromptAudit }> {
868
+ const selected = this.snapshot.items[this.selected];
869
+ if (selected?.kind !== "foreground-active" || !this.state.currentSessionId || selected.control.sessionId !== this.state.currentSessionId) return [];
870
+ return this.snapshot.items.flatMap((item) => {
871
+ if (item.kind !== "foreground-active" || item.control !== selected.control) return [];
872
+ const prompt = getLivePromptAudit(item.control, item.index ?? 0);
873
+ return prompt ? [{ item, prompt }] : [];
874
+ });
875
+ }
876
+
877
+ private selectedPromptText(): string | undefined {
878
+ const prompt = this.selectedPromptAudit();
879
+ return prompt ? promptAuditText(prompt, this.promptAuditView) : undefined;
880
+ }
881
+
882
+ private movePromptSelection(delta: number): void {
883
+ const items = this.promptAuditItems();
884
+ if (items.length === 0) return;
885
+ const currentKey = this.snapshot.items[this.selected]?.key;
886
+ const current = Math.max(0, items.findIndex(({ item }) => item.key === currentKey));
887
+ const target = items[Math.max(0, Math.min(items.length - 1, current + delta))]?.item;
888
+ if (!target) return;
889
+ this.selected = this.snapshot.items.findIndex((item) => item.key === target.key);
890
+ this.selectedKey = target.key;
891
+ this.detailScroll = 0;
892
+ this.detailAutoFollow = false;
893
+ this.tui.requestRender();
894
+ }
895
+
896
+ private resetActionInput(): void {
897
+ this.steerDraft = undefined;
898
+ this.redoGuidanceDraft = undefined;
899
+ this.steerMode = "steer";
900
+ this.stopConfirming = false;
901
+ }
902
+
903
+ private selectedAsyncAction(): { item: Extract<FleetItem, { kind: "async" }> } | { reason: string } {
904
+ const item = this.snapshot.items[this.selected];
905
+ if (!item) return { reason: "No child is selected." };
906
+ if (item.kind === "external") return { reason: "External jobs are display-only and remain controlled by their owning extension." };
907
+ if (item.kind !== "async") return { reason: "Fleet controls are available for current-session top-level async runs only." };
908
+ if (!isActionableAsyncState(item.run.state) || !isActionableAsyncState(item.state)) return { reason: `Selected child is ${item.state}; controls require a running or queued async child.` };
909
+ return { item };
910
+ }
911
+
912
+ private selectedSteerAction(): { runId: string; asyncDir: string; index?: number } | { reason: string } {
913
+ const item = this.snapshot.items[this.selected];
914
+ if (item?.kind === "foreground-active" && item.control.parentWorkflowRunId) {
915
+ const parent = this.state.asyncJobs.get(item.control.parentWorkflowRunId) ?? this.state.fleetJobs?.get(item.control.parentWorkflowRunId);
916
+ if (!parent || !isActionableAsyncState(parent.status)) return { reason: "The parent workflow is no longer available for steering." };
917
+ return { runId: item.runId, asyncDir: parent.asyncDir, ...(item.index !== undefined ? { index: item.index } : {}) };
918
+ }
919
+ const target = this.selectedAsyncAction();
920
+ if ("reason" in target) return target;
921
+ return { runId: target.item.runId, asyncDir: target.item.run.asyncDir, ...(target.item.index !== undefined ? { index: target.item.index } : {}) };
922
+ }
923
+
924
+ private selectedHerdrInspectAction(): { runId: string; asyncDir: string; index?: number } | { reason: string } {
925
+ const item = this.snapshot.items[this.selected];
926
+ if (!item) return { reason: "No child is selected." };
927
+ if (item.kind === "external") return { reason: "External jobs are display-only and have no Herdr controls." };
928
+ if (item.kind === "async") {
929
+ if (!isActionableAsyncState(item.run.state) || !isActionableAsyncState(item.state)) return { reason: `Selected child is ${item.state}; controls require a running or queued async child.` };
930
+ return { runId: item.runId, asyncDir: item.run.asyncDir, ...(item.index !== undefined ? { index: item.index } : {}) };
931
+ }
932
+ if (item.kind !== "foreground-active" || !item.control.parentWorkflowRunId) return { reason: "Fleet controls are available for current-session top-level async runs only." };
933
+ const parent = this.state.asyncJobs.get(item.control.parentWorkflowRunId) ?? this.state.fleetJobs?.get(item.control.parentWorkflowRunId);
934
+ if (!parent || !isActionableAsyncState(parent.status)) return { reason: "The parent workflow is no longer available for Herdr inspection." };
935
+ return { runId: parent.asyncId, asyncDir: parent.asyncDir };
936
+ }
937
+
938
+ private actionLines(): string[] {
939
+ const lines: string[] = [];
940
+ if (this.actionBusy) lines.push(this.theme.fg("accent", "Action pending..."));
941
+ if (this.steerDraft !== undefined) {
942
+ lines.push(this.theme.fg("accent", `Steer message (${this.steerMode}): ${this.steerDraft}${this.theme.fg("dim", "▌")}`));
943
+ lines.push(this.theme.fg("dim", "Enter sends · Tab changes mode · Esc cancels · Backspace edits"));
944
+ } else if (this.redoGuidanceDraft !== undefined) {
945
+ lines.push(this.theme.fg("accent", `Redo guidance: ${this.redoGuidanceDraft}${this.theme.fg("dim", "▌")}`));
946
+ lines.push(this.theme.fg("dim", "Enter rewrites and reruns · Esc cancels · Backspace edits"));
947
+ } else if (this.stopConfirming) {
948
+ const selected = this.snapshot.items[this.selected];
949
+ lines.push(this.theme.fg("warning", `Confirm stop for async run ${selected?.runId ?? "selected run"}?`));
950
+ lines.push(this.theme.fg("dim", "Stop ends the run; use interrupt for a resumable pause. Enter/Y confirms · N returns · Esc cancels"));
951
+ } else if (this.actionNotice) {
952
+ lines.push(this.theme.fg(this.actionNotice.isError ? "error" : "success", this.actionNotice.text));
953
+ }
954
+ return lines;
955
+ }
956
+
957
+ private withActionLines(body: string[]): string[] {
958
+ const actionLines = this.actionLines();
959
+ return actionLines.length ? [...actionLines, "", ...body] : body;
960
+ }
961
+
962
+ private setActionNotice(result: FleetActionResult): void {
963
+ this.actionNotice = result;
964
+ this.resetActionInput();
965
+ this.detailAutoFollow = false;
966
+ this.detailScroll = 0;
967
+ this.refresh();
968
+ this.tui.requestRender();
969
+ }
970
+
971
+ private runAction(action: () => Promise<FleetActionResult>): void {
972
+ if (this.actionBusy) return;
973
+ this.actionBusy = true;
974
+ this.actionNotice = undefined;
975
+ this.tui.requestRender();
976
+ void action()
977
+ .then((result) => this.setActionNotice(result))
978
+ .catch((error) => this.setActionNotice({ text: error instanceof Error ? error.message : String(error), isError: true }))
979
+ .finally(() => {
980
+ this.actionBusy = false;
981
+ if (!this.disposed) this.tui.requestRender();
982
+ });
983
+ }
984
+
985
+ private scrollDetail(delta: number): void {
986
+ const maxScroll = Math.max(0, this.detailLineCount - this.detailViewportHeight);
987
+ this.detailScroll = Math.max(0, Math.min(maxScroll, this.detailScroll + delta));
988
+ this.detailAutoFollow = this.detailScroll >= maxScroll;
989
+ this.tui.requestRender();
990
+ }
991
+
992
+ handleInput(data: string): void {
993
+ if (this.promptAuditOpen && this.redoGuidanceDraft !== undefined) {
994
+ if (matchesKey(data, "escape") || matchesKey(data, "ctrl+c")) {
995
+ this.resetActionInput();
996
+ this.tui.requestRender();
997
+ return;
998
+ }
999
+ if (matchesKey(data, "return") || data === "\r" || data === "\n") {
1000
+ const guidance = this.redoGuidanceDraft.trim();
1001
+ if (!guidance) {
1002
+ this.setActionNotice({ text: "Redo guidance cannot be empty.", isError: true });
1003
+ return;
1004
+ }
1005
+ const selected = this.snapshot.items[this.selected];
1006
+ if (selected?.kind !== "foreground-active" || !this.options.actions?.redoPrompt) {
1007
+ this.setActionNotice({ text: "Redo is unavailable for this prompt.", isError: true });
1008
+ return;
1009
+ }
1010
+ this.runAction(() => this.options.actions!.redoPrompt!({ runId: selected.runId, index: selected.index ?? 0, guidance, control: selected.control }));
1011
+ return;
1012
+ }
1013
+ if (matchesKey(data, "backspace") || data === "\x7f") {
1014
+ this.redoGuidanceDraft = this.redoGuidanceDraft.slice(0, -1);
1015
+ this.tui.requestRender();
1016
+ return;
1017
+ }
1018
+ if (data.length === 1 && data >= " " && data !== "\x7f") {
1019
+ this.redoGuidanceDraft += data;
1020
+ this.tui.requestRender();
1021
+ }
1022
+ return;
1023
+ }
1024
+ if (this.promptAuditOpen) {
1025
+ if (matchesKey(data, "escape") || matchesKey(data, "ctrl+c")) {
1026
+ this.promptAuditOpen = false;
1027
+ this.detailAutoFollow = true;
1028
+ this.tui.requestRender();
1029
+ return;
1030
+ }
1031
+ if (data === "j") return this.movePromptSelection(1);
1032
+ if (data === "k") return this.movePromptSelection(-1);
1033
+ if (data === "1" || data === "2" || data === "3") {
1034
+ this.promptAuditView = data === "1" ? "authored" : data === "2" ? "runtime" : "effective";
1035
+ this.detailScroll = 0;
1036
+ this.tui.requestRender();
1037
+ return;
1038
+ }
1039
+ if (data === "g") {
1040
+ const prompt = this.selectedPromptAudit();
1041
+ if (!prompt) this.setActionNotice({ text: "Prompt Audit is available only for a live child owned by this session.", isError: true });
1042
+ else if (!prompt.rerun) this.setActionNotice({ text: "Redo is not safe for this prompt in this slice.", isError: true });
1043
+ else if (!this.options.actions?.redoPrompt) this.setActionNotice({ text: "Redo controls are unavailable in this context.", isError: true });
1044
+ else {
1045
+ this.actionNotice = undefined;
1046
+ this.redoGuidanceDraft = "";
1047
+ this.detailAutoFollow = false;
1048
+ this.detailScroll = 0;
1049
+ this.tui.requestRender();
1050
+ }
1051
+ return;
1052
+ }
1053
+ if (data === "c") {
1054
+ const text = this.selectedPromptText();
1055
+ if (!text) this.setActionNotice({ text: "No prompt view is available to copy.", isError: true });
1056
+ else if (!this.options.copyText) this.setActionNotice({ text: "Clipboard is unavailable in this context.", isError: true });
1057
+ else this.runAction(async () => {
1058
+ await this.options.copyText!(text);
1059
+ return { text: "Copied visible prompt view." };
1060
+ });
1061
+ return;
1062
+ }
1063
+ if (matchesFleetAction(data, this.keybindings, "scrollUp")) return this.scrollDetail(-1);
1064
+ if (matchesFleetAction(data, this.keybindings, "scrollDown")) return this.scrollDetail(1);
1065
+ if (matchesFleetAction(data, this.keybindings, "pageUp")) return this.scrollDetail(-this.detailViewportHeight);
1066
+ if (matchesFleetAction(data, this.keybindings, "pageDown")) return this.scrollDetail(this.detailViewportHeight);
1067
+ return;
1068
+ }
1069
+ if (this.steerDraft !== undefined) {
1070
+ if (matchesKey(data, "escape") || matchesKey(data, "ctrl+c")) {
1071
+ this.resetActionInput();
1072
+ this.tui.requestRender();
1073
+ return;
1074
+ }
1075
+ if (matchesKey(data, "return") || data === "\r" || data === "\n") {
1076
+ const message = this.steerDraft.trim();
1077
+ if (!message) {
1078
+ this.setActionNotice({ text: "Steer message cannot be empty.", isError: true });
1079
+ return;
1080
+ }
1081
+ const target = this.selectedSteerAction();
1082
+ if ("reason" in target || !this.options.actions) {
1083
+ this.setActionNotice({ text: "reason" in target ? target.reason : "Fleet controls are unavailable in this context.", isError: true });
1084
+ return;
1085
+ }
1086
+ this.runAction(() => this.options.actions!.steer({ ...target, message, mode: this.steerMode }));
1087
+ return;
1088
+ }
1089
+ if (matchesKey(data, "tab") || data === "\t") {
1090
+ const modes: SteerDeliveryMode[] = ["steer", "follow_up", "auto"];
1091
+ this.steerMode = modes[(modes.indexOf(this.steerMode) + 1) % modes.length]!;
1092
+ this.tui.requestRender();
1093
+ return;
1094
+ }
1095
+ if (matchesKey(data, "backspace") || data === "\x7f") {
1096
+ this.steerDraft = this.steerDraft.slice(0, -1);
1097
+ this.tui.requestRender();
1098
+ return;
1099
+ }
1100
+ if (data.length === 1 && data >= " " && data !== "\x7f") {
1101
+ this.steerDraft += data;
1102
+ this.tui.requestRender();
1103
+ }
1104
+ return;
1105
+ }
1106
+ if (this.stopConfirming) {
1107
+ if (matchesKey(data, "return") || data.toLowerCase() === "y") {
1108
+ const target = this.selectedAsyncAction();
1109
+ if ("reason" in target || !this.options.actions) {
1110
+ this.setActionNotice({ text: "reason" in target ? target.reason : "Fleet controls are unavailable in this context.", isError: true });
1111
+ return;
1112
+ }
1113
+ this.runAction(() => Promise.resolve(this.options.actions!.stop({ runId: target.item.runId, asyncDir: target.item.run.asyncDir, ...(target.item.index !== undefined ? { index: target.item.index } : {}) })));
1114
+ return;
1115
+ }
1116
+ if (matchesKey(data, "escape") || matchesKey(data, "ctrl+c") || data.toLowerCase() === "n" || matchesKey(data, "backspace")) {
1117
+ this.resetActionInput();
1118
+ this.tui.requestRender();
1119
+ }
1120
+ return;
1121
+ }
1122
+ if (matchesFleetAction(data, this.keybindings, "close")) {
1123
+ this.stopRefresh();
1124
+ this.done(undefined);
1125
+ return;
1126
+ }
1127
+ if (matchesFleetAction(data, this.keybindings, "scrollUp")) return this.scrollDetail(-1);
1128
+ if (matchesFleetAction(data, this.keybindings, "scrollDown")) return this.scrollDetail(1);
1129
+ if (matchesFleetAction(data, this.keybindings, "selectUp")) return this.moveSelection(-1);
1130
+ if (matchesFleetAction(data, this.keybindings, "selectDown")) return this.moveSelection(1);
1131
+ if (matchesFleetAction(data, this.keybindings, "selectFirst")) return this.moveSelection(-this.snapshot.items.length);
1132
+ if (matchesFleetAction(data, this.keybindings, "selectLast")) return this.moveSelection(this.snapshot.items.length);
1133
+ if (matchesFleetAction(data, this.keybindings, "pageUp")) return this.scrollDetail(-this.detailViewportHeight);
1134
+ if (matchesFleetAction(data, this.keybindings, "pageDown")) return this.scrollDetail(this.detailViewportHeight);
1135
+ if (matchesFleetAction(data, this.keybindings, "refresh")) {
1136
+ this.transcriptCache = undefined;
1137
+ this.refresh();
1138
+ this.tui.requestRender();
1139
+ return;
1140
+ }
1141
+ if (data === "p") {
1142
+ if (!this.selectedPromptAudit()) this.setActionNotice({ text: "Prompt Audit is available only for a live child owned by this session.", isError: true });
1143
+ else {
1144
+ this.promptAuditOpen = true;
1145
+ this.promptAuditView = "authored";
1146
+ this.detailScroll = 0;
1147
+ this.detailAutoFollow = false;
1148
+ this.actionNotice = undefined;
1149
+ this.tui.requestRender();
1150
+ }
1151
+ return;
1152
+ }
1153
+ if (matchesFleetAction(data, this.keybindings, "steer")) {
1154
+ const target = this.selectedSteerAction();
1155
+ if ("reason" in target || !this.options.actions) this.setActionNotice({ text: "reason" in target ? target.reason : "Fleet controls are unavailable in this context.", isError: true });
1156
+ else {
1157
+ this.actionNotice = undefined;
1158
+ this.steerDraft = "";
1159
+ this.detailAutoFollow = false;
1160
+ this.detailScroll = 0;
1161
+ this.tui.requestRender();
1162
+ }
1163
+ return;
1164
+ }
1165
+ if (matchesFleetAction(data, this.keybindings, "inspect")) {
1166
+ const target = this.selectedHerdrInspectAction();
1167
+ if ("reason" in target || !this.options.actions?.inspect) this.setActionNotice({ text: "reason" in target ? target.reason : "Herdr inspector controls are unavailable in this context.", isError: true });
1168
+ else this.runAction(() => this.options.actions!.inspect!(target));
1169
+ return;
1170
+ }
1171
+ if (matchesFleetAction(data, this.keybindings, "stop")) {
1172
+ const target = this.selectedAsyncAction();
1173
+ if ("reason" in target || !this.options.actions) this.setActionNotice({ text: "reason" in target ? target.reason : "Fleet controls are unavailable in this context.", isError: true });
1174
+ else {
1175
+ this.actionNotice = undefined;
1176
+ this.stopConfirming = true;
1177
+ this.detailAutoFollow = false;
1178
+ this.detailScroll = 0;
1179
+ this.tui.requestRender();
1180
+ }
1181
+ return;
1182
+ }
1183
+ if (matchesFleetAction(data, this.keybindings, "toggleTools")) {
1184
+ this.expandedTools = !this.expandedTools;
1185
+ this.transcriptCache = undefined;
1186
+ this.tui.requestRender();
1187
+ }
1188
+ }
1189
+
1190
+ private rosterLines(width: number): string[] {
1191
+ if (this.snapshot.items.length === 0) return [this.theme.fg("dim", "No tracked children")];
1192
+ const start = Math.max(0, Math.min(this.selected - this.bodyHeight + 1, Math.max(0, this.snapshot.items.length - this.bodyHeight)));
1193
+ return this.snapshot.items.slice(start, start + this.bodyHeight).map((item, offset) => {
1194
+ const index = start + offset;
1195
+ const marker = index === this.selected ? this.theme.fg("accent", "›") : " ";
1196
+ const context = item.kind === "async" ? contextModeBadge(this.theme, item.step?.context ?? item.run.context) : item.kind === "foreground-recent" ? contextModeBadge(this.theme, item.child.context) : "";
1197
+ const agent = index === this.selected ? this.theme.bold(item.agent) : item.agent;
1198
+ const identity = item.runId.slice(0, 8);
1199
+ const left = `${marker} ${statusGlyph(item, this.theme)} ${agent}${context} ${this.theme.fg("dim", `· ${identity}`)}`;
1200
+ return rightAligned(left, this.theme.fg("dim", item.state), width);
1201
+ });
1202
+ }
1203
+
1204
+ private renderedTranscript(target: { path: string; trustedRoots: string[] }, width: number): { transcript: FleetTranscript; body: string[] } {
1205
+ const fingerprint = `${target.trustedRoots.join("\0")}|${transcriptFingerprint(target.path)}`;
1206
+ if (this.transcriptCache
1207
+ && this.transcriptCache.path === target.path
1208
+ && this.transcriptCache.fingerprint === fingerprint
1209
+ && this.transcriptCache.width === width
1210
+ && this.transcriptCache.expandedTools === this.expandedTools) {
1211
+ return { transcript: this.transcriptCache.transcript, body: [...this.transcriptCache.body] };
1212
+ }
1213
+ const transcript = readFleetTranscript(target.path, { trustedRoots: target.trustedRoots });
1214
+ const body = transcript.events.length > 0
1215
+ ? renderFleetTranscript(transcript, width, this.theme, this.markdownTheme, { expandedTools: this.expandedTools })
1216
+ : [];
1217
+ this.transcriptCache = { path: target.path, fingerprint, width, expandedTools: this.expandedTools, transcript, body };
1218
+ return { transcript, body: [...body] };
1219
+ }
1220
+
1221
+ private promptAuditDetail(width: number): FleetDetailSections {
1222
+ const selected = this.snapshot.items[this.selected];
1223
+ const prompt = this.selectedPromptAudit();
1224
+ const items = this.promptAuditItems();
1225
+ const selectedPosition = selected ? items.findIndex(({ item }) => item.key === selected.key) : -1;
1226
+ const live = selected?.kind === "foreground-active" ? selected.activeChild ?? selected.control : undefined;
1227
+ const viewLabel = promptAuditViewLabel(this.promptAuditView);
1228
+ const promptText = this.selectedPromptText()
1229
+ ?? this.theme.fg("muted", "Selected prompt unavailable.");
1230
+ const raw = [
1231
+ this.theme.bold("Prompt Audit"),
1232
+ this.theme.fg("dim", "Retention: live memory only · no storage"),
1233
+ selected?.kind === "foreground-active" ? `Run: ${selected.runId}${selected.index !== undefined ? ` · Child: ${selected.index}` : ""} · Agent: ${selected.agent}` : "Selected prompt unavailable",
1234
+ live ? `Started: ${new Date(live.startedAt).toISOString()}` : undefined,
1235
+ live ? `Model: ${formatModelThinking(live.model, live.thinking) || "default"}` : undefined,
1236
+ prompt?.cwd ? `Cwd: ${prompt.cwd}` : undefined,
1237
+ prompt?.outputPath ? `Output: ${prompt.outputPath}` : undefined,
1238
+ this.theme.fg("dim", `Live children: ${items.map(({ item }) => item.agent).join(", ") || "none"}`),
1239
+ this.theme.fg("dim", selectedPosition >= 0 ? `Selected: ${selectedPosition + 1}/${items.length}` : "Selected prompt unavailable"),
1240
+ "",
1241
+ this.theme.fg("accent", viewLabel),
1242
+ promptText,
1243
+ ];
1244
+ const body = raw.filter((line): line is string => line !== undefined).flatMap((line) => wrapTextWithAnsi(line, Math.max(1, width)));
1245
+ return { header: [], body: this.withActionLines(body) };
1246
+ }
1247
+
1248
+ private wrappedDetail(width: number): FleetDetailSections {
1249
+ if (this.promptAuditOpen) return this.promptAuditDetail(width);
1250
+ const selected = this.snapshot.items[this.selected];
1251
+ let transcriptWarning: string | undefined;
1252
+ if (selected) {
1253
+ const target = transcriptTarget(selected, this.state);
1254
+ if (target) {
1255
+ const { transcript, body } = this.renderedTranscript(target, width);
1256
+ transcriptWarning = transcript.warning;
1257
+ if (transcript.events.length > 0) {
1258
+ if (this.snapshot.error) body.unshift(this.theme.fg("warning", `Fleet scan warning: ${this.snapshot.error}`), "");
1259
+ const latest = transcript.events.at(-1);
1260
+ const conversationState = latest?.kind === "assistant"
1261
+ ? "assistant response"
1262
+ : latest?.kind === "user"
1263
+ ? "supervisor message"
1264
+ : latest?.kind === "tool"
1265
+ ? `${latest.name} · ${latest.status}`
1266
+ : "activity";
1267
+ const promptSummary = selected.kind === "foreground-active" ? foregroundAuthoredPromptSummary(selected, this.state) : undefined;
1268
+ return { header: structuredHeader(selected, width, this.theme, conversationState, promptSummary), body: this.withActionLines(body) };
1269
+ }
1270
+ }
1271
+ }
1272
+
1273
+ const raw = detailLines(selected, this.snapshot.error, this.state);
1274
+ if (transcriptWarning) raw.unshift(`Transcript preview warning: ${transcriptWarning}`, "");
1275
+ const lines: string[] = [];
1276
+ for (const line of raw) {
1277
+ const styled = /^(Run|State|Mode|Source|Child|Agent|Model|Task):/.test(line)
1278
+ ? this.theme.bold(line)
1279
+ : /^(Transcript|Result transcript tail)/.test(line)
1280
+ ? this.theme.fg("accent", line)
1281
+ : /^(Output|Session|Transcript file|Artifacts):/.test(line)
1282
+ ? this.theme.fg("muted", line)
1283
+ : /^Transcript preview warning:/.test(line)
1284
+ ? this.theme.fg("warning", line)
1285
+ : line;
1286
+ const wrapped = wrapTextWithAnsi(styled, Math.max(1, width));
1287
+ lines.push(...(wrapped.length ? wrapped : [""]));
1288
+ }
1289
+ return { header: [], body: this.withActionLines(lines) };
1290
+ }
1291
+
1292
+ render(width: number): string[] {
1293
+ if (width < 36) return [truncateToWidth("Subagent fleet needs at least 36 columns. Esc closes.", width)];
1294
+ const innerWidth = width - 2;
1295
+ const rows = this.tui.terminal?.rows ?? 32;
1296
+ this.bodyHeight = Math.max(2, Math.floor(rows * 0.85) - 6);
1297
+ const rosterWidth = Math.max(22, Math.min(46, Math.floor((innerWidth - 1) * 0.38)));
1298
+ const detailWidth = Math.max(1, innerWidth - rosterWidth - 1);
1299
+ const roster = this.rosterLines(rosterWidth);
1300
+ const detail = this.wrappedDetail(detailWidth);
1301
+ const detailHeader = detail.header.slice(0, Math.max(0, this.bodyHeight - 1));
1302
+ this.detailViewportHeight = Math.max(1, this.bodyHeight - detailHeader.length);
1303
+ this.detailLineCount = detail.body.length;
1304
+ const maxDetailScroll = Math.max(0, detail.body.length - this.detailViewportHeight);
1305
+ if (this.detailAutoFollow) this.detailScroll = maxDetailScroll;
1306
+ else if (this.detailScroll > maxDetailScroll) this.detailScroll = maxDetailScroll;
1307
+ const visibleDetails = [
1308
+ ...detailHeader,
1309
+ ...detail.body.slice(this.detailScroll, this.detailScroll + this.detailViewportHeight),
1310
+ ];
1311
+ const lines = [this.theme.fg("border", `╭${"─".repeat(innerWidth)}╮`)];
1312
+ const selected = this.snapshot.items[this.selected];
1313
+ const title = selected?.kind === "external"
1314
+ ? ` ${this.theme.bold("Fleet inspector")} ${this.theme.fg("dim", "· external display-only")}`
1315
+ : ` ${this.theme.bold("Subagent fleet inspector")} ${this.theme.fg("dim", "· live controls")}`;
1316
+ const selectedStatus = selected
1317
+ ? `${statusGlyph(selected, this.theme)} ${selected.agent} · ${selected.state} `
1318
+ : this.theme.fg("dim", "no children ");
1319
+ lines.push(this.theme.fg("border", "│") + rightAligned(title, selectedStatus, innerWidth) + this.theme.fg("border", "│"));
1320
+ lines.push(this.theme.fg("border", `├${"─".repeat(rosterWidth)}┬${"─".repeat(detailWidth)}┤`));
1321
+ for (let index = 0; index < this.bodyHeight; index++) {
1322
+ lines.push(
1323
+ this.theme.fg("border", "│")
1324
+ + fit(roster[index] ?? "", rosterWidth)
1325
+ + this.theme.fg("border", "│")
1326
+ + fit(visibleDetails[index] ?? "", detailWidth)
1327
+ + this.theme.fg("border", "│"),
1328
+ );
1329
+ }
1330
+ lines.push(this.theme.fg("border", `├${"─".repeat(rosterWidth)}┴${"─".repeat(detailWidth)}┤`));
1331
+ const position = this.snapshot.items.length ? `${this.selected + 1}/${this.snapshot.items.length}` : "0/0";
1332
+ const footer = this.promptAuditOpen
1333
+ ? ` j/k child · 1/2/3 view · g redo with guidance · c copy · Esc close Prompt Audit · ${position}`
1334
+ : selected?.kind === "external"
1335
+ ? ` ${bindingLabel(this.keybindings, "selectUp")}/${bindingLabel(this.keybindings, "selectDown")} job · display-only · ${bindingLabel(this.keybindings, "refresh")} refresh · ${bindingLabel(this.keybindings, "close")} close · ${position}`
1336
+ : ` ${bindingLabel(this.keybindings, "selectUp")}/${bindingLabel(this.keybindings, "selectDown")} agent · p Prompt Audit · ${bindingLabel(this.keybindings, "inspect")} Herdr · ${bindingLabel(this.keybindings, "steer")} steer · ${bindingLabel(this.keybindings, "stop")} stop · ${bindingLabel(this.keybindings, "toggleTools")} tools · ${bindingLabel(this.keybindings, "refresh")} refresh · ${bindingLabel(this.keybindings, "close")} close · ${position}`;
1337
+ lines.push(this.theme.fg("border", "│") + fit(this.theme.fg("dim", footer), innerWidth) + this.theme.fg("border", "│"));
1338
+ lines.push(this.theme.fg("border", `╰${"─".repeat(innerWidth)}╯`));
1339
+ return lines.map((line) => truncateToWidth(line, width));
1340
+ }
1341
+
1342
+ invalidate(): void {
1343
+ this.transcriptCache = undefined;
1344
+ this.refresh();
1345
+ }
1346
+
1347
+ dispose(): void {
1348
+ this.stopRefresh();
1349
+ }
1350
+ }
1351
+
1352
+ export async function openSubagentFleet(ctx: ExtensionContext, state: SubagentState, options: FleetViewOptions = {}): Promise<void> {
1353
+ const wasOpen = state.fleetInspectorOpen === true;
1354
+ state.fleetInspectorOpen = true;
1355
+ if (typeof ctx.ui.setWidget === "function") ctx.ui.setWidget(FLEET_STATUS_WIDGET_KEY, undefined);
1356
+ const copyText = options.copyText ?? (async (text: string) => {
1357
+ const module = await import("@selesai/code");
1358
+ const copyToClipboard = (module as { copyToClipboard?: (value: string) => Promise<void> | void }).copyToClipboard;
1359
+ if (!copyToClipboard) throw new Error("Clipboard is unavailable in this Pi version.");
1360
+ await copyToClipboard(text);
1361
+ });
1362
+ const actions = options.actions ?? {
1363
+ steer: async (input: { runId: string; asyncDir: string; index?: number; message: string; mode: SteerDeliveryMode }) => {
1364
+ const status = readStatus(input.asyncDir);
1365
+ const liveWorkflowRunId = status?.mode === "workflow" && state.workflowControllers?.has(status.runId || input.runId)
1366
+ ? status.runId || input.runId
1367
+ : undefined;
1368
+ if (liveWorkflowRunId) {
1369
+ const route = state.foregroundControls.get(input.runId)?.parentWorkflowRunId === liveWorkflowRunId
1370
+ ? resolveWorkflowForegroundSteeringTarget({ state, childRunId: input.runId, asyncDirRoot: options.asyncDirRoot ?? DIRS.async })
1371
+ : resolveWorkflowForegroundSteeringTarget({ state, workflowRunId: liveWorkflowRunId, asyncDirRoot: options.asyncDirRoot ?? DIRS.async });
1372
+ if (!route.ok) return { text: route.message, isError: true };
1373
+ return firstToolResultText(await steerWorkflowForegroundTarget({ target: route.target, message: input.message, mode: input.mode, ...(input.index !== undefined ? { index: input.index } : {}) }), `Failed to steer foreground run ${input.runId}.`);
1374
+ }
1375
+ return firstToolResultText(await steerAsyncRun({
1376
+ state,
1377
+ runId: input.runId,
1378
+ ...(input.index !== undefined ? { index: input.index } : {}),
1379
+ message: input.message,
1380
+ mode: input.mode,
1381
+ location: { asyncDir: input.asyncDir, resolvedId: input.runId } as Parameters<typeof steerAsyncRun>[0]["location"],
1382
+ }), `Failed to steer async run ${input.runId}.`);
1383
+ },
1384
+ stop: (input: { runId: string; asyncDir: string; index?: number }) => firstToolResultText(stopAsyncRun(state, input.runId, undefined, { asyncDir: input.asyncDir, resolvedId: input.runId }), `Failed to stop async run ${input.runId}.`),
1385
+ inspect: async (input: { runId: string; asyncDir: string; index?: number }) => firstToolResultText(await handleHerdrInspectorAction("inspector.open", {
1386
+ id: input.runId,
1387
+ dir: input.asyncDir,
1388
+ focus: true,
1389
+ ...(input.index !== undefined ? { index: input.index } : {}),
1390
+ }, {
1391
+ state,
1392
+ sessionRoots: state.trustedSessionRoots,
1393
+ cwd: state.baseCwd,
1394
+ ...(options.herdrClient ? { client: options.herdrClient } : {}),
1395
+ ...(state.authorityPolicy ? { authorityPolicy: state.authorityPolicy } : {}),
1396
+ ...(state.missionStoreConfig ? { missions: state.missionStoreConfig } : {}),
1397
+ }), `Failed to open Herdr inspector for async run ${input.runId}.`),
1398
+ redoPrompt: async (input: { runId: string; index: number; guidance: string; control?: ForegroundRunControl }) => {
1399
+ const control = input.control ?? state.foregroundControls.get(input.runId);
1400
+ if (!control?.promptAuditRedo) return { text: "Redo is not available for this live child.", isError: true };
1401
+ return control.promptAuditRedo(input.index, input.guidance);
1402
+ },
1403
+ } satisfies FleetActionHandlers;
1404
+ try {
1405
+ await ctx.ui.custom<undefined>(
1406
+ (tui, theme, _keybindings, done) => new SubagentFleetComponent(tui, theme, state, done, { ...options, actions, copyText }),
1407
+ {
1408
+ overlay: true,
1409
+ overlayOptions: { anchor: "center", width: "95%", minWidth: 60, maxHeight: "85%", margin: 1 },
1410
+ },
1411
+ );
1412
+ } finally {
1413
+ state.fleetInspectorOpen = wasOpen;
1414
+ }
1415
+ }