@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,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/mcp",
3
- "version": "0.8.27",
3
+ "version": "0.8.28-alpha.2",
4
4
  "private": true,
5
5
  "description": "Atomic extension that adapts MCP (Model Context Protocol) servers into the coding agent. Fork of: https://github.com/nicobailon/pi-mcp-adapter",
6
6
  "contributors": [
@@ -50,7 +50,7 @@
50
50
  "dependencies": {
51
51
  "@modelcontextprotocol/ext-apps": "^1.7.2",
52
52
  "@modelcontextprotocol/sdk": "^1.25.1",
53
- "open": "^10.2.0",
53
+ "open": "^11.0.0",
54
54
  "typebox": "^1.1.24",
55
55
  "zod": "^3.25.0 || ^4.0.0"
56
56
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/subagents",
3
- "version": "0.8.27",
3
+ "version": "0.8.28-alpha.2",
4
4
  "private": true,
5
5
  "description": "Atomic extension for delegating tasks to subagents with chains, parallel execution, and TUI clarification. Fork of: https://github.com/nicobailon/pi-subagents",
6
6
  "contributors": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/web-access",
3
- "version": "0.8.27",
3
+ "version": "0.8.28-alpha.2",
4
4
  "private": true,
5
5
  "description": "Atomic extension for web search, URL fetching, GitHub repo cloning, PDF/video extraction. Fork of: https://github.com/nicobailon/pi-web-access",
6
6
  "contributors": [
@@ -6,6 +6,28 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.8.28-alpha.2] - 2026-06-10
10
+
11
+ ### Fixed
12
+
13
+ - Fixed the builtin `open-claude-design` workflow not installing the browser skill's `browse` CLI before it is needed. The workflow now runs an initial deterministic, best-effort setup step that probes `PATH` (`which`/`where browse`) and installs the CLI with `npm install -g browse` when missing (skipped under automated tests); per-run bootstrap guidance is derived from the outcome and injected into every browser-using stage (assume-available when ensured, with concrete recovery steps surfaced when the install failed), the install outcome is exposed via a new `browse_cli_status` output, and the read-only `read`/`grep`/`ls` tools are granted to the refinement and pre-export decision gates so they can inspect `preview.html` without mutating it. The step never throws or blocks the run, so stages keep their graceful-degradation fallback ([#1327](https://github.com/bastani-inc/atomic/issues/1327)).
14
+ - Fixed paused workflow run detail cards to surface the natural `workflow resume` action hint while preserving the interrupt hint for non-paused active runs ([#1283](https://github.com/bastani-inc/atomic/issues/1283)).
15
+ - Fixed paused workflow runs being counted as running and displayed as pending/running in `/workflow status` and `/workflow status <id>`, with paused runs now shown separately as `❚❚ paused` ([#1283](https://github.com/bastani-inc/atomic/issues/1283)).
16
+
17
+ ## [0.8.28-alpha.1] - 2026-06-09
18
+
19
+ ### Added
20
+
21
+ - Added workflow `ctx.ui.custom<T>(factory, options?)` for graph-visible custom TUI human-in-the-loop prompts. Custom prompts create `awaiting_input` prompt nodes, reuse the stage UI broker/attached stage chat component path, expose the same real TUI/theme/keybinding/component types as Atomic extension custom UI, participate in live-memory prompt replay through hashed custom identities, keep labels display-only/outside replay identity, honor prompt/run abort signals, and reject clearly in headless/unavailable UI modes. Iteration 1 supports inline graph rendering; `overlay: true` and non-TUI `workflow send` answers for arbitrary custom widget results return clear unsupported errors rather than silently degrading ([#1309](https://github.com/bastani-inc/atomic/issues/1309)).
22
+
23
+ ### Changed
24
+
25
+ - Changed workflow transcript introspection to return `sessionFile`/`transcriptPath` metadata with a lazy-read prompt by default when a transcript path exists, while keeping bounded inline previews behind explicit `tail`/`limit` requests and falling back to a small preview when no path is available ([#1314](https://github.com/bastani-inc/atomic/issues/1314)).
26
+
27
+ ### Fixed
28
+
29
+ - Fixed a workflow kill/abort race that could crash the entire CLI with a process-level uncaught exception (for example `No API key found for ...`). When a workflow was killed mid-prompt, the executor's `raceAbort` left the already-in-flight stage prompt promise unobserved; its later rejection escaped every workflow error boundary and became an unhandled rejection. `raceAbort` now always observes the in-flight promise in the already-aborted branch so a killed run can no longer orphan a rejecting prompt.
30
+
9
31
  ## [0.8.27] - 2026-06-08
10
32
 
11
33
  ### Changed
@@ -139,7 +139,9 @@ export default defineWorkflow("review-and-merge")
139
139
  .compile();
140
140
  ```
141
141
 
142
- Human input is runtime-only: call `ctx.ui.input`, `ctx.ui.confirm`, `ctx.ui.select`, or `ctx.ui.editor` at the point where the workflow actually needs a decision. No builder-level declaration is required or supported.
142
+ Human input is runtime-only: call `ctx.ui.input`, `ctx.ui.confirm`, `ctx.ui.select`, `ctx.ui.editor`, or `ctx.ui.custom<T>` at the point where the workflow actually needs a decision. No builder-level declaration is required or supported.
143
+
144
+ `ctx.ui.custom<T>(factory, options?)` mounts an arbitrary focused TUI component in the attached workflow graph/stage UI and resolves with the value passed to `done(value)`. The factory uses the same real TUI/theme/keybinding/component types as Atomic extension `ctx.ui.custom`. Use `options.label` for a safe display-only graph/status label and `options.replayIdentity` (do not include secrets) when the widget's semantics can change without the callsite changing; label text is not part of replay identity. Custom widget prompts require an interactive workflow graph; they are not answerable through non-TUI `workflow send` in iteration 1. Inline graph rendering is supported; `overlay: true` is rejected clearly because nested workflow graph overlays are not safely supported yet.
143
145
 
144
146
  ### Example 4 — Compose workflows
145
147
 
@@ -458,11 +460,11 @@ Tradeoff: `Type.Unsafe<T>()` does not deeply validate at runtime — it trusts t
458
460
 
459
461
  Input overrides are bare `key=value` tokens (no leading `--`). Values are JSON-parsed when possible, so numbers, booleans, and quoted strings work as expected (e.g. `count=3`, `flag=true`, `prompt="multi word value"`). A whole-object override can be passed as a single JSON token (e.g. `{"prompt":"...","count":3}`). Runtime validation is strict: unknown input keys, missing required values, type mismatches, and invalid `select` choices fail before a named workflow run starts.
460
462
 
461
- Workflows always run as **background tasks** in interactive sessions — the chat editor stays free while a run executes. Press **F2** (or `/workflow connect <run-id>`) to attach to the live graph viewer; HIL prompts (`ctx.ui.input/confirm/select/editor`) appear as awaiting-input graph nodes. Press Enter on the node to answer locally, never as a modal dialog over the chat. Human input is detected when those runtime `ctx.ui.*` calls execute; workflows no longer have a declaration-time HIL flag.
463
+ Workflows always run as **background tasks** in interactive sessions — the chat editor stays free while a run executes. Press **F2** (or `/workflow connect <run-id>`) to attach to the live graph viewer; HIL prompts (`ctx.ui.input/confirm/select/editor/custom`) appear as awaiting-input graph nodes. Press Enter on the node to answer locally, never as a modal dialog over the chat. Human input is detected when those runtime `ctx.ui.*` calls execute; workflows no longer have a declaration-time HIL flag.
462
464
 
463
465
  Nested `ctx.workflow(...)` calls are displayed as an expanded graph within the top-level run. `/workflow status` and run pickers list only top-level user-launched workflows, not implementation-owned child runs. The `workflow` tool's `stages`, `stage`, `transcript`, `send`, `pause`, `interrupt`, and `resume` actions can still target visible child stage ids, prefixes, or names from the expanded graph; Atomic routes the control action to the owning nested run internally. (`stages`, `stage`, `transcript`, and `send` are `workflow` tool actions, not `/workflow` slash subcommands; the slash command exposes `connect`, `attach`, `pause`, `list`, `status`, `interrupt`, `kill`, `resume`, `reload`, and `inputs`.)
464
466
 
465
- Prompt answer replay is live-memory only. `StageSnapshot.promptAnswerState` reports whether continuation can replay a prompt answer (`available`), must ask again because the private ledger entry is gone (`unavailable`), or must ask again because multiple matching prompt nodes are ambiguous (`ambiguous`). Raw answers stay in a private `PromptAnswerRecord` ledger, are never serialized to snapshots or persistence, and remain resident in memory until the answer is cleared, the run is removed, or the store is cleared. Replay keys include prompt kind, message text, select choices, input/editor initial value, and hashed author callsite, so changing any of those inputs may intentionally re-ask on continuation. Empty `ctx.ui.select(..., [])` calls throw before creating a prompt node.
467
+ Prompt answer replay is live-memory only. `StageSnapshot.promptAnswerState` reports whether continuation can replay a prompt answer (`available`), must ask again because the private ledger entry is gone (`unavailable`), or must ask again because multiple matching prompt nodes are ambiguous (`ambiguous`). Raw answers stay in a private `PromptAnswerRecord` ledger, are never serialized to snapshots or persistence, and remain resident in memory until the answer is cleared, the run is removed, or the store is cleared. Replay keys include prompt kind, message text, select choices, input/editor initial value, custom prompt identity hash, and hashed author callsite, so changing any of those inputs may intentionally re-ask on continuation. Empty `ctx.ui.select(..., [])` calls throw before creating a prompt node. Arbitrary custom-widget answers cannot be supplied with `workflow send`; focus the `custom` awaiting-input node in the interactive graph instead.
466
468
 
467
469
  ### `workflow` tool (LLM-callable)
468
470
 
@@ -471,7 +473,7 @@ Prompt answer replay is live-memory only. `StageSnapshot.promptAnswerState` repo
471
473
  ```json
472
474
  {
473
475
  "name": "workflow",
474
- "description": "Run named workflows or direct one-off task/tasks/chain workflows; discover with list/get/inputs, inspect status/stages/stage details, send prompt answers or steering, pause/resume/interrupt/kill runs, and reload workflow resources. For large stage handoffs, write context to files/artifacts, pass paths via reads, and prompt downstream agents to 'Read the file at <path>...' instead of injecting large previous text. For transcripts, prefer status/stages/stage to get sessionFile/transcriptPath, quote the exact path without rewriting separators (Windows backslashes are valid), search it with rg/grep, and read small ranges; transcript defaults to at most 5 recent entries and explicit tail/limit overrides that preview.",
476
+ "description": "Run named workflows or direct one-off task/tasks/chain workflows; discover with list/get/inputs, inspect status/stages/stage details, send prompt answers or steering, pause/resume/interrupt/kill runs, and reload workflow resources. For large stage handoffs, write context to files/artifacts, pass paths via reads, and prompt downstream agents to 'Read the file at <path>...' instead of injecting large previous text. For transcripts, prefer status/stages/stage to get sessionFile/transcriptPath, quote the exact path without rewriting separators (Windows backslashes are valid), then search it with rg/grep and read small ranges; transcript is path-only by default when sessionFile/transcriptPath exists, explicit tail/limit returns bounded previews, and missing transcript paths fall back to a small preview.",
475
477
  "parameters": {
476
478
  "workflow": "string (optional) — workflow ID or normalized name",
477
479
  "inputs": "object (optional) — key/value map of workflow inputs",
@@ -480,9 +482,9 @@ Prompt answer replay is live-memory only. `StageSnapshot.promptAnswerState` repo
480
482
  "stageId": "optional stage id, prefix, or name for stage-scoped actions; cannot be combined with all:true",
481
483
  "statusFilter": "optional stages filter: pending/running/awaiting_input/paused/blocked/completed/failed/skipped/all",
482
484
  "format": "optional agent-facing output format: text or json",
483
- "limit": "transcript-only explicit maximum number of recent entries; omitted with tail omitted uses the default 5-entry preview plus metadata/path",
485
+ "limit": "transcript-only explicit maximum number of recent entries; omitted with tail omitted uses the path-only default when sessionFile/transcriptPath exists",
484
486
  "tail": "transcript-only explicit last-N entry count; overrides limit for quick recent-context checks",
485
- "includeToolOutput": "transcript-only flag for explicit snapshot tool-event output; prefer rg/grep on the exact quoted sessionFile/transcriptPath for large outputs",
487
+ "includeToolOutput": "transcript-only flag for inlined snapshot preview/fallback tool-event output; does not bypass the path-only default; prefer rg/grep on the exact quoted sessionFile/transcriptPath for large outputs",
486
488
  "text": "optional string payload for send/resume; explicit empty text answers pending prompts",
487
489
  "response": "optional structured payload for answering pending prompts; explicit empty response is valid",
488
490
  "message": "optional string payload for send/resume when text is not provided",
@@ -506,8 +508,8 @@ Prompt answer replay is live-memory only. `StageSnapshot.promptAnswerState` repo
506
508
 
507
509
  - **`renderCall`** — renders a compact workflow call summary in the chat scroll.
508
510
  - **`renderResult`** — renders the result or dispatch banner; live progress continues through the widget and graph viewer. Named workflow runs are background-oriented.
509
- - **`transcript`** — reference-first with a small preview by default: use `status`, `stages`, or `stage` to identify the stage and its `sessionFile`/`transcriptPath`, quote the exact path without changing platform separators (for example, preserve Windows backslashes), then search that file with `rg`/`grep` for targeted terms and read only small surrounding ranges. Text results include JSON-escaped `sessionFileJson`/`transcriptPathJson` lines for copy-safe path literals plus up to 5 recent entries by default. Passing explicit `tail` or `limit` overrides that preview for quick context checks. A registered live stage handle is used when one exists, even before live messages arrive; otherwise the action falls back to stored stage snapshots. Snapshot entries are ordered chronologically before `tail`/`limit` is applied, with terminal result/error entries kept after tool entries when timestamps are missing or tied. `includeToolOutput` applies to snapshot tool-event results; live session transcripts may not expose tool output.
510
- - **`send`** — answers pending stage prompts only when `text`, `response`, or `message` is present; an explicit empty string is a valid answer, while an omitted payload is a no-op. `delivery: "auto"` answers pending prompts first, then resumes paused stages, steers streaming stages, or queues a follow-up.
511
+ - **`transcript`** — path-only by default when a transcript file exists: use `status`, `stages`, or `stage` to identify the stage and its `sessionFile`/`transcriptPath`, quote the exact path without changing platform separators (for example, preserve Windows backslashes), then search that file with `rg`/`grep` for targeted terms and read only small surrounding ranges. Default text results include JSON-escaped `sessionFileJson`/`transcriptPathJson` lines for copy-safe path literals plus a `lazyReadPrompt`, with `entries: not inlined` so transcript bodies and tool outputs stay out of model context. Passing explicit `tail` or `limit` opts into a bounded inline preview for quick context checks. If no transcript path is available, the action falls back to a bounded preview of up to 5 recent entries with a `fallbackNote`. A registered live stage handle is used when one exists, even before live messages arrive; otherwise the action falls back to stored stage snapshots. Snapshot entries are ordered chronologically before `tail`/`limit` is applied, with terminal result/error entries kept after tool entries when timestamps are missing or tied. `includeToolOutput` applies only to inlined snapshot previews or no-path fallback previews; live session transcripts may not expose tool output.
512
+ - **`send`** — answers pending primitive/structured stage prompts only when `text`, `response`, or `message` is present; an explicit empty string is a valid answer, while an omitted payload is a no-op. Arbitrary `ctx.ui.custom<T>` widget prompts require the interactive workflow graph and return a clear unsupported message when targeted through `send`. `delivery: "auto"` answers pending prompts first, then resumes paused stages, steers streaming stages, or queues a follow-up.
511
513
  - **`reload`** — refreshes workflow resources directly in-process instead of queuing a literal `/workflow reload` chat follow-up.
512
514
 
513
515
  ### F2 keyboard shortcut
@@ -520,7 +522,7 @@ Press **F2** while a workflow is running to open the DAG overlay for the active
520
522
 
521
523
  For interactive use, run workflows through `/workflow <name> [key=value ...]` or let the LLM call the `workflow` tool. In non-interactive (`-p` / `--print` / `--mode json`) sessions, `/workflow <name> key=value` and LLM calls to the `workflow` tool remain available for deterministic workflows. The input picker and graph picker are disabled, top-level `ctx.ui.*` is unavailable, and stage child sessions exclude `ask_user_question`. Named workflow dispatch waits for the terminal run snapshot before returning.
522
524
 
523
- Because human input is runtime-only and workflows no longer carry a declaration-time HIL marker, headless dispatch does not reject a workflow just because its source contains `ctx.ui.*`. If you copy the HIL example above into a non-interactive session, it can pass dispatch and then fail when execution reaches the prompt with an error such as `atomic-workflows: HIL ctx.ui.confirm is unavailable because Atomic runtime did not provide a UI adapter` (the primitive name varies). Run those workflows interactively, or guard/remove runtime `ctx.ui.*` calls before using headless mode.
525
+ Because human input is runtime-only and workflows no longer carry a declaration-time HIL marker, headless dispatch does not reject a workflow just because its source contains `ctx.ui.*`. If you copy the HIL example above into a non-interactive session, it can pass dispatch and then fail when execution reaches the prompt with an error such as `atomic-workflows: HIL ctx.ui.confirm is unavailable because Atomic runtime did not provide a UI adapter` (the primitive name varies, including `ctx.ui.custom`). Run those workflows interactively, or guard/remove runtime `ctx.ui.*` calls before using headless mode.
524
526
 
525
527
  For library or package authoring, define reusable workflows with the builder and export the compiled definition. Hand-written objects with `__piWorkflow: true` are rejected by discovery and composition; `defineWorkflow(...).compile()` is the public authoring surface. Standalone TypeScript workflow packages can import `defineWorkflow` and `Type` from `@bastani/workflows` directly with no local `.d.ts` file or `declare module` shim. The former imperative `runWorkflow` object-form API is removed; use compiled workflow definitions with the exported `run()` / registry helpers for programmatic execution.
526
528
 
@@ -23,7 +23,10 @@
23
23
  * a real HTML page on disk (`preview.html`). The workflow attempts to open it
24
24
  * through the `browser` skill so the user can interactively review;
25
25
  * when browser automation is unavailable, the file path is surfaced so the user
26
- * can open it manually. The final exporter produces a rich `spec.html` that
26
+ * can open it manually. Before any stage runs, an initial deterministic setup
27
+ * step ensures the browser skill's `browse` CLI is available (`which browse`,
28
+ * then `npm install -g browse` when missing); it is best-effort and never
29
+ * blocks the run. The final exporter produces a rich `spec.html` that
27
30
  * embeds the agreed-upon design alongside the implementation handoff.
28
31
  */
29
32
 
@@ -33,6 +36,7 @@ import type {
33
36
  WorkflowTaskResult,
34
37
  WorkflowTaskStep,
35
38
  } from "../src/shared/types.js";
39
+ import { spawnSync } from "node:child_process";
36
40
  import { mkdirSync } from "node:fs";
37
41
  import { tmpdir } from "node:os";
38
42
  import { join } from "node:path";
@@ -49,6 +53,15 @@ type OutputType = (typeof OUTPUT_TYPES)[number];
49
53
  const DEFAULT_OUTPUT_TYPE: OutputType = "prototype";
50
54
  const DEFAULT_MAX_REFINEMENTS = 3;
51
55
 
56
+ /**
57
+ * Read-only builtin tools granted to the structured-decision stages
58
+ * (user-feedback refinement gate and pre-export gate) so they can actually
59
+ * inspect the on-disk `preview.html` before emitting their decision. The
60
+ * artifact stays immutable here — writes/edits belong to apply-changes and
61
+ * forced-fix, so this list deliberately excludes write/edit/bash.
62
+ */
63
+ const READ_ONLY_TOOLS = ["read", "grep", "ls"] as const;
64
+
52
65
  type PromptSection = readonly [tag: string, content: string];
53
66
 
54
67
  function taggedPrompt(sections: readonly PromptSection[]): string {
@@ -275,11 +288,126 @@ const ANTI_SLOP_RULES = [
275
288
  "Commit to a specific aesthetic direction; do not hedge with generic SaaS defaults.",
276
289
  ].join("\n");
277
290
 
278
- const BROWSER_USE_BOOTSTRAP_RULES = [
279
- "Probe for the browser skill's `browse` CLI with `which browse`; if it is unavailable, install the CLI with `npm install -g browse` as documented by the skill, then retry once. Do not add project dependencies.",
280
- "Use `browse open <url> --local --headed` when a generated local preview should be visible to the user, and use `browse snapshot` plus `browse screenshot --path <file>` for review evidence.",
281
- "If `browse` is unavailable after three attempts or the browser runtime still fails, degrade gracefully and surface the manual file path / URL.",
282
- ].join("\n");
291
+ type BrowseCliStatus = {
292
+ /** Whether the `browse` CLI is expected to be available to downstream stages. */
293
+ readonly available: boolean;
294
+ /** True when the CLI was already on PATH and no install was attempted. */
295
+ readonly alreadyPresent: boolean;
296
+ /** True when this step installed the CLI via `npm install -g browse`. */
297
+ readonly installed: boolean;
298
+ /** Human-readable, single-line outcome surfaced as a workflow output. */
299
+ readonly summary: string;
300
+ /** Raw failure reason when the install could not complete; absent on success. */
301
+ readonly error?: string;
302
+ };
303
+
304
+ /**
305
+ * Initial deterministic setup step (no LLM): ensure the browser skill's `browse`
306
+ * CLI is available before any design stage runs. Mirrors the browser skill's
307
+ * documented bootstrap (`which browse || npm install -g browse`) but performs it
308
+ * once, deterministically, instead of relying on each stage to probe/install it.
309
+ * The PATH probe always runs, but the actual global install is skipped under
310
+ * automated tests (`NODE_ENV=test`) to avoid slow, networked, environment-
311
+ * mutating side effects.
312
+ *
313
+ * Best-effort by contract: it never throws and never blocks the workflow. When
314
+ * the CLI cannot be located or installed, downstream stages keep their graceful
315
+ * degradation path (surface the manual preview path / URL).
316
+ */
317
+ function ensureBrowseCli(): BrowseCliStatus {
318
+ const isWindows = process.platform === "win32";
319
+ const onPath = (): boolean => {
320
+ try {
321
+ const probe = spawnSync(isWindows ? "where" : "which", ["browse"], {
322
+ stdio: "ignore",
323
+ timeout: 15_000,
324
+ shell: isWindows,
325
+ });
326
+ return probe.status === 0;
327
+ } catch {
328
+ return false;
329
+ }
330
+ };
331
+
332
+ if (onPath()) {
333
+ return {
334
+ available: true,
335
+ alreadyPresent: true,
336
+ installed: false,
337
+ summary: "browse CLI already on PATH; skipped install.",
338
+ };
339
+ }
340
+
341
+ // Never perform a real global `npm install` during automated tests: it is
342
+ // slow, network-dependent, and would mutate the test runner's global
343
+ // environment. The PATH probe above and the prompt guidance below are still
344
+ // exercised; only the install side effect is skipped.
345
+ if (process.env.NODE_ENV === "test") {
346
+ return {
347
+ available: false,
348
+ alreadyPresent: false,
349
+ installed: false,
350
+ summary:
351
+ "browse CLI not found; skipped global install under the test environment.",
352
+ error: "global install skipped during tests",
353
+ };
354
+ }
355
+
356
+ try {
357
+ const install = spawnSync("npm", ["install", "-g", "browse"], {
358
+ stdio: "ignore",
359
+ timeout: 180_000,
360
+ shell: isWindows,
361
+ });
362
+ if (install.status === 0) {
363
+ return {
364
+ available: true,
365
+ alreadyPresent: false,
366
+ installed: true,
367
+ summary: "Installed browse CLI via `npm install -g browse`.",
368
+ };
369
+ }
370
+ const reason =
371
+ install.error?.message ??
372
+ (typeof install.status === "number"
373
+ ? `npm install -g browse exited with code ${install.status}`
374
+ : "npm install -g browse did not complete");
375
+ return {
376
+ available: false,
377
+ alreadyPresent: false,
378
+ installed: false,
379
+ summary: `Could not install browse CLI (${reason}); stages will degrade gracefully.`,
380
+ error: reason,
381
+ };
382
+ } catch (error) {
383
+ const reason =
384
+ error instanceof Error ? error.message : String(error);
385
+ return {
386
+ available: false,
387
+ alreadyPresent: false,
388
+ installed: false,
389
+ summary: `Could not install browse CLI (${reason}); stages will degrade gracefully.`,
390
+ error: reason,
391
+ };
392
+ }
393
+ }
394
+
395
+ /**
396
+ * Build the per-run browser bootstrap guidance injected into stage prompts.
397
+ * When the deterministic setup step already ensured `browse` is installed, the
398
+ * guidance tells stages to assume availability and not waste turns reinstalling;
399
+ * otherwise it retains the original probe-and-install fallback.
400
+ */
401
+ function buildBrowserBootstrapRules(status: BrowseCliStatus): string {
402
+ const probeRule = status.available
403
+ ? "The workflow's deterministic setup step already ensured the browser skill's `browse` CLI is installed and on PATH; assume it is available and do NOT reinstall it. Only if a `browse` command reports the executable as missing should you re-probe with `which browse` and run `npm install -g browse` once before retrying. Do not add project dependencies."
404
+ : `The workflow's deterministic setup step attempted to install the browser skill's \`browse\` CLI but it FAILED with: "${status.error ?? "unknown error"}". Treat this as a known starting condition to work around, not a hard blocker. Probe with \`which browse\` and retry once with \`npm install -g browse\`; if it still fails, use the error above to diagnose a workaround (for example: EACCES/permission errors → retry with a user-writable global prefix; missing npm/Node → report it plainly; network/registry errors → surface them). If the CLI still cannot be made available, degrade gracefully and surface the manual file path / URL. Do not add project dependencies.`;
405
+ return [
406
+ probeRule,
407
+ "Use `browse open <url> --local --headed` when a generated local preview should be visible to the user, and use `browse snapshot` plus `browse screenshot --path <file>` for review evidence.",
408
+ "If `browse` is unavailable after three attempts or the browser runtime still fails, degrade gracefully and surface the manual file path / URL.",
409
+ ].join("\n");
410
+ }
283
411
 
284
412
  export default defineWorkflow("open-claude-design")
285
413
  .description(
@@ -316,7 +444,15 @@ export default defineWorkflow("open-claude-design")
316
444
  .output("preview_file_url", Type.Optional(Type.String({ description: "file:// URL for the generated preview.html file." })))
317
445
  .output("spec_path", Type.Optional(Type.String({ description: "Absolute path to the generated spec.html file." })))
318
446
  .output("spec_file_url", Type.Optional(Type.String({ description: "file:// URL for the generated spec.html file." })))
447
+ .output("browse_cli_status", Type.Optional(Type.String({ description: "Outcome of the initial deterministic step that ensures the browser skill's `browse` CLI is installed." })))
319
448
  .run(async (ctx) => {
449
+ // Initial deterministic setup step (no LLM): ensure the browser skill's
450
+ // `browse` CLI is installed before any design stage runs. Best-effort —
451
+ // a failed install never blocks the workflow; downstream stages keep their
452
+ // graceful-degradation fallback (surface the manual preview path / URL).
453
+ const browseCli = ensureBrowseCli();
454
+ const browserBootstrapRules = buildBrowserBootstrapRules(browseCli);
455
+
320
456
  const inputs = ctx.inputs;
321
457
 
322
458
  const prompt = inputs.prompt;
@@ -344,12 +480,12 @@ export default defineWorkflow("open-claude-design")
344
480
  };
345
481
  const refinementDecisionConfig = {
346
482
  ...designModelConfig,
347
- tools: [refinementDecisionTool.name],
483
+ tools: [...READ_ONLY_TOOLS, refinementDecisionTool.name],
348
484
  customTools: [refinementDecisionTool],
349
485
  };
350
486
  const exportGateDecisionConfig = {
351
487
  ...designModelConfig,
352
- tools: [exportGateDecisionTool.name],
488
+ tools: [...READ_ONLY_TOOLS, exportGateDecisionTool.name],
353
489
  customTools: [exportGateDecisionTool],
354
490
  };
355
491
 
@@ -551,7 +687,7 @@ export default defineWorkflow("open-claude-design")
551
687
  `Capture transferable design intent from this reference for: ${prompt}. Apply the impeccable \`extract\` sub-skill to lift concrete, citable design traits from the reference URL. Use browser/screenshot tooling if available; never guess about visual traits without observable evidence.`,
552
688
  ],
553
689
  ["reference_url", reference],
554
- ["browser_use_guidelines", BROWSER_USE_BOOTSTRAP_RULES],
690
+ ["browser_use_guidelines", browserBootstrapRules],
555
691
  [
556
692
  "instructions",
557
693
  [
@@ -671,7 +807,7 @@ export default defineWorkflow("open-claude-design")
671
807
  ],
672
808
  ["preview_path", previewPath],
673
809
  ["preview_file_url", previewFileUrl],
674
- ["browser_use_guidelines", BROWSER_USE_BOOTSTRAP_RULES],
810
+ ["browser_use_guidelines", browserBootstrapRules],
675
811
  [
676
812
  "instructions",
677
813
  [
@@ -794,7 +930,7 @@ export default defineWorkflow("open-claude-design")
794
930
  ["current_design_and_feedback", "{previous}"],
795
931
  [
796
932
  "browser_use_guidelines",
797
- BROWSER_USE_BOOTSTRAP_RULES,
933
+ browserBootstrapRules,
798
934
  ],
799
935
  [
800
936
  "instructions",
@@ -881,7 +1017,7 @@ export default defineWorkflow("open-claude-design")
881
1017
  ["preview_file_url", previewFileUrl],
882
1018
  [
883
1019
  "browser_use_bootstrap",
884
- BROWSER_USE_BOOTSTRAP_RULES,
1020
+ browserBootstrapRules,
885
1021
  ],
886
1022
  [
887
1023
  "instructions",
@@ -1044,7 +1180,7 @@ export default defineWorkflow("open-claude-design")
1044
1180
  ["spec_file_url", specFileUrl],
1045
1181
  ["preview_path", previewPath],
1046
1182
  ["preview_file_url", previewFileUrl],
1047
- ["browser_use_guidelines", BROWSER_USE_BOOTSTRAP_RULES],
1183
+ ["browser_use_guidelines", browserBootstrapRules],
1048
1184
  [
1049
1185
  "instructions",
1050
1186
  [
@@ -1078,6 +1214,7 @@ export default defineWorkflow("open-claude-design")
1078
1214
  preview_file_url: previewFileUrl,
1079
1215
  spec_path: specPath,
1080
1216
  spec_file_url: specFileUrl,
1217
+ browse_cli_status: browseCli.summary,
1081
1218
  };
1082
1219
  })
1083
1220
  .compile();
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/workflows",
3
- "version": "0.8.27",
3
+ "version": "0.8.28-alpha.2",
4
4
  "private": true,
5
5
  "description": "Atomic extension for multi-stage workflow authoring and execution.",
6
6
  "contributors": [
@@ -57,7 +57,7 @@ export declare const Type: Omit<typeof TypeboxType, "Any" | "Array" | "BigInt" |
57
57
  Void(): TVoid;
58
58
  };
59
59
  export type { Static, TSchema } from "typebox";
60
- export type { AgentSessionAdapter, CompleteAdapter, CompleteStageOpts, GitWorktreeSetupOptions, GitWorktreeSetupResult, PromptAdapter, PromptOptions, ResolvedInputs, RunResult, RunStatus, StageAdapters, StageStatus, StageOptions, StageContext, StageSnapshot, StageExecutionMeta, StageMcpOptions, StageOutputOptions, StagePromptOptions, StageSessionCreateOptions, StageSessionCreateResult, StageSessionRuntime, WorkflowAction, WorkflowArtifact, WorkflowChainOptions, WorkflowChainStep, WorkflowChildResult, WorkflowContextMode, WorkflowControlEvent, WorkflowCustomToolDefinition, WorkflowDetails, WorkflowDetailsMode, WorkflowDetailsStatus, WorkflowDirectOptions, WorkflowDirectTaskItem, WorkflowExecutionMode, WorkflowExecutionPolicy, WorkflowInputBindings, WorkflowInputSchema, WorkflowInputSchemaMap, WorkflowInputValues, WorkflowIntercomSummary, WorkflowMaxOutput, WorkflowMcpPort, WorkflowModelAttempt, WorkflowModelCatalogPort, WorkflowModelFallbackFields, WorkflowModelInfo, WorkflowModelUsage, WorkflowModelValue, WorkflowOutputMode, WorkflowOutputSchema, WorkflowOutputSchemaMap, WorkflowOutputValues, WorkflowParallelChainStep, WorkflowParallelOptions, WorkflowPersistencePort, WorkflowProgressSummary, WorkflowRunChildOptions, WorkflowRunOutput, WorkflowRuntimeConfig, WorkflowSerializableObject, WorkflowSerializablePrimitive, WorkflowSerializableValue, WorkflowSharedTaskDefaults, WorkflowTaskContext, WorkflowTaskContextInput, WorkflowTaskOptions, WorkflowTaskResult, WorkflowTaskSessionFields, WorkflowTaskSessionOptions, WorkflowTaskStep, WorkflowThinkingLevel, WorkflowUIAdapter, WorkflowUIContext, WorkflowWorktreeInputBinding, } from "./shared/authoring-contract.js";
60
+ export type { AgentSessionAdapter, CompleteAdapter, CompleteStageOpts, GitWorktreeSetupOptions, GitWorktreeSetupResult, PromptAdapter, PromptOptions, ResolvedInputs, RunResult, RunStatus, StageAdapters, StageStatus, StageOptions, StageContext, StageSnapshot, StageExecutionMeta, StageMcpOptions, StageOutputOptions, StagePromptOptions, StageSessionCreateOptions, StageSessionCreateResult, StageSessionRuntime, WorkflowAction, WorkflowArtifact, WorkflowChainOptions, WorkflowChainStep, WorkflowChildResult, WorkflowContextMode, WorkflowControlEvent, WorkflowCustomToolDefinition, WorkflowCustomUiComponent, WorkflowCustomUiFactory, WorkflowCustomUiKeybindings, WorkflowCustomUiOptions, WorkflowCustomUiOverlayHandle, WorkflowCustomUiOverlayOptions, WorkflowCustomUiTheme, WorkflowCustomUiTui, WorkflowDetails, WorkflowDetailsMode, WorkflowDetailsStatus, WorkflowDirectOptions, WorkflowDirectTaskItem, WorkflowExecutionMode, WorkflowExecutionPolicy, WorkflowInputBindings, WorkflowInputSchema, WorkflowInputSchemaMap, WorkflowInputValues, WorkflowIntercomSummary, WorkflowMaxOutput, WorkflowMcpPort, WorkflowModelAttempt, WorkflowModelCatalogPort, WorkflowModelFallbackFields, WorkflowModelInfo, WorkflowModelUsage, WorkflowModelValue, WorkflowOutputMode, WorkflowOutputSchema, WorkflowOutputSchemaMap, WorkflowOutputValues, WorkflowParallelChainStep, WorkflowParallelOptions, WorkflowPersistencePort, WorkflowProgressSummary, WorkflowRunChildOptions, WorkflowRunOutput, WorkflowRuntimeConfig, WorkflowSerializableObject, WorkflowSerializablePrimitive, WorkflowSerializableValue, WorkflowSharedTaskDefaults, WorkflowTaskContext, WorkflowTaskContextInput, WorkflowTaskOptions, WorkflowTaskResult, WorkflowTaskSessionFields, WorkflowTaskSessionOptions, WorkflowTaskStep, WorkflowThinkingLevel, WorkflowUIAdapter, WorkflowUIContext, WorkflowWorktreeInputBinding, } from "./shared/authoring-contract.js";
61
61
  import type * as AuthoringContract from "./shared/authoring-contract.js";
62
62
  import type { GitWorktreeSetupOptions, GitWorktreeSetupResult, ResolvedInputs, RunResult, RunStatus, StageSnapshot, WorkflowDefinition as WorkflowContractDefinition, WorkflowDetails, WorkflowDirectOptions, WorkflowDirectTaskItem, WorkflowExecutionPolicy, WorkflowInputValues, WorkflowOutputValues, WorkflowSerializableObject, WorkflowChainStep } from "./shared/authoring-contract.js";
63
63
  declare const workflowDefinitionBrand: unique symbol;
@@ -118,13 +118,16 @@ export interface StageNode extends WorkflowSerializableObject {
118
118
  readonly parentIds: readonly string[];
119
119
  }
120
120
  export type NoticeLevel = "info" | "warning" | "error";
121
- export type PromptKind = "input" | "confirm" | "select" | "editor";
121
+ export type PromptKind = "input" | "confirm" | "select" | "editor" | "custom";
122
+ export type CustomPromptIdentitySource = "caller" | "factory" | "callsite";
122
123
  export interface PendingPrompt extends WorkflowSerializableObject {
123
124
  readonly id: string;
124
125
  readonly kind: PromptKind;
125
126
  readonly message: string;
126
127
  readonly choices?: readonly string[];
127
128
  readonly initial?: string;
129
+ readonly customIdentityHash?: string;
130
+ readonly customIdentitySource?: CustomPromptIdentitySource;
128
131
  readonly createdAt: number;
129
132
  }
130
133
  export interface ToolEvent {
@@ -36,8 +36,10 @@ import type {
36
36
  } from "../shared/store-types.js";
37
37
  import type { WorkflowUIAdapter } from "../shared/types.js";
38
38
 
39
+ type BackgroundPromptKind = Exclude<PromptKind, "custom">;
40
+
39
41
  interface PromptDescriptor {
40
- readonly kind: PromptKind;
42
+ readonly kind: BackgroundPromptKind;
41
43
  readonly message: string;
42
44
  readonly choices?: readonly string[];
43
45
  readonly initial?: string;
@@ -76,7 +76,6 @@ export function installWorkflowHilAnswerNotifications(
76
76
  if (typeof send !== "function") return () => undefined;
77
77
 
78
78
  const state = options.state ?? createWorkflowHilAnswerNotificationState();
79
- let previousSnapshot = options.store.snapshot();
80
79
 
81
80
  const emitOnce = (details: WorkflowHilAnswerNoticeDetails): void => {
82
81
  const key = answerNoticeKey(details.runId, details.stageId, details.promptId, details.promptKind);
@@ -86,23 +85,21 @@ export function installWorkflowHilAnswerNotifications(
86
85
  sendHilAnswerNotice(send, details);
87
86
  };
88
87
 
89
- const inspectSimplePromptAnswers = (snapshot: StoreSnapshot): void => {
90
- for (const previousRun of previousSnapshot.runs) {
91
- const currentRun = snapshot.runs.find((run) => run.id === previousRun.id);
92
- if (currentRun === undefined) continue;
93
-
94
- for (const previousStage of previousRun.stages) {
95
- const answeredPrompt = simplePromptAnswer(previousStage, currentRun);
96
- if (answeredPrompt === undefined) continue;
97
- const answerRecord = options.store.getStagePromptAnswer(currentRun.id, answeredPrompt.stage.id);
98
- if (answerRecord?.answerSource === "workflow_tool") continue;
99
- emitOnce(makeSimplePromptAnswerNotice(currentRun, answeredPrompt.stage, answeredPrompt.prompt, answerRecord?.value));
88
+ const inspectWorkflowPromptAnswers = (snapshot: StoreSnapshot): void => {
89
+ for (const currentRun of snapshot.runs) {
90
+ for (const currentStage of currentRun.stages) {
91
+ const prompt = workflowPromptAnswerCandidate(currentStage);
92
+ if (prompt === undefined) continue;
93
+ const answerRecord = options.store.getStagePromptAnswer(currentRun.id, currentStage.id);
94
+ if (answerRecord === undefined) continue;
95
+ if (answerRecord.promptId !== prompt.id) continue;
96
+ if (answerRecord.answerSource === "workflow_tool") continue;
97
+ emitOnce(makeSimplePromptAnswerNotice(currentRun, currentStage, prompt, answerRecord.value, answerRecord.answeredAt));
100
98
  }
101
99
  }
102
- previousSnapshot = snapshot;
103
100
  };
104
101
 
105
- const unsubscribeStore = options.store.subscribe(inspectSimplePromptAnswers);
102
+ const unsubscribeStore = options.store.subscribe(inspectWorkflowPromptAnswers);
106
103
  const unsubscribeBroker = options.stageUiBroker?.onStagePromptResolved((event) => {
107
104
  if (event.answerSource === "workflow_tool") return;
108
105
  const answeredStage = findStageSnapshot(options.store.snapshot(), event.runId, event.stageId);
@@ -180,17 +177,11 @@ function sendHilAnswerNotice(
180
177
  }
181
178
  }
182
179
 
183
- function simplePromptAnswer(
184
- previousStage: StageSnapshot,
185
- currentRun: RunSnapshot,
186
- ): { stage: StageSnapshot; prompt: PendingPrompt } | undefined {
187
- const prompt = previousStage.pendingPrompt;
180
+ function workflowPromptAnswerCandidate(stage: StageSnapshot): PendingPrompt | undefined {
181
+ const prompt = stage.promptFootprint;
188
182
  if (prompt === undefined) return undefined;
189
- const currentStage = currentRun.stages.find((stage) => stage.id === previousStage.id);
190
- if (currentStage === undefined) return undefined;
191
- if (currentStage.pendingPrompt !== undefined) return undefined;
192
- if (currentStage.promptAnswerState !== "available") return undefined;
193
- return { stage: currentStage, prompt };
183
+ if (stage.promptAnswerState !== "available") return undefined;
184
+ return prompt;
194
185
  }
195
186
 
196
187
  function findStageSnapshot(
@@ -215,6 +206,7 @@ function makeSimplePromptAnswerNotice(
215
206
  stage: StageSnapshot,
216
207
  prompt: PendingPrompt,
217
208
  answer: unknown,
209
+ answeredAt: number,
218
210
  ): WorkflowHilAnswerNoticeDetails {
219
211
  return {
220
212
  kind: "hil_answered",
@@ -226,7 +218,7 @@ function makeSimplePromptAnswerNotice(
226
218
  promptId: prompt.id,
227
219
  promptKind: prompt.kind,
228
220
  promptMessage: truncateAnswerSnippet(prompt.message),
229
- answeredAt: Date.now(),
221
+ answeredAt,
230
222
  answerAvailable: true,
231
223
  answerIncluded: true,
232
224
  answerSummary: formatAnswerSummary(answer),