mixdog 1.1.2 → 1.2.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 (424) hide show
  1. package/README.md +8 -5
  2. package/package.json +2 -1
  3. package/scripts/lib/run-node-tests.mjs +9 -0
  4. package/scripts/prune-desktop-runtime.mjs +3 -0
  5. package/scripts/test-direct.mjs +4 -2
  6. package/src/defaults/shipped-history.json +10 -0
  7. package/src/defaults/skills/pptx/SKILL.md +6 -6
  8. package/src/defaults/skills/pptx/references/review.md +6 -4
  9. package/src/defaults/skills/pptx/scripts/source-extract.mjs +1 -1
  10. package/src/defaults/skills/setup/references/actions.md +18 -5
  11. package/src/defaults/skills/visualize/SKILL.md +160 -0
  12. package/src/defaults/skills/visualize/references/craft.md +88 -0
  13. package/src/headless-command.mjs +56 -3
  14. package/src/headless-exec.mjs +17 -1
  15. package/src/help.mjs +2 -0
  16. package/src/rules/shared/60-verification.md +3 -1
  17. package/src/rules/shared/70-delivery.md +4 -2
  18. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
  19. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +1 -0
  20. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +2 -0
  21. package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
  22. package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
  23. package/src/runtime/agent/orchestrator/config-providers-merge.mjs +17 -11
  24. package/src/runtime/agent/orchestrator/config-storage.mjs +1 -0
  25. package/src/runtime/agent/orchestrator/config.mjs +19 -5
  26. package/src/runtime/agent/orchestrator/context/collect.mjs +2 -1
  27. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +11 -5
  28. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +74 -21
  29. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +133 -15
  30. package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +55 -8
  31. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +86 -8
  32. package/src/runtime/agent/orchestrator/mcp/client.mjs +474 -164
  33. package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
  34. package/src/runtime/agent/orchestrator/mcp/plugin-placeholders.mjs +54 -0
  35. package/src/runtime/agent/orchestrator/mcp/reconnect-singleflight.mjs +4 -0
  36. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +108 -17
  37. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  38. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +3 -0
  39. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +15 -1
  40. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +32 -12
  41. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -0
  42. package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +9 -0
  43. package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +337 -0
  44. package/src/runtime/agent/orchestrator/providers/command-code-oauth-tokens.mjs +159 -0
  45. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +444 -0
  46. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +2 -0
  47. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  48. package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +2 -1
  49. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
  50. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +21 -6
  51. package/src/runtime/agent/orchestrator/providers/effort-rejection.mjs +244 -0
  52. package/src/runtime/agent/orchestrator/providers/gemini.mjs +41 -28
  53. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  54. package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
  55. package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
  56. package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +8 -40
  57. package/src/runtime/agent/orchestrator/providers/mimo-oauth-tokens.mjs +2 -0
  58. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +51 -12
  59. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +37 -2
  60. package/src/runtime/agent/orchestrator/providers/model-proxy-bridge.mjs +1080 -0
  61. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +82 -0
  62. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +556 -0
  63. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +251 -0
  64. package/src/runtime/agent/orchestrator/providers/muse-code-oauth-tokens.mjs +2 -0
  65. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +69 -102
  66. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +15 -0
  67. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
  68. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -1
  69. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +6 -2
  70. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +11 -0
  71. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +2 -1
  72. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +15 -4
  73. package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog-store.mjs +1 -1
  74. package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +5 -2
  75. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +3 -0
  76. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +4 -4
  77. package/src/runtime/agent/orchestrator/providers/registry.mjs +47 -7
  78. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +10 -0
  79. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +36 -3
  80. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -11
  81. package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +15 -55
  82. package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +15 -2
  83. package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +16 -1
  84. package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +278 -84
  85. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +4 -1
  86. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +21 -0
  87. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +54 -3
  88. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +10 -3
  89. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -0
  90. package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.mjs +9 -5
  91. package/src/runtime/agent/orchestrator/session/cache/read-cache.mjs +18 -8
  92. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
  93. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +268 -0
  94. package/src/runtime/agent/orchestrator/session/catalog-db/sqlite-gate.mjs +27 -0
  95. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +628 -0
  96. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +10 -3
  97. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +24 -13
  98. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +13 -5
  99. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +362 -0
  100. package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +253 -0
  101. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +184 -0
  102. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +136 -0
  103. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +128 -0
  104. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +127 -0
  105. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +101 -0
  106. package/src/runtime/agent/orchestrator/session/explicit-skills.mjs +83 -5
  107. package/src/runtime/agent/orchestrator/session/imported-message.mjs +11 -0
  108. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +2 -1
  109. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -1
  110. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/continuation.mjs +1 -1
  111. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/diagnostic.mjs +1 -7
  112. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/refusal.mjs +1 -1
  113. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +3 -2
  114. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +5 -3
  115. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +7 -4
  116. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +21 -10
  117. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
  118. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +3 -0
  119. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -3
  120. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +15 -3
  121. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +22 -12
  122. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +9 -2
  123. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +9 -3
  124. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +5 -2
  125. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +37 -16
  126. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +4 -0
  127. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +17 -4
  128. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +90 -0
  129. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +22 -12
  130. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +32 -3
  131. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +27 -0
  132. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -1
  133. package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +1 -0
  134. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +2 -0
  135. package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
  136. package/src/runtime/agent/orchestrator/session/message-ids.mjs +123 -0
  137. package/src/runtime/agent/orchestrator/session/message-ids.test-support.mjs +29 -0
  138. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +33 -22
  139. package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
  140. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +3 -0
  141. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
  142. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +10 -3
  143. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +11 -0
  144. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +817 -0
  145. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +36 -0
  146. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +23 -12
  147. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +158 -0
  148. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +202 -374
  149. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +20 -3
  150. package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +3 -1
  151. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +1 -1
  152. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +48 -9
  153. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +161 -0
  154. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +17 -1
  155. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -0
  156. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +52 -2
  157. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +32 -22
  158. package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +10 -3
  159. package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +2 -2
  160. package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +6 -6
  161. package/src/runtime/agent/orchestrator/tools/builtin/read-cache-policy.mjs +8 -0
  162. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +203 -33
  163. package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +32 -35
  164. package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
  165. package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +11 -12
  166. package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +9 -6
  167. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +83 -68
  168. package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +8 -3
  169. package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +20 -3
  170. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +16 -7
  171. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +2 -1
  172. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +137 -0
  173. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +11 -10
  174. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +21 -11
  175. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +12 -1
  176. package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +13 -10
  177. package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +1 -1
  178. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +17 -12
  179. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +56 -13
  180. package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +58 -0
  181. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +2 -2
  182. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
  183. package/src/runtime/agent/orchestrator/tools/code-graph/trusted-roots.mjs +25 -1
  184. package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +4 -4
  185. package/src/runtime/agent/orchestrator/tools/patch/apply-patch/route.mjs +2 -2
  186. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +1 -1
  187. package/src/runtime/agent/orchestrator/tools/patch/read-redirects.mjs +34 -30
  188. package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +7 -7
  189. package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +1 -1
  190. package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +78 -5
  191. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +2 -0
  192. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
  193. package/src/runtime/attachments/store.d.mts +3 -0
  194. package/src/runtime/attachments/store.mjs +38 -0
  195. package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +1 -1
  196. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +16 -4
  197. package/src/runtime/channels/lib/worker-main.mjs +17 -14
  198. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -2
  199. package/src/runtime/effort-judge/judge-client.mjs +56 -18
  200. package/src/runtime/memory/lib/memory.mjs +1 -1
  201. package/src/runtime/memory/lib/session-ingest.mjs +2 -2
  202. package/src/runtime/shared/atomic-file.mjs +33 -6
  203. package/src/runtime/shared/best-effort-stderr.mjs +8 -0
  204. package/src/runtime/shared/code-graph-state.mjs +12 -0
  205. package/src/runtime/shared/defaults-separation.mjs +2 -0
  206. package/src/runtime/shared/extension-scopes.mjs +5 -3
  207. package/src/runtime/shared/file-lock.mjs +37 -11
  208. package/src/runtime/shared/git-runner-worker.mjs +3 -2
  209. package/src/runtime/shared/git-runner.mjs +4 -3
  210. package/src/runtime/shared/llm/anthropic-effort.mjs +14 -0
  211. package/src/runtime/shared/llm/default-context-window.mjs +6 -0
  212. package/src/runtime/shared/llm/model-catalog-projection.mjs +5 -4
  213. package/src/runtime/shared/llm/model-catalog.mjs +240 -130
  214. package/src/runtime/shared/llm/provider-catalog-cache.mjs +36 -28
  215. package/src/runtime/shared/llm/provider-catalog-registry.mjs +162 -0
  216. package/src/runtime/shared/llm/provider-seed-rosters.mjs +130 -0
  217. package/src/runtime/shared/model-proxy-mode.d.mts +3 -0
  218. package/src/runtime/shared/model-proxy-mode.mjs +19 -0
  219. package/src/runtime/shared/plugin-manifest.mjs +18 -9
  220. package/src/runtime/shared/pristine-execution-contract.json +9 -2
  221. package/src/runtime/shared/pristine-execution.mjs +28 -4
  222. package/src/runtime/shared/provider-accounts.mjs +125 -21
  223. package/src/runtime/shared/provider-api-key.mjs +33 -1
  224. package/src/runtime/shared/schedule-model-ref.mjs +11 -2
  225. package/src/runtime/shared/session-usage-totals.mjs +19 -0
  226. package/src/runtime/shared/sharp-electron-linux.mjs +25 -0
  227. package/src/runtime/shared/shell-display.mjs +9 -3
  228. package/src/runtime/shared/singleton-owner.mjs +36 -6
  229. package/src/runtime/shared/skill-mentions.d.mts +10 -0
  230. package/src/runtime/shared/skill-mentions.mjs +133 -0
  231. package/src/runtime/shared/skill-script-runtime.mjs +264 -0
  232. package/src/runtime/shared/statusline/statusline-segments.mjs +68 -14
  233. package/src/runtime/shared/tool-primitives.mjs +35 -2
  234. package/src/runtime/shared/tool-surface.mjs +7 -0
  235. package/src/runtime/shared/tool-work-units.mjs +14 -0
  236. package/src/runtime/shared/transcript-metadata.mjs +17 -1
  237. package/src/runtime/shared/turn-changes.mjs +791 -0
  238. package/src/runtime/shared/turn-snapshot-store.mjs +346 -12
  239. package/src/runtime/shared/turn-snapshot.mjs +690 -81
  240. package/src/runtime/shared/turn-worktree-snapshot.mjs +185 -15
  241. package/src/runtime/shared/worker-requests.mjs +15 -2
  242. package/src/runtime/shared/worktrees/cache-cleanups.mjs +52 -0
  243. package/src/runtime/shared/worktrees/contract.mjs +551 -0
  244. package/src/runtime/shared/worktrees/disk.mjs +57 -0
  245. package/src/runtime/shared/worktrees/git.mjs +247 -0
  246. package/src/runtime/shared/worktrees/include.mjs +480 -0
  247. package/src/runtime/shared/worktrees/lock.mjs +46 -0
  248. package/src/runtime/shared/worktrees/maintenance.mjs +96 -0
  249. package/src/runtime/shared/worktrees/manager.mjs +1215 -0
  250. package/src/runtime/shared/worktrees/merge.mjs +182 -0
  251. package/src/runtime/shared/worktrees/owner.mjs +46 -0
  252. package/src/runtime/shared/worktrees/paths.mjs +62 -0
  253. package/src/runtime/shared/worktrees/registry.mjs +110 -0
  254. package/src/runtime/shared/worktrees/settings.mjs +84 -0
  255. package/src/runtime/shared/worktrees/slug.mjs +62 -0
  256. package/src/runtime/shared/worktrees/test-support.mjs +96 -0
  257. package/src/runtime/visualize-bridge/client.mjs +181 -0
  258. package/src/runtime/visualize-bridge/tool-defs.mjs +97 -0
  259. package/src/session-runtime/automation-agents.mjs +8 -2
  260. package/src/session-runtime/boot/apis.mjs +90 -0
  261. package/src/session-runtime/boot/config.mjs +7 -2
  262. package/src/session-runtime/boot/facade.mjs +21 -0
  263. package/src/session-runtime/boot/infrastructure.mjs +30 -18
  264. package/src/session-runtime/boot/session.mjs +1 -0
  265. package/src/session-runtime/boot/tools.mjs +4 -0
  266. package/src/session-runtime/config-lifecycle.mjs +10 -1
  267. package/src/session-runtime/conversation-import/discovery.mjs +698 -0
  268. package/src/session-runtime/conversation-import/service.mjs +369 -0
  269. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +21 -6
  270. package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
  271. package/src/session-runtime/global-extensions.mjs +2 -2
  272. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +27 -2
  273. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +32 -1
  274. package/src/session-runtime/internal-tool-executor.mjs +9 -1
  275. package/src/session-runtime/lifecycle/session-catalog.mjs +8 -1
  276. package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +5 -0
  277. package/src/session-runtime/lifecycle/session-switch/resume.mjs +21 -3
  278. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +16 -0
  279. package/src/session-runtime/mcp-glue/connect.mjs +68 -16
  280. package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
  281. package/src/session-runtime/mcp-glue/server-catalog.mjs +122 -33
  282. package/src/session-runtime/mcp-glue/server-input.mjs +29 -0
  283. package/src/session-runtime/mcp-glue.mjs +22 -2
  284. package/src/session-runtime/model-route/route-persist.mjs +3 -0
  285. package/src/session-runtime/model-route/set-route.mjs +15 -2
  286. package/src/session-runtime/new-session-config.mjs +3 -2
  287. package/src/session-runtime/notification-bus.mjs +18 -3
  288. package/src/session-runtime/provider-auth/accounts.mjs +33 -15
  289. package/src/session-runtime/provider-models/row-hydration.mjs +2 -0
  290. package/src/session-runtime/provider-models/web-search-catalog.mjs +5 -1
  291. package/src/session-runtime/provider-readiness.mjs +16 -10
  292. package/src/session-runtime/resource-extension-sync.mjs +45 -7
  293. package/src/session-runtime/resource-mcp-api.mjs +121 -84
  294. package/src/session-runtime/resource-plugins-api.mjs +29 -41
  295. package/src/session-runtime/resource-scope-decorate.mjs +6 -8
  296. package/src/session-runtime/resource-skills-api.mjs +23 -2
  297. package/src/session-runtime/route-resolution.mjs +10 -1
  298. package/src/session-runtime/route-state.mjs +16 -2
  299. package/src/session-runtime/runtime-core.mjs +5 -0
  300. package/src/session-runtime/runtime-facade.mjs +8 -0
  301. package/src/session-runtime/runtime-review-api.mjs +9 -0
  302. package/src/session-runtime/schedule-session-run.mjs +1 -1
  303. package/src/session-runtime/services/agent-tool/helpers.mjs +5 -0
  304. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +3 -0
  305. package/src/session-runtime/services/agent-tool/job-views/job-lookup.mjs +1 -0
  306. package/src/session-runtime/services/agent-tool/job-views/spawn-meta.mjs +1 -0
  307. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +15 -0
  308. package/src/session-runtime/services/agent-tool/send-flow.mjs +1 -0
  309. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +10 -2
  310. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -7
  311. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
  312. package/src/session-runtime/services/agent-tool/tag-registry.mjs +2 -1
  313. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -0
  314. package/src/session-runtime/services/agent-tool/worker-rows.mjs +1 -0
  315. package/src/session-runtime/services/agent-tool.mjs +1 -0
  316. package/src/session-runtime/services/channel-session-router.mjs +4 -1
  317. package/src/session-runtime/services/daemon-candidate.mjs +3 -2
  318. package/src/session-runtime/services/daemon-crash-capture/spawn-capture.mjs +55 -0
  319. package/src/session-runtime/services/hook-bus/command-handler.mjs +4 -1
  320. package/src/session-runtime/services/hook-bus/handlers.mjs +7 -3
  321. package/src/session-runtime/services/provider-admin.mjs +64 -18
  322. package/src/session-runtime/services/usage-dashboard-model.mjs +3 -0
  323. package/src/session-runtime/session-create/session-options.mjs +10 -1
  324. package/src/session-runtime/session-turn-api.mjs +1 -0
  325. package/src/session-runtime/settings-api.mjs +4 -2
  326. package/src/session-runtime/settings-builtin-tools-api.mjs +9 -2
  327. package/src/session-runtime/settings-worktree-api.mjs +17 -0
  328. package/src/session-runtime/setup-tool/executor.mjs +23 -5
  329. package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
  330. package/src/session-runtime/setup-tool/settings-contract.mjs +4 -1
  331. package/src/session-runtime/setup-tool/tool-defs.mjs +38 -4
  332. package/src/session-runtime/skills-api.mjs +7 -3
  333. package/src/session-runtime/turn/agent-ops.mjs +12 -1
  334. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +14 -3
  335. package/src/session-runtime/turn/turn-run/snapshot-tracker.mjs +20 -15
  336. package/src/session-runtime/turn/turn-run/turn-open.mjs +4 -5
  337. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +29 -1
  338. package/src/session-runtime/turn/turn-run/turn-settle.mjs +6 -1
  339. package/src/session-runtime/turn/turn-run.mjs +6 -7
  340. package/src/session-runtime/webhook-session-run.mjs +16 -4
  341. package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -3
  342. package/src/session-runtime/workspace/admission-gate.mjs +197 -0
  343. package/src/session-runtime/workspace/project-branches.mjs +136 -0
  344. package/src/session-runtime/workspace/transition-steps.mjs +364 -0
  345. package/src/session-runtime/workspace/transitions.mjs +651 -0
  346. package/src/session-runtime/workspace/workspace-state.mjs +112 -0
  347. package/src/skill-script-entry.mjs +36 -0
  348. package/src/standalone/channel-transport/http-routes.mjs +17 -0
  349. package/src/standalone/channel-transport.mjs +13 -1
  350. package/src/standalone/daemon-desktop-runtime.mjs +1 -0
  351. package/src/standalone/daemon-owner.mjs +372 -0
  352. package/src/standalone/daemon-stored-session-views.mjs +15 -4
  353. package/src/standalone/daemon.mjs +179 -8
  354. package/src/standalone/desktop-service-registry.mjs +20 -0
  355. package/src/standalone/local-session-runtime.mjs +11 -0
  356. package/src/standalone/session-client/attachment-calls.mjs +3 -1
  357. package/src/standalone/session-client/daemon-unavailable.mjs +62 -0
  358. package/src/standalone/session-client/lease-heartbeat.mjs +47 -0
  359. package/src/standalone/session-client.mjs +104 -13
  360. package/src/standalone/session-protocol.mjs +21 -0
  361. package/src/standalone/session-proxy.mjs +3 -0
  362. package/src/standalone/session-service/agent-tree/agent-child.mjs +4 -0
  363. package/src/standalone/session-service/agent-tree/agent-rehydrate.mjs +1 -0
  364. package/src/standalone/session-service/entries/lifecycle.mjs +6 -0
  365. package/src/standalone/session-service/projection/revisions.mjs +2 -0
  366. package/src/standalone/session-service/projection/transcript-window.mjs +149 -19
  367. package/src/standalone/session-service/projection/workspace.mjs +14 -0
  368. package/src/standalone/session-service/session-calls/session-action.mjs +17 -4
  369. package/src/standalone/session-transport/call-route.mjs +13 -0
  370. package/src/standalone/session-transport/client-registry/client-grace.mjs +45 -3
  371. package/src/standalone/session-transport/client-registry/registration-replays.mjs +1 -0
  372. package/src/standalone/session-transport/client-registry.mjs +20 -3
  373. package/src/standalone/session-transport/routes.mjs +79 -2
  374. package/src/standalone/session-transport/stack.mjs +2 -0
  375. package/src/standalone/session-transport.mjs +24 -1
  376. package/src/tui/App.jsx +9 -1
  377. package/src/tui/app/app-view/floating-panel.jsx +9 -1
  378. package/src/tui/app/app-view.jsx +6 -0
  379. package/src/tui/app/extension-pickers/plugins-pickers.mjs +35 -16
  380. package/src/tui/app/message-selector.mjs +2 -1
  381. package/src/tui/app/model-options.mjs +37 -5
  382. package/src/tui/app/model-picker/provider-models-list.mjs +2 -2
  383. package/src/tui/app/model-picker.mjs +4 -2
  384. package/src/tui/app/skill-mention-palette.mjs +88 -0
  385. package/src/tui/app/slash-palette.mjs +23 -7
  386. package/src/tui/app/transcript-row-estimate.mjs +11 -3
  387. package/src/tui/app/use-prompt-draft-flow.mjs +7 -2
  388. package/src/tui/app/use-prompt-state.mjs +5 -0
  389. package/src/tui/components/Message.jsx +22 -1
  390. package/src/tui/components/PromptInput.jsx +21 -3
  391. package/src/tui/components/SlashCommandPalette.jsx +12 -3
  392. package/src/tui/components/TranscriptItem.jsx +9 -1
  393. package/src/tui/components/prompt-input/key-handler.mjs +21 -8
  394. package/src/tui/components/user-message-skills.mjs +38 -0
  395. package/src/tui/dist/index.mjs +839 -207
  396. package/src/tui/index.jsx +10 -2
  397. package/src/tui/session/compaction-view.mjs +147 -0
  398. package/src/tui/session/context-state.mjs +6 -0
  399. package/src/tui/session/initial-state.mjs +3 -0
  400. package/src/tui/session/queue-helpers.mjs +7 -2
  401. package/src/tui/session/quota-resume.mjs +2 -1
  402. package/src/tui/session/session-api/commands.mjs +10 -2
  403. package/src/tui/session/session-api/controls.mjs +4 -0
  404. package/src/tui/session/session-api/extensions.mjs +4 -2
  405. package/src/tui/session/session-api/intake/rewind.mjs +2 -1
  406. package/src/tui/session/session-api/integrations.mjs +17 -0
  407. package/src/tui/session/session-api/lifecycle/dispose.mjs +6 -1
  408. package/src/tui/session/session-api/lifecycle/inheritance.mjs +2 -0
  409. package/src/tui/session/session-api/lifecycle/resume.mjs +3 -0
  410. package/src/tui/session/session-api/routes.mjs +10 -1
  411. package/src/tui/session/session-api/settings.mjs +9 -0
  412. package/src/tui/session/session-api/worktree.mjs +60 -0
  413. package/src/tui/session/session-api.mjs +2 -0
  414. package/src/tui/session/session-flow/auto-clear.mjs +31 -12
  415. package/src/tui/session/session-flow/drain.mjs +27 -3
  416. package/src/tui/session/session-flow/session-reset.mjs +4 -3
  417. package/src/tui/session/session-flow.mjs +2 -0
  418. package/src/tui/session/transcript-intake.mjs +14 -5
  419. package/src/tui/session/tui-steering-persist.mjs +25 -9
  420. package/src/tui/session/turn-stream.mjs +32 -4
  421. package/src/tui/session/turn-tool-cards.mjs +10 -2
  422. package/src/tui/session/turn.mjs +56 -10
  423. package/src/runtime/effort-judge/previous-human-request.mjs +0 -162
  424. package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
@@ -31,6 +31,7 @@ export function createInternalToolExecutor({
31
31
  mcpStatus,
32
32
  applyResolvedCwd,
33
33
  skillToolContent,
34
+ getWorkspaceApi,
34
35
  }) {
35
36
  const handlers = {
36
37
  ...createBridgeToolHandlers({ rt }),
@@ -46,7 +47,14 @@ export function createInternalToolExecutor({
46
47
  mcpStatus,
47
48
  skillToolContent,
48
49
  }),
49
- ...createWorkspaceToolHandlers({ rt, goalRuntime, agentTool, notifyFnForSession, applyResolvedCwd }),
50
+ ...createWorkspaceToolHandlers({
51
+ rt,
52
+ goalRuntime,
53
+ agentTool,
54
+ notifyFnForSession,
55
+ applyResolvedCwd,
56
+ getWorkspaceApi,
57
+ }),
50
58
  };
51
59
 
52
60
  // Settings-disabled features are refused for model-initiated calls before
@@ -8,7 +8,12 @@ import {
8
8
  isRootLeadSession,
9
9
  } from '../../runtime/agent/orchestrator/session/store-summary-visibility.mjs';
10
10
  import { listSessionHeartbeatMtimes } from '../../runtime/agent/orchestrator/session/store/paths-heartbeat.mjs';
11
- import { sessionMessageText, isSessionPreviewNoise, cleanSessionPreview, clean } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
11
+ import {
12
+ sessionMessageText,
13
+ isSessionPreviewNoise,
14
+ cleanSessionPreview,
15
+ clean,
16
+ } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
12
17
 
13
18
  const VISIBLE_OWNERS = ['cli', 'user', 'mixdog'];
14
19
 
@@ -58,6 +63,8 @@ function leadSessionRow(s, heartbeatMtimes) {
58
63
  // it remains an ordinary resumable session, not a child dispatch.
59
64
  if (!isRootLeadSession(s) && owner && !VISIBLE_OWNERS.includes(owner)) return null;
60
65
  const sourceType = clean(s.sourceType || '').toLowerCase();
66
+ // One-shot `mixdog exec` runs are never resumable conversations.
67
+ if (sourceType === 'exec') return null;
61
68
  if (!isLeadShaped(s, owner, sourceType)) return null;
62
69
  const { preview, messageCount } = previewOf(s);
63
70
  if (!preview && messageCount === 0) return null;
@@ -3,6 +3,7 @@
3
3
  * new desktop context (cwd + desktop session) or a fresh session.
4
4
  */
5
5
  import { isScratchSession } from '../shared.mjs';
6
+ import { replacementSessionCwd } from '../../workspace/workspace-state.mjs';
6
7
 
7
8
  export function createContextSwitch(deps, { ingestSessionIntoMemory, closeSurfaceSession, releaseSessionWork }) {
8
9
  const {
@@ -59,11 +60,15 @@ export function createContextSwitch(deps, { ingestSessionIntoMemory, closeSurfac
59
60
  async function newSession() {
60
61
  deps.assertNotAddressed?.('newSession');
61
62
  const session = getSession();
63
+ // Leaving a worktree-bound Lead: the new session starts in the Project
64
+ // folder, never in the worktree the old session retains.
65
+ const projectFolder = replacementSessionCwd(session);
62
66
  if (session?.id) {
63
67
  void ingestSessionIntoMemory(session);
64
68
  closeSurfaceSession(session, 'cli-new', { tombstone: isScratchSession(session) });
65
69
  setSession(null);
66
70
  }
71
+ if (projectFolder) await applyResolvedCwd(projectFolder);
67
72
  invalidateContextStatusCache();
68
73
  await createCurrentSession();
69
74
  return getSession().id;
@@ -10,8 +10,16 @@ import {
10
10
  deferredSurfaceModeForLead,
11
11
  } from '../../../runtime/agent/orchestrator/runtime-core/effort.mjs';
12
12
  import { isScratchConversation } from '../shared.mjs';
13
+ import { compactionArchiveRange } from '../../../runtime/agent/orchestrator/session/compaction-archive.mjs';
14
+ import { stampCompactionMessageIds } from '../../../runtime/agent/orchestrator/session/compaction-archive-capture.mjs';
15
+ import { boundWorkspaceCwd, restoreWorkspaceAfterResume } from '../../workspace/workspace-state.mjs';
13
16
 
14
17
  export function resolveResumeCwd(session, currentCwd) {
18
+ // A worktree-bound Lead resumes in its worktree whatever its desktop class;
19
+ // a vanished worktree resumes in the Project folder in `recovery`, where
20
+ // turns are refused (restoreWorkspaceAfterResume) rather than silently run.
21
+ const bound = boundWorkspaceCwd(session);
22
+ if (bound) return bound.cwd;
15
23
  const desktop = session?.desktopSession;
16
24
  if (desktop?.classification === 'project') {
17
25
  // `session.cwd` is the execution source of truth. Older builds updated it
@@ -60,9 +68,9 @@ export function createSessionResume(deps, { ingestSessionIntoMemory, closeSurfac
60
68
  }
61
69
 
62
70
  // The resumed session's OWN effort wins. resolveRoute always returns an
63
- // effort key, so this used to reinstate the effort of whichever session
64
- // happened to be open before — a schedule/webhook session opened with a
65
- // different effort than the one it actually ran with.
71
+ // effort key, so the route's effort applies only when the session has none —
72
+ // otherwise a schedule/webhook session would reopen with the effort of
73
+ // whichever session happened to be open before.
66
74
  function resumedRouteFor(resumed) {
67
75
  const route = getRoute();
68
76
  const resumeEffort = resumed.effort || (hasOwn(route, 'effort') ? route.effort : undefined);
@@ -71,6 +79,7 @@ export function createSessionResume(deps, { ingestSessionIntoMemory, closeSurfac
71
79
  model: resumed.model,
72
80
  effort: resumeEffort,
73
81
  fast: resumed.fast === true,
82
+ autoEffort: resumed.autoEffort !== false,
74
83
  modelParameters: resumed.modelParameters || {},
75
84
  });
76
85
  }
@@ -92,6 +101,8 @@ export function createSessionResume(deps, { ingestSessionIntoMemory, closeSurfac
92
101
  const activeSession = getSession();
93
102
  activeSession.effort = getRoute().effectiveEffort || null;
94
103
  activeSession.fast = getRoute().fast === true;
104
+ if (getRoute().autoEffort === false) activeSession.autoEffort = false;
105
+ else delete activeSession.autoEffort;
95
106
  activeSession.cwd = getCurrentCwd();
96
107
  restoreResumedToolSurface(activeSession, getRoute());
97
108
  writeStatuslineRoute(statusRoutes, activeSession, getRoute());
@@ -124,11 +135,16 @@ export function createSessionResume(deps, { ingestSessionIntoMemory, closeSurfac
124
135
  };
125
136
  const resumed = await mgr.resumeSession(id, toolSpecForMode(getMode()), resumeOptions);
126
137
  if (!resumed) return null;
138
+ // Restored rows carry their messages' stable ids (legacy transcripts are
139
+ // stamped here and persisted), so a live compaction can grey exactly the
140
+ // rows of what it drops.
141
+ stampCompactionMessageIds(resumed.messages, resumed.id || id);
127
142
  retirePrevious(previous, resumed);
128
143
  setSession(resumed);
129
144
  // Resume is not work: the Lead pool row is written only by turn
130
145
  // start/settle, so opening an old conversation never re-lists it in the
131
146
  // Agent window for another reap window (user report).
147
+ restoreWorkspaceAfterResume(resumed);
132
148
  applyResolvedCwd(resolveResumeCwd(resumed, getCurrentCwd()));
133
149
  // Commit the applied cwd before returning the resume transcript.
134
150
  resumed.cwd = getCurrentCwd();
@@ -154,6 +170,8 @@ export function createSessionResume(deps, { ingestSessionIntoMemory, closeSurfac
154
170
  cwd: getCurrentCwd(),
155
171
  provider: resumed.provider,
156
172
  model: resumed.model,
173
+ // The display-only compaction archive above the restored rows.
174
+ transcriptArchive: compactionArchiveRange(resumed),
157
175
  };
158
176
  }
159
177
 
@@ -7,6 +7,7 @@ import { clean } from '../../../runtime/agent/orchestrator/runtime-core/session-
7
7
  import { forgetSessionSearch } from '../../../runtime/session-search/session-search-ingest.mjs';
8
8
  import { listLeadSessions } from '../session-catalog.mjs';
9
9
  import { SESSION_ID_PATTERN } from '../shared.mjs';
10
+ import { replacementSessionCwd } from '../../workspace/workspace-state.mjs';
10
11
 
11
12
  export function createSessionDelete(deps, { cancelBackgroundTasks }) {
12
13
  const {
@@ -49,6 +50,14 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
49
50
  }
50
51
  }
51
52
 
53
+ // The deleted task's worktree: the autoCleanup setting decides (clean and
54
+ // merged → removed; otherwise kept). Off the deletion path; never fails it.
55
+ function releaseDeletedWorktree(sessionId) {
56
+ return Promise.resolve()
57
+ .then(() => deps.cleanupDeletedSessionWorktree?.(sessionId))
58
+ .catch(() => {});
59
+ }
60
+
52
61
  async function deleteSession(id) {
53
62
  const sessionId = clean(id);
54
63
  if (!sessionId || !SESSION_ID_PATTERN.test(sessionId)) return false;
@@ -68,8 +77,12 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
68
77
  mgr.deleteSession(childId);
69
78
  } catch {}
70
79
  }
80
+ void releaseDeletedWorktree(sessionId);
71
81
  return true;
72
82
  }
83
+ // Leaving a worktree-bound Lead: the replacement starts in the Project
84
+ // folder, and the worktree can go once nothing runs in it.
85
+ const projectFolder = replacementSessionCwd(current);
73
86
  const cleanupReason = 'desktop-session-delete';
74
87
  releaseSessionWork(sessionId, cleanupReason);
75
88
  // Active sessions retain a tombstone until the normal sweep. Unlinking
@@ -86,15 +99,18 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
86
99
  } catch {}
87
100
  }
88
101
  setSession(null);
102
+ if (projectFolder) await deps.applyResolvedCwd?.(projectFolder);
89
103
  invalidateContextStatusCache();
90
104
  invalidatePreSessionToolSurface();
91
105
  // An addressed runtime never mints a replacement under the deleted
92
106
  // address: it becomes terminal and a new conversation needs a new entry.
93
107
  if (deps.getAddressedSessionId?.()) {
94
108
  deps.markAddressTerminal?.();
109
+ void releaseDeletedWorktree(sessionId);
95
110
  return true;
96
111
  }
97
112
  await createCurrentSession();
113
+ void releaseDeletedWorktree(sessionId);
98
114
  return true;
99
115
  }
100
116
 
@@ -3,32 +3,50 @@
3
3
  // connect. All mutable progress lives on the caller-owned `state`.
4
4
  import { clean } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
5
5
  import { envFlag } from '../../runtime/shared/env.mjs';
6
+ import { ensurePluginServerData } from './plugin-servers.mjs';
6
7
 
7
- export function createMcpConnect({ mcpClient, getMcpScopeId, state, resolveEffectiveMcpServers, mcpStatus }) {
8
+ export function createMcpConnect({
9
+ mcpClient,
10
+ getMcpScopeId,
11
+ getCurrentCwd = () => '',
12
+ state,
13
+ resolveEffectiveMcpServers,
14
+ mcpStatus,
15
+ }) {
8
16
  const scopeOptions = () => ({ scopeId: getMcpScopeId() });
17
+ // name -> the resolved config this runtime last (re)connected the server
18
+ // with. Reconcile compares against it so only new or changed servers
19
+ // reconnect (a cwd switch changes only cwd-following plugin servers).
20
+ const applied = () => {
21
+ if (!(state.mcpApplied instanceof Map)) state.mcpApplied = new Map();
22
+ return state.mcpApplied;
23
+ };
24
+ const fingerprint = (cfg) => JSON.stringify(cfg);
25
+ // Roots advertised by cwd-following servers track this runtime's cwd.
26
+ const syncScopeRoot = () => mcpClient.setMcpScopeRoot?.(getMcpScopeId(), clean(getCurrentCwd?.()));
9
27
 
10
28
  // Connect/disconnect exactly one server in the live registry, leaving all
11
29
  // others untouched. Used by the enable/disable toggle so a single-server
12
30
  // change never triggers a full disconnectAll()/reconnect freeze.
13
- async function applyMcpServerConnection(name, enabled) {
31
+ async function applyMcpServerConnection(name, enabled, servers = resolveEffectiveMcpServers().servers) {
14
32
  const target = clean(name);
15
33
  if (!target) return;
16
- const { servers } = resolveEffectiveMcpServers();
17
34
  // Changing this server's state clears any stale failure record for it.
18
35
  if (Array.isArray(state.mcpFailures)) {
19
36
  state.mcpFailures = state.mcpFailures.filter((row) => row.name !== target);
20
37
  }
21
- if (enabled === false) {
38
+ const cfg = servers[target];
39
+ if (enabled === false || !cfg || cfg.enabled === false) {
40
+ applied().delete(target);
22
41
  await mcpClient.disconnectMcpServer?.(target, scopeOptions());
23
42
  return;
24
43
  }
25
- const cfg = servers[target];
26
- if (!cfg) return;
27
- // Drop any existing live entry first so connectMcpServers doesn't overwrite
28
- // the registry Map entry and leak the old transport/process.
29
- await mcpClient.disconnectMcpServer?.(target, scopeOptions());
44
+ applied().set(target, fingerprint(cfg));
45
+ // Close-then-connect as one generation-guarded op: a shutdown landing
46
+ // between the close and the connect never resurrects the server.
30
47
  try {
31
- await mcpClient.connectMcpServers({ [target]: cfg }, scopeOptions());
48
+ ensurePluginServerData(cfg);
49
+ await mcpClient.reconnectSingleMcpServer(getMcpScopeId(), target, cfg);
32
50
  } catch (error) {
33
51
  const failures = Array.isArray(error?.failures)
34
52
  ? error.failures
@@ -37,10 +55,28 @@ export function createMcpConnect({ mcpClient, getMcpScopeId, state, resolveEffec
37
55
  }
38
56
  }
39
57
 
40
- async function connectConfiguredMcp({ reset = false, only = null, enabled = true } = {}) {
58
+ // Bring the registry in line with the effective set: drop servers that are
59
+ // gone or disabled, (re)connect servers that are new or whose resolved
60
+ // config changed; untouched servers keep their connection.
61
+ async function reconcileServers() {
62
+ syncScopeRoot();
63
+ const { servers } = resolveEffectiveMcpServers();
64
+ const known = applied();
65
+ const drops = [...known.keys()].filter((name) => !servers[name] || servers[name].enabled === false);
66
+ const connects = Object.entries(servers)
67
+ .filter(([name, cfg]) => cfg?.enabled !== false && known.get(name) !== fingerprint(cfg))
68
+ .map(([name]) => name);
69
+ await Promise.allSettled([
70
+ ...drops.map((name) => applyMcpServerConnection(name, false, servers)),
71
+ ...connects.map((name) => applyMcpServerConnection(name, true, servers)),
72
+ ]);
73
+ }
74
+
75
+ async function connectConfiguredMcp({ reset = false, only = null, enabled = true, reconcile = false } = {}) {
41
76
  if (envFlag('MIXDOG_DISABLE_MCP')) {
42
77
  ++state.mcpConnectGeneration;
43
78
  state.mcpFailures = [];
79
+ applied().clear();
44
80
  if (only) await mcpClient.disconnectMcpServer?.(only, scopeOptions());
45
81
  else await mcpClient.disconnectAll?.(scopeOptions());
46
82
  return mcpStatus();
@@ -50,7 +86,7 @@ export function createMcpConnect({ mcpClient, getMcpScopeId, state, resolveEffec
50
86
  // just wait for any in-flight run, then bail if a newer full reset has
51
87
  // been requested in the meantime. Registering as in-flight makes a later
52
88
  // reset serialize behind us instead of interleaving disconnect/connect.
53
- if (only) {
89
+ if (only || reconcile) {
54
90
  // Atomically capture the current generation AND the prior in-flight
55
91
  // promise in the same synchronous step, then chain our op onto it. No
56
92
  // await sits between the capture and the `state.mcpConnectInFlight = run`
@@ -69,7 +105,8 @@ export function createMcpConnect({ mcpClient, getMcpScopeId, state, resolveEffec
69
105
  }
70
106
  }
71
107
  if (gen !== state.mcpConnectGeneration) return;
72
- await applyMcpServerConnection(only, enabled);
108
+ if (reconcile) await reconcileServers();
109
+ else await applyMcpServerConnection(only, enabled);
73
110
  })();
74
111
  state.mcpConnectInFlight = run;
75
112
  try {
@@ -96,11 +133,20 @@ export function createMcpConnect({ mcpClient, getMcpScopeId, state, resolveEffec
96
133
  }
97
134
  if (gen !== state.mcpConnectGeneration) return mcpStatus();
98
135
  const run = (async () => {
99
- if (reset) await mcpClient.disconnectAll?.(scopeOptions());
136
+ if (reset) {
137
+ await mcpClient.disconnectAll?.(scopeOptions());
138
+ applied().clear();
139
+ }
100
140
  state.mcpFailures = [];
141
+ syncScopeRoot();
101
142
  const { servers } = resolveEffectiveMcpServers();
143
+ for (const [name, cfg] of Object.entries(servers)) {
144
+ if (cfg?.enabled === false) applied().delete(name);
145
+ else applied().set(name, fingerprint(cfg));
146
+ }
102
147
  if (Object.keys(servers).length === 0) return;
103
148
  try {
149
+ for (const cfg of Object.values(servers)) if (cfg?.enabled !== false) ensurePluginServerData(cfg);
104
150
  await mcpClient.connectMcpServers(servers, scopeOptions());
105
151
  } catch (error) {
106
152
  state.mcpFailures = Array.isArray(error?.failures)
@@ -126,8 +172,14 @@ export function createMcpConnect({ mcpClient, getMcpScopeId, state, resolveEffec
126
172
  if (!inFlight) return;
127
173
  let budgetMs = 10000;
128
174
  try {
129
- const resolved = mcpClient.resolveMcpStartupTimeoutMs?.({});
130
- if (Number.isFinite(resolved)) budgetMs = resolved;
175
+ // The gate must outlast the slowest enabled server's own startup budget;
176
+ // a server with its budget disabled (0) means the connect may never
177
+ // settle, so the whole gate is disabled (handled below).
178
+ const configs = Object.values(resolveEffectiveMcpServers().servers).filter((cfg) => cfg?.enabled !== false);
179
+ const budgets = (configs.length > 0 ? configs : [{}])
180
+ .map((cfg) => mcpClient.resolveMcpStartupTimeoutMs?.(cfg))
181
+ .filter((value) => Number.isFinite(value));
182
+ if (budgets.length > 0) budgetMs = budgets.includes(0) ? 0 : Math.max(...budgets);
131
183
  } catch {
132
184
  /* fall back to default budget */
133
185
  }