@bastani/atomic 0.8.10 → 0.8.12-0

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 (514) hide show
  1. package/CHANGELOG.md +29 -2
  2. package/dist/builtin/intercom/package.json +1 -1
  3. package/dist/builtin/mcp/package.json +1 -1
  4. package/dist/builtin/subagents/CHANGELOG.md +3 -0
  5. package/dist/builtin/subagents/package.json +1 -1
  6. package/dist/builtin/subagents/src/agents/agent-serializer.ts +3 -2
  7. package/dist/builtin/subagents/src/agents/agents.ts +1 -1
  8. package/dist/builtin/subagents/src/extension/index.ts +597 -471
  9. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +16 -8
  10. package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +9 -13
  11. package/dist/builtin/subagents/src/runs/foreground/execution.ts +7 -3
  12. package/dist/builtin/subagents/src/shared/formatters.ts +8 -3
  13. package/dist/builtin/subagents/src/slash/slash-commands.ts +625 -468
  14. package/dist/builtin/subagents/src/tui/render.ts +342 -158
  15. package/dist/builtin/web-access/package.json +1 -1
  16. package/dist/builtin/workflows/package.json +1 -1
  17. package/dist/builtin/workflows/src/runs/foreground/executor.ts +15 -4
  18. package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +75 -33
  19. package/dist/builtin/workflows/src/shared/store-types.ts +3 -4
  20. package/dist/builtin/workflows/src/shared/store.ts +2 -3
  21. package/dist/builtin/workflows/src/tui/graph-view.ts +12 -1
  22. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +1 -2
  23. package/dist/builtin/workflows/src/tui/status-helpers.ts +1 -1
  24. package/dist/bun/cli.d.ts.map +1 -1
  25. package/dist/bun/cli.js.map +1 -1
  26. package/dist/cli/args.d.ts +1 -1
  27. package/dist/cli/args.d.ts.map +1 -1
  28. package/dist/cli/args.js.map +1 -1
  29. package/dist/cli/config-selector.d.ts +2 -2
  30. package/dist/cli/config-selector.d.ts.map +1 -1
  31. package/dist/cli/config-selector.js.map +1 -1
  32. package/dist/cli/file-processor.d.ts.map +1 -1
  33. package/dist/cli/file-processor.js.map +1 -1
  34. package/dist/cli/initial-message.d.ts +1 -1
  35. package/dist/cli/initial-message.d.ts.map +1 -1
  36. package/dist/cli/initial-message.js.map +1 -1
  37. package/dist/cli/list-models.d.ts +1 -1
  38. package/dist/cli/list-models.d.ts.map +1 -1
  39. package/dist/cli/list-models.js.map +1 -1
  40. package/dist/cli/session-picker.d.ts +1 -1
  41. package/dist/cli/session-picker.d.ts.map +1 -1
  42. package/dist/cli/session-picker.js.map +1 -1
  43. package/dist/cli.d.ts.map +1 -1
  44. package/dist/cli.js +2 -6
  45. package/dist/cli.js.map +1 -1
  46. package/dist/config.d.ts.map +1 -1
  47. package/dist/config.js +45 -22
  48. package/dist/config.js.map +1 -1
  49. package/dist/core/agent-session-runtime.d.ts +9 -9
  50. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  51. package/dist/core/agent-session-runtime.js +2 -3
  52. package/dist/core/agent-session-runtime.js.map +1 -1
  53. package/dist/core/agent-session-services.d.ts +7 -7
  54. package/dist/core/agent-session-services.d.ts.map +1 -1
  55. package/dist/core/agent-session-services.js.map +1 -1
  56. package/dist/core/agent-session.d.ts +10 -10
  57. package/dist/core/agent-session.d.ts.map +1 -1
  58. package/dist/core/agent-session.js.map +1 -1
  59. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  60. package/dist/core/atomic-guide-command.js.map +1 -1
  61. package/dist/core/auth-guidance.d.ts.map +1 -1
  62. package/dist/core/auth-guidance.js.map +1 -1
  63. package/dist/core/auth-storage.d.ts +1 -1
  64. package/dist/core/auth-storage.d.ts.map +1 -1
  65. package/dist/core/auth-storage.js +1 -1
  66. package/dist/core/auth-storage.js.map +1 -1
  67. package/dist/core/bash-executor.d.ts +1 -1
  68. package/dist/core/bash-executor.d.ts.map +1 -1
  69. package/dist/core/bash-executor.js.map +1 -1
  70. package/dist/core/builtin-packages.d.ts.map +1 -1
  71. package/dist/core/builtin-packages.js.map +1 -1
  72. package/dist/core/compaction/branch-summarization.d.ts +3 -3
  73. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  74. package/dist/core/compaction/branch-summarization.js.map +1 -1
  75. package/dist/core/compaction/compaction.d.ts +2 -2
  76. package/dist/core/compaction/compaction.d.ts.map +1 -1
  77. package/dist/core/compaction/compaction.js.map +1 -1
  78. package/dist/core/compaction/index.d.ts +3 -3
  79. package/dist/core/compaction/index.d.ts.map +1 -1
  80. package/dist/core/compaction/index.js.map +1 -1
  81. package/dist/core/exec.d.ts.map +1 -1
  82. package/dist/core/exec.js.map +1 -1
  83. package/dist/core/export-html/index.d.ts +1 -1
  84. package/dist/core/export-html/index.d.ts.map +1 -1
  85. package/dist/core/export-html/index.js.map +1 -1
  86. package/dist/core/export-html/tool-renderer.d.ts +2 -2
  87. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  88. package/dist/core/export-html/tool-renderer.js.map +1 -1
  89. package/dist/core/extensions/index.d.ts +8 -8
  90. package/dist/core/extensions/index.d.ts.map +1 -1
  91. package/dist/core/extensions/index.js.map +1 -1
  92. package/dist/core/extensions/loader.d.ts +3 -3
  93. package/dist/core/extensions/loader.d.ts.map +1 -1
  94. package/dist/core/extensions/loader.js.map +1 -1
  95. package/dist/core/extensions/runner.d.ts +6 -6
  96. package/dist/core/extensions/runner.d.ts.map +1 -1
  97. package/dist/core/extensions/runner.js.map +1 -1
  98. package/dist/core/extensions/types.d.ts +20 -20
  99. package/dist/core/extensions/types.d.ts.map +1 -1
  100. package/dist/core/extensions/types.js.map +1 -1
  101. package/dist/core/extensions/wrapper.d.ts +2 -2
  102. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  103. package/dist/core/extensions/wrapper.js.map +1 -1
  104. package/dist/core/footer-data-provider.d.ts.map +1 -1
  105. package/dist/core/footer-data-provider.js.map +1 -1
  106. package/dist/core/http-dispatcher.d.ts +32 -0
  107. package/dist/core/http-dispatcher.d.ts.map +1 -0
  108. package/dist/core/http-dispatcher.js +43 -0
  109. package/dist/core/http-dispatcher.js.map +1 -0
  110. package/dist/core/index.d.ts +8 -8
  111. package/dist/core/index.d.ts.map +1 -1
  112. package/dist/core/index.js.map +1 -1
  113. package/dist/core/keybindings.d.ts.map +1 -1
  114. package/dist/core/keybindings.js.map +1 -1
  115. package/dist/core/model-registry.d.ts +4 -4
  116. package/dist/core/model-registry.d.ts.map +1 -1
  117. package/dist/core/model-registry.js +2 -2
  118. package/dist/core/model-registry.js.map +1 -1
  119. package/dist/core/model-resolver.d.ts +1 -1
  120. package/dist/core/model-resolver.d.ts.map +1 -1
  121. package/dist/core/model-resolver.js.map +1 -1
  122. package/dist/core/package-manager.d.ts +1 -1
  123. package/dist/core/package-manager.d.ts.map +1 -1
  124. package/dist/core/package-manager.js +10 -11
  125. package/dist/core/package-manager.js.map +1 -1
  126. package/dist/core/prompt-templates.d.ts +1 -1
  127. package/dist/core/prompt-templates.d.ts.map +1 -1
  128. package/dist/core/prompt-templates.js.map +1 -1
  129. package/dist/core/resolve-config-value.d.ts.map +1 -1
  130. package/dist/core/resolve-config-value.js.map +1 -1
  131. package/dist/core/resource-loader.d.ts +9 -9
  132. package/dist/core/resource-loader.d.ts.map +1 -1
  133. package/dist/core/resource-loader.js.map +1 -1
  134. package/dist/core/sdk.d.ts +13 -13
  135. package/dist/core/sdk.d.ts.map +1 -1
  136. package/dist/core/sdk.js.map +1 -1
  137. package/dist/core/session-manager.d.ts +1 -1
  138. package/dist/core/session-manager.d.ts.map +1 -1
  139. package/dist/core/session-manager.js.map +1 -1
  140. package/dist/core/settings-manager.d.ts +3 -0
  141. package/dist/core/settings-manager.d.ts.map +1 -1
  142. package/dist/core/settings-manager.js +21 -0
  143. package/dist/core/settings-manager.js.map +1 -1
  144. package/dist/core/skills.d.ts +2 -2
  145. package/dist/core/skills.d.ts.map +1 -1
  146. package/dist/core/skills.js.map +1 -1
  147. package/dist/core/slash-commands.d.ts +1 -1
  148. package/dist/core/slash-commands.d.ts.map +1 -1
  149. package/dist/core/slash-commands.js.map +1 -1
  150. package/dist/core/source-info.d.ts +1 -1
  151. package/dist/core/source-info.d.ts.map +1 -1
  152. package/dist/core/source-info.js.map +1 -1
  153. package/dist/core/system-prompt.d.ts +1 -1
  154. package/dist/core/system-prompt.d.ts.map +1 -1
  155. package/dist/core/system-prompt.js +7 -8
  156. package/dist/core/system-prompt.js.map +1 -1
  157. package/dist/core/telemetry.d.ts +1 -1
  158. package/dist/core/telemetry.d.ts.map +1 -1
  159. package/dist/core/telemetry.js.map +1 -1
  160. package/dist/core/timings.d.ts.map +1 -1
  161. package/dist/core/timings.js.map +1 -1
  162. package/dist/core/tools/ask-user-question/ask-user-question.d.ts +4 -4
  163. package/dist/core/tools/ask-user-question/ask-user-question.d.ts.map +1 -1
  164. package/dist/core/tools/ask-user-question/ask-user-question.js.map +1 -1
  165. package/dist/core/tools/ask-user-question/index.d.ts +1 -1
  166. package/dist/core/tools/ask-user-question/index.d.ts.map +1 -1
  167. package/dist/core/tools/ask-user-question/index.js.map +1 -1
  168. package/dist/core/tools/ask-user-question/state/build-questionnaire.d.ts +5 -5
  169. package/dist/core/tools/ask-user-question/state/build-questionnaire.d.ts.map +1 -1
  170. package/dist/core/tools/ask-user-question/state/build-questionnaire.js.map +1 -1
  171. package/dist/core/tools/ask-user-question/state/key-router.d.ts +2 -2
  172. package/dist/core/tools/ask-user-question/state/key-router.d.ts.map +1 -1
  173. package/dist/core/tools/ask-user-question/state/key-router.js.map +1 -1
  174. package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts +3 -3
  175. package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts.map +1 -1
  176. package/dist/core/tools/ask-user-question/state/questionnaire-session.js.map +1 -1
  177. package/dist/core/tools/ask-user-question/state/row-intent.d.ts +2 -2
  178. package/dist/core/tools/ask-user-question/state/row-intent.d.ts.map +1 -1
  179. package/dist/core/tools/ask-user-question/state/row-intent.js.map +1 -1
  180. package/dist/core/tools/ask-user-question/state/selectors/contract.d.ts +6 -6
  181. package/dist/core/tools/ask-user-question/state/selectors/contract.d.ts.map +1 -1
  182. package/dist/core/tools/ask-user-question/state/selectors/contract.js.map +1 -1
  183. package/dist/core/tools/ask-user-question/state/selectors/derivations.d.ts +2 -2
  184. package/dist/core/tools/ask-user-question/state/selectors/derivations.d.ts.map +1 -1
  185. package/dist/core/tools/ask-user-question/state/selectors/derivations.js.map +1 -1
  186. package/dist/core/tools/ask-user-question/state/selectors/focus.d.ts +1 -1
  187. package/dist/core/tools/ask-user-question/state/selectors/focus.d.ts.map +1 -1
  188. package/dist/core/tools/ask-user-question/state/selectors/focus.js.map +1 -1
  189. package/dist/core/tools/ask-user-question/state/selectors/projections.d.ts +8 -8
  190. package/dist/core/tools/ask-user-question/state/selectors/projections.d.ts.map +1 -1
  191. package/dist/core/tools/ask-user-question/state/selectors/projections.js.map +1 -1
  192. package/dist/core/tools/ask-user-question/state/state-reducer.d.ts +4 -4
  193. package/dist/core/tools/ask-user-question/state/state-reducer.d.ts.map +1 -1
  194. package/dist/core/tools/ask-user-question/state/state-reducer.js.map +1 -1
  195. package/dist/core/tools/ask-user-question/state/state.d.ts +2 -2
  196. package/dist/core/tools/ask-user-question/state/state.d.ts.map +1 -1
  197. package/dist/core/tools/ask-user-question/state/state.js.map +1 -1
  198. package/dist/core/tools/ask-user-question/tool/format-answer.d.ts +1 -1
  199. package/dist/core/tools/ask-user-question/tool/format-answer.d.ts.map +1 -1
  200. package/dist/core/tools/ask-user-question/tool/format-answer.js.map +1 -1
  201. package/dist/core/tools/ask-user-question/tool/response-envelope.d.ts +1 -1
  202. package/dist/core/tools/ask-user-question/tool/response-envelope.d.ts.map +1 -1
  203. package/dist/core/tools/ask-user-question/tool/response-envelope.js.map +1 -1
  204. package/dist/core/tools/ask-user-question/tool/types.d.ts.map +1 -1
  205. package/dist/core/tools/ask-user-question/tool/types.js.map +1 -1
  206. package/dist/core/tools/ask-user-question/tool/validate-questionnaire.d.ts +1 -1
  207. package/dist/core/tools/ask-user-question/tool/validate-questionnaire.d.ts.map +1 -1
  208. package/dist/core/tools/ask-user-question/tool/validate-questionnaire.js.map +1 -1
  209. package/dist/core/tools/ask-user-question/view/body-residual-spacer.d.ts.map +1 -1
  210. package/dist/core/tools/ask-user-question/view/body-residual-spacer.js.map +1 -1
  211. package/dist/core/tools/ask-user-question/view/component-binding.d.ts +4 -4
  212. package/dist/core/tools/ask-user-question/view/component-binding.d.ts.map +1 -1
  213. package/dist/core/tools/ask-user-question/view/component-binding.js.map +1 -1
  214. package/dist/core/tools/ask-user-question/view/components/chat-row-view.d.ts +2 -2
  215. package/dist/core/tools/ask-user-question/view/components/chat-row-view.d.ts.map +1 -1
  216. package/dist/core/tools/ask-user-question/view/components/chat-row-view.js.map +1 -1
  217. package/dist/core/tools/ask-user-question/view/components/multi-select-view.d.ts +4 -4
  218. package/dist/core/tools/ask-user-question/view/components/multi-select-view.d.ts.map +1 -1
  219. package/dist/core/tools/ask-user-question/view/components/multi-select-view.js.map +1 -1
  220. package/dist/core/tools/ask-user-question/view/components/option-list-view.d.ts +2 -2
  221. package/dist/core/tools/ask-user-question/view/components/option-list-view.d.ts.map +1 -1
  222. package/dist/core/tools/ask-user-question/view/components/option-list-view.js.map +1 -1
  223. package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.d.ts +2 -2
  224. package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.d.ts.map +1 -1
  225. package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.js.map +1 -1
  226. package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.d.ts +3 -3
  227. package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.d.ts.map +1 -1
  228. package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.js.map +1 -1
  229. package/dist/core/tools/ask-user-question/view/components/preview/preview-layout-decider.d.ts +2 -2
  230. package/dist/core/tools/ask-user-question/view/components/preview/preview-layout-decider.d.ts.map +1 -1
  231. package/dist/core/tools/ask-user-question/view/components/preview/preview-layout-decider.js.map +1 -1
  232. package/dist/core/tools/ask-user-question/view/components/preview/preview-pane.d.ts +8 -8
  233. package/dist/core/tools/ask-user-question/view/components/preview/preview-pane.d.ts.map +1 -1
  234. package/dist/core/tools/ask-user-question/view/components/preview/preview-pane.js.map +1 -1
  235. package/dist/core/tools/ask-user-question/view/components/submit-picker.d.ts +3 -3
  236. package/dist/core/tools/ask-user-question/view/components/submit-picker.d.ts.map +1 -1
  237. package/dist/core/tools/ask-user-question/view/components/submit-picker.js.map +1 -1
  238. package/dist/core/tools/ask-user-question/view/components/tab-bar.d.ts +3 -3
  239. package/dist/core/tools/ask-user-question/view/components/tab-bar.d.ts.map +1 -1
  240. package/dist/core/tools/ask-user-question/view/components/tab-bar.js.map +1 -1
  241. package/dist/core/tools/ask-user-question/view/dialog-builder.d.ts +8 -8
  242. package/dist/core/tools/ask-user-question/view/dialog-builder.d.ts.map +1 -1
  243. package/dist/core/tools/ask-user-question/view/dialog-builder.js.map +1 -1
  244. package/dist/core/tools/ask-user-question/view/props-adapter.d.ts +5 -5
  245. package/dist/core/tools/ask-user-question/view/props-adapter.d.ts.map +1 -1
  246. package/dist/core/tools/ask-user-question/view/props-adapter.js.map +1 -1
  247. package/dist/core/tools/ask-user-question/view/tab-components.d.ts +4 -4
  248. package/dist/core/tools/ask-user-question/view/tab-components.d.ts.map +1 -1
  249. package/dist/core/tools/ask-user-question/view/tab-components.js.map +1 -1
  250. package/dist/core/tools/ask-user-question/view/tab-content-strategy.d.ts +9 -9
  251. package/dist/core/tools/ask-user-question/view/tab-content-strategy.d.ts.map +1 -1
  252. package/dist/core/tools/ask-user-question/view/tab-content-strategy.js +2 -2
  253. package/dist/core/tools/ask-user-question/view/tab-content-strategy.js.map +1 -1
  254. package/dist/core/tools/bash.d.ts +2 -2
  255. package/dist/core/tools/bash.d.ts.map +1 -1
  256. package/dist/core/tools/bash.js +9 -1
  257. package/dist/core/tools/bash.js.map +1 -1
  258. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  259. package/dist/core/tools/edit-diff.js.map +1 -1
  260. package/dist/core/tools/edit.d.ts +2 -2
  261. package/dist/core/tools/edit.d.ts.map +1 -1
  262. package/dist/core/tools/edit.js.map +1 -1
  263. package/dist/core/tools/find.d.ts +2 -2
  264. package/dist/core/tools/find.d.ts.map +1 -1
  265. package/dist/core/tools/find.js.map +1 -1
  266. package/dist/core/tools/grep.d.ts +2 -2
  267. package/dist/core/tools/grep.d.ts.map +1 -1
  268. package/dist/core/tools/grep.js.map +1 -1
  269. package/dist/core/tools/index.d.ts +19 -19
  270. package/dist/core/tools/index.d.ts.map +1 -1
  271. package/dist/core/tools/index.js.map +1 -1
  272. package/dist/core/tools/ls.d.ts +2 -2
  273. package/dist/core/tools/ls.d.ts.map +1 -1
  274. package/dist/core/tools/ls.js.map +1 -1
  275. package/dist/core/tools/output-accumulator.d.ts +1 -1
  276. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  277. package/dist/core/tools/output-accumulator.js.map +1 -1
  278. package/dist/core/tools/read.d.ts +2 -2
  279. package/dist/core/tools/read.d.ts.map +1 -1
  280. package/dist/core/tools/read.js.map +1 -1
  281. package/dist/core/tools/render-utils.d.ts +1 -1
  282. package/dist/core/tools/render-utils.d.ts.map +1 -1
  283. package/dist/core/tools/render-utils.js.map +1 -1
  284. package/dist/core/tools/todos.d.ts +1 -1
  285. package/dist/core/tools/todos.d.ts.map +1 -1
  286. package/dist/core/tools/todos.js.map +1 -1
  287. package/dist/core/tools/tool-definition-wrapper.d.ts +1 -1
  288. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  289. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  290. package/dist/core/tools/write.d.ts +1 -1
  291. package/dist/core/tools/write.d.ts.map +1 -1
  292. package/dist/core/tools/write.js.map +1 -1
  293. package/dist/index.d.ts +30 -29
  294. package/dist/index.d.ts.map +1 -1
  295. package/dist/index.js +1 -0
  296. package/dist/index.js.map +1 -1
  297. package/dist/main.d.ts +1 -1
  298. package/dist/main.d.ts.map +1 -1
  299. package/dist/main.js +2 -0
  300. package/dist/main.js.map +1 -1
  301. package/dist/migrations.d.ts.map +1 -1
  302. package/dist/migrations.js.map +1 -1
  303. package/dist/modes/index.d.ts +5 -5
  304. package/dist/modes/index.d.ts.map +1 -1
  305. package/dist/modes/index.js.map +1 -1
  306. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  307. package/dist/modes/interactive/components/armin.js.map +1 -1
  308. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  309. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  310. package/dist/modes/interactive/components/atomic-banner.d.ts +1 -1
  311. package/dist/modes/interactive/components/atomic-banner.d.ts.map +1 -1
  312. package/dist/modes/interactive/components/atomic-banner.js.map +1 -1
  313. package/dist/modes/interactive/components/bash-execution.d.ts +1 -1
  314. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  315. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  316. package/dist/modes/interactive/components/bordered-loader.d.ts +1 -1
  317. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  318. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  319. package/dist/modes/interactive/components/branch-summary-message.d.ts +1 -1
  320. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  321. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  322. package/dist/modes/interactive/components/chat-message-renderer.d.ts +3 -3
  323. package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
  324. package/dist/modes/interactive/components/chat-message-renderer.js +1 -1
  325. package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
  326. package/dist/modes/interactive/components/chat-transcript.d.ts.map +1 -1
  327. package/dist/modes/interactive/components/chat-transcript.js.map +1 -1
  328. package/dist/modes/interactive/components/compaction-summary-message.d.ts +1 -1
  329. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  330. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  331. package/dist/modes/interactive/components/config-selector.d.ts +2 -2
  332. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  333. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  334. package/dist/modes/interactive/components/countdown-timer.d.ts +2 -2
  335. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  336. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  337. package/dist/modes/interactive/components/custom-editor.d.ts +1 -1
  338. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  339. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  340. package/dist/modes/interactive/components/custom-message.d.ts +2 -2
  341. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  342. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  343. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  344. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  345. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  346. package/dist/modes/interactive/components/diff.js.map +1 -1
  347. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  348. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  349. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
  350. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
  351. package/dist/modes/interactive/components/extension-editor.d.ts +1 -1
  352. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  353. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  354. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  355. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  356. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  357. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  358. package/dist/modes/interactive/components/footer.d.ts +3 -3
  359. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  360. package/dist/modes/interactive/components/footer.js +1 -1
  361. package/dist/modes/interactive/components/footer.js.map +1 -1
  362. package/dist/modes/interactive/components/index.d.ts +34 -34
  363. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  364. package/dist/modes/interactive/components/index.js.map +1 -1
  365. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  366. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  367. package/dist/modes/interactive/components/login-dialog.d.ts +1 -1
  368. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  369. package/dist/modes/interactive/components/login-dialog.js +1 -1
  370. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  371. package/dist/modes/interactive/components/model-selector.d.ts +2 -2
  372. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  373. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  374. package/dist/modes/interactive/components/oauth-selector.d.ts +1 -1
  375. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  376. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  377. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  378. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  379. package/dist/modes/interactive/components/session-selector-search.d.ts +1 -1
  380. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  381. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  382. package/dist/modes/interactive/components/session-selector.d.ts +3 -3
  383. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  384. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  385. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  386. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  387. package/dist/modes/interactive/components/settings-selector.js +13 -0
  388. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  389. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  390. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  391. package/dist/modes/interactive/components/skill-invocation-message.d.ts +1 -1
  392. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  393. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  394. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  395. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  396. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  397. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  398. package/dist/modes/interactive/components/tool-execution.d.ts +1 -1
  399. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  400. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  401. package/dist/modes/interactive/components/tree-selector.d.ts +1 -1
  402. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  403. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  404. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  405. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  406. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  407. package/dist/modes/interactive/components/user-message.js.map +1 -1
  408. package/dist/modes/interactive/components/working-status.d.ts.map +1 -1
  409. package/dist/modes/interactive/components/working-status.js.map +1 -1
  410. package/dist/modes/interactive/interactive-mode.d.ts +2 -2
  411. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  412. package/dist/modes/interactive/interactive-mode.js +7 -1
  413. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  414. package/dist/modes/interactive/theme/theme.d.ts +1 -1
  415. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  416. package/dist/modes/interactive/theme/theme.js.map +1 -1
  417. package/dist/modes/print-mode.d.ts +1 -1
  418. package/dist/modes/print-mode.d.ts.map +1 -1
  419. package/dist/modes/print-mode.js.map +1 -1
  420. package/dist/modes/rpc/rpc-client.d.ts +5 -5
  421. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  422. package/dist/modes/rpc/rpc-client.js +1 -1
  423. package/dist/modes/rpc/rpc-client.js.map +1 -1
  424. package/dist/modes/rpc/rpc-mode.d.ts +2 -2
  425. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  426. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  427. package/dist/modes/rpc/rpc-types.d.ts +4 -4
  428. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  429. package/dist/modes/rpc/rpc-types.js.map +1 -1
  430. package/dist/package-manager-cli.d.ts.map +1 -1
  431. package/dist/package-manager-cli.js +22 -6
  432. package/dist/package-manager-cli.js.map +1 -1
  433. package/dist/utils/changelog.d.ts +1 -1
  434. package/dist/utils/changelog.d.ts.map +1 -1
  435. package/dist/utils/changelog.js.map +1 -1
  436. package/dist/utils/child-process.d.ts +5 -2
  437. package/dist/utils/child-process.d.ts.map +1 -1
  438. package/dist/utils/child-process.js +9 -7
  439. package/dist/utils/child-process.js.map +1 -1
  440. package/dist/utils/clipboard-image.d.ts.map +1 -1
  441. package/dist/utils/clipboard-image.js.map +1 -1
  442. package/dist/utils/clipboard.d.ts.map +1 -1
  443. package/dist/utils/clipboard.js.map +1 -1
  444. package/dist/utils/exif-orientation.d.ts +1 -1
  445. package/dist/utils/exif-orientation.d.ts.map +1 -1
  446. package/dist/utils/exif-orientation.js.map +1 -1
  447. package/dist/utils/image-convert.d.ts.map +1 -1
  448. package/dist/utils/image-convert.js.map +1 -1
  449. package/dist/utils/image-resize.d.ts.map +1 -1
  450. package/dist/utils/image-resize.js.map +1 -1
  451. package/dist/utils/shell.d.ts.map +1 -1
  452. package/dist/utils/shell.js.map +1 -1
  453. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  454. package/dist/utils/syntax-highlight.js.map +1 -1
  455. package/dist/utils/tools-manager.d.ts.map +1 -1
  456. package/dist/utils/tools-manager.js.map +1 -1
  457. package/dist/utils/version-check.d.ts.map +1 -1
  458. package/dist/utils/version-check.js.map +1 -1
  459. package/dist/utils/windows-self-update.d.ts +3 -0
  460. package/dist/utils/windows-self-update.d.ts.map +1 -0
  461. package/dist/utils/windows-self-update.js +78 -0
  462. package/dist/utils/windows-self-update.js.map +1 -0
  463. package/docs/compaction.md +5 -5
  464. package/docs/custom-provider.md +2 -2
  465. package/docs/development.md +22 -16
  466. package/docs/docs.json +6 -2
  467. package/docs/extensions.md +25 -25
  468. package/docs/index.md +11 -14
  469. package/docs/keybindings.md +5 -5
  470. package/docs/models.md +6 -6
  471. package/docs/packages.md +55 -48
  472. package/docs/prompt-templates.md +5 -5
  473. package/docs/providers.md +10 -10
  474. package/docs/quickstart.md +32 -30
  475. package/docs/rpc.md +9 -9
  476. package/docs/sdk.md +1 -1
  477. package/docs/session-format.md +3 -3
  478. package/docs/sessions.md +11 -11
  479. package/docs/settings.md +18 -15
  480. package/docs/shell-aliases.md +2 -2
  481. package/docs/skills.md +11 -11
  482. package/docs/terminal-setup.md +8 -8
  483. package/docs/termux.md +6 -6
  484. package/docs/themes.md +10 -10
  485. package/docs/tui.md +5 -4
  486. package/docs/usage.md +50 -50
  487. package/docs/windows.md +2 -2
  488. package/docs/workflows.md +695 -0
  489. package/examples/extensions/custom-provider-gitlab-duo/test.ts +1 -1
  490. package/examples/extensions/doom-overlay/doom-component.ts +2 -2
  491. package/examples/extensions/doom-overlay/index.ts +3 -3
  492. package/examples/extensions/overlay-qa-tests.ts +116 -33
  493. package/examples/extensions/overlay-test.ts +9 -3
  494. package/examples/extensions/plan-mode/index.ts +1 -1
  495. package/examples/extensions/subagent/index.ts +1159 -903
  496. package/package.json +6 -4
  497. package/dist/builtin/workflows/skills/workflow/SKILL.md +0 -322
  498. package/dist/builtin/workflows/skills/workflow/references/context-engineering/advanced-evaluation.md +0 -404
  499. package/dist/builtin/workflows/skills/workflow/references/context-engineering/bdi-mental-states.md +0 -313
  500. package/dist/builtin/workflows/skills/workflow/references/context-engineering/context-compression.md +0 -274
  501. package/dist/builtin/workflows/skills/workflow/references/context-engineering/context-degradation.md +0 -208
  502. package/dist/builtin/workflows/skills/workflow/references/context-engineering/context-fundamentals.md +0 -203
  503. package/dist/builtin/workflows/skills/workflow/references/context-engineering/context-optimization.md +0 -197
  504. package/dist/builtin/workflows/skills/workflow/references/context-engineering/evaluation.md +0 -253
  505. package/dist/builtin/workflows/skills/workflow/references/context-engineering/filesystem-context.md +0 -289
  506. package/dist/builtin/workflows/skills/workflow/references/context-engineering/hosted-agents.md +0 -262
  507. package/dist/builtin/workflows/skills/workflow/references/context-engineering/memory-systems.md +0 -221
  508. package/dist/builtin/workflows/skills/workflow/references/context-engineering/multi-agent-patterns.md +0 -259
  509. package/dist/builtin/workflows/skills/workflow/references/context-engineering/project-development.md +0 -293
  510. package/dist/builtin/workflows/skills/workflow/references/context-engineering/tool-design.md +0 -273
  511. package/dist/builtin/workflows/skills/workflow/references/context-engineering.md +0 -23
  512. package/dist/builtin/workflows/skills/workflow/references/design-checklist.md +0 -83
  513. package/dist/builtin/workflows/skills/workflow/references/running-workflows.md +0 -159
  514. package/dist/builtin/workflows/skills/workflow/references/sdk-authoring.md +0 -260
@@ -30,11 +30,7 @@ import {
30
30
  formatToolCall,
31
31
  shortenPath,
32
32
  } from "../shared/formatters.ts";
33
- import {
34
- getDisplayItems,
35
- getLastActivity,
36
- getSingleResultOutput,
37
- } from "../shared/utils.ts";
33
+ import { getDisplayItems, getSingleResultOutput } from "../shared/utils.ts";
38
34
  import { flatToLogicalStepIndex } from "../runs/background/parallel-groups.ts";
39
35
  import {
40
36
  aggregateStepStatus,
@@ -45,6 +41,14 @@ import {
45
41
 
46
42
  type Theme = ExtensionContext["ui"]["theme"];
47
43
 
44
+ type RenderRequestingContext = ExtensionContext & {
45
+ ui: ExtensionContext["ui"] & { requestRender?: () => void };
46
+ };
47
+
48
+ function requestRender(ctx: ExtensionContext): void {
49
+ (ctx as RenderRequestingContext).ui.requestRender?.();
50
+ }
51
+
48
52
  function getTermWidth(): number {
49
53
  return process.stdout.columns || 120;
50
54
  }
@@ -107,9 +111,12 @@ function truncLine(text: string, maxWidth: number): string {
107
111
  return result + activeStyles.join("") + "…";
108
112
  }
109
113
 
110
- const SPINNER = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
111
- const WIDGET_ANIMATION_MS = 80;
114
+ const RUNNING_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
115
+ const STATIC_RUNNING_GLYPH = "●";
116
+ const RUNNING_ANIMATION_MS = 80;
117
+ const STALE_EXTENSION_CONTEXT_MESSAGE = "This extension ctx is stale after session replacement or reload";
112
118
 
119
+ let runningAnimationFrame = 0;
113
120
  let widgetTimer: ReturnType<typeof setInterval> | undefined;
114
121
  let latestWidgetCtx: ExtensionContext | undefined;
115
122
  let latestWidgetJobs: AsyncJobState[] = [];
@@ -118,40 +125,71 @@ const resultAnimationTimers = new Map<
118
125
  ReturnType<typeof setInterval>,
119
126
  ResultAnimationContext["state"]
120
127
  >();
121
- const outputActivityCache = new Map<
122
- string,
123
- { checkedAt: number; text: string }
124
- >();
125
- const STALE_EXTENSION_CONTEXT_MESSAGE =
126
- "This extension ctx is stale after session replacement or reload";
128
+
129
+ type ProgressSeedSource = Partial<
130
+ Pick<
131
+ AgentProgress,
132
+ | "index"
133
+ | "toolCount"
134
+ | "tokens"
135
+ | "durationMs"
136
+ | "lastActivityAt"
137
+ | "currentToolStartedAt"
138
+ | "turnCount"
139
+ >
140
+ >;
141
+
142
+ function runningSeed(...values: Array<number | undefined>): number | undefined {
143
+ let seed: number | undefined;
144
+ for (const value of values) {
145
+ if (value === undefined || !Number.isFinite(value)) continue;
146
+ seed = (seed ?? 0) + Math.trunc(value);
147
+ }
148
+ return seed;
149
+ }
150
+
151
+ function runningGlyph(seed?: number): string {
152
+ const animatedSeed = runningSeed(seed, runningAnimationFrame);
153
+ if (animatedSeed === undefined) return STATIC_RUNNING_GLYPH;
154
+ return RUNNING_FRAMES[Math.abs(animatedSeed) % RUNNING_FRAMES.length]!;
155
+ }
156
+
157
+ function progressRunningSeed(
158
+ progress: ProgressSeedSource | undefined,
159
+ ): number | undefined {
160
+ if (!progress) return undefined;
161
+ return runningSeed(
162
+ progress.index,
163
+ progress.toolCount,
164
+ progress.tokens,
165
+ progress.durationMs,
166
+ progress.lastActivityAt,
167
+ progress.currentToolStartedAt,
168
+ progress.turnCount,
169
+ );
170
+ }
127
171
 
128
172
  interface ResultAnimationContext {
129
173
  state: { subagentResultAnimationTimer?: ReturnType<typeof setInterval> };
130
174
  invalidate: () => void;
131
175
  }
132
176
 
133
- function spinnerFrame(): string {
134
- return SPINNER[
135
- Math.floor(Date.now() / WIDGET_ANIMATION_MS) % SPINNER.length
136
- ]!;
177
+ interface LegacyResultAnimationContext {
178
+ state: { subagentResultAnimationTimer?: ReturnType<typeof setInterval> };
137
179
  }
138
180
 
139
181
  function isStaleExtensionContextError(error: unknown): boolean {
140
- if (!(error instanceof Error)) return false;
141
- return error.message.includes(STALE_EXTENSION_CONTEXT_MESSAGE);
182
+ return error instanceof Error && error.message.includes(STALE_EXTENSION_CONTEXT_MESSAGE);
142
183
  }
143
184
 
144
185
  function resultIsRunning(result: AgentToolResult<Details>): boolean {
145
- return (
186
+ return Boolean(
146
187
  result.details?.progress?.some((entry) => entry.status === "running") ||
147
- result.details?.results.some(
148
- (entry) => entry.progress?.status === "running",
149
- ) ||
150
- false
188
+ result.details?.results.some((entry) => entry.progress?.status === "running"),
151
189
  );
152
190
  }
153
191
 
154
- function stopResultAnimation(context: ResultAnimationContext): void {
192
+ function stopResultAnimation(context: LegacyResultAnimationContext): void {
155
193
  const timer = context.state.subagentResultAnimationTimer;
156
194
  if (!timer) return;
157
195
  clearInterval(timer);
@@ -159,6 +197,12 @@ function stopResultAnimation(context: ResultAnimationContext): void {
159
197
  context.state.subagentResultAnimationTimer = undefined;
160
198
  }
161
199
 
200
+ export function clearLegacyResultAnimationTimer(
201
+ context: LegacyResultAnimationContext,
202
+ ): void {
203
+ stopResultAnimation(context);
204
+ }
205
+
162
206
  export function syncResultAnimation(
163
207
  result: AgentToolResult<Details>,
164
208
  context: ResultAnimationContext,
@@ -169,18 +213,27 @@ export function syncResultAnimation(
169
213
  }
170
214
  if (context.state.subagentResultAnimationTimer) return;
171
215
  const timer = setInterval(() => {
216
+ runningAnimationFrame = (runningAnimationFrame + 1) % RUNNING_FRAMES.length;
172
217
  try {
173
218
  context.invalidate();
174
219
  } catch (error) {
175
220
  if (!isStaleExtensionContextError(error)) throw error;
176
221
  stopResultAnimation(context);
177
222
  }
178
- }, WIDGET_ANIMATION_MS);
223
+ }, RUNNING_ANIMATION_MS);
179
224
  timer.unref?.();
180
225
  context.state.subagentResultAnimationTimer = timer;
181
226
  resultAnimationTimers.set(timer, context.state);
182
227
  }
183
228
 
229
+ export function stopResultAnimations(): void {
230
+ for (const [timer, state] of resultAnimationTimers) {
231
+ clearInterval(timer);
232
+ state.subagentResultAnimationTimer = undefined;
233
+ }
234
+ resultAnimationTimers.clear();
235
+ }
236
+
184
237
  function extractOutputTarget(task: string): string | undefined {
185
238
  const writeToMatch = task.match(/\[Write to:\s*([^\]\n]+)\]/i);
186
239
  if (writeToMatch?.[1]?.trim()) return writeToMatch[1].trim();
@@ -223,6 +276,20 @@ function getToolCallLines(
223
276
  );
224
277
  }
225
278
 
279
+ function snapshotNowForProgress(
280
+ progress: Pick<
281
+ AgentProgress,
282
+ "currentToolStartedAt" | "durationMs" | "lastActivityAt"
283
+ >,
284
+ ): number | undefined {
285
+ if (
286
+ progress.currentToolStartedAt !== undefined &&
287
+ progress.durationMs !== undefined
288
+ )
289
+ return progress.currentToolStartedAt + progress.durationMs;
290
+ return progress.lastActivityAt;
291
+ }
292
+
226
293
  function formatCurrentToolLine(
227
294
  progress: Pick<
228
295
  AgentProgress,
@@ -230,6 +297,7 @@ function formatCurrentToolLine(
230
297
  >,
231
298
  availableWidth: number,
232
299
  expanded: boolean,
300
+ snapshotNow?: number,
233
301
  ): string | undefined {
234
302
  if (!progress.currentTool) return undefined;
235
303
  const maxToolArgsLen = Math.max(50, availableWidth - 20);
@@ -239,8 +307,8 @@ function formatCurrentToolLine(
239
307
  : `${progress.currentToolArgs.slice(0, maxToolArgsLen)}...`
240
308
  : "";
241
309
  const durationSuffix =
242
- progress.currentToolStartedAt !== undefined
243
- ? ` | ${formatDuration(Math.max(0, Date.now() - progress.currentToolStartedAt))}`
310
+ progress.currentToolStartedAt !== undefined && snapshotNow !== undefined
311
+ ? ` | ${formatDuration(Math.max(0, snapshotNow - progress.currentToolStartedAt))}`
244
312
  : "";
245
313
  return toolArgsPreview
246
314
  ? `${progress.currentTool}: ${toolArgsPreview}${durationSuffix}`
@@ -249,8 +317,19 @@ function formatCurrentToolLine(
249
317
 
250
318
  function buildLiveStatusLine(
251
319
  progress: Pick<AgentProgress, "activityState" | "lastActivityAt">,
320
+ snapshotNow?: number,
252
321
  ): string | undefined {
253
- return formatActivityLabel(progress.lastActivityAt, progress.activityState);
322
+ if (progress.lastActivityAt !== undefined && snapshotNow !== undefined)
323
+ return formatActivityLabel(
324
+ progress.lastActivityAt,
325
+ progress.activityState,
326
+ snapshotNow,
327
+ );
328
+ if (progress.activityState === "needs_attention") return "needs attention";
329
+ if (progress.activityState === "active_long_running")
330
+ return "active but long-running";
331
+ if (progress.lastActivityAt !== undefined) return "active";
332
+ return undefined;
254
333
  }
255
334
 
256
335
  function themeBold(theme: Theme, text: string): string {
@@ -318,8 +397,9 @@ function resultGlyph(
318
397
  output: string,
319
398
  theme: Theme,
320
399
  running = result.progress?.status === "running",
400
+ seed = progressRunningSeed(result.progress ?? result.progressSummary),
321
401
  ): string {
322
- if (running) return theme.fg("accent", spinnerFrame());
402
+ if (running) return theme.fg("accent", runningGlyph(seed));
323
403
  if (result.detached) return theme.fg("warning", "■");
324
404
  if (result.interrupted) return theme.fg("warning", "■");
325
405
  if (result.exitCode !== 0) return theme.fg("error", "✗");
@@ -329,15 +409,39 @@ function resultGlyph(
329
409
  }
330
410
 
331
411
  function compactCurrentActivity(progress: AgentProgress): string {
412
+ const snapshotNow = snapshotNowForProgress(progress);
332
413
  return (
333
- formatCurrentToolLine(progress, getTermWidth() - 4, false) ??
334
- buildLiveStatusLine(progress) ??
414
+ formatCurrentToolLine(progress, getTermWidth() - 4, false, snapshotNow) ??
415
+ buildLiveStatusLine(progress, snapshotNow) ??
335
416
  "thinking…"
336
417
  );
337
418
  }
338
419
 
339
- function hasAnimatedWidgetJobs(jobs: AsyncJobState[]): boolean {
340
- return jobs.some((job) => job.status === "running");
420
+ export function widgetRenderKey(job: AsyncJobState): string {
421
+ return JSON.stringify({
422
+ asyncDir: job.asyncDir,
423
+ status: job.status,
424
+ activityState: job.activityState,
425
+ lastActivityAt: job.lastActivityAt,
426
+ currentTool: job.currentTool,
427
+ currentToolStartedAt: job.currentToolStartedAt,
428
+ currentPath: job.currentPath,
429
+ turnCount: job.turnCount,
430
+ toolCount: job.toolCount,
431
+ mode: job.mode,
432
+ agents: job.agents,
433
+ currentStep: job.currentStep,
434
+ chainStepCount: job.chainStepCount,
435
+ parallelGroups: job.parallelGroups,
436
+ steps: job.steps,
437
+ stepsTotal: job.stepsTotal,
438
+ runningSteps: job.runningSteps,
439
+ completedSteps: job.completedSteps,
440
+ activeParallelGroup: job.activeParallelGroup,
441
+ startedAt: job.startedAt,
442
+ updatedAt: job.updatedAt,
443
+ totalTokens: job.totalTokens,
444
+ });
341
445
  }
342
446
 
343
447
  function formatWidgetAgents(agents: string[]): string {
@@ -357,29 +461,21 @@ function widgetJobName(job: AsyncJobState): string {
357
461
  return job.mode ?? "subagent";
358
462
  }
359
463
 
360
- function getCachedLastActivity(outputFile: string | undefined): string {
361
- if (!outputFile) return "";
362
- const now = Date.now();
363
- const cached = outputActivityCache.get(outputFile);
364
- if (cached && now - cached.checkedAt < 1000) return cached.text;
365
- const text = getLastActivity(outputFile);
366
- outputActivityCache.set(outputFile, { checkedAt: now, text });
367
- return text;
368
- }
369
-
370
464
  function widgetActivity(job: AsyncJobState): string {
371
465
  const facts: string[] = [];
372
- if (job.currentTool && job.currentToolStartedAt !== undefined)
466
+ if (
467
+ job.currentTool &&
468
+ job.currentToolStartedAt !== undefined &&
469
+ job.updatedAt !== undefined
470
+ )
373
471
  facts.push(
374
- `${job.currentTool} ${formatDuration(Math.max(0, Date.now() - job.currentToolStartedAt))}`,
472
+ `${job.currentTool} ${formatDuration(Math.max(0, job.updatedAt - job.currentToolStartedAt))}`,
375
473
  );
376
474
  else if (job.currentTool) facts.push(job.currentTool);
377
475
  if (job.currentPath) facts.push(shortenPath(job.currentPath));
378
476
  if (job.turnCount !== undefined) facts.push(`${job.turnCount} turns`);
379
477
  if (job.toolCount !== undefined) facts.push(`${job.toolCount} tools`);
380
- const activity =
381
- formatActivityLabel(job.lastActivityAt, job.activityState) ??
382
- (job.status === "running" ? getCachedLastActivity(job.outputFile) : "");
478
+ const activity = buildLiveStatusLine(job, job.updatedAt);
383
479
  if (activity && facts.length) return `${activity} · ${facts.join(" · ")}`;
384
480
  if (activity) return activity;
385
481
  if (facts.length) return facts.join(" · ");
@@ -390,16 +486,66 @@ function widgetActivity(job: AsyncJobState): string {
390
486
  return "Done";
391
487
  }
392
488
 
489
+ function widgetStepRunningSeed(
490
+ step: NonNullable<AsyncJobState["steps"]>[number],
491
+ fallbackIndex?: number,
492
+ ): number | undefined {
493
+ return runningSeed(
494
+ fallbackIndex,
495
+ step.index,
496
+ step.toolCount,
497
+ step.turnCount,
498
+ step.tokens?.total,
499
+ step.lastActivityAt,
500
+ step.currentToolStartedAt,
501
+ step.durationMs,
502
+ );
503
+ }
504
+
505
+ function widgetStepsRunningSeed(
506
+ steps: Array<NonNullable<AsyncJobState["steps"]>[number]> | undefined,
507
+ ): number | undefined {
508
+ let seed: number | undefined;
509
+ for (const [index, step] of (steps ?? []).entries())
510
+ seed = runningSeed(seed, widgetStepRunningSeed(step, index));
511
+ return seed;
512
+ }
513
+
514
+ function widgetJobRunningSeed(job: AsyncJobState): number | undefined {
515
+ return runningSeed(
516
+ job.updatedAt,
517
+ job.lastActivityAt,
518
+ job.toolCount,
519
+ job.turnCount,
520
+ job.totalTokens?.total,
521
+ job.currentStep,
522
+ job.runningSteps,
523
+ job.completedSteps,
524
+ widgetStepsRunningSeed(job.steps),
525
+ );
526
+ }
527
+
528
+ function widgetJobsRunningSeed(jobs: AsyncJobState[]): number | undefined {
529
+ let seed: number | undefined;
530
+ for (const job of jobs) seed = runningSeed(seed, widgetJobRunningSeed(job));
531
+ return seed;
532
+ }
533
+
393
534
  function widgetStatusGlyph(job: AsyncJobState, theme: Theme): string {
394
- if (job.status === "running") return theme.fg("accent", spinnerFrame());
535
+ if (job.status === "running")
536
+ return theme.fg("accent", runningGlyph(widgetJobRunningSeed(job)));
395
537
  if (job.status === "queued") return theme.fg("muted", "◦");
396
538
  if (job.status === "complete") return theme.fg("success", "✓");
397
539
  if (job.status === "paused") return theme.fg("warning", "■");
398
540
  return theme.fg("error", "✗");
399
541
  }
400
542
 
401
- function widgetStepGlyph(status: AsyncJobStep["status"], theme: Theme): string {
402
- if (status === "running") return theme.fg("accent", spinnerFrame());
543
+ function widgetStepGlyph(
544
+ status: AsyncJobStep["status"],
545
+ theme: Theme,
546
+ seed?: number,
547
+ ): string {
548
+ if (status === "running") return theme.fg("accent", runningGlyph(seed));
403
549
  if (status === "complete" || status === "completed")
404
550
  return theme.fg("success", "✓");
405
551
  if (status === "failed") return theme.fg("error", "✗");
@@ -421,18 +567,23 @@ function widgetStepStatus(
421
567
 
422
568
  function widgetStepActivity(
423
569
  step: NonNullable<AsyncJobState["steps"]>[number],
570
+ snapshotNow?: number,
424
571
  ): string {
425
572
  const facts: string[] = [];
426
- if (step.currentTool && step.currentToolStartedAt !== undefined)
573
+ if (
574
+ step.currentTool &&
575
+ step.currentToolStartedAt !== undefined &&
576
+ snapshotNow !== undefined
577
+ )
427
578
  facts.push(
428
- `${step.currentTool} ${formatDuration(Math.max(0, Date.now() - step.currentToolStartedAt))}`,
579
+ `${step.currentTool} ${formatDuration(Math.max(0, snapshotNow - step.currentToolStartedAt))}`,
429
580
  );
430
581
  else if (step.currentTool) facts.push(step.currentTool);
431
582
  if (step.currentPath) facts.push(shortenPath(step.currentPath));
432
583
  if (step.turnCount !== undefined) facts.push(`${step.turnCount} turns`);
433
584
  if (step.toolCount !== undefined) facts.push(`${step.toolCount} tools`);
434
585
  if (step.tokens?.total) facts.push(formatTokenStat(step.tokens.total));
435
- const activity = formatActivityLabel(step.lastActivityAt, step.activityState);
586
+ const activity = buildLiveStatusLine(step, snapshotNow);
436
587
  if (activity && facts.length) return `${activity} · ${facts.join(" · ")}`;
437
588
  if (activity) return activity;
438
589
  return facts.join(" · ");
@@ -456,7 +607,7 @@ function widgetChainDetails(
456
607
  if (span.isParallel) {
457
608
  const status = aggregateStepStatus(steps);
458
609
  lines.push(
459
- ` ${widgetStepGlyph(status, theme)} Step ${span.stepIndex + 1}/${total}: ${themeBold(theme, "parallel group")} ${theme.fg("dim", "·")} ${theme.fg("dim", formatParallelOutcome(steps, span.count))}`,
610
+ ` ${widgetStepGlyph(status, theme, widgetStepsRunningSeed(steps))} Step ${span.stepIndex + 1}/${total}: ${themeBold(theme, "parallel group")} ${theme.fg("dim", "·")} ${theme.fg("dim", formatParallelOutcome(steps, span.count))}`,
460
611
  );
461
612
  continue;
462
613
  }
@@ -498,11 +649,11 @@ function widgetParallelAgentDetails(
498
649
  const total = job.stepsTotal ?? job.steps.length;
499
650
  return job.steps.map((step, index) => {
500
651
  const marker = index === job.steps!.length - 1 ? "└" : "├";
501
- const activity = widgetStepActivity(step);
652
+ const activity = widgetStepActivity(step, job.updatedAt);
502
653
  const itemTitle =
503
654
  job.mode === "parallel" || job.activeParallelGroup ? "Agent" : "Step";
504
655
  const modelDisplay = modelThinkingBadge(theme, step.model, step.thinking);
505
- return ` ${theme.fg("dim", `${marker} ${widgetStepGlyph(step.status, theme)} ${itemTitle} ${index + 1}/${total}: ${step.agent} · ${widgetStepStatus(step.status, theme)}${modelDisplay}${activity ? ` · ${activity}` : ""}`)}`;
656
+ return ` ${theme.fg("dim", `${marker} ${widgetStepGlyph(step.status, theme, widgetStepRunningSeed(step, index))} ${itemTitle} ${index + 1}/${total}: ${step.agent} · ${widgetStepStatus(step.status, theme)}${modelDisplay}${activity ? ` · ${activity}` : ""}`)}`;
506
657
  });
507
658
  }
508
659
 
@@ -843,14 +994,8 @@ function widgetStats(job: AsyncJobState, theme: Theme): string {
843
994
  if (job.toolCount !== undefined) parts.push(formatToolUseStat(job.toolCount));
844
995
  if (job.totalTokens?.total)
845
996
  parts.push(formatTokenStat(job.totalTokens.total));
846
- const endTime =
847
- job.status === "complete" ||
848
- job.status === "failed" ||
849
- job.status === "paused"
850
- ? (job.updatedAt ?? Date.now())
851
- : Date.now();
852
- if (job.startedAt)
853
- parts.push(formatDuration(Math.max(0, endTime - job.startedAt)));
997
+ if (job.startedAt !== undefined && job.updatedAt !== undefined)
998
+ parts.push(formatDuration(Math.max(0, job.updatedAt - job.startedAt)));
854
999
  return statJoin(theme, parts);
855
1000
  }
856
1001
 
@@ -879,10 +1024,11 @@ function widgetStepActivityLine(
879
1024
  step: NonNullable<AsyncJobState["steps"]>[number],
880
1025
  width: number,
881
1026
  expanded: boolean,
1027
+ snapshotNow?: number,
882
1028
  ): string {
883
- const toolLine = formatCurrentToolLine(step, width, expanded);
1029
+ const toolLine = formatCurrentToolLine(step, width, expanded, snapshotNow);
884
1030
  if (toolLine) return toolLine;
885
- const activity = formatActivityLabel(step.lastActivityAt, step.activityState);
1031
+ const activity = buildLiveStatusLine(step, snapshotNow);
886
1032
  if (activity) return activity;
887
1033
  if (step.status === "running") return "thinking…";
888
1034
  return "";
@@ -910,9 +1056,9 @@ function foregroundStyleWidgetStepLines(
910
1056
  const stats = widgetStepStats(theme, step);
911
1057
  const modelDisplay = modelThinkingBadge(theme, step.model, step.thinking);
912
1058
  const lines = [
913
- ` ${widgetStepGlyph(step.status, theme)} ${itemTitle} ${index}/${total}: ${themeBold(theme, step.agent)} ${theme.fg("dim", "·")} ${status}${modelDisplay}${stats ? ` ${theme.fg("dim", "·")} ${stats}` : ""}`,
1059
+ ` ${widgetStepGlyph(step.status, theme, widgetStepRunningSeed(step, index - 1))} ${itemTitle} ${index}/${total}: ${themeBold(theme, step.agent)} ${theme.fg("dim", "·")} ${status}${modelDisplay}${stats ? ` ${theme.fg("dim", "·")} ${stats}` : ""}`,
914
1060
  ];
915
- const activity = widgetStepActivityLine(step, width, expanded);
1061
+ const activity = widgetStepActivityLine(step, width, expanded, job.updatedAt);
916
1062
  if (activity) lines.push(` ${theme.fg("dim", `⎿ ${activity}`)}`);
917
1063
  if (step.status === "running") {
918
1064
  if (!expanded)
@@ -921,7 +1067,7 @@ function foregroundStyleWidgetStepLines(
921
1067
  if (output)
922
1068
  lines.push(` ${theme.fg("dim", `output: ${shortenPath(output)}`)}`);
923
1069
  if (expanded) {
924
- const liveStatus = buildLiveStatusLine(step);
1070
+ const liveStatus = buildLiveStatusLine(step, job.updatedAt);
925
1071
  if (liveStatus && liveStatus !== activity)
926
1072
  lines.push(` ${theme.fg("accent", liveStatus)}`);
927
1073
  for (const tool of step.recentTools?.slice(-3) ?? []) {
@@ -1016,14 +1162,14 @@ function compactSingleWidgetLines(
1016
1162
  const lines = fullLines.slice(0, 2);
1017
1163
  for (const [index, step] of job.steps.entries()) {
1018
1164
  const status = widgetStepStatus(step.status, theme);
1019
- const activity = widgetStepActivityLine(step, width, false);
1165
+ const activity = widgetStepActivityLine(step, width, false, job.updatedAt);
1020
1166
  const stepStats = widgetStepStats(theme, step);
1021
1167
  const activitySuffix = activity
1022
1168
  ? ` ${theme.fg("dim", "·")} ${theme.fg("dim", activity)}`
1023
1169
  : "";
1024
1170
  const modelDisplay = modelThinkingBadge(theme, step.model, step.thinking);
1025
1171
  lines.push(
1026
- ` ${widgetStepGlyph(step.status, theme)} ${itemTitle} ${index + 1}/${total}: ${themeBold(theme, step.agent)} ${theme.fg("dim", "·")} ${status}${modelDisplay}${activitySuffix}${stepStats ? ` ${theme.fg("dim", "·")} ${stepStats}` : ""}`,
1172
+ ` ${widgetStepGlyph(step.status, theme, widgetStepRunningSeed(step, index))} ${itemTitle} ${index + 1}/${total}: ${themeBold(theme, step.agent)} ${theme.fg("dim", "·")} ${status}${modelDisplay}${activitySuffix}${stepStats ? ` ${theme.fg("dim", "·")} ${stepStats}` : ""}`,
1027
1173
  );
1028
1174
  }
1029
1175
  if (job.steps.some((step) => step.status === "running"))
@@ -1046,29 +1192,78 @@ function fitWidgetLineBudget(
1046
1192
  const hiddenCount = lines.length - visibleLines;
1047
1193
  const hint = expanded
1048
1194
  ? `… ${hiddenCount} live-detail lines hidden`
1049
- : `… ${hiddenCount} lines hidden · Ctrl+O expands`;
1195
+ : `… ${hiddenCount} lines hidden · ctrl+o expands`;
1050
1196
  return [
1051
1197
  ...lines.slice(0, visibleLines),
1052
1198
  truncLine(theme.fg("dim", hint), width),
1053
1199
  ];
1054
1200
  }
1055
1201
 
1056
- function buildWidgetComponent(
1057
- jobs: AsyncJobState[],
1058
- expanded: boolean,
1059
- ): (_tui: unknown, theme: Theme) => Component {
1060
- return (_tui, theme) => {
1061
- const width = getTermWidth();
1202
+ class LiveWidgetComponent implements Component {
1203
+ constructor(
1204
+ private readonly jobs: AsyncJobState[],
1205
+ private readonly theme: Theme,
1206
+ private readonly getExpanded: () => boolean,
1207
+ ) {}
1208
+
1209
+ render(width: number): string[] {
1210
+ const termWidth = Math.min(width, getTermWidth());
1211
+ const expanded = this.getExpanded();
1062
1212
  const lines = expanded
1063
- ? buildWidgetLines(jobs, theme, width, true)
1064
- : jobs.length === 1
1065
- ? compactSingleWidgetLines(jobs[0]!, theme, width)
1066
- : buildWidgetLines(jobs, theme, width, false);
1213
+ ? buildWidgetLines(this.jobs, this.theme, termWidth, true)
1214
+ : this.jobs.length === 1
1215
+ ? compactSingleWidgetLines(this.jobs[0]!, this.theme, termWidth)
1216
+ : buildWidgetLines(this.jobs, this.theme, termWidth, false);
1067
1217
  const container = new Container();
1068
- for (const line of fitWidgetLineBudget(lines, theme, width, expanded))
1218
+ for (const line of fitWidgetLineBudget(lines, this.theme, termWidth, expanded))
1069
1219
  container.addChild(new Text(line, 1, 0));
1070
- return container;
1071
- };
1220
+ return container.render(termWidth);
1221
+ }
1222
+
1223
+ invalidate(): void {}
1224
+ }
1225
+
1226
+ function buildWidgetComponent(
1227
+ jobs: AsyncJobState[],
1228
+ getExpanded: () => boolean,
1229
+ ): (_tui: unknown, theme: Theme) => Component {
1230
+ return (_tui, theme) => new LiveWidgetComponent(jobs, theme, getExpanded);
1231
+ }
1232
+
1233
+ function hasAnimatedWidgetJobs(jobs: AsyncJobState[]): boolean {
1234
+ return jobs.some((job) => job.status === "running");
1235
+ }
1236
+
1237
+ function refreshAnimatedWidget(): void {
1238
+ if (!latestWidgetCtx?.hasUI) return;
1239
+ runningAnimationFrame = (runningAnimationFrame + 1) % RUNNING_FRAMES.length;
1240
+ try {
1241
+ requestRender(latestWidgetCtx);
1242
+ } catch (error) {
1243
+ if (!isStaleExtensionContextError(error)) throw error;
1244
+ stopWidgetAnimation();
1245
+ }
1246
+ }
1247
+
1248
+ function ensureWidgetAnimation(): void {
1249
+ if (widgetTimer) return;
1250
+ widgetTimer = setInterval(() => {
1251
+ if (!hasAnimatedWidgetJobs(latestWidgetJobs)) {
1252
+ stopWidgetAnimation();
1253
+ return;
1254
+ }
1255
+ refreshAnimatedWidget();
1256
+ }, RUNNING_ANIMATION_MS);
1257
+ widgetTimer.unref?.();
1258
+ }
1259
+
1260
+ export function stopWidgetAnimation(): void {
1261
+ if (widgetTimer) {
1262
+ clearInterval(widgetTimer);
1263
+ widgetTimer = undefined;
1264
+ }
1265
+ latestWidgetCtx = undefined;
1266
+ latestWidgetJobs = [];
1072
1267
  }
1073
1268
 
1074
1269
  export function buildWidgetLines(
@@ -1088,9 +1283,15 @@ export function buildWidgetLines(
1088
1283
 
1089
1284
  const lines: string[] = [];
1090
1285
  const hasActive = running.length > 0 || queued.length > 0;
1286
+ const headerGlyph =
1287
+ running.length > 0
1288
+ ? runningGlyph(widgetJobsRunningSeed(running))
1289
+ : hasActive
1290
+ ? "●"
1291
+ : "○";
1091
1292
  lines.push(
1092
1293
  truncLine(
1093
- `${theme.fg(hasActive ? "accent" : "dim", hasActive ? "●" : "○")} ${theme.fg(hasActive ? "accent" : "dim", "Async agents")} ${theme.fg("dim", "· background")}`,
1294
+ `${theme.fg(hasActive ? "accent" : "dim", headerGlyph)} ${theme.fg(hasActive ? "accent" : "dim", "Async agents")} ${theme.fg("dim", "· background")}`,
1094
1295
  width,
1095
1296
  ),
1096
1297
  );
@@ -1164,53 +1365,6 @@ export function buildWidgetLines(
1164
1365
  return lines;
1165
1366
  }
1166
1367
 
1167
- function refreshAnimatedWidget(): void {
1168
- try {
1169
- if (!latestWidgetCtx?.hasUI || latestWidgetJobs.length === 0) return;
1170
- latestWidgetCtx.ui.setWidget(
1171
- WIDGET_KEY,
1172
- buildWidgetComponent(
1173
- latestWidgetJobs,
1174
- latestWidgetCtx.ui.getToolsExpanded?.() ?? false,
1175
- ),
1176
- );
1177
- latestWidgetCtx.ui.requestRender?.();
1178
- } catch (error) {
1179
- if (!isStaleExtensionContextError(error)) throw error;
1180
- stopWidgetAnimation();
1181
- }
1182
- }
1183
-
1184
- function ensureWidgetAnimation(): void {
1185
- if (widgetTimer) return;
1186
- widgetTimer = setInterval(() => {
1187
- if (!hasAnimatedWidgetJobs(latestWidgetJobs)) {
1188
- stopWidgetAnimation();
1189
- return;
1190
- }
1191
- refreshAnimatedWidget();
1192
- }, WIDGET_ANIMATION_MS);
1193
- widgetTimer.unref?.();
1194
- }
1195
-
1196
- export function stopWidgetAnimation(): void {
1197
- if (widgetTimer) {
1198
- clearInterval(widgetTimer);
1199
- widgetTimer = undefined;
1200
- }
1201
- latestWidgetCtx = undefined;
1202
- latestWidgetJobs = [];
1203
- outputActivityCache.clear();
1204
- }
1205
-
1206
- export function stopResultAnimations(): void {
1207
- for (const [timer, state] of resultAnimationTimers) {
1208
- clearInterval(timer);
1209
- state.subagentResultAnimationTimer = undefined;
1210
- }
1211
- resultAnimationTimers.clear();
1212
- }
1213
-
1214
1368
  /**
1215
1369
  * Render the async jobs widget
1216
1370
  */
@@ -1229,10 +1383,9 @@ export function renderWidget(
1229
1383
  }
1230
1384
  latestWidgetCtx = ctx;
1231
1385
  latestWidgetJobs = [...jobs];
1232
-
1233
1386
  ctx.ui.setWidget(
1234
1387
  WIDGET_KEY,
1235
- buildWidgetComponent(jobs, ctx.ui.getToolsExpanded?.() ?? false),
1388
+ buildWidgetComponent(jobs, () => ctx.ui.getToolsExpanded?.() ?? false),
1236
1389
  );
1237
1390
  if (hasAnimatedWidgetJobs(jobs)) ensureWidgetAnimation();
1238
1391
  else stopWidgetAnimation();
@@ -1267,11 +1420,12 @@ function renderSingleCompact(
1267
1420
  );
1268
1421
 
1269
1422
  if (isRunning && r.progress) {
1423
+ const progressSnapshotNow = snapshotNowForProgress(r.progress);
1270
1424
  const activity = compactCurrentActivity(r.progress);
1271
1425
  c.addChild(
1272
1426
  new Text(truncLine(theme.fg("dim", ` ⎿ ${activity}`), width), 0, 0),
1273
1427
  );
1274
- const liveStatus = buildLiveStatusLine(r.progress);
1428
+ const liveStatus = buildLiveStatusLine(r.progress, progressSnapshotNow);
1275
1429
  if (liveStatus && liveStatus !== activity)
1276
1430
  c.addChild(
1277
1431
  new Text(truncLine(theme.fg("dim", ` ${liveStatus}`), width), 0, 0),
@@ -1393,7 +1547,12 @@ function renderMultiCompact(d: Details, theme: Theme): Component {
1393
1547
  formatProgressStats(theme, totalSummary),
1394
1548
  ]);
1395
1549
  const glyph = hasRunning
1396
- ? theme.fg("accent", spinnerFrame())
1550
+ ? theme.fg(
1551
+ "accent",
1552
+ runningGlyph(
1553
+ runningSeed(progressRunningSeed(totalSummary), d.currentStepIndex),
1554
+ ),
1555
+ )
1397
1556
  : failed
1398
1557
  ? theme.fg("error", "✗")
1399
1558
  : paused
@@ -1453,9 +1612,10 @@ function renderMultiCompact(d: Details, theme: Theme): Component {
1453
1612
  const progressFromArray =
1454
1613
  d.progress?.find((p) => p.index === i) ||
1455
1614
  d.progress?.find((p) => p.agent === r.agent && p.status === "running");
1456
- const rProg = r.progress || progressFromArray || r.progressSummary;
1457
- const rRunning = rProg && "status" in rProg && rProg.status === "running";
1458
- const rPending = rProg && "status" in rProg && rProg.status === "pending";
1615
+ const liveProgress = r.progress || progressFromArray;
1616
+ const rProg = liveProgress || r.progressSummary;
1617
+ const rRunning = liveProgress?.status === "running";
1618
+ const rPending = liveProgress?.status === "pending";
1459
1619
  const stepNumber =
1460
1620
  r.progress?.index !== undefined
1461
1621
  ? r.progress.index + 1
@@ -1465,13 +1625,13 @@ function renderMultiCompact(d: Details, theme: Theme): Component {
1465
1625
  const stepStats = formatProgressStats(theme, rProg);
1466
1626
  const glyph = rPending
1467
1627
  ? theme.fg("dim", "◦")
1468
- : resultGlyph(r, output, theme, rRunning);
1628
+ : resultGlyph(r, output, theme, rRunning, progressRunningSeed(rProg));
1469
1629
  const pendingLabel = rPending ? ` ${theme.fg("dim", "· pending")}` : "";
1470
1630
  const stepLabel = resultRowLabel(d, multiLabel, i, stepNumber);
1471
1631
  const line = `${glyph} ${stepLabel}: ${themeBold(theme, agentName)}${stepStats ? ` ${theme.fg("dim", "·")} ${stepStats}` : ""}${pendingLabel}`;
1472
1632
  c.addChild(new Text(truncLine(` ${line}`, width), 0, 0));
1473
- if (rRunning && rProg && "status" in rProg) {
1474
- const activity = compactCurrentActivity(rProg);
1633
+ if (rRunning && liveProgress) {
1634
+ const activity = compactCurrentActivity(liveProgress);
1475
1635
  c.addChild(
1476
1636
  new Text(truncLine(theme.fg("dim", ` ⎿ ${activity}`), width), 0, 0),
1477
1637
  );
@@ -1613,11 +1773,20 @@ export function renderSubagentResult(
1613
1773
  c.addChild(new Spacer(1));
1614
1774
 
1615
1775
  if (isRunning && r.progress) {
1616
- const toolLine = formatCurrentToolLine(r.progress, w, expanded);
1776
+ const progressSnapshotNow = snapshotNowForProgress(r.progress);
1777
+ const toolLine = formatCurrentToolLine(
1778
+ r.progress,
1779
+ w,
1780
+ expanded,
1781
+ progressSnapshotNow,
1782
+ );
1617
1783
  if (toolLine) {
1618
1784
  c.addChild(new Text(fit(theme.fg("warning", `> ${toolLine}`)), 0, 0));
1619
1785
  }
1620
- const liveStatusLine = buildLiveStatusLine(r.progress);
1786
+ const liveStatusLine = buildLiveStatusLine(
1787
+ r.progress,
1788
+ progressSnapshotNow,
1789
+ );
1621
1790
  if (liveStatusLine) {
1622
1791
  c.addChild(new Text(fit(theme.fg("accent", liveStatusLine)), 0, 0));
1623
1792
  }
@@ -1865,10 +2034,11 @@ export function renderSubagentResult(
1865
2034
  const progressFromArray =
1866
2035
  d.progress?.find((p) => p.index === i) ||
1867
2036
  d.progress?.find((p) => p.agent === r.agent && p.status === "running");
1868
- const rProg = r.progress || progressFromArray || r.progressSummary;
1869
- const rRunning = rProg?.status === "running";
2037
+ const liveProgress = r.progress || progressFromArray;
2038
+ const rProg = liveProgress || r.progressSummary;
2039
+ const rRunning = liveProgress?.status === "running";
1870
2040
  const stepNumber =
1871
- typeof rProg?.index === "number" ? rProg.index + 1 : i + 1;
2041
+ typeof liveProgress?.index === "number" ? liveProgress.index + 1 : i + 1;
1872
2042
 
1873
2043
  const resultOutput = getSingleResultOutput(r);
1874
2044
  const statusIcon = rRunning
@@ -1935,23 +2105,37 @@ export function renderSubagentResult(
1935
2105
  );
1936
2106
  }
1937
2107
 
1938
- if (rRunning && rProg) {
1939
- if (rProg.skills?.length) {
2108
+ if (rRunning && liveProgress) {
2109
+ if (liveProgress.skills?.length) {
1940
2110
  c.addChild(
1941
2111
  new Text(
1942
- fit(theme.fg("accent", ` skills: ${rProg.skills.join(", ")}`)),
2112
+ fit(
2113
+ theme.fg(
2114
+ "accent",
2115
+ ` skills: ${liveProgress.skills.join(", ")}`,
2116
+ ),
2117
+ ),
1943
2118
  0,
1944
2119
  0,
1945
2120
  ),
1946
2121
  );
1947
2122
  }
1948
- const toolLine = formatCurrentToolLine(rProg, w, expanded);
2123
+ const progressSnapshotNow = snapshotNowForProgress(liveProgress);
2124
+ const toolLine = formatCurrentToolLine(
2125
+ liveProgress,
2126
+ w,
2127
+ expanded,
2128
+ progressSnapshotNow,
2129
+ );
1949
2130
  if (toolLine) {
1950
2131
  c.addChild(
1951
2132
  new Text(fit(theme.fg("warning", ` > ${toolLine}`)), 0, 0),
1952
2133
  );
1953
2134
  }
1954
- const liveStatusLine = buildLiveStatusLine(rProg);
2135
+ const liveStatusLine = buildLiveStatusLine(
2136
+ liveProgress,
2137
+ progressSnapshotNow,
2138
+ );
1955
2139
  if (liveStatusLine) {
1956
2140
  c.addChild(
1957
2141
  new Text(fit(theme.fg("accent", ` ${liveStatusLine}`)), 0, 0),
@@ -1978,8 +2162,8 @@ export function renderSubagentResult(
1978
2162
  ),
1979
2163
  );
1980
2164
  }
1981
- if (rProg.recentTools?.length) {
1982
- for (const t of rProg.recentTools.slice(-3)) {
2165
+ if (liveProgress.recentTools?.length) {
2166
+ for (const t of liveProgress.recentTools.slice(-3)) {
1983
2167
  const maxArgsLen = Math.max(40, w - 30);
1984
2168
  const argsPreview =
1985
2169
  expanded || t.args.length <= maxArgsLen
@@ -1994,7 +2178,7 @@ export function renderSubagentResult(
1994
2178
  );
1995
2179
  }
1996
2180
  }
1997
- const recentLines = (rProg.recentOutput ?? []).slice(-5);
2181
+ const recentLines = (liveProgress.recentOutput ?? []).slice(-5);
1998
2182
  for (const line of recentLines) {
1999
2183
  c.addChild(new Text(fit(theme.fg("dim", ` ${line}`)), 0, 0));
2000
2184
  }