@bastani/atomic 0.8.27 → 0.8.28-alpha.2

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 (397) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/README.md +120 -118
  3. package/dist/builtin/intercom/package.json +1 -1
  4. package/dist/builtin/mcp/package.json +2 -2
  5. package/dist/builtin/subagents/package.json +1 -1
  6. package/dist/builtin/web-access/package.json +1 -1
  7. package/dist/builtin/workflows/CHANGELOG.md +22 -0
  8. package/dist/builtin/workflows/README.md +11 -9
  9. package/dist/builtin/workflows/builtin/open-claude-design.ts +150 -13
  10. package/dist/builtin/workflows/package.json +1 -1
  11. package/dist/builtin/workflows/src/authoring.d.ts +5 -2
  12. package/dist/builtin/workflows/src/extension/background-ui-adapter.ts +3 -1
  13. package/dist/builtin/workflows/src/extension/hil-answer-notifications.ts +17 -25
  14. package/dist/builtin/workflows/src/extension/index.ts +133 -18
  15. package/dist/builtin/workflows/src/extension/render-result.ts +22 -2
  16. package/dist/builtin/workflows/src/extension/workflow-schema.ts +3 -3
  17. package/dist/builtin/workflows/src/runs/foreground/executor.ts +210 -16
  18. package/dist/builtin/workflows/src/sdk-surface.ts +1 -1
  19. package/dist/builtin/workflows/src/shared/authoring-contract.d.ts +42 -5
  20. package/dist/builtin/workflows/src/shared/store-types.ts +8 -2
  21. package/dist/builtin/workflows/src/shared/store.ts +51 -0
  22. package/dist/builtin/workflows/src/shared/types.ts +14 -4
  23. package/dist/builtin/workflows/src/tui/chat-surface.ts +32 -33
  24. package/dist/builtin/workflows/src/tui/graph-view.ts +4 -1
  25. package/dist/builtin/workflows/src/tui/prompt-card.ts +6 -0
  26. package/dist/builtin/workflows/src/tui/run-detail.ts +11 -4
  27. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +11 -1
  28. package/dist/builtin/workflows/src/tui/status-list.ts +32 -2
  29. package/dist/cli/args.d.ts +4 -0
  30. package/dist/cli/args.d.ts.map +1 -1
  31. package/dist/cli/args.js +35 -0
  32. package/dist/cli/args.js.map +1 -1
  33. package/dist/cli/project-trust.d.ts +10 -0
  34. package/dist/cli/project-trust.d.ts.map +1 -0
  35. package/dist/cli/project-trust.js +36 -0
  36. package/dist/cli/project-trust.js.map +1 -0
  37. package/dist/cli/startup-ui.d.ts +7 -0
  38. package/dist/cli/startup-ui.d.ts.map +1 -0
  39. package/dist/cli/startup-ui.js +57 -0
  40. package/dist/cli/startup-ui.js.map +1 -0
  41. package/dist/config.d.ts.map +1 -1
  42. package/dist/config.js +24 -3
  43. package/dist/config.js.map +1 -1
  44. package/dist/core/agent-session-runtime.d.ts +3 -1
  45. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  46. package/dist/core/agent-session-runtime.js +1 -0
  47. package/dist/core/agent-session-runtime.js.map +1 -1
  48. package/dist/core/agent-session-services.d.ts +2 -1
  49. package/dist/core/agent-session-services.d.ts.map +1 -1
  50. package/dist/core/agent-session-services.js +2 -2
  51. package/dist/core/agent-session-services.js.map +1 -1
  52. package/dist/core/agent-session.d.ts +9 -5
  53. package/dist/core/agent-session.d.ts.map +1 -1
  54. package/dist/core/agent-session.js +205 -51
  55. package/dist/core/agent-session.js.map +1 -1
  56. package/dist/core/auth-guidance.d.ts +10 -1
  57. package/dist/core/auth-guidance.d.ts.map +1 -1
  58. package/dist/core/auth-guidance.js +26 -1
  59. package/dist/core/auth-guidance.js.map +1 -1
  60. package/dist/core/auth-storage.d.ts.map +1 -1
  61. package/dist/core/auth-storage.js +4 -3
  62. package/dist/core/auth-storage.js.map +1 -1
  63. package/dist/core/compaction/branch-summarization.d.ts +5 -3
  64. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  65. package/dist/core/compaction/branch-summarization.js +16 -10
  66. package/dist/core/compaction/branch-summarization.js.map +1 -1
  67. package/dist/core/compaction/compaction.d.ts +4 -84
  68. package/dist/core/compaction/compaction.d.ts.map +1 -1
  69. package/dist/core/compaction/compaction.js +20 -502
  70. package/dist/core/compaction/compaction.js.map +1 -1
  71. package/dist/core/compaction/context-compaction.d.ts.map +1 -1
  72. package/dist/core/compaction/context-compaction.js +39 -82
  73. package/dist/core/compaction/context-compaction.js.map +1 -1
  74. package/dist/core/compaction/index.d.ts +1 -1
  75. package/dist/core/compaction/index.d.ts.map +1 -1
  76. package/dist/core/compaction/index.js +1 -1
  77. package/dist/core/compaction/index.js.map +1 -1
  78. package/dist/core/compaction/utils.d.ts +1 -1
  79. package/dist/core/compaction/utils.d.ts.map +1 -1
  80. package/dist/core/compaction/utils.js +1 -1
  81. package/dist/core/compaction/utils.js.map +1 -1
  82. package/dist/core/experimental.d.ts +2 -0
  83. package/dist/core/experimental.d.ts.map +1 -0
  84. package/dist/core/experimental.js +5 -0
  85. package/dist/core/experimental.js.map +1 -0
  86. package/dist/core/export-html/template.js +19 -6
  87. package/dist/core/extensions/index.d.ts +1 -1
  88. package/dist/core/extensions/index.d.ts.map +1 -1
  89. package/dist/core/extensions/index.js.map +1 -1
  90. package/dist/core/extensions/loader.d.ts +1 -1
  91. package/dist/core/extensions/loader.d.ts.map +1 -1
  92. package/dist/core/extensions/loader.js +6 -4
  93. package/dist/core/extensions/loader.js.map +1 -1
  94. package/dist/core/extensions/runner.d.ts +11 -4
  95. package/dist/core/extensions/runner.d.ts.map +1 -1
  96. package/dist/core/extensions/runner.js +53 -3
  97. package/dist/core/extensions/runner.js.map +1 -1
  98. package/dist/core/extensions/types.d.ts +44 -12
  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/footer-data-provider.d.ts +2 -0
  102. package/dist/core/footer-data-provider.d.ts.map +1 -1
  103. package/dist/core/footer-data-provider.js +27 -1
  104. package/dist/core/footer-data-provider.js.map +1 -1
  105. package/dist/core/index.d.ts +2 -1
  106. package/dist/core/index.d.ts.map +1 -1
  107. package/dist/core/index.js +1 -0
  108. package/dist/core/index.js.map +1 -1
  109. package/dist/core/messages.d.ts +1 -11
  110. package/dist/core/messages.d.ts.map +1 -1
  111. package/dist/core/messages.js +10 -25
  112. package/dist/core/messages.js.map +1 -1
  113. package/dist/core/model-registry.d.ts.map +1 -1
  114. package/dist/core/model-registry.js +64 -7
  115. package/dist/core/model-registry.js.map +1 -1
  116. package/dist/core/model-resolver.d.ts.map +1 -1
  117. package/dist/core/model-resolver.js +1 -0
  118. package/dist/core/model-resolver.js.map +1 -1
  119. package/dist/core/output-guard.d.ts +1 -0
  120. package/dist/core/output-guard.d.ts.map +1 -1
  121. package/dist/core/output-guard.js +52 -22
  122. package/dist/core/output-guard.js.map +1 -1
  123. package/dist/core/package-manager.d.ts +1 -0
  124. package/dist/core/package-manager.d.ts.map +1 -1
  125. package/dist/core/package-manager.js +20 -8
  126. package/dist/core/package-manager.js.map +1 -1
  127. package/dist/core/project-trust.d.ts +15 -0
  128. package/dist/core/project-trust.d.ts.map +1 -0
  129. package/dist/core/project-trust.js +58 -0
  130. package/dist/core/project-trust.js.map +1 -0
  131. package/dist/core/prompt-templates.d.ts +5 -4
  132. package/dist/core/prompt-templates.d.ts.map +1 -1
  133. package/dist/core/prompt-templates.js +30 -29
  134. package/dist/core/prompt-templates.js.map +1 -1
  135. package/dist/core/provider-attribution.d.ts +4 -0
  136. package/dist/core/provider-attribution.d.ts.map +1 -0
  137. package/dist/core/provider-attribution.js +73 -0
  138. package/dist/core/provider-attribution.js.map +1 -0
  139. package/dist/core/provider-display-names.d.ts.map +1 -1
  140. package/dist/core/provider-display-names.js +3 -0
  141. package/dist/core/provider-display-names.js.map +1 -1
  142. package/dist/core/resolve-config-value.d.ts +9 -1
  143. package/dist/core/resolve-config-value.d.ts.map +1 -1
  144. package/dist/core/resolve-config-value.js +134 -11
  145. package/dist/core/resolve-config-value.js.map +1 -1
  146. package/dist/core/resource-loader.d.ts +12 -2
  147. package/dist/core/resource-loader.d.ts.map +1 -1
  148. package/dist/core/resource-loader.js +108 -18
  149. package/dist/core/resource-loader.js.map +1 -1
  150. package/dist/core/sdk.d.ts.map +1 -1
  151. package/dist/core/sdk.js +12 -42
  152. package/dist/core/sdk.js.map +1 -1
  153. package/dist/core/session-manager.d.ts +11 -15
  154. package/dist/core/session-manager.d.ts.map +1 -1
  155. package/dist/core/session-manager.js +111 -111
  156. package/dist/core/session-manager.js.map +1 -1
  157. package/dist/core/settings-manager.d.ts +15 -5
  158. package/dist/core/settings-manager.d.ts.map +1 -1
  159. package/dist/core/settings-manager.js +69 -14
  160. package/dist/core/settings-manager.js.map +1 -1
  161. package/dist/core/slash-commands.d.ts.map +1 -1
  162. package/dist/core/slash-commands.js +1 -0
  163. package/dist/core/slash-commands.js.map +1 -1
  164. package/dist/core/system-prompt.d.ts.map +1 -1
  165. package/dist/core/system-prompt.js +0 -3
  166. package/dist/core/system-prompt.js.map +1 -1
  167. package/dist/core/tools/bash.d.ts.map +1 -1
  168. package/dist/core/tools/bash.js +2 -1
  169. package/dist/core/tools/bash.js.map +1 -1
  170. package/dist/core/tools/edit.d.ts.map +1 -1
  171. package/dist/core/tools/edit.js +7 -10
  172. package/dist/core/tools/edit.js.map +1 -1
  173. package/dist/core/tools/find.d.ts.map +1 -1
  174. package/dist/core/tools/find.js +1 -1
  175. package/dist/core/tools/find.js.map +1 -1
  176. package/dist/core/tools/grep.d.ts.map +1 -1
  177. package/dist/core/tools/grep.js +1 -1
  178. package/dist/core/tools/grep.js.map +1 -1
  179. package/dist/core/tools/ls.d.ts.map +1 -1
  180. package/dist/core/tools/ls.js +1 -1
  181. package/dist/core/tools/ls.js.map +1 -1
  182. package/dist/core/tools/oversized-tool-result.d.ts +53 -0
  183. package/dist/core/tools/oversized-tool-result.d.ts.map +1 -0
  184. package/dist/core/tools/oversized-tool-result.js +206 -0
  185. package/dist/core/tools/oversized-tool-result.js.map +1 -0
  186. package/dist/core/tools/read.d.ts +12 -0
  187. package/dist/core/tools/read.d.ts.map +1 -1
  188. package/dist/core/tools/read.js +99 -34
  189. package/dist/core/tools/read.js.map +1 -1
  190. package/dist/core/tools/render-utils.d.ts +6 -0
  191. package/dist/core/tools/render-utils.d.ts.map +1 -1
  192. package/dist/core/tools/render-utils.js +17 -1
  193. package/dist/core/tools/render-utils.js.map +1 -1
  194. package/dist/core/tools/tool-definition-wrapper.d.ts +6 -0
  195. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  196. package/dist/core/tools/tool-definition-wrapper.js +2 -0
  197. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  198. package/dist/core/tools/tool-limits.d.ts +25 -0
  199. package/dist/core/tools/tool-limits.d.ts.map +1 -0
  200. package/dist/core/tools/tool-limits.js +25 -0
  201. package/dist/core/tools/tool-limits.js.map +1 -0
  202. package/dist/core/tools/write.d.ts.map +1 -1
  203. package/dist/core/tools/write.js +1 -1
  204. package/dist/core/tools/write.js.map +1 -1
  205. package/dist/core/trust-manager.d.ts +31 -0
  206. package/dist/core/trust-manager.d.ts.map +1 -0
  207. package/dist/core/trust-manager.js +196 -0
  208. package/dist/core/trust-manager.js.map +1 -0
  209. package/dist/index.d.ts +12 -7
  210. package/dist/index.d.ts.map +1 -1
  211. package/dist/index.js +8 -4
  212. package/dist/index.js.map +1 -1
  213. package/dist/main.d.ts.map +1 -1
  214. package/dist/main.js +142 -30
  215. package/dist/main.js.map +1 -1
  216. package/dist/migrations.d.ts +3 -1
  217. package/dist/migrations.d.ts.map +1 -1
  218. package/dist/migrations.js +325 -7
  219. package/dist/migrations.js.map +1 -1
  220. package/dist/modes/index.d.ts +1 -1
  221. package/dist/modes/index.d.ts.map +1 -1
  222. package/dist/modes/index.js.map +1 -1
  223. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  224. package/dist/modes/interactive/components/bash-execution.js +2 -2
  225. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  226. package/dist/modes/interactive/components/chat-message-renderer.d.ts +1 -5
  227. package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
  228. package/dist/modes/interactive/components/chat-message-renderer.js +5 -9
  229. package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
  230. package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
  231. package/dist/modes/interactive/components/chat-session-host.js +0 -3
  232. package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
  233. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  234. package/dist/modes/interactive/components/footer.js +6 -0
  235. package/dist/modes/interactive/components/footer.js.map +1 -1
  236. package/dist/modes/interactive/components/index.d.ts +1 -1
  237. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  238. package/dist/modes/interactive/components/index.js +1 -1
  239. package/dist/modes/interactive/components/index.js.map +1 -1
  240. package/dist/modes/interactive/components/login-dialog.d.ts +1 -1
  241. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  242. package/dist/modes/interactive/components/login-dialog.js +9 -16
  243. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  244. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  245. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  246. package/dist/modes/interactive/components/settings-selector.js +20 -0
  247. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  248. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  249. package/dist/modes/interactive/components/tool-execution.js +22 -0
  250. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  251. package/dist/modes/interactive/components/trust-selector.d.ts +23 -0
  252. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -0
  253. package/dist/modes/interactive/components/trust-selector.js +85 -0
  254. package/dist/modes/interactive/components/trust-selector.js.map +1 -0
  255. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  256. package/dist/modes/interactive/components/user-message.js +1 -1
  257. package/dist/modes/interactive/components/user-message.js.map +1 -1
  258. package/dist/modes/interactive/interactive-mode.d.ts +9 -0
  259. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  260. package/dist/modes/interactive/interactive-mode.js +134 -36
  261. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  262. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  263. package/dist/modes/interactive/theme/theme.js +10 -0
  264. package/dist/modes/interactive/theme/theme.js.map +1 -1
  265. package/dist/modes/print-mode.d.ts.map +1 -1
  266. package/dist/modes/print-mode.js +1 -0
  267. package/dist/modes/print-mode.js.map +1 -1
  268. package/dist/modes/rpc/rpc-client.d.ts +4 -1
  269. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  270. package/dist/modes/rpc/rpc-client.js +52 -8
  271. package/dist/modes/rpc/rpc-client.js.map +1 -1
  272. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  273. package/dist/modes/rpc/rpc-mode.js +24 -5
  274. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  275. package/dist/modes/rpc/rpc-types.d.ts +1 -1
  276. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  277. package/dist/modes/rpc/rpc-types.js.map +1 -1
  278. package/dist/package-manager-cli.d.ts +6 -2
  279. package/dist/package-manager-cli.d.ts.map +1 -1
  280. package/dist/package-manager-cli.js +104 -10
  281. package/dist/package-manager-cli.js.map +1 -1
  282. package/dist/utils/changelog.d.ts +1 -0
  283. package/dist/utils/changelog.d.ts.map +1 -1
  284. package/dist/utils/changelog.js +72 -0
  285. package/dist/utils/changelog.js.map +1 -1
  286. package/dist/utils/deprecation.d.ts +4 -0
  287. package/dist/utils/deprecation.d.ts.map +1 -0
  288. package/dist/utils/deprecation.js +13 -0
  289. package/dist/utils/deprecation.js.map +1 -0
  290. package/dist/utils/git.d.ts.map +1 -1
  291. package/dist/utils/git.js +54 -22
  292. package/dist/utils/git.js.map +1 -1
  293. package/dist/utils/json.d.ts +3 -0
  294. package/dist/utils/json.d.ts.map +1 -0
  295. package/dist/utils/json.js +7 -0
  296. package/dist/utils/json.js.map +1 -0
  297. package/dist/utils/open-browser.d.ts +9 -0
  298. package/dist/utils/open-browser.d.ts.map +1 -0
  299. package/dist/utils/open-browser.js +22 -0
  300. package/dist/utils/open-browser.js.map +1 -0
  301. package/docs/compaction.md +210 -181
  302. package/docs/containerization.md +111 -0
  303. package/docs/custom-provider.md +9 -9
  304. package/docs/development.md +1 -1
  305. package/docs/docs.json +2 -0
  306. package/docs/extensions.md +71 -24
  307. package/docs/index.md +2 -0
  308. package/docs/json.md +3 -4
  309. package/docs/models.md +10 -10
  310. package/docs/packages.md +1 -1
  311. package/docs/prompt-templates.md +9 -2
  312. package/docs/providers.md +18 -5
  313. package/docs/quickstart.md +1 -0
  314. package/docs/rpc.md +3 -2
  315. package/docs/sdk.md +5 -0
  316. package/docs/security.md +56 -0
  317. package/docs/session-format.md +14 -23
  318. package/docs/sessions.md +11 -1
  319. package/docs/settings.md +23 -9
  320. package/docs/skills.md +1 -1
  321. package/docs/terminal-setup.md +44 -2
  322. package/docs/themes.md +1 -1
  323. package/docs/tmux.md +4 -2
  324. package/docs/tui.md +14 -5
  325. package/docs/usage.md +17 -3
  326. package/docs/workflows.md +11 -9
  327. package/examples/README.md +1 -1
  328. package/examples/extensions/README.md +9 -6
  329. package/examples/extensions/bash-spawn-hook.ts +1 -1
  330. package/examples/extensions/built-in-tool-renderer.ts +1 -1
  331. package/examples/extensions/claude-rules.ts +1 -1
  332. package/examples/extensions/commands.ts +1 -1
  333. package/examples/extensions/custom-compaction.ts +43 -106
  334. package/examples/extensions/custom-header.ts +1 -1
  335. package/examples/extensions/custom-provider-anthropic/index.ts +3 -3
  336. package/examples/extensions/custom-provider-anthropic/package-lock.json +4 -4
  337. package/examples/extensions/custom-provider-anthropic/package.json +6 -6
  338. package/examples/extensions/custom-provider-gitlab-duo/index.ts +55 -4
  339. package/examples/extensions/custom-provider-gitlab-duo/package.json +3 -3
  340. package/examples/extensions/doom-overlay/README.md +1 -1
  341. package/examples/extensions/doom-overlay/index.ts +2 -2
  342. package/examples/extensions/git-merge-and-resolve.ts +115 -0
  343. package/examples/extensions/gondolin/index.ts +523 -0
  344. package/examples/extensions/gondolin/package-lock.json +185 -0
  345. package/examples/extensions/gondolin/package.json +19 -0
  346. package/examples/extensions/handoff.ts +7 -45
  347. package/examples/extensions/hidden-thinking-label.ts +1 -1
  348. package/examples/extensions/inline-bash.ts +2 -2
  349. package/examples/extensions/input-transform-streaming.ts +39 -0
  350. package/examples/extensions/input-transform.ts +3 -3
  351. package/examples/extensions/interactive-shell.ts +2 -2
  352. package/examples/extensions/mac-system-theme.ts +2 -2
  353. package/examples/extensions/minimal-mode.ts +1 -1
  354. package/examples/extensions/modal-editor.ts +1 -1
  355. package/examples/extensions/model-status.ts +1 -1
  356. package/examples/extensions/overlay-qa-tests.ts +198 -179
  357. package/examples/extensions/overlay-test.ts +1 -1
  358. package/examples/extensions/pirate.ts +1 -1
  359. package/examples/extensions/preset.ts +14 -12
  360. package/examples/extensions/project-trust.ts +64 -0
  361. package/examples/extensions/prompt-customizer.ts +1 -1
  362. package/examples/extensions/qna.ts +1 -1
  363. package/examples/extensions/question.ts +1 -1
  364. package/examples/extensions/questionnaire.ts +1 -1
  365. package/examples/extensions/rainbow-editor.ts +1 -1
  366. package/examples/extensions/sandbox/index.ts +16 -14
  367. package/examples/extensions/sandbox/package-lock.json +90 -90
  368. package/examples/extensions/sandbox/package.json +17 -17
  369. package/examples/extensions/snake.ts +1 -1
  370. package/examples/extensions/space-invaders.ts +1 -1
  371. package/examples/extensions/ssh.ts +2 -2
  372. package/examples/extensions/subagent/README.md +13 -13
  373. package/examples/extensions/subagent/agents.ts +4 -2
  374. package/examples/extensions/subagent/index.ts +6 -6
  375. package/examples/extensions/summarize.ts +1 -1
  376. package/examples/extensions/tic-tac-toe.ts +1 -1
  377. package/examples/extensions/titlebar-spinner.ts +1 -1
  378. package/examples/extensions/todo.ts +1 -1
  379. package/examples/extensions/tool-override.ts +1 -1
  380. package/examples/extensions/tools.ts +6 -1
  381. package/examples/extensions/trigger-compact.ts +5 -4
  382. package/examples/extensions/with-deps/package-lock.json +4 -4
  383. package/examples/extensions/with-deps/package.json +7 -7
  384. package/examples/extensions/working-indicator.ts +4 -4
  385. package/examples/extensions/working-message-test.ts +1 -1
  386. package/examples/sdk/01-minimal.ts +1 -1
  387. package/examples/sdk/03-custom-prompt.ts +1 -1
  388. package/examples/sdk/04-skills.ts +1 -1
  389. package/examples/sdk/06-extensions.ts +2 -2
  390. package/examples/sdk/08-prompt-templates.ts +1 -1
  391. package/examples/sdk/09-api-keys-and-oauth.ts +2 -2
  392. package/examples/sdk/README.md +2 -2
  393. package/package.json +8 -8
  394. package/dist/modes/interactive/components/compaction-summary-message.d.ts +0 -16
  395. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +0 -1
  396. package/dist/modes/interactive/components/compaction-summary-message.js +0 -43
  397. package/dist/modes/interactive/components/compaction-summary-message.js.map +0 -1
@@ -1,10 +1,13 @@
1
1
  /**
2
- * Dependency-light workflow authoring contract shared by the runtime type graph
3
- * and the standalone package typing surface.
2
+ * Workflow authoring contract shared by the runtime type graph and the
3
+ * standalone package typing surface.
4
4
  *
5
- * This module intentionally imports only TypeBox types. Do not import
6
- * @bastani/atomic, executor internals, stores, or runtime graph modules here.
5
+ * This module intentionally avoids executor internals, stores, or runtime graph
6
+ * modules here. Public custom-TUI types are type-only imports from the same
7
+ * extension-compatible surfaces used by Atomic extension UI.
7
8
  */
9
+ import type { KeybindingsManager, Theme } from "@bastani/atomic";
10
+ import type { Component, OverlayHandle, OverlayOptions, TUI } from "@earendil-works/pi-tui";
8
11
  import type { Static, TOptional, TSchema } from "typebox";
9
12
  export type { Static, TSchema };
10
13
  export type WorkflowSerializablePrimitive = string | number | boolean | null;
@@ -335,13 +338,47 @@ export interface WorkflowChildResult<TOutputs extends WorkflowOutputValues = Wor
335
338
  readonly status: "completed";
336
339
  readonly outputs: TOutputs;
337
340
  }
341
+ export type WorkflowCustomUiComponent = Component & {
342
+ dispose?(): void;
343
+ };
344
+ export type WorkflowCustomUiTui = TUI;
345
+ export type WorkflowCustomUiTheme = Theme;
346
+ export type WorkflowCustomUiKeybindings = KeybindingsManager;
347
+ export type WorkflowCustomUiOverlayOptions = OverlayOptions;
348
+ export type WorkflowCustomUiOverlayHandle = OverlayHandle;
349
+ export type WorkflowCustomUiFactory<T> = (tui: TUI, theme: Theme, keybindings: KeybindingsManager, done: (value: T) => void) => WorkflowCustomUiComponent | Promise<WorkflowCustomUiComponent>;
350
+ export interface WorkflowCustomUiOptions {
351
+ /** Render as a nested overlay. Workflow graph hosts may reject this when unsupported. */
352
+ readonly overlay?: boolean;
353
+ /** AbortSignal to programmatically dismiss the custom UI. */
354
+ readonly signal?: AbortSignal;
355
+ /** Overlay positioning/sizing options. Can be static or a function for dynamic updates. */
356
+ readonly overlayOptions?: OverlayOptions | (() => OverlayOptions);
357
+ /** Called with the real overlay handle after an overlay is shown. */
358
+ readonly onHandle?: (handle: OverlayHandle) => void;
359
+ /**
360
+ * Workflow-only replay identity. Recommended whenever widget state or
361
+ * semantics can change without the callsite changing. Do not include secrets;
362
+ * the runtime stores only a hash.
363
+ */
364
+ readonly replayIdentity?: string;
365
+ /** Safe display-only label for graph/status surfaces. Defaults to "Custom TUI prompt". Not part of replay identity. */
366
+ readonly label?: string;
367
+ }
338
368
  export interface WorkflowUIContext {
339
369
  input(prompt: string): Promise<string>;
340
370
  confirm(message: string): Promise<boolean>;
341
371
  select<T extends string>(message: string, options: readonly T[]): Promise<T>;
342
372
  editor(initial?: string): Promise<string>;
373
+ custom<T>(factory: WorkflowCustomUiFactory<T>, options?: WorkflowCustomUiOptions): Promise<T>;
374
+ }
375
+ export interface WorkflowUIAdapter {
376
+ input(prompt: string): Promise<string>;
377
+ confirm(message: string): Promise<boolean>;
378
+ select<T extends string>(message: string, options: readonly T[]): Promise<T>;
379
+ editor(initial?: string): Promise<string>;
380
+ custom?<T>(factory: WorkflowCustomUiFactory<T>, options?: WorkflowCustomUiOptions): Promise<T>;
343
381
  }
344
- export type WorkflowUIAdapter = WorkflowUIContext;
345
382
  export interface WorkflowRunContext<TInputs extends WorkflowInputValues = WorkflowInputValues, TDefinitionBrand extends object = {}> {
346
383
  readonly inputs: Readonly<TInputs>;
347
384
  readonly cwd?: string;
@@ -32,10 +32,12 @@ export type WorkflowFailureCode =
32
32
  | "unknown";
33
33
 
34
34
  /**
35
- * Human-in-the-loop prompt kind. Mirrors the four `WorkflowUIContext` methods.
35
+ * Human-in-the-loop prompt kind. Mirrors the `WorkflowUIContext` methods.
36
36
  * cross-ref: src/shared/types.ts WorkflowUIContext
37
37
  */
38
- export type PromptKind = "input" | "confirm" | "select" | "editor";
38
+ export type PromptKind = "input" | "confirm" | "select" | "editor" | "custom";
39
+
40
+ export type CustomPromptIdentitySource = "caller" | "factory" | "callsite";
39
41
 
40
42
  /**
41
43
  * A pending HIL prompt awaiting user response. Surfaced through the graph
@@ -53,6 +55,10 @@ export interface PendingPrompt {
53
55
  readonly choices?: readonly string[];
54
56
  /** Initial value for `kind: "input"` and `kind: "editor"`. */
55
57
  readonly initial?: string;
58
+ /** Hash of caller-supplied or derived replay identity for `kind: "custom"`. */
59
+ readonly customIdentityHash?: string;
60
+ /** Explains how a custom prompt replay identity was derived without storing the raw identity. */
61
+ readonly customIdentitySource?: CustomPromptIdentitySource;
56
62
  /** Issue timestamp (ms since epoch). */
57
63
  readonly createdAt: number;
58
64
  }
@@ -119,6 +119,11 @@ export interface ResolveStagePendingPromptOptions {
119
119
  readonly answerSource?: StagePromptAnswerSource;
120
120
  }
121
121
 
122
+ export interface RecordStagePromptAnswerOptions {
123
+ /** Identifies who answered the prompt so notification code can avoid echoing workflow-tool answers. */
124
+ readonly answerSource?: StagePromptAnswerSource;
125
+ }
126
+
122
127
  export interface Store {
123
128
  runs(): readonly RunSnapshot[];
124
129
  notices(): readonly WorkflowNotice[];
@@ -206,6 +211,19 @@ export interface Store {
206
211
  ): boolean;
207
212
  /** Wait for a stage/node-scoped HIL prompt to resolve. */
208
213
  awaitStagePendingPrompt(runId: string, stageId: string, promptId: string): Promise<unknown>;
214
+ /**
215
+ * Record a live-only prompt answer for prompt-node UIs that do not use
216
+ * `stage.pendingPrompt` (notably arbitrary `ctx.ui.custom<T>` widgets).
217
+ * The raw value stays in the private answer ledger and is never serialized
218
+ * into snapshots or persistence.
219
+ */
220
+ recordStagePromptAnswer(
221
+ runId: string,
222
+ stageId: string,
223
+ prompt: PendingPrompt,
224
+ response: unknown,
225
+ options?: RecordStagePromptAnswerOptions,
226
+ ): boolean;
209
227
  /**
210
228
  * Record a live-only draft for an active stage-local input/editor prompt.
211
229
  * Draft text may contain secrets and must never be copied into snapshots,
@@ -774,6 +792,39 @@ export function createStore(): Store {
774
792
  });
775
793
  },
776
794
 
795
+ recordStagePromptAnswer(
796
+ runId: string,
797
+ stageId: string,
798
+ prompt: PendingPrompt,
799
+ response: unknown,
800
+ options: RecordStagePromptAnswerOptions = {},
801
+ ): boolean {
802
+ const run = findRun(runId);
803
+ if (!run) return false;
804
+ if (TERMINAL_STATUSES.has(run.status)) return false;
805
+ const stage = findStage(run, stageId);
806
+ if (!stage) return false;
807
+ if (isTerminalStageStatus(stage.status)) return false;
808
+ _stagePromptAnswers.set(stagePromptAnswerKey(runId, stageId), {
809
+ runId,
810
+ stageId,
811
+ promptId: prompt.id,
812
+ kind: prompt.kind,
813
+ value: response,
814
+ answeredAt: Date.now(),
815
+ ...(options.answerSource !== undefined ? { answerSource: options.answerSource } : {}),
816
+ });
817
+ if (stage.promptFootprint === undefined) stage.promptFootprint = { ...prompt };
818
+ stage.promptAnswerState = "available";
819
+ if (stage.status === "awaiting_input") {
820
+ stage.status = "running";
821
+ delete stage.awaitingInputSince;
822
+ }
823
+ _version++;
824
+ notify();
825
+ return true;
826
+ },
827
+
777
828
  recordStagePromptDraft(runId: string, stageId: string, promptId: string, text: string): boolean {
778
829
  if (stageHasActiveTextPrompt(runId, stageId, promptId) === undefined) return false;
779
830
  _stagePromptDrafts.set(stagePromptDraftKey(runId, stageId, promptId), text);
@@ -116,14 +116,24 @@ export interface WorkflowChildResult<TOutputs extends WorkflowOutputValues = Wor
116
116
  * Each primitive suspends the current stage until the user responds.
117
117
  * Mirrors pi ctx.ui.input / confirm / select / editor methods.
118
118
  */
119
- export type WorkflowUIContext = AuthoringContract.WorkflowUIContext;
119
+ export type WorkflowCustomUiComponent = AuthoringContract.WorkflowCustomUiComponent;
120
+ export type WorkflowCustomUiTui = AuthoringContract.WorkflowCustomUiTui;
121
+ export type WorkflowCustomUiTheme = AuthoringContract.WorkflowCustomUiTheme;
122
+ export type WorkflowCustomUiKeybindings = AuthoringContract.WorkflowCustomUiKeybindings;
123
+ export type WorkflowCustomUiOverlayOptions = AuthoringContract.WorkflowCustomUiOverlayOptions;
124
+ export type WorkflowCustomUiOverlayHandle = AuthoringContract.WorkflowCustomUiOverlayHandle;
125
+ export type WorkflowCustomUiFactory<T> = AuthoringContract.WorkflowCustomUiFactory<T>;
126
+ export type WorkflowCustomUiOptions = AuthoringContract.WorkflowCustomUiOptions;
127
+
128
+ export interface WorkflowUIContext extends AuthoringContract.WorkflowUIContext {}
120
129
 
121
130
  /**
122
131
  * Adapter supplied by the pi runtime (or test harness) to back the HIL
123
- * primitives. Must implement the same surface as WorkflowUIContext so that
124
- * the executor can delegate directly.
132
+ * primitives. The custom-widget method is optional for compatibility with
133
+ * existing primitive-only adapters; the executor normalizes a missing custom
134
+ * method to the same unavailable-UI rejection used in headless mode.
125
135
  */
126
- export type WorkflowUIAdapter = AuthoringContract.WorkflowUIAdapter;
136
+ export interface WorkflowUIAdapter extends AuthoringContract.WorkflowUIAdapter {}
127
137
 
128
138
  // ---------------------------------------------------------------------------
129
139
  // StageOptions — per-stage configuration + pi SDK session options
@@ -11,9 +11,11 @@
11
11
  * left, a `surface0` tag carrying the runId / workflow name, a
12
12
  * bolded title beside it, and one optional second row indented past
13
13
  * the stripe.
14
- * - **Progress strip**: bracketed `[✓]` / `[●]` / `[]` / `[]` cells,
15
- * coloured by stage status. Truncates with a trailing `…` when the
16
- * rendered cells exceed the available budget.
14
+ * - **Progress strip**: bracketed status cells such as `[]`, `[]`,
15
+ * `[○]`, `[✗]`, and `[❚❚]`, coloured by stage status. Cells are
16
+ * measured by visible width per rendered glyph rather than assumed to
17
+ * be a fixed 3 columns, and the strip truncates with a trailing `…`
18
+ * when the rendered cells exceed the available budget.
17
19
  * - **Hint rows**: a single grammar — `▸ /slash command verb-phrase
18
20
  * hint`.
19
21
  *
@@ -440,7 +442,7 @@ function renderTaggedCardPlain(opts: RenderTaggedCardOpts, width: number): strin
440
442
  }
441
443
 
442
444
  // ---------------------------------------------------------------------------
443
- // Progress strip — `[✓][●][○][✗]` cells, coloured by stage status
445
+ // Progress strip — variable-width bracketed cells, coloured by stage status
444
446
  // ---------------------------------------------------------------------------
445
447
 
446
448
  export interface ProgressCell {
@@ -449,45 +451,40 @@ export interface ProgressCell {
449
451
 
450
452
  /**
451
453
  * Render a progress strip whose visible width is at most `budget` cells.
452
- * Each cell renders as a 3-character bracket-glyph-bracket sequence
453
- * (`[✓]`). When the strip would exceed the budget, the rendered output
454
- * is truncated and a trailing `…` is appended.
454
+ * Each cell renders as a bracketed status glyph whose visible width can
455
+ * vary by status (`[✓]` is 3 cells, `[❚❚]` is 4 cells). Truncation uses
456
+ * the measured width of each rendered cell and appends a trailing `…`
457
+ * when the next whole cell would exceed the budget.
455
458
  *
456
459
  * Themed mode colours the glyphs by status; plain mode emits the same
457
- * ASCII shape so logs remain readable.
460
+ * bracketed shape so logs remain readable.
458
461
  */
459
462
  export function progressStrip(
460
463
  cells: readonly ProgressCell[],
461
464
  budget: number,
462
465
  theme?: GraphTheme,
463
466
  ): string {
464
- const CELL_WIDTH = 3;
465
467
  const usable = Math.max(0, Math.floor(budget));
466
- const maxCells = Math.max(0, Math.floor(usable / CELL_WIDTH));
467
- if (maxCells === 0 || cells.length === 0) return "";
468
-
469
- const truncated = cells.length > maxCells;
470
- // Reserve 1 cell of width for the trailing ellipsis if truncating, so the
471
- // rendered output still fits.
472
- const visibleCount = truncated
473
- ? Math.max(0, Math.floor((usable - 1) / CELL_WIDTH))
474
- : cells.length;
475
- const slice = cells.slice(0, visibleCount);
476
-
477
- let out = "";
478
- if (theme) {
479
- for (const cell of slice) {
480
- out += renderCellThemed(cell.status, theme);
481
- }
482
- } else {
483
- for (const cell of slice) {
484
- out += renderCellPlain(cell.status);
485
- }
468
+ if (usable < 3 || cells.length === 0) return "";
469
+
470
+ const ellipsisWidth = visibleWidth(ELLIPSIS);
471
+ const out: string[] = [];
472
+ let used = 0;
473
+
474
+ for (let i = 0; i < cells.length; i++) {
475
+ const rendered = theme ? renderCellThemed(cells[i]!.status, theme) : renderCellPlain(cells[i]!.status);
476
+ const renderedWidth = visibleWidth(rendered);
477
+ const isLast = i === cells.length - 1;
478
+ const reserved = isLast ? 0 : ellipsisWidth;
479
+ if (used + renderedWidth + reserved > usable) break;
480
+ out.push(rendered);
481
+ used += renderedWidth;
482
+ if (isLast) return out.join("");
486
483
  }
487
- if (truncated) {
488
- out += theme ? `${hexToAnsi(theme.dim)}${ELLIPSIS}${RESET}` : ELLIPSIS;
489
- }
490
- return out;
484
+
485
+ if (out.length === 0 && ellipsisWidth > usable) return "";
486
+ const suffix = theme ? `${hexToAnsi(theme.dim)}${ELLIPSIS}${RESET}` : ELLIPSIS;
487
+ return `${out.join("")}${suffix}`;
491
488
  }
492
489
 
493
490
  function renderCellThemed(status: StageStatus, theme: GraphTheme): string {
@@ -506,6 +503,7 @@ function stageGlyph(status: StageStatus): string {
506
503
  switch (status) {
507
504
  case "completed": return "✓";
508
505
  case "running": return "●";
506
+ case "paused": return "❚❚";
509
507
  case "failed": return "✗";
510
508
  case "awaiting_input": return "?";
511
509
  case "skipped": return "⊘";
@@ -518,6 +516,7 @@ function stageColor(status: StageStatus, theme: GraphTheme): string {
518
516
  switch (status) {
519
517
  case "completed": return hexToAnsi(theme.success);
520
518
  case "running": return hexToAnsi(theme.warning);
519
+ case "paused": return hexToAnsi(theme.warning);
521
520
  case "failed": return hexToAnsi(theme.error);
522
521
  case "awaiting_input": return hexToAnsi(theme.info);
523
522
  case "skipped": return hexToAnsi(theme.dim);
@@ -357,7 +357,10 @@ export class GraphView implements Component {
357
357
  ? expandWorkflowGraph(this.currentSnapshot, run.id)
358
358
  : { stages: [], targets: new Map() };
359
359
  const stages = [...this.expandedGraph.stages];
360
- const hasStagePrompt = stages.some((stage) => stage.pendingPrompt !== undefined);
360
+ const hasStagePrompt = stages.some((stage) =>
361
+ stage.pendingPrompt !== undefined ||
362
+ (stage.status === "awaiting_input" && stage.promptFootprint?.kind === "custom")
363
+ );
361
364
  if (!hasStagePrompt) return stages;
362
365
  return stages.filter((stage) => {
363
366
  // Prompt-node injection can leave unstarted author stages in the store
@@ -130,6 +130,8 @@ export function handlePromptCardInput(
130
130
  return handleInput(data, state, keybindings);
131
131
  case "editor":
132
132
  return handleEditor(data, state, keybindings);
133
+ case "custom":
134
+ return { kind: "noop" };
133
135
  }
134
136
  }
135
137
 
@@ -436,6 +438,8 @@ export function defaultResponseFor(prompt: PendingPrompt): unknown {
436
438
  return false;
437
439
  case "select":
438
440
  return prompt.choices?.[0] ?? "";
441
+ case "custom":
442
+ return undefined;
439
443
  }
440
444
  }
441
445
 
@@ -669,6 +673,8 @@ function renderResponseField(
669
673
  return [renderInputRow(state, theme, usable, cursorOn)];
670
674
  case "editor":
671
675
  return renderEditorRows(state, theme, usable, cursorOn);
676
+ case "custom":
677
+ return [padToUsable("", usable)];
672
678
  }
673
679
  }
674
680
 
@@ -90,7 +90,10 @@ function renderPlain(detail: RunDetail, now: number, width: number): string {
90
90
  }
91
91
 
92
92
  if (detail.endedAt === undefined) {
93
- out.push(truncateToWidth(` workflow interrupt id=${sid} cancel `, width - 2, ""));
93
+ const hint = detail.status === "paused"
94
+ ? ` ▸ workflow resume id=${sid} continue workflow `
95
+ : ` ▸ workflow interrupt id=${sid} cancel `;
96
+ out.push(truncateToWidth(hint, width - 2, "…"));
94
97
  } else {
95
98
  out.push(truncateToWidth(` ▸ workflow resume id=${sid} reopen graph `, width - 2, "…"));
96
99
  }
@@ -143,9 +146,10 @@ function renderThemed(detail: RunDetail, now: number, theme: GraphTheme, width:
143
146
  }
144
147
 
145
148
  if (detail.endedAt === undefined) {
146
- out.push(
147
- truncateToWidth(` ${dim}▸${RESET} ${accent}workflow interrupt id=${sid}${RESET}${dim} cancel${RESET} `, width - 2, "…"),
148
- );
149
+ const hint = detail.status === "paused"
150
+ ? ` ${dim}▸${RESET} ${accent}workflow resume id=${sid}${RESET}${dim} continue workflow${RESET} `
151
+ : ` ${dim}▸${RESET} ${accent}workflow interrupt id=${sid}${RESET}${dim} cancel${RESET} `;
152
+ out.push(truncateToWidth(hint, width - 2, "…"));
149
153
  } else {
150
154
  out.push(
151
155
  truncateToWidth(` ${dim}▸${RESET} ${accent}workflow resume id=${sid}${RESET}${dim} reopen graph${RESET} `, width - 2, "…"),
@@ -295,6 +299,8 @@ function stateBadges(detail: RunDetail, theme: GraphTheme): FlatBandBadge[] {
295
299
  switch (detail.status) {
296
300
  case "running":
297
301
  return [{ text: "● running", fg: theme.warning }];
302
+ case "paused":
303
+ return [{ text: "❚❚ paused", fg: theme.warning }];
298
304
  case "completed":
299
305
  return [{ text: "✓ completed", fg: theme.success }];
300
306
  case "failed":
@@ -310,6 +316,7 @@ function stateBadges(detail: RunDetail, theme: GraphTheme): FlatBandBadge[] {
310
316
  function stateLabel(detail: RunDetail): string {
311
317
  switch (detail.status) {
312
318
  case "running": return "● running";
319
+ case "paused": return "❚❚ paused";
313
320
  case "completed": return "✓ completed";
314
321
  case "failed": return "✗ failed";
315
322
  case "killed": return "⊘ killed";
@@ -424,6 +424,14 @@ export class StageChatView implements Component, Focusable {
424
424
  );
425
425
  return;
426
426
  }
427
+ if (request.options?.overlay === true) {
428
+ this.mountingRequestId = null;
429
+ this.stageUiBroker.reject(
430
+ request,
431
+ new Error("atomic-workflows: ctx.ui.custom overlay mode is unavailable in the workflow graph viewer"),
432
+ );
433
+ return;
434
+ }
427
435
  try {
428
436
  const mounted = await mountStageCustomUi(
429
437
  request,
@@ -1595,7 +1603,6 @@ function transcriptDebugText(entry: TranscriptEntry): string {
1595
1603
  case "custom":
1596
1604
  return extractMessageText(entry.message.content);
1597
1605
  case "branchSummary":
1598
- case "compactionSummary":
1599
1606
  return entry.message.summary;
1600
1607
  }
1601
1608
  }
@@ -1850,6 +1857,9 @@ function renderHintsForPrompt(kind: PendingPrompt["kind"], theme: GraphTheme): s
1850
1857
  if (kind === "input" || kind === "editor") {
1851
1858
  return `${paint("enter", theme.textMuted, { bold: true })} Submit · ${paint("ctrl+c", theme.textMuted, { bold: true })} Skip`;
1852
1859
  }
1860
+ if (kind === "custom") {
1861
+ return `${paint("ctrl+d", theme.textMuted, { bold: true })} Graph · ${paint("ctrl+c", theme.textMuted, { bold: true })} Close`;
1862
+ }
1853
1863
  return `${paint("enter", theme.textMuted, { bold: true })} Select · ${paint("ctrl+c", theme.textMuted, { bold: true })} Skip`;
1854
1864
  }
1855
1865
 
@@ -160,6 +160,7 @@ function runAccent(run: RunSnapshot, theme?: GraphTheme): string {
160
160
  switch (run.status) {
161
161
  case "completed": return theme.success;
162
162
  case "running": return theme.warning;
163
+ case "paused": return theme.warning;
163
164
  case "failed": return theme.error;
164
165
  case "killed": return theme.error;
165
166
  case "pending":
@@ -171,6 +172,7 @@ function runTrailing(run: RunSnapshot, theme?: GraphTheme): { text: string; fg?:
171
172
  switch (run.status) {
172
173
  case "completed": return { text: "✓ completed", fg: theme?.success };
173
174
  case "running": return { text: "● running", fg: theme?.warning };
175
+ case "paused": return { text: "❚❚ paused", fg: theme?.warning };
174
176
  case "failed": return { text: "✗ failed", fg: theme?.error };
175
177
  case "killed": return { text: "⊘ killed", fg: theme?.error };
176
178
  case "pending":
@@ -181,6 +183,7 @@ function runTrailing(run: RunSnapshot, theme?: GraphTheme): { text: string; fg?:
181
183
  function runCardMeta(run: RunSnapshot, now: number): string {
182
184
  // Builds the right-aligned meta tail.
183
185
  // running → `3/8 · review-a · 1m42s`
186
+ // paused → `3/8 · review-a · 1m42s` (elapsed is frozen by pausedAt)
184
187
  // failed → `failed at partition · 4m24s ago`
185
188
  // killed → `<stage> · <duration> · <when>` (mirrors mockup §2)
186
189
  // completed→ `<stage> · <duration> · <when>`
@@ -204,6 +207,14 @@ function runCardMeta(run: RunSnapshot, now: number): string {
204
207
  return parts.join(" · ");
205
208
  }
206
209
 
210
+ if (run.status === "paused") {
211
+ if (isChain) parts.push(`${done}/${total}`);
212
+ const labels = pausedStageLabels(run);
213
+ if (labels) parts.push(labels);
214
+ if (ago) parts.push(ago);
215
+ return parts.join(" · ");
216
+ }
217
+
207
218
  if (run.status === "failed" || run.status === "killed") {
208
219
  const failed = run.stages.find((s) => s.status === "failed");
209
220
  if (failed && isChain) parts.push(`failed at ${failed.name}`);
@@ -235,6 +246,13 @@ function runningStageLabels(run: RunSnapshot): string | undefined {
235
246
  return truncateToWidth(joined, STAGE_LABEL_BUDGET, ELLIPSIS);
236
247
  }
237
248
 
249
+ function pausedStageLabels(run: RunSnapshot): string | undefined {
250
+ const paused = run.stages.filter((s) => s.status === "paused").map((s) => s.name);
251
+ if (paused.length === 0) return undefined;
252
+ const joined = paused.join(", ");
253
+ return truncateToWidth(joined, STAGE_LABEL_BUDGET, ELLIPSIS);
254
+ }
255
+
238
256
  function lastStageDuration(run: RunSnapshot, now: number): string | undefined {
239
257
  // Pick a representative stage duration: the most-recent terminal stage,
240
258
  // or the running stage if everything's still in flight.
@@ -263,6 +281,7 @@ function stageStatusFromRun(run: RunSnapshot): StageStatus {
263
281
  switch (run.status) {
264
282
  case "completed": return "completed";
265
283
  case "running": return "running";
284
+ case "paused": return "paused";
266
285
  case "failed": return "failed";
267
286
  case "killed": return "failed";
268
287
  case "pending":
@@ -285,17 +304,21 @@ function effectiveWidth(width?: number): number {
285
304
 
286
305
  interface Counts {
287
306
  active: number;
307
+ paused: number;
288
308
  completed: number;
289
309
  failed: number;
290
310
  pending: number;
291
311
  }
292
312
 
293
313
  function countBuckets(runs: readonly RunSnapshot[]): Counts {
294
- const c: Counts = { active: 0, completed: 0, failed: 0, pending: 0 };
314
+ const c: Counts = { active: 0, paused: 0, completed: 0, failed: 0, pending: 0 };
295
315
  for (const r of runs) {
296
316
  if (r.endedAt === undefined) {
297
317
  if (r.status === "pending") c.pending++;
298
- else c.active++;
318
+ else if (r.status === "paused") c.paused++;
319
+ else if (r.status === "running") c.active++;
320
+ else if (r.status === "completed") c.completed++;
321
+ else c.failed++;
299
322
  } else if (r.status === "completed") c.completed++;
300
323
  else c.failed++;
301
324
  }
@@ -306,6 +329,9 @@ function themedBadges(c: Counts, theme: GraphTheme): FlatBandBadge[] {
306
329
  const out: FlatBandBadge[] = [];
307
330
  if (c.completed > 0) out.push({ text: `✓ ${c.completed}`, fg: theme.success });
308
331
  if (c.active > 0) out.push({ text: `● ${c.active}`, fg: theme.warning });
332
+ // Keep the word label: the pause glyph is less familiar than the other
333
+ // status glyphs, so this intentional asymmetry improves scanability.
334
+ if (c.paused > 0) out.push({ text: `❚❚ ${c.paused} paused`, fg: theme.warning });
309
335
  if (c.pending > 0) out.push({ text: `○ ${c.pending}`, fg: theme.dim });
310
336
  if (c.failed > 0) out.push({ text: `⊘ ${c.failed}`, fg: theme.error });
311
337
  return out;
@@ -315,6 +341,9 @@ function plainBadges(c: Counts): FlatBandBadge[] {
315
341
  const out: FlatBandBadge[] = [];
316
342
  if (c.completed > 0) out.push({ text: `✓ ${c.completed}` });
317
343
  if (c.active > 0) out.push({ text: `● ${c.active}` });
344
+ // Keep the word label: the pause glyph is less familiar than the other
345
+ // status glyphs, so this intentional asymmetry improves scanability.
346
+ if (c.paused > 0) out.push({ text: `❚❚ ${c.paused} paused` });
318
347
  if (c.pending > 0) out.push({ text: `○ ${c.pending}` });
319
348
  if (c.failed > 0) out.push({ text: `⊘ ${c.failed}` });
320
349
  return out;
@@ -344,6 +373,7 @@ function statusIconForRun(run: RunSnapshot): string {
344
373
  switch (run.status) {
345
374
  case "completed": return "✓";
346
375
  case "running": return "●";
376
+ case "paused": return "❚❚";
347
377
  case "failed": return "✗";
348
378
  case "killed": return "⊘";
349
379
  case "pending":
@@ -16,12 +16,15 @@ export interface Args {
16
16
  help?: boolean;
17
17
  version?: boolean;
18
18
  mode?: Mode;
19
+ name?: string;
19
20
  noSession?: boolean;
20
21
  session?: string;
22
+ sessionId?: string;
21
23
  fork?: string;
22
24
  sessionDir?: string;
23
25
  models?: string[];
24
26
  tools?: string[];
27
+ excludeTools?: string[];
25
28
  noTools?: boolean;
26
29
  noBuiltinTools?: boolean;
27
30
  extensions?: string[];
@@ -38,6 +41,7 @@ export interface Args {
38
41
  listModels?: string | true;
39
42
  offline?: boolean;
40
43
  verbose?: boolean;
44
+ projectTrustOverride?: boolean;
41
45
  messages: string[];
42
46
  fileArgs: string[];
43
47
  /** Unknown flags (potentially extension flags) - map of flag name to value */