@bastani/atomic 0.9.9 → 0.9.10-alpha.1

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 (864) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/README.md +2 -0
  3. package/dist/builtin/cursor/CHANGELOG.md +6 -0
  4. package/dist/builtin/cursor/package.json +3 -3
  5. package/dist/builtin/intercom/CHANGELOG.md +15 -0
  6. package/dist/builtin/intercom/README.md +12 -4
  7. package/dist/builtin/intercom/broker/broker.ts +96 -14
  8. package/dist/builtin/intercom/broker/client-message-validation.ts +39 -0
  9. package/dist/builtin/intercom/broker/client.ts +101 -92
  10. package/dist/builtin/intercom/broker/group-isolation.ts +28 -0
  11. package/dist/builtin/intercom/broker/send-handler.ts +62 -10
  12. package/dist/builtin/intercom/broker/send-signature.ts +3 -0
  13. package/dist/builtin/intercom/broker/supervisor-channel.ts +126 -0
  14. package/dist/builtin/intercom/closed-workflow-stage-message.ts +66 -0
  15. package/dist/builtin/intercom/config.ts +10 -0
  16. package/dist/builtin/intercom/contact-supervisor-tool.ts +14 -10
  17. package/dist/builtin/intercom/foreground-detach-handoff.ts +12 -2
  18. package/dist/builtin/intercom/group.ts +46 -0
  19. package/dist/builtin/intercom/inbound-message-admission.ts +79 -0
  20. package/dist/builtin/intercom/incoming-message-delivery.ts +49 -0
  21. package/dist/builtin/intercom/index-heavy.ts +148 -94
  22. package/dist/builtin/intercom/index.ts +66 -4
  23. package/dist/builtin/intercom/intercom-test-seams.ts +6 -0
  24. package/dist/builtin/intercom/intercom-tool.ts +71 -20
  25. package/dist/builtin/intercom/intercom-utils.ts +15 -2
  26. package/dist/builtin/intercom/late-stage-message-router.ts +148 -0
  27. package/dist/builtin/intercom/lifecycle.ts +10 -4
  28. package/dist/builtin/intercom/package.json +2 -2
  29. package/dist/builtin/intercom/reconnect-backoff.ts +6 -0
  30. package/dist/builtin/intercom/reply-tracker.ts +8 -0
  31. package/dist/builtin/intercom/skills/intercom/SKILL.md +2 -0
  32. package/dist/builtin/intercom/stable-delivery-retry.ts +32 -0
  33. package/dist/builtin/intercom/subagent-relay.ts +67 -14
  34. package/dist/builtin/intercom/supervisor-authorization-registry.ts +22 -0
  35. package/dist/builtin/intercom/terminal-ordering-barrier.ts +144 -25
  36. package/dist/builtin/intercom/types.ts +18 -5
  37. package/dist/builtin/intercom/workflow-reply-tracker.ts +19 -0
  38. package/dist/builtin/intercom/workflow-stage-admission.ts +43 -0
  39. package/dist/builtin/intercom/workflow-stage-delivery-failure.ts +77 -0
  40. package/dist/builtin/mcp/CHANGELOG.md +11 -0
  41. package/dist/builtin/mcp/README.md +6 -2
  42. package/dist/builtin/mcp/config.ts +8 -8
  43. package/dist/builtin/mcp/direct-tool-executor.ts +7 -6
  44. package/dist/builtin/mcp/package.json +3 -3
  45. package/dist/builtin/mcp/proxy-call.ts +5 -4
  46. package/dist/builtin/mcp/sampling-handler.ts +7 -2
  47. package/dist/builtin/mcp/tool-call-timeout.ts +101 -0
  48. package/dist/builtin/mcp/tool-result-renderer.ts +3 -2
  49. package/dist/builtin/mcp/types.ts +5 -0
  50. package/dist/builtin/mcp/ui-server.ts +3 -2
  51. package/dist/builtin/subagents/CHANGELOG.md +21 -0
  52. package/dist/builtin/subagents/README.md +6 -3
  53. package/dist/builtin/subagents/agents/code-simplifier.md +1 -1
  54. package/dist/builtin/subagents/agents/codebase-analyzer.md +1 -1
  55. package/dist/builtin/subagents/agents/codebase-locator.md +1 -1
  56. package/dist/builtin/subagents/agents/codebase-online-researcher.md +1 -1
  57. package/dist/builtin/subagents/agents/codebase-pattern-finder.md +1 -1
  58. package/dist/builtin/subagents/agents/codebase-research-analyzer.md +1 -1
  59. package/dist/builtin/subagents/agents/codebase-research-locator.md +1 -1
  60. package/dist/builtin/subagents/agents/debugger.md +1 -1
  61. package/dist/builtin/subagents/agents/worker.md +1 -1
  62. package/dist/builtin/subagents/package.json +4 -4
  63. package/dist/builtin/subagents/skills/subagent/SKILL.md +1 -1
  64. package/dist/builtin/subagents/src/extension/index.ts +37 -61
  65. package/dist/builtin/subagents/src/extension/notification-content.ts +80 -0
  66. package/dist/builtin/subagents/src/extension/schemas.ts +9 -0
  67. package/dist/builtin/subagents/src/extension/tool-description.ts +1 -0
  68. package/dist/builtin/subagents/src/intercom/supervisor-authorization.ts +23 -0
  69. package/dist/builtin/subagents/src/runs/background/async-execution-chain.ts +4 -0
  70. package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +2 -0
  71. package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +4 -0
  72. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +75 -13
  73. package/dist/builtin/subagents/src/runs/background/async-status.ts +19 -0
  74. package/dist/builtin/subagents/src/runs/background/completion-notification.ts +4 -3
  75. package/dist/builtin/subagents/src/runs/background/notify.ts +76 -15
  76. package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +1 -1
  77. package/dist/builtin/subagents/src/runs/background/subagent-runner-dynamic.ts +13 -0
  78. package/dist/builtin/subagents/src/runs/background/subagent-runner-parallel.ts +1 -0
  79. package/dist/builtin/subagents/src/runs/background/subagent-runner-sequential.ts +1 -0
  80. package/dist/builtin/subagents/src/runs/background/subagent-runner-step.ts +2 -1
  81. package/dist/builtin/subagents/src/runs/background/subagent-runner-types.ts +4 -0
  82. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +13 -0
  83. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-step.ts +19 -2
  84. package/dist/builtin/subagents/src/runs/foreground/detached-cleanup-barrier.ts +26 -0
  85. package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +19 -30
  86. package/dist/builtin/subagents/src/runs/foreground/execution-intercom-detach.ts +47 -0
  87. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +60 -2
  88. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +21 -0
  89. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +21 -2
  90. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-resume.ts +6 -1
  91. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +2 -0
  92. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +2 -0
  93. package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +1 -1
  94. package/dist/builtin/subagents/src/runs/shared/intercom-group.ts +50 -0
  95. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +16 -0
  96. package/dist/builtin/subagents/src/runs/shared/worktree-post-create.ts +75 -0
  97. package/dist/builtin/subagents/src/runs/shared/worktree-root.ts +51 -0
  98. package/dist/builtin/subagents/src/runs/shared/worktree.ts +69 -77
  99. package/dist/builtin/subagents/src/shared/types-config.ts +6 -0
  100. package/dist/builtin/subagents/src/slash/slash-commands.ts +3 -2
  101. package/dist/builtin/subagents/src/tui/render-result-compact.ts +5 -3
  102. package/dist/builtin/subagents/src/tui/render-result.ts +5 -3
  103. package/dist/builtin/subagents/src/tui/render-widget-graph.ts +7 -4
  104. package/dist/builtin/web-access/CHANGELOG.md +11 -0
  105. package/dist/builtin/web-access/extract-frames.ts +14 -13
  106. package/dist/builtin/web-access/extract.ts +2 -2
  107. package/dist/builtin/web-access/gemini-api.ts +0 -3
  108. package/dist/builtin/web-access/gemini-web-config.ts +1 -3
  109. package/dist/builtin/web-access/gemini-web.ts +1 -0
  110. package/dist/builtin/web-access/package.json +2 -2
  111. package/dist/builtin/web-access/perplexity.ts +0 -3
  112. package/dist/builtin/web-access/result-renderers.ts +7 -5
  113. package/dist/builtin/web-access/subprocess.ts +100 -0
  114. package/dist/builtin/web-access/summary-review.ts +14 -3
  115. package/dist/builtin/web-access/video-extract.ts +12 -17
  116. package/dist/builtin/web-access/web-search-browser.ts +18 -10
  117. package/dist/builtin/web-access/web-search-summary.ts +9 -2
  118. package/dist/builtin/web-access/youtube-extract.ts +22 -25
  119. package/dist/builtin/workflows/CHANGELOG.md +77 -0
  120. package/dist/builtin/workflows/README.md +76 -38
  121. package/dist/builtin/workflows/ambient.d.ts +30 -0
  122. package/dist/builtin/workflows/builtin/adversarial-verification-prompts.ts +15 -0
  123. package/dist/builtin/workflows/builtin/adversarial-verification-runner.ts +93 -0
  124. package/dist/builtin/workflows/builtin/adversarial-verification.d.ts +11 -0
  125. package/dist/builtin/workflows/builtin/adversarial-verification.ts +24 -0
  126. package/dist/builtin/workflows/builtin/classify-and-act-prompts.ts +11 -0
  127. package/dist/builtin/workflows/builtin/classify-and-act-runner.ts +110 -0
  128. package/dist/builtin/workflows/builtin/classify-and-act.d.ts +24 -0
  129. package/dist/builtin/workflows/builtin/classify-and-act.ts +35 -0
  130. package/dist/builtin/workflows/builtin/deep-research-codebase-utils.ts +8 -2
  131. package/dist/builtin/workflows/builtin/fan-out-and-synthesize-prompts.ts +11 -0
  132. package/dist/builtin/workflows/builtin/fan-out-and-synthesize-runner.ts +96 -0
  133. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.d.ts +23 -0
  134. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.ts +32 -0
  135. package/dist/builtin/workflows/builtin/generate-and-filter-prompts.ts +15 -0
  136. package/dist/builtin/workflows/builtin/generate-and-filter-runner.ts +75 -0
  137. package/dist/builtin/workflows/builtin/generate-and-filter.d.ts +11 -0
  138. package/dist/builtin/workflows/builtin/generate-and-filter.ts +26 -0
  139. package/dist/builtin/workflows/builtin/goal-models.ts +72 -0
  140. package/dist/builtin/workflows/builtin/goal-runner.ts +2 -64
  141. package/dist/builtin/workflows/builtin/index.d.ts +44 -0
  142. package/dist/builtin/workflows/builtin/index.ts +6 -0
  143. package/dist/builtin/workflows/builtin/loop-until-done-prompts.ts +79 -0
  144. package/dist/builtin/workflows/builtin/loop-until-done-runner.ts +189 -0
  145. package/dist/builtin/workflows/builtin/loop-until-done.d.ts +34 -0
  146. package/dist/builtin/workflows/builtin/loop-until-done.ts +31 -0
  147. package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +6 -1
  148. package/dist/builtin/workflows/builtin/pattern-artifact-root.ts +28 -0
  149. package/dist/builtin/workflows/builtin/ralph-models.ts +26 -5
  150. package/dist/builtin/workflows/builtin/ralph-runner.ts +1 -0
  151. package/dist/builtin/workflows/builtin/tournament-prompts.ts +79 -0
  152. package/dist/builtin/workflows/builtin/tournament-runner.ts +188 -0
  153. package/dist/builtin/workflows/builtin/tournament.d.ts +33 -0
  154. package/dist/builtin/workflows/builtin/tournament.ts +34 -0
  155. package/dist/builtin/workflows/package.json +2 -2
  156. package/dist/builtin/workflows/src/authoring.d.ts +2 -6
  157. package/dist/builtin/workflows/src/durable/backend.ts +163 -120
  158. package/dist/builtin/workflows/src/durable/completed-catalog.ts +37 -64
  159. package/dist/builtin/workflows/src/durable/completed-inspection.ts +4 -72
  160. package/dist/builtin/workflows/src/durable/dbos-backend.ts +242 -195
  161. package/dist/builtin/workflows/src/durable/dbos-embedded-postgres.ts +207 -0
  162. package/dist/builtin/workflows/src/durable/dbos-envelope.ts +42 -42
  163. package/dist/builtin/workflows/src/durable/dbos-lifecycle.ts +155 -0
  164. package/dist/builtin/workflows/src/durable/dbos-local-postgres.ts +126 -0
  165. package/dist/builtin/workflows/src/durable/dbos-metadata.ts +105 -58
  166. package/dist/builtin/workflows/src/durable/dbos-prompt-reservations.ts +320 -0
  167. package/dist/builtin/workflows/src/durable/dbos-sdk-handle.ts +161 -0
  168. package/dist/builtin/workflows/src/durable/dbos-status-transition.ts +62 -0
  169. package/dist/builtin/workflows/src/durable/dbos-tombstone.ts +2 -2
  170. package/dist/builtin/workflows/src/durable/durable-hash.ts +20 -0
  171. package/dist/builtin/workflows/src/durable/factory.ts +23 -83
  172. package/dist/builtin/workflows/src/durable/format-version.ts +4 -10
  173. package/dist/builtin/workflows/src/durable/index.ts +16 -20
  174. package/dist/builtin/workflows/src/durable/local-command.ts +63 -0
  175. package/dist/builtin/workflows/src/durable/prompt-reservation-state.ts +177 -0
  176. package/dist/builtin/workflows/src/durable/prompt-reservations.ts +36 -0
  177. package/dist/builtin/workflows/src/durable/resume-catalog.ts +2 -200
  178. package/dist/builtin/workflows/src/durable/resume-eligibility.ts +42 -2
  179. package/dist/builtin/workflows/src/durable/resume-runtime.ts +121 -118
  180. package/dist/builtin/workflows/src/durable/retention-policy.ts +42 -0
  181. package/dist/builtin/workflows/src/durable/run-timing.ts +98 -0
  182. package/dist/builtin/workflows/src/durable/scoped-backend.ts +62 -14
  183. package/dist/builtin/workflows/src/durable/stage-primitive.ts +15 -2
  184. package/dist/builtin/workflows/src/durable/tool-primitive.ts +11 -7
  185. package/dist/builtin/workflows/src/durable/types.ts +25 -18
  186. package/dist/builtin/workflows/src/durable/ui-primitive.ts +117 -29
  187. package/dist/builtin/workflows/src/durable/workflow-status-transition.ts +30 -0
  188. package/dist/builtin/workflows/src/engine/primitives/parallel.ts +20 -5
  189. package/dist/builtin/workflows/src/engine/primitives/task.ts +3 -2
  190. package/dist/builtin/workflows/src/engine/primitives/ui.ts +6 -3
  191. package/dist/builtin/workflows/src/engine/run-durable-finalize.ts +14 -22
  192. package/dist/builtin/workflows/src/engine/run-durable-stage-session.ts +14 -14
  193. package/dist/builtin/workflows/src/engine/run.ts +35 -37
  194. package/dist/builtin/workflows/src/engine/runtime.ts +3 -0
  195. package/dist/builtin/workflows/src/engine/workflow-activity.ts +9 -0
  196. package/dist/builtin/workflows/src/extension/completed-stage-intercom-ask.ts +155 -0
  197. package/dist/builtin/workflows/src/extension/config-file-loader.ts +13 -0
  198. package/dist/builtin/workflows/src/extension/config-loader.ts +20 -0
  199. package/dist/builtin/workflows/src/extension/dispatcher.ts +56 -17
  200. package/dist/builtin/workflows/src/extension/extension-factory.ts +13 -10
  201. package/dist/builtin/workflows/src/extension/extension-lifecycle.ts +37 -59
  202. package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +16 -18
  203. package/dist/builtin/workflows/src/extension/lifecycle-notification-delivery.ts +83 -0
  204. package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +80 -41
  205. package/dist/builtin/workflows/src/extension/postmortem-deps.ts +73 -0
  206. package/dist/builtin/workflows/src/extension/public-types.ts +11 -51
  207. package/dist/builtin/workflows/src/extension/render-call.ts +3 -9
  208. package/dist/builtin/workflows/src/extension/render-result.ts +22 -7
  209. package/dist/builtin/workflows/src/extension/runtime-active-block-claim.ts +78 -0
  210. package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +50 -29
  211. package/dist/builtin/workflows/src/extension/runtime.ts +70 -219
  212. package/dist/builtin/workflows/src/extension/ui-surface.ts +107 -3
  213. package/dist/builtin/workflows/src/extension/wiring.ts +76 -7
  214. package/dist/builtin/workflows/src/extension/workflow-command-completions.ts +10 -5
  215. package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +27 -5
  216. package/dist/builtin/workflows/src/extension/workflow-durable-resume-command.ts +49 -19
  217. package/dist/builtin/workflows/src/extension/workflow-prompts.ts +8 -8
  218. package/dist/builtin/workflows/src/extension/workflow-resume-picker-rows.ts +81 -0
  219. package/dist/builtin/workflows/src/extension/workflow-resume-shadow.ts +55 -0
  220. package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +193 -145
  221. package/dist/builtin/workflows/src/extension/workflow-schema.ts +9 -133
  222. package/dist/builtin/workflows/src/extension/workflow-status-summary.ts +189 -0
  223. package/dist/builtin/workflows/src/extension/workflow-targets.ts +1 -1
  224. package/dist/builtin/workflows/src/extension/workflow-tool-content.ts +78 -3
  225. package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +185 -89
  226. package/dist/builtin/workflows/src/extension/workflow-tool-send.ts +92 -11
  227. package/dist/builtin/workflows/src/extension/workflow-tool.ts +18 -24
  228. package/dist/builtin/workflows/src/runs/background/durable-resume-transition.ts +63 -0
  229. package/dist/builtin/workflows/src/runs/background/quit.ts +139 -29
  230. package/dist/builtin/workflows/src/runs/background/resume-acknowledgements.ts +97 -0
  231. package/dist/builtin/workflows/src/runs/background/run-inspect.ts +111 -0
  232. package/dist/builtin/workflows/src/runs/background/runner.ts +46 -17
  233. package/dist/builtin/workflows/src/runs/background/startup-admission.ts +77 -0
  234. package/dist/builtin/workflows/src/runs/background/status.ts +133 -224
  235. package/dist/builtin/workflows/src/runs/background/workflow-lifecycle-aggregate.ts +44 -0
  236. package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +57 -256
  237. package/dist/builtin/workflows/src/runs/foreground/executor-hil.ts +7 -4
  238. package/dist/builtin/workflows/src/runs/foreground/executor-lifecycle.ts +12 -1
  239. package/dist/builtin/workflows/src/runs/foreground/executor-prompt-nodes.ts +39 -0
  240. package/dist/builtin/workflows/src/runs/foreground/executor-queued-user-message.ts +75 -0
  241. package/dist/builtin/workflows/src/runs/foreground/executor-stage-call.ts +44 -12
  242. package/dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts +63 -12
  243. package/dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts +30 -4
  244. package/dist/builtin/workflows/src/runs/foreground/executor-stage-replay.ts +3 -0
  245. package/dist/builtin/workflows/src/runs/foreground/executor-stage-types.ts +4 -1
  246. package/dist/builtin/workflows/src/runs/foreground/executor-task-prompts.ts +0 -67
  247. package/dist/builtin/workflows/src/runs/foreground/executor-types.ts +6 -0
  248. package/dist/builtin/workflows/src/runs/foreground/executor.ts +0 -1
  249. package/dist/builtin/workflows/src/runs/foreground/postmortem-stage-chat.ts +169 -0
  250. package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +38 -1
  251. package/dist/builtin/workflows/src/runs/foreground/stage-runner-candidate.ts +21 -0
  252. package/dist/builtin/workflows/src/runs/foreground/stage-runner-context.ts +21 -3
  253. package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +85 -84
  254. package/dist/builtin/workflows/src/runs/foreground/stage-runner-message-admission.ts +195 -0
  255. package/dist/builtin/workflows/src/runs/foreground/stage-runner-options.ts +12 -5
  256. package/dist/builtin/workflows/src/runs/foreground/stage-runner-replacement.ts +42 -0
  257. package/dist/builtin/workflows/src/runs/foreground/stage-runner-send-user-message.ts +100 -8
  258. package/dist/builtin/workflows/src/runs/foreground/stage-runner-session-options.ts +51 -0
  259. package/dist/builtin/workflows/src/runs/foreground/stage-runner-session.ts +19 -0
  260. package/dist/builtin/workflows/src/runs/foreground/stage-runner-types.ts +28 -2
  261. package/dist/builtin/workflows/src/runs/shared/prompt-callsite.ts +4 -6
  262. package/dist/builtin/workflows/src/runs/shared/worktree-git-runner.ts +89 -0
  263. package/dist/builtin/workflows/src/runs/shared/worktree-git.ts +29 -133
  264. package/dist/builtin/workflows/src/runs/shared/worktree-post-create.ts +130 -0
  265. package/dist/builtin/workflows/src/runs/shared/worktree-root.ts +84 -0
  266. package/dist/builtin/workflows/src/runs/shared/worktree-setup.ts +77 -63
  267. package/dist/builtin/workflows/src/runs/shared/worktree-types.ts +4 -0
  268. package/dist/builtin/workflows/src/sdk-surface.ts +1 -1
  269. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +29 -22
  270. package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +26 -24
  271. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +5 -0
  272. package/dist/builtin/workflows/src/shared/authoring-contract-ui.ts +5 -0
  273. package/dist/builtin/workflows/src/shared/intercom-group.ts +51 -0
  274. package/dist/builtin/workflows/src/shared/persistence-restore-helpers.ts +6 -0
  275. package/dist/builtin/workflows/src/shared/persistence-restore.ts +4 -0
  276. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +3 -0
  277. package/dist/builtin/workflows/src/shared/prompt-callsite-context.ts +13 -0
  278. package/dist/builtin/workflows/src/shared/returned-run-status.ts +2 -1
  279. package/dist/builtin/workflows/src/shared/session-transcript.ts +74 -0
  280. package/dist/builtin/workflows/src/shared/store-stage-methods.ts +1 -0
  281. package/dist/builtin/workflows/src/shared/store-types.ts +8 -0
  282. package/dist/builtin/workflows/src/shared/timing.ts +4 -1
  283. package/dist/builtin/workflows/src/shared/types.ts +2 -6
  284. package/dist/builtin/workflows/src/tui/chat-surface-message.ts +2 -42
  285. package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +2 -2
  286. package/dist/builtin/workflows/src/tui/graph-view-constants.ts +7 -3
  287. package/dist/builtin/workflows/src/tui/graph-view-input.ts +29 -67
  288. package/dist/builtin/workflows/src/tui/graph-view-render-helpers.ts +15 -10
  289. package/dist/builtin/workflows/src/tui/graph-view-state.ts +0 -2
  290. package/dist/builtin/workflows/src/tui/graph-view-types.ts +3 -9
  291. package/dist/builtin/workflows/src/tui/host-input-form.ts +62 -0
  292. package/dist/builtin/workflows/src/tui/mouse-input.ts +63 -0
  293. package/dist/builtin/workflows/src/tui/node-card.ts +1 -0
  294. package/dist/builtin/workflows/src/tui/overlay-adapter.ts +67 -42
  295. package/dist/builtin/workflows/src/tui/overlay-terminal-modes.ts +49 -0
  296. package/dist/builtin/workflows/src/tui/session-overlays.ts +3 -104
  297. package/dist/builtin/workflows/src/tui/session-picker.ts +3 -12
  298. package/dist/builtin/workflows/src/tui/stage-chat-composer-drafts.ts +19 -0
  299. package/dist/builtin/workflows/src/tui/stage-chat-view-archive-history.ts +30 -10
  300. package/dist/builtin/workflows/src/tui/stage-chat-view-footer-status.ts +19 -9
  301. package/dist/builtin/workflows/src/tui/stage-chat-view-input.ts +25 -38
  302. package/dist/builtin/workflows/src/tui/stage-chat-view-render-helpers.ts +1 -1
  303. package/dist/builtin/workflows/src/tui/stage-chat-view-state.ts +7 -6
  304. package/dist/builtin/workflows/src/tui/stage-chat-view-types.ts +7 -1
  305. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +3 -1
  306. package/dist/builtin/workflows/src/tui/store-widget-installer.ts +19 -20
  307. package/dist/builtin/workflows/src/tui/switcher.ts +4 -4
  308. package/dist/builtin/workflows/src/tui/widget.ts +46 -33
  309. package/dist/builtin/workflows/src/tui/workflow-attach-pane-handle.ts +26 -0
  310. package/dist/builtin/workflows/src/tui/workflow-attach-pane-types.ts +14 -2
  311. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +26 -27
  312. package/dist/builtin/workflows/src/tui/workflow-resume-selector.ts +208 -69
  313. package/dist/bun/cli.js +3 -0
  314. package/dist/bun/cli.js.map +1 -1
  315. package/dist/cli/session-picker.d.ts.map +1 -1
  316. package/dist/cli/session-picker.js +3 -0
  317. package/dist/cli/session-picker.js.map +1 -1
  318. package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
  319. package/dist/core/agent-session-auto-compaction.js +19 -2
  320. package/dist/core/agent-session-auto-compaction.js.map +1 -1
  321. package/dist/core/agent-session-compaction.js +2 -2
  322. package/dist/core/agent-session-compaction.js.map +1 -1
  323. package/dist/core/agent-session-events.d.ts.map +1 -1
  324. package/dist/core/agent-session-events.js +5 -3
  325. package/dist/core/agent-session-events.js.map +1 -1
  326. package/dist/core/agent-session-export.js +1 -1
  327. package/dist/core/agent-session-export.js.map +1 -1
  328. package/dist/core/agent-session-extension-bindings.d.ts +2 -4
  329. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  330. package/dist/core/agent-session-extension-bindings.js +9 -2
  331. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  332. package/dist/core/agent-session-message-queue.d.ts +6 -0
  333. package/dist/core/agent-session-message-queue.d.ts.map +1 -1
  334. package/dist/core/agent-session-message-queue.js +107 -36
  335. package/dist/core/agent-session-message-queue.js.map +1 -1
  336. package/dist/core/agent-session-methods.d.ts +18 -7
  337. package/dist/core/agent-session-methods.d.ts.map +1 -1
  338. package/dist/core/agent-session-methods.js.map +1 -1
  339. package/dist/core/agent-session-models.d.ts +3 -1
  340. package/dist/core/agent-session-models.d.ts.map +1 -1
  341. package/dist/core/agent-session-models.js +1 -1
  342. package/dist/core/agent-session-models.js.map +1 -1
  343. package/dist/core/agent-session-post-tool-compaction.d.ts +16 -0
  344. package/dist/core/agent-session-post-tool-compaction.d.ts.map +1 -0
  345. package/dist/core/agent-session-post-tool-compaction.js +113 -0
  346. package/dist/core/agent-session-post-tool-compaction.js.map +1 -0
  347. package/dist/core/agent-session-prompt.d.ts +12 -1
  348. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  349. package/dist/core/agent-session-prompt.js +22 -5
  350. package/dist/core/agent-session-prompt.js.map +1 -1
  351. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  352. package/dist/core/agent-session-runtime.js +3 -0
  353. package/dist/core/agent-session-runtime.js.map +1 -1
  354. package/dist/core/agent-session-tool-hooks.d.ts.map +1 -1
  355. package/dist/core/agent-session-tool-hooks.js +21 -0
  356. package/dist/core/agent-session-tool-hooks.js.map +1 -1
  357. package/dist/core/agent-session-tree.d.ts.map +1 -1
  358. package/dist/core/agent-session-tree.js +2 -1
  359. package/dist/core/agent-session-tree.js.map +1 -1
  360. package/dist/core/agent-session-types.d.ts +7 -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 +6 -0
  364. package/dist/core/agent-session.d.ts.map +1 -1
  365. package/dist/core/agent-session.js +18 -1
  366. package/dist/core/agent-session.js.map +1 -1
  367. package/dist/core/async/job-manager.d.ts +1 -0
  368. package/dist/core/async/job-manager.d.ts.map +1 -1
  369. package/dist/core/async/job-manager.js +29 -5
  370. package/dist/core/async/job-manager.js.map +1 -1
  371. package/dist/core/async/session-manager.d.ts +2 -4
  372. package/dist/core/async/session-manager.d.ts.map +1 -1
  373. package/dist/core/async/session-manager.js +5 -32
  374. package/dist/core/async/session-manager.js.map +1 -1
  375. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  376. package/dist/core/atomic-guide-command.js +2 -0
  377. package/dist/core/atomic-guide-command.js.map +1 -1
  378. package/dist/core/auth-storage.d.ts +20 -10
  379. package/dist/core/auth-storage.d.ts.map +1 -1
  380. package/dist/core/auth-storage.js +151 -92
  381. package/dist/core/auth-storage.js.map +1 -1
  382. package/dist/core/callback-activity.d.ts +27 -0
  383. package/dist/core/callback-activity.d.ts.map +1 -0
  384. package/dist/core/callback-activity.js +44 -0
  385. package/dist/core/callback-activity.js.map +1 -0
  386. package/dist/core/compaction/branch-summarization.d.ts +4 -1
  387. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  388. package/dist/core/compaction/branch-summarization.js +4 -3
  389. package/dist/core/compaction/branch-summarization.js.map +1 -1
  390. package/dist/core/compaction/compaction-boundary.d.ts +1 -1
  391. package/dist/core/compaction/compaction-boundary.d.ts.map +1 -1
  392. package/dist/core/compaction/compaction-boundary.js +10 -23
  393. package/dist/core/compaction/compaction-boundary.js.map +1 -1
  394. package/dist/core/compaction/compaction-runner.d.ts +4 -1
  395. package/dist/core/compaction/compaction-runner.d.ts.map +1 -1
  396. package/dist/core/compaction/compaction-runner.js +1 -1
  397. package/dist/core/compaction/compaction-runner.js.map +1 -1
  398. package/dist/core/compaction/compaction-types.d.ts +3 -2
  399. package/dist/core/compaction/compaction-types.d.ts.map +1 -1
  400. package/dist/core/compaction/compaction-types.js.map +1 -1
  401. package/dist/core/compaction/compaction.d.ts +6 -6
  402. package/dist/core/compaction/compaction.d.ts.map +1 -1
  403. package/dist/core/compaction/compaction.js +12 -9
  404. package/dist/core/compaction/compaction.js.map +1 -1
  405. package/dist/core/compaction/index.d.ts +1 -0
  406. package/dist/core/compaction/index.d.ts.map +1 -1
  407. package/dist/core/compaction/index.js +1 -0
  408. package/dist/core/compaction/index.js.map +1 -1
  409. package/dist/core/compaction/range-planner-diagnostics.d.ts +101 -0
  410. package/dist/core/compaction/range-planner-diagnostics.d.ts.map +1 -0
  411. package/dist/core/compaction/range-planner-diagnostics.js +116 -0
  412. package/dist/core/compaction/range-planner-diagnostics.js.map +1 -0
  413. package/dist/core/compaction/range-planner.d.ts +13 -3
  414. package/dist/core/compaction/range-planner.d.ts.map +1 -1
  415. package/dist/core/compaction/range-planner.js +117 -68
  416. package/dist/core/compaction/range-planner.js.map +1 -1
  417. package/dist/core/compaction/truncated-range-recovery.d.ts +47 -0
  418. package/dist/core/compaction/truncated-range-recovery.d.ts.map +1 -0
  419. package/dist/core/compaction/truncated-range-recovery.js +112 -0
  420. package/dist/core/compaction/truncated-range-recovery.js.map +1 -0
  421. package/dist/core/extensions/api-types.d.ts +2 -2
  422. package/dist/core/extensions/api-types.d.ts.map +1 -1
  423. package/dist/core/extensions/api-types.js.map +1 -1
  424. package/dist/core/extensions/context-types.d.ts +23 -1
  425. package/dist/core/extensions/context-types.d.ts.map +1 -1
  426. package/dist/core/extensions/context-types.js.map +1 -1
  427. package/dist/core/extensions/index.d.ts +1 -1
  428. package/dist/core/extensions/index.d.ts.map +1 -1
  429. package/dist/core/extensions/index.js.map +1 -1
  430. package/dist/core/extensions/loader-api.js +2 -2
  431. package/dist/core/extensions/loader-api.js.map +1 -1
  432. package/dist/core/extensions/loader-core.d.ts.map +1 -1
  433. package/dist/core/extensions/loader-core.js +8 -1
  434. package/dist/core/extensions/loader-core.js.map +1 -1
  435. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  436. package/dist/core/extensions/loader-virtual-modules.js +9 -6
  437. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  438. package/dist/core/extensions/message-types.d.ts +17 -0
  439. package/dist/core/extensions/message-types.d.ts.map +1 -1
  440. package/dist/core/extensions/message-types.js.map +1 -1
  441. package/dist/core/extensions/provider-types.d.ts +3 -0
  442. package/dist/core/extensions/provider-types.d.ts.map +1 -1
  443. package/dist/core/extensions/provider-types.js.map +1 -1
  444. package/dist/core/extensions/runner-events.d.ts.map +1 -1
  445. package/dist/core/extensions/runner-events.js +11 -10
  446. package/dist/core/extensions/runner-events.js.map +1 -1
  447. package/dist/core/extensions/runtime-types.d.ts +2 -2
  448. package/dist/core/extensions/runtime-types.d.ts.map +1 -1
  449. package/dist/core/extensions/runtime-types.js.map +1 -1
  450. package/dist/core/extensions/ui-types.d.ts +78 -0
  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/model-registry-auth.d.ts +2 -1
  454. package/dist/core/model-registry-auth.d.ts.map +1 -1
  455. package/dist/core/model-registry-auth.js +25 -6
  456. package/dist/core/model-registry-auth.js.map +1 -1
  457. package/dist/core/model-registry-builtins.d.ts +3 -2
  458. package/dist/core/model-registry-builtins.d.ts.map +1 -1
  459. package/dist/core/model-registry-builtins.js +12 -6
  460. package/dist/core/model-registry-builtins.js.map +1 -1
  461. package/dist/core/model-registry-dynamic.d.ts +1 -0
  462. package/dist/core/model-registry-dynamic.d.ts.map +1 -1
  463. package/dist/core/model-registry-dynamic.js +53 -13
  464. package/dist/core/model-registry-dynamic.js.map +1 -1
  465. package/dist/core/model-registry-loader.d.ts +2 -1
  466. package/dist/core/model-registry-loader.d.ts.map +1 -1
  467. package/dist/core/model-registry-loader.js +2 -2
  468. package/dist/core/model-registry-loader.js.map +1 -1
  469. package/dist/core/model-registry-types.d.ts +10 -3
  470. package/dist/core/model-registry-types.d.ts.map +1 -1
  471. package/dist/core/model-registry-types.js.map +1 -1
  472. package/dist/core/model-registry.d.ts +15 -1
  473. package/dist/core/model-registry.d.ts.map +1 -1
  474. package/dist/core/model-registry.js +214 -30
  475. package/dist/core/model-registry.js.map +1 -1
  476. package/dist/core/models-store.d.ts +25 -0
  477. package/dist/core/models-store.d.ts.map +1 -0
  478. package/dist/core/models-store.js +73 -0
  479. package/dist/core/models-store.js.map +1 -0
  480. package/dist/core/oauth-compat.d.ts +17 -0
  481. package/dist/core/oauth-compat.d.ts.map +1 -0
  482. package/dist/core/oauth-compat.js +2 -0
  483. package/dist/core/oauth-compat.js.map +1 -0
  484. package/dist/core/oauth-provider-bridge.d.ts +40 -0
  485. package/dist/core/oauth-provider-bridge.d.ts.map +1 -0
  486. package/dist/core/oauth-provider-bridge.js +169 -0
  487. package/dist/core/oauth-provider-bridge.js.map +1 -0
  488. package/dist/core/output-guard.d.ts +2 -0
  489. package/dist/core/output-guard.d.ts.map +1 -1
  490. package/dist/core/output-guard.js +14 -0
  491. package/dist/core/output-guard.js.map +1 -1
  492. package/dist/core/remote-catalog-provider.d.ts +5 -0
  493. package/dist/core/remote-catalog-provider.d.ts.map +1 -0
  494. package/dist/core/remote-catalog-provider.js +138 -0
  495. package/dist/core/remote-catalog-provider.js.map +1 -0
  496. package/dist/core/sdk.d.ts.map +1 -1
  497. package/dist/core/sdk.js +8 -3
  498. package/dist/core/sdk.js.map +1 -1
  499. package/dist/core/session-manager-core.d.ts +1 -1
  500. package/dist/core/session-manager-core.d.ts.map +1 -1
  501. package/dist/core/session-manager-core.js +1 -1
  502. package/dist/core/session-manager-core.js.map +1 -1
  503. package/dist/core/session-manager-entries.d.ts +1 -1
  504. package/dist/core/session-manager-entries.d.ts.map +1 -1
  505. package/dist/core/session-manager-entries.js.map +1 -1
  506. package/dist/core/session-manager-history.d.ts +2 -2
  507. package/dist/core/session-manager-history.js +2 -2
  508. package/dist/core/session-manager-history.js.map +1 -1
  509. package/dist/core/session-manager-list.d.ts.map +1 -1
  510. package/dist/core/session-manager-list.js +65 -23
  511. package/dist/core/session-manager-list.js.map +1 -1
  512. package/dist/core/session-manager-types.d.ts +3 -2
  513. package/dist/core/session-manager-types.d.ts.map +1 -1
  514. package/dist/core/session-manager-types.js.map +1 -1
  515. package/dist/core/slash-commands.d.ts.map +1 -1
  516. package/dist/core/slash-commands.js +9 -5
  517. package/dist/core/slash-commands.js.map +1 -1
  518. package/dist/core/tools/bash.d.ts.map +1 -1
  519. package/dist/core/tools/bash.js +2 -3
  520. package/dist/core/tools/bash.js.map +1 -1
  521. package/dist/core/tools/find.js +2 -2
  522. package/dist/core/tools/find.js.map +1 -1
  523. package/dist/core/tools/grep.js +2 -2
  524. package/dist/core/tools/grep.js.map +1 -1
  525. package/dist/core/tools/ls.js +2 -2
  526. package/dist/core/tools/ls.js.map +1 -1
  527. package/dist/core/tools/read.d.ts.map +1 -1
  528. package/dist/core/tools/read.js +4 -3
  529. package/dist/core/tools/read.js.map +1 -1
  530. package/dist/core/tools/todos-render.d.ts.map +1 -1
  531. package/dist/core/tools/todos-render.js +3 -2
  532. package/dist/core/tools/todos-render.js.map +1 -1
  533. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  534. package/dist/core/tools/tool-definition-wrapper.js +3 -2
  535. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  536. package/dist/core/tools/write.js +2 -2
  537. package/dist/core/tools/write.js.map +1 -1
  538. package/dist/core/workflow-stage-admission.d.ts +29 -0
  539. package/dist/core/workflow-stage-admission.d.ts.map +1 -0
  540. package/dist/core/workflow-stage-admission.js +81 -0
  541. package/dist/core/workflow-stage-admission.js.map +1 -0
  542. package/dist/index-extensions.d.ts +1 -1
  543. package/dist/index-extensions.d.ts.map +1 -1
  544. package/dist/index-extensions.js.map +1 -1
  545. package/dist/index.d.ts +4 -1
  546. package/dist/index.d.ts.map +1 -1
  547. package/dist/index.js +4 -1
  548. package/dist/index.js.map +1 -1
  549. package/dist/main-types.d.ts +13 -0
  550. package/dist/main-types.d.ts.map +1 -0
  551. package/dist/main-types.js +2 -0
  552. package/dist/main-types.js.map +1 -0
  553. package/dist/main.d.ts +2 -5
  554. package/dist/main.d.ts.map +1 -1
  555. package/dist/main.js +25 -17
  556. package/dist/main.js.map +1 -1
  557. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  558. package/dist/modes/interactive/components/assistant-message.js +17 -12
  559. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  560. package/dist/modes/interactive/components/atomic-banner.d.ts +7 -0
  561. package/dist/modes/interactive/components/atomic-banner.d.ts.map +1 -1
  562. package/dist/modes/interactive/components/atomic-banner.js +20 -0
  563. package/dist/modes/interactive/components/atomic-banner.js.map +1 -1
  564. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  565. package/dist/modes/interactive/components/bash-execution.js +5 -3
  566. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  567. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  568. package/dist/modes/interactive/components/branch-summary-message.js +3 -4
  569. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  570. package/dist/modes/interactive/components/chat-message-renderer.d.ts +4 -0
  571. package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
  572. package/dist/modes/interactive/components/chat-message-renderer.js +4 -0
  573. package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
  574. package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
  575. package/dist/modes/interactive/components/chat-session-host-events.js +79 -8
  576. package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
  577. package/dist/modes/interactive/components/chat-session-host-rendering.d.ts.map +1 -1
  578. package/dist/modes/interactive/components/chat-session-host-rendering.js +4 -2
  579. package/dist/modes/interactive/components/chat-session-host-rendering.js.map +1 -1
  580. package/dist/modes/interactive/components/chat-session-host.d.ts +1 -0
  581. package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
  582. package/dist/modes/interactive/components/chat-session-host.js +4 -1
  583. package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
  584. package/dist/modes/interactive/components/compaction-boundary-message.d.ts.map +1 -1
  585. package/dist/modes/interactive/components/compaction-boundary-message.js +3 -4
  586. package/dist/modes/interactive/components/compaction-boundary-message.js.map +1 -1
  587. package/dist/modes/interactive/components/host-input-form-mount.d.ts +14 -0
  588. package/dist/modes/interactive/components/host-input-form-mount.d.ts.map +1 -0
  589. package/dist/modes/interactive/components/host-input-form-mount.js +79 -0
  590. package/dist/modes/interactive/components/host-input-form-mount.js.map +1 -0
  591. package/dist/modes/interactive/components/host-input-form.d.ts +52 -0
  592. package/dist/modes/interactive/components/host-input-form.d.ts.map +1 -0
  593. package/dist/modes/interactive/components/host-input-form.js +278 -0
  594. package/dist/modes/interactive/components/host-input-form.js.map +1 -0
  595. package/dist/modes/interactive/components/host-session-picker.d.ts +46 -0
  596. package/dist/modes/interactive/components/host-session-picker.d.ts.map +1 -0
  597. package/dist/modes/interactive/components/host-session-picker.js +183 -0
  598. package/dist/modes/interactive/components/host-session-picker.js.map +1 -0
  599. package/dist/modes/interactive/components/index.d.ts +1 -1
  600. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  601. package/dist/modes/interactive/components/index.js +1 -1
  602. package/dist/modes/interactive/components/index.js.map +1 -1
  603. package/dist/modes/interactive/components/keybinding-hints.d.ts +2 -0
  604. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  605. package/dist/modes/interactive/components/keybinding-hints.js +12 -0
  606. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  607. package/dist/modes/interactive/components/login-dialog.d.ts +3 -1
  608. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  609. package/dist/modes/interactive/components/login-dialog.js +8 -2
  610. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  611. package/dist/modes/interactive/components/model-selector.d.ts +7 -1
  612. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  613. package/dist/modes/interactive/components/model-selector.js +57 -10
  614. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  615. package/dist/modes/interactive/components/session-selector.d.ts +15 -0
  616. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  617. package/dist/modes/interactive/components/session-selector.js +35 -3
  618. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  619. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  620. package/dist/modes/interactive/components/skill-invocation-message.js +3 -2
  621. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  622. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  623. package/dist/modes/interactive/components/tool-execution.js +9 -0
  624. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  625. package/dist/modes/interactive/interactive-agent-events.js +24 -10
  626. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  627. package/dist/modes/interactive/interactive-auth-login.js +7 -1
  628. package/dist/modes/interactive/interactive-auth-login.js.map +1 -1
  629. package/dist/modes/interactive/interactive-auth-routing.js +3 -3
  630. package/dist/modes/interactive/interactive-auth-routing.js.map +1 -1
  631. package/dist/modes/interactive/interactive-autocomplete.js +49 -0
  632. package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  633. package/dist/modes/interactive/interactive-bash-compact.js +2 -0
  634. package/dist/modes/interactive/interactive-bash-compact.js.map +1 -1
  635. package/dist/modes/interactive/interactive-extension-context.js +14 -0
  636. package/dist/modes/interactive/interactive-extension-context.js.map +1 -1
  637. package/dist/modes/interactive/interactive-extension-runtime.js +1 -1
  638. package/dist/modes/interactive/interactive-extension-runtime.js.map +1 -1
  639. package/dist/modes/interactive/interactive-global-clear.d.ts +13 -0
  640. package/dist/modes/interactive/interactive-global-clear.d.ts.map +1 -0
  641. package/dist/modes/interactive/interactive-global-clear.js +11 -0
  642. package/dist/modes/interactive/interactive-global-clear.js.map +1 -0
  643. package/dist/modes/interactive/interactive-input-handling.js +17 -10
  644. package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
  645. package/dist/modes/interactive/interactive-mode-base.d.ts +6 -1
  646. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  647. package/dist/modes/interactive/interactive-mode-base.js +25 -2
  648. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  649. package/dist/modes/interactive/interactive-mode-deps.d.ts +4 -3
  650. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  651. package/dist/modes/interactive/interactive-mode-deps.js +2 -2
  652. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  653. package/dist/modes/interactive/interactive-mode-helpers.d.ts +4 -1
  654. package/dist/modes/interactive/interactive-mode-helpers.d.ts.map +1 -1
  655. package/dist/modes/interactive/interactive-mode-helpers.js +14 -1
  656. package/dist/modes/interactive/interactive-mode-helpers.js.map +1 -1
  657. package/dist/modes/interactive/interactive-mode-surface.d.ts +3 -2
  658. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  659. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  660. package/dist/modes/interactive/interactive-mode-types.d.ts +3 -0
  661. package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
  662. package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
  663. package/dist/modes/interactive/interactive-model-routing.js +7 -4
  664. package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
  665. package/dist/modes/interactive/interactive-queueing.js +2 -2
  666. package/dist/modes/interactive/interactive-queueing.js.map +1 -1
  667. package/dist/modes/interactive/interactive-render-chat.js +25 -4
  668. package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
  669. package/dist/modes/interactive/interactive-session-routing.js +3 -0
  670. package/dist/modes/interactive/interactive-session-routing.js.map +1 -1
  671. package/dist/modes/interactive/interactive-slash-commands.js +5 -2
  672. package/dist/modes/interactive/interactive-slash-commands.js.map +1 -1
  673. package/dist/modes/interactive/interactive-startup.d.ts +1 -1
  674. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  675. package/dist/modes/interactive/interactive-startup.js +22 -9
  676. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  677. package/dist/modes/interactive/interactive-terminal-title.d.ts +6 -0
  678. package/dist/modes/interactive/interactive-terminal-title.d.ts.map +1 -0
  679. package/dist/modes/interactive/interactive-terminal-title.js +7 -0
  680. package/dist/modes/interactive/interactive-terminal-title.js.map +1 -0
  681. package/dist/modes/interactive-engine/activity-watchdog.d.ts +45 -0
  682. package/dist/modes/interactive-engine/activity-watchdog.d.ts.map +1 -0
  683. package/dist/modes/interactive-engine/activity-watchdog.js +74 -0
  684. package/dist/modes/interactive-engine/activity-watchdog.js.map +1 -0
  685. package/dist/modes/interactive-engine/create-isolated-runtime.d.ts +14 -0
  686. package/dist/modes/interactive-engine/create-isolated-runtime.d.ts.map +1 -0
  687. package/dist/modes/interactive-engine/create-isolated-runtime.js +56 -0
  688. package/dist/modes/interactive-engine/create-isolated-runtime.js.map +1 -0
  689. package/dist/modes/interactive-engine/engine-args.d.ts +10 -0
  690. package/dist/modes/interactive-engine/engine-args.d.ts.map +1 -0
  691. package/dist/modes/interactive-engine/engine-args.js +55 -0
  692. package/dist/modes/interactive-engine/engine-args.js.map +1 -0
  693. package/dist/modes/interactive-engine/engine-child-liveness.d.ts +7 -0
  694. package/dist/modes/interactive-engine/engine-child-liveness.d.ts.map +1 -0
  695. package/dist/modes/interactive-engine/engine-child-liveness.js +50 -0
  696. package/dist/modes/interactive-engine/engine-child-liveness.js.map +1 -0
  697. package/dist/modes/interactive-engine/engine-custom-ui.d.ts +47 -0
  698. package/dist/modes/interactive-engine/engine-custom-ui.d.ts.map +1 -0
  699. package/dist/modes/interactive-engine/engine-custom-ui.js +276 -0
  700. package/dist/modes/interactive-engine/engine-custom-ui.js.map +1 -0
  701. package/dist/modes/interactive-engine/engine-input-form.d.ts +13 -0
  702. package/dist/modes/interactive-engine/engine-input-form.d.ts.map +1 -0
  703. package/dist/modes/interactive-engine/engine-input-form.js +49 -0
  704. package/dist/modes/interactive-engine/engine-input-form.js.map +1 -0
  705. package/dist/modes/interactive-engine/engine-monitor.d.ts +18 -0
  706. package/dist/modes/interactive-engine/engine-monitor.d.ts.map +1 -0
  707. package/dist/modes/interactive-engine/engine-monitor.js +63 -0
  708. package/dist/modes/interactive-engine/engine-monitor.js.map +1 -0
  709. package/dist/modes/interactive-engine/engine-render-service.d.ts +17 -0
  710. package/dist/modes/interactive-engine/engine-render-service.d.ts.map +1 -0
  711. package/dist/modes/interactive-engine/engine-render-service.js +150 -0
  712. package/dist/modes/interactive-engine/engine-render-service.js.map +1 -0
  713. package/dist/modes/interactive-engine/engine-session-picker.d.ts +22 -0
  714. package/dist/modes/interactive-engine/engine-session-picker.d.ts.map +1 -0
  715. package/dist/modes/interactive-engine/engine-session-picker.js +106 -0
  716. package/dist/modes/interactive-engine/engine-session-picker.js.map +1 -0
  717. package/dist/modes/interactive-engine/extension-ui-bridge.d.ts +23 -0
  718. package/dist/modes/interactive-engine/extension-ui-bridge.d.ts.map +1 -0
  719. package/dist/modes/interactive-engine/extension-ui-bridge.js +126 -0
  720. package/dist/modes/interactive-engine/extension-ui-bridge.js.map +1 -0
  721. package/dist/modes/interactive-engine/input-form-host.d.ts +15 -0
  722. package/dist/modes/interactive-engine/input-form-host.d.ts.map +1 -0
  723. package/dist/modes/interactive-engine/input-form-host.js +44 -0
  724. package/dist/modes/interactive-engine/input-form-host.js.map +1 -0
  725. package/dist/modes/interactive-engine/isolated-runtime.d.ts +75 -0
  726. package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -0
  727. package/dist/modes/interactive-engine/isolated-runtime.js +448 -0
  728. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -0
  729. package/dist/modes/interactive-engine/protocol.d.ts +184 -0
  730. package/dist/modes/interactive-engine/protocol.d.ts.map +1 -0
  731. package/dist/modes/interactive-engine/protocol.js +254 -0
  732. package/dist/modes/interactive-engine/protocol.js.map +1 -0
  733. package/dist/modes/interactive-engine/remote-command-catalog.d.ts +33 -0
  734. package/dist/modes/interactive-engine/remote-command-catalog.d.ts.map +1 -0
  735. package/dist/modes/interactive-engine/remote-command-catalog.js +51 -0
  736. package/dist/modes/interactive-engine/remote-command-catalog.js.map +1 -0
  737. package/dist/modes/interactive-engine/remote-component.d.ts +16 -0
  738. package/dist/modes/interactive-engine/remote-component.d.ts.map +1 -0
  739. package/dist/modes/interactive-engine/remote-component.js +209 -0
  740. package/dist/modes/interactive-engine/remote-component.js.map +1 -0
  741. package/dist/modes/interactive-engine/remote-frame-clamp.d.ts +25 -0
  742. package/dist/modes/interactive-engine/remote-frame-clamp.d.ts.map +1 -0
  743. package/dist/modes/interactive-engine/remote-frame-clamp.js +43 -0
  744. package/dist/modes/interactive-engine/remote-frame-clamp.js.map +1 -0
  745. package/dist/modes/interactive-engine/remote-renderer.d.ts +59 -0
  746. package/dist/modes/interactive-engine/remote-renderer.d.ts.map +1 -0
  747. package/dist/modes/interactive-engine/remote-renderer.js +123 -0
  748. package/dist/modes/interactive-engine/remote-renderer.js.map +1 -0
  749. package/dist/modes/interactive-engine/session-picker-host.d.ts +25 -0
  750. package/dist/modes/interactive-engine/session-picker-host.d.ts.map +1 -0
  751. package/dist/modes/interactive-engine/session-picker-host.js +75 -0
  752. package/dist/modes/interactive-engine/session-picker-host.js.map +1 -0
  753. package/dist/modes/interactive-engine/terminal-mode-controller.d.ts +43 -0
  754. package/dist/modes/interactive-engine/terminal-mode-controller.d.ts.map +1 -0
  755. package/dist/modes/interactive-engine/terminal-mode-controller.js +109 -0
  756. package/dist/modes/interactive-engine/terminal-mode-controller.js.map +1 -0
  757. package/dist/modes/rpc/bounded-writer.d.ts +27 -0
  758. package/dist/modes/rpc/bounded-writer.d.ts.map +1 -0
  759. package/dist/modes/rpc/bounded-writer.js +103 -0
  760. package/dist/modes/rpc/bounded-writer.js.map +1 -0
  761. package/dist/modes/rpc/jsonl.d.ts +15 -12
  762. package/dist/modes/rpc/jsonl.d.ts.map +1 -1
  763. package/dist/modes/rpc/jsonl.js +102 -28
  764. package/dist/modes/rpc/jsonl.js.map +1 -1
  765. package/dist/modes/rpc/rpc-client-api.d.ts +83 -0
  766. package/dist/modes/rpc/rpc-client-api.d.ts.map +1 -0
  767. package/dist/modes/rpc/rpc-client-api.js +64 -0
  768. package/dist/modes/rpc/rpc-client-api.js.map +1 -0
  769. package/dist/modes/rpc/rpc-client-process.d.ts +19 -0
  770. package/dist/modes/rpc/rpc-client-process.d.ts.map +1 -0
  771. package/dist/modes/rpc/rpc-client-process.js +79 -0
  772. package/dist/modes/rpc/rpc-client-process.js.map +1 -0
  773. package/dist/modes/rpc/rpc-client-waits.d.ts +8 -0
  774. package/dist/modes/rpc/rpc-client-waits.d.ts.map +1 -0
  775. package/dist/modes/rpc/rpc-client-waits.js +33 -0
  776. package/dist/modes/rpc/rpc-client-waits.js.map +1 -0
  777. package/dist/modes/rpc/rpc-client.d.ts +48 -124
  778. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  779. package/dist/modes/rpc/rpc-client.js +295 -249
  780. package/dist/modes/rpc/rpc-client.js.map +1 -1
  781. package/dist/modes/rpc/rpc-command-handler.d.ts +5 -1
  782. package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
  783. package/dist/modes/rpc/rpc-command-handler.js +79 -3
  784. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  785. package/dist/modes/rpc/rpc-event-buffer.d.ts +11 -0
  786. package/dist/modes/rpc/rpc-event-buffer.d.ts.map +1 -0
  787. package/dist/modes/rpc/rpc-event-buffer.js +30 -0
  788. package/dist/modes/rpc/rpc-event-buffer.js.map +1 -0
  789. package/dist/modes/rpc/rpc-extension-ui.d.ts +7 -1
  790. package/dist/modes/rpc/rpc-extension-ui.d.ts.map +1 -1
  791. package/dist/modes/rpc/rpc-extension-ui.js +54 -32
  792. package/dist/modes/rpc/rpc-extension-ui.js.map +1 -1
  793. package/dist/modes/rpc/rpc-input-scheduler.d.ts +16 -0
  794. package/dist/modes/rpc/rpc-input-scheduler.d.ts.map +1 -0
  795. package/dist/modes/rpc/rpc-input-scheduler.js +69 -0
  796. package/dist/modes/rpc/rpc-input-scheduler.js.map +1 -0
  797. package/dist/modes/rpc/rpc-input.d.ts +2 -1
  798. package/dist/modes/rpc/rpc-input.d.ts.map +1 -1
  799. package/dist/modes/rpc/rpc-input.js +4 -9
  800. package/dist/modes/rpc/rpc-input.js.map +1 -1
  801. package/dist/modes/rpc/rpc-keybindings-reload.d.ts +27 -0
  802. package/dist/modes/rpc/rpc-keybindings-reload.d.ts.map +1 -0
  803. package/dist/modes/rpc/rpc-keybindings-reload.js +69 -0
  804. package/dist/modes/rpc/rpc-keybindings-reload.js.map +1 -0
  805. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  806. package/dist/modes/rpc/rpc-mode.js +63 -8
  807. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  808. package/dist/modes/rpc/rpc-output-buffer.d.ts +10 -0
  809. package/dist/modes/rpc/rpc-output-buffer.d.ts.map +1 -0
  810. package/dist/modes/rpc/rpc-output-buffer.js +70 -0
  811. package/dist/modes/rpc/rpc-output-buffer.js.map +1 -0
  812. package/dist/modes/rpc/rpc-session-binding.d.ts +16 -1
  813. package/dist/modes/rpc/rpc-session-binding.d.ts.map +1 -1
  814. package/dist/modes/rpc/rpc-session-binding.js +16 -3
  815. package/dist/modes/rpc/rpc-session-binding.js.map +1 -1
  816. package/dist/modes/rpc/rpc-types.d.ts +109 -0
  817. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  818. package/dist/modes/rpc/rpc-types.js.map +1 -1
  819. package/dist/package-manager-cli-parser.d.ts +2 -0
  820. package/dist/package-manager-cli-parser.d.ts.map +1 -1
  821. package/dist/package-manager-cli-parser.js +24 -5
  822. package/dist/package-manager-cli-parser.js.map +1 -1
  823. package/dist/package-manager-cli.d.ts +7 -0
  824. package/dist/package-manager-cli.d.ts.map +1 -1
  825. package/dist/package-manager-cli.js +65 -1
  826. package/dist/package-manager-cli.js.map +1 -1
  827. package/dist/utils/shell.d.ts +1 -0
  828. package/dist/utils/shell.d.ts.map +1 -1
  829. package/dist/utils/shell.js +46 -0
  830. package/dist/utils/shell.js.map +1 -1
  831. package/docs/changelog.mdx +11 -0
  832. package/docs/compaction.md +53 -17
  833. package/docs/custom-provider.md +24 -5
  834. package/docs/development.md +9 -7
  835. package/docs/docs.json +1 -0
  836. package/docs/extensions.md +30 -16
  837. package/docs/intercom.md +489 -0
  838. package/docs/json.md +1 -1
  839. package/docs/keybindings.md +1 -1
  840. package/docs/packages.md +1 -0
  841. package/docs/quickstart.md +11 -5
  842. package/docs/rpc.md +9 -7
  843. package/docs/sdk.md +6 -0
  844. package/docs/session-format.md +7 -6
  845. package/docs/sessions.md +4 -2
  846. package/docs/settings.md +2 -2
  847. package/docs/subagents.md +7 -2
  848. package/docs/tui.md +61 -2
  849. package/docs/usage.md +6 -5
  850. package/docs/workflows.md +2572 -1379
  851. package/examples/extensions/handoff.ts +1 -1
  852. package/examples/extensions/qna.ts +1 -1
  853. package/examples/extensions/summarize.ts +1 -1
  854. package/npm-shrinkwrap.json +225 -76
  855. package/package.json +7 -6
  856. package/dist/builtin/workflows/src/durable/file-backend.ts +0 -439
  857. package/dist/builtin/workflows/src/durable/file-lock.ts +0 -153
  858. package/dist/builtin/workflows/src/durable/file-state.ts +0 -104
  859. package/dist/builtin/workflows/src/extension/runtime-direct.ts +0 -96
  860. package/dist/builtin/workflows/src/extension/workflow-tool-helpers.ts +0 -66
  861. package/dist/builtin/workflows/src/runs/foreground/executor-direct-output.ts +0 -91
  862. package/dist/builtin/workflows/src/runs/foreground/executor-direct.ts +0 -282
  863. package/dist/builtin/workflows/src/shared/resumable-workflow-notices.ts +0 -43
  864. package/dist/builtin/workflows/src/tui/session-confirm.ts +0 -299
@@ -1,6 +1,7 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { delimiter } from "node:path";
3
3
  import { spawn, spawnSync } from "child_process";
4
+ import { Worker } from "node:worker_threads";
4
5
  import { getBinDir } from "../config.js";
5
6
  function isLegacyWslBashPath(path) {
6
7
  const normalized = path.replace(/\//g, "\\").toLowerCase();
@@ -145,6 +146,48 @@ export function sanitizeBinaryOutput(str) {
145
146
  })
146
147
  .join("");
147
148
  }
149
+ let detachedChildGuardian;
150
+ const PARENT_GUARDIAN_SOURCE = String.raw `
151
+ const { parentPort, workerData } = require("node:worker_threads");
152
+ const { spawn } = require("node:child_process");
153
+ const { existsSync } = require("node:fs");
154
+ const tracked = new Set();
155
+ parentPort.on("message", ({ action, pid }) => {
156
+ if (action === "track") tracked.add(pid);
157
+ else tracked.delete(pid);
158
+ });
159
+ function killTree(pid) {
160
+ if (process.platform === "win32") {
161
+ try { spawn("taskkill", ["/F", "/T", "/PID", String(pid)], { stdio: "ignore", detached: true }); } catch {}
162
+ return;
163
+ }
164
+ try { process.kill(-pid, "SIGKILL"); }
165
+ catch { try { process.kill(pid, "SIGKILL"); } catch {} }
166
+ }
167
+ const timer = setInterval(() => {
168
+ let parentAlive = true;
169
+ try { process.kill(workerData.parentPid, 0); } catch { parentAlive = false; }
170
+ if (parentAlive && (!workerData.stopFile || !existsSync(workerData.stopFile))) return;
171
+ for (const pid of tracked) killTree(pid);
172
+ killTree(process.pid);
173
+ }, 50);
174
+ timer.unref?.();
175
+ `;
176
+ export function startParentProcessGuardian(parentPid, stopFile) {
177
+ if (detachedChildGuardian)
178
+ return async () => { };
179
+ const guardian = new Worker(PARENT_GUARDIAN_SOURCE, { eval: true, workerData: { parentPid, stopFile } });
180
+ detachedChildGuardian = guardian;
181
+ for (const pid of trackedDetachedChildPids)
182
+ guardian.postMessage({ action: "track", pid });
183
+ guardian.unref();
184
+ return async () => {
185
+ if (detachedChildGuardian !== guardian)
186
+ return;
187
+ detachedChildGuardian = undefined;
188
+ await guardian.terminate();
189
+ };
190
+ }
148
191
  /**
149
192
  * Detached child processes must be tracked so they can be killed on parent
150
193
  * shutdown signals (SIGHUP/SIGTERM).
@@ -152,13 +195,16 @@ export function sanitizeBinaryOutput(str) {
152
195
  const trackedDetachedChildPids = new Set();
153
196
  export function trackDetachedChildPid(pid) {
154
197
  trackedDetachedChildPids.add(pid);
198
+ detachedChildGuardian?.postMessage({ action: "track", pid });
155
199
  }
156
200
  export function untrackDetachedChildPid(pid) {
157
201
  trackedDetachedChildPids.delete(pid);
202
+ detachedChildGuardian?.postMessage({ action: "untrack", pid });
158
203
  }
159
204
  export function killTrackedDetachedChildren() {
160
205
  for (const pid of trackedDetachedChildPids) {
161
206
  killProcessTree(pid);
207
+ detachedChildGuardian?.postMessage({ action: "untrack", pid });
162
208
  }
163
209
  trackedDetachedChildPids.clear();
164
210
  }
@@ -1 +1 @@
1
- {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/utils/shell.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { delimiter } from \"node:path\";\nimport { spawn, spawnSync } from \"child_process\";\nimport { getBinDir } from \"../config.ts\";\n\nexport interface ShellConfig {\n\tshell: string;\n\targs: string[];\n\tcommandTransport?: \"argv\" | \"stdin\";\n}\n\nfunction isLegacyWslBashPath(path: string): boolean {\n\tconst normalized = path.replace(/\\//g, \"\\\\\").toLowerCase();\n\treturn /^[a-z]:\\\\windows\\\\(?:system32|sysnative)\\\\bash\\.exe$/.test(normalized);\n}\n\nfunction getBashShellConfig(shell: string): ShellConfig {\n\treturn isLegacyWslBashPath(shell) ? { shell, args: [\"-s\"], commandTransport: \"stdin\" } : { shell, args: [\"-c\"] };\n}\n\n/**\n * Find bash executable on PATH (cross-platform)\n */\nfunction findBashOnPath(): string | null {\n\tif (process.platform === \"win32\") {\n\t\t// Windows: Use 'where' and verify file exists (where can return non-existent paths)\n\t\ttry {\n\t\t\tconst result = spawnSync(\"where\", [\"bash.exe\"], { encoding: \"utf-8\", timeout: 5000 });\n\t\t\tif (result.status === 0 && result.stdout) {\n\t\t\t\tconst firstMatch = result.stdout.trim().split(/\\r?\\n/)[0];\n\t\t\t\tif (firstMatch && existsSync(firstMatch)) {\n\t\t\t\t\treturn firstMatch;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore errors\n\t\t}\n\t\treturn null;\n\t}\n\n\t// Unix: Use 'which' and trust its output (handles Termux and special filesystems)\n\ttry {\n\t\tconst result = spawnSync(\"which\", [\"bash\"], { encoding: \"utf-8\", timeout: 5000 });\n\t\tif (result.status === 0 && result.stdout) {\n\t\t\tconst firstMatch = result.stdout.trim().split(/\\r?\\n/)[0];\n\t\t\tif (firstMatch) {\n\t\t\t\treturn firstMatch;\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Ignore errors\n\t}\n\treturn null;\n}\n\n/**\n * Resolve shell configuration based on platform and an optional explicit shell path.\n * Resolution order:\n * 1. User-specified shellPath\n * 2. On Windows: Git Bash in known locations, then bash on PATH\n * 3. On Unix: /bin/bash, then bash on PATH, then fallback to sh\n */\nexport function getShellConfig(customShellPath?: string): ShellConfig {\n\t// 1. Check user-specified shell path\n\tif (customShellPath) {\n\t\tif (existsSync(customShellPath)) {\n\t\t\treturn getBashShellConfig(customShellPath);\n\t\t}\n\t\tthrow new Error(`Custom shell path not found: ${customShellPath}`);\n\t}\n\n\tif (process.platform === \"win32\") {\n\t\t// 2. Try Git Bash in known locations\n\t\tconst paths: string[] = [];\n\t\tconst programFiles = process.env.ProgramFiles;\n\t\tif (programFiles) {\n\t\t\tpaths.push(`${programFiles}\\\\Git\\\\bin\\\\bash.exe`);\n\t\t}\n\t\tconst programFilesX86 = process.env[\"ProgramFiles(x86)\"];\n\t\tif (programFilesX86) {\n\t\t\tpaths.push(`${programFilesX86}\\\\Git\\\\bin\\\\bash.exe`);\n\t\t}\n\n\t\tfor (const path of paths) {\n\t\t\tif (existsSync(path)) {\n\t\t\t\treturn getBashShellConfig(path);\n\t\t\t}\n\t\t}\n\n\t\t// 3. Fallback: search bash.exe on PATH (Cygwin, MSYS2, WSL, etc.)\n\t\tconst bashOnPath = findBashOnPath();\n\t\tif (bashOnPath) {\n\t\t\treturn getBashShellConfig(bashOnPath);\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`No bash shell found. Options:\\n` +\n\t\t\t\t` 1. Install Git for Windows: https://git-scm.com/download/win\\n` +\n\t\t\t\t` 2. Add your bash to PATH (Cygwin, MSYS2, etc.)\\n` +\n\t\t\t\t\" 3. Set shellPath in settings.json\\n\\n\" +\n\t\t\t\t`Searched Git Bash in:\\n${paths.map((p) => ` ${p}`).join(\"\\n\")}`,\n\t\t);\n\t}\n\n\t// Unix: try /bin/bash, then bash on PATH, then fallback to sh\n\tif (existsSync(\"/bin/bash\")) {\n\t\treturn getBashShellConfig(\"/bin/bash\");\n\t}\n\n\tconst bashOnPath = findBashOnPath();\n\tif (bashOnPath) {\n\t\treturn getBashShellConfig(bashOnPath);\n\t}\n\n\treturn { shell: \"sh\", args: [\"-c\"] };\n}\n\nexport function getShellEnv(): NodeJS.ProcessEnv {\n\tconst binDir = getBinDir();\n\tconst pathKey = Object.keys(process.env).find((key) => key.toLowerCase() === \"path\") ?? \"PATH\";\n\tconst currentPath = process.env[pathKey] ?? \"\";\n\tconst pathEntries = currentPath.split(delimiter).filter(Boolean);\n\tconst hasBinDir = pathEntries.includes(binDir);\n\tconst updatedPath = hasBinDir ? currentPath : [binDir, currentPath].filter(Boolean).join(delimiter);\n\n\treturn {\n\t\t...process.env,\n\t\t[pathKey]: updatedPath,\n\t};\n}\n\n/**\n * Sanitize binary output for display/storage.\n * Removes characters that crash string-width or cause display issues:\n * - Control characters (except tab, newline, carriage return)\n * - Lone surrogates\n * - Unicode Format characters (crash string-width due to a bug)\n * - Characters with undefined code points\n */\nexport function sanitizeBinaryOutput(str: string): string {\n\t// Use Array.from to properly iterate over code points (not code units)\n\t// This handles surrogate pairs correctly and catches edge cases where\n\t// codePointAt() might return undefined\n\treturn Array.from(str)\n\t\t.filter((char) => {\n\t\t\t// Filter out characters that cause string-width to crash\n\t\t\t// This includes:\n\t\t\t// - Unicode format characters\n\t\t\t// - Lone surrogates (already filtered by Array.from)\n\t\t\t// - Control chars except \\t \\n \\r\n\t\t\t// - Characters with undefined code points\n\n\t\t\tconst code = char.codePointAt(0);\n\n\t\t\t// Skip if code point is undefined (edge case with invalid strings)\n\t\t\tif (code === undefined) return false;\n\n\t\t\t// Allow tab, newline, carriage return\n\t\t\tif (code === 0x09 || code === 0x0a || code === 0x0d) return true;\n\n\t\t\t// Filter out control characters (0x00-0x1F, except 0x09, 0x0a, 0x0x0d)\n\t\t\tif (code <= 0x1f) return false;\n\n\t\t\t// Filter out Unicode format characters\n\t\t\tif (code >= 0xfff9 && code <= 0xfffb) return false;\n\n\t\t\treturn true;\n\t\t})\n\t\t.join(\"\");\n}\n\n/**\n * Detached child processes must be tracked so they can be killed on parent\n * shutdown signals (SIGHUP/SIGTERM).\n */\nconst trackedDetachedChildPids = new Set<number>();\n\nexport function trackDetachedChildPid(pid: number): void {\n\ttrackedDetachedChildPids.add(pid);\n}\n\nexport function untrackDetachedChildPid(pid: number): void {\n\ttrackedDetachedChildPids.delete(pid);\n}\n\nexport function killTrackedDetachedChildren(): void {\n\tfor (const pid of trackedDetachedChildPids) {\n\t\tkillProcessTree(pid);\n\t}\n\ttrackedDetachedChildPids.clear();\n}\n\n/**\n * Kill a process and all its children (cross-platform)\n */\nexport function killProcessTree(pid: number): void {\n\tif (process.platform === \"win32\") {\n\t\t// Use taskkill on Windows to kill process tree\n\t\ttry {\n\t\t\tspawn(\"taskkill\", [\"/F\", \"/T\", \"/PID\", String(pid)], {\n\t\t\t\tstdio: \"ignore\",\n\t\t\t\tdetached: true,\n\t\t\t});\n\t\t} catch {\n\t\t\t// Ignore errors if taskkill fails\n\t\t}\n\t} else {\n\t\t// Use SIGKILL on Unix/Linux/Mac\n\t\ttry {\n\t\t\tprocess.kill(-pid, \"SIGKILL\");\n\t\t} catch {\n\t\t\t// Fallback to killing just the child if process group kill fails\n\t\t\ttry {\n\t\t\t\tprocess.kill(pid, \"SIGKILL\");\n\t\t\t} catch {\n\t\t\t\t// Process already dead\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/utils/shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAQzC,SAAS,mBAAmB,CAAC,IAAY;IACxC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3D,OAAO,sDAAsD,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa;IACxC,OAAO,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;AAClH,CAAC;AAED;;GAEG;AACH,SAAS,cAAc;IACtB,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAClC,oFAAoF;QACpF,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACtF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAC1C,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC1D,IAAI,UAAU,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC1C,OAAO,UAAU,CAAC;gBACnB,CAAC;YACF,CAAC;QACF,CAAC;QAAC,MAAM,CAAC;YACR,gBAAgB;QACjB,CAAC;QACD,OAAO,IAAI,CAAC;IACb,CAAC;IAED,kFAAkF;IAClF,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAClF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1D,IAAI,UAAU,EAAE,CAAC;gBAChB,OAAO,UAAU,CAAC;YACnB,CAAC;QACF,CAAC;IACF,CAAC;IAAC,MAAM,CAAC;QACR,gBAAgB;IACjB,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,eAAwB;IACtD,qCAAqC;IACrC,IAAI,eAAe,EAAE,CAAC;QACrB,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YACjC,OAAO,kBAAkB,CAAC,eAAe,CAAC,CAAC;QAC5C,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,gCAAgC,eAAe,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAClC,qCAAqC;QACrC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QAC9C,IAAI,YAAY,EAAE,CAAC;YAClB,KAAK,CAAC,IAAI,CAAC,GAAG,YAAY,sBAAsB,CAAC,CAAC;QACnD,CAAC;QACD,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACzD,IAAI,eAAe,EAAE,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,GAAG,eAAe,sBAAsB,CAAC,CAAC;QACtD,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtB,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC;YACjC,CAAC;QACF,CAAC;QAED,kEAAkE;QAClE,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC;QACpC,IAAI,UAAU,EAAE,CAAC;YAChB,OAAO,kBAAkB,CAAC,UAAU,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,IAAI,KAAK,CACd,iCAAiC;YAChC,kEAAkE;YAClE,oDAAoD;YACpD,yCAAyC;YACzC,0BAA0B,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAClE,CAAC;IACH,CAAC;IAED,8DAA8D;IAC9D,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,OAAO,kBAAkB,CAAC,WAAW,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC;IACpC,IAAI,UAAU,EAAE,CAAC;QAChB,OAAO,kBAAkB,CAAC,UAAU,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,WAAW;IAC1B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC;IAC/F,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAC/C,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACjE,MAAM,SAAS,GAAG,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEpG,OAAO;QACN,GAAG,OAAO,CAAC,GAAG;QACd,CAAC,OAAO,CAAC,EAAE,WAAW;KACtB,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC/C,uEAAuE;IACvE,sEAAsE;IACtE,uCAAuC;IACvC,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;SACpB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QAChB,yDAAyD;QACzD,iBAAiB;QACjB,8BAA8B;QAC9B,qDAAqD;QACrD,kCAAkC;QAClC,0CAA0C;QAE1C,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAEjC,mEAAmE;QACnE,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAErC,sCAAsC;QACtC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAEjE,uEAAuE;QACvE,IAAI,IAAI,IAAI,IAAI;YAAE,OAAO,KAAK,CAAC;QAE/B,uCAAuC;QACvC,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM;YAAE,OAAO,KAAK,CAAC;QAEnD,OAAO,IAAI,CAAC;IACb,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;AACZ,CAAC;AAQD,IAAI,qBAAwD,CAAC;AAE7D,MAAM,sBAAsB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;CAyBxC,CAAC;AAEF,MAAM,UAAU,0BAA0B,CAAC,SAAiB,EAAE,QAAiB;IAC9E,IAAI,qBAAqB;QAAE,OAAO,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,sBAAsB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;IACzG,qBAAqB,GAAG,QAAQ,CAAC;IACjC,KAAK,MAAM,GAAG,IAAI,wBAAwB;QAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;IAC3F,QAAQ,CAAC,KAAK,EAAE,CAAC;IACjB,OAAO,KAAK,IAAI,EAAE;QACjB,IAAI,qBAAqB,KAAK,QAAQ;YAAE,OAAO;QAC/C,qBAAqB,GAAG,SAAS,CAAC;QAClC,MAAM,QAAQ,CAAC,SAAS,EAAE,CAAC;IAC5B,CAAC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,wBAAwB,GAAG,IAAI,GAAG,EAAU,CAAC;AAEnD,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAChD,wBAAwB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClC,qBAAqB,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,GAAW;IAClD,wBAAwB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrC,qBAAqB,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,2BAA2B;IAC1C,KAAK,MAAM,GAAG,IAAI,wBAAwB,EAAE,CAAC;QAC5C,eAAe,CAAC,GAAG,CAAC,CAAC;QACrB,qBAAqB,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,wBAAwB,CAAC,KAAK,EAAE,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW;IAC1C,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAClC,+CAA+C;QAC/C,IAAI,CAAC;YACJ,KAAK,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE;gBACpD,KAAK,EAAE,QAAQ;gBACf,QAAQ,EAAE,IAAI;aACd,CAAC,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACR,kCAAkC;QACnC,CAAC;IACF,CAAC;SAAM,CAAC;QACP,gCAAgC;QAChC,IAAI,CAAC;YACJ,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACR,iEAAiE;YACjE,IAAI,CAAC;gBACJ,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAC9B,CAAC;YAAC,MAAM,CAAC;gBACR,uBAAuB;YACxB,CAAC;QACF,CAAC;IACF,CAAC;AACF,CAAC","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { delimiter } from \"node:path\";\nimport { spawn, spawnSync } from \"child_process\";\nimport { Worker } from \"node:worker_threads\";\nimport { getBinDir } from \"../config.ts\";\n\nexport interface ShellConfig {\n\tshell: string;\n\targs: string[];\n\tcommandTransport?: \"argv\" | \"stdin\";\n}\n\nfunction isLegacyWslBashPath(path: string): boolean {\n\tconst normalized = path.replace(/\\//g, \"\\\\\").toLowerCase();\n\treturn /^[a-z]:\\\\windows\\\\(?:system32|sysnative)\\\\bash\\.exe$/.test(normalized);\n}\n\nfunction getBashShellConfig(shell: string): ShellConfig {\n\treturn isLegacyWslBashPath(shell) ? { shell, args: [\"-s\"], commandTransport: \"stdin\" } : { shell, args: [\"-c\"] };\n}\n\n/**\n * Find bash executable on PATH (cross-platform)\n */\nfunction findBashOnPath(): string | null {\n\tif (process.platform === \"win32\") {\n\t\t// Windows: Use 'where' and verify file exists (where can return non-existent paths)\n\t\ttry {\n\t\t\tconst result = spawnSync(\"where\", [\"bash.exe\"], { encoding: \"utf-8\", timeout: 5000 });\n\t\t\tif (result.status === 0 && result.stdout) {\n\t\t\t\tconst firstMatch = result.stdout.trim().split(/\\r?\\n/)[0];\n\t\t\t\tif (firstMatch && existsSync(firstMatch)) {\n\t\t\t\t\treturn firstMatch;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore errors\n\t\t}\n\t\treturn null;\n\t}\n\n\t// Unix: Use 'which' and trust its output (handles Termux and special filesystems)\n\ttry {\n\t\tconst result = spawnSync(\"which\", [\"bash\"], { encoding: \"utf-8\", timeout: 5000 });\n\t\tif (result.status === 0 && result.stdout) {\n\t\t\tconst firstMatch = result.stdout.trim().split(/\\r?\\n/)[0];\n\t\t\tif (firstMatch) {\n\t\t\t\treturn firstMatch;\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Ignore errors\n\t}\n\treturn null;\n}\n\n/**\n * Resolve shell configuration based on platform and an optional explicit shell path.\n * Resolution order:\n * 1. User-specified shellPath\n * 2. On Windows: Git Bash in known locations, then bash on PATH\n * 3. On Unix: /bin/bash, then bash on PATH, then fallback to sh\n */\nexport function getShellConfig(customShellPath?: string): ShellConfig {\n\t// 1. Check user-specified shell path\n\tif (customShellPath) {\n\t\tif (existsSync(customShellPath)) {\n\t\t\treturn getBashShellConfig(customShellPath);\n\t\t}\n\t\tthrow new Error(`Custom shell path not found: ${customShellPath}`);\n\t}\n\n\tif (process.platform === \"win32\") {\n\t\t// 2. Try Git Bash in known locations\n\t\tconst paths: string[] = [];\n\t\tconst programFiles = process.env.ProgramFiles;\n\t\tif (programFiles) {\n\t\t\tpaths.push(`${programFiles}\\\\Git\\\\bin\\\\bash.exe`);\n\t\t}\n\t\tconst programFilesX86 = process.env[\"ProgramFiles(x86)\"];\n\t\tif (programFilesX86) {\n\t\t\tpaths.push(`${programFilesX86}\\\\Git\\\\bin\\\\bash.exe`);\n\t\t}\n\n\t\tfor (const path of paths) {\n\t\t\tif (existsSync(path)) {\n\t\t\t\treturn getBashShellConfig(path);\n\t\t\t}\n\t\t}\n\n\t\t// 3. Fallback: search bash.exe on PATH (Cygwin, MSYS2, WSL, etc.)\n\t\tconst bashOnPath = findBashOnPath();\n\t\tif (bashOnPath) {\n\t\t\treturn getBashShellConfig(bashOnPath);\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`No bash shell found. Options:\\n` +\n\t\t\t\t` 1. Install Git for Windows: https://git-scm.com/download/win\\n` +\n\t\t\t\t` 2. Add your bash to PATH (Cygwin, MSYS2, etc.)\\n` +\n\t\t\t\t\" 3. Set shellPath in settings.json\\n\\n\" +\n\t\t\t\t`Searched Git Bash in:\\n${paths.map((p) => ` ${p}`).join(\"\\n\")}`,\n\t\t);\n\t}\n\n\t// Unix: try /bin/bash, then bash on PATH, then fallback to sh\n\tif (existsSync(\"/bin/bash\")) {\n\t\treturn getBashShellConfig(\"/bin/bash\");\n\t}\n\n\tconst bashOnPath = findBashOnPath();\n\tif (bashOnPath) {\n\t\treturn getBashShellConfig(bashOnPath);\n\t}\n\n\treturn { shell: \"sh\", args: [\"-c\"] };\n}\n\nexport function getShellEnv(): NodeJS.ProcessEnv {\n\tconst binDir = getBinDir();\n\tconst pathKey = Object.keys(process.env).find((key) => key.toLowerCase() === \"path\") ?? \"PATH\";\n\tconst currentPath = process.env[pathKey] ?? \"\";\n\tconst pathEntries = currentPath.split(delimiter).filter(Boolean);\n\tconst hasBinDir = pathEntries.includes(binDir);\n\tconst updatedPath = hasBinDir ? currentPath : [binDir, currentPath].filter(Boolean).join(delimiter);\n\n\treturn {\n\t\t...process.env,\n\t\t[pathKey]: updatedPath,\n\t};\n}\n\n/**\n * Sanitize binary output for display/storage.\n * Removes characters that crash string-width or cause display issues:\n * - Control characters (except tab, newline, carriage return)\n * - Lone surrogates\n * - Unicode Format characters (crash string-width due to a bug)\n * - Characters with undefined code points\n */\nexport function sanitizeBinaryOutput(str: string): string {\n\t// Use Array.from to properly iterate over code points (not code units)\n\t// This handles surrogate pairs correctly and catches edge cases where\n\t// codePointAt() might return undefined\n\treturn Array.from(str)\n\t\t.filter((char) => {\n\t\t\t// Filter out characters that cause string-width to crash\n\t\t\t// This includes:\n\t\t\t// - Unicode format characters\n\t\t\t// - Lone surrogates (already filtered by Array.from)\n\t\t\t// - Control chars except \\t \\n \\r\n\t\t\t// - Characters with undefined code points\n\n\t\t\tconst code = char.codePointAt(0);\n\n\t\t\t// Skip if code point is undefined (edge case with invalid strings)\n\t\t\tif (code === undefined) return false;\n\n\t\t\t// Allow tab, newline, carriage return\n\t\t\tif (code === 0x09 || code === 0x0a || code === 0x0d) return true;\n\n\t\t\t// Filter out control characters (0x00-0x1F, except 0x09, 0x0a, 0x0x0d)\n\t\t\tif (code <= 0x1f) return false;\n\n\t\t\t// Filter out Unicode format characters\n\t\t\tif (code >= 0xfff9 && code <= 0xfffb) return false;\n\n\t\t\treturn true;\n\t\t})\n\t\t.join(\"\");\n}\n\ninterface DetachedChildGuardian {\n\tpostMessage(message: { action: \"track\" | \"untrack\"; pid: number }): void;\n\tterminate(): Promise<number>;\n\tunref(): void;\n}\n\nlet detachedChildGuardian: DetachedChildGuardian | undefined;\n\nconst PARENT_GUARDIAN_SOURCE = String.raw`\nconst { parentPort, workerData } = require(\"node:worker_threads\");\nconst { spawn } = require(\"node:child_process\");\nconst { existsSync } = require(\"node:fs\");\nconst tracked = new Set();\nparentPort.on(\"message\", ({ action, pid }) => {\n if (action === \"track\") tracked.add(pid);\n else tracked.delete(pid);\n});\nfunction killTree(pid) {\n if (process.platform === \"win32\") {\n try { spawn(\"taskkill\", [\"/F\", \"/T\", \"/PID\", String(pid)], { stdio: \"ignore\", detached: true }); } catch {}\n return;\n }\n try { process.kill(-pid, \"SIGKILL\"); }\n catch { try { process.kill(pid, \"SIGKILL\"); } catch {} }\n}\nconst timer = setInterval(() => {\n let parentAlive = true;\n try { process.kill(workerData.parentPid, 0); } catch { parentAlive = false; }\n if (parentAlive && (!workerData.stopFile || !existsSync(workerData.stopFile))) return;\n for (const pid of tracked) killTree(pid);\n killTree(process.pid);\n}, 50);\ntimer.unref?.();\n`;\n\nexport function startParentProcessGuardian(parentPid: number, stopFile?: string): () => Promise<void> {\n\tif (detachedChildGuardian) return async () => {};\n\tconst guardian = new Worker(PARENT_GUARDIAN_SOURCE, { eval: true, workerData: { parentPid, stopFile } });\n\tdetachedChildGuardian = guardian;\n\tfor (const pid of trackedDetachedChildPids) guardian.postMessage({ action: \"track\", pid });\n\tguardian.unref();\n\treturn async () => {\n\t\tif (detachedChildGuardian !== guardian) return;\n\t\tdetachedChildGuardian = undefined;\n\t\tawait guardian.terminate();\n\t};\n}\n\n/**\n * Detached child processes must be tracked so they can be killed on parent\n * shutdown signals (SIGHUP/SIGTERM).\n */\nconst trackedDetachedChildPids = new Set<number>();\n\nexport function trackDetachedChildPid(pid: number): void {\n\ttrackedDetachedChildPids.add(pid);\n\tdetachedChildGuardian?.postMessage({ action: \"track\", pid });\n}\n\nexport function untrackDetachedChildPid(pid: number): void {\n\ttrackedDetachedChildPids.delete(pid);\n\tdetachedChildGuardian?.postMessage({ action: \"untrack\", pid });\n}\n\nexport function killTrackedDetachedChildren(): void {\n\tfor (const pid of trackedDetachedChildPids) {\n\t\tkillProcessTree(pid);\n\t\tdetachedChildGuardian?.postMessage({ action: \"untrack\", pid });\n\t}\n\ttrackedDetachedChildPids.clear();\n}\n\n/**\n * Kill a process and all its children (cross-platform)\n */\nexport function killProcessTree(pid: number): void {\n\tif (process.platform === \"win32\") {\n\t\t// Use taskkill on Windows to kill process tree\n\t\ttry {\n\t\t\tspawn(\"taskkill\", [\"/F\", \"/T\", \"/PID\", String(pid)], {\n\t\t\t\tstdio: \"ignore\",\n\t\t\t\tdetached: true,\n\t\t\t});\n\t\t} catch {\n\t\t\t// Ignore errors if taskkill fails\n\t\t}\n\t} else {\n\t\t// Use SIGKILL on Unix/Linux/Mac\n\t\ttry {\n\t\t\tprocess.kill(-pid, \"SIGKILL\");\n\t\t} catch {\n\t\t\t// Fallback to killing just the child if process group kill fails\n\t\t\ttry {\n\t\t\t\tprocess.kill(pid, \"SIGKILL\");\n\t\t\t} catch {\n\t\t\t\t// Process already dead\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
@@ -3,6 +3,17 @@ title: "Changelog"
3
3
  description: "What's new in Atomic"
4
4
  ---
5
5
 
6
+ <Update label="July 18, 2026">
7
+
8
+ ## Model catalogs and provider authentication
9
+
10
+ - **Dynamic provider catalogs stay current.** The model picker renders its cached snapshot immediately and reports concise success, partial-failure, or timeout status. Run `atomic update --models` to force-refresh authenticated dynamic provider catalogs.
11
+ - **Complete authentication reaches provider requests.** API keys, provider headers, and credential-specific enterprise endpoints are preserved across normal chat and SDK requests.
12
+ - **Interaction reliability improved.** Adjacent thinking blocks render as one section, Windows startup restores Atomic's terminal title after package checks, standalone Bun binaries include every interactive OAuth adapter, and early clone/fork attempts explain that the first assistant response must save the session.
13
+
14
+ See [SDK](/sdk) and [Custom providers](/custom-provider).
15
+
16
+ </Update>
6
17
  <Update label="July 10, 2026">
7
18
 
8
19
  ## Pi 0.80.6 compatibility
@@ -1,6 +1,6 @@
1
1
  # Compaction & Branch Summarization
2
2
 
3
- LLMs have finite context windows. Atomic reduces older context with **verbatim line compaction** while preserving recent logical turns as ordinary messages. Branch summarization is a separate, intentionally lossy feature used only when navigating away from a branch.
3
+ LLMs have finite context windows. Atomic reduces transcript context with **verbatim line compaction** while preserving an exact count of recent context-visible messages as ordinary messages. Branch summarization is a separate, intentionally lossy feature used only when navigating away from a branch.
4
4
 
5
5
  Compaction runs entirely locally with the active session model; no external compaction service is involved. The model only selects which lines to delete — Atomic reconstructs the retained text mechanically, so surviving lines are never rewritten.
6
6
 
@@ -8,7 +8,7 @@ Compaction runs entirely locally with the active session model; no external comp
8
8
 
9
9
  | Mechanism | Trigger | Model output | Durable result |
10
10
  |---|---|---|---|
11
- | Verbatim compaction | `/compact`, RPC `compact`, or automatic threshold/overflow recovery | Compact JSON `{"d":[[start,end],...]}` only | A `CompactionEntry` whose `summary` is mechanically reconstructed transcript text |
11
+ | Verbatim compaction | `/compact`, RPC `compact`, or automatic threshold/overflow recovery | Bare `start,end` deletion records (one per line) | A `CompactionEntry` whose `summary` is mechanically reconstructed transcript text |
12
12
  | Branch summarization | Optional `/tree` navigation | Generated summary prose | A `BranchSummaryEntry` |
13
13
 
14
14
  There is one context-compaction door: `compact`.
@@ -28,13 +28,13 @@ Atomic serializes the compactable part of the conversation into role-tagged line
28
28
  [Assistant]: The off-by-one error is fixed.
29
29
  ```
30
30
 
31
- The planner sees the same text numbered as `N→content` and may return only one-based, inclusive line ranges:
31
+ The planner sees the same text numbered as `N→content` and returns only one-based, inclusive line ranges as bare records:
32
32
 
33
- ```json
34
- {"d":[[2,5]]}
33
+ ```text
34
+ 2,5
35
35
  ```
36
36
 
37
- Prompt version 3 accepts only this compact grammar. Atomic safety-normalizes finite integer endpoints by truncating, swapping reversed pairs, clamping to the transcript, sorting, merging overlap/adjacency, and splitting around explicit protected spans. It then reconstructs from the original input lines. The model never writes, summarizes, reorders, or normalizes retained text. Every retained non-marker line is byte-identical to an input line and remains in input order.
37
+ Each line is `start,end` unsigned decimal integers, one comma, no brackets or prose. Atomic safety-normalizes endpoints by swapping reversed pairs, clamping to the transcript, sorting, merging overlap/adjacency, and splitting around explicit protected spans. It then reconstructs from the original input lines. The model never writes, summarizes, reorders, or normalizes retained text. Every retained non-marker line is byte-identical to an input line and remains in input order.
38
38
 
39
39
  ### Markers and repeated compaction
40
40
 
@@ -44,11 +44,11 @@ Each deleted span is replaced on its own line with exactly:
44
44
  (filtered N lines)
45
45
  ```
46
46
 
47
- The spelling is always plural, including `(filtered 1 lines)`. When a later compaction swallows an earlier marker, Atomic adds the earlier marker's count to the new marker. Adjacent old markers are folded too, so counts remain cumulative across repeated compactions.
47
+ The spelling is always plural, including `(filtered 1 lines)`. When a later compaction swallows an earlier marker, Atomic adds the earlier marker's count to the new marker. Adjacent old markers are folded too, so counts remain cumulative across repeated compactions. On repeated compaction, the planner receives the prior durable verbatim summary plus every currently active ordinary message except the exact protected tail.
48
48
 
49
49
  ### Protected structure
50
50
 
51
- Role-header lines such as `[User]:` and `[Assistant]:` are ordinary ranked lines and may be deleted. Explicit protected spans, including blank lines, are never deleted. The recent logical-turn tail is protected client-side by remaining outside the classifier request entirely.
51
+ Role-header lines such as `[User]:` and `[Assistant]:` are ordinary ranked lines and may be deleted. Explicit protected spans, including blank lines, are never deleted. The configured number of newest context-visible messages remains outside the classifier request entirely; all preceding active transcript content is included.
52
52
 
53
53
  Images in the compactable region become the literal line `[image]`; images in the protected recent tail remain normal image content. Tool-result text remains capped at 16,000 characters before becoming durable compaction text, with an explicit truncation marker for the remainder.
54
54
 
@@ -59,10 +59,10 @@ The effective parameters appear in extension events and successful results:
59
59
  | Parameter | Default | Meaning |
60
60
  |---|---:|---|
61
61
  | `compression_ratio` | `0.5` | Fraction of compactable **lines to keep**, not a token ratio |
62
- | `preserve_recent` | `2` | Number of recent context-visible messages protected client-side; the cut widens backward to a user-turn start |
62
+ | `preserve_recent` | `2` | Exact number of newest context-visible messages protected client-side |
63
63
  | `query` | Last visible user message | Relevance focus for deciding which older lines to retain |
64
64
 
65
- `preserve_recent` never leaves an assistant message or tool result at the start of the kept tail. Even when it is `0`, Atomic keeps the final logical turn. If `query` is absent, Atomic derives it from the last visible user message.
65
+ `preserve_recent` counts context-visible messages without aligning the boundary to a user turn. An assistant message or tool result may therefore begin the kept tail. A value of `0` protects no messages and makes the entire active transcript compactable. If `query` is absent, Atomic derives it from the last visible user message.
66
66
 
67
67
  Configure defaults in `~/.atomic/agent/settings.json` or `.atomic/settings.json`:
68
68
 
@@ -83,18 +83,54 @@ Configure defaults in `~/.atomic/agent/settings.json` or `.atomic/settings.json`
83
83
  ## When compaction runs
84
84
 
85
85
  - **Manual:** `/compact`, `ctx.compact()`, `session.compact()`, or RPC `{ "type": "compact" }`.
86
- - **Threshold:** automatic compaction starts when estimated context usage reaches the effective input budget minus `reserveTokens`.
86
+ - **Threshold:** automatic compaction starts when estimated context usage exceeds the effective input budget minus `reserveTokens`. Atomic checks both completed responses and the prospective next-turn context after tool results have been appended. A post-tool crossing is compacted before the active Pi tool loop sends its follow-up provider request.
87
87
  - **Overflow:** an actual provider context overflow compacts and then retries the interrupted turn.
88
88
 
89
- The in-flight/final logical turn is outside the compactable region. Cancellation and abort behavior remains consistent with normal session operations. Atomic writes a backup snapshot immediately before appending a compaction boundary.
89
+ Exactly the configured recent-message tail is outside the compactable region; Atomic does not force the final logical turn to remain outside it. Pressing Escape while compaction is active cancels it like other session operations. In isolated interactive mode, cancellation and host UI response frames use an independent RPC control lane, so they can reach the engine while the ordinary `compact` request is still pending instead of waiting behind it. Atomic writes a backup snapshot immediately before appending a compaction boundary.
90
+
91
+ The post-tool check stays inside the active Pi loop: it runs at most one ordinary verbatim compaction attempt for that completed tool turn, returns the rebuilt context to the loop, and never calls or schedules `agent.continue()`. Normal context reconstruction preserves provider tool-call/result protocol validity. Below-threshold tool turns follow the unchanged request path. Because the same active run resumes without emitting another `agent_start`, the interactive TUI replaces the compaction loader with its working spinner as soon as successful mid-turn compaction ends; streaming feedback therefore resumes immediately without waiting for another user interaction.
90
92
 
91
93
  ## One-pass planning and failure behavior
92
94
 
93
95
  Atomic asks the active session model, at the active reasoning level and through the normal session stream/provider wrapper, to rank every eligible line in one global pass and apply one threshold. The entire compactable region is sent in exactly one classifier request; it is never split into chunks. Manual, threshold, and overflow compaction all calculate the line target directly from the prepared `compression_ratio`. Explicit protected lines form a hard keep floor.
94
96
 
95
- The request uses the same provider path and failure handling as pi's summary compaction. Provider/API errors, overflow, abort, malformed JSON, or empty/unusable safe ranges fail after that one request. These failures write no compaction entry and schedule no continuation. There is no semantic retry, critical rung, deterministic fallback, or deterministic target correction.
97
+ The request uses the same provider path and failure handling as pi's summary compaction. Provider/API errors, overflow, abort, malformed output, or empty/unusable safe ranges fail after that one request. These failures write no compaction entry and schedule no continuation. During the post-tool preflight, failure or cancellation also stops the active loop before its follow-up provider request, is surfaced through the normal compaction lifecycle, and is not admitted to ordinary provider retry or model fallback. There is no semantic retry, critical rung, deterministic fallback, or deterministic target correction.
98
+
99
+ A syntactically valid usable result is accepted once after safety-only normalization, even when it deletes fewer lines or tokens than requested. Atomic never adds or restores model-selected deletions to force a target. During overflow recovery, the existing one-shot compact-and-retry continuation may therefore surface unresolved overflow naturally. During a post-tool preflight, Atomic likewise does not add a second compaction strategy or attempt; if the rebuilt context is still known to exceed the provider's hard input limit, it refuses to send the follow-up request and reports the limit failure clearly.
100
+
101
+ ### Length-truncated response recovery
102
+
103
+ When the planner model's output is truncated by `max_tokens` (indicated by `stopReason: "length"`), Atomic silently recovers complete newline-terminated deletion records from the truncated response. A deterministic line parser validates each completed line (those followed by a newline) against the strict `start,end` grammar. The final fragment after the last newline is always discarded — even if it looks syntactically complete — because EOF may have cut a multi-digit integer (e.g. `300,30` could have intended `300,305`). If any completed line has invalid syntax or zero usable records survive validation, recovery fails and the normal `RangePlanError` path applies.
104
+
105
+ Example of truncated output:
106
+
107
+ ```text
108
+ 120,180
109
+ 6,40
110
+ 300,
111
+ ```
112
+
113
+ Recovery yields `120,180` and `6,40`; discards `300,` without guessing. The planner prompt instructs the model to emit ranges in descending deletion confidence (lowest continuation value first) so the most important deletions appear earliest and survive truncation.
114
+
115
+ Successful partial recovery is an ordinary successful compaction: no warning, banner, toast, or special status copy appears. The UI shows the normal spinner then `✻ Context compacted`.
116
+
117
+ For operational observability, a private recovery diagnostic sidecar is written beside persisted sessions with `0600` permissions. It records the full raw response, stop reason, usage, request `maxTokens`, model metadata, recovered range count, and recovery category. The sidecar path is never surfaced in the success UI, error messages, or user-visible status. In-memory sessions and sidecar write failures do not affect the successful recovery.
118
+
119
+ ### Planner failure diagnostics
120
+
121
+ For a persisted session, a failed planner call writes a JSON sidecar beside the session JSONL and includes its path in the `RangePlanError`, for example:
122
+
123
+ ```text
124
+ Compaction range planning returned malformed output (diagnostic: /path/session-compaction-diagnostic-….json)
125
+ ```
126
+
127
+ The private sidecar uses `0600` permissions where supported and records the full planner response text, stop reason, provider error, usage, request `maxTokens`, timestamp, failure category, and non-secret model metadata. It does not record API keys, request headers, the planner prompt, or the numbered transcript request. The raw response itself may contain sensitive text if the model echoed input, so treat the sidecar with the same care as its adjacent session file.
128
+
129
+ Diagnostic categories distinguish malformed output, valid output with no usable ranges, provider errors, and stream failures. In-memory sessions do not create sidecars. If the diagnostic write fails, Atomic preserves the original error and classification rather than replacing the planner failure.
130
+
131
+ Interactive main chat and attached workflow stage chat treat `compaction_end` as the authority for cancellation and failure UI. A failed or cancelled `/compact` stops its spinner, shows the event-provided status or diagnostic path without a duplicate stack trace, writes no boundary, and leaves the session usable for another `/compact` attempt or a normal follow-up turn.
96
132
 
97
- A syntactically valid usable result is accepted once after safety-only normalization, even when it deletes fewer lines or tokens than requested. Atomic never adds or restores model-selected deletions to force a target. During overflow recovery, the existing one-shot compact-and-retry continuation may therefore surface unresolved overflow naturally.
133
+ Context thresholds and persisted token-reduction statistics use API-aware normalized usage. OpenAI Responses, Codex Responses, and OpenAI Completions sum uncached input plus cache-read/cache-write partitions. Anthropic Messages alone applies the mirrored-cache guard needed by compatible endpoints that duplicate the same prompt tokens across `input` and cache fields.
98
134
 
99
135
  ## Persistence and resume
100
136
 
@@ -119,9 +155,9 @@ A successful run appends the existing pi-style `type:"compaction"` entry shape:
119
155
  }
120
156
  ```
121
157
 
122
- A `compaction` entry is active only when `details.strategy === "verbatim-lines"`. On rebuild, Atomic emits a visible custom-role boundary message containing the durable `summary`, followed by the original messages beginning at `firstKeptEntryId`. The boundary is converted to a user-role provider message and shown in the TUI as a collapsible compaction card.
158
+ A `compaction` entry is active only when `details.strategy === "verbatim-lines"`. On rebuild, Atomic emits a visible custom-role boundary message containing the durable `summary`, followed by the original messages beginning at `firstKeptEntryId`. When no pre-boundary context-visible message is retained—such as with `preserve_recent: 0`—`firstKeptEntryId` is `null`. Messages appended after the boundary are always replayed. The boundary is converted to a user-role provider message and shown in the TUI as a collapsible compaction card.
123
159
 
124
- Resume does not rerun planning or re-derive deletions: the exact compacted string is already in JSONL. Legacy `context_compaction` logical-deletion records and old `compaction` summary records without the discriminator are inert archival data. Their historical omissions are not reapplied when an old session resumes.
160
+ Resume does not rerun planning or re-derive deletions: the exact compacted string and nullable tail boundary are already in JSONL. Existing records with a string `firstKeptEntryId` keep their original resume behavior. Legacy `context_compaction` logical-deletion records and old `compaction` summary records without the discriminator are inert archival data. Their historical omissions are not reapplied when an old session resumes.
125
161
 
126
162
  ## Extension hooks
127
163
 
@@ -345,7 +381,7 @@ Configure compaction in `~/.atomic/agent/settings.json` or `<project-dir>/.atomi
345
381
  | Setting | Default | Description |
346
382
  |---------|---------|-------------|
347
383
  | `enabled` | `true` | Enable automatic Verbatim Compaction. |
348
- | `reserveTokens` | `16384` | Tokens to reserve for the next LLM response; threshold auto-compaction starts when context usage exceeds the model's effective input budget minus this reserve. |
384
+ | `reserveTokens` | `16384` | Tokens to reserve for the next LLM response; threshold auto-compaction starts when completed-response usage or a prospective post-tool context exceeds the model's effective input budget minus this reserve. |
349
385
 
350
386
  Disable auto-compaction with `"enabled": false`. You can still compact manually with `/compact`.
351
387
 
@@ -231,9 +231,7 @@ models: [{
231
231
  Use `openrouter` for OpenRouter-style `reasoning: { effort }` controls. Use `together` for Together-style `reasoning: { enabled }` controls; with `supportsReasoningEffort`, it also sends `reasoning_effort`. Use `qwen-chat-template` for local Qwen-compatible servers that read `chat_template_kwargs.enable_thinking` and need `preserve_thinking`.
232
232
  Use `cacheControlFormat: "anthropic"` for OpenAI-compatible providers that expose Anthropic-style prompt caching via `cache_control` on the system prompt, last tool definition, and last user/assistant text content.
233
233
 
234
- > Migration note: Mistral moved from `openai-completions` to `mistral-conversations`.
235
- > Use `mistral-conversations` for native Mistral models.
236
- > If you intentionally route Mistral-compatible/custom endpoints through `openai-completions`, set `compat` flags explicitly as needed.
234
+ Use `mistral-conversations` for native Mistral models. If you intentionally route a Mistral-compatible or custom endpoint through `openai-completions`, set the required `compat` flags explicitly.
237
235
 
238
236
  ### Auth Header
239
237
 
@@ -313,6 +311,28 @@ pi.registerProvider("corporate-ai", {
313
311
 
314
312
  After registration, users can authenticate via `/login corporate-ai`.
315
313
 
314
+ Existing extension OAuth definitions keep their `login`, `refreshToken`, `getApiKey`, and optional `modifyModels` methods. OAuth refresh is serialized so concurrent requests do not overwrite each other's credentials.
315
+
316
+ ## Dynamic model catalog refresh
317
+
318
+ Providers whose catalogs change at runtime can add `refreshModels`. Atomic calls it during the asynchronous model refresh used by the model picker and authentication flows:
319
+
320
+ ```typescript
321
+ pi.registerProvider("corporate-ai", {
322
+ baseUrl: "https://ai.corp.com/v1",
323
+ api: "openai-responses",
324
+ apiKey: "$CORPORATE_AI_KEY",
325
+ models: cachedModels,
326
+ async refreshModels({ signal, force, credential, store }) {
327
+ const models = await fetchCorporateModels({ signal, force, credential });
328
+ await store.write({ models, checkedAt: Date.now() });
329
+ return models;
330
+ }
331
+ });
332
+ ```
333
+
334
+ The current catalog stays readable while refresh is pending. Successful provider results are applied independently; a provider that fails, times out, or observes an aborted `signal` retains its previous list. Use the provider-scoped `store` only when the catalog should persist across sessions.
335
+
316
336
  ### OAuthLoginCallbacks
317
337
 
318
338
  The `callbacks` object provides three ways to authenticate:
@@ -346,7 +366,6 @@ interface OAuthCredentials {
346
366
 
347
367
  For providers with non-standard APIs, implement `streamSimple`. Study the existing provider implementations before writing your own:
348
368
 
349
- > **Compatibility note (Pi 0.80.2 sync):** Upstream Pi 0.80.2 made the `@earendil-works/pi-ai` root entrypoint core-only and moved the legacy global provider/model API (`stream`, `complete`, `registerApiProvider`, `getEnvApiKey`, `streamSimple`, and the `Model`/`Api`/`SimpleStreamOptions`/`AssistantMessageEventStream` types shown below) onto the `@earendil-works/pi-ai/compat` entrypoint. Atomic's extension loader aliases the `@earendil-works/pi-ai` root to `/compat` at runtime, so extensions that import these symbols from the root keep working unchanged. For new TypeScript code that needs this legacy surface, prefer importing from `@earendil-works/pi-ai/compat` for accurate type resolution. The `/oauth` subpath is unaffected.
350
369
 
351
370
  **Reference implementations:**
352
371
 
@@ -670,4 +689,4 @@ The `cost` shape is equivalent to `Model<Api>["cost"]`. Base rates and every tie
670
689
  `openrouter` sends `reasoning: { effort }`. `deepseek` sends `thinking: { type: "enabled" | "disabled" }` and `reasoning_effort` when enabled. `together` sends `reasoning: { enabled }` and also `reasoning_effort` when `supportsReasoningEffort` is enabled. `qwen` is for DashScope-style top-level `enable_thinking`. Use `qwen-chat-template` for local Qwen-compatible servers that read `chat_template_kwargs.enable_thinking` and need `preserve_thinking`. Use `chat-template` for configurable `chat_template_kwargs`, for example DeepSeek V3.x behind vLLM with `chatTemplateKwargs: { "thinking": { "$var": "thinking.enabled" } }`.
671
690
  `cacheControlFormat: "anthropic"` applies Anthropic-style `cache_control` markers to the system prompt, last tool definition, and last user/assistant text content.
672
691
 
673
- For `openai-responses` providers, Pi v0.80.7 replaced `compat.sendSessionIdHeader` with `compat.sessionAffinityFormat`. Use `"openai"` for `session_id` plus `x-client-request-id`, `"openai-nosession"` to omit `session_id` while retaining `x-client-request-id`, or `"openrouter"` for `x-session-id`. Responses-compatible providers may also set `supportsToolSearch` when they support deferred tool loading.
692
+ For `openai-responses` providers, set `compat.sessionAffinityFormat` to `"openai"` for `session_id` plus `x-client-request-id`, `"openai-nosession"` to omit `session_id` while retaining `x-client-request-id`, or `"openrouter"` for `x-session-id`. Responses-compatible providers may also set `supportsToolSearch` when they support deferred tool loading.
@@ -16,7 +16,7 @@ This monorepo uses Bun for development commands; avoid npm/yarn/pnpm except for
16
16
 
17
17
  ```bash
18
18
  bun run test:unit
19
- bun --cwd packages/coding-agent run build
19
+ bun run --cwd packages/coding-agent build
20
20
  ```
21
21
 
22
22
  Atomic keeps the caller's current working directory when launched from development wrappers.
@@ -67,21 +67,23 @@ bun run test:unit # Run unit tests
67
67
  bun run test:integration # Run integration tests
68
68
  bun run test:all # Run all tests
69
69
  # Run package Vitest tests
70
- bun --cwd packages/coding-agent run test -- test/specific.test.ts
70
+ bun run --cwd packages/coding-agent test -- test/specific.test.ts
71
71
  ```
72
72
 
73
- The file-length gate scans tracked `.ts`, `.tsx`, `.js`, `.jsx`, `.mjs`, `.cjs`, and `.rs` files via `git ls-files`, falls back to a recursive walk outside Git, and counts physical lines with a no-final-newline correction. Only generated/vendored path globs (`node_modules`, `dist`, `target`, `binaries`, `.git`, `vendor`, minified bundles, and the bundled third-party `packages/workflows/skills/impeccable/**` skill) plus first-five-line generated markers are excluded; there is no grandfather/baseline allowlist for authored files.
73
+ The file-length gate scans tracked `.ts`, `.tsx`, `.js`, `.jsx`, `.mjs`, `.cjs`, and `.rs` files via `git ls-files`, falls back to a recursive walk outside Git, and counts physical lines with a no-final-newline correction. Only generated/vendored path globs (`node_modules`, `dist`, `target`, `binaries`, `.git`, `vendor`, minified bundles, and the bundled third-party `packages/workflows/skills/impeccable/**` skill) plus first-five-line generated markers are excluded.
74
74
 
75
- ## Release shrinkwrap
75
+ ## Deterministic installs
76
76
 
77
- `@bastani/atomic` ships `packages/coding-agent/npm-shrinkwrap.json` for deterministic package-manager installs. Main stays versionless at `0.0.0`; `scripts/cut-release.ts` stamps the real version in an off-main worktree and regenerates the shrinkwrap there before tagging.
78
-
79
- The shrinkwrap generator is hermetic for Atomic-owned packages. It derives `@bastani/atomic-natives` and generated native optional package entries from local package metadata plus deterministic registry tarball URLs, so release publishing does not depend on npm metadata for native packages that were just published.
77
+ `@bastani/atomic` ships `packages/coding-agent/npm-shrinkwrap.json` so package-manager installs resolve the same dependency tree every time. Contributors working from a source checkout can validate that the checked-in shrinkwrap is up to date with:
80
78
 
81
79
  ```bash
82
80
  bun run scripts/generate-coding-agent-shrinkwrap.mjs --check
83
81
  ```
84
82
 
83
+ ## Release security boundary
84
+
85
+ Atomic's release bases remain at the `0.0.0` placeholder. `scripts/cut-release.ts` stamps the real version only on a detached tagged release commit. Tag creation runs an inert signal workflow; a separate `workflow_run` publisher loaded from protected `main` validates the exact upstream repository, source workflow/event/run, tag/SHA, immutable release-base trailers, and deterministic release tree. The privileged trigger checks out only protected workflow code: it treats the tag tree as data, exports it only after deterministic verification, and makes every read-only build verify the protected job's source checksum instead of checking out tag-selected code. Same-run artifact transport failures receive at most one retry after partial-download cleanup and still fail explicitly on the second error; verified source archives are streamed to tar over stdin for portable Windows drive-letter handling. Preparation restores the digest-verified source after documentation validation before producing artifacts. Release-source jobs configure no dependency cache, npm publication has OIDC without repository write, and GitHub Release creation has repository write without OIDC. Never move or recreate a failed release tag or dispatch the privileged publisher. See the repository's [CI/CD pipeline](https://github.com/bastani-inc/atomic/blob/main/docs/ci.md#release-pipeline) for trusted-publisher configuration.
86
+
85
87
  ## Project Structure
86
88
 
87
89
  ```
package/docs/docs.json CHANGED
@@ -32,6 +32,7 @@
32
32
  "extensions",
33
33
  "skills",
34
34
  "subagents",
35
+ "intercom",
35
36
  "workflows",
36
37
  "prompt-templates",
37
38
  "themes",
@@ -31,6 +31,7 @@ See [examples/extensions/](https://github.com/bastani-inc/atomic/tree/main/packa
31
31
  ## Table of Contents
32
32
 
33
33
  - [Startup and lazy discovery](#startup-and-lazy-discovery)
34
+ - [Interactive callback isolation](#interactive-callback-isolation)
34
35
  - [Quick Start](#quick-start)
35
36
  - [Extension Locations](#extension-locations)
36
37
  - [Available Imports](#available-imports)
@@ -55,11 +56,21 @@ See [examples/extensions/](https://github.com/bastani-inc/atomic/tree/main/packa
55
56
 
56
57
  ## Startup and lazy discovery
57
58
 
58
- Atomic keeps the interactive startup path responsive by registering lightweight command/tool wrappers first and deferring noncritical discovery work until after the session is usable. Built-in MCP, workflow, subagent, web-access, and Intercom extensions expose their public commands/tools immediately, but expensive server connections, workflow module evaluation, result-watcher priming, cleanup scans, and browser/provider loading may run in the background or on first explicit use. Commands such as `/workflow list`, named workflow runs/inputs, failed or durable workflow resume, `/mcp`, direct MCP tool calls, `mcp({ search })`, `mcp({ describe })`, `mcp({ server })`, and explicit reload/setup flows still wait for the resources they need before returning results; cold-cache MCP proxy `describe` first narrows hydration to prefix-matched or explicitly requested servers without starting unrelated servers after a prefix-directed miss, cold-cache unscoped MCP proxy `search` intentionally hydrates all uncached lazy servers so it can search the full configured tool set, env-selected MCP direct tools warm only their selected servers and refresh live tool registration when ready, workflow direct `task`/`tasks`/`chain` runs and paused live-run resume/pickers bypass full workflow discovery, autocomplete falls back to current/admin completions when lazy discovery fails, and workflow session restore reads only lightweight config during `session_start` so persisted-run settings apply without evaluating workflow modules.
59
+ Atomic keeps the interactive startup path responsive by registering lightweight command/tool wrappers first and deferring noncritical discovery work until after the session is usable. Built-in MCP, workflow, subagent, web-access, and Intercom extensions expose their public commands/tools immediately, but expensive server connections, workflow module evaluation, result-watcher priming, cleanup scans, and browser/provider loading may run in the background or on first explicit use. Commands such as `/workflow list`, named workflow runs/inputs, failed or durable workflow resume, `/mcp`, direct MCP tool calls, `mcp({ search })`, `mcp({ describe })`, `mcp({ server })`, and explicit reload/setup flows still wait for the resources they need before returning results; cold-cache MCP proxy `describe` first narrows hydration to prefix-matched or explicitly requested servers without starting unrelated servers after a prefix-directed miss, cold-cache unscoped MCP proxy `search` intentionally hydrates all uncached lazy servers so it can search the full configured tool set, env-selected MCP direct tools warm only their selected servers and refresh live tool registration when ready, paused live-workflow resume/pickers bypass full workflow discovery, autocomplete falls back to current/admin completions when lazy discovery fails, and workflow session restore reads only lightweight config during `session_start` so persisted-run settings apply without evaluating workflow modules.
59
60
 
60
61
  Web-access and Intercom first-use calls await one shared lazy initializer plus the latest active lifecycle replay before executing. Failed initializer/replay attempts remain retryable. Session-scoped leases retire candidates synchronously on shutdown, reject calls spanning teardown, and require fresh initialization after restart; shutdown awaits retired replay/initializer cleanup before the extension instance can be replaced, and Intercom serializes replay with live lifecycle forwarding so matching ends and newer model selections cannot be overtaken by stale replay. Aborting one web-access caller during a shared wait does not cancel initialization for other callers, and host abort after provider/curator execution preserves the exact abort reason while explicit curator user cancellation remains result-shaped. Non-empty `web_search`/`fetch_content` batches with no successful items are marked as tool errors with stage diagnostics; partial successes remain successful and retain their completed items.
61
62
 
62
- Bundled MCP startup, proxy calls, direct tools, and readiness-critical commands share a generation-scoped initializer and exact session lease. Failed background attempts remain retryable and single-flight; stale contexts cannot reuse initialized state; commands keep the state they initialized across lazy imports; and direct/proxy operations revalidate ownership after lifecycle-spanning waits and before metadata or SDK side effects. Caller cancellation races readiness, connection, manager-close, and UI-start waits with the exact reason, closes any UI runtime produced after cancellation, and does not cancel shared producers needed by survivors. Session restart/shutdown retires OAuth ownership immediately and uses bounded, observed cleanup so non-abortable SDK work cannot permanently block replacement sessions while late completion remains fenced. SDK-supported resource/tool requests still receive the call signal, though protocol-level remote cancellation is advisory; UI-backed MCP Apps calls preserve terminal cancellation ordering and keep successful result events mutually exclusive.
63
+ Bundled MCP startup, proxy calls, direct tools, and readiness-critical commands share a generation-scoped initializer and exact session lease. Failed background attempts remain retryable and single-flight; stale contexts cannot reuse initialized state; commands keep the state they initialized across lazy imports; and direct/proxy operations revalidate ownership after lifecycle-spanning waits and before metadata or SDK side effects. Caller cancellation races readiness, connection, manager-close, and UI-start waits with the exact reason, closes any UI runtime produced after cancellation, and does not cancel shared producers needed by survivors. Session restart/shutdown retires OAuth ownership immediately and uses bounded, observed cleanup so non-abortable SDK work cannot permanently block replacement sessions while late completion remains fenced. SDK-supported resource/tool requests still receive the call signal, though protocol-level remote cancellation is advisory; UI-backed MCP Apps calls preserve terminal cancellation ordering and keep successful result events mutually exclusive. Per-server `timeoutMs` applies a validated local-or-remote MCP tool-call inactivity limit at every call path while composing with the host abort signal; progress resets that timer, so a continuously reporting tool can run indefinitely, and omitting the field keeps the MCP SDK default.
64
+
65
+ ## Interactive callback isolation
66
+
67
+ Interactive Atomic sessions run the agent engine, extensions, tools, hooks, workflow code, and extension-owned render components in a supervised child process. The terminal host owns stdin and cached rendering, so a synchronous busy loop in one callback cannot stop keyboard handling, spinners, or render scheduling. The engine sends a heartbeat every 50 ms; Atomic identifies the active callback after a 250 ms heartbeat gap and marks the engine unresponsive after one second. Escape requests cooperative cancellation and escalates to terminating the engine when it cannot acknowledge; the interrupted result is reported as unknown and is never retried automatically.
68
+
69
+ Dialogs and `ctx.ui.custom()` components are proxied to the host as rendered lines with asynchronous input forwarding. Custom UI results must be JSON-safe. APIs that require a synchronous callback in the terminal process—raw `onTerminalInput` transforms, synchronous `getEditorText`, custom editor factories, autocomplete wrappers, component-factory widgets, and custom header/footer factories—are unavailable in isolated interactive mode and produce a warning rather than executing extension code in the host. Print and public RPC modes retain their existing execution model.
70
+
71
+ For session-style list pickers use `ctx.ui.hostSessionPicker(request)` instead of remote-rendering a selector through `ctx.ui.custom()`: the terminal host mounts the real built-in session selector natively, fed with JSON-safe rows (`HostSessionPickerRow`: `SessionInfo` with `createdAt`/`modifiedAt` epoch millis). Arrow-key navigation and search never cross the process boundary; only semantic events do — the returned handle exposes `result` (resolves with the selected row's `path`, or `undefined` on cancel), `update(rows)`, `error(message)`, and `close()`, and the request's `onDelete(path)` callback owns deletion (the host keeps the row until the extension replies with `update` or `error`). Every interactive host implements the identical API — in-process (no IPC) when not isolated, over the engine protocol when isolated — so callers never branch; the member is absent only on non-interactive surfaces (headless RPC, print), where commands should fail with an actionable error. See [Host-native session picker](/tui#host-native-session-picker) for an example.
72
+
73
+ For structured forms use `ctx.ui.hostInputForm(request)`. It accepts JSON-safe field descriptors (`string`, `text`, `number`, `integer`, `boolean`, or `select`, each with a raw `initialValue`) and resolves to a raw string record or `undefined` on cancellation. The terminal host owns the component, focus, validation, configured-keybinding handling, and mutable text state, so Tab, arrows, editing, Enter, Escape, and Ctrl+C are host-local rather than asynchronously forwarded to the engine child. Both interactive modes expose the same optional API; headless RPC and print omit it. See [Host-native input form](/tui#host-native-input-form).
63
74
 
64
75
  ## Quick Start
65
76
 
@@ -319,8 +330,9 @@ user sends prompt ────────────────────
319
330
  │ │ ├─► tool_result (can modify) │ │
320
331
  │ │ └─► tool_execution_end │ │
321
332
  │ │ │ │
322
- └─► turn_end │ │
323
-
333
+ ├─► turn_end │ │
334
+ └─► post-tool threshold preflight
335
+ │ (may compact before the next provider request) │
324
336
  └─► agent_end │
325
337
 
326
338
  user sends another prompt ◄────────────────────────────────┘
@@ -460,14 +472,14 @@ Do cleanup work in `session_shutdown`, then reestablish any in-memory state in `
460
472
 
461
473
  #### session_before_compact / session_compact
462
474
 
463
- Fired by `/compact` and auto-compaction. Atomic prepares a protected recent tail and a numbered compactable region. Extensions may cancel or provide a complete, non-empty `compactedText` replacement for that region; they cannot move `firstKeptEntryId`. The override is persisted verbatim and works without provider credentials.
475
+ Fired by `/compact` and auto-compaction, including a threshold crossing detected after tool results enter the prospective next-turn context. Atomic prepares the complete active transcript except for the exact newest `preserve_recent` context-visible messages. Extensions may cancel or provide a complete, non-empty `compactedText` replacement for that region; they cannot move `firstKeptEntryId`. The override is persisted verbatim and works without provider credentials. A successful post-tool compaction returns its rebuilt context directly to the already-active Pi loop; it does not start a separate continuation. Cancellation or failure prevents that loop's follow-up provider request.
464
476
 
465
477
  ```typescript
466
478
  pi.on("session_before_compact", async (event) => {
467
479
  const { preparation, branchEntries, parameters, reason, signal } = event;
468
480
 
469
481
  // preparation.region.lines - unnumbered compactable transcript lines
470
- // preparation.firstKeptEntryId - fixed start of the verbatim tail
482
+ // preparation.firstKeptEntryId - fixed start of the exact tail, or null when the tail is empty
471
483
  // preparation.tokensBefore - whole-context token estimate
472
484
  // parameters - compression_ratio, preserve_recent, query
473
485
  // branchEntries - raw entries on the active branch
@@ -649,7 +661,7 @@ pi.on("tool_execution_end", async (event, ctx) => {
649
661
 
650
662
  #### context
651
663
 
652
- Fired before each LLM call. Modify messages non-destructively. See [Session Format](/session-format) for message types.
664
+ Fired before each LLM call. Modify messages non-destructively. See [Session Format](/session-format) for message types. When tool output crosses the buffered compaction threshold, the post-tool compaction preflight finishes before this hook runs for the follow-up call, so `event.messages` contains the rebuilt compacted context.
653
665
 
654
666
  ```typescript
655
667
  pi.on("context", async (event, ctx) => {
@@ -1045,12 +1057,12 @@ if (usage && usage.tokens > 100_000) {
1045
1057
 
1046
1058
  ### ctx.compact()
1047
1059
 
1048
- Trigger Atomic's verbatim line compactor without awaiting completion. The planner emits numbered deleted-line ranges only; Atomic validates them and reconstructs retained text mechanically. Use `compression_ratio` (fraction of compactable lines to keep), client-side `preserve_recent`, and `query` to tune the run, and `onComplete`/`onError` for follow-up actions.
1060
+ Trigger Atomic's verbatim line compactor without awaiting completion. The planner emits numbered deleted-line ranges only; Atomic validates them and reconstructs retained text mechanically. Use `compression_ratio` (fraction of compactable lines to keep), client-side `preserve_recent` (an exact context-visible message count), and `query` to tune the run, and `onComplete`/`onError` for follow-up actions.
1049
1061
 
1050
1062
  ```typescript
1051
1063
  ctx.compact({
1052
1064
  compression_ratio: 0.5, // fraction of compactable lines to keep
1053
- preserve_recent: 2, // keep recent messages and widen to a user-turn start
1065
+ preserve_recent: 2, // protect exactly the newest two context-visible messages
1054
1066
  query: "keep active migration details",
1055
1067
  onComplete: (result) => {
1056
1068
  ctx.ui.notify(`Compaction kept ${result.stats.linesKept}/${result.stats.linesBefore} lines`, "info");
@@ -1377,7 +1389,7 @@ pi.registerTool({
1377
1389
 
1378
1390
  ### pi.sendMessage(message, options?)
1379
1391
 
1380
- Inject a custom message into the session.
1392
+ Inject a custom message into the session. The call returns `void | Promise<void>` for compatibility with synchronous hosts; use `await Promise.resolve(pi.sendMessage(...))` when admission or routing failure must be observed. Atomic's AgentSession runtime returns an admission receipt: it settles after the message is accepted by the local queue or workflow late-message route, without waiting for the resulting model turn to finish.
1381
1393
 
1382
1394
  ```typescript
1383
1395
  pi.sendMessage({
@@ -1403,7 +1415,7 @@ pi.sendMessage({
1403
1415
 
1404
1416
  ### pi.sendMessages(messages, options?)
1405
1417
 
1406
- Atomically admit a batch of custom messages in array order. Admission is indivisible, but the resulting model turn remains asynchronous; use this when a prelude and terminal notice must stay contiguous without globally serializing other extension work.
1418
+ Atomically admit a batch of custom messages in array order. The call returns `void | Promise<void>` for compatibility with synchronous hosts; use `await Promise.resolve(pi.sendMessages(...))` when admission or routing failure must be observed. The promise is an admission receipt and does not wait for the resulting model turn. Admission is indivisible; use this when a prelude and terminal notice must stay contiguous without globally serializing other extension work.
1407
1419
 
1408
1420
  ```typescript
1409
1421
  pi.sendMessages([
@@ -2159,22 +2171,24 @@ If a slot intentionally has no visible content, return an empty `Component` such
2159
2171
 
2160
2172
  #### Keybinding Hints
2161
2173
 
2162
- Use `keyHint()` to display keybinding hints that respect the active keybinding configuration:
2174
+ Use `keyHintIfBound()` when an affordance should disappear if the action has no effective keybinding. Add surrounding punctuation only when the helper returns text:
2163
2175
 
2164
2176
  ```typescript
2165
- import { keyHint } from "@bastani/atomic";
2177
+ import { keyHintIfBound } from "@bastani/atomic";
2166
2178
 
2167
2179
  renderResult(result, { expanded }, theme, context) {
2168
2180
  let text = theme.fg("success", "✓ Done");
2169
- if (!expanded) {
2170
- text += ` (${keyHint("app.tools.expand", "to expand")})`;
2181
+ const expandHint = keyHintIfBound("app.tools.expand", "to expand");
2182
+ if (!expanded && expandHint) {
2183
+ text += ` (${expandHint})`;
2171
2184
  }
2172
2185
  return new Text(text, 0, 0);
2173
2186
  }
2174
2187
  ```
2175
2188
 
2176
2189
  Available functions:
2177
- - `keyHint(keybinding, description)` - Formats a configured keybinding id such as `"app.tools.expand"` or `"tui.select.confirm"`
2190
+ - `keyHint(keybinding, description)` - Formats a configured keybinding id such as `"app.tools.expand"` or `"tui.select.confirm"`; use it when the binding is required by the surrounding UI
2191
+ - `keyHintIfBound(keybinding, description)` - Formats the hint only when the action has an effective key list; use it for optional affordances and conditionally compose parentheses or separators
2178
2192
  - `keyText(keybinding)` - Returns the raw configured key text for a keybinding id
2179
2193
  - `rawKeyHint(key, description)` - Format a raw key string
2180
2194