mixdog 1.4.1 → 1.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (630) hide show
  1. package/package.json +4 -3
  2. package/scripts/build-shipped-history.mjs +125 -33
  3. package/scripts/gate-local.mjs +220 -63
  4. package/scripts/graph-parity.mjs +8 -3
  5. package/scripts/lib/gate-scheduler.mjs +139 -32
  6. package/scripts/lib/gate-timing-reporter.mjs +16 -0
  7. package/scripts/lib/run-node-tests.mjs +71 -34
  8. package/scripts/lib/scoped-temp.mjs +1 -0
  9. package/scripts/lib/test-failure-records.mjs +14 -1
  10. package/scripts/lib/test-failure-summary.mjs +9 -4
  11. package/scripts/lib/test-spawn-ledger.mjs +43 -3
  12. package/scripts/post-release-check.mjs +26 -16
  13. package/scripts/pptx-kit-index.mjs +5 -6
  14. package/scripts/provider-pingpong-live.mjs +1 -1
  15. package/scripts/prune-embedding-runtime.mjs +3 -1
  16. package/scripts/release-paths.mjs +7 -1
  17. package/scripts/suite-health.mjs +110 -28
  18. package/scripts/test.mjs +9 -14
  19. package/src/agents/advisor/AGENT.md +4 -4
  20. package/src/agents/advisor/agent.json +1 -1
  21. package/src/agents/explore/AGENT.md +22 -0
  22. package/src/agents/explore/agent.json +6 -0
  23. package/src/cli.mjs +7 -0
  24. package/src/defaults/agents.json +7 -0
  25. package/src/defaults/shipped-history.json +38 -2
  26. package/src/defaults/skills/browser-use/SKILL.md +4 -1
  27. package/src/defaults/skills/code-tidy/SKILL.md +71 -102
  28. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
  29. package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
  30. package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
  31. package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
  32. package/src/defaults/skills/computer-use/SKILL.md +12 -2
  33. package/src/defaults/skills/setup/SKILL.md +2 -2
  34. package/src/defaults/skills/setup/references/actions.md +28 -9
  35. package/src/defaults/skills/setup/references/surfaces.md +5 -2
  36. package/src/defaults/skills/setup-guide/SKILL.md +11 -3
  37. package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
  38. package/src/defaults/skills/skill-creator/SKILL.md +85 -190
  39. package/src/defaults/skills/skill-creator/references/design.md +70 -162
  40. package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
  41. package/src/defaults/skills/test-suite/SKILL.md +194 -0
  42. package/src/defaults/skills/test-suite/references/case-management.md +51 -0
  43. package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
  44. package/src/defaults/skills/test-suite/references/reliability.md +49 -0
  45. package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
  46. package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
  47. package/src/defaults/skills/visualize/SKILL.md +6 -2
  48. package/src/lib/instruction-text.cjs +36 -0
  49. package/src/lib/rules-builder.cjs +40 -50
  50. package/src/orchestration/balanced.md +23 -0
  51. package/src/orchestration/focused.md +22 -0
  52. package/src/orchestration/none.md +5 -0
  53. package/src/orchestration/swarm.md +24 -0
  54. package/src/rules/agent-mode/AGENT_MODE.md +3 -1
  55. package/src/rules/agent-mode/MIXY.md +2 -2
  56. package/src/rules/lead/LEAD.md +3 -3
  57. package/src/rules/shared/20-research.md +3 -6
  58. package/src/rules/shared/40-editing.md +1 -0
  59. package/src/rules/shared/60-verification.md +10 -9
  60. package/src/rules/shared/70-delivery.md +4 -3
  61. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
  62. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +3 -3
  63. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -2
  64. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +132 -21
  65. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -9
  66. package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +2 -2
  67. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +67 -0
  69. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
  70. package/src/runtime/agent/orchestrator/config.mjs +12 -7
  71. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +7 -7
  72. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +9 -30
  73. package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
  74. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +124 -12
  75. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +204 -49
  76. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +16 -7
  77. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +157 -57
  78. package/src/runtime/agent/orchestrator/mcp/client.mjs +54 -23
  79. package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +1 -1
  80. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +8 -2
  81. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +83 -52
  82. package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +1 -1
  83. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +14 -0
  84. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +43 -27
  85. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +43 -8
  86. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +30 -28
  87. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  88. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
  89. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-stop.mjs +3 -3
  90. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
  91. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
  92. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  93. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
  94. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
  95. package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
  96. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
  97. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
  98. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
  99. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
  100. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
  101. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +2 -2
  102. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +48 -31
  103. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
  104. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
  105. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
  106. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
  107. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
  108. package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
  109. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +4 -6
  110. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2784 -2872
  111. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +5 -8
  112. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +26 -28
  113. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +288 -300
  114. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +3 -1
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +1 -0
  116. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
  117. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
  118. package/src/runtime/agent/orchestrator/providers/registry.mjs +33 -2
  119. package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
  120. package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
  121. package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
  122. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +576 -0
  123. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +10 -30
  124. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +32 -0
  125. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +0 -11
  126. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +8 -0
  127. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +17 -3
  128. package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +47 -27
  129. package/src/runtime/agent/orchestrator/runtime-core/goal-deadlines.mjs +141 -10
  130. package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +26 -63
  131. package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +28 -3
  132. package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +36 -11
  133. package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +88 -56
  134. package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +4 -1
  135. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +51 -32
  136. package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +45 -145
  137. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -98
  138. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +32 -99
  139. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +23 -78
  140. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +69 -47
  141. package/src/runtime/agent/orchestrator/runtime-core/todo-list.mjs +367 -0
  142. package/src/runtime/agent/orchestrator/runtime-core/todo-tool-defs.mjs +47 -0
  143. package/src/runtime/agent/orchestrator/runtime-core/tool-availability.mjs +155 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +12 -0
  145. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +119 -35
  146. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +4 -1
  147. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +15 -6
  148. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
  149. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +28 -22
  150. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +30 -0
  151. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
  152. package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
  153. package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +1 -1
  154. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +94 -10
  155. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -2
  156. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +1 -1
  157. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -1
  158. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +3 -0
  159. package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +1 -1
  160. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -12
  161. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +4 -4
  162. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +11 -6
  163. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +6 -6
  164. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +7 -3
  165. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +11 -1
  166. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
  167. package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +1 -1
  168. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +37 -8
  169. package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +1 -1
  170. package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +1 -1
  171. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +11 -1
  172. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
  173. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +5 -3
  174. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
  175. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/todo-check.mjs +196 -0
  176. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +116 -50
  177. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +8 -1
  178. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +1 -1
  179. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +1 -1
  180. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -1
  181. package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +5 -6
  182. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +27 -3
  183. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +18 -2
  184. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
  185. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
  186. package/src/runtime/agent/orchestrator/session/loop/turn-report.mjs +35 -0
  187. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +1 -1
  188. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +103 -50
  189. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +9 -7
  190. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +21 -3
  191. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +27 -11
  192. package/src/runtime/agent/orchestrator/session/manager/ask-turn-open.mjs +37 -34
  193. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +15 -0
  194. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +25 -15
  195. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +79 -24
  196. package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +3 -0
  197. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +12 -1
  198. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
  199. package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +6 -1
  200. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +9 -1
  201. package/src/runtime/agent/orchestrator/session/manager/pending-spool-path.mjs +2 -2
  202. package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +1 -1
  203. package/src/runtime/agent/orchestrator/session/manager/prompt-settings.mjs +598 -0
  204. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +20 -0
  205. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -14
  206. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +2 -0
  207. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +12 -0
  208. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
  209. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +1 -1
  210. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +56 -14
  211. package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +31 -0
  212. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +59 -20
  213. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +2 -0
  214. package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
  215. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
  216. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +18 -4
  217. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +8 -9
  218. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +339 -88
  219. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +135 -11
  220. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +377 -104
  221. package/src/runtime/agent/orchestrator/session/manager/turn-durability.mjs +144 -0
  222. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +48 -30
  223. package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
  224. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +4 -0
  225. package/src/runtime/agent/orchestrator/session/manager.mjs +6 -0
  226. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +12 -6
  227. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +8 -1
  228. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +1 -1
  229. package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +5 -1
  230. package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +1 -1
  231. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +2 -2
  232. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +23 -2
  233. package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +3 -3
  234. package/src/runtime/agent/orchestrator/session/store/transcript-durability.mjs +88 -0
  235. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +5 -0
  236. package/src/runtime/agent/orchestrator/session/store-summary-log.mjs +1 -1
  237. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +243 -38
  238. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
  239. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +177 -8
  240. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
  241. package/src/runtime/agent/orchestrator/session/store.mjs +5 -0
  242. package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +7 -1
  243. package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +9 -1
  244. package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
  245. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +3 -1
  246. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +2 -2
  247. package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -5
  248. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -1
  249. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
  250. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +21 -3
  251. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  252. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/worktree-add-guard.mjs +77 -0
  253. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -1
  254. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +42 -28
  255. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +30 -14
  256. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +2 -2
  257. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
  258. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +1 -1
  259. package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +0 -1
  260. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
  261. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +0 -10
  262. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +95 -20
  263. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
  264. package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -24
  265. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary/child-kill.mjs +4 -3
  266. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +1 -2
  267. package/src/runtime/agent/orchestrator/tools/code-graph/modes/calls.mjs +1 -1
  268. package/src/runtime/agent/orchestrator/tools/code-graph/modes/symbols.mjs +2 -2
  269. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +4 -5
  270. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +3 -4
  271. package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4 -22
  272. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  273. package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
  274. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
  275. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +105 -15
  276. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
  277. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
  278. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
  279. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +35 -11
  280. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +2 -0
  281. package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
  282. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -6
  283. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +0 -1
  284. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  285. package/src/runtime/attachments/attachment-reference.mjs +1 -1
  286. package/src/runtime/attachments/pdf-extract.mjs +1 -1
  287. package/src/runtime/attachments/store.d.mts +1 -0
  288. package/src/runtime/attachments/store.mjs +2 -2
  289. package/src/runtime/channels/lib/config-reload-watch.mjs +42 -0
  290. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +29 -9
  291. package/src/runtime/channels/lib/scheduler.mjs +33 -0
  292. package/src/runtime/channels/lib/schedules-db.mjs +11 -4
  293. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +4 -1
  294. package/src/runtime/channels/lib/webhooks-db.mjs +9 -3
  295. package/src/runtime/channels/lib/whisper-port.mjs +19 -10
  296. package/src/runtime/channels/lib/whisper-server.mjs +22 -13
  297. package/src/runtime/channels/lib/worker-main.mjs +9 -31
  298. package/src/runtime/computer-bridge/linux-readiness.mjs +10 -14
  299. package/src/runtime/connectors/connector-accounts-mcp.mjs +372 -103
  300. package/src/runtime/connectors/gmail-app-password.mjs +4 -4
  301. package/src/runtime/connectors/google-mcp.mjs +1 -1
  302. package/src/runtime/effort-judge/judge-client.mjs +2 -2
  303. package/src/runtime/effort-judge/judge-input.mjs +4 -4
  304. package/src/runtime/explore/explorer.mjs +88 -0
  305. package/src/runtime/explore/tool-defs.mjs +35 -0
  306. package/src/runtime/explore/tool.mjs +123 -0
  307. package/src/runtime/local-provider/hardware.mjs +1 -1
  308. package/src/runtime/media/adapters/codex-image.mjs +3 -3
  309. package/src/runtime/media/adapters/gemini-video.mjs +1 -1
  310. package/src/runtime/media/media-usage.mjs +1 -1
  311. package/src/runtime/media/store.mjs +1 -1
  312. package/src/runtime/memory/index.mjs +15 -1
  313. package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
  314. package/src/runtime/memory/lib/embedding-reindex.mjs +27 -0
  315. package/src/runtime/memory/lib/embedding-worker.mjs +4 -0
  316. package/src/runtime/memory/lib/memory-embed.mjs +83 -14
  317. package/src/runtime/memory/lib/memory-process-lock.mjs +159 -36
  318. package/src/runtime/memory/lib/memory-text-utils.mjs +6 -1
  319. package/src/runtime/memory/lib/memory.mjs +17 -0
  320. package/src/runtime/memory/lib/pg/process.mjs +1 -1
  321. package/src/runtime/memory/lib/pg/supervisor.mjs +16 -96
  322. package/src/runtime/memory/lib/recall-hybrid/hybrid-sql.mjs +12 -3
  323. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  324. package/src/runtime/office/authoring/pptx-author-action.mjs +1 -1
  325. package/src/runtime/office/authoring/xlsx-html-build.mjs +1 -1
  326. package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
  327. package/src/runtime/office/capabilities.mjs +1 -1
  328. package/src/runtime/office/core/office-core.mjs +1 -1
  329. package/src/runtime/office/design/content-model.mjs +3 -3
  330. package/src/runtime/office/design/docx/design-docx/section.mjs +6 -6
  331. package/src/runtime/office/design/xlsx/design-xlsx-components.mjs +1 -1
  332. package/src/runtime/office/design/xlsx/design-xlsx.mjs +1 -1
  333. package/src/runtime/office/pdf/ocr-engine.mjs +1 -1
  334. package/src/runtime/office/pdf/pdf-writer.mjs +4 -4
  335. package/src/runtime/office/portable/portable-docx-operations.mjs +2 -2
  336. package/src/runtime/office/portable/portable-soffice.mjs +8 -6
  337. package/src/runtime/office/portable/xlsx-contract.mjs +1 -1
  338. package/src/runtime/office/quality/assurance-structure-docx.mjs +1 -1
  339. package/src/runtime/shared/agent-route-config.mjs +17 -2
  340. package/src/runtime/shared/atomic-file.d.mts +8 -0
  341. package/src/runtime/shared/atomic-file.mjs +103 -2
  342. package/src/runtime/shared/background-tasks.mjs +37 -10
  343. package/src/runtime/shared/background-wait.mjs +66 -0
  344. package/src/runtime/shared/child-guardian.mjs +17 -7
  345. package/src/runtime/shared/config.mjs +313 -16
  346. package/src/runtime/shared/connector-accounts.mjs +5 -5
  347. package/src/runtime/shared/connector-catalog.d.mts +14 -8
  348. package/src/runtime/shared/connector-catalog.mjs +70 -52
  349. package/src/runtime/shared/custom-provider-keys.mjs +20 -0
  350. package/src/runtime/shared/file-has-data.mjs +26 -2
  351. package/src/runtime/shared/file-lock.mjs +21 -18
  352. package/src/runtime/shared/git-launch.d.mts +9 -0
  353. package/src/runtime/shared/git-launch.mjs +213 -0
  354. package/src/runtime/shared/git-runner-worker.mjs +2 -1
  355. package/src/runtime/shared/git-runner.mjs +7 -2
  356. package/src/runtime/shared/idle-gc.mjs +30 -7
  357. package/src/runtime/shared/llm/cost.mjs +6 -1
  358. package/src/runtime/shared/llm/http-agent.mjs +316 -29
  359. package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
  360. package/src/runtime/shared/llm/model-catalog.mjs +46 -6
  361. package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
  362. package/src/runtime/shared/llm/system-proxy.mjs +453 -0
  363. package/src/runtime/shared/llm/usage-ledger-quota.mjs +31 -12
  364. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +84 -8
  365. package/src/runtime/shared/llm/usage-ledger.mjs +3 -0
  366. package/src/runtime/shared/llm/usage-rollup.mjs +48 -0
  367. package/src/runtime/shared/maintenance-schedule.mjs +109 -0
  368. package/src/runtime/shared/process-runner.mjs +8 -4
  369. package/src/runtime/shared/provider-accounts.mjs +52 -2
  370. package/src/runtime/shared/routine-trigger.d.mts +13 -0
  371. package/src/runtime/shared/routine-trigger.mjs +34 -0
  372. package/src/runtime/shared/run-child.d.mts +2 -1
  373. package/src/runtime/shared/run-child.mjs +70 -18
  374. package/src/runtime/shared/session-scratch.mjs +14 -2
  375. package/src/runtime/shared/shipped-definitions.mjs +7 -1
  376. package/src/runtime/shared/staged-install-worker.mjs +5 -0
  377. package/src/runtime/shared/staged-update.mjs +47 -2
  378. package/src/runtime/shared/tool-card-model.golden.json +3 -12
  379. package/src/runtime/shared/tool-execution-contract.mjs +2 -0
  380. package/src/runtime/shared/tool-surface.mjs +110 -36
  381. package/src/runtime/shared/tool-work-units.mjs +35 -6
  382. package/src/runtime/shared/turn-snapshot.mjs +26 -4
  383. package/src/runtime/shared/turn-worktree-snapshot.mjs +409 -54
  384. package/src/runtime/shared/worker-requests.mjs +17 -3
  385. package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
  386. package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
  387. package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
  388. package/src/runtime/shared/worktrees/branch-management.mjs +5 -3
  389. package/src/runtime/shared/worktrees/contract.mjs +16 -6
  390. package/src/runtime/shared/worktrees/dependencies.mjs +127 -89
  391. package/src/runtime/shared/worktrees/disk.mjs +79 -2
  392. package/src/runtime/shared/worktrees/git.mjs +97 -7
  393. package/src/runtime/shared/worktrees/include.mjs +6 -4
  394. package/src/runtime/shared/worktrees/maintenance.mjs +422 -30
  395. package/src/runtime/shared/worktrees/manager.mjs +962 -197
  396. package/src/runtime/shared/worktrees/settings.mjs +33 -7
  397. package/src/runtime/shared/worktrees/test-support.mjs +5 -1
  398. package/src/runtime/shared/worktrees/worker-snapshots.mjs +82 -0
  399. package/src/runtime/tidy/install.mjs +95 -15
  400. package/src/runtime/tidy/languages.mjs +17 -15
  401. package/src/runtime/tidy/process.mjs +9 -5
  402. package/src/runtime/tidy/resolve.mjs +19 -16
  403. package/src/runtime/tidy/runners/biome.mjs +3 -3
  404. package/src/runtime/tidy/tool.mjs +1 -1
  405. package/src/runtime/tidy/worktree.mjs +10 -6
  406. package/src/runtime/visualize-bridge/client.mjs +4 -1
  407. package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
  408. package/src/runtime/web-search/index.mjs +4 -23
  409. package/src/runtime/web-search/lib/web-tools.mjs +2 -2
  410. package/src/runtime/web-search/tool-defs.mjs +17 -26
  411. package/src/session-runtime/agent-profile-changes.mjs +55 -4
  412. package/src/session-runtime/agent-task-sessions.mjs +410 -353
  413. package/src/session-runtime/boot/apis.mjs +27 -4
  414. package/src/session-runtime/boot/begin.mjs +2 -0
  415. package/src/session-runtime/boot/config.mjs +10 -1
  416. package/src/session-runtime/boot/facade.mjs +1 -0
  417. package/src/session-runtime/boot/providers.mjs +70 -3
  418. package/src/session-runtime/boot/session.mjs +2 -0
  419. package/src/session-runtime/boot/tools.mjs +71 -25
  420. package/src/session-runtime/bot-status.mjs +103 -103
  421. package/src/session-runtime/channel-config-api.mjs +1 -0
  422. package/src/session-runtime/config-change-effects.mjs +179 -0
  423. package/src/session-runtime/config-lifecycle/config-writers.mjs +1 -0
  424. package/src/session-runtime/config-lifecycle.mjs +160 -24
  425. package/src/session-runtime/connector-merge-migration.mjs +18 -15
  426. package/src/session-runtime/conversation-import/discovery.mjs +245 -47
  427. package/src/session-runtime/conversation-import/service.mjs +12 -5
  428. package/src/session-runtime/goal-facade-api.mjs +49 -3
  429. package/src/session-runtime/handoff-attachments.mjs +1 -1
  430. package/src/session-runtime/held-requests.mjs +3 -1
  431. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +3 -0
  432. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -2
  433. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -11
  434. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
  435. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +161 -120
  436. package/src/session-runtime/internal-tool-executor.mjs +12 -19
  437. package/src/session-runtime/lifecycle/cold-heir.mjs +7 -0
  438. package/src/session-runtime/lifecycle/memory-ingest.mjs +3 -3
  439. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +53 -5
  440. package/src/session-runtime/lifecycle/session-switch.mjs +13 -2
  441. package/src/session-runtime/lifecycle/teardown/session-close.mjs +10 -5
  442. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  443. package/src/session-runtime/lifecycle-api.mjs +1 -0
  444. package/src/session-runtime/mcp-glue/server-catalog.mjs +27 -10
  445. package/src/session-runtime/mcp-glue/server-connection.mjs +34 -8
  446. package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
  447. package/src/session-runtime/mixy-heartbeat.mjs +1 -1
  448. package/src/session-runtime/model-route/set-route.mjs +40 -7
  449. package/src/session-runtime/native-web-search/routes.mjs +3 -3
  450. package/src/session-runtime/provider-auth/login.mjs +2 -2
  451. package/src/session-runtime/provider-auth/refresh.mjs +6 -3
  452. package/src/session-runtime/provider-auth/setup.mjs +1 -1
  453. package/src/session-runtime/provider-readiness.mjs +53 -4
  454. package/src/session-runtime/resource-api.mjs +1 -1
  455. package/src/session-runtime/resource-extension-sync.mjs +4 -8
  456. package/src/session-runtime/resource-mcp-api.mjs +98 -35
  457. package/src/session-runtime/resource-mcp-connector-accounts.mjs +49 -32
  458. package/src/session-runtime/resource-mcp-secrets.mjs +27 -10
  459. package/src/session-runtime/resource-mcp-servers.mjs +5 -4
  460. package/src/session-runtime/resource-plugins-api.mjs +4 -0
  461. package/src/session-runtime/routine-executor.mjs +152 -0
  462. package/src/session-runtime/routine-home-turn.mjs +46 -5
  463. package/src/session-runtime/runtime-facade.mjs +5 -0
  464. package/src/session-runtime/runtime-feature-gates.mjs +2 -11
  465. package/src/session-runtime/schedule-session-run.mjs +1 -0
  466. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +6 -1
  467. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +7 -0
  468. package/src/session-runtime/services/agent-tool/send-flow.mjs +120 -8
  469. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +12 -0
  470. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +5 -0
  471. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
  472. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +28 -7
  473. package/src/session-runtime/services/agent-tool.mjs +51 -1
  474. package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
  475. package/src/session-runtime/services/channel-admin.mjs +18 -0
  476. package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
  477. package/src/session-runtime/services/daemon-candidate.mjs +4 -1
  478. package/src/session-runtime/services/hook-bus/command-handler.mjs +7 -11
  479. package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
  480. package/src/session-runtime/services/plugin-admin.mjs +14 -6
  481. package/src/session-runtime/services/provider-admin.mjs +281 -10
  482. package/src/session-runtime/services/seeds.mjs +7 -0
  483. package/src/session-runtime/services/usage-stats-model.mjs +32 -11
  484. package/src/session-runtime/session-create/materialize.mjs +4 -2
  485. package/src/session-runtime/session-create/session-options.mjs +2 -0
  486. package/src/session-runtime/session-turn-api.mjs +2 -0
  487. package/src/session-runtime/settings-builtin-tools-api.mjs +5 -10
  488. package/src/session-runtime/settings-system-api.mjs +1 -1
  489. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
  490. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
  491. package/src/session-runtime/setup-tool/executor.mjs +14 -3
  492. package/src/session-runtime/setup-tool/extended-actions.mjs +2 -0
  493. package/src/session-runtime/setup-tool/settings-contract.mjs +28 -0
  494. package/src/session-runtime/setup-tool/tool-defs.mjs +28 -2
  495. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +40 -43
  496. package/src/session-runtime/tool-policy/mode-switch.mjs +1 -1
  497. package/src/session-runtime/tool-policy/policy-stage.mjs +106 -8
  498. package/src/session-runtime/tool-policy/workflow-overlay.mjs +2 -1
  499. package/src/session-runtime/tool-policy-refresh.mjs +182 -5
  500. package/src/session-runtime/tool-surface.mjs +38 -1
  501. package/src/session-runtime/turn/agent-ops.mjs +33 -2
  502. package/src/session-runtime/turn/session-ops.mjs +2 -0
  503. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +5 -0
  504. package/src/session-runtime/turn/turn-run.mjs +1 -1
  505. package/src/session-runtime/webhook-session-run.mjs +2 -0
  506. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +46 -11
  507. package/src/session-runtime/workflow-agents-api/agent-route.mjs +2 -0
  508. package/src/session-runtime/workflow-agents-api/instruction-files.mjs +165 -0
  509. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +5 -4
  510. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +2 -3
  511. package/src/session-runtime/workflow-agents-api.mjs +2 -0
  512. package/src/session-runtime/workspace/activity-guards.mjs +176 -0
  513. package/src/session-runtime/workspace/project-branches.mjs +1 -1
  514. package/src/session-runtime/workspace/session-view.mjs +149 -0
  515. package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
  516. package/src/session-runtime/workspace/transition-runner.mjs +188 -0
  517. package/src/session-runtime/workspace/transitions.mjs +128 -1070
  518. package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
  519. package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
  520. package/src/session-runtime/workspace/worktree-maintenance.mjs +200 -0
  521. package/src/session-runtime/workspace/worktree-setup.mjs +97 -0
  522. package/src/session-runtime/workspace/worktree-tool.mjs +70 -54
  523. package/src/standalone/daemon-agent-control.mjs +25 -8
  524. package/src/standalone/daemon-desktop-runtime.mjs +8 -2
  525. package/src/standalone/daemon-lag-profiler.mjs +7 -7
  526. package/src/standalone/daemon-session-control.mjs +151 -136
  527. package/src/standalone/daemon.mjs +61 -2
  528. package/src/standalone/desktop-service-registry.mjs +9 -0
  529. package/src/standalone/local-session-runtime.mjs +21 -1
  530. package/src/standalone/session-client/daemon-unavailable.mjs +4 -1
  531. package/src/standalone/session-client.mjs +5 -1
  532. package/src/standalone/session-frame-stream.mjs +83 -11
  533. package/src/standalone/session-protocol.mjs +15 -0
  534. package/src/standalone/session-service/agent-route-follow.mjs +23 -20
  535. package/src/standalone/session-service/agent-tree/agent-turns.mjs +18 -6
  536. package/src/standalone/session-service/agent-tree.mjs +45 -9
  537. package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
  538. package/src/standalone/session-service/quota-resume.mjs +9 -0
  539. package/src/standalone/session-service/session-calls/session-action.mjs +51 -1
  540. package/src/standalone/session-service/session-calls/session-turns.mjs +37 -18
  541. package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
  542. package/src/standalone/session-service/session-calls/turn-gate.mjs +34 -0
  543. package/src/standalone/session-service/session-calls.mjs +2 -1
  544. package/src/standalone/session-service/stored-reader.mjs +127 -40
  545. package/src/tui/App.jsx +162 -164
  546. package/src/tui/app/app-view/floating-panel.jsx +3 -0
  547. package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
  548. package/src/tui/app/clipboard.mjs +22 -11
  549. package/src/tui/app/create-app-pickers.mjs +2 -0
  550. package/src/tui/app/doctor.mjs +2 -2
  551. package/src/tui/app/panel-signature.mjs +1 -1
  552. package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
  553. package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
  554. package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
  555. package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
  556. package/src/tui/app/provider-setup/oauth-actions.mjs +25 -6
  557. package/src/tui/app/provider-setup-picker.mjs +20 -13
  558. package/src/tui/app/settings-picker.mjs +53 -8
  559. package/src/tui/app/shell-layout/row-budgets.mjs +14 -12
  560. package/src/tui/app/slash-commands.mjs +2 -1
  561. package/src/tui/app/slash-dispatch/route-commands.mjs +1 -1
  562. package/src/tui/app/slash-dispatch/session-commands.mjs +47 -1
  563. package/src/tui/app/slash-dispatch.mjs +1 -1
  564. package/src/tui/app/use-btw-panel.mjs +29 -0
  565. package/src/tui/app/use-context-panel-refresh.mjs +31 -0
  566. package/src/tui/app/use-model-catalog-cache.mjs +13 -10
  567. package/src/tui/app/use-mouse-input.mjs +11 -0
  568. package/src/tui/app/use-onboarding-start.mjs +8 -3
  569. package/src/tui/app/use-panel-transition.mjs +10 -1
  570. package/src/tui/app/use-pasted-buffers.mjs +28 -20
  571. package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
  572. package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
  573. package/src/tui/app/use-prompt-queue-history.mjs +5 -4
  574. package/src/tui/app/use-selection-focus.mjs +11 -2
  575. package/src/tui/app/use-selection-geometry.mjs +18 -9
  576. package/src/tui/app/use-selection-paint.mjs +4 -4
  577. package/src/tui/app/use-selection-stitch.mjs +3 -3
  578. package/src/tui/app/use-slash-palette.mjs +62 -0
  579. package/src/tui/app/use-terminal-chrome.mjs +2 -2
  580. package/src/tui/app/use-transcript-activity.mjs +48 -33
  581. package/src/tui/app/use-transcript-follow.mjs +12 -4
  582. package/src/tui/app/use-transcript-scroll.mjs +46 -17
  583. package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
  584. package/src/tui/app/use-transcript-window/geometry.mjs +20 -6
  585. package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
  586. package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
  587. package/src/tui/app/use-transcript-window.mjs +21 -11
  588. package/src/tui/app/use-tui-ready.mjs +18 -0
  589. package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
  590. package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
  591. package/src/tui/components/Picker.jsx +27 -3
  592. package/src/tui/components/SignInUrl.jsx +68 -0
  593. package/src/tui/components/TextEntryPanel.jsx +76 -46
  594. package/src/tui/components/prompt-input/escape-policy.d.mts +0 -1
  595. package/src/tui/components/prompt-input/escape-policy.mjs +1 -1
  596. package/src/tui/components/question-panel-model.mjs +4 -4
  597. package/src/tui/components/sign-in-url-layout.mjs +24 -0
  598. package/src/tui/components/tool-execution/standard-card.jsx +3 -4
  599. package/src/tui/components/user-message-skills.mjs +1 -1
  600. package/src/tui/dist/index.mjs +2205 -1371
  601. package/src/tui/markdown/render-ansi.mjs +1 -1
  602. package/src/tui/session/agent-job-feed/notification-router.mjs +10 -0
  603. package/src/tui/session/agent-job-feed.mjs +2 -0
  604. package/src/tui/session/context-state.mjs +3 -0
  605. package/src/tui/session/goal-turn-state.mjs +6 -2
  606. package/src/tui/session/quota-resume.mjs +1 -1
  607. package/src/tui/session/session-api/controls.mjs +4 -0
  608. package/src/tui/session/session-api/extensions.mjs +8 -0
  609. package/src/tui/session/session-api/intake/abort.mjs +2 -1
  610. package/src/tui/session/session-api/intake.mjs +2 -0
  611. package/src/tui/session/session-api/integrations.mjs +2 -2
  612. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  613. package/src/tui/session/session-api/lifecycle/session-reset.mjs +7 -0
  614. package/src/tui/session/session-api/routes-agent-definitions.mjs +6 -0
  615. package/src/tui/session/session-api/settings.mjs +2 -2
  616. package/src/tui/session/session-api/worktree.mjs +13 -1
  617. package/src/tui/session/session-flow/drain.mjs +11 -14
  618. package/src/tui/session/tool-card-results/grouped-result.mjs +2 -2
  619. package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
  620. package/src/tui/session/transcript-spill.mjs +92 -4
  621. package/src/tui/session/transcript-store.mjs +2 -0
  622. package/src/tui/session/turn-quiet.mjs +1 -1
  623. package/src/tui/session/turn.mjs +3 -0
  624. package/src/tui/session/worktree-setup-notice.mjs +1 -1
  625. package/src/tui/spinner-meta.mjs +3 -3
  626. package/src/tui/spinner-verbs.mjs +2 -2
  627. package/src/defaults/skills/goal-management/SKILL.md +0 -169
  628. package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
  629. package/src/runtime/agent/orchestrator/runtime-core/goal-tasks.mjs +0 -156
  630. package/src/session-runtime/goal-tasks.mjs +0 -1
@@ -4,6 +4,7 @@
4
4
  * tombstone barrier and the turn abort.
5
5
  */
6
6
  import { SessionClosedError } from '../../../runtime/agent/orchestrator/session/manager/session-errors.mjs';
7
+ import { armTurnTimeout } from '../../../runtime/agent/orchestrator/session/manager/turn-reap.mjs';
7
8
  import { isScratchSession } from '../shared.mjs';
8
9
 
9
10
  // SessionEnd reason mapped to standard values ('clear'/'exit' where
@@ -34,10 +35,10 @@ export async function dispatchSessionEnd(deps, reason) {
34
35
  }
35
36
  }
36
37
 
37
- // Runtime stop/exit (TUI Ctrl-C, process exit) previously always tombstoned
38
- // the current session, so a session you were mid-conversation in vanished
39
- // from the Resume list the instant you quit and was hard-deleted by the 24h
40
- // tombstone sweep. Only tombstone truly-empty scratch sessions.
38
+ // Runtime stop/exit (TUI Ctrl-C, process exit) must not tombstone a session
39
+ // you were mid-conversation in: it would vanish from the Resume list the
40
+ // instant you quit and be hard-deleted by the 24h tombstone sweep. Only
41
+ // tombstone truly-empty scratch sessions.
41
42
  export function closeOwnSession(deps, closeSurfaceSession, reason) {
42
43
  const {
43
44
  getSession,
@@ -88,11 +89,15 @@ export function closeCanonicalSession(deps, reason = 'canonical-session-close',
88
89
  return true;
89
90
  }
90
91
 
91
- export function abortRuntime(deps, reason = 'cli-abort') {
92
+ /** `options.timeout` is the progress watchdog's explicit "this abort is a
93
+ * timeout": the reap is armed before either abort runs, while the turn is
94
+ * still un-aborted (the outer abort cascades into the manager's controller). */
95
+ export function abortRuntime(deps, reason = 'cli-abort', { timeout = false } = {}) {
92
96
  const { getSession, getReservedSessionId, abortActiveTurns, mgr } = deps;
93
97
  const session = getSession();
94
98
  const sessionId = session?.id || getReservedSessionId?.() || 'pending';
95
99
  const abortError = new SessionClosedError(sessionId, `runtime abort (reason=${reason})`, reason);
100
+ if (timeout && session?.id) armTurnTimeout(session.id);
96
101
  let outerAborted = false;
97
102
  try {
98
103
  outerAborted = abortActiveTurns?.(abortError) === true;
@@ -281,6 +281,6 @@ export function createTeardown(deps, { ingestSessionIntoMemory, closeSurfaceSess
281
281
  return {
282
282
  closeCanonicalSession: (reason, options) => closeCanonicalSession(deps, reason, options),
283
283
  close,
284
- abort: (reason) => abortRuntime(deps, reason),
284
+ abort: (reason, options) => abortRuntime(deps, reason, options),
285
285
  };
286
286
  }
@@ -38,6 +38,7 @@ export function createLifecycleApi(deps) {
38
38
  listSessions: switching.listSessions,
39
39
  sessionStoreDir: switching.sessionStoreDir,
40
40
  deleteSession: switching.deleteSession,
41
+ deleteSessionIfIdle: switching.deleteSessionIfIdle,
41
42
  switchContext: switching.switchContext,
42
43
  newSession: switching.newSession,
43
44
  prefetchSession: switching.prefetchSession,
@@ -4,12 +4,16 @@
4
4
  import { clean } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
5
5
  import {
6
6
  connectorAccountEnabled,
7
+ connectorAccountId,
7
8
  connectorAccountServer,
8
9
  connectorAccountsOf,
9
10
  connectorOfServer,
10
11
  gmailAppPasswordAccount,
11
12
  } from '../../runtime/shared/connector-catalog.mjs';
12
- import { connectorAccountHealth } from '../../runtime/connectors/connector-accounts-mcp.mjs';
13
+ import {
14
+ connectorAccountHealth,
15
+ connectorAccountInUseRecord,
16
+ } from '../../runtime/connectors/connector-accounts-mcp.mjs';
13
17
  import { googleOAuthClient } from '../../runtime/shared/google-oauth-client.mjs';
14
18
  import { envFlag } from '../../runtime/shared/env.mjs';
15
19
  import { resolveMcpServerCatalog } from './plugin-servers.mjs';
@@ -119,10 +123,12 @@ export function createMcpServerCatalog({
119
123
  };
120
124
  }
121
125
 
122
- /** One account of a multi-account connector server, as its row lists it:
123
- * `{ name, email, enabled?, appPassword?, oauth?, ownClient?, error?, authRequired? }`
124
- * (`enabled: false` only for an account that is switched off). */
125
- function accountRow(accountCfg, enabled) {
126
+ /** One account of a connector server, as its row lists it:
127
+ * `{ name, email, enabled?, inUse?, appPassword?, oauth?, ownClient?, error?, authRequired? }`
128
+ * (`enabled: false` only for an account that is switched off; `inUse:
129
+ * true` only for the connector's last-used account, the one a call
130
+ * without a conversation history uses). */
131
+ function accountRow(accountCfg, enabled, inUse) {
126
132
  const address = gmailAppPasswordAccount(accountCfg);
127
133
  const oauth = address ? null : mcpClient.getMcpServerOAuthState?.(accountCfg);
128
134
  const state = connectorAccountHealth(accountCfg.name);
@@ -130,6 +136,7 @@ export function createMcpServerCatalog({
130
136
  return {
131
137
  name: accountCfg.name,
132
138
  ...(enabled ? {} : { enabled: false }),
139
+ ...(inUse ? { inUse: true } : {}),
133
140
  email: address || oauth?.account || state?.email || '',
134
141
  ...(address ? { appPassword: { account: address } } : {}),
135
142
  ...(oauth ? { oauth } : {}),
@@ -152,11 +159,21 @@ export function createMcpServerCatalog({
152
159
  failures.get(name) || (dead ? { msg: live.error || live.lastError || 'MCP server is not alive' } : undefined);
153
160
  const entry = entries[name] || {};
154
161
  const loginPending = !(live && !dead) && mcpClient.isMcpLoginPending?.(name, getMcpScopeId()) === true;
155
- const accounts = entry.owner
156
- ? []
157
- : connectorAccountsOf(cfg).map((account) =>
158
- accountRow(connectorAccountServer(cfg, account), connectorAccountEnabled(account))
159
- );
162
+ const stored = entry.owner ? [] : connectorAccountsOf(cfg);
163
+ // The connector's last-used account (none when that one was removed),
164
+ // else its topmost switched-on one.
165
+ // A record names an account only while that account is still it (a new
166
+ // account given a removed one's name is not).
167
+ const record = stored.length ? connectorAccountInUseRecord(connectorOfServer(cfg)) : null;
168
+ const recorded = record
169
+ ? stored.find(
170
+ (account) => account.name === record.name && record.id && connectorAccountId(cfg, account) === record.id
171
+ )?.name
172
+ : '';
173
+ const inUse = record ? recorded : stored.find(connectorAccountEnabled)?.name;
174
+ const accounts = stored.map((account) =>
175
+ accountRow(connectorAccountServer(cfg, account), connectorAccountEnabled(account), account.name === inUse)
176
+ );
160
177
  // A connector server none of whose accounts is signed in needs a sign-in, not a repair.
161
178
  const accountsSignIn = accounts.length > 0 && accounts.every((account) => account.authRequired === true);
162
179
  const status = mcpServerStatus(
@@ -18,20 +18,23 @@ export function createServerConnection({
18
18
  // change never triggers a full disconnectAll()/reconnect freeze. Only an
19
19
  // explicit sign-in passes `login` ({ openBrowser }): every other connect is
20
20
  // non-interactive and reports a server that needs one as sign-in required.
21
+ // Answers the connect's failure (recorded in state.mcpFailures), null once
22
+ // it connected or disconnected. The server's fingerprint is recorded only
23
+ // once it connected, so one that failed is connected again by the next
24
+ // reconcile although its config is unchanged.
21
25
  async function applyMcpServerConnection(name, enabled, servers = resolveEffectiveMcpServers().servers, login = null) {
22
26
  const target = clean(name);
23
- if (!target) return;
27
+ if (!target) return null;
24
28
  // Changing this server's state clears any stale failure record for it.
25
29
  if (Array.isArray(state.mcpFailures)) {
26
30
  state.mcpFailures = state.mcpFailures.filter((row) => row.name !== target);
27
31
  }
28
32
  const cfg = servers[target];
33
+ applied().delete(target);
29
34
  if (enabled === false || !cfg || cfg.enabled === false) {
30
- applied().delete(target);
31
35
  await mcpClient.disconnectMcpServer?.(target, scopeOptions());
32
- return;
36
+ return null;
33
37
  }
34
- applied().set(target, fingerprint(cfg));
35
38
  // Close-then-connect as one generation-guarded op: a shutdown landing
36
39
  // between the close and the connect never resurrects the server.
37
40
  try {
@@ -42,29 +45,52 @@ export function createServerConnection({
42
45
  cfg,
43
46
  login ? { interactive: true, openBrowser: login.openBrowser } : {}
44
47
  );
48
+ applied().set(target, fingerprint(cfg));
49
+ return null;
45
50
  } catch (error) {
46
51
  const failure = { name: target, msg: error?.message || String(error) };
47
52
  if (error?.authRequired) failure.authRequired = true;
48
53
  const failures = Array.isArray(error?.failures) ? error.failures : [failure];
49
54
  state.mcpFailures = [...(state.mcpFailures || []), ...failures];
55
+ return failure;
50
56
  }
51
57
  }
52
58
 
53
59
  // Bring the registry in line with the effective set: drop servers that are
54
60
  // gone or disabled, (re)connect servers that are new or whose resolved
55
- // config changed; untouched servers keep their connection.
61
+ // config changed; untouched servers keep their connection. A server whose
62
+ // last connect failed is retried too (one the full connect recorded as
63
+ // connected included): reconcile also runs when a sign-in or a stored
64
+ // credential changed (possibly in another process), which leaves its
65
+ // config, and so its fingerprint, as it was; so is a connection the client
66
+ // reports dead. Answers the failures of this run that are not a needed
67
+ // sign-in (that waits on the user, whose sign-in reconciles again); they
68
+ // stay in the status, which the change step checks to retry them.
56
69
  async function reconcileServers() {
57
70
  syncScopeRoot();
58
71
  const { servers } = resolveEffectiveMcpServers();
59
72
  const known = applied();
60
- const drops = [...known.keys()].filter((name) => !servers[name] || servers[name].enabled === false);
73
+ const dead = (mcpClient.getMcpServerStatus?.(getMcpScopeId()) || [])
74
+ .filter((row) => row.alive === false || row.connected === false)
75
+ .map((row) => row.name);
76
+ const failed = new Set([
77
+ ...(Array.isArray(state.mcpFailures) ? state.mcpFailures : []).map((row) => row.name),
78
+ ...dead,
79
+ ]);
80
+ const drops = [...new Set([...known.keys(), ...failed])].filter(
81
+ (name) => !servers[name] || servers[name].enabled === false
82
+ );
61
83
  const connects = Object.entries(servers)
62
- .filter(([name, cfg]) => cfg?.enabled !== false && known.get(name) !== fingerprint(cfg))
84
+ .filter(([name, cfg]) => cfg?.enabled !== false && (known.get(name) !== fingerprint(cfg) || failed.has(name)))
63
85
  .map(([name]) => name);
64
- await Promise.allSettled([
86
+ const results = await Promise.allSettled([
65
87
  ...drops.map((name) => applyMcpServerConnection(name, false, servers)),
66
88
  ...connects.map((name) => applyMcpServerConnection(name, true, servers)),
67
89
  ]);
90
+ return results.flatMap((one) => {
91
+ if (one.status === 'rejected') return [{ msg: one.reason?.message || String(one.reason) }];
92
+ return one.value && !one.value.authRequired ? [one.value] : [];
93
+ });
68
94
  }
69
95
 
70
96
  return { applyMcpServerConnection, reconcileServers };
@@ -79,8 +79,11 @@ export function createMcpServerInput({ mcpClient, getCurrentCwd }) {
79
79
  const type = clean(input.type).toLowerCase();
80
80
  if (url) {
81
81
  const kind = URL_TRANSPORT_TYPES.get(type) || (/^wss?:\/\//i.test(url) ? 'ws' : 'http');
82
- const secureUrl =
82
+ const normalizedUrl =
83
83
  typeof mcpClient.normalizeMcpTransportUrl === 'function' ? mcpClient.normalizeMcpTransportUrl(url, kind) : url;
84
+ // URL parsing adds a "/" to a bare origin (`https://mcp.stripe.com`):
85
+ // keep the address as it was given, as the catalog and legacy entries do.
86
+ const secureUrl = normalizedUrl === `${url}/` ? url : normalizedUrl;
84
87
  return { name, config: withOptionalHeaders({ type: kind, url: secureUrl }) };
85
88
  }
86
89
  const command = clean(input.command);
@@ -635,7 +635,7 @@ export function createMixyHeartbeat({
635
635
  now = Date.now,
636
636
  path = defaultStatePath(),
637
637
  isEnabled = async () =>
638
- (await import('../runtime/agent/orchestrator/config.mjs')).loadConfig({ secrets: false }).heartbeat !== false,
638
+ (await import('../runtime/agent/orchestrator/config.mjs')).loadConfig({ secrets: false }).heartbeat === true,
639
639
  // Whether the representative bot exists (mixy-presence.mjs, the rule the
640
640
  // desktop and her routines follow): without it no check runs at all.
641
641
  mixyExists = async () => (await import('./routine-owner.mjs')).readMixyExists(),
@@ -136,6 +136,23 @@ function refreshSessionFallbacks(deps, session) {
136
136
  deps.mgr.updateSessionRoute?.(session.id, fields, { session });
137
137
  }
138
138
 
139
+ /** The route fields a model pick held for the next turn keeps on its session. */
140
+ function heldRoutePick(route) {
141
+ const pick = {
142
+ provider: route.provider,
143
+ model: route.model,
144
+ ...(route.preset ? { preset: route.preset } : {}),
145
+ ...(route.effort !== undefined ? { effort: route.effort } : {}),
146
+ fast: route.fast === true,
147
+ ...(route.autoEffort === false ? { autoEffort: false } : {}),
148
+ ...(route.modelParameters ? { modelParameters: route.modelParameters } : {}),
149
+ ...(route.contextPercent !== undefined ? { contextPercent: route.contextPercent } : {}),
150
+ ...(route.contextTokens ? { contextTokens: route.contextTokens } : {}),
151
+ ...(route.selectedContextWindow ? { selectedContextWindow: route.selectedContextWindow } : {}),
152
+ };
153
+ return pick;
154
+ }
155
+
139
156
  /** Rewrite the addressed empty session to the route it was asked to run on. */
140
157
  function updateSessionInPlace(deps, session, updateOptions) {
141
158
  const { getRoute, getSession, setSession, mgr, statusRoutes } = deps;
@@ -386,9 +403,16 @@ export function createSetRoute(deps, persist) {
386
403
  const session = getSession();
387
404
  if (options.deferUntilNextTurn === true) {
388
405
  pending = session?.id ? { generation: lease.token } : null;
406
+ // Held on the session too (saved like a pending workflow switch), so a
407
+ // restart before the next turn still applies it.
408
+ if (session?.id) {
409
+ session.pendingRoute = heldRoutePick(getRoute());
410
+ deps.persistSession?.(session);
411
+ }
389
412
  return getRoute();
390
413
  }
391
414
  pending = null;
415
+ if (session?.pendingRoute) delete session.pendingRoute;
392
416
  // A session the user has already talked in or compacted keeps its route
393
417
  // unless the selection was addressed to it. A current session with no
394
418
  // model reply, no compaction summary and no in-flight first turn — empty,
@@ -436,21 +460,30 @@ export function createSetRoute(deps, persist) {
436
460
  return getRoute();
437
461
  }
438
462
  setRoute.applyPendingRoute = () => {
439
- if (!pending) return null;
440
- const selection = pending;
441
- if (selection.generation !== getSessionGeneration()) {
463
+ const session = getSession();
464
+ const held = session?.pendingRoute;
465
+ if (session && held) delete session.pendingRoute;
466
+ if (pending) {
467
+ const selection = pending;
442
468
  pending = null;
469
+ if (selection.generation !== getSessionGeneration()) return null;
470
+ // The live route is the latest selection: effort/Fast tuned after the
471
+ // deferred model choice replace it.
472
+ } else if (held?.provider && held.model) {
473
+ // Held by an earlier process (a restart in between): the saved pick
474
+ // becomes the live route again.
475
+ deps.setRouteState(deps.resolveRoute(deps.getConfig(), held));
476
+ } else {
443
477
  return null;
444
478
  }
445
- // The live route is the latest selection: effort/Fast tuned after the
446
- // deferred model choice replace it, so no snapshot is kept.
447
- const modelSwitch = switchSessionInPlace(deps, getSession());
479
+ const modelSwitch = switchSessionInPlace(deps, session);
448
480
  invalidateContextStatusCache();
449
- pending = null;
450
481
  return modelSwitch;
451
482
  };
452
483
  setRoute.clearPendingRoute = () => {
453
484
  pending = null;
485
+ const session = getSession();
486
+ if (session?.pendingRoute) delete session.pendingRoute;
454
487
  };
455
488
  return setRoute;
456
489
  }
@@ -46,9 +46,9 @@ export function createWebSearchRouteCandidates({
46
46
  await awaitKeychainPrewarm();
47
47
  const cfg = ensureFullConfig();
48
48
  // An unset webSearchRoute IS the default ("follow the Main Model") — the
49
- // sidebar has always presented it that way. Materialize it here instead of
50
- // treating a missing key as "not configured", which used to fail the search
51
- // before the Main Model was ever consulted.
49
+ // sidebar presents it that way. Materialize it here instead of treating a
50
+ // missing key as "not configured", which would fail the search before the
51
+ // Main Model is consulted.
52
52
  const webSearchRoute = webSearchRouteOrDefault(cfg.webSearchRoute, getWebSearchRoute());
53
53
  setWebSearchRoute(webSearchRoute);
54
54
  const candidates = [];
@@ -61,8 +61,8 @@ export function createLoginApi({ cfgMod, awaitKeychainPrewarm, reloadFullConfig,
61
61
  reloadFullConfig();
62
62
  return completeOAuthLogin(result);
63
63
  },
64
- async saveProviderApiKey(providerId, secret) {
65
- const result = await saveProviderApiKey(cfgMod, providerId, secret);
64
+ async saveProviderApiKey(providerId, secret, options) {
65
+ const result = await saveProviderApiKey(cfgMod, providerId, secret, options);
66
66
  refresh.afterCredentialChange();
67
67
  return result;
68
68
  },
@@ -3,7 +3,7 @@
3
3
  import { resetProviderAdmissionCooldowns } from '../../runtime/agent/orchestrator/providers/admission-scheduler.mjs';
4
4
 
5
5
  export function createAuthRefresh({
6
- reloadFullConfig,
6
+ applyConfigChange,
7
7
  invalidateProviderCaches,
8
8
  warmProviderModelCache,
9
9
  refreshProviderCatalogs,
@@ -42,14 +42,17 @@ export function createAuthRefresh({
42
42
  warmProviderModelCache();
43
43
  }
44
44
 
45
+ // The change step (reload + effects keyed by the config/secret change) runs
46
+ // here at once rather than on the notification that follows, so this
47
+ // runtime's notification finds the change already applied.
45
48
  function afterCredentialChange() {
46
- reloadFullConfig();
49
+ applyConfigChange();
47
50
  adoptCredentials();
48
51
  }
49
52
 
50
53
  /** Usage-dashboard credentials affect no admission lane or catalog. */
51
54
  function afterUsageAuthChange() {
52
- reloadFullConfig();
55
+ applyConfigChange();
53
56
  invalidateProviderCaches();
54
57
  }
55
58
 
@@ -48,7 +48,7 @@ export function createSetupApi({
48
48
  return cachedProviderSetup({ force: force || options?.recheckKeychain === true });
49
49
  }
50
50
  // An unforced read never blocks: the authoritative setup waits on the OS
51
- // keychain, which can take seconds on a cold start and used to stall the
51
+ // keychain, which can take seconds on a cold start and would stall the
52
52
  // whole settings sweep behind it. Serve
53
53
  // the no-secrets snapshot until the real one is cached — flagged, so the
54
54
  // caller shows "checking" instead of a wrong "not connected" — and let the
@@ -51,6 +51,13 @@ export function createProviderReadiness({ rt, keychain, getReg, getWarmProviderM
51
51
  const providerModelCaches = { ...emptyModelCaches(), providerModelsLoadSeq: 0 };
52
52
  const providerUsageCaches = emptyUsageCaches();
53
53
  const providerInitPromises = new Map();
54
+ // Whether this runtime has started its providers: a rebuild after a change
55
+ // follows it, a failed initialization (whose gate is dropped) included.
56
+ let providersStarted = false;
57
+ // Advances whenever the init gates are cleared (a provider config or
58
+ // credential change): an initialization registered before it is superseded
59
+ // and never writes the shared registry.
60
+ let providerInitGeneration = 0;
54
61
 
55
62
  function invalidateProviderCaches(options = {}) {
56
63
  // Auth/account/config changes alter what providers list: the process-wide
@@ -59,7 +66,10 @@ export function createProviderReadiness({ rt, keychain, getReg, getWarmProviderM
59
66
  Object.assign(providerModelCaches, emptyModelCaches());
60
67
  providerModelCaches.providerModelsLoadSeq += 1;
61
68
  Object.assign(providerUsageCaches, emptyUsageCaches());
62
- if (options.preserveProviderInit !== true) providerInitPromises.clear();
69
+ if (options.preserveProviderInit !== true) {
70
+ providerInitPromises.clear();
71
+ providerInitGeneration += 1;
72
+ }
63
73
  modelMetaByRoute.clear();
64
74
  }
65
75
 
@@ -67,19 +77,44 @@ export function createProviderReadiness({ rt, keychain, getReg, getWarmProviderM
67
77
  // absent (provider setup, init gates) is stale.
68
78
  keychain.onKeychainRecovered?.(() => invalidateProviderCaches());
69
79
 
70
- async function ensureProvidersReady(providerConfig = rt.config.providers || {}) {
80
+ // The one edit a caller makes to the provider config it passes is turning a
81
+ // route's provider on (ensureProviderEnabled); those providers, judged
82
+ // against the runtime's config when the request was made.
83
+ function forcedProviders(requested, base) {
84
+ return Object.keys(requested || {}).filter(
85
+ (name) => requested[name]?.enabled === true && base?.[name]?.enabled !== true
86
+ );
87
+ }
88
+
89
+ // Waits for the keychain, then initializes the registry with
90
+ // `providerConfig` unless a change superseded it meanwhile: a superseded
91
+ // request is replayed on the latest config (with the providers it turned on),
92
+ // so the latest config always wins.
93
+ async function initializeProviders(providerConfig) {
94
+ const generation = providerInitGeneration;
95
+ const forced = forcedProviders(providerConfig, rt.config.providers);
71
96
  await awaitKeychainPrewarm();
72
97
  if (rt.closeRequested) throw new Error('runtime is closing');
98
+ if (generation === providerInitGeneration) return getReg().initProviders(providerConfig);
99
+ const latest = { ...(rt.config.providers || {}) };
100
+ for (const name of forced) latest[name] = { ...(latest[name] || {}), enabled: true };
101
+ return ensureProvidersReady(latest);
102
+ }
103
+
104
+ async function ensureProvidersReady(providerConfig = rt.config.providers || {}) {
105
+ if (rt.closeRequested) throw new Error('runtime is closing');
106
+ providersStarted = true;
73
107
  const initKey = providerInitCacheKey(providerConfig);
74
108
  // Provider initialization is idempotent for one normalized config. Keep
75
109
  // the fulfilled promise, not only the in-flight one: session resume used
76
110
  // to rerun registry/keychain setup on every click even though neither the
77
111
  // provider config nor the registry had changed. Auth/config mutations call
78
112
  // invalidateProviderCaches(), which clears this gate and preserves the
79
- // existing refresh semantics.
113
+ // existing refresh semantics. Registered before any await, so a change
114
+ // applied while it waits on the keychain sees (and supersedes) it.
80
115
  let providerInitPromise = providerInitPromises.get(initKey);
81
116
  if (!providerInitPromise) {
82
- providerInitPromise = Promise.resolve().then(() => getReg().initProviders(providerConfig));
117
+ providerInitPromise = initializeProviders(providerConfig);
83
118
  providerInitPromises.set(initKey, providerInitPromise);
84
119
  }
85
120
  let result;
@@ -125,9 +160,23 @@ export function createProviderReadiness({ rt, keychain, getReg, getWarmProviderM
125
160
  return result;
126
161
  }
127
162
 
163
+ // Provider config or secrets changed: drop everything keyed to the old ones
164
+ // and, when this runtime had initialized providers, rebuild the shared
165
+ // registry from its reloaded config now, so no runtime's stale copy is the
166
+ // last one to have initialized it. Rejects when that rebuild failed.
167
+ function reinitProviders() {
168
+ invalidateProviderCaches();
169
+ if (!providersStarted || rt.closeRequested) return Promise.resolve();
170
+ return ensureProvidersReady().catch((error) => {
171
+ bootProfile('providers:reinit-failed', { error: error?.message || String(error) });
172
+ throw error;
173
+ });
174
+ }
175
+
128
176
  return {
129
177
  awaitKeychainPrewarm,
130
178
  invalidateProviderCaches,
179
+ reinitProviders,
131
180
  ensureProvidersReady,
132
181
  modelMetaByRoute,
133
182
  providerModelCaches,
@@ -31,7 +31,7 @@ export function createResourceApi(deps) {
31
31
  throw new Error(`extension scope kind must be one of ${EXTENSION_SCOPE_KINDS.join(', ')}`);
32
32
  }
33
33
  // A connector is on in every project unless a project switches it off
34
- // (setProjectConnectorEnabled); "only in this project" no longer exists.
34
+ // (setProjectConnectorEnabled); there is no "only in this project" scope.
35
35
  if (scopeKind === 'mcp') {
36
36
  throw new Error('MCP servers are switched off per project in Project settings (setProjectConnectorEnabled)');
37
37
  }
@@ -7,7 +7,6 @@ export function createExtensionSync({
7
7
  connectConfiguredMcp,
8
8
  cancelMcpLogin,
9
9
  invalidatePreSessionToolSurface,
10
- refreshEmptySessionToolPolicy,
11
10
  reloadFullConfig,
12
11
  invalidateSkills,
13
12
  }) {
@@ -19,14 +18,11 @@ export function createExtensionSync({
19
18
  // session.
20
19
  const mcpToggleChains = new Map(); // name -> { desired, running }
21
20
 
22
- async function refreshSurface(kind) {
21
+ // The invalidation moves the surface generation: an empty session rebuilds
22
+ // at its next turn start (reconcileTurnSettings); MCP has its own
23
+ // first-turn/late-tool reconciliation against the live connection registry.
24
+ async function refreshSurface() {
23
25
  invalidatePreSessionToolSurface();
24
- // Existing conversations retain their stable prompt/session identity.
25
- // Empty sessions can safely rebuild their policy in place; MCP has its own
26
- // first-turn/late-tool reconciliation against the live connection registry.
27
- if ((kind === 'skills' || kind === 'plugins') && typeof refreshEmptySessionToolPolicy === 'function') {
28
- await refreshEmptySessionToolPolicy();
29
- }
30
26
  }
31
27
 
32
28
  // Apply per-server MCP changes in order, then reconcile: a configured server