mixdog 1.4.0 → 1.4.2

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 (493) hide show
  1. package/package.json +3 -2
  2. package/scripts/build-shipped-history.mjs +115 -33
  3. package/scripts/check-voice-runtime-inputs.mjs +25 -0
  4. package/scripts/gate-local.mjs +183 -63
  5. package/scripts/latest-guard.mjs +21 -9
  6. package/scripts/lib/gate-scheduler.mjs +138 -32
  7. package/scripts/lib/gate-timing-reporter.mjs +16 -0
  8. package/scripts/lib/isolated-test-env.mjs +10 -5
  9. package/scripts/lib/run-node-tests.mjs +91 -66
  10. package/scripts/lib/scoped-temp.d.mts +16 -0
  11. package/scripts/lib/scoped-temp.mjs +124 -0
  12. package/scripts/lib/stale-temp.mjs +44 -0
  13. package/scripts/lib/test-failure-records.mjs +14 -1
  14. package/scripts/lib/test-failure-summary.mjs +16 -4
  15. package/scripts/lib/test-spawn-ledger.mjs +12 -3
  16. package/scripts/post-release-check.mjs +1 -6
  17. package/scripts/pptx-kit-index.mjs +17 -5
  18. package/scripts/suite-health.mjs +115 -24
  19. package/scripts/test-data-dir.mjs +10 -7
  20. package/scripts/test.mjs +9 -14
  21. package/src/agents/advisor/AGENT.md +4 -4
  22. package/src/agents/advisor/agent.json +1 -1
  23. package/src/agents/explore/AGENT.md +22 -0
  24. package/src/agents/explore/agent.json +6 -0
  25. package/src/app.mjs +4 -0
  26. package/src/cli.mjs +7 -0
  27. package/src/defaults/agents.json +7 -0
  28. package/src/defaults/shipped-history.json +23 -2
  29. package/src/defaults/skills/browser-use/SKILL.md +10 -5
  30. package/src/defaults/skills/code-tidy/SKILL.md +71 -102
  31. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
  32. package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
  33. package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
  34. package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
  35. package/src/defaults/skills/computer-use/SKILL.md +16 -4
  36. package/src/defaults/skills/goal-management/SKILL.md +1 -1
  37. package/src/defaults/skills/setup/references/actions.md +12 -6
  38. package/src/defaults/skills/setup/references/surfaces.md +2 -2
  39. package/src/defaults/skills/setup-guide/SKILL.md +5 -2
  40. package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
  41. package/src/defaults/skills/skill-creator/SKILL.md +85 -190
  42. package/src/defaults/skills/skill-creator/references/design.md +70 -162
  43. package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
  44. package/src/defaults/skills/test-suite/SKILL.md +194 -0
  45. package/src/defaults/skills/test-suite/references/case-management.md +51 -0
  46. package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
  47. package/src/defaults/skills/test-suite/references/reliability.md +49 -0
  48. package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
  49. package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
  50. package/src/defaults/skills/visualize/SKILL.md +6 -2
  51. package/src/lib/rules-builder.cjs +35 -42
  52. package/src/output-styles/common.md +2 -2
  53. package/src/output-styles/simple.md +1 -1
  54. package/src/rules/agent/AGENT.md +5 -4
  55. package/src/rules/lead/LEAD.md +12 -7
  56. package/src/rules/shared/10-tool-workflow.md +3 -1
  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/45-destructive.md +0 -2
  60. package/src/rules/shared/50-execution.md +2 -0
  61. package/src/rules/shared/60-verification.md +10 -9
  62. package/src/rules/shared/70-delivery.md +8 -9
  63. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
  64. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -1
  65. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +156 -24
  66. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -0
  67. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
  69. package/src/runtime/agent/orchestrator/config.mjs +12 -7
  70. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +8 -8
  71. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +5 -26
  72. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +3 -1
  73. package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
  74. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +122 -12
  75. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -3
  76. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +13 -2
  77. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +152 -58
  78. package/src/runtime/agent/orchestrator/mcp/client.mjs +51 -18
  79. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +88 -54
  80. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +42 -26
  81. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +54 -8
  82. package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
  83. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +37 -31
  84. package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
  85. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
  86. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
  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-oauth-request/initial-status.mjs +3 -1
  90. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +14 -3
  91. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +6 -0
  92. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
  93. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
  94. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
  95. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  96. package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
  97. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
  98. package/src/runtime/agent/orchestrator/providers/cursor.mjs +3 -0
  99. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
  100. package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
  101. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
  102. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
  103. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
  104. package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
  105. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
  106. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
  107. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +248 -41
  108. package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
  109. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
  110. package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
  111. package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
  112. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
  113. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
  114. package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
  115. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
  116. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
  117. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
  118. package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
  119. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
  120. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
  121. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
  122. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
  123. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
  124. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
  125. package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
  126. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
  127. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
  128. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
  129. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
  130. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
  131. package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
  132. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
  133. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +160 -31
  134. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +22 -12
  135. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
  136. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +49 -22
  137. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
  138. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
  139. package/src/runtime/agent/orchestrator/providers/registry.mjs +45 -2
  140. package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
  141. package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
  142. package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
  143. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +567 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +41 -13
  145. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
  146. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -6
  147. package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +7 -3
  148. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  149. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -1
  150. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +14 -5
  151. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
  152. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
  153. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
  154. package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
  155. package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
  156. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +102 -12
  157. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
  158. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
  159. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
  160. package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
  161. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +160 -36
  162. package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
  163. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +164 -23
  164. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +139 -19
  165. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
  166. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
  167. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +100 -22
  168. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
  169. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -6
  170. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +33 -3
  171. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +9 -2
  172. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
  173. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
  174. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +14 -0
  175. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +13 -1
  176. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +23 -4
  177. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +2 -0
  178. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
  179. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +39 -21
  180. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
  181. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +50 -28
  182. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
  183. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
  184. package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +2 -2
  185. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +1 -0
  186. package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +2 -1
  187. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +30 -13
  188. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +63 -6
  189. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +7 -0
  190. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
  191. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +35 -13
  192. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +24 -14
  193. package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
  194. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
  195. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +10 -6
  196. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
  197. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +3 -0
  198. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +56 -29
  199. package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
  200. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +11 -5
  201. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +5 -1
  202. package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +30 -7
  203. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
  204. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
  205. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
  206. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
  207. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +37 -8
  208. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +252 -39
  209. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
  210. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +164 -4
  211. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
  212. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +61 -2
  213. package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
  214. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
  215. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
  216. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
  217. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -1
  218. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +46 -20
  219. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
  220. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +67 -31
  221. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +25 -13
  222. package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
  223. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
  224. package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
  225. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
  226. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
  227. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
  228. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
  229. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
  230. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
  231. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +96 -20
  232. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
  233. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
  234. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
  235. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  236. package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
  237. package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
  238. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
  239. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +103 -13
  240. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
  241. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
  242. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
  243. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +34 -10
  244. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +28 -4
  245. package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
  246. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -2
  247. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  248. package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
  249. package/src/runtime/channels/lib/whisper-port.mjs +29 -11
  250. package/src/runtime/channels/lib/whisper-server.mjs +10 -1
  251. package/src/runtime/computer-bridge/action-schema.mjs +2 -2
  252. package/src/runtime/computer-bridge/core-actions.mjs +2 -2
  253. package/src/runtime/computer-bridge/error-recovery.mjs +5 -4
  254. package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
  255. package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
  256. package/src/runtime/connectors/connector-accounts-mcp.mjs +236 -103
  257. package/src/runtime/connectors/gmail-app-password.mjs +3 -3
  258. package/src/runtime/explore/explorer.mjs +93 -0
  259. package/src/runtime/explore/tool-defs.mjs +35 -0
  260. package/src/runtime/explore/tool.mjs +123 -0
  261. package/src/runtime/local-provider/server-process.mjs +2 -1
  262. package/src/runtime/media/adapters/gemini-video.mjs +4 -1
  263. package/src/runtime/media/adapters/xai-media.mjs +2 -1
  264. package/src/runtime/memory/index.mjs +4 -0
  265. package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
  266. package/src/runtime/memory/lib/embedding-worker.mjs +10 -3
  267. package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
  268. package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
  269. package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
  270. package/src/runtime/office/design/design-art-direction.mjs +29 -27
  271. package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
  272. package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
  273. package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
  274. package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
  275. package/src/runtime/office/quality/assurance-structure-docx.mjs +4 -2
  276. package/src/runtime/office/quality/design-review.mjs +1 -5
  277. package/src/runtime/office/quality/document-brief.mjs +1 -5
  278. package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
  279. package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
  280. package/src/runtime/shared/agent-route-config.mjs +17 -2
  281. package/src/runtime/shared/atomic-file.mjs +103 -2
  282. package/src/runtime/shared/background-tasks.mjs +15 -6
  283. package/src/runtime/shared/bot-owned-work.mjs +56 -0
  284. package/src/runtime/shared/connector-accounts.mjs +5 -5
  285. package/src/runtime/shared/connector-catalog.d.mts +11 -4
  286. package/src/runtime/shared/connector-catalog.mjs +60 -52
  287. package/src/runtime/shared/custom-provider-keys.mjs +20 -0
  288. package/src/runtime/shared/defaults-separation.mjs +1 -4
  289. package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
  290. package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
  291. package/src/runtime/shared/file-has-data.mjs +26 -2
  292. package/src/runtime/shared/file-lock.mjs +13 -15
  293. package/src/runtime/shared/git-launch.d.mts +9 -0
  294. package/src/runtime/shared/git-launch.mjs +213 -0
  295. package/src/runtime/shared/git-runner-worker.mjs +2 -1
  296. package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
  297. package/src/runtime/shared/handoff-artifacts.mjs +18 -8
  298. package/src/runtime/shared/idle-auto-clear-gate.mjs +29 -7
  299. package/src/runtime/shared/llm/cost.mjs +11 -2
  300. package/src/runtime/shared/llm/http-agent.mjs +313 -29
  301. package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
  302. package/src/runtime/shared/llm/model-catalog.mjs +46 -6
  303. package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
  304. package/src/runtime/shared/llm/system-proxy.mjs +452 -0
  305. package/src/runtime/shared/loopback-listener.mjs +25 -2
  306. package/src/runtime/shared/model-route-chain.d.mts +7 -2
  307. package/src/runtime/shared/model-route-chain.mjs +22 -4
  308. package/src/runtime/shared/open-url.mjs +10 -0
  309. package/src/runtime/shared/provider-accounts.mjs +52 -2
  310. package/src/runtime/shared/session-activity-signal.mjs +14 -0
  311. package/src/runtime/shared/session-scratch.mjs +37 -0
  312. package/src/runtime/shared/staged-install-worker.mjs +5 -0
  313. package/src/runtime/shared/staged-update.mjs +47 -2
  314. package/src/runtime/shared/tool-card-model/agent-surface.mjs +1 -3
  315. package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
  316. package/src/runtime/shared/tool-result-summary.mjs +1 -1
  317. package/src/runtime/shared/tool-surface.mjs +113 -36
  318. package/src/runtime/shared/tool-work-units.mjs +6 -0
  319. package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
  320. package/src/runtime/shared/turn-worktree-snapshot.mjs +414 -54
  321. package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
  322. package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
  323. package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
  324. package/src/runtime/shared/worktrees/branch-management.mjs +9 -3
  325. package/src/runtime/shared/worktrees/contract.mjs +4 -1
  326. package/src/runtime/shared/worktrees/git.mjs +72 -0
  327. package/src/runtime/shared/worktrees/manager.mjs +285 -168
  328. package/src/runtime/shared/worktrees/test-support.mjs +6 -10
  329. package/src/runtime/tidy/install.mjs +95 -15
  330. package/src/runtime/tidy/languages.mjs +17 -15
  331. package/src/runtime/tidy/process.mjs +7 -4
  332. package/src/runtime/tidy/resolve.mjs +19 -16
  333. package/src/runtime/tidy/runners/biome.mjs +3 -3
  334. package/src/runtime/tidy/tool.mjs +1 -1
  335. package/src/runtime/tidy/worktree.mjs +10 -6
  336. package/src/runtime/visualize-bridge/client.mjs +6 -1
  337. package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
  338. package/src/runtime/web-search/index.mjs +1 -1
  339. package/src/session-runtime/agent-home-delivery.mjs +41 -0
  340. package/src/session-runtime/agent-task-sessions.mjs +458 -312
  341. package/src/session-runtime/agent-tool-routing.mjs +8 -41
  342. package/src/session-runtime/boot/tools.mjs +7 -1
  343. package/src/session-runtime/bot-status.mjs +107 -101
  344. package/src/session-runtime/bot-target.mjs +38 -0
  345. package/src/session-runtime/channel-config-api.mjs +6 -1
  346. package/src/session-runtime/connector-merge-migration.mjs +18 -15
  347. package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
  348. package/src/session-runtime/conversation-import/discovery.mjs +401 -36
  349. package/src/session-runtime/conversation-import/service.mjs +35 -8
  350. package/src/session-runtime/handoff-attachments.mjs +82 -31
  351. package/src/session-runtime/held-requests.mjs +3 -1
  352. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +12 -13
  353. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +1 -0
  354. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -0
  355. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
  356. package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
  357. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +145 -112
  358. package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
  359. package/src/session-runtime/lifecycle/session-catalog.mjs +9 -1
  360. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -1
  361. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  362. package/src/session-runtime/mcp-glue/server-catalog.mjs +16 -10
  363. package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
  364. package/src/session-runtime/mixy-heartbeat.mjs +1 -1
  365. package/src/session-runtime/model-route/set-route.mjs +11 -2
  366. package/src/session-runtime/provider-auth/login.mjs +2 -2
  367. package/src/session-runtime/provider-catalog-cache.mjs +82 -36
  368. package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
  369. package/src/session-runtime/provider-models.mjs +4 -2
  370. package/src/session-runtime/resource-mcp-api.mjs +98 -35
  371. package/src/session-runtime/resource-mcp-connector-accounts.mjs +44 -31
  372. package/src/session-runtime/resource-mcp-secrets.mjs +28 -11
  373. package/src/session-runtime/resource-mcp-servers.mjs +5 -4
  374. package/src/session-runtime/resource-recall-api.mjs +6 -1
  375. package/src/session-runtime/runtime-feature-gates.mjs +5 -1
  376. package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
  377. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
  378. package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
  379. package/src/session-runtime/services/agent-tool/render.mjs +71 -17
  380. package/src/session-runtime/services/agent-tool/send-flow.mjs +10 -2
  381. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
  382. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +4 -1
  383. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +6 -2
  384. package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
  385. package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
  386. package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
  387. package/src/session-runtime/services/daemon-candidate.mjs +4 -1
  388. package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
  389. package/src/session-runtime/services/plugin-admin.mjs +10 -6
  390. package/src/session-runtime/services/provider-admin.mjs +283 -11
  391. package/src/session-runtime/session-turn-api.mjs +2 -0
  392. package/src/session-runtime/settings-builtin-tools-api.mjs +4 -1
  393. package/src/session-runtime/settings-system-api.mjs +1 -1
  394. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
  395. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
  396. package/src/session-runtime/setup-tool/executor.mjs +6 -2
  397. package/src/session-runtime/setup-tool/tool-defs.mjs +2 -1
  398. package/src/session-runtime/tool-policy/policy-stage.mjs +1 -0
  399. package/src/session-runtime/turn/agent-ops.mjs +23 -0
  400. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +49 -11
  401. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
  402. package/src/session-runtime/workflow-agents-api/agent-route.mjs +25 -5
  403. package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
  404. package/src/session-runtime/workspace/activity-guards.mjs +176 -0
  405. package/src/session-runtime/workspace/session-view.mjs +149 -0
  406. package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
  407. package/src/session-runtime/workspace/transition-runner.mjs +188 -0
  408. package/src/session-runtime/workspace/transitions.mjs +108 -1041
  409. package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
  410. package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
  411. package/src/session-runtime/workspace/worktree-maintenance.mjs +80 -0
  412. package/src/session-runtime/workspace/worktree-setup.mjs +85 -0
  413. package/src/session-runtime/workspace/worktree-tool.mjs +73 -56
  414. package/src/standalone/daemon-desktop-runtime.mjs +2 -0
  415. package/src/standalone/daemon-session-control.mjs +169 -138
  416. package/src/standalone/daemon.mjs +7 -0
  417. package/src/standalone/desktop-service-registry.mjs +9 -0
  418. package/src/standalone/local-session-runtime.mjs +5 -1
  419. package/src/standalone/session-client/daemon-unavailable.mjs +3 -0
  420. package/src/standalone/session-client.mjs +5 -1
  421. package/src/standalone/session-frame-stream.mjs +83 -11
  422. package/src/standalone/session-protocol.mjs +4 -0
  423. package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
  424. package/src/standalone/session-service/agent-tree.mjs +45 -9
  425. package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
  426. package/src/standalone/session-service/session-calls/session-action.mjs +10 -3
  427. package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
  428. package/src/standalone/session-service/stored-reader.mjs +127 -40
  429. package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
  430. package/src/tui/App.jsx +154 -164
  431. package/src/tui/app/app-view/floating-panel.jsx +10 -4
  432. package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
  433. package/src/tui/app/clipboard.mjs +21 -10
  434. package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
  435. package/src/tui/app/model-picker/route-selection.mjs +5 -6
  436. package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
  437. package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
  438. package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
  439. package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
  440. package/src/tui/app/provider-setup/oauth-actions.mjs +58 -21
  441. package/src/tui/app/provider-setup/provider-items.mjs +8 -2
  442. package/src/tui/app/provider-setup-picker.mjs +29 -18
  443. package/src/tui/app/shell-layout/row-budgets.mjs +12 -10
  444. package/src/tui/app/slash-commands.mjs +1 -0
  445. package/src/tui/app/slash-dispatch/session-commands.mjs +46 -0
  446. package/src/tui/app/slash-dispatch.mjs +1 -1
  447. package/src/tui/app/use-btw-panel.mjs +29 -0
  448. package/src/tui/app/use-context-panel-refresh.mjs +31 -0
  449. package/src/tui/app/use-model-catalog-cache.mjs +13 -10
  450. package/src/tui/app/use-mouse-input.mjs +11 -0
  451. package/src/tui/app/use-onboarding-start.mjs +8 -3
  452. package/src/tui/app/use-panel-transition.mjs +10 -1
  453. package/src/tui/app/use-pasted-buffers.mjs +28 -20
  454. package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
  455. package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
  456. package/src/tui/app/use-prompt-queue-history.mjs +3 -2
  457. package/src/tui/app/use-selection-focus.mjs +11 -2
  458. package/src/tui/app/use-selection-geometry.mjs +18 -9
  459. package/src/tui/app/use-selection-paint.mjs +4 -4
  460. package/src/tui/app/use-selection-stitch.mjs +3 -3
  461. package/src/tui/app/use-slash-palette.mjs +62 -0
  462. package/src/tui/app/use-terminal-chrome.mjs +2 -2
  463. package/src/tui/app/use-transcript-activity.mjs +47 -32
  464. package/src/tui/app/use-transcript-follow.mjs +12 -4
  465. package/src/tui/app/use-transcript-scroll.mjs +46 -17
  466. package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
  467. package/src/tui/app/use-transcript-window/geometry.mjs +19 -5
  468. package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
  469. package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
  470. package/src/tui/app/use-transcript-window.mjs +21 -11
  471. package/src/tui/app/use-tui-ready.mjs +18 -0
  472. package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
  473. package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
  474. package/src/tui/components/Picker.jsx +27 -3
  475. package/src/tui/components/QuestionPanel.jsx +13 -4
  476. package/src/tui/components/SignInUrl.jsx +68 -0
  477. package/src/tui/components/TextEntryPanel.jsx +76 -46
  478. package/src/tui/components/sign-in-url-layout.mjs +24 -0
  479. package/src/tui/dist/index.mjs +1963 -1361
  480. package/src/tui/session/goal-turn-state.mjs +6 -2
  481. package/src/tui/session/session-api/controls.mjs +4 -0
  482. package/src/tui/session/session-api/extensions.mjs +8 -0
  483. package/src/tui/session/session-api/intake/abort.mjs +2 -1
  484. package/src/tui/session/session-api/intake.mjs +2 -0
  485. package/src/tui/session/session-api/integrations.mjs +2 -2
  486. package/src/tui/session/session-api/routes-agent-definitions.mjs +1 -0
  487. package/src/tui/session/session-api/settings.mjs +2 -2
  488. package/src/tui/session/session-flow/queue/take-entries.mjs +11 -0
  489. package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
  490. package/src/tui/session/transcript-spill.mjs +92 -4
  491. package/src/tui/session/transcript-store.mjs +2 -0
  492. package/src/ui/statusline-agents.mjs +1 -3
  493. package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
@@ -4,7 +4,8 @@
4
4
  // catalog flattened into deduplicated rows with per-provider profiling.
5
5
  import { modelProxyClientMode } from '../../runtime/shared/model-proxy-mode.mjs';
6
6
  import { isSelectableLlmModel } from '../model-recency.mjs';
7
- import { sharedProviderCatalog } from '../provider-catalog-cache.mjs';
7
+ import { scopedProviderCatalog, sharedProviderCatalog } from '../provider-catalog-cache.mjs';
8
+ import { providerRows } from '../services/agent-tool/model-select.mjs';
8
9
  import { NO_ENABLED_PROVIDERS } from '../../runtime/agent/orchestrator/providers/registry-errors.mjs';
9
10
 
10
11
  export function createCatalogLoader({
@@ -42,7 +43,7 @@ export function createCatalogLoader({
42
43
  * refresh invalidates it, leaving the UI on the stale first-open rows.
43
44
  * Resolves false when no provider is enabled: a fresh install has nothing
44
45
  * to load, and the registry refuses an all-disabled init by design. */
45
- async function prepare({ forceRefresh, loadSecrets }) {
46
+ async function prepare({ forceRefresh, loadSecrets, provider }) {
46
47
  if (loadSecrets) {
47
48
  const secretsStartedAt = performance.now();
48
49
  await awaitKeychainPrewarm();
@@ -69,7 +70,15 @@ export function createCatalogLoader({
69
70
  if (!forceRefresh && typeof reg().refreshProviderCatalogsOnStartup === 'function') {
70
71
  await reg().refreshProviderCatalogsOnStartup();
71
72
  }
72
- if (forceRefresh && typeof reg().refreshCatalogs === 'function') {
73
+ if (forceRefresh && provider) {
74
+ // A provider-scoped refresh asks only the registry providers the name
75
+ // matches and folds their entries into the shared catalog; every other
76
+ // provider keeps what it loaded.
77
+ const known = [...reg().getAllProviders().keys()].map((name) => ({ provider: name }));
78
+ const names = providerRows(known, provider).map((row) => row.provider);
79
+ await reg().refreshProviderCatalogsFor(names);
80
+ await scopedProviderCatalog(reg(), names, { timeoutMs: providerTimeoutMs });
81
+ } else if (forceRefresh && typeof reg().refreshCatalogs === 'function') {
73
82
  await reg().refreshCatalogs({ force: true });
74
83
  }
75
84
  profile('catalog-refresh-ready', { ms: (performance.now() - refreshStartedAt).toFixed(1) });
@@ -81,13 +90,18 @@ export function createCatalogLoader({
81
90
  * providers that failed or timed out, `request.partial` marks a load
82
91
  * where some but not all providers answered, and `request.retryAt` is when
83
92
  * the first missing provider may be asked again. */
84
- return async function loadProviderModelsFresh({ forceRefresh = false, loadSecrets = true, request = null } = {}) {
93
+ return async function loadProviderModelsFresh({
94
+ forceRefresh = false,
95
+ loadSecrets = true,
96
+ request = null,
97
+ provider = null,
98
+ } = {}) {
85
99
  const startedAt = performance.now();
86
100
  profile('load:start', { forceRefresh, loadSecrets });
87
101
  // No enabled provider is an empty catalog, not a failure. The request
88
102
  // stays incomplete so this answer is never cached: connecting a provider
89
103
  // is picked up by the next read.
90
- if (!(await prepare({ forceRefresh, loadSecrets }))) {
104
+ if (!(await prepare({ forceRefresh, loadSecrets, provider }))) {
91
105
  profile('load:done', { ms: (performance.now() - startedAt).toFixed(1), providers: 0, rows: 0 });
92
106
  return [];
93
107
  }
@@ -97,7 +111,10 @@ export function createCatalogLoader({
97
111
  // forward only for the still-current request, never for a superseded load.
98
112
  if (ownsLoad) request.seq = caches.providerModelsLoadSeq;
99
113
  const seq = request?.seq ?? caches.providerModelsLoadSeq;
100
- const catalogEntries = await sharedProviderCatalog(reg(), { force: forceRefresh, timeoutMs: providerTimeoutMs });
114
+ const catalogEntries = await sharedProviderCatalog(reg(), {
115
+ force: forceRefresh && !provider,
116
+ timeoutMs: providerTimeoutMs,
117
+ });
101
118
  if (request) {
102
119
  const failed = catalogEntries.filter((entry) => Object.hasOwn(entry, 'error'));
103
120
  request.missing = failed.map((entry) => entry.name);
@@ -156,7 +156,9 @@ export function createProviderModels({
156
156
  return promise;
157
157
  }
158
158
 
159
- async function collectProviderModels({ force = false, quick = false } = {}) {
159
+ /** `provider` (a name or fragment of one) scopes a forced read: only the
160
+ * providers it names are refreshed, the rest keep their loaded entries. */
161
+ async function collectProviderModels({ force = false, quick = false, provider = null } = {}) {
160
162
  meta.syncCatalogRevision();
161
163
  const cached = caches.providerModelsCache;
162
164
  if (!force && Array.isArray(cached.models)) {
@@ -180,7 +182,7 @@ export function createProviderModels({
180
182
  }
181
183
  if (force) {
182
184
  const request = { seq: ++caches.providerModelsLoadSeq };
183
- const models = await loadProviderModelsFresh({ forceRefresh: true, loadSecrets: true, request });
185
+ const models = await loadProviderModelsFresh({ forceRefresh: true, loadSecrets: true, request, provider });
184
186
  adoptProviderModelCache(models, request);
185
187
  return withCatalogState(rows.providerModelsFromCacheRows(models), partialOf(request));
186
188
  }
@@ -14,9 +14,11 @@ import { migrateMergedConnectorServers } from './connector-merge-migration.mjs';
14
14
  import {
15
15
  connectorAccountServers,
16
16
  connectorAccountsOf,
17
+ connectorAppPasswordOnly,
17
18
  connectorById,
18
- connectorMultiAccount,
19
+ connectorServerInput,
19
20
  gmailAppPasswordAccount,
21
+ gmailAppPasswordServerInput,
20
22
  mergeConnectorAccountServers,
21
23
  } from '../runtime/shared/connector-catalog.mjs';
22
24
  import { saveMcpOAuthClientSecret } from '../runtime/agent/orchestrator/mcp/oauth-client.mjs';
@@ -75,14 +77,24 @@ export function createMcpResourceApi({ deps, sync, decorate }) {
75
77
  resolveMcpCatalog,
76
78
  pluginMcpServer,
77
79
  });
78
- const { storeOAuthClientSecret, storeGmailAppPassword, releaseOAuth, forgetUnusedGmailAppPassword, releaseAccount } =
79
- createMcpServerSecrets({
80
- gmailAppPassword,
81
- saveOAuthClientSecret,
82
- clearMcpServerOAuth,
83
- resolveConfiguredMcpCatalog,
84
- });
85
- const { addConnectorAccount, saveConnectorAccount, setConnectorAccountEnabled } = createConnectorAccountEdits({
80
+ const {
81
+ storeOAuthClientSecret,
82
+ storeGmailAppPassword,
83
+ releaseOAuth,
84
+ forgetUnusedGmailAppPassword,
85
+ forgetStoredSecrets,
86
+ releaseAccount,
87
+ } = createMcpServerSecrets({
88
+ gmailAppPassword,
89
+ saveOAuthClientSecret,
90
+ clearMcpServerOAuth,
91
+ resolveConfiguredMcpCatalog,
92
+ });
93
+ const {
94
+ addConnectorAccount: joinConnectorAccount,
95
+ saveConnectorAccount,
96
+ setConnectorAccountEnabled,
97
+ } = createConnectorAccountEdits({
86
98
  normalizeMcpServerInput,
87
99
  pluginMcpServer,
88
100
  sync,
@@ -91,16 +103,65 @@ export function createMcpResourceApi({ deps, sync, decorate }) {
91
103
  storeOAuthClientSecret,
92
104
  storeGmailAppPassword,
93
105
  forgetUnusedGmailAppPassword,
106
+ forgetStoredSecrets,
94
107
  releaseOAuth,
95
108
  });
96
109
  // Peers reload config from disk on receipt: land the write before publishing.
97
110
  const persisted = async () => {
98
111
  await flushSkillsSave?.();
99
112
  };
113
+ // One account addition of a connector at a time, each reading the servers
114
+ // the one before it saved: two at once never take the same name, nor does
115
+ // one's save drop the other's account.
116
+ const connectorAdds = new Map();
117
+ const oneAddAtATime = (connector, run) => {
118
+ const next = (connectorAdds.get(connector) || Promise.resolve()).then(run, run);
119
+ const settled = next.then(
120
+ () => {},
121
+ () => {}
122
+ );
123
+ connectorAdds.set(connector, settled);
124
+ void settled.then(() => {
125
+ if (connectorAdds.get(connector) === settled) connectorAdds.delete(connector);
126
+ });
127
+ return next;
128
+ };
129
+
130
+ async function addMcpServer(input = {}) {
131
+ // A catalog connector's account (as its own server config) joins that
132
+ // connector's one server.
133
+ const connector = clean(input.connector);
134
+ if (connector && !Array.isArray(input.accounts)) return oneAddAtATime(connector, () => addServerNow(input));
135
+ return addServerNow(input);
136
+ }
137
+
138
+ async function addServerNow(input) {
139
+ const { name, config: serverConfig } = normalizeMcpServerInput(input);
140
+ // A catalog connector's server keeps its catalog id (connector-catalog.mjs).
141
+ const connector = clean(input.connector);
142
+ if (connector) {
143
+ if (!connectorById(connector)) throw new Error(`Unknown connector: ${connector}`);
144
+ serverConfig.connector = connector;
145
+ }
146
+ const servers = userServers();
147
+ if (connector && !Array.isArray(input.accounts)) {
148
+ return joinConnectorAccount(servers, connector, name, serverConfig, input);
149
+ }
150
+ if (Object.hasOwn(servers, name) || accountTarget(servers, name)) {
151
+ throw nameTakenError(servers, name);
152
+ }
153
+ const owned = pluginMcpServer(name);
154
+ if (owned) throw new Error(`MCP server already exists: ${name} (provided by plugin "${owned.owner.id}")`);
155
+ await storeOAuthClientSecret(input, serverConfig);
156
+ await storeGmailAppPassword(input, serverConfig, true);
157
+ saveServers({ ...servers, [name]: serverConfig });
158
+ const status = await sync.reconnectMcpAndAnnounce({ only: name, enabled: serverConfig.enabled !== false });
159
+ return { name, status };
160
+ }
100
161
 
101
162
  return {
102
- /** One-time, idempotent: merge the one-account servers of a multi-account
103
- * connector (`gmail`, `gmail-2`…) into one server holding the accounts
163
+ /** One-time, idempotent: merge the one-account servers of a catalog
164
+ * connector (`notion`, `notion-2`…) into one server holding the accounts
104
165
  * (connector-catalog.mjs mergeConnectorAccountServers). Every account
105
166
  * keeps its address, so its stored sign-in and app password stay as
106
167
  * they are. Settings keyed by a merged-away server name go with it:
@@ -155,30 +216,32 @@ export function createMcpResourceApi({ deps, sync, decorate }) {
155
216
  },
156
217
  // Sign-in / sign-out (resource-mcp-oauth-api.mjs), in this key position.
157
218
  ...oauthApi,
158
- async addMcpServer(input = {}) {
159
- const { name, config: serverConfig } = normalizeMcpServerInput(input);
160
- // A catalog connector's server keeps its catalog id (connector-catalog.mjs).
161
- const connector = clean(input.connector);
162
- if (connector) {
163
- if (!connectorById(connector)) throw new Error(`Unknown connector: ${connector}`);
164
- serverConfig.connector = connector;
165
- }
166
- const servers = userServers();
167
- // A multi-account connector's account (as its own server config) joins
168
- // that connector's one server.
169
- if (connector && connectorMultiAccount(connectorById(connector)) && !Array.isArray(input.accounts)) {
170
- return addConnectorAccount(servers, connector, name, serverConfig, input);
171
- }
172
- if (Object.hasOwn(servers, name) || accountTarget(servers, name)) {
173
- throw nameTakenError(servers, name);
174
- }
175
- const owned = pluginMcpServer(name);
176
- if (owned) throw new Error(`MCP server already exists: ${name} (provided by plugin "${owned.owner.id}")`);
177
- await storeOAuthClientSecret(input, serverConfig);
178
- await storeGmailAppPassword(input, serverConfig, true);
179
- saveServers({ ...servers, [name]: serverConfig });
180
- const status = await sync.reconnectMcpAndAnnounce({ only: name, enabled: serverConfig.enabled !== false });
181
- return { name, status };
219
+ addMcpServer,
220
+ /** One more account of catalog connector `input.connector`, connected as
221
+ * its catalog entry says: `key` for an API-key service (Hugging Face,
222
+ * Stripe; Postgres takes its connection string), `email` and
223
+ * `appPassword` for Gmail, nothing more for a sign-in service (the
224
+ * account then signs in with beginMcpOAuthLogin(account)); the user's own
225
+ * OAuth client rides on `oauthClientId` / `oauthClientSecret`. The account
226
+ * gets a free name (`notion`, `notion-2`…) and joins the connector's one
227
+ * server, which is made when there is none. Resolves `{ name, account,
228
+ * status }`: the server's name and the new account's (for a Gmail
229
+ * address already connected, that account, which took the new password). */
230
+ async addConnectorAccount(input = {}) {
231
+ const entry = connectorById(clean(input.connector));
232
+ if (!entry) throw new Error(`Unknown connector: ${clean(input.connector)}`);
233
+ // Its name is picked from the servers the additions before it saved.
234
+ return oneAddAtATime(entry.id, () => {
235
+ const name = freeName(userServers(), entry.id);
236
+ const account = connectorAppPasswordOnly(entry)
237
+ ? gmailAppPasswordServerInput(name, input.email, input.appPassword)
238
+ : connectorServerInput(entry, name, input.key);
239
+ const ownClient = clean(input.oauthClientId);
240
+ return addServerNow({
241
+ ...account,
242
+ ...(ownClient ? { oauthClientId: ownClient, oauthClientSecret: input.oauthClientSecret } : {}),
243
+ });
244
+ });
182
245
  },
183
246
  async saveMcpServer(input = {}) {
184
247
  const servers = userServers();
@@ -1,6 +1,7 @@
1
- // The accounts of a multi-account connector server as the MCP server API
2
- // edits them: adding one more account (into its server, or a new server
3
- // holding it) and editing one account's transport, app password or client.
1
+ // The accounts of a connector server as the MCP server API edits them: adding
2
+ // one more account (into its server, or a new server holding it) and editing
3
+ // one account's transport, app password or client.
4
+ import { randomUUID } from 'node:crypto';
4
5
  import { clean } from '../runtime/agent/orchestrator/runtime-core/session-text.mjs';
5
6
  import {
6
7
  mergeMcpServerConfig,
@@ -13,15 +14,16 @@ import {
13
14
  connectorAccountServers,
14
15
  connectorAccountsOf,
15
16
  connectorAccountsUrl,
16
- connectorById,
17
17
  connectorOfServer,
18
+ connectorServerSettings,
18
19
  gmailAppPasswordAccount,
19
20
  withConnectorAccountEnabled,
20
21
  } from '../runtime/shared/connector-catalog.mjs';
21
22
  import { forgetConnectorAccountHealth } from '../runtime/connectors/connector-accounts-mcp.mjs';
22
- import { accountTarget, mergedServerInput, nameTakenError, oauthUrlOf } from './resource-mcp-servers.mjs';
23
+ import { hasConfiguredMcpAuth } from '../runtime/agent/orchestrator/mcp/client-transport.mjs';
24
+ import { accountTarget, mergedServerInput, nameTakenError, oauthCredentialOf } from './resource-mcp-servers.mjs';
23
25
 
24
- /** The server of multi-account connector `connector` in `servers`, or ''. */
26
+ /** The server of connector `connector` in `servers`, or ''. */
25
27
  function connectorServerName(servers, connector) {
26
28
  return (
27
29
  Object.keys(servers).find(
@@ -36,7 +38,7 @@ function connectorServerName(servers, connector) {
36
38
  export const editsServerItself = (target, input) => {
37
39
  if (target.serverName !== target.account.name || !clean(input.url)) return false;
38
40
  try {
39
- return oauthUrlOf({ type: input.type || 'http', url: input.url }) === oauthUrlOf(target.cfg);
41
+ return oauthCredentialOf({ type: input.type || 'http', url: input.url }) === oauthCredentialOf(target.cfg);
40
42
  } catch {
41
43
  return false;
42
44
  }
@@ -51,12 +53,14 @@ export function createConnectorAccountEdits({
51
53
  storeOAuthClientSecret,
52
54
  storeGmailAppPassword,
53
55
  forgetUnusedGmailAppPassword,
56
+ forgetStoredSecrets,
54
57
  releaseOAuth,
55
58
  }) {
56
- /** One more account of multi-account connector `connector` (one-account
57
- * config `accountCfg` as normalized from `input`): into its server, or a
58
- * new server named `name` holding it. The same Gmail address again takes
59
- * the new app password. Resolves `{ name, account, status }`. */
59
+ /** One more account of connector `connector` (one-account config
60
+ * `accountCfg` as normalized from `input`): into its server, or a new
61
+ * server named `name` holding it. The same Gmail address again takes the
62
+ * new app password. `servers` is read under the caller's per-connector
63
+ * serialization (resource-mcp-api.mjs). Resolves `{ name, account, status }`. */
60
64
  async function addConnectorAccount(servers, connector, name, accountCfg, input) {
61
65
  const serverName = connectorServerName(servers, connector);
62
66
  const address = gmailAppPasswordAccount(accountCfg);
@@ -77,29 +81,38 @@ export function createConnectorAccountEdits({
77
81
  }
78
82
  const accountName = serverName ? freeName(servers, name) : name;
79
83
  const account = connectorAccountEntry(accountName, accountCfg);
80
- // Sign-in tokens are stored per exact URL: another account needs its own.
81
- const backendUrl = connectorById(connector)?.backend?.url;
82
- if (
83
- !address &&
84
- cfg &&
85
- connectorAccountServers(cfg).some((other) => oauthUrlOf(other) === oauthUrlOf({ type: 'http', url: account.url }))
86
- ) {
87
- account.url = `${backendUrl}?account=${encodeURIComponent(accountName)}`;
84
+ // A sign-in is stored per exact URL: another account signing in at the
85
+ // same URL gets its own key, so the two never share tokens.
86
+ const asServer = connectorAccountServer({ connector }, account);
87
+ const signIn = hasConfiguredMcpAuth(asServer) ? null : oauthCredentialOf(asServer);
88
+ if (signIn && cfg && connectorAccountServers(cfg).some((other) => oauthCredentialOf(other) === signIn)) {
89
+ account.oauthKey = randomUUID();
88
90
  }
89
91
  const storedCfg = connectorAccountServer({ connector }, account);
90
- await storeOAuthClientSecret(input, storedCfg);
91
- await storeGmailAppPassword(input, storedCfg, true);
92
- forgetConnectorAccountHealth(accountName);
93
92
  let target = serverName;
94
- if (cfg) {
95
- servers[serverName] = { ...cfg, accounts: [...connectorAccountsOf(cfg), account] };
96
- } else {
97
- // The server's own settings (timeouts, enabled) ride on the input.
98
- const { type: _type, url: _url, headers: _headers, oauthClientId: _client, ...rest } = accountCfg;
99
- target = name;
100
- servers[name] = { ...rest, type: 'http', url: connectorAccountsUrl(connector), connector, accounts: [account] };
93
+ // Its secrets and its config land together: a failed step takes back the secrets.
94
+ try {
95
+ await storeOAuthClientSecret(input, storedCfg);
96
+ await storeGmailAppPassword(input, storedCfg, true);
97
+ if (cfg) {
98
+ servers[serverName] = { ...cfg, accounts: [...connectorAccountsOf(cfg), account] };
99
+ } else {
100
+ // The server's own settings (timeouts, enabled) ride on the input.
101
+ target = name;
102
+ servers[name] = {
103
+ ...connectorServerSettings(accountCfg),
104
+ type: 'http',
105
+ url: connectorAccountsUrl(connector),
106
+ connector,
107
+ accounts: [account],
108
+ };
109
+ }
110
+ saveServers(servers);
111
+ } catch (error) {
112
+ await forgetStoredSecrets(storedCfg);
113
+ throw error;
101
114
  }
102
- saveServers(servers);
115
+ forgetConnectorAccountHealth(accountName);
103
116
  const status = await sync.reconnectMcpAndAnnounce({ only: target, enabled: servers[target].enabled !== false });
104
117
  return { name: target, account: accountName, status };
105
118
  }
@@ -116,7 +129,7 @@ export function createConnectorAccountEdits({
116
129
  await storeOAuthClientSecret(input, next, accountCfg);
117
130
  await storeGmailAppPassword(input, next, false);
118
131
  // Settings that are not the account's transport (timeouts) are the server's.
119
- const { type: _type, url: _url, headers: _headers, oauthClientId: _client, ...serverFields } = config;
132
+ const serverFields = connectorServerSettings(config);
120
133
  const server = { ...cfg };
121
134
  for (const group of MCP_TIMEOUT_FIELD_GROUPS) {
122
135
  if (group.some((field) => Object.hasOwn(serverFields, field))) for (const field of group) delete server[field];
@@ -6,8 +6,8 @@ import {
6
6
  gmailAppPasswordValue,
7
7
  connectorAccountServers,
8
8
  } from '../runtime/shared/connector-catalog.mjs';
9
- import { forgetConnectorAccountHealth } from '../runtime/connectors/connector-accounts-mcp.mjs';
10
- import { oauthUrlOf } from './resource-mcp-servers.mjs';
9
+ import { forgetConnectorAccountHealth, retireConnectorAccount } from '../runtime/connectors/connector-accounts-mcp.mjs';
10
+ import { oauthCredentialOf } from './resource-mcp-servers.mjs';
11
11
 
12
12
  /** Every config `servers` connects with, a multi-account server's accounts
13
13
  * as the one-account configs they are. */
@@ -44,15 +44,16 @@ export function createMcpServerSecrets({
44
44
  }
45
45
  };
46
46
  // A server's OAuth tokens and client registration go with it, unless another
47
- // configured server (plugin or disabled ones included, even with MCP
48
- // disabled for this runtime) still uses them through the same exact URL.
49
- // `signIn` tells the caller what happened to the sign-in: `removed` (local
50
- // secrets deleted, `revoked` when the provider confirmed the revocation
51
- // too), `shared` (another server still uses it), or none (null).
47
+ // configured server or account (plugin or disabled ones included, even with
48
+ // MCP disabled for this runtime) still uses them through the same exact URL
49
+ // (or the same account key). `signIn` tells the caller what happened to the
50
+ // sign-in: `removed` (local secrets deleted, `revoked` when the provider
51
+ // confirmed the revocation too), `shared` (another server still uses it),
52
+ // or none (null).
52
53
  const releaseOAuth = async (cfg) => {
53
- const url = oauthUrlOf(cfg);
54
- if (!url) return null;
55
- if (expandedConfigs(resolveConfiguredMcpCatalog().servers).some((other) => oauthUrlOf(other) === url)) {
54
+ const key = oauthCredentialOf(cfg);
55
+ if (!key) return null;
56
+ if (expandedConfigs(resolveConfiguredMcpCatalog().servers).some((other) => oauthCredentialOf(other) === key)) {
56
57
  return { signIn: 'shared', revoked: false };
57
58
  }
58
59
  const { revoked = false } = (await clearMcpServerOAuth(cfg, { revoke: true })) || {};
@@ -66,10 +67,19 @@ export function createMcpServerSecrets({
66
67
  await gmailAppPassword.forget(account);
67
68
  return true;
68
69
  };
70
+ // What storeOAuthClientSecret / storeGmailAppPassword stored for `cfg`, gone
71
+ // again unless a configured server uses it (an add that was not saved).
72
+ const forgetStoredSecrets = async (cfg) => {
73
+ await forgetUnusedGmailAppPassword(gmailAppPasswordAccount(cfg));
74
+ if (!cfg?.url || !cfg.oauthClientId) return;
75
+ const servers = expandedConfigs(resolveConfiguredMcpCatalog().servers);
76
+ if (!servers.some((other) => other.url === cfg.url && other.oauthClientId)) await saveOAuthClientSecret(cfg.url, '');
77
+ };
69
78
  // A removed account keeps no sign-in another configured server or account
70
79
  // does not share: `{ signIn, revoked }` as removeMcpServer reports it.
71
80
  const releaseAccount = async (accountCfg) => {
72
81
  forgetConnectorAccountHealth(accountCfg.name);
82
+ retireConnectorAccount(accountCfg.connector, accountCfg.name);
73
83
  const address = gmailAppPasswordAccount(accountCfg);
74
84
  if (address) {
75
85
  const forgotten = await forgetUnusedGmailAppPassword(address);
@@ -78,5 +88,12 @@ export function createMcpServerSecrets({
78
88
  return releaseOAuth(accountCfg);
79
89
  };
80
90
 
81
- return { storeOAuthClientSecret, storeGmailAppPassword, releaseOAuth, forgetUnusedGmailAppPassword, releaseAccount };
91
+ return {
92
+ storeOAuthClientSecret,
93
+ storeGmailAppPassword,
94
+ releaseOAuth,
95
+ forgetUnusedGmailAppPassword,
96
+ forgetStoredSecrets,
97
+ releaseAccount,
98
+ };
82
99
  }
@@ -3,7 +3,7 @@
3
3
  // name refusals and the merge of a partial server edit.
4
4
  import { clean } from '../runtime/agent/orchestrator/runtime-core/session-text.mjs';
5
5
  import { MCP_TIMEOUT_FIELD_GROUPS } from '../runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs';
6
- import { resolveMcpOAuthUrl } from '../runtime/agent/orchestrator/mcp/client-config.mjs';
6
+ import { resolveMcpOAuthCredentialKey } from '../runtime/agent/orchestrator/mcp/client-config.mjs';
7
7
  import {
8
8
  connectorAccountServer,
9
9
  connectorAccountsOf,
@@ -11,10 +11,11 @@ import {
11
11
  connectorOfServer,
12
12
  } from '../runtime/shared/connector-catalog.mjs';
13
13
 
14
- /** The URL a server's OAuth credentials are stored under, or null. */
15
- export function oauthUrlOf(cfg) {
14
+ /** What a server's OAuth credentials are stored under (its URL, or a
15
+ * connector account's own key), or null. */
16
+ export function oauthCredentialOf(cfg) {
16
17
  try {
17
- return resolveMcpOAuthUrl(cfg);
18
+ return resolveMcpOAuthCredentialKey(cfg);
18
19
  } catch {
19
20
  // No valid remote URL: such a server never logged in.
20
21
  return null;
@@ -1,6 +1,11 @@
1
1
  // Memory control and recall: the current session's own rows first, then the
2
2
  // memory runtime (with a forced ingest of the live session when it is empty).
3
- import { clean, toolResponseText, isEmptyRecallText, currentSessionRecallRows } from '../runtime/agent/orchestrator/runtime-core/session-text.mjs';
3
+ import {
4
+ clean,
5
+ toolResponseText,
6
+ isEmptyRecallText,
7
+ currentSessionRecallRows,
8
+ } from '../runtime/agent/orchestrator/runtime-core/session-text.mjs';
4
9
 
5
10
  function isIdentityRecallQuery(query) {
6
11
  const q = clean(query).toLowerCase().replace(/\s+/g, '');
@@ -4,7 +4,11 @@
4
4
  //
5
5
  // Key names mirror the dependency names of settings-api.mjs / the session-build
6
6
  // deps, so the runtime can hand them straight through.
7
- import { builtinFeatureActive, featureDisallowedToolsFor, localGitToolsActive } from '../runtime/agent/orchestrator/runtime-core/builtin-features.mjs';
7
+ import {
8
+ builtinFeatureActive,
9
+ featureDisallowedToolsFor,
10
+ localGitToolsActive,
11
+ } from '../runtime/agent/orchestrator/runtime-core/builtin-features.mjs';
8
12
  import { recapEnabled } from '../runtime/agent/orchestrator/runtime-core/config-helpers.mjs';
9
13
  import { browserBridgeAvailableSync } from '../runtime/browser-bridge/client.mjs';
10
14
  import { computerBridgeAvailableSync } from '../runtime/computer-bridge/client.mjs';
@@ -66,15 +66,20 @@ export function createAgentExecute({
66
66
  });
67
67
  }
68
68
  // Targetless status is the same compact overview as list.
69
- return renderResult({
70
- // Idle workers stay open for follow-ups; the model must see them to close them.
71
- workers: views.list({
72
- scanSessions: registry.wantsSessionScan(args),
73
- context: scopedContext,
74
- includeIdle: true,
75
- }),
76
- jobs: views.listJobs(scopedContext),
77
- });
69
+ return renderResult(
70
+ {
71
+ // Idle workers stay open for follow-ups; the roster counts them and
72
+ // lists a bounded tail (or the `tag` matches) so they can be closed.
73
+ workers: views.list({
74
+ scanSessions: registry.wantsSessionScan(args),
75
+ context: scopedContext,
76
+ includeIdle: true,
77
+ includeClosed: true,
78
+ }),
79
+ jobs: views.listJobs(scopedContext),
80
+ },
81
+ { listFilter: clean(args.tag) }
82
+ );
78
83
  case 'read':
79
84
  return await readJob(args, scopedContext);
80
85
  case 'cleanup':
@@ -27,8 +27,12 @@ export function isActiveWorkerRow(row = {}) {
27
27
 
28
28
  // A finished worker that is still open: it takes follow-ups and can be closed.
29
29
  function isOpenIdleRow(row = {}) {
30
- const status = String(row.status ?? '').trim().toLowerCase();
31
- const stage = String(row.stage ?? '').trim().toLowerCase();
30
+ const status = String(row.status ?? '')
31
+ .trim()
32
+ .toLowerCase();
33
+ const stage = String(row.stage ?? '')
34
+ .trim()
35
+ .toLowerCase();
32
36
  if (CANCELLED_WORKER_STATUS.test(stage) || CANCELLED_WORKER_STATUS.test(status)) return false;
33
37
  return (status || stage) === 'idle';
34
38
  }
@@ -86,7 +90,13 @@ function agentRow({ tag, session, runtime, progress, now, indexRow = null }) {
86
90
  }
87
91
 
88
92
  export function createAgentList({ mgr, refreshTagsFromSessions, agentSessionEntries, progress }) {
89
- return function list({ scanSessions = false, context = {}, includeTerminal = false, includeIdle = false } = {}) {
93
+ return function list({
94
+ scanSessions = false,
95
+ context = {},
96
+ includeTerminal = false,
97
+ includeIdle = false,
98
+ includeClosed = false,
99
+ } = {}) {
90
100
  refreshTagsFromSessions({ scanSessions, context });
91
101
  const now = Date.now();
92
102
  const rows = [];
@@ -98,7 +108,13 @@ export function createAgentList({ mgr, refreshTagsFromSessions, agentSessionEntr
98
108
  // 2 s) would otherwise read every worker it ever ran, whole transcripts
99
109
  // on first sight, synchronously on the daemon loop.
100
110
  const state = rowState(session, runtime);
101
- if (!includeTerminal && !isActiveWorkerRow(state) && !(includeIdle && isOpenIdleRow(state))) continue;
111
+ if (
112
+ !includeTerminal &&
113
+ !isActiveWorkerRow(state) &&
114
+ !(includeIdle && isOpenIdleRow(state)) &&
115
+ !(includeClosed && state.status === 'closed')
116
+ )
117
+ continue;
102
118
  rows.push(
103
119
  agentRow({
104
120
  tag,