@selesai/code 0.13.13 → 0.13.14

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 (1776) hide show
  1. package/dist/bun/cli.d.ts +2 -0
  2. package/dist/bun/cli.js +10 -0
  3. package/dist/bun/register-bedrock.d.ts +1 -0
  4. package/dist/bun/register-bedrock.js +3 -0
  5. package/dist/bun/restore-sandbox-env.d.ts +16 -0
  6. package/dist/bun/restore-sandbox-env.js +35 -0
  7. package/dist/cli/args.d.ts +59 -0
  8. package/dist/cli/args.js +428 -0
  9. package/dist/cli/args.test.d.ts +1 -0
  10. package/dist/cli/args.test.js +32 -0
  11. package/dist/cli/config-selector.d.ts +15 -0
  12. package/dist/cli/config-selector.js +30 -0
  13. package/dist/cli/credential-print.d.ts +22 -0
  14. package/dist/cli/credential-print.js +116 -0
  15. package/dist/cli/file-processor.d.ts +14 -0
  16. package/dist/cli/file-processor.js +69 -0
  17. package/dist/cli/initial-message.d.ts +17 -0
  18. package/dist/cli/initial-message.js +21 -0
  19. package/dist/cli/list-models.d.ts +8 -0
  20. package/dist/cli/list-models.js +97 -0
  21. package/dist/cli/project-trust.d.ts +9 -0
  22. package/dist/cli/project-trust.js +47 -0
  23. package/dist/cli/session-picker.d.ts +9 -0
  24. package/dist/cli/session-picker.js +35 -0
  25. package/dist/cli/startup-ui.d.ts +22 -0
  26. package/dist/cli/startup-ui.js +172 -0
  27. package/dist/cli.d.ts +2 -0
  28. package/dist/cli.js +17 -0
  29. package/dist/config.d.ts +181 -0
  30. package/dist/config.js +788 -0
  31. package/dist/core/agent-session-auto-handoff.test.d.ts +1 -0
  32. package/dist/core/agent-session-auto-handoff.test.js +183 -0
  33. package/dist/core/agent-session-length-continuation.test.d.ts +1 -0
  34. package/dist/core/agent-session-length-continuation.test.js +107 -0
  35. package/dist/core/agent-session-runtime.d.ts +118 -0
  36. package/dist/core/agent-session-runtime.js +305 -0
  37. package/dist/core/agent-session-services.d.ts +84 -0
  38. package/dist/core/agent-session-services.js +132 -0
  39. package/dist/core/agent-session-skill-block.test.d.ts +1 -0
  40. package/dist/core/agent-session-skill-block.test.js +19 -0
  41. package/dist/core/agent-session.d.ts +713 -0
  42. package/dist/core/agent-session.js +3054 -0
  43. package/dist/core/agents.d.ts +52 -0
  44. package/dist/core/agents.js +237 -0
  45. package/dist/core/auth-guidance.d.ts +4 -0
  46. package/dist/core/auth-guidance.js +20 -0
  47. package/dist/core/auth-storage.d.ts +61 -0
  48. package/dist/core/auth-storage.js +249 -0
  49. package/dist/core/bash-executor.d.ts +31 -0
  50. package/dist/core/bash-executor.js +110 -0
  51. package/dist/core/built-in-extensions.d.ts +2 -0
  52. package/dist/core/built-in-extensions.js +2 -0
  53. package/dist/core/cache-stats.d.ts +48 -0
  54. package/dist/core/cache-stats.js +100 -0
  55. package/dist/core/compaction/branch-summarization.d.ts +97 -0
  56. package/dist/core/compaction/branch-summarization.js +246 -0
  57. package/dist/core/compaction/compaction.d.ts +141 -0
  58. package/dist/core/compaction/compaction.js +659 -0
  59. package/dist/core/compaction/index.d.ts +6 -0
  60. package/dist/core/compaction/index.js +6 -0
  61. package/dist/core/compaction/utils.d.ts +37 -0
  62. package/dist/core/compaction/utils.js +141 -0
  63. package/dist/core/defaults.d.ts +3 -0
  64. package/dist/core/defaults.js +10 -0
  65. package/dist/core/diagnostics.d.ts +15 -0
  66. package/dist/core/diagnostics.js +1 -0
  67. package/dist/core/event-bus.d.ts +8 -0
  68. package/dist/core/event-bus.js +24 -0
  69. package/dist/core/exec.d.ts +28 -0
  70. package/dist/core/exec.js +74 -0
  71. package/dist/core/experimental.d.ts +5 -0
  72. package/dist/core/experimental.js +7 -0
  73. package/dist/core/export-html/ansi-to-html.d.ts +21 -0
  74. package/dist/core/export-html/ansi-to-html.js +248 -0
  75. package/dist/core/export-html/index.d.ts +36 -0
  76. package/dist/core/export-html/index.js +225 -0
  77. package/dist/core/export-html/template.css +1066 -0
  78. package/dist/core/export-html/template.html +55 -0
  79. package/dist/core/export-html/template.js +1864 -0
  80. package/dist/core/export-html/tool-renderer.d.ts +33 -0
  81. package/dist/core/export-html/tool-renderer.js +107 -0
  82. package/dist/core/export-html/vendor/highlight.min.js +1213 -0
  83. package/dist/core/export-html/vendor/marked.min.js +78 -0
  84. package/dist/core/extensions/index.d.ts +11 -0
  85. package/dist/core/extensions/index.js +8 -0
  86. package/dist/core/extensions/loader.d.ts +22 -0
  87. package/dist/core/extensions/loader.js +632 -0
  88. package/dist/core/extensions/loader.test.d.ts +1 -0
  89. package/dist/core/extensions/loader.test.js +21 -0
  90. package/dist/core/extensions/runner.d.ts +176 -0
  91. package/dist/core/extensions/runner.js +1016 -0
  92. package/dist/core/extensions/types.d.ts +1313 -0
  93. package/dist/core/extensions/types.js +44 -0
  94. package/dist/core/extensions/wrapper.d.ts +19 -0
  95. package/dist/core/extensions/wrapper.js +40 -0
  96. package/dist/core/footer-data-provider.d.ts +63 -0
  97. package/dist/core/footer-data-provider.js +337 -0
  98. package/dist/core/git-command.d.ts +8 -0
  99. package/dist/core/git-command.js +48 -0
  100. package/dist/core/handoff.d.ts +11 -0
  101. package/dist/core/handoff.js +49 -0
  102. package/dist/core/http-dispatcher.d.ts +21 -0
  103. package/dist/core/http-dispatcher.js +90 -0
  104. package/dist/core/index.d.ts +12 -0
  105. package/dist/core/index.js +12 -0
  106. package/dist/core/keybindings.d.ts +421 -0
  107. package/dist/core/keybindings.js +295 -0
  108. package/dist/core/llama/client.d.ts +66 -0
  109. package/dist/core/llama/client.js +308 -0
  110. package/dist/core/llama/huggingface.d.ts +22 -0
  111. package/dist/core/llama/huggingface.js +140 -0
  112. package/dist/core/llama/index.d.ts +2 -0
  113. package/dist/core/llama/index.js +207 -0
  114. package/dist/core/llama/provider.d.ts +11 -0
  115. package/dist/core/llama/provider.js +143 -0
  116. package/dist/core/llama/ui.d.ts +41 -0
  117. package/dist/core/llama/ui.js +415 -0
  118. package/dist/core/messages.d.ts +76 -0
  119. package/dist/core/messages.js +122 -0
  120. package/dist/core/model-config.d.ts +547 -0
  121. package/dist/core/model-config.js +278 -0
  122. package/dist/core/model-registry.d.ts +45 -0
  123. package/dist/core/model-registry.js +107 -0
  124. package/dist/core/model-resolver.d.ts +122 -0
  125. package/dist/core/model-resolver.js +558 -0
  126. package/dist/core/model-runtime.d.ts +86 -0
  127. package/dist/core/model-runtime.js +472 -0
  128. package/dist/core/models-store.d.ts +16 -0
  129. package/dist/core/models-store.js +44 -0
  130. package/dist/core/output-guard.d.ts +6 -0
  131. package/dist/core/output-guard.js +88 -0
  132. package/dist/core/package-manager.d.ts +221 -0
  133. package/dist/core/package-manager.js +2232 -0
  134. package/dist/core/package-manager.test.d.ts +1 -0
  135. package/dist/core/package-manager.test.js +58 -0
  136. package/dist/core/project-trust.d.ts +14 -0
  137. package/dist/core/project-trust.js +58 -0
  138. package/dist/core/prompt-templates.d.ts +53 -0
  139. package/dist/core/prompt-templates.js +235 -0
  140. package/dist/core/provider-attribution.d.ts +3 -0
  141. package/dist/core/provider-attribution.js +71 -0
  142. package/dist/core/provider-composer.d.ts +54 -0
  143. package/dist/core/provider-composer.js +387 -0
  144. package/dist/core/radius.d.ts +1 -0
  145. package/dist/core/radius.js +1 -0
  146. package/dist/core/remote-catalog-provider.d.ts +4 -0
  147. package/dist/core/remote-catalog-provider.js +119 -0
  148. package/dist/core/resolve-config-value.d.ts +29 -0
  149. package/dist/core/resolve-config-value.js +246 -0
  150. package/dist/core/resource-loader.d.ts +256 -0
  151. package/dist/core/resource-loader.js +974 -0
  152. package/dist/core/runtime-credentials.d.ts +16 -0
  153. package/dist/core/runtime-credentials.js +41 -0
  154. package/dist/core/sdk.d.ts +107 -0
  155. package/dist/core/sdk.js +279 -0
  156. package/dist/core/session-cwd.d.ts +18 -0
  157. package/dist/core/session-cwd.js +37 -0
  158. package/dist/core/session-manager.d.ts +355 -0
  159. package/dist/core/session-manager.js +1339 -0
  160. package/dist/core/settings-manager-auto-handoff.test.d.ts +1 -0
  161. package/dist/core/settings-manager-auto-handoff.test.js +42 -0
  162. package/dist/core/settings-manager.d.ts +350 -0
  163. package/dist/core/settings-manager.js +1076 -0
  164. package/dist/core/skills.d.ts +70 -0
  165. package/dist/core/skills.js +401 -0
  166. package/dist/core/slash-commands.d.ts +14 -0
  167. package/dist/core/slash-commands.js +27 -0
  168. package/dist/core/source-info.d.ts +17 -0
  169. package/dist/core/source-info.js +18 -0
  170. package/dist/core/system-prompt.d.ts +30 -0
  171. package/dist/core/system-prompt.js +129 -0
  172. package/dist/core/system-prompt.test.d.ts +1 -0
  173. package/dist/core/system-prompt.test.js +94 -0
  174. package/dist/core/telemetry.d.ts +2 -0
  175. package/dist/core/telemetry.js +8 -0
  176. package/dist/core/timings.d.ts +9 -0
  177. package/dist/core/timings.js +40 -0
  178. package/dist/core/tools/bash.d.ts +86 -0
  179. package/dist/core/tools/bash.js +409 -0
  180. package/dist/core/tools/edit-diff.d.ts +105 -0
  181. package/dist/core/tools/edit-diff.js +423 -0
  182. package/dist/core/tools/edit.d.ts +50 -0
  183. package/dist/core/tools/edit.js +285 -0
  184. package/dist/core/tools/file-mutation-queue.d.ts +5 -0
  185. package/dist/core/tools/file-mutation-queue.js +51 -0
  186. package/dist/core/tools/find.d.ts +34 -0
  187. package/dist/core/tools/find.js +304 -0
  188. package/dist/core/tools/grep.d.ts +36 -0
  189. package/dist/core/tools/grep.js +303 -0
  190. package/dist/core/tools/index.d.ts +42 -0
  191. package/dist/core/tools/index.js +119 -0
  192. package/dist/core/tools/ls.d.ts +36 -0
  193. package/dist/core/tools/ls.js +166 -0
  194. package/dist/core/tools/output-accumulator.d.ts +51 -0
  195. package/dist/core/tools/output-accumulator.js +183 -0
  196. package/dist/core/tools/path-utils.d.ts +9 -0
  197. package/dist/core/tools/path-utils.js +98 -0
  198. package/dist/core/tools/powershell.d.ts +15 -0
  199. package/dist/core/tools/powershell.js +38 -0
  200. package/dist/core/tools/powershell.test.d.ts +1 -0
  201. package/dist/core/tools/powershell.test.js +20 -0
  202. package/dist/core/tools/read-vision.test.d.ts +1 -0
  203. package/dist/core/tools/read-vision.test.js +122 -0
  204. package/dist/core/tools/read.d.ts +46 -0
  205. package/dist/core/tools/read.js +327 -0
  206. package/dist/core/tools/render-utils.d.ts +23 -0
  207. package/dist/core/tools/render-utils.js +64 -0
  208. package/dist/core/tools/tool-definition-wrapper.d.ts +13 -0
  209. package/dist/core/tools/tool-definition-wrapper.js +35 -0
  210. package/dist/core/tools/truncate.d.ts +69 -0
  211. package/dist/core/tools/truncate.js +214 -0
  212. package/dist/core/tools/write.d.ts +25 -0
  213. package/dist/core/tools/write.js +198 -0
  214. package/dist/core/trust-manager.d.ts +35 -0
  215. package/dist/core/trust-manager.js +201 -0
  216. package/dist/core/usage-totals.d.ts +20 -0
  217. package/dist/core/usage-totals.js +61 -0
  218. package/dist/core/vision-caption.d.ts +30 -0
  219. package/dist/core/vision-caption.js +62 -0
  220. package/dist/defaults/models.json +335 -0
  221. package/dist/defaults/settings.json +61 -0
  222. package/dist/extensions/agent-browser.test.ts +371 -0
  223. package/dist/extensions/agent-browser.ts +160 -0
  224. package/dist/extensions/auto-session-name.test.ts +169 -0
  225. package/dist/extensions/auto-session-name.ts +100 -0
  226. package/dist/extensions/context-compaction-reminder.test.ts +82 -0
  227. package/dist/extensions/context-compaction-reminder.ts +28 -0
  228. package/dist/extensions/copy-turn.test.ts +383 -0
  229. package/dist/extensions/copy-turn.ts +146 -0
  230. package/dist/extensions/cost-reconcile.test.ts +272 -0
  231. package/dist/extensions/cost-reconcile.ts +264 -0
  232. package/dist/extensions/grep-app/index.test.ts +406 -0
  233. package/dist/extensions/grep-app/index.ts +216 -0
  234. package/dist/extensions/handoff-new.test.ts +434 -0
  235. package/dist/extensions/handoff-new.ts +129 -0
  236. package/dist/extensions/herdr-agent-state.ts +310 -0
  237. package/dist/extensions/inline-skills.test.ts +204 -0
  238. package/dist/extensions/inline-skills.ts +102 -0
  239. package/dist/extensions/package.json +32 -0
  240. package/dist/extensions/pi-hermes-memory/CHANGELOG.md +371 -0
  241. package/dist/extensions/pi-hermes-memory/LICENSE +21 -0
  242. package/dist/extensions/pi-hermes-memory/README.md +643 -0
  243. package/dist/extensions/pi-hermes-memory/docs/0.1/TASKS.md +197 -0
  244. package/dist/extensions/pi-hermes-memory/docs/0.2/PLAN.md +290 -0
  245. package/dist/extensions/pi-hermes-memory/docs/0.2/TASKS.md +134 -0
  246. package/dist/extensions/pi-hermes-memory/docs/0.2/TEST-PLAN.md +216 -0
  247. package/dist/extensions/pi-hermes-memory/docs/0.3/PLAN.md +330 -0
  248. package/dist/extensions/pi-hermes-memory/docs/0.3/TASKS.md +125 -0
  249. package/dist/extensions/pi-hermes-memory/docs/0.4/PLAN.md +160 -0
  250. package/dist/extensions/pi-hermes-memory/docs/0.4/TASKS.md +113 -0
  251. package/dist/extensions/pi-hermes-memory/docs/0.6/CHANGELOG.md +57 -0
  252. package/dist/extensions/pi-hermes-memory/docs/0.6/PLAN.md +202 -0
  253. package/dist/extensions/pi-hermes-memory/docs/0.6/TASKS.md +144 -0
  254. package/dist/extensions/pi-hermes-memory/docs/0.7/PLAN.md +349 -0
  255. package/dist/extensions/pi-hermes-memory/docs/0.7/TASKS.md +110 -0
  256. package/dist/extensions/pi-hermes-memory/docs/PUBLISHING.md +149 -0
  257. package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +468 -0
  258. package/dist/extensions/pi-hermes-memory/docs/images/memory-architecture.svg +1 -0
  259. package/dist/extensions/pi-hermes-memory/docs/images/pi-logo.svg +22 -0
  260. package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.png +0 -0
  261. package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.svg +19 -0
  262. package/dist/extensions/pi-hermes-memory/docs/images/security-flow.svg +1 -0
  263. package/dist/extensions/pi-hermes-memory/docs/images/session-lifecycle.svg +1 -0
  264. package/dist/extensions/pi-hermes-memory/docs/images/source-architecture.svg +1 -0
  265. package/dist/extensions/pi-hermes-memory/docs/mermaid/memory-architecture.mmd +49 -0
  266. package/dist/extensions/pi-hermes-memory/docs/mermaid/security-flow.mmd +40 -0
  267. package/dist/extensions/pi-hermes-memory/docs/mermaid/session-lifecycle.mmd +56 -0
  268. package/dist/extensions/pi-hermes-memory/docs/mermaid/source-architecture.mmd +54 -0
  269. package/dist/extensions/pi-hermes-memory/package-lock.json +3799 -0
  270. package/dist/extensions/pi-hermes-memory/package.json +66 -0
  271. package/dist/extensions/pi-hermes-memory/scripts/check-min-sdk.mjs +99 -0
  272. package/dist/extensions/pi-hermes-memory/scripts/ensure-dev.mjs +57 -0
  273. package/dist/extensions/pi-hermes-memory/src/auto-consolidation-warning.ts +6 -0
  274. package/dist/extensions/pi-hermes-memory/src/config.ts +178 -0
  275. package/dist/extensions/pi-hermes-memory/src/constants.ts +424 -0
  276. package/dist/extensions/pi-hermes-memory/src/extension-root-migration.ts +639 -0
  277. package/dist/extensions/pi-hermes-memory/src/handlers/auto-consolidate.ts +401 -0
  278. package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +297 -0
  279. package/dist/extensions/pi-hermes-memory/src/handlers/child-process-watchdog.mjs +90 -0
  280. package/dist/extensions/pi-hermes-memory/src/handlers/correction-detector.ts +300 -0
  281. package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +86 -0
  282. package/dist/extensions/pi-hermes-memory/src/handlers/insights.ts +78 -0
  283. package/dist/extensions/pi-hermes-memory/src/handlers/interview.ts +37 -0
  284. package/dist/extensions/pi-hermes-memory/src/handlers/learn-memory.ts +186 -0
  285. package/dist/extensions/pi-hermes-memory/src/handlers/message-parts.ts +27 -0
  286. package/dist/extensions/pi-hermes-memory/src/handlers/pi-child-process.ts +485 -0
  287. package/dist/extensions/pi-hermes-memory/src/handlers/preview-context.ts +105 -0
  288. package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +506 -0
  289. package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +145 -0
  290. package/dist/extensions/pi-hermes-memory/src/handlers/session-flush.ts +151 -0
  291. package/dist/extensions/pi-hermes-memory/src/handlers/session-live-index.ts +94 -0
  292. package/dist/extensions/pi-hermes-memory/src/handlers/skills-command.ts +1334 -0
  293. package/dist/extensions/pi-hermes-memory/src/handlers/standing-pin.ts +111 -0
  294. package/dist/extensions/pi-hermes-memory/src/handlers/switch-project.ts +75 -0
  295. package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +266 -0
  296. package/dist/extensions/pi-hermes-memory/src/index.ts +384 -0
  297. package/dist/extensions/pi-hermes-memory/src/lifecycle-timing.ts +54 -0
  298. package/dist/extensions/pi-hermes-memory/src/paths.ts +61 -0
  299. package/dist/extensions/pi-hermes-memory/src/project-context.ts +13 -0
  300. package/dist/extensions/pi-hermes-memory/src/project-memory-migration.ts +93 -0
  301. package/dist/extensions/pi-hermes-memory/src/project.ts +157 -0
  302. package/dist/extensions/pi-hermes-memory/src/prompt-context.ts +55 -0
  303. package/dist/extensions/pi-hermes-memory/src/store/atomic-lock-coordinator.ts +375 -0
  304. package/dist/extensions/pi-hermes-memory/src/store/canonical-storage-path.ts +54 -0
  305. package/dist/extensions/pi-hermes-memory/src/store/content-scanner.ts +101 -0
  306. package/dist/extensions/pi-hermes-memory/src/store/db.ts +1180 -0
  307. package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +101 -0
  308. package/dist/extensions/pi-hermes-memory/src/store/markdown-mutation-lock.ts +38 -0
  309. package/dist/extensions/pi-hermes-memory/src/store/memory-lookup.ts +24 -0
  310. package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +1191 -0
  311. package/dist/extensions/pi-hermes-memory/src/store/recovery-maintenance.ts +66 -0
  312. package/dist/extensions/pi-hermes-memory/src/store/schema.ts +118 -0
  313. package/dist/extensions/pi-hermes-memory/src/store/session-anchor-search.ts +472 -0
  314. package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +511 -0
  315. package/dist/extensions/pi-hermes-memory/src/store/session-parser.ts +213 -0
  316. package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +234 -0
  317. package/dist/extensions/pi-hermes-memory/src/store/skill-store.ts +950 -0
  318. package/dist/extensions/pi-hermes-memory/src/store/skill-utils.ts +133 -0
  319. package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +1002 -0
  320. package/dist/extensions/pi-hermes-memory/src/store/sqlite-native.ts +241 -0
  321. package/dist/extensions/pi-hermes-memory/src/store/standing-instructions.ts +247 -0
  322. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +95 -0
  323. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +469 -0
  324. package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +246 -0
  325. package/dist/extensions/pi-hermes-memory/src/tools/shared-output-view.ts +170 -0
  326. package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +333 -0
  327. package/dist/extensions/pi-hermes-memory/src/tools/tool-result-views.ts +105 -0
  328. package/dist/extensions/pi-hermes-memory/src/types.ts +214 -0
  329. package/dist/extensions/pi-hermes-memory/tests/config.test.ts +434 -0
  330. package/dist/extensions/pi-hermes-memory/tests/extension-root-migration.test.ts +368 -0
  331. package/dist/extensions/pi-hermes-memory/tests/handlers/auto-consolidate.test.ts +984 -0
  332. package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +950 -0
  333. package/dist/extensions/pi-hermes-memory/tests/handlers/correction-detector.test.ts +671 -0
  334. package/dist/extensions/pi-hermes-memory/tests/handlers/insights.test.ts +157 -0
  335. package/dist/extensions/pi-hermes-memory/tests/handlers/interview.test.ts +127 -0
  336. package/dist/extensions/pi-hermes-memory/tests/handlers/pi-child-process.test.ts +905 -0
  337. package/dist/extensions/pi-hermes-memory/tests/handlers/preview-context.test.ts +152 -0
  338. package/dist/extensions/pi-hermes-memory/tests/handlers/prompt-context.test.ts +166 -0
  339. package/dist/extensions/pi-hermes-memory/tests/handlers/resources-discover.test.ts +71 -0
  340. package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +614 -0
  341. package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +192 -0
  342. package/dist/extensions/pi-hermes-memory/tests/handlers/session-flush.test.ts +677 -0
  343. package/dist/extensions/pi-hermes-memory/tests/handlers/session-live-index.test.ts +225 -0
  344. package/dist/extensions/pi-hermes-memory/tests/handlers/skills-command.test.ts +827 -0
  345. package/dist/extensions/pi-hermes-memory/tests/handlers/standing-pin.test.ts +134 -0
  346. package/dist/extensions/pi-hermes-memory/tests/handlers/sync-markdown-memories.test.ts +491 -0
  347. package/dist/extensions/pi-hermes-memory/tests/handlers/system-prompt.test.ts +199 -0
  348. package/dist/extensions/pi-hermes-memory/tests/handlers/thinking-max.test.ts +64 -0
  349. package/dist/extensions/pi-hermes-memory/tests/index.test.ts +30 -0
  350. package/dist/extensions/pi-hermes-memory/tests/integration/flow.test.ts +126 -0
  351. package/dist/extensions/pi-hermes-memory/tests/lifecycle-timing.test.ts +76 -0
  352. package/dist/extensions/pi-hermes-memory/tests/paths.test.ts +23 -0
  353. package/dist/extensions/pi-hermes-memory/tests/project-memory-migration.test.ts +80 -0
  354. package/dist/extensions/pi-hermes-memory/tests/project-rebinding.test.ts +115 -0
  355. package/dist/extensions/pi-hermes-memory/tests/project.test.ts +120 -0
  356. package/dist/extensions/pi-hermes-memory/tests/run-all-timeout.test.ts +107 -0
  357. package/dist/extensions/pi-hermes-memory/tests/run-all.sh +45 -0
  358. package/dist/extensions/pi-hermes-memory/tests/store/atomic-lock-coordinator.test.ts +381 -0
  359. package/dist/extensions/pi-hermes-memory/tests/store/content-scanner.test.ts +388 -0
  360. package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +1046 -0
  361. package/dist/extensions/pi-hermes-memory/tests/store/markdown-mutation-lock.test.ts +34 -0
  362. package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +2150 -0
  363. package/dist/extensions/pi-hermes-memory/tests/store/recovery-maintenance.test.ts +170 -0
  364. package/dist/extensions/pi-hermes-memory/tests/store/session-anchor-search.test.ts +210 -0
  365. package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +643 -0
  366. package/dist/extensions/pi-hermes-memory/tests/store/session-parser.test.ts +282 -0
  367. package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +287 -0
  368. package/dist/extensions/pi-hermes-memory/tests/store/skill-store.test.ts +678 -0
  369. package/dist/extensions/pi-hermes-memory/tests/store/skill-utils.test.ts +21 -0
  370. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-lazy-load.test.ts +78 -0
  371. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +543 -0
  372. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +164 -0
  373. package/dist/extensions/pi-hermes-memory/tests/store/standing-instructions.test.ts +171 -0
  374. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +84 -0
  375. package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +709 -0
  376. package/dist/extensions/pi-hermes-memory/tests/tools/session-search-tool.test.ts +345 -0
  377. package/dist/extensions/pi-hermes-memory/tests/tools/shared-output-view.test.ts +362 -0
  378. package/dist/extensions/pi-hermes-memory/tests/tools/skill-tool.test.ts +478 -0
  379. package/dist/extensions/pi-hermes-memory/tests/tools/tool-result-renderer-wiring.test.ts +40 -0
  380. package/dist/extensions/pi-hermes-memory/tsconfig.json +19 -0
  381. package/dist/extensions/pi-intercom/CHANGELOG.md +321 -0
  382. package/dist/extensions/pi-intercom/LICENSE +21 -0
  383. package/dist/extensions/pi-intercom/README.md +598 -0
  384. package/dist/extensions/pi-intercom/banner.png +0 -0
  385. package/dist/extensions/pi-intercom/broker/broker.ts +1721 -0
  386. package/dist/extensions/pi-intercom/broker/client-liveness.test.ts +173 -0
  387. package/dist/extensions/pi-intercom/broker/client.test.ts +83 -0
  388. package/dist/extensions/pi-intercom/broker/client.ts +793 -0
  389. package/dist/extensions/pi-intercom/broker/extension-state.ts +197 -0
  390. package/dist/extensions/pi-intercom/broker/extension.test.ts +486 -0
  391. package/dist/extensions/pi-intercom/broker/framing.test.ts +114 -0
  392. package/dist/extensions/pi-intercom/broker/framing.ts +115 -0
  393. package/dist/extensions/pi-intercom/broker/paths.test.ts +153 -0
  394. package/dist/extensions/pi-intercom/broker/paths.ts +134 -0
  395. package/dist/extensions/pi-intercom/broker/protocol.ts +208 -0
  396. package/dist/extensions/pi-intercom/broker/runtime-claim.test.ts +34 -0
  397. package/dist/extensions/pi-intercom/broker/runtime-claim.ts +21 -0
  398. package/dist/extensions/pi-intercom/broker/spawn.test.ts +252 -0
  399. package/dist/extensions/pi-intercom/broker/spawn.ts +420 -0
  400. package/dist/extensions/pi-intercom/config.test.ts +104 -0
  401. package/dist/extensions/pi-intercom/config.ts +163 -0
  402. package/dist/extensions/pi-intercom/cwd.test.ts +40 -0
  403. package/dist/extensions/pi-intercom/cwd.ts +31 -0
  404. package/dist/extensions/pi-intercom/extension-api.ts +84 -0
  405. package/dist/extensions/pi-intercom/format-context.test.ts +31 -0
  406. package/dist/extensions/pi-intercom/format-context.ts +32 -0
  407. package/dist/extensions/pi-intercom/index.ts +2821 -0
  408. package/dist/extensions/pi-intercom/intercom.integration.test.ts +4232 -0
  409. package/dist/extensions/pi-intercom/package.json +49 -0
  410. package/dist/extensions/pi-intercom/project-agent.test.ts +145 -0
  411. package/dist/extensions/pi-intercom/project-agent.ts +324 -0
  412. package/dist/extensions/pi-intercom/reply-tracker.test.ts +239 -0
  413. package/dist/extensions/pi-intercom/reply-tracker.ts +160 -0
  414. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +452 -0
  415. package/dist/extensions/pi-intercom/test/inline-message.test.ts +184 -0
  416. package/dist/extensions/pi-intercom/test/overlay-width.test.ts +66 -0
  417. package/dist/extensions/pi-intercom/types.ts +165 -0
  418. package/dist/extensions/pi-intercom/ui/compose.ts +143 -0
  419. package/dist/extensions/pi-intercom/ui/inline-message.ts +118 -0
  420. package/dist/extensions/pi-intercom/ui/session-list.ts +166 -0
  421. package/dist/extensions/pi-rewind-hook/README.md +248 -0
  422. package/dist/extensions/pi-rewind-hook/index.ts +1575 -0
  423. package/dist/extensions/pi-rewind-hook/package.json +31 -0
  424. package/dist/extensions/pi-subagents/.github/assets/subagent-fleet-inspector.png +0 -0
  425. package/dist/extensions/pi-subagents/.github/workflows/release.yml +28 -0
  426. package/dist/extensions/pi-subagents/.github/workflows/test.yml +51 -0
  427. package/dist/extensions/pi-subagents/.greptile/config.json +33 -0
  428. package/dist/extensions/pi-subagents/.greptile/files.json +8 -0
  429. package/dist/extensions/pi-subagents/.greptile/rules.md +16 -0
  430. package/dist/extensions/pi-subagents/.oxlintrc.json +43 -0
  431. package/dist/extensions/pi-subagents/AGENTS.md +5 -0
  432. package/dist/extensions/pi-subagents/CHANGELOG.md +2325 -0
  433. package/dist/extensions/pi-subagents/LICENSE +21 -0
  434. package/dist/extensions/pi-subagents/README.md +126 -0
  435. package/dist/extensions/pi-subagents/VISION.md +92 -0
  436. package/dist/extensions/pi-subagents/agents/delegate.md +14 -0
  437. package/dist/extensions/pi-subagents/agents/oracle.md +78 -0
  438. package/dist/extensions/pi-subagents/agents/researcher.md +52 -0
  439. package/dist/extensions/pi-subagents/agents/reviewer.md +89 -0
  440. package/dist/extensions/pi-subagents/agents/scout.md +50 -0
  441. package/dist/extensions/pi-subagents/agents/worker.md +60 -0
  442. package/dist/extensions/pi-subagents/async-retention-discovery-worker.mjs +180 -0
  443. package/dist/extensions/pi-subagents/docs/agents.md +382 -0
  444. package/dist/extensions/pi-subagents/docs/configuration.md +534 -0
  445. package/dist/extensions/pi-subagents/docs/extension-api.md +443 -0
  446. package/dist/extensions/pi-subagents/docs/missions.md +121 -0
  447. package/dist/extensions/pi-subagents/docs/models.md +258 -0
  448. package/dist/extensions/pi-subagents/docs/observability.md +265 -0
  449. package/dist/extensions/pi-subagents/docs/tool-reference.md +482 -0
  450. package/dist/extensions/pi-subagents/docs/watchdog.md +154 -0
  451. package/dist/extensions/pi-subagents/docs/workflows.md +475 -0
  452. package/dist/extensions/pi-subagents/index.ts +10 -0
  453. package/dist/extensions/pi-subagents/inspector-runner.mjs +11 -0
  454. package/dist/extensions/pi-subagents/install.mjs +93 -0
  455. package/dist/extensions/pi-subagents/package-lock.json +1872 -0
  456. package/dist/extensions/pi-subagents/package.json +109 -0
  457. package/dist/extensions/pi-subagents/prompts/council.md +60 -0
  458. package/dist/extensions/pi-subagents/prompts/gather-context-and-clarify.md +13 -0
  459. package/dist/extensions/pi-subagents/prompts/parallel-cleanup.md +59 -0
  460. package/dist/extensions/pi-subagents/prompts/parallel-research.md +50 -0
  461. package/dist/extensions/pi-subagents/prompts/parallel-review.md +58 -0
  462. package/dist/extensions/pi-subagents/prompts/review-loop.md +47 -0
  463. package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +59 -0
  464. package/dist/extensions/pi-subagents/skills/council-mode/references/pass-contracts.md +150 -0
  465. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +103 -0
  466. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +70 -0
  467. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +539 -0
  468. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +161 -0
  469. package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +51 -0
  470. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +295 -0
  471. package/dist/extensions/pi-subagents/skills/pi-subagents/references/review-and-validation.md +73 -0
  472. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +1373 -0
  473. package/dist/extensions/pi-subagents/src/agents/agent-memory.ts +254 -0
  474. package/dist/extensions/pi-subagents/src/agents/agent-refinements.ts +624 -0
  475. package/dist/extensions/pi-subagents/src/agents/agent-scope.ts +6 -0
  476. package/dist/extensions/pi-subagents/src/agents/agent-selection.ts +25 -0
  477. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +179 -0
  478. package/dist/extensions/pi-subagents/src/agents/agents.ts +2790 -0
  479. package/dist/extensions/pi-subagents/src/agents/builtin-names.ts +9 -0
  480. package/dist/extensions/pi-subagents/src/agents/chain-serializer.ts +280 -0
  481. package/dist/extensions/pi-subagents/src/agents/frontmatter.ts +153 -0
  482. package/dist/extensions/pi-subagents/src/agents/identity.ts +30 -0
  483. package/dist/extensions/pi-subagents/src/agents/proactive-skills.ts +194 -0
  484. package/dist/extensions/pi-subagents/src/agents/runtime-agent-events.ts +70 -0
  485. package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +429 -0
  486. package/dist/extensions/pi-subagents/src/agents/skills.ts +754 -0
  487. package/dist/extensions/pi-subagents/src/api/agents.ts +12 -0
  488. package/dist/extensions/pi-subagents/src/api/background-work.ts +206 -0
  489. package/dist/extensions/pi-subagents/src/api/capability-ceiling.ts +17 -0
  490. package/dist/extensions/pi-subagents/src/api/control-channel.ts +4 -0
  491. package/dist/extensions/pi-subagents/src/api/delegation.ts +112 -0
  492. package/dist/extensions/pi-subagents/src/api/external-job-provider.ts +195 -0
  493. package/dist/extensions/pi-subagents/src/api/external-runs.ts +282 -0
  494. package/dist/extensions/pi-subagents/src/api/intercom-bridge.ts +3 -0
  495. package/dist/extensions/pi-subagents/src/api/pi-args.ts +5 -0
  496. package/dist/extensions/pi-subagents/src/api/preflight.ts +501 -0
  497. package/dist/extensions/pi-subagents/src/api/project-panes.ts +32 -0
  498. package/dist/extensions/pi-subagents/src/api/shared-types.ts +27 -0
  499. package/dist/extensions/pi-subagents/src/extension/config.ts +255 -0
  500. package/dist/extensions/pi-subagents/src/extension/control-notices.ts +58 -0
  501. package/dist/extensions/pi-subagents/src/extension/doctor.ts +278 -0
  502. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +205 -0
  503. package/dist/extensions/pi-subagents/src/extension/index.ts +1093 -0
  504. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +210 -0
  505. package/dist/extensions/pi-subagents/src/extension/rpc.ts +860 -0
  506. package/dist/extensions/pi-subagents/src/extension/schemas.ts +419 -0
  507. package/dist/extensions/pi-subagents/src/extension/steering-notices.ts +35 -0
  508. package/dist/extensions/pi-subagents/src/extension/subagent-guide.ts +39 -0
  509. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +204 -0
  510. package/dist/extensions/pi-subagents/src/extension/tool-result.ts +19 -0
  511. package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +235 -0
  512. package/dist/extensions/pi-subagents/src/inspectors/herdr/client.ts +130 -0
  513. package/dist/extensions/pi-subagents/src/inspectors/herdr/focus.ts +55 -0
  514. package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +153 -0
  515. package/dist/extensions/pi-subagents/src/inspectors/herdr/project-panes.ts +730 -0
  516. package/dist/extensions/pi-subagents/src/inspectors/herdr/session-roots-codec.ts +42 -0
  517. package/dist/extensions/pi-subagents/src/inspectors/herdr/shell-command.ts +16 -0
  518. package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +396 -0
  519. package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +191 -0
  520. package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +812 -0
  521. package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +423 -0
  522. package/dist/extensions/pi-subagents/src/missions/actions.ts +433 -0
  523. package/dist/extensions/pi-subagents/src/missions/goal-driver.ts +164 -0
  524. package/dist/extensions/pi-subagents/src/missions/lifecycle.ts +367 -0
  525. package/dist/extensions/pi-subagents/src/missions/store.ts +584 -0
  526. package/dist/extensions/pi-subagents/src/missions/types.ts +190 -0
  527. package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +260 -0
  528. package/dist/extensions/pi-subagents/src/policy/authority.ts +46 -0
  529. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +662 -0
  530. package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +516 -0
  531. package/dist/extensions/pi-subagents/src/runs/background/active-run-index.ts +139 -0
  532. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +2080 -0
  533. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +781 -0
  534. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +631 -0
  535. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +903 -0
  536. package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +48 -0
  537. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +761 -0
  538. package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +68 -0
  539. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +321 -0
  540. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +270 -0
  541. package/dist/extensions/pi-subagents/src/runs/background/completion-batcher.ts +168 -0
  542. package/dist/extensions/pi-subagents/src/runs/background/completion-dedupe.ts +58 -0
  543. package/dist/extensions/pi-subagents/src/runs/background/completion-replay.ts +287 -0
  544. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +768 -0
  545. package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +620 -0
  546. package/dist/extensions/pi-subagents/src/runs/background/index-segment.ts +59 -0
  547. package/dist/extensions/pi-subagents/src/runs/background/inspect-rpc.ts +443 -0
  548. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +645 -0
  549. package/dist/extensions/pi-subagents/src/runs/background/owned-process-tree.ts +104 -0
  550. package/dist/extensions/pi-subagents/src/runs/background/parallel-groups.ts +45 -0
  551. package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +310 -0
  552. package/dist/extensions/pi-subagents/src/runs/background/result-delivery-ownership.ts +45 -0
  553. package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +519 -0
  554. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +792 -0
  555. package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +56 -0
  556. package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +135 -0
  557. package/dist/extensions/pi-subagents/src/runs/background/run-id-query.ts +7 -0
  558. package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +175 -0
  559. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +714 -0
  560. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +965 -0
  561. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +410 -0
  562. package/dist/extensions/pi-subagents/src/runs/background/steering.ts +242 -0
  563. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +5683 -0
  564. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +725 -0
  565. package/dist/extensions/pi-subagents/src/runs/background/terminal-run-index.ts +138 -0
  566. package/dist/extensions/pi-subagents/src/runs/background/top-level-async.ts +14 -0
  567. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +209 -0
  568. package/dist/extensions/pi-subagents/src/runs/background/wait-config.ts +50 -0
  569. package/dist/extensions/pi-subagents/src/runs/background/wait-subscriptions.ts +348 -0
  570. package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +51 -0
  571. package/dist/extensions/pi-subagents/src/runs/foreground/async-dismiss-action.ts +86 -0
  572. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +262 -0
  573. package/dist/extensions/pi-subagents/src/runs/foreground/async-stop-action.ts +86 -0
  574. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +2443 -0
  575. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +153 -0
  576. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +160 -0
  577. package/dist/extensions/pi-subagents/src/runs/foreground/prompt-audit.ts +172 -0
  578. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +6971 -0
  579. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +299 -0
  580. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +188 -0
  581. package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +119 -0
  582. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +1525 -0
  583. package/dist/extensions/pi-subagents/src/runs/shared/agent-contract.ts +38 -0
  584. package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +565 -0
  585. package/dist/extensions/pi-subagents/src/runs/shared/background-process-options.ts +9 -0
  586. package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +210 -0
  587. package/dist/extensions/pi-subagents/src/runs/shared/chain-outputs.ts +116 -0
  588. package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +51 -0
  589. package/dist/extensions/pi-subagents/src/runs/shared/child-launch-plan.ts +151 -0
  590. package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +415 -0
  591. package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +89 -0
  592. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +252 -0
  593. package/dist/extensions/pi-subagents/src/runs/shared/context-mode.ts +44 -0
  594. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +297 -0
  595. package/dist/extensions/pi-subagents/src/runs/shared/extension-bindings.ts +78 -0
  596. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-contract.ts +138 -0
  597. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +122 -0
  598. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +429 -0
  599. package/dist/extensions/pi-subagents/src/runs/shared/external-job-bridge.ts +460 -0
  600. package/dist/extensions/pi-subagents/src/runs/shared/external-job-runner.ts +389 -0
  601. package/dist/extensions/pi-subagents/src/runs/shared/fast-mode-extension.ts +10 -0
  602. package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +231 -0
  603. package/dist/extensions/pi-subagents/src/runs/shared/lane-metadata.ts +126 -0
  604. package/dist/extensions/pi-subagents/src/runs/shared/launch-cwd.ts +16 -0
  605. package/dist/extensions/pi-subagents/src/runs/shared/llm-intent-arbiter.ts +302 -0
  606. package/dist/extensions/pi-subagents/src/runs/shared/long-running-guard.ts +221 -0
  607. package/dist/extensions/pi-subagents/src/runs/shared/mcp-config-sources.ts +422 -0
  608. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +483 -0
  609. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-grant.ts +194 -0
  610. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +305 -0
  611. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +578 -0
  612. package/dist/extensions/pi-subagents/src/runs/shared/model-scope.ts +205 -0
  613. package/dist/extensions/pi-subagents/src/runs/shared/mutation-evidence.ts +199 -0
  614. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +1086 -0
  615. package/dist/extensions/pi-subagents/src/runs/shared/nested-path.ts +52 -0
  616. package/dist/extensions/pi-subagents/src/runs/shared/nested-render.ts +127 -0
  617. package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +499 -0
  618. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +696 -0
  619. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +275 -0
  620. package/dist/extensions/pi-subagents/src/runs/shared/permissions.ts +100 -0
  621. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +1059 -0
  622. package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +199 -0
  623. package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +32 -0
  624. package/dist/extensions/pi-subagents/src/runs/shared/run-fanout-budget.ts +280 -0
  625. package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +201 -0
  626. package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +71 -0
  627. package/dist/extensions/pi-subagents/src/runs/shared/session-lease.ts +293 -0
  628. package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +304 -0
  629. package/dist/extensions/pi-subagents/src/runs/shared/spawn-budget.ts +128 -0
  630. package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +223 -0
  631. package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +292 -0
  632. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +825 -0
  633. package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +116 -0
  634. package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +211 -0
  635. package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +81 -0
  636. package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +80 -0
  637. package/dist/extensions/pi-subagents/src/runs/shared/tool-timeout.ts +93 -0
  638. package/dist/extensions/pi-subagents/src/runs/shared/usage-budget.ts +65 -0
  639. package/dist/extensions/pi-subagents/src/runs/shared/workflow-graph.ts +225 -0
  640. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +847 -0
  641. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +1206 -0
  642. package/dist/extensions/pi-subagents/src/shared/accessible-dir.ts +47 -0
  643. package/dist/extensions/pi-subagents/src/shared/agent-stream-options.ts +5 -0
  644. package/dist/extensions/pi-subagents/src/shared/artifacts.ts +281 -0
  645. package/dist/extensions/pi-subagents/src/shared/atomic-json.ts +83 -0
  646. package/dist/extensions/pi-subagents/src/shared/capacity-resilient-json.ts +102 -0
  647. package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +46 -0
  648. package/dist/extensions/pi-subagents/src/shared/child-transcript.ts +264 -0
  649. package/dist/extensions/pi-subagents/src/shared/completion-owner.ts +14 -0
  650. package/dist/extensions/pi-subagents/src/shared/display-text.ts +150 -0
  651. package/dist/extensions/pi-subagents/src/shared/extension-context.ts +24 -0
  652. package/dist/extensions/pi-subagents/src/shared/file-coalescer.ts +49 -0
  653. package/dist/extensions/pi-subagents/src/shared/file-system-retry.ts +95 -0
  654. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +293 -0
  655. package/dist/extensions/pi-subagents/src/shared/fork-session-cwd.ts +27 -0
  656. package/dist/extensions/pi-subagents/src/shared/formatters.ts +146 -0
  657. package/dist/extensions/pi-subagents/src/shared/jsonl-writer.ts +81 -0
  658. package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +138 -0
  659. package/dist/extensions/pi-subagents/src/shared/model-info.ts +101 -0
  660. package/dist/extensions/pi-subagents/src/shared/node-executable.ts +21 -0
  661. package/dist/extensions/pi-subagents/src/shared/post-exit-stdio-guard.ts +85 -0
  662. package/dist/extensions/pi-subagents/src/shared/prompt-resources.ts +11 -0
  663. package/dist/extensions/pi-subagents/src/shared/pruned-fork.ts +450 -0
  664. package/dist/extensions/pi-subagents/src/shared/session-file-trust.ts +19 -0
  665. package/dist/extensions/pi-subagents/src/shared/session-identity.ts +10 -0
  666. package/dist/extensions/pi-subagents/src/shared/session-tokens.ts +55 -0
  667. package/dist/extensions/pi-subagents/src/shared/settings.ts +409 -0
  668. package/dist/extensions/pi-subagents/src/shared/shortcuts.ts +17 -0
  669. package/dist/extensions/pi-subagents/src/shared/status-format.ts +55 -0
  670. package/dist/extensions/pi-subagents/src/shared/thinking-ceiling.ts +52 -0
  671. package/dist/extensions/pi-subagents/src/shared/types.ts +2872 -0
  672. package/dist/extensions/pi-subagents/src/shared/utf8.ts +11 -0
  673. package/dist/extensions/pi-subagents/src/shared/utils.ts +601 -0
  674. package/dist/extensions/pi-subagents/src/shared/watch-strategy.ts +10 -0
  675. package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +207 -0
  676. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +426 -0
  677. package/dist/extensions/pi-subagents/src/slash/delegation-json.ts +108 -0
  678. package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +162 -0
  679. package/dist/extensions/pi-subagents/src/slash/prompt-template-bridge.ts +419 -0
  680. package/dist/extensions/pi-subagents/src/slash/prompt-workflows.ts +287 -0
  681. package/dist/extensions/pi-subagents/src/slash/selector.ts +147 -0
  682. package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +192 -0
  683. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +1345 -0
  684. package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +310 -0
  685. package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +449 -0
  686. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +964 -0
  687. package/dist/extensions/pi-subagents/src/tui/fleet-transcript.ts +536 -0
  688. package/dist/extensions/pi-subagents/src/tui/fleet.ts +1441 -0
  689. package/dist/extensions/pi-subagents/src/tui/render-helpers.ts +111 -0
  690. package/dist/extensions/pi-subagents/src/tui/render.ts +3359 -0
  691. package/dist/extensions/pi-subagents/src/types/pi-runtime-compat.d.ts +8 -0
  692. package/dist/extensions/pi-subagents/src/watchdog/change-signature.ts +260 -0
  693. package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +227 -0
  694. package/dist/extensions/pi-subagents/src/watchdog/diff-tool.ts +77 -0
  695. package/dist/extensions/pi-subagents/src/watchdog/emission-guard.ts +125 -0
  696. package/dist/extensions/pi-subagents/src/watchdog/guidance.ts +20 -0
  697. package/dist/extensions/pi-subagents/src/watchdog/lsp-diagnostics.ts +538 -0
  698. package/dist/extensions/pi-subagents/src/watchdog/model-selection.ts +167 -0
  699. package/dist/extensions/pi-subagents/src/watchdog/permission-arbiter.ts +154 -0
  700. package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +120 -0
  701. package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +441 -0
  702. package/dist/extensions/pi-subagents/src/watchdog/render.ts +53 -0
  703. package/dist/extensions/pi-subagents/src/watchdog/review.ts +314 -0
  704. package/dist/extensions/pi-subagents/src/watchdog/rules.ts +70 -0
  705. package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +851 -0
  706. package/dist/extensions/pi-subagents/src/watchdog/scope.ts +63 -0
  707. package/dist/extensions/pi-subagents/src/watchdog/settings.ts +512 -0
  708. package/dist/extensions/pi-subagents/src/watchdog/tool-actions.ts +155 -0
  709. package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +161 -0
  710. package/dist/extensions/pi-subagents/src/watchdog/types.ts +184 -0
  711. package/dist/extensions/pi-subagents/src/watchdog/warning-format.ts +72 -0
  712. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +152 -0
  713. package/dist/extensions/pi-subagents/src/workflows/host-command.ts +235 -0
  714. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +2183 -0
  715. package/dist/extensions/pi-subagents/src/workflows/workflow-checklist.ts +439 -0
  716. package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +121 -0
  717. package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +297 -0
  718. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +330 -0
  719. package/dist/extensions/pi-subagents/src/workflows/workflow-resources.ts +150 -0
  720. package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +246 -0
  721. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +224 -0
  722. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/cli.d.ts +3 -0
  723. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/register-bedrock.d.ts +2 -0
  724. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/restore-sandbox-env.d.ts +17 -0
  725. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/args.d.ts +57 -0
  726. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/config-selector.d.ts +16 -0
  727. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/file-processor.d.ts +15 -0
  728. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/initial-message.d.ts +18 -0
  729. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/list-models.d.ts +9 -0
  730. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/project-trust.d.ts +10 -0
  731. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/session-picker.d.ts +10 -0
  732. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/startup-ui.d.ts +20 -0
  733. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli.d.ts +3 -0
  734. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/config.d.ts +96 -0
  735. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-runtime.d.ts +119 -0
  736. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-services.d.ts +85 -0
  737. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session.d.ts +620 -0
  738. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-guidance.d.ts +5 -0
  739. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-storage.d.ts +56 -0
  740. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/bash-executor.d.ts +32 -0
  741. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/cache-stats.d.ts +49 -0
  742. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/branch-summarization.d.ts +93 -0
  743. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/compaction.d.ts +128 -0
  744. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/index.d.ts +7 -0
  745. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/utils.d.ts +38 -0
  746. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/defaults.d.ts +3 -0
  747. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/diagnostics.d.ts +15 -0
  748. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/event-bus.d.ts +9 -0
  749. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/exec.d.ts +29 -0
  750. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/experimental.d.ts +2 -0
  751. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/ansi-to-html.d.ts +22 -0
  752. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/index.d.ts +37 -0
  753. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/tool-renderer.d.ts +34 -0
  754. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/index.d.ts +12 -0
  755. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/loader.d.ts +23 -0
  756. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/runner.d.ts +171 -0
  757. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/types.d.ts +1261 -0
  758. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/wrapper.d.ts +20 -0
  759. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/footer-data-provider.d.ts +54 -0
  760. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/http-dispatcher.d.ts +22 -0
  761. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/index.d.ts +13 -0
  762. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/keybindings.d.ts +358 -0
  763. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/messages.d.ts +77 -0
  764. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-config.d.ts +512 -0
  765. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-registry.d.ts +43 -0
  766. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-resolver.d.ts +121 -0
  767. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-runtime.d.ts +82 -0
  768. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/models-store.d.ts +17 -0
  769. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/output-guard.d.ts +7 -0
  770. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/package-manager.d.ts +210 -0
  771. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/project-trust.d.ts +15 -0
  772. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/prompt-templates.d.ts +54 -0
  773. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-attribution.d.ts +4 -0
  774. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-composer.d.ts +55 -0
  775. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/radius.d.ts +2 -0
  776. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/remote-catalog-provider.d.ts +5 -0
  777. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resolve-config-value.d.ts +30 -0
  778. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resource-loader.d.ts +206 -0
  779. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/runtime-credentials.d.ts +15 -0
  780. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/sdk.d.ts +106 -0
  781. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-cwd.d.ts +19 -0
  782. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-manager.d.ts +356 -0
  783. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/settings-manager.d.ts +297 -0
  784. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/skills.d.ts +60 -0
  785. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/slash-commands.d.ts +15 -0
  786. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/source-info.d.ts +18 -0
  787. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/system-prompt.d.ts +28 -0
  788. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/telemetry.d.ts +3 -0
  789. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/timings.d.ts +10 -0
  790. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/bash.d.ts +68 -0
  791. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit-diff.d.ts +106 -0
  792. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit.d.ts +51 -0
  793. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/file-mutation-queue.d.ts +6 -0
  794. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/find.d.ts +35 -0
  795. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/grep.d.ts +37 -0
  796. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/index.d.ts +40 -0
  797. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/ls.d.ts +37 -0
  798. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/output-accumulator.d.ts +52 -0
  799. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/path-utils.d.ts +10 -0
  800. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/read.d.ts +35 -0
  801. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/render-utils.d.ts +24 -0
  802. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
  803. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/truncate.d.ts +70 -0
  804. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/write.d.ts +26 -0
  805. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/trust-manager.d.ts +36 -0
  806. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/usage-totals.d.ts +19 -0
  807. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/index.d.ts +3 -0
  808. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/client.d.ts +61 -0
  809. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/huggingface.d.ts +23 -0
  810. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/index.d.ts +3 -0
  811. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/provider.d.ts +10 -0
  812. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/ui.d.ts +42 -0
  813. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/index.d.ts +35 -0
  814. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/main.d.ts +12 -0
  815. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/migrations.d.ts +33 -0
  816. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/index.d.ts +9 -0
  817. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/armin.d.ts +34 -0
  818. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/assistant-message.d.ts +22 -0
  819. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bash-execution.d.ts +34 -0
  820. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
  821. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
  822. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
  823. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/config-selector.d.ts +102 -0
  824. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
  825. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-editor.d.ts +21 -0
  826. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-entry.d.ts +19 -0
  827. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-message.d.ts +20 -0
  828. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/daxnuts.d.ts +23 -0
  829. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/diff.d.ts +12 -0
  830. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
  831. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
  832. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-editor.d.ts +22 -0
  833. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-input.d.ts +23 -0
  834. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-selector.d.ts +26 -0
  835. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/first-time-setup.d.ts +25 -0
  836. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/footer.d.ts +32 -0
  837. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/index.d.ts +34 -0
  838. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/keybinding-hints.d.ts +13 -0
  839. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/login-dialog.d.ts +52 -0
  840. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/model-selector.d.ts +54 -0
  841. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/oauth-selector.d.ts +33 -0
  842. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/scoped-models-selector.d.ts +42 -0
  843. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
  844. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector.d.ts +95 -0
  845. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/settings-selector.d.ts +77 -0
  846. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
  847. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
  848. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/status-indicator.d.ts +28 -0
  849. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/theme-selector.d.ts +11 -0
  850. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
  851. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tool-execution.d.ts +63 -0
  852. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tree-selector.d.ts +94 -0
  853. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/trust-selector.d.ts +23 -0
  854. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
  855. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message.d.ts +14 -0
  856. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
  857. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/interactive-mode.d.ts +394 -0
  858. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/model-search.d.ts +12 -0
  859. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme-controller.d.ts +29 -0
  860. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme.d.ts +120 -0
  861. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/print-mode.d.ts +28 -0
  862. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/jsonl.d.ts +17 -0
  863. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-client.d.ts +246 -0
  864. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-mode.d.ts +20 -0
  865. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-types.d.ts +457 -0
  866. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/package-manager-cli.d.ts +8 -0
  867. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/rpc-entry.d.ts +3 -0
  868. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/ansi.d.ts +2 -0
  869. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/changelog.d.ts +22 -0
  870. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/child-process.d.ts +18 -0
  871. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-image.d.ts +11 -0
  872. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-native.d.ts +11 -0
  873. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard.d.ts +4 -0
  874. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/deprecation.d.ts +4 -0
  875. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/exif-orientation.d.ts +5 -0
  876. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/frontmatter.d.ts +8 -0
  877. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/fs-watch.d.ts +5 -0
  878. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/git.d.ts +26 -0
  879. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/html.d.ts +7 -0
  880. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-convert.d.ts +10 -0
  881. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-process.d.ts +18 -0
  882. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-core.d.ts +30 -0
  883. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-worker.d.ts +2 -0
  884. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize.d.ts +16 -0
  885. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/json.d.ts +3 -0
  886. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/mime.d.ts +3 -0
  887. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/open-browser.d.ts +9 -0
  888. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/paths.d.ts +31 -0
  889. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/photon.d.ts +21 -0
  890. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/pi-user-agent.d.ts +2 -0
  891. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/shell.d.ts +31 -0
  892. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/sleep.d.ts +5 -0
  893. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/syntax-highlight.d.ts +12 -0
  894. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/tools-manager.d.ts +3 -0
  895. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/version-check.d.ts +15 -0
  896. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/windows-self-update.d.ts +3 -0
  897. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/index.mjs +84 -0
  898. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/package.json +14 -0
  899. package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +472 -0
  900. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +6986 -0
  901. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +2000 -0
  902. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +1300 -0
  903. package/dist/extensions/pi-subagents/test/integration/detect-error.test.ts +249 -0
  904. package/dist/extensions/pi-subagents/test/integration/doctor-executor.test.ts +128 -0
  905. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +281 -0
  906. package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +167 -0
  907. package/dist/extensions/pi-subagents/test/integration/foreground-result-size.test.ts +188 -0
  908. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +1356 -0
  909. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +1946 -0
  910. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +214 -0
  911. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +1408 -0
  912. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +2094 -0
  913. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +2442 -0
  914. package/dist/extensions/pi-subagents/test/integration/session-tokens.test.ts +62 -0
  915. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +9292 -0
  916. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +1517 -0
  917. package/dist/extensions/pi-subagents/test/integration/slash-live-state.test.ts +166 -0
  918. package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +344 -0
  919. package/dist/extensions/pi-subagents/test/integration/top-level-async.test.ts +43 -0
  920. package/dist/extensions/pi-subagents/test/support/cursor-smoke-inputs.ts +51 -0
  921. package/dist/extensions/pi-subagents/test/support/helpers.ts +250 -0
  922. package/dist/extensions/pi-subagents/test/support/isolated-temp-root.mjs +20 -0
  923. package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +447 -0
  924. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +159 -0
  925. package/dist/extensions/pi-subagents/test/support/node-command.ts +15 -0
  926. package/dist/extensions/pi-subagents/test/support/real-session-child-cli.mjs +185 -0
  927. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +311 -0
  928. package/dist/extensions/pi-subagents/test/support/register-loader.mjs +16 -0
  929. package/dist/extensions/pi-subagents/test/support/session-lease-child.mjs +42 -0
  930. package/dist/extensions/pi-subagents/test/support/ts-loader.mjs +100 -0
  931. package/dist/extensions/pi-subagents/test/unit/abort-recovery.test.ts +152 -0
  932. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +1556 -0
  933. package/dist/extensions/pi-subagents/test/unit/accessible-dir.test.ts +82 -0
  934. package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +463 -0
  935. package/dist/extensions/pi-subagents/test/unit/agent-contract.test.ts +14 -0
  936. package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +213 -0
  937. package/dist/extensions/pi-subagents/test/unit/agent-discovery-cache.test.ts +232 -0
  938. package/dist/extensions/pi-subagents/test/unit/agent-eject-disable.test.ts +343 -0
  939. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +2324 -0
  940. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +1408 -0
  941. package/dist/extensions/pi-subagents/test/unit/agent-memory.test.ts +420 -0
  942. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +1174 -0
  943. package/dist/extensions/pi-subagents/test/unit/agent-refinements.test.ts +178 -0
  944. package/dist/extensions/pi-subagents/test/unit/agent-scan-dirs.test.ts +133 -0
  945. package/dist/extensions/pi-subagents/test/unit/agent-scope.test.ts +20 -0
  946. package/dist/extensions/pi-subagents/test/unit/agent-selection.test.ts +88 -0
  947. package/dist/extensions/pi-subagents/test/unit/agent-stream-options.test.ts +14 -0
  948. package/dist/extensions/pi-subagents/test/unit/anti-slop-oxlint.test.ts +98 -0
  949. package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +78 -0
  950. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +280 -0
  951. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +1022 -0
  952. package/dist/extensions/pi-subagents/test/unit/async-permission-session.test.ts +100 -0
  953. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +188 -0
  954. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +978 -0
  955. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +635 -0
  956. package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +260 -0
  957. package/dist/extensions/pi-subagents/test/unit/async-status-snapshot.test.ts +204 -0
  958. package/dist/extensions/pi-subagents/test/unit/atomic-json.test.ts +192 -0
  959. package/dist/extensions/pi-subagents/test/unit/authority-policy.test.ts +22 -0
  960. package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +83 -0
  961. package/dist/extensions/pi-subagents/test/unit/background-process-options.test.ts +17 -0
  962. package/dist/extensions/pi-subagents/test/unit/background-work.test.ts +365 -0
  963. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +102 -0
  964. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-pi-args.test.ts +84 -0
  965. package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +68 -0
  966. package/dist/extensions/pi-subagents/test/unit/capacity-resilient-json.test.ts +155 -0
  967. package/dist/extensions/pi-subagents/test/unit/chain-append.test.ts +283 -0
  968. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +236 -0
  969. package/dist/extensions/pi-subagents/test/unit/chain-serializer.test.ts +229 -0
  970. package/dist/extensions/pi-subagents/test/unit/child-launch-plan.test.ts +94 -0
  971. package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +202 -0
  972. package/dist/extensions/pi-subagents/test/unit/child-session-name.test.ts +50 -0
  973. package/dist/extensions/pi-subagents/test/unit/child-transcript.test.ts +267 -0
  974. package/dist/extensions/pi-subagents/test/unit/close-grace-timer.test.ts +101 -0
  975. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +98 -0
  976. package/dist/extensions/pi-subagents/test/unit/completion-batcher.test.ts +230 -0
  977. package/dist/extensions/pi-subagents/test/unit/completion-dedupe.test.ts +35 -0
  978. package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +150 -0
  979. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +753 -0
  980. package/dist/extensions/pi-subagents/test/unit/completion-replay.test.ts +305 -0
  981. package/dist/extensions/pi-subagents/test/unit/config-dir-runtime.test.ts +107 -0
  982. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +630 -0
  983. package/dist/extensions/pi-subagents/test/unit/control-notices.test.ts +110 -0
  984. package/dist/extensions/pi-subagents/test/unit/cursor-smoke-inputs.test.ts +77 -0
  985. package/dist/extensions/pi-subagents/test/unit/default-extensions.test.ts +219 -0
  986. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +588 -0
  987. package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +201 -0
  988. package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +219 -0
  989. package/dist/extensions/pi-subagents/test/unit/ensure-accessible-dir.test.ts +125 -0
  990. package/dist/extensions/pi-subagents/test/unit/extension-bindings.test.ts +79 -0
  991. package/dist/extensions/pi-subagents/test/unit/extension-context.test.ts +27 -0
  992. package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +339 -0
  993. package/dist/extensions/pi-subagents/test/unit/external-job-runner.test.ts +961 -0
  994. package/dist/extensions/pi-subagents/test/unit/external-runs.test.ts +261 -0
  995. package/dist/extensions/pi-subagents/test/unit/extra-agent-dirs.test.ts +88 -0
  996. package/dist/extensions/pi-subagents/test/unit/fast-mode-extension.test.ts +27 -0
  997. package/dist/extensions/pi-subagents/test/unit/file-coalescer.test.ts +83 -0
  998. package/dist/extensions/pi-subagents/test/unit/file-system-retry.test.ts +64 -0
  999. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +1377 -0
  1000. package/dist/extensions/pi-subagents/test/unit/fleet-transcript.test.ts +435 -0
  1001. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +1786 -0
  1002. package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +125 -0
  1003. package/dist/extensions/pi-subagents/test/unit/foreground-tool-call-compaction.test.ts +115 -0
  1004. package/dist/extensions/pi-subagents/test/unit/fork-cache-key.test.ts +91 -0
  1005. package/dist/extensions/pi-subagents/test/unit/fork-context.test.ts +588 -0
  1006. package/dist/extensions/pi-subagents/test/unit/formatters.test.ts +14 -0
  1007. package/dist/extensions/pi-subagents/test/unit/get-final-output.test.ts +175 -0
  1008. package/dist/extensions/pi-subagents/test/unit/herdr-inspector-bootstrap.test.ts +101 -0
  1009. package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +479 -0
  1010. package/dist/extensions/pi-subagents/test/unit/herdr-session-roots-codec.test.ts +63 -0
  1011. package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +59 -0
  1012. package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +716 -0
  1013. package/dist/extensions/pi-subagents/test/unit/host-command.test.ts +157 -0
  1014. package/dist/extensions/pi-subagents/test/unit/host-peer-runtime-imports.test.ts +157 -0
  1015. package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +98 -0
  1016. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +1307 -0
  1017. package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +96 -0
  1018. package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +617 -0
  1019. package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +220 -0
  1020. package/dist/extensions/pi-subagents/test/unit/jsonl-writer.test.ts +119 -0
  1021. package/dist/extensions/pi-subagents/test/unit/llm-intent-arbiter.test.ts +226 -0
  1022. package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-grant.test.ts +155 -0
  1023. package/dist/extensions/pi-subagents/test/unit/mission-goal-driver.test.ts +180 -0
  1024. package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +300 -0
  1025. package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +470 -0
  1026. package/dist/extensions/pi-subagents/test/unit/mock-pi.test.ts +22 -0
  1027. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +258 -0
  1028. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +903 -0
  1029. package/dist/extensions/pi-subagents/test/unit/model-info.test.ts +162 -0
  1030. package/dist/extensions/pi-subagents/test/unit/model-scope-settings.test.ts +101 -0
  1031. package/dist/extensions/pi-subagents/test/unit/model-scope.test.ts +198 -0
  1032. package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +177 -0
  1033. package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +796 -0
  1034. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +655 -0
  1035. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +492 -0
  1036. package/dist/extensions/pi-subagents/test/unit/node-executable.test.ts +26 -0
  1037. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +816 -0
  1038. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +545 -0
  1039. package/dist/extensions/pi-subagents/test/unit/owned-process-tree.test.ts +69 -0
  1040. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +241 -0
  1041. package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +563 -0
  1042. package/dist/extensions/pi-subagents/test/unit/parallel-utils.test.ts +269 -0
  1043. package/dist/extensions/pi-subagents/test/unit/path-handling.test.ts +108 -0
  1044. package/dist/extensions/pi-subagents/test/unit/path-resolution.test.ts +103 -0
  1045. package/dist/extensions/pi-subagents/test/unit/permissions.test.ts +46 -0
  1046. package/dist/extensions/pi-subagents/test/unit/pi-args-permission-system.test.ts +437 -0
  1047. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +2347 -0
  1048. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +461 -0
  1049. package/dist/extensions/pi-subagents/test/unit/pi-spawn.test.ts +493 -0
  1050. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +978 -0
  1051. package/dist/extensions/pi-subagents/test/unit/proactive-skills.test.ts +118 -0
  1052. package/dist/extensions/pi-subagents/test/unit/process-terminal.test.ts +279 -0
  1053. package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +373 -0
  1054. package/dist/extensions/pi-subagents/test/unit/project-panes-public-api.test.ts +293 -0
  1055. package/dist/extensions/pi-subagents/test/unit/prompt-template-bridge.test.ts +244 -0
  1056. package/dist/extensions/pi-subagents/test/unit/prompt-workflows.test.ts +167 -0
  1057. package/dist/extensions/pi-subagents/test/unit/pruned-fork.test.ts +214 -0
  1058. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +182 -0
  1059. package/dist/extensions/pi-subagents/test/unit/reads-resolution.test.ts +66 -0
  1060. package/dist/extensions/pi-subagents/test/unit/recursion-guard.test.ts +265 -0
  1061. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +639 -0
  1062. package/dist/extensions/pi-subagents/test/unit/result-delivery-ownership.test.ts +34 -0
  1063. package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +501 -0
  1064. package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +258 -0
  1065. package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +191 -0
  1066. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +1124 -0
  1067. package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +191 -0
  1068. package/dist/extensions/pi-subagents/test/unit/run-id-resolver.test.ts +247 -0
  1069. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +1545 -0
  1070. package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +52 -0
  1071. package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +349 -0
  1072. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +904 -0
  1073. package/dist/extensions/pi-subagents/test/unit/scheduled-store-root.test.ts +67 -0
  1074. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +657 -0
  1075. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +2501 -0
  1076. package/dist/extensions/pi-subagents/test/unit/selector.test.ts +57 -0
  1077. package/dist/extensions/pi-subagents/test/unit/session-lease.test.ts +339 -0
  1078. package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +361 -0
  1079. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +709 -0
  1080. package/dist/extensions/pi-subagents/test/unit/slash-bridge.test.ts +115 -0
  1081. package/dist/extensions/pi-subagents/test/unit/spawn-budget.test.ts +124 -0
  1082. package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +440 -0
  1083. package/dist/extensions/pi-subagents/test/unit/status-format.test.ts +26 -0
  1084. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +435 -0
  1085. package/dist/extensions/pi-subagents/test/unit/steering-notices.test.ts +58 -0
  1086. package/dist/extensions/pi-subagents/test/unit/steering.test.ts +217 -0
  1087. package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +78 -0
  1088. package/dist/extensions/pi-subagents/test/unit/subagent-action-recovery.test.ts +85 -0
  1089. package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +342 -0
  1090. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +37 -0
  1091. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +1593 -0
  1092. package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +104 -0
  1093. package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +1367 -0
  1094. package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +153 -0
  1095. package/dist/extensions/pi-subagents/test/unit/temp-paths.test.ts +147 -0
  1096. package/dist/extensions/pi-subagents/test/unit/thinking-ceiling.test.ts +73 -0
  1097. package/dist/extensions/pi-subagents/test/unit/timeout-defaults.test.ts +138 -0
  1098. package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +67 -0
  1099. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +308 -0
  1100. package/dist/extensions/pi-subagents/test/unit/tool-timeout.test.ts +108 -0
  1101. package/dist/extensions/pi-subagents/test/unit/total-cost.test.ts +61 -0
  1102. package/dist/extensions/pi-subagents/test/unit/ts-loader.test.ts +33 -0
  1103. package/dist/extensions/pi-subagents/test/unit/types-fork-preamble.test.ts +23 -0
  1104. package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +110 -0
  1105. package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +663 -0
  1106. package/dist/extensions/pi-subagents/test/unit/watch-strategy.test.ts +24 -0
  1107. package/dist/extensions/pi-subagents/test/unit/watchdog-change-signature.test.ts +434 -0
  1108. package/dist/extensions/pi-subagents/test/unit/watchdog-child-status.test.ts +170 -0
  1109. package/dist/extensions/pi-subagents/test/unit/watchdog-diff-tool.test.ts +79 -0
  1110. package/dist/extensions/pi-subagents/test/unit/watchdog-emission-guard.test.ts +62 -0
  1111. package/dist/extensions/pi-subagents/test/unit/watchdog-lsp-diagnostics.test.ts +144 -0
  1112. package/dist/extensions/pi-subagents/test/unit/watchdog-model-selection.test.ts +121 -0
  1113. package/dist/extensions/pi-subagents/test/unit/watchdog-permission-arbiter.test.ts +113 -0
  1114. package/dist/extensions/pi-subagents/test/unit/watchdog-render.test.ts +75 -0
  1115. package/dist/extensions/pi-subagents/test/unit/watchdog-review.test.ts +372 -0
  1116. package/dist/extensions/pi-subagents/test/unit/watchdog-rules.test.ts +37 -0
  1117. package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +990 -0
  1118. package/dist/extensions/pi-subagents/test/unit/watchdog-scope.test.ts +33 -0
  1119. package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +345 -0
  1120. package/dist/extensions/pi-subagents/test/unit/watchdog-tool-actions.test.ts +91 -0
  1121. package/dist/extensions/pi-subagents/test/unit/watchdog-turn-delta.test.ts +130 -0
  1122. package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +171 -0
  1123. package/dist/extensions/pi-subagents/test/unit/windows-hide-spawn.test.ts +49 -0
  1124. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +570 -0
  1125. package/dist/extensions/pi-subagents/test/unit/workflow-checklist.test.ts +223 -0
  1126. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +777 -0
  1127. package/dist/extensions/pi-subagents/test/unit/workflow-graph.test.ts +134 -0
  1128. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +407 -0
  1129. package/dist/extensions/pi-subagents/test/unit/workflow-preflight.test.ts +177 -0
  1130. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +461 -0
  1131. package/dist/extensions/pi-subagents/test/unit/workflow-resources.test.ts +98 -0
  1132. package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +365 -0
  1133. package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +349 -0
  1134. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +827 -0
  1135. package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +25 -0
  1136. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/index.ts +13 -0
  1137. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/rules/no-service-constructor-imports.ts +52 -0
  1138. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/index.ts +41 -0
  1139. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-chained-type-assertions.ts +77 -0
  1140. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-conditional-empty-object-spread.ts +49 -0
  1141. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-known-value-widening.ts +247 -0
  1142. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-module-mocking.ts +91 -0
  1143. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-object-parameters.ts +126 -0
  1144. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-apply.ts +28 -0
  1145. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-get.ts +28 -0
  1146. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-runtime-typeof.ts +67 -0
  1147. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-shape-in-symbol-names.ts +39 -0
  1148. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-parameters.ts +83 -0
  1149. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-returns.ts +115 -0
  1150. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-type-aliases.ts +72 -0
  1151. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unsafe-dictionary-type.ts +134 -0
  1152. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-widen-then-assert.ts +366 -0
  1153. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/require-safety-comment-for-type-assertion.ts +62 -0
  1154. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/dictionary-types.ts +502 -0
  1155. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/lexical-type-parameters.ts +60 -0
  1156. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/reflect-method.ts +35 -0
  1157. package/dist/extensions/pi-subagents/tsconfig.json +15 -0
  1158. package/dist/extensions/pi-tool-display/CHANGELOG.md +329 -0
  1159. package/dist/extensions/pi-tool-display/LICENSE +21 -0
  1160. package/dist/extensions/pi-tool-display/README.md +417 -0
  1161. package/dist/extensions/pi-tool-display/config/config.example.json +40 -0
  1162. package/dist/extensions/pi-tool-display/index.ts +3 -0
  1163. package/dist/extensions/pi-tool-display/package-lock.json +2555 -0
  1164. package/dist/extensions/pi-tool-display/package.json +86 -0
  1165. package/dist/extensions/pi-tool-display/src/agent-dir.ts +35 -0
  1166. package/dist/extensions/pi-tool-display/src/ansi-utils.ts +116 -0
  1167. package/dist/extensions/pi-tool-display/src/bash-display.ts +213 -0
  1168. package/dist/extensions/pi-tool-display/src/capabilities.ts +88 -0
  1169. package/dist/extensions/pi-tool-display/src/config-modal.ts +541 -0
  1170. package/dist/extensions/pi-tool-display/src/config-store.ts +304 -0
  1171. package/dist/extensions/pi-tool-display/src/debug-logger.ts +150 -0
  1172. package/dist/extensions/pi-tool-display/src/diff-presentation.ts +72 -0
  1173. package/dist/extensions/pi-tool-display/src/diff-renderer.ts +2517 -0
  1174. package/dist/extensions/pi-tool-display/src/disposable.ts +34 -0
  1175. package/dist/extensions/pi-tool-display/src/extension-lifecycle.ts +14 -0
  1176. package/dist/extensions/pi-tool-display/src/index.ts +109 -0
  1177. package/dist/extensions/pi-tool-display/src/line-width-safety.ts +93 -0
  1178. package/dist/extensions/pi-tool-display/src/modal-icons.ts +57 -0
  1179. package/dist/extensions/pi-tool-display/src/pending-diff-preview.ts +370 -0
  1180. package/dist/extensions/pi-tool-display/src/presets.ts +117 -0
  1181. package/dist/extensions/pi-tool-display/src/render-utils.ts +186 -0
  1182. package/dist/extensions/pi-tool-display/src/settings-inspector-modal.ts +475 -0
  1183. package/dist/extensions/pi-tool-display/src/thinking-label.ts +343 -0
  1184. package/dist/extensions/pi-tool-display/src/tool-call-box.ts +181 -0
  1185. package/dist/extensions/pi-tool-display/src/tool-metadata.ts +139 -0
  1186. package/dist/extensions/pi-tool-display/src/tool-overrides.ts +2168 -0
  1187. package/dist/extensions/pi-tool-display/src/types.ts +109 -0
  1188. package/dist/extensions/pi-tool-display/src/user-message-box-markdown.ts +64 -0
  1189. package/dist/extensions/pi-tool-display/src/user-message-box-native.ts +66 -0
  1190. package/dist/extensions/pi-tool-display/src/user-message-box-patch.ts +72 -0
  1191. package/dist/extensions/pi-tool-display/src/user-message-box-renderer.ts +419 -0
  1192. package/dist/extensions/pi-tool-display/src/user-message-box-utils.ts +106 -0
  1193. package/dist/extensions/pi-tool-display/src/write-display-utils.ts +31 -0
  1194. package/dist/extensions/pi-tool-display/src/zellij-modal.ts +1027 -0
  1195. package/dist/extensions/pi-tool-display/tests/active-backlog-red.test.ts +65 -0
  1196. package/dist/extensions/pi-tool-display/tests/ansi-utils.test.ts +345 -0
  1197. package/dist/extensions/pi-tool-display/tests/bash-display.test.ts +442 -0
  1198. package/dist/extensions/pi-tool-display/tests/capabilities-edge.test.ts +360 -0
  1199. package/dist/extensions/pi-tool-display/tests/capabilities.test.ts +54 -0
  1200. package/dist/extensions/pi-tool-display/tests/config-modal.test.ts +360 -0
  1201. package/dist/extensions/pi-tool-display/tests/config-store.test.ts +87 -0
  1202. package/dist/extensions/pi-tool-display/tests/custom-tool-overrides.test.ts +415 -0
  1203. package/dist/extensions/pi-tool-display/tests/debug-logger-edge.test.ts +630 -0
  1204. package/dist/extensions/pi-tool-display/tests/debug-logger.test.ts +62 -0
  1205. package/dist/extensions/pi-tool-display/tests/diff-renderer-ansi.test.ts +55 -0
  1206. package/dist/extensions/pi-tool-display/tests/diff-renderer-edge.test.ts +886 -0
  1207. package/dist/extensions/pi-tool-display/tests/diff-renderer-numbering.test.ts +135 -0
  1208. package/dist/extensions/pi-tool-display/tests/diff-renderer-width.test.ts +454 -0
  1209. package/dist/extensions/pi-tool-display/tests/diff-renderer-wrap.test.ts +169 -0
  1210. package/dist/extensions/pi-tool-display/tests/index-integration.test.ts +354 -0
  1211. package/dist/extensions/pi-tool-display/tests/pending-diff-preview.test.ts +79 -0
  1212. package/dist/extensions/pi-tool-display/tests/presets-edge.test.ts +229 -0
  1213. package/dist/extensions/pi-tool-display/tests/presets.test.ts +26 -0
  1214. package/dist/extensions/pi-tool-display/tests/reload-behavior.test.ts +1241 -0
  1215. package/dist/extensions/pi-tool-display/tests/render-utils.test.ts +710 -0
  1216. package/dist/extensions/pi-tool-display/tests/settings-inspector.test.ts +450 -0
  1217. package/dist/extensions/pi-tool-display/tests/thinking-label-edge.test.ts +904 -0
  1218. package/dist/extensions/pi-tool-display/tests/thinking-label.test.ts +72 -0
  1219. package/dist/extensions/pi-tool-display/tests/tool-call-box.test.ts +105 -0
  1220. package/dist/extensions/pi-tool-display/tests/tool-overrides-config.test.ts +613 -0
  1221. package/dist/extensions/pi-tool-display/tests/tool-overrides-mcp.test.ts +499 -0
  1222. package/dist/extensions/pi-tool-display/tests/tool-overrides-registration.test.ts +315 -0
  1223. package/dist/extensions/pi-tool-display/tests/tool-overrides-write-meta.test.ts +68 -0
  1224. package/dist/extensions/pi-tool-display/tests/tool-ui-utils.test.ts +413 -0
  1225. package/dist/extensions/pi-tool-display/tests/user-message-box-performance-red.test.ts +176 -0
  1226. package/dist/extensions/pi-tool-display/tests/user-message-box.test.ts +908 -0
  1227. package/dist/extensions/pi-tool-display/tests/zellij-modal.test.ts +848 -0
  1228. package/dist/extensions/pi-tool-display/tool-display-api-consumer.d.ts +30 -0
  1229. package/dist/extensions/pi-tool-display/tool-display-api-consumer.js +40 -0
  1230. package/dist/extensions/pi-web-agent/CHANGELOG.md +410 -0
  1231. package/dist/extensions/pi-web-agent/README.md +131 -0
  1232. package/dist/extensions/pi-web-agent/package.json +33 -0
  1233. package/dist/extensions/pi-web-agent/src/backends/config.ts +264 -0
  1234. package/dist/extensions/pi-web-agent/src/backends/doctor.ts +272 -0
  1235. package/dist/extensions/pi-web-agent/src/backends/factory.ts +253 -0
  1236. package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +46 -0
  1237. package/dist/extensions/pi-web-agent/src/cache/ttl-cache.ts +28 -0
  1238. package/dist/extensions/pi-web-agent/src/changelog-notice.ts +136 -0
  1239. package/dist/extensions/pi-web-agent/src/commands/web-agent-config.ts +1082 -0
  1240. package/dist/extensions/pi-web-agent/src/extension.ts +163 -0
  1241. package/dist/extensions/pi-web-agent/src/extract/readability.ts +126 -0
  1242. package/dist/extensions/pi-web-agent/src/fetch/browser-resolution.ts +199 -0
  1243. package/dist/extensions/pi-web-agent/src/fetch/firecrawl-fetch.ts +100 -0
  1244. package/dist/extensions/pi-web-agent/src/fetch/headless-fetch.ts +117 -0
  1245. package/dist/extensions/pi-web-agent/src/fetch/http-fetch.ts +67 -0
  1246. package/dist/extensions/pi-web-agent/src/orchestration/answer-synthesizer.ts +60 -0
  1247. package/dist/extensions/pi-web-agent/src/orchestration/candidate-selector.ts +51 -0
  1248. package/dist/extensions/pi-web-agent/src/orchestration/direct-url.ts +29 -0
  1249. package/dist/extensions/pi-web-agent/src/orchestration/evidence-quality.ts +108 -0
  1250. package/dist/extensions/pi-web-agent/src/orchestration/evidence-ranker.ts +47 -0
  1251. package/dist/extensions/pi-web-agent/src/orchestration/index.ts +28 -0
  1252. package/dist/extensions/pi-web-agent/src/orchestration/query-planner.ts +47 -0
  1253. package/dist/extensions/pi-web-agent/src/orchestration/research-orchestrator.ts +441 -0
  1254. package/dist/extensions/pi-web-agent/src/orchestration/research-types.ts +71 -0
  1255. package/dist/extensions/pi-web-agent/src/orchestration/research-worker.ts +206 -0
  1256. package/dist/extensions/pi-web-agent/src/orchestration/source-profile.ts +105 -0
  1257. package/dist/extensions/pi-web-agent/src/orchestration/stop-decider.ts +81 -0
  1258. package/dist/extensions/pi-web-agent/src/orchestration/url.ts +35 -0
  1259. package/dist/extensions/pi-web-agent/src/presentation/config-store.ts +210 -0
  1260. package/dist/extensions/pi-web-agent/src/presentation/config.ts +75 -0
  1261. package/dist/extensions/pi-web-agent/src/presentation/explore-presentation.ts +73 -0
  1262. package/dist/extensions/pi-web-agent/src/presentation/fetch-presentation.ts +54 -0
  1263. package/dist/extensions/pi-web-agent/src/presentation/search-presentation.ts +53 -0
  1264. package/dist/extensions/pi-web-agent/src/presentation/select-view.ts +20 -0
  1265. package/dist/extensions/pi-web-agent/src/presentation/types.ts +63 -0
  1266. package/dist/extensions/pi-web-agent/src/readers/github-reader.ts +150 -0
  1267. package/dist/extensions/pi-web-agent/src/readers/limits.ts +3 -0
  1268. package/dist/extensions/pi-web-agent/src/readers/pdf-reader.ts +87 -0
  1269. package/dist/extensions/pi-web-agent/src/readers/resolver.ts +25 -0
  1270. package/dist/extensions/pi-web-agent/src/readers/types.ts +11 -0
  1271. package/dist/extensions/pi-web-agent/src/readers/youtube-reader.ts +79 -0
  1272. package/dist/extensions/pi-web-agent/src/search/brave.ts +114 -0
  1273. package/dist/extensions/pi-web-agent/src/search/duckduckgo.ts +99 -0
  1274. package/dist/extensions/pi-web-agent/src/search/exa.ts +109 -0
  1275. package/dist/extensions/pi-web-agent/src/search/fanout.ts +154 -0
  1276. package/dist/extensions/pi-web-agent/src/search/searxng.ts +96 -0
  1277. package/dist/extensions/pi-web-agent/src/search/tavily.ts +113 -0
  1278. package/dist/extensions/pi-web-agent/src/search/tokenin.ts +130 -0
  1279. package/dist/extensions/pi-web-agent/src/search/youcom.ts +109 -0
  1280. package/dist/extensions/pi-web-agent/src/tools/web-explore.ts +71 -0
  1281. package/dist/extensions/pi-web-agent/src/tools/web-fetch-headless.ts +31 -0
  1282. package/dist/extensions/pi-web-agent/src/tools/web-fetch.ts +31 -0
  1283. package/dist/extensions/pi-web-agent/src/tools/web-search.ts +170 -0
  1284. package/dist/extensions/pi-web-agent/src/types.ts +103 -0
  1285. package/dist/extensions/pi-zentui/.editorconfig +12 -0
  1286. package/dist/extensions/pi-zentui/.github/CODEOWNERS +1 -0
  1287. package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/bug_report.yml +110 -0
  1288. package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/config.yml +8 -0
  1289. package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/config_question.yml +56 -0
  1290. package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/feature_request.yml +63 -0
  1291. package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/rendering_issue.yml +106 -0
  1292. package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/runtime_detection.yml +103 -0
  1293. package/dist/extensions/pi-zentui/.github/dependabot.yml +47 -0
  1294. package/dist/extensions/pi-zentui/.github/pull_request_template.md +34 -0
  1295. package/dist/extensions/pi-zentui/.github/release.yml +18 -0
  1296. package/dist/extensions/pi-zentui/.github/workflows/ci.yml +79 -0
  1297. package/dist/extensions/pi-zentui/.github/workflows/publish.yml +63 -0
  1298. package/dist/extensions/pi-zentui/AGENTS.md +107 -0
  1299. package/dist/extensions/pi-zentui/CONTRIBUTING.md +68 -0
  1300. package/dist/extensions/pi-zentui/LICENSE +21 -0
  1301. package/dist/extensions/pi-zentui/README.md +202 -0
  1302. package/dist/extensions/pi-zentui/SECURITY.md +18 -0
  1303. package/dist/extensions/pi-zentui/assets/main-cover.png +0 -0
  1304. package/dist/extensions/pi-zentui/assets/screenshots/editor-accent-rail.png +0 -0
  1305. package/dist/extensions/pi-zentui/assets/screenshots/editor-minimalist.png +0 -0
  1306. package/dist/extensions/pi-zentui/assets/screenshots/editor-opencode-copy-friendly.png +0 -0
  1307. package/dist/extensions/pi-zentui/assets/screenshots/editor-opencode.png +0 -0
  1308. package/dist/extensions/pi-zentui/assets/screenshots/user-message-compact.png +0 -0
  1309. package/dist/extensions/pi-zentui/assets/screenshots/user-message-framed-copy-friendly.png +0 -0
  1310. package/dist/extensions/pi-zentui/assets/screenshots/user-message-framed.png +0 -0
  1311. package/dist/extensions/pi-zentui/assets/screenshots/user-message-labeled.png +0 -0
  1312. package/dist/extensions/pi-zentui/assets/zentui.png +0 -0
  1313. package/dist/extensions/pi-zentui/biome.json +31 -0
  1314. package/dist/extensions/pi-zentui/docs/configuration.md +537 -0
  1315. package/dist/extensions/pi-zentui/docs/footer-format.md +162 -0
  1316. package/dist/extensions/pi-zentui/extensions/zentui/accent-rail-editor.ts +99 -0
  1317. package/dist/extensions/pi-zentui/extensions/zentui/accent-rail-layout-patch.ts +457 -0
  1318. package/dist/extensions/pi-zentui/extensions/zentui/completion-menu.ts +157 -0
  1319. package/dist/extensions/pi-zentui/extensions/zentui/config.ts +2129 -0
  1320. package/dist/extensions/pi-zentui/extensions/zentui/editor-metadata-format.ts +321 -0
  1321. package/dist/extensions/pi-zentui/extensions/zentui/editor-transfer.ts +73 -0
  1322. package/dist/extensions/pi-zentui/extensions/zentui/extension-status.ts +89 -0
  1323. package/dist/extensions/pi-zentui/extensions/zentui/footer-format.ts +364 -0
  1324. package/dist/extensions/pi-zentui/extensions/zentui/footer-layout.ts +122 -0
  1325. package/dist/extensions/pi-zentui/extensions/zentui/footer.ts +812 -0
  1326. package/dist/extensions/pi-zentui/extensions/zentui/format.ts +620 -0
  1327. package/dist/extensions/pi-zentui/extensions/zentui/git.ts +384 -0
  1328. package/dist/extensions/pi-zentui/extensions/zentui/icons.ts +252 -0
  1329. package/dist/extensions/pi-zentui/extensions/zentui/index.ts +1445 -0
  1330. package/dist/extensions/pi-zentui/extensions/zentui/interaction-summary.ts +1049 -0
  1331. package/dist/extensions/pi-zentui/extensions/zentui/live-context.ts +75 -0
  1332. package/dist/extensions/pi-zentui/extensions/zentui/minimalist-editor.ts +463 -0
  1333. package/dist/extensions/pi-zentui/extensions/zentui/package-version.ts +651 -0
  1334. package/dist/extensions/pi-zentui/extensions/zentui/project-refresh.ts +120 -0
  1335. package/dist/extensions/pi-zentui/extensions/zentui/project-state.ts +59 -0
  1336. package/dist/extensions/pi-zentui/extensions/zentui/prototype-patch-registry.ts +210 -0
  1337. package/dist/extensions/pi-zentui/extensions/zentui/repository-root.ts +98 -0
  1338. package/dist/extensions/pi-zentui/extensions/zentui/runtime.ts +841 -0
  1339. package/dist/extensions/pi-zentui/extensions/zentui/selector-border.ts +93 -0
  1340. package/dist/extensions/pi-zentui/extensions/zentui/session-lifecycle.ts +60 -0
  1341. package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +1908 -0
  1342. package/dist/extensions/pi-zentui/extensions/zentui/settings-previews.ts +245 -0
  1343. package/dist/extensions/pi-zentui/extensions/zentui/state.ts +94 -0
  1344. package/dist/extensions/pi-zentui/extensions/zentui/style.ts +424 -0
  1345. package/dist/extensions/pi-zentui/extensions/zentui/telemetry.ts +82 -0
  1346. package/dist/extensions/pi-zentui/extensions/zentui/thinking-experimental.ts +1768 -0
  1347. package/dist/extensions/pi-zentui/extensions/zentui/thinking-status.ts +69 -0
  1348. package/dist/extensions/pi-zentui/extensions/zentui/thinking-steps.ts +155 -0
  1349. package/dist/extensions/pi-zentui/extensions/zentui/ui.ts +1291 -0
  1350. package/dist/extensions/pi-zentui/extensions/zentui/user-message-osc.ts +262 -0
  1351. package/dist/extensions/pi-zentui/extensions/zentui/user-message-styles.ts +215 -0
  1352. package/dist/extensions/pi-zentui/extensions/zentui/user-message.ts +206 -0
  1353. package/dist/extensions/pi-zentui/extensions/zentui/working-line-messages.ts +24 -0
  1354. package/dist/extensions/pi-zentui/extensions/zentui/working-line-spinners.ts +54 -0
  1355. package/dist/extensions/pi-zentui/extensions/zentui/working-line.ts +1433 -0
  1356. package/dist/extensions/pi-zentui/package-lock.json +5311 -0
  1357. package/dist/extensions/pi-zentui/package.json +60 -0
  1358. package/dist/extensions/pi-zentui/test/accent-rail-editor.test.ts +232 -0
  1359. package/dist/extensions/pi-zentui/test/accent-rail-layout-patch.test.ts +669 -0
  1360. package/dist/extensions/pi-zentui/test/completion-menu.test.ts +265 -0
  1361. package/dist/extensions/pi-zentui/test/config-load-lifecycle.test.ts +124 -0
  1362. package/dist/extensions/pi-zentui/test/config.test.ts +3199 -0
  1363. package/dist/extensions/pi-zentui/test/editor-metadata-format.test.ts +405 -0
  1364. package/dist/extensions/pi-zentui/test/editor-transfer.test.ts +260 -0
  1365. package/dist/extensions/pi-zentui/test/editor-viewport-indicators.test.ts +1301 -0
  1366. package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +7245 -0
  1367. package/dist/extensions/pi-zentui/test/extension-status.test.ts +182 -0
  1368. package/dist/extensions/pi-zentui/test/fixtures/starship-nerd-font-symbols.toml +172 -0
  1369. package/dist/extensions/pi-zentui/test/footer-format.test.ts +431 -0
  1370. package/dist/extensions/pi-zentui/test/footer-layout.test.ts +113 -0
  1371. package/dist/extensions/pi-zentui/test/footer-repository-path.test.ts +123 -0
  1372. package/dist/extensions/pi-zentui/test/format.test.ts +927 -0
  1373. package/dist/extensions/pi-zentui/test/git.test.ts +212 -0
  1374. package/dist/extensions/pi-zentui/test/icons.test.ts +69 -0
  1375. package/dist/extensions/pi-zentui/test/interaction-summary.test.ts +1402 -0
  1376. package/dist/extensions/pi-zentui/test/live-context-integration.test.ts +378 -0
  1377. package/dist/extensions/pi-zentui/test/live-context.test.ts +139 -0
  1378. package/dist/extensions/pi-zentui/test/minimalist-editor.test.ts +811 -0
  1379. package/dist/extensions/pi-zentui/test/package-contents.mjs +33 -0
  1380. package/dist/extensions/pi-zentui/test/package-version.test.ts +321 -0
  1381. package/dist/extensions/pi-zentui/test/project-refresh.test.ts +250 -0
  1382. package/dist/extensions/pi-zentui/test/project-state.test.ts +159 -0
  1383. package/dist/extensions/pi-zentui/test/prototype-patch-registry.test.ts +131 -0
  1384. package/dist/extensions/pi-zentui/test/repository-root.test.ts +108 -0
  1385. package/dist/extensions/pi-zentui/test/responsive-dependencies.test.ts +825 -0
  1386. package/dist/extensions/pi-zentui/test/runtime.test.ts +183 -0
  1387. package/dist/extensions/pi-zentui/test/session-lifecycle.test.ts +40 -0
  1388. package/dist/extensions/pi-zentui/test/settings-command.test.ts +1663 -0
  1389. package/dist/extensions/pi-zentui/test/settings-previews.test.ts +453 -0
  1390. package/dist/extensions/pi-zentui/test/state.test.ts +84 -0
  1391. package/dist/extensions/pi-zentui/test/telemetry-lifecycle-integration.test.ts +276 -0
  1392. package/dist/extensions/pi-zentui/test/telemetry.test.ts +105 -0
  1393. package/dist/extensions/pi-zentui/test/thinking-experimental-docs.test.ts +51 -0
  1394. package/dist/extensions/pi-zentui/test/thinking-experimental-loader-diagnostics.mjs +54 -0
  1395. package/dist/extensions/pi-zentui/test/thinking-experimental-missing-export.test.ts +44 -0
  1396. package/dist/extensions/pi-zentui/test/thinking-experimental-rows.test.ts +297 -0
  1397. package/dist/extensions/pi-zentui/test/thinking-experimental-tui.mjs +2329 -0
  1398. package/dist/extensions/pi-zentui/test/thinking-experimental.test.ts +1668 -0
  1399. package/dist/extensions/pi-zentui/test/thinking-status.test.ts +85 -0
  1400. package/dist/extensions/pi-zentui/test/thinking-steps.test.ts +122 -0
  1401. package/dist/extensions/pi-zentui/test/turn-summary-lifecycle.integration.test.ts +327 -0
  1402. package/dist/extensions/pi-zentui/test/user-message-osc.test.ts +222 -0
  1403. package/dist/extensions/pi-zentui/test/user-message-styles.test.ts +292 -0
  1404. package/dist/extensions/pi-zentui/test/working-line-lifecycle.integration.test.ts +730 -0
  1405. package/dist/extensions/pi-zentui/test/working-line-messages.test.ts +34 -0
  1406. package/dist/extensions/pi-zentui/test/working-line.test.ts +1990 -0
  1407. package/dist/extensions/pi-zentui/tsconfig.json +16 -0
  1408. package/dist/extensions/ponytail/index.js +176 -0
  1409. package/dist/extensions/ponytail/package.json +8 -0
  1410. package/dist/extensions/ponytail/ponytail-config.cjs +151 -0
  1411. package/dist/extensions/ponytail/ponytail-instructions.cjs +112 -0
  1412. package/dist/extensions/ponytail/test/extension.test.js +299 -0
  1413. package/dist/extensions/ponytail/test/helpers.test.js +312 -0
  1414. package/dist/extensions/question/batch.ts +103 -0
  1415. package/dist/extensions/question/constants.ts +31 -0
  1416. package/dist/extensions/question/helpers.ts +58 -0
  1417. package/dist/extensions/question/index.ts +688 -0
  1418. package/dist/extensions/question/navigation.ts +14 -0
  1419. package/dist/extensions/question/package.json +19 -0
  1420. package/dist/extensions/question/question-list.ts +533 -0
  1421. package/dist/extensions/question/row-layout.ts +165 -0
  1422. package/dist/extensions/question/schemas.ts +43 -0
  1423. package/dist/extensions/question/selection-mode.ts +47 -0
  1424. package/dist/extensions/question/shortcuts.ts +44 -0
  1425. package/dist/extensions/question/tests/batch.test.ts +113 -0
  1426. package/dist/extensions/question/tests/exp.test.ts +70 -0
  1427. package/dist/extensions/question/tests/exp2.test.ts +59 -0
  1428. package/dist/extensions/question/tests/exp3.test.ts +47 -0
  1429. package/dist/extensions/question/tests/helpers.test.ts +93 -0
  1430. package/dist/extensions/question/tests/question-list.test.ts +694 -0
  1431. package/dist/extensions/question/tests/row-layout.test.ts +215 -0
  1432. package/dist/extensions/question/tests/schemas.test.ts +53 -0
  1433. package/dist/extensions/question/tests/selection-mode.test.ts +54 -0
  1434. package/dist/extensions/question/tests/shortcuts.test.ts +107 -0
  1435. package/dist/extensions/question/tests/wizard.test.ts +839 -0
  1436. package/dist/extensions/question/tests/zz-ig3.test.ts +20 -0
  1437. package/dist/extensions/question/tests/zz-probe.test.ts +29 -0
  1438. package/dist/extensions/question/types.ts +132 -0
  1439. package/dist/extensions/rtk.test.ts +320 -0
  1440. package/dist/extensions/rtk.ts +123 -0
  1441. package/dist/extensions/test-resolve-hook-impl.mjs +7 -0
  1442. package/dist/extensions/test-resolve-hook.mjs +7 -0
  1443. package/dist/extensions/tokenin-onboarding.ts +883 -0
  1444. package/dist/extensions/tps.test.ts +38 -0
  1445. package/dist/extensions/tps.ts +349 -0
  1446. package/dist/extensions/undo.test.ts +720 -0
  1447. package/dist/extensions/undo.ts +298 -0
  1448. package/dist/extensions/web-agent-onboarding.test.ts +415 -0
  1449. package/dist/extensions/web-agent-onboarding.ts +222 -0
  1450. package/dist/index.d.ts +36 -0
  1451. package/dist/index.js +48 -0
  1452. package/dist/main.d.ts +11 -0
  1453. package/dist/main.js +768 -0
  1454. package/dist/migrations.d.ts +32 -0
  1455. package/dist/migrations.js +280 -0
  1456. package/dist/modes/index.d.ts +8 -0
  1457. package/dist/modes/index.js +7 -0
  1458. package/dist/modes/interactive/assets/clankolas.png +0 -0
  1459. package/dist/modes/interactive/components/armin.d.ts +33 -0
  1460. package/dist/modes/interactive/components/armin.js +332 -0
  1461. package/dist/modes/interactive/components/assistant-message.d.ts +21 -0
  1462. package/dist/modes/interactive/components/assistant-message.js +142 -0
  1463. package/dist/modes/interactive/components/bash-execution.d.ts +33 -0
  1464. package/dist/modes/interactive/components/bash-execution.js +174 -0
  1465. package/dist/modes/interactive/components/bordered-loader.d.ts +15 -0
  1466. package/dist/modes/interactive/components/bordered-loader.js +53 -0
  1467. package/dist/modes/interactive/components/branch-summary-message.d.ts +15 -0
  1468. package/dist/modes/interactive/components/branch-summary-message.js +43 -0
  1469. package/dist/modes/interactive/components/compaction-summary-message.d.ts +15 -0
  1470. package/dist/modes/interactive/components/compaction-summary-message.js +44 -0
  1471. package/dist/modes/interactive/components/config-selector.d.ts +101 -0
  1472. package/dist/modes/interactive/components/config-selector.js +760 -0
  1473. package/dist/modes/interactive/components/countdown-timer.d.ts +13 -0
  1474. package/dist/modes/interactive/components/countdown-timer.js +32 -0
  1475. package/dist/modes/interactive/components/custom-editor.d.ts +20 -0
  1476. package/dist/modes/interactive/components/custom-editor.js +69 -0
  1477. package/dist/modes/interactive/components/custom-entry.d.ts +18 -0
  1478. package/dist/modes/interactive/components/custom-entry.js +51 -0
  1479. package/dist/modes/interactive/components/custom-message.d.ts +21 -0
  1480. package/dist/modes/interactive/components/custom-message.js +86 -0
  1481. package/dist/modes/interactive/components/daxnuts.d.ts +22 -0
  1482. package/dist/modes/interactive/components/daxnuts.js +139 -0
  1483. package/dist/modes/interactive/components/diff.d.ts +11 -0
  1484. package/dist/modes/interactive/components/diff.js +132 -0
  1485. package/dist/modes/interactive/components/dynamic-border.d.ts +14 -0
  1486. package/dist/modes/interactive/components/dynamic-border.js +20 -0
  1487. package/dist/modes/interactive/components/earendil-announcement.d.ts +4 -0
  1488. package/dist/modes/interactive/components/earendil-announcement.js +39 -0
  1489. package/dist/modes/interactive/components/extension-editor.d.ts +20 -0
  1490. package/dist/modes/interactive/components/extension-editor.js +97 -0
  1491. package/dist/modes/interactive/components/extension-input.d.ts +22 -0
  1492. package/dist/modes/interactive/components/extension-input.js +60 -0
  1493. package/dist/modes/interactive/components/extension-selector.d.ts +25 -0
  1494. package/dist/modes/interactive/components/extension-selector.js +82 -0
  1495. package/dist/modes/interactive/components/first-time-setup.d.ts +24 -0
  1496. package/dist/modes/interactive/components/first-time-setup.js +116 -0
  1497. package/dist/modes/interactive/components/footer.d.ts +31 -0
  1498. package/dist/modes/interactive/components/footer.js +221 -0
  1499. package/dist/modes/interactive/components/index.d.ts +33 -0
  1500. package/dist/modes/interactive/components/index.js +34 -0
  1501. package/dist/modes/interactive/components/keybinding-hints.d.ts +12 -0
  1502. package/dist/modes/interactive/components/keybinding-hints.js +35 -0
  1503. package/dist/modes/interactive/components/login-dialog.d.ts +51 -0
  1504. package/dist/modes/interactive/components/login-dialog.js +187 -0
  1505. package/dist/modes/interactive/components/model-selector.d.ts +63 -0
  1506. package/dist/modes/interactive/components/model-selector.js +321 -0
  1507. package/dist/modes/interactive/components/oauth-selector.d.ts +32 -0
  1508. package/dist/modes/interactive/components/oauth-selector.js +162 -0
  1509. package/dist/modes/interactive/components/scoped-models-selector.d.ts +41 -0
  1510. package/dist/modes/interactive/components/scoped-models-selector.js +301 -0
  1511. package/dist/modes/interactive/components/session-selector-search.d.ts +22 -0
  1512. package/dist/modes/interactive/components/session-selector-search.js +154 -0
  1513. package/dist/modes/interactive/components/session-selector.d.ts +94 -0
  1514. package/dist/modes/interactive/components/session-selector.js +866 -0
  1515. package/dist/modes/interactive/components/settings-selector.d.ts +103 -0
  1516. package/dist/modes/interactive/components/settings-selector.js +726 -0
  1517. package/dist/modes/interactive/components/show-images-selector.d.ts +9 -0
  1518. package/dist/modes/interactive/components/show-images-selector.js +38 -0
  1519. package/dist/modes/interactive/components/skill-invocation-message.d.ts +16 -0
  1520. package/dist/modes/interactive/components/skill-invocation-message.js +46 -0
  1521. package/dist/modes/interactive/components/startup-box.d.ts +38 -0
  1522. package/dist/modes/interactive/components/startup-box.js +90 -0
  1523. package/dist/modes/interactive/components/status-indicator.d.ts +30 -0
  1524. package/dist/modes/interactive/components/status-indicator.js +64 -0
  1525. package/dist/modes/interactive/components/theme-selector.d.ts +10 -0
  1526. package/dist/modes/interactive/components/theme-selector.js +49 -0
  1527. package/dist/modes/interactive/components/thinking-selector.d.ts +10 -0
  1528. package/dist/modes/interactive/components/thinking-selector.js +51 -0
  1529. package/dist/modes/interactive/components/tool-execution.d.ts +62 -0
  1530. package/dist/modes/interactive/components/tool-execution.js +325 -0
  1531. package/dist/modes/interactive/components/tree-selector.d.ts +93 -0
  1532. package/dist/modes/interactive/components/tree-selector.js +1244 -0
  1533. package/dist/modes/interactive/components/trust-selector.d.ts +22 -0
  1534. package/dist/modes/interactive/components/trust-selector.js +90 -0
  1535. package/dist/modes/interactive/components/user-message-selector.d.ts +29 -0
  1536. package/dist/modes/interactive/components/user-message-selector.js +113 -0
  1537. package/dist/modes/interactive/components/user-message.d.ts +13 -0
  1538. package/dist/modes/interactive/components/user-message.js +41 -0
  1539. package/dist/modes/interactive/components/visual-truncate.d.ts +23 -0
  1540. package/dist/modes/interactive/components/visual-truncate.js +32 -0
  1541. package/dist/modes/interactive/external-editor.d.ts +11 -0
  1542. package/dist/modes/interactive/external-editor.js +36 -0
  1543. package/dist/modes/interactive/interactive-mode.d.ts +447 -0
  1544. package/dist/modes/interactive/interactive-mode.js +5489 -0
  1545. package/dist/modes/interactive/model-catalog-refresh.d.ts +6 -0
  1546. package/dist/modes/interactive/model-catalog-refresh.js +33 -0
  1547. package/dist/modes/interactive/model-search.d.ts +11 -0
  1548. package/dist/modes/interactive/model-search.js +14 -0
  1549. package/dist/modes/interactive/theme/dark.json +90 -0
  1550. package/dist/modes/interactive/theme/light.json +89 -0
  1551. package/dist/modes/interactive/theme/theme-controller.d.ts +39 -0
  1552. package/dist/modes/interactive/theme/theme-controller.js +124 -0
  1553. package/dist/modes/interactive/theme/theme-schema.json +348 -0
  1554. package/dist/modes/interactive/theme/theme.d.ts +121 -0
  1555. package/dist/modes/interactive/theme/theme.js +1090 -0
  1556. package/dist/modes/print-mode.d.ts +27 -0
  1557. package/dist/modes/print-mode.js +141 -0
  1558. package/dist/modes/rpc/jsonl.d.ts +16 -0
  1559. package/dist/modes/rpc/jsonl.js +48 -0
  1560. package/dist/modes/rpc/rpc-client.d.ts +438 -0
  1561. package/dist/modes/rpc/rpc-client.js +712 -0
  1562. package/dist/modes/rpc/rpc-mode.d.ts +19 -0
  1563. package/dist/modes/rpc/rpc-mode.js +1459 -0
  1564. package/dist/modes/rpc/rpc-types.d.ts +902 -0
  1565. package/dist/modes/rpc/rpc-types.js +7 -0
  1566. package/dist/package-manager-cli.d.ts +7 -0
  1567. package/dist/package-manager-cli.js +789 -0
  1568. package/dist/rpc-entry.d.ts +2 -0
  1569. package/dist/rpc-entry.js +9 -0
  1570. package/dist/skills/agent-browser/SKILL.md +53 -0
  1571. package/dist/skills/batch-grill-me/SKILL.md +20 -0
  1572. package/dist/skills/brandkit/SKILL.md +798 -0
  1573. package/dist/skills/brutalist/SKILL.md +92 -0
  1574. package/dist/skills/design-references/SKILL.md +32 -0
  1575. package/dist/skills/design-references/references/clickhouse/DESIGN.md +544 -0
  1576. package/dist/skills/gpt-taste/SKILL.md +74 -0
  1577. package/dist/skills/grill-me/SKILL.md +11 -0
  1578. package/dist/skills/handoff/SKILL.md +17 -0
  1579. package/dist/skills/handoff-text/SKILL.md +15 -0
  1580. package/dist/skills/image-to-code/SKILL.md +1228 -0
  1581. package/dist/skills/imagegen-frontend-mobile/SKILL.md +1465 -0
  1582. package/dist/skills/imagegen-frontend-web/SKILL.md +987 -0
  1583. package/dist/skills/implanger/SKILL.md +70 -0
  1584. package/dist/skills/improve-codebase/REFERENCE.md +78 -0
  1585. package/dist/skills/improve-codebase/SKILL.md +180 -0
  1586. package/dist/skills/minimalist/SKILL.md +85 -0
  1587. package/dist/skills/output/SKILL.md +49 -0
  1588. package/dist/skills/pi-subagents/SKILL.md +50 -0
  1589. package/dist/skills/pi-subagents/references/constraints-and-recipes.md +274 -0
  1590. package/dist/skills/pi-subagents/references/execution-controls.md +463 -0
  1591. package/dist/skills/pi-subagents/references/management-authoring-rpc.md +161 -0
  1592. package/dist/skills/pi-subagents/references/multi-lane-orchestration.md +39 -0
  1593. package/dist/skills/pi-subagents/references/prompting-and-roles.md +267 -0
  1594. package/dist/skills/planger/SKILL.md +167 -0
  1595. package/dist/skills/ponytail/SKILL.md +121 -0
  1596. package/dist/skills/ponytail-audit/SKILL.md +42 -0
  1597. package/dist/skills/ponytail-debt/SKILL.md +45 -0
  1598. package/dist/skills/ponytail-gain/SKILL.md +51 -0
  1599. package/dist/skills/ponytail-help/SKILL.md +72 -0
  1600. package/dist/skills/ponytail-review/SKILL.md +58 -0
  1601. package/dist/skills/redesign/SKILL.md +178 -0
  1602. package/dist/skills/selesai-handoff/SKILL.md +21 -0
  1603. package/dist/skills/soft/SKILL.md +98 -0
  1604. package/dist/skills/stitch/DESIGN.md +121 -0
  1605. package/dist/skills/stitch/SKILL.md +184 -0
  1606. package/dist/skills/taste/SKILL.md +1206 -0
  1607. package/dist/skills/taste-v1/SKILL.md +226 -0
  1608. package/dist/skills/unlazy/CHANGELOG.md +109 -0
  1609. package/dist/skills/unlazy/CONTRIBUTING.md +63 -0
  1610. package/dist/skills/unlazy/LICENSE +21 -0
  1611. package/dist/skills/unlazy/README.md +228 -0
  1612. package/dist/skills/unlazy/SECURITY.md +60 -0
  1613. package/dist/skills/unlazy/SKILL.md +93 -0
  1614. package/dist/skills/unlazy/package.json +13 -0
  1615. package/dist/skills/unlazy/references/dispatch.md +79 -0
  1616. package/dist/skills/unlazy/references/gates.md +132 -0
  1617. package/dist/skills/unlazy/references/method.md +49 -0
  1618. package/dist/skills/unlazy/references/orchestration.md +98 -0
  1619. package/dist/skills/unlazy/references/parallel.md +111 -0
  1620. package/dist/skills/unlazy/references/token-economy.md +39 -0
  1621. package/dist/skills/unlazy/research/validation-protocol.md +81 -0
  1622. package/dist/skills/unlazy/scripts/dispatch-check.mjs +108 -0
  1623. package/dist/skills/unlazy/scripts/gate-check.mjs +879 -0
  1624. package/dist/skills/unlazy/scripts/gate-lint.mjs +178 -0
  1625. package/dist/skills/unlazy/scripts/lib/check-supervisor.mjs +46 -0
  1626. package/dist/skills/unlazy/scripts/lib/dispatch.mjs +283 -0
  1627. package/dist/skills/unlazy/scripts/lib/gates.mjs +625 -0
  1628. package/dist/skills/unlazy/scripts/lib/process-tree.mjs +161 -0
  1629. package/dist/skills/unlazy/scripts/lib/regex-worker.mjs +9 -0
  1630. package/dist/skills/unlazy/templates/PLAN.md +65 -0
  1631. package/dist/skills/unlazy/templates/gates-leaf.md +51 -0
  1632. package/dist/skills/unlazy/templates/gates-node.md +50 -0
  1633. package/dist/skills/unlazy/tests/contract-tests.mjs +127 -0
  1634. package/dist/skills/unlazy/tests/dispatch-tests.mjs +296 -0
  1635. package/dist/skills/unlazy/tests/hardening-tests.mjs +900 -0
  1636. package/dist/skills/unlazy/tests/lint-tests.mjs +242 -0
  1637. package/dist/skills/unlazy/tests/run-tests.mjs +360 -0
  1638. package/dist/skills/unlazy/tests/self-check.mjs +152 -0
  1639. package/dist/skills/unlazy/tests/stress-tests.mjs +165 -0
  1640. package/dist/skills/web-design-guidelines/SKILL.md +41 -0
  1641. package/dist/skills/workflow/SKILL.md +95 -0
  1642. package/dist/themes/adventure.json +84 -0
  1643. package/dist/themes/adwaita-dark.json +84 -0
  1644. package/dist/themes/arcoiris.json +84 -0
  1645. package/dist/themes/arthur.json +84 -0
  1646. package/dist/themes/atom.json +84 -0
  1647. package/dist/themes/aura.json +84 -0
  1648. package/dist/themes/black-metal-bathory.json +84 -0
  1649. package/dist/themes/black-metal-burzum.json +84 -0
  1650. package/dist/themes/black-metal-khold.json +84 -0
  1651. package/dist/themes/box.json +84 -0
  1652. package/dist/themes/brogrammer.json +84 -0
  1653. package/dist/themes/carbonfox.json +84 -0
  1654. package/dist/themes/catppuccin-mocha.json +84 -0
  1655. package/dist/themes/citruszest.json +84 -0
  1656. package/dist/themes/cursor-dark.json +84 -0
  1657. package/dist/themes/cutie-pro.json +84 -0
  1658. package/dist/themes/dark-modern.json +84 -0
  1659. package/dist/themes/dark-pastel.json +84 -0
  1660. package/dist/themes/dimmed-monokai.json +84 -0
  1661. package/dist/themes/doom-peacock.json +84 -0
  1662. package/dist/themes/dracula-plus.json +84 -0
  1663. package/dist/themes/dracula.json +80 -0
  1664. package/dist/themes/earthsong.json +84 -0
  1665. package/dist/themes/everforest-dark-hard.json +84 -0
  1666. package/dist/themes/everforest-dark.json +80 -0
  1667. package/dist/themes/fahrenheit.json +84 -0
  1668. package/dist/themes/flatland.json +84 -0
  1669. package/dist/themes/flexoki-dark.json +84 -0
  1670. package/dist/themes/front-end-delight.json +84 -0
  1671. package/dist/themes/fun-forrest.json +84 -0
  1672. package/dist/themes/galizur.json +84 -0
  1673. package/dist/themes/github-dark-colorblind.json +84 -0
  1674. package/dist/themes/github-dark-high-contrast.json +84 -0
  1675. package/dist/themes/glacier.json +84 -0
  1676. package/dist/themes/gruber-darker.json +84 -0
  1677. package/dist/themes/gruvbox-dark-hard.json +84 -0
  1678. package/dist/themes/gruvbox-dark.json +84 -0
  1679. package/dist/themes/gruvbox-material.json +84 -0
  1680. package/dist/themes/guezwhoz.json +84 -0
  1681. package/dist/themes/hacktober.json +84 -0
  1682. package/dist/themes/hardcore.json +84 -0
  1683. package/dist/themes/havn-skumring.json +84 -0
  1684. package/dist/themes/ic-orange-ppl.json +84 -0
  1685. package/dist/themes/iterm2-smoooooth.json +84 -0
  1686. package/dist/themes/iterm2-tango-dark.json +84 -0
  1687. package/dist/themes/japanesque.json +84 -0
  1688. package/dist/themes/jellybeans.json +84 -0
  1689. package/dist/themes/kanagawa-wave.json +84 -0
  1690. package/dist/themes/kurokula.json +84 -0
  1691. package/dist/themes/later-this-evening.json +84 -0
  1692. package/dist/themes/lovelace.json +84 -0
  1693. package/dist/themes/material-darker.json +84 -0
  1694. package/dist/themes/matte-black.json +84 -0
  1695. package/dist/themes/mellow.json +84 -0
  1696. package/dist/themes/miasma.json +84 -0
  1697. package/dist/themes/nord.json +80 -0
  1698. package/dist/themes/nvim-dark.json +84 -0
  1699. package/dist/themes/one-dark.json +80 -0
  1700. package/dist/themes/popping-and-locking.json +84 -0
  1701. package/dist/themes/rose-pine.json +80 -0
  1702. package/dist/themes/sea-shells.json +84 -0
  1703. package/dist/themes/sleepy-hollow.json +84 -0
  1704. package/dist/themes/smyck.json +84 -0
  1705. package/dist/themes/solarized-dark.json +80 -0
  1706. package/dist/themes/tokyo-night.json +80 -0
  1707. package/dist/themes/tomorrow-night-bright.json +84 -0
  1708. package/dist/themes/tomorrow-night-burns.json +84 -0
  1709. package/dist/themes/tomorrow-night.json +84 -0
  1710. package/dist/themes/twilight.json +84 -0
  1711. package/dist/themes/vague.json +84 -0
  1712. package/dist/themes/vesper.json +84 -0
  1713. package/dist/themes/xcode-dark-hc.json +84 -0
  1714. package/dist/utils/abort.d.ts +4 -0
  1715. package/dist/utils/abort.js +47 -0
  1716. package/dist/utils/ansi.d.ts +1 -0
  1717. package/dist/utils/ansi.js +51 -0
  1718. package/dist/utils/changelog.d.ts +21 -0
  1719. package/dist/utils/changelog.js +164 -0
  1720. package/dist/utils/child-process.d.ts +17 -0
  1721. package/dist/utils/child-process.js +105 -0
  1722. package/dist/utils/clipboard-image.d.ts +10 -0
  1723. package/dist/utils/clipboard-image.js +250 -0
  1724. package/dist/utils/clipboard-native.d.ts +10 -0
  1725. package/dist/utils/clipboard-native.js +19 -0
  1726. package/dist/utils/clipboard.d.ts +3 -0
  1727. package/dist/utils/clipboard.js +140 -0
  1728. package/dist/utils/deprecation.d.ts +3 -0
  1729. package/dist/utils/deprecation.js +12 -0
  1730. package/dist/utils/exif-orientation.d.ts +4 -0
  1731. package/dist/utils/exif-orientation.js +157 -0
  1732. package/dist/utils/frontmatter.d.ts +7 -0
  1733. package/dist/utils/frontmatter.js +25 -0
  1734. package/dist/utils/fs-watch.d.ts +4 -0
  1735. package/dist/utils/fs-watch.js +24 -0
  1736. package/dist/utils/git.d.ts +25 -0
  1737. package/dist/utils/git.js +194 -0
  1738. package/dist/utils/html.d.ts +6 -0
  1739. package/dist/utils/html.js +39 -0
  1740. package/dist/utils/image-convert.d.ts +9 -0
  1741. package/dist/utils/image-convert.js +44 -0
  1742. package/dist/utils/image-process.d.ts +17 -0
  1743. package/dist/utils/image-process.js +82 -0
  1744. package/dist/utils/image-resize-core.d.ts +29 -0
  1745. package/dist/utils/image-resize-core.js +123 -0
  1746. package/dist/utils/image-resize-worker.d.ts +1 -0
  1747. package/dist/utils/image-resize-worker.js +30 -0
  1748. package/dist/utils/image-resize.d.ts +15 -0
  1749. package/dist/utils/image-resize.js +96 -0
  1750. package/dist/utils/json.d.ts +2 -0
  1751. package/dist/utils/json.js +6 -0
  1752. package/dist/utils/mime.d.ts +2 -0
  1753. package/dist/utils/mime.js +132 -0
  1754. package/dist/utils/open-browser.d.ts +8 -0
  1755. package/dist/utils/open-browser.js +21 -0
  1756. package/dist/utils/paths.d.ts +30 -0
  1757. package/dist/utils/paths.js +91 -0
  1758. package/dist/utils/photon.d.ts +20 -0
  1759. package/dist/utils/photon.js +120 -0
  1760. package/dist/utils/pi-user-agent.d.ts +1 -0
  1761. package/dist/utils/pi-user-agent.js +4 -0
  1762. package/dist/utils/shell.d.ts +33 -0
  1763. package/dist/utils/shell.js +215 -0
  1764. package/dist/utils/sleep.d.ts +4 -0
  1765. package/dist/utils/sleep.js +16 -0
  1766. package/dist/utils/syntax-highlight.d.ts +11 -0
  1767. package/dist/utils/syntax-highlight.js +117 -0
  1768. package/dist/utils/thinking-tags.d.ts +6 -0
  1769. package/dist/utils/thinking-tags.js +62 -0
  1770. package/dist/utils/tools-manager.d.ts +7 -0
  1771. package/dist/utils/tools-manager.js +402 -0
  1772. package/dist/utils/version-check.d.ts +19 -0
  1773. package/dist/utils/version-check.js +72 -0
  1774. package/dist/utils/windows-self-update.d.ts +2 -0
  1775. package/dist/utils/windows-self-update.js +76 -0
  1776. package/package.json +1 -1
@@ -0,0 +1,3359 @@
1
+ /**
2
+ * Rendering functions for subagent results
3
+ */
4
+
5
+ import * as path from "node:path";
6
+ import { createHash } from "node:crypto";
7
+ import type { AgentToolResult } from "@earendil-works/pi-agent-core";
8
+ import { getMarkdownTheme, keyText, type ExtensionContext } from "@selesai/code";
9
+ import { Container, Markdown, Spacer, Text, visibleWidth, type Component } from "@earendil-works/pi-tui";
10
+ import { unresolvedChildWatchdogBlockers } from "../watchdog/child-status.ts";
11
+ import {
12
+ type AgentProgress,
13
+ type AsyncJobState,
14
+ type AsyncJobStep,
15
+ type AsyncParallelGroupStatus,
16
+ type Details,
17
+ type HostStepState,
18
+ type HostStepVerdict,
19
+ type NestedRunSummary,
20
+ type NestedStepSummary,
21
+ type WorkflowGraphNode,
22
+ type WorkflowNodeStatus,
23
+ type MainWindowRendererConfig,
24
+ MAX_WIDGET_JOBS,
25
+ WIDGET_ANIMATION_INTERVAL_MS,
26
+ WIDGET_KEY,
27
+ } from "../shared/types.ts";
28
+ import { previewDisplayText, sanitizeDisplayText, truncateDisplayText } from "../shared/display-text.ts";
29
+ import { FLEET_OPEN_SHORTCUT, formatShortcutLabel } from "../shared/shortcuts.ts";
30
+ import { formatContextUsage, formatTokens, formatUsage, formatDuration, formatModelThinking, formatToolCall, formatTokenUsage, shortenPath } from "../shared/formatters.ts";
31
+ import { getDisplayItems, getSingleResultOutput, PROMPT_REDACTED } from "../shared/utils.ts";
32
+ import { flatToLogicalStepIndex } from "../runs/background/parallel-groups.ts";
33
+ import { formatNestedAggregate } from "../runs/shared/nested-render.ts";
34
+ import { aggregateStepStatus, formatActivityLabel, formatAgentRunningLabel, formatParallelOutcome } from "../shared/status-format.ts";
35
+ import { contextModeBadge, contextModePrefix } from "../runs/shared/context-mode.ts";
36
+ import { shouldSuppressSingleStep, stripRepeatedAgentPrefix, withDuplicateLabelDiscriminators } from "./render-helpers.ts";
37
+ import { buildWorkflowChatProgressRows, type WorkflowChatProgressRow } from "../workflows/chat-progress.ts";
38
+ import { formatWorkflowPreflight, formatWorkflowPreflightPlanSummary, formatWorkflowPreflightWarningSummary, formatWorkflowPreflightWarnings } from "../workflows/workflow-preflight.ts";
39
+ import { encodeAsyncStatusSnapshotWidget } from "../runs/background/async-status-snapshot.ts";
40
+ import { projectAsyncWorkflowRows, type AsyncStatusWorkflowRow } from "../runs/shared/async-status-projection.ts";
41
+ import { hostStepReportName, hostStepVerdictLabel } from "../runs/shared/host-step-status.ts";
42
+ import { workflowGraphStageNodes } from "../runs/shared/workflow-graph.ts";
43
+ import { formatWorkflowChecklistBottleneck, formatWorkflowChecklistPhase, formatWorkflowChecklistSummary, projectWorkflowChecklist, type WorkflowChecklistItem, type WorkflowChecklistProjection, type WorkflowChecklistState, type WorkflowChecklistStep } from "../workflows/workflow-checklist.ts";
44
+
45
+ type Theme = ExtensionContext["ui"]["theme"];
46
+
47
+ interface WorkflowWidgetProjection {
48
+ stages: WorkflowGraphNode[];
49
+ steps: AsyncJobStep[];
50
+ stageProgress?: { total: number; current?: number };
51
+ plannedKeys?: Set<string>;
52
+ checklist?: WorkflowChecklistProjection;
53
+ }
54
+
55
+ type WorkflowWidgetProjectionLookup = (job: AsyncJobState) => WorkflowWidgetProjection;
56
+
57
+ interface MainWindowRenderLayout {
58
+ horizontalSpacing: number;
59
+ compactResultMaxLines?: number;
60
+ }
61
+
62
+ function resolveMainWindowRenderLayout(config?: MainWindowRendererConfig): MainWindowRenderLayout {
63
+ return {
64
+ horizontalSpacing: config?.horizontalSpacing ?? 2,
65
+ ...(config?.compactResultMaxLines !== undefined ? { compactResultMaxLines: config.compactResultMaxLines } : {}),
66
+ };
67
+ }
68
+
69
+ function mainWindowIndent(layout: MainWindowRenderLayout, level: number): string {
70
+ return " ".repeat(Math.max(0, layout.horizontalSpacing * level));
71
+ }
72
+
73
+ function capCompactMainWindowResult(component: Component, layout: MainWindowRenderLayout, theme: Theme, enabled: boolean): Component {
74
+ const maxLines = layout.compactResultMaxLines;
75
+ if (!enabled || maxLines === undefined) return component;
76
+ const capped = new Container();
77
+ capped.render = (width: number): string[] => {
78
+ const lines = component.render(width);
79
+ if (lines.length <= maxLines) return lines;
80
+ const visibleRows = maxLines === 1 ? 1 : maxLines - 1;
81
+ const hiddenCount = lines.length - visibleRows;
82
+ const hint = theme.fg("accent", `… ${hiddenCount} rows hidden · ${liveDetailKeyText()} expands`);
83
+ if (maxLines === 1) return [truncLine(`${lines[0] ?? ""} ${hint}`, width)];
84
+ return [...lines.slice(0, visibleRows), truncLine(hint, width)];
85
+ };
86
+ return capped;
87
+ }
88
+
89
+ function liveDetailKeyText(): string {
90
+ return keyText("app.tools.expand");
91
+ }
92
+
93
+ export function liveDetailHintText(): string {
94
+ return `Press ${liveDetailKeyText()} for live detail · ${formatShortcutLabel(FLEET_OPEN_SHORTCUT)} Fleet`;
95
+ }
96
+
97
+ function foregroundSingleHintText(shortcut?: string): string {
98
+ if (!shortcut) return liveDetailHintText();
99
+ const label = formatShortcutLabel(shortcut);
100
+ return `${liveDetailHintText()} · ${label} to run in background`;
101
+ }
102
+
103
+ function getTermWidth(): number {
104
+ return process.stdout.columns || 120;
105
+ }
106
+
107
+ const segmenter = new Intl.Segmenter(undefined, { granularity: "grapheme" });
108
+ const ansiStylePattern = /\x1b\[[0-9;]*m/y;
109
+
110
+ /**
111
+ * Truncate a line to maxWidth, preserving ANSI styling through the ellipsis.
112
+ *
113
+ * pi-tui's truncateToWidth adds \x1b[0m before ellipsis which resets all styling,
114
+ * causing background color bleed in the TUI. This implementation tracks active
115
+ * ANSI styles and re-applies them before the ellipsis.
116
+ *
117
+ * Uses Intl.Segmenter for proper Unicode/emoji handling (not char-by-char).
118
+ */
119
+ export function truncLine(text: string, maxWidth: number): string {
120
+ if (maxWidth <= 0) return "";
121
+ if (visibleWidth(text) <= maxWidth) return text;
122
+
123
+ const targetWidth = maxWidth - 1;
124
+ let result = "";
125
+ let currentWidth = 0;
126
+ let activeStyles: string[] = [];
127
+ let i = 0;
128
+
129
+ while (i < text.length) {
130
+ ansiStylePattern.lastIndex = i;
131
+ const ansiMatch = ansiStylePattern.exec(text);
132
+ if (ansiMatch) {
133
+ const code = ansiMatch[0];
134
+ result += code;
135
+
136
+ if (code === "\x1b[0m" || code === "\x1b[m") {
137
+ activeStyles = [];
138
+ } else {
139
+ activeStyles.push(code);
140
+ }
141
+ i += code.length;
142
+ continue;
143
+ }
144
+
145
+ let end = text.indexOf("\x1b[", i);
146
+ if (end === i) end = text.indexOf("\x1b[", i + 2);
147
+ if (end === -1) end = text.length;
148
+ const textPortion = text.slice(i, end);
149
+ for (const seg of segmenter.segment(textPortion)) {
150
+ const grapheme = seg.segment;
151
+ const graphemeWidth = grapheme === "\x1b" ? 0 : visibleWidth(grapheme);
152
+
153
+ if (currentWidth + graphemeWidth > targetWidth) {
154
+ return result + activeStyles.join("") + "…";
155
+ }
156
+
157
+ result += grapheme;
158
+ currentWidth += graphemeWidth;
159
+ }
160
+ i = end;
161
+ }
162
+
163
+ return result + activeStyles.join("") + "…";
164
+ }
165
+
166
+ function wrapPlainText(text: string, maxWidth: number): string[] {
167
+ if (maxWidth <= 0) return [""];
168
+ const lines: string[] = [];
169
+ for (const rawLine of text.split("\n")) {
170
+ if (rawLine.length === 0) {
171
+ lines.push("");
172
+ continue;
173
+ }
174
+ let current = "";
175
+ let currentWidth = 0;
176
+ for (const seg of segmenter.segment(rawLine)) {
177
+ const grapheme = seg.segment;
178
+ const graphemeWidth = visibleWidth(grapheme);
179
+ if (graphemeWidth > maxWidth) continue;
180
+ if (currentWidth > 0 && currentWidth + graphemeWidth > maxWidth) {
181
+ lines.push(current);
182
+ current = grapheme;
183
+ currentWidth = graphemeWidth;
184
+ continue;
185
+ }
186
+ current += grapheme;
187
+ currentWidth += graphemeWidth;
188
+ }
189
+ lines.push(current);
190
+ }
191
+ return lines;
192
+ }
193
+
194
+ const RUNNING_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
195
+ const STATIC_RUNNING_GLYPH = "●";
196
+
197
+ type ProgressSeedSource = Partial<Pick<AgentProgress, "index" | "toolCount" | "tokens" | "durationMs" | "lastActivityAt" | "currentToolStartedAt" | "turnCount">>;
198
+
199
+ function runningSeed(...values: Array<number | undefined>): number | undefined {
200
+ let seed: number | undefined;
201
+ for (const value of values) {
202
+ if (value === undefined || !Number.isFinite(value)) continue;
203
+ seed = (seed ?? 0) + Math.trunc(value);
204
+ }
205
+ return seed;
206
+ }
207
+
208
+ function runningGlyph(seed?: number): string {
209
+ if (seed === undefined) return STATIC_RUNNING_GLYPH;
210
+ return RUNNING_FRAMES[Math.abs(seed) % RUNNING_FRAMES.length]!;
211
+ }
212
+
213
+ function animatedSeed(seed: number | undefined, frame: number | undefined): number | undefined {
214
+ if (frame === undefined) return seed;
215
+ return (seed ?? 0) + frame;
216
+ }
217
+
218
+ function progressRunningSeed(progress: ProgressSeedSource | undefined): number | undefined {
219
+ if (!progress) return undefined;
220
+ return runningSeed(
221
+ progress.index,
222
+ progress.toolCount,
223
+ progress.tokens,
224
+ progress.durationMs,
225
+ progress.lastActivityAt,
226
+ progress.currentToolStartedAt,
227
+ progress.turnCount,
228
+ );
229
+ }
230
+
231
+ interface LegacyResultAnimationContext {
232
+ state: { subagentResultAnimationTimer?: ReturnType<typeof setInterval> };
233
+ }
234
+
235
+ export function clearLegacyResultAnimationTimer(context: LegacyResultAnimationContext): void {
236
+ const timer = context.state.subagentResultAnimationTimer;
237
+ if (!timer) return;
238
+ clearInterval(timer);
239
+ context.state.subagentResultAnimationTimer = undefined;
240
+ }
241
+
242
+ function extractOutputTarget(task: string): string | undefined {
243
+ const writeToMatch = task.match(/\[Write to:\s*([^\]\n]+)\]/i);
244
+ if (writeToMatch?.[1]?.trim()) return writeToMatch[1].trim();
245
+ const findingsMatch = task.match(/Write your findings to(?: exactly this path)?:\s*([^\r\n]+)/i);
246
+ if (findingsMatch?.[1]?.trim()) return findingsMatch[1].trim();
247
+ const outputMatch = task.match(/[Oo]utput(?:\s+to)?\s*:\s*(\S+)/i);
248
+ if (outputMatch?.[1]?.trim()) return outputMatch[1].trim();
249
+ return undefined;
250
+ }
251
+
252
+ function hasEmptyTextOutputWithoutOutputTarget(task: string, output: string): boolean {
253
+ if (output.trim()) return false;
254
+ return !extractOutputTarget(task);
255
+ }
256
+
257
+ function getToolCallLines(
258
+ result: Pick<Details["results"][number], "messages" | "toolCalls">,
259
+ expanded: boolean,
260
+ ): string[] {
261
+ if (result.messages) {
262
+ return getDisplayItems(result.messages)
263
+ .filter((item): item is { type: "tool"; name: string; args: Record<string, unknown> } => item.type === "tool")
264
+ .map((item) => formatToolCall(item.name, item.args, expanded));
265
+ }
266
+ return result.toolCalls?.map((toolCall) => expanded ? toolCall.expandedText : toolCall.text) ?? [];
267
+ }
268
+
269
+ const ansiEscapePattern = /\x1b\[[0-9;]*m/g;
270
+ const noisyStatusPatterns = [
271
+ /^(?:i|we)\s+(?:will|need|can|should|am|are)\b/i,
272
+ /^i(?:'m|’m| am)\b/i,
273
+ /\bso i (?:will|need|can)\b/i,
274
+ /^(?:checking|fetching|reading|inspecting|verifying|collecting|confirming|polling)\b/i,
275
+ /^(?:async\s+subagent\s+)?[\w.-]+\s*·\s*(?:step|agent)\s+\d+\/\d+\s*·/i,
276
+ /^(?:Step|Agent)\s+\d+\/\d+:\s+[\w.-]+\s*·\s*(?:running|queued|pending|complete|completed)\b/i,
277
+ /^(?:async\s+subagent\s+)?[\w.-]+(?:\s+\[(?:fresh|fork|mixed)\])?\s*·\s*(?:running|queued|pending|complete|completed|done)\b/i,
278
+ /^Press\s+\S+\s+for\s+live\s+detail$/i,
279
+ /^output:\s+.+\/async-subagent-runs\//i,
280
+ ];
281
+ const liveOutputWordSignalPattern = /\b(?:access denied|denied|error|exception|fail(?:ed|ure)?|fatal|panic|rejected|timeout|timed out|unable|warning)\b/i;
282
+ const liveOutputCodeSignalPattern = /\bE[A-Z0-9_]{2,}\b/;
283
+
284
+ function oneLine(text: string): string {
285
+ return text.replace(ansiEscapePattern, "").replace(/\s+/g, " ").trim();
286
+ }
287
+
288
+ const COMPACT_TASK_MAX_CHARS = 96;
289
+
290
+ /** Display label for a child run: the derived session name (agent + task
291
+ * excerpt) when the launcher provided one, else the bare agent name. */
292
+ function childDisplayName(result: { agent?: string; sessionName?: string } | undefined, fallback = "subagent"): string {
293
+ return result?.sessionName?.trim() || result?.agent || fallback;
294
+ }
295
+
296
+ export function compactTaskText(task: string | undefined, label?: string): string | undefined {
297
+ const taskText = task?.trim();
298
+ const labelText = label?.trim();
299
+ const normalizedTask = taskText && taskText !== PROMPT_REDACTED ? oneLine(taskText) : "";
300
+ const normalizedLabel = labelText && labelText !== PROMPT_REDACTED ? oneLine(labelText) : "";
301
+ const normalized = normalizedLabel && normalizedTask && normalizedLabel !== normalizedTask
302
+ ? `${normalizedLabel} — ${normalizedTask}`
303
+ : normalizedLabel || normalizedTask;
304
+ if (!normalized) return undefined;
305
+ return previewDisplayText(normalized, COMPACT_TASK_MAX_CHARS);
306
+ }
307
+
308
+ export interface AsyncLaneProjection {
309
+ label?: string;
310
+ role: string;
311
+ phase?: string;
312
+ state: AsyncJobState["status"] | AsyncJobStep["status"];
313
+ gate?: string;
314
+ next?: string;
315
+ output?: string;
316
+ workspace?: string;
317
+ ref: string;
318
+ chips: string[];
319
+ }
320
+
321
+ const LANE_VALUE_MAX_CHARS = 48;
322
+
323
+ function boundedLaneValue(value: string | undefined, maxChars = LANE_VALUE_MAX_CHARS): string | undefined {
324
+ if (!value?.trim() || value.trim() === PROMPT_REDACTED) return undefined;
325
+ return previewDisplayText(oneLine(value), maxChars);
326
+ }
327
+
328
+ function workflowNodeStepStatus(status: WorkflowNodeStatus): AsyncJobStep["status"] {
329
+ switch (status) {
330
+ case "completed":
331
+ return "completed";
332
+ case "detached":
333
+ return "paused";
334
+ default:
335
+ return status;
336
+ }
337
+ }
338
+
339
+ function workflowNodeStatusLabel(status: WorkflowNodeStatus): string {
340
+ switch (status) {
341
+ case "completed":
342
+ return "complete";
343
+ case "detached":
344
+ return "paused";
345
+ default:
346
+ return status;
347
+ }
348
+ }
349
+
350
+ function workflowStepPriority(step: AsyncJobStep, currentNodeId?: string): number {
351
+ const isCurrent = step.workflowKey === currentNodeId;
352
+ if (step.status === "running" || (isCurrent && step.status !== "complete" && step.status !== "completed")) return 0;
353
+ const gate = laneGate(step);
354
+ if (
355
+ step.status === "failed"
356
+ || step.status === "partial"
357
+ || step.status === "paused"
358
+ || step.status === "stopped"
359
+ || step.status === "rejected"
360
+ || step.toolBudgetBlocked === true
361
+ || step.turnBudgetExceeded === true
362
+ || step.activityState === "needs_attention"
363
+ || step.watchdog?.phase === "stale"
364
+ || unresolvedChildWatchdogBlockers(step.watchdog).length > 0
365
+ || gate !== undefined
366
+ ) return 1;
367
+ if (step.status === "pending") return 2;
368
+ return 3;
369
+ }
370
+
371
+ /** Merge materialized child rows with the planned workflow stages for rendering. */
372
+ function workflowWidgetSteps(job: AsyncJobState, planned = job.mode === "workflow" ? workflowGraphStageNodes(job.workflowGraph) : []): AsyncJobStep[] {
373
+ const loaded = job.steps ?? [];
374
+ if (planned.length === 0) return loaded;
375
+
376
+ const loadedIndexesByKey = new Map<string, number[]>();
377
+ for (const [index, step] of loaded.entries()) {
378
+ if (!step.workflowKey) continue;
379
+ const indexes = loadedIndexesByKey.get(step.workflowKey) ?? [];
380
+ indexes.push(index);
381
+ loadedIndexesByKey.set(step.workflowKey, indexes);
382
+ }
383
+ const consumed = new Set<number>();
384
+ const entries: Array<{ step: AsyncJobStep; order: number }> = [];
385
+ for (const [order, node] of planned.entries()) {
386
+ const loadedIndex = loadedIndexesByKey.get(node.id)?.find((index) => !consumed.has(index));
387
+ if (loadedIndex !== undefined) {
388
+ consumed.add(loadedIndex);
389
+ const loadedStep = loaded[loadedIndex]!;
390
+ entries.push({
391
+ step: {
392
+ ...loadedStep,
393
+ index: node.flatIndex ?? loadedStep.index ?? order,
394
+ agent: loadedStep.agent || node.agent || job.agents?.[0] || "workflow",
395
+ phase: loadedStep.phase ?? node.phase,
396
+ label: loadedStep.label ?? node.label,
397
+ workflowKey: loadedStep.workflowKey ?? node.id,
398
+ ...(loadedStep.outputName === undefined && node.outputName !== undefined ? { outputName: node.outputName } : {}),
399
+ ...(loadedStep.structured === undefined && node.structured !== undefined ? { structured: node.structured } : {}),
400
+ ...(loadedStep.error === undefined && node.error !== undefined ? { error: node.error } : {}),
401
+ },
402
+ order,
403
+ });
404
+ continue;
405
+ }
406
+ entries.push({
407
+ step: {
408
+ index: node.flatIndex ?? order,
409
+ agent: node.agent ?? job.agents?.[0] ?? "workflow",
410
+ status: workflowNodeStepStatus(node.status),
411
+ workflowKey: node.id,
412
+ label: node.label,
413
+ ...(node.phase ? { phase: node.phase } : {}),
414
+ ...(node.outputName ? { outputName: node.outputName } : {}),
415
+ ...(node.structured !== undefined ? { structured: node.structured } : {}),
416
+ ...(node.error ? { error: node.error } : {}),
417
+ },
418
+ order,
419
+ });
420
+ }
421
+ for (const [index, step] of loaded.entries()) {
422
+ if (!consumed.has(index)) entries.push({ step, order: planned.length + index });
423
+ }
424
+ entries.sort((left, right) => workflowStepPriority(left.step, job.workflowGraph?.currentNodeId) - workflowStepPriority(right.step, job.workflowGraph?.currentNodeId) || left.order - right.order);
425
+ return entries.map(({ step }) => step);
426
+ }
427
+
428
+ function workflowStageProgress(job: AsyncJobState, stages = job.mode === "workflow" ? workflowGraphStageNodes(job.workflowGraph) : []): { total: number; current?: number } | undefined {
429
+ if (job.mode !== "workflow") return undefined;
430
+ if (stages.length === 0) return undefined;
431
+ const currentId = job.workflowGraph?.currentNodeId;
432
+ const currentIndex = currentId ? stages.findIndex((stage) => stage.id === currentId) : -1;
433
+ if (currentIndex >= 0 && stages[currentIndex]?.status !== "completed") return { total: stages.length, current: currentIndex };
434
+ const runningIndex = stages.findIndex((stage) => stage.status === "running");
435
+ if (runningIndex >= 0) return { total: stages.length, current: runningIndex };
436
+ const indexedStage = job.currentStep !== undefined && job.currentStep >= 0 ? stages[job.currentStep] : undefined;
437
+ if (indexedStage && indexedStage.status !== "completed") return { total: stages.length, current: job.currentStep };
438
+ if (stages.every((stage) => stage.status === "completed")) return { total: stages.length, current: stages.length - 1 };
439
+ return { total: stages.length };
440
+ }
441
+
442
+ function buildWorkflowWidgetProjection(job: AsyncJobState): WorkflowWidgetProjection {
443
+ const stages = job.mode === "workflow" ? workflowGraphStageNodes(job.workflowGraph) : [];
444
+ const stageProgress = workflowStageProgress(job, stages);
445
+ const steps = workflowWidgetSteps(job, stages);
446
+ const projection: WorkflowWidgetProjection = { stages, steps };
447
+ if (stageProgress) projection.stageProgress = stageProgress;
448
+ if (stages.length) projection.plannedKeys = new Set(stages.map((node) => node.id));
449
+ if (job.mode === "workflow") {
450
+ const checklist = projectWorkflowChecklist({
451
+ graph: job.workflowGraph,
452
+ steps: job.steps,
453
+ hostSteps: job.hostSteps,
454
+ preflight: job.preflight,
455
+ trace: job.workflow?.trace,
456
+ now: job.updatedAt ?? Date.now(),
457
+ });
458
+ if (checklist.total > 0) projection.checklist = checklist;
459
+ }
460
+ return projection;
461
+ }
462
+
463
+ function workflowWidgetProjectionLookup(): WorkflowWidgetProjectionLookup {
464
+ const projections = new WeakMap<AsyncJobState, WorkflowWidgetProjection>();
465
+ return (job: AsyncJobState) => {
466
+ const cached = projections.get(job);
467
+ if (cached) return cached;
468
+ const projection = buildWorkflowWidgetProjection(job);
469
+ projections.set(job, projection);
470
+ return projection;
471
+ };
472
+ }
473
+
474
+ function laneStepForJob(job: AsyncJobState, steps = workflowWidgetSteps(job)): AsyncJobStep | undefined {
475
+ if (steps.length === 0) return undefined;
476
+ const graphCurrent = job.workflowGraph?.currentNodeId;
477
+ if (graphCurrent) {
478
+ const current = steps.find((step) => step.workflowKey === graphCurrent);
479
+ if (current) return current;
480
+ }
481
+ if (job.currentStep !== undefined) {
482
+ const current = steps[job.currentStep];
483
+ if (current && (current.index === undefined || current.index === job.currentStep)) return current;
484
+ // Active parallel groups retain flat indices while exposing only the group slice.
485
+ const indexedCurrent = steps.find((step) => step.index === job.currentStep);
486
+ if (indexedCurrent) return indexedCurrent;
487
+ return steps[0];
488
+ }
489
+ return steps.find((step) => step.status === "running")
490
+ ?? steps.find((step) => step.status === "pending")
491
+ ?? steps.at(-1);
492
+ }
493
+
494
+ function laneTraceForJob(job: AsyncJobState): NonNullable<AsyncJobState["workflow"]>["trace"][number] | undefined {
495
+ return Array.isArray(job.workflow?.trace) ? job.workflow.trace.at(-1) : undefined;
496
+ }
497
+
498
+ function laneGate(step: AsyncJobStep | undefined): string | undefined {
499
+ const review = step?.review?.status ?? step?.acceptance?.reviewResult?.status;
500
+ if (review === "blockers") return "review blockers";
501
+ if (review === "review-required") return "review required";
502
+ if (review === "reviewed") return "reviewed";
503
+ const acceptance = step?.acceptance?.status;
504
+ if (acceptance === "review-required") return "acceptance review";
505
+ if (acceptance === "checked" || acceptance === "verified" || acceptance === "accepted") return "acceptance";
506
+ return undefined;
507
+ }
508
+
509
+ function laneNextAction(state: AsyncLaneProjection["state"], step: AsyncJobStep | undefined, output: string | undefined, gate: string | undefined): string | undefined {
510
+ if (unresolvedChildWatchdogBlockers(step?.watchdog).length > 0) return "resolve watchdog blockers";
511
+ if (step?.watchdog?.phase === "stale") return "inspect stale state";
512
+ if (step?.toolBudgetBlocked === true || step?.turnBudgetExceeded === true) return "inspect blocked state";
513
+ if (gate === "review blockers") return "resolve review blockers";
514
+ if (gate === "review required" || gate === "acceptance review") return "review output";
515
+ if (step?.activityState === "needs_attention") return "inspect attention";
516
+ if (state === "queued" || state === "pending") return "await launch";
517
+ if (state === "failed" || state === "rejected") return "inspect failure";
518
+ if (state === "partial") return "inspect partial state";
519
+ if (state === "paused") return "inspect paused state";
520
+ if (state === "stopped") return "inspect stopped state";
521
+ if ((state === "complete" || state === "completed") && gate === "reviewed") return "ready";
522
+ if ((state === "complete" || state === "completed") && output) return "inspect output";
523
+ return undefined;
524
+ }
525
+
526
+ function isTerminalLaneState(state: AsyncJobState["status"]): boolean {
527
+ return state !== "queued" && state !== "running";
528
+ }
529
+
530
+ /** Project already-loaded async status facts into one bounded, render-only lane row. */
531
+ export function projectAsyncLane(job: AsyncJobState, ...args: [selectedStep?: AsyncJobStep]): AsyncLaneProjection | undefined {
532
+ const selectedStep = args.length === 0 ? laneStepForJob(job) : args[0];
533
+ const trace = laneTraceForJob(job);
534
+ const workspace = job.cwd ? boundedLaneValue(shortenPath(job.cwd)) : undefined;
535
+ const label = compactTaskText(selectedStep?.description, selectedStep?.label)
536
+ ?? boundedLaneValue(trace?.label)
537
+ ?? (workspace ? undefined : boundedLaneValue(selectedStep?.workflowKey ?? job.workflowKey));
538
+ const role = boundedLaneValue(selectedStep?.agent ?? trace?.agent ?? job.agents?.[0] ?? widgetJobName(job), 32) ?? "subagent";
539
+ const phase = boundedLaneValue(selectedStep?.phase ?? trace?.phase);
540
+ const gate = laneGate(selectedStep);
541
+ const output = boundedLaneValue(selectedStep?.outputName);
542
+ const ref = boundedLaneValue(selectedStep?.workflowKey ?? job.workflowKey ?? job.asyncId.slice(0, 8), 24) ?? job.asyncId.slice(0, 8);
543
+ const chips = [
544
+ selectedStep?.context,
545
+ selectedStep?.structured ? "structured" : undefined,
546
+ selectedStep?.activityState === "active_long_running" ? "long-running" : undefined,
547
+ selectedStep?.activityState === "needs_attention" ? "attention" : undefined,
548
+ selectedStep?.watchdog?.phase === "stale" ? "stale" : undefined,
549
+ unresolvedChildWatchdogBlockers(selectedStep?.watchdog).length > 0 ? `wd:${unresolvedChildWatchdogBlockers(selectedStep?.watchdog).length}` : undefined,
550
+ selectedStep?.toolBudgetBlocked === true || selectedStep?.turnBudgetExceeded === true ? "blocked" : undefined,
551
+ ].filter((chip): chip is string => Boolean(chip));
552
+ const state = isTerminalLaneState(job.status) ? job.status : selectedStep?.status ?? job.status;
553
+ const next = laneNextAction(state, selectedStep, output, gate);
554
+ if (!label && !phase && !gate && !output && !selectedStep?.workflowKey && !job.workflowKey && !trace?.label && !trace?.phase) return undefined;
555
+ return { ...(label ? { label } : {}), role, ...(phase ? { phase } : {}), state, ...(gate ? { gate } : {}), ...(next ? { next } : {}), ...(output ? { output } : {}), ...(workspace ? { workspace } : {}), ref, chips };
556
+ }
557
+
558
+ function laneStateLabel(state: AsyncLaneProjection["state"], theme: Theme): string {
559
+ if (state === "running") return theme.fg("accent", "running");
560
+ if (state === "queued" || state === "pending") return theme.fg("muted", state);
561
+ if (state === "complete" || state === "completed") return theme.fg("success", "complete");
562
+ if (state === "failed" || state === "rejected") return theme.fg("error", state === "rejected" ? "rejected" : "failed");
563
+ return theme.fg("warning", state);
564
+ }
565
+
566
+ function formatLaneProjection(lane: AsyncLaneProjection, theme: Theme): string {
567
+ const label = boundedLaneValue(lane.label, 56);
568
+ const identity = [label, lane.role ? `role:${lane.role}` : undefined].filter(Boolean).join(" · ");
569
+ return `${identity ? theme.bold(identity) : theme.bold(lane.role)} · ${laneStateLabel(lane.state, theme)}`;
570
+ }
571
+
572
+ function formatLaneChip(chip: string, theme: Theme): string {
573
+ const text = `[${chip}]`;
574
+ if (chip === "blocked") return theme.fg("error", text);
575
+ if (chip === "stale") return theme.fg("warning", text);
576
+ return text;
577
+ }
578
+
579
+ function formatLaneProjectionDetails(lane: AsyncLaneProjection, theme: Theme): string | undefined {
580
+ const details = [
581
+ lane.phase ? `phase:${lane.phase}` : undefined,
582
+ lane.gate ? `gate:${lane.gate}` : undefined,
583
+ lane.next ? `next:${lane.next}` : undefined,
584
+ lane.output ? `out:${lane.output}` : undefined,
585
+ lane.workspace ? `workspace:${lane.workspace}` : lane.ref ? `ref:${lane.ref}` : undefined,
586
+ ].filter(Boolean);
587
+ const chips = lane.chips.map((chip) => formatLaneChip(chip, theme));
588
+ return [...(details.length ? [theme.fg("dim", details.join(" · "))] : []), ...chips].join(" · ") || undefined;
589
+ }
590
+
591
+ function formatLaneProjectionLines(lane: AsyncLaneProjection, theme: Theme, indent: string): string[] {
592
+ const details = formatLaneProjectionDetails(lane, theme);
593
+ return [
594
+ `${indent}${formatLaneProjection(lane, theme)}`,
595
+ ...(details ? [`${indent} ${details}`] : []),
596
+ ];
597
+ }
598
+
599
+ function laneRenderKey(job: AsyncJobState, projection?: WorkflowWidgetProjection): unknown {
600
+ const selectedStep = projection ? laneStepForJob(job, projection.steps) : laneStepForJob(job);
601
+ const lane = projectAsyncLane(job, selectedStep);
602
+ return lane ? [lane.label, lane.role, lane.phase, lane.state, lane.gate, lane.next, lane.output, lane.workspace, lane.ref, lane.chips] : undefined;
603
+ }
604
+
605
+ function widgetLaneDetailLines(job: AsyncJobState, theme: Theme, projection?: WorkflowWidgetProjection): string[] {
606
+ if (job.steps?.length && (job.mode === "parallel" || job.mode === "chain")) return [];
607
+ const selectedStep = projection ? laneStepForJob(job, projection.steps) : laneStepForJob(job);
608
+ const lane = projectAsyncLane(job, selectedStep);
609
+ return lane ? formatLaneProjectionLines(lane, theme, " ") : [];
610
+ }
611
+
612
+ function workflowPreflightLines(job: AsyncJobState, expanded = false): string[] {
613
+ if (job.mode !== "workflow" || !job.preflight) return [];
614
+ if (!expanded) {
615
+ const warning = formatWorkflowPreflightWarningSummary(job.workflow?.preflightWarnings, { indent: " ", hint: "expand for debug" });
616
+ return [
617
+ formatWorkflowPreflightPlanSummary(job.preflight, { indent: " " }),
618
+ ...(warning ? [warning] : []),
619
+ ];
620
+ }
621
+ return [
622
+ ...formatWorkflowPreflight(job.preflight, { indent: " " }).split("\n"),
623
+ ...(job.workflow?.preflightWarnings ? formatWorkflowPreflightWarnings(job.workflow.preflightWarnings, { indent: " " }).split("\n") : []),
624
+ ];
625
+ }
626
+
627
+ function workflowLabelForResult(details: Details, resultIndex: number): string | undefined {
628
+ const flatIndex = foregroundResultIndex(details, resultIndex);
629
+ const visit = (nodes: NonNullable<Details["workflowGraph"]>["nodes"]): string | undefined => {
630
+ for (const node of nodes) {
631
+ if (node.flatIndex === flatIndex && node.label.trim()) return node.label;
632
+ const nested = node.children ? visit(node.children) : undefined;
633
+ if (nested) return nested;
634
+ }
635
+ return undefined;
636
+ };
637
+ return details.workflowGraph ? visit(details.workflowGraph.nodes) : undefined;
638
+ }
639
+
640
+ function foregroundProgressForResult(details: Details, resultIndex: number): AgentProgress | undefined {
641
+ const result = details.results[resultIndex];
642
+ if (result?.progress) return result.progress;
643
+ const index = result?.index ?? resultIndex;
644
+ const indexed = details.progress?.find((progress) => progress.index === index);
645
+ if (indexed) return indexed;
646
+ return result?.agent
647
+ ? details.progress?.find((progress) => progress.agent === result.agent && progress.status === "running")
648
+ : undefined;
649
+ }
650
+
651
+ function foregroundResultIndex(details: Details, resultIndex: number): number {
652
+ const result = details.results[resultIndex];
653
+ if (typeof result?.index === "number") return result.index;
654
+ return foregroundProgressForResult(details, resultIndex)?.index ?? resultIndex;
655
+ }
656
+
657
+ function foregroundResultDisplayName(
658
+ details: Details,
659
+ resultIndex: number,
660
+ result: Details["results"][number] | undefined,
661
+ fallback: string,
662
+ ): string {
663
+ const progress = foregroundProgressForResult(details, resultIndex);
664
+ const agent = normalizedParallelDisplayText(result?.agent) ?? normalizedParallelDisplayText(progress?.agent);
665
+ const workflowLabel = normalizedParallelDisplayText(workflowLabelForResult(details, resultIndex));
666
+ if (workflowLabel) return compactTaskText(undefined, workflowLabel) ?? workflowLabel;
667
+
668
+ const sessionName = normalizedParallelDisplayText(result?.sessionName) ?? normalizedParallelDisplayText(progress?.sessionName);
669
+ if (sessionName) {
670
+ const sessionTask = stripRepeatedAgentPrefix(sessionName, agent);
671
+ if (sessionTask && sessionTask !== PROMPT_REDACTED && sessionTask.toLowerCase() !== agent?.toLowerCase()) {
672
+ return compactTaskText(sessionTask) ?? sessionTask;
673
+ }
674
+ }
675
+
676
+ return compactTaskText(result?.task) ?? compactTaskText(progress?.task) ?? agent ?? fallback;
677
+ }
678
+
679
+ function foregroundSingleDisplayName(result: Details["results"][number] | undefined): string {
680
+ return normalizedParallelDisplayText(result?.agent)
681
+ ?? normalizedParallelDisplayText(result?.sessionName)
682
+ ?? compactTaskText(result?.task)
683
+ ?? "subagent";
684
+ }
685
+
686
+ function hasLiveOutputSignal(line: string): boolean {
687
+ const clean = oneLine(line);
688
+ return liveOutputWordSignalPattern.test(clean) || liveOutputCodeSignalPattern.test(clean);
689
+ }
690
+
691
+ function isNoisyStatusLine(line: string): boolean {
692
+ const clean = oneLine(line);
693
+ return clean.length > 0
694
+ && clean.length <= 240
695
+ && !hasLiveOutputSignal(clean)
696
+ && noisyStatusPatterns.some((pattern) => pattern.test(clean));
697
+ }
698
+
699
+ function latestActivityText(line: string): string {
700
+ return oneLine(line)
701
+ .replace(/^i (?:will|can|need to|am going to)\s+/i, "")
702
+ .replace(/^i(?:'m|’m| am)\s+/i, "");
703
+ }
704
+
705
+ function progressUpdateSummary(lines: string[]): string {
706
+ const counts = new Map<string, number>();
707
+ for (const line of lines) counts.set(line.toLowerCase(), (counts.get(line.toLowerCase()) ?? 0) + 1);
708
+ const exactRepeatCount = Math.max(...counts.values());
709
+ const latest = latestActivityText(lines[lines.length - 1]!);
710
+ const repeat = exactRepeatCount > 1 ? ` · repeated ${exactRepeatCount}×` : "";
711
+ return `↻ ${lines.length} progress updates${repeat} · latest: ${latest}`;
712
+ }
713
+
714
+ function compactRecentOutputLines(recentOutput: string[] | undefined): string[] {
715
+ const lines: string[] = [];
716
+ const noisyLines: string[] = [];
717
+ const otherLines: string[] = [];
718
+ for (const rawLine of recentOutput ?? []) {
719
+ const line = oneLine(rawLine);
720
+ if (!line || line === "(running...)") continue;
721
+ lines.push(line);
722
+ (isNoisyStatusLine(line) ? noisyLines : otherLines).push(line);
723
+ }
724
+ if (noisyLines.length >= 4 && !otherLines.some(hasLiveOutputSignal)) {
725
+ if (otherLines.length === 0) {
726
+ return [
727
+ progressUpdateSummary(noisyLines),
728
+ "pattern: repeated short status lines",
729
+ ];
730
+ }
731
+ const visibleTail = otherLines.slice(-3);
732
+ const hiddenSignals = otherLines.slice(0, -3).filter(hasLiveOutputSignal);
733
+ return [
734
+ progressUpdateSummary(noisyLines),
735
+ ...(hiddenSignals.length > 0 ? [`… ${hiddenSignals.length} older signal ${hiddenSignals.length === 1 ? "line" : "lines"}: ${hiddenSignals.at(-1)}`] : []),
736
+ ...visibleTail,
737
+ ].slice(0, 5);
738
+ }
739
+ if (lines.length <= 5) return lines;
740
+
741
+ const tail = lines.slice(-5);
742
+ const hiddenSignals = lines.slice(0, -5).filter(hasLiveOutputSignal);
743
+ if (hiddenSignals.length === 0) return tail;
744
+ return [
745
+ `… ${hiddenSignals.length} older signal ${hiddenSignals.length === 1 ? "line" : "lines"}: ${hiddenSignals.at(-1)}`,
746
+ ...lines.slice(-4),
747
+ ];
748
+ }
749
+
750
+ function compactWorkflowError(error: string): string {
751
+ const outputMatch = error.match(/(?:^|\n)Output:\s*([\s\S]+)/);
752
+ if (!outputMatch) return oneLine(error);
753
+ const prefix = oneLine(error.slice(0, outputMatch.index)).replace(/:$/, "") || "Failed";
754
+ const outputLines = outputMatch[1]!.split(/\r?\n/).map(oneLine).filter(Boolean);
755
+ const allOutputLinesAreNoisy = outputLines.length > 0 && outputLines.every(isNoisyStatusLine);
756
+ const latest = outputLines.at(-1);
757
+ return allOutputLinesAreNoisy && latest
758
+ ? `${prefix} · latest: ${latestActivityText(latest)}`
759
+ : `${prefix} · ${oneLine(outputMatch[1] ?? "")}`;
760
+ }
761
+
762
+ const WORKFLOW_LIVE_ROW_LIMIT = 8;
763
+
764
+ function visibleWorkflowRows(rows: WorkflowChatProgressRow[]): { rows: WorkflowChatProgressRow[]; hiddenRows: number } {
765
+ if (rows.length <= WORKFLOW_LIVE_ROW_LIMIT) return { rows, hiddenRows: 0 };
766
+ const selected = new Set<string>();
767
+ const add = (row: WorkflowChatProgressRow): void => {
768
+ if (selected.size >= WORKFLOW_LIVE_ROW_LIMIT || selected.has(row.key)) return;
769
+ selected.add(row.key);
770
+ };
771
+ for (const row of [...rows].reverse()) {
772
+ if (row.state === "failed" || row.state === "detached") add(row);
773
+ }
774
+ for (const row of [...rows].reverse()) add(row);
775
+ return {
776
+ rows: rows.filter((row) => selected.has(row.key)),
777
+ hiddenRows: rows.length - selected.size,
778
+ };
779
+ }
780
+
781
+ function snapshotNowForProgress(progress: Pick<AgentProgress, "currentToolStartedAt" | "durationMs" | "lastActivityAt">): number | undefined {
782
+ if (progress.currentToolStartedAt !== undefined && progress.durationMs !== undefined) return progress.currentToolStartedAt + progress.durationMs;
783
+ return progress.lastActivityAt;
784
+ }
785
+
786
+ function renderToolArgsPreview(value: string, maxLength: number, expanded: boolean): string {
787
+ const normalized = sanitizeDisplayText(value);
788
+ if (expanded || normalized.length <= maxLength) return normalized;
789
+ return `${truncateDisplayText(normalized, maxLength)}...`;
790
+ }
791
+
792
+ function formatCurrentToolLine(
793
+ progress: Pick<AgentProgress, "currentTool" | "currentToolArgs" | "currentToolStartedAt">,
794
+ availableWidth: number,
795
+ expanded: boolean,
796
+ snapshotNow?: number,
797
+ ): string | undefined {
798
+ if (!progress.currentTool) return undefined;
799
+ const maxToolArgsLen = Math.max(50, availableWidth - 20);
800
+ const toolArgsPreview = progress.currentToolArgs
801
+ ? renderToolArgsPreview(progress.currentToolArgs, maxToolArgsLen, expanded)
802
+ : "";
803
+ const durationSuffix = progress.currentToolStartedAt !== undefined && snapshotNow !== undefined
804
+ ? ` | ${formatDuration(Math.max(0, snapshotNow - progress.currentToolStartedAt))}`
805
+ : "";
806
+ return toolArgsPreview
807
+ ? `${progress.currentTool}: ${toolArgsPreview}${durationSuffix}`
808
+ : `${progress.currentTool}${durationSuffix}`;
809
+ }
810
+
811
+ function buildLiveStatusLine(progress: Pick<AgentProgress, "activityState" | "lastActivityAt">, snapshotNow?: number): string | undefined {
812
+ if (progress.lastActivityAt !== undefined && snapshotNow !== undefined) return formatActivityLabel(progress.lastActivityAt, progress.activityState, snapshotNow);
813
+ if (progress.activityState === "needs_attention") return "needs attention";
814
+ if (progress.activityState === "active_long_running") return "active but long-running";
815
+ if (progress.lastActivityAt !== undefined) return "active";
816
+ return undefined;
817
+ }
818
+
819
+ function themeBold(theme: Theme, text: string): string {
820
+ return ((theme as { bold?: (value: string) => string }).bold?.(text)) ?? text;
821
+ }
822
+
823
+ function statJoin(theme: Theme, parts: string[]): string {
824
+ return parts.filter(Boolean).map((part) => theme.fg("dim", part)).join(` ${theme.fg("dim", "·")} `);
825
+ }
826
+
827
+ function formatTokenStat(tokens: number): string {
828
+ return `${formatTokens(tokens)} token`;
829
+ }
830
+
831
+ function formatToolUseStat(count: number): string {
832
+ return `${count} tool use${count === 1 ? "" : "s"}`;
833
+ }
834
+
835
+ function formatTotalCostStat(totalCost: Details["totalCost"] | undefined): string {
836
+ if (!totalCost || (totalCost.inputTokens === 0 && totalCost.outputTokens === 0 && totalCost.costUsd === 0)) return "";
837
+ const parts: string[] = [];
838
+ if (totalCost.inputTokens) parts.push(`in:${formatTokens(totalCost.inputTokens)}`);
839
+ if (totalCost.outputTokens) parts.push(`out:${formatTokens(totalCost.outputTokens)}`);
840
+ if (totalCost.costUsd) parts.push(`$${totalCost.costUsd.toFixed(4)}`);
841
+ return parts.join(" ");
842
+ }
843
+
844
+ function formatProgressStats(theme: Theme, progress: Pick<AgentProgress, "toolCount" | "tokens" | "durationMs"> | undefined, includeDuration = true): string {
845
+ if (!progress) return "";
846
+ const parts: string[] = [];
847
+ if (progress.toolCount > 0) parts.push(formatToolUseStat(progress.toolCount));
848
+ if (progress.tokens > 0) parts.push(formatTokenStat(progress.tokens));
849
+ if (includeDuration && progress.durationMs > 0) parts.push(formatDuration(progress.durationMs));
850
+ return statJoin(theme, parts);
851
+ }
852
+
853
+ function firstOutputLine(text: string): string {
854
+ return text.split("\n").find((line) => line.trim())?.trim() ?? "";
855
+ }
856
+
857
+ function resultStatusLine(result: Details["results"][number], output: string): string {
858
+ if (result.detached) return result.detachedReason ? `Detached: ${result.detachedReason}` : "Detached";
859
+ if (result.stopped) return "Stopped";
860
+ if (result.interrupted) return "Paused";
861
+ if (result.exitCode !== 0) return `Error: ${result.error ?? (firstOutputLine(output) || `exit ${result.exitCode}`)}`;
862
+ if (result.acceptance?.status && result.acceptance.status !== "not-required") return `Done · acceptance: ${result.acceptance.status}`;
863
+ if (hasEmptyTextOutputWithoutOutputTarget(result.task, output)) return "Done (no text output)";
864
+ return "Done";
865
+ }
866
+
867
+ type ResultPresentation = {
868
+ glyph: string;
869
+ label: "running" | "detached" | "stopped" | "paused" | "failed" | "partial" | "completed";
870
+ tone: "accent" | "warning" | "error" | "success";
871
+ };
872
+
873
+ function semanticResultPresentation(input: {
874
+ running?: boolean;
875
+ detached?: boolean;
876
+ stopped?: boolean;
877
+ interrupted?: boolean;
878
+ failed?: boolean;
879
+ partial?: boolean;
880
+ completedWithoutOutput?: boolean;
881
+ seed?: number;
882
+ frame?: number;
883
+ }): ResultPresentation {
884
+ if (input.running) {
885
+ const glyph = input.frame !== undefined ? runningGlyph((input.seed ?? 0) + input.frame) : runningGlyph(input.seed);
886
+ return { glyph, label: "running", tone: "accent" };
887
+ }
888
+ if (input.detached) return { glyph: "■", label: "detached", tone: "warning" };
889
+ if (input.stopped) return { glyph: "■", label: "stopped", tone: "warning" };
890
+ if (input.interrupted) return { glyph: "■", label: "paused", tone: "warning" };
891
+ if (input.failed) return { glyph: "✗", label: "failed", tone: "error" };
892
+ if (input.partial) return { glyph: "■", label: "partial", tone: "warning" };
893
+ return { glyph: "✓", label: "completed", tone: input.completedWithoutOutput ? "warning" : "success" };
894
+ }
895
+
896
+ function hasTerminalResultFlag(result: Details["results"][number]): boolean {
897
+ return Boolean(result.detached || result.stopped || result.interrupted);
898
+ }
899
+
900
+ function hasTerminalResult(result: Details["results"][number]): boolean {
901
+ if (hasTerminalResultFlag(result)) return true;
902
+ const status = result.progress?.status;
903
+ if (status === "running" || status === "pending") return false;
904
+ return result.exitCode !== undefined;
905
+ }
906
+
907
+ function isResultRunning(result: Details["results"][number], status = result.progress?.status): boolean {
908
+ return status === "running" && !hasTerminalResultFlag(result);
909
+ }
910
+
911
+ function detailsHaveRunningResult(details: Details): boolean {
912
+ return details.progress?.some((progress) => {
913
+ if (progress.status !== "running") return false;
914
+ const result = details.results.find((entry) => entry.progress?.index === progress.index) ?? details.results[progress.index];
915
+ return !result || !hasTerminalResultFlag(result);
916
+ })
917
+ || details.results.some((result) => isResultRunning(result))
918
+ || workflowGraphHasStatus(details, ["running"]);
919
+ }
920
+
921
+ function resultPresentation(result: Details["results"][number], output: string, running = isResultRunning(result), seed = progressRunningSeed(result.progress ?? result.progressSummary), frame?: number): ResultPresentation {
922
+ return semanticResultPresentation({
923
+ running,
924
+ detached: result.detached,
925
+ stopped: result.stopped,
926
+ interrupted: result.interrupted,
927
+ failed: result.exitCode !== 0,
928
+ completedWithoutOutput: hasEmptyTextOutputWithoutOutputTarget(result.task, output),
929
+ seed,
930
+ frame,
931
+ });
932
+ }
933
+
934
+ function resultGlyph(result: Details["results"][number], output: string, theme: Theme, running = isResultRunning(result), seed = progressRunningSeed(result.progress ?? result.progressSummary), frame?: number): string {
935
+ const presentation = resultPresentation(result, output, running, seed, frame);
936
+ return theme.fg(presentation.tone, presentation.glyph);
937
+ }
938
+
939
+ function styledResultPresentation(presentation: ResultPresentation, theme: Theme): { glyph: string; label: string } {
940
+ return {
941
+ glyph: theme.fg(presentation.tone, presentation.glyph),
942
+ label: theme.fg(presentation.tone, presentation.label),
943
+ };
944
+ }
945
+
946
+ function compactCurrentActivity(progress: AgentProgress): string {
947
+ const snapshotNow = snapshotNowForProgress(progress);
948
+ return formatCurrentToolLine(progress, getTermWidth() - 4, false, snapshotNow) ?? buildLiveStatusLine(progress, snapshotNow) ?? "thinking…";
949
+ }
950
+
951
+ function textDigest(text: string): string {
952
+ return createHash("sha256").update(text).digest("hex").slice(0, 16);
953
+ }
954
+
955
+ function displayTextRenderKey(text: string): unknown[] {
956
+ const normalized = sanitizeDisplayText(text);
957
+ return [normalized.length, textDigest(normalized)];
958
+ }
959
+
960
+ function expandedStepActivityRenderKey(step: AsyncJobStep): unknown[] {
961
+ return [
962
+ step.recentTools?.slice(-3).map((tool) => [tool.tool, displayTextRenderKey(tool.args), tool.endMs]),
963
+ compactRecentOutputLines(step.recentOutput).map(displayTextRenderKey),
964
+ ];
965
+ }
966
+
967
+ function widgetStepRenderKey(step: AsyncJobStep, index: number, expanded = false): unknown[] {
968
+ return [
969
+ step.index ?? index,
970
+ step.agent,
971
+ step.sessionName,
972
+ step.workflowKey,
973
+ step.phase,
974
+ step.label,
975
+ step.status,
976
+ step.activityState,
977
+ step.lastActivityAt,
978
+ step.currentTool,
979
+ step.currentToolArgs,
980
+ step.currentToolStartedAt,
981
+ step.currentPath,
982
+ step.turnCount,
983
+ step.toolCount,
984
+ step.startedAt,
985
+ step.endedAt,
986
+ step.durationMs,
987
+ step.tokens?.total,
988
+ step.model,
989
+ step.thinking,
990
+ step.context,
991
+ step.description,
992
+ step.outputName,
993
+ step.structured,
994
+ step.acceptance?.status,
995
+ step.acceptance?.reviewResult?.status,
996
+ step.review?.status,
997
+ step.toolBudgetBlocked,
998
+ step.turnBudgetExceeded,
999
+ step.timedOut,
1000
+ step.stopped,
1001
+ step.execution?.status,
1002
+ step.execution?.error,
1003
+ step.execution?.timedOut,
1004
+ step.execution?.interrupted,
1005
+ step.execution?.stopped,
1006
+ step.execution?.detached,
1007
+ step.watchdog?.phase,
1008
+ unresolvedChildWatchdogBlockers(step.watchdog).length,
1009
+ step.error,
1010
+ expanded ? expandedStepActivityRenderKey(step) : undefined,
1011
+ nestedRenderKey(step.children, expanded),
1012
+ ];
1013
+ }
1014
+
1015
+ function nestedRenderKey(children: NestedRunSummary[] | undefined, expanded = false): unknown[] {
1016
+ return (children ?? []).map((child) => [
1017
+ child.id,
1018
+ child.state,
1019
+ child.agent,
1020
+ child.sessionName,
1021
+ child.model,
1022
+ child.thinking,
1023
+ child.activityState,
1024
+ child.lastActivityAt,
1025
+ child.currentTool,
1026
+ child.currentToolStartedAt,
1027
+ child.currentPath,
1028
+ child.turnCount,
1029
+ child.toolCount,
1030
+ child.startedAt,
1031
+ child.endedAt,
1032
+ child.lastUpdate,
1033
+ child.error,
1034
+ child.totalTokens?.total,
1035
+ child.steps?.map((step, index) => widgetStepRenderKey({ ...step, agent: step.agent, status: step.status }, index, expanded)),
1036
+ nestedRenderKey(child.children, expanded),
1037
+ ]);
1038
+ }
1039
+
1040
+ function hostStepRenderKey(row: AsyncStatusWorkflowRow): unknown[] {
1041
+ return [
1042
+ row.kind,
1043
+ row.name,
1044
+ row.state,
1045
+ row.provider,
1046
+ row.role,
1047
+ row.verdict,
1048
+ row.reasonCode,
1049
+ row.detail,
1050
+ row.target,
1051
+ row.freshness,
1052
+ row.reportPath,
1053
+ ];
1054
+ }
1055
+
1056
+ export function widgetRenderKey(job: AsyncJobState, expanded = false): string {
1057
+ const projection = buildWorkflowWidgetProjection(job);
1058
+ return JSON.stringify({
1059
+ asyncDir: job.asyncDir,
1060
+ status: job.status,
1061
+ activityState: job.activityState,
1062
+ lastActivityAt: job.lastActivityAt,
1063
+ currentTool: job.currentTool,
1064
+ currentToolStartedAt: job.currentToolStartedAt,
1065
+ currentPath: job.currentPath,
1066
+ turnCount: job.turnCount,
1067
+ toolCount: job.toolCount,
1068
+ mode: job.mode,
1069
+ agents: job.agents,
1070
+ currentStep: job.currentStep,
1071
+ chainStepCount: job.chainStepCount,
1072
+ parallelGroups: job.parallelGroups,
1073
+ workflowHostSteps: projectAsyncWorkflowRows([], job.hostSteps).map(hostStepRenderKey),
1074
+ workflowGraph: job.mode === "workflow" && job.workflowGraph ? {
1075
+ currentNodeId: job.workflowGraph.currentNodeId,
1076
+ stages: projection.stages.map((node) => [node.id, node.status, node.agent, node.phase, node.label, node.flatIndex, node.outputName, node.structured, node.error]),
1077
+ } : undefined,
1078
+ preflight: expanded ? job.preflight : job.preflight ? formatWorkflowPreflightPlanSummary(job.preflight) : undefined,
1079
+ preflightWarnings: expanded ? job.workflow?.preflightWarnings : job.workflow?.preflightWarnings?.length || undefined,
1080
+ checklist: projection.checklist ? {
1081
+ total: projection.checklist.total,
1082
+ done: projection.checklist.done,
1083
+ running: projection.checklist.running,
1084
+ queued: projection.checklist.queued,
1085
+ blocked: projection.checklist.blocked,
1086
+ failed: projection.checklist.failed,
1087
+ phases: projection.checklist.phases.map((phase) => [phase.key, phase.state, phase.done, phase.total, phase.running, phase.queued, phase.blocked, phase.failed, phase.paused, phase.stopped, phase.items.map((item) => [item.key, item.state, item.currentTool, item.currentPath, item.durationMs, item.toolCount, item.error])]),
1088
+ } : undefined,
1089
+ steps: job.steps?.map((step, index) => widgetStepRenderKey(step, index, expanded)),
1090
+ nestedChildren: nestedRenderKey(job.nestedChildren, expanded),
1091
+ lane: laneRenderKey(job, projection),
1092
+ stepsTotal: job.stepsTotal,
1093
+ runningSteps: job.runningSteps,
1094
+ completedSteps: job.completedSteps,
1095
+ activeParallelGroup: job.activeParallelGroup,
1096
+ startedAt: job.startedAt,
1097
+ updatedAt: job.updatedAt,
1098
+ timedOut: job.timedOut,
1099
+ stopped: job.stopped,
1100
+ totalTokens: job.totalTokens,
1101
+ });
1102
+ }
1103
+
1104
+ function formatWidgetAgents(agents: string[]): string {
1105
+ const distinct = [...new Set(agents)];
1106
+ if (distinct.length === 1 && agents.length > 1) return `${distinct[0]} ×${agents.length}`;
1107
+ if (agents.length > 3) return `${agents.slice(0, 2).join(", ")} +${agents.length - 2} more`;
1108
+ return agents.join(", ");
1109
+ }
1110
+
1111
+ function widgetJobName(job: AsyncJobState): string {
1112
+ if (job.mode === "parallel") return "parallel";
1113
+ if (job.mode === "chain") return "chain";
1114
+ if (job.mode === "single" && job.agents?.length === 1) return job.agents[0]!;
1115
+ if (job.agents?.length) return formatWidgetAgents(job.agents);
1116
+ return job.mode ?? "subagent";
1117
+ }
1118
+
1119
+ function isSingleChildAsyncJob(job: AsyncJobState): boolean {
1120
+ return job.mode === "single"
1121
+ && job.steps?.length === 1
1122
+ && shouldSuppressSingleStep(job.chainStepCount, job.stepsTotal);
1123
+ }
1124
+
1125
+ function isCompletedWidgetStepStatus(status: AsyncJobStep["status"]): boolean {
1126
+ return status === "complete" || status === "completed";
1127
+ }
1128
+
1129
+ function singleChildAgentName(job: AsyncJobState, step: AsyncJobStep): string {
1130
+ return job.agents?.length === 1 ? job.agents[0]! : step.agent || widgetJobName(job);
1131
+ }
1132
+
1133
+ function hasSingleChildDetailEvidence(job: AsyncJobState, step: AsyncJobStep): boolean {
1134
+ return Boolean(
1135
+ step.error?.trim()
1136
+ || step.execution?.error?.trim()
1137
+ || step.phase?.trim()
1138
+ || step.label?.trim()
1139
+ || step.workflowKey?.trim()
1140
+ || step.outputName?.trim()
1141
+ || step.lane
1142
+ || job.workflowKey?.trim()
1143
+ || job.lane
1144
+ || laneTraceForJob(job)?.phase?.trim()
1145
+ || laneTraceForJob(job)?.label?.trim()
1146
+ || step.timedOut
1147
+ || step.stopped
1148
+ || step.execution?.timedOut
1149
+ || step.execution?.interrupted
1150
+ || step.execution?.stopped
1151
+ || step.execution?.detached
1152
+ || job.timedOut
1153
+ || job.stopped
1154
+ || ["failed", "partial", "paused", "stopped", "detached"].includes(step.execution?.status ?? "")
1155
+ || step.acceptance?.status === "rejected"
1156
+ || step.acceptance?.reviewResult?.status === "blockers"
1157
+ || step.review?.status === "blockers",
1158
+ );
1159
+ }
1160
+
1161
+ function shouldCollapseSingleChildDetails(job: AsyncJobState, step: AsyncJobStep): boolean {
1162
+ if (!isSingleChildAsyncJob(job) || hasSingleChildDetailEvidence(job, step)) return false;
1163
+ if (job.status === "running") return step.status === "running";
1164
+ if (job.status === "complete") return isCompletedWidgetStepStatus(step.status);
1165
+ return false;
1166
+ }
1167
+
1168
+ function singleChildTask(job: AsyncJobState, step: AsyncJobStep): string | undefined {
1169
+ const task = compactTaskText(step.description, step.label);
1170
+ if (task) return task;
1171
+ const sessionName = step.sessionName?.trim();
1172
+ if (!sessionName) return undefined;
1173
+ const agentName = singleChildAgentName(job, step);
1174
+ const sessionTask = stripRepeatedAgentPrefix(sessionName, agentName);
1175
+ return sessionTask === agentName ? undefined : compactTaskText(sessionTask);
1176
+ }
1177
+
1178
+ function widgetActivity(job: AsyncJobState): string {
1179
+ const facts: string[] = [];
1180
+ if (job.currentTool && job.currentToolStartedAt !== undefined && job.updatedAt !== undefined) facts.push(`${job.currentTool} ${formatDuration(Math.max(0, job.updatedAt - job.currentToolStartedAt))}`);
1181
+ else if (job.currentTool) facts.push(job.currentTool);
1182
+ if (job.currentPath) facts.push(shortenPath(job.currentPath));
1183
+ if (job.turnCount !== undefined) facts.push(`${job.turnCount} turns`);
1184
+ if (job.toolCount !== undefined) facts.push(`${job.toolCount} tools`);
1185
+ const activity = buildLiveStatusLine(job, job.updatedAt);
1186
+ if (activity && facts.length) return `${activity} · ${facts.join(" · ")}`;
1187
+ if (activity) return activity;
1188
+ if (facts.length) return facts.join(" · ");
1189
+ if (job.status === "running") return "thinking…";
1190
+ if (job.status === "queued") return "queued…";
1191
+ if (job.status === "paused") return "Paused";
1192
+ if (job.status === "stopped") return "Stopped";
1193
+ if (job.status === "partial") return "Partial";
1194
+ if (job.status === "failed") return "Failed";
1195
+ return "Done";
1196
+ }
1197
+
1198
+ function widgetStepRunningSeed(step: NonNullable<AsyncJobState["steps"]>[number], fallbackIndex?: number): number | undefined {
1199
+ return runningSeed(
1200
+ fallbackIndex,
1201
+ step.index,
1202
+ step.toolCount,
1203
+ step.turnCount,
1204
+ step.tokens?.total,
1205
+ step.lastActivityAt,
1206
+ step.currentToolStartedAt,
1207
+ step.durationMs,
1208
+ );
1209
+ }
1210
+
1211
+ function widgetStepsRunningSeed(steps: Array<NonNullable<AsyncJobState["steps"]>[number]> | undefined): number | undefined {
1212
+ let seed: number | undefined;
1213
+ for (const [index, step] of (steps ?? []).entries()) seed = runningSeed(seed, widgetStepRunningSeed(step, index));
1214
+ return seed;
1215
+ }
1216
+
1217
+ function widgetJobRunningSeed(job: AsyncJobState): number | undefined {
1218
+ return runningSeed(
1219
+ job.updatedAt,
1220
+ job.lastActivityAt,
1221
+ job.toolCount,
1222
+ job.turnCount,
1223
+ job.totalTokens?.total,
1224
+ job.currentStep,
1225
+ job.runningSteps,
1226
+ job.completedSteps,
1227
+ widgetStepsRunningSeed(job.steps),
1228
+ );
1229
+ }
1230
+
1231
+ function widgetJobsRunningSeed(jobs: AsyncJobState[]): number | undefined {
1232
+ let seed: number | undefined;
1233
+ for (const job of jobs) seed = runningSeed(seed, widgetJobRunningSeed(job));
1234
+ return seed;
1235
+ }
1236
+
1237
+ function widgetStatusGlyph(job: AsyncJobState, theme: Theme, frame?: number): string {
1238
+ if (job.status === "running") return theme.fg("accent", runningGlyph(animatedSeed(widgetJobRunningSeed(job), frame)));
1239
+ if (job.status === "queued") return theme.fg("muted", "◦");
1240
+ if (job.status === "complete") return theme.fg("success", "✓");
1241
+ if (job.status === "paused") return theme.fg("warning", "■");
1242
+ if (job.status === "stopped") return theme.fg("warning", "■");
1243
+ return theme.fg("error", "✗");
1244
+ }
1245
+
1246
+ function widgetStepGlyph(status: AsyncJobStep["status"], theme: Theme, seed?: number, frame?: number): string {
1247
+ if (status === "running") return theme.fg("accent", runningGlyph(animatedSeed(seed, frame)));
1248
+ if (status === "complete" || status === "completed") return theme.fg("success", "✓");
1249
+ if (status === "failed") return theme.fg("error", "✗");
1250
+ if (status === "paused") return theme.fg("warning", "■");
1251
+ if (status === "stopped") return theme.fg("warning", "■");
1252
+ return theme.fg("muted", "◦");
1253
+ }
1254
+
1255
+ function widgetStepStatus(status: AsyncJobStep["status"], theme: Theme): string {
1256
+ if (status === "running") return theme.fg("accent", "running");
1257
+ if (status === "complete" || status === "completed") return theme.fg("success", "complete");
1258
+ if (status === "failed") return theme.fg("error", "failed");
1259
+ if (status === "paused") return theme.fg("warning", "paused");
1260
+ if (status === "stopped") return theme.fg("warning", "stopped");
1261
+ return theme.fg("dim", status);
1262
+ }
1263
+
1264
+ function workflowChecklistStateLabel(state: WorkflowChecklistState): string {
1265
+ if (state === "running") return "running";
1266
+ if (state === "complete") return "complete";
1267
+ return state;
1268
+ }
1269
+
1270
+ function workflowChecklistGlyph(item: { state: WorkflowChecklistState; startedAt?: number; durationMs?: number; toolCount?: number; currentToolStartedAt?: number }, theme: Theme, frame?: number): string {
1271
+ if (item.state === "running") return theme.fg("accent", runningGlyph(animatedSeed(runningSeed(item.startedAt, item.durationMs, item.toolCount, item.currentToolStartedAt), frame)));
1272
+ if (item.state === "complete") return theme.fg("success", "✓");
1273
+ if (item.state === "blocked") return theme.fg("error", "!");
1274
+ if (item.state === "failed") return theme.fg("error", "✗");
1275
+ if (item.state === "paused" || item.state === "stopped") return theme.fg("warning", "■");
1276
+ return theme.fg("muted", "◦");
1277
+ }
1278
+
1279
+ function workflowChecklistItemPriority(state: WorkflowChecklistState): number {
1280
+ if (state === "blocked") return 0;
1281
+ if (state === "failed") return 1;
1282
+ if (state === "running") return 2;
1283
+ if (state === "paused") return 3;
1284
+ if (state === "stopped") return 4;
1285
+ if (state === "queued") return 5;
1286
+ return 6;
1287
+ }
1288
+
1289
+ function workflowChecklistItemLine(item: WorkflowChecklistItem, theme: Theme, indent: string, frame?: number): string {
1290
+ const identity = [item.label, item.agent && item.agent !== item.label ? item.agent : undefined].filter(Boolean).join(" · ");
1291
+ const context = contextModeBadge(theme, item.context);
1292
+ const state = item.state === "complete" ? "" : ` ${theme.fg("dim", `· ${workflowChecklistStateLabel(item.state)}`)}`;
1293
+ const details = [
1294
+ item.currentTool ? `${item.currentTool}${item.durationMs !== undefined ? ` ${formatDuration(item.durationMs)}` : ""}` : undefined,
1295
+ !item.currentTool && item.currentPath ? shortenPath(item.currentPath) : undefined,
1296
+ !item.currentTool && item.durationMs !== undefined ? formatDuration(item.durationMs) : undefined,
1297
+ item.toolCount !== undefined ? `${item.toolCount} tools` : undefined,
1298
+ item.outputName ? `out:${item.outputName}` : undefined,
1299
+ item.error ? `error:${oneLine(item.error)}` : undefined,
1300
+ ].filter(Boolean).join(" · ");
1301
+ return `${indent}${workflowChecklistGlyph(item, theme, frame)} ${theme.bold(identity || item.key)}${context}${state}${details ? ` ${theme.fg("dim", `· ${details}`)}` : ""}`;
1302
+ }
1303
+
1304
+ const COLLAPSED_WORKFLOW_PHASE_LIMIT = 4;
1305
+
1306
+ function workflowChecklistWidgetLines(checklist: WorkflowChecklistProjection | undefined, theme: Theme, indent: string, expanded: boolean, frame?: number, includeSummary = true, limitPhases = !expanded, includeBottleneckOutput = expanded): string[] {
1307
+ if (!checklist?.total) return [];
1308
+ const lines = includeSummary ? [`${indent}${theme.fg("dim", `Checklist ${formatWorkflowChecklistSummary(checklist)}`)}`] : [];
1309
+ const phases = !limitPhases || checklist.phases.length <= COLLAPSED_WORKFLOW_PHASE_LIMIT
1310
+ ? checklist.phases
1311
+ : checklist.phases
1312
+ .map((phase, index) => ({ phase, index }))
1313
+ .sort((left, right) => Number(left.phase.state !== "running") - Number(right.phase.state !== "running")
1314
+ || Number(left.phase.state === "complete") - Number(right.phase.state === "complete")
1315
+ || left.index - right.index)
1316
+ .slice(0, COLLAPSED_WORKFLOW_PHASE_LIMIT)
1317
+ .sort((left, right) => left.index - right.index)
1318
+ .map(({ phase }) => phase);
1319
+ for (const phase of phases) {
1320
+ const phaseItem = phase.items.find((item) => item.state === "running") ?? phase.items[0];
1321
+ const glyph = workflowChecklistGlyph({
1322
+ state: phase.state,
1323
+ startedAt: phaseItem?.startedAt,
1324
+ durationMs: phaseItem?.durationMs,
1325
+ toolCount: phaseItem?.toolCount,
1326
+ currentToolStartedAt: phaseItem?.currentToolStartedAt,
1327
+ }, theme, frame);
1328
+ lines.push(`${indent}${glyph} ${theme.bold(formatWorkflowChecklistPhase(phase))}`);
1329
+ if (expanded) {
1330
+ for (const item of [...phase.items].sort((left, right) => workflowChecklistItemPriority(left.state) - workflowChecklistItemPriority(right.state))) {
1331
+ lines.push(workflowChecklistItemLine(item, theme, `${indent} `, frame));
1332
+ }
1333
+ }
1334
+ }
1335
+ const bottleneck = formatWorkflowChecklistBottleneck(checklist.bottleneck, { includeOutput: includeBottleneckOutput });
1336
+ if (bottleneck) {
1337
+ const tone = checklist.bottleneck?.state === "blocked" || checklist.bottleneck?.state === "failed" ? "error" : checklist.bottleneck?.state === "running" ? "accent" : "warning";
1338
+ lines.push(`${indent}${theme.fg(tone, `bottleneck · ${bottleneck}`)}`);
1339
+ }
1340
+ return lines;
1341
+ }
1342
+
1343
+ function widgetStepActivity(step: NonNullable<AsyncJobState["steps"]>[number], snapshotNow?: number): string {
1344
+ const facts: string[] = [];
1345
+ if (step.currentTool && step.currentToolStartedAt !== undefined && snapshotNow !== undefined) facts.push(`${step.currentTool} ${formatDuration(Math.max(0, snapshotNow - step.currentToolStartedAt))}`);
1346
+ else if (step.currentTool) facts.push(step.currentTool);
1347
+ if (step.currentPath) facts.push(shortenPath(step.currentPath));
1348
+ if (step.turnCount !== undefined) facts.push(`${step.turnCount} turns`);
1349
+ if (step.toolCount !== undefined) facts.push(`${step.toolCount} tools`);
1350
+ if (step.tokens?.total) facts.push(formatTokenUsage(step.tokens, "token"));
1351
+ const activity = buildLiveStatusLine(step, snapshotNow);
1352
+ if (activity && facts.length) return `${activity} · ${facts.join(" · ")}`;
1353
+ if (activity) return activity;
1354
+ return facts.join(" · ");
1355
+ }
1356
+
1357
+
1358
+ function widgetChainDetails(job: AsyncJobState, theme: Theme, expanded = false, width = getTermWidth(), frame?: number): string[] {
1359
+ if (!job.steps?.length) return [];
1360
+ const total = job.chainStepCount ?? job.steps.length;
1361
+ const lines: string[] = [];
1362
+ for (const span of buildAsyncChainStepSpans(total, job.steps.length, job.parallelGroups)) {
1363
+ const steps = job.steps.slice(span.start, span.start + span.count);
1364
+ if (span.isParallel) {
1365
+ lines.push(...parallelWidgetGroupDetails(job, theme, { steps, total: span.count, stepIndex: span.stepIndex, chainTotal: total }, expanded, width, frame, false));
1366
+ continue;
1367
+ }
1368
+ const step = steps[0];
1369
+ if (!step) {
1370
+ lines.push(` ${theme.fg("dim", `◦ Step ${span.stepIndex + 1}/${total}: pending`)}`);
1371
+ continue;
1372
+ }
1373
+ lines.push(...foregroundStyleWidgetStepLines(job, theme, step, "Step", span.stepIndex + 1, total, expanded, width, frame));
1374
+ }
1375
+ return lines;
1376
+ }
1377
+
1378
+ function widgetParallelAgentDetails(job: AsyncJobState, theme: Theme, expanded = false, width = getTermWidth(), frame?: number): string[] {
1379
+ if (!job.steps?.length) return [];
1380
+ if (job.mode !== "parallel" && job.mode !== "chain") return [];
1381
+ if (job.mode === "chain" && !job.activeParallelGroup && job.parallelGroups?.length) return widgetChainDetails(job, theme, expanded, width, frame);
1382
+ const group = activeParallelWidgetGroup(job);
1383
+ if (group) return parallelWidgetGroupDetails(job, theme, group, expanded, width, frame, Boolean(job.activeParallelGroup));
1384
+ const total = job.stepsTotal ?? job.steps.length;
1385
+ const lines: string[] = [];
1386
+ for (const [index, step] of job.steps.entries()) {
1387
+ const marker = index === job.steps.length - 1 ? "└" : "├";
1388
+ const activity = widgetStepActivity(step, job.updatedAt);
1389
+ const itemTitle = job.mode === "parallel" || job.activeParallelGroup ? "Agent" : "Step";
1390
+ const modelDisplay = modelThinkingBadge(theme, step.model, step.thinking);
1391
+ const label = compactTaskText(step.description, step.label);
1392
+ const display = step.sessionName?.trim() || (label ? `${label} (${step.agent})` : step.agent);
1393
+ lines.push(` ${theme.fg("dim", `${marker} ${widgetStepGlyph(step.status, theme, widgetStepRunningSeed(step, index), frame)} ${itemTitle} ${index + 1}/${total}: ${display} · ${widgetStepStatus(step.status, theme)}${modelDisplay}${activity ? ` · ${activity}` : ""}`)}`);
1394
+ const lane = projectAsyncLane(job, step);
1395
+ if (lane) lines.push(...formatLaneProjectionLines(lane, theme, " "));
1396
+ for (const nestedLine of formatNestedWidgetLines(step.children, theme, width, expanded, job.updatedAt, expanded ? 8 : 6)) lines.push(` ${nestedLine}`);
1397
+ }
1398
+ return lines;
1399
+ }
1400
+
1401
+ function parseParallelGroupAgentCount(label: string | undefined): number | undefined {
1402
+ if (!label || !label.startsWith("[") || !label.endsWith("]")) return undefined;
1403
+ const inner = label.slice(1, -1).trim();
1404
+ if (!inner) return 0;
1405
+ return inner.split("+").map((part) => part.trim()).filter(Boolean).length;
1406
+ }
1407
+
1408
+ interface ChainStepSpan {
1409
+ stepIndex: number;
1410
+ start: number;
1411
+ count: number;
1412
+ isParallel: boolean;
1413
+ status?: WorkflowNodeStatus;
1414
+ label?: string;
1415
+ error?: string;
1416
+ }
1417
+
1418
+ function buildChainStepSpans(details: Pick<Details, "chainAgents" | "workflowGraph">): ChainStepSpan[] {
1419
+ if (details.workflowGraph?.nodes?.length) {
1420
+ const spans: ChainStepSpan[] = [];
1421
+ let flatCursor = 0;
1422
+ for (const node of details.workflowGraph.nodes) {
1423
+ if (node.stepIndex === undefined) continue;
1424
+ if (node.kind === "parallel-group" || node.kind === "dynamic-parallel-group") {
1425
+ const childFlatIndexes = (node.children ?? [])
1426
+ .map((child) => child.flatIndex)
1427
+ .filter((value): value is number => typeof value === "number");
1428
+ const start = childFlatIndexes.length ? Math.min(...childFlatIndexes) : flatCursor;
1429
+ const count = node.children?.length ?? 0;
1430
+ spans.push({ stepIndex: node.stepIndex, start, count, isParallel: true, status: node.status, label: node.label, error: node.error });
1431
+ flatCursor = Math.max(flatCursor, start + count);
1432
+ continue;
1433
+ }
1434
+ const start = node.flatIndex ?? flatCursor;
1435
+ spans.push({ stepIndex: node.stepIndex, start, count: 1, isParallel: false, status: node.status, label: node.label, error: node.error });
1436
+ flatCursor = Math.max(flatCursor, start + 1);
1437
+ }
1438
+ if (spans.length) return spans.sort((left, right) => left.stepIndex - right.stepIndex);
1439
+ }
1440
+
1441
+ if (!details.chainAgents?.length) return [];
1442
+ const spans: ChainStepSpan[] = [];
1443
+ let start = 0;
1444
+ for (let stepIndex = 0; stepIndex < details.chainAgents.length; stepIndex++) {
1445
+ const label = details.chainAgents[stepIndex]!;
1446
+ const parsedCount = parseParallelGroupAgentCount(label);
1447
+ const count = parsedCount ?? 1;
1448
+ spans.push({ stepIndex, start, count, isParallel: parsedCount !== undefined });
1449
+ start += count;
1450
+ }
1451
+ return spans;
1452
+ }
1453
+
1454
+ function buildAsyncChainStepSpans(total: number, stepCount: number, parallelGroups: AsyncParallelGroupStatus[] = []): ChainStepSpan[] {
1455
+ const groupsByStep = new Map<number, AsyncParallelGroupStatus>();
1456
+ for (const group of parallelGroups) {
1457
+ if (!groupsByStep.has(group.stepIndex)) groupsByStep.set(group.stepIndex, group);
1458
+ }
1459
+ const spans: ChainStepSpan[] = [];
1460
+ let flatIndex = 0;
1461
+ for (let stepIndex = 0; stepIndex < total; stepIndex++) {
1462
+ const group = groupsByStep.get(stepIndex);
1463
+ if (group) {
1464
+ spans.push({ stepIndex, start: group.start, count: group.count, isParallel: true });
1465
+ flatIndex = Math.max(flatIndex, group.start + group.count);
1466
+ continue;
1467
+ }
1468
+ spans.push({ stepIndex, start: flatIndex, count: flatIndex < stepCount ? 1 : 0, isParallel: false });
1469
+ flatIndex++;
1470
+ }
1471
+ return spans;
1472
+ }
1473
+
1474
+ interface ParallelWidgetGroup {
1475
+ steps: AsyncJobStep[];
1476
+ total: number;
1477
+ stepIndex?: number;
1478
+ chainTotal?: number;
1479
+ }
1480
+
1481
+ interface ParallelWidgetStepRow {
1482
+ step: AsyncJobStep;
1483
+ index: number;
1484
+ rowLabel: string;
1485
+ }
1486
+
1487
+ function normalizedParallelDisplayText(value: string | undefined): string | undefined {
1488
+ if (!value?.trim()) return undefined;
1489
+ const normalized = oneLine(value);
1490
+ return normalized && normalized !== PROMPT_REDACTED ? normalized : undefined;
1491
+ }
1492
+
1493
+ function parallelWidgetStepDisplayName(step: AsyncJobStep): string {
1494
+ const agent = normalizedParallelDisplayText(step.agent);
1495
+ const explicitLabel = normalizedParallelDisplayText(step.label);
1496
+ if (explicitLabel) {
1497
+ const label = compactTaskText(step.description, explicitLabel) ?? explicitLabel;
1498
+ return agent ? `${label} (${agent})` : label;
1499
+ }
1500
+
1501
+ const sessionName = normalizedParallelDisplayText(step.sessionName);
1502
+ if (sessionName) {
1503
+ const sessionTask = stripRepeatedAgentPrefix(sessionName, agent);
1504
+ if (sessionTask && sessionTask !== PROMPT_REDACTED && sessionTask.toLowerCase() !== agent?.toLowerCase()) return sessionTask;
1505
+ }
1506
+
1507
+ return compactTaskText(step.description) ?? agent ?? "subagent";
1508
+ }
1509
+
1510
+ function parallelWidgetStepPriority(step: AsyncJobStep): number {
1511
+ if (step.status === "running" || step.activityState === "needs_attention") return 0;
1512
+ switch (step.status) {
1513
+ case "failed":
1514
+ case "rejected":
1515
+ case "partial":
1516
+ case "stopped":
1517
+ case "paused":
1518
+ return 1;
1519
+ case "complete":
1520
+ case "completed":
1521
+ return 2;
1522
+ default:
1523
+ return 3;
1524
+ }
1525
+ }
1526
+
1527
+ function parallelWidgetStepRows(steps: AsyncJobStep[], total: number, prioritizeActive: boolean): ParallelWidgetStepRow[] {
1528
+ const indexed = steps.map((step, index) => ({ step, index, displayName: parallelWidgetStepDisplayName(step) }));
1529
+ if (prioritizeActive) indexed.sort((left, right) => parallelWidgetStepPriority(left.step) - parallelWidgetStepPriority(right.step) || left.index - right.index);
1530
+ return withDuplicateLabelDiscriminators(indexed, total).map(({ displayName, ...row }) => row);
1531
+ }
1532
+
1533
+ function activeParallelWidgetGroup(job: AsyncJobState): ParallelWidgetGroup | undefined {
1534
+ const steps = job.steps ?? [];
1535
+ if (!steps.length) return undefined;
1536
+ if (job.mode === "parallel") return { steps, total: job.stepsTotal ?? steps.length };
1537
+ if (job.mode !== "chain" || !job.activeParallelGroup) return undefined;
1538
+
1539
+ const chainTotal = job.chainStepCount ?? job.stepsTotal ?? steps.length;
1540
+ const spans = buildAsyncChainStepSpans(chainTotal, steps.length, job.parallelGroups);
1541
+ const currentStep = job.currentStep;
1542
+ const activeSpan = currentStep === undefined
1543
+ ? spans.find((span) => span.isParallel)
1544
+ : spans.find((span) => span.isParallel
1545
+ && currentStep >= span.start
1546
+ && currentStep < span.start + span.count);
1547
+ return {
1548
+ steps,
1549
+ total: activeSpan?.count ?? job.stepsTotal ?? steps.length,
1550
+ stepIndex: activeSpan?.stepIndex,
1551
+ chainTotal,
1552
+ };
1553
+ }
1554
+
1555
+ function parallelWidgetGroupHeader(
1556
+ group: ParallelWidgetGroup,
1557
+ theme: Theme,
1558
+ frame?: number,
1559
+ ): string {
1560
+ const status = aggregateStepStatus(group.steps);
1561
+ const label = group.stepIndex !== undefined && group.chainTotal !== undefined
1562
+ ? `Step ${group.stepIndex + 1}/${group.chainTotal}: parallel group`
1563
+ : "parallel group";
1564
+ return ` ${widgetStepGlyph(status, theme, widgetStepsRunningSeed(group.steps), frame)} ${themeBold(theme, label)} ${theme.fg("dim", "·")} ${theme.fg("dim", formatParallelOutcome(group.steps, group.total))}`;
1565
+ }
1566
+
1567
+ function parallelWidgetGroupDetails(
1568
+ job: AsyncJobState,
1569
+ theme: Theme,
1570
+ group: ParallelWidgetGroup,
1571
+ expanded: boolean,
1572
+ width: number,
1573
+ frame: number | undefined,
1574
+ prioritizeActive: boolean,
1575
+ ): string[] {
1576
+ const lines = [parallelWidgetGroupHeader(group, theme, frame)];
1577
+ const rows = parallelWidgetStepRows(group.steps, group.total, prioritizeActive);
1578
+ for (const [rowIndex, row] of rows.entries()) {
1579
+ const marker = rowIndex === rows.length - 1 && rows.length >= group.total ? "└─" : "├─";
1580
+ lines.push(...foregroundStyleWidgetStepLines(job, theme, row.step, "Agent", row.index + 1, group.total, expanded, width, frame, {
1581
+ rowLabel: row.rowLabel,
1582
+ rowIndent: " ",
1583
+ detailIndent: " ",
1584
+ rowMarker: marker,
1585
+ includeCurrentPath: true,
1586
+ }));
1587
+ }
1588
+ for (let index = rows.length; index < group.total; index++) {
1589
+ const marker = index === group.total - 1 ? "└─" : "├─";
1590
+ lines.push(` ${marker} ${theme.fg("muted", "◦")} ${theme.fg("dim", "pending")}`);
1591
+ }
1592
+ return lines;
1593
+ }
1594
+
1595
+ function isDoneResult(result: Details["results"][number]): boolean {
1596
+ const status = result.progress?.status;
1597
+ if (status === "completed") return true;
1598
+ if (status === "running" || status === "pending") return false;
1599
+ if (result.interrupted || result.detached) return false;
1600
+ return result.exitCode === 0;
1601
+ }
1602
+
1603
+ function workflowGraphHasStatus(details: Pick<Details, "workflowGraph">, statuses: WorkflowNodeStatus[]): boolean {
1604
+ return details.workflowGraph?.nodes.some((node) => statuses.includes(node.status)) ?? false;
1605
+ }
1606
+
1607
+ interface ChainRenderResultEntry {
1608
+ kind: "result";
1609
+ resultIndex: number;
1610
+ rowNumber: number;
1611
+ rowLabel?: string;
1612
+ agentName: string;
1613
+ displayIndex: number;
1614
+ isParallel?: boolean;
1615
+ }
1616
+
1617
+ interface ChainRenderGroupEntry {
1618
+ kind: "group";
1619
+ stepLabel: string;
1620
+ groupLabel?: string;
1621
+ status: WorkflowNodeStatus;
1622
+ error?: string;
1623
+ }
1624
+
1625
+ type ChainRenderEntry = ChainRenderResultEntry | ChainRenderGroupEntry;
1626
+
1627
+ function chainSpanStatus(details: Details, span: ChainStepSpan): WorkflowNodeStatus {
1628
+ if (span.status) return span.status;
1629
+ const results = details.results.slice(span.start, span.start + span.count);
1630
+ if (results.some((result) => isResultRunning(result))) return "running";
1631
+ if (results.some((result) => !hasTerminalResultFlag(result) && (result.progress?.status === "failed" || result.exitCode !== 0) && !isResultRunning(result))) return "failed";
1632
+ if (results.some((result) => result.stopped)) return "stopped";
1633
+ if (results.some((result) => result.interrupted)) return "paused";
1634
+ if (results.some((result) => result.detached || result.progress?.status === "detached")) return "detached";
1635
+ if (results.length < span.count) return "pending";
1636
+ if (results.length > 0 && results.every(isDoneResult)) return "completed";
1637
+ return "pending";
1638
+ }
1639
+
1640
+ function withDuplicateForegroundLabels(entries: ChainRenderResultEntry[], total: number): ChainRenderResultEntry[] {
1641
+ return withDuplicateLabelDiscriminators(
1642
+ entries.map((entry) => ({ ...entry, index: entry.displayIndex, displayName: entry.agentName })),
1643
+ total,
1644
+ ).map(({ displayName, rowLabel, ...entry }) => ({
1645
+ ...entry,
1646
+ rowLabel: rowLabel === displayName ? undefined : rowLabel.slice(0, -(displayName.length + 2)),
1647
+ }));
1648
+ }
1649
+
1650
+ function buildChainRenderEntries(details: Details, label: MultiProgressLabel): ChainRenderEntry[] | undefined {
1651
+ if (details.mode !== "chain" || !label.hasParallelInChain || label.showActiveGroupOnly) return undefined;
1652
+ const entries: ChainRenderEntry[] = [];
1653
+ for (const span of buildChainStepSpans(details)) {
1654
+ if (span.isParallel) {
1655
+ entries.push({
1656
+ kind: "group",
1657
+ stepLabel: `Step ${span.stepIndex + 1}/${label.logicalStepCount}: parallel group`,
1658
+ groupLabel: span.label?.trim() || undefined,
1659
+ status: chainSpanStatus(details, span),
1660
+ error: span.error,
1661
+ });
1662
+ const groupEntries: ChainRenderResultEntry[] = [];
1663
+ for (let index = span.start; index < span.start + span.count; index++) {
1664
+ const result = details.results[index];
1665
+ const localIndex = foregroundResultIndex(details, index);
1666
+ const displayIndex = localIndex >= span.start && localIndex < span.start + span.count
1667
+ ? localIndex - span.start
1668
+ : index - span.start;
1669
+ groupEntries.push({
1670
+ kind: "result",
1671
+ resultIndex: index,
1672
+ rowNumber: index - span.start + 1,
1673
+ agentName: foregroundResultDisplayName(details, index, result, `agent-${displayIndex + 1}`),
1674
+ displayIndex,
1675
+ isParallel: true,
1676
+ });
1677
+ }
1678
+ entries.push(...withDuplicateForegroundLabels(groupEntries, span.count));
1679
+ continue;
1680
+ }
1681
+ for (let index = span.start; index < span.start + span.count; index++) {
1682
+ const result = details.results[index];
1683
+ entries.push({
1684
+ kind: "result",
1685
+ resultIndex: index,
1686
+ rowNumber: span.stepIndex + 1,
1687
+ rowLabel: resultRowLabel(label, span.stepIndex + 1),
1688
+ agentName: foregroundResultDisplayName(details, index, result, details.chainAgents?.[span.stepIndex] ?? `step-${span.stepIndex + 1}`),
1689
+ displayIndex: foregroundResultIndex(details, index),
1690
+ });
1691
+ }
1692
+ }
1693
+ return entries;
1694
+ }
1695
+
1696
+ interface MultiProgressLabel {
1697
+ headerLabel: string;
1698
+ itemTitle: "Step" | "Agent";
1699
+ totalCount: number;
1700
+ hasParallelInChain: boolean;
1701
+ activeParallelGroup: boolean;
1702
+ groupStartIndex: number;
1703
+ groupEndIndex: number;
1704
+ showActiveGroupOnly: boolean;
1705
+ logicalStepCount: number;
1706
+ }
1707
+
1708
+ function buildMultiProgressLabel(details: Pick<Details, "mode" | "results" | "progress" | "totalSteps" | "currentStepIndex" | "chainAgents" | "workflowGraph">, hasRunning: boolean): MultiProgressLabel {
1709
+ const stepSpans = buildChainStepSpans(details);
1710
+ const hasParallelInChain = details.mode === "chain" && stepSpans.some((span) => span.isParallel);
1711
+ const activeParallelGroup = details.mode === "chain"
1712
+ && details.currentStepIndex !== undefined
1713
+ && stepSpans.some((span) => span.stepIndex === details.currentStepIndex && span.isParallel);
1714
+ const itemTitle: "Step" | "Agent" = details.mode === "parallel" || activeParallelGroup ? "Agent" : "Step";
1715
+
1716
+ if (details.mode === "parallel") {
1717
+ const totalCount = details.totalSteps ?? details.results.length;
1718
+ const statuses = new Array(totalCount).fill("pending") as Array<"pending" | "running" | "completed" | "failed" | "stopped" | "detached">;
1719
+ for (const progress of details.progress ?? []) {
1720
+ if (progress.index >= 0 && progress.index < totalCount) statuses[progress.index] = progress.status;
1721
+ }
1722
+ for (let i = 0; i < details.results.length; i++) {
1723
+ const result = details.results[i]!;
1724
+ const progressFromArray = details.progress?.find((progress) => progress.index === i)
1725
+ || details.progress?.find((progress) => progress.agent === result.agent && progress.status === "running");
1726
+ const index = result.progress?.index ?? progressFromArray?.index ?? i;
1727
+ if (index < 0 || index >= totalCount) continue;
1728
+ const status = result.stopped
1729
+ ? "stopped"
1730
+ : result.interrupted || result.detached
1731
+ ? "detached"
1732
+ : result.progress?.status
1733
+ ?? (result.exitCode === 0 ? "completed" : "failed");
1734
+ statuses[index] = status;
1735
+ }
1736
+ const running = statuses.filter((status) => status === "running").length;
1737
+ const done = statuses.filter((status) => status === "completed").length;
1738
+ const headerLabel = hasRunning
1739
+ ? `${formatAgentRunningLabel(running)} · ${done}/${totalCount} done`
1740
+ : `${done}/${totalCount} done`;
1741
+ return { headerLabel, itemTitle, totalCount, hasParallelInChain, activeParallelGroup, groupStartIndex: 0, groupEndIndex: totalCount, showActiveGroupOnly: false, logicalStepCount: totalCount };
1742
+ }
1743
+
1744
+ if (activeParallelGroup) {
1745
+ const currentStepIndex = details.currentStepIndex!;
1746
+ const span = stepSpans[currentStepIndex];
1747
+ const groupSize = span?.count ?? 1;
1748
+ const groupStart = span?.start ?? 0;
1749
+ const groupEnd = groupStart + groupSize;
1750
+ let running = 0;
1751
+ let done = 0;
1752
+ for (let index = groupStart; index < groupEnd; index++) {
1753
+ const progressEntry = details.progress?.find((progress) => progress.index === index);
1754
+ const resultEntry = details.results.find((result) => result.progress?.index === index) ?? details.results[index];
1755
+ if (progressEntry?.status === "running" && (!resultEntry || !hasTerminalResultFlag(resultEntry))) {
1756
+ running++;
1757
+ continue;
1758
+ }
1759
+ if (progressEntry?.status === "completed") {
1760
+ done++;
1761
+ continue;
1762
+ }
1763
+ if (resultEntry && isDoneResult(resultEntry)) done++;
1764
+ }
1765
+ const totalSteps = details.totalSteps ?? details.chainAgents?.length ?? 1;
1766
+ const headerLabel = hasRunning
1767
+ ? `step ${currentStepIndex + 1}/${totalSteps} · parallel group: ${formatAgentRunningLabel(running)} · ${done}/${groupSize} done`
1768
+ : `step ${currentStepIndex + 1}/${totalSteps} · parallel group: ${done}/${groupSize} done`;
1769
+ return { headerLabel, itemTitle, totalCount: groupSize, hasParallelInChain, activeParallelGroup, groupStartIndex: groupStart, groupEndIndex: groupEnd, showActiveGroupOnly: true, logicalStepCount: totalSteps };
1770
+ }
1771
+
1772
+ if (details.mode === "chain" && details.chainAgents?.length) {
1773
+ const totalCount = details.totalSteps ?? details.chainAgents.length;
1774
+ const doneLogical = stepSpans.filter((span) => {
1775
+ if (span.status && span.status !== "completed") return false;
1776
+ if (span.count === 0) return span.status === "completed";
1777
+ for (let index = span.start; index < span.start + span.count; index++) {
1778
+ const progressEntry = details.progress?.find((progress) => progress.index === index);
1779
+ const resultEntry = details.results.find((result) => result.progress?.index === index) ?? details.results[index];
1780
+ if (progressEntry?.status === "running" || progressEntry?.status === "pending" || progressEntry?.status === "failed") return false;
1781
+ if (!resultEntry || !isDoneResult(resultEntry)) return false;
1782
+ }
1783
+ return true;
1784
+ }).length;
1785
+ const currentStep = details.currentStepIndex !== undefined ? details.currentStepIndex + 1 : Math.min(totalCount, doneLogical + (hasRunning ? 1 : 0));
1786
+ const headerLabel = hasRunning ? `step ${currentStep}/${totalCount}` : `step ${doneLogical}/${totalCount}`;
1787
+ return { headerLabel, itemTitle, totalCount, hasParallelInChain, activeParallelGroup, groupStartIndex: 0, groupEndIndex: details.results.length, showActiveGroupOnly: false, logicalStepCount: totalCount };
1788
+ }
1789
+
1790
+ const totalCount = details.totalSteps ?? details.results.length;
1791
+ const currentStep = details.currentStepIndex !== undefined ? details.currentStepIndex + 1 : Math.min(totalCount, details.results.filter(isDoneResult).length + (hasRunning ? 1 : 0));
1792
+ const done = details.results.filter(isDoneResult).length;
1793
+ const headerLabel = hasRunning ? `step ${currentStep}/${totalCount}` : `step ${done}/${totalCount}`;
1794
+ return { headerLabel, itemTitle, totalCount, hasParallelInChain, activeParallelGroup, groupStartIndex: 0, groupEndIndex: details.results.length, showActiveGroupOnly: false, logicalStepCount: totalCount };
1795
+ }
1796
+
1797
+ function resultRowLabel(label: MultiProgressLabel, stepNumber: number): string | undefined {
1798
+ if (label.itemTitle === "Agent") return undefined;
1799
+ if (shouldSuppressSingleStep(label.logicalStepCount)) return undefined;
1800
+ return `Step ${stepNumber}/${label.logicalStepCount}`;
1801
+ }
1802
+
1803
+ function buildForegroundResultEntries(
1804
+ details: Details,
1805
+ label: MultiProgressLabel,
1806
+ displayStart: number,
1807
+ displayEnd: number,
1808
+ useResultsDirectly: boolean,
1809
+ ): ChainRenderResultEntry[] {
1810
+ const fallbackLabel = label.itemTitle.toLowerCase();
1811
+ const entries = Array.from({ length: displayEnd - displayStart }, (_, offset): ChainRenderResultEntry => {
1812
+ const index = displayStart + offset;
1813
+ const result = details.results[index];
1814
+ const stableIndex = foregroundResultIndex(details, index);
1815
+ const rowNumber = label.showActiveGroupOnly ? index - label.groupStartIndex + 1 : stableIndex + 1;
1816
+ const fallbackAgent = useResultsDirectly
1817
+ ? (result?.agent || `${fallbackLabel}-${rowNumber}`)
1818
+ : (details.chainAgents![index] || result?.agent || `${fallbackLabel}-${rowNumber}`);
1819
+ const displayIndex = label.activeParallelGroup && stableIndex >= label.groupStartIndex && stableIndex < label.groupEndIndex
1820
+ ? stableIndex - label.groupStartIndex
1821
+ : label.activeParallelGroup ? index - label.groupStartIndex : stableIndex;
1822
+ return {
1823
+ kind: "result",
1824
+ resultIndex: index,
1825
+ rowNumber,
1826
+ rowLabel: resultRowLabel(label, rowNumber),
1827
+ agentName: foregroundResultDisplayName(details, index, result, fallbackAgent),
1828
+ displayIndex,
1829
+ };
1830
+ });
1831
+ return label.itemTitle === "Agent" ? withDuplicateForegroundLabels(entries, label.totalCount) : entries;
1832
+ }
1833
+
1834
+ function widgetStats(job: AsyncJobState, theme: Theme, projection = buildWorkflowWidgetProjection(job), collapsed = false): string {
1835
+ const parts: string[] = [];
1836
+ const { stageProgress } = projection;
1837
+ const stepsTotal = stageProgress?.total ?? job.stepsTotal ?? (job.agents?.length ?? 1);
1838
+ const isSingleChild = isSingleChildAsyncJob(job);
1839
+ const checklistPrimary = collapsed && job.mode === "workflow" && projection.checklist !== undefined;
1840
+ if (checklistPrimary) {
1841
+ parts.push(formatWorkflowChecklistSummary(projection.checklist!));
1842
+ } else if (stageProgress) {
1843
+ const currentStage = stageProgress.current !== undefined ? projection.stages[stageProgress.current] : undefined;
1844
+ const focus = currentStage
1845
+ ? [compactTaskText(undefined, currentStage.label) ?? boundedLaneValue(currentStage.id), currentStage.agent ? boundedLaneValue(currentStage.agent) : "", workflowNodeStatusLabel(currentStage.status)].filter(Boolean)
1846
+ : [];
1847
+ parts.push(["staged lane", stageProgress.current !== undefined ? `stage ${stageProgress.current + 1}/${stageProgress.total}` : `${stageProgress.total} stages`, ...focus].join(" · "));
1848
+ } else if (job.activeParallelGroup) {
1849
+ const running = job.runningSteps ?? (job.status === "running" ? 1 : 0);
1850
+ const done = job.completedSteps ?? (job.status === "complete" ? stepsTotal : 0);
1851
+ if (job.mode === "parallel") {
1852
+ if (job.status === "running" && running > 0) parts.push(formatAgentRunningLabel(running));
1853
+ if (stepsTotal > 0) parts.push(`${done}/${stepsTotal} done`);
1854
+ } else {
1855
+ const activeGroup = job.currentStep !== undefined
1856
+ ? job.parallelGroups?.find((group) => job.currentStep! >= group.start && job.currentStep! < group.start + group.count)
1857
+ : job.parallelGroups?.find((group) => group.start === 0);
1858
+ const logicalStep = activeGroup?.stepIndex ?? job.currentStep ?? 0;
1859
+ const total = job.chainStepCount ?? stepsTotal;
1860
+ const groupParts = [`${done}/${stepsTotal} done`];
1861
+ if (job.status === "running" && running > 0) groupParts.unshift(formatAgentRunningLabel(running));
1862
+ parts.push(`step ${logicalStep + 1}/${total} · parallel group: ${groupParts.join(" · ")}`);
1863
+ }
1864
+ } else if (job.currentStep !== undefined) {
1865
+ if (job.mode === "chain") {
1866
+ const total = job.chainStepCount ?? stepsTotal;
1867
+ parts.push(`step ${flatToLogicalStepIndex(job.currentStep, total, job.parallelGroups ?? []) + 1}/${total}`);
1868
+ } else if (!isSingleChild) {
1869
+ parts.push(`step ${job.currentStep + 1}/${stepsTotal}`);
1870
+ }
1871
+ } else if (stepsTotal > 1) {
1872
+ parts.push(`steps ${stepsTotal}`);
1873
+ }
1874
+ if (projection.checklist && !checklistPrimary) parts.push(formatWorkflowChecklistSummary(projection.checklist));
1875
+ if (job.toolCount !== undefined) parts.push(formatToolUseStat(job.toolCount));
1876
+ if (job.totalTokens?.total) parts.push(formatTokenUsage(job.totalTokens, "token"));
1877
+ if (job.startedAt !== undefined && job.updatedAt !== undefined) parts.push(formatDuration(Math.max(0, job.updatedAt - job.startedAt)));
1878
+ return statJoin(theme, parts);
1879
+ }
1880
+
1881
+ function widgetStepStats(theme: Theme, step: NonNullable<AsyncJobState["steps"]>[number]): string {
1882
+ return statJoin(theme, [
1883
+ step.turnCount !== undefined ? `${step.turnCount} turns` : "",
1884
+ step.toolCount !== undefined ? formatToolUseStat(step.toolCount) : "",
1885
+ step.tokens
1886
+ ? step.contextLimit !== undefined
1887
+ ? formatContextUsage(step.tokens, step.contextLimit) ?? formatTokenUsage(step.tokens, "token")
1888
+ : step.tokens.total ? formatTokenUsage(step.tokens, "token") : ""
1889
+ : "",
1890
+ step.durationMs !== undefined ? formatDuration(step.durationMs) : "",
1891
+ ]);
1892
+ }
1893
+
1894
+ function modelThinkingBadge(theme: Theme, model?: string, thinking?: string): string {
1895
+ const label = formatModelThinking(model, thinking);
1896
+ return label ? theme.fg("dim", ` (${label})`) : "";
1897
+ }
1898
+
1899
+ function widgetStepActivityLine(step: NonNullable<AsyncJobState["steps"]>[number], width: number, expanded: boolean, snapshotNow?: number): string {
1900
+ const toolLine = formatCurrentToolLine(step, width, expanded, snapshotNow);
1901
+ if (toolLine) return toolLine;
1902
+ const activity = buildLiveStatusLine(step, snapshotNow);
1903
+ if (activity) return activity;
1904
+ if (step.status === "running") return "thinking…";
1905
+ return "";
1906
+ }
1907
+
1908
+ function widgetOutputPath(job: AsyncJobState, step: NonNullable<AsyncJobState["steps"]>[number]): string | undefined {
1909
+ if (typeof step.index !== "number") return undefined;
1910
+ return path.join(job.asyncDir, `output-${step.index}.log`);
1911
+ }
1912
+
1913
+ function nestedRunName(run: NestedRunSummary): string {
1914
+ if (run.sessionName?.trim()) return run.sessionName.trim();
1915
+ if (run.agent) return run.agent;
1916
+ if (run.agents?.length) return formatWidgetAgents(run.agents);
1917
+ return run.id;
1918
+ }
1919
+
1920
+ function nestedStatusGlyph(state: NestedRunSummary["state"] | NestedStepSummary["status"], theme: Theme, seed?: number): string {
1921
+ if (state === "running") return theme.fg("accent", runningGlyph(seed));
1922
+ if (state === "complete" || state === "completed") return theme.fg("success", "✓");
1923
+ if (state === "failed") return theme.fg("error", "✗");
1924
+ if (state === "partial") return theme.fg("warning", "■");
1925
+ if (state === "paused") return theme.fg("warning", "■");
1926
+ if (state === "stopped") return theme.fg("warning", "■");
1927
+ return theme.fg("muted", "◦");
1928
+ }
1929
+
1930
+ function nestedRunSeed(run: NestedRunSummary): number | undefined {
1931
+ return runningSeed(run.lastUpdate, run.lastActivityAt, run.currentStep, run.toolCount, run.turnCount, run.totalTokens?.total, run.currentToolStartedAt);
1932
+ }
1933
+
1934
+ function formatClockTime(ms: number | undefined): string | undefined {
1935
+ if (ms === undefined || !Number.isFinite(ms)) return undefined;
1936
+ const date = new Date(ms);
1937
+ const pad = (value: number) => value.toString().padStart(2, "0");
1938
+ return `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
1939
+ }
1940
+
1941
+ function nestedRunEventTime(run: NestedRunSummary): number | undefined {
1942
+ return run.state === "running"
1943
+ ? (run.lastActivityAt ?? run.currentToolStartedAt ?? run.lastUpdate ?? run.startedAt)
1944
+ : (run.endedAt ?? run.lastUpdate ?? run.lastActivityAt ?? run.startedAt);
1945
+ }
1946
+
1947
+ function nestedStepTimestamp(step: NestedStepSummary, fallback?: number): string | undefined {
1948
+ return formatClockTime(step.status === "running"
1949
+ ? (step.lastActivityAt ?? step.currentToolStartedAt ?? fallback ?? step.startedAt)
1950
+ : (step.endedAt ?? step.lastActivityAt ?? fallback ?? step.startedAt));
1951
+ }
1952
+
1953
+ function nestedTimestampPrefix(timestamp: string | undefined): string {
1954
+ return timestamp ? `[${timestamp}] ` : "";
1955
+ }
1956
+
1957
+ function nestedActivity(input: Pick<NestedRunSummary | NestedStepSummary, "activityState" | "lastActivityAt" | "currentTool" | "currentToolStartedAt" | "currentPath" | "turnCount" | "toolCount">, state: NestedRunSummary["state"] | NestedStepSummary["status"], snapshotNow?: number): string {
1958
+ const facts: string[] = [];
1959
+ if (input.currentTool && input.currentToolStartedAt !== undefined && snapshotNow !== undefined) facts.push(`${input.currentTool} ${formatDuration(Math.max(0, snapshotNow - input.currentToolStartedAt))}`);
1960
+ else if (input.currentTool) facts.push(input.currentTool);
1961
+ if (input.currentPath) facts.push(shortenPath(input.currentPath));
1962
+ if (input.turnCount !== undefined) facts.push(`${input.turnCount} turns`);
1963
+ if (input.toolCount !== undefined) facts.push(`${input.toolCount} tools`);
1964
+ const activity = buildLiveStatusLine(input, snapshotNow);
1965
+ if (activity && facts.length) return `${activity} · ${facts.join(" · ")}`;
1966
+ if (activity) return activity;
1967
+ if (facts.length) return facts.join(" · ");
1968
+ if (state === "running") return "thinking…";
1969
+ if (state === "queued" || state === "pending") return "queued…";
1970
+ if (state === "paused") return "Paused";
1971
+ if (state === "stopped") return "Stopped";
1972
+ if (state === "partial") return "Partial";
1973
+ if (state === "failed") return "Failed";
1974
+ return "Done";
1975
+ }
1976
+
1977
+ function formatNestedWidgetLines(children: NestedRunSummary[] | undefined, theme: Theme, width: number, expanded: boolean, snapshotNow?: number, lineBudget = expanded ? 12 : 1): string[] {
1978
+ if (!children?.length || lineBudget <= 0) return [];
1979
+ if (!expanded) {
1980
+ type CollapsedRow = { text: string; prefix: string };
1981
+ const rows: CollapsedRow[] = [];
1982
+ const maxLeaves = 4;
1983
+ const maxLines = Math.min(6, lineBudget);
1984
+ let leaves = 0;
1985
+ let overflow = 0;
1986
+ const appendLeaf = (step: NestedStepSummary | NestedRunSummary, prefix: string, fallback?: number): void => {
1987
+ if (leaves >= maxLeaves) {
1988
+ overflow++;
1989
+ return;
1990
+ }
1991
+ leaves++;
1992
+ const state = "status" in step ? step.status : step.state;
1993
+ const modelThinking = formatModelThinking(step.model, step.thinking);
1994
+ const activity = nestedActivity(step, state, snapshotNow ?? fallback);
1995
+ const timestamp = "status" in step ? nestedStepTimestamp(step, fallback) : formatClockTime(nestedRunEventTime(step));
1996
+ const error = step.error ? ` · ${step.error}` : "";
1997
+ const name = "status" in step ? childDisplayName(step) : nestedRunName(step);
1998
+ rows.push({
1999
+ prefix,
2000
+ text: `${nestedTimestampPrefix(timestamp)}${nestedStatusGlyph(state, theme)} ${name} · ${state}${modelThinking ? ` · ${modelThinking}` : ""}${activity ? ` · ${activity}` : ""}${error}`,
2001
+ });
2002
+ };
2003
+ for (const child of children) {
2004
+ const steps = (child.mode === "parallel" || child.mode === "chain") ? child.steps ?? [] : [];
2005
+ if (steps.length > 0) {
2006
+ const ownerModelThinking = formatModelThinking(child.model, child.thinking);
2007
+ const ownerActivity = nestedActivity(child, child.state, snapshotNow ?? child.lastUpdate);
2008
+ const ownerError = child.error ? ` · ${child.error}` : "";
2009
+ rows.push({
2010
+ prefix: "↳ ",
2011
+ text: `OWNER ${nestedStatusGlyph(child.state, theme, nestedRunSeed(child))} ${nestedRunName(child)} · ${child.state}${ownerModelThinking ? ` · ${ownerModelThinking}` : ""}${ownerActivity ? ` · ${ownerActivity}` : ""}${ownerError}`,
2012
+ });
2013
+ for (const step of steps) appendLeaf(step, "↳ │ ", child.lastUpdate);
2014
+ } else {
2015
+ appendLeaf(child, "↳ ", child.lastUpdate);
2016
+ }
2017
+ }
2018
+ if (overflow > 0) rows.push({ prefix: "↳ ", text: `… +${overflow} more nested leaves` });
2019
+ const visibleRows = rows.length <= maxLines
2020
+ ? rows
2021
+ : overflow > 0
2022
+ ? [...rows.slice(0, Math.max(0, maxLines - 1)), rows.at(-1)!]
2023
+ : rows.slice(0, maxLines);
2024
+ return visibleRows.map((row, index) => {
2025
+ const marker = index === visibleRows.length - 1 ? "└─" : "├─";
2026
+ const prefix = row.prefix;
2027
+ const text = row.text.startsWith("OWNER ") ? row.text.slice("OWNER ".length) : row.text;
2028
+ return truncLine(theme.fg("dim", `${prefix}${marker} ${text}`), width);
2029
+ });
2030
+ }
2031
+ const lines: string[] = [];
2032
+ const maxDepth = 2;
2033
+ const append = (items: NestedRunSummary[] | undefined, depth: number, prefix: string): void => {
2034
+ if (!items?.length || lines.length >= lineBudget) return;
2035
+ if (depth > maxDepth) {
2036
+ const aggregate = formatNestedAggregate(items);
2037
+ if (aggregate && lines.length < lineBudget) lines.push(theme.fg("dim", `${prefix}↳ ${aggregate}`));
2038
+ return;
2039
+ }
2040
+ for (let index = 0; index < items.length; index++) {
2041
+ const child = items[index]!;
2042
+ if (lines.length >= lineBudget) {
2043
+ const aggregate = formatNestedAggregate(items.slice(index));
2044
+ if (aggregate) lines[lines.length - 1] = theme.fg("dim", `${prefix}↳ ${aggregate}`);
2045
+ return;
2046
+ }
2047
+ const activity = nestedActivity(child, child.state, snapshotNow ?? child.lastUpdate);
2048
+ const error = child.error ? ` · ${child.error}` : "";
2049
+ const modelThinking = formatModelThinking(child.model, child.thinking);
2050
+ lines.push(theme.fg("dim", `${prefix}↳ ${nestedTimestampPrefix(formatClockTime(nestedRunEventTime(child)))}${nestedStatusGlyph(child.state, theme, nestedRunSeed(child))} ${nestedRunName(child)} · ${child.state}${modelThinking ? ` · ${modelThinking}` : ""} · ${activity}${error}`));
2051
+ if (depth === maxDepth) {
2052
+ const aggregate = formatNestedAggregate([...(child.steps?.flatMap((step) => step.children ?? []) ?? []), ...(child.children ?? [])]);
2053
+ if (aggregate && lines.length < lineBudget) lines.push(theme.fg("dim", `${prefix} ↳ ${aggregate}`));
2054
+ continue;
2055
+ }
2056
+ for (const step of child.steps ?? []) {
2057
+ if (lines.length >= lineBudget) return;
2058
+ const modelThinking = formatModelThinking(step.model, step.thinking);
2059
+ lines.push(theme.fg("dim", `${prefix} ↳ ${nestedTimestampPrefix(nestedStepTimestamp(step, child.lastUpdate))}${nestedStatusGlyph(step.status, theme)} ${childDisplayName(step)} · ${step.status}${modelThinking ? ` · ${modelThinking}` : ""} · ${nestedActivity(step, step.status, snapshotNow ?? child.lastUpdate)}`));
2060
+ append(step.children, depth + 1, `${prefix} `);
2061
+ }
2062
+ append(child.children, depth + 1, `${prefix} `);
2063
+ }
2064
+ };
2065
+ append(children, 0, "");
2066
+ return lines.map((line) => truncLine(line, width));
2067
+ }
2068
+
2069
+ function foregroundStyleWidgetStepLines(
2070
+ job: AsyncJobState,
2071
+ theme: Theme,
2072
+ step: NonNullable<AsyncJobState["steps"]>[number],
2073
+ itemTitle: "Agent" | "Stage" | "Step",
2074
+ index: number,
2075
+ total: number,
2076
+ expanded: boolean,
2077
+ width: number,
2078
+ frame?: number,
2079
+ options?: { rowLabel?: string; rowIndent?: string; detailIndent?: string; rowMarker?: string; includeCurrentPath?: boolean },
2080
+ ): string[] {
2081
+ const rowIndent = options?.rowIndent ?? " ";
2082
+ const detailIndent = options?.detailIndent ?? " ";
2083
+ const status = widgetStepStatus(step.status, theme);
2084
+ const stats = widgetStepStats(theme, step);
2085
+ const modelDisplay = modelThinkingBadge(theme, step.model, step.thinking);
2086
+ const collapseDetails = shouldCollapseSingleChildDetails(job, step);
2087
+ const displayName = collapseDetails ? singleChildAgentName(job, step) : childDisplayName(step);
2088
+ const stageName = itemTitle === "Stage"
2089
+ ? compactTaskText(undefined, step.label) ?? boundedLaneValue(step.workflowKey) ?? displayName
2090
+ : undefined;
2091
+ const stageIdentity = stageName && stageName !== displayName ? `${stageName} (${displayName})` : stageName ?? displayName;
2092
+ const rowLabel = collapseDetails ? displayName : (options?.rowLabel ?? `${itemTitle} ${index}/${total}: ${itemTitle === "Stage" ? stageIdentity : displayName}`);
2093
+ const rowMarker = options?.rowMarker ? `${options.rowMarker} ` : "";
2094
+ const lines = [`${rowIndent}${rowMarker}${widgetStepGlyph(step.status, theme, widgetStepRunningSeed(step, index - 1), frame)} ${themeBold(theme, rowLabel)}${contextModeBadge(theme, step.context)} ${theme.fg("dim", "·")} ${status}${modelDisplay}${stats ? ` ${theme.fg("dim", "·")} ${stats}` : ""}`];
2095
+ const lane = projectAsyncLane(job, step);
2096
+ if (lane) lines.push(...formatLaneProjectionLines(lane, theme, detailIndent));
2097
+ const task = collapseDetails ? singleChildTask(job, step) : compactTaskText(step.description, step.label);
2098
+ if (task) lines.push(`${detailIndent}${theme.fg("dim", `task: ${task}`)}`);
2099
+ const activity = widgetStepActivityLine(step, width, expanded, job.updatedAt);
2100
+ const currentPath = options?.includeCurrentPath && step.currentPath ? shortenPath(step.currentPath) : undefined;
2101
+ const activityWithPath = currentPath && activity && !activity.includes(currentPath)
2102
+ ? `${activity} · ${currentPath}`
2103
+ : activity ?? currentPath;
2104
+ if (activityWithPath) lines.push(`${detailIndent}${theme.fg("dim", `⎿ ${activityWithPath}`)}`);
2105
+ for (const nestedLine of formatNestedWidgetLines(step.children, theme, width, expanded, job.updatedAt, expanded ? 12 : 6)) {
2106
+ lines.push(`${detailIndent}${nestedLine}`);
2107
+ }
2108
+ const error = step.error?.trim() || step.execution?.error?.trim();
2109
+ if (error) lines.push(`${detailIndent}${theme.fg("error", `error: ${oneLine(error)}`)}`);
2110
+ if (step.status === "running") {
2111
+ if (!expanded) lines.push(`${detailIndent}${theme.fg("accent", liveDetailHintText())}`);
2112
+ const output = widgetOutputPath(job, step);
2113
+ if (output) lines.push(`${detailIndent}${theme.fg("dim", `output: ${shortenPath(output)}`)}`);
2114
+ if (expanded) {
2115
+ const liveStatus = buildLiveStatusLine(step, job.updatedAt);
2116
+ if (liveStatus && liveStatus !== activity) lines.push(`${detailIndent}${theme.fg("accent", liveStatus)}`);
2117
+ for (const tool of step.recentTools?.slice(-3) ?? []) {
2118
+ const maxArgsLen = Math.max(40, width - 30);
2119
+ const argsPreview = renderToolArgsPreview(tool.args, maxArgsLen, expanded);
2120
+ lines.push(`${detailIndent} ${theme.fg("dim", `${tool.tool}${argsPreview ? `: ${argsPreview}` : ""}`)}`);
2121
+ }
2122
+ for (const line of compactRecentOutputLines(step.recentOutput)) {
2123
+ lines.push(`${detailIndent} ${theme.fg("dim", line)}`);
2124
+ }
2125
+ }
2126
+ }
2127
+ return lines;
2128
+ }
2129
+
2130
+ function hostStepWidgetLines(job: AsyncJobState, theme: Theme, indent: string): string[] {
2131
+ const rows = projectAsyncWorkflowRows([], job.hostSteps).filter((row) => row.kind);
2132
+ const visible = rows.slice(0, 8);
2133
+ const lines = visible.map((row) => {
2134
+ const state = hostStepVerdictLabel(row.state as HostStepState, row.verdict as HostStepVerdict | undefined);
2135
+ const glyph = state === "running" ? theme.fg("accent", "●")
2136
+ : state === "pending" ? theme.fg("muted", "◦")
2137
+ : state === "pass" ? theme.fg("success", "✓")
2138
+ : state === "fail" || state === "error" ? theme.fg("error", "✗")
2139
+ : theme.fg("warning", "■");
2140
+ const details = [
2141
+ row.provider ? `provider:${row.provider}` : undefined,
2142
+ row.role ? `role:${row.role}` : undefined,
2143
+ row.target,
2144
+ row.detail,
2145
+ row.reasonCode ? `reason:${row.reasonCode}` : undefined,
2146
+ row.freshness?.stale ? "stale" : row.freshness?.observedRef ? `ref:${row.freshness.observedRef}` : undefined,
2147
+ row.reportPath ? `out:${hostStepReportName(row.reportPath)}` : undefined,
2148
+ ].filter(Boolean).join(" · ");
2149
+ return `${indent}${glyph} ${row.kind}: ${row.name} · ${state}${details ? ` · ${details}` : ""}`;
2150
+ });
2151
+ if (rows.length > visible.length) lines.push(`${indent}${theme.fg("dim", `… +${rows.length - visible.length} host steps hidden`)}`);
2152
+ return lines;
2153
+ }
2154
+
2155
+ function foregroundStyleWidgetDetails(job: AsyncJobState, theme: Theme, expanded: boolean, width: number, frame?: number, projection = buildWorkflowWidgetProjection(job)): string[] {
2156
+ const { steps } = projection;
2157
+ const checklistPrimary = !expanded && job.mode === "workflow" && projection.checklist !== undefined;
2158
+ if (checklistPrimary) {
2159
+ const lines = [
2160
+ ...workflowPreflightLines(job, false),
2161
+ ...workflowChecklistWidgetLines(projection.checklist, theme, " ", false, frame, false),
2162
+ ];
2163
+ if (job.status === "running" || projection.checklist!.running > 0) lines.push(` ${theme.fg("accent", liveDetailHintText())}`);
2164
+ return lines;
2165
+ }
2166
+ if (!steps.length) {
2167
+ const lane = projectAsyncLane(job, laneStepForJob(job, steps));
2168
+ return [
2169
+ ...workflowPreflightLines(job, expanded),
2170
+ ...workflowChecklistWidgetLines(projection.checklist, theme, " ", expanded, frame),
2171
+ ...(lane ? formatLaneProjectionLines(lane, theme, " ") : []),
2172
+ ...hostStepWidgetLines(job, theme, " "),
2173
+ ` ${theme.fg("dim", `⎿ ${widgetActivity(job)}`)}`,
2174
+ ...formatNestedWidgetLines(job.nestedChildren, theme, width, expanded, job.updatedAt, expanded ? 12 : 6).map((line) => ` ${line}`),
2175
+ ];
2176
+ }
2177
+ if (job.mode === "chain" && !job.activeParallelGroup && job.parallelGroups?.length) return widgetChainDetails(job, theme, expanded, width, frame);
2178
+ const lines: string[] = [
2179
+ ...workflowPreflightLines(job, expanded),
2180
+ ...workflowChecklistWidgetLines(projection.checklist, theme, " ", expanded, frame),
2181
+ ];
2182
+ const group = activeParallelWidgetGroup(job);
2183
+ if (group) {
2184
+ lines.push(...parallelWidgetGroupDetails(job, theme, group, expanded, width, frame, Boolean(job.activeParallelGroup)));
2185
+ } else {
2186
+ const { stageProgress, plannedKeys } = projection;
2187
+ const total = job.mode === "chain"
2188
+ ? job.chainStepCount ?? job.stepsTotal ?? steps.length
2189
+ : stageProgress?.total ?? job.stepsTotal ?? steps.length;
2190
+ const stageTotal = stageProgress?.total ?? total;
2191
+ const extraStepCount = plannedKeys
2192
+ ? steps.filter((step) => step.workflowKey === undefined || !plannedKeys.has(step.workflowKey)).length
2193
+ : total;
2194
+ let extraStepIndex = 0;
2195
+ for (const [index, step] of steps.entries()) {
2196
+ const isPlannedStage = plannedKeys !== undefined && step.workflowKey !== undefined && plannedKeys.has(step.workflowKey);
2197
+ const itemTitle = isPlannedStage ? "Stage" : "Step";
2198
+ const displayIndex = isPlannedStage ? (step.index ?? index) + 1 : plannedKeys ? ++extraStepIndex : index + 1;
2199
+ const displayTotal = isPlannedStage ? stageTotal : extraStepCount;
2200
+ lines.push(...foregroundStyleWidgetStepLines(job, theme, step, itemTitle, displayIndex, displayTotal, expanded, width, frame));
2201
+ }
2202
+ }
2203
+ lines.push(...hostStepWidgetLines(job, theme, " "));
2204
+ const attached = new Set(steps.flatMap((step) => step.children?.map((child) => child.id) ?? []));
2205
+ const unattached = job.nestedChildren?.filter((child) => !attached.has(child.id)) ?? [];
2206
+ for (const nestedLine of formatNestedWidgetLines(unattached, theme, width, expanded, job.updatedAt, expanded ? 12 : 6)) {
2207
+ lines.push(` ${nestedLine}`);
2208
+ }
2209
+ return lines;
2210
+ }
2211
+
2212
+ function buildSingleWidgetLines(job: AsyncJobState, theme: Theme, width: number, expanded: boolean, frame?: number, projection = buildWorkflowWidgetProjection(job)): string[] {
2213
+ const stats = widgetStats(job, theme, projection, !expanded);
2214
+ const count = job.mode === "workflow"
2215
+ ? projection.checklist?.total ?? projection.stageProgress?.total ?? job.stepsTotal ?? job.agents?.length ?? job.steps?.length
2216
+ : job.mode === "chain" ? job.chainStepCount : projection.stageProgress?.total ?? job.stepsTotal ?? job.agents?.length ?? job.steps?.length;
2217
+ const mode = widgetJobName(job);
2218
+ const title = isSingleChildAsyncJob(job)
2219
+ ? "async subagent"
2220
+ : `async subagent ${mode}${count && count > 1 ? ` (${count})` : ""}`;
2221
+ const checklistPrimary = !expanded && job.mode === "workflow" && projection.checklist !== undefined;
2222
+ const collapseDetails = !checklistPrimary && job.steps?.length === 1 && shouldCollapseSingleChildDetails(job, job.steps[0]!);
2223
+ const summary = `${widgetStatusGlyph(job, theme, frame)} ${themeBold(theme, mode)}${contextModeBadge(theme, job.context)}${stats ? ` ${theme.fg("dim", "·")} ${stats}` : ""}`;
2224
+ return [
2225
+ `${theme.fg("toolTitle", themeBold(theme, title))} ${theme.fg("dim", "· background")}`,
2226
+ ...(collapseDetails ? [] : [summary]),
2227
+ ...foregroundStyleWidgetDetails(job, theme, expanded, width, frame, projection),
2228
+ ].map((line) => truncLine(line, width));
2229
+ }
2230
+
2231
+ function compactSingleWidgetLines(job: AsyncJobState, theme: Theme, width: number, frame?: number, projection = buildWorkflowWidgetProjection(job)): string[] {
2232
+ const fullLines = buildSingleWidgetLines(job, theme, width, false, frame, projection);
2233
+ if (fullLines.length <= 10 || !job.steps?.length || (job.mode !== "parallel" && !job.activeParallelGroup)) return fullLines;
2234
+
2235
+ const group = activeParallelWidgetGroup(job);
2236
+ if (!group) return fullLines;
2237
+ const rows = parallelWidgetStepRows(group.steps, group.total, Boolean(job.activeParallelGroup));
2238
+ const lines = fullLines.slice(0, 2);
2239
+ lines.push(parallelWidgetGroupHeader(group, theme, frame));
2240
+ for (const [rowIndex, row] of rows.entries()) {
2241
+ const step = row.step;
2242
+ const status = widgetStepStatus(step.status, theme);
2243
+ const activity = widgetStepActivityLine(step, width, false, job.updatedAt);
2244
+ const stepStats = widgetStepStats(theme, step);
2245
+ const activitySuffix = activity ? ` ${theme.fg("dim", "·")} ${theme.fg("dim", activity)}` : "";
2246
+ const modelDisplay = modelThinkingBadge(theme, step.model, step.thinking);
2247
+ const task = compactTaskText(step.description, step.label);
2248
+ const taskSuffix = task ? ` ${theme.fg("dim", "·")} ${theme.fg("dim", `task: ${task}`)}` : "";
2249
+ const marker = rowIndex === rows.length - 1 && rowIndex >= group.total - 1 ? "└─" : "├─";
2250
+ lines.push(` ${marker} ${widgetStepGlyph(step.status, theme, widgetStepRunningSeed(step, row.index), frame)} ${themeBold(theme, row.rowLabel)}${contextModeBadge(theme, step.context)} ${theme.fg("dim", "·")} ${status}${modelDisplay}${taskSuffix}${activitySuffix}${stepStats ? ` ${theme.fg("dim", "·")} ${stepStats}` : ""}`);
2251
+ const lane = projectAsyncLane(job, step);
2252
+ if (lane) lines.push(...formatLaneProjectionLines(lane, theme, " "));
2253
+ for (const nestedLine of formatNestedWidgetLines(step.children, theme, width, false, job.updatedAt, 6)) lines.push(` ${nestedLine}`);
2254
+ }
2255
+ lines.push(...hostStepWidgetLines(job, theme, " "));
2256
+ if (job.steps.some((step) => step.status === "running")) lines.push(theme.fg("accent", ` ${liveDetailHintText()}`));
2257
+ return lines.map((line) => truncLine(line, width));
2258
+ }
2259
+
2260
+ type WidgetRenderTier = "full" | "single-line" | "progressive";
2261
+
2262
+ interface WidgetLayoutSession {
2263
+ expanded: boolean;
2264
+ rows: number;
2265
+ columns: number;
2266
+ tier: WidgetRenderTier;
2267
+ lockedRows?: number;
2268
+ visibleJobKeys: string[];
2269
+ }
2270
+
2271
+ const RESERVED_NON_WIDGET_ROWS = 19;
2272
+
2273
+ let widgetLayoutSession: WidgetLayoutSession | undefined;
2274
+
2275
+ function resetWidgetLayoutSession(): void {
2276
+ widgetLayoutSession = undefined;
2277
+ }
2278
+
2279
+ function estimateAvailableWidgetRows(): number {
2280
+ const rows = process.stdout.rows || 30;
2281
+ return Math.max(1, rows - RESERVED_NON_WIDGET_ROWS);
2282
+ }
2283
+
2284
+ function currentTerminalRows(): number {
2285
+ return process.stdout.rows || 30;
2286
+ }
2287
+
2288
+ function currentTerminalColumns(): number {
2289
+ return process.stdout.columns || 120;
2290
+ }
2291
+
2292
+ function widgetSessionMatches(expanded: boolean): boolean {
2293
+ return widgetLayoutSession?.expanded === expanded
2294
+ && widgetLayoutSession.rows === currentTerminalRows()
2295
+ && widgetLayoutSession.columns === currentTerminalColumns();
2296
+ }
2297
+
2298
+ function widgetHeaderCounts(jobs: AsyncJobState[]): { running: AsyncJobState[]; queued: AsyncJobState[]; complete: AsyncJobState[]; failed: AsyncJobState[]; paused: AsyncJobState[]; stopped: AsyncJobState[] } {
2299
+ return {
2300
+ running: jobs.filter((job) => job.status === "running"),
2301
+ queued: jobs.filter((job) => job.status === "queued"),
2302
+ complete: jobs.filter((job) => job.status === "complete"),
2303
+ failed: jobs.filter((job) => job.status === "failed"),
2304
+ paused: jobs.filter((job) => job.status === "paused"),
2305
+ stopped: jobs.filter((job) => job.status === "stopped"),
2306
+ };
2307
+ }
2308
+
2309
+ function buildSingleLineWidgetLines(jobs: AsyncJobState[], theme: Theme, width: number, frame?: number): string[] {
2310
+ const counts = widgetHeaderCounts(jobs);
2311
+ const hasActive = counts.running.length > 0 || counts.queued.length > 0;
2312
+ const glyph = counts.running.length > 0 ? runningGlyph(animatedSeed(widgetJobsRunningSeed(counts.running), frame)) : hasActive ? "●" : "○";
2313
+ const parts: string[] = [];
2314
+ if (counts.running.length > 0) parts.push(`${counts.running.length}/${jobs.length} running`);
2315
+ if (counts.queued.length > 0) parts.push(`${counts.queued.length} queued`);
2316
+ if (counts.failed.length > 0) parts.push(`${counts.failed.length} failed`);
2317
+ if (counts.stopped.length > 0) parts.push(`${counts.stopped.length} stopped`);
2318
+ if (counts.paused.length > 0) parts.push(`${counts.paused.length} paused`);
2319
+ if (!hasActive && counts.complete.length > 0) parts.push(`${counts.complete.length}/${jobs.length} done`);
2320
+ return [truncLine(`${theme.fg(hasActive ? "accent" : "dim", glyph)} ${theme.fg(hasActive ? "accent" : "dim", "subagents")} (${parts.join(", ") || `${jobs.length} total`})`, width)];
2321
+ }
2322
+
2323
+ function orderedWidgetJobs(jobs: AsyncJobState[]): AsyncJobState[] {
2324
+ return [
2325
+ ...jobs.filter((job) => job.status === "running"),
2326
+ ...jobs.filter((job) => job.status === "queued"),
2327
+ ...jobs.filter((job) => job.status !== "running" && job.status !== "queued"),
2328
+ ];
2329
+ }
2330
+
2331
+ function progressiveJobKey(job: AsyncJobState): string {
2332
+ return job.asyncId;
2333
+ }
2334
+
2335
+ function isProgressiveActiveJob(job: AsyncJobState | undefined): boolean {
2336
+ return job?.status === "running" || job?.status === "queued";
2337
+ }
2338
+
2339
+ function selectProgressiveJobKeys(jobs: AsyncJobState[], previousKeys: string[], bodyRows: number): string[] {
2340
+ if (bodyRows <= 0) return [];
2341
+ const jobsByKey = new Map(jobs.map((job) => [progressiveJobKey(job), job]));
2342
+ const selected: string[] = [];
2343
+ const append = (key: string): void => {
2344
+ if (selected.includes(key) || !jobsByKey.has(key)) return;
2345
+ selected.push(key);
2346
+ };
2347
+ for (const key of previousKeys) {
2348
+ if (!isProgressiveActiveJob(jobsByKey.get(key))) continue;
2349
+ append(key);
2350
+ if (selected.length >= bodyRows) return selected;
2351
+ }
2352
+ for (const job of orderedWidgetJobs(jobs)) {
2353
+ if (!isProgressiveActiveJob(job)) continue;
2354
+ const key = progressiveJobKey(job);
2355
+ append(key);
2356
+ if (selected.length >= bodyRows) break;
2357
+ }
2358
+ if (selected.length >= bodyRows) return selected;
2359
+ for (const key of previousKeys) {
2360
+ if (isProgressiveActiveJob(jobsByKey.get(key))) continue;
2361
+ append(key);
2362
+ if (selected.length >= bodyRows) return selected;
2363
+ }
2364
+ for (const job of orderedWidgetJobs(jobs)) {
2365
+ const key = progressiveJobKey(job);
2366
+ append(key);
2367
+ if (selected.length >= bodyRows) break;
2368
+ }
2369
+ return selected;
2370
+ }
2371
+
2372
+ function progressiveHeaderLine(jobs: AsyncJobState[], theme: Theme, width: number, frame?: number): string {
2373
+ const counts = widgetHeaderCounts(jobs);
2374
+ const hasActive = counts.running.length > 0 || counts.queued.length > 0;
2375
+ const glyph = counts.running.length > 0 ? runningGlyph(animatedSeed(widgetJobsRunningSeed(counts.running), frame)) : hasActive ? "●" : "○";
2376
+ const parts: string[] = [];
2377
+ if (counts.running.length > 0) parts.push(formatAgentRunningLabel(counts.running.length));
2378
+ if (counts.queued.length > 0) parts.push(`${counts.queued.length} queued`);
2379
+ if (!hasActive) {
2380
+ if (counts.failed.length > 0) parts.push(`${counts.failed.length} failed`);
2381
+ if (counts.stopped.length > 0) parts.push(`${counts.stopped.length} stopped`);
2382
+ if (counts.paused.length > 0) parts.push(`${counts.paused.length} paused`);
2383
+ if (counts.complete.length > 0) parts.push(`${counts.complete.length}/${jobs.length} done`);
2384
+ }
2385
+ return truncLine(`${theme.fg(hasActive ? "accent" : "dim", glyph)} ${theme.fg(hasActive ? "accent" : "dim", "Async agents")} ${theme.fg("dim", "·")} ${theme.fg("dim", parts.join(", ") || `${jobs.length} total`)}`, width);
2386
+ }
2387
+
2388
+ function progressiveJobLine(job: AsyncJobState, theme: Theme, width: number, frame?: number, projection = buildWorkflowWidgetProjection(job)): string {
2389
+ const checklistPrimary = job.mode === "workflow" && projection.checklist !== undefined;
2390
+ const stats = widgetStats(job, theme, projection, true);
2391
+ const activity = checklistPrimary ? "" : widgetActivity(job);
2392
+ const status = job.status === "complete" ? "done" : job.status;
2393
+ const lane = checklistPrimary ? undefined : projectAsyncLane(job, laneStepForJob(job, projection.steps));
2394
+ const laneSummary = lane
2395
+ ? [lane.label ?? lane.role, lane.phase ? `phase:${lane.phase}` : undefined, lane.output ? `out:${lane.output}` : undefined, lane.workspace ? `workspace:${lane.workspace}` : `ref:${lane.ref}`].filter(Boolean).join(" · ")
2396
+ : "";
2397
+ const laneSignals = lane
2398
+ ? [lane.next ? `next:${lane.next}` : undefined, ...lane.chips.map((chip) => formatLaneChip(chip, theme))].filter(Boolean).join(" · ")
2399
+ : "";
2400
+ const parts = [
2401
+ `${themeBold(theme, widgetJobName(job))}${contextModeBadge(theme, job.context)}`,
2402
+ theme.fg("dim", status),
2403
+ laneSignals ? laneSignals : "",
2404
+ laneSummary ? theme.fg("dim", laneSummary) : "",
2405
+ stats,
2406
+ activity && activity.toLowerCase() !== status ? theme.fg("dim", activity) : "",
2407
+ ].filter(Boolean);
2408
+ return truncLine(` ${widgetStatusGlyph(job, theme, frame)} ${parts.join(` ${theme.fg("dim", "·")} `)}`, width);
2409
+ }
2410
+
2411
+ function progressiveHiddenLine(hiddenJobs: AsyncJobState[], theme: Theme, width: number): string {
2412
+ const counts = widgetHeaderCounts(hiddenJobs);
2413
+ const parts: string[] = [];
2414
+ if (counts.running.length > 0) parts.push(`${counts.running.length} running`);
2415
+ if (counts.queued.length > 0) parts.push(`${counts.queued.length} queued`);
2416
+ const finished = counts.complete.length + counts.failed.length + counts.paused.length + counts.stopped.length;
2417
+ if (finished > 0) parts.push(`${finished} finished`);
2418
+ return truncLine(theme.fg("dim", ` +${hiddenJobs.length} more${parts.length ? ` (${parts.join(", ")})` : ""}`), width);
2419
+ }
2420
+
2421
+ function buildProgressiveWidgetLines(jobs: AsyncJobState[], theme: Theme, width: number, lockedRows: number, previousKeys: string[], frame?: number, projectionFor: WorkflowWidgetProjectionLookup = workflowWidgetProjectionLookup()): { lines: string[]; visibleJobKeys: string[] } {
2422
+ const rowCount = Math.max(1, lockedRows);
2423
+ if (rowCount === 1) return { lines: buildSingleLineWidgetLines(jobs, theme, width, frame), visibleJobKeys: [] };
2424
+
2425
+ const bodyRows = rowCount - 1;
2426
+ let visibleJobKeys = selectProgressiveJobKeys(jobs, previousKeys, bodyRows);
2427
+ const jobsByKey = new Map(jobs.map((job) => [progressiveJobKey(job), job]));
2428
+ let visibleJobs = visibleJobKeys.map((key) => jobsByKey.get(key)).filter((job): job is AsyncJobState => Boolean(job));
2429
+ let hiddenJobs = jobs.filter((job) => !visibleJobKeys.includes(progressiveJobKey(job)));
2430
+ const needsHiddenLine = hiddenJobs.length > 0;
2431
+
2432
+ if (needsHiddenLine && visibleJobs.length >= bodyRows && bodyRows > 0) {
2433
+ visibleJobs = visibleJobs.slice(0, bodyRows - 1);
2434
+ visibleJobKeys = visibleJobs.map(progressiveJobKey);
2435
+ hiddenJobs = jobs.filter((job) => !visibleJobKeys.includes(progressiveJobKey(job)));
2436
+ }
2437
+
2438
+ const lines = [
2439
+ progressiveHeaderLine(jobs, theme, width, frame),
2440
+ ...visibleJobs.map((job) => progressiveJobLine(job, theme, width, frame, projectionFor(job))),
2441
+ ];
2442
+ if (hiddenJobs.length > 0 && lines.length < rowCount) lines.push(progressiveHiddenLine(hiddenJobs, theme, width));
2443
+ while (lines.length < rowCount) lines.push(" ");
2444
+ return { lines: lines.slice(0, rowCount), visibleJobKeys };
2445
+ }
2446
+
2447
+ function collapsedWidgetLineBudget(rows: number): number {
2448
+ return Math.max(10, Math.min(14, Math.floor(rows * 0.35)));
2449
+ }
2450
+
2451
+ function paddedWidgetLine(line: string, width: number): string {
2452
+ if (width <= 2) return " ".repeat(Math.max(0, width));
2453
+ const text = ` ${truncLine(line, width - 2)} `;
2454
+ return `${text}${" ".repeat(Math.max(0, width - visibleWidth(text)))}`;
2455
+ }
2456
+
2457
+ function fitWidgetLineBudget(lines: string[], theme: Theme, width: number, expanded: boolean): string[] {
2458
+ const rows = process.stdout.rows || 30;
2459
+ const budget = expanded
2460
+ ? Math.max(12, Math.min(24, Math.floor(rows * 0.55)))
2461
+ : collapsedWidgetLineBudget(rows);
2462
+ if (lines.length <= budget) return lines;
2463
+ const visibleLines = Math.max(1, budget - 1);
2464
+ const hiddenCount = lines.length - visibleLines;
2465
+ const hint = expanded
2466
+ ? `… ${hiddenCount} live-detail lines hidden`
2467
+ : `… ${hiddenCount} lines hidden · ${liveDetailKeyText()} expands`;
2468
+ return [...lines.slice(0, visibleLines), truncLine(theme.fg("dim", hint), width)];
2469
+ }
2470
+
2471
+ function fitAdaptiveWidgetLines(jobs: AsyncJobState[], buildLines: () => string[], theme: Theme, width: number, expanded: boolean, frame?: number, projectionFor?: WorkflowWidgetProjectionLookup): string[] {
2472
+ if (expanded) {
2473
+ resetWidgetLayoutSession();
2474
+ return fitWidgetLineBudget(buildLines(), theme, width, true);
2475
+ }
2476
+
2477
+ const hasMatchingSession = widgetSessionMatches(expanded);
2478
+ const rows = currentTerminalRows();
2479
+ const columns = currentTerminalColumns();
2480
+ const availableRows = estimateAvailableWidgetRows();
2481
+
2482
+ if (hasMatchingSession && widgetLayoutSession?.tier === "single-line") {
2483
+ return buildSingleLineWidgetLines(jobs, theme, width, frame);
2484
+ }
2485
+
2486
+ if (hasMatchingSession && widgetLayoutSession?.tier === "progressive" && widgetLayoutSession.lockedRows !== undefined) {
2487
+ const rendered = buildProgressiveWidgetLines(jobs, theme, width, widgetLayoutSession.lockedRows, widgetLayoutSession.visibleJobKeys, frame, projectionFor);
2488
+ widgetLayoutSession.visibleJobKeys = rendered.visibleJobKeys;
2489
+ return rendered.lines;
2490
+ }
2491
+
2492
+ const lines = buildLines();
2493
+ if (lines.length <= availableRows) {
2494
+ widgetLayoutSession = { expanded, rows, columns, tier: "full", visibleJobKeys: [] };
2495
+ return fitWidgetLineBudget(lines, theme, width, false);
2496
+ }
2497
+ if (availableRows > 2 && jobs.length === 1 && projectionFor?.(jobs[0]!).stageProgress) {
2498
+ widgetLayoutSession = { expanded, rows, columns, tier: "full", visibleJobKeys: [] };
2499
+ return fitWidgetLineBudget(lines, theme, width, false);
2500
+ }
2501
+
2502
+ if (availableRows <= 2) {
2503
+ widgetLayoutSession = { expanded, rows, columns, tier: "single-line", visibleJobKeys: [] };
2504
+ return buildSingleLineWidgetLines(jobs, theme, width, frame);
2505
+ }
2506
+
2507
+ const lockedRows = Math.min(availableRows, collapsedWidgetLineBudget(rows));
2508
+ const rendered = buildProgressiveWidgetLines(jobs, theme, width, lockedRows, [], frame, projectionFor);
2509
+ widgetLayoutSession = { expanded, rows, columns, tier: "progressive", lockedRows, visibleJobKeys: rendered.visibleJobKeys };
2510
+ return rendered.lines;
2511
+ }
2512
+
2513
+ function buildWidgetComponent(jobs: AsyncJobState[], isExpanded: () => boolean): (_tui: unknown, theme: Theme) => Component {
2514
+ return (_tui, theme) => {
2515
+ const container = new Container();
2516
+ let cachedRenderWidth: number | undefined;
2517
+ let cachedFrame: number | undefined;
2518
+ let cachedExpanded: boolean | undefined;
2519
+ let cachedLines: string[] | undefined;
2520
+ container.render = (renderWidth: number): string[] => {
2521
+ const frame = Math.floor(Date.now() / WIDGET_ANIMATION_INTERVAL_MS);
2522
+ const expanded = isExpanded();
2523
+ if (cachedLines && cachedRenderWidth === renderWidth && cachedFrame === frame && cachedExpanded === expanded) return cachedLines;
2524
+ const width = Math.max(0, renderWidth - 2);
2525
+ const projectionFor = workflowWidgetProjectionLookup();
2526
+ const buildLines = (): string[] => expanded
2527
+ ? buildWidgetLinesWithProjection(jobs, theme, width, true, frame, projectionFor)
2528
+ : jobs.length === 1
2529
+ ? compactSingleWidgetLines(jobs[0]!, theme, width, frame, projectionFor(jobs[0]!))
2530
+ : buildWidgetLinesWithProjection(jobs, theme, width, false, frame, projectionFor);
2531
+ cachedRenderWidth = renderWidth;
2532
+ cachedFrame = frame;
2533
+ cachedExpanded = expanded;
2534
+ cachedLines = fitAdaptiveWidgetLines(jobs, buildLines, theme, width, expanded, frame, projectionFor).map((line) => paddedWidgetLine(line, renderWidth));
2535
+ return cachedLines;
2536
+ };
2537
+ return container;
2538
+ };
2539
+ }
2540
+
2541
+ function buildWidgetLinesWithProjection(jobs: AsyncJobState[], theme: Theme, width = getTermWidth(), expanded = false, frame?: number, projectionFor: WorkflowWidgetProjectionLookup = workflowWidgetProjectionLookup()): string[] {
2542
+ if (jobs.length === 0) return [];
2543
+ if (jobs.length === 1) return buildSingleWidgetLines(jobs[0]!, theme, width, expanded, frame, projectionFor(jobs[0]!));
2544
+ const running = jobs.filter((job) => job.status === "running");
2545
+ const queued = jobs.filter((job) => job.status === "queued");
2546
+ const finished = jobs.filter((job) => job.status !== "running" && job.status !== "queued");
2547
+
2548
+ const lines: string[] = [];
2549
+ const hasActive = running.length > 0 || queued.length > 0;
2550
+ const headerGlyph = running.length > 0 ? runningGlyph(animatedSeed(widgetJobsRunningSeed(running), frame)) : hasActive ? "●" : "○";
2551
+ lines.push(truncLine(`${theme.fg(hasActive ? "accent" : "dim", headerGlyph)} ${theme.fg(hasActive ? "accent" : "dim", "Async agents")} ${theme.fg("dim", "· background")}`, width));
2552
+
2553
+ const items: string[][] = [];
2554
+ let hiddenRunning = 0;
2555
+ let hiddenFinished = 0;
2556
+ let queuedSummaryShown = false;
2557
+ let slots = MAX_WIDGET_JOBS;
2558
+ const appendJob = (job: AsyncJobState): void => {
2559
+ const projection = projectionFor(job);
2560
+ const checklistPrimary = !expanded && job.mode === "workflow" && projection.checklist !== undefined;
2561
+ const stats = widgetStats(job, theme, projection, !expanded);
2562
+ const details = checklistPrimary
2563
+ ? [
2564
+ ...workflowChecklistWidgetLines(projection.checklist, theme, " ", false, frame, false),
2565
+ ...(job.status === "running" || projection.checklist!.running > 0 ? [` ${theme.fg("accent", liveDetailHintText())}`] : []),
2566
+ ]
2567
+ : [
2568
+ ` ${theme.fg("dim", `⎿ ${widgetActivity(job)}`)}`,
2569
+ ...widgetLaneDetailLines(job, theme, projection),
2570
+ ...workflowChecklistWidgetLines(projection.checklist, theme, " ", expanded, frame),
2571
+ ...widgetParallelAgentDetails(job, theme, expanded, width, frame),
2572
+ ];
2573
+ items.push([
2574
+ `${widgetStatusGlyph(job, theme, frame)} ${themeBold(theme, widgetJobName(job))}${contextModeBadge(theme, job.context)}${stats ? ` ${theme.fg("dim", "·")} ${stats}` : ""}`,
2575
+ ...details,
2576
+ ]);
2577
+ };
2578
+
2579
+ for (const job of running) {
2580
+ if (slots <= 0) { hiddenRunning++; continue; }
2581
+ appendJob(job);
2582
+ slots--;
2583
+ }
2584
+
2585
+ if (queued.length > 0 && slots > 0) {
2586
+ items.push([`${theme.fg("muted", "◦")} ${theme.fg("dim", `${queued.length} queued`)}`]);
2587
+ queuedSummaryShown = true;
2588
+ slots--;
2589
+ }
2590
+
2591
+ for (const job of finished) {
2592
+ if (slots <= 0) { hiddenFinished++; continue; }
2593
+ appendJob(job);
2594
+ slots--;
2595
+ }
2596
+
2597
+ const hiddenQueued = queued.length > 0 && !queuedSummaryShown ? queued.length : 0;
2598
+ const hiddenTotal = hiddenRunning + hiddenFinished + hiddenQueued;
2599
+ if (hiddenTotal > 0) {
2600
+ const parts: string[] = [];
2601
+ if (hiddenRunning > 0) parts.push(`${hiddenRunning} running`);
2602
+ if (hiddenQueued > 0) parts.push(`${hiddenQueued} queued`);
2603
+ if (hiddenFinished > 0) parts.push(`${hiddenFinished} finished`);
2604
+ items.push([theme.fg("dim", `+${hiddenTotal} more (${parts.join(", ")})`)]);
2605
+ }
2606
+
2607
+ for (let i = 0; i < items.length; i++) {
2608
+ const item = items[i]!;
2609
+ const last = i === items.length - 1;
2610
+ const branch = last ? "└─" : "├─";
2611
+ const continuation = last ? " " : "│ ";
2612
+ lines.push(truncLine(`${theme.fg("dim", branch)} ${item[0]}`, width));
2613
+ for (const detail of item.slice(1)) {
2614
+ lines.push(truncLine(`${theme.fg("dim", continuation)} ${detail}`, width));
2615
+ }
2616
+ }
2617
+
2618
+ return lines;
2619
+ }
2620
+
2621
+ export function buildWidgetLines(jobs: AsyncJobState[], theme: Theme, width = getTermWidth(), expanded = false, frame?: number): string[] {
2622
+ return buildWidgetLinesWithProjection(jobs, theme, width, expanded, frame);
2623
+ }
2624
+
2625
+ /**
2626
+ * Render the async jobs widget
2627
+ */
2628
+ export function renderWidget(ctx: ExtensionContext, jobs: AsyncJobState[]): void {
2629
+ if (jobs.length === 0) {
2630
+ resetWidgetLayoutSession();
2631
+ if (ctx.hasUI) ctx.ui.setWidget(WIDGET_KEY, undefined);
2632
+ return;
2633
+ }
2634
+ if (!ctx.hasUI) return;
2635
+ if ((ctx as { mode?: string }).mode === "rpc") {
2636
+ ctx.ui.setWidget(WIDGET_KEY, encodeAsyncStatusSnapshotWidget(jobs));
2637
+ return;
2638
+ }
2639
+ ctx.ui.setWidget(WIDGET_KEY, buildWidgetComponent(jobs, () => ctx.ui.getToolsExpanded?.() ?? false));
2640
+ }
2641
+
2642
+ function renderSingleCompact(
2643
+ d: Details,
2644
+ r: Details["results"][number],
2645
+ theme: Theme,
2646
+ layout: MainWindowRenderLayout,
2647
+ frame?: number,
2648
+ foregroundDetachShortcut?: string,
2649
+ ): Component {
2650
+ const output = r.truncation?.text || getSingleResultOutput(r);
2651
+ const progress = r.progress || r.progressSummary;
2652
+ const isRunning = isResultRunning(r);
2653
+ const contextBadge = contextModeBadge(theme, r.context ?? d.context);
2654
+ const stats = statJoin(theme, [
2655
+ r.usage?.turns ? `⟳ ${r.usage.turns}` : "",
2656
+ formatProgressStats(theme, progress),
2657
+ ]);
2658
+ const c = new Container();
2659
+ const width = getTermWidth() - 4;
2660
+ const detailIndent = mainWindowIndent(layout, 1);
2661
+ const continuationIndent = mainWindowIndent(layout, 2) + (layout.horizontalSpacing > 0 ? " " : "");
2662
+ const modelDisplay = modelThinkingBadge(theme, r.model ?? r.progress?.model, r.thinking ?? r.progress?.thinking);
2663
+ c.addChild(new Text(truncLine(`${resultGlyph(r, output, theme, isRunning, undefined, frame)} ${theme.fg("toolTitle", theme.bold(foregroundSingleDisplayName(r)))}${modelDisplay}${contextBadge}${stats ? ` ${theme.fg("dim", "·")} ${stats}` : ""}`, width), 0, 0));
2664
+
2665
+ if (isRunning && r.progress) {
2666
+ const task = compactTaskText(r.task);
2667
+ if (task) c.addChild(new Text(truncLine(theme.fg("dim", `${detailIndent}task: ${task}`), width), 0, 0));
2668
+ const progressSnapshotNow = snapshotNowForProgress(r.progress);
2669
+ const activity = compactCurrentActivity(r.progress);
2670
+ c.addChild(new Text(truncLine(theme.fg("dim", `${detailIndent}⎿ ${activity}`), width), 0, 0));
2671
+ const liveStatus = buildLiveStatusLine(r.progress, progressSnapshotNow);
2672
+ if (liveStatus && liveStatus !== activity) c.addChild(new Text(truncLine(theme.fg("dim", `${continuationIndent}${liveStatus}`), width), 0, 0));
2673
+ for (const nestedLine of formatNestedWidgetLines(r.children, theme, width, false, progressSnapshotNow)) {
2674
+ c.addChild(new Text(truncLine(`${detailIndent}${nestedLine}`, width), 0, 0));
2675
+ }
2676
+ c.addChild(new Text(truncLine(theme.fg("accent", `${detailIndent}${foregroundSingleHintText(foregroundDetachShortcut)}`), width), 0, 0));
2677
+ if (r.artifactPaths) c.addChild(new Text(truncLine(theme.fg("dim", `${detailIndent}output: ${shortenPath(r.artifactPaths.outputPath)}`), width), 0, 0));
2678
+ return c;
2679
+ }
2680
+
2681
+ for (const nestedLine of formatNestedWidgetLines(r.children, theme, width, false, r.progress?.lastActivityAt)) {
2682
+ c.addChild(new Text(truncLine(`${detailIndent}${nestedLine}`, width), 0, 0));
2683
+ }
2684
+ c.addChild(new Text(truncLine(theme.fg("dim", `${detailIndent}⎿ ${resultStatusLine(r, output)}`), width), 0, 0));
2685
+ const preview = firstOutputLine(output);
2686
+ if (preview && r.exitCode === 0 && !hasEmptyTextOutputWithoutOutputTarget(r.task, output)) {
2687
+ c.addChild(new Text(truncLine(theme.fg("dim", `${continuationIndent}${preview}`), width), 0, 0));
2688
+ }
2689
+ if (r.sessionFile) c.addChild(new Text(truncLine(theme.fg("dim", `${detailIndent}session: ${shortenPath(r.sessionFile)}`), width), 0, 0));
2690
+ if (r.artifactPaths) c.addChild(new Text(truncLine(theme.fg("dim", `${detailIndent}output: ${shortenPath(r.artifactPaths.outputPath)}`), width), 0, 0));
2691
+ if (r.truncation?.artifactPath) c.addChild(new Text(truncLine(theme.fg("dim", `${detailIndent}full output: ${shortenPath(r.truncation.artifactPath)}`), width), 0, 0));
2692
+ return c;
2693
+ }
2694
+
2695
+ function workflowRowGlyph(row: WorkflowChatProgressRow, theme: Theme, frame?: number): string {
2696
+ if (row.state === "planned") return theme.fg("muted", "◦");
2697
+ if (row.state === "running") return theme.fg("accent", runningGlyph(frame));
2698
+ if (row.state === "complete") return theme.fg("success", "✓");
2699
+ if (row.state === "detached" || row.state === "stopped") return theme.fg("warning", "■");
2700
+ return theme.fg("error", "✗");
2701
+ }
2702
+
2703
+ function workflowRowStateLabel(row: WorkflowChatProgressRow, theme: Theme): string {
2704
+ const label = (row.state === "complete" ? "complete" : row.state).padEnd(8);
2705
+ if (row.state === "planned") return theme.fg("dim", label);
2706
+ if (row.state === "running") return theme.fg("accent", label);
2707
+ if (row.state === "complete") return theme.fg("success", label);
2708
+ if (row.state === "detached" || row.state === "stopped") return theme.fg("warning", label);
2709
+ return theme.fg("error", label);
2710
+ }
2711
+
2712
+ function workflowOverallState(rows: WorkflowChatProgressRow[], hasTerminalValue: boolean, isError?: boolean): "running" | "complete" | "failed" | "paused" {
2713
+ if (rows.some((row) => row.state === "failed")) return "failed";
2714
+ if (rows.some((row) => row.state === "detached")) return "paused";
2715
+ if (isError) return "failed";
2716
+ if ((rows.length > 0 && rows.every((row) => row.state === "complete")) || hasTerminalValue) return "complete";
2717
+ return "running";
2718
+ }
2719
+
2720
+ function foregroundWorkflowChecklist(details: Details): WorkflowChecklistProjection | undefined {
2721
+ if (details.mode !== "workflow") return undefined;
2722
+ const stageNodes = details.workflowGraph ? workflowGraphStageNodes(details.workflowGraph) : [];
2723
+ const steps: WorkflowChecklistStep[] = details.results.flatMap((result, resultIndex) => {
2724
+ const stableIndex = foregroundResultIndex(details, resultIndex);
2725
+ const workflowKey = (result as { workflowKey?: unknown }).workflowKey;
2726
+ if (details.workflowGraph && typeof workflowKey !== "string") return [];
2727
+ const node = typeof workflowKey === "string"
2728
+ ? stageNodes.find((candidate) => candidate.id === workflowKey)
2729
+ : undefined;
2730
+ const progress = foregroundProgressForResult(details, resultIndex);
2731
+ const status = isResultRunning(result) || progress?.status === "running"
2732
+ ? "running"
2733
+ : result.detached
2734
+ ? "paused"
2735
+ : result.stopped
2736
+ ? "stopped"
2737
+ : result.exitCode === 0
2738
+ ? "complete"
2739
+ : "failed";
2740
+ return [{
2741
+ key: node?.id ?? (typeof workflowKey === "string" ? workflowKey : `result-${resultIndex + 1}`),
2742
+ label: node?.label ?? workflowLabelForResult(details, resultIndex) ?? result.task ?? result.agent,
2743
+ phase: node?.phase,
2744
+ agent: result.agent,
2745
+ status,
2746
+ context: result.context,
2747
+ activityState: progress?.activityState,
2748
+ startedAt: progress?.lastActivityAt !== undefined && progress.durationMs !== undefined ? progress.lastActivityAt - progress.durationMs : undefined,
2749
+ durationMs: progress?.durationMs,
2750
+ currentTool: progress?.currentTool,
2751
+ currentToolStartedAt: progress?.currentToolStartedAt,
2752
+ currentPath: progress?.currentPath,
2753
+ turnCount: progress?.turnCount,
2754
+ toolCount: progress?.toolCount ?? result.progressSummary?.toolCount,
2755
+ error: result.error,
2756
+ toolBudgetBlocked: result.toolBudgetBlocked,
2757
+ turnBudgetExceeded: result.turnBudgetExceeded,
2758
+ timedOut: result.timedOut,
2759
+ stopped: result.stopped,
2760
+ acceptance: result.acceptance ? { status: result.acceptance.status, reviewResult: result.acceptance.reviewResult ? { status: result.acceptance.reviewResult.status } : undefined } : undefined,
2761
+ review: result.review ? { status: result.review.status } : undefined,
2762
+ watchdog: result.watchdog,
2763
+ }];
2764
+ });
2765
+ const checklist = projectWorkflowChecklist({
2766
+ graph: details.workflowGraph,
2767
+ steps,
2768
+ hostSteps: details.workflow?.receipt?.hostSteps,
2769
+ preflight: details.preflight,
2770
+ trace: details.workflow?.trace,
2771
+ now: Date.now(),
2772
+ });
2773
+ return checklist.total > 0 ? checklist : undefined;
2774
+ }
2775
+
2776
+ function renderWorkflowChatProgress(d: Details, result: AgentToolResult<Details>, theme: Theme, layout: MainWindowRenderLayout, frame?: number, expanded = false): Component {
2777
+ const workflow = d.workflow;
2778
+ const rows = workflow ? buildWorkflowChatProgressRows(workflow.trace, d.preflight) : d.preflight ? buildWorkflowChatProgressRows([], d.preflight) : [];
2779
+ const state = workflowOverallState(rows, workflow?.value !== undefined, result.isError);
2780
+ const glyph = state === "running" ? theme.fg("accent", runningGlyph(frame)) : state === "complete" ? theme.fg("success", "✓") : state === "paused" ? theme.fg("warning", "■") : theme.fg("error", "✗");
2781
+ const width = getTermWidth() - 4;
2782
+ const runId = d.runId ? d.runId.slice(0, 12) : "workflow";
2783
+ const repoLabel = d.chatProgress?.repoLabel ?? (d.chatProgress?.repoRelation === "same" ? "same repo" : "other repo");
2784
+ const phase = rows.find((row) => row.state === "running" && row.phase)?.phase ?? [...rows].reverse().find((row) => row.phase)?.phase;
2785
+ const c = new Container();
2786
+ const rowIndent = mainWindowIndent(layout, 1);
2787
+ c.addChild(new Text(truncLine(`${glyph} ${theme.fg("toolTitle", theme.bold("workflow"))} ${runId} ${theme.fg("dim", "·")} ${d.chatProgress?.repoRelation === "same" ? "same repo" : "other repo"} ${theme.fg("dim", "·")} ${state}`, width), 0, 0));
2788
+ c.addChild(new Text(truncLine(theme.fg("dim", `${rowIndent}Repo ${repoLabel}`), width), 0, 0));
2789
+ if (d.preflight) c.addChild(new Text(truncLine(theme.fg("dim", formatWorkflowPreflightPlanSummary(d.preflight, { indent: rowIndent })), width), 0, 0));
2790
+ if (phase) c.addChild(new Text(truncLine(theme.fg("dim", `${rowIndent}Phase ${phase}`), width), 0, 0));
2791
+ const checklist = projectWorkflowChecklist({ hostSteps: workflow?.receipt?.hostSteps, preflight: d.preflight, trace: workflow?.trace, now: Date.now() });
2792
+ for (const line of workflowChecklistWidgetLines(checklist, theme, rowIndent, false, frame, true, !expanded, expanded)) {
2793
+ c.addChild(new Text(truncLine(line, width), 0, 0));
2794
+ }
2795
+ if (rows.length === 0) {
2796
+ c.addChild(new Text(truncLine(theme.fg("dim", `${rowIndent}◦ waiting for workflow child launches`), width), 0, 0));
2797
+ return c;
2798
+ }
2799
+ const visible = visibleWorkflowRows(rows);
2800
+ if (visible.hiddenRows > 0) c.addChild(new Text(truncLine(theme.fg("dim", `${rowIndent}… ${visible.hiddenRows} older workflow rows hidden`), width), 0, 0));
2801
+ for (const row of visible.rows) {
2802
+ const status = workflowRowStateLabel(row, theme);
2803
+ const label = row.label && row.label !== row.key ? ` ${oneLine(row.label)}` : "";
2804
+ const duration = row.durationMs !== undefined ? ` ${theme.fg("dim", `· ${formatDuration(row.durationMs)}`)}` : "";
2805
+ const run = row.runId ? ` ${theme.fg("dim", `[${row.runId.slice(0, 8)}]`)}` : "";
2806
+ const error = row.error ? ` ${theme.fg(row.state === "detached" ? "warning" : "error", `· ${compactWorkflowError(row.error)}`)}` : "";
2807
+ const hints = expanded && row.preflight ? [
2808
+ row.preflight.mode ? `mode:${row.preflight.mode}` : undefined,
2809
+ row.preflight.decision ? `decision:${row.preflight.decision}` : undefined,
2810
+ row.preflight.claims?.length ? `claims:${row.preflight.claims.join(",")}` : undefined,
2811
+ row.preflight.expectedOutput ? `expected:${row.preflight.expectedOutput}` : undefined,
2812
+ row.preflight.independence ? `independence:${row.preflight.independence}` : undefined,
2813
+ ].filter((value): value is string => Boolean(value)).join(" · ") : "";
2814
+ c.addChild(new Text(truncLine(`${rowIndent}${workflowRowGlyph(row, theme, frame)} ${status} ${theme.bold(row.key)}${label}${run}${duration}${error}${hints ? ` ${theme.fg("dim", `· ${hints}`)}` : ""}`, width), 0, 0));
2815
+ }
2816
+ if (workflow?.preflightWarnings?.length) {
2817
+ const warningLines = expanded
2818
+ ? formatWorkflowPreflightWarnings(workflow.preflightWarnings, { indent: rowIndent }).split("\n")
2819
+ : [formatWorkflowPreflightWarningSummary(workflow.preflightWarnings, { indent: rowIndent, hint: "expand for debug" })];
2820
+ for (const warningLine of warningLines) c.addChild(new Text(truncLine(theme.fg("warning", warningLine), width), 0, 0));
2821
+ }
2822
+ if (workflow?.emits.length) c.addChild(new Text(truncLine(theme.fg("dim", `${rowIndent}Emits ${workflow.emits.length}`), width), 0, 0));
2823
+ return c;
2824
+ }
2825
+
2826
+ function renderMultiCompact(d: Details, theme: Theme, layout: MainWindowRenderLayout, frame?: number): Component {
2827
+ const hasRunning = detailsHaveRunningResult(d);
2828
+ const detached = d.results.some((r) => r.detached)
2829
+ || workflowGraphHasStatus(d, ["detached"]);
2830
+ const stopped = d.results.some((r) => r.stopped)
2831
+ || workflowGraphHasStatus(d, ["stopped"]);
2832
+ const failed = d.results.some((r) => !hasTerminalResultFlag(r) && r.exitCode !== 0 && !isResultRunning(r))
2833
+ || workflowGraphHasStatus(d, ["failed"]);
2834
+ const paused = d.results.some((r) => r.interrupted)
2835
+ || workflowGraphHasStatus(d, ["paused"]);
2836
+ const partial = workflowGraphHasStatus(d, ["partial"]);
2837
+ let totalSummary = d.progressSummary;
2838
+ if (!totalSummary) {
2839
+ let sawProgress = false;
2840
+ const summary = { toolCount: 0, tokens: 0, durationMs: 0 };
2841
+ for (const r of d.results) {
2842
+ const prog = r.progress || r.progressSummary;
2843
+ if (!prog) continue;
2844
+ sawProgress = true;
2845
+ summary.toolCount += prog.toolCount;
2846
+ summary.tokens += prog.tokens;
2847
+ summary.durationMs = d.mode === "chain" ? summary.durationMs + prog.durationMs : Math.max(summary.durationMs, prog.durationMs);
2848
+ }
2849
+ if (sawProgress) totalSummary = summary;
2850
+ }
2851
+ const multiLabel = buildMultiProgressLabel(d, hasRunning);
2852
+ const itemTitle = multiLabel.itemTitle;
2853
+ const workflowChecklist = foregroundWorkflowChecklist(d);
2854
+ const checklistPrimary = d.mode === "workflow" && workflowChecklist !== undefined;
2855
+ const stats = statJoin(theme, [checklistPrimary ? formatWorkflowChecklistSummary(workflowChecklist) : multiLabel.headerLabel, formatProgressStats(theme, totalSummary), formatTotalCostStat(d.totalCost)]);
2856
+ const aggregatePresentation = semanticResultPresentation({
2857
+ running: hasRunning,
2858
+ detached,
2859
+ stopped,
2860
+ interrupted: paused,
2861
+ failed,
2862
+ partial,
2863
+ seed: runningSeed(progressRunningSeed(totalSummary), d.currentStepIndex),
2864
+ frame,
2865
+ });
2866
+ const glyph = theme.fg(aggregatePresentation.tone, aggregatePresentation.glyph);
2867
+ const contextBadge = contextModeBadge(theme, d.context);
2868
+ const c = new Container();
2869
+ const width = getTermWidth() - 4;
2870
+ const rowIndent = mainWindowIndent(layout, 1);
2871
+ const detailIndent = mainWindowIndent(layout, 2);
2872
+ c.addChild(new Text(truncLine(`${glyph} ${theme.fg("toolTitle", theme.bold(d.mode))}${contextBadge}${stats ? ` ${theme.fg("dim", "·")} ${stats}` : ""}`, width), 0, 0));
2873
+ if (checklistPrimary) {
2874
+ for (const line of workflowChecklistWidgetLines(workflowChecklist, theme, rowIndent, false, frame, false)) {
2875
+ c.addChild(new Text(truncLine(line, width), 0, 0));
2876
+ }
2877
+ if (hasRunning || workflowChecklist.running > 0) c.addChild(new Text(truncLine(theme.fg("accent", `${rowIndent}${liveDetailHintText()}`), width), 0, 0));
2878
+ return c;
2879
+ }
2880
+ for (const line of workflowChecklistWidgetLines(workflowChecklist, theme, rowIndent, false, frame)) {
2881
+ c.addChild(new Text(truncLine(line, width), 0, 0));
2882
+ }
2883
+
2884
+ const useResultsDirectly = multiLabel.hasParallelInChain || !d.chainAgents?.length;
2885
+ const displayStart = multiLabel.showActiveGroupOnly ? multiLabel.groupStartIndex : 0;
2886
+ const displayEnd = multiLabel.showActiveGroupOnly ? multiLabel.groupEndIndex : (useResultsDirectly ? d.results.length : d.chainAgents!.length);
2887
+ const chainEntries = buildChainRenderEntries(d, multiLabel);
2888
+ const renderEntries = chainEntries ?? buildForegroundResultEntries(d, multiLabel, displayStart, displayEnd, useResultsDirectly);
2889
+ for (const entry of renderEntries) {
2890
+ if (entry.kind === "group") {
2891
+ const glyph = widgetStepGlyph(entry.status as AsyncJobStep["status"], theme);
2892
+ const statusLabel = widgetStepStatus(entry.status as AsyncJobStep["status"], theme);
2893
+ const groupLabel = entry.groupLabel ? ` (${compactTaskText(undefined, entry.groupLabel) ?? entry.groupLabel})` : "";
2894
+ c.addChild(new Text(truncLine(`${rowIndent}${glyph} ${entry.stepLabel}${groupLabel} ${theme.fg("dim", "·")} ${statusLabel}`, width), 0, 0));
2895
+ if (entry.error) c.addChild(new Text(truncLine(theme.fg("error", `${detailIndent}⎿ Error: ${entry.error}`), width), 0, 0));
2896
+ continue;
2897
+ }
2898
+ const i = entry.resultIndex;
2899
+ const r = d.results[i];
2900
+ const rowNumber = entry.rowNumber;
2901
+ const agentName = entry.agentName;
2902
+ if (!r) {
2903
+ const pendingLabel = entry.rowLabel ?? (entry.isParallel ? "" : `${itemTitle} ${rowNumber}`);
2904
+ const labelPrefix = pendingLabel ? `${pendingLabel}: ` : "";
2905
+ c.addChild(new Text(truncLine(theme.fg("dim", `${rowIndent}◦ ${labelPrefix}${agentName} · pending`), width), 0, 0));
2906
+ continue;
2907
+ }
2908
+ const output = getSingleResultOutput(r);
2909
+ const progressFromArray = foregroundProgressForResult(d, i);
2910
+ const rProg = r.progress || progressFromArray || r.progressSummary;
2911
+ const rRunning = rProg && "status" in rProg && isResultRunning(r, rProg.status);
2912
+ const rPending = rProg && "status" in rProg && rProg.status === "pending";
2913
+ const stepStats = formatProgressStats(theme, rProg);
2914
+ const glyph = rPending ? theme.fg("dim", "◦") : resultGlyph(r, output, theme, rRunning, progressRunningSeed(rProg), frame);
2915
+ const pendingLabel = rPending ? ` ${theme.fg("dim", "· pending")}` : "";
2916
+ const stepLabel = entry.rowLabel;
2917
+ const rowProgressModel = rProg && "status" in rProg ? rProg : undefined;
2918
+ const rowModelDisplay = modelThinkingBadge(theme, r.model ?? rowProgressModel?.model, r.thinking ?? rowProgressModel?.thinking);
2919
+ const labelPrefix = stepLabel ? `${stepLabel}: ` : "";
2920
+ const line = `${glyph} ${labelPrefix}${themeBold(theme, agentName)}${contextModeBadge(theme, r.context)}${rowModelDisplay}${stepStats ? ` ${theme.fg("dim", "·")} ${stepStats}` : ""}${pendingLabel}`;
2921
+ c.addChild(new Text(truncLine(`${rowIndent}${line}`, width), 0, 0));
2922
+ if (rRunning || rPending) {
2923
+ const task = compactTaskText(r.task, workflowLabelForResult(d, i));
2924
+ if (task) c.addChild(new Text(truncLine(theme.fg("dim", `${detailIndent}task: ${task}`), width), 0, 0));
2925
+ }
2926
+ if (rRunning && rProg && "status" in rProg) {
2927
+ const liveProgress = rProg as AgentProgress;
2928
+ const activity = compactCurrentActivity(liveProgress);
2929
+ c.addChild(new Text(truncLine(theme.fg("dim", `${detailIndent}⎿ ${activity}`), width), 0, 0));
2930
+ for (const nestedLine of formatNestedWidgetLines(r.children, theme, width, false, snapshotNowForProgress(liveProgress))) {
2931
+ c.addChild(new Text(truncLine(`${detailIndent}${nestedLine}`, width), 0, 0));
2932
+ }
2933
+ c.addChild(new Text(truncLine(theme.fg("accent", `${detailIndent}${liveDetailHintText()}`), width), 0, 0));
2934
+ } else if (!rPending && (r.exitCode !== 0 || r.interrupted || r.detached || hasEmptyTextOutputWithoutOutputTarget(r.task, output))) {
2935
+ c.addChild(new Text(truncLine(theme.fg(r.exitCode !== 0 ? "error" : "dim", `${detailIndent}⎿ ${resultStatusLine(r, output)}`), width), 0, 0));
2936
+ }
2937
+ if (!rRunning && !rPending) {
2938
+ for (const nestedLine of formatNestedWidgetLines(r.children, theme, width, false, r.progress?.lastActivityAt)) {
2939
+ c.addChild(new Text(truncLine(`${detailIndent}${nestedLine}`, width), 0, 0));
2940
+ }
2941
+ }
2942
+ const outputTarget = extractOutputTarget(r.task);
2943
+ if (outputTarget) c.addChild(new Text(truncLine(theme.fg("dim", `${detailIndent}output: ${outputTarget}`), width), 0, 0));
2944
+ if (r.artifactPaths) c.addChild(new Text(truncLine(theme.fg("dim", `${detailIndent}output: ${shortenPath(r.artifactPaths.outputPath)}`), width), 0, 0));
2945
+ }
2946
+ if (d.artifacts) c.addChild(new Text(truncLine(theme.fg("dim", `${rowIndent}artifacts: ${shortenPath(d.artifacts.dir)}`), width), 0, 0));
2947
+ return c;
2948
+ }
2949
+
2950
+ export function renderSubagentSummary(
2951
+ result: AgentToolResult<Details>,
2952
+ options: { isPartial?: boolean },
2953
+ theme: Theme,
2954
+ ): Component {
2955
+ const details = result.details;
2956
+ const results = details?.results ?? [];
2957
+ const hasSingleTerminalResult = results.length === 1 && hasTerminalResult(results[0]!);
2958
+ const hasOnlyTerminalResults = results.length > 0 && results.every(hasTerminalResult);
2959
+ const running = !hasSingleTerminalResult && !hasOnlyTerminalResults && (
2960
+ options.isPartial === true
2961
+ || Boolean(details?.asyncId && details.mode !== "management")
2962
+ || Boolean(details && detailsHaveRunningResult(details))
2963
+ );
2964
+ const stopped = results.some((entry) => entry.stopped)
2965
+ || Boolean(details && workflowGraphHasStatus(details, ["stopped"]));
2966
+ const paused = results.some((entry) => entry.interrupted || entry.detached)
2967
+ || Boolean(details && workflowGraphHasStatus(details, ["paused", "detached"]));
2968
+ const failed = result.isError === true
2969
+ || results.some((entry) => !hasTerminalResultFlag(entry) && entry.exitCode !== 0 && !isResultRunning(entry))
2970
+ || Boolean(details && workflowGraphHasStatus(details, ["failed"]));
2971
+ const partial = Boolean(details && workflowGraphHasStatus(details, ["partial"]));
2972
+ const state = running ? "running" : failed ? "failed" : stopped ? "stopped" : paused ? "paused" : partial ? "partial" : "completed";
2973
+ const glyph = state === "running"
2974
+ ? theme.fg("accent", STATIC_RUNNING_GLYPH)
2975
+ : state === "completed"
2976
+ ? theme.fg("success", "✓")
2977
+ : state === "failed"
2978
+ ? theme.fg("error", "✗")
2979
+ : theme.fg("warning", "■");
2980
+ const label = details?.mode === "single" && results.length === 1
2981
+ ? foregroundSingleDisplayName(results[0])
2982
+ : details?.mode || "subagent";
2983
+ return new Text(
2984
+ truncLine(`${glyph} ${theme.fg("toolTitle", theme.bold(label))} ${theme.fg("dim", "·")} ${theme.fg(state === "failed" ? "error" : state === "completed" ? "success" : state === "running" ? "accent" : "warning", state)}`, getTermWidth() - 4),
2985
+ 0,
2986
+ 0,
2987
+ );
2988
+ }
2989
+
2990
+ /**
2991
+ * Render a subagent result
2992
+ */
2993
+ export function renderSubagentResult(
2994
+ result: AgentToolResult<Details>,
2995
+ options: { expanded: boolean },
2996
+ theme: Theme,
2997
+ frame?: number,
2998
+ rendererConfig?: MainWindowRendererConfig,
2999
+ foregroundDetachShortcut?: string,
3000
+ ): Component {
3001
+ const layout = resolveMainWindowRenderLayout(rendererConfig);
3002
+ const compact = (component: Component): Component => capCompactMainWindowResult(component, layout, theme, !options.expanded);
3003
+ const d = result.details;
3004
+ if (d?.mode === "workflow" && d.chatProgress?.mode === "live-card" && d.workflow?.value === undefined && (!result.isError || (d.workflow?.trace.length ?? 0) > 0)) {
3005
+ return compact(renderWorkflowChatProgress(d, result, theme, options.expanded ? resolveMainWindowRenderLayout() : layout, frame, options.expanded));
3006
+ }
3007
+ if (!d || !d.results.length) {
3008
+ const t = result.content[0];
3009
+ const text = t?.type === "text" ? t.text : "(no output)";
3010
+ const contextPrefix = contextModePrefix(theme, d?.context);
3011
+ const width = getTermWidth() - 4;
3012
+ if (!text.includes("\n")) return compact(new Text(truncLine(`${contextPrefix}${text}`, width), 0, 0));
3013
+ if (d && !options.expanded && !result.isError) {
3014
+ const lines = text.split(/\r?\n/);
3015
+ const firstNonEmptyLine = lines.find((line) => line.trim())?.trim() || "(no output)";
3016
+ const compactLine = d.mode === "workflow" && d.preflight
3017
+ ? formatWorkflowPreflightPlanSummary(d.preflight)
3018
+ : firstNonEmptyLine;
3019
+ const c = new Container();
3020
+ const detailIndent = mainWindowIndent(layout, 1);
3021
+ c.addChild(new Text(truncLine(`${contextPrefix}${compactLine} · ${lines.length} lines`, width), 0, 0));
3022
+ c.addChild(new Text(truncLine(theme.fg("accent", `${detailIndent}Press ${liveDetailKeyText()} for full output`), width), 0, 0));
3023
+ return compact(c);
3024
+ }
3025
+ const c = new Container();
3026
+ const wrapped = wrapPlainText(`${contextPrefix}${text}`, width);
3027
+ for (const line of wrapped) c.addChild(new Text(line, 0, 0));
3028
+ return c;
3029
+ }
3030
+
3031
+ const expanded = options.expanded;
3032
+ const mdTheme = getMarkdownTheme();
3033
+
3034
+ if (d.mode === "single" && d.results.length === 1) {
3035
+ const r = d.results[0];
3036
+ const detachableShortcut = d.asyncId || d.background ? undefined : foregroundDetachShortcut;
3037
+ if (!r) return compact(renderMultiCompact(d, theme, layout, frame));
3038
+ if (!expanded) return compact(renderSingleCompact(d, r, theme, layout, frame, detachableShortcut));
3039
+ const isRunning = isResultRunning(r);
3040
+ const contextBadge = contextModeBadge(theme, r.context ?? d.context);
3041
+ const output = r.truncation?.text || getSingleResultOutput(r);
3042
+ const presentation = styledResultPresentation(resultPresentation(r, output, isRunning, undefined, frame), theme);
3043
+
3044
+ const progressInfo = isRunning && r.progress
3045
+ ? ` | ${r.progress.toolCount} tools, ${formatTokens(r.progress.tokens)} tok, ${formatDuration(r.progress.durationMs)}`
3046
+ : r.progressSummary
3047
+ ? ` | ${r.progressSummary.toolCount} tools, ${formatTokens(r.progressSummary.tokens)} tok, ${formatDuration(r.progressSummary.durationMs)}`
3048
+ : "";
3049
+
3050
+ const w = getTermWidth() - 4;
3051
+ const fit = (text: string) => expanded ? text : truncLine(text, w);
3052
+ const toolCallLines = getToolCallLines(r, expanded);
3053
+ const c = new Container();
3054
+ c.addChild(new Text(fit(`${presentation.glyph} ${theme.fg("toolTitle", theme.bold(foregroundSingleDisplayName(r)))}${contextBadge}${progressInfo} ${theme.fg("dim", "·")} ${presentation.label}`), 0, 0));
3055
+ c.addChild(new Spacer(1));
3056
+ const taskMaxLen = Math.max(20, w - 8);
3057
+ const taskPreview = expanded || r.task.length <= taskMaxLen
3058
+ ? r.task
3059
+ : `${r.task.slice(0, taskMaxLen)}...`;
3060
+ c.addChild(
3061
+ new Text(fit(theme.fg("dim", `Task: ${taskPreview}`)), 0, 0),
3062
+ );
3063
+ c.addChild(new Spacer(1));
3064
+ if (!isRunning && (r.exitCode !== 0 || r.interrupted || r.detached || r.stopped)) {
3065
+ c.addChild(new Text(fit(theme.fg(r.exitCode !== 0 ? "error" : "dim", ` ⎿ ${resultStatusLine(r, output)}`)), 0, 0));
3066
+ }
3067
+
3068
+ if (isRunning && r.progress) {
3069
+ const progressSnapshotNow = snapshotNowForProgress(r.progress);
3070
+ for (const nestedLine of formatNestedWidgetLines(r.children, theme, w, true, progressSnapshotNow, 12)) {
3071
+ c.addChild(new Text(fit(` ${nestedLine}`), 0, 0));
3072
+ }
3073
+ const toolLine = formatCurrentToolLine(r.progress, w, expanded, progressSnapshotNow);
3074
+ if (toolLine) {
3075
+ c.addChild(new Text(fit(theme.fg("warning", `> ${toolLine}`)), 0, 0));
3076
+ }
3077
+ const liveStatusLine = buildLiveStatusLine(r.progress, progressSnapshotNow);
3078
+ if (liveStatusLine) {
3079
+ c.addChild(new Text(fit(theme.fg("accent", liveStatusLine)), 0, 0));
3080
+ }
3081
+ c.addChild(new Text(fit(theme.fg("accent", foregroundSingleHintText(detachableShortcut))), 0, 0));
3082
+ if (r.artifactPaths) {
3083
+ c.addChild(new Text(fit(theme.fg("dim", `Artifacts: ${shortenPath(r.artifactPaths.outputPath)}`)), 0, 0));
3084
+ }
3085
+ if (r.progress.recentTools?.length) {
3086
+ for (const t of r.progress.recentTools.slice(-3)) {
3087
+ const maxArgsLen = Math.max(40, w - 24);
3088
+ const argsPreview = renderToolArgsPreview(t.args, maxArgsLen, expanded);
3089
+ c.addChild(new Text(fit(theme.fg("dim", `${t.tool}: ${argsPreview}`)), 0, 0));
3090
+ }
3091
+ }
3092
+ for (const line of compactRecentOutputLines(r.progress.recentOutput)) {
3093
+ c.addChild(new Text(fit(theme.fg("dim", ` ${line}`)), 0, 0));
3094
+ }
3095
+ if (toolLine || liveStatusLine || r.progress.recentTools?.length || r.progress.recentOutput?.length || r.artifactPaths) {
3096
+ c.addChild(new Spacer(1));
3097
+ }
3098
+ } else {
3099
+ for (const nestedLine of formatNestedWidgetLines(r.children, theme, w, true, r.progress?.lastActivityAt, 8)) {
3100
+ c.addChild(new Text(fit(` ${nestedLine}`), 0, 0));
3101
+ }
3102
+ }
3103
+
3104
+ if (expanded) {
3105
+ for (const line of toolCallLines) {
3106
+ c.addChild(new Text(fit(theme.fg("muted", line)), 0, 0));
3107
+ }
3108
+ if (toolCallLines.length) c.addChild(new Spacer(1));
3109
+ }
3110
+
3111
+ if (output) c.addChild(new Markdown(output, 0, 0, mdTheme));
3112
+ c.addChild(new Spacer(1));
3113
+ if (r.skills?.length) {
3114
+ c.addChild(new Text(fit(theme.fg("dim", `Skills: ${r.skills.join(", ")}`)), 0, 0));
3115
+ }
3116
+ if (r.skillsWarning) {
3117
+ c.addChild(new Text(fit(theme.fg("warning", `Warning: ${r.skillsWarning}`)), 0, 0));
3118
+ }
3119
+ if (r.attemptedModels && r.attemptedModels.length > 1) {
3120
+ c.addChild(new Text(fit(theme.fg("dim", `Fallbacks: ${r.attemptedModels.join(" → ")}`)), 0, 0));
3121
+ }
3122
+ c.addChild(new Text(fit(theme.fg("dim", formatUsage(r.usage, r.model))), 0, 0));
3123
+ if (r.sessionFile) {
3124
+ c.addChild(new Text(fit(theme.fg("dim", `Session: ${shortenPath(r.sessionFile)}`)), 0, 0));
3125
+ }
3126
+
3127
+ if (!isRunning && r.artifactPaths) {
3128
+ c.addChild(new Spacer(1));
3129
+ c.addChild(new Text(fit(theme.fg("dim", `Artifacts: ${shortenPath(r.artifactPaths.outputPath)}`)), 0, 0));
3130
+ }
3131
+ return c;
3132
+ }
3133
+
3134
+ if (!expanded) return compact(renderMultiCompact(d, theme, layout, frame));
3135
+
3136
+ const hasRunning = detailsHaveRunningResult(d);
3137
+ const detached = d.results.some((r) => r.detached)
3138
+ || workflowGraphHasStatus(d, ["detached"]);
3139
+ const stopped = d.results.some((r) => r.stopped)
3140
+ || workflowGraphHasStatus(d, ["stopped"]);
3141
+ const failed = d.results.some((r) => !hasTerminalResultFlag(r) && r.exitCode !== 0 && !isResultRunning(r))
3142
+ || workflowGraphHasStatus(d, ["failed"]);
3143
+ const paused = d.results.some((r) => r.interrupted)
3144
+ || workflowGraphHasStatus(d, ["paused"]);
3145
+ const partial = workflowGraphHasStatus(d, ["partial"]);
3146
+ const completedWithoutOutput = d.results.some((r) =>
3147
+ !hasTerminalResultFlag(r)
3148
+ && r.exitCode === 0
3149
+ && !isResultRunning(r)
3150
+ && hasEmptyTextOutputWithoutOutputTarget(r.task, getSingleResultOutput(r)),
3151
+ );
3152
+ const presentation = styledResultPresentation(semanticResultPresentation({
3153
+ running: hasRunning,
3154
+ detached,
3155
+ stopped,
3156
+ interrupted: paused,
3157
+ failed,
3158
+ partial,
3159
+ completedWithoutOutput,
3160
+ frame,
3161
+ }), theme);
3162
+
3163
+ const totalSummary =
3164
+ d.progressSummary ||
3165
+ d.results.reduce(
3166
+ (acc, r) => {
3167
+ const prog = r.progress || r.progressSummary;
3168
+ if (prog) {
3169
+ acc.toolCount += prog.toolCount;
3170
+ acc.tokens += prog.tokens;
3171
+ acc.durationMs =
3172
+ d.mode === "chain"
3173
+ ? acc.durationMs + prog.durationMs
3174
+ : Math.max(acc.durationMs, prog.durationMs);
3175
+ }
3176
+ return acc;
3177
+ },
3178
+ { toolCount: 0, tokens: 0, durationMs: 0 },
3179
+ );
3180
+
3181
+ const summaryParts = [
3182
+ totalSummary.toolCount || totalSummary.tokens
3183
+ ? `${totalSummary.toolCount} tools, ${formatTokens(totalSummary.tokens)} tok, ${formatDuration(totalSummary.durationMs)}`
3184
+ : "",
3185
+ formatTotalCostStat(d.totalCost),
3186
+ ].filter(Boolean);
3187
+ const summaryStr = summaryParts.length ? ` | ${summaryParts.join(", ")}` : "";
3188
+
3189
+ const modeLabel = d.mode;
3190
+ const contextBadge = contextModeBadge(theme, d.context);
3191
+ const multiLabel = buildMultiProgressLabel(d, hasRunning);
3192
+ const itemTitle = multiLabel.itemTitle;
3193
+
3194
+ const chainVis = d.chainAgents?.length && !multiLabel.hasParallelInChain
3195
+ ? d.chainAgents
3196
+ .map((agent, i) => {
3197
+ const result = d.results[i];
3198
+ const displayName = foregroundResultDisplayName(d, i, result, agent);
3199
+ const isCurrent = i === (d.currentStepIndex ?? d.results.length);
3200
+ const stepPresentation = result
3201
+ ? styledResultPresentation(resultPresentation(result, getSingleResultOutput(result), isCurrent && hasRunning && !hasTerminalResultFlag(result)), theme)
3202
+ : undefined;
3203
+ const stepStatus = stepPresentation
3204
+ ? `${stepPresentation.glyph} ${stepPresentation.label}`
3205
+ : theme.fg("dim", "◦ pending");
3206
+ return `${stepStatus} ${displayName}${contextModeBadge(theme, result?.context)}`;
3207
+ })
3208
+ .join(theme.fg("dim", " → "))
3209
+ : null;
3210
+
3211
+ const w = getTermWidth() - 4;
3212
+ const fit = (text: string) => expanded ? text : truncLine(text, w);
3213
+ const c = new Container();
3214
+ c.addChild(
3215
+ new Text(
3216
+ fit(`${presentation.glyph} ${theme.fg("toolTitle", theme.bold(modeLabel))}${contextBadge} · ${multiLabel.headerLabel}${summaryStr} ${theme.fg("dim", "·")} ${presentation.label}`),
3217
+ 0,
3218
+ 0,
3219
+ ),
3220
+ );
3221
+ if (chainVis) {
3222
+ c.addChild(new Text(fit(` ${chainVis}`), 0, 0));
3223
+ }
3224
+ const workflowChecklist = foregroundWorkflowChecklist(d);
3225
+ for (const line of workflowChecklistWidgetLines(workflowChecklist, theme, " ", true, frame)) {
3226
+ c.addChild(new Text(fit(line), 0, 0));
3227
+ }
3228
+
3229
+ const useResultsDirectly = multiLabel.hasParallelInChain || !d.chainAgents?.length;
3230
+ const displayStart = multiLabel.showActiveGroupOnly ? multiLabel.groupStartIndex : 0;
3231
+ const displayEnd = multiLabel.showActiveGroupOnly ? multiLabel.groupEndIndex : (useResultsDirectly ? d.results.length : d.chainAgents!.length);
3232
+ const chainEntries = buildChainRenderEntries(d, multiLabel);
3233
+ const renderEntries = chainEntries ?? buildForegroundResultEntries(d, multiLabel, displayStart, displayEnd, useResultsDirectly);
3234
+
3235
+ c.addChild(new Spacer(1));
3236
+
3237
+ for (const entry of renderEntries) {
3238
+ if (entry.kind === "group") {
3239
+ const statusLabel = widgetStepStatus(entry.status as AsyncJobStep["status"], theme);
3240
+ const groupLabel = entry.groupLabel ? ` (${compactTaskText(undefined, entry.groupLabel) ?? entry.groupLabel})` : "";
3241
+ c.addChild(new Text(fit(` ${statusLabel} ${entry.stepLabel}${groupLabel}`), 0, 0));
3242
+ c.addChild(new Text(theme.fg(entry.status === "failed" ? "error" : "dim", ` status: ${entry.status}`), 0, 0));
3243
+ if (entry.error) c.addChild(new Text(theme.fg("error", ` error: ${entry.error}`), 0, 0));
3244
+ c.addChild(new Spacer(1));
3245
+ continue;
3246
+ }
3247
+ const i = entry.resultIndex;
3248
+ const r = d.results[i];
3249
+ const rowNumber = entry.rowNumber;
3250
+ const agentName = entry.agentName;
3251
+
3252
+ if (!r) {
3253
+ const pendingLabel = entry.rowLabel ?? (entry.isParallel ? "" : `${itemTitle} ${rowNumber}`);
3254
+ const labelPrefix = pendingLabel ? `${pendingLabel}: ` : "";
3255
+ c.addChild(new Text(fit(theme.fg("dim", ` ${labelPrefix}${agentName}`)), 0, 0));
3256
+ c.addChild(new Text(theme.fg("dim", ` status: pending`), 0, 0));
3257
+ c.addChild(new Spacer(1));
3258
+ continue;
3259
+ }
3260
+
3261
+ const progressFromArray = foregroundProgressForResult(d, i);
3262
+ const rProg = r.progress || progressFromArray || r.progressSummary;
3263
+ const rRunning = isResultRunning(r, rProg?.status);
3264
+
3265
+ const resultOutput = getSingleResultOutput(r);
3266
+ const rowPresentation = styledResultPresentation(resultPresentation(r, resultOutput, rRunning, progressRunningSeed(rProg), frame), theme);
3267
+ const stats = rProg ? ` | ${rProg.toolCount} tools, ${formatDuration(rProg.durationMs)}` : "";
3268
+ const modelDisplay = modelThinkingBadge(theme, r.model ?? rProg?.model, r.thinking ?? rProg?.thinking);
3269
+ const stepLabel = entry.rowLabel;
3270
+ const contextBadge = contextModeBadge(theme, r.context);
3271
+ const labelPrefix = stepLabel ? `${stepLabel}: ` : "";
3272
+ const stepHeader = rRunning
3273
+ ? `${rowPresentation.glyph} ${labelPrefix}${theme.bold(theme.fg("warning", agentName))}${contextBadge}${modelDisplay}${stats} ${theme.fg("dim", "·")} ${rowPresentation.label}`
3274
+ : `${rowPresentation.glyph} ${labelPrefix}${theme.bold(agentName)}${contextBadge}${modelDisplay}${stats} ${theme.fg("dim", "·")} ${rowPresentation.label}`;
3275
+ const toolCallLines = getToolCallLines(r, expanded);
3276
+ c.addChild(new Text(fit(stepHeader), 0, 0));
3277
+
3278
+ const taskMaxLen = Math.max(20, w - 12);
3279
+ const taskPreview = expanded || r.task.length <= taskMaxLen
3280
+ ? r.task
3281
+ : `${r.task.slice(0, taskMaxLen)}...`;
3282
+ c.addChild(new Text(fit(theme.fg("dim", ` task: ${taskPreview}`)), 0, 0));
3283
+
3284
+ const outputTarget = extractOutputTarget(r.task);
3285
+ if (outputTarget) {
3286
+ c.addChild(new Text(fit(theme.fg("dim", ` output: ${outputTarget}`)), 0, 0));
3287
+ }
3288
+ if (!rRunning && (r.exitCode !== 0 || r.interrupted || r.detached || r.stopped)) {
3289
+ c.addChild(new Text(fit(theme.fg(r.exitCode !== 0 ? "error" : "dim", ` ⎿ ${resultStatusLine(r, resultOutput)}`)), 0, 0));
3290
+ }
3291
+
3292
+ if (r.skills?.length) {
3293
+ c.addChild(new Text(fit(theme.fg("dim", ` skills: ${r.skills.join(", ")}`)), 0, 0));
3294
+ }
3295
+ if (r.skillsWarning) {
3296
+ c.addChild(new Text(fit(theme.fg("warning", ` Warning: ${r.skillsWarning}`)), 0, 0));
3297
+ }
3298
+ if (r.attemptedModels && r.attemptedModels.length > 1) {
3299
+ c.addChild(new Text(fit(theme.fg("dim", ` fallbacks: ${r.attemptedModels.join(" → ")}`)), 0, 0));
3300
+ }
3301
+
3302
+ if (rRunning && rProg) {
3303
+ if (rProg.skills?.length) {
3304
+ c.addChild(new Text(fit(theme.fg("accent", ` skills: ${rProg.skills.join(", ")}`)), 0, 0));
3305
+ }
3306
+ const progressSnapshotNow = snapshotNowForProgress(rProg);
3307
+ const toolLine = formatCurrentToolLine(rProg, w, expanded, progressSnapshotNow);
3308
+ if (toolLine) {
3309
+ c.addChild(new Text(fit(theme.fg("warning", ` > ${toolLine}`)), 0, 0));
3310
+ }
3311
+ const liveStatusLine = buildLiveStatusLine(rProg, progressSnapshotNow);
3312
+ if (liveStatusLine) {
3313
+ c.addChild(new Text(fit(theme.fg("accent", ` ${liveStatusLine}`)), 0, 0));
3314
+ }
3315
+ for (const nestedLine of formatNestedWidgetLines(r.children, theme, w, true, progressSnapshotNow, 8)) {
3316
+ c.addChild(new Text(fit(` ${nestedLine}`), 0, 0));
3317
+ }
3318
+ c.addChild(new Text(fit(theme.fg("accent", ` ${liveDetailHintText()}`)), 0, 0));
3319
+ if (r.artifactPaths) {
3320
+ c.addChild(new Text(fit(theme.fg("dim", ` artifacts: ${shortenPath(r.artifactPaths.outputPath)}`)), 0, 0));
3321
+ }
3322
+ if (rProg.recentTools?.length) {
3323
+ for (const t of rProg.recentTools.slice(-3)) {
3324
+ const maxArgsLen = Math.max(40, w - 30);
3325
+ const argsPreview = renderToolArgsPreview(t.args, maxArgsLen, expanded);
3326
+ c.addChild(new Text(fit(theme.fg("dim", ` ${t.tool}: ${argsPreview}`)), 0, 0));
3327
+ }
3328
+ }
3329
+ for (const line of compactRecentOutputLines(rProg.recentOutput)) {
3330
+ c.addChild(new Text(fit(theme.fg("dim", ` ${line}`)), 0, 0));
3331
+ }
3332
+ }
3333
+
3334
+ if (!rRunning) {
3335
+ for (const nestedLine of formatNestedWidgetLines(r.children, theme, w, true, r.progress?.lastActivityAt, 8)) {
3336
+ c.addChild(new Text(fit(` ${nestedLine}`), 0, 0));
3337
+ }
3338
+ }
3339
+
3340
+ if (!rRunning && r.artifactPaths) {
3341
+ c.addChild(new Text(fit(theme.fg("dim", ` artifacts: ${shortenPath(r.artifactPaths.outputPath)}`)), 0, 0));
3342
+ }
3343
+
3344
+ if (expanded && !rRunning) {
3345
+ for (const line of toolCallLines) {
3346
+ c.addChild(new Text(fit(theme.fg("muted", ` ${line}`)), 0, 0));
3347
+ }
3348
+ if (toolCallLines.length) c.addChild(new Spacer(1));
3349
+ }
3350
+
3351
+ c.addChild(new Spacer(1));
3352
+ }
3353
+
3354
+ if (d.artifacts) {
3355
+ c.addChild(new Spacer(1));
3356
+ c.addChild(new Text(fit(theme.fg("dim", `Artifacts dir: ${shortenPath(d.artifacts.dir)}`)), 0, 0));
3357
+ }
3358
+ return c;
3359
+ }