@bastani/atomic 0.9.13-alpha.1 → 0.9.13-alpha.3

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 (1174) hide show
  1. package/CHANGELOG.md +144 -0
  2. package/README.md +36 -18
  3. package/dist/builtin/i-have-adhd/CHANGELOG.md +17 -0
  4. package/dist/builtin/i-have-adhd/LICENSE +21 -0
  5. package/dist/builtin/i-have-adhd/README.md +18 -0
  6. package/dist/builtin/i-have-adhd/index.ts +238 -0
  7. package/dist/builtin/i-have-adhd/package.json +56 -0
  8. package/dist/builtin/i-have-adhd/skills/i-have-adhd/SKILL.md +140 -0
  9. package/dist/builtin/intercom/CHANGELOG.md +33 -0
  10. package/dist/builtin/intercom/README.md +36 -15
  11. package/dist/builtin/intercom/broker/bounded-stderr-install.ts +18 -0
  12. package/dist/builtin/intercom/broker/bounded-stderr.ts +132 -0
  13. package/dist/builtin/intercom/broker/broker.ts +12 -23
  14. package/dist/builtin/intercom/broker/client.ts +70 -3
  15. package/dist/builtin/intercom/broker/paths.ts +9 -0
  16. package/dist/builtin/intercom/broker/presence-handler.ts +103 -0
  17. package/dist/builtin/intercom/broker/spawn.ts +128 -29
  18. package/dist/builtin/intercom/foreground-detach-handoff.ts +30 -14
  19. package/dist/builtin/intercom/group.ts +64 -25
  20. package/dist/builtin/intercom/incoming-message-delivery.ts +1 -1
  21. package/dist/builtin/intercom/index-heavy.ts +38 -5
  22. package/dist/builtin/intercom/index.ts +8 -4
  23. package/dist/builtin/intercom/intercom-tool.ts +83 -6
  24. package/dist/builtin/intercom/intercom-utils.ts +3 -6
  25. package/dist/builtin/intercom/lazy-subagent-ack.ts +11 -6
  26. package/dist/builtin/intercom/package.json +2 -3
  27. package/dist/builtin/intercom/result-renderers.ts +1 -1
  28. package/dist/builtin/intercom/runtime-group.ts +13 -0
  29. package/dist/builtin/intercom/session-target.ts +1 -15
  30. package/dist/builtin/intercom/skills/intercom/SKILL.md +35 -7
  31. package/dist/builtin/intercom/subagent-relay.ts +32 -16
  32. package/dist/builtin/intercom/terminal-ordering-barrier.ts +23 -6
  33. package/dist/builtin/intercom/types.ts +3 -1
  34. package/dist/builtin/intercom/ui/compose.ts +8 -6
  35. package/dist/builtin/intercom/ui/inline-message.ts +7 -5
  36. package/dist/builtin/intercom/ui/session-list.ts +30 -15
  37. package/dist/builtin/mcp/CHANGELOG.md +13 -0
  38. package/dist/builtin/mcp/glimpse-ui.ts +2 -1
  39. package/dist/builtin/mcp/index.ts +1 -11
  40. package/dist/builtin/mcp/mcp-panel.ts +35 -34
  41. package/dist/builtin/mcp/mcp-setup-panel.ts +35 -33
  42. package/dist/builtin/mcp/npx-resolver.ts +3 -2
  43. package/dist/builtin/mcp/package.json +3 -3
  44. package/dist/builtin/mcp/sampling-handler.ts +5 -1
  45. package/dist/builtin/mcp/server-manager.ts +4 -7
  46. package/dist/builtin/subagents/CHANGELOG.md +52 -0
  47. package/dist/builtin/subagents/README.md +140 -383
  48. package/dist/builtin/subagents/agents/worker.md +1 -1
  49. package/dist/builtin/subagents/package.json +5 -5
  50. package/dist/builtin/subagents/prompts/parallel-cleanup.md +1 -1
  51. package/dist/builtin/subagents/prompts/parallel-context-build.md +2 -2
  52. package/dist/builtin/subagents/prompts/parallel-handoff-plan.md +4 -4
  53. package/dist/builtin/subagents/prompts/parallel-review.md +1 -1
  54. package/dist/builtin/subagents/prompts/review-loop.md +2 -2
  55. package/dist/builtin/subagents/skills/subagent/SKILL.md +55 -154
  56. package/dist/builtin/subagents/skills/tmux/SKILL.md +1 -1
  57. package/dist/builtin/subagents/src/agents/agent-discovery.ts +1 -29
  58. package/dist/builtin/subagents/src/agents/agent-loaders.ts +1 -40
  59. package/dist/builtin/subagents/src/agents/agent-management-helpers.ts +6 -135
  60. package/dist/builtin/subagents/src/agents/agent-management.ts +52 -282
  61. package/dist/builtin/subagents/src/agents/agent-paths.ts +0 -22
  62. package/dist/builtin/subagents/src/agents/agent-types.ts +0 -40
  63. package/dist/builtin/subagents/src/agents/agents.ts +0 -3
  64. package/dist/builtin/subagents/src/agents/identity.ts +2 -4
  65. package/dist/builtin/subagents/src/agents/skills-paths.ts +8 -1
  66. package/dist/builtin/subagents/src/extension/control-notices.ts +2 -3
  67. package/dist/builtin/subagents/src/extension/doctor.ts +4 -36
  68. package/dist/builtin/subagents/src/extension/fanout-child.ts +1 -17
  69. package/dist/builtin/subagents/src/extension/index.ts +18 -77
  70. package/dist/builtin/subagents/src/extension/notification-content.ts +1 -1
  71. package/dist/builtin/subagents/src/extension/prompt-guidance.ts +3 -3
  72. package/dist/builtin/subagents/src/extension/schemas.ts +3 -165
  73. package/dist/builtin/subagents/src/extension/startup-maintenance.ts +0 -2
  74. package/dist/builtin/subagents/src/extension/tool-description.ts +6 -16
  75. package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +7 -3
  76. package/dist/builtin/subagents/src/intercom/result-intercom.ts +25 -68
  77. package/dist/builtin/subagents/src/intercom/supervisor-authorization.ts +9 -2
  78. package/dist/builtin/subagents/src/runs/{background → foreground}/completion-notification.ts +10 -5
  79. package/dist/builtin/subagents/src/runs/foreground/execution-updates.ts +0 -5
  80. package/dist/builtin/subagents/src/runs/foreground/execution.ts +1 -4
  81. package/dist/builtin/subagents/src/runs/foreground/inprocess-run-sync.ts +119 -80
  82. package/dist/builtin/subagents/src/runs/{background → foreground}/notify.ts +58 -22
  83. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-context.ts +22 -50
  84. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-input.ts +10 -173
  85. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +9 -4
  86. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +11 -2
  87. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-runtime.ts +0 -5
  88. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +39 -22
  89. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-status.ts +36 -16
  90. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +2 -19
  91. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-worktree.ts +1 -14
  92. package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +150 -69
  93. package/dist/builtin/subagents/src/runs/inprocess/index.ts +1 -1
  94. package/dist/builtin/subagents/src/runs/inprocess/runner.ts +348 -94
  95. package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-api.ts +0 -7
  96. package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-core.ts +0 -10
  97. package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-projection.ts +3 -110
  98. package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-sanitize.ts +1 -7
  99. package/dist/builtin/subagents/src/runs/shared/intercom-group.ts +23 -7
  100. package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +0 -86
  101. package/dist/builtin/subagents/src/runs/shared/subagent-control.ts +1 -1
  102. package/dist/builtin/subagents/src/runs/shared/worktree.ts +7 -2
  103. package/dist/builtin/subagents/src/shared/formatters.ts +5 -61
  104. package/dist/builtin/subagents/src/shared/model-resolution.ts +78 -0
  105. package/dist/builtin/subagents/src/shared/settings.ts +14 -350
  106. package/dist/builtin/subagents/src/shared/status-format.ts +4 -11
  107. package/dist/builtin/subagents/src/shared/types-config.ts +30 -31
  108. package/dist/builtin/subagents/src/shared/types-depth.ts +30 -56
  109. package/dist/builtin/subagents/src/shared/types-nested.ts +127 -0
  110. package/dist/builtin/subagents/src/shared/types-results.ts +11 -66
  111. package/dist/builtin/subagents/src/shared/types-runtime.ts +0 -10
  112. package/dist/builtin/subagents/src/shared/types.ts +1 -1
  113. package/dist/builtin/subagents/src/shared/utils.ts +6 -109
  114. package/dist/builtin/subagents/src/slash/bridge-settlement.ts +87 -0
  115. package/dist/builtin/subagents/src/slash/prompt-template-bridge.ts +47 -7
  116. package/dist/builtin/subagents/src/slash/slash-bridge.ts +27 -7
  117. package/dist/builtin/subagents/src/slash/slash-commands.ts +44 -99
  118. package/dist/builtin/subagents/src/slash/slash-live-state.ts +1 -92
  119. package/dist/builtin/subagents/src/tui/render-event-formatting.ts +2 -285
  120. package/dist/builtin/subagents/src/tui/render-layout.ts +4 -4
  121. package/dist/builtin/subagents/src/tui/render-progress.ts +89 -0
  122. package/dist/builtin/subagents/src/tui/render-result-compact.ts +43 -71
  123. package/dist/builtin/subagents/src/tui/render-result.ts +41 -99
  124. package/dist/builtin/subagents/src/tui/render-stable-output.ts +1 -39
  125. package/dist/builtin/subagents/src/tui/render.ts +0 -2
  126. package/dist/builtin/web-access/CHANGELOG.md +14 -0
  127. package/dist/builtin/web-access/chrome-cookies.ts +3 -2
  128. package/dist/builtin/web-access/github-api.ts +7 -6
  129. package/dist/builtin/web-access/github-extract.ts +2 -1
  130. package/dist/builtin/web-access/package.json +3 -3
  131. package/dist/builtin/web-access/subprocess.ts +3 -1
  132. package/dist/builtin/web-access/summary-review.ts +2 -2
  133. package/dist/builtin/web-access/web-search-features.ts +38 -22
  134. package/dist/builtin/web-access/web-search-summary.ts +2 -2
  135. package/dist/builtin/workflows/CHANGELOG.md +57 -0
  136. package/dist/builtin/workflows/README.md +44 -4
  137. package/dist/builtin/workflows/builtin/open-claude-design-utils.ts +3 -0
  138. package/dist/builtin/workflows/builtin/ralph-models.ts +25 -20
  139. package/dist/builtin/workflows/builtin/shared-prompts.ts +5 -2
  140. package/dist/builtin/workflows/package.json +2 -2
  141. package/dist/builtin/workflows/src/durable/backend.ts +29 -1
  142. package/dist/builtin/workflows/src/durable/completed-catalog-stage-groups.ts +123 -28
  143. package/dist/builtin/workflows/src/durable/completed-catalog.ts +230 -23
  144. package/dist/builtin/workflows/src/durable/completed-subtree.ts +22 -7
  145. package/dist/builtin/workflows/src/durable/dbos-backend.ts +42 -24
  146. package/dist/builtin/workflows/src/durable/dbos-envelope.ts +2 -1
  147. package/dist/builtin/workflows/src/durable/dbos-metadata.ts +4 -0
  148. package/dist/builtin/workflows/src/durable/local-command.ts +2 -1
  149. package/dist/builtin/workflows/src/durable/run-timing.ts +28 -7
  150. package/dist/builtin/workflows/src/durable/scoped-backend.ts +4 -0
  151. package/dist/builtin/workflows/src/durable/targeted-inspection.ts +110 -0
  152. package/dist/builtin/workflows/src/durable/types.ts +17 -1
  153. package/dist/builtin/workflows/src/durable/workflow-child-result.ts +3 -1
  154. package/dist/builtin/workflows/src/engine/primitives/workflow.ts +1 -1
  155. package/dist/builtin/workflows/src/engine/run-durable-finalize.ts +10 -2
  156. package/dist/builtin/workflows/src/engine/run-durable-stage-session.ts +2 -2
  157. package/dist/builtin/workflows/src/engine/run-durable-topology.ts +9 -2
  158. package/dist/builtin/workflows/src/engine/runtime.ts +19 -2
  159. package/dist/builtin/workflows/src/extension/atomic-stage-session.ts +7 -1
  160. package/dist/builtin/workflows/src/extension/companions.ts +1 -1
  161. package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +3 -0
  162. package/dist/builtin/workflows/src/extension/index.bundle.mjs +1624 -596
  163. package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +31 -3
  164. package/dist/builtin/workflows/src/extension/mcp.ts +13 -2
  165. package/dist/builtin/workflows/src/extension/render-result.ts +1 -0
  166. package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +6 -0
  167. package/dist/builtin/workflows/src/extension/ui-surface.ts +9 -20
  168. package/dist/builtin/workflows/src/extension/wiring.ts +33 -6
  169. package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +6 -1
  170. package/dist/builtin/workflows/src/extension/workflow-ports.ts +14 -6
  171. package/dist/builtin/workflows/src/extension/workflow-prompts.ts +11 -6
  172. package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +8 -0
  173. package/dist/builtin/workflows/src/extension/workflow-targets.ts +18 -10
  174. package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +2 -0
  175. package/dist/builtin/workflows/src/extension/workflow-tool-inspection.ts +31 -16
  176. package/dist/builtin/workflows/src/extension/workflow-tool-send.ts +75 -3
  177. package/dist/builtin/workflows/src/extension/workflow-tool.ts +53 -6
  178. package/dist/builtin/workflows/src/intercom/intercom-routing.ts +12 -6
  179. package/dist/builtin/workflows/src/intercom/result-intercom.ts +35 -4
  180. package/dist/builtin/workflows/src/runs/background/run-inspect.ts +5 -1
  181. package/dist/builtin/workflows/src/runs/background/status.ts +15 -0
  182. package/dist/builtin/workflows/src/runs/foreground/executor-abort.ts +11 -3
  183. package/dist/builtin/workflows/src/runs/foreground/executor-child-boundary.ts +2 -1
  184. package/dist/builtin/workflows/src/runs/foreground/executor-exit-manager.ts +26 -2
  185. package/dist/builtin/workflows/src/runs/foreground/executor-run-finalizers.ts +3 -2
  186. package/dist/builtin/workflows/src/runs/foreground/executor-stage-call.ts +94 -60
  187. package/dist/builtin/workflows/src/runs/foreground/executor-stage-context.ts +1 -1
  188. package/dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts +7 -7
  189. package/dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts +25 -4
  190. package/dist/builtin/workflows/src/runs/foreground/executor-stage-types.ts +4 -1
  191. package/dist/builtin/workflows/src/runs/foreground/executor-types.ts +2 -0
  192. package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +142 -4
  193. package/dist/builtin/workflows/src/runs/foreground/stage-runner-types.ts +2 -0
  194. package/dist/builtin/workflows/src/runs/foreground/stage-session-heartbeat.ts +88 -0
  195. package/dist/builtin/workflows/src/runs/shared/worktree-git-runner.ts +5 -2
  196. package/dist/builtin/workflows/src/runs/shared/worktree-setup.ts +2 -0
  197. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +5 -3
  198. package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +5 -3
  199. package/dist/builtin/workflows/src/shared/graph-store-snapshot.ts +34 -2
  200. package/dist/builtin/workflows/src/shared/persistence-restore-helpers.ts +23 -6
  201. package/dist/builtin/workflows/src/shared/stage-ui-broker.ts +10 -4
  202. package/dist/builtin/workflows/src/shared/store-public-types.ts +4 -2
  203. package/dist/builtin/workflows/src/shared/store-types.ts +1 -1
  204. package/dist/builtin/workflows/src/shared/workflow-artifact-env.ts +21 -0
  205. package/dist/builtin/workflows/src/shared/workflow-artifacts.ts +2 -5
  206. package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +37 -2
  207. package/dist/builtin/workflows/src/tui/graph-view-constants.ts +0 -15
  208. package/dist/builtin/workflows/src/tui/graph-view-graph-render.ts +38 -47
  209. package/dist/builtin/workflows/src/tui/graph-view-input.ts +48 -45
  210. package/dist/builtin/workflows/src/tui/graph-view-layout.ts +266 -0
  211. package/dist/builtin/workflows/src/tui/graph-view-render-helpers.ts +1 -86
  212. package/dist/builtin/workflows/src/tui/graph-view-render.ts +209 -91
  213. package/dist/builtin/workflows/src/tui/graph-view-state.ts +5 -7
  214. package/dist/builtin/workflows/src/tui/graph-view-types.ts +13 -7
  215. package/dist/builtin/workflows/src/tui/inline-form-editor.ts +8 -6
  216. package/dist/builtin/workflows/src/tui/inline-form-overlay.ts +2 -1
  217. package/dist/builtin/workflows/src/tui/inputs-overlay.ts +7 -4
  218. package/dist/builtin/workflows/src/tui/inputs-picker-input.ts +66 -0
  219. package/dist/builtin/workflows/src/tui/keybindings-adapter.ts +1 -0
  220. package/dist/builtin/workflows/src/tui/node-card.ts +1 -1
  221. package/dist/builtin/workflows/src/tui/overlay-adapter.ts +18 -46
  222. package/dist/builtin/workflows/src/tui/overlay-terminal-modes.ts +15 -26
  223. package/dist/builtin/workflows/src/tui/run-detail.ts +25 -12
  224. package/dist/builtin/workflows/src/tui/session-overlays.ts +5 -2
  225. package/dist/builtin/workflows/src/tui/session-picker.ts +27 -0
  226. package/dist/builtin/workflows/src/tui/stage-chat-view-footer-status.ts +5 -14
  227. package/dist/builtin/workflows/src/tui/stage-chat-view-input.ts +8 -7
  228. package/dist/builtin/workflows/src/tui/stage-chat-view-state.ts +12 -3
  229. package/dist/builtin/workflows/src/tui/stage-chat-view-types.ts +1 -11
  230. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +0 -8
  231. package/dist/builtin/workflows/src/tui/status-list.ts +1 -0
  232. package/dist/builtin/workflows/src/tui/store-widget-installer.ts +2 -6
  233. package/dist/builtin/workflows/src/tui/workflow-attach-pane-types.ts +0 -15
  234. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +2 -26
  235. package/dist/builtin/workflows/src/tui/workflow-resume-selector.ts +1 -0
  236. package/dist/builtin/workflows/src/tui/workflow-status.ts +3 -3
  237. package/dist/bun/split-loader.js +2 -0
  238. package/dist/bun/split-loader.js.map +1 -1
  239. package/dist/cli/args.d.ts.map +1 -1
  240. package/dist/cli/args.js +6 -2
  241. package/dist/cli/args.js.map +1 -1
  242. package/dist/cli/auth-check.d.ts +35 -0
  243. package/dist/cli/auth-check.d.ts.map +1 -0
  244. package/dist/cli/auth-check.js +100 -0
  245. package/dist/cli/auth-check.js.map +1 -0
  246. package/dist/cli/auth-command.d.ts +27 -0
  247. package/dist/cli/auth-command.d.ts.map +1 -0
  248. package/dist/cli/auth-command.js +150 -0
  249. package/dist/cli/auth-command.js.map +1 -0
  250. package/dist/cli/config-selector.js +2 -2
  251. package/dist/cli/config-selector.js.map +1 -1
  252. package/dist/cli/credential-print.d.ts +18 -23
  253. package/dist/cli/credential-print.d.ts.map +1 -1
  254. package/dist/cli/credential-print.js +42 -88
  255. package/dist/cli/credential-print.js.map +1 -1
  256. package/dist/cli/experimental/auth.d.ts +16 -0
  257. package/dist/cli/experimental/auth.d.ts.map +1 -0
  258. package/dist/cli/experimental/auth.js +13 -0
  259. package/dist/cli/experimental/auth.js.map +1 -0
  260. package/dist/cli/experimental/cli.d.ts +6 -0
  261. package/dist/cli/experimental/cli.d.ts.map +1 -0
  262. package/dist/cli/experimental/cli.js +5 -0
  263. package/dist/cli/experimental/cli.js.map +1 -0
  264. package/dist/cli/experimental/command-options.d.ts +17 -0
  265. package/dist/cli/experimental/command-options.d.ts.map +1 -0
  266. package/dist/cli/experimental/command-options.js +35 -0
  267. package/dist/cli/experimental/command-options.js.map +1 -0
  268. package/dist/cli/experimental/command.d.ts +63 -0
  269. package/dist/cli/experimental/command.d.ts.map +1 -0
  270. package/dist/cli/experimental/command.js +127 -0
  271. package/dist/cli/experimental/command.js.map +1 -0
  272. package/dist/cli/experimental/commands/client.d.ts +13 -0
  273. package/dist/cli/experimental/commands/client.d.ts.map +1 -0
  274. package/dist/cli/experimental/commands/client.js +25 -0
  275. package/dist/cli/experimental/commands/client.js.map +1 -0
  276. package/dist/cli/experimental/commands/pi.d.ts +15 -0
  277. package/dist/cli/experimental/commands/pi.d.ts.map +1 -0
  278. package/dist/cli/experimental/commands/pi.js +28 -0
  279. package/dist/cli/experimental/commands/pi.js.map +1 -0
  280. package/dist/cli/experimental/commands/server.d.ts +13 -0
  281. package/dist/cli/experimental/commands/server.d.ts.map +1 -0
  282. package/dist/cli/experimental/commands/server.js +25 -0
  283. package/dist/cli/experimental/commands/server.js.map +1 -0
  284. package/dist/cli/experimental/transport-address.d.ts +10 -0
  285. package/dist/cli/experimental/transport-address.d.ts.map +1 -0
  286. package/dist/cli/experimental/transport-address.js +38 -0
  287. package/dist/cli/experimental/transport-address.js.map +1 -0
  288. package/dist/cli/session-picker.js +2 -2
  289. package/dist/cli/session-picker.js.map +1 -1
  290. package/dist/cli/startup-ui.d.ts.map +1 -1
  291. package/dist/cli/startup-ui.js +4 -10
  292. package/dist/cli/startup-ui.js.map +1 -1
  293. package/dist/cli.js +2 -0
  294. package/dist/cli.js.map +1 -1
  295. package/dist/client/index.d.ts +3 -0
  296. package/dist/client/index.d.ts.map +1 -0
  297. package/dist/client/index.js +3 -0
  298. package/dist/client/index.js.map +1 -0
  299. package/dist/client/remote-session.d.ts +64 -0
  300. package/dist/client/remote-session.d.ts.map +1 -0
  301. package/dist/client/remote-session.js +351 -0
  302. package/dist/client/remote-session.js.map +1 -0
  303. package/dist/client/transcript.d.ts +12 -0
  304. package/dist/client/transcript.d.ts.map +1 -0
  305. package/dist/client/transcript.js +98 -0
  306. package/dist/client/transcript.js.map +1 -0
  307. package/dist/core/agent-session-auto-compaction.d.ts +17 -13
  308. package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
  309. package/dist/core/agent-session-auto-compaction.js +146 -64
  310. package/dist/core/agent-session-auto-compaction.js.map +1 -1
  311. package/dist/core/agent-session-bash.d.ts.map +1 -1
  312. package/dist/core/agent-session-bash.js +2 -0
  313. package/dist/core/agent-session-bash.js.map +1 -1
  314. package/dist/core/agent-session-compaction.d.ts +3 -6
  315. package/dist/core/agent-session-compaction.d.ts.map +1 -1
  316. package/dist/core/agent-session-compaction.js +64 -28
  317. package/dist/core/agent-session-compaction.js.map +1 -1
  318. package/dist/core/agent-session-events.d.ts +1 -11
  319. package/dist/core/agent-session-events.d.ts.map +1 -1
  320. package/dist/core/agent-session-events.js +28 -25
  321. package/dist/core/agent-session-events.js.map +1 -1
  322. package/dist/core/agent-session-export.d.ts.map +1 -1
  323. package/dist/core/agent-session-export.js +2 -1
  324. package/dist/core/agent-session-export.js.map +1 -1
  325. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  326. package/dist/core/agent-session-extension-bindings.js +4 -2
  327. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  328. package/dist/core/agent-session-methods.d.ts +14 -6
  329. package/dist/core/agent-session-methods.d.ts.map +1 -1
  330. package/dist/core/agent-session-methods.js.map +1 -1
  331. package/dist/core/agent-session-models.d.ts +1 -0
  332. package/dist/core/agent-session-models.d.ts.map +1 -1
  333. package/dist/core/agent-session-models.js +11 -4
  334. package/dist/core/agent-session-models.js.map +1 -1
  335. package/dist/core/agent-session-post-tool-compaction.d.ts.map +1 -1
  336. package/dist/core/agent-session-post-tool-compaction.js +22 -6
  337. package/dist/core/agent-session-post-tool-compaction.js.map +1 -1
  338. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  339. package/dist/core/agent-session-prompt.js +5 -0
  340. package/dist/core/agent-session-prompt.js.map +1 -1
  341. package/dist/core/agent-session-runtime-auth.d.ts.map +1 -1
  342. package/dist/core/agent-session-runtime-auth.js +3 -0
  343. package/dist/core/agent-session-runtime-auth.js.map +1 -1
  344. package/dist/core/agent-session-summary.d.ts +21 -0
  345. package/dist/core/agent-session-summary.d.ts.map +1 -0
  346. package/dist/core/agent-session-summary.js +156 -0
  347. package/dist/core/agent-session-summary.js.map +1 -0
  348. package/dist/core/agent-session-tool-hooks.d.ts.map +1 -1
  349. package/dist/core/agent-session-tool-hooks.js +25 -14
  350. package/dist/core/agent-session-tool-hooks.js.map +1 -1
  351. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  352. package/dist/core/agent-session-tool-registry.js +4 -4
  353. package/dist/core/agent-session-tool-registry.js.map +1 -1
  354. package/dist/core/agent-session-transfer.d.ts.map +1 -1
  355. package/dist/core/agent-session-transfer.js +0 -2
  356. package/dist/core/agent-session-transfer.js.map +1 -1
  357. package/dist/core/agent-session-tree.d.ts.map +1 -1
  358. package/dist/core/agent-session-tree.js +6 -0
  359. package/dist/core/agent-session-tree.js.map +1 -1
  360. package/dist/core/agent-session-types.d.ts +2 -0
  361. package/dist/core/agent-session-types.d.ts.map +1 -1
  362. package/dist/core/agent-session-types.js.map +1 -1
  363. package/dist/core/agent-session.d.ts +13 -3
  364. package/dist/core/agent-session.d.ts.map +1 -1
  365. package/dist/core/agent-session.js +38 -5
  366. package/dist/core/agent-session.js.map +1 -1
  367. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  368. package/dist/core/atomic-guide-command.js +4 -5
  369. package/dist/core/atomic-guide-command.js.map +1 -1
  370. package/dist/core/auth-storage.d.ts +18 -1
  371. package/dist/core/auth-storage.d.ts.map +1 -1
  372. package/dist/core/auth-storage.js +83 -0
  373. package/dist/core/auth-storage.js.map +1 -1
  374. package/dist/core/bash-executor.d.ts +5 -0
  375. package/dist/core/bash-executor.d.ts.map +1 -1
  376. package/dist/core/bash-executor.js +43 -19
  377. package/dist/core/bash-executor.js.map +1 -1
  378. package/dist/core/builtin-packages.d.ts.map +1 -1
  379. package/dist/core/builtin-packages.js +6 -0
  380. package/dist/core/builtin-packages.js.map +1 -1
  381. package/dist/core/codex-fast-mode.d.ts.map +1 -1
  382. package/dist/core/codex-fast-mode.js +8 -3
  383. package/dist/core/codex-fast-mode.js.map +1 -1
  384. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  385. package/dist/core/compaction/branch-summarization.js +1 -0
  386. package/dist/core/compaction/branch-summarization.js.map +1 -1
  387. package/dist/core/compaction/index.d.ts +1 -0
  388. package/dist/core/compaction/index.d.ts.map +1 -1
  389. package/dist/core/compaction/index.js +1 -0
  390. package/dist/core/compaction/index.js.map +1 -1
  391. package/dist/core/compaction/session-summarization.d.ts +41 -0
  392. package/dist/core/compaction/session-summarization.d.ts.map +1 -0
  393. package/dist/core/compaction/session-summarization.js +97 -0
  394. package/dist/core/compaction/session-summarization.js.map +1 -0
  395. package/dist/core/exec.d.ts.map +1 -1
  396. package/dist/core/exec.js +4 -3
  397. package/dist/core/exec.js.map +1 -1
  398. package/dist/core/extensions/agent-events.d.ts +0 -1
  399. package/dist/core/extensions/agent-events.d.ts.map +1 -1
  400. package/dist/core/extensions/agent-events.js.map +1 -1
  401. package/dist/core/extensions/api-types.d.ts +5 -3
  402. package/dist/core/extensions/api-types.d.ts.map +1 -1
  403. package/dist/core/extensions/api-types.js.map +1 -1
  404. package/dist/core/extensions/context-types.d.ts +15 -0
  405. package/dist/core/extensions/context-types.d.ts.map +1 -1
  406. package/dist/core/extensions/context-types.js.map +1 -1
  407. package/dist/core/extensions/event-results.d.ts +5 -0
  408. package/dist/core/extensions/event-results.d.ts.map +1 -1
  409. package/dist/core/extensions/event-results.js.map +1 -1
  410. package/dist/core/extensions/index.d.ts +2 -1
  411. package/dist/core/extensions/index.d.ts.map +1 -1
  412. package/dist/core/extensions/index.js +1 -0
  413. package/dist/core/extensions/index.js.map +1 -1
  414. package/dist/core/extensions/loader-api.d.ts.map +1 -1
  415. package/dist/core/extensions/loader-api.js +14 -1
  416. package/dist/core/extensions/loader-api.js.map +1 -1
  417. package/dist/core/extensions/loader-discovery.d.ts.map +1 -1
  418. package/dist/core/extensions/loader-discovery.js +3 -23
  419. package/dist/core/extensions/loader-discovery.js.map +1 -1
  420. package/dist/core/extensions/loader-runtime.d.ts.map +1 -1
  421. package/dist/core/extensions/loader-runtime.js +20 -3
  422. package/dist/core/extensions/loader-runtime.js.map +1 -1
  423. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  424. package/dist/core/extensions/loader-virtual-modules.js +7 -1
  425. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  426. package/dist/core/extensions/message-types.d.ts +6 -0
  427. package/dist/core/extensions/message-types.d.ts.map +1 -1
  428. package/dist/core/extensions/message-types.js.map +1 -1
  429. package/dist/core/extensions/provider-types.d.ts +9 -3
  430. package/dist/core/extensions/provider-types.d.ts.map +1 -1
  431. package/dist/core/extensions/provider-types.js.map +1 -1
  432. package/dist/core/extensions/runner-registries.d.ts +2 -1
  433. package/dist/core/extensions/runner-registries.d.ts.map +1 -1
  434. package/dist/core/extensions/runner-registries.js +3 -0
  435. package/dist/core/extensions/runner-registries.js.map +1 -1
  436. package/dist/core/extensions/runner-ui.d.ts.map +1 -1
  437. package/dist/core/extensions/runner-ui.js +1 -0
  438. package/dist/core/extensions/runner-ui.js.map +1 -1
  439. package/dist/core/extensions/runner.d.ts +2 -1
  440. package/dist/core/extensions/runner.d.ts.map +1 -1
  441. package/dist/core/extensions/runner.js +6 -2
  442. package/dist/core/extensions/runner.js.map +1 -1
  443. package/dist/core/extensions/runtime-types.d.ts +4 -1
  444. package/dist/core/extensions/runtime-types.d.ts.map +1 -1
  445. package/dist/core/extensions/runtime-types.js.map +1 -1
  446. package/dist/core/extensions/stale-context.d.ts +5 -0
  447. package/dist/core/extensions/stale-context.d.ts.map +1 -0
  448. package/dist/core/extensions/stale-context.js +11 -0
  449. package/dist/core/extensions/stale-context.js.map +1 -0
  450. package/dist/core/extensions/ui-types.d.ts +16 -11
  451. package/dist/core/extensions/ui-types.d.ts.map +1 -1
  452. package/dist/core/extensions/ui-types.js.map +1 -1
  453. package/dist/core/footer-data-provider.d.ts.map +1 -1
  454. package/dist/core/footer-data-provider.js +3 -2
  455. package/dist/core/footer-data-provider.js.map +1 -1
  456. package/dist/core/index.d.ts +1 -1
  457. package/dist/core/index.d.ts.map +1 -1
  458. package/dist/core/index.js.map +1 -1
  459. package/dist/core/intercom-runtime-group.d.ts +13 -0
  460. package/dist/core/intercom-runtime-group.d.ts.map +1 -0
  461. package/dist/core/intercom-runtime-group.js +23 -0
  462. package/dist/core/intercom-runtime-group.js.map +1 -0
  463. package/dist/core/keybindings.d.ts +44 -4
  464. package/dist/core/keybindings.d.ts.map +1 -1
  465. package/dist/core/model-config.d.ts +39 -5
  466. package/dist/core/model-config.d.ts.map +1 -1
  467. package/dist/core/model-config.js +6 -0
  468. package/dist/core/model-config.js.map +1 -1
  469. package/dist/core/model-registry.d.ts +12 -5
  470. package/dist/core/model-registry.d.ts.map +1 -1
  471. package/dist/core/model-registry.js +20 -12
  472. package/dist/core/model-registry.js.map +1 -1
  473. package/dist/core/model-resolver-cli.d.ts.map +1 -1
  474. package/dist/core/model-resolver-cli.js +46 -14
  475. package/dist/core/model-resolver-cli.js.map +1 -1
  476. package/dist/core/model-resolver-defaults.d.ts.map +1 -1
  477. package/dist/core/model-resolver-defaults.js +2 -0
  478. package/dist/core/model-resolver-defaults.js.map +1 -1
  479. package/dist/core/model-resolver-scope.d.ts +2 -0
  480. package/dist/core/model-resolver-scope.d.ts.map +1 -1
  481. package/dist/core/model-resolver-scope.js +12 -9
  482. package/dist/core/model-resolver-scope.js.map +1 -1
  483. package/dist/core/model-resolver.d.ts +1 -1
  484. package/dist/core/model-resolver.d.ts.map +1 -1
  485. package/dist/core/model-resolver.js +1 -1
  486. package/dist/core/model-resolver.js.map +1 -1
  487. package/dist/core/model-runtime-snapshot.d.ts +10 -0
  488. package/dist/core/model-runtime-snapshot.d.ts.map +1 -1
  489. package/dist/core/model-runtime-snapshot.js +14 -1
  490. package/dist/core/model-runtime-snapshot.js.map +1 -1
  491. package/dist/core/model-runtime-streaming.d.ts +3 -1
  492. package/dist/core/model-runtime-streaming.d.ts.map +1 -1
  493. package/dist/core/model-runtime-streaming.js +16 -0
  494. package/dist/core/model-runtime-streaming.js.map +1 -1
  495. package/dist/core/model-runtime-types.d.ts +2 -0
  496. package/dist/core/model-runtime-types.d.ts.map +1 -1
  497. package/dist/core/model-runtime-types.js.map +1 -1
  498. package/dist/core/model-runtime.d.ts +37 -10
  499. package/dist/core/model-runtime.d.ts.map +1 -1
  500. package/dist/core/model-runtime.js +312 -113
  501. package/dist/core/model-runtime.js.map +1 -1
  502. package/dist/core/oauth-login.d.ts.map +1 -1
  503. package/dist/core/oauth-login.js +2 -1
  504. package/dist/core/oauth-login.js.map +1 -1
  505. package/dist/core/openai-responses-payload-sanitizer.d.ts.map +1 -1
  506. package/dist/core/openai-responses-payload-sanitizer.js +18 -2
  507. package/dist/core/openai-responses-payload-sanitizer.js.map +1 -1
  508. package/dist/core/package-manager-git.d.ts.map +1 -1
  509. package/dist/core/package-manager-git.js +56 -10
  510. package/dist/core/package-manager-git.js.map +1 -1
  511. package/dist/core/package-manager-manifest.d.ts +1 -1
  512. package/dist/core/package-manager-manifest.d.ts.map +1 -1
  513. package/dist/core/package-manager-manifest.js +19 -9
  514. package/dist/core/package-manager-manifest.js.map +1 -1
  515. package/dist/core/package-manager-resource-collector.js.map +1 -1
  516. package/dist/core/package-manager-resource-files.d.ts.map +1 -1
  517. package/dist/core/package-manager-resource-files.js +1 -2
  518. package/dist/core/package-manager-resource-files.js.map +1 -1
  519. package/dist/core/provider-composer-internal.d.ts +10 -2
  520. package/dist/core/provider-composer-internal.d.ts.map +1 -1
  521. package/dist/core/provider-composer-internal.js +7 -3
  522. package/dist/core/provider-composer-internal.js.map +1 -1
  523. package/dist/core/provider-composer.d.ts.map +1 -1
  524. package/dist/core/provider-composer.js +19 -12
  525. package/dist/core/provider-composer.js.map +1 -1
  526. package/dist/core/provider-display-names.d.ts.map +1 -1
  527. package/dist/core/provider-display-names.js +2 -0
  528. package/dist/core/provider-display-names.js.map +1 -1
  529. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  530. package/dist/core/remote-catalog-provider.js +77 -67
  531. package/dist/core/remote-catalog-provider.js.map +1 -1
  532. package/dist/core/resolve-config-value.d.ts.map +1 -1
  533. package/dist/core/resolve-config-value.js +3 -0
  534. package/dist/core/resolve-config-value.js.map +1 -1
  535. package/dist/core/resource-loader-context-files.d.ts.map +1 -1
  536. package/dist/core/resource-loader-context-files.js +13 -5
  537. package/dist/core/resource-loader-context-files.js.map +1 -1
  538. package/dist/core/runtime-credentials.d.ts +5 -5
  539. package/dist/core/runtime-credentials.d.ts.map +1 -1
  540. package/dist/core/runtime-credentials.js +8 -8
  541. package/dist/core/runtime-credentials.js.map +1 -1
  542. package/dist/core/session-manager-core.d.ts +3 -1
  543. package/dist/core/session-manager-core.d.ts.map +1 -1
  544. package/dist/core/session-manager-core.js +9 -1
  545. package/dist/core/session-manager-core.js.map +1 -1
  546. package/dist/core/session-manager-entries.d.ts +24 -1
  547. package/dist/core/session-manager-entries.d.ts.map +1 -1
  548. package/dist/core/session-manager-entries.js +48 -0
  549. package/dist/core/session-manager-entries.js.map +1 -1
  550. package/dist/core/session-manager-list.d.ts.map +1 -1
  551. package/dist/core/session-manager-list.js +13 -1
  552. package/dist/core/session-manager-list.js.map +1 -1
  553. package/dist/core/session-manager-types.d.ts +10 -1
  554. package/dist/core/session-manager-types.d.ts.map +1 -1
  555. package/dist/core/session-manager-types.js.map +1 -1
  556. package/dist/core/settings-manager-basic-accessors.d.ts +3 -0
  557. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  558. package/dist/core/settings-manager-basic-accessors.js +5 -0
  559. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  560. package/dist/core/settings-manager-ui-accessors.d.ts +8 -1
  561. package/dist/core/settings-manager-ui-accessors.d.ts.map +1 -1
  562. package/dist/core/settings-manager-ui-accessors.js +31 -0
  563. package/dist/core/settings-manager-ui-accessors.js.map +1 -1
  564. package/dist/core/settings-manager.d.ts +2 -1
  565. package/dist/core/settings-manager.d.ts.map +1 -1
  566. package/dist/core/settings-manager.js.map +1 -1
  567. package/dist/core/settings-merge.d.ts.map +1 -1
  568. package/dist/core/settings-merge.js +13 -16
  569. package/dist/core/settings-merge.js.map +1 -1
  570. package/dist/core/settings-types.d.ts +9 -0
  571. package/dist/core/settings-types.d.ts.map +1 -1
  572. package/dist/core/settings-types.js.map +1 -1
  573. package/dist/core/slash-commands.d.ts.map +1 -1
  574. package/dist/core/slash-commands.js +2 -4
  575. package/dist/core/slash-commands.js.map +1 -1
  576. package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts +2 -2
  577. package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts.map +1 -1
  578. package/dist/core/tools/ask-user-question/state/questionnaire-session.js +39 -2
  579. package/dist/core/tools/ask-user-question/state/questionnaire-session.js.map +1 -1
  580. package/dist/core/tools/bash-pty-native.d.ts.map +1 -1
  581. package/dist/core/tools/bash-pty-native.js +2 -1
  582. package/dist/core/tools/bash-pty-native.js.map +1 -1
  583. package/dist/core/tools/bash.d.ts +9 -15
  584. package/dist/core/tools/bash.d.ts.map +1 -1
  585. package/dist/core/tools/bash.js +36 -96
  586. package/dist/core/tools/bash.js.map +1 -1
  587. package/dist/core/tools/directory-tree.d.ts +11 -0
  588. package/dist/core/tools/directory-tree.d.ts.map +1 -1
  589. package/dist/core/tools/directory-tree.js +26 -0
  590. package/dist/core/tools/directory-tree.js.map +1 -1
  591. package/dist/core/tools/edit.d.ts +4 -0
  592. package/dist/core/tools/edit.d.ts.map +1 -1
  593. package/dist/core/tools/edit.js +12 -8
  594. package/dist/core/tools/edit.js.map +1 -1
  595. package/dist/core/tools/errno.d.ts +25 -0
  596. package/dist/core/tools/errno.d.ts.map +1 -0
  597. package/dist/core/tools/errno.js +29 -0
  598. package/dist/core/tools/errno.js.map +1 -0
  599. package/dist/core/tools/fetch-url.d.ts +12 -0
  600. package/dist/core/tools/fetch-url.d.ts.map +1 -1
  601. package/dist/core/tools/fetch-url.js +76 -10
  602. package/dist/core/tools/fetch-url.js.map +1 -1
  603. package/dist/core/tools/find.d.ts +8 -1
  604. package/dist/core/tools/find.d.ts.map +1 -1
  605. package/dist/core/tools/find.js +20 -15
  606. package/dist/core/tools/find.js.map +1 -1
  607. package/dist/core/tools/grep.d.ts.map +1 -1
  608. package/dist/core/tools/grep.js +5 -1
  609. package/dist/core/tools/grep.js.map +1 -1
  610. package/dist/core/tools/index.d.ts +7 -7
  611. package/dist/core/tools/index.d.ts.map +1 -1
  612. package/dist/core/tools/index.js +11 -11
  613. package/dist/core/tools/index.js.map +1 -1
  614. package/dist/core/tools/ls.d.ts +4 -0
  615. package/dist/core/tools/ls.d.ts.map +1 -1
  616. package/dist/core/tools/ls.js +5 -1
  617. package/dist/core/tools/ls.js.map +1 -1
  618. package/dist/core/tools/output-accumulator.d.ts +8 -1
  619. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  620. package/dist/core/tools/output-accumulator.js +50 -28
  621. package/dist/core/tools/output-accumulator.js.map +1 -1
  622. package/dist/core/tools/oversized-tool-result.d.ts.map +1 -1
  623. package/dist/core/tools/oversized-tool-result.js +129 -22
  624. package/dist/core/tools/oversized-tool-result.js.map +1 -1
  625. package/dist/core/tools/persisted-output-file.d.ts +80 -0
  626. package/dist/core/tools/persisted-output-file.d.ts.map +1 -0
  627. package/dist/core/tools/persisted-output-file.js +284 -0
  628. package/dist/core/tools/persisted-output-file.js.map +1 -0
  629. package/dist/core/tools/read.d.ts +10 -0
  630. package/dist/core/tools/read.d.ts.map +1 -1
  631. package/dist/core/tools/read.js +20 -8
  632. package/dist/core/tools/read.js.map +1 -1
  633. package/dist/core/tools/search.d.ts +4 -0
  634. package/dist/core/tools/search.d.ts.map +1 -1
  635. package/dist/core/tools/search.js +5 -1
  636. package/dist/core/tools/search.js.map +1 -1
  637. package/dist/core/tools/session-temp-cleanup.d.ts +133 -0
  638. package/dist/core/tools/session-temp-cleanup.d.ts.map +1 -0
  639. package/dist/core/tools/session-temp-cleanup.js +669 -0
  640. package/dist/core/tools/session-temp-cleanup.js.map +1 -0
  641. package/dist/core/tools/session-temp-dir.d.ts +116 -0
  642. package/dist/core/tools/session-temp-dir.d.ts.map +1 -0
  643. package/dist/core/tools/session-temp-dir.js +408 -0
  644. package/dist/core/tools/session-temp-dir.js.map +1 -0
  645. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  646. package/dist/core/tools/tool-definition-wrapper.js +2 -0
  647. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  648. package/dist/core/tools/tool-limits.d.ts +11 -0
  649. package/dist/core/tools/tool-limits.d.ts.map +1 -1
  650. package/dist/core/tools/tool-limits.js +11 -0
  651. package/dist/core/tools/tool-limits.js.map +1 -1
  652. package/dist/core/tools/windows-directory-security.d.ts +82 -0
  653. package/dist/core/tools/windows-directory-security.d.ts.map +1 -0
  654. package/dist/core/tools/windows-directory-security.js +238 -0
  655. package/dist/core/tools/windows-directory-security.js.map +1 -0
  656. package/dist/core/tools/write.d.ts +4 -0
  657. package/dist/core/tools/write.d.ts.map +1 -1
  658. package/dist/core/tools/write.js +8 -4
  659. package/dist/core/tools/write.js.map +1 -1
  660. package/dist/core/trust-manager.js +1 -1
  661. package/dist/core/trust-manager.js.map +1 -1
  662. package/dist/core/usage-totals.js +1 -1
  663. package/dist/core/usage-totals.js.map +1 -1
  664. package/dist/extensions/llama/huggingface-ui.d.ts +1 -1
  665. package/dist/extensions/llama/huggingface-ui.d.ts.map +1 -1
  666. package/dist/extensions/llama/huggingface-ui.js +6 -5
  667. package/dist/extensions/llama/huggingface-ui.js.map +1 -1
  668. package/dist/extensions/llama/index.d.ts.map +1 -1
  669. package/dist/extensions/llama/index.js +11 -2
  670. package/dist/extensions/llama/index.js.map +1 -1
  671. package/dist/extensions/llama/provider.d.ts.map +1 -1
  672. package/dist/extensions/llama/provider.js +24 -8
  673. package/dist/extensions/llama/provider.js.map +1 -1
  674. package/dist/extensions/llama/ui.d.ts.map +1 -1
  675. package/dist/extensions/llama/ui.js +5 -2
  676. package/dist/extensions/llama/ui.js.map +1 -1
  677. package/dist/index-extensions.d.ts +2 -2
  678. package/dist/index-extensions.d.ts.map +1 -1
  679. package/dist/index-extensions.js +1 -1
  680. package/dist/index-extensions.js.map +1 -1
  681. package/dist/index.d.ts +5 -2
  682. package/dist/index.d.ts.map +1 -1
  683. package/dist/index.js +6 -2
  684. package/dist/index.js.map +1 -1
  685. package/dist/main-runtime-api-key.d.ts +2 -2
  686. package/dist/main-runtime-api-key.d.ts.map +1 -1
  687. package/dist/main-runtime-api-key.js +7 -2
  688. package/dist/main-runtime-api-key.js.map +1 -1
  689. package/dist/main-session.js +2 -2
  690. package/dist/main-session.js.map +1 -1
  691. package/dist/main.d.ts.map +1 -1
  692. package/dist/main.js +130 -26
  693. package/dist/main.js.map +1 -1
  694. package/dist/modes/index.d.ts +1 -0
  695. package/dist/modes/index.d.ts.map +1 -1
  696. package/dist/modes/index.js.map +1 -1
  697. package/dist/modes/interactive/components/assistant-message.d.ts +6 -2
  698. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  699. package/dist/modes/interactive/components/assistant-message.js +18 -5
  700. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  701. package/dist/modes/interactive/components/bordered-loader.d.ts +1 -1
  702. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  703. package/dist/modes/interactive/components/bordered-loader.js +5 -4
  704. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  705. package/dist/modes/interactive/components/branch-summary-message.d.ts +2 -1
  706. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  707. package/dist/modes/interactive/components/branch-summary-message.js +3 -2
  708. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  709. package/dist/modes/interactive/components/chat-message-renderer.d.ts +17 -7
  710. package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
  711. package/dist/modes/interactive/components/chat-message-renderer.js +35 -69
  712. package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
  713. package/dist/modes/interactive/components/chat-session-host-actions.d.ts.map +1 -1
  714. package/dist/modes/interactive/components/chat-session-host-actions.js +11 -3
  715. package/dist/modes/interactive/components/chat-session-host-actions.js.map +1 -1
  716. package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
  717. package/dist/modes/interactive/components/chat-session-host-events.js +25 -15
  718. package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
  719. package/dist/modes/interactive/components/chat-session-host-rendering.d.ts.map +1 -1
  720. package/dist/modes/interactive/components/chat-session-host-rendering.js +9 -4
  721. package/dist/modes/interactive/components/chat-session-host-rendering.js.map +1 -1
  722. package/dist/modes/interactive/components/chat-session-host-state.d.ts +2 -0
  723. package/dist/modes/interactive/components/chat-session-host-state.d.ts.map +1 -1
  724. package/dist/modes/interactive/components/chat-session-host-state.js +2 -0
  725. package/dist/modes/interactive/components/chat-session-host-state.js.map +1 -1
  726. package/dist/modes/interactive/components/chat-session-host.d.ts +9 -0
  727. package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
  728. package/dist/modes/interactive/components/chat-session-host.js +14 -0
  729. package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
  730. package/dist/modes/interactive/components/chat-transcript.d.ts +32 -0
  731. package/dist/modes/interactive/components/chat-transcript.d.ts.map +1 -1
  732. package/dist/modes/interactive/components/chat-transcript.js +173 -5
  733. package/dist/modes/interactive/components/chat-transcript.js.map +1 -1
  734. package/dist/modes/interactive/components/config-selector-list.d.ts +1 -1
  735. package/dist/modes/interactive/components/config-selector-list.d.ts.map +1 -1
  736. package/dist/modes/interactive/components/config-selector-list.js +9 -8
  737. package/dist/modes/interactive/components/config-selector-list.js.map +1 -1
  738. package/dist/modes/interactive/components/custom-editor.d.ts +1 -1
  739. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  740. package/dist/modes/interactive/components/custom-editor.js +32 -10
  741. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  742. package/dist/modes/interactive/components/custom-message.d.ts +2 -1
  743. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  744. package/dist/modes/interactive/components/custom-message.js +3 -2
  745. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  746. package/dist/modes/interactive/components/extension-editor.d.ts +1 -1
  747. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  748. package/dist/modes/interactive/components/extension-editor.js +3 -2
  749. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  750. package/dist/modes/interactive/components/extension-input.d.ts +1 -1
  751. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  752. package/dist/modes/interactive/components/extension-input.js +1 -0
  753. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  754. package/dist/modes/interactive/components/extension-selector.d.ts +1 -1
  755. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  756. package/dist/modes/interactive/components/extension-selector.js +4 -0
  757. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  758. package/dist/modes/interactive/components/fast-mode-selector.d.ts +1 -1
  759. package/dist/modes/interactive/components/fast-mode-selector.d.ts.map +1 -1
  760. package/dist/modes/interactive/components/fast-mode-selector.js +7 -5
  761. package/dist/modes/interactive/components/fast-mode-selector.js.map +1 -1
  762. package/dist/modes/interactive/components/first-time-setup.d.ts +1 -1
  763. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  764. package/dist/modes/interactive/components/first-time-setup.js +3 -0
  765. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  766. package/dist/modes/interactive/components/footer.js +2 -2
  767. package/dist/modes/interactive/components/footer.js.map +1 -1
  768. package/dist/modes/interactive/components/host-input-form.d.ts +1 -1
  769. package/dist/modes/interactive/components/host-input-form.d.ts.map +1 -1
  770. package/dist/modes/interactive/components/host-input-form.js +6 -5
  771. package/dist/modes/interactive/components/host-input-form.js.map +1 -1
  772. package/dist/modes/interactive/components/host-session-picker.d.ts.map +1 -1
  773. package/dist/modes/interactive/components/host-session-picker.js +1 -0
  774. package/dist/modes/interactive/components/host-session-picker.js.map +1 -1
  775. package/dist/modes/interactive/components/index.d.ts +1 -1
  776. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  777. package/dist/modes/interactive/components/index.js.map +1 -1
  778. package/dist/modes/interactive/components/login-dialog.d.ts +1 -1
  779. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  780. package/dist/modes/interactive/components/login-dialog.js +2 -1
  781. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  782. package/dist/modes/interactive/components/markdown-transform.d.ts +3 -0
  783. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -0
  784. package/dist/modes/interactive/components/markdown-transform.js +19 -0
  785. package/dist/modes/interactive/components/markdown-transform.js.map +1 -0
  786. package/dist/modes/interactive/components/mermaid.d.ts +11 -0
  787. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -0
  788. package/dist/modes/interactive/components/mermaid.js +81 -0
  789. package/dist/modes/interactive/components/mermaid.js.map +1 -0
  790. package/dist/modes/interactive/components/model-selector.d.ts +2 -2
  791. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  792. package/dist/modes/interactive/components/model-selector.js +9 -6
  793. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  794. package/dist/modes/interactive/components/oauth-selector.d.ts +1 -1
  795. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  796. package/dist/modes/interactive/components/oauth-selector.js +3 -2
  797. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  798. package/dist/modes/interactive/components/scoped-models-selector.d.ts +6 -2
  799. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  800. package/dist/modes/interactive/components/scoped-models-selector.js +39 -13
  801. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  802. package/dist/modes/interactive/components/session-selector-delete.d.ts.map +1 -1
  803. package/dist/modes/interactive/components/session-selector-delete.js +2 -1
  804. package/dist/modes/interactive/components/session-selector-delete.js.map +1 -1
  805. package/dist/modes/interactive/components/session-selector-list.d.ts +1 -1
  806. package/dist/modes/interactive/components/session-selector-list.d.ts.map +1 -1
  807. package/dist/modes/interactive/components/session-selector-list.js +41 -15
  808. package/dist/modes/interactive/components/session-selector-list.js.map +1 -1
  809. package/dist/modes/interactive/components/session-selector-search.js +1 -1
  810. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  811. package/dist/modes/interactive/components/session-selector.d.ts +1 -1
  812. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  813. package/dist/modes/interactive/components/session-selector.js +3 -3
  814. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  815. package/dist/modes/interactive/components/settings-selector-handlers.d.ts.map +1 -1
  816. package/dist/modes/interactive/components/settings-selector-handlers.js +9 -0
  817. package/dist/modes/interactive/components/settings-selector-handlers.js.map +1 -1
  818. package/dist/modes/interactive/components/settings-selector-items.d.ts.map +1 -1
  819. package/dist/modes/interactive/components/settings-selector-items.js +21 -0
  820. package/dist/modes/interactive/components/settings-selector-items.js.map +1 -1
  821. package/dist/modes/interactive/components/settings-selector-submenus.d.ts +3 -3
  822. package/dist/modes/interactive/components/settings-selector-submenus.d.ts.map +1 -1
  823. package/dist/modes/interactive/components/settings-selector-submenus.js +6 -1
  824. package/dist/modes/interactive/components/settings-selector-submenus.js.map +1 -1
  825. package/dist/modes/interactive/components/settings-selector-types.d.ts +8 -1
  826. package/dist/modes/interactive/components/settings-selector-types.d.ts.map +1 -1
  827. package/dist/modes/interactive/components/settings-selector-types.js.map +1 -1
  828. package/dist/modes/interactive/components/skill-invocation-message.d.ts +2 -1
  829. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  830. package/dist/modes/interactive/components/skill-invocation-message.js +3 -2
  831. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  832. package/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  833. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  834. package/dist/modes/interactive/components/tool-execution.js +50 -27
  835. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  836. package/dist/modes/interactive/components/tree-selector-component.d.ts +1 -1
  837. package/dist/modes/interactive/components/tree-selector-component.d.ts.map +1 -1
  838. package/dist/modes/interactive/components/tree-selector-component.js +2 -3
  839. package/dist/modes/interactive/components/tree-selector-component.js.map +1 -1
  840. package/dist/modes/interactive/components/tree-selector-content.d.ts.map +1 -1
  841. package/dist/modes/interactive/components/tree-selector-content.js +6 -0
  842. package/dist/modes/interactive/components/tree-selector-content.js.map +1 -1
  843. package/dist/modes/interactive/components/tree-selector-help.d.ts +1 -1
  844. package/dist/modes/interactive/components/tree-selector-help.d.ts.map +1 -1
  845. package/dist/modes/interactive/components/tree-selector-help.js +3 -1
  846. package/dist/modes/interactive/components/tree-selector-help.js.map +1 -1
  847. package/dist/modes/interactive/components/tree-selector-label-input.d.ts +1 -1
  848. package/dist/modes/interactive/components/tree-selector-label-input.d.ts.map +1 -1
  849. package/dist/modes/interactive/components/tree-selector-label-input.js +1 -0
  850. package/dist/modes/interactive/components/tree-selector-label-input.js.map +1 -1
  851. package/dist/modes/interactive/components/tree-selector-list.d.ts +1 -1
  852. package/dist/modes/interactive/components/tree-selector-list.d.ts.map +1 -1
  853. package/dist/modes/interactive/components/tree-selector-list.js +3 -0
  854. package/dist/modes/interactive/components/tree-selector-list.js.map +1 -1
  855. package/dist/modes/interactive/components/trust-selector.d.ts +1 -1
  856. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
  857. package/dist/modes/interactive/components/trust-selector.js +4 -0
  858. package/dist/modes/interactive/components/trust-selector.js.map +1 -1
  859. package/dist/modes/interactive/components/user-message-selector.d.ts +1 -1
  860. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  861. package/dist/modes/interactive/components/user-message-selector.js +4 -0
  862. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  863. package/dist/modes/interactive/components/user-message.d.ts +4 -1
  864. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  865. package/dist/modes/interactive/components/user-message.js +10 -2
  866. package/dist/modes/interactive/components/user-message.js.map +1 -1
  867. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  868. package/dist/modes/interactive/external-editor.js +2 -1
  869. package/dist/modes/interactive/external-editor.js.map +1 -1
  870. package/dist/modes/interactive/interactive-agent-events.js +36 -18
  871. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  872. package/dist/modes/interactive/interactive-auth-login.js +9 -2
  873. package/dist/modes/interactive/interactive-auth-login.js.map +1 -1
  874. package/dist/modes/interactive/interactive-auth-routing.d.ts.map +1 -1
  875. package/dist/modes/interactive/interactive-auth-routing.js +5 -1
  876. package/dist/modes/interactive/interactive-auth-routing.js.map +1 -1
  877. package/dist/modes/interactive/interactive-bash-compact.js +16 -4
  878. package/dist/modes/interactive/interactive-bash-compact.js.map +1 -1
  879. package/dist/modes/interactive/interactive-deferred-startup.d.ts.map +1 -1
  880. package/dist/modes/interactive/interactive-deferred-startup.js +3 -0
  881. package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -1
  882. package/dist/modes/interactive/interactive-editor-actions.js +2 -0
  883. package/dist/modes/interactive/interactive-editor-actions.js.map +1 -1
  884. package/dist/modes/interactive/interactive-extension-context.js +12 -7
  885. package/dist/modes/interactive/interactive-extension-context.js.map +1 -1
  886. package/dist/modes/interactive/interactive-extension-custom-ui.js +1 -0
  887. package/dist/modes/interactive/interactive-extension-custom-ui.js.map +1 -1
  888. package/dist/modes/interactive/interactive-extension-dialogs.js +7 -0
  889. package/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
  890. package/dist/modes/interactive/interactive-extension-widgets.js +7 -24
  891. package/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
  892. package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
  893. package/dist/modes/interactive/interactive-input-handling.js +9 -8
  894. package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
  895. package/dist/modes/interactive/interactive-mode-base.d.ts +52 -3
  896. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  897. package/dist/modes/interactive/interactive-mode-base.js +143 -5
  898. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  899. package/dist/modes/interactive/interactive-mode-deps.d.ts +2 -2
  900. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  901. package/dist/modes/interactive/interactive-mode-deps.js +2 -2
  902. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  903. package/dist/modes/interactive/interactive-mode-surface.d.ts +9 -3
  904. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  905. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  906. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  907. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  908. package/dist/modes/interactive/interactive-mode.js +1 -0
  909. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  910. package/dist/modes/interactive/interactive-model-routing.js +107 -41
  911. package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
  912. package/dist/modes/interactive/interactive-process-lifecycle.js +1 -1
  913. package/dist/modes/interactive/interactive-process-lifecycle.js.map +1 -1
  914. package/dist/modes/interactive/interactive-render-chat.js +24 -6
  915. package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
  916. package/dist/modes/interactive/interactive-selectors.js +44 -5
  917. package/dist/modes/interactive/interactive-selectors.js.map +1 -1
  918. package/dist/modes/interactive/interactive-session-runtime.js +1 -0
  919. package/dist/modes/interactive/interactive-session-runtime.js.map +1 -1
  920. package/dist/modes/interactive/interactive-slash-commands.js +9 -4
  921. package/dist/modes/interactive/interactive-slash-commands.js.map +1 -1
  922. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  923. package/dist/modes/interactive/interactive-startup.js +37 -18
  924. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  925. package/dist/modes/interactive/interactive-tui.d.ts +21 -0
  926. package/dist/modes/interactive/interactive-tui.d.ts.map +1 -0
  927. package/dist/modes/interactive/interactive-tui.js +279 -0
  928. package/dist/modes/interactive/interactive-tui.js.map +1 -0
  929. package/dist/modes/interactive/streaming-assistant-message.d.ts +34 -0
  930. package/dist/modes/interactive/streaming-assistant-message.d.ts.map +1 -0
  931. package/dist/modes/interactive/streaming-assistant-message.js +76 -0
  932. package/dist/modes/interactive/streaming-assistant-message.js.map +1 -0
  933. package/dist/modes/interactive/theme/catppuccin-frappe.json +1 -0
  934. package/dist/modes/interactive/theme/catppuccin-latte.json +1 -0
  935. package/dist/modes/interactive/theme/catppuccin-macchiato.json +1 -0
  936. package/dist/modes/interactive/theme/catppuccin-mocha.json +1 -0
  937. package/dist/modes/interactive/theme/dark.json +1 -0
  938. package/dist/modes/interactive/theme/light.json +1 -0
  939. package/dist/modes/interactive/theme/terminal-detection.d.ts +10 -0
  940. package/dist/modes/interactive/theme/terminal-detection.d.ts.map +1 -1
  941. package/dist/modes/interactive/theme/terminal-detection.js +19 -0
  942. package/dist/modes/interactive/theme/terminal-detection.js.map +1 -1
  943. package/dist/modes/interactive/theme/theme-class.d.ts +2 -2
  944. package/dist/modes/interactive/theme/theme-class.d.ts.map +1 -1
  945. package/dist/modes/interactive/theme/theme-class.js +5 -1
  946. package/dist/modes/interactive/theme/theme-class.js.map +1 -1
  947. package/dist/modes/interactive/theme/theme-controller.d.ts +3 -1
  948. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  949. package/dist/modes/interactive/theme/theme-controller.js +10 -13
  950. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  951. package/dist/modes/interactive/theme/theme-loading.d.ts.map +1 -1
  952. package/dist/modes/interactive/theme/theme-loading.js +1 -0
  953. package/dist/modes/interactive/theme/theme-loading.js.map +1 -1
  954. package/dist/modes/interactive/theme/theme-schema.d.ts +4 -0
  955. package/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  956. package/dist/modes/interactive/theme/theme-schema.js +2 -1
  957. package/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  958. package/dist/modes/interactive/theme/theme-schema.json +5 -1
  959. package/dist/modes/interactive/theme/theme.d.ts +1 -1
  960. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  961. package/dist/modes/interactive/theme/theme.js +1 -1
  962. package/dist/modes/interactive/theme/theme.js.map +1 -1
  963. package/dist/modes/interactive-engine/engine-custom-ui.d.ts +1 -1
  964. package/dist/modes/interactive-engine/engine-custom-ui.d.ts.map +1 -1
  965. package/dist/modes/interactive-engine/engine-custom-ui.js +28 -11
  966. package/dist/modes/interactive-engine/engine-custom-ui.js.map +1 -1
  967. package/dist/modes/interactive-engine/engine-render-service.js +3 -3
  968. package/dist/modes/interactive-engine/engine-render-service.js.map +1 -1
  969. package/dist/modes/interactive-engine/extension-ui-bridge.d.ts +2 -1
  970. package/dist/modes/interactive-engine/extension-ui-bridge.d.ts.map +1 -1
  971. package/dist/modes/interactive-engine/extension-ui-bridge.js +2 -2
  972. package/dist/modes/interactive-engine/extension-ui-bridge.js.map +1 -1
  973. package/dist/modes/interactive-engine/isolated-runtime.d.ts +7 -0
  974. package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
  975. package/dist/modes/interactive-engine/isolated-runtime.js +7 -0
  976. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  977. package/dist/modes/interactive-engine/protocol.d.ts +12 -10
  978. package/dist/modes/interactive-engine/protocol.d.ts.map +1 -1
  979. package/dist/modes/interactive-engine/protocol.js +18 -12
  980. package/dist/modes/interactive-engine/protocol.js.map +1 -1
  981. package/dist/modes/interactive-engine/remote-component.d.ts +11 -1
  982. package/dist/modes/interactive-engine/remote-component.d.ts.map +1 -1
  983. package/dist/modes/interactive-engine/remote-component.js +48 -8
  984. package/dist/modes/interactive-engine/remote-component.js.map +1 -1
  985. package/dist/modes/interactive-engine/terminal-mode-controller.d.ts +19 -12
  986. package/dist/modes/interactive-engine/terminal-mode-controller.d.ts.map +1 -1
  987. package/dist/modes/interactive-engine/terminal-mode-controller.js +54 -35
  988. package/dist/modes/interactive-engine/terminal-mode-controller.js.map +1 -1
  989. package/dist/modes/json-event.d.ts +28 -0
  990. package/dist/modes/json-event.d.ts.map +1 -0
  991. package/dist/modes/json-event.js +12 -0
  992. package/dist/modes/json-event.js.map +1 -0
  993. package/dist/modes/print-mode.d.ts.map +1 -1
  994. package/dist/modes/print-mode.js +2 -1
  995. package/dist/modes/print-mode.js.map +1 -1
  996. package/dist/modes/rpc/rpc-client-process.d.ts +1 -0
  997. package/dist/modes/rpc/rpc-client-process.d.ts.map +1 -1
  998. package/dist/modes/rpc/rpc-client-process.js +5 -1
  999. package/dist/modes/rpc/rpc-client-process.js.map +1 -1
  1000. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  1001. package/dist/modes/rpc/rpc-client.js +7 -2
  1002. package/dist/modes/rpc/rpc-client.js.map +1 -1
  1003. package/dist/modes/rpc/rpc-command-handler.js +1 -1
  1004. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  1005. package/dist/modes/rpc/rpc-event-buffer.d.ts +9 -0
  1006. package/dist/modes/rpc/rpc-event-buffer.d.ts.map +1 -1
  1007. package/dist/modes/rpc/rpc-event-buffer.js +10 -5
  1008. package/dist/modes/rpc/rpc-event-buffer.js.map +1 -1
  1009. package/dist/modes/rpc/rpc-extension-ui.d.ts.map +1 -1
  1010. package/dist/modes/rpc/rpc-extension-ui.js +3 -0
  1011. package/dist/modes/rpc/rpc-extension-ui.js.map +1 -1
  1012. package/dist/modes/rpc/rpc-input.js +1 -1
  1013. package/dist/modes/rpc/rpc-input.js.map +1 -1
  1014. package/dist/modes/rpc/rpc-output-buffer.d.ts +9 -0
  1015. package/dist/modes/rpc/rpc-output-buffer.d.ts.map +1 -1
  1016. package/dist/modes/rpc/rpc-output-buffer.js +10 -5
  1017. package/dist/modes/rpc/rpc-output-buffer.js.map +1 -1
  1018. package/dist/modes/rpc/rpc-provider-auth.d.ts.map +1 -1
  1019. package/dist/modes/rpc/rpc-provider-auth.js +3 -0
  1020. package/dist/modes/rpc/rpc-provider-auth.js.map +1 -1
  1021. package/dist/modes/rpc/rpc-responses.d.ts +1 -1
  1022. package/dist/modes/rpc/rpc-responses.d.ts.map +1 -1
  1023. package/dist/modes/rpc/rpc-responses.js +13 -1
  1024. package/dist/modes/rpc/rpc-responses.js.map +1 -1
  1025. package/dist/modes/rpc/rpc-session-binding.d.ts.map +1 -1
  1026. package/dist/modes/rpc/rpc-session-binding.js +2 -1
  1027. package/dist/modes/rpc/rpc-session-binding.js.map +1 -1
  1028. package/dist/modes/rpc/rpc-types.d.ts +9 -2
  1029. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  1030. package/dist/modes/rpc/rpc-types.js.map +1 -1
  1031. package/dist/rpc-entry.js +2 -0
  1032. package/dist/rpc-entry.js.map +1 -1
  1033. package/dist/self-update-plan.d.ts.map +1 -1
  1034. package/dist/self-update-plan.js +5 -4
  1035. package/dist/self-update-plan.js.map +1 -1
  1036. package/dist/server/create-harness.d.ts +53 -0
  1037. package/dist/server/create-harness.d.ts.map +1 -0
  1038. package/dist/server/create-harness.js +349 -0
  1039. package/dist/server/create-harness.js.map +1 -0
  1040. package/dist/utils/agent-attribution.d.ts +2 -0
  1041. package/dist/utils/agent-attribution.d.ts.map +1 -0
  1042. package/dist/utils/agent-attribution.js +2 -0
  1043. package/dist/utils/agent-attribution.js.map +1 -0
  1044. package/dist/utils/child-process.d.ts +3 -1
  1045. package/dist/utils/child-process.d.ts.map +1 -1
  1046. package/dist/utils/child-process.js +24 -4
  1047. package/dist/utils/child-process.js.map +1 -1
  1048. package/dist/utils/clipboard-image.d.ts.map +1 -1
  1049. package/dist/utils/clipboard-image.js +2 -1
  1050. package/dist/utils/clipboard-image.js.map +1 -1
  1051. package/dist/utils/clipboard.d.ts.map +1 -1
  1052. package/dist/utils/clipboard.js +12 -3
  1053. package/dist/utils/clipboard.js.map +1 -1
  1054. package/dist/utils/management-http.d.ts +23 -0
  1055. package/dist/utils/management-http.d.ts.map +1 -0
  1056. package/dist/utils/management-http.js +50 -0
  1057. package/dist/utils/management-http.js.map +1 -0
  1058. package/dist/utils/open-browser.d.ts.map +1 -1
  1059. package/dist/utils/open-browser.js +2 -1
  1060. package/dist/utils/open-browser.js.map +1 -1
  1061. package/dist/utils/paths.d.ts +2 -0
  1062. package/dist/utils/paths.d.ts.map +1 -1
  1063. package/dist/utils/paths.js +13 -0
  1064. package/dist/utils/paths.js.map +1 -1
  1065. package/dist/utils/shell.d.ts.map +1 -1
  1066. package/dist/utils/shell.js +17 -4
  1067. package/dist/utils/shell.js.map +1 -1
  1068. package/dist/utils/tool-result-images.d.ts +17 -0
  1069. package/dist/utils/tool-result-images.d.ts.map +1 -0
  1070. package/dist/utils/tool-result-images.js +41 -0
  1071. package/dist/utils/tool-result-images.js.map +1 -0
  1072. package/dist/utils/tools-manager.d.ts.map +1 -1
  1073. package/dist/utils/tools-manager.js +7 -8
  1074. package/dist/utils/tools-manager.js.map +1 -1
  1075. package/dist/utils/version-check.d.ts +4 -0
  1076. package/dist/utils/version-check.d.ts.map +1 -1
  1077. package/dist/utils/version-check.js +20 -2
  1078. package/dist/utils/version-check.js.map +1 -1
  1079. package/docs/compaction.md +2 -1
  1080. package/docs/custom-provider.md +15 -7
  1081. package/docs/development.md +1 -0
  1082. package/docs/docs.json +1 -0
  1083. package/docs/environment-variables.md +5 -1
  1084. package/docs/extensions.md +102 -18
  1085. package/docs/i-have-adhd.md +36 -0
  1086. package/docs/intercom.md +45 -26
  1087. package/docs/json.md +2 -2
  1088. package/docs/keybindings.md +55 -12
  1089. package/docs/models/model-selection.md +34 -8
  1090. package/docs/models.md +28 -3
  1091. package/docs/providers.md +20 -2
  1092. package/docs/quickstart.md +10 -6
  1093. package/docs/rpc.md +18 -12
  1094. package/docs/sdk.md +44 -8
  1095. package/docs/security.md +10 -10
  1096. package/docs/session-format.md +15 -0
  1097. package/docs/sessions.md +10 -0
  1098. package/docs/settings.md +31 -5
  1099. package/docs/subagents.md +27 -54
  1100. package/docs/themes.md +5 -3
  1101. package/docs/tools.md +23 -5
  1102. package/docs/tui.md +41 -24
  1103. package/docs/usage.md +41 -15
  1104. package/docs/windows.md +3 -1
  1105. package/docs/workflows.md +262 -38
  1106. package/examples/extensions/custom-provider-anthropic/index.ts +9 -2
  1107. package/examples/extensions/custom-provider-gitlab-duo/index.ts +9 -2
  1108. package/examples/extensions/modal-editor.ts +8 -10
  1109. package/examples/extensions/rainbow-editor.ts +3 -2
  1110. package/examples/extensions/subagent/README.md +16 -45
  1111. package/examples/extensions/subagent/index.ts +6 -96
  1112. package/examples/extensions/subagent/render.ts +0 -78
  1113. package/examples/extensions/subagent/runner.ts +0 -3
  1114. package/examples/extensions/subagent/schemas.ts +0 -13
  1115. package/examples/extensions/subagent/types.ts +1 -2
  1116. package/examples/sdk/09-api-keys-and-oauth.ts +6 -2
  1117. package/examples/sdk/12-full-control.ts +8 -2
  1118. package/examples/sdk/README.md +4 -1
  1119. package/npm-shrinkwrap.json +191 -634
  1120. package/package.json +14 -7
  1121. package/dist/builtin/subagents/src/agents/chain-serializer.ts +0 -257
  1122. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +0 -250
  1123. package/dist/builtin/subagents/src/runs/foreground/chain-execution-details.ts +0 -38
  1124. package/dist/builtin/subagents/src/runs/foreground/chain-execution-dynamic-step.ts +0 -280
  1125. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +0 -217
  1126. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-step.ts +0 -271
  1127. package/dist/builtin/subagents/src/runs/foreground/chain-execution-sequential-step.ts +0 -271
  1128. package/dist/builtin/subagents/src/runs/foreground/chain-execution-types.ts +0 -200
  1129. package/dist/builtin/subagents/src/runs/foreground/chain-execution.ts +0 -184
  1130. package/dist/builtin/subagents/src/runs/foreground/execution-structured-retries.ts +0 -19
  1131. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +0 -190
  1132. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-chain.ts +0 -109
  1133. package/dist/builtin/subagents/src/runs/inprocess/background-single.ts +0 -179
  1134. package/dist/builtin/subagents/src/runs/inprocess/background.ts +0 -89
  1135. package/dist/builtin/subagents/src/runs/shared/chain-outputs.ts +0 -126
  1136. package/dist/builtin/subagents/src/runs/shared/dynamic-fanout.ts +0 -393
  1137. package/dist/builtin/subagents/src/runs/shared/structured-output.ts +0 -150
  1138. package/dist/builtin/subagents/src/runs/shared/workflow-graph.ts +0 -232
  1139. package/dist/builtin/subagents/src/shared/types-async.ts +0 -270
  1140. package/dist/builtin/subagents/src/slash/saved-chain-mapping.ts +0 -60
  1141. package/dist/builtin/subagents/src/tui/render-chain-graph.ts +0 -341
  1142. package/dist/builtin/subagents/src/tui/render-widget-graph.ts +0 -266
  1143. package/dist/builtin/subagents/src/tui/render-widget.ts +0 -366
  1144. package/dist/core/async/format.d.ts +0 -3
  1145. package/dist/core/async/format.d.ts.map +0 -1
  1146. package/dist/core/async/format.js +0 -52
  1147. package/dist/core/async/format.js.map +0 -1
  1148. package/dist/core/async/job-manager.d.ts +0 -40
  1149. package/dist/core/async/job-manager.d.ts.map +0 -1
  1150. package/dist/core/async/job-manager.js +0 -293
  1151. package/dist/core/async/job-manager.js.map +0 -1
  1152. package/dist/core/async/session-manager.d.ts +0 -16
  1153. package/dist/core/async/session-manager.d.ts.map +0 -1
  1154. package/dist/core/async/session-manager.js +0 -34
  1155. package/dist/core/async/session-manager.js.map +0 -1
  1156. package/dist/core/async/types.d.ts +0 -23
  1157. package/dist/core/async/types.d.ts.map +0 -1
  1158. package/dist/core/async/types.js +0 -2
  1159. package/dist/core/async/types.js.map +0 -1
  1160. package/dist/core/tools/bash-async-execution.d.ts +0 -25
  1161. package/dist/core/tools/bash-async-execution.d.ts.map +0 -1
  1162. package/dist/core/tools/bash-async-execution.js +0 -78
  1163. package/dist/core/tools/bash-async-execution.js.map +0 -1
  1164. package/dist/core/tools/bash-async-jobs.d.ts +0 -30
  1165. package/dist/core/tools/bash-async-jobs.d.ts.map +0 -1
  1166. package/dist/core/tools/bash-async-jobs.js +0 -87
  1167. package/dist/core/tools/bash-async-jobs.js.map +0 -1
  1168. package/dist/core/tools/bash-async-output.d.ts +0 -12
  1169. package/dist/core/tools/bash-async-output.d.ts.map +0 -1
  1170. package/dist/core/tools/bash-async-output.js +0 -87
  1171. package/dist/core/tools/bash-async-output.js.map +0 -1
  1172. package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
  1173. package/examples/extensions/subagent/prompts/implement.md +0 -10
  1174. package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
@@ -35556,6 +35556,7 @@ Defaulting to 2020, but this will stop working in the future.`)), t3.ecmaVersion
35556
35556
  });
35557
35557
 
35558
35558
  // dist/builtin/workflows/src/intercom/intercom-routing.ts
35559
+ import { isStaleExtensionContextError } from "@bastani/atomic";
35559
35560
  function toNoticeLevel(raw) {
35560
35561
  if (raw === "warning" || raw === "error")
35561
35562
  return raw;
@@ -35579,12 +35580,17 @@ function buildIntercomCallbacks(deps) {
35579
35580
  requiresAck: true
35580
35581
  });
35581
35582
  const accepted = typeof confirm === "function" ? await confirm("Subagent needs decision", payload.message).catch(() => false) : false;
35582
- emit?.("subagent:control-intercom:response", {
35583
- requestId: payload.requestId ?? "",
35584
- runId: payload.runId ?? "",
35585
- stageId: payload.stageId ?? "",
35586
- accepted
35587
- });
35583
+ try {
35584
+ emit?.("subagent:control-intercom:response", {
35585
+ requestId: payload.requestId ?? "",
35586
+ runId: payload.runId ?? "",
35587
+ stageId: payload.stageId ?? "",
35588
+ accepted
35589
+ });
35590
+ } catch (error) {
35591
+ if (!isStaleExtensionContextError(error))
35592
+ throw error;
35593
+ }
35588
35594
  store.ackNotice(noticeId);
35589
35595
  },
35590
35596
  onNotify(payload) {
@@ -35611,6 +35617,7 @@ function buildIntercomCallbacks(deps) {
35611
35617
  }
35612
35618
 
35613
35619
  // dist/builtin/workflows/src/intercom/result-intercom.ts
35620
+ import { isStaleExtensionContextError as isStaleExtensionContextError2 } from "@bastani/atomic";
35614
35621
  function subscribeIntercomControl(pi, callbacks) {
35615
35622
  if (typeof pi.events?.on !== "function")
35616
35623
  return null;
@@ -35635,11 +35642,23 @@ function subscribeIntercomControl(pi, callbacks) {
35635
35642
  Promise.reject(new Error(`atomic-workflows: intercom callback error (type=${payload.type}): ${err instanceof Error ? err.message : String(err)}`));
35636
35643
  });
35637
35644
  };
35638
- const unsubscribe = pi.events.on("subagent:control-intercom", handler);
35645
+ let unsubscribe;
35646
+ try {
35647
+ unsubscribe = pi.events.on("subagent:control-intercom", handler);
35648
+ } catch (error) {
35649
+ if (!isStaleExtensionContextError2(error))
35650
+ throw error;
35651
+ return null;
35652
+ }
35639
35653
  return () => {
35640
35654
  active = false;
35641
- if (typeof unsubscribe === "function")
35642
- unsubscribe();
35655
+ try {
35656
+ if (typeof unsubscribe === "function")
35657
+ unsubscribe();
35658
+ } catch (error) {
35659
+ if (!isStaleExtensionContextError2(error))
35660
+ throw error;
35661
+ }
35643
35662
  };
35644
35663
  }
35645
35664
 
@@ -35650,6 +35669,7 @@ function flattenTruncatedString(value2) {
35650
35669
 
35651
35670
  // dist/builtin/workflows/src/shared/graph-store-snapshot.ts
35652
35671
  var COMPACT_RESULT_FIELD_LIMIT = 1024;
35672
+ var COMPACT_EXIT_OUTPUT_LIMIT = COMPACT_RESULT_FIELD_LIMIT * 4;
35653
35673
  function compactResultField(value2) {
35654
35674
  if (typeof value2 !== "string")
35655
35675
  return;
@@ -35657,7 +35677,7 @@ function compactResultField(value2) {
35657
35677
  return value2;
35658
35678
  return flattenTruncatedString(value2.slice(0, COMPACT_RESULT_FIELD_LIMIT));
35659
35679
  }
35660
- function compactRunResult(result) {
35680
+ function compactRunResult(result, preserveExitedOutputs = false) {
35661
35681
  if (result === undefined)
35662
35682
  return;
35663
35683
  const status = compactResultField(result.status);
@@ -35670,8 +35690,31 @@ function compactRunResult(result) {
35670
35690
  ...remainingWork !== undefined ? { remaining_work: remainingWork } : {},
35671
35691
  ...resultText !== undefined ? { result: resultText } : {}
35672
35692
  };
35693
+ if (!preserveExitedOutputs)
35694
+ return Object.keys(compact).length === 0 ? undefined : compact;
35695
+ return compactExitedOutputs(result, compact);
35696
+ }
35697
+ function compactExitedOutputs(result, compact) {
35698
+ try {
35699
+ const serialized = JSON.stringify(result);
35700
+ if (serialized !== undefined && serialized.length <= COMPACT_EXIT_OUTPUT_LIMIT) {
35701
+ const parsed = JSON.parse(serialized);
35702
+ if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
35703
+ return compactExitedObject(parsed);
35704
+ }
35705
+ }
35706
+ } catch {}
35673
35707
  return Object.keys(compact).length === 0 ? undefined : compact;
35674
35708
  }
35709
+ function compactExitedObject(result) {
35710
+ const compacted = { ...result };
35711
+ for (const key of ["status", "summary", "remaining_work", "result"]) {
35712
+ const value2 = compacted[key];
35713
+ if (typeof value2 === "string")
35714
+ compacted[key] = compactResultField(value2) ?? "";
35715
+ }
35716
+ return Object.keys(compacted).length === 0 ? undefined : compacted;
35717
+ }
35675
35718
  function clonePrompt(prompt) {
35676
35719
  return {
35677
35720
  ...prompt,
@@ -35730,7 +35773,7 @@ function compactToolNode(node) {
35730
35773
  }
35731
35774
  function compactRun(run) {
35732
35775
  const { inputs: _inputs, result: sourceResult, stages, toolNodes, pendingPrompt, ...metadata } = run;
35733
- const result = compactRunResult(sourceResult);
35776
+ const result = compactRunResult(sourceResult, run.exited === true && run.status === "failed");
35734
35777
  return {
35735
35778
  ...metadata,
35736
35779
  inputs: {},
@@ -37296,10 +37339,14 @@ function renderInputsSegment(inputs, budget, theme) {
37296
37339
  fitted: false
37297
37340
  };
37298
37341
  }
37342
+ var ROW_BREAKING_RE = /[\p{Cc}\u2028\u2029]+/gu;
37343
+ function toSingleLine(value2) {
37344
+ return value2.replace(ROW_BREAKING_RE, " ");
37345
+ }
37299
37346
  function renderInputValue(value2, budget) {
37300
37347
  if (typeof value2 === "string") {
37301
37348
  const interior = Math.max(0, budget - 2);
37302
- const trimmed = truncateToWidth(value2, interior, ELLIPSIS);
37349
+ const trimmed = truncateToWidth(toSingleLine(value2), interior, ELLIPSIS);
37303
37350
  return `"${trimmed}"`;
37304
37351
  }
37305
37352
  if (typeof value2 === "number" || typeof value2 === "boolean") {
@@ -37308,7 +37355,7 @@ function renderInputValue(value2, budget) {
37308
37355
  if (value2 === null)
37309
37356
  return "null";
37310
37357
  const json = JSON.stringify(value2);
37311
- return truncateToWidth(json ?? "", budget, ELLIPSIS);
37358
+ return truncateToWidth(toSingleLine(json ?? ""), budget, ELLIPSIS);
37312
37359
  }
37313
37360
  function effectiveWidth(width) {
37314
37361
  return chatWidth(width);
@@ -37508,6 +37555,8 @@ function summaryRows(detail, now) {
37508
37555
  rows.push(["error", detail.error.split(`
37509
37556
  `)[0] ?? ""]);
37510
37557
  }
37558
+ if (detail.resumeGuidance)
37559
+ rows.push(["guidance", detail.resumeGuidance]);
37511
37560
  return rows;
37512
37561
  }
37513
37562
  function artifactRowsFor(detail) {
@@ -37621,6 +37670,8 @@ function stateBadges(detail, theme) {
37621
37670
  switch (detail.status) {
37622
37671
  case "running":
37623
37672
  return [{ text: "● running", fg: theme.warning }];
37673
+ case "crashed":
37674
+ return [{ text: detail.resumable === true ? "✗ crashed · resumable" : "✗ crashed", fg: theme.error }];
37624
37675
  case "paused":
37625
37676
  return [{ text: "❚❚ paused", fg: theme.warning }];
37626
37677
  case "completed":
@@ -37643,6 +37694,8 @@ function stateLabel(detail) {
37643
37694
  switch (detail.status) {
37644
37695
  case "running":
37645
37696
  return "● running";
37697
+ case "crashed":
37698
+ return detail.resumable === true ? "✗ crashed · resumable" : "✗ crashed";
37646
37699
  case "paused":
37647
37700
  return "❚❚ paused";
37648
37701
  case "completed":
@@ -37682,8 +37735,10 @@ function renderIdentifierRows2(id, width, theme) {
37682
37735
  });
37683
37736
  }
37684
37737
  function renderDetailHintRows(detail, width, theme) {
37685
- const prefix = detail.endedAt === undefined ? detail.status === "paused" ? " workflow resume id=" : " workflow interrupt id=" : " workflow resume id=";
37686
- const suffix = detail.endedAt === undefined ? detail.status === "paused" ? " continue workflow " : " cancel " : " reopen graph ";
37738
+ const resumable = detail.status === "paused" && detail.resumable !== false || detail.resumable === true && (detail.status === "crashed" || detail.status === "failed" || detail.status === "blocked");
37739
+ const inspectOnly = detail.ownerActiveElsewhere === true || detail.status === "crashed" && !resumable || detail.endedAt !== undefined && !resumable;
37740
+ const prefix = inspectOnly ? " ▸ workflow status id=" : resumable ? " ▸ workflow resume id=" : " ▸ workflow interrupt id=";
37741
+ const suffix = inspectOnly ? detail.ownerActiveElsewhere === true ? " inspect; owner active elsewhere " : " inspect retained state " : resumable ? " continue workflow " : " cancel ";
37687
37742
  const continuation = " ";
37688
37743
  const rows = wrapIdentifierLines(detail.runId, width, prefix, continuation);
37689
37744
  const last = rows[rows.length - 1];
@@ -37961,6 +38016,8 @@ function runCardMeta(run, now) {
37961
38016
  return parts.join(" · ");
37962
38017
  }
37963
38018
  if (effectiveRunStatus(run) === "failed" || effectiveRunStatus(run) === "killed") {
38019
+ if (run.exitReason !== undefined && run.exitReason.length > 0 && run.exited === true)
38020
+ parts.push(run.exitReason);
37964
38021
  const failed = run.stages.find((s) => s.status === "failed");
37965
38022
  if (failed && isChain)
37966
38023
  parts.push(`failed at ${failed.name}`);
@@ -38526,6 +38583,9 @@ function deriveGraphThemeFromPiTheme(theme) {
38526
38583
  return deriveGraphTheme(cleaned);
38527
38584
  }
38528
38585
 
38586
+ // dist/builtin/workflows/src/tui/inline-form-overlay.ts
38587
+ import { isStaleExtensionContextError as isStaleExtensionContextError3 } from "@bastani/atomic";
38588
+
38529
38589
  // dist/builtin/workflows/src/tui/header.ts
38530
38590
  function pillFor(run, theme) {
38531
38591
  if (run.status === "failed")
@@ -38887,7 +38947,8 @@ function computeInvalid(fields, raw) {
38887
38947
 
38888
38948
  // dist/builtin/workflows/src/tui/keybindings-adapter.ts
38889
38949
  var APP_ACTION = {
38890
- toolsExpand: "app.tools.expand"
38950
+ toolsExpand: "app.tools.expand",
38951
+ thinkingToggle: "app.thinking.toggle"
38891
38952
  };
38892
38953
  var TUI_ACTION = {
38893
38954
  editorCursorUp: "tui.editor.cursorUp",
@@ -38958,6 +39019,30 @@ function deleteRange(text, start, end, caret) {
38958
39019
  }
38959
39020
 
38960
39021
  // dist/builtin/workflows/src/tui/inputs-picker-input.ts
39022
+ function isInputsPickerKey(key, state, fields, keybindings) {
39023
+ if (fields.length === 0)
39024
+ return isCancelKey(key);
39025
+ if (isCancelKey(key) || matchesKey(key, Key.tab) || matchesKey(key, Key.shift("tab")))
39026
+ return true;
39027
+ if (state.focusedIdx === fields.length) {
39028
+ return matchesAction(keybindings, key, TUI_ACTION.selectUp) || matchesAction(keybindings, key, TUI_ACTION.selectDown) || matchesAction(keybindings, key, TUI_ACTION.editorCursorUp) || matchesAction(keybindings, key, TUI_ACTION.editorCursorDown) || matchesKey(key, Key.enter) || matchesAction(keybindings, key, TUI_ACTION.selectConfirm) || matchesAction(keybindings, key, TUI_ACTION.inputSubmit);
39029
+ }
39030
+ const field = fields[state.focusedIdx];
39031
+ if (!field)
39032
+ return false;
39033
+ if (field.type === "select") {
39034
+ if ((field.choices ?? []).length === 0)
39035
+ return false;
39036
+ return matchesAction(keybindings, key, TUI_ACTION.selectUp) || matchesAction(keybindings, key, TUI_ACTION.selectDown) || matchesAction(keybindings, key, TUI_ACTION.editorCursorLeft) || matchesAction(keybindings, key, TUI_ACTION.editorCursorRight) || matchesAction(keybindings, key, TUI_ACTION.selectConfirm) || matchesAction(keybindings, key, TUI_ACTION.inputSubmit);
39037
+ }
39038
+ if (field.type === "boolean") {
39039
+ return matchesKey(key, Key.space) || matchesAction(keybindings, key, TUI_ACTION.selectUp) || matchesAction(keybindings, key, TUI_ACTION.selectDown) || matchesAction(keybindings, key, TUI_ACTION.editorCursorLeft) || matchesAction(keybindings, key, TUI_ACTION.editorCursorRight) || matchesAction(keybindings, key, TUI_ACTION.selectConfirm) || matchesAction(keybindings, key, TUI_ACTION.inputSubmit);
39040
+ }
39041
+ if (matchesAction(keybindings, key, TUI_ACTION.editorCursorUp) || matchesAction(keybindings, key, TUI_ACTION.editorCursorDown) || matchesAction(keybindings, key, "tui.editor.cursorWordLeft") || matchesAction(keybindings, key, "tui.editor.cursorWordRight") || matchesAction(keybindings, key, "tui.editor.cursorLineStart") || matchesAction(keybindings, key, "tui.editor.cursorLineEnd") || matchesAction(keybindings, key, TUI_ACTION.editorCursorLeft) || matchesAction(keybindings, key, TUI_ACTION.editorCursorRight) || matchesAction(keybindings, key, "tui.editor.deleteWordBackward") || matchesAction(keybindings, key, "tui.editor.deleteWordForward") || matchesAction(keybindings, key, "tui.editor.deleteToLineStart") || matchesAction(keybindings, key, "tui.editor.deleteToLineEnd") || matchesAction(keybindings, key, "tui.editor.deleteCharBackward") || matchesAction(keybindings, key, "tui.editor.deleteCharForward") || matchesAction(keybindings, key, TUI_ACTION.inputSubmit) || matchesAction(keybindings, key, "tui.input.newLine")) {
39042
+ return true;
39043
+ }
39044
+ return isPrintableGrapheme(decodePrintableKey(key) ?? key);
39045
+ }
38961
39046
  function handleInputsPickerInput(key, state, fields, keybindings) {
38962
39047
  if (fields.length === 0) {
38963
39048
  if (isCancelKey(key))
@@ -39855,7 +39940,7 @@ class InlineFormEditor {
39855
39940
  handleInput(data) {
39856
39941
  const state = getForm(this.opts.formId);
39857
39942
  if (state?.status !== "editing")
39858
- return;
39943
+ return false;
39859
39944
  if (data.includes(PASTE_START)) {
39860
39945
  this.isInPaste = true;
39861
39946
  this.pasteBuffer = "";
@@ -39865,7 +39950,7 @@ class InlineFormEditor {
39865
39950
  this.pasteBuffer += data;
39866
39951
  const endIdx = this.pasteBuffer.indexOf(PASTE_END);
39867
39952
  if (endIdx === -1)
39868
- return;
39953
+ return true;
39869
39954
  const content = this.pasteBuffer.slice(0, endIdx);
39870
39955
  const remaining = this.pasteBuffer.slice(endIdx + PASTE_END.length);
39871
39956
  this.isInPaste = false;
@@ -39876,20 +39961,22 @@ class InlineFormEditor {
39876
39961
  }
39877
39962
  if (remaining.length > 0)
39878
39963
  this.handleInput(remaining);
39879
- return;
39964
+ return true;
39880
39965
  }
39881
39966
  if (data.length > 1 && isPrintableTextChunk(data)) {
39882
- if (this.applyPaste(data, state)) {
39967
+ const consumed2 = this.applyPaste(data, state);
39968
+ if (consumed2) {
39883
39969
  touch(state);
39884
39970
  this.tui.requestRender?.();
39885
39971
  }
39886
- return;
39972
+ return consumed2;
39887
39973
  }
39888
39974
  const consumed = this.routeKey(data, state);
39889
39975
  if (consumed) {
39890
39976
  touch(state);
39891
39977
  this.tui.requestRender?.();
39892
39978
  }
39979
+ return consumed;
39893
39980
  }
39894
39981
  applyPaste(content, state) {
39895
39982
  const field = state.fields[state.focusedIdx];
@@ -40209,7 +40296,7 @@ async function openInlineInputsForm(pi, ctx, opts) {
40209
40296
  try {
40210
40297
  return getEditor.call(ctx.ui) === installedFactory;
40211
40298
  } catch (err) {
40212
- if (err instanceof Error && err.message.includes("This extension ctx is stale")) {
40299
+ if (isStaleExtensionContextError3(err)) {
40213
40300
  return false;
40214
40301
  }
40215
40302
  return true;
@@ -40505,15 +40592,8 @@ function subscribeStoreInvalidation(store2, listener) {
40505
40592
  }
40506
40593
 
40507
40594
  // dist/builtin/workflows/src/tui/overlay-terminal-modes.ts
40508
- var MOUSE_SCROLL_TRACKING_ON = "\x1B[?1000h\x1B[?1002h\x1B[?1006h";
40509
- var MOUSE_SCROLL_TRACKING_OFF = "\x1B[?1006l\x1B[?1002l\x1B[?1000l";
40510
40595
  var TERMINAL_AUTOWRAP_ON = "\x1B[?7h";
40511
40596
  var TERMINAL_AUTOWRAP_OFF = "\x1B[?7l";
40512
- function setMouseScrollTracking(enabled, output) {
40513
- if (!output.isTTY)
40514
- return;
40515
- output.write(enabled ? MOUSE_SCROLL_TRACKING_ON : MOUSE_SCROLL_TRACKING_OFF);
40516
- }
40517
40597
  function setTerminalAutowrap(enabled, output) {
40518
40598
  if (output.platform !== "win32" || !output.isTTY)
40519
40599
  return;
@@ -40521,13 +40601,9 @@ function setTerminalAutowrap(enabled, output) {
40521
40601
  }
40522
40602
  function remoteTerminalControlFrom(tui) {
40523
40603
  const terminal = tui.terminal;
40524
- if (terminal === undefined || typeof terminal.setMouseScrollTracking !== "function" || typeof terminal.setAutowrap !== "function") {
40604
+ if (terminal === undefined || typeof terminal.setAutowrap !== "function")
40525
40605
  return null;
40526
- }
40527
- return {
40528
- setMouseScrollTracking: terminal.setMouseScrollTracking.bind(terminal),
40529
- setAutowrap: terminal.setAutowrap.bind(terminal)
40530
- };
40606
+ return { setAutowrap: terminal.setAutowrap.bind(terminal) };
40531
40607
  }
40532
40608
 
40533
40609
  // dist/builtin/workflows/src/runs/foreground/stage-queued-user-messages.ts
@@ -40957,12 +41033,9 @@ var COMPACT_HINT_KEYS = [
40957
41033
  { key: "↵", label: "stage chat" }
40958
41034
  ];
40959
41035
  var MODE_PILL_LABEL = "GRAPH";
40960
- var OVERLAY_LINE_COUNT = 32;
40961
- var OVERLAY_VERTICAL_MARGIN_ROWS = 1;
40962
41036
  var ANIMATION_TICK_MS = 100;
40963
41037
  var PULSE_PERIOD_MS = 2000;
40964
41038
  var GRAPH_SCROLL_STEP_COLS = 4;
40965
- var GRAPH_SCROLL_STEP_ROWS = 4;
40966
41039
 
40967
41040
  // dist/builtin/workflows/src/tui/graph-canvas.ts
40968
41041
  function dirsForGlyph(ch) {
@@ -42016,7 +42089,7 @@ class GraphViewState {
42016
42089
  onDetach;
42017
42090
  initialFocusedStageId;
42018
42091
  initialFocusedRunId;
42019
- getViewportRows;
42092
+ piTui;
42020
42093
  requestRender;
42021
42094
  piKeybindings;
42022
42095
  footerData;
@@ -42036,12 +42109,11 @@ class GraphViewState {
42036
42109
  targets: new Map
42037
42110
  };
42038
42111
  currentSnapshot = null;
42039
- graphScrollOffset = 0;
42040
42112
  graphScrollColOffset = 0;
42041
42113
  graphNodeHitRects = [];
42042
42114
  lastGraphViewport = null;
42043
- lastGraphTotalRows = 0;
42044
- lastOverlayFrameWidth = 80;
42115
+ lastGraphTopPad = 0;
42116
+ lastGraphVisibleRows = 0;
42045
42117
  pendingEnsureFocusedVisible = true;
42046
42118
  lastAutoFocusedAwaitingInputKey = null;
42047
42119
  lastBuiltSnapshotVersion = null;
@@ -42063,7 +42135,7 @@ class GraphViewState {
42063
42135
  this.onDetach = opts.onDetach;
42064
42136
  this.initialFocusedStageId = opts.initialFocusedStageId;
42065
42137
  this.initialFocusedRunId = opts.initialFocusedRunId;
42066
- this.getViewportRows = opts.getViewportRows;
42138
+ this.piTui = opts.piTui;
42067
42139
  this.requestRender = opts.requestRender;
42068
42140
  this.piKeybindings = opts.piKeybindings;
42069
42141
  this.footerData = opts.footerData;
@@ -42098,7 +42170,6 @@ class GraphViewState {
42098
42170
  this.cachedRenderGeometry = { canvasWidth: 0, totalRows: 0, bands: [], edges: [] };
42099
42171
  this.expandedGraph = { stages: [], renderStages: [], tools: [], nodes: [], targets: new Map };
42100
42172
  this.focusedIndex = 0;
42101
- this.graphScrollOffset = 0;
42102
42173
  this.graphScrollColOffset = 0;
42103
42174
  this.graphNodeHitRects = [];
42104
42175
  this.lastGraphViewport = null;
@@ -42230,7 +42301,6 @@ class GraphViewState {
42230
42301
  }
42231
42302
  if (this.cachedLayout.length === 0) {
42232
42303
  this.focusedIndex = 0;
42233
- this.graphScrollOffset = 0;
42234
42304
  this.graphScrollColOffset = 0;
42235
42305
  } else if (this.focusedIndex >= this.cachedLayout.length) {
42236
42306
  this.focusedIndex = this.cachedLayout.length - 1;
@@ -42373,48 +42443,10 @@ class GraphViewState {
42373
42443
 
42374
42444
  // dist/builtin/workflows/src/tui/workflow-status.ts
42375
42445
  var WORKFLOW_STATUS_KEY = "pi-workflows";
42376
- var OVERLAY_HIDDEN_STATUS_KEYS = new Set(["mcp"]);
42446
+ var OVERLAY_HIDDEN_STATUS_KEYS = new Set(["mcp", "i-have-adhd"]);
42377
42447
 
42378
42448
  // dist/builtin/workflows/src/tui/graph-view-render-helpers.ts
42379
42449
  class GraphViewRenderHelpers extends GraphViewState {
42380
- _overlayLineCount() {
42381
- const reported = this.getViewportRows?.();
42382
- if (typeof reported !== "number" || !Number.isFinite(reported)) {
42383
- return OVERLAY_LINE_COUNT;
42384
- }
42385
- return Math.max(7, Math.floor(reported));
42386
- }
42387
- _overlayBodyRows(lineCount) {
42388
- return Math.max(1, lineCount - 3 - 3);
42389
- }
42390
- _overlayVerticalMarginRows(lineCount = this._overlayLineCount()) {
42391
- return lineCount >= 9 ? OVERLAY_VERTICAL_MARGIN_ROWS : 0;
42392
- }
42393
- _overlayPanelLineCount() {
42394
- const lineCount = this._overlayLineCount();
42395
- const margins = this._overlayVerticalMarginRows(lineCount) * 2;
42396
- return Math.max(7, lineCount - margins);
42397
- }
42398
- _marginRow(width) {
42399
- return " ".repeat(width);
42400
- }
42401
- _withVerticalMargins(panelLines, width) {
42402
- const expected = this._overlayLineCount();
42403
- const marginRows = this._overlayVerticalMarginRows(expected);
42404
- const panelTarget = this._overlayPanelLineCount();
42405
- const body = panelLines.slice(0, panelTarget);
42406
- while (body.length < panelTarget)
42407
- body.push(this._blankRow(width));
42408
- const margins = Array.from({ length: marginRows }, () => this._marginRow(width));
42409
- const lines = [...margins, ...body, ...margins];
42410
- if (lines.length > expected)
42411
- return lines.slice(0, expected);
42412
- while (lines.length < expected) {
42413
- const insertAt = marginRows > 0 ? Math.max(0, lines.length - marginRows) : lines.length;
42414
- lines.splice(insertAt, 0, this._blankRow(width));
42415
- }
42416
- return lines;
42417
- }
42418
42450
  _externalStatusText() {
42419
42451
  const entries = Array.from(this.footerData?.getExtensionStatuses() ?? []).filter(([key, value2]) => value2.trim().length > 0 && key !== WORKFLOW_STATUS_KEY && !key.startsWith(`${WORKFLOW_STATUS_KEY}:`) && !OVERLAY_HIDDEN_STATUS_KEYS.has(key)).sort(([a], [b]) => a.localeCompare(b));
42420
42452
  if (entries.length === 0)
@@ -42477,10 +42509,6 @@ class GraphViewRenderHelpers extends GraphViewState {
42477
42509
  const rightPadLen = Math.max(0, totalWidth - leftPad - cardW);
42478
42510
  return `${bg}${" ".repeat(leftPad)}${RESET}${cardLine}${bg}${" ".repeat(rightPadLen)}${RESET}`;
42479
42511
  }
42480
- _clampGraphScroll(totalRows, bodyRows) {
42481
- const maxOffset = Math.max(0, totalRows - bodyRows);
42482
- this.graphScrollOffset = Math.max(0, Math.min(maxOffset, this.graphScrollOffset));
42483
- }
42484
42512
  _clampGraphHorizontalScroll(totalCols, viewportCols) {
42485
42513
  const maxOffset = Math.max(0, totalCols - viewportCols);
42486
42514
  this.graphScrollColOffset = Math.max(0, Math.min(maxOffset, this.graphScrollColOffset));
@@ -42498,23 +42526,6 @@ class GraphViewRenderHelpers extends GraphViewState {
42498
42526
  }
42499
42527
  this._clampGraphHorizontalScroll(totalCols, viewportCols);
42500
42528
  }
42501
- _scrollFocusedIntoView(frameWidth, bodyRows, totalRows) {
42502
- const range = this._focusedGraphRowRange(frameWidth);
42503
- if (!range)
42504
- return;
42505
- if (range.start < this.graphScrollOffset) {
42506
- this.graphScrollOffset = range.start;
42507
- } else if (range.end >= this.graphScrollOffset + bodyRows) {
42508
- this.graphScrollOffset = range.end - bodyRows + 1;
42509
- }
42510
- this._clampGraphScroll(totalRows, bodyRows);
42511
- }
42512
- _focusedGraphRowRange(_frameWidth) {
42513
- const node = this.cachedLayout[this.focusedIndex];
42514
- if (!node)
42515
- return null;
42516
- return { start: node.y, end: node.y + NODE_H - 1 };
42517
- }
42518
42529
  _plotEdge(canvas, px, py, cx, cy, color) {
42519
42530
  const parentCol = px + Math.floor(NODE_W / 2);
42520
42531
  const childCol = cx + Math.floor(NODE_W / 2);
@@ -42649,7 +42660,7 @@ function metaText(stage) {
42649
42660
  return "topology unavailable";
42650
42661
  const deps = stage.parentIds.length;
42651
42662
  const dependencyText = deps === 0 ? "root" : deps === 1 ? "1 dep" : `${deps} deps`;
42652
- return stage.fastMode === true ? `${dependencyText} · fast` : dependencyText;
42663
+ return dependencyText;
42653
42664
  }
42654
42665
  function workflowChildRunRows(stage, width) {
42655
42666
  const child = stage.workflowChild ?? stage.workflowChildRun;
@@ -42767,56 +42778,53 @@ function renderNodeCard(stage, opts) {
42767
42778
 
42768
42779
  // dist/builtin/workflows/src/tui/graph-view-graph-render.ts
42769
42780
  class GraphViewGraphRenderer extends GraphViewRenderHelpers {
42770
- _renderGraph(width) {
42771
- const run = this._getCurrentRun();
42781
+ _renderGraph(width, viewportTop, viewportRows, renderRun) {
42782
+ const safeRows = Math.max(0, Math.floor(viewportRows));
42783
+ const run = renderRun !== undefined ? renderRun : this._getCurrentRun();
42772
42784
  if (!run || this.cachedLayout.length === 0) {
42773
42785
  this.lastGraphViewport = null;
42774
42786
  this.graphNodeHitRects = [];
42775
- this.lastGraphTotalRows = 1;
42776
- const dim = hexToAnsi(this.graphTheme.dim);
42777
- return [this._centerCanvasContent(`${dim}waiting for stage events…${RESET}`, width)];
42787
+ this.lastGraphTopPad = 0;
42788
+ this.lastGraphVisibleRows = safeRows;
42789
+ const lines = Array.from({ length: safeRows }, () => "");
42790
+ if (safeRows > 0) {
42791
+ const dim = hexToAnsi(this.graphTheme.dim);
42792
+ lines[Math.floor((safeRows - 1) / 2)] = this._centerCanvasContent(`${dim}waiting for stage events…${RESET}`, width);
42793
+ }
42794
+ return lines;
42778
42795
  }
42779
42796
  const graphInner = Math.max(1, width - 4);
42780
42797
  const { canvasWidth, totalRows, bands, edges } = this.cachedRenderGeometry;
42781
- this.lastGraphTotalRows = totalRows;
42782
42798
  const leftMargin = Math.max(2, canvasWidth <= graphInner ? Math.floor((graphInner - canvasWidth) / 2) : 2);
42783
42799
  const viewportWidth = Math.max(1, width - leftMargin);
42784
42800
  const fullCanvasWidth = Math.max(canvasWidth, viewportWidth);
42785
42801
  this.lastGraphViewport = { leftMargin, viewportWidth };
42802
+ const safeTop = Math.max(0, Math.min(totalRows, Math.floor(viewportTop)));
42803
+ const graphRows = Math.max(0, Math.min(safeRows, totalRows - safeTop));
42804
+ const viewportBottom = safeTop + graphRows;
42786
42805
  this._clampGraphHorizontalScroll(fullCanvasWidth, viewportWidth);
42787
- if (this.pendingEnsureFocusedVisible) {
42788
- this._scrollFocusedColumnIntoView(viewportWidth, fullCanvasWidth);
42789
- }
42790
- const bodyRows = this._overlayBodyRows(this._overlayPanelLineCount());
42791
- if (totalRows > bodyRows) {
42792
- this._clampGraphScroll(totalRows, bodyRows);
42793
- if (this.pendingEnsureFocusedVisible)
42794
- this._scrollFocusedIntoView(width, bodyRows, totalRows);
42795
- this._clampGraphScroll(totalRows, bodyRows);
42796
- } else {
42797
- this.graphScrollOffset = 0;
42798
- }
42799
- const viewportTop = this.graphScrollOffset;
42800
- const viewportBottom = Math.min(totalRows, viewportTop + bodyRows);
42806
+ const topPad = safeTop === 0 && totalRows <= safeRows ? Math.min(3, Math.floor((safeRows - totalRows) / 2)) : 0;
42807
+ this.lastGraphTopPad = topPad;
42808
+ this.lastGraphVisibleRows = graphRows;
42801
42809
  const viewportLeft = this.graphScrollColOffset;
42802
42810
  const viewportRight = viewportLeft + viewportWidth;
42803
42811
  const pulsePhase = Date.now() % PULSE_PERIOD_MS / PULSE_PERIOD_MS;
42804
42812
  const edgeCanvas = new GraphCanvas({
42805
- top: viewportTop,
42813
+ top: safeTop,
42806
42814
  bottom: viewportBottom,
42807
42815
  left: viewportLeft,
42808
42816
  right: viewportRight
42809
42817
  });
42810
42818
  const edgeColor = this.graphTheme.borderDim;
42811
42819
  for (const edge of edges) {
42812
- if (edge.bottom <= viewportTop || edge.top >= viewportBottom || edge.right <= viewportLeft || edge.left >= viewportRight) {
42820
+ if (edge.bottom <= safeTop || edge.top >= viewportBottom || edge.right <= viewportLeft || edge.left >= viewportRight) {
42813
42821
  continue;
42814
42822
  }
42815
42823
  this._plotEdge(edgeCanvas, edge.parentX, edge.parentY, edge.childX, edge.childY, edgeColor);
42816
42824
  }
42817
42825
  const edgeLines = edgeCanvas.toLines();
42818
42826
  const placements = new Map;
42819
- for (let bandIndex = this._firstVisibleLayoutBand(viewportTop);bandIndex < bands.length; bandIndex++) {
42827
+ for (let bandIndex = this._firstVisibleLayoutBand(safeTop);bandIndex < bands.length; bandIndex++) {
42820
42828
  const band = bands[bandIndex];
42821
42829
  if (band.top >= viewportBottom)
42822
42830
  break;
@@ -42837,9 +42845,9 @@ class GraphViewGraphRenderer extends GraphViewRenderHelpers {
42837
42845
  const visibleRight = Math.min(node.x + NODE_W, viewportRight);
42838
42846
  for (let li = 0;li < cardLines.length; li++) {
42839
42847
  const globalRow = node.y + li;
42840
- if (globalRow < viewportTop || globalRow >= viewportBottom)
42848
+ if (globalRow < safeTop || globalRow >= viewportBottom)
42841
42849
  continue;
42842
- const localRow = globalRow - viewportTop;
42850
+ const localRow = globalRow - safeTop;
42843
42851
  let bucket = placements.get(localRow);
42844
42852
  if (!bucket) {
42845
42853
  bucket = [];
@@ -42855,10 +42863,10 @@ class GraphViewGraphRenderer extends GraphViewRenderHelpers {
42855
42863
  }
42856
42864
  const bg = hexBg(this.graphTheme.bg);
42857
42865
  const leftPad = `${bg}${" ".repeat(leftMargin)}${RESET}`;
42858
- const composed = [];
42859
- for (let localRow = 0;localRow < viewportBottom - viewportTop; localRow++) {
42866
+ const composed = Array.from({ length: safeRows }, () => "");
42867
+ for (let localRow = 0;localRow < graphRows; localRow++) {
42860
42868
  const line = this._composeRow(edgeLines[localRow] ?? "", placements.get(localRow) ?? [], edgeColor);
42861
- composed.push(`${leftPad}${this._padCanvas(line, viewportWidth)}`);
42869
+ composed[topPad + localRow] = `${leftPad}${this._padCanvas(line, viewportWidth)}`;
42862
42870
  }
42863
42871
  return composed;
42864
42872
  }
@@ -42873,8 +42881,8 @@ class GraphViewGraphRenderer extends GraphViewRenderHelpers {
42873
42881
  const viewportLeft = viewport.leftMargin;
42874
42882
  const viewportRight = viewport.leftMargin + viewport.viewportWidth;
42875
42883
  const rects = [];
42876
- const viewportTop = this.graphScrollOffset;
42877
- const viewportBottom = viewportTop + visibleRowCount;
42884
+ const viewportTop = this._graphScrollTop();
42885
+ const viewportBottom = Math.min(this.cachedRenderGeometry.totalRows, viewportTop + visibleRowCount);
42878
42886
  const { bands } = this.cachedRenderGeometry;
42879
42887
  for (let bandIndex = this._firstVisibleLayoutBand(viewportTop);bandIndex < bands.length; bandIndex++) {
42880
42888
  const band = bands[bandIndex];
@@ -42897,13 +42905,260 @@ class GraphViewGraphRenderer extends GraphViewRenderHelpers {
42897
42905
  }
42898
42906
  this.graphNodeHitRects = rects;
42899
42907
  }
42900
- _visibleGraphLines(graphLines, _frameWidth, bodyRows) {
42901
- this.pendingEnsureFocusedVisible = false;
42908
+ }
42909
+
42910
+ // dist/builtin/workflows/src/tui/graph-view-layout.ts
42911
+ import { ScrollView, VStack } from "@earendil-works/pi-tui";
42912
+ import {
42913
+ getScrollbarGeometry,
42914
+ getScrollViewBox,
42915
+ renderLayoutFrame
42916
+ } from "@earendil-works/pi-tui/dist/layout.js";
42917
+
42918
+ // dist/builtin/workflows/src/tui/mouse-input.ts
42919
+ function parseTerminalMouseInput(data) {
42920
+ const sgr = data.match(/^\x1b\[<(\d+);(\d+);(\d+)([Mm])$/);
42921
+ if (sgr) {
42922
+ const oneBasedCol = Number.parseInt(sgr[2], 10);
42923
+ const oneBasedRow = Number.parseInt(sgr[3], 10);
42924
+ if (oneBasedCol < 1 || oneBasedRow < 1)
42925
+ return null;
42926
+ return {
42927
+ protocol: "sgr",
42928
+ action: sgr[4] === "M" ? "press" : "release",
42929
+ buttonCode: Number.parseInt(sgr[1], 10),
42930
+ col: oneBasedCol - 1,
42931
+ row: oneBasedRow - 1
42932
+ };
42933
+ }
42934
+ if (!data.startsWith("\x1B[M") || data.length !== 6)
42935
+ return null;
42936
+ const buttonCode = data.charCodeAt(3) - 32;
42937
+ const col = data.charCodeAt(4) - 33;
42938
+ const row = data.charCodeAt(5) - 33;
42939
+ if (buttonCode < 0 || col < 0 || row < 0)
42940
+ return null;
42941
+ return {
42942
+ protocol: "x10",
42943
+ action: (buttonCode & (64 | 32)) === 0 && (buttonCode & 3) === 3 ? "release" : "press",
42944
+ buttonCode,
42945
+ col,
42946
+ row
42947
+ };
42948
+ }
42949
+ function terminalMouseWheelDirection(event) {
42950
+ if (event.action !== "press" || (event.buttonCode & 64) === 0)
42951
+ return null;
42952
+ const direction = event.buttonCode & 3;
42953
+ if (direction === 0)
42954
+ return "up";
42955
+ if (direction === 1)
42956
+ return "down";
42957
+ if (direction === 2)
42958
+ return "left";
42959
+ return "right";
42960
+ }
42961
+ function isTerminalLeftMousePress(event) {
42962
+ return event.action === "press" && (event.buttonCode & 64) === 0 && (event.buttonCode & 32) === 0 && (event.buttonCode & 3) === 0;
42963
+ }
42964
+
42965
+ // dist/builtin/workflows/src/tui/graph-view-layout.ts
42966
+ var EMPTY_RENDER = () => {};
42967
+ var GRAPH_HEADER_ROWS = 3;
42968
+ var GRAPH_FOOTER_ROWS = 3;
42969
+ function graphLayoutMarginRows(height) {
42970
+ return Math.max(1, Math.floor(height)) >= 9 ? 1 : 0;
42971
+ }
42972
+ function graphLayoutBodyRows(height) {
42973
+ const safeHeight = Math.max(1, Math.floor(height));
42974
+ return Math.max(0, safeHeight - GRAPH_HEADER_ROWS - GRAPH_FOOTER_ROWS - graphLayoutMarginRows(safeHeight) * 2);
42975
+ }
42976
+ function graphLayoutNaturalHeight(bodyRows) {
42977
+ const safeBodyRows = Math.max(1, Math.floor(bodyRows));
42978
+ const base = GRAPH_HEADER_ROWS + GRAPH_FOOTER_ROWS + safeBodyRows;
42979
+ return base >= GRAPH_HEADER_ROWS + GRAPH_FOOTER_ROWS + 3 ? base + 2 : base;
42980
+ }
42981
+ function collectWrappedRows(box, height, wrappedRows) {
42982
+ if (box.lines) {
42983
+ const offset = box.lineOffset ?? 0;
42984
+ const firstRow = Math.max(box.rect.y, box.clip.y, 0);
42985
+ const lastRow = Math.min(box.rect.y + box.rect.height, box.clip.y + box.clip.height, height);
42986
+ for (let row = firstRow;row < lastRow; row++) {
42987
+ if (box.lines[offset + row - box.rect.y] !== undefined)
42988
+ wrappedRows[row] = true;
42989
+ }
42990
+ }
42991
+ for (const child of box.children)
42992
+ collectWrappedRows(child, height, wrappedRows);
42993
+ }
42994
+
42995
+ class CallbackComponent {
42996
+ renderLines;
42997
+ constructor(renderLines) {
42998
+ this.renderLines = renderLines;
42999
+ }
43000
+ render(width) {
43001
+ return this.renderLines(width);
43002
+ }
43003
+ invalidate() {}
43004
+ }
43005
+
43006
+ class GraphViewLayout {
43007
+ scrollView;
43008
+ root;
43009
+ callbacks;
43010
+ bodyViewportRows = 0;
43011
+ bodyContentRows = 0;
43012
+ scrollbar;
43013
+ draggingScrollbar;
43014
+ constructor(callbacks) {
43015
+ this.callbacks = callbacks;
43016
+ const margin = new CallbackComponent(() => [""]);
43017
+ const header = new CallbackComponent((width) => this.callbacks.renderHeader(width));
43018
+ const body = new CallbackComponent((width) => this.renderBody(width));
43019
+ const footer = new CallbackComponent((width) => this.callbacks.renderFooter(width));
43020
+ this.scrollView = new ScrollView(body, {
43021
+ axis: "vertical",
43022
+ follow: "none",
43023
+ overscroll: "contain",
43024
+ scrollbar: "hidden"
43025
+ });
43026
+ const marginVisible = ({ height }) => graphLayoutMarginRows(height) > 0;
43027
+ this.root = new VStack([
43028
+ { component: margin, basis: 1, grow: 0, shrink: 0, minSize: 0, visible: marginVisible },
43029
+ { component: header, basis: GRAPH_HEADER_ROWS, grow: 0, shrink: 1, minSize: 0 },
43030
+ { component: this.scrollView, basis: 0, grow: 1, shrink: 1, minSize: 0 },
43031
+ { component: footer, basis: GRAPH_FOOTER_ROWS, grow: 0, shrink: 1, minSize: 1 },
43032
+ { component: margin, basis: 1, grow: 0, shrink: 0, minSize: 0, visible: marginVisible }
43033
+ ]);
43034
+ }
43035
+ render(width, height) {
43036
+ const safeWidth = Math.max(1, Math.floor(width));
43037
+ const safeHeight = Math.max(1, Math.floor(height));
43038
+ const marginRows = graphLayoutMarginRows(safeHeight);
43039
+ this.bodyViewportRows = graphLayoutBodyRows(safeHeight);
43040
+ this.bodyContentRows = Math.max(0, Math.floor(this.callbacks.bodyContentHeight(safeWidth, this.bodyViewportRows)));
43041
+ const requestRender = this.callbacks.requestRender ?? EMPTY_RENDER;
43042
+ this.scrollView.updateLayout(this.bodyContentRows, this.bodyViewportRows, requestRender);
43043
+ this.scrollView.setScrollbar(this.bodyContentRows > this.bodyViewportRows ? "always" : "hidden");
43044
+ this.callbacks.beforeFrame?.(this.scrollView, this.bodyViewportRows, this.bodyContentRows, safeWidth);
43045
+ const frame = renderLayoutFrame(this.root, safeWidth, safeHeight, requestRender);
43046
+ const bodyBox = getScrollViewBox(frame, this.scrollView);
43047
+ this.scrollbar = bodyBox ? getScrollbarGeometry(bodyBox) : undefined;
43048
+ if (!this.scrollbar)
43049
+ this.draggingScrollbar = undefined;
43050
+ const wrappedRows = Array.from({ length: safeHeight }, () => false);
43051
+ collectWrappedRows(frame.root, safeHeight, wrappedRows);
42902
43052
  return {
42903
- lines: graphLines,
42904
- topPad: this.lastGraphTotalRows <= bodyRows ? Math.min(3, Math.max(0, Math.floor((bodyRows - this.lastGraphTotalRows) / 2))) : 0
43053
+ frame,
43054
+ bodyBox,
43055
+ topMarginRows: marginRows,
43056
+ bottomMarginRows: marginRows,
43057
+ wrappedRows,
43058
+ scrollbar: this.scrollbar
42905
43059
  };
42906
43060
  }
43061
+ paintScrollbar(lines, width) {
43062
+ const geometry = this.scrollbar;
43063
+ if (!geometry)
43064
+ return;
43065
+ for (let offset = 0;offset < geometry.thumbHeight; offset++) {
43066
+ const row = geometry.thumbTop + offset;
43067
+ if (row < 0 || row >= lines.length || geometry.column < 0 || geometry.column >= width)
43068
+ continue;
43069
+ const line = lines[row] ?? " ".repeat(width);
43070
+ const before = sliceColumns(line, 0, geometry.column, true);
43071
+ const after = sliceColumns(line, geometry.column + 1, width - geometry.column - 1, true);
43072
+ const beforePad = " ".repeat(Math.max(0, geometry.column - visibleWidth(before)));
43073
+ const afterPad = " ".repeat(Math.max(0, width - geometry.column - 1 - visibleWidth(after)));
43074
+ lines[row] = `${before}${beforePad}${this.scrollView.scrollbarStyle(" ")}${after}${afterPad}`;
43075
+ }
43076
+ }
43077
+ dispose() {
43078
+ this.draggingScrollbar = undefined;
43079
+ this.scrollbar = undefined;
43080
+ this.scrollView.updateLayout(this.bodyContentRows, this.bodyViewportRows, EMPTY_RENDER);
43081
+ this.scrollView.setScrollbarActive(false);
43082
+ this.scrollView.setScrollbar("hidden");
43083
+ }
43084
+ get viewportRows() {
43085
+ return this.bodyViewportRows;
43086
+ }
43087
+ get contentRows() {
43088
+ return this.bodyContentRows;
43089
+ }
43090
+ get scrollbarGeometry() {
43091
+ return this.scrollbar;
43092
+ }
43093
+ isScrollbarInput(data) {
43094
+ const event = parseTerminalMouseInput(data);
43095
+ if (!event)
43096
+ return false;
43097
+ if (this.draggingScrollbar) {
43098
+ return event.action === "release" || (event.buttonCode & 32) !== 0 && (event.buttonCode & 3) === 0;
43099
+ }
43100
+ const geometry = this.scrollbar;
43101
+ return geometry !== undefined && event.action === "press" && (event.buttonCode & 64) === 0 && (event.buttonCode & 32) === 0 && (event.buttonCode & 3) === 0 && event.col === geometry.column && event.row >= geometry.trackTop && event.row < geometry.trackTop + geometry.trackHeight;
43102
+ }
43103
+ handleScrollbarInput(data) {
43104
+ const event = parseTerminalMouseInput(data);
43105
+ if (!event)
43106
+ return false;
43107
+ if (event.action === "release") {
43108
+ if (!this.draggingScrollbar)
43109
+ return false;
43110
+ this.draggingScrollbar = undefined;
43111
+ return true;
43112
+ }
43113
+ const moving = (event.buttonCode & 32) !== 0;
43114
+ const leftButton = (event.buttonCode & 3) === 0;
43115
+ if (this.draggingScrollbar && moving && leftButton) {
43116
+ this.scrollToScrollbarRow(event.row);
43117
+ return true;
43118
+ }
43119
+ const geometry = this.scrollbar;
43120
+ if (!geometry)
43121
+ return false;
43122
+ if (!isTerminalLeftMousePress(event) || event.col !== geometry.column)
43123
+ return false;
43124
+ if (event.row < geometry.trackTop || event.row >= geometry.trackTop + geometry.trackHeight)
43125
+ return false;
43126
+ if (event.row >= geometry.thumbTop && event.row < geometry.thumbTop + geometry.thumbHeight) {
43127
+ this.draggingScrollbar = { grabOffset: event.row - geometry.thumbTop };
43128
+ } else {
43129
+ this.scrollToScrollbarRow(event.row - Math.floor(geometry.thumbHeight / 2));
43130
+ }
43131
+ return true;
43132
+ }
43133
+ invalidate() {
43134
+ this.root.invalidate();
43135
+ }
43136
+ renderBody(width) {
43137
+ const contentRows = this.bodyContentRows;
43138
+ const lines = new Array(contentRows);
43139
+ const top = Math.max(0, Math.min(contentRows, this.scrollView.scrollTop));
43140
+ const rows = Math.max(0, Math.min(this.bodyViewportRows, contentRows - top));
43141
+ const visible = this.callbacks.renderBody(width, top, rows, contentRows);
43142
+ for (let index = 0;index < visible.length && index < rows; index++) {
43143
+ lines[top + index] = visible[index];
43144
+ }
43145
+ if (top > 0)
43146
+ lines[top - 1] = " ";
43147
+ return lines;
43148
+ }
43149
+ scrollToScrollbarRow(row) {
43150
+ const geometry = this.scrollbar;
43151
+ if (!geometry || geometry.maxScrollTop <= 0)
43152
+ return;
43153
+ const maxThumbTop = Math.max(0, geometry.trackHeight - geometry.thumbHeight);
43154
+ if (maxThumbTop === 0) {
43155
+ this.scrollView.scrollTo(0);
43156
+ return;
43157
+ }
43158
+ const thumbTop = Math.max(geometry.trackTop, Math.min(geometry.trackTop + maxThumbTop, row - (this.draggingScrollbar?.grabOffset ?? 0)));
43159
+ const ratio = (thumbTop - geometry.trackTop) / maxThumbTop;
43160
+ this.scrollView.scrollTo(Math.round(ratio * geometry.maxScrollTop));
43161
+ }
42907
43162
  }
42908
43163
 
42909
43164
  // dist/builtin/workflows/src/tui/switcher.ts
@@ -43000,18 +43255,47 @@ function renderSwitcher(stages, state, opts) {
43000
43255
  }
43001
43256
 
43002
43257
  // dist/builtin/workflows/src/tui/graph-view-render.ts
43258
+ var LAYOUT_OSC_RESET = "\x1B[0m\x1B]8;;\x07";
43259
+ function stripLayoutWrapper(line) {
43260
+ const startsWithWrapper = line.startsWith(LAYOUT_OSC_RESET);
43261
+ const endsWithWrapper = line.endsWith(LAYOUT_OSC_RESET);
43262
+ const start = startsWithWrapper ? LAYOUT_OSC_RESET.length : 0;
43263
+ const end = endsWithWrapper ? line.length - LAYOUT_OSC_RESET.length : line.length;
43264
+ return line.slice(start, Math.max(start, end));
43265
+ }
43266
+
43003
43267
  class GraphViewRenderer extends GraphViewGraphRenderer {
43268
+ graphLayout;
43269
+ lastOverlayFrameHeight = 0;
43270
+ hasReportedViewportRows = false;
43271
+ renderRun;
43272
+ constructor(opts) {
43273
+ super(opts);
43274
+ this.graphLayout = new GraphViewLayout({
43275
+ renderHeader: (width) => this._renderHeader(width),
43276
+ renderBody: (width, top, rows, contentRows) => this._renderBody(width, top, rows, contentRows),
43277
+ renderFooter: (width) => this._renderStatusline(width),
43278
+ bodyContentHeight: (_width, viewportRows) => this._graphBodyContentHeight(viewportRows),
43279
+ beforeFrame: (scrollView, viewportRows, contentRows, width) => this._prepareGraphScroll(scrollView, viewportRows, contentRows, width),
43280
+ requestRender: () => this.requestRender?.()
43281
+ });
43282
+ }
43283
+ _graphScrollTop() {
43284
+ return this.graphLayout.scrollView.scrollTop;
43285
+ }
43004
43286
  render(width) {
43005
- if (this.mode === "widget") {
43287
+ if (this.mode === "widget")
43006
43288
  return this._renderWidget(width);
43007
- }
43008
43289
  return this._renderOverlay(width);
43009
43290
  }
43291
+ dispose() {
43292
+ this.graphLayout.dispose();
43293
+ super.dispose();
43294
+ }
43010
43295
  _renderWidget(width) {
43011
43296
  const run = this._getCurrentRun();
43012
- if (!run) {
43297
+ if (!run)
43013
43298
  return [`${hexToAnsi(this.graphTheme.dim)}no active workflow${RESET}`];
43014
- }
43015
43299
  const displayStages = this._displayStages(run);
43016
43300
  const headerLines = renderHeader({ ...run, stages: displayStages }, { width, theme: this.graphTheme });
43017
43301
  const counts = this._counts(displayStages);
@@ -43020,95 +43304,150 @@ class GraphViewRenderer extends GraphViewGraphRenderer {
43020
43304
  }
43021
43305
  _renderOverlay(width) {
43022
43306
  const frameWidth = Math.max(40, width);
43023
- this.lastOverlayFrameWidth = frameWidth;
43024
- const lines = [];
43025
43307
  const run = this._getCurrentRun();
43026
- if (!run) {
43027
- return this._renderEmptyState(frameWidth);
43028
- }
43029
- lines.push(...renderHeader({ ...run, stages: this._displayStages(run) }, { width: frameWidth, theme: this.graphTheme }));
43030
- const graphLines = this._renderGraph(frameWidth);
43031
- const bodyTarget = this._overlayBodyRows(this._overlayPanelLineCount());
43032
- const visibleGraph = this._visibleGraphLines(graphLines, frameWidth, bodyTarget);
43033
- this._recordGraphNodeHitRects(this._overlayVerticalMarginRows() + 3 + visibleGraph.topPad, visibleGraph.lines.length);
43034
- for (let i = 0;i < visibleGraph.topPad; i++)
43035
- lines.push(this._blankRow(frameWidth));
43036
- for (const line of visibleGraph.lines) {
43037
- lines.push(this._canvasRow(line, frameWidth));
43038
- }
43039
- while (lines.length < 3 + bodyTarget)
43040
- lines.push(this._blankRow(frameWidth));
43041
- if (lines.length > 3 + bodyTarget)
43042
- lines.length = 3 + bodyTarget;
43043
- this._renderSwitcherOverlay(lines, run, frameWidth, bodyTarget);
43044
- this._renderPromptOverlay(lines, frameWidth, bodyTarget);
43045
- lines.push(...this._renderStatusline(frameWidth));
43046
- return this._withVerticalMargins(lines, frameWidth);
43047
- }
43048
- _renderEmptyState(width) {
43049
- this.graphNodeHitRects = [];
43050
- this.lastGraphViewport = null;
43308
+ this.renderRun = run;
43309
+ try {
43310
+ const frameHeight = this._overlayFrameHeight(run);
43311
+ const layoutFrame = this.graphLayout.render(frameWidth, frameHeight);
43312
+ const lines = this._normalizeLayoutLines(layoutFrame.frame.lines, layoutFrame.wrappedRows, frameWidth, frameHeight, layoutFrame.topMarginRows, layoutFrame.bottomMarginRows);
43313
+ const bodyStart = layoutFrame.bodyBox?.rect.y ?? layoutFrame.topMarginRows + GRAPH_HEADER_ROWS;
43314
+ const bodyRows = layoutFrame.bodyBox?.rect.height ?? this.graphLayout.viewportRows;
43315
+ if (run) {
43316
+ this._recordGraphNodeHitRects(bodyStart + this.lastGraphTopPad, this.lastGraphVisibleRows);
43317
+ this._renderSwitcherOverlay(lines, run, frameWidth, bodyStart, bodyRows);
43318
+ this._renderPromptOverlay(lines, frameWidth, bodyStart, bodyRows);
43319
+ } else {
43320
+ this.graphNodeHitRects = [];
43321
+ this.lastGraphViewport = null;
43322
+ }
43323
+ this.graphLayout.paintScrollbar(lines, frameWidth);
43324
+ return lines;
43325
+ } finally {
43326
+ this.renderRun = undefined;
43327
+ }
43328
+ }
43329
+ _overlayFrameHeight(run = this._currentRenderRun()) {
43330
+ const reported = this.piTui?.terminal?.rows;
43331
+ if (typeof reported === "number" && Number.isFinite(reported) && reported > 0) {
43332
+ this.hasReportedViewportRows = true;
43333
+ this.lastOverlayFrameHeight = Math.max(1, Math.floor(reported));
43334
+ return this.lastOverlayFrameHeight;
43335
+ }
43336
+ if (this.hasReportedViewportRows && this.lastOverlayFrameHeight > 0)
43337
+ return this.lastOverlayFrameHeight;
43338
+ const bodyRows = run ? Math.max(1, this.cachedRenderGeometry.totalRows) : 2;
43339
+ this.lastOverlayFrameHeight = graphLayoutNaturalHeight(bodyRows);
43340
+ return this.lastOverlayFrameHeight;
43341
+ }
43342
+ _currentRenderRun() {
43343
+ return this.renderRun !== undefined ? this.renderRun : this._getCurrentRun();
43344
+ }
43345
+ _graphBodyContentHeight(viewportRows) {
43346
+ const rows = Math.max(0, Math.floor(viewportRows));
43347
+ if (!this._currentRenderRun() || this.cachedRenderGeometry.totalRows <= 0)
43348
+ return rows;
43349
+ return Math.max(rows, this.cachedRenderGeometry.totalRows);
43350
+ }
43351
+ _prepareGraphScroll(scrollView, viewportRows, _contentRows, width) {
43352
+ const run = this._currentRenderRun();
43353
+ if (viewportRows <= 0)
43354
+ return;
43355
+ if (!run || this.cachedRenderGeometry.totalRows <= 0) {
43356
+ scrollView.scrollToStart();
43357
+ this.pendingEnsureFocusedVisible = false;
43358
+ return;
43359
+ }
43360
+ if (this.pendingEnsureFocusedVisible) {
43361
+ const node = this.cachedLayout[this.focusedIndex];
43362
+ if (node) {
43363
+ let next = scrollView.scrollTop;
43364
+ if (node.y < next)
43365
+ next = node.y;
43366
+ else if (node.y + NODE_H > next + viewportRows)
43367
+ next = node.y + NODE_H - viewportRows;
43368
+ scrollView.scrollTo(next);
43369
+ const graphInner = Math.max(1, width - 4);
43370
+ const leftMargin = Math.max(2, this.cachedRenderGeometry.canvasWidth <= graphInner ? Math.floor((graphInner - this.cachedRenderGeometry.canvasWidth) / 2) : 2);
43371
+ const viewportWidth = Math.max(1, width - leftMargin);
43372
+ const fullCanvasWidth = Math.max(this.cachedRenderGeometry.canvasWidth, viewportWidth);
43373
+ this._scrollFocusedColumnIntoView(viewportWidth, fullCanvasWidth);
43374
+ }
43375
+ this.pendingEnsureFocusedVisible = false;
43376
+ }
43377
+ }
43378
+ _renderHeader(width) {
43379
+ const run = this._currentRenderRun();
43380
+ if (run)
43381
+ return renderHeader({ ...run, stages: this._displayStages(run) }, { width, theme: this.graphTheme });
43051
43382
  const t = this.graphTheme;
43052
43383
  const muted = hexToAnsi(t.textMuted);
43053
- const dim = hexToAnsi(t.dim);
43054
- const accent = hexToAnsi(t.accent);
43055
43384
  const chromeBg = hexBg(t.backgroundPanel);
43056
43385
  const { top, mid, bot, visibleWidth: pillW } = renderOutlinePill("ORCHESTRATOR", t.accent, chromeBg);
43057
- const idleLabel = ` ${muted}idle${RESET}`;
43058
43386
  const fillerVisible = Math.max(0, width - 1 - pillW - 6 - 2);
43059
43387
  const filler = " ".repeat(fillerVisible);
43060
- const lines = [
43388
+ return [
43061
43389
  `${chromeBg} ${RESET}${top}${chromeBg}${" ".repeat(6 + fillerVisible)}${" ".repeat(2)}${RESET}`,
43062
- `${chromeBg} ${RESET}${mid}${chromeBg}${idleLabel}${filler}${" ".repeat(2)}${RESET}`,
43390
+ `${chromeBg} ${RESET}${mid}${chromeBg} ${muted}idle${RESET}${filler}${" ".repeat(2)}${RESET}`,
43063
43391
  `${chromeBg} ${RESET}${bot}${chromeBg}${" ".repeat(6 + fillerVisible)}${" ".repeat(2)}${RESET}`
43064
43392
  ];
43065
- const bodyTarget = this._overlayBodyRows(this._overlayPanelLineCount());
43393
+ }
43394
+ _renderBody(width, top, rows, _contentRows) {
43395
+ const run = this._currentRenderRun();
43396
+ const raw = run ? this._renderGraph(width, top, rows, run) : this._renderEmptyBody(width, rows);
43397
+ return raw.map((line) => this._canvasRow(line, width));
43398
+ }
43399
+ _renderEmptyBody(width, rows) {
43066
43400
  const body = [
43067
- this._canvasRow(` ${muted}No active workflow run.${RESET}`, width),
43068
- this._canvasRow(` ${dim}Start one with ${accent}/workflow <name>${RESET}${dim} or press ${accent}F2${RESET}${dim} on an active run.${RESET}`, width)
43401
+ this._centerCanvasContent(` ${hexToAnsi(this.graphTheme.textMuted)}No active workflow run.${RESET}`, width),
43402
+ this._centerCanvasContent(` ${hexToAnsi(this.graphTheme.dim)}Start one with ${hexToAnsi(this.graphTheme.accent)}/workflow <name>${RESET}${hexToAnsi(this.graphTheme.dim)} or press ${hexToAnsi(this.graphTheme.accent)}F2${RESET}${hexToAnsi(this.graphTheme.dim)} on an active run.${RESET}`, width)
43069
43403
  ];
43070
- const topPad = Math.max(0, Math.floor((bodyTarget - body.length) / 2));
43071
- for (let i = 0;i < topPad; i++)
43072
- lines.push(this._blankRow(width));
43073
- for (const l of body)
43074
- lines.push(l);
43075
- while (lines.length < 3 + bodyTarget)
43076
- lines.push(this._blankRow(width));
43077
- lines.push(...this._renderStatusline(width));
43078
- return this._withVerticalMargins(lines, width);
43079
- }
43080
- _renderSwitcherOverlay(lines, run, frameWidth, bodyTarget) {
43404
+ const lines = Array.from({ length: rows }, () => "");
43405
+ const topPad = Math.max(0, Math.floor((rows - body.length) / 2));
43406
+ for (let index = 0;index < body.length; index++) {
43407
+ const target = topPad + index;
43408
+ if (target < lines.length)
43409
+ lines[target] = body[index];
43410
+ }
43411
+ return lines;
43412
+ }
43413
+ _normalizeLayoutLines(lines, wrappedRows, width, height, topMarginRows, bottomMarginRows) {
43414
+ return Array.from({ length: height }, (_, row) => {
43415
+ if (row < topMarginRows || row >= height - bottomMarginRows)
43416
+ return " ".repeat(width);
43417
+ const source = lines[row] ?? "";
43418
+ const clean = wrappedRows[row] === true ? stripLayoutWrapper(source) : source;
43419
+ if (visibleWidth(clean) === 0)
43420
+ return this._blankRow(width);
43421
+ if (visibleWidth(clean) > width)
43422
+ return truncateToWidth(clean, width, "…", true);
43423
+ return `${clean}${" ".repeat(width - visibleWidth(clean))}`;
43424
+ });
43425
+ }
43426
+ _renderSwitcherOverlay(lines, run, frameWidth, bodyStart, bodyRows) {
43081
43427
  if (!this.switcherOpen)
43082
43428
  return;
43083
- const bodyStart = 3;
43084
- const bodyEnd = 3 + bodyTarget;
43085
- for (let row = bodyStart;row < bodyEnd; row++) {
43429
+ const bodyEnd = bodyStart + bodyRows;
43430
+ for (let row = bodyStart;row < bodyEnd; row++)
43086
43431
  lines[row] = this._blankRow(frameWidth);
43087
- }
43088
43432
  const switcherWidth = Math.min(60, Math.max(40, frameWidth - 8));
43089
43433
  const switcherLines = renderSwitcher(this._displayStages(run), this.switcherState, {
43090
43434
  width: switcherWidth,
43091
43435
  theme: this.graphTheme,
43092
43436
  canOpenStageChat: (stage) => this._stageChatTarget(stage) !== undefined
43093
43437
  });
43094
- const insertAt = Math.max(bodyStart, bodyStart + Math.min(2, Math.floor((bodyTarget - switcherLines.length) / 3)));
43438
+ const insertAt = Math.max(bodyStart, bodyStart + Math.min(2, Math.floor((bodyRows - switcherLines.length) / 3)));
43095
43439
  const switcherLeft = Math.max(2, Math.floor((frameWidth - switcherWidth) / 2));
43096
- for (let i = 0;i < switcherLines.length; i++) {
43097
- const lineIdx = insertAt + i;
43098
- if (lineIdx >= bodyEnd)
43440
+ for (let index = 0;index < switcherLines.length; index++) {
43441
+ const lineIndex = insertAt + index;
43442
+ if (lineIndex >= bodyEnd)
43099
43443
  break;
43100
- const base = lines[lineIdx] ?? this._blankRow(frameWidth);
43101
- const merged = this._overlayCard(base, switcherLines[i], switcherLeft, frameWidth);
43102
- if (lineIdx < lines.length)
43103
- lines[lineIdx] = merged;
43104
- else
43105
- lines.push(merged);
43444
+ lines[lineIndex] = this._overlayCard(lines[lineIndex] ?? this._blankRow(frameWidth), switcherLines[index], switcherLeft, frameWidth);
43106
43445
  }
43107
43446
  }
43108
- _renderPromptOverlay(lines, frameWidth, bodyTarget) {
43447
+ _renderPromptOverlay(lines, frameWidth, bodyStart, bodyRows) {
43109
43448
  if (!this.promptState || this.switcherOpen)
43110
43449
  return;
43111
- const run = this._getCurrentRun();
43450
+ const run = this._currentRenderRun();
43112
43451
  const cardWidth = Math.min(72, Math.max(40, frameWidth - 6));
43113
43452
  const cardLines = renderPromptCard({
43114
43453
  state: this.promptState,
@@ -43116,93 +43455,43 @@ class GraphViewRenderer extends GraphViewGraphRenderer {
43116
43455
  width: cardWidth,
43117
43456
  cursorOn: (Date.now() / 530 | 0) % 2 === 0,
43118
43457
  identity: run ? { runId: run.id, name: run.name } : undefined,
43119
- maxRows: bodyTarget
43458
+ maxRows: bodyRows
43120
43459
  });
43121
- const bodyStart = 3;
43122
- const bodyEnd = bodyStart + bodyTarget;
43123
- const slot = Math.max(bodyStart, bodyStart + Math.floor((bodyTarget - cardLines.length) / 2));
43124
- if (cardLines.length > bodyTarget || slot + cardLines.length > bodyEnd)
43460
+ const bodyEnd = bodyStart + bodyRows;
43461
+ const slot = Math.max(bodyStart, bodyStart + Math.floor((bodyRows - cardLines.length) / 2));
43462
+ if (cardLines.length > bodyRows || slot + cardLines.length > bodyEnd)
43125
43463
  return;
43126
43464
  const leftPad = Math.max(0, Math.floor((frameWidth - cardWidth) / 2));
43127
- for (let i = 0;i < cardLines.length; i++) {
43128
- const lineIdx = slot + i;
43129
- const base = lines[lineIdx] ?? this._blankRow(frameWidth);
43130
- lines[lineIdx] = this._overlayCard(base, cardLines[i], leftPad, frameWidth);
43465
+ for (let index = 0;index < cardLines.length; index++) {
43466
+ const lineIndex = slot + index;
43467
+ lines[lineIndex] = this._overlayCard(lines[lineIndex] ?? this._blankRow(frameWidth), cardLines[index], leftPad, frameWidth);
43131
43468
  }
43132
43469
  }
43133
43470
  }
43134
43471
 
43135
- // dist/builtin/workflows/src/tui/mouse-input.ts
43136
- function parseTerminalMouseInput(data) {
43137
- const sgr = data.match(/^\x1b\[<(\d+);(\d+);(\d+)([Mm])$/);
43138
- if (sgr) {
43139
- const oneBasedCol = Number.parseInt(sgr[2], 10);
43140
- const oneBasedRow = Number.parseInt(sgr[3], 10);
43141
- if (oneBasedCol < 1 || oneBasedRow < 1)
43142
- return null;
43143
- return {
43144
- protocol: "sgr",
43145
- action: sgr[4] === "M" ? "press" : "release",
43146
- buttonCode: Number.parseInt(sgr[1], 10),
43147
- col: oneBasedCol - 1,
43148
- row: oneBasedRow - 1
43149
- };
43150
- }
43151
- if (!data.startsWith("\x1B[M") || data.length !== 6)
43152
- return null;
43153
- const buttonCode = data.charCodeAt(3) - 32;
43154
- const col = data.charCodeAt(4) - 33;
43155
- const row = data.charCodeAt(5) - 33;
43156
- if (buttonCode < 0 || col < 0 || row < 0)
43157
- return null;
43158
- return {
43159
- protocol: "x10",
43160
- action: (buttonCode & (64 | 32)) === 0 && (buttonCode & 3) === 3 ? "release" : "press",
43161
- buttonCode,
43162
- col,
43163
- row
43164
- };
43165
- }
43166
- function terminalMouseWheelDirection(event) {
43167
- if (event.action !== "press" || (event.buttonCode & 64) === 0)
43168
- return null;
43169
- const direction = event.buttonCode & 3;
43170
- if (direction === 0)
43171
- return "up";
43172
- if (direction === 1)
43173
- return "down";
43174
- if (direction === 2)
43175
- return "left";
43176
- return "right";
43177
- }
43178
- function isTerminalLeftMousePress(event) {
43179
- return event.action === "press" && (event.buttonCode & 64) === 0 && (event.buttonCode & 32) === 0 && (event.buttonCode & 3) === 0;
43180
- }
43181
-
43182
43472
  // dist/builtin/workflows/src/tui/graph-view-input.ts
43473
+ var GRAPH_SCROLL_WHEEL_LINES = 4;
43474
+
43183
43475
  class GraphViewInputController extends GraphViewRenderer {
43184
43476
  handleInput(data) {
43185
43477
  if (this._isReturnToMainChatInput(data)) {
43186
43478
  this._returnToMainChat();
43187
43479
  return true;
43188
43480
  }
43189
- if (this.switcherOpen) {
43481
+ if (this.graphLayout.isScrollbarInput(data))
43482
+ return this._handleGraphInput(data);
43483
+ if (this.switcherOpen)
43190
43484
  return this._handleSwitcherInput(data);
43191
- }
43192
- if (this.promptState) {
43193
- if (this._isNonTextGraphControlBeforePrompt(data)) {
43194
- return this._handleGraphInput(data);
43195
- }
43485
+ const wheelDelta = this._mouseWheelDelta(data);
43486
+ if (wheelDelta)
43487
+ return this._handleWheelDelta(wheelDelta);
43488
+ if (this.promptState)
43196
43489
  return this._handlePromptInput(data);
43197
- }
43198
43490
  return this._handleGraphInput(data);
43199
43491
  }
43200
43492
  _promptKeybindings() {
43201
43493
  return isKeybindingsLike(this.piKeybindings) ? this.piKeybindings : undefined;
43202
43494
  }
43203
- _isNonTextGraphControlBeforePrompt(data) {
43204
- return this._mouseWheelDelta(data) !== null;
43205
- }
43206
43495
  _isReturnToMainChatInput(data) {
43207
43496
  return matchesKey(data, Key.ctrl("x"));
43208
43497
  }
@@ -43236,14 +43525,13 @@ class GraphViewInputController extends GraphViewRenderer {
43236
43525
  }
43237
43526
  _handleGraphInput(data) {
43238
43527
  const stageCount = this.cachedLayout.length;
43239
- const wheelDelta = this._mouseWheelDelta(data);
43240
- if (wheelDelta) {
43241
- if (wheelDelta.rows !== 0)
43242
- this._scrollGraphBy(wheelDelta.rows);
43243
- if (wheelDelta.cols !== 0)
43244
- this._scrollGraphHorizontallyBy(wheelDelta.cols);
43528
+ if (this.graphLayout.handleScrollbarInput(data)) {
43529
+ this.pendingEnsureFocusedVisible = false;
43245
43530
  return true;
43246
43531
  }
43532
+ const wheelDelta = this._mouseWheelDelta(data);
43533
+ if (wheelDelta)
43534
+ return this._handleWheelDelta(wheelDelta);
43247
43535
  const clickedNodeIndex = this._graphNodeIndexForClick(data);
43248
43536
  if (clickedNodeIndex !== undefined) {
43249
43537
  if (clickedNodeIndex !== null) {
@@ -43318,21 +43606,18 @@ class GraphViewInputController extends GraphViewRenderer {
43318
43606
  this.switcherOpen = false;
43319
43607
  return true;
43320
43608
  }
43321
- if (matchesKey(data, Key.down)) {
43322
- const filtered = filterStages(stages, this.switcherState.query);
43323
- this.switcherState = {
43324
- ...this.switcherState,
43325
- selectedIndex: Math.min(this.switcherState.selectedIndex + 1, filtered.length - 1)
43326
- };
43327
- return true;
43328
- }
43329
- if (matchesKey(data, Key.up)) {
43330
- this.switcherState = {
43331
- ...this.switcherState,
43332
- selectedIndex: Math.max(this.switcherState.selectedIndex - 1, 0)
43333
- };
43609
+ const wheelEvent = parseTerminalMouseInput(data);
43610
+ const wheelDirection = wheelEvent ? terminalMouseWheelDirection(wheelEvent) : null;
43611
+ if (wheelDirection === "down")
43612
+ return this._moveSwitcherSelection(1);
43613
+ if (wheelDirection === "up")
43614
+ return this._moveSwitcherSelection(-1);
43615
+ if (wheelDirection !== null)
43334
43616
  return true;
43335
- }
43617
+ if (matchesKey(data, Key.down))
43618
+ return this._moveSwitcherSelection(1);
43619
+ if (matchesKey(data, Key.up))
43620
+ return this._moveSwitcherSelection(-1);
43336
43621
  if (matchesKey(data, Key.backspace)) {
43337
43622
  this.switcherState = {
43338
43623
  query: this.switcherState.query.slice(0, -1),
@@ -43349,6 +43634,16 @@ class GraphViewInputController extends GraphViewRenderer {
43349
43634
  }
43350
43635
  return false;
43351
43636
  }
43637
+ _moveSwitcherSelection(step) {
43638
+ const stages = this.cachedLayout.map((layoutNode) => layoutNode.stage);
43639
+ const filtered = filterStages(stages, this.switcherState.query);
43640
+ const maxIndex = Math.max(0, filtered.length - 1);
43641
+ this.switcherState = {
43642
+ ...this.switcherState,
43643
+ selectedIndex: Math.max(0, Math.min(this.switcherState.selectedIndex + step, maxIndex))
43644
+ };
43645
+ return true;
43646
+ }
43352
43647
  _moveByDepth(step) {
43353
43648
  const cur = this.cachedLayout[this.focusedIndex];
43354
43649
  if (!cur)
@@ -43405,9 +43700,16 @@ class GraphViewInputController extends GraphViewRenderer {
43405
43700
  this.focusedIndex = next;
43406
43701
  this.pendingEnsureFocusedVisible = true;
43407
43702
  }
43408
- _scrollGraphBy(deltaRows) {
43703
+ _scrollGraphVertically(deltaRows) {
43409
43704
  this.pendingEnsureFocusedVisible = false;
43410
- this.graphScrollOffset = Math.max(0, this.graphScrollOffset + deltaRows);
43705
+ this.graphLayout.scrollView.scrollBy(deltaRows);
43706
+ }
43707
+ _handleWheelDelta(delta) {
43708
+ if (delta.rows !== 0)
43709
+ this._scrollGraphVertically(delta.rows);
43710
+ if (delta.cols !== 0)
43711
+ this._scrollGraphHorizontallyBy(delta.cols);
43712
+ return true;
43411
43713
  }
43412
43714
  _scrollGraphHorizontallyBy(deltaCols) {
43413
43715
  this.pendingEnsureFocusedVisible = false;
@@ -43440,15 +43742,18 @@ class GraphViewInputController extends GraphViewRenderer {
43440
43742
  return null;
43441
43743
  const direction = terminalMouseWheelDirection(event);
43442
43744
  if (direction === "up")
43443
- return { cols: 0, rows: -GRAPH_SCROLL_STEP_ROWS };
43745
+ return { cols: 0, rows: -GRAPH_SCROLL_WHEEL_LINES };
43444
43746
  if (direction === "down")
43445
- return { cols: 0, rows: GRAPH_SCROLL_STEP_ROWS };
43747
+ return { cols: 0, rows: GRAPH_SCROLL_WHEEL_LINES };
43446
43748
  if (direction === "left")
43447
43749
  return { cols: -GRAPH_SCROLL_STEP_COLS, rows: 0 };
43448
43750
  if (direction === "right")
43449
43751
  return { cols: GRAPH_SCROLL_STEP_COLS, rows: 0 };
43450
43752
  return null;
43451
43753
  }
43754
+ get _graphScrollbarGeometry() {
43755
+ return this.graphLayout.scrollbarGeometry;
43756
+ }
43452
43757
  get _focusedIndex() {
43453
43758
  return this.focusedIndex;
43454
43759
  }
@@ -43459,7 +43764,7 @@ class GraphViewInputController extends GraphViewRenderer {
43459
43764
  return this.switcherState;
43460
43765
  }
43461
43766
  get _graphScrollOffset() {
43462
- return this.graphScrollOffset;
43767
+ return this._graphScrollTop();
43463
43768
  }
43464
43769
  get _graphScrollColOffset() {
43465
43770
  return this.graphScrollColOffset;
@@ -43664,16 +43969,6 @@ function renderHintsForPrompt(kind, theme) {
43664
43969
  return `${paint2("enter", theme.textMuted, { bold: true })} Select · ${paint2("ctrl+c", theme.textMuted, { bold: true })} Skip`;
43665
43970
  }
43666
43971
 
43667
- // dist/builtin/workflows/src/tui/stage-chat-view-types.ts
43668
- var VIEW_LINE_COUNT = 32;
43669
- var PROMPT_SCROLL_STEP_ROWS = 4;
43670
- var HEADER_ROWS = 2;
43671
- var SEP_ROWS = 1;
43672
- var STAGE_CHAT_MOUSE_SCROLL_TOGGLE_LABEL = "ctrl+t";
43673
- function isReadOnlyArchiveStatus(status) {
43674
- return status === "completed" || status === "failed" || status === "skipped";
43675
- }
43676
-
43677
43972
  // dist/builtin/workflows/src/tui/stage-chat-view-footer-status.ts
43678
43973
  function renderHeader2(ctx, width, stage) {
43679
43974
  const t = ctx.theme;
@@ -43762,14 +44057,13 @@ function embedOrchestratorReturnHintInWidget(ctx, widgetLines, width) {
43762
44057
  return lines;
43763
44058
  }
43764
44059
  function mergeOrchestratorReturnHintIntoLine(ctx, line, width, options = {}) {
43765
- const copyModeState = ctx.mouseScrollCaptureEnabled ? "off" : "on";
43766
44060
  const fullHint = {
43767
- plain: `ctrl+x return to graph · ${STAGE_CHAT_MOUSE_SCROLL_TOGGLE_LABEL} copy mode ${copyModeState}`,
43768
- styled: paint2("ctrl+x", ctx.theme.text, { bold: true }) + paint2(" return to graph · ", ctx.theme.textMuted) + paint2(STAGE_CHAT_MOUSE_SCROLL_TOGGLE_LABEL, ctx.theme.text, { bold: true }) + paint2(` copy mode ${copyModeState}`, ctx.theme.textMuted)
44061
+ plain: "ctrl+x return to graph",
44062
+ styled: paint2("ctrl+x", ctx.theme.text, { bold: true }) + paint2(" return to graph", ctx.theme.textMuted)
43769
44063
  };
43770
44064
  const compactHint = {
43771
- plain: `ctrl+x graph · ${STAGE_CHAT_MOUSE_SCROLL_TOGGLE_LABEL} ${copyModeState}`,
43772
- styled: paint2("ctrl+x", ctx.theme.text, { bold: true }) + paint2(" graph · ", ctx.theme.textMuted) + paint2(STAGE_CHAT_MOUSE_SCROLL_TOGGLE_LABEL, ctx.theme.text, { bold: true }) + paint2(` ${copyModeState}`, ctx.theme.textMuted)
44065
+ plain: "ctrl+x graph",
44066
+ styled: paint2("ctrl+x", ctx.theme.text, { bold: true }) + paint2(" graph", ctx.theme.textMuted)
43773
44067
  };
43774
44068
  const trailingBorder = options.preserveTrailingBorder === true ? trailingWidgetBorderChar(line) : "";
43775
44069
  const suffixWidth = visibleWidth(trailingBorder);
@@ -44286,7 +44580,7 @@ async function mountStageCustomUi(request, tui, theme, keybindings, broker, onDo
44286
44580
  });
44287
44581
  const component = {
44288
44582
  render: (width) => rawComponent.render(width),
44289
- ...rawComponent.handleInput !== undefined ? { handleInput: (data) => rawComponent.handleInput?.(data) } : {},
44583
+ ...rawComponent.handleInput !== undefined ? { handleInput: (data) => rawComponent.handleInput?.(data) === true } : {},
44290
44584
  invalidate: () => rawComponent.invalidate?.(),
44291
44585
  ...rawComponent.dispose !== undefined ? { dispose: () => rawComponent.dispose?.() } : {}
44292
44586
  };
@@ -44870,6 +45164,15 @@ function stageNoticeFields(entry, valueTone = "text") {
44870
45164
  ];
44871
45165
  }
44872
45166
 
45167
+ // dist/builtin/workflows/src/tui/stage-chat-view-types.ts
45168
+ var VIEW_LINE_COUNT = 32;
45169
+ var PROMPT_SCROLL_STEP_ROWS = 4;
45170
+ var HEADER_ROWS = 2;
45171
+ var SEP_ROWS = 1;
45172
+ function isReadOnlyArchiveStatus(status) {
45173
+ return status === "completed" || status === "failed" || status === "skipped";
45174
+ }
45175
+
44873
45176
  // dist/builtin/workflows/src/tui/stage-chat-view-state.ts
44874
45177
  function initializeStageChatView(ctx, opts) {
44875
45178
  ctx.store = opts.store;
@@ -44884,7 +45187,6 @@ function initializeStageChatView(ctx, opts) {
44884
45187
  ctx.requestRender = opts.requestRender;
44885
45188
  ctx.requestFocus = opts.requestFocus;
44886
45189
  ctx.focusHoldTimer = undefined;
44887
- ctx.getViewportRows = opts.getViewportRows;
44888
45190
  ctx.piTui = opts.piTui;
44889
45191
  ctx.piTheme = opts.piTheme;
44890
45192
  ctx.piKeybindings = opts.piKeybindings;
@@ -44904,7 +45206,6 @@ function initializeStageChatView(ctx, opts) {
44904
45206
  ctx.promptMaxScroll = 0;
44905
45207
  ctx.promptVisibleRows = 0;
44906
45208
  ctx.localPaused = false;
44907
- ctx.mouseScrollCaptureEnabled = true;
44908
45209
  ctx.lastObservedStageStatus = undefined;
44909
45210
  ctx.lastObservedRunStatus = undefined;
44910
45211
  ctx.seenNoticeIds = new Set;
@@ -45113,6 +45414,7 @@ function snapshotMessagesFromHandle(ctx) {
45113
45414
  if (!handle)
45114
45415
  return;
45115
45416
  ctx.chatHost.appendMessages(handle.messages);
45417
+ ctx.chatHost.hydrateStreamingAssistantMessage(handle.agentSession?.agent?.state.streamingMessage);
45116
45418
  }
45117
45419
  function snapshotMessagesFromSessionFile(ctx, stage) {
45118
45420
  ctx.chatHost.loadSessionFile(liveHandle(ctx)?.sessionFile ?? stage?.sessionFile);
@@ -45245,7 +45547,7 @@ function resolvePromptResponse(ctx, promptId, response, metadata = {}) {
45245
45547
  ctx.onDetach("prompt-resolved", metadata);
45246
45548
  }
45247
45549
  function viewLineCount(ctx) {
45248
- const reported = ctx.getViewportRows?.();
45550
+ const reported = ctx.piTui?.terminal?.rows;
45249
45551
  if (typeof reported !== "number" || !Number.isFinite(reported)) {
45250
45552
  return VIEW_LINE_COUNT;
45251
45553
  }
@@ -45342,6 +45644,10 @@ function promptPageSize(ctx) {
45342
45644
 
45343
45645
  // dist/builtin/workflows/src/tui/stage-chat-view-input.ts
45344
45646
  function handleStageChatInput(ctx, data) {
45647
+ const keybindings = isKeybindingsLike(ctx.piKeybindings) ? ctx.piKeybindings : undefined;
45648
+ if (matchesKey(data, Key.ctrl("t")) && matchesAction(keybindings, data, APP_ACTION.thinkingToggle)) {
45649
+ return false;
45650
+ }
45345
45651
  if (matchesKey(data, Key.ctrl("x"))) {
45346
45652
  if (ctx.mountedCustomUi)
45347
45653
  releaseMountedCustomUi(ctx);
@@ -45353,11 +45659,6 @@ function handleStageChatInput(ctx, data) {
45353
45659
  ctx.onDetach();
45354
45660
  return true;
45355
45661
  }
45356
- if (matchesKey(data, Key.ctrl("t"))) {
45357
- ctx.mouseScrollCaptureEnabled = !ctx.mouseScrollCaptureEnabled;
45358
- ctx.requestRender?.();
45359
- return true;
45360
- }
45361
45662
  if (ctx.mountedCustomUi) {
45362
45663
  return handleMountedCustomUiInput(ctx, data);
45363
45664
  }
@@ -45435,9 +45736,9 @@ function handleMountedCustomUiInput(ctx, data) {
45435
45736
  }
45436
45737
  const component = mounted.component;
45437
45738
  setComponentFocused(component, ctx.focused);
45438
- component.handleInput?.(data);
45739
+ const handled = component.handleInput?.(data) === true;
45439
45740
  ctx.requestRender?.();
45440
- return true;
45741
+ return handled;
45441
45742
  }
45442
45743
  function handlePromptInput(ctx, data) {
45443
45744
  const state = ctx.promptState;
@@ -45535,7 +45836,6 @@ class StageChatView {
45535
45836
  requestRender;
45536
45837
  requestFocus;
45537
45838
  focusHoldTimer;
45538
- getViewportRows;
45539
45839
  piTui;
45540
45840
  piTheme;
45541
45841
  piKeybindings;
@@ -45556,7 +45856,6 @@ class StageChatView {
45556
45856
  promptMaxScroll;
45557
45857
  promptVisibleRows;
45558
45858
  localPaused;
45559
- mouseScrollCaptureEnabled;
45560
45859
  seenNoticeIds;
45561
45860
  _unsubscribeStore;
45562
45861
  _unsubscribeHandle;
@@ -45630,9 +45929,6 @@ class StageChatView {
45630
45929
  ];
45631
45930
  return fitStageChatFrame(lines, totalRows, blankLine(w));
45632
45931
  }
45633
- wantsMouseScrollTracking() {
45634
- return this.mouseScrollCaptureEnabled;
45635
- }
45636
45932
  handleInput(data) {
45637
45933
  return handleStageChatInput(this._ctx(), data);
45638
45934
  }
@@ -45655,7 +45951,6 @@ class StageChatView {
45655
45951
  this.requestRender;
45656
45952
  this.requestFocus;
45657
45953
  this.focusHoldTimer;
45658
- this.getViewportRows;
45659
45954
  this.piTui;
45660
45955
  this.piTheme;
45661
45956
  this.piKeybindings;
@@ -45672,7 +45967,6 @@ class StageChatView {
45672
45967
  this.promptScrollOffset;
45673
45968
  this.promptMaxScroll;
45674
45969
  this.promptVisibleRows;
45675
- this.mouseScrollCaptureEnabled;
45676
45970
  this.seenNoticeIds;
45677
45971
  this._unsubscribeStore;
45678
45972
  this._unsubscribeHandle;
@@ -45727,10 +46021,8 @@ class WorkflowAttachPane {
45727
46021
  onClose;
45728
46022
  onHide;
45729
46023
  onPromptResolve;
45730
- getViewportRows;
45731
46024
  hostRequestRender;
45732
46025
  hostRequestFocus;
45733
- setMouseScrollTracking;
45734
46026
  piTui;
45735
46027
  piTheme;
45736
46028
  piKeybindings;
@@ -45762,10 +46054,8 @@ class WorkflowAttachPane {
45762
46054
  this.onClose = opts.onClose;
45763
46055
  this.onHide = opts.onHide;
45764
46056
  this.onPromptResolve = opts.onPromptResolve;
45765
- this.getViewportRows = opts.getViewportRows;
45766
46057
  this.hostRequestRender = opts.requestRender;
45767
46058
  this.hostRequestFocus = opts.requestFocus;
45768
- this.setMouseScrollTracking = opts.setMouseScrollTracking;
45769
46059
  this.piTui = opts.piTui;
45770
46060
  this.piTheme = opts.piTheme;
45771
46061
  this.piKeybindings = opts.piKeybindings;
@@ -45783,7 +46073,6 @@ class WorkflowAttachPane {
45783
46073
  } else {
45784
46074
  this._syncAwaitingInputKeys(readGraphStoreSnapshot(this.store));
45785
46075
  this._armGraphEnterQuarantineIfRunNeedsInput();
45786
- this._syncMouseScrollTracking();
45787
46076
  }
45788
46077
  }
45789
46078
  _buildGraphView(initialFocusedStageId, initialFocusedRunId) {
@@ -45804,7 +46093,7 @@ class WorkflowAttachPane {
45804
46093
  },
45805
46094
  initialFocusedStageId,
45806
46095
  initialFocusedRunId,
45807
- getViewportRows: this.getViewportRows,
46096
+ piTui: this.piTui,
45808
46097
  piKeybindings: this.piKeybindings,
45809
46098
  footerData: this.footerData,
45810
46099
  getStageQueuedMessageCount: (runId, stageId) => this._stageQueuedMessageCount(runId, stageId),
@@ -45866,14 +46155,12 @@ class WorkflowAttachPane {
45866
46155
  getToolsExpanded: this.getToolsExpanded,
45867
46156
  setToolsExpanded: this.setToolsExpanded,
45868
46157
  footerData: this.footerData,
45869
- getViewportRows: this.getViewportRows,
45870
46158
  stageUiBroker: this.stageUiBroker,
45871
46159
  canSubmitPrompt: (candidateRunId, candidateStageId) => this.visible && this.mode === "stage-chat" && this.chatView === chatView && this.attachedRunId === candidateRunId && this.lastAttachedStageId === candidateStageId && this._isStageMarkedAttached(candidateRunId, candidateStageId)
45872
46160
  });
45873
46161
  this.chatView = chatView;
45874
46162
  this.mode = "stage-chat";
45875
46163
  this.store.recordStageAttached(runId, stageId, this.visible);
45876
- this._syncMouseScrollTracking();
45877
46164
  }
45878
46165
  _detachFromStage(reason = "user", metadata = {}) {
45879
46166
  this.composerDrafts.capture(this.attachedRunId, this.lastAttachedStageId, this.chatView?._inputBuffer);
@@ -45890,7 +46177,6 @@ class WorkflowAttachPane {
45890
46177
  this.lastStageAwaitingInputKey = null;
45891
46178
  this.lastGraphAwaitingInputKey = this.runId ? this._runAwaitingInputKey(readGraphStoreSnapshot(this.store), this.runId) : null;
45892
46179
  this.graphEnterQuarantineUntil = reason === "prompt-resolved" && metadata.suppressNextGraphSubmit === true ? this.now() + ENTER_TRANSITION_QUARANTINE_MS : 0;
45893
- this._syncMouseScrollTracking();
45894
46180
  }
45895
46181
  retarget(runId, stageId, stageRunId) {
45896
46182
  if (this.chatView && this.attachedRunId && this.lastAttachedStageId) {
@@ -45915,7 +46201,6 @@ class WorkflowAttachPane {
45915
46201
  }
45916
46202
  }
45917
46203
  this._armGraphEnterQuarantineIfRunNeedsInput();
45918
- this._syncMouseScrollTracking();
45919
46204
  }
45920
46205
  _resolveGraphStageTarget(rootRunId, stageId) {
45921
46206
  const graph = expandWorkflowGraph(readGraphStoreSnapshot(this.store), rootRunId);
@@ -45971,15 +46256,6 @@ class WorkflowAttachPane {
45971
46256
  this.store.recordStageAttached(this.attachedRunId, this.lastAttachedStageId, visible);
45972
46257
  }
45973
46258
  }
45974
- _syncMouseScrollTracking() {
45975
- this.setMouseScrollTracking?.(this.wantsMouseScrollTracking());
45976
- }
45977
- wantsMouseScrollTracking() {
45978
- if (this.mode === "stage-chat" && this.chatView) {
45979
- return this.chatView.wantsMouseScrollTracking();
45980
- }
45981
- return this.mode === "graph";
45982
- }
45983
46259
  wantsFocusForAwaitingInput(snapshot) {
45984
46260
  if (!this.visible)
45985
46261
  return false;
@@ -46010,12 +46286,7 @@ class WorkflowAttachPane {
46010
46286
  if (this.mode === "stage-chat" && this.chatView) {
46011
46287
  if (this._shouldQuarantineStagePromptEnter(data))
46012
46288
  return true;
46013
- const beforeMouseTracking = this.chatView.wantsMouseScrollTracking();
46014
- const handled = this.chatView.handleInput(data);
46015
- const afterMouseTracking = this.chatView?.wantsMouseScrollTracking();
46016
- if (afterMouseTracking !== undefined && afterMouseTracking !== beforeMouseTracking)
46017
- this._syncMouseScrollTracking();
46018
- return handled;
46289
+ return this.chatView.handleInput(data);
46019
46290
  }
46020
46291
  if (this._shouldQuarantineGraphEnter(data))
46021
46292
  return true;
@@ -46133,7 +46404,6 @@ class WorkflowAttachPane {
46133
46404
  this.chatView?.dispose();
46134
46405
  this.chatView = null;
46135
46406
  this.graphView.dispose();
46136
- this.setMouseScrollTracking?.(false);
46137
46407
  }
46138
46408
  get _mode() {
46139
46409
  return this.mode;
@@ -46173,12 +46443,7 @@ function buildGraphOverlayAdapter(pi, store2, buildOpts = {}) {
46173
46443
  }
46174
46444
  };
46175
46445
  let remoteTerminalControl = null;
46176
- const updateMouseScrollTracking = (enabled) => {
46177
- if (remoteTerminalControl)
46178
- remoteTerminalControl.setMouseScrollTracking(enabled);
46179
- else
46180
- setMouseScrollTracking(enabled, terminalOutput);
46181
- };
46446
+ let localTerminalModesSuppressed = false;
46182
46447
  let currentView = null;
46183
46448
  let currentHandle = null;
46184
46449
  let mounted = false;
@@ -46197,7 +46462,8 @@ function buildGraphOverlayAdapter(pi, store2, buildOpts = {}) {
46197
46462
  remoteTerminalControl.setAutowrap(!visible);
46198
46463
  return;
46199
46464
  }
46200
- setTerminalAutowrap(!visible, terminalOutput);
46465
+ if (!localTerminalModesSuppressed)
46466
+ setTerminalAutowrap(!visible, terminalOutput);
46201
46467
  }
46202
46468
  function readHostCustomUiActive(ui = observedUi) {
46203
46469
  const state = ui?.getHostCustomUiState?.();
@@ -46231,7 +46497,6 @@ function buildGraphOverlayAdapter(pi, store2, buildOpts = {}) {
46231
46497
  updateMainChatInputHint(readHostCustomUiActive(ui));
46232
46498
  }
46233
46499
  function close() {
46234
- updateMouseScrollTracking(false);
46235
46500
  currentHandle?.hide();
46236
46501
  updateTerminalAutowrap(false);
46237
46502
  finishMounted?.();
@@ -46242,11 +46507,11 @@ function buildGraphOverlayAdapter(pi, store2, buildOpts = {}) {
46242
46507
  currentView = null;
46243
46508
  mounted = false;
46244
46509
  remoteTerminalControl = null;
46510
+ localTerminalModesSuppressed = false;
46245
46511
  requestMountedRender = null;
46246
46512
  clearHostCustomUiObservation();
46247
46513
  }
46248
46514
  function hideMounted() {
46249
- updateMouseScrollTracking(false);
46250
46515
  observedUi?.setStatus?.(MAIN_CHAT_INPUT_STATUS_KEY, undefined);
46251
46516
  if (currentHandle) {
46252
46517
  currentView?.setVisible(false);
@@ -46289,11 +46554,11 @@ function buildGraphOverlayAdapter(pi, store2, buildOpts = {}) {
46289
46554
  const consumed = view.handleInput(data);
46290
46555
  if (consumed)
46291
46556
  tui.requestRender?.();
46557
+ return consumed === true;
46292
46558
  },
46293
46559
  invalidate: () => tui.requestRender?.(),
46294
46560
  dispose: () => {
46295
46561
  updateTerminalAutowrap(false);
46296
- updateMouseScrollTracking(false);
46297
46562
  remoteTerminalControl = null;
46298
46563
  requestMountedRender = null;
46299
46564
  unsubscribe();
@@ -46308,7 +46573,6 @@ function buildGraphOverlayAdapter(pi, store2, buildOpts = {}) {
46308
46573
  currentView?.retarget(runId, stageId, stageRunId);
46309
46574
  currentView?.setVisible(true);
46310
46575
  updateTerminalAutowrap(true);
46311
- updateMouseScrollTracking(currentView?.wantsMouseScrollTracking() ?? true);
46312
46576
  currentHandle.setHidden(false);
46313
46577
  currentHandle.focus();
46314
46578
  requestMountedRender?.();
@@ -46317,7 +46581,6 @@ function buildGraphOverlayAdapter(pi, store2, buildOpts = {}) {
46317
46581
  if (mounted) {
46318
46582
  currentView?.retarget(runId, stageId, stageRunId);
46319
46583
  updateTerminalAutowrap(true);
46320
- updateMouseScrollTracking(currentView?.wantsMouseScrollTracking() ?? true);
46321
46584
  currentHandle?.focus();
46322
46585
  return;
46323
46586
  }
@@ -46326,12 +46589,12 @@ function buildGraphOverlayAdapter(pi, store2, buildOpts = {}) {
46326
46589
  return;
46327
46590
  let settled = false;
46328
46591
  const factory = (tui, theme, keybindings, done) => {
46592
+ localTerminalModesSuppressed = tui.mode === "fullscreen";
46329
46593
  remoteTerminalControl = remoteTerminalControlFrom(tui);
46330
46594
  const finish = () => {
46331
46595
  if (settled)
46332
46596
  return;
46333
46597
  settled = true;
46334
- updateMouseScrollTracking(false);
46335
46598
  observedUi?.setStatus?.(MAIN_CHAT_INPUT_STATUS_KEY, undefined);
46336
46599
  currentView?.dispose();
46337
46600
  currentView = null;
@@ -46345,6 +46608,7 @@ function buildGraphOverlayAdapter(pi, store2, buildOpts = {}) {
46345
46608
  } finally {
46346
46609
  updateTerminalAutowrap(false);
46347
46610
  remoteTerminalControl = null;
46611
+ localTerminalModesSuppressed = false;
46348
46612
  }
46349
46613
  };
46350
46614
  const view = new WorkflowAttachPane({
@@ -46366,7 +46630,6 @@ function buildGraphOverlayAdapter(pi, store2, buildOpts = {}) {
46366
46630
  getToolsExpanded: ui?.getToolsExpanded,
46367
46631
  setToolsExpanded: ui?.setToolsExpanded,
46368
46632
  footerData: ui?.getFooterDataProvider?.(),
46369
- getViewportRows: () => tui.terminal?.rows,
46370
46633
  requestRender: () => {
46371
46634
  if (currentHandle?.isHidden() === true)
46372
46635
  return;
@@ -46379,14 +46642,12 @@ function buildGraphOverlayAdapter(pi, store2, buildOpts = {}) {
46379
46642
  return;
46380
46643
  currentHandle?.focus();
46381
46644
  },
46382
- setMouseScrollTracking: updateMouseScrollTracking,
46383
46645
  now: buildOpts.now
46384
46646
  });
46385
46647
  currentView = view;
46386
46648
  finishMounted = finish;
46387
46649
  mounted = true;
46388
46650
  updateTerminalAutowrap(true);
46389
- updateMouseScrollTracking(view.wantsMouseScrollTracking());
46390
46651
  updateMainChatInputHint(readHostCustomUiActive(ui));
46391
46652
  return makeComponent2(view, tui);
46392
46653
  };
@@ -46409,7 +46670,6 @@ function buildGraphOverlayAdapter(pi, store2, buildOpts = {}) {
46409
46670
  currentView?.setVisible(!nowHidden);
46410
46671
  if (!nowHidden)
46411
46672
  updateTerminalAutowrap(true);
46412
- updateMouseScrollTracking(nowHidden ? false : currentView?.wantsMouseScrollTracking() ?? true);
46413
46673
  currentHandle.setHidden(nowHidden);
46414
46674
  if (nowHidden)
46415
46675
  updateTerminalAutowrap(false);
@@ -46431,7 +46691,8 @@ function buildGraphOverlayAdapter(pi, store2, buildOpts = {}) {
46431
46691
  // dist/builtin/workflows/src/tui/store-widget-installer.ts
46432
46692
  import {
46433
46693
  decideReactiveWidgetAction,
46434
- installReactiveWidget
46694
+ installReactiveWidget,
46695
+ isStaleExtensionContextError as isStaleExtensionContextError4
46435
46696
  } from "@bastani/atomic";
46436
46697
 
46437
46698
  // dist/builtin/workflows/src/tui/widget.ts
@@ -46710,10 +46971,6 @@ var defaultTimerApi = {
46710
46971
  clearTimeout: (handle) => clearTimeout(handle)
46711
46972
  };
46712
46973
  var WIDGET_KEY = "workflow.run";
46713
- var STALE_CONTEXT = "This extension ctx is stale";
46714
- function isStale(err) {
46715
- return err instanceof Error && err.message.includes(STALE_CONTEXT);
46716
- }
46717
46974
  function liveWidgetSnapshot(storeInstance) {
46718
46975
  return {
46719
46976
  runs: storeInstance.runs(),
@@ -46740,7 +46997,7 @@ function installStoreWidget(pi, storeInstance, timers = defaultTimerApi) {
46740
46997
  render: (snap, { theme, width, now }) => buildThemedWidgetLines(snap, theme, width, now),
46741
46998
  getNextRefreshDelayMs: (snap, now) => nextWidgetRefreshDelayMs(snap, now),
46742
46999
  requestRenderOnStateNoop: false,
46743
- isStaleError: isStale
47000
+ isStaleError: isStaleExtensionContextError4
46744
47001
  });
46745
47002
  return () => controller.dispose();
46746
47003
  }
@@ -47590,7 +47847,7 @@ function isModelUsage(value2) {
47590
47847
  if (typeof value2 !== "object" || value2 === null || Array.isArray(value2))
47591
47848
  return false;
47592
47849
  const usage = value2;
47593
- return ["input", "output", "cacheRead", "cacheWrite", "cost", "turns"].every((key2) => usage[key2] === undefined || typeof usage[key2] === "number" && Number.isFinite(usage[key2]));
47850
+ return ["input", "output", "cacheRead", "cacheWrite", "cost", "turns"].every((key2) => usage[key2] === undefined || typeof usage[key2] === "number" && Number.isFinite(usage[key2]) && usage[key2] >= 0);
47594
47851
  }
47595
47852
  function isUiPromptKind(value2) {
47596
47853
  return value2 === "input" || value2 === "confirm" || value2 === "select" || value2 === "editor" || value2 === "custom";
@@ -47818,7 +48075,7 @@ class InMemoryDurableBackend {
47818
48075
  ...handle.label !== undefined ? { label: handle.label } : {},
47819
48076
  ...handle.rootWorkflowId !== undefined ? { rootWorkflowId: handle.rootWorkflowId } : {},
47820
48077
  ...handle.resumable !== undefined ? { resumable: handle.resumable } : {},
47821
- ...workflowFailureFields(handle.error !== undefined ? handle : handle.status === "running" ? undefined : existing?.handle),
48078
+ ...workflowFailureFields(hasWorkflowFailureMetadata(handle) ? handle : handle.status === "running" ? undefined : existing?.handle),
47822
48079
  ...handle.ownerExecutorId !== undefined ? { ownerExecutorId: handle.ownerExecutorId } : existing?.handle.ownerExecutorId !== undefined ? { ownerExecutorId: existing.handle.ownerExecutorId } : {}
47823
48080
  };
47824
48081
  if (existing)
@@ -47916,6 +48173,12 @@ class InMemoryDurableBackend {
47916
48173
  return this.getWorkflow(workflowId);
47917
48174
  }
47918
48175
  async hydrateWorkflow(_workflowId) {}
48176
+ async hydrateWorkflowForInspection(workflowId) {
48177
+ const handle = this.getLoadableWorkflow(workflowId);
48178
+ if (handle !== undefined)
48179
+ return { kind: "current", handle };
48180
+ return { kind: this.deletedWorkflowIds.has(workflowId) ? "deleted" : "absent" };
48181
+ }
47919
48182
  async hydrateResumableWorkflows() {}
47920
48183
  async prepareWorkflowCatalog() {
47921
48184
  return { resumable: this.listResumableWorkflows(), completed: this.listCompletedWorkflows() };
@@ -47927,6 +48190,8 @@ class InMemoryDurableBackend {
47927
48190
  rec.handle = {
47928
48191
  ...rec.handle,
47929
48192
  error: undefined,
48193
+ exited: undefined,
48194
+ exitReason: undefined,
47930
48195
  failureKind: undefined,
47931
48196
  failureCode: undefined,
47932
48197
  failureRecoverability: undefined,
@@ -48061,11 +48326,16 @@ function hasResumeProgress(handle) {
48061
48326
  function isHistoricalHandle(handle) {
48062
48327
  return handle.status === "completed" && hasResumeProgress(handle) || handle.status === "failed" && !isDurableWorkflowResumable(handle) && hasResumeProgress(handle);
48063
48328
  }
48329
+ function hasWorkflowFailureMetadata(handle) {
48330
+ return handle.error !== undefined || handle.exited !== undefined || handle.exitReason !== undefined || handle.failureKind !== undefined || handle.failureCode !== undefined || handle.failureRecoverability !== undefined || handle.failureDisposition !== undefined || handle.failedToolNodeId !== undefined;
48331
+ }
48064
48332
  function workflowFailureFields(handle) {
48065
48333
  if (handle === undefined)
48066
48334
  return {};
48067
48335
  return {
48068
48336
  ...handle.error !== undefined ? { error: handle.error } : {},
48337
+ ...handle.exited !== undefined ? { exited: handle.exited } : {},
48338
+ ...handle.exitReason !== undefined ? { exitReason: handle.exitReason } : {},
48069
48339
  ...handle.failureKind !== undefined ? { failureKind: handle.failureKind } : {},
48070
48340
  ...handle.failureCode !== undefined ? { failureCode: handle.failureCode } : {},
48071
48341
  ...handle.failureRecoverability !== undefined ? { failureRecoverability: handle.failureRecoverability } : {},
@@ -48306,7 +48576,7 @@ function isWorkflowChildResult(value2) {
48306
48576
  return parseWorkflowChildResult(value2) !== undefined;
48307
48577
  }
48308
48578
  function isWorkflowExitStatus(value2) {
48309
- return value2 === "completed" || value2 === "skipped" || value2 === "cancelled" || value2 === "blocked";
48579
+ return value2 === "completed" || value2 === "skipped" || value2 === "cancelled" || value2 === "blocked" || value2 === "failed";
48310
48580
  }
48311
48581
  function isOrdinaryObject(value2) {
48312
48582
  if (typeof value2 !== "object" || value2 === null || Array.isArray(value2))
@@ -49294,6 +49564,8 @@ function encodeMetadata(metadata) {
49294
49564
  ...metadata.label !== undefined ? { label: metadata.label } : {},
49295
49565
  ...metadata.rootWorkflowId !== undefined ? { rootWorkflowId: metadata.rootWorkflowId } : {},
49296
49566
  ...metadata.resumable !== undefined ? { resumable: metadata.resumable } : {},
49567
+ ...metadata.exited !== undefined ? { exited: metadata.exited } : {},
49568
+ ...metadata.exitReason !== undefined ? { exitReason: metadata.exitReason } : {},
49297
49569
  ...metadata.error !== undefined ? { error: metadata.error } : {},
49298
49570
  ...metadata.failureKind !== undefined ? { failureKind: metadata.failureKind } : {},
49299
49571
  ...metadata.failureCode !== undefined ? { failureCode: metadata.failureCode } : {},
@@ -49344,7 +49616,7 @@ function parseDurableWorkflowMetadata(value2, workflowId) {
49344
49616
  if (typeof value2 !== "object" || value2 === null || Array.isArray(value2))
49345
49617
  return;
49346
49618
  const metadata = value2;
49347
- if (metadata.workflowId !== workflowId || typeof metadata.workflowId !== "string" || typeof metadata.name !== "string" || typeof metadata.inputs !== "object" || metadata.inputs === null || Array.isArray(metadata.inputs) || typeof metadata.status !== "string" || !isDurableWorkflowStatus(metadata.status) || typeof metadata.completedCheckpoints !== "number" || typeof metadata.createdAt !== "number" || typeof metadata.pendingPrompts !== "number" || typeof metadata.promptReservationEpoch !== "string" || typeof metadata.updatedAt !== "number" || metadata.ownerExecutorId !== undefined && typeof metadata.ownerExecutorId !== "string" || metadata.transitionClaimId !== undefined && typeof metadata.transitionClaimId !== "string" || metadata.sessionFile !== undefined && typeof metadata.sessionFile !== "string" || metadata.label !== undefined && typeof metadata.label !== "string" || metadata.rootWorkflowId !== undefined && typeof metadata.rootWorkflowId !== "string" || metadata.resumable !== undefined && typeof metadata.resumable !== "boolean" || metadata.error !== undefined && typeof metadata.error !== "string" || metadata.failureKind !== undefined && !isWorkflowFailureKind(metadata.failureKind) || metadata.failureCode !== undefined && !isWorkflowFailureCode(metadata.failureCode) || metadata.failureRecoverability !== undefined && !isWorkflowFailureRecoverability(metadata.failureRecoverability) || metadata.failureDisposition !== undefined && !isWorkflowFailureDisposition(metadata.failureDisposition) || metadata.failedToolNodeId !== undefined && typeof metadata.failedToolNodeId !== "string" || metadata.invocationCwd !== undefined && typeof metadata.invocationCwd !== "string" || metadata.workflowCwd !== undefined && typeof metadata.workflowCwd !== "string" || metadata.repositoryRoot !== undefined && typeof metadata.repositoryRoot !== "string" || metadata.gitWorktreeRoot !== undefined && typeof metadata.gitWorktreeRoot !== "string")
49619
+ if (metadata.workflowId !== workflowId || typeof metadata.workflowId !== "string" || typeof metadata.name !== "string" || typeof metadata.inputs !== "object" || metadata.inputs === null || Array.isArray(metadata.inputs) || typeof metadata.status !== "string" || !isDurableWorkflowStatus(metadata.status) || typeof metadata.completedCheckpoints !== "number" || typeof metadata.createdAt !== "number" || typeof metadata.pendingPrompts !== "number" || typeof metadata.promptReservationEpoch !== "string" || typeof metadata.updatedAt !== "number" || metadata.ownerExecutorId !== undefined && typeof metadata.ownerExecutorId !== "string" || metadata.transitionClaimId !== undefined && typeof metadata.transitionClaimId !== "string" || metadata.sessionFile !== undefined && typeof metadata.sessionFile !== "string" || metadata.label !== undefined && typeof metadata.label !== "string" || metadata.rootWorkflowId !== undefined && typeof metadata.rootWorkflowId !== "string" || metadata.resumable !== undefined && typeof metadata.resumable !== "boolean" || metadata.exited !== undefined && typeof metadata.exited !== "boolean" || metadata.exitReason !== undefined && typeof metadata.exitReason !== "string" || metadata.error !== undefined && typeof metadata.error !== "string" || metadata.failureKind !== undefined && !isWorkflowFailureKind(metadata.failureKind) || metadata.failureCode !== undefined && !isWorkflowFailureCode(metadata.failureCode) || metadata.failureRecoverability !== undefined && !isWorkflowFailureRecoverability(metadata.failureRecoverability) || metadata.failureDisposition !== undefined && !isWorkflowFailureDisposition(metadata.failureDisposition) || metadata.failedToolNodeId !== undefined && typeof metadata.failedToolNodeId !== "string" || metadata.invocationCwd !== undefined && typeof metadata.invocationCwd !== "string" || metadata.workflowCwd !== undefined && typeof metadata.workflowCwd !== "string" || metadata.repositoryRoot !== undefined && typeof metadata.repositoryRoot !== "string" || metadata.gitWorktreeRoot !== undefined && typeof metadata.gitWorktreeRoot !== "string")
49348
49620
  return;
49349
49621
  const { origin, ...metadataWithoutOrigin } = metadata;
49350
49622
  return {
@@ -50042,17 +50314,24 @@ class DbosDurableBackend {
50042
50314
  throw first;
50043
50315
  }
50044
50316
  async hydrateWorkflow(workflowId) {
50045
- if (this.locallyRegistered.has(workflowId))
50046
- return;
50047
- const info = await this.sdk.retrieveWorkflow(workflowId);
50048
- if (info !== undefined) {
50049
- await this.hydrateInfo(info);
50050
- return;
50317
+ await this.hydrateWorkflowForInspection(workflowId);
50318
+ }
50319
+ async hydrateWorkflowForInspection(workflowId) {
50320
+ if (this.locallyRegistered.has(workflowId)) {
50321
+ const handle = this.getLoadableWorkflow(workflowId);
50322
+ return handle === undefined ? { kind: "malformed" } : { kind: "current", handle };
50051
50323
  }
50324
+ const info = await this.sdk.retrieveWorkflow(workflowId);
50325
+ if (info !== undefined)
50326
+ return await this.hydrateInfo(info);
50052
50327
  const records = await this.sdk.listStepRecords(workflowId);
50053
50328
  const deletion = classifyDbosDeletionTombstone(records, workflowId);
50054
- if (deletion !== "absent")
50055
- await this.suppressWorkflow(workflowId);
50329
+ if (deletion === "absent" && records.length === 0)
50330
+ return { kind: "absent" };
50331
+ await this.suppressWorkflow(workflowId);
50332
+ if (deletion === "absent")
50333
+ return { kind: "malformed" };
50334
+ return { kind: deletion === "current" ? "deleted" : "malformed" };
50056
50335
  }
50057
50336
  async hydrateResumableWorkflows() {
50058
50337
  const all = await this.sdk.listAllWorkflows();
@@ -50064,10 +50343,15 @@ class DbosDurableBackend {
50064
50343
  }
50065
50344
  async hydrateInfo(info) {
50066
50345
  const records = await this.sdk.listStepRecords(info.workflowId);
50346
+ const deletion = classifyDbosDeletionTombstone(records, info.workflowId);
50347
+ if (deletion !== "absent") {
50348
+ await this.suppressWorkflow(info.workflowId);
50349
+ return { kind: deletion === "current" ? "deleted" : "malformed" };
50350
+ }
50067
50351
  const metadata = classifyLatestMetadata(records, info.workflowId);
50068
50352
  if (metadata.kind !== "current") {
50069
50353
  await this.suppressWorkflow(info.workflowId);
50070
- return;
50354
+ return { kind: "malformed" };
50071
50355
  }
50072
50356
  const checkpoints = [];
50073
50357
  for (const record of records) {
@@ -50076,7 +50360,7 @@ class DbosDurableBackend {
50076
50360
  const classified = classifyCheckpointPayload(info.workflowId, record.stepName, record.output);
50077
50361
  if (classified.kind === "unknown") {
50078
50362
  await this.suppressWorkflow(info.workflowId);
50079
- return;
50363
+ return { kind: "malformed" };
50080
50364
  }
50081
50365
  checkpoints.push(classified.checkpoint);
50082
50366
  }
@@ -50087,14 +50371,21 @@ class DbosDurableBackend {
50087
50371
  for (const checkpoint of checkpoints)
50088
50372
  this.mem.recordCheckpoint(checkpoint);
50089
50373
  const current = this.mem.getWorkflow(info.workflowId);
50090
- if (current !== undefined) {
50091
- const pendingPrompts2 = this.promptReservations.hydrate(info.workflowId, metadata.metadata.pendingPrompts, records, metadata.metadata.promptReservationEpoch);
50092
- this.applyMetadata(info.workflowId, {
50093
- ...metadata.metadata,
50094
- pendingPrompts: pendingPrompts2,
50095
- completedCheckpoints: current.completedCheckpoints
50096
- });
50374
+ if (current === undefined) {
50375
+ await this.suppressWorkflow(info.workflowId);
50376
+ return { kind: "malformed" };
50097
50377
  }
50378
+ const pendingPrompts2 = this.promptReservations.hydrate(info.workflowId, metadata.metadata.pendingPrompts, records, metadata.metadata.promptReservationEpoch);
50379
+ this.applyMetadata(info.workflowId, {
50380
+ ...metadata.metadata,
50381
+ pendingPrompts: pendingPrompts2,
50382
+ completedCheckpoints: current.completedCheckpoints
50383
+ });
50384
+ const handle = this.getLoadableWorkflow(info.workflowId);
50385
+ if (handle !== undefined)
50386
+ return { kind: "current", handle };
50387
+ await this.suppressWorkflow(info.workflowId);
50388
+ return { kind: "malformed" };
50098
50389
  }
50099
50390
  async suppressWorkflow(workflowId) {
50100
50391
  this.invalid.add(workflowId);
@@ -50158,13 +50449,14 @@ import { dirname, join } from "node:path";
50158
50449
  // dist/builtin/workflows/src/durable/local-command.ts
50159
50450
  import { spawn } from "node:child_process";
50160
50451
  import { connect } from "node:net";
50452
+ import { createChildProcessEnvironment } from "@bastani/atomic";
50161
50453
  var OUTPUT_LIMIT_BYTES = 16384;
50162
50454
  function runLocalCommand(command, args, options) {
50163
50455
  return new Promise((resolve, reject) => {
50164
50456
  const child = spawn(command, [...args], {
50165
50457
  stdio: ["ignore", "pipe", "pipe"],
50166
50458
  windowsHide: true,
50167
- ...options?.env !== undefined ? { env: { ...process.env, ...options.env } } : {},
50459
+ env: createChildProcessEnvironment(options?.env ? { ...options.env } : undefined),
50168
50460
  ...options?.uid !== undefined ? { uid: options.uid } : {},
50169
50461
  ...options?.gid !== undefined ? { gid: options.gid } : {}
50170
50462
  });
@@ -50807,20 +51099,34 @@ function priorRunElapsedMs(backend, workflowId) {
50807
51099
  return elapsedMs;
50808
51100
  }
50809
51101
  function recordRunTimingCheckpoint(backend, run, options) {
51102
+ const checkpoint = runTimingCheckpoint(backend, run, options);
51103
+ if (checkpoint === undefined)
51104
+ return false;
51105
+ backend.recordCheckpoint(checkpoint);
51106
+ return true;
51107
+ }
51108
+ async function recordRunTimingCheckpointAsync(backend, run, options) {
51109
+ const checkpoint = runTimingCheckpoint(backend, run, options);
51110
+ if (checkpoint === undefined)
51111
+ return false;
51112
+ await backend.recordCheckpointAsync(checkpoint);
51113
+ return true;
51114
+ }
51115
+ function runTimingCheckpoint(backend, run, options) {
50810
51116
  const now = options?.now ?? Date.now();
50811
51117
  const elapsedMs = elapsedRunMs(run, now);
50812
51118
  if (elapsedMs <= 0)
50813
- return false;
51119
+ return;
50814
51120
  if (backend.listCheckpoints(run.id).length === 0)
50815
- return false;
51121
+ return;
50816
51122
  const recorded = priorRunElapsedMs(backend, run.id);
50817
51123
  if (recorded !== undefined) {
50818
51124
  if (elapsedMs <= recorded)
50819
- return false;
51125
+ return;
50820
51126
  if (options?.debounce === true && timingBucket(elapsedMs) === timingBucket(recorded))
50821
- return false;
51127
+ return;
50822
51128
  }
50823
- const checkpoint = {
51129
+ return {
50824
51130
  kind: "tool",
50825
51131
  workflowId: run.id,
50826
51132
  checkpointId: `run-timing:${elapsedMs}`,
@@ -50829,8 +51135,6 @@ function recordRunTimingCheckpoint(backend, run, options) {
50829
51135
  output: { elapsedMs },
50830
51136
  completedAt: now
50831
51137
  };
50832
- backend.recordCheckpoint(checkpoint);
50833
- return true;
50834
51138
  }
50835
51139
  function inheritedRunElapsedMs(input) {
50836
51140
  const now = input.now ?? Date.now();
@@ -51669,6 +51973,16 @@ async function resumeRun(runId, opts) {
51669
51973
  message: "This workflow is not resumable; inspect the snapshot and start a new workflow run when ready."
51670
51974
  };
51671
51975
  }
51976
+ if (current.status === "failed" && current.endedAt !== undefined && current.exited === true && current.resumable === true) {
51977
+ return {
51978
+ ok: true,
51979
+ runId,
51980
+ snapshot,
51981
+ resumed: resumedCopy,
51982
+ mode: "snapshot",
51983
+ message: `This failed run is marked resumable; use /workflow resume ${runId} to ask the durable backend to retry it or start a new workflow run.`
51984
+ };
51985
+ }
51672
51986
  if (current.endedAt === undefined && current.resumable === true && current.failureRecoverability === "recoverable" && current.failedStageId !== undefined) {
51673
51987
  return {
51674
51988
  ok: true,
@@ -52303,7 +52617,9 @@ function formatWorkflowLifecycleNoticeText(details) {
52303
52617
  const tool = lifecycleToolOrigin(details);
52304
52618
  const failureSite = stage2 ? `, stage ${stage2}` : tool !== undefined ? `, tool ${tool}` : "";
52305
52619
  const errorText = details.error ? `: ${details.error}` : "";
52306
- return `✗ Workflow "${workflowName}" failed (run ${details.runId}${failureSite})${origin}${errorText}. Inspect: /workflow status ${details.runId}`;
52620
+ const outputsText = formatLifecycleOutputs(details.outputs);
52621
+ const outputSuffix = outputsText === undefined ? "" : ` Partial outputs: ${outputsText}`;
52622
+ return `✗ Workflow "${workflowName}" failed (run ${details.runId}${failureSite})${origin}${errorText}${outputSuffix}. Inspect: /workflow status ${details.runId}`;
52307
52623
  }
52308
52624
  if (details.kind === "blocked") {
52309
52625
  const errorText = details.error ? `: ${details.error}` : "";
@@ -52339,7 +52655,8 @@ function makeTerminalNotice(run, kind) {
52339
52655
  const failedToolNodeId = kind === "failed" && run.failedStageId === undefined ? run.failedToolNodeId : undefined;
52340
52656
  const failedTool = (run.toolNodes ?? []).find((node) => node.id === failedToolNodeId);
52341
52657
  const activeBlocked = kind === "blocked" && isActiveRecoverableBlockedRun(run);
52342
- const error = activeBlocked ? run.failureMessage ?? structuredRecoverableWorkflowFailureText(run) ?? run.error : run.error ?? returnedNoticeError(run, kind) ?? (kind === "blocked" ? run.exitReason : undefined);
52658
+ const outputs = kind === "failed" && run.exited === true && run.result !== undefined ? run.result : undefined;
52659
+ const error = activeBlocked ? run.failureMessage ?? structuredRecoverableWorkflowFailureText(run) ?? run.error : run.error ?? returnedNoticeError(run, kind) ?? (kind === "blocked" || kind === "failed" ? run.exitReason : undefined);
52343
52660
  return {
52344
52661
  kind,
52345
52662
  scope: "run",
@@ -52347,7 +52664,9 @@ function makeTerminalNotice(run, kind) {
52347
52664
  workflowName: run.name,
52348
52665
  status: effectiveRunStatus(run),
52349
52666
  ...activeBlocked ? { active: true } : {},
52667
+ ...run.exited === true && run.status === "failed" && run.resumable !== undefined ? { resumable: run.resumable } : {},
52350
52668
  ...error ? { error: truncateSnippet(error) } : {},
52669
+ ...outputs !== undefined ? { outputs } : {},
52351
52670
  ...run.failedStageId ? { failedStageId: run.failedStageId } : {},
52352
52671
  ...failedStage ? { stageId: failedStage.id, stageName: failedStage.name } : {},
52353
52672
  ...failedToolNodeId !== undefined ? { toolNodeId: failedToolNodeId } : {},
@@ -52409,6 +52728,8 @@ function lifecycleOccurrenceAt(run, kind) {
52409
52728
  return run.endedAt;
52410
52729
  }
52411
52730
  function returnedNoticeError(run, kind) {
52731
+ if (run.exited === true && (kind === "failed" || kind === "blocked"))
52732
+ return run.exitReason;
52412
52733
  const structuredFailureText = structuredRecoverableWorkflowFailureText(run);
52413
52734
  if (kind === "blocked" && structuredFailureText !== undefined)
52414
52735
  return structuredFailureText;
@@ -52491,6 +52812,16 @@ function truncateSnippet(value2) {
52491
52812
  return normalized;
52492
52813
  return `${normalized.slice(0, LIFECYCLE_NOTICE_SNIPPET_LIMIT - 1)}…`;
52493
52814
  }
52815
+ function formatLifecycleOutputs(outputs) {
52816
+ if (outputs === undefined)
52817
+ return;
52818
+ try {
52819
+ const serialized = JSON.stringify(outputs);
52820
+ return serialized === undefined ? "available; inspect the run result" : truncateSnippet(serialized);
52821
+ } catch {
52822
+ return "available; inspect the run result";
52823
+ }
52824
+ }
52494
52825
  function makeNoticeComponent2(details, theme) {
52495
52826
  const text = formatWorkflowLifecycleNoticeText(details);
52496
52827
  return {
@@ -52522,6 +52853,11 @@ function renderLifecycleNoticeCard(details, opts) {
52522
52853
  { label: "launched", value: details.origin, tone: "muted" },
52523
52854
  { label: "prompt", value: details.promptMessage, tone: "muted" },
52524
52855
  { label: "error", value: details.error, tone: "error" },
52856
+ {
52857
+ label: "partial outputs",
52858
+ value: formatLifecycleOutputs(details.outputs),
52859
+ tone: "muted"
52860
+ },
52525
52861
  { label: "resumable", value: resumableFieldValue(details), tone: "muted" },
52526
52862
  { label: "duration", value: formatDurationMs(details.durationMs), tone: "muted" }
52527
52863
  ],
@@ -52701,33 +53037,33 @@ function isRunStatus(value2) {
52701
53037
  return false;
52702
53038
  }
52703
53039
  }
52704
- function resolveRunId(target) {
53040
+ function resolveRunId(target, activeStore = store) {
52705
53041
  if (!isFullRunId(target))
52706
53042
  return { kind: "malformed", message: malformedRunIdMessage(target) };
52707
- const exact = store.runs().find((r) => r.id === target);
53043
+ const exact = activeStore.runs().find((r) => r.id === target);
52708
53044
  if (exact)
52709
53045
  return { kind: "exact", runId: exact.id };
52710
53046
  return { kind: "not_found" };
52711
53047
  }
52712
- function resolveToolRunTarget(args, emptyMessage) {
53048
+ function resolveToolRunTarget(args, emptyMessage, activeStore = store) {
52713
53049
  const rawTarget = args.runId?.trim() ?? "";
52714
53050
  if (args.all === true || rawTarget === "--all")
52715
53051
  return { kind: "all" };
52716
- const target = rawTarget || store.activeRunId() || "";
53052
+ const target = rawTarget || activeStore.activeRunId() || "";
52717
53053
  if (!target)
52718
53054
  return { kind: "not_found", target: rawTarget, message: emptyMessage };
52719
- const resolved = resolveRunId(target);
53055
+ const resolved = resolveRunId(target, activeStore);
52720
53056
  if (resolved.kind === "exact")
52721
53057
  return { kind: "run", runId: resolved.runId };
52722
53058
  if (resolved.kind === "malformed")
52723
53059
  return { kind: "malformed", target, message: resolved.message };
52724
53060
  return { kind: "not_found", target, message: `Run not found: ${target}` };
52725
53061
  }
52726
- function resolveStageTarget(runId, stageTarget) {
53062
+ function resolveStageTarget(runId, stageTarget, activeStore = store) {
52727
53063
  const target = stageTarget?.trim();
52728
53064
  if (!target)
52729
53065
  return { ok: true, runId };
52730
- const graph = expandWorkflowGraph(readGraphStoreSnapshot(store), runId);
53066
+ const graph = expandWorkflowGraph(readGraphStoreSnapshot(activeStore), runId);
52731
53067
  const exactVirtualIds = graph.stages.filter((stage) => stage.id === target);
52732
53068
  if (exactVirtualIds.length === 1)
52733
53069
  return resolvedStageTarget(exactVirtualIds[0]);
@@ -52763,8 +53099,8 @@ function ambiguousStageTarget(target, stages) {
52763
53099
  message: `Ambiguous stage identifier "${target}" matches: ${stages.map(expandedStageLabel).join(", ")}`
52764
53100
  };
52765
53101
  }
52766
- function resolveToolStageTarget(runId, stageTarget) {
52767
- return resolveStageTarget(runId, stageTarget);
53102
+ function resolveToolStageTarget(runId, stageTarget, activeStore = store) {
53103
+ return resolveStageTarget(runId, stageTarget, activeStore);
52768
53104
  }
52769
53105
  function resolveControlNodeTarget(runId, stageTarget) {
52770
53106
  const target = stageTarget?.trim();
@@ -53504,10 +53840,13 @@ var CONTRACT_FIDELITY_AUDIT = [
53504
53840
  ].join(`
53505
53841
  `);
53506
53842
  var REVIEWER_INTERCOM_COORDINATION_PROTOCOL = [
53507
- "Concurrent reviewer coordination:",
53843
+ "Concurrent reviewer coordination (constructive quorum):",
53508
53844
  "- At review start, use Intercom to discover sibling reviewers and share validation plans and check ownership.",
53509
53845
  "- Claim, serialize, announce, and release expensive or conflicting shared-checkout/environment work such as suites, builds, package operations, browser/E2E sessions, migrations, and generated-artifact steps; share reusable command evidence.",
53510
- "- Coordination is operational only: inspect independently and return your own verdict rather than copying or deferring to sibling conclusions."
53846
+ "- First, inspect independently and form a preliminary assessment before reading or relying on sibling findings or verdicts. After the exchange, inspect independently and return your own verdict rather than copying or deferring to sibling conclusions.",
53847
+ "- Then run exactly one bounded evidence-exchange round over Intercom: share your preliminary verdict, concise findings, and evidence; challenge blocking findings, surface defects a sibling missed, and correct objective/acceptance-criteria misreadings. Do not start a second round or continue substantive discussion.",
53848
+ "- Verdicts change only through concrete evidence, never through deference to a sibling's approval or rejection; inspect shared evidence yourself before deciding.",
53849
+ "- In `overall_explanation`, record whether deliberation changed your preliminary verdict and, if it did, which concrete evidence caused the change. If it did not, say so; return your own structured decision even when dissent remains."
53511
53850
  ].join(`
53512
53851
  `);
53513
53852
  var REVIEWER_INDEPENDENT_VERIFICATION_CONTRACT = [
@@ -54636,8 +54975,12 @@ import { existsSync as existsSync3 } from "node:fs";
54636
54975
  import { mkdir as mkdir2, readdir, rm, stat } from "node:fs/promises";
54637
54976
  import { dirname as dirname3, join as join10 } from "node:path";
54638
54977
  import { getAgentDir as getAgentDir2, getEnvValue as getEnvValue2 } from "@bastani/atomic";
54978
+
54979
+ // dist/builtin/workflows/src/shared/workflow-artifact-env.ts
54639
54980
  var WORKFLOW_ARTIFACT_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
54640
54981
  var ENV_WORKFLOW_ARTIFACT_DIR = "ATOMIC_WORKFLOW_ARTIFACT_DIR";
54982
+
54983
+ // dist/builtin/workflows/src/shared/workflow-artifacts.ts
54641
54984
  var ARTIFACT_PRUNE_RECHECK_MS = 60 * 60 * 1000;
54642
54985
  var lastArtifactPruneAt = new Map;
54643
54986
  var pendingArtifactPrunes = new Map;
@@ -55703,6 +56046,7 @@ import { mkdirSync as mkdirSync2 } from "node:fs";
55703
56046
  import { tmpdir as tmpdir2, userInfo } from "node:os";
55704
56047
  import { join as join13 } from "node:path";
55705
56048
  import { Type as Type11 } from "typebox";
56049
+ import { createChildProcessEnvironment as createChildProcessEnvironment2 } from "@bastani/atomic";
55706
56050
  var OUTPUT_TYPES = [
55707
56051
  "prototype",
55708
56052
  "wireframe",
@@ -55812,7 +56156,8 @@ function ensurePlaywrightCli() {
55812
56156
  const probe = spawnSync(isWindows ? "where" : "which", ["playwright-cli"], {
55813
56157
  stdio: "ignore",
55814
56158
  timeout: 15000,
55815
- shell: isWindows
56159
+ shell: isWindows,
56160
+ env: createChildProcessEnvironment2()
55816
56161
  });
55817
56162
  return probe.status === 0;
55818
56163
  } catch {
@@ -55832,7 +56177,8 @@ function ensurePlaywrightCli() {
55832
56177
  const install = spawnSync("npm", ["install", "-g", "@playwright/cli@latest"], {
55833
56178
  stdio: "ignore",
55834
56179
  timeout: 180000,
55835
- shell: isWindows
56180
+ shell: isWindows,
56181
+ env: createChildProcessEnvironment2()
55836
56182
  });
55837
56183
  if (install.status === 0) {
55838
56184
  return {
@@ -57617,29 +57963,34 @@ var promptEngineerModelConfig = {
57617
57963
  excludedTools: ["ask_user_question"]
57618
57964
  };
57619
57965
  var researchModelConfig = {
57620
- model: "openai-codex/gpt-5.6-luna:max",
57966
+ model: "anthropic/claude-opus-5:high",
57621
57967
  fallbackModels: [
57622
- "github-copilot/gpt-5.6-luna:max",
57623
- "openai/gpt-5.6-luna:max",
57624
- "anthropic/claude-opus-5:low",
57625
- "github-copilot/claude-opus-5:low",
57626
- "anthropic/claude-fable-5:low",
57627
- "github-copilot/claude-fable-5:low",
57628
- "openai-codex/gpt-5.5:medium",
57629
- "github-copilot/gpt-5.5:medium",
57630
- "openai/gpt-5.5:medium",
57631
- "anthropic/claude-opus-4-8:medium",
57632
- "github-copilot/claude-opus-4.8:medium",
57968
+ "github-copilot/claude-opus-5:high",
57969
+ "openai-codex/gpt-5.6-sol:xhigh",
57970
+ "github-copilot/gpt-5.6-sol:xhigh",
57971
+ "openai/gpt-5.6-sol:xhigh",
57972
+ "anthropic/claude-fable-5:high",
57973
+ "github-copilot/claude-fable-5:high",
57974
+ "kimi-coding/k3:max",
57975
+ "moonshotai/kimi-k3:max",
57976
+ "moonshotai-cn/kimi-k3:max",
57977
+ "openai-codex/gpt-5.5:xhigh",
57978
+ "github-copilot/gpt-5.5:xhigh",
57979
+ "openai/gpt-5.5:xhigh",
57980
+ "anthropic/claude-opus-4-8:high",
57981
+ "github-copilot/claude-opus-4.8:high",
57633
57982
  "xai/grok-4.5:high",
57634
- "zai/glm-5.2:high",
57635
- "zai-coding-cn/glm-5.2:high",
57636
- "openrouter/openai/gpt-5.6-luna:max",
57637
- "openrouter/anthropic/claude-opus-5:low",
57638
- "openrouter/openai/gpt-5.5:medium",
57639
- "openrouter/anthropic/claude-fable-5:low",
57640
- "openrouter/anthropic/claude-opus-4-8:medium",
57983
+ "zai/glm-5.2:xhigh",
57984
+ "zai-coding-cn/glm-5.2:xhigh",
57985
+ "openrouter/anthropic/claude-opus-5:high",
57986
+ "openrouter/openai/gpt-5.6-sol:xhigh",
57987
+ "openrouter/anthropic/claude-fable-5:high",
57988
+ "openrouter/moonshotai/kimi-k3:max",
57989
+ "openrouter/sakana/fugu-ultra:high",
57990
+ "openrouter/openai/gpt-5.5:xhigh",
57991
+ "openrouter/anthropic/claude-opus-4-8:high",
57641
57992
  "openrouter/x-ai/grok-4.5",
57642
- "openrouter/z-ai/glm-5.2:high"
57993
+ "openrouter/z-ai/glm-5.2:xhigh"
57643
57994
  ],
57644
57995
  excludedTools: ["ask_user_question"]
57645
57996
  };
@@ -58615,7 +58966,8 @@ var WORKFLOW_EXIT_STATUSES = new Set([
58615
58966
  "completed",
58616
58967
  "skipped",
58617
58968
  "cancelled",
58618
- "blocked"
58969
+ "blocked",
58970
+ "failed"
58619
58971
  ]);
58620
58972
  function makeWorkflowExitSignal(input) {
58621
58973
  return {
@@ -58623,6 +58975,7 @@ function makeWorkflowExitSignal(input) {
58623
58975
  scope: input.scope,
58624
58976
  status: input.status,
58625
58977
  ...input.reason !== undefined ? { reason: input.reason } : {},
58978
+ ...input.resumable !== undefined ? { resumable: input.resumable } : {},
58626
58979
  ...input.outputSnapshot !== undefined ? { outputSnapshot: input.outputSnapshot } : {},
58627
58980
  ...input.validationError !== undefined ? { validationError: input.validationError } : {}
58628
58981
  };
@@ -58859,6 +59212,9 @@ function readWorkflowExitSignalCandidate(value2, scope) {
58859
59212
  const reason = safeGetProperty(value2, "reason");
58860
59213
  if (!reason.ok || reason.value !== undefined && typeof reason.value !== "string")
58861
59214
  return;
59215
+ const resumable = safeGetProperty(value2, "resumable");
59216
+ if (!resumable.ok || resumable.value !== undefined && typeof resumable.value !== "boolean")
59217
+ return;
58862
59218
  const outputSnapshotValue = safeGetProperty(value2, "outputSnapshot");
58863
59219
  if (!outputSnapshotValue.ok)
58864
59220
  return;
@@ -58873,6 +59229,7 @@ function readWorkflowExitSignalCandidate(value2, scope) {
58873
59229
  scope,
58874
59230
  status: status.value,
58875
59231
  ...reason.value !== undefined ? { reason: reason.value } : {},
59232
+ ...resumable.value !== undefined ? { resumable: resumable.value } : {},
58876
59233
  ...outputSnapshot !== undefined ? { outputSnapshot } : {},
58877
59234
  ...validationError.value !== undefined ? { validationError: safeErrorValue(validationError.value) } : {}
58878
59235
  };
@@ -60789,6 +61146,9 @@ class ScopedDurableBackend {
60789
61146
  hydrateWorkflow(_workflowId) {
60790
61147
  return Promise.resolve();
60791
61148
  }
61149
+ hydrateWorkflowForInspection(_workflowId) {
61150
+ return Promise.resolve({ kind: "absent" });
61151
+ }
60792
61152
  hydrateResumableWorkflows() {
60793
61153
  return Promise.resolve();
60794
61154
  }
@@ -61138,7 +61498,7 @@ function openGitWorktreeGenerationAnchor(worktreeRoot) {
61138
61498
 
61139
61499
  // dist/builtin/workflows/src/runs/shared/worktree-git-runner.ts
61140
61500
  import { spawnSync as spawnSync2 } from "node:child_process";
61141
- import { createGitEnvironment } from "@bastani/atomic";
61501
+ import { createChildProcessEnvironment as createChildProcessEnvironment3, createGitEnvironment } from "@bastani/atomic";
61142
61502
  var DISABLED_GIT_HOOKS_PATH = process.platform === "win32" ? "NUL" : "/dev/null";
61143
61503
  var GIT_COMMAND_TIMEOUT_MS = 60000;
61144
61504
  var GIT_READ_ONLY_PROBE_TIMEOUT_ATTEMPTS = 2;
@@ -61162,7 +61522,7 @@ function spawnGit(cwd, args, plain) {
61162
61522
  const result = spawnSync2("git", plain ? args : gitCommandArgs(args), {
61163
61523
  cwd,
61164
61524
  encoding: "utf-8",
61165
- env: createGitEnvironment({ GIT_OPTIONAL_LOCKS: "0", GIT_TERMINAL_PROMPT: "0", GCM_INTERACTIVE: "never" }),
61525
+ env: createGitEnvironment({ GIT_OPTIONAL_LOCKS: "0", GIT_TERMINAL_PROMPT: "0", GCM_INTERACTIVE: "never" }, createChildProcessEnvironment3()),
61166
61526
  timeout: GIT_COMMAND_TIMEOUT_MS
61167
61527
  });
61168
61528
  return {
@@ -61798,6 +62158,7 @@ import { spawnSync as spawnSync3 } from "node:child_process";
61798
62158
  import * as fs6 from "node:fs";
61799
62159
  import * as os from "node:os";
61800
62160
  import * as path6 from "node:path";
62161
+ import { createChildProcessEnvironment as createChildProcessEnvironment4 } from "@bastani/atomic";
61801
62162
 
61802
62163
  // dist/builtin/workflows/src/runs/shared/worktree-post-create.ts
61803
62164
  import * as fs5 from "node:fs";
@@ -62080,6 +62441,7 @@ function runWorktreeSetupHook(hook, input) {
62080
62441
  cwd: input.worktreePath,
62081
62442
  encoding: "utf-8",
62082
62443
  input: JSON.stringify(input),
62444
+ env: createChildProcessEnvironment4(),
62083
62445
  timeout: hook.timeoutMs,
62084
62446
  shell: false
62085
62447
  });
@@ -63499,8 +63861,9 @@ function createRunFinalizers(input) {
63499
63861
  } catch (err) {
63500
63862
  return finalizeWorkflowExitValidationFailure(err, signal.reason);
63501
63863
  }
63864
+ const resumable = signal.status === "failed" && signal.resumable === true;
63502
63865
  const metadata = {
63503
- resumable: false,
63866
+ resumable,
63504
63867
  exited: true,
63505
63868
  ...signal.reason !== undefined ? { exitReason: signal.reason } : {}
63506
63869
  };
@@ -63511,7 +63874,7 @@ function createRunFinalizers(input) {
63511
63874
  result: outputs,
63512
63875
  exited: true,
63513
63876
  ...signal.reason !== undefined ? { exitReason: signal.reason } : {},
63514
- resumable: false,
63877
+ resumable,
63515
63878
  ts: Date.now()
63516
63879
  });
63517
63880
  return reconcileTerminalRunResult(input.runId, input.runSnapshot, input.activeStore, {
@@ -63879,7 +64242,7 @@ function createWorkflowExitManager(input) {
63879
64242
  if (!statusRead.ok) {
63880
64243
  captureValidationError(statusRead.error);
63881
64244
  } else if (!isWorkflowExitStatus2(rawStatus)) {
63882
- captureValidationError(new TypeError(`atomic-workflows: ctx.exit() status must be one of completed, skipped, cancelled, blocked; got ${describeWorkflowExitOptionValue(rawStatus)}`));
64245
+ captureValidationError(new TypeError(`atomic-workflows: ctx.exit() status must be one of completed, skipped, cancelled, blocked, failed; got ${describeWorkflowExitOptionValue(rawStatus)}`));
63883
64246
  }
63884
64247
  const status = isWorkflowExitStatus2(rawStatus) ? rawStatus : "completed";
63885
64248
  const reasonRead = readWorkflowExitOption(rawOptions, "reason");
@@ -63891,6 +64254,17 @@ function createWorkflowExitManager(input) {
63891
64254
  captureValidationError(new TypeError(`atomic-workflows: ctx.exit() reason must be a string when provided; got ${workflowSerializableTypeName(rawReason)}`));
63892
64255
  }
63893
64256
  const reason = typeof rawReason === "string" ? rawReason : undefined;
64257
+ const resumableRead = readWorkflowExitOption(rawOptions, "resumable");
64258
+ throwNestedSelectedExit();
64259
+ const rawResumable = resumableRead.ok ? resumableRead.value : undefined;
64260
+ if (!resumableRead.ok) {
64261
+ captureValidationError(resumableRead.error);
64262
+ } else if (rawResumable !== undefined && typeof rawResumable !== "boolean") {
64263
+ captureValidationError(new TypeError(`atomic-workflows: ctx.exit() resumable must be a boolean when provided; got ${workflowSerializableTypeName(rawResumable)}`));
64264
+ } else if (rawResumable !== undefined && rawStatus !== "failed") {
64265
+ captureValidationError(new TypeError(`atomic-workflows: ctx.exit() resumable is only valid with status failed; got ${describeWorkflowExitOptionValue(rawStatus)}`));
64266
+ }
64267
+ const resumable = status === "failed" && rawResumable === true;
63894
64268
  const outputsRead = readWorkflowExitOption(rawOptions, "outputs");
63895
64269
  throwNestedSelectedExit();
63896
64270
  const outputSnapshot = !outputsRead.ok ? freezeWorkflowExitOutputSnapshot({ ok: false, error: outputsRead.error }) : outputsRead.value !== undefined ? captureWorkflowExitOutputSnapshot(outputsRead.value) : undefined;
@@ -63899,6 +64273,7 @@ function createWorkflowExitManager(input) {
63899
64273
  scope: input.exitScope,
63900
64274
  status,
63901
64275
  ...reason !== undefined ? { reason } : {},
64276
+ ...status === "failed" ? { resumable } : {},
63902
64277
  ...outputSnapshot !== undefined ? { outputSnapshot } : {},
63903
64278
  ...validationError !== undefined ? { validationError } : {}
63904
64279
  }));
@@ -64329,7 +64704,7 @@ function createChildWorkflowRunner(input) {
64329
64704
  if (childRun.status === "paused" && childRun.exitReason === WORKFLOW_GRACEFUL_QUIT_EXIT_REASON && childRunId !== undefined) {
64330
64705
  throw new WorkflowGracefulQuitError(childRunId, `child workflow "${childName}" (${child.name})`);
64331
64706
  }
64332
- if (!isWorkflowExitStatus2(childRun.status)) {
64707
+ if (!isWorkflowExitStatus2(childRun.status) || childRun.status === "failed" && childRun.exited !== true) {
64333
64708
  const failedChildStage = childRun.stages.find((stage) => stage.failureKind !== undefined);
64334
64709
  throw new Error(`atomic-workflows: child workflow "${childName}" (${child.name}) failed with status ${childRun.status}${childRun.error !== undefined ? `: ${childRun.error}` : ""}`, {
64335
64710
  cause: {
@@ -64418,8 +64793,12 @@ async function finalizeDurableTerminalStatus(input) {
64418
64793
  if (durableStatus === "failed" || durableStatus === "blocked") {
64419
64794
  recordRunTimingCheckpoint(input.durableBackend, input.runSnapshot);
64420
64795
  }
64421
- const failure3 = durableStatus === "failed" && input.runSnapshot.error !== undefined ? {
64422
- error: input.runSnapshot.error,
64796
+ const failure3 = durableStatus === "failed" ? {
64797
+ ...input.runSnapshot.error !== undefined ? { error: input.runSnapshot.error } : {},
64798
+ ...input.runSnapshot.exited === true ? {
64799
+ exited: true,
64800
+ ...input.runSnapshot.exitReason !== undefined ? { exitReason: input.runSnapshot.exitReason } : {}
64801
+ } : {},
64423
64802
  ...input.runSnapshot.failureKind !== undefined ? { failureKind: input.runSnapshot.failureKind } : {},
64424
64803
  ...input.runSnapshot.failureCode !== undefined ? { failureCode: input.runSnapshot.failureCode } : {},
64425
64804
  ...input.runSnapshot.failureRecoverability !== undefined ? { failureRecoverability: input.runSnapshot.failureRecoverability } : {},
@@ -64453,7 +64832,7 @@ function createDurableStageSessionRecorder(input) {
64453
64832
  if (stageRunId === input.runId) {
64454
64833
  await recordStageSessionCheckpoint(input.deps, snapshot, { force: options?.forceDurable === true });
64455
64834
  if (input.runSnapshot !== undefined) {
64456
- recordRunTimingCheckpoint(input.deps.backend, input.runSnapshot, {
64835
+ await recordRunTimingCheckpointAsync(input.deps.backend, input.runSnapshot, {
64457
64836
  debounce: options?.forceDurable !== true
64458
64837
  });
64459
64838
  }
@@ -64502,7 +64881,7 @@ function hasUsableContentBlock(block) {
64502
64881
  }
64503
64882
 
64504
64883
  // dist/builtin/workflows/src/durable/completed-catalog-stage-groups.ts
64505
- function validBoundaryRecordSet(checkpoints, strict) {
64884
+ function validBoundaryRecordSet(checkpoints, strict, requireActiveFingerprint = false) {
64506
64885
  const stages = checkpoints.filter((item) => item.kind === "stage");
64507
64886
  const boundaries = stages.filter((item) => item.topology?.boundary !== undefined);
64508
64887
  const startsByReplay = new Map;
@@ -64517,42 +64896,59 @@ function validBoundaryRecordSet(checkpoints, strict) {
64517
64896
  return false;
64518
64897
  if (boundaries.some((checkpoint) => checkpoint.topology.boundary.event === "terminal" && startsByReplay.get(checkpoint.replayKey)?.length !== 1))
64519
64898
  return false;
64520
- return [...startsByReplay.values()].every((starts) => boundaryTransitionError(starts[0], stages, strict) === undefined);
64899
+ return [...startsByReplay.values()].every((starts) => {
64900
+ const start = starts[0];
64901
+ if (boundaryTransitionError(start, stages, strict) !== undefined)
64902
+ return false;
64903
+ if (!requireActiveFingerprint || start.topology.boundary.invocationFingerprint !== undefined)
64904
+ return true;
64905
+ return stages.some((stage) => stage.replayKey === start.replayKey && stage.topology?.boundary?.event === "terminal" && stage.topology.boundary.status === "completed") && boundaryTransitionError(start, stages, true) === undefined;
64906
+ });
64521
64907
  }
64522
- function validStageGroup(drafts, runId, allowedNodeIds = new Set) {
64908
+ function validStageGroup(drafts, runId, rootRunId, tools = []) {
64523
64909
  if (drafts.some((draft) => draft.topology.stageId.length === 0))
64524
64910
  return false;
64525
- const stageIds = new Set(drafts.map((draft) => draft.topology.stageId));
64526
- if (stageIds.size !== drafts.length)
64911
+ if (tools.some((tool) => tool.topology !== undefined && (tool.topology.version !== DURABLE_TOOL_TOPOLOGY_VERSION || tool.topology.nodeId.length === 0)))
64527
64912
  return false;
64528
- const ids = new Set([...allowedNodeIds, ...stageIds]);
64529
- if (ids.size !== allowedNodeIds.size + stageIds.size)
64913
+ const stageIds = drafts.map((draft) => draft.topology.stageId);
64914
+ const toolIds = tools.map((tool) => tool.topology?.nodeId ?? tool.checkpointId);
64915
+ const ids = new Set([...stageIds, ...toolIds]);
64916
+ if (ids.size !== stageIds.length + toolIds.length)
64530
64917
  return false;
64531
64918
  const orders = drafts.flatMap((draft) => draft.topology.sourceOrder === undefined ? [] : [draft.topology.sourceOrder]);
64532
64919
  if (new Set(orders).size !== orders.length)
64533
64920
  return false;
64534
- if (drafts.some((draft) => draft.topology.parentIds.some((parentId) => !ids.has(parentId))))
64921
+ const parentEntries = [
64922
+ ...drafts.map((draft) => [draft.topology.stageId, draft.topology.parentIds]),
64923
+ ...tools.map((tool) => [tool.topology?.nodeId ?? tool.checkpointId, tool.topology?.parentIds ?? []])
64924
+ ];
64925
+ if (parentEntries.some(([, parentIds]) => parentIds.some((parentId) => !ids.has(parentId))))
64535
64926
  return false;
64536
- const runs = drafts.flatMap((draft) => draft.topology?.run === undefined ? [] : [draft.topology.run]);
64927
+ const runs = [
64928
+ ...drafts.flatMap((draft) => draft.topology?.run === undefined ? [] : [draft.topology.run]),
64929
+ ...tools.flatMap((tool) => tool.topology?.run === undefined ? [] : [tool.topology.run])
64930
+ ];
64537
64931
  const first = runs[0];
64538
64932
  if (runs.some((run) => run.runId !== runId || first !== undefined && (run.runName !== first.runName || run.parentRunId !== first.parentRunId || run.parentStageId !== first.parentStageId || run.rootRunId !== first.rootRunId)))
64539
64933
  return false;
64540
- const parents = new Map(drafts.map((draft) => [draft.topology.stageId, draft.topology.parentIds]));
64934
+ if (runId === rootRunId && runs.some((run) => run.parentRunId !== undefined || run.parentStageId !== undefined || run.rootRunId !== undefined))
64935
+ return false;
64936
+ const parents = new Map(parentEntries);
64541
64937
  const visiting = new Set;
64542
64938
  const visited = new Set;
64543
- const cyclic = (stageId) => {
64544
- if (visiting.has(stageId))
64939
+ const cyclic = (nodeId) => {
64940
+ if (visiting.has(nodeId))
64545
64941
  return true;
64546
- if (visited.has(stageId))
64942
+ if (visited.has(nodeId))
64547
64943
  return false;
64548
- visiting.add(stageId);
64549
- if ((parents.get(stageId) ?? []).some(cyclic))
64944
+ visiting.add(nodeId);
64945
+ if ((parents.get(nodeId) ?? []).some(cyclic))
64550
64946
  return true;
64551
- visiting.delete(stageId);
64552
- visited.add(stageId);
64947
+ visiting.delete(nodeId);
64948
+ visited.add(nodeId);
64553
64949
  return false;
64554
64950
  };
64555
- return ![...stageIds].some(cyclic);
64951
+ return ![...ids].some(cyclic);
64556
64952
  }
64557
64953
  function compareDraftSourceOrder(left, right) {
64558
64954
  const leftOrder = left.topology?.sourceOrder;
@@ -64568,16 +64964,24 @@ function compareDraftSourceOrder(left, right) {
64568
64964
  function runTopologyFor(drafts, tools) {
64569
64965
  return drafts.find((draft) => draft.topology?.run !== undefined)?.topology?.run ?? tools.find((checkpoint) => checkpoint.topology?.run !== undefined)?.topology?.run;
64570
64966
  }
64571
- function validateRunGroups(grouped, rootRunId, tools) {
64967
+ function validateRunGroups(grouped, rootRunId, tools, checkpoints) {
64572
64968
  const toolsFor = (runId) => tools.filter((checkpoint) => (checkpoint.topology?.run?.runId ?? rootRunId) === runId);
64573
64969
  const owners = new Map;
64970
+ const syntheticChildIds = new Set;
64574
64971
  for (const [parentRunId, drafts] of grouped) {
64575
64972
  for (const draft of drafts) {
64576
64973
  const childRunId = childRunIdFromDraft(draft);
64577
64974
  if (childRunId === undefined)
64578
64975
  continue;
64579
- if (!grouped.has(childRunId) || childRunId === parentRunId || owners.has(childRunId))
64976
+ if (childRunId === parentRunId || owners.has(childRunId))
64580
64977
  return false;
64978
+ if (!grouped.has(childRunId)) {
64979
+ if (!isSyntheticExitedChild(draft, parentRunId, childRunId, rootRunId) || childScopedEvidenceExists(checkpoints, draft.replayKey, childRunId))
64980
+ return false;
64981
+ syntheticChildIds.add(childRunId);
64982
+ owners.set(childRunId, draft);
64983
+ continue;
64984
+ }
64581
64985
  const childRun = runTopologyFor(grouped.get(childRunId), toolsFor(childRunId));
64582
64986
  if (childRun?.parentRunId !== parentRunId || childRun.parentStageId !== draft.topology?.stageId || childRun.rootRunId !== undefined && childRun.rootRunId !== rootRunId)
64583
64987
  return false;
@@ -64589,6 +64993,8 @@ function validateRunGroups(grouped, rootRunId, tools) {
64589
64993
  return false;
64590
64994
  }
64591
64995
  for (const runId of owners.keys()) {
64996
+ if (syntheticChildIds.has(runId))
64997
+ continue;
64592
64998
  const seen = new Set;
64593
64999
  let current = runId;
64594
65000
  while (current !== undefined && current !== rootRunId) {
@@ -64602,6 +65008,18 @@ function validateRunGroups(grouped, rootRunId, tools) {
64602
65008
  }
64603
65009
  return true;
64604
65010
  }
65011
+ function isSyntheticExitedChild(draft, parentRunId, childRunId, rootRunId) {
65012
+ const child = workflowChildFromDraft(draft);
65013
+ const boundary = draft.topology?.boundary;
65014
+ return child?.runId === childRunId && child.exited === true && boundary?.event === "terminal" && boundary.status === "completed" && boundary.child.runId === childRunId && boundary.child.parentRunId === parentRunId && boundary.child.parentStageId === draft.topology?.stageId && boundary.child.rootRunId === rootRunId;
65015
+ }
65016
+ function childScopedEvidenceExists(checkpoints, boundaryReplayKey, childRunId) {
65017
+ const prefix = `${boundaryReplayKey}:`;
65018
+ return checkpoints.some((checkpoint) => {
65019
+ const lookupIdentity = checkpoint.kind === "tool" ? checkpoint.argsHash : checkpoint.kind === "ui" ? checkpoint.promptHash : checkpoint.replayKey;
65020
+ return checkpoint.checkpointId.startsWith(prefix) || lookupIdentity.startsWith(prefix) || checkpoint.kind !== "ui" && checkpoint.topology?.run?.runId === childRunId;
65021
+ });
65022
+ }
64605
65023
  function retainReachableRunGroups(grouped, rootRunId) {
64606
65024
  const reachable = new Set([rootRunId]);
64607
65025
  const pending = [rootRunId];
@@ -64699,15 +65117,17 @@ function valueOrExisting(key2, checkpoint, existing) {
64699
65117
  }
64700
65118
  function workflowChildFromDraft(draft) {
64701
65119
  const strict = parseWorkflowChildResult(draft.output);
64702
- const child = strict ?? (hasCurrentStageIdentity(draft) ? undefined : parseLegacyWorkflowChildResult(draft.output));
65120
+ const legacy = hasCurrentStageIdentity(draft) ? undefined : parseLegacyWorkflowChildResult(draft.output);
65121
+ const child = strict ?? legacy;
64703
65122
  if (child === undefined)
64704
65123
  return;
65124
+ const exited = strict?.exited ?? false;
64705
65125
  return {
64706
65126
  alias: child.workflow,
64707
65127
  workflow: child.workflow,
64708
65128
  runId: child.runId,
64709
65129
  status: child.status,
64710
- ...child.exited !== undefined ? { exited: child.exited } : {},
65130
+ exited,
64711
65131
  outputs: child.outputs,
64712
65132
  ...typeof child.exitReason === "string" ? { exitReason: child.exitReason } : {}
64713
65133
  };
@@ -65070,7 +65490,7 @@ function completedWorkflowRunSnapshots(backend, entry) {
65070
65490
  const checkpoints = backend.listCheckpoints(entry.workflowId);
65071
65491
  if (checkpoints.length === 0)
65072
65492
  return [];
65073
- const runs = runSnapshotsFromCheckpoints(checkpoints, handle.workflowId, handle.name, handle.updatedAt).map((run2) => ({ ...run2, stages: run2.stages.map(validatedStageTranscript) }));
65493
+ const runs = runSnapshotsFromCheckpoints(checkpoints, handle.workflowId, handle.name, handle.updatedAt, COMPLETED_RECONSTRUCTION).map((run2) => ({ ...run2, stages: run2.stages.map(validatedStageTranscript) }));
65074
65494
  const rootIndex = runs.findIndex((run2) => run2.id === handle.workflowId);
65075
65495
  if (rootIndex < 0)
65076
65496
  return [];
@@ -65083,6 +65503,8 @@ function completedWorkflowRunSnapshots(backend, entry) {
65083
65503
  endedAt: handle.updatedAt,
65084
65504
  durationMs: rootDuration,
65085
65505
  ...handle.error !== undefined ? { error: handle.error } : {},
65506
+ ...handle.exited !== undefined ? { exited: handle.exited } : {},
65507
+ ...handle.exitReason !== undefined ? { exitReason: handle.exitReason } : {},
65086
65508
  ...handle.failureKind !== undefined ? { failureKind: handle.failureKind } : {},
65087
65509
  ...handle.failureCode !== undefined ? { failureCode: handle.failureCode } : {},
65088
65510
  ...handle.failureRecoverability !== undefined ? { failureRecoverability: handle.failureRecoverability } : {},
@@ -65092,11 +65514,45 @@ function completedWorkflowRunSnapshots(backend, entry) {
65092
65514
  };
65093
65515
  return [root, ...runs.filter((_, index) => index !== rootIndex)];
65094
65516
  }
65517
+ function durableWorkflowRunSnapshots(backend, handle) {
65518
+ const checkpoints = backend.listCheckpoints(handle.workflowId);
65519
+ if (checkpoints.length === 0) {
65520
+ return [rootSnapshot(backend, handle, { stages: [], toolNodes: [] })];
65521
+ }
65522
+ const requiresTerminalTopology = handle.status === "completed" || handle.status === "failed";
65523
+ const runs = runSnapshotsFromCheckpoints(checkpoints, handle.workflowId, handle.name, handle.updatedAt, requiresTerminalTopology ? COMPLETED_RECONSTRUCTION : ACTIVE_INSPECTION_RECONSTRUCTION);
65524
+ const rootIndex = runs.findIndex((run2) => run2.id === handle.workflowId);
65525
+ if (rootIndex < 0)
65526
+ return [];
65527
+ return [rootSnapshot(backend, handle, runs[rootIndex]), ...runs.filter((_, index) => index !== rootIndex)];
65528
+ }
65529
+ function rootSnapshot(backend, handle, graph) {
65530
+ const terminal = handle.status === "completed" || handle.status === "failed" || handle.status === "cancelled";
65531
+ const priorDurationMs = priorRunElapsedMs(backend, handle.workflowId);
65532
+ const terminalDurationMs = priorDurationMs ?? Math.max(0, handle.updatedAt - handle.createdAt);
65533
+ return {
65534
+ id: handle.workflowId,
65535
+ name: handle.name,
65536
+ inputs: { ...handle.inputs },
65537
+ status: handle.status,
65538
+ stages: graph.stages,
65539
+ toolNodes: graph.toolNodes,
65540
+ startedAt: handle.createdAt,
65541
+ ...terminal ? { endedAt: handle.updatedAt, durationMs: terminalDurationMs } : priorDurationMs === undefined ? {} : { accumulatedDurationMs: priorDurationMs },
65542
+ ...handle.error !== undefined ? { error: handle.error } : {},
65543
+ ...handle.failureKind !== undefined ? { failureKind: handle.failureKind } : {},
65544
+ ...handle.failureCode !== undefined ? { failureCode: handle.failureCode } : {},
65545
+ ...handle.failureRecoverability !== undefined ? { failureRecoverability: handle.failureRecoverability } : {},
65546
+ ...handle.failureDisposition !== undefined ? { failureDisposition: handle.failureDisposition } : {},
65547
+ ...handle.failedToolNodeId !== undefined ? { failedToolNodeId: handle.failedToolNodeId } : {},
65548
+ resumable: isDurableWorkflowResumable(handle)
65549
+ };
65550
+ }
65095
65551
  function durableNestedRunSnapshots(backend, rootWorkflowId) {
65096
65552
  const handle = backend.getWorkflow(rootWorkflowId);
65097
65553
  if (handle === undefined)
65098
65554
  return [];
65099
- return runSnapshotsFromCheckpoints(backend.listCheckpoints(rootWorkflowId), rootWorkflowId, handle.name, handle.updatedAt, false).filter((run2) => run2.id !== rootWorkflowId);
65555
+ return runSnapshotsFromCheckpoints(backend.listCheckpoints(rootWorkflowId), rootWorkflowId, handle.name, handle.updatedAt, LEGACY_ACTIVE_RECONSTRUCTION).filter((run2) => run2.id !== rootWorkflowId);
65100
65556
  }
65101
65557
  function validatedStageTranscript(stage) {
65102
65558
  if (stage.sessionFile === undefined || isReopenableSessionTranscript(stage.sessionFile))
@@ -65166,15 +65622,36 @@ function summarizeCompletedToolResult(value2) {
65166
65622
  return flattenTruncatedString(String(value2).slice(0, 240));
65167
65623
  return serialized.length <= 240 ? serialized : `${flattenTruncatedString(serialized.slice(0, 237))}...`;
65168
65624
  }
65169
- function runSnapshotsFromCheckpoints(checkpoints, rootRunId, rootRunName, fallbackCompletedAt, strict = true) {
65170
- if (!validBoundaryRecordSet(checkpoints, strict))
65625
+ var COMPLETED_RECONSTRUCTION = {
65626
+ requireTerminal: true,
65627
+ failClosed: true,
65628
+ retainActive: false,
65629
+ failOnUnreachable: false,
65630
+ requireActiveBoundaryFingerprint: false
65631
+ };
65632
+ var ACTIVE_INSPECTION_RECONSTRUCTION = {
65633
+ requireTerminal: false,
65634
+ failClosed: true,
65635
+ retainActive: true,
65636
+ failOnUnreachable: true,
65637
+ requireActiveBoundaryFingerprint: true
65638
+ };
65639
+ var LEGACY_ACTIVE_RECONSTRUCTION = {
65640
+ requireTerminal: false,
65641
+ failClosed: false,
65642
+ retainActive: true,
65643
+ failOnUnreachable: false,
65644
+ requireActiveBoundaryFingerprint: false
65645
+ };
65646
+ function runSnapshotsFromCheckpoints(checkpoints, rootRunId, rootRunName, fallbackCompletedAt, policy = COMPLETED_RECONSTRUCTION) {
65647
+ if (!validBoundaryRecordSet(checkpoints, policy.requireTerminal, policy.requireActiveBoundaryFingerprint))
65171
65648
  return [];
65172
65649
  const stageRecords = checkpoints.filter((checkpoint) => checkpoint.kind === "stage");
65173
65650
  const identityRecords = stageRecords.filter((stage) => stage.topology?.sourceOrder !== undefined || stage.topology?.status !== undefined || stage.topology?.occurrenceKey !== undefined || stage.topology?.boundary !== undefined);
65174
65651
  if (immutableStageGroupError(identityRecords) !== undefined)
65175
65652
  return [];
65176
65653
  const recordsByGroup = groupByDurableStageKey(stageRecords);
65177
- const candidates = [...recordsByGroup.values()].map((records) => mergeStageGroup(records, stageRecords, checkpoints)).filter((draft) => !strict || draft.topology?.run === undefined || draft.endedAt !== undefined || draft.output !== undefined).map((draft) => draft.topology !== undefined ? draft : {
65654
+ const candidates = [...recordsByGroup.values()].map((records) => mergeStageGroup(records, stageRecords, checkpoints)).filter((draft) => policy.retainActive || draft.topology?.run === undefined || draft.endedAt !== undefined || draft.output !== undefined).map((draft) => draft.topology !== undefined ? draft : {
65178
65655
  ...draft,
65179
65656
  topology: {
65180
65657
  version: DURABLE_STAGE_TOPOLOGY_VERSION,
@@ -65185,13 +65662,36 @@ function runSnapshotsFromCheckpoints(checkpoints, rootRunId, rootRunName, fallba
65185
65662
  }).sort(compareDraftSourceOrder);
65186
65663
  const drafts = checkpointDrafts(checkpoints);
65187
65664
  const toolCheckpoints = drafts.tools;
65665
+ if (policy.failClosed) {
65666
+ for (const draft of candidates) {
65667
+ const boundary = draft.topology?.boundary;
65668
+ if (boundary === undefined || childRunIdFromDraft(draft) === undefined)
65669
+ continue;
65670
+ if (boundary.replayScope !== draft.replayKey)
65671
+ return [];
65672
+ const expectedChildRun = {
65673
+ runId: boundary.child.runId,
65674
+ runName: boundary.child.runName,
65675
+ parentRunId: boundary.child.parentRunId,
65676
+ parentStageId: boundary.child.parentStageId,
65677
+ rootRunId: boundary.child.rootRunId
65678
+ };
65679
+ const childToolIds = new Set(toolCheckpoints.flatMap((checkpoint) => checkpoint.topology?.run?.runId === expectedChildRun.runId ? [checkpoint.topology.nodeId] : []));
65680
+ if (directChildTopologyError(stageRecords, boundary.replayScope, expectedChildRun, true, childToolIds) !== undefined)
65681
+ return [];
65682
+ }
65683
+ }
65188
65684
  if (candidates.length === 0 && toolCheckpoints.length === 0) {
65189
- return strict ? [] : [syntheticRun(rootRunId, rootRunName, checkpoints.length, fallbackCompletedAt)];
65685
+ const supportedNonGraphState = checkpoints.every((checkpoint) => checkpoint.kind === "ui" || checkpoint.kind === "tool" && checkpoint.argsHash === RUN_TIMING_CHECKPOINT_NAME);
65686
+ if (policy.failClosed && supportedNonGraphState) {
65687
+ return [emptyGraphRun(rootRunId, rootRunName, fallbackCompletedAt)];
65688
+ }
65689
+ return policy.failClosed ? [] : [syntheticRun(rootRunId, rootRunName, checkpoints.length, fallbackCompletedAt)];
65190
65690
  }
65191
65691
  const grouped = new Map;
65192
65692
  for (const draft of candidates) {
65193
65693
  if (draft.topology?.version !== DURABLE_STAGE_TOPOLOGY_VERSION) {
65194
- if (strict)
65694
+ if (policy.failClosed)
65195
65695
  return [];
65196
65696
  continue;
65197
65697
  }
@@ -65207,13 +65707,30 @@ function runSnapshotsFromCheckpoints(checkpoints, rootRunId, rootRunName, fallba
65207
65707
  }
65208
65708
  for (const group of grouped.values())
65209
65709
  group.sort(compareDraftSourceOrder);
65710
+ const groupedCount = grouped.size;
65210
65711
  retainReachableRunGroups(grouped, rootRunId);
65211
- if (!validateRunGroups(grouped, rootRunId, toolCheckpoints))
65712
+ if (policy.failOnUnreachable && grouped.size !== groupedCount)
65713
+ return [];
65714
+ if (!validateRunGroups(grouped, rootRunId, toolCheckpoints, checkpoints))
65212
65715
  return [];
65716
+ const syntheticChildren = [];
65717
+ for (const [parentRunId, runDrafts] of grouped) {
65718
+ for (const draft of runDrafts) {
65719
+ const child = workflowChildFromDraft(draft);
65720
+ if (child?.exited !== true || grouped.has(child.runId))
65721
+ continue;
65722
+ if (!isSyntheticExitedChild(draft, parentRunId, child.runId, rootRunId) || childScopedEvidenceExists(checkpoints, draft.replayKey, child.runId)) {
65723
+ if (policy.failClosed)
65724
+ return [];
65725
+ continue;
65726
+ }
65727
+ syntheticChildren.push({ parentRunId, owner: draft, child });
65728
+ }
65729
+ }
65213
65730
  const idMaps = new Map;
65214
65731
  for (const [runId, runDrafts] of grouped) {
65215
- const ownedToolIds = new Set(toolCheckpoints.flatMap((checkpoint) => (checkpoint.topology?.run?.runId ?? rootRunId) === runId ? [checkpoint.topology?.nodeId ?? checkpoint.checkpointId] : []));
65216
- if (!validStageGroup(runDrafts, runId, ownedToolIds))
65732
+ const ownedTools = toolCheckpoints.filter((checkpoint) => (checkpoint.topology?.run?.runId ?? rootRunId) === runId);
65733
+ if (!validStageGroup(runDrafts, runId, rootRunId, ownedTools))
65217
65734
  return [];
65218
65735
  const ids = new Map;
65219
65736
  let hasIdentityConflict = false;
@@ -65229,7 +65746,7 @@ function runSnapshotsFromCheckpoints(checkpoints, rootRunId, rootRunName, fallba
65229
65746
  }
65230
65747
  });
65231
65748
  if (hasIdentityConflict) {
65232
- if (strict)
65749
+ if (policy.failClosed)
65233
65750
  return [];
65234
65751
  grouped.delete(runId);
65235
65752
  continue;
@@ -65243,12 +65760,13 @@ function runSnapshotsFromCheckpoints(checkpoints, rootRunId, rootRunName, fallba
65243
65760
  idMaps.set(runId, ids);
65244
65761
  }
65245
65762
  const runs = [];
65763
+ const emittedRunIds = new Set;
65246
65764
  for (const [runId, runDrafts] of grouped) {
65247
65765
  const ids = idMaps.get(runId);
65248
65766
  const ownedTools = toolCheckpoints.filter((checkpoint) => (checkpoint.topology?.run?.runId ?? rootRunId) === runId);
65249
65767
  const hasUnknownParents = runDrafts.some((draft) => draft.topology.parentIds.some((parentId) => !ids.has(parentId))) || ownedTools.some((checkpoint) => checkpoint.topology?.parentIds.some((parentId) => !ids.has(parentId)) === true);
65250
65768
  if (hasUnknownParents) {
65251
- if (strict)
65769
+ if (policy.failClosed)
65252
65770
  return [];
65253
65771
  continue;
65254
65772
  }
@@ -65258,23 +65776,66 @@ function runSnapshotsFromCheckpoints(checkpoints, rootRunId, rootRunName, fallba
65258
65776
  const startedAt = Math.min(...stages.map((stage) => stage.startedAt ?? fallbackCompletedAt), ...toolNodes.map((tool) => tool.startedAt ?? tool.endedAt ?? fallbackCompletedAt));
65259
65777
  const endedAt = Math.max(...stages.map((stage) => stage.endedAt ?? fallbackCompletedAt), ...toolNodes.map((tool) => tool.endedAt ?? fallbackCompletedAt));
65260
65778
  const owner = runId === rootRunId ? undefined : boundaryOwner(grouped, runId);
65779
+ const status = owner === undefined ? "completed" : childRunStatus(owner);
65780
+ const terminal = status !== "running" && status !== "pending" && status !== "paused" && status !== "blocked";
65261
65781
  const parentRunId = run2?.parentRunId ?? rootRunId;
65262
65782
  const boundarySourceId = grouped.get(parentRunId)?.find((draft) => childRunIdFromDraft(draft) === runId)?.topology?.stageId;
65263
65783
  const declaredParentStageId = run2?.parentStageId === undefined ? undefined : idMaps.get(parentRunId)?.get(run2.parentStageId);
65264
65784
  const parentStageId = declaredParentStageId ?? (boundarySourceId === undefined ? undefined : idMaps.get(parentRunId)?.get(boundarySourceId));
65785
+ const ownerChild = owner === undefined ? undefined : workflowChildFromDraft(owner);
65265
65786
  runs.push({
65266
65787
  id: runId,
65267
65788
  name: run2?.runName ?? rootRunName,
65268
65789
  inputs: {},
65269
- status: owner === undefined ? "completed" : childRunStatus(owner),
65790
+ status,
65270
65791
  stages,
65271
65792
  toolNodes,
65272
65793
  startedAt,
65273
- endedAt,
65274
- durationMs: Math.max(0, endedAt - startedAt),
65794
+ ...terminal ? { endedAt, durationMs: Math.max(0, endedAt - startedAt) } : {},
65275
65795
  ...run2?.parentRunId !== undefined ? { parentRunId: run2.parentRunId } : {},
65276
65796
  ...parentStageId !== undefined ? { parentStageId } : {},
65277
65797
  ...run2?.rootRunId !== undefined ? { rootRunId: run2.rootRunId } : {},
65798
+ ...ownerChild?.exited === true ? {
65799
+ result: ownerChild.outputs,
65800
+ exited: true,
65801
+ ...ownerChild.exitReason !== undefined ? { exitReason: ownerChild.exitReason } : {}
65802
+ } : {},
65803
+ resumable: false
65804
+ });
65805
+ emittedRunIds.add(runId);
65806
+ }
65807
+ for (const { parentRunId, owner, child } of syntheticChildren) {
65808
+ if (!emittedRunIds.has(parentRunId)) {
65809
+ if (policy.failClosed)
65810
+ return [];
65811
+ continue;
65812
+ }
65813
+ const topology = owner.topology;
65814
+ const boundary = topology.boundary;
65815
+ const parentStageId = idMaps.get(parentRunId)?.get(topology.stageId);
65816
+ if (parentStageId === undefined) {
65817
+ if (policy.failClosed)
65818
+ return [];
65819
+ continue;
65820
+ }
65821
+ const startedAt = owner.startedAt ?? owner.firstCompletedAt;
65822
+ const endedAt = owner.endedAt ?? owner.firstCompletedAt;
65823
+ runs.push({
65824
+ id: child.runId,
65825
+ name: boundary.child.runName,
65826
+ inputs: {},
65827
+ status: child.status,
65828
+ stages: [],
65829
+ toolNodes: [],
65830
+ startedAt,
65831
+ endedAt,
65832
+ durationMs: Math.max(0, endedAt - startedAt),
65833
+ parentRunId,
65834
+ parentStageId,
65835
+ rootRunId: boundary.child.rootRunId,
65836
+ result: child.outputs,
65837
+ exited: true,
65838
+ ...child.exitReason !== undefined ? { exitReason: child.exitReason } : {},
65278
65839
  resumable: false
65279
65840
  });
65280
65841
  }
@@ -65322,6 +65883,20 @@ function stageResult(draft) {
65322
65883
  return;
65323
65884
  return typeof draft.output === "string" ? draft.output : JSON.stringify(draft.output);
65324
65885
  }
65886
+ function emptyGraphRun(runId, runName, completedAt) {
65887
+ return {
65888
+ id: runId,
65889
+ name: runName,
65890
+ inputs: {},
65891
+ status: "completed",
65892
+ stages: [],
65893
+ toolNodes: [],
65894
+ startedAt: completedAt,
65895
+ endedAt: completedAt,
65896
+ durationMs: 0,
65897
+ resumable: false
65898
+ };
65899
+ }
65325
65900
  function syntheticRun(runId, runName, checkpointCount, completedAt) {
65326
65901
  return {
65327
65902
  id: runId,
@@ -65355,6 +65930,14 @@ function durableCompletedNestedRunSubtree(backend, rootWorkflowId, childRunId) {
65355
65930
  const nested = durableNestedRunSnapshots(backend, rootWorkflowId);
65356
65931
  if (!nested.some((run2) => run2.id === childRunId))
65357
65932
  return;
65933
+ const intentionalExitStatuses = new Map;
65934
+ for (const checkpoint of backend.listCheckpoints(rootWorkflowId)) {
65935
+ if (checkpoint.kind !== "stage")
65936
+ continue;
65937
+ const child = parseWorkflowChildResult(checkpoint.output);
65938
+ if (child?.exited === true)
65939
+ intentionalExitStatuses.set(child.runId, child.status);
65940
+ }
65358
65941
  const included = new Set([childRunId]);
65359
65942
  let priorSize = -1;
65360
65943
  while (priorSize !== included.size) {
@@ -65365,9 +65948,17 @@ function durableCompletedNestedRunSubtree(backend, rootWorkflowId, childRunId) {
65365
65948
  }
65366
65949
  }
65367
65950
  const subtree = nested.filter((run2) => included.has(run2.id));
65368
- const complete = subtree.length === included.size && subtree.every((run2) => run2.status === "completed" && run2.endedAt !== undefined && run2.stages.every((stage) => isTerminalStage2(stage.status) && stage.endedAt !== undefined));
65951
+ const complete = subtree.length === included.size && subtree.every((run2) => isCompleteCachedRun(run2, intentionalExitStatuses));
65369
65952
  return complete ? subtree : undefined;
65370
65953
  }
65954
+ function isCompleteCachedRun(run2, intentionalExitStatuses) {
65955
+ if (run2.endedAt === undefined || !run2.stages.every((stage) => isTerminalStage2(stage.status) && stage.endedAt !== undefined)) {
65956
+ return false;
65957
+ }
65958
+ if (run2.status === "completed" || run2.exited === true)
65959
+ return true;
65960
+ return intentionalExitStatuses.get(run2.id) === run2.status;
65961
+ }
65371
65962
  function isTerminalStage2(status) {
65372
65963
  return status === "completed" || status === "failed" || status === "skipped";
65373
65964
  }
@@ -65509,6 +66100,8 @@ function createDurableCachedStageRecorder(input) {
65509
66100
  }
65510
66101
  function reconcileCachedDirectChildParentStage(input) {
65511
66102
  const existingRun = input.store.runs().find((run2) => run2.id === input.checkpointChildRunId);
66103
+ if (existingRun === undefined)
66104
+ return false;
65512
66105
  const runById = new Map(input.store.runs().map((run2) => [run2.id, run2]));
65513
66106
  const storedParentRun = runById.get(input.parentRun.id);
65514
66107
  if (storedParentRun !== undefined && (storedParentRun.parentRunId !== input.parentRun.parentRunId || storedParentRun.parentStageId !== input.parentRun.parentStageId))
@@ -65519,7 +66112,8 @@ function reconcileCachedDirectChildParentStage(input) {
65519
66112
  if (expectedRootRunId === undefined)
65520
66113
  return false;
65521
66114
  const storedBoundary = storedParentRun?.stages.find((stage) => stage.id === input.boundary.id);
65522
- if (!rootMatches(input.parentRun.rootRunId, expectedRootRunId) || !rootMatches(storedParentRun?.rootRunId, expectedRootRunId) || authoritativeWorkflowChildRunId(input.boundary) !== input.checkpointChildRunId || storedParentRun !== undefined && authoritativeWorkflowChildRunId(storedBoundary) !== input.checkpointChildRunId || input.catalogRun.id !== input.checkpointChildRunId || existingRun?.status !== "completed" || input.catalogRun.status !== "completed" || existingRun.parentRunId !== input.parentRun.id || input.catalogRun.parentRunId !== input.parentRun.id || input.catalogRun.parentStageId === undefined || existingRun.parentStageId !== input.catalogRun.parentStageId || !rootMatches(existingRun.rootRunId, expectedRootRunId) || !rootMatches(input.catalogRun.rootRunId, expectedRootRunId))
66115
+ const cachedChildStatusMatches = existingRun?.status === "completed" && input.catalogRun.status === "completed" || input.boundary.workflowChild?.exited === true && input.boundary.workflowChild.runId === input.checkpointChildRunId && existingRun?.status === input.catalogRun.status && input.boundary.workflowChild.status === input.catalogRun.status;
66116
+ if (!rootMatches(input.parentRun.rootRunId, expectedRootRunId) || !rootMatches(storedParentRun?.rootRunId, expectedRootRunId) || authoritativeWorkflowChildRunId(input.boundary) !== input.checkpointChildRunId || storedParentRun !== undefined && authoritativeWorkflowChildRunId(storedBoundary) !== input.checkpointChildRunId || input.catalogRun.id !== input.checkpointChildRunId || !cachedChildStatusMatches || existingRun.parentRunId !== input.parentRun.id || input.catalogRun.parentRunId !== input.parentRun.id || input.catalogRun.parentStageId === undefined || existingRun.parentStageId !== input.catalogRun.parentStageId || !rootMatches(existingRun.rootRunId, expectedRootRunId) || !rootMatches(input.catalogRun.rootRunId, expectedRootRunId))
65523
66117
  return false;
65524
66118
  return input.store.reconcileRunParentStage(existingRun.id, input.catalogRun.parentStageId, input.boundary.id);
65525
66119
  }
@@ -65873,11 +66467,12 @@ function createTrackedToolPrimitive(input) {
65873
66467
 
65874
66468
  // dist/builtin/workflows/src/runs/foreground/executor-child-boundary.ts
65875
66469
  function workflowChildResultFromReplay(snapshot) {
66470
+ const exited = snapshot.exited ?? (snapshot.status === "completed" ? false : undefined);
65876
66471
  const candidate = {
65877
66472
  workflow: snapshot.workflow,
65878
66473
  runId: snapshot.runId,
65879
66474
  status: snapshot.status,
65880
- exited: snapshot.exited,
66475
+ exited,
65881
66476
  outputs: cloneWorkflowChildValue(snapshot.outputs),
65882
66477
  ...snapshot.exitReason !== undefined ? { exitReason: snapshot.exitReason } : {}
65883
66478
  };
@@ -66185,7 +66780,7 @@ function createTrackedStageCaller(input) {
66185
66780
  if (suppressQueuedContinuation)
66186
66781
  runtime.state.suppressQueuedUserMessageContinuation = true;
66187
66782
  try {
66188
- result = await raceAbort(runtime.innerCtx.prompt(RESUME_CONTINUATION_PROMPT), runtime.signal);
66783
+ result = await runtime.raceStageSessionHeartbeat(raceAbort(runtime.innerCtx.prompt(RESUME_CONTINUATION_PROMPT), runtime.signal));
66189
66784
  } finally {
66190
66785
  if (suppressQueuedContinuation)
66191
66786
  runtime.state.suppressQueuedUserMessageContinuation = false;
@@ -66212,46 +66807,51 @@ function createTrackedStageCaller(input) {
66212
66807
  throw err;
66213
66808
  }
66214
66809
  const trackStageLifecycle = !runtime.state.stageFinalized;
66215
- let refreshedParentIds;
66216
- if (trackStageLifecycle && !input.hasContinuation && runtime.stageSnapshot.startedAt === undefined && !input.hasScopedParents) {
66217
- const actualParentIds = runtime.scheduler.tracker.currentParents();
66218
- const sameParents = actualParentIds.length === runtime.stageSnapshot.parentIds.length && actualParentIds.every((value2) => runtime.stageSnapshot.parentIds.includes(value2));
66219
- if (!sameParents) {
66220
- runtime.scheduler.tracker.replaceParents(runtime.stageId, actualParentIds);
66221
- refreshedParentIds = actualParentIds;
66222
- }
66223
- }
66224
- if (trackStageLifecycle) {
66225
- const now = Date.now();
66226
- const hasNoExplicitModelConfig = input.options?.model === undefined && input.options?.fallbackModels === undefined;
66227
- const promptAdapterHandlesInitialPrompt = input.adapters.prompt !== undefined;
66228
- if (callOptions.eagerSession && !promptAdapterHandlesInitialPrompt && (hasNoExplicitModelConfig || await hasExplicitFastModeCandidate({
66229
- model: input.options?.model,
66230
- fallbackModels: input.options?.fallbackModels,
66231
- models: runtime.opts.models
66232
- }))) {
66233
- try {
66234
- await runtime.innerCtx.__ensureSession();
66235
- runtime.captureStageSessionMeta();
66236
- } catch (err) {
66237
- if (!(err instanceof Error && err.message.includes("prompt adapter not configured")))
66238
- throw err;
66810
+ let applyTerminalStageState;
66811
+ let terminalStateIsSuccess = false;
66812
+ try {
66813
+ let refreshedParentIds;
66814
+ if (trackStageLifecycle && !input.hasContinuation && runtime.stageSnapshot.startedAt === undefined && !input.hasScopedParents) {
66815
+ const actualParentIds = runtime.scheduler.tracker.currentParents();
66816
+ const sameParents = actualParentIds.length === runtime.stageSnapshot.parentIds.length && actualParentIds.every((value2) => runtime.stageSnapshot.parentIds.includes(value2));
66817
+ if (!sameParents) {
66818
+ runtime.scheduler.tracker.replaceParents(runtime.stageId, actualParentIds);
66819
+ refreshedParentIds = actualParentIds;
66239
66820
  }
66240
66821
  }
66241
- if (refreshedParentIds !== undefined) {
66242
- runtime.scheduler.setStageParentIds(runtime.stageSnapshot, refreshedParentIds);
66822
+ if (trackStageLifecycle) {
66823
+ const now = Date.now();
66824
+ const hasNoExplicitModelConfig = input.options?.model === undefined && input.options?.fallbackModels === undefined;
66825
+ const promptAdapterHandlesInitialPrompt = input.adapters.prompt !== undefined;
66826
+ if (callOptions.eagerSession && !promptAdapterHandlesInitialPrompt && (hasNoExplicitModelConfig || await hasExplicitFastModeCandidate({
66827
+ model: input.options?.model,
66828
+ fallbackModels: input.options?.fallbackModels,
66829
+ models: runtime.opts.models
66830
+ }))) {
66831
+ try {
66832
+ await runtime.innerCtx.__ensureSession();
66833
+ } catch (err) {
66834
+ if (!(err instanceof Error && err.message.includes("prompt adapter not configured")))
66835
+ throw err;
66836
+ }
66837
+ }
66838
+ if (refreshedParentIds !== undefined) {
66839
+ runtime.scheduler.setStageParentIds(runtime.stageSnapshot, refreshedParentIds);
66840
+ }
66841
+ runtime.stageSnapshot.status = "running";
66842
+ runtime.stageSnapshot.startedAt ??= rebasedStageStartedAt(input.options?.durableAccumulatedDurationMs, now);
66843
+ runtime.applyModelFallbackMeta(runtime.innerCtx.__modelFallbackMeta());
66844
+ runtime.activeStore.recordStageStart(runtime.runId, runtime.stageSnapshot);
66845
+ runtime.appendStageStartOnce();
66846
+ const sessionMeta = runtime.innerCtx.__sessionMeta();
66847
+ if (sessionMeta.sessionId !== undefined || sessionMeta.sessionFile !== undefined) {
66848
+ await runtime.captureStageSessionMeta({ awaitDurable: true });
66849
+ }
66850
+ runtime.startStageSessionHeartbeat();
66851
+ } else {
66852
+ runtime.applyModelFallbackMeta(runtime.innerCtx.__modelFallbackMeta());
66243
66853
  }
66244
- runtime.stageSnapshot.status = "running";
66245
- runtime.stageSnapshot.startedAt ??= rebasedStageStartedAt(input.options?.durableAccumulatedDurationMs, now);
66246
- runtime.applyModelFallbackMeta(runtime.innerCtx.__modelFallbackMeta());
66247
- runtime.activeStore.recordStageStart(runtime.runId, runtime.stageSnapshot);
66248
- runtime.appendStageStartOnce();
66249
- } else {
66250
- runtime.applyModelFallbackMeta(runtime.innerCtx.__modelFallbackMeta());
66251
- }
66252
- runtime.mcpScope.apply();
66253
- let applyTerminalStageState;
66254
- try {
66854
+ runtime.mcpScope.apply();
66255
66855
  const abortSession = () => {
66256
66856
  runtime.innerCtx.abort().catch(() => {});
66257
66857
  };
@@ -66263,7 +66863,7 @@ function createTrackedStageCaller(input) {
66263
66863
  try {
66264
66864
  runtime.state.askUserQuestionObservedThisTurn = false;
66265
66865
  runtime.state.chatAnswerObservedThisTurn = false;
66266
- result = await raceAbort(call(), runtime.signal);
66866
+ result = await runtime.raceStageSessionHeartbeat(raceAbort(call(), runtime.signal));
66267
66867
  const initialDrain = await drainResumeContinuations(result);
66268
66868
  result = initialDrain.result;
66269
66869
  let repeatReadinessAfterChatTurn = initialDrain.chatAnswerObserved;
@@ -66287,10 +66887,10 @@ function createTrackedStageCaller(input) {
66287
66887
  runtime.state.chatAnswerObservedThisTurn = false;
66288
66888
  runtime.state.waitingForStageChatTurn = true;
66289
66889
  try {
66290
- await raceAbort(new Promise((resolve12) => {
66890
+ await runtime.raceStageSessionHeartbeat(raceAbort(new Promise((resolve12) => {
66291
66891
  resolveNextTurnEnd = resolve12;
66292
66892
  runtime.state.wakeWaitingForStageChatTurn = resolve12;
66293
- }), runtime.signal);
66893
+ }), runtime.signal));
66294
66894
  } finally {
66295
66895
  runtime.state.wakeWaitingForStageChatTurn = undefined;
66296
66896
  runtime.state.waitingForStageChatTurn = false;
@@ -66314,7 +66914,7 @@ function createTrackedStageCaller(input) {
66314
66914
  runtime.signal.removeEventListener("abort", abortSession);
66315
66915
  }
66316
66916
  await runtime.innerCtx.__closeGeneration();
66317
- runtime.captureStageSessionMeta();
66917
+ await runtime.captureStageSessionMeta({ awaitDurable: true });
66318
66918
  runtime.applyModelFallbackMeta(runtime.innerCtx.__modelFallbackMeta());
66319
66919
  if (trackStageLifecycle && runtime.stageFailFastScope?.failed === true && runtime.stageFailFastScope.activeStages.has(runtime.stageId)) {
66320
66920
  runtime.markSkippedForParallelFailFast();
@@ -66324,6 +66924,7 @@ function createTrackedStageCaller(input) {
66324
66924
  throw runtime.parallelFailFastError();
66325
66925
  if (trackStageLifecycle) {
66326
66926
  const assistantText = runtime.innerCtx.__getLastAssistantText();
66927
+ terminalStateIsSuccess = true;
66327
66928
  applyTerminalStageState = () => {
66328
66929
  runtime.stageSnapshot.status = "completed";
66329
66930
  if (assistantText !== undefined)
@@ -66348,15 +66949,30 @@ function createTrackedStageCaller(input) {
66348
66949
  }
66349
66950
  throw err;
66350
66951
  } finally {
66351
- runtime.mcpScope.clear();
66352
66952
  let finalizationError;
66953
+ let durableCheckpointError;
66353
66954
  try {
66354
- await runtime.innerCtx.__closeGeneration();
66355
- runtime.captureStageSessionMeta();
66955
+ runtime.mcpScope.clear();
66356
66956
  } catch (err) {
66357
66957
  finalizationError = { thrown: true, error: err };
66358
66958
  }
66959
+ try {
66960
+ await runtime.drainStageSessionHeartbeat();
66961
+ } catch (err) {
66962
+ durableCheckpointError = { thrown: true, error: err };
66963
+ }
66964
+ try {
66965
+ await runtime.innerCtx.__closeGeneration();
66966
+ await runtime.captureStageSessionMeta({ awaitDurable: true });
66967
+ } catch (err) {
66968
+ durableCheckpointError ??= { thrown: true, error: err };
66969
+ }
66970
+ finalizationError ??= durableCheckpointError;
66359
66971
  if (trackStageLifecycle) {
66972
+ if (durableCheckpointError !== undefined && terminalStateIsSuccess) {
66973
+ const failure3 = runtime.classifyExecutorFailure(durableCheckpointError.error);
66974
+ applyTerminalStageState = () => applyFailureToStage(runtime.stageSnapshot, failure3);
66975
+ }
66360
66976
  if (!runtime.state.stageFinalized)
66361
66977
  applyTerminalStageState?.();
66362
66978
  try {
@@ -66593,7 +67209,7 @@ function createStageControlHandle(runtime) {
66593
67209
  if (sessionFile === undefined)
66594
67210
  return;
66595
67211
  await runtime.innerCtx.__ensureSessionFromFile(sessionFile);
66596
- runtime.captureStageSessionMeta();
67212
+ await runtime.captureStageSessionMeta({ awaitDurable: true });
66597
67213
  };
66598
67214
  const toolExecutions = new StageToolExecutionBuffer;
66599
67215
  const queuedUserMessages = new StageQueuedUserMessageBuffer;
@@ -66637,7 +67253,7 @@ function createStageControlHandle(runtime) {
66637
67253
  await ensureMessagingSession();
66638
67254
  await runtime.innerCtx.__ensureSession();
66639
67255
  runtime.throwIfStageMutationBlocked();
66640
- runtime.captureStageSessionMeta();
67256
+ await runtime.captureStageSessionMeta({ awaitDurable: true });
66641
67257
  },
66642
67258
  async sendUserMessage(text, options, beforeDelivery) {
66643
67259
  runtime.throwIfStageMutationBlocked();
@@ -67795,6 +68411,28 @@ function terminatingToolCallId(event) {
67795
68411
  }
67796
68412
 
67797
68413
  // dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts
68414
+ function hasMeaningfulUsage(usage) {
68415
+ if (usage === undefined)
68416
+ return false;
68417
+ const values = [usage.input, usage.output, usage.cacheRead, usage.cacheWrite, usage.totalTokens, usage.cost.total];
68418
+ return values.every((value2) => Number.isFinite(value2) && value2 >= 0) && values.some((value2) => value2 > 0);
68419
+ }
68420
+ function usageForAttempt(messages, start, discarded) {
68421
+ const totals = { ...discarded };
68422
+ let meaningful = totals.turns > 0;
68423
+ for (const message of messages.slice(start)) {
68424
+ if (message.role !== "assistant" || !hasMeaningfulUsage(message.usage))
68425
+ continue;
68426
+ totals.input += message.usage.input;
68427
+ totals.output += message.usage.output;
68428
+ totals.cacheRead += message.usage.cacheRead;
68429
+ totals.cacheWrite += message.usage.cacheWrite;
68430
+ totals.cost += message.usage.cost.total;
68431
+ totals.turns += 1;
68432
+ meaningful = true;
68433
+ }
68434
+ return meaningful ? totals : undefined;
68435
+ }
67798
68436
  function isSessionCreationPauseResult(value2) {
67799
68437
  return "kind" in value2 && value2.kind === "paused";
67800
68438
  }
@@ -67857,6 +68495,15 @@ class StageSessionController {
67857
68495
  sessionPromise;
67858
68496
  reattachSessionFile;
67859
68497
  lastPromptStartIndex;
68498
+ attemptUsageStartIndex;
68499
+ discardedAttemptUsage = {
68500
+ input: 0,
68501
+ output: 0,
68502
+ cacheRead: 0,
68503
+ cacheWrite: 0,
68504
+ cost: 0,
68505
+ turns: 0
68506
+ };
67860
68507
  terminatingToolCallIds = new Set;
67861
68508
  latestStructuredOutputToolErrorValue;
67862
68509
  unsubscribeTerminateWatcher;
@@ -68056,6 +68703,7 @@ class StageSessionController {
68056
68703
  this.activeCandidateIndex = index;
68057
68704
  this.selectedModel = candidate.id;
68058
68705
  this.notifyModelFallbackMetaChange();
68706
+ this.beginAttemptUsage(activeSession);
68059
68707
  const { terminalScanStartIndex } = await this.promptWithThrownErrorRetry(activeSession, promptText, sdkOptions);
68060
68708
  const terminalFailure = latestTerminalAssistantFailureSince(activeSession.messages, terminalScanStartIndex);
68061
68709
  if (terminalFailure !== undefined) {
@@ -68194,9 +68842,38 @@ class StageSessionController {
68194
68842
  }
68195
68843
  return;
68196
68844
  }
68845
+ beginAttemptUsage(session) {
68846
+ this.attemptUsageStartIndex = session.messages.length;
68847
+ this.discardedAttemptUsage = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 };
68848
+ }
68849
+ takeAttemptUsage(session) {
68850
+ const start = this.attemptUsageStartIndex;
68851
+ const usage = session === undefined || start === undefined ? undefined : usageForAttempt(session.messages, start, this.discardedAttemptUsage);
68852
+ this.clearAttemptUsage();
68853
+ return usage;
68854
+ }
68855
+ clearAttemptUsage() {
68856
+ this.attemptUsageStartIndex = undefined;
68857
+ this.discardedAttemptUsage = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 };
68858
+ }
68859
+ accrueDiscardedAttemptUsage(message) {
68860
+ if (!hasMeaningfulUsage(message.usage))
68861
+ return;
68862
+ this.discardedAttemptUsage.input += message.usage.input;
68863
+ this.discardedAttemptUsage.output += message.usage.output;
68864
+ this.discardedAttemptUsage.cacheRead += message.usage.cacheRead;
68865
+ this.discardedAttemptUsage.cacheWrite += message.usage.cacheWrite;
68866
+ this.discardedAttemptUsage.cost += message.usage.cost.total;
68867
+ this.discardedAttemptUsage.turns += 1;
68868
+ }
68197
68869
  restoreSessionMessages(session, snapshot, promptText, keepPrompt) {
68198
68870
  const snapshotMessages = new Set(snapshot);
68199
68871
  const admitted = session.messages.filter((message) => !snapshotMessages.has(message));
68872
+ for (const message of admitted) {
68873
+ if (message.role !== "assistant" || message.stopReason !== "error")
68874
+ continue;
68875
+ this.accrueDiscardedAttemptUsage(message);
68876
+ }
68200
68877
  const failedAssistantIndex = admitted.findLastIndex((message) => message.role === "assistant" && message.stopReason === "error");
68201
68878
  const promptUser = admitted.slice(0, failedAssistantIndex < 0 ? admitted.length : failedAssistantIndex).findLast((message) => message.role === "user" && stageUserMessageText(message) === promptText);
68202
68879
  const retainedMessages = admitted.filter((message) => {
@@ -68545,7 +69222,11 @@ class StageSessionController {
68545
69222
  throw new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`);
68546
69223
  throw this.staleCreationReason(startGeneration);
68547
69224
  }
68548
- return attachCreatedStageSession(created, this.disposed, this.opts.stageName, (result) => this.attachSession(result));
69225
+ const session = attachCreatedStageSession(created, this.disposed, this.opts.stageName, (result) => this.attachSession(result));
69226
+ if (session instanceof Promise)
69227
+ return await session;
69228
+ await this.opts.onSessionReady?.();
69229
+ return session;
68549
69230
  }
68550
69231
  attachSession(created) {
68551
69232
  const result = normalizeSessionCreateResult(created);
@@ -68653,11 +69334,17 @@ class StageSessionController {
68653
69334
  const resumedSession = this.session;
68654
69335
  const resumedLabel = this.selectedModel ?? workflowModelId(resumedSession.model) ?? candidates[0].id;
68655
69336
  this.notifyModelFallbackMetaChange();
69337
+ this.beginAttemptUsage(resumedSession);
68656
69338
  try {
68657
69339
  const { terminalScanStartIndex } = await this.promptWithThrownErrorRetry(resumedSession, text, sdkOptions);
68658
69340
  const terminalFailure = latestTerminalAssistantFailureSince(resumedSession.messages, terminalScanStartIndex);
68659
69341
  if (terminalFailure === undefined || this.capturedStructuredOutputForAttempt()) {
68660
- this.modelAttempts.push({ model: resumedLabel, success: true });
69342
+ const usage = this.takeAttemptUsage(resumedSession);
69343
+ this.modelAttempts.push({
69344
+ model: resumedLabel,
69345
+ success: true,
69346
+ ...usage === undefined ? {} : { usage }
69347
+ });
68661
69348
  this.pendingFallbackWarnings.length = 0;
68662
69349
  this.resumeCurrentSession = true;
68663
69350
  return true;
@@ -68665,13 +69352,24 @@ class StageSessionController {
68665
69352
  throw new WorkflowPromptModelFailure(terminalFailure);
68666
69353
  } catch (err) {
68667
69354
  if (this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err)) {
68668
- this.modelAttempts.push({ model: resumedLabel, success: true });
69355
+ const usage2 = this.takeAttemptUsage(resumedSession);
69356
+ this.modelAttempts.push({
69357
+ model: resumedLabel,
69358
+ success: true,
69359
+ ...usage2 === undefined ? {} : { usage: usage2 }
69360
+ });
68669
69361
  this.pendingFallbackWarnings.length = 0;
68670
69362
  this.resumeCurrentSession = true;
68671
69363
  return true;
68672
69364
  }
68673
69365
  const message = errorMessage3(err);
68674
- this.modelAttempts.push({ model: resumedLabel, success: false, error: message });
69366
+ const usage = this.takeAttemptUsage(resumedSession);
69367
+ this.modelAttempts.push({
69368
+ model: resumedLabel,
69369
+ success: false,
69370
+ ...usage === undefined ? {} : { usage },
69371
+ error: message
69372
+ });
68675
69373
  if (this.opts.signal?.aborted || !isRetryableModelFailure(err)) {
68676
69374
  this.modelWarnings.push(...this.pendingFallbackWarnings);
68677
69375
  this.pendingFallbackWarnings.length = 0;
@@ -68697,10 +69395,12 @@ class StageSessionController {
68697
69395
  this.recordSuccessfulAttempt(candidate);
68698
69396
  return "handled";
68699
69397
  }
69398
+ const usage = this.takeAttemptUsage(this.session);
68700
69399
  this.modelAttempts.push({
68701
69400
  model: candidate.id,
68702
69401
  success: false,
68703
69402
  ...modelAttemptReasoning(candidate, this.effectiveStageOptions?.thinkingLevel),
69403
+ ...usage === undefined ? {} : { usage },
68704
69404
  error: message
68705
69405
  });
68706
69406
  if (this.opts.signal?.aborted || !isRetryableModelFailure(err) || index === candidates.length - 1) {
@@ -68718,10 +69418,12 @@ class StageSessionController {
68718
69418
  return this.structuredOutputCapture?.called === true && this.opts.signal?.aborted !== true;
68719
69419
  }
68720
69420
  recordSuccessfulAttempt(candidate) {
69421
+ const usage = this.takeAttemptUsage(this.session);
68721
69422
  this.modelAttempts.push({
68722
69423
  model: candidate.id,
68723
69424
  success: true,
68724
- ...modelAttemptReasoning(candidate, this.effectiveStageOptions?.thinkingLevel)
69425
+ ...modelAttemptReasoning(candidate, this.effectiveStageOptions?.thinkingLevel),
69426
+ ...usage === undefined ? {} : { usage }
68725
69427
  });
68726
69428
  this.pendingFallbackWarnings.length = 0;
68727
69429
  this.resumeCurrentSession = true;
@@ -69158,6 +69860,81 @@ function createStageContext2(opts) {
69158
69860
  }
69159
69861
  };
69160
69862
  }
69863
+ // dist/builtin/workflows/src/runs/foreground/stage-session-heartbeat.ts
69864
+ var STAGE_SESSION_HEARTBEAT_INTERVAL_MS = 30000;
69865
+ function createStageSessionHeartbeat(checkpoint, intervalMs = STAGE_SESSION_HEARTBEAT_INTERVAL_MS) {
69866
+ let active2 = false;
69867
+ let timer;
69868
+ let generation = 0;
69869
+ let nextDeadline = 0;
69870
+ let failure3;
69871
+ let inFlight;
69872
+ let rejectFailure;
69873
+ const failureSignal = new Promise((_resolve, reject) => {
69874
+ rejectFailure = reject;
69875
+ });
69876
+ failureSignal.catch(() => {
69877
+ return;
69878
+ });
69879
+ const stopScheduling = () => {
69880
+ active2 = false;
69881
+ generation += 1;
69882
+ if (timer !== undefined)
69883
+ clearTimeout(timer);
69884
+ timer = undefined;
69885
+ };
69886
+ const fail = (error) => {
69887
+ if (failure3 !== undefined)
69888
+ return;
69889
+ failure3 = error;
69890
+ stopScheduling();
69891
+ rejectFailure(error);
69892
+ };
69893
+ const schedule = (scheduledGeneration) => {
69894
+ if (!active2 || failure3 !== undefined || scheduledGeneration !== generation)
69895
+ return;
69896
+ const delayMs = Math.max(0, nextDeadline - Date.now());
69897
+ timer = setTimeout(() => {
69898
+ timer = undefined;
69899
+ const startedAt = Date.now();
69900
+ do
69901
+ nextDeadline += intervalMs;
69902
+ while (nextDeadline <= startedAt);
69903
+ const running = checkpoint().catch(fail).finally(() => {
69904
+ if (inFlight === running)
69905
+ inFlight = undefined;
69906
+ schedule(scheduledGeneration);
69907
+ });
69908
+ inFlight = running;
69909
+ }, delayMs);
69910
+ timer.unref?.();
69911
+ };
69912
+ const drain = async () => {
69913
+ stopScheduling();
69914
+ await inFlight;
69915
+ if (failure3 !== undefined)
69916
+ throw failure3;
69917
+ };
69918
+ return {
69919
+ start() {
69920
+ if (active2 || failure3 !== undefined)
69921
+ return;
69922
+ active2 = true;
69923
+ generation += 1;
69924
+ nextDeadline = Date.now() + intervalMs;
69925
+ schedule(generation);
69926
+ },
69927
+ stop: stopScheduling,
69928
+ drain,
69929
+ fail,
69930
+ race(work) {
69931
+ if (failure3 !== undefined)
69932
+ return Promise.reject(failure3);
69933
+ return Promise.race([work, failureSignal]);
69934
+ }
69935
+ };
69936
+ }
69937
+
69161
69938
  // dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts
69162
69939
  function createWorkflowStageFactory(input) {
69163
69940
  return (name, options, stageFailFastScope) => {
@@ -69238,6 +70015,15 @@ function createWorkflowStageFactory(input) {
69238
70015
  if (meta2.modelAttempts !== undefined)
69239
70016
  stageSnapshot.modelAttempts = meta2.modelAttempts;
69240
70017
  };
70018
+ let runtime;
70019
+ const stageSessionHeartbeat = createStageSessionHeartbeat(async () => {
70020
+ try {
70021
+ await runtime.captureStageSessionMeta({ awaitDurable: true });
70022
+ } catch (error) {
70023
+ await runtime.innerCtx.abort().catch(() => {});
70024
+ throw error;
70025
+ }
70026
+ });
69241
70027
  const innerCtx = createStageContext2({
69242
70028
  stageId,
69243
70029
  stageName: name,
@@ -69253,6 +70039,12 @@ function createWorkflowStageFactory(input) {
69253
70039
  applyModelFallbackMeta(meta2);
69254
70040
  if (stageSnapshot.status === "running")
69255
70041
  input.activeStore.recordStageStart(input.runId, stageSnapshot);
70042
+ },
70043
+ async onSessionReady() {
70044
+ if (stageSnapshot.status !== "running")
70045
+ return;
70046
+ await runtime.captureStageSessionMeta({ awaitDurable: true });
70047
+ runtime.startStageSessionHeartbeat();
69256
70048
  }
69257
70049
  });
69258
70050
  const state2 = {
@@ -69315,8 +70107,7 @@ function createWorkflowStageFactory(input) {
69315
70107
  stageUiBroker.clearStagePrompt(input.runId, stageId);
69316
70108
  await innerCtx.__dispose();
69317
70109
  };
69318
- let runtime;
69319
- const captureStageSessionMeta = (checkpointOptions) => {
70110
+ const captureStageSessionMeta = async (checkpointOptions) => {
69320
70111
  const meta2 = innerCtx.__sessionMeta();
69321
70112
  if (meta2.sessionId !== undefined)
69322
70113
  stageSnapshot.sessionId = meta2.sessionId;
@@ -69325,15 +70116,17 @@ function createWorkflowStageFactory(input) {
69325
70116
  if (meta2.sessionId !== undefined || meta2.sessionFile !== undefined)
69326
70117
  input.activeStore.recordStageSession(input.runId, stageId, meta2);
69327
70118
  const pending = input.opts.onStageSession?.(input.runId, stageSnapshot, checkpointOptions);
69328
- if (checkpointOptions?.forceDurable === true)
69329
- return pending;
70119
+ if (checkpointOptions?.forceDurable === true || checkpointOptions?.awaitDurable === true) {
70120
+ await pending;
70121
+ return;
70122
+ }
69330
70123
  Promise.resolve(pending).catch(() => {});
69331
- return;
69332
70124
  };
69333
70125
  const releaseLiveHandle = async () => {
69334
70126
  if (state2.liveHandleReleased)
69335
70127
  return;
69336
70128
  state2.liveHandleReleased = true;
70129
+ stageSessionHeartbeat.stop();
69337
70130
  runtime.dropStageControlHandle();
69338
70131
  runtime.unregisterStageHandle();
69339
70132
  await disposeInnerContext();
@@ -69366,6 +70159,7 @@ function createWorkflowStageFactory(input) {
69366
70159
  });
69367
70160
  };
69368
70161
  const finalizeStageSnapshot = async () => {
70162
+ stageSessionHeartbeat.stop();
69369
70163
  if (state2.stageFinalized)
69370
70164
  return false;
69371
70165
  if (stageSnapshot.endedAt !== undefined && isTerminalStage(stageSnapshot)) {
@@ -69438,6 +70232,9 @@ function createWorkflowStageFactory(input) {
69438
70232
  dropStageControlHandle: () => {},
69439
70233
  unregisterWorkflowExitCleanup: () => {},
69440
70234
  captureStageSessionMeta,
70235
+ startStageSessionHeartbeat: stageSessionHeartbeat.start,
70236
+ drainStageSessionHeartbeat: stageSessionHeartbeat.drain,
70237
+ raceStageSessionHeartbeat: stageSessionHeartbeat.race,
69441
70238
  applyModelFallbackMeta,
69442
70239
  appendStageStartOnce,
69443
70240
  finalizeStageSnapshot,
@@ -69590,9 +70387,22 @@ class EngineRuntime {
69590
70387
  apply: () => {
69591
70388
  if (!this.childRunOptions.mcp || !hasScope)
69592
70389
  return;
69593
- if (depth === 0)
70390
+ if (depth > 0) {
70391
+ depth += 1;
70392
+ return;
70393
+ }
70394
+ depth = 1;
70395
+ try {
69594
70396
  this.childRunOptions.mcp.setScope(stageId, allow, deny);
69595
- depth += 1;
70397
+ } catch (error) {
70398
+ depth = 0;
70399
+ try {
70400
+ this.childRunOptions.mcp.clearScope(stageId);
70401
+ } catch (cleanupError) {
70402
+ throw new AggregateError([error, cleanupError], "MCP scope setup failed and compensating cleanup failed");
70403
+ }
70404
+ throw error;
70405
+ }
69596
70406
  },
69597
70407
  clear: () => {
69598
70408
  if (!this.childRunOptions.mcp || !hasScope)
@@ -70935,6 +71745,72 @@ function disposeCompletedChatHandle(handle) {
70935
71745
  });
70936
71746
  }
70937
71747
 
71748
+ // dist/builtin/workflows/src/durable/targeted-inspection.ts
71749
+ async function inspectTargetedDurableWorkflow(backend, workflowId, now = Date.now()) {
71750
+ const hydrated = backend.hydrateWorkflowForInspection ? await backend.hydrateWorkflowForInspection(workflowId) : await hydrateWithoutClassification(backend, workflowId);
71751
+ if (hydrated.kind !== "current")
71752
+ return hydrationFailure(workflowId, hydrated.kind);
71753
+ const handle = hydrated.handle;
71754
+ if (handle.rootWorkflowId !== undefined && handle.rootWorkflowId !== handle.workflowId) {
71755
+ return malformed(workflowId, "the requested id belongs to a nested workflow rather than a durable root");
71756
+ }
71757
+ const reconstructed = durableWorkflowRunSnapshots(backend, handle);
71758
+ if (reconstructed.length === 0)
71759
+ return malformed(workflowId, "durable checkpoint topology is malformed or incomplete");
71760
+ const runs = structuredClone(reconstructed);
71761
+ const inspectionStore = createStore();
71762
+ for (const run2 of runs)
71763
+ inspectionStore.recordRunStart(structuredClone(run2));
71764
+ const inspected = inspectRun(workflowId, { store: inspectionStore });
71765
+ if (!inspected.ok)
71766
+ return malformed(workflowId, "the durable checkpoint graph has no reciprocal root");
71767
+ const foreignLive = isForeignLiveWorkflow(handle, getAtomicExecutorId(), now);
71768
+ const live = isLiveRunningWorkflow(handle, now);
71769
+ const crashed = handle.status === "running" && !live;
71770
+ const resumeGuidance = crashed ? inspected.detail.resumable === true ? `This workflow appears to have crashed and is resumable. Resume it explicitly with /workflow resume ${workflowId}.` : "This workflow appears to have crashed, but its retained state is not resumable." : foreignLive ? "This workflow is actively running in another Atomic session. Inspect it here, but control it from its owner session." : live ? "This workflow still has a fresh durable heartbeat. Inspect it here without starting another executor." : terminalGuidance(handle.status, workflowId, inspected.detail.resumable === true);
71771
+ return {
71772
+ kind: "found",
71773
+ runs,
71774
+ store: inspectionStore,
71775
+ detail: {
71776
+ ...inspected.detail,
71777
+ ...crashed ? { status: "crashed" } : {},
71778
+ ...live ? { resumable: false } : {},
71779
+ ...foreignLive ? { ownerActiveElsewhere: true } : {},
71780
+ resumeGuidance
71781
+ }
71782
+ };
71783
+ }
71784
+ function terminalGuidance(status, workflowId, resumable) {
71785
+ if (resumable)
71786
+ return `This retained workflow is ${status} and resumable. Resume it explicitly with /workflow resume ${workflowId}.`;
71787
+ return `This retained workflow is ${status} and available for read-only inspection.`;
71788
+ }
71789
+ async function hydrateWithoutClassification(backend, workflowId) {
71790
+ await backend.hydrateWorkflow(workflowId);
71791
+ const handle = backend.getLoadableWorkflow(workflowId);
71792
+ return handle === undefined ? { kind: "absent" } : { kind: "current", handle };
71793
+ }
71794
+ function hydrationFailure(workflowId, kind) {
71795
+ switch (kind) {
71796
+ case "absent":
71797
+ return {
71798
+ kind,
71799
+ message: `Run not found: ${workflowId} (not present in the current session or durable store).`
71800
+ };
71801
+ case "deleted":
71802
+ return { kind, message: `Durable workflow was deleted: ${workflowId}` };
71803
+ case "malformed":
71804
+ return malformed(workflowId, "current DBOS metadata or checkpoints are malformed");
71805
+ }
71806
+ }
71807
+ function malformed(workflowId, reason) {
71808
+ return {
71809
+ kind: "malformed",
71810
+ message: `Durable workflow ${workflowId} cannot be inspected safely: ${reason}.`
71811
+ };
71812
+ }
71813
+
70938
71814
  // dist/builtin/workflows/src/extension/runtime-durable-resume.ts
70939
71815
  function createDurableResumeRuntime(deps) {
70940
71816
  const hydrateStoredWorkflowCandidates = async (backend, target) => {
@@ -70944,6 +71820,10 @@ function createDurableResumeRuntime(deps) {
70944
71820
  };
70945
71821
  let preparedCatalog = [];
70946
71822
  return {
71823
+ async inspectDurableWorkflow(workflowId) {
71824
+ await deps.ensureReady();
71825
+ return await inspectTargetedDurableWorkflow(getDurableBackend(), workflowId);
71826
+ },
70947
71827
  async resumeDurableWorkflow(workflowId, options) {
70948
71828
  await deps.ensureReady();
70949
71829
  const backend = getDurableBackend();
@@ -71387,6 +72267,7 @@ function workflowModelCatalogFromContext(ctx) {
71387
72267
  }
71388
72268
 
71389
72269
  // dist/builtin/workflows/src/extension/mcp.ts
72270
+ import { isStaleExtensionContextError as isStaleExtensionContextError5 } from "@bastani/atomic";
71390
72271
  function setMcpScope(pi, opts) {
71391
72272
  if (!pi.events)
71392
72273
  return;
@@ -71395,7 +72276,12 @@ function setMcpScope(pi, opts) {
71395
72276
  allow: opts.allow ?? null,
71396
72277
  deny: opts.deny ?? null
71397
72278
  };
71398
- pi.events.emit("mcp.scope.set", payload);
72279
+ try {
72280
+ pi.events.emit("mcp.scope.set", payload);
72281
+ } catch (error) {
72282
+ if (!isStaleExtensionContextError5(error))
72283
+ throw error;
72284
+ }
71399
72285
  }
71400
72286
  function clearMcpScope(pi, stageId) {
71401
72287
  if (!pi.events)
@@ -71405,7 +72291,12 @@ function clearMcpScope(pi, stageId) {
71405
72291
  allow: null,
71406
72292
  deny: null
71407
72293
  };
71408
- pi.events.emit("mcp.scope.set", payload);
72294
+ try {
72295
+ pi.events.emit("mcp.scope.set", payload);
72296
+ } catch (error) {
72297
+ if (!isStaleExtensionContextError5(error))
72298
+ throw error;
72299
+ }
71409
72300
  }
71410
72301
 
71411
72302
  // dist/builtin/workflows/src/extension/workflow-ports.ts
@@ -71433,14 +72324,18 @@ function makeMcpPort(pi) {
71433
72324
  };
71434
72325
  return {
71435
72326
  setScope(stageId, allow, deny) {
71436
- setMcpScope(piForMcp, {
71437
- stageId,
71438
- allow: allow ?? undefined,
71439
- deny: deny ?? undefined
71440
- });
72327
+ try {
72328
+ setMcpScope(piForMcp, {
72329
+ stageId,
72330
+ allow: allow ?? undefined,
72331
+ deny: deny ?? undefined
72332
+ });
72333
+ } catch {}
71441
72334
  },
71442
72335
  clearScope(stageId) {
71443
- clearMcpScope(piForMcp, stageId);
72336
+ try {
72337
+ clearMcpScope(piForMcp, stageId);
72338
+ } catch {}
71444
72339
  }
71445
72340
  };
71446
72341
  }
@@ -71603,6 +72498,9 @@ function createWorkflowExtensionRuntimeState(pi, adapters, resolveCwd = () => pi
71603
72498
  resumeDurableWorkflow(workflowId, options) {
71604
72499
  return runtimeRef.current.resumeDurableWorkflow(workflowId, options);
71605
72500
  },
72501
+ inspectDurableWorkflow(workflowId) {
72502
+ return runtimeRef.current.inspectDurableWorkflow(workflowId);
72503
+ },
71606
72504
  listDurableResumable() {
71607
72505
  return runtimeRef.current.listDurableResumable();
71608
72506
  },
@@ -71919,11 +72817,16 @@ function renderRunSummary(payload) {
71919
72817
  return `${icon} workflow [${payload.runId}] ${payload.status}`;
71920
72818
  }
71921
72819
 
72820
+ // dist/builtin/workflows/src/extension/wiring.ts
72821
+ import {
72822
+ isStaleExtensionContextError as isStaleExtensionContextError6
72823
+ } from "@bastani/atomic";
72824
+
71922
72825
  // dist/builtin/workflows/src/extension/atomic-stage-session.ts
71923
72826
  import { basename as basename5 } from "node:path";
71924
72827
  var WORKFLOW_STAGE_SUBAGENT_POLICY = {
71925
72828
  managementActions: "full",
71926
- fanoutAuthorized: false,
72829
+ fanoutAuthorized: true,
71927
72830
  inheritProjectContext: true,
71928
72831
  inheritSkills: true
71929
72832
  };
@@ -72130,11 +73033,26 @@ function emitLateIntercomRoute(pi, meta2, messages, options, batch) {
72130
73033
  workflowStageId: meta2.stageId,
72131
73034
  workflowStageName: meta2.stageName
72132
73035
  };
72133
- pi.events.emit(LATE_STAGE_MESSAGE_EVENT2, event);
73036
+ try {
73037
+ pi.events.emit(LATE_STAGE_MESSAGE_EVENT2, event);
73038
+ } catch (error) {
73039
+ if (!isStaleExtensionContextError6(error))
73040
+ throw error;
73041
+ return Promise.reject(error);
73042
+ }
72134
73043
  if (!event.handled)
72135
73044
  return;
72136
73045
  return event.completion ?? Promise.resolve();
72137
73046
  }
73047
+ function routeThroughStaleContextGuard(route) {
73048
+ try {
73049
+ return route();
73050
+ } catch (error) {
73051
+ if (!isStaleExtensionContextError6(error))
73052
+ throw error;
73053
+ return Promise.reject(error);
73054
+ }
73055
+ }
72138
73056
  function makeWorkflowStageOrchestrationContext(meta2, pi) {
72139
73057
  const intercomGroup = stageHasIntercomAccess(meta2.stageOptions) ? resolveStageGroup(meta2.stageOptions, meta2.workflowIntercomGroup) : undefined;
72140
73058
  return {
@@ -72149,16 +73067,18 @@ function makeWorkflowStageOrchestrationContext(meta2, pi) {
72149
73067
  const intercomRoute = emitLateIntercomRoute(pi, meta2, [message], options, false);
72150
73068
  if (intercomRoute)
72151
73069
  return intercomRoute;
72152
- if (!pi.sendMessage)
73070
+ const sendMessage = pi.sendMessage;
73071
+ if (!sendMessage)
72153
73072
  throw new Error("atomic-workflows: main-chat late-message route is unavailable");
72154
- return pi.sendMessage(message, options);
73073
+ return routeThroughStaleContextGuard(() => sendMessage(message, options));
72155
73074
  },
72156
73075
  routeMessages(messages, options) {
72157
73076
  const intercomRoute = emitLateIntercomRoute(pi, meta2, messages, options, true);
72158
73077
  if (intercomRoute)
72159
73078
  return intercomRoute;
72160
- if (pi.sendMessages)
72161
- return pi.sendMessages(messages, options);
73079
+ const sendMessages = pi.sendMessages;
73080
+ if (sendMessages)
73081
+ return routeThroughStaleContextGuard(() => sendMessages(messages, options));
72162
73082
  const sendMessage = pi.sendMessage;
72163
73083
  if (!sendMessage)
72164
73084
  throw new Error("atomic-workflows: main-chat late-message route is unavailable");
@@ -72489,12 +73409,14 @@ function openInputsPicker(ui, opts) {
72489
73409
  }),
72490
73410
  handleInput: (data) => {
72491
73411
  const kb = keys;
73412
+ const consumed = isInputsPickerKey(data, state2, fields, kb);
72492
73413
  const action = handleInputsPickerInput(data, state2, fields, kb);
72493
73414
  if (action.kind === "noop") {
72494
73415
  tui.requestRender?.();
72495
- return;
73416
+ return consumed;
72496
73417
  }
72497
73418
  finish(action);
73419
+ return true;
72498
73420
  },
72499
73421
  invalidate: () => tui.requestRender?.(),
72500
73422
  dispose: () => {
@@ -72733,6 +73655,15 @@ function renderSessionPicker(opts) {
72733
73655
  lines.push(renderHintsRow(width, theme, state2));
72734
73656
  return lines;
72735
73657
  }
73658
+ function isSessionPickerKey(data, state2, rows) {
73659
+ if (state2.filterFocused) {
73660
+ return matchesKey(data, Key.escape) || data === DOUBLE_ESCAPE_SEQUENCE || matchesKey(data, Key.enter) || matchesKey(data, Key.backspace) || data.length === 1 && data >= " " && data <= "~";
73661
+ }
73662
+ if (matchesKey(data, "/") || matchesKey(data, Key.escape) || matchesKey(data, "q") || matchesKey(data, Key.shift("q")) || matchesKey(data, "a") || matchesKey(data, Key.shift("a")) || matchesKey(data, Key.down) || matchesKey(data, "j") || matchesKey(data, Key.up) || matchesKey(data, "k")) {
73663
+ return true;
73664
+ }
73665
+ return matchesKey(data, Key.enter) && rows[state2.selectedIndex] !== undefined;
73666
+ }
72736
73667
  function handleSessionPickerInput(data, state2, rows) {
72737
73668
  if (state2.filterFocused) {
72738
73669
  if (matchesKey(data, Key.escape) || data === DOUBLE_ESCAPE_SEQUENCE) {
@@ -73115,10 +74046,11 @@ function openSessionPicker(ui, store2, theme, intent = "connect") {
73115
74046
  },
73116
74047
  handleInput: (data) => {
73117
74048
  const rows = selectRows();
74049
+ const consumed = isSessionPickerKey(data, state2, rows);
73118
74050
  const action = handleSessionPickerInput(data, state2, rows);
73119
74051
  if (action.kind === "noop") {
73120
74052
  tui.requestRender?.();
73121
- return;
74053
+ return consumed;
73122
74054
  }
73123
74055
  if (action.kind === "close")
73124
74056
  finish({ kind: "close" });
@@ -73126,6 +74058,7 @@ function openSessionPicker(ui, store2, theme, intent = "connect") {
73126
74058
  finish(toResult(action));
73127
74059
  else
73128
74060
  finish(toResult(action));
74061
+ return true;
73129
74062
  },
73130
74063
  invalidate: () => tui.requestRender?.(),
73131
74064
  dispose: () => {
@@ -73237,6 +74170,7 @@ function toPickerRow(session) {
73237
74170
  modifiedAt: session.modified.getTime(),
73238
74171
  messageCount: session.messageCount,
73239
74172
  firstMessage: session.firstMessage,
74173
+ ...session.summary !== undefined ? { summary: session.summary } : {},
73240
74174
  allMessagesText: session.allMessagesText,
73241
74175
  ...session.name !== undefined ? { name: session.name } : {},
73242
74176
  ...session.messageColor !== undefined ? { messageColor: session.messageColor } : {}
@@ -73811,7 +74745,11 @@ Picker requires an interactive UI surface. Pass a runId: /workflow attach <id> [
73811
74745
  }
73812
74746
  const run3 = store.runs().find((r) => r.id === resolved.runId);
73813
74747
  const isPaused3 = run3 !== undefined && workflowHasPausedState(store, resolved.runId);
74748
+ const isDurableAuthorExit2 = run3?.exited === true && run3.status === "failed" && run3.resumable === true;
73814
74749
  const isResumableContinuation2 = run3 !== undefined && !isPaused3 && run3.exitReason !== "quit" && isWorkflowRunResumable(workflowRunResumeCandidate(run3));
74750
+ if (isDurableAuthorExit2) {
74751
+ return await handleDurableResume(resolved.runId, ctx, reporter, deps);
74752
+ }
73815
74753
  if (isResumableContinuation2) {
73816
74754
  await ensureWorkflowResourcesVisible();
73817
74755
  const continuation = await deps.runtimeForContext(ctx).resumeFailedRun(resolved.runId, undefined, { policy, actor: "user" });
@@ -73945,12 +74883,16 @@ Picker requires an interactive UI surface. Pass a runId: /workflow attach <id> [
73945
74883
  const hadPausedRunState = run2?.status === "paused";
73946
74884
  const hadPausedStageState = run2 !== undefined && workflowHasPausedStages(store, stageRunId);
73947
74885
  const isPaused2 = run2 !== undefined && workflowHasPausedState(store, stageRunId);
74886
+ const isDurableAuthorExit = run2?.exited === true && run2.status === "failed" && run2.resumable === true;
73948
74887
  const isResumableContinuation = run2 !== undefined && !isPaused2 && run2.exitReason !== "quit" && isWorkflowRunResumable(workflowRunResumeCandidate(run2));
73949
74888
  const isActivelyRunning = run2 !== undefined && run2.endedAt === undefined && run2.status === "running" && !isPaused2 && run2.exitReason !== "quit";
73950
74889
  if (isActivelyRunning && !isResumableContinuation && action === "resume" && !hasPendingDurableResumeTransition(stageRunId)) {
73951
74890
  fail(`Workflow ${stageRunId} is already running in this session. Attach with \`/workflow connect ${stageRunId}\` instead of resuming.`);
73952
74891
  return true;
73953
74892
  }
74893
+ if (isDurableAuthorExit) {
74894
+ return await handleDurableResume(stageRunId, ctx, reporter, deps);
74895
+ }
73954
74896
  if (isResumableContinuation) {
73955
74897
  await ensureWorkflowResourcesVisible();
73956
74898
  const continuation = await deps.runtimeForContext(ctx).resumeFailedRun(stageRunId, stageId, { policy, actor: "user" });
@@ -74078,8 +75020,13 @@ Available: ${formatAvailableWorkflowNames(deps.runtimeProxy.registry.names())}`)
74078
75020
  const resolved = resolveRunId(target);
74079
75021
  if (resolved.kind === "malformed")
74080
75022
  return fail(resolved.message);
74081
- if (resolved.kind === "not_found")
74082
- return fail(`Run not found: ${target}`);
75023
+ if (resolved.kind === "not_found") {
75024
+ const durable = await deps.runtimeForContext(ctx).inspectDurableWorkflow(target);
75025
+ if (durable.kind !== "found")
75026
+ return fail(durable.message);
75027
+ emitChatSurface(pi, { kind: "detail", detail: durable.detail });
75028
+ return;
75029
+ }
74083
75030
  const inspected = inspectRun(resolved.runId);
74084
75031
  if (!inspected.ok)
74085
75032
  return fail(`Run not found: ${target}`);
@@ -74942,7 +75889,10 @@ async function workflowResumeAction(args, deps) {
74942
75889
  const hadPausedRunState = run2?.status === "paused";
74943
75890
  const hadPausedStageState = run2 !== undefined && workflowHasPausedStages(store, stageRunId);
74944
75891
  const isPaused2 = run2 !== undefined && workflowHasPausedState(store, stageRunId);
75892
+ const isDurableAuthorExit = run2?.exited === true && run2.status === "failed" && run2.resumable === true;
74945
75893
  const isResumableContinuation = run2 !== undefined && !isPaused2 && run2.exitReason !== "quit" && isWorkflowRunResumable(workflowRunResumeCandidate(run2));
75894
+ if (isDurableAuthorExit)
75895
+ return resumeDurableShadow(stageRunId, deps);
74946
75896
  if (isResumableContinuation) {
74947
75897
  try {
74948
75898
  await deps.ensureWorkflowResourcesLoaded();
@@ -75150,8 +76100,9 @@ function snapshotTranscriptEntryCount(snapshot) {
75150
76100
  }
75151
76101
 
75152
76102
  // dist/builtin/workflows/src/extension/workflow-tool-inspection.ts
75153
- function workflowStagesResult(args) {
75154
- const target = resolveToolRunTarget(args, "No active run to inspect.");
76103
+ function workflowStagesResult(args, source) {
76104
+ const activeStore = source?.store ?? store;
76105
+ const target = resolveToolRunTarget(args, "No active run to inspect.", activeStore);
75155
76106
  const filter = args.statusFilter ?? "all";
75156
76107
  if (target.kind === "all") {
75157
76108
  return {
@@ -75171,19 +76122,20 @@ function workflowStagesResult(args) {
75171
76122
  error: target.message
75172
76123
  };
75173
76124
  }
75174
- const run2 = store.runs().find((r) => r.id === target.runId);
75175
- const stages = (run2?.stages ?? []).filter((stage) => filter === "all" || stage.status === filter).map(summarizeStage);
76125
+ const stageSnapshots = source?.store === undefined ? activeStore.runs().find((run2) => run2.id === target.runId)?.stages ?? [] : expandWorkflowGraph(readGraphStoreSnapshot(activeStore), target.runId).stages;
76126
+ const stages = stageSnapshots.filter((stage) => filter === "all" || stage.status === filter).map(summarizeStage);
75176
76127
  return { action: "stages", runId: target.runId, filter, stages };
75177
76128
  }
75178
- function workflowStageResult(args) {
75179
- const target = resolveToolRunTarget(args, "No active run to inspect.");
76129
+ function workflowStageResult(args, source) {
76130
+ const activeStore = source?.store ?? store;
76131
+ const target = resolveToolRunTarget(args, "No active run to inspect.", activeStore);
75180
76132
  if (target.kind === "all") {
75181
76133
  return { action: "stage", runId: "--all", error: "Stage inspection requires a single run." };
75182
76134
  }
75183
76135
  if (target.kind === "malformed" || target.kind === "not_found") {
75184
76136
  return { action: "stage", runId: target.target, error: target.message };
75185
76137
  }
75186
- const stage = resolveToolStageTarget(target.runId, args.stageId);
76138
+ const stage = resolveToolStageTarget(target.runId, args.stageId, activeStore);
75187
76139
  if (!stage.ok || stage.stageId === undefined) {
75188
76140
  return {
75189
76141
  action: "stage",
@@ -75192,7 +76144,7 @@ function workflowStageResult(args) {
75192
76144
  };
75193
76145
  }
75194
76146
  const stageRunId = stage.runId ?? target.runId;
75195
- const run2 = store.runs().find((r) => r.id === stageRunId);
76147
+ const run2 = activeStore.runs().find((r) => r.id === stageRunId);
75196
76148
  const snapshot = run2?.stages.find((s) => s.id === stage.stageId);
75197
76149
  return snapshot ? { action: "stage", runId: stageRunId, stage: cloneStage(snapshot) } : {
75198
76150
  action: "stage",
@@ -75200,8 +76152,9 @@ function workflowStageResult(args) {
75200
76152
  error: `Stage not found in run ${stageRunId}: ${stage.stageId}`
75201
76153
  };
75202
76154
  }
75203
- function workflowTranscriptResult(args) {
75204
- const target = resolveToolRunTarget(args, "No active run to inspect.");
76155
+ function workflowTranscriptResult(args, source) {
76156
+ const activeStore = source?.store ?? store;
76157
+ const target = resolveToolRunTarget(args, "No active run to inspect.", activeStore);
75205
76158
  if (target.kind === "all") {
75206
76159
  return {
75207
76160
  action: "transcript",
@@ -75222,7 +76175,7 @@ function workflowTranscriptResult(args) {
75222
76175
  truncated: false
75223
76176
  };
75224
76177
  }
75225
- const stage = resolveToolStageTarget(target.runId, args.stageId);
76178
+ const stage = resolveToolStageTarget(target.runId, args.stageId, activeStore);
75226
76179
  if (!stage.ok || stage.stageId === undefined) {
75227
76180
  return {
75228
76181
  action: "transcript",
@@ -75234,9 +76187,9 @@ function workflowTranscriptResult(args) {
75234
76187
  };
75235
76188
  }
75236
76189
  const stageRunId = stage.runId ?? target.runId;
75237
- const run2 = store.runs().find((r) => r.id === stageRunId);
76190
+ const run2 = activeStore.runs().find((r) => r.id === stageRunId);
75238
76191
  const snapshot = run2?.stages.find((s) => s.id === stage.stageId);
75239
- const liveHandle2 = stageControlRegistry.get(stageRunId, stage.stageId);
76192
+ const liveHandle2 = source?.allowLiveHandles === false ? undefined : stageControlRegistry.get(stageRunId, stage.stageId);
75240
76193
  if (liveHandle2 !== undefined) {
75241
76194
  const sessionFile = liveHandle2.sessionFile ?? snapshot?.sessionFile;
75242
76195
  const sessionId = liveHandle2.sessionId ?? snapshot?.sessionId;
@@ -75296,6 +76249,41 @@ function brokerAnswerFromArgs(args) {
75296
76249
  const text = textPayloadFromArgs(args);
75297
76250
  return text !== undefined ? { text } : {};
75298
76251
  }
76252
+ function answersPendingPrompt(delivery, promptId) {
76253
+ return delivery === "answer" || delivery === "auto" || promptId !== undefined;
76254
+ }
76255
+ function answerablePromptIds(stage) {
76256
+ const target = stage.workflowGraphTarget;
76257
+ const ids = [];
76258
+ const brokered = stageUiBroker.peekStagePrompt(target.runId, target.stageId);
76259
+ if (brokered !== undefined)
76260
+ ids.push(brokered.id);
76261
+ if (stage.pendingPrompt !== undefined)
76262
+ ids.push(stage.pendingPrompt.id);
76263
+ if (stage.status === "awaiting_input" && stage.promptFootprint?.kind === "custom") {
76264
+ ids.push(stage.promptFootprint.id);
76265
+ }
76266
+ return ids;
76267
+ }
76268
+ function inferPromptStageTarget(runId, delivery, promptId) {
76269
+ if (!answersPendingPrompt(delivery, promptId))
76270
+ return { ok: true, runId };
76271
+ const pending = expandWorkflowGraph(readGraphStoreSnapshot(store), runId).stages.filter((stage) => {
76272
+ const ids = answerablePromptIds(stage);
76273
+ return promptId === undefined ? ids.length > 0 : ids.includes(promptId);
76274
+ });
76275
+ const only = pending[0];
76276
+ if (pending.length === 1 && only !== undefined) {
76277
+ return { ok: true, runId: only.workflowGraphTarget.runId, stageId: only.workflowGraphTarget.stageId };
76278
+ }
76279
+ if (pending.length === 0) {
76280
+ return promptId === undefined ? { ok: true, runId } : { ok: false, message: `No pending prompt ${promptId} in run ${runId}.` };
76281
+ }
76282
+ return {
76283
+ ok: false,
76284
+ message: `${pending.length} prompts pending; pass stageId: ${pending.map(expandedStageLabel).join(", ")}`
76285
+ };
76286
+ }
75299
76287
  function workflowSendResult(runId, stageId, delivery, status, message) {
75300
76288
  return { action: "send", runId, stageId, delivery, status, message };
75301
76289
  }
@@ -75356,7 +76344,8 @@ async function workflowSendAction(args, deps = {}) {
75356
76344
  if (rootRun !== undefined && isTerminalRunStatus(rootRun.status)) {
75357
76345
  return terminalWorkflowSendResult(rootRun.id, args.stageId?.trim() ?? "", rootRun.status);
75358
76346
  }
75359
- const stage = resolveToolStageTarget(target.runId, args.stageId);
76347
+ const requested = resolveToolStageTarget(target.runId, args.stageId);
76348
+ const stage = requested.ok && requested.stageId === undefined ? inferPromptStageTarget(target.runId, requestedDelivery, args.promptId) : requested;
75360
76349
  if (!stage.ok || stage.stageId === undefined) {
75361
76350
  return workflowSendResult(target.runId, "", requestedDelivery, "noop", stage.ok ? "Stage id or name is required." : stage.message);
75362
76351
  }
@@ -75497,6 +76486,32 @@ async function workflowSendAction(args, deps = {}) {
75497
76486
  }
75498
76487
 
75499
76488
  // dist/builtin/workflows/src/extension/workflow-tool.ts
76489
+ async function resolveDurableInspectionSource(args, runtime) {
76490
+ const target = args.runId?.trim();
76491
+ if (args.all === true || target === undefined || target.length === 0 || target === "--all")
76492
+ return { kind: "local" };
76493
+ const local = resolveRunId(target);
76494
+ if (local.kind !== "not_found")
76495
+ return { kind: "local" };
76496
+ const durable = await runtime.inspectDurableWorkflow(target);
76497
+ if (durable.kind !== "found")
76498
+ return { kind: "error", message: durable.message };
76499
+ return { kind: "durable", source: { store: durable.store, allowLiveHandles: false } };
76500
+ }
76501
+ function durableInspectionError(action, runId, message) {
76502
+ if (action === "stages")
76503
+ return { action, runId, filter: "all", stages: [], error: message };
76504
+ if (action === "stage")
76505
+ return { action, runId, error: message };
76506
+ return {
76507
+ action,
76508
+ runId,
76509
+ stageId: "",
76510
+ source: "error",
76511
+ entries: [{ role: "notice", text: message }],
76512
+ truncated: false
76513
+ };
76514
+ }
75500
76515
  function makeExecuteWorkflowTool(runtime, reloadWorkflowResources, ensureWorkflowResourcesLoaded = () => {}, sendDeps = {}) {
75501
76516
  return async function executeWorkflowTool(args, ctx) {
75502
76517
  const action = args.action ?? "run";
@@ -75552,7 +76567,8 @@ function makeExecuteWorkflowTool(runtime, reloadWorkflowResources, ensureWorkflo
75552
76567
  return { action: "statusDetail", runId: target, error: resolved.message };
75553
76568
  }
75554
76569
  if (resolved.kind === "not_found") {
75555
- return { action: "statusDetail", runId: target, error: `run not found: ${target}` };
76570
+ const durable = await getRuntime().inspectDurableWorkflow(target);
76571
+ return durable.kind === "found" ? { action: "statusDetail", runId: target, detail: durable.detail } : { action: "statusDetail", runId: target, error: durable.message };
75556
76572
  }
75557
76573
  const result2 = inspectRun(resolved.runId);
75558
76574
  return result2.ok ? { action: "statusDetail", runId: result2.runId, detail: result2.detail } : { action: "statusDetail", runId: target, error: `run not found: ${target}` };
@@ -75568,11 +76584,18 @@ function makeExecuteWorkflowTool(runtime, reloadWorkflowResources, ensureWorkflo
75568
76584
  return result;
75569
76585
  }
75570
76586
  case "stages":
75571
- return workflowStagesResult(args);
75572
76587
  case "stage":
75573
- return workflowStageResult(args);
75574
- case "transcript":
75575
- return workflowTranscriptResult(args);
76588
+ case "transcript": {
76589
+ const resolved = await resolveDurableInspectionSource(args, getRuntime());
76590
+ if (resolved.kind === "error")
76591
+ return durableInspectionError(action, args.runId ?? "", resolved.message);
76592
+ const source = resolved.kind === "durable" ? resolved.source : undefined;
76593
+ if (action === "stages")
76594
+ return workflowStagesResult(args, source);
76595
+ if (action === "stage")
76596
+ return workflowStageResult(args, source);
76597
+ return workflowTranscriptResult(args, source);
76598
+ }
75576
76599
  case "send":
75577
76600
  return workflowSendAction(args, sendDeps);
75578
76601
  case "pause":
@@ -75789,7 +76812,7 @@ function renderResult(result, opts) {
75789
76812
  const guidance = r.details.message === undefined ? "" : ` — ${r.details.message}`;
75790
76813
  return renderNotice("WORKFLOW RUN", `${r.runId}${label2}: ${r.details.mode} ${r.details.status}${guidance}`, opts, themed);
75791
76814
  }
75792
- if (r.status === "completed" || r.status === "skipped" || r.status === "cancelled" || r.status === "blocked" || r.status === "killed") {
76815
+ if (r.status === "completed" || r.status === "failed" || r.status === "skipped" || r.status === "cancelled" || r.status === "blocked" || r.status === "killed") {
75793
76816
  const label2 = r.name ? ` (${r.name})` : "";
75794
76817
  return renderNotice("WORKFLOW RUN", `${r.runId}${label2}: ${r.status}`, opts, themed);
75795
76818
  }
@@ -75876,7 +76899,7 @@ var DEFAULT_PROMPT_GUIDANCE = [
75876
76899
  - Workflow fit check: prefer a workflow for implementation, build, debug/diagnosis, bug-fix, migration, new-feature, scoped multi-file, or docs/code changes with validation; and whenever there are multiple steps, dependencies, handoffs, uncertainty, review/validation needs, long-running work, measurable done criteria, or an outcome that needs evidence.
75877
76900
  - Treat loop or stop-condition wording as a strong workflow signal, especially "do X until Y", "repeat until", "iterate until", "review/fix until passing", "run checks and fix until green", "keep going until done", or any prompt that names an approval gate or evidence requirement.
75878
76901
  - Do not force-fit an installed workflow. When another graph better matches the task, write a task-specific TypeScript workflow inline. Rich custom workflows may use deterministic branching, dynamic fan-out, child workflows, artifacts, structured outputs, human-in-the-loop prompts, gates, retries, and explicit stop conditions.
75879
- - Before launching any workflow for a non-trivial task, perform a short workflow-architecture pass. Derive implementation lifecycle needs, whole-codebase research needs, independent slices, competing strategies, exact API/type/build contracts, schema or generated-artifact contracts, state transitions/lifecycle behavior, deterministic stop conditions, and required evidence. Use a compact internal coverage matrix: \`requirement/risk | required evidence | workflow/stage that produces it | gap\`. Add the topology row \`acyclic topology | node/edge sketch for branches and loops | architecture pass | unresolved back-edge\`. Unresolved material rows or back-edges must change the graph before launch.
76902
+ - Before launching any workflow for a non-trivial task, perform a short workflow-architecture pass. Derive implementation lifecycle needs, whole-codebase research needs, independent slices, competing strategies, exact API/type/build contracts, schema or generated-artifact contracts, state transitions/lifecycle behavior, deterministic stop conditions, and required evidence. Enumerate implementation slices in this same pass, not a second planning ritual; give each slice its own objective, acceptance criteria, and gates, and require each to leave a buildable, testable repository state before the next slice. Use a compact internal coverage matrix: \`requirement/risk | required evidence | workflow/stage that produces it | gap\`. Add the topology row \`acyclic topology | node/edge sketch for branches and loops | architecture pass | unresolved back-edge\`. Unresolved material rows or back-edges must change the graph before launch.
75880
76903
  - In that architecture pass, sketch each branch, loop, and nested workflow boundary. Identify which stages repeat, require distinct tracked work for every iteration, name the current frontier before each repeat, reject self-edges and ancestor edges, compose nested workflows through \`ctx.workflow(...)\` boundaries rather than recursive \`run\` invocation, and preserve stable per-iteration identity and call order for resume/replay.
75881
76904
  - Compare candidate workflows by guarantees, not broad objectives: run one named workflow only when it covers the lifecycle and produces evidence for every material requirement/risk. A generic implementation workflow may cover the lifecycle without covering exact API/type/build contracts, schemas/generated artifacts, state transitions, or domain-specific gates. Do not treat "has reviewers" as proof that a task-specific risk is covered.
75882
76905
  - Use these routing signals without adding decorative stages: broad repository uncertainty → Fan-out-and-synthesize with repository-focused branches; independent slices → Fan-out-and-synthesize; plausible-but-wrong contract risk → Adversarial verification or a task-specific verification stage; competing architectures or implementations → Generate-and-filter or Tournament; an explicit repeat-until condition → Loop until done; implementation lifecycle → a task-specific worker/reviewer loop; exact API/build/schema requirements → dedicated deterministic gates.
@@ -75890,9 +76913,11 @@ var DEFAULT_PROMPT_GUIDANCE = [
75890
76913
  - When plausible-but-wrong behavior is a material risk in an arbitrary task-specific workflow, prefer a bounded evidence-backed adversarial loop. Give a fresh-context grumpy/skeptical-but-fair reviewer the literal objective and require actionable, evidence-backed falsification probes without invented requirements. Have it emit a structured verifier plan containing each exact probe, inputs, command/assertion, expected success condition, and requirement/risk covered.
75891
76914
  - Support both verifier shapes: for explicit known contracts, author direct task-specific \`ctx.tool(...)\` gates before launch; for risks requiring adversarial discovery, let the model select high-value probes through structured output, then execute the selected compile, test, schema generation/validation, runtime, or artifact-inspection checks authoritatively through durable \`ctx.tool(...)\` calls. Actual tool results—not model self-report—must feed skeptical evaluation, consolidated evidence-backed repair findings, and reruns after the implementation child repairs them.
75892
76915
  - Define bounded pass, repair, failure, and iteration-limit conditions before launch. Use \`ctx.tool\` for workflow-owned external checks and side effects whose results should be durably checkpointed. Each \`ctx.tool\` call is tracked as a durable, non-chat graph node and may run before, between, after, or without model stages; a tool-only workflow is valid tracked execution; keep pure transformations as ordinary TypeScript, and do not wrap every model-stage action in a tool call.
75893
- - Choose the cheapest graph that covers every material coverage row. Avoid decorative composition and duplicated research or review loops. Prefer composing a proven builtin or shared child over copying its prompt/graph.
76916
+ - Choose the cheapest graph that covers every material coverage row without collapsing independently verifiable implementation slices merely to minimize stage count. Avoid decorative composition and duplicated research or review loops. Prefer composing a proven builtin or shared child over copying its prompt/graph.
75894
76917
  - Before the first launch, state the selected graph, why one broad builtin is sufficient or insufficient, the evidence each major stage produces, and the stop/repair conditions. A simple direct match may use one sentence; a composed graph must briefly name its children and task-specific gates. For a custom adversarial loop, also name the skeptical reviewer, deterministic \`ctx.tool\` verifier gates, how model-selected plans become tool executions, and how failures reach bounded repair.
75895
- - Example custom shapes: classify a request and dispatch category-specific stages; fan out per package and synthesize artifact-backed results; implement, run fresh-context verifiers, reduce findings, and loop through repairs until approved; generate several plans and filter or tournament-rank them; or rerun checks and fixes until green with a progress ledger and max-iteration escape hatch.
76918
+ - Before launching an authored workflow, assign every model stage a role, failure cost, primary model, thinking level, and fallback policy. Use the role/risk defaults in the model-selection guide: reserve \`max\` for high-cost-of-error roles such as security, identity, adversarial challenge, and final approval; use \`high\` for demanding codebase mapping, lifecycle analysis, compatibility, planning, synthesis, triage, and repair; use \`medium\` for user-impact review and final reporting; keep deterministic checks as tool nodes with no model call. An explicit user request for a thinking level always wins over these defaults, subject to catalog support. For a mixed workflow, mapping may be \`high\`, approval \`max\`, reporting \`medium\`, and tests tool-only; never assign \`max\` to every model stage without a stage-specific reason.
76919
+ - Print a compact \`Stage | Model | Thinking | Role\` assignment before launch with a short cost/quality rationale for each model stage. Apply the same role/risk policy to every fallback attempt rather than inheriting \`max\` mechanically; choose each primary and fallback level from the configured catalog, and if no selected catalog model supports the role's level, leave the stage unpinned rather than inventing an unsupported level.
76920
+ - Example custom shapes: classify a request and dispatch category-specific stages; fan out per package and synthesize artifact-backed results; decompose one implementation objective into stacked, independently verified slices with a bounded child lifecycle per slice; implement, run fresh-context verifiers, reduce findings, and loop through repairs until approved; generate several plans and filter or tournament-rank them; or rerun checks and fixes until green with a progress ledger and max-iteration escape hatch.
75896
76921
  - Budget reconnaissance: once workflow fit is clear, keep pre-workflow exploration to a few quick reads that sharpen the objective and validation criteria. Put deep research, upstream/design comparison, and behavior probing inside the workflow. Pass large context through files/artifacts and \`reads\` rather than injecting it into prompts.
75897
76922
  - Course-correct instead of drifting: after roughly ten exploratory tool calls with no artifact, edit, or commit, or repeated "let me verify one more thing" loops, stop, write findings to a context file, and hand the task to the best-fit named or custom workflow. Sunk inline research transfers through files; it is not a reason to stay inline.
75898
76923
  - Only skip workflows for tiny, deterministic, low-risk answers or direct edits where stage tracking clearly costs more than it adds, typically a single-file/no-test/no-review change or a simple answer.`,
@@ -75908,12 +76933,15 @@ var DEFAULT_PROMPT_GUIDANCE = [
75908
76933
  `**Workflow authoring and handoffs**:
75909
76934
  - When a user asks to create or edit a workflow, clarify only unresolved requirements that materially affect its purpose, inputs, stages, handoffs, validation, success criteria, or starter pattern. Read the workflow docs/examples, implement the TypeScript definition with normal coding tools, reload it, and run representative test inputs before presenting it. Use the create-spec skill when it adds value; it is not mandatory when context is already sufficient.
75910
76935
  - After creating and reloading a newly authored custom workflow, close the loop by stating the folder containing the workflow file just written, for example \`.atomic/workflows/\`, in this shape: \`Custom workflow created. You can inspect its code at: <workflow-folder-path>\`. Do this only for newly created custom workflows, never builtin or pre-existing workflows.
75911
- - When creating or editing a workflow that pins an explicit stage \`model\` or \`fallbackModels\`, consult \`packages/coding-agent/docs/models/model-selection.md\` for role-based recommendations, then call \`workflow({ action: "models" })\` to see the models actually present in the user's configured catalog. Use only the catalog's returned \`fullId\` values as model strings, and append a thinking suffix only when that exact level appears in the entry's \`availableThinkingLevels\`; treat an absent or empty \`availableThinkingLevels\` as no suffix support rather than inferring one. If a guide-recommended model for the role is unavailable, try another guide-recommended model that is present in the catalog. If no recommendation intersects with the catalog, leave the stage unpinned rather than inventing a substitute, and mention the limitation, asking the user only if the workflow requires an explicit model choice. If the catalog is empty, continue with unpinned stages, state that no configured models were returned, and do not fabricate model IDs. Do not inspect or infer credentials, environment variables, auth files, token validity, entitlements, or the reason a model is absent; \`isCurrent\` marks the active selection, not a quality recommendation.
75912
- - Consult docs/workflows.md and its starter patterns (Classify-and-act, Fan-out-and-synthesize, Adversarial verification, Generate-and-filter, Tournament, and Loop until done) when designing a stage graph.
76936
+ - When creating or editing a workflow that pins an explicit stage \`model\` or \`fallbackModels\`, consult \`packages/coding-agent/docs/models/model-selection.md\` for role-based recommendations, treating benchmark thinking levels as measurement configurations rather than universal workflow defaults, then call \`workflow({ action: "models" })\` to see the models actually present in the user's configured catalog. Use only the catalog's returned \`fullId\` values as model strings, and append a thinking suffix only when that exact level appears in the entry's \`availableThinkingLevels\`; apply the stage role and failure-cost policy independently to the primary and every fallback; treat an absent or empty \`availableThinkingLevels\` as no suffix support rather than inferring one. If a guide-recommended model for the role is unavailable, try another guide-recommended model that is present in the catalog. If the selected model does not support the role's level, choose another catalog model that does or leave the stage unpinned rather than inventing or silently promoting a level. An explicit user request for a level overrides the role default, but never fabricate an unsupported catalog level. If no recommendation intersects with the catalog, leave the stage unpinned rather than inventing a substitute, and mention the limitation, asking the user only if the workflow requires an explicit model choice. If the catalog is empty, continue with unpinned stages, state that no configured models were returned, and do not fabricate model IDs. Do not inspect or infer credentials, environment variables, auth files, token validity, entitlements, or the reason a model is absent; \`isCurrent\` marks the active selection, not a quality recommendation.
76937
+ - Consult docs/workflows.md and its starter patterns (Classify-and-act, Fan-out-and-synthesize, Adversarial verification, Generate-and-filter, Tournament, Loop until done, and Stacked implementation slices) when designing a stage graph.
75913
76938
  - Treat workflow composition as a first-class authoring option. Before duplicating stages, inspect reusable workflow modules and builtin exports; import their definitions and invoke them with \`ctx.workflow(...)\`, mapping typed inputs and consuming only declared outputs. Nested workflows can themselves import children, so combine small reusable graphs into a richer parent while respecting \`maxDepth\`.
76939
+ - For implementation objectives, prefer the smallest independently verifiable slice: target roughly 100–500 changed lines between verification points by default, with one reviewable concern that builds and tests on its own. This is a default, not a law: a genuinely atomic change (for example, a mechanical rename across many files or a generated-artifact refresh) stays one slice, and a small objective is not split merely to reach a count.
76940
+ - Decompose those slices during the pre-launch architecture pass, not in a second planning ritual. Run every slice through a child workflow with its own implement/review/repair lifecycle: invoke imported \`goal\`, \`ralph\`, or a task-specific child via \`ctx.workflow(...)\`, rather than making one parent stage own all slices.
76941
+ - Stack implementation slices in order: give each slice an explicit branch input and, before invoking its child, create or check out that named branch in its worktree with a durable \`ctx.tool(...)\` step; \`base_branch\` and \`git_worktree_dir\` alone do not create/check out a feature branch. Slice N+1 must be created from slice N's verified branch, pass that branch as \`base_branch\`, and use a distinct worktree. Verify each slice before proceeding; if a slice fails its gates, stop at the first unverified slice; earlier verified slices remain verified and are reported as such; do not roll them back or continue past the failure.
75914
76942
  - Atomic \`workflow({ run })\` definitions are imperative, dynamic TypeScript. Discovery validates module loading, imports, and definition shape, including schemas and the \`run\` function, but it does not compile \`run\` into a complete graph or prove acyclicity. Runtime inputs, branches, loops, files, network data, model or human output, helpers, and nested workflows determine the materialized graph during execution.
75915
76943
  - Cyclic workflow graphs are unsupported. Workflow authors and coding agents MUST NOT create self-edges or dependency edges from the current frontier to an existing ancestor. Every materialized execution topology must remain a DAG. Redesign or stop before launch if a cycle cannot be removed.
75916
- - Bounded loops must create distinct tracked work for every iteration; never reopen an ancestor below its downstream work. If a retained session receives follow-up without new dependency work, keep it as non-topological activity metadata rather than adding a back-edge. Before launch, sketch nodes and dependencies for every branch and loop and reject any proposed parent edge to the node itself or an ancestor.
76944
+ - Bounded loops must create distinct tracked work for every iteration; never reopen an ancestor below its downstream work. Stacked implementation slices are unrolled, not looped: each slice gets a fresh child boundary and distinct tracked nodes, and no slice may add an edge back to the current frontier, itself, or an ancestor. If a retained session receives follow-up without new dependency work, keep it as non-topological activity metadata rather than adding a back-edge. Before launch, sketch nodes and dependencies for every branch and loop and reject any proposed parent edge to the node itself or an ancestor.
75917
76945
  - Treat dynamic graph validation during execution, replay, and DBOS hydration as the authoritative cycle boundary. If runtime topology code changes, require incremental edge checks and DBOS hydration validation; prompt guidance and TypeScript types cannot replace those runtime checks.
75918
76946
  - Every workflow invocation automatically receives one stable, non-default Intercom group. Intercom-capable stages inherit it, nested workflows keep the top-level invocation group, and subagents inherit their launching stage's group. Do not mint or thread group names through ordinary workflow definitions. Use an explicit \`group\` only for an intentional override: a named group or \`group: true\` creates a subgroup, while \`group: "default"\` opts into the shared default group. Stages without Intercom access receive no group, and \`contact_supervisor\` still crosses group boundaries for authorized escalation.
75919
76947
  - Prefer \`ctx.tool(name, args, fn)\` for workflow-owned TypeScript operations with side effects, such as filesystem writes, network mutations, and external API actions. It creates a tracked, non-attachable durable graph node before invoking \`fn\`; it may be used before, between, after, or without model stages. A completed \`ctx.tool\` call is durably checkpointed with its serializable result, so resume replays that result without rerunning \`fn\`. For checks that may fail during a bounded repair loop, opt into \`failureMode: "return"\`, branch on the typed outcome, and pass only the needed error fields to the repair stage or artifact yourself; Atomic does not inject failure evidence into later prompts. Cancellation and storage faults still throw. Keep pure computation and side-effect-free transformations as ordinary TypeScript. Do not wrap agent-stage internals or every function call indiscriminately; this rule applies to side effects orchestrated directly by the workflow definition.