mixdog 1.4.1 → 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 (326) hide show
  1. package/package.json +3 -2
  2. package/scripts/build-shipped-history.mjs +115 -33
  3. package/scripts/gate-local.mjs +172 -61
  4. package/scripts/lib/gate-scheduler.mjs +138 -32
  5. package/scripts/lib/gate-timing-reporter.mjs +16 -0
  6. package/scripts/lib/run-node-tests.mjs +54 -29
  7. package/scripts/lib/scoped-temp.mjs +1 -0
  8. package/scripts/lib/test-failure-records.mjs +14 -1
  9. package/scripts/lib/test-failure-summary.mjs +16 -4
  10. package/scripts/lib/test-spawn-ledger.mjs +12 -3
  11. package/scripts/pptx-kit-index.mjs +5 -6
  12. package/scripts/suite-health.mjs +110 -28
  13. package/scripts/test.mjs +9 -14
  14. package/src/agents/advisor/AGENT.md +4 -4
  15. package/src/agents/advisor/agent.json +1 -1
  16. package/src/agents/explore/AGENT.md +22 -0
  17. package/src/agents/explore/agent.json +6 -0
  18. package/src/cli.mjs +7 -0
  19. package/src/defaults/agents.json +7 -0
  20. package/src/defaults/shipped-history.json +18 -2
  21. package/src/defaults/skills/browser-use/SKILL.md +4 -1
  22. package/src/defaults/skills/code-tidy/SKILL.md +71 -102
  23. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
  24. package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
  25. package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
  26. package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
  27. package/src/defaults/skills/computer-use/SKILL.md +12 -2
  28. package/src/defaults/skills/goal-management/SKILL.md +1 -1
  29. package/src/defaults/skills/setup/references/actions.md +12 -6
  30. package/src/defaults/skills/setup/references/surfaces.md +2 -2
  31. package/src/defaults/skills/setup-guide/SKILL.md +5 -2
  32. package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
  33. package/src/defaults/skills/skill-creator/SKILL.md +85 -190
  34. package/src/defaults/skills/skill-creator/references/design.md +70 -162
  35. package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
  36. package/src/defaults/skills/test-suite/SKILL.md +194 -0
  37. package/src/defaults/skills/test-suite/references/case-management.md +51 -0
  38. package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
  39. package/src/defaults/skills/test-suite/references/reliability.md +49 -0
  40. package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
  41. package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
  42. package/src/defaults/skills/visualize/SKILL.md +6 -2
  43. package/src/lib/rules-builder.cjs +6 -30
  44. package/src/rules/lead/LEAD.md +3 -3
  45. package/src/rules/shared/20-research.md +3 -6
  46. package/src/rules/shared/40-editing.md +1 -0
  47. package/src/rules/shared/60-verification.md +10 -9
  48. package/src/rules/shared/70-delivery.md +4 -3
  49. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
  50. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -1
  51. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +130 -21
  52. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -0
  53. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
  54. package/src/runtime/agent/orchestrator/config.mjs +12 -7
  55. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +7 -7
  56. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +5 -26
  57. package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
  58. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +122 -12
  59. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -3
  60. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +13 -2
  61. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +152 -58
  62. package/src/runtime/agent/orchestrator/mcp/client.mjs +51 -18
  63. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +83 -52
  64. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +42 -26
  65. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +43 -8
  66. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +30 -28
  67. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  68. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
  69. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
  70. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
  71. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  72. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
  73. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
  74. package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
  75. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
  76. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
  77. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
  78. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
  79. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
  80. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +48 -31
  81. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
  82. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
  83. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
  84. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
  85. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
  86. package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
  87. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +26 -28
  88. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +3 -1
  89. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +1 -0
  90. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
  91. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
  92. package/src/runtime/agent/orchestrator/providers/registry.mjs +33 -2
  93. package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
  94. package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
  95. package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
  96. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +567 -0
  97. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
  98. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +2 -1
  99. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  100. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +3 -0
  101. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +14 -5
  102. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
  103. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
  104. package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
  105. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +94 -10
  106. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +3 -3
  107. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +10 -5
  108. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +5 -5
  109. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +11 -1
  110. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
  111. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -6
  112. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +5 -3
  113. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +21 -2
  114. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +2 -0
  115. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
  116. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
  117. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +50 -28
  118. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +1 -0
  119. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +3 -4
  120. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +2 -0
  121. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +7 -0
  122. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
  123. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +25 -14
  124. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +17 -14
  125. package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
  126. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
  127. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +7 -3
  128. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +47 -29
  129. package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
  130. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +11 -5
  131. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +1 -1
  132. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +243 -38
  133. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
  134. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +164 -4
  135. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
  136. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
  137. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +36 -26
  138. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +3 -5
  139. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
  140. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
  141. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +96 -20
  142. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
  143. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  144. package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
  145. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
  146. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +103 -13
  147. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
  148. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
  149. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
  150. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +34 -10
  151. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +2 -0
  152. package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
  153. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -2
  154. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  155. package/src/runtime/channels/lib/whisper-port.mjs +19 -10
  156. package/src/runtime/channels/lib/whisper-server.mjs +10 -1
  157. package/src/runtime/connectors/connector-accounts-mcp.mjs +236 -103
  158. package/src/runtime/connectors/gmail-app-password.mjs +3 -3
  159. package/src/runtime/explore/explorer.mjs +93 -0
  160. package/src/runtime/explore/tool-defs.mjs +35 -0
  161. package/src/runtime/explore/tool.mjs +123 -0
  162. package/src/runtime/memory/index.mjs +4 -0
  163. package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
  164. package/src/runtime/memory/lib/embedding-worker.mjs +4 -0
  165. package/src/runtime/office/quality/assurance-structure-docx.mjs +1 -1
  166. package/src/runtime/shared/agent-route-config.mjs +17 -2
  167. package/src/runtime/shared/atomic-file.mjs +103 -2
  168. package/src/runtime/shared/background-tasks.mjs +15 -6
  169. package/src/runtime/shared/connector-accounts.mjs +5 -5
  170. package/src/runtime/shared/connector-catalog.d.mts +11 -4
  171. package/src/runtime/shared/connector-catalog.mjs +60 -52
  172. package/src/runtime/shared/custom-provider-keys.mjs +20 -0
  173. package/src/runtime/shared/file-has-data.mjs +26 -2
  174. package/src/runtime/shared/file-lock.mjs +13 -15
  175. package/src/runtime/shared/git-launch.d.mts +9 -0
  176. package/src/runtime/shared/git-launch.mjs +213 -0
  177. package/src/runtime/shared/git-runner-worker.mjs +2 -1
  178. package/src/runtime/shared/llm/cost.mjs +6 -1
  179. package/src/runtime/shared/llm/http-agent.mjs +313 -29
  180. package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
  181. package/src/runtime/shared/llm/model-catalog.mjs +46 -6
  182. package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
  183. package/src/runtime/shared/llm/system-proxy.mjs +452 -0
  184. package/src/runtime/shared/provider-accounts.mjs +52 -2
  185. package/src/runtime/shared/staged-install-worker.mjs +5 -0
  186. package/src/runtime/shared/staged-update.mjs +47 -2
  187. package/src/runtime/shared/tool-surface.mjs +110 -36
  188. package/src/runtime/shared/tool-work-units.mjs +4 -0
  189. package/src/runtime/shared/turn-worktree-snapshot.mjs +414 -54
  190. package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
  191. package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
  192. package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
  193. package/src/runtime/shared/worktrees/branch-management.mjs +9 -3
  194. package/src/runtime/shared/worktrees/git.mjs +57 -0
  195. package/src/runtime/shared/worktrees/manager.mjs +205 -137
  196. package/src/runtime/tidy/install.mjs +95 -15
  197. package/src/runtime/tidy/languages.mjs +17 -15
  198. package/src/runtime/tidy/process.mjs +7 -4
  199. package/src/runtime/tidy/resolve.mjs +19 -16
  200. package/src/runtime/tidy/runners/biome.mjs +3 -3
  201. package/src/runtime/tidy/tool.mjs +1 -1
  202. package/src/runtime/tidy/worktree.mjs +10 -6
  203. package/src/runtime/visualize-bridge/client.mjs +4 -1
  204. package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
  205. package/src/runtime/web-search/index.mjs +1 -1
  206. package/src/session-runtime/agent-task-sessions.mjs +410 -353
  207. package/src/session-runtime/boot/tools.mjs +2 -0
  208. package/src/session-runtime/bot-status.mjs +103 -103
  209. package/src/session-runtime/connector-merge-migration.mjs +18 -15
  210. package/src/session-runtime/conversation-import/discovery.mjs +159 -40
  211. package/src/session-runtime/conversation-import/service.mjs +9 -3
  212. package/src/session-runtime/handoff-attachments.mjs +1 -1
  213. package/src/session-runtime/held-requests.mjs +3 -1
  214. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -0
  215. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
  216. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +143 -116
  217. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -1
  218. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  219. package/src/session-runtime/mcp-glue/server-catalog.mjs +16 -10
  220. package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
  221. package/src/session-runtime/mixy-heartbeat.mjs +1 -1
  222. package/src/session-runtime/provider-auth/login.mjs +2 -2
  223. package/src/session-runtime/resource-mcp-api.mjs +98 -35
  224. package/src/session-runtime/resource-mcp-connector-accounts.mjs +44 -31
  225. package/src/session-runtime/resource-mcp-secrets.mjs +28 -11
  226. package/src/session-runtime/resource-mcp-servers.mjs +5 -4
  227. package/src/session-runtime/services/agent-tool/send-flow.mjs +10 -2
  228. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
  229. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +4 -1
  230. package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
  231. package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
  232. package/src/session-runtime/services/daemon-candidate.mjs +4 -1
  233. package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
  234. package/src/session-runtime/services/plugin-admin.mjs +10 -6
  235. package/src/session-runtime/services/provider-admin.mjs +281 -10
  236. package/src/session-runtime/session-turn-api.mjs +2 -0
  237. package/src/session-runtime/settings-builtin-tools-api.mjs +4 -1
  238. package/src/session-runtime/settings-system-api.mjs +1 -1
  239. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
  240. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
  241. package/src/session-runtime/setup-tool/executor.mjs +6 -2
  242. package/src/session-runtime/setup-tool/tool-defs.mjs +2 -1
  243. package/src/session-runtime/turn/agent-ops.mjs +23 -0
  244. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +49 -11
  245. package/src/session-runtime/workflow-agents-api/agent-route.mjs +10 -1
  246. package/src/session-runtime/workspace/activity-guards.mjs +176 -0
  247. package/src/session-runtime/workspace/session-view.mjs +149 -0
  248. package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
  249. package/src/session-runtime/workspace/transition-runner.mjs +188 -0
  250. package/src/session-runtime/workspace/transitions.mjs +108 -1066
  251. package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
  252. package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
  253. package/src/session-runtime/workspace/worktree-maintenance.mjs +80 -0
  254. package/src/session-runtime/workspace/worktree-setup.mjs +85 -0
  255. package/src/session-runtime/workspace/worktree-tool.mjs +54 -54
  256. package/src/standalone/daemon-desktop-runtime.mjs +2 -0
  257. package/src/standalone/daemon-session-control.mjs +151 -136
  258. package/src/standalone/daemon.mjs +7 -0
  259. package/src/standalone/desktop-service-registry.mjs +9 -0
  260. package/src/standalone/local-session-runtime.mjs +5 -1
  261. package/src/standalone/session-client/daemon-unavailable.mjs +3 -0
  262. package/src/standalone/session-client.mjs +5 -1
  263. package/src/standalone/session-frame-stream.mjs +83 -11
  264. package/src/standalone/session-protocol.mjs +4 -0
  265. package/src/standalone/session-service/agent-tree.mjs +45 -9
  266. package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
  267. package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
  268. package/src/standalone/session-service/stored-reader.mjs +127 -40
  269. package/src/tui/App.jsx +154 -164
  270. package/src/tui/app/app-view/floating-panel.jsx +3 -0
  271. package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
  272. package/src/tui/app/clipboard.mjs +21 -10
  273. package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
  274. package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
  275. package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
  276. package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
  277. package/src/tui/app/provider-setup/oauth-actions.mjs +25 -6
  278. package/src/tui/app/provider-setup-picker.mjs +20 -13
  279. package/src/tui/app/shell-layout/row-budgets.mjs +12 -10
  280. package/src/tui/app/slash-commands.mjs +1 -0
  281. package/src/tui/app/slash-dispatch/session-commands.mjs +46 -0
  282. package/src/tui/app/slash-dispatch.mjs +1 -1
  283. package/src/tui/app/use-btw-panel.mjs +29 -0
  284. package/src/tui/app/use-context-panel-refresh.mjs +31 -0
  285. package/src/tui/app/use-model-catalog-cache.mjs +13 -10
  286. package/src/tui/app/use-mouse-input.mjs +11 -0
  287. package/src/tui/app/use-onboarding-start.mjs +8 -3
  288. package/src/tui/app/use-panel-transition.mjs +10 -1
  289. package/src/tui/app/use-pasted-buffers.mjs +28 -20
  290. package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
  291. package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
  292. package/src/tui/app/use-prompt-queue-history.mjs +3 -2
  293. package/src/tui/app/use-selection-focus.mjs +11 -2
  294. package/src/tui/app/use-selection-geometry.mjs +18 -9
  295. package/src/tui/app/use-selection-paint.mjs +4 -4
  296. package/src/tui/app/use-selection-stitch.mjs +3 -3
  297. package/src/tui/app/use-slash-palette.mjs +62 -0
  298. package/src/tui/app/use-terminal-chrome.mjs +2 -2
  299. package/src/tui/app/use-transcript-activity.mjs +47 -32
  300. package/src/tui/app/use-transcript-follow.mjs +12 -4
  301. package/src/tui/app/use-transcript-scroll.mjs +46 -17
  302. package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
  303. package/src/tui/app/use-transcript-window/geometry.mjs +19 -5
  304. package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
  305. package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
  306. package/src/tui/app/use-transcript-window.mjs +21 -11
  307. package/src/tui/app/use-tui-ready.mjs +18 -0
  308. package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
  309. package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
  310. package/src/tui/components/Picker.jsx +27 -3
  311. package/src/tui/components/SignInUrl.jsx +68 -0
  312. package/src/tui/components/TextEntryPanel.jsx +76 -46
  313. package/src/tui/components/sign-in-url-layout.mjs +24 -0
  314. package/src/tui/dist/index.mjs +1896 -1341
  315. package/src/tui/session/goal-turn-state.mjs +6 -2
  316. package/src/tui/session/session-api/controls.mjs +4 -0
  317. package/src/tui/session/session-api/extensions.mjs +8 -0
  318. package/src/tui/session/session-api/intake/abort.mjs +2 -1
  319. package/src/tui/session/session-api/intake.mjs +2 -0
  320. package/src/tui/session/session-api/integrations.mjs +2 -2
  321. package/src/tui/session/session-api/routes-agent-definitions.mjs +1 -0
  322. package/src/tui/session/session-api/settings.mjs +2 -2
  323. package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
  324. package/src/tui/session/transcript-spill.mjs +92 -4
  325. package/src/tui/session/transcript-store.mjs +2 -0
  326. package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
@@ -0,0 +1,35 @@
1
+ import { TOOL_SYNC_EXECUTION_CONTRACT } from '../shared/tool-execution-contract.mjs';
2
+
3
+ export const EXPLORE_MAX_QUERIES = 8;
4
+
5
+ export const TOOL_DEFS = [
6
+ {
7
+ name: 'explore',
8
+ title: 'Explore',
9
+ annotations: {
10
+ title: 'Explore',
11
+ readOnlyHint: true,
12
+ destructiveHint: false,
13
+ idempotentHint: true,
14
+ openWorldHint: false,
15
+ },
16
+ description:
17
+ 'Read-only code search in parallel explorers outside your context; returns one merged answer with path:line evidence. ' +
18
+ 'Use when locating needs 3+ searches, spans 2+ files or areas, or covers independent questions; a known file or one lookup: read/grep. ' +
19
+ TOOL_SYNC_EXECUTION_CONTRACT,
20
+ inputSchema: {
21
+ type: 'object',
22
+ properties: {
23
+ query: {
24
+ anyOf: [
25
+ { type: 'string', minLength: 1 },
26
+ { type: 'array', items: { type: 'string', minLength: 1 }, minItems: 1, maxItems: EXPLORE_MAX_QUERIES },
27
+ ],
28
+ description: 'One self-contained question, or an array of independent ones (one explorer each).',
29
+ },
30
+ },
31
+ required: ['query'],
32
+ additionalProperties: false,
33
+ },
34
+ },
35
+ ];
@@ -0,0 +1,123 @@
1
+ // The explore tool: one read-only explorer loop per query (explorer.mjs), all
2
+ // in parallel, merged into one bounded answer within the same tool call.
3
+ import { resolveMaintenanceRoute } from '../agent/orchestrator/agent-runtime/maintenance-route.mjs';
4
+ import { loadConfig } from '../agent/orchestrator/config.mjs';
5
+ import { getProvider, initProviders } from '../agent/orchestrator/providers/registry.mjs';
6
+ import { EXPLORE_MAX_QUERIES } from './tool-defs.mjs';
7
+ import { runExplorer } from './explorer.mjs';
8
+
9
+ // Hidden ids are reserved from user agents, so this one keeps the `-agent`
10
+ // suffix: a plain `explorer` would hide a user's own Explorer agent.
11
+ export const EXPLORER_AGENT = 'explore-agent';
12
+ export const EXPLORE_TIMEOUT_MS = 120_000;
13
+ export const EXPLORE_OUTPUT_CAP = 24_000;
14
+ const TRUNCATED = '\n[explore: answer truncated]';
15
+
16
+ function result(text, isError = false) {
17
+ return { content: [{ type: 'text', text }], ...(isError ? { isError: true } : {}) };
18
+ }
19
+
20
+ export function normalizeExploreQueries(raw) {
21
+ const list = Array.isArray(raw) ? raw : [raw];
22
+ return list.map((q) => (typeof q === 'string' ? q.trim() : '')).filter(Boolean);
23
+ }
24
+
25
+ function capped(text, budget) {
26
+ return text.length <= budget ? text : text.slice(0, Math.max(0, budget - TRUNCATED.length)) + TRUNCATED;
27
+ }
28
+
29
+ // Headings and error lines are labels, not answers: the truncation marker
30
+ // would tell the caller that evidence was lost when none was.
31
+ function shortened(text, max) {
32
+ return text.length <= max ? text : `${text.slice(0, max - 1)}…`;
33
+ }
34
+
35
+ /**
36
+ * @param {{ query: string|string[] }} args
37
+ * @param {{ cwd?: string, signal?: AbortSignal, callerSessionId?: string }} ctx
38
+ * @param {object} [deps] injectable for tests
39
+ */
40
+ export async function runExplore(args = {}, ctx = {}, deps = {}) {
41
+ const {
42
+ load = () => loadConfig({ secrets: false }),
43
+ initialize = initProviders,
44
+ providerFor = getProvider,
45
+ timeoutMs = EXPLORE_TIMEOUT_MS,
46
+ } = deps;
47
+ const queries = normalizeExploreQueries(args.query);
48
+ if (!queries.length) return result('[explore error] query is required', true);
49
+ if (queries.length > EXPLORE_MAX_QUERIES) {
50
+ return result(`[explore error] at most ${EXPLORE_MAX_QUERIES} queries per call`, true);
51
+ }
52
+ const config = load();
53
+ const route = resolveMaintenanceRoute({ agent: EXPLORER_AGENT, config, includeDefault: false });
54
+ if (!route || typeof route !== 'object') {
55
+ return result('[explore error] Explore has no model; pick one under Workflows → Built-in agents → Explore', true);
56
+ }
57
+
58
+ // One controller per call: caller cancellation and the deadline both abort
59
+ // every explorer, and the call waits for each loop to settle.
60
+ const controller = new AbortController();
61
+ const parent = ctx.signal;
62
+ const onParentAbort = () => controller.abort(parent.reason);
63
+ if (parent?.aborted) return result('[explore error] cancelled', true);
64
+ parent?.addEventListener('abort', onParentAbort, { once: true });
65
+ let timedOut = false;
66
+ const timer = setTimeout(() => {
67
+ timedOut = true;
68
+ const reason = new Error(`explore timed out after ${Math.round(timeoutMs / 1000)}s`);
69
+ // Lets an explorer return the answer text it already wrote.
70
+ reason.salvagePartial = true;
71
+ controller.abort(reason);
72
+ }, timeoutMs);
73
+
74
+ try {
75
+ await initialize(config.providers || {}, { signal: controller.signal });
76
+ const provider = providerFor(route.provider);
77
+ if (!provider || typeof provider.send !== 'function') {
78
+ return result(`[explore error] provider "${route.provider}" is not ready`, true);
79
+ }
80
+ const settled = await Promise.all(
81
+ queries.map((query) =>
82
+ runExplorer({
83
+ query,
84
+ route,
85
+ provider,
86
+ cwd: ctx.cwd || null,
87
+ signal: controller.signal,
88
+ ownerSessionId: ctx.callerSessionId || null,
89
+ }).then(
90
+ (text) => {
91
+ const answer = String(text || '').trim();
92
+ return { ok: Boolean(answer), text: answer, late: timedOut };
93
+ },
94
+ (error) => ({ ok: false, error, late: timedOut })
95
+ )
96
+ )
97
+ );
98
+ if (parent?.aborted) return result('[explore error] cancelled', true);
99
+ const budget = Math.floor(EXPLORE_OUTPUT_CAP / queries.length);
100
+ const bodies = settled.map((entry) => {
101
+ if (entry.ok) return capped(entry.late ? `${entry.text}\n[explore: partial, timed out]` : entry.text, budget);
102
+ if (entry.late) return `[explore error] timed out after ${Math.round(timeoutMs / 1000)}s with no answer`;
103
+ if (entry.error) return `[explore error] ${shortened(String(entry.error?.message || entry.error), 500)}`;
104
+ return '[explore error] explorer returned no answer';
105
+ });
106
+ const text =
107
+ queries.length === 1
108
+ ? bodies[0]
109
+ : bodies
110
+ .map((body, i) => `## Q${i + 1}: ${shortened(queries[i].replace(/\s+/g, ' '), 100)}\n${body}`)
111
+ .join('\n\n');
112
+ return result(
113
+ text,
114
+ settled.every((entry) => !entry.ok)
115
+ );
116
+ } catch (error) {
117
+ if (parent?.aborted) return result('[explore error] cancelled', true);
118
+ return result(`[explore error] ${error?.message || error}`, true);
119
+ } finally {
120
+ clearTimeout(timer);
121
+ parent?.removeEventListener('abort', onParentAbort);
122
+ }
123
+ }
@@ -71,6 +71,7 @@ import {
71
71
  } from './lib/trace-store.mjs';
72
72
  import { writeJsonAtomicSync } from '../shared/atomic-file.mjs';
73
73
  import { safeIpcSend } from '../shared/safe-ipc-send.mjs';
74
+ import { adoptSystemProxy } from '../shared/llm/system-proxy.mjs';
74
75
  import { resolvePluginData, mixdogHome } from '../shared/plugin-paths.mjs';
75
76
  import { scheduledCycle1Signature } from './lib/cycle-signatures.mjs';
76
77
  import { createTranscriptIngest } from './lib/transcript-ingest.mjs';
@@ -96,6 +97,9 @@ import {
96
97
  } from './lib/memory-config-flags.mjs';
97
98
  const IS_MEMORY_ENTRY = !!process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href;
98
99
  if (IS_MEMORY_ENTRY) {
100
+ // Runtime and model downloads follow the system proxy the launching daemon
101
+ // handed over (removed from this env so child processes never see it).
102
+ adoptSystemProxy();
99
103
  // Node's own warning printer stays off in this runtime, but a listener leak
100
104
  // is still logged, with the stack that names its source.
101
105
  process.removeAllListeners('warning');
@@ -12,6 +12,7 @@ import { writeProfilePoint } from './model-profile.mjs';
12
12
  import { createCompactVectorCache } from './compact-vector-cache.mjs';
13
13
  import { EMBED_KEEP_WARM_MS } from './embedding-idle-lease.mjs';
14
14
  import { workerExecArgv } from '../../shared/worker-exec-argv.mjs';
15
+ import { systemProxyHandoffEnv } from '../../shared/llm/system-proxy.mjs';
15
16
  import {
16
17
  getConfiguredEmbeddingModelId,
17
18
  getDefaultEmbeddingDtype,
@@ -69,7 +70,9 @@ function ensureWorker() {
69
70
  _lastRestartMs = now;
70
71
  const execArgv = embeddingWorkerExecArgv();
71
72
  const created = new Worker(WORKER_PATH, {
72
- env: { ...process.env },
73
+ // The model download runs in this worker: it gets the system proxy
74
+ // decision explicitly (and removes it from its own env on start).
75
+ env: { ...process.env, ...systemProxyHandoffEnv() },
73
76
  execArgv,
74
77
  workerData: { dtype: _configuredDtype },
75
78
  });
@@ -8,6 +8,7 @@ import os from 'node:os';
8
8
  import { execFile } from 'node:child_process';
9
9
  import { promisify } from 'node:util';
10
10
  import { resolvePluginData } from '../../shared/plugin-paths.mjs';
11
+ import { adoptSystemProxy } from '../../shared/llm/system-proxy.mjs';
11
12
  import { compressEmbeddingModelCache } from './embedding-model-cache-compression.mjs';
12
13
  import { createIdleLease } from './embedding-idle-lease.mjs';
13
14
  import { ensureModelFile, ensureModelGraph } from './embedding-model-files.mjs';
@@ -24,6 +25,9 @@ import {
24
25
  prepareEmbeddingInput,
25
26
  } from './embedding-model-config.mjs';
26
27
 
28
+ // The model download goes through the system proxy the parent handed over.
29
+ adoptSystemProxy();
30
+
27
31
  const MODEL_ID = getConfiguredEmbeddingModelId();
28
32
 
29
33
  // Reroute ALL worker-thread stdio through parentPort. Without stdout:true/
@@ -235,7 +235,7 @@ function shortTableSplitIssues(tables, issues) {
235
235
  }
236
236
 
237
237
  // A total row is a total by its label; it reads as one only when it is set apart from the rows it sums.
238
- export const TOTAL_LABEL = /^(?:(?:grand\s+total|sub\s*total|total)\b|(?:합계|총계|소계|계)(?:\s|$))/i;
238
+ const TOTAL_LABEL = /^(?:(?:grand\s+total|sub\s*total|total)\b|(?:합계|총계|소계|계)(?:\s|$))/i;
239
239
  const FIGURE_TEXT = /^[\s+\-−₩$€¥]*[\d,.]+\s*(?:%|%p|[가-힣A-Za-z]{0,3})?\s*$/;
240
240
  const DISPLAY_SIZE = 18;
241
241
 
@@ -12,9 +12,16 @@ export const DEFAULT_DISABLED_AGENT_IDS = Object.freeze([
12
12
  'writer',
13
13
  ]);
14
14
 
15
+ export const EXPLORE_AGENT_ID = 'explore';
16
+
15
17
  // The Maintainer also starts off: background upkeep spends model calls, so it
16
- // runs only once the user turns it on and picks its model.
17
- export const DEFAULT_DISABLED_AGENT_ROSTER = Object.freeze([...DEFAULT_DISABLED_AGENT_IDS, 'maintainer']);
18
+ // runs only once the user turns it on and picks its model. Explore likewise:
19
+ // its tool reaches the model only once the user picks its model.
20
+ export const DEFAULT_DISABLED_AGENT_ROSTER = Object.freeze([
21
+ ...DEFAULT_DISABLED_AGENT_IDS,
22
+ 'maintainer',
23
+ EXPLORE_AGENT_ID,
24
+ ]);
18
25
 
19
26
  /** The AGENT.md frontmatter `kind` the Workflows page writes when it creates
20
27
  * an agent: a workflow delegation role, never a contact (봇). */
@@ -149,6 +156,14 @@ export function configuredAgentRouteCandidates(config, agentId) {
149
156
  return route ? [route] : [];
150
157
  }
151
158
 
159
+ /** The explore tool runs only on Explore's own model (never Main) while it is on. */
160
+ export function exploreRouteConfigured(config) {
161
+ return (
162
+ !isAgentDisabled(config, EXPLORE_AGENT_ID) &&
163
+ configuredAgentRouteCandidates(config, EXPLORE_AGENT_ID).some(isCompleteAgentRoute)
164
+ );
165
+ }
166
+
152
167
  function canonicalizeAgentRoutes(config = {}) {
153
168
  const agents = Object.fromEntries(
154
169
  Object.entries(record(config.agents)).filter(([, route]) => isCompleteAgentRoute(route))
@@ -128,12 +128,113 @@ export function renameWithRetrySync(src, dst, opts = {}) {
128
128
  }
129
129
  }
130
130
 
131
+ // Windows refuses to rename over a file while any handle on it is open, so
132
+ // this process's own reads of a busy state file (a delivery loop polling it)
133
+ // could fail every attempt of its writer's rename until the retries ran out.
134
+ // Here a rename attempt waits for the reads of its target in flight and holds
135
+ // new ones off only while it runs; other processes are what the retries cover.
136
+ // A read still open after RENAME_READ_WAIT_MS is left behind with its path's
137
+ // entry (a stuck read must not hold the writer, its lock, or later readers),
138
+ // and the attempt goes ahead under those same retries. Likewise a rename not
139
+ // returned by then: readers held off read anyway, as without it. A reader's
140
+ // bound counts from the rename call, not from the attempt's own (bounded)
141
+ // wait for reads, so a rename that just started is never read across.
142
+ export const RENAME_READ_WAIT_MS = 1_000;
143
+ const targetUse = new Map();
144
+ const targetKey = (path) => {
145
+ const full = resolve(path);
146
+ return process.platform === 'win32' ? full.toLowerCase() : full;
147
+ };
148
+ function useOf(key) {
149
+ let use = targetUse.get(key);
150
+ if (!use) targetUse.set(key, (use = { reads: 0, renaming: null, draining: null, drained: [] }));
151
+ return use;
152
+ }
153
+ function forgetIfIdle(key, use) {
154
+ if (use.reads === 0 && !use.renaming && targetUse.get(key) === use) targetUse.delete(key);
155
+ }
156
+
157
+ // Waits for the rename `use` runs; one that has not returned within the bound
158
+ // is left behind with the entry, and the caller goes on as without it.
159
+ async function outwaitRename(key, use) {
160
+ await use.draining;
161
+ if (use.renaming && !(await settlesWithin(use.renaming, RENAME_READ_WAIT_MS)) && targetUse.get(key) === use) {
162
+ targetUse.delete(key);
163
+ }
164
+ return useOf(key);
165
+ }
166
+
167
+ function settlesWithin(promise, ms) {
168
+ let timer;
169
+ const bound = new Promise((resolve) => {
170
+ timer = setTimeout(() => resolve(false), ms);
171
+ });
172
+ return Promise.race([promise.then(() => true), bound]).finally(() => clearTimeout(timer));
173
+ }
174
+
175
+ async function readTarget(path, read) {
176
+ const key = targetKey(path);
177
+ let use = useOf(key);
178
+ while (use.renaming) use = await outwaitRename(key, use);
179
+ use.reads += 1;
180
+ try {
181
+ return await read();
182
+ } finally {
183
+ use.reads -= 1;
184
+ if (use.reads === 0) for (const done of use.drained.splice(0)) done();
185
+ forgetIfIdle(key, use);
186
+ }
187
+ }
188
+
189
+ async function renameOver(src, dst) {
190
+ const key = targetKey(dst);
191
+ let use = useOf(key);
192
+ while (use.renaming) use = await outwaitRename(key, use);
193
+ let finish;
194
+ use.renaming = new Promise((resolve) => {
195
+ finish = resolve;
196
+ });
197
+ use.draining = use.reads > 0 ? readsDrained(use, RENAME_READ_WAIT_MS) : null;
198
+ try {
199
+ if (use.draining && !(await use.draining) && targetUse.get(key) === use) targetUse.delete(key);
200
+ await renameAsync(src, dst);
201
+ } finally {
202
+ use.renaming = null;
203
+ use.draining = null;
204
+ finish();
205
+ forgetIfIdle(key, use);
206
+ }
207
+ }
208
+
209
+ // True once `use` has no read in flight, false after `ms` (its waiter removed).
210
+ function readsDrained(use, ms) {
211
+ return new Promise((resolve) => {
212
+ const done = () => {
213
+ clearTimeout(timer);
214
+ resolve(true);
215
+ };
216
+ const timer = setTimeout(() => {
217
+ const at = use.drained.indexOf(done);
218
+ if (at >= 0) use.drained.splice(at, 1);
219
+ resolve(false);
220
+ }, ms);
221
+ use.drained.push(done);
222
+ });
223
+ }
224
+
225
+ /** Test seam: the per-path coordination left (entries, drain waiters). */
226
+ export function _renameCoordinationForTest() {
227
+ let waiters = 0;
228
+ for (const use of targetUse.values()) waiters += use.drained.length;
229
+ return { entries: targetUse.size, waiters };
230
+ }
231
+
131
232
  async function renameWithRetry(src, dst, opts = {}) {
132
233
  const backoffs = renameBackoffs(opts);
133
234
  let lastErr = null;
134
235
  for (let attempt = 0; attempt <= backoffs.length; attempt++) {
135
236
  try {
136
- await renameAsync(src, dst);
237
+ await renameOver(src, dst);
137
238
  return true;
138
239
  } catch (err) {
139
240
  lastErr = err;
@@ -433,7 +534,7 @@ function readContentOrNullSync(filePath) {
433
534
 
434
535
  async function readContentOrNullAsync(filePath) {
435
536
  try {
436
- return await readFileAsync(filePath);
537
+ return await readTarget(filePath, () => readFileAsync(filePath));
437
538
  } catch (err) {
438
539
  if (err?.code === 'ENOENT') return null;
439
540
  throw err;
@@ -310,7 +310,9 @@ export function cleanupBackgroundTasks(options = {}) {
310
310
  function cancelRunningTask(task, reason, notify, terminalReason = null) {
311
311
  try {
312
312
  task.cancel?.();
313
- } catch {}
313
+ } catch {
314
+ // A failing cancel hook must not stop the task from being marked cancelled.
315
+ }
314
316
  completeBackgroundTask(task.taskId, { status: 'cancelled', error: reason, notify: notify === true, terminalReason });
315
317
  if (task.notifyOnCancel !== true || notify === true || task.status !== 'cancelled' || task.cancelNotify) return;
316
318
  if (notify === false) {
@@ -370,9 +372,12 @@ export function cancelBackgroundTasks(options = {}) {
370
372
  const wanted = clean(options.surface);
371
373
  const executionSessionId = clean(options.executionSessionId);
372
374
  const scope = normalizeTaskScope(options);
373
- let cancelled = 0;
375
+ // Optional: only tasks started at/after this time (a turn's own work).
376
+ const startedSinceMs = Number(options.startedSinceMs) || 0;
377
+ const taskIds = [];
374
378
  for (const task of [...tasks.values()]) {
375
379
  if (wanted && task.surface !== wanted) continue;
380
+ if (startedSinceMs > 0 && !(task.startedAtMs >= startedSinceMs)) continue;
376
381
  // Scoped teardown must be exact. Legacy tasks without ownership stay
377
382
  // visible/recoverable, but may not be claimed by whichever session happens
378
383
  // to close first.
@@ -386,9 +391,9 @@ export function cancelBackgroundTasks(options = {}) {
386
391
  continue;
387
392
  }
388
393
  cancelRunningTask(task, reason, options.notify, terminalReason);
389
- cancelled += 1;
394
+ taskIds.push(task.taskId);
390
395
  }
391
- return { cancelled };
396
+ return { cancelled: taskIds.length, taskIds };
392
397
  }
393
398
 
394
399
  export function acknowledgeBackgroundTaskCompletion(taskId, options = {}) {
@@ -415,13 +420,17 @@ function resultTextForTask(task) {
415
420
  // fallback below so the completion notification still carries a body.
416
421
  try {
417
422
  process.stderr.write(`[background-${task.surface}] renderResult failed: ${err?.message || err}\n`);
418
- } catch {}
423
+ } catch {
424
+ // A closed stderr must not lose the completion body.
425
+ }
419
426
  }
420
427
  }
421
428
  if (typeof task.result === 'string') return task.result;
422
429
  try {
423
430
  return JSON.stringify(task.result, null, 2);
424
- } catch {}
431
+ } catch {
432
+ // Unserializable result (circular, BigInt): fall back to the empty body.
433
+ }
425
434
  }
426
435
  return '';
427
436
  }
@@ -1,7 +1,7 @@
1
- // What a multi-account connector server tells the model about itself (MCP
1
+ // What a connector server tells the model about its accounts (MCP
2
2
  // `instructions`), in one line: the connected accounts, and that each tool
3
- // takes `account` (asked of the user when several are connected and none was
4
- // named). An account that cannot be used right now is listed with why.
3
+ // takes `account` (left out, the account used last). An account that cannot
4
+ // be used right now is listed with why.
5
5
 
6
6
  /** The MCP instructions naming `accounts` (`{ email, note? }`, `note` a short
7
7
  * reason it is unusable such as "needs sign-in"; one without an address is
@@ -12,12 +12,12 @@ export function connectorAccountsInstructions(accounts) {
12
12
  const list = named.map(({ email, note }) => (note ? `${email} (${note})` : email)).join(', ');
13
13
  return named.length === 1
14
14
  ? `Accounts: ${list}. \`account\` may be left out.`
15
- : `Accounts: ${list}. Pass \`account\`; if the user named none and there are several, ask which.`;
15
+ : `Accounts: ${list}. \`account\` picks one; left out, a call uses the account used last, and its result names it.`;
16
16
  }
17
17
 
18
18
  /** The account addresses instructions from connectorAccountsInstructions name. */
19
19
  export function accountsOfInstructions(instructions) {
20
- const list = /^Accounts: (.+?)\. (?:`account`|Pass `account`)/.exec(String(instructions || ''))?.[1] || '';
20
+ const list = /^Accounts: (.+?)\. `account`/.exec(String(instructions || ''))?.[1] || '';
21
21
  return list
22
22
  .split(', ')
23
23
  .map((part) => part.replace(/ \(.*\)$/, '').trim())
@@ -40,8 +40,7 @@ export function connectorToolDefault(connectorId: string, tool: string): 'auto'
40
40
  export function connectorServerInput(
41
41
  entry: ConnectorCatalogEntry,
42
42
  name: string,
43
- key?: string,
44
- options?: { extraAccount?: boolean }
43
+ key?: string
45
44
  ): Record<string, unknown>;
46
45
  export function connectorAppPasswordOnly(entry: ConnectorCatalogEntry | null | undefined): boolean;
47
46
  export function connectorUsesGoogleClient(entry: ConnectorCatalogEntry | null | undefined): boolean;
@@ -52,12 +51,19 @@ export function gmailAppPasswordValue(value: unknown): string;
52
51
  export function gmailAppPasswordAccount(cfg: unknown): string;
53
52
  export function gmailAppPasswordServerInput(name: string, email: string, password: string): Record<string, unknown>;
54
53
 
55
- /** One stored account of a multi-account connector server. */
54
+ /** One stored account of a connector server. */
56
55
  export interface ConnectorAccountEntry {
57
56
  name: string;
58
- url: string;
57
+ /** Absent: http. */
58
+ type?: string;
59
+ url?: string;
59
60
  headers?: Record<string, string>;
60
61
  oauthClientId?: string;
62
+ /** The account's own sign-in key, when another account signs in at its URL. */
63
+ oauthKey?: string;
64
+ command?: string;
65
+ args?: string[];
66
+ env?: Record<string, string>;
61
67
  /** `false`: the account is kept but neither connected nor called. */
62
68
  enabled?: boolean;
63
69
  }
@@ -76,6 +82,7 @@ export function withConnectorAccountEnabled(
76
82
  enabled: boolean
77
83
  ): Record<string, unknown>;
78
84
  export function connectorAccountEntry(name: string, cfg: Record<string, unknown>): ConnectorAccountEntry;
85
+ export function connectorServerSettings(cfg: Record<string, unknown>): Record<string, unknown>;
79
86
  export function mergeConnectorAccountServers(servers: Record<string, unknown>): {
80
87
  servers: Record<string, unknown>;
81
88
  merged: { connector: string; name: string; from: string[] }[];