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
@@ -8,24 +8,32 @@ import { createMcpOAuth } from './oauth.mjs';
8
8
  import { mcpOAuthClientFor, mcpOAuthDisplayName } from './oauth-client.mjs';
9
9
  import { googleMcpService, withGoogleMcp } from '../../../connectors/google-mcp.mjs';
10
10
  import { gmailAppPasswordService, withGmailAppPasswordMcp } from '../../../connectors/gmail-app-password.mjs';
11
- import { connectorAccountRequest, withConnectorAccountsMcp } from '../../../connectors/connector-accounts-mcp.mjs';
11
+ import { withConnectorAccountsMcp } from '../../../connectors/connector-accounts-mcp.mjs';
12
12
  import {
13
+ connectorAccountEnabled,
14
+ connectorAccountId,
13
15
  connectorAccountsOf,
14
16
  connectorLiveAccountServers,
15
17
  gmailAppPasswordAccount,
16
18
  } from '../../../shared/connector-catalog.mjs';
17
- import { isMcpOAuthReauthenticationRequired } from './oauth.mjs';
19
+ import { runAbortable } from '../../../shared/abort-race.mjs';
20
+ import { isMcpOAuthReauthenticationRequired, storedMcpOAuthIdentity } from './oauth.mjs';
21
+ import { shutdownStdioChild } from './child-tree.mjs';
22
+ import { listAllMcpTools } from './client-handshake.mjs';
18
23
  import {
19
24
  AUTO_DETECT_PORTS,
25
+ MCP_MAX_TIMER_MS,
20
26
  expandEnvVars,
21
27
  findMissingMcpEnvVars,
22
28
  mcpUrlForLog,
23
29
  normalizeMcpTransportUrl,
24
30
  resolveMcpHttpHeaders,
31
+ resolveMcpOAuthCredentialKey,
25
32
  resolveMcpOAuthUrl,
26
33
  resolveMcpStdioEnvironment,
27
34
  resolveMcpTransportKind,
28
35
  scrubMcpConnectionMessage,
36
+ scrubMcpSecrets,
29
37
  } from './client-config.mjs';
30
38
 
31
39
  /**
@@ -76,57 +84,142 @@ export function hasConfiguredMcpAuth(cfg) {
76
84
  );
77
85
  }
78
86
 
79
- /** One account of a multi-account connector server (connector-catalog.mjs
80
- * connectorAccountServer) as connector-accounts-mcp.mjs calls it: through
81
- * the transport the account had as a server of its own — its app-password
82
- * header, or its own non-interactive OAuth sign-in (refreshed as needed; a
83
- * new sign-in goes through 계정 바꾸기, never through a tool call). */
84
- function connectorAccountClient(serverName, accountCfg, oauthOptions) {
85
- const base = { name: accountCfg.name, email: '', appPassword: false, close() {} };
86
- let url;
87
+ // A stdio account (Postgres) runs one process per account config, shared by
88
+ // the connector server of every scope like any stdio server (client.mjs):
89
+ // account config → its connection, which closes with its last holder.
90
+ const sharedAccountConnections = new Map();
91
+
92
+ /** Close one account connection: a stdio child with its whole process tree. */
93
+ async function closeAccountConnection(connection) {
94
+ connection.dead = true;
95
+ if (connection.transport?._process) await shutdownStdioChild(connection.transport).catch(() => {});
96
+ await connection.client.close().catch(() => {});
97
+ }
98
+
99
+ /** Whether a call failure is the account server's own JSON-RPC answer: its
100
+ * connection stays. */
101
+ const answeredError = (error) => error?.name === 'McpError' && error.code !== -32000;
102
+
103
+ /** The address a remote account is signed in as, '' when none is known. */
104
+ function signedInAs(accountCfg) {
87
105
  try {
88
- url = resolveMcpOAuthUrl(accountCfg);
89
- if (hasConfiguredMcpAuth(accountCfg)) {
90
- const email = gmailAppPasswordAccount(accountCfg);
91
- const fetchImpl = gmailAppPasswordService(url) ? withGmailAppPasswordMcp() : fetch;
92
- return {
93
- ...base,
94
- email,
95
- appPassword: Boolean(email),
96
- request: connectorAccountRequest(url, fetchImpl, resolveMcpHttpHeaders(accountCfg)),
97
- };
106
+ const url = resolveMcpOAuthUrl(accountCfg);
107
+ if (!url || hasConfiguredMcpAuth(accountCfg)) return '';
108
+ return storedMcpOAuthIdentity(url, resolveMcpOAuthCredentialKey(accountCfg))?.account || '';
109
+ } catch {
110
+ return '';
111
+ }
112
+ }
113
+
114
+ /** One account of a connector server (connector-catalog.mjs
115
+ * connectorAccountServer) as connector-accounts-mcp.mjs calls it: its own
116
+ * MCP connection through the transport it had as a server of its own — its
117
+ * key header, its app password, its local command, or its own
118
+ * non-interactive OAuth sign-in (refreshed as needed; a new sign-in goes
119
+ * through 계정 바꾸기, never through a tool call). Connected on first use and
120
+ * again after its connection failed. */
121
+ function connectorAccountClient(serverName, accountCfg, { sdk, log, oauthOptions }) {
122
+ const { interactive: _interactive, ...ownOAuth } = oauthOptions || {};
123
+ const address = gmailAppPasswordAccount(accountCfg);
124
+ const shareKey = resolveMcpTransportKind(accountCfg) === 'stdio' ? JSON.stringify(accountCfg) : null;
125
+ const secretsOf = (connection) => connection?.transport?.oauth?.secrets() || [];
126
+ const accountError = (error, connection) => {
127
+ if (isMcpOAuthReauthenticationRequired(error)) {
128
+ return Object.assign(new Error('Sign-in required; sign this account in again in Connectors.'), {
129
+ authRequired: true,
130
+ });
98
131
  }
99
- const oauth = createMcpOAuth({
100
- url,
101
- serverName: mcpOAuthDisplayName(accountCfg, serverName),
102
- oauthClient: mcpOAuthClientFor(accountCfg, url),
103
- ...(oauthOptions?.fetchImpl ? { fetchImpl: oauthOptions.fetchImpl } : {}),
104
- ...(googleMcpService(url) ? { fetchImpl: withGoogleMcp(oauthOptions?.fetchImpl) } : {}),
105
- });
106
- const send = connectorAccountRequest(url, (input, init) => oauth.fetch(input, init));
107
- return {
108
- ...base,
109
- async request(message, options) {
110
- try {
111
- return await send(message, options);
112
- } catch (error) {
113
- const reason = scrubMcpConnectionMessage(error?.message || String(error), accountCfg);
114
- const scrubbed = new Error(
115
- isMcpOAuthReauthenticationRequired(error)
116
- ? 'Sign-in required; sign this account in again in Connectors.'
117
- : reason
118
- );
119
- if (isMcpOAuthReauthenticationRequired(error)) scrubbed.authRequired = true;
120
- throw scrubbed;
121
- }
122
- },
123
- close: () => oauth.close(),
132
+ const reason = scrubMcpConnectionMessage(error?.message || String(error), accountCfg, secretsOf(connection));
133
+ return new Error(appendMcpStderrTail(reason, connection?.stderrTail?.() || ''));
134
+ };
135
+ const open = () => {
136
+ const connection = { users: 0, dead: false };
137
+ try {
138
+ const made = createMcpTransport({ name: accountCfg.name, cfg: accountCfg, sdk, log, oauthOptions: ownOAuth });
139
+ connection.transport = made.transport;
140
+ connection.stderrTail = made.stderrTail;
141
+ } catch (error) {
142
+ // A broken account (no sign-in client, an invalid address) stays listed with why.
143
+ connection.dead = true;
144
+ connection.client = { close: async () => {} };
145
+ connection.ready = Promise.reject(error);
146
+ connection.ready.catch(() => {});
147
+ return connection;
148
+ }
149
+ const client = new sdk.Client({ name: `mixdog-agent/${serverName}`, version: '1.0.0' });
150
+ connection.client = client;
151
+ const retire = () => {
152
+ connection.dead = true;
153
+ if (shareKey && sharedAccountConnections.get(shareKey) === connection) sharedAccountConnections.delete(shareKey);
124
154
  };
125
- } catch (error) {
126
- // A broken account (no sign-in client, an invalid address) stays listed with why.
127
- const failed = new Error(error?.message || String(error));
128
- return { ...base, request: async () => Promise.reject(failed) };
129
- }
155
+ client.onclose = retire;
156
+ connection.retire = retire;
157
+ connection.ready = (async () => {
158
+ await client.connect(connection.transport, { timeout: MCP_MAX_TIMER_MS });
159
+ const tools = client.getServerCapabilities()?.tools
160
+ ? (await listAllMcpTools(client, { timeout: MCP_MAX_TIMER_MS }))?.tools
161
+ : [];
162
+ if (!Array.isArray(tools)) throw new Error('The account listed its tools in an invalid shape');
163
+ return { instructions: client.getInstructions() || '', tools };
164
+ })();
165
+ connection.ready.catch(() => {
166
+ retire();
167
+ void closeAccountConnection(connection);
168
+ });
169
+ return connection;
170
+ };
171
+ let held = null;
172
+ const release = () => {
173
+ const connection = held;
174
+ held = null;
175
+ if (!connection || --connection.users > 0) return;
176
+ connection.retire?.();
177
+ void closeAccountConnection(connection);
178
+ };
179
+ const acquire = () => {
180
+ if (held && !held.dead) return held;
181
+ release();
182
+ let connection = shareKey ? sharedAccountConnections.get(shareKey) : null;
183
+ if (!connection || connection.dead) {
184
+ connection = open();
185
+ if (shareKey && !connection.dead) sharedAccountConnections.set(shareKey, connection);
186
+ }
187
+ connection.users += 1;
188
+ held = connection;
189
+ return connection;
190
+ };
191
+ return {
192
+ name: accountCfg.name,
193
+ email: address || signedInAs(accountCfg),
194
+ async connect(signal) {
195
+ const connection = acquire();
196
+ try {
197
+ return await runAbortable(signal, () => connection.ready);
198
+ } catch (error) {
199
+ throw accountError(error, connection);
200
+ }
201
+ },
202
+ async callTool(params, { signal, onprogress } = {}) {
203
+ const connection = acquire();
204
+ try {
205
+ await runAbortable(signal, () => connection.ready);
206
+ // The caller's deadline governs (it resets on the progress passed up).
207
+ const result = await connection.client.callTool(params, undefined, {
208
+ signal,
209
+ timeout: MCP_MAX_TIMER_MS,
210
+ ...(onprogress ? { onprogress } : {}),
211
+ });
212
+ return scrubMcpSecrets(result, secretsOf(connection));
213
+ } catch (error) {
214
+ const failed = accountError(error, connection);
215
+ if (answeredError(error)) return { content: [{ type: 'text', text: failed.message }], isError: true };
216
+ // A connection a call failed on is opened again for the next call.
217
+ if (!signal?.aborted) connection.retire?.();
218
+ throw failed;
219
+ }
220
+ },
221
+ close: release,
222
+ };
130
223
  }
131
224
 
132
225
  // The SDK's WebSocket transport opens its socket without a way to set request
@@ -177,13 +270,19 @@ function missingEnvWarnings(name, cfg, strictEnv, log) {
177
270
  return warnings;
178
271
  }
179
272
 
180
- // A multi-account connector: one server, every account behind it; closing the
181
- // transport closes every account client.
182
- function connectorAccountsTransport({ name, cfg, Transport, url, accountServers, oauthOptions, log }) {
183
- const accounts = accountServers.map((accountCfg) => connectorAccountClient(name, accountCfg, oauthOptions));
184
- const transport = new Transport(new URL(url), {
185
- fetch: withConnectorAccountsMcp({ connector: cfg.connector, accounts }),
273
+ // A connector server: one server, every account behind it (its account choice
274
+ // on `connectorAccounts`); closing the transport closes every account client.
275
+ function connectorAccountsTransport({ name, cfg, Transport, url, accountServers, sdk, oauthOptions, log }) {
276
+ // `accountServers` are the switched-on stored accounts, in order.
277
+ const stored = connectorAccountsOf(cfg).filter(connectorAccountEnabled);
278
+ const accounts = accountServers.map((accountCfg, index) => {
279
+ const account = connectorAccountClient(name, accountCfg, { sdk, log, oauthOptions });
280
+ account.id = connectorAccountId(cfg, stored[index]);
281
+ return account;
186
282
  });
283
+ const fetchImpl = withConnectorAccountsMcp({ connector: cfg.connector, accounts });
284
+ const transport = new Transport(new URL(url), { fetch: fetchImpl });
285
+ transport.connectorAccounts = fetchImpl.connectorAccounts;
187
286
  const close = transport.close.bind(transport);
188
287
  transport.close = async () => {
189
288
  for (const account of accounts) account.close();
@@ -204,6 +303,7 @@ function remoteHttpTransport({ name, cfg, kind, Transport, url, oauthOptions, lo
204
303
  if (!hasConfiguredMcpAuth(cfg)) {
205
304
  oauth = createMcpOAuth({
206
305
  url,
306
+ credentialKey: resolveMcpOAuthCredentialKey(cfg),
207
307
  serverName: mcpOAuthDisplayName(cfg, name),
208
308
  oauthClient: mcpOAuthClientFor(cfg, url),
209
309
  ...oauthOptions,
@@ -291,7 +391,7 @@ export function createMcpTransport({ name, cfg, sdk, log, strictEnv, oauthOption
291
391
  throw new Error(`Every account of "${name}" is disabled`);
292
392
  }
293
393
  const transport = accountServers.length
294
- ? connectorAccountsTransport({ name, cfg, Transport, url, accountServers, oauthOptions, log })
394
+ ? connectorAccountsTransport({ name, cfg, Transport, url, accountServers, sdk, oauthOptions, log })
295
395
  : remoteHttpTransport({ name, cfg, kind, Transport, url, oauthOptions, log });
296
396
  return { transport, autoDetectAdvert: null, stderrTail: noStderrTail, warnings };
297
397
  }
@@ -25,6 +25,7 @@ import { currentToolExecutionOwner } from '../../../shared/tool-execution-owner.
25
25
  import { positiveInt } from '../../../shared/numbers.mjs';
26
26
  import {
27
27
  providerSafeMcpToolName,
28
+ resolveMcpOAuthCredentialKey,
28
29
  resolveMcpOAuthUrl,
29
30
  resolveMcpRequestTimeouts,
30
31
  resolveMcpTransportKind,
@@ -39,6 +40,7 @@ import { mcpOAuthClientFor, mcpOAuthDisplayName } from './oauth-client.mjs';
39
40
  import { googleMcpService, withGoogleMcp } from '../../../connectors/google-mcp.mjs';
40
41
  import { gmailAppPasswordService } from '../../../connectors/gmail-app-password.mjs';
41
42
  import { connectorLiveAccountServers } from '../../../shared/connector-catalog.mjs';
43
+ import { CONVERSATION_META } from '../../../connectors/connector-accounts-mcp.mjs';
42
44
  import {
43
45
  clearMcpOAuth,
44
46
  commitMcpOAuthSwitch,
@@ -52,8 +54,9 @@ import {
52
54
  export { probeMcpServerAuth } from './oauth-probe.mjs';
53
55
 
54
56
  // Config interpretation (transport kind, URL policy, env expansion, headers,
55
- // timeouts, log scrubbing) lives in client-config.mjs; re-exported so every
56
- // existing importer resolves unchanged.
57
+ // timeouts, log scrubbing) lives in client-config.mjs; the names importers
58
+ // use (including through namespace loads such as boot.mcpClient) are
59
+ // re-exported here.
57
60
  export {
58
61
  normalizeMcpTransportUrl,
59
62
  mcpUrlForLog,
@@ -62,9 +65,6 @@ export {
62
65
  resolveMcpHttpHeaders,
63
66
  resolveMcpTransportKind,
64
67
  resolveMcpStartupTimeoutMs,
65
- resolveMcpCallTimeoutMs,
66
- resolveMcpMaxTotalTimeoutMs,
67
- resolveMcpRequestTimeouts,
68
68
  } from './client-config.mjs';
69
69
  const servers = new Map();
70
70
  const reconnects = createKeyedSingleflight();
@@ -503,10 +503,15 @@ export async function executeMcpTool(name, args, options = {}) {
503
503
  const serverName = server.name;
504
504
  const toolName = definition?.mcpToolName || match[2];
505
505
  const callSignal = options?.signal || null;
506
+ // A connector server's call names the conversation it is made in: its
507
+ // account default, and the account it makes the last used.
508
+ const conversation = String(options?.conversation || '').trim();
509
+ const metaFor = (target) =>
510
+ conversation && target.transport?.connectorAccounts ? { [CONVERSATION_META]: conversation } : undefined;
506
511
  const dispatch = (target) =>
507
512
  definition?.mcpOperation
508
513
  ? _callMcpFeatureWithTimeout(target, definition.mcpOperation, args, callSignal)
509
- : _callToolWithTimeout(target, toolName, args, callSignal);
514
+ : _callToolWithTimeout(target, toolName, args, callSignal, metaFor(target));
510
515
  let retryServer = null;
511
516
  const secrets = () => oauthSecrets(server.transport, retryServer?.transport);
512
517
  const gate = callAdmissionFor(server);
@@ -999,7 +1004,7 @@ export function raceMcpAbort(promise, signal, message) {
999
1004
  });
1000
1005
  }
1001
1006
 
1002
- async function _callToolWithTimeout(server, toolName, args, signal = null) {
1007
+ async function _callToolWithTimeout(server, toolName, args, signal = null, meta = undefined) {
1003
1008
  // The request's signal goes INTO the SDK: an aborted caller (or our own
1004
1009
  // timeout) cancels the live JSON-RPC request (notifications/cancelled)
1005
1010
  // instead of merely walking away from it. The abort race additionally frees
@@ -1008,7 +1013,8 @@ async function _callToolWithTimeout(server, toolName, args, signal = null) {
1008
1013
  return runMcpRequest(
1009
1014
  server,
1010
1015
  signal,
1011
- (options) => server.client.callTool({ name: toolName, arguments: args }, undefined, options),
1016
+ (options) =>
1017
+ server.client.callTool({ name: toolName, arguments: args, ...(meta ? { _meta: meta } : {}) }, undefined, options),
1012
1018
  {
1013
1019
  abortMessage: `MCP tool call aborted (server="${server?.name}", tool="${toolName}")`,
1014
1020
  timeoutMessage: (ms) =>
@@ -1119,6 +1125,24 @@ export function isMcpTool(name) {
1119
1125
  export function isRegisteredMcpTool(name, scopeId = DEFAULT_MCP_SCOPE_ID) {
1120
1126
  return Boolean(resolveMcpToolTarget(scopeId, name)?.definition);
1121
1127
  }
1128
+ /**
1129
+ * The account (`{ name, label }`: its unique name, which binds a call to it,
1130
+ * and what it is shown as) a call of the prefixed tool `name` with `args`
1131
+ * would use on its connector server, made in `conversation`
1132
+ * (connectors/connector-accounts-mcp.mjs): the one `args.account` names, else
1133
+ * the one used last. Null when the tool's server holds no accounts. Throws the
1134
+ * refusal (usable accounts listed) when that account cannot be used.
1135
+ */
1136
+ export function resolveMcpToolAccount(name, args, { scopeId = DEFAULT_MCP_SCOPE_ID, conversation = '' } = {}) {
1137
+ const target = resolveMcpToolTarget(normalizeMcpScopeId(scopeId), name);
1138
+ const accounts = target?.server?.transport?.connectorAccounts;
1139
+ if (!accounts || target.definition?.mcpOperation) return null;
1140
+ return accounts.choose({
1141
+ tool: target.definition?.mcpToolName || MCP_TOOL_NAME_RE.exec(name)?.[2],
1142
+ wanted: args?.account,
1143
+ conversation: String(conversation || '').trim(),
1144
+ });
1145
+ }
1122
1146
  /** True when the prefixed name is `read_email` of a server whose every
1123
1147
  * endpoint Mixdog answers in-process (the Gmail app-password connector,
1124
1148
  * alone or behind the multi-account server): its result is a mail as the
@@ -1272,18 +1296,19 @@ export function isMcpLoginPending(name, options = {}) {
1272
1296
  * for servers that never use MCP OAuth.
1273
1297
  */
1274
1298
  export function getMcpServerOAuthState(cfg) {
1275
- let url;
1299
+ let key;
1276
1300
  try {
1277
- url = resolveMcpOAuthUrl(cfg);
1301
+ key = resolveMcpOAuthCredentialKey(cfg);
1278
1302
  } catch {
1279
1303
  return null;
1280
1304
  }
1281
- if (!url || hasConfiguredMcpAuth(cfg)) return null;
1282
- const signedIn = hasStoredMcpOAuthTokens(url);
1305
+ if (!key || hasConfiguredMcpAuth(cfg)) return null;
1306
+ const url = resolveMcpOAuthUrl(cfg);
1307
+ const signedIn = hasStoredMcpOAuthTokens(url, key);
1283
1308
  if (!signedIn) return { signedIn };
1284
1309
  // Who it is signed in as (never guessed: empty when the server named nobody)
1285
1310
  // and whether 계정 바꾸기 can make the provider show its account choice.
1286
- const who = storedMcpOAuthIdentity(url);
1311
+ const who = storedMcpOAuthIdentity(url, key);
1287
1312
  return {
1288
1313
  signedIn,
1289
1314
  account: typeof who?.account === 'string' ? who.account : '',
@@ -1298,32 +1323,38 @@ export function startMcpServerOAuthSwitch(cfg, launch, serverName) {
1298
1323
  if (!url) throw new Error(`MCP server "${serverName}" does not use OAuth sign-in`);
1299
1324
  return startMcpOAuthSwitch({
1300
1325
  url,
1326
+ credentialKey: resolveMcpOAuthCredentialKey(cfg),
1301
1327
  launch,
1302
1328
  serverName: mcpOAuthDisplayName(cfg, serverName),
1303
1329
  oauthClient: mcpOAuthClientFor(cfg, url),
1304
1330
  ...(googleMcpService(url) ? { fetchImpl: withGoogleMcp() } : {}),
1305
1331
  });
1306
1332
  }
1307
- /** Store a switch's sign-in for the server's URL; resolves its rollback. */
1333
+ /** Store a switch's sign-in as the server's (its URL's, or its own key's);
1334
+ * resolves its rollback. */
1308
1335
  export function commitMcpServerOAuthSwitch(cfg, signIn) {
1309
- return commitMcpOAuthSwitch({ url: resolveMcpOAuthUrl(cfg), signIn });
1336
+ return commitMcpOAuthSwitch({
1337
+ url: resolveMcpOAuthUrl(cfg),
1338
+ credentialKey: resolveMcpOAuthCredentialKey(cfg),
1339
+ signIn,
1340
+ });
1310
1341
  }
1311
1342
  /**
1312
- * Log out of an HTTP/SSE server URL: delete the OAuth tokens and client
1313
- * registration stored for it, shared by every server configured with that
1314
- * exact URL, and drop them from live connections. `options.revoke` also
1315
- * revokes the grant where the authorization server documents how; resolves
1316
- * `{ revoked }`.
1343
+ * Log out of an HTTP/SSE server: delete the OAuth tokens and client
1344
+ * registration stored for it (shared by every server configured with that
1345
+ * exact URL, unless it has its own credential key), and drop them from live
1346
+ * connections. `options.revoke` also revokes the grant where the
1347
+ * authorization server documents how; resolves `{ revoked }`.
1317
1348
  */
1318
1349
  export async function clearMcpServerOAuth(cfg, options = {}) {
1319
- let url;
1350
+ let key;
1320
1351
  try {
1321
- url = resolveMcpOAuthUrl(cfg);
1352
+ key = resolveMcpOAuthCredentialKey(cfg);
1322
1353
  } catch {
1323
1354
  // A config without a valid remote URL never connected, so never logged in.
1324
1355
  return { revoked: false };
1325
1356
  }
1326
- if (url) return clearMcpOAuth({ url, revoke: options.revoke === true });
1357
+ if (key) return clearMcpOAuth({ url: resolveMcpOAuthUrl(cfg), credentialKey: key, revoke: options.revoke === true });
1327
1358
  return { revoked: false };
1328
1359
  }
1329
1360
  /**
@@ -6,7 +6,7 @@
6
6
  // - else the catalog connector's (connector-catalog.mjs `oauthClient`), with
7
7
  // its scopes and the provider's offline-access parameter.
8
8
  import { createHash } from 'node:crypto';
9
- import keychain from '../../../../lib/keychain-cjs.cjs';
9
+ import { keychainSecretStore as keychain } from '../../../shared/config.mjs';
10
10
  import { connectorById, connectorOfServer, gmailAppPasswordAccount } from '../../../shared/connector-catalog.mjs';
11
11
  import { GOOGLE_AUTH_PARAMS, googleOAuthClient } from '../../../shared/google-oauth-client.mjs';
12
12
  import { normalizeMcpTransportUrl } from './client-config.mjs';
@@ -145,11 +145,16 @@ export function createCredentialCache({ url, credentialStore, account }) {
145
145
  }
146
146
  exists = Boolean(saved);
147
147
  }
148
+ const signedIn = Boolean(creds.tokens);
148
149
  change();
149
150
  hold();
151
+ // Other processes follow a refresh through the revision marker; only a
152
+ // sign-in or sign-out is announced as a settings change (it may let a
153
+ // server that needed sign-in connect, or end its connection).
154
+ const announce = remove ? signedIn : Boolean(creds.tokens) !== signedIn;
150
155
  if (remove) {
151
156
  await writeRevisionMarker(account, null);
152
- if (exists) await credentialStore.deleteSecretAsync(account);
157
+ if (exists) await credentialStore.deleteSecretAsync(account, { announce });
153
158
  await writeIdentityFile(account, null);
154
159
  creds.observed = null;
155
160
  } else {
@@ -158,7 +163,8 @@ export function createCredentialCache({ url, credentialStore, account }) {
158
163
  const { tokens, clientInformation, redirectUrl, discovery, identity } = creds;
159
164
  await credentialStore.setSecretAsync(
160
165
  account,
161
- JSON.stringify({ url, revision, tokens, clientInformation, redirectUrl, discovery, identity })
166
+ JSON.stringify({ url, revision, tokens, clientInformation, redirectUrl, discovery, identity }),
167
+ { announce }
162
168
  );
163
169
  await writeIdentityFile(account, creds);
164
170
  creds.observed = revision;
@@ -6,6 +6,72 @@ import { identityFromTokenResponse } from './oauth-account.mjs';
6
6
  import { answerOAuthCallback } from './oauth-callback.mjs';
7
7
  import { anySignal, loginFailed, reauthenticationRequired, scopeNotGranted } from './oauth-shared.mjs';
8
8
 
9
+ // Fetch for the SDK: transport-URL normalized, no redirects, bounded by the
10
+ // login `signal`. The token endpoint's answer is read for who the tokens
11
+ // belong to (oauth-account.mjs): the SDK keeps only the token fields.
12
+ function makeSafeFetch({ fetchImpl, flow, signal }) {
13
+ return async (input, init = {}) => {
14
+ const response = await fetchImpl(normalizeMcpTransportUrl(input), {
15
+ ...init,
16
+ redirect: 'error',
17
+ signal: anySignal(signal, init.signal),
18
+ });
19
+ if (response.ok && /(^|&)grant_type=/.test(String(init.body ?? ''))) {
20
+ flow.identity = identityFromTokenResponse(
21
+ await response
22
+ .clone()
23
+ .json()
24
+ .catch(() => null)
25
+ );
26
+ }
27
+ return response;
28
+ };
29
+ }
30
+
31
+ // The caller's progress hooks (mcp-oauth-login.mjs): the callback arrived,
32
+ // then the tokens are stored.
33
+ function reportProgress(browser, hook) {
34
+ try {
35
+ browser?.[hook]?.();
36
+ } catch {
37
+ /* progress reporting never fails the login */
38
+ }
39
+ }
40
+
41
+ // The callback promise of one login, and the browser page held open for the
42
+ // loopback callback until the code exchange and scope check end: `settle()` is
43
+ // success, `settle({ code })` a failure. Bounded by `signal`, like the
44
+ // exchange itself. `setFlushing` receives each answered page's flush.
45
+ function awaitCallback({ flow, signal, stopListening, setFlushing }) {
46
+ let abort;
47
+ let respond;
48
+ const settle = (failure) => {
49
+ const answer = respond;
50
+ respond = undefined;
51
+ if (!answer) return undefined;
52
+ const flushed = answer(failure);
53
+ setFlushing(flushed);
54
+ return flushed;
55
+ };
56
+ const callback = new Promise((resolve, reject) => {
57
+ const finish = (code, page) => {
58
+ if (page) respond = page;
59
+ return code ? resolve(code) : reject(loginFailed());
60
+ };
61
+ flow.finishCallback = finish;
62
+ // Timeout, cancel or abort: the held page gets the generic failure now
63
+ // (the exchange or a credential write may be stalled past the deadline),
64
+ // and the listener closes once it is flushed.
65
+ abort = () => {
66
+ finish();
67
+ settle({});
68
+ stopListening();
69
+ };
70
+ signal.addEventListener('abort', abort, { once: true });
71
+ });
72
+ return { callback, settle, abort };
73
+ }
74
+
9
75
  /**
10
76
  * The browser login of one connection over its credential `cache` and login
11
77
  * `flow` state: the loopback callback listener and the SDK authorization
@@ -65,61 +131,19 @@ export function createLoginFlow({ url, cache, flow, provider, lifetimeSignal, op
65
131
  // the token fields, so the token endpoint's answer is read here.
66
132
  flow.identity = undefined;
67
133
  flow.signal = signal;
68
- const safeFetch = async (input, init = {}) => {
69
- const response = await fetchImpl(normalizeMcpTransportUrl(input), {
70
- ...init,
71
- redirect: 'error',
72
- signal: anySignal(signal, init.signal),
73
- });
74
- if (response.ok && /(^|&)grant_type=/.test(String(init.body ?? ''))) {
75
- flow.identity = identityFromTokenResponse(
76
- await response
77
- .clone()
78
- .json()
79
- .catch(() => null)
80
- );
81
- }
82
- return response;
83
- };
84
- // The caller's progress hooks (mcp-oauth-login.mjs): the callback arrived,
85
- // then the tokens are stored.
86
- const progress = (hook) => {
87
- try {
88
- browser?.[hook]?.();
89
- } catch {
90
- /* progress reporting never fails the login */
91
- }
92
- };
93
- let abort;
94
- // The browser page held open for the loopback callback until the code
95
- // exchange and scope check end: `settle()` is success, `settle({ code })`
96
- // a failure. Bounded by `signal`, like the exchange itself.
97
- let respond;
98
- const settle = (failure) => {
99
- const answer = respond;
100
- respond = undefined;
101
- if (!answer) return undefined;
102
- flushing = answer(failure);
103
- return flushing;
104
- };
105
- const callback = new Promise((resolve, reject) => {
106
- const finish = (code, page) => {
107
- if (page) respond = page;
108
- return code ? resolve(code) : reject(loginFailed());
109
- };
110
- flow.finishCallback = finish;
111
- // Timeout, cancel or abort: the held page gets the generic failure now
112
- // (the exchange or a credential write may be stalled past the deadline),
113
- // and the listener closes once it is flushed.
114
- abort = () => {
115
- finish();
116
- settle({});
117
- stopListening();
118
- };
119
- signal.addEventListener('abort', abort, { once: true });
134
+ const safeFetch = makeSafeFetch({ fetchImpl, flow, signal });
135
+ const progress = (hook) => reportProgress(browser, hook);
136
+ const { callback, settle, abort } = awaitCallback({
137
+ flow,
138
+ signal,
139
+ stopListening,
140
+ setFlushing: (page) => {
141
+ flushing = page;
142
+ },
120
143
  });
121
144
  // A discovery/registration error can precede waiting for the callback.
122
145
  callback.catch(() => {});
146
+ let codeReceived = false;
123
147
  try {
124
148
  signal.throwIfAborted();
125
149
  const { auth } = await import('@modelcontextprotocol/sdk/client/auth.js');
@@ -141,6 +165,7 @@ export function createLoginFlow({ url, cache, flow, provider, lifetimeSignal, op
141
165
  });
142
166
  if (result === 'REDIRECT') {
143
167
  const code = await callback;
168
+ codeReceived = true;
144
169
  signal.throwIfAborted();
145
170
  progress('onCallback');
146
171
  const exchanged = await cache.withLock(async () => {
@@ -157,6 +182,12 @@ export function createLoginFlow({ url, cache, flow, provider, lifetimeSignal, op
157
182
  await settle();
158
183
  } catch (error) {
159
184
  await settle({ code: error?.code });
185
+ // An authorization server that no longer knows our client_id answers the
186
+ // browser with an HTTP error, never a redirect or a token-endpoint
187
+ // invalid_client, so the SDK cannot see it: register again next time.
188
+ if (interactive && flow.browserOpened && !codeReceived && !provider.preRegistered) {
189
+ await provider.invalidateCredentials('client').catch(() => {});
190
+ }
160
191
  // SDK errors may contain authorization server response bodies/secrets.
161
192
  if (error?.code === 'reauthenticationRequired' || !interactive) throw reauthenticationRequired();
162
193
  // Our own error names scopes only (no token data): the one to pass on.
@@ -12,7 +12,7 @@ import {
12
12
  } from './client-config.mjs';
13
13
  import { hasConfiguredMcpAuth } from './client-transport.mjs';
14
14
 
15
- export const MCP_AUTH_PROBE_TIMEOUT_MS = 10_000;
15
+ const MCP_AUTH_PROBE_TIMEOUT_MS = 10_000;
16
16
 
17
17
  const INITIALIZE_PROBE = JSON.stringify({
18
18
  jsonrpc: '2.0',