mixdog 1.4.1 → 1.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (630) hide show
  1. package/package.json +4 -3
  2. package/scripts/build-shipped-history.mjs +125 -33
  3. package/scripts/gate-local.mjs +220 -63
  4. package/scripts/graph-parity.mjs +8 -3
  5. package/scripts/lib/gate-scheduler.mjs +139 -32
  6. package/scripts/lib/gate-timing-reporter.mjs +16 -0
  7. package/scripts/lib/run-node-tests.mjs +71 -34
  8. package/scripts/lib/scoped-temp.mjs +1 -0
  9. package/scripts/lib/test-failure-records.mjs +14 -1
  10. package/scripts/lib/test-failure-summary.mjs +9 -4
  11. package/scripts/lib/test-spawn-ledger.mjs +43 -3
  12. package/scripts/post-release-check.mjs +26 -16
  13. package/scripts/pptx-kit-index.mjs +5 -6
  14. package/scripts/provider-pingpong-live.mjs +1 -1
  15. package/scripts/prune-embedding-runtime.mjs +3 -1
  16. package/scripts/release-paths.mjs +7 -1
  17. package/scripts/suite-health.mjs +110 -28
  18. package/scripts/test.mjs +9 -14
  19. package/src/agents/advisor/AGENT.md +4 -4
  20. package/src/agents/advisor/agent.json +1 -1
  21. package/src/agents/explore/AGENT.md +22 -0
  22. package/src/agents/explore/agent.json +6 -0
  23. package/src/cli.mjs +7 -0
  24. package/src/defaults/agents.json +7 -0
  25. package/src/defaults/shipped-history.json +38 -2
  26. package/src/defaults/skills/browser-use/SKILL.md +4 -1
  27. package/src/defaults/skills/code-tidy/SKILL.md +71 -102
  28. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
  29. package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
  30. package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
  31. package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
  32. package/src/defaults/skills/computer-use/SKILL.md +12 -2
  33. package/src/defaults/skills/setup/SKILL.md +2 -2
  34. package/src/defaults/skills/setup/references/actions.md +28 -9
  35. package/src/defaults/skills/setup/references/surfaces.md +5 -2
  36. package/src/defaults/skills/setup-guide/SKILL.md +11 -3
  37. package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
  38. package/src/defaults/skills/skill-creator/SKILL.md +85 -190
  39. package/src/defaults/skills/skill-creator/references/design.md +70 -162
  40. package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
  41. package/src/defaults/skills/test-suite/SKILL.md +194 -0
  42. package/src/defaults/skills/test-suite/references/case-management.md +51 -0
  43. package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
  44. package/src/defaults/skills/test-suite/references/reliability.md +49 -0
  45. package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
  46. package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
  47. package/src/defaults/skills/visualize/SKILL.md +6 -2
  48. package/src/lib/instruction-text.cjs +36 -0
  49. package/src/lib/rules-builder.cjs +40 -50
  50. package/src/orchestration/balanced.md +23 -0
  51. package/src/orchestration/focused.md +22 -0
  52. package/src/orchestration/none.md +5 -0
  53. package/src/orchestration/swarm.md +24 -0
  54. package/src/rules/agent-mode/AGENT_MODE.md +3 -1
  55. package/src/rules/agent-mode/MIXY.md +2 -2
  56. package/src/rules/lead/LEAD.md +3 -3
  57. package/src/rules/shared/20-research.md +3 -6
  58. package/src/rules/shared/40-editing.md +1 -0
  59. package/src/rules/shared/60-verification.md +10 -9
  60. package/src/rules/shared/70-delivery.md +4 -3
  61. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
  62. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +3 -3
  63. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -2
  64. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +132 -21
  65. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -9
  66. package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +2 -2
  67. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +67 -0
  69. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
  70. package/src/runtime/agent/orchestrator/config.mjs +12 -7
  71. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +7 -7
  72. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +9 -30
  73. package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
  74. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +124 -12
  75. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +204 -49
  76. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +16 -7
  77. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +157 -57
  78. package/src/runtime/agent/orchestrator/mcp/client.mjs +54 -23
  79. package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +1 -1
  80. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +8 -2
  81. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +83 -52
  82. package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +1 -1
  83. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +14 -0
  84. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +43 -27
  85. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +43 -8
  86. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +30 -28
  87. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  88. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
  89. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-stop.mjs +3 -3
  90. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
  91. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
  92. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  93. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
  94. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
  95. package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
  96. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
  97. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
  98. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
  99. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
  100. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
  101. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +2 -2
  102. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +48 -31
  103. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
  104. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
  105. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
  106. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
  107. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
  108. package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
  109. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +4 -6
  110. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2784 -2872
  111. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +5 -8
  112. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +26 -28
  113. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +288 -300
  114. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +3 -1
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +1 -0
  116. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
  117. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
  118. package/src/runtime/agent/orchestrator/providers/registry.mjs +33 -2
  119. package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
  120. package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
  121. package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
  122. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +576 -0
  123. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +10 -30
  124. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +32 -0
  125. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +0 -11
  126. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +8 -0
  127. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +17 -3
  128. package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +47 -27
  129. package/src/runtime/agent/orchestrator/runtime-core/goal-deadlines.mjs +141 -10
  130. package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +26 -63
  131. package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +28 -3
  132. package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +36 -11
  133. package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +88 -56
  134. package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +4 -1
  135. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +51 -32
  136. package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +45 -145
  137. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -98
  138. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +32 -99
  139. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +23 -78
  140. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +69 -47
  141. package/src/runtime/agent/orchestrator/runtime-core/todo-list.mjs +367 -0
  142. package/src/runtime/agent/orchestrator/runtime-core/todo-tool-defs.mjs +47 -0
  143. package/src/runtime/agent/orchestrator/runtime-core/tool-availability.mjs +155 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +12 -0
  145. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +119 -35
  146. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +4 -1
  147. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +15 -6
  148. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
  149. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +28 -22
  150. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +30 -0
  151. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
  152. package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
  153. package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +1 -1
  154. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +94 -10
  155. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -2
  156. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +1 -1
  157. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -1
  158. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +3 -0
  159. package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +1 -1
  160. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -12
  161. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +4 -4
  162. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +11 -6
  163. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +6 -6
  164. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +7 -3
  165. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +11 -1
  166. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
  167. package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +1 -1
  168. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +37 -8
  169. package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +1 -1
  170. package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +1 -1
  171. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +11 -1
  172. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
  173. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +5 -3
  174. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
  175. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/todo-check.mjs +196 -0
  176. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +116 -50
  177. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +8 -1
  178. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +1 -1
  179. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +1 -1
  180. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -1
  181. package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +5 -6
  182. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +27 -3
  183. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +18 -2
  184. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
  185. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
  186. package/src/runtime/agent/orchestrator/session/loop/turn-report.mjs +35 -0
  187. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +1 -1
  188. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +103 -50
  189. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +9 -7
  190. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +21 -3
  191. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +27 -11
  192. package/src/runtime/agent/orchestrator/session/manager/ask-turn-open.mjs +37 -34
  193. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +15 -0
  194. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +25 -15
  195. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +79 -24
  196. package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +3 -0
  197. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +12 -1
  198. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
  199. package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +6 -1
  200. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +9 -1
  201. package/src/runtime/agent/orchestrator/session/manager/pending-spool-path.mjs +2 -2
  202. package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +1 -1
  203. package/src/runtime/agent/orchestrator/session/manager/prompt-settings.mjs +598 -0
  204. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +20 -0
  205. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -14
  206. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +2 -0
  207. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +12 -0
  208. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
  209. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +1 -1
  210. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +56 -14
  211. package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +31 -0
  212. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +59 -20
  213. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +2 -0
  214. package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
  215. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
  216. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +18 -4
  217. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +8 -9
  218. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +339 -88
  219. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +135 -11
  220. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +377 -104
  221. package/src/runtime/agent/orchestrator/session/manager/turn-durability.mjs +144 -0
  222. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +48 -30
  223. package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
  224. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +4 -0
  225. package/src/runtime/agent/orchestrator/session/manager.mjs +6 -0
  226. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +12 -6
  227. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +8 -1
  228. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +1 -1
  229. package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +5 -1
  230. package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +1 -1
  231. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +2 -2
  232. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +23 -2
  233. package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +3 -3
  234. package/src/runtime/agent/orchestrator/session/store/transcript-durability.mjs +88 -0
  235. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +5 -0
  236. package/src/runtime/agent/orchestrator/session/store-summary-log.mjs +1 -1
  237. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +243 -38
  238. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
  239. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +177 -8
  240. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
  241. package/src/runtime/agent/orchestrator/session/store.mjs +5 -0
  242. package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +7 -1
  243. package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +9 -1
  244. package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
  245. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +3 -1
  246. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +2 -2
  247. package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -5
  248. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -1
  249. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
  250. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +21 -3
  251. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  252. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/worktree-add-guard.mjs +77 -0
  253. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -1
  254. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +42 -28
  255. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +30 -14
  256. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +2 -2
  257. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
  258. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +1 -1
  259. package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +0 -1
  260. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
  261. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +0 -10
  262. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +95 -20
  263. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
  264. package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -24
  265. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary/child-kill.mjs +4 -3
  266. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +1 -2
  267. package/src/runtime/agent/orchestrator/tools/code-graph/modes/calls.mjs +1 -1
  268. package/src/runtime/agent/orchestrator/tools/code-graph/modes/symbols.mjs +2 -2
  269. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +4 -5
  270. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +3 -4
  271. package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4 -22
  272. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  273. package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
  274. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
  275. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +105 -15
  276. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
  277. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
  278. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
  279. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +35 -11
  280. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +2 -0
  281. package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
  282. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -6
  283. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +0 -1
  284. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  285. package/src/runtime/attachments/attachment-reference.mjs +1 -1
  286. package/src/runtime/attachments/pdf-extract.mjs +1 -1
  287. package/src/runtime/attachments/store.d.mts +1 -0
  288. package/src/runtime/attachments/store.mjs +2 -2
  289. package/src/runtime/channels/lib/config-reload-watch.mjs +42 -0
  290. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +29 -9
  291. package/src/runtime/channels/lib/scheduler.mjs +33 -0
  292. package/src/runtime/channels/lib/schedules-db.mjs +11 -4
  293. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +4 -1
  294. package/src/runtime/channels/lib/webhooks-db.mjs +9 -3
  295. package/src/runtime/channels/lib/whisper-port.mjs +19 -10
  296. package/src/runtime/channels/lib/whisper-server.mjs +22 -13
  297. package/src/runtime/channels/lib/worker-main.mjs +9 -31
  298. package/src/runtime/computer-bridge/linux-readiness.mjs +10 -14
  299. package/src/runtime/connectors/connector-accounts-mcp.mjs +372 -103
  300. package/src/runtime/connectors/gmail-app-password.mjs +4 -4
  301. package/src/runtime/connectors/google-mcp.mjs +1 -1
  302. package/src/runtime/effort-judge/judge-client.mjs +2 -2
  303. package/src/runtime/effort-judge/judge-input.mjs +4 -4
  304. package/src/runtime/explore/explorer.mjs +88 -0
  305. package/src/runtime/explore/tool-defs.mjs +35 -0
  306. package/src/runtime/explore/tool.mjs +123 -0
  307. package/src/runtime/local-provider/hardware.mjs +1 -1
  308. package/src/runtime/media/adapters/codex-image.mjs +3 -3
  309. package/src/runtime/media/adapters/gemini-video.mjs +1 -1
  310. package/src/runtime/media/media-usage.mjs +1 -1
  311. package/src/runtime/media/store.mjs +1 -1
  312. package/src/runtime/memory/index.mjs +15 -1
  313. package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
  314. package/src/runtime/memory/lib/embedding-reindex.mjs +27 -0
  315. package/src/runtime/memory/lib/embedding-worker.mjs +4 -0
  316. package/src/runtime/memory/lib/memory-embed.mjs +83 -14
  317. package/src/runtime/memory/lib/memory-process-lock.mjs +159 -36
  318. package/src/runtime/memory/lib/memory-text-utils.mjs +6 -1
  319. package/src/runtime/memory/lib/memory.mjs +17 -0
  320. package/src/runtime/memory/lib/pg/process.mjs +1 -1
  321. package/src/runtime/memory/lib/pg/supervisor.mjs +16 -96
  322. package/src/runtime/memory/lib/recall-hybrid/hybrid-sql.mjs +12 -3
  323. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  324. package/src/runtime/office/authoring/pptx-author-action.mjs +1 -1
  325. package/src/runtime/office/authoring/xlsx-html-build.mjs +1 -1
  326. package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
  327. package/src/runtime/office/capabilities.mjs +1 -1
  328. package/src/runtime/office/core/office-core.mjs +1 -1
  329. package/src/runtime/office/design/content-model.mjs +3 -3
  330. package/src/runtime/office/design/docx/design-docx/section.mjs +6 -6
  331. package/src/runtime/office/design/xlsx/design-xlsx-components.mjs +1 -1
  332. package/src/runtime/office/design/xlsx/design-xlsx.mjs +1 -1
  333. package/src/runtime/office/pdf/ocr-engine.mjs +1 -1
  334. package/src/runtime/office/pdf/pdf-writer.mjs +4 -4
  335. package/src/runtime/office/portable/portable-docx-operations.mjs +2 -2
  336. package/src/runtime/office/portable/portable-soffice.mjs +8 -6
  337. package/src/runtime/office/portable/xlsx-contract.mjs +1 -1
  338. package/src/runtime/office/quality/assurance-structure-docx.mjs +1 -1
  339. package/src/runtime/shared/agent-route-config.mjs +17 -2
  340. package/src/runtime/shared/atomic-file.d.mts +8 -0
  341. package/src/runtime/shared/atomic-file.mjs +103 -2
  342. package/src/runtime/shared/background-tasks.mjs +37 -10
  343. package/src/runtime/shared/background-wait.mjs +66 -0
  344. package/src/runtime/shared/child-guardian.mjs +17 -7
  345. package/src/runtime/shared/config.mjs +313 -16
  346. package/src/runtime/shared/connector-accounts.mjs +5 -5
  347. package/src/runtime/shared/connector-catalog.d.mts +14 -8
  348. package/src/runtime/shared/connector-catalog.mjs +70 -52
  349. package/src/runtime/shared/custom-provider-keys.mjs +20 -0
  350. package/src/runtime/shared/file-has-data.mjs +26 -2
  351. package/src/runtime/shared/file-lock.mjs +21 -18
  352. package/src/runtime/shared/git-launch.d.mts +9 -0
  353. package/src/runtime/shared/git-launch.mjs +213 -0
  354. package/src/runtime/shared/git-runner-worker.mjs +2 -1
  355. package/src/runtime/shared/git-runner.mjs +7 -2
  356. package/src/runtime/shared/idle-gc.mjs +30 -7
  357. package/src/runtime/shared/llm/cost.mjs +6 -1
  358. package/src/runtime/shared/llm/http-agent.mjs +316 -29
  359. package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
  360. package/src/runtime/shared/llm/model-catalog.mjs +46 -6
  361. package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
  362. package/src/runtime/shared/llm/system-proxy.mjs +453 -0
  363. package/src/runtime/shared/llm/usage-ledger-quota.mjs +31 -12
  364. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +84 -8
  365. package/src/runtime/shared/llm/usage-ledger.mjs +3 -0
  366. package/src/runtime/shared/llm/usage-rollup.mjs +48 -0
  367. package/src/runtime/shared/maintenance-schedule.mjs +109 -0
  368. package/src/runtime/shared/process-runner.mjs +8 -4
  369. package/src/runtime/shared/provider-accounts.mjs +52 -2
  370. package/src/runtime/shared/routine-trigger.d.mts +13 -0
  371. package/src/runtime/shared/routine-trigger.mjs +34 -0
  372. package/src/runtime/shared/run-child.d.mts +2 -1
  373. package/src/runtime/shared/run-child.mjs +70 -18
  374. package/src/runtime/shared/session-scratch.mjs +14 -2
  375. package/src/runtime/shared/shipped-definitions.mjs +7 -1
  376. package/src/runtime/shared/staged-install-worker.mjs +5 -0
  377. package/src/runtime/shared/staged-update.mjs +47 -2
  378. package/src/runtime/shared/tool-card-model.golden.json +3 -12
  379. package/src/runtime/shared/tool-execution-contract.mjs +2 -0
  380. package/src/runtime/shared/tool-surface.mjs +110 -36
  381. package/src/runtime/shared/tool-work-units.mjs +35 -6
  382. package/src/runtime/shared/turn-snapshot.mjs +26 -4
  383. package/src/runtime/shared/turn-worktree-snapshot.mjs +409 -54
  384. package/src/runtime/shared/worker-requests.mjs +17 -3
  385. package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
  386. package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
  387. package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
  388. package/src/runtime/shared/worktrees/branch-management.mjs +5 -3
  389. package/src/runtime/shared/worktrees/contract.mjs +16 -6
  390. package/src/runtime/shared/worktrees/dependencies.mjs +127 -89
  391. package/src/runtime/shared/worktrees/disk.mjs +79 -2
  392. package/src/runtime/shared/worktrees/git.mjs +97 -7
  393. package/src/runtime/shared/worktrees/include.mjs +6 -4
  394. package/src/runtime/shared/worktrees/maintenance.mjs +422 -30
  395. package/src/runtime/shared/worktrees/manager.mjs +962 -197
  396. package/src/runtime/shared/worktrees/settings.mjs +33 -7
  397. package/src/runtime/shared/worktrees/test-support.mjs +5 -1
  398. package/src/runtime/shared/worktrees/worker-snapshots.mjs +82 -0
  399. package/src/runtime/tidy/install.mjs +95 -15
  400. package/src/runtime/tidy/languages.mjs +17 -15
  401. package/src/runtime/tidy/process.mjs +9 -5
  402. package/src/runtime/tidy/resolve.mjs +19 -16
  403. package/src/runtime/tidy/runners/biome.mjs +3 -3
  404. package/src/runtime/tidy/tool.mjs +1 -1
  405. package/src/runtime/tidy/worktree.mjs +10 -6
  406. package/src/runtime/visualize-bridge/client.mjs +4 -1
  407. package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
  408. package/src/runtime/web-search/index.mjs +4 -23
  409. package/src/runtime/web-search/lib/web-tools.mjs +2 -2
  410. package/src/runtime/web-search/tool-defs.mjs +17 -26
  411. package/src/session-runtime/agent-profile-changes.mjs +55 -4
  412. package/src/session-runtime/agent-task-sessions.mjs +410 -353
  413. package/src/session-runtime/boot/apis.mjs +27 -4
  414. package/src/session-runtime/boot/begin.mjs +2 -0
  415. package/src/session-runtime/boot/config.mjs +10 -1
  416. package/src/session-runtime/boot/facade.mjs +1 -0
  417. package/src/session-runtime/boot/providers.mjs +70 -3
  418. package/src/session-runtime/boot/session.mjs +2 -0
  419. package/src/session-runtime/boot/tools.mjs +71 -25
  420. package/src/session-runtime/bot-status.mjs +103 -103
  421. package/src/session-runtime/channel-config-api.mjs +1 -0
  422. package/src/session-runtime/config-change-effects.mjs +179 -0
  423. package/src/session-runtime/config-lifecycle/config-writers.mjs +1 -0
  424. package/src/session-runtime/config-lifecycle.mjs +160 -24
  425. package/src/session-runtime/connector-merge-migration.mjs +18 -15
  426. package/src/session-runtime/conversation-import/discovery.mjs +245 -47
  427. package/src/session-runtime/conversation-import/service.mjs +12 -5
  428. package/src/session-runtime/goal-facade-api.mjs +49 -3
  429. package/src/session-runtime/handoff-attachments.mjs +1 -1
  430. package/src/session-runtime/held-requests.mjs +3 -1
  431. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +3 -0
  432. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -2
  433. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -11
  434. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
  435. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +161 -120
  436. package/src/session-runtime/internal-tool-executor.mjs +12 -19
  437. package/src/session-runtime/lifecycle/cold-heir.mjs +7 -0
  438. package/src/session-runtime/lifecycle/memory-ingest.mjs +3 -3
  439. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +53 -5
  440. package/src/session-runtime/lifecycle/session-switch.mjs +13 -2
  441. package/src/session-runtime/lifecycle/teardown/session-close.mjs +10 -5
  442. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  443. package/src/session-runtime/lifecycle-api.mjs +1 -0
  444. package/src/session-runtime/mcp-glue/server-catalog.mjs +27 -10
  445. package/src/session-runtime/mcp-glue/server-connection.mjs +34 -8
  446. package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
  447. package/src/session-runtime/mixy-heartbeat.mjs +1 -1
  448. package/src/session-runtime/model-route/set-route.mjs +40 -7
  449. package/src/session-runtime/native-web-search/routes.mjs +3 -3
  450. package/src/session-runtime/provider-auth/login.mjs +2 -2
  451. package/src/session-runtime/provider-auth/refresh.mjs +6 -3
  452. package/src/session-runtime/provider-auth/setup.mjs +1 -1
  453. package/src/session-runtime/provider-readiness.mjs +53 -4
  454. package/src/session-runtime/resource-api.mjs +1 -1
  455. package/src/session-runtime/resource-extension-sync.mjs +4 -8
  456. package/src/session-runtime/resource-mcp-api.mjs +98 -35
  457. package/src/session-runtime/resource-mcp-connector-accounts.mjs +49 -32
  458. package/src/session-runtime/resource-mcp-secrets.mjs +27 -10
  459. package/src/session-runtime/resource-mcp-servers.mjs +5 -4
  460. package/src/session-runtime/resource-plugins-api.mjs +4 -0
  461. package/src/session-runtime/routine-executor.mjs +152 -0
  462. package/src/session-runtime/routine-home-turn.mjs +46 -5
  463. package/src/session-runtime/runtime-facade.mjs +5 -0
  464. package/src/session-runtime/runtime-feature-gates.mjs +2 -11
  465. package/src/session-runtime/schedule-session-run.mjs +1 -0
  466. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +6 -1
  467. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +7 -0
  468. package/src/session-runtime/services/agent-tool/send-flow.mjs +120 -8
  469. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +12 -0
  470. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +5 -0
  471. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
  472. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +28 -7
  473. package/src/session-runtime/services/agent-tool.mjs +51 -1
  474. package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
  475. package/src/session-runtime/services/channel-admin.mjs +18 -0
  476. package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
  477. package/src/session-runtime/services/daemon-candidate.mjs +4 -1
  478. package/src/session-runtime/services/hook-bus/command-handler.mjs +7 -11
  479. package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
  480. package/src/session-runtime/services/plugin-admin.mjs +14 -6
  481. package/src/session-runtime/services/provider-admin.mjs +281 -10
  482. package/src/session-runtime/services/seeds.mjs +7 -0
  483. package/src/session-runtime/services/usage-stats-model.mjs +32 -11
  484. package/src/session-runtime/session-create/materialize.mjs +4 -2
  485. package/src/session-runtime/session-create/session-options.mjs +2 -0
  486. package/src/session-runtime/session-turn-api.mjs +2 -0
  487. package/src/session-runtime/settings-builtin-tools-api.mjs +5 -10
  488. package/src/session-runtime/settings-system-api.mjs +1 -1
  489. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
  490. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
  491. package/src/session-runtime/setup-tool/executor.mjs +14 -3
  492. package/src/session-runtime/setup-tool/extended-actions.mjs +2 -0
  493. package/src/session-runtime/setup-tool/settings-contract.mjs +28 -0
  494. package/src/session-runtime/setup-tool/tool-defs.mjs +28 -2
  495. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +40 -43
  496. package/src/session-runtime/tool-policy/mode-switch.mjs +1 -1
  497. package/src/session-runtime/tool-policy/policy-stage.mjs +106 -8
  498. package/src/session-runtime/tool-policy/workflow-overlay.mjs +2 -1
  499. package/src/session-runtime/tool-policy-refresh.mjs +182 -5
  500. package/src/session-runtime/tool-surface.mjs +38 -1
  501. package/src/session-runtime/turn/agent-ops.mjs +33 -2
  502. package/src/session-runtime/turn/session-ops.mjs +2 -0
  503. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +5 -0
  504. package/src/session-runtime/turn/turn-run.mjs +1 -1
  505. package/src/session-runtime/webhook-session-run.mjs +2 -0
  506. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +46 -11
  507. package/src/session-runtime/workflow-agents-api/agent-route.mjs +2 -0
  508. package/src/session-runtime/workflow-agents-api/instruction-files.mjs +165 -0
  509. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +5 -4
  510. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +2 -3
  511. package/src/session-runtime/workflow-agents-api.mjs +2 -0
  512. package/src/session-runtime/workspace/activity-guards.mjs +176 -0
  513. package/src/session-runtime/workspace/project-branches.mjs +1 -1
  514. package/src/session-runtime/workspace/session-view.mjs +149 -0
  515. package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
  516. package/src/session-runtime/workspace/transition-runner.mjs +188 -0
  517. package/src/session-runtime/workspace/transitions.mjs +128 -1070
  518. package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
  519. package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
  520. package/src/session-runtime/workspace/worktree-maintenance.mjs +200 -0
  521. package/src/session-runtime/workspace/worktree-setup.mjs +97 -0
  522. package/src/session-runtime/workspace/worktree-tool.mjs +70 -54
  523. package/src/standalone/daemon-agent-control.mjs +25 -8
  524. package/src/standalone/daemon-desktop-runtime.mjs +8 -2
  525. package/src/standalone/daemon-lag-profiler.mjs +7 -7
  526. package/src/standalone/daemon-session-control.mjs +151 -136
  527. package/src/standalone/daemon.mjs +61 -2
  528. package/src/standalone/desktop-service-registry.mjs +9 -0
  529. package/src/standalone/local-session-runtime.mjs +21 -1
  530. package/src/standalone/session-client/daemon-unavailable.mjs +4 -1
  531. package/src/standalone/session-client.mjs +5 -1
  532. package/src/standalone/session-frame-stream.mjs +83 -11
  533. package/src/standalone/session-protocol.mjs +15 -0
  534. package/src/standalone/session-service/agent-route-follow.mjs +23 -20
  535. package/src/standalone/session-service/agent-tree/agent-turns.mjs +18 -6
  536. package/src/standalone/session-service/agent-tree.mjs +45 -9
  537. package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
  538. package/src/standalone/session-service/quota-resume.mjs +9 -0
  539. package/src/standalone/session-service/session-calls/session-action.mjs +51 -1
  540. package/src/standalone/session-service/session-calls/session-turns.mjs +37 -18
  541. package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
  542. package/src/standalone/session-service/session-calls/turn-gate.mjs +34 -0
  543. package/src/standalone/session-service/session-calls.mjs +2 -1
  544. package/src/standalone/session-service/stored-reader.mjs +127 -40
  545. package/src/tui/App.jsx +162 -164
  546. package/src/tui/app/app-view/floating-panel.jsx +3 -0
  547. package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
  548. package/src/tui/app/clipboard.mjs +22 -11
  549. package/src/tui/app/create-app-pickers.mjs +2 -0
  550. package/src/tui/app/doctor.mjs +2 -2
  551. package/src/tui/app/panel-signature.mjs +1 -1
  552. package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
  553. package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
  554. package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
  555. package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
  556. package/src/tui/app/provider-setup/oauth-actions.mjs +25 -6
  557. package/src/tui/app/provider-setup-picker.mjs +20 -13
  558. package/src/tui/app/settings-picker.mjs +53 -8
  559. package/src/tui/app/shell-layout/row-budgets.mjs +14 -12
  560. package/src/tui/app/slash-commands.mjs +2 -1
  561. package/src/tui/app/slash-dispatch/route-commands.mjs +1 -1
  562. package/src/tui/app/slash-dispatch/session-commands.mjs +47 -1
  563. package/src/tui/app/slash-dispatch.mjs +1 -1
  564. package/src/tui/app/use-btw-panel.mjs +29 -0
  565. package/src/tui/app/use-context-panel-refresh.mjs +31 -0
  566. package/src/tui/app/use-model-catalog-cache.mjs +13 -10
  567. package/src/tui/app/use-mouse-input.mjs +11 -0
  568. package/src/tui/app/use-onboarding-start.mjs +8 -3
  569. package/src/tui/app/use-panel-transition.mjs +10 -1
  570. package/src/tui/app/use-pasted-buffers.mjs +28 -20
  571. package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
  572. package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
  573. package/src/tui/app/use-prompt-queue-history.mjs +5 -4
  574. package/src/tui/app/use-selection-focus.mjs +11 -2
  575. package/src/tui/app/use-selection-geometry.mjs +18 -9
  576. package/src/tui/app/use-selection-paint.mjs +4 -4
  577. package/src/tui/app/use-selection-stitch.mjs +3 -3
  578. package/src/tui/app/use-slash-palette.mjs +62 -0
  579. package/src/tui/app/use-terminal-chrome.mjs +2 -2
  580. package/src/tui/app/use-transcript-activity.mjs +48 -33
  581. package/src/tui/app/use-transcript-follow.mjs +12 -4
  582. package/src/tui/app/use-transcript-scroll.mjs +46 -17
  583. package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
  584. package/src/tui/app/use-transcript-window/geometry.mjs +20 -6
  585. package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
  586. package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
  587. package/src/tui/app/use-transcript-window.mjs +21 -11
  588. package/src/tui/app/use-tui-ready.mjs +18 -0
  589. package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
  590. package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
  591. package/src/tui/components/Picker.jsx +27 -3
  592. package/src/tui/components/SignInUrl.jsx +68 -0
  593. package/src/tui/components/TextEntryPanel.jsx +76 -46
  594. package/src/tui/components/prompt-input/escape-policy.d.mts +0 -1
  595. package/src/tui/components/prompt-input/escape-policy.mjs +1 -1
  596. package/src/tui/components/question-panel-model.mjs +4 -4
  597. package/src/tui/components/sign-in-url-layout.mjs +24 -0
  598. package/src/tui/components/tool-execution/standard-card.jsx +3 -4
  599. package/src/tui/components/user-message-skills.mjs +1 -1
  600. package/src/tui/dist/index.mjs +2205 -1371
  601. package/src/tui/markdown/render-ansi.mjs +1 -1
  602. package/src/tui/session/agent-job-feed/notification-router.mjs +10 -0
  603. package/src/tui/session/agent-job-feed.mjs +2 -0
  604. package/src/tui/session/context-state.mjs +3 -0
  605. package/src/tui/session/goal-turn-state.mjs +6 -2
  606. package/src/tui/session/quota-resume.mjs +1 -1
  607. package/src/tui/session/session-api/controls.mjs +4 -0
  608. package/src/tui/session/session-api/extensions.mjs +8 -0
  609. package/src/tui/session/session-api/intake/abort.mjs +2 -1
  610. package/src/tui/session/session-api/intake.mjs +2 -0
  611. package/src/tui/session/session-api/integrations.mjs +2 -2
  612. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  613. package/src/tui/session/session-api/lifecycle/session-reset.mjs +7 -0
  614. package/src/tui/session/session-api/routes-agent-definitions.mjs +6 -0
  615. package/src/tui/session/session-api/settings.mjs +2 -2
  616. package/src/tui/session/session-api/worktree.mjs +13 -1
  617. package/src/tui/session/session-flow/drain.mjs +11 -14
  618. package/src/tui/session/tool-card-results/grouped-result.mjs +2 -2
  619. package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
  620. package/src/tui/session/transcript-spill.mjs +92 -4
  621. package/src/tui/session/transcript-store.mjs +2 -0
  622. package/src/tui/session/turn-quiet.mjs +1 -1
  623. package/src/tui/session/turn.mjs +3 -0
  624. package/src/tui/session/worktree-setup-notice.mjs +1 -1
  625. package/src/tui/spinner-meta.mjs +3 -3
  626. package/src/tui/spinner-verbs.mjs +2 -2
  627. package/src/defaults/skills/goal-management/SKILL.md +0 -169
  628. package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
  629. package/src/runtime/agent/orchestrator/runtime-core/goal-tasks.mjs +0 -156
  630. package/src/session-runtime/goal-tasks.mjs +0 -1
@@ -111,13 +111,25 @@ import {
111
111
  providerAccountLimit,
112
112
  providerAccountBlockedUntil,
113
113
  ACCOUNT_PROVIDERS,
114
+ MAX_ACCOUNTS,
115
+ customProviderKeyIds,
116
+ setCustomProviderKeyIds,
114
117
  } from '../../runtime/shared/provider-accounts.mjs';
118
+ import { customProviderKeyAccount } from '../../runtime/shared/custom-provider-keys.mjs';
115
119
  import { currentProviderAccountId, withProviderAccount } from '../../runtime/shared/provider-auth-binding.mjs';
116
120
  import {
117
121
  CUSTOM_API_KEY_ENV_RE,
118
122
  effectiveCustomModelRows,
119
123
  normalizeCustomProviderConfig as normalizeStoredCustomConfig,
120
124
  } from '../../runtime/agent/orchestrator/providers/custom-provider-config.mjs';
125
+ import {
126
+ VERTEX_ADC_MODE,
127
+ VERTEX_API_KEY_MODE,
128
+ describeVertexAdc,
129
+ parseVertexServiceAccount,
130
+ probeVertexMetadata,
131
+ } from '../../runtime/agent/orchestrator/providers/vertex-ai-auth.mjs';
132
+ import { vertexEnvLocation } from '../../runtime/agent/orchestrator/providers/vertex-ai-models.mjs';
121
133
 
122
134
  const API_PROVIDERS = Object.freeze([
123
135
  Object.freeze({ id: 'openrouter', name: 'OpenRouter', env: 'OPENROUTER_API_KEY', url: 'https://openrouter.ai/keys' }),
@@ -134,6 +146,7 @@ const API_PROVIDERS = Object.freeze([
134
146
  url: 'https://console.anthropic.com/settings/keys',
135
147
  }),
136
148
  Object.freeze({ id: 'gemini', name: 'Gemini API', env: 'GEMINI_API_KEY', url: 'https://aistudio.google.com/apikey' }),
149
+ Object.freeze({ id: 'vertex-ai', name: 'Vertex AI', env: null, url: null }),
137
150
  Object.freeze({
138
151
  id: 'deepseek',
139
152
  name: 'DeepSeek API',
@@ -374,6 +387,23 @@ function storedSecretDetail(account) {
374
387
  return isFallbackSecret(account) ? 'stored in private file' : 'stored in keychain';
375
388
  }
376
389
 
390
+ // The Vertex AI gcloud-login row's detail: who is signed in and where, or what to fix.
391
+ function vertexAdcDetail(adc, location) {
392
+ if (!adc) return `gcloud login · ${location}`;
393
+ if (adc.state !== 'ready') return adc.message;
394
+ const account = adc.account || (adc.type === 'metadata' ? 'metadata server' : 'gcloud user login');
395
+ return [account, adc.projectId || 'no project', location].join(' · ');
396
+ }
397
+
398
+ // The Vertex AI location a row shows and where it comes from: the saved one
399
+ // ('config'), else what the runtime would use unset ('environment' or
400
+ // 'default'), which the connect form offers as a hint without saving it.
401
+ function vertexRowLocation(configured) {
402
+ if (configured.location) return { location: String(configured.location), locationSource: 'config' };
403
+ const env = vertexEnvLocation();
404
+ return env ? { location: env, locationSource: 'environment' } : { location: 'global', locationSource: 'default' };
405
+ }
406
+
377
407
  // `keychainIssue`: the setup response's one keyring check (never asked per row).
378
408
  function apiProviderSetup(p, providers, checkSecrets, keychainIssue) {
379
409
  const configured = providers[p.id] || {};
@@ -402,6 +432,74 @@ function apiProviderSetup(p, providers, checkSecrets, keychainIssue) {
402
432
  }
403
433
  const rowIssue = authenticated ? null : keychainIssue;
404
434
  if (rowIssue) detail = rowIssue.message;
435
+ if (p.id === 'vertex-ai' && configured.authMode === VERTEX_ADC_MODE) {
436
+ // gcloud login: nothing is stored; connected while enabled and the login is readable.
437
+ const { location, locationSource } = vertexRowLocation(configured);
438
+ const adc = checkSecrets ? describeVertexAdc({ projectId: configured.projectId }) : null;
439
+ // Without a login file a metadata server may stand in: probed once, in the
440
+ // background, for the next refresh to report.
441
+ if (adc?.state === 'missing') void probeVertexMetadata();
442
+ const ready = configuredEnabled && (!adc || adc.state === 'ready');
443
+ let adcStatus = configuredEnabled ? 'Not connected' : 'Off';
444
+ if (ready) adcStatus = 'Set';
445
+ return {
446
+ ...p,
447
+ group: 'api',
448
+ type: 'api-key',
449
+ authKind: 'adc',
450
+ authMode: VERTEX_ADC_MODE,
451
+ enabled: configuredEnabled,
452
+ authenticated: ready,
453
+ stored: false,
454
+ env: false,
455
+ envName: null,
456
+ status: adcStatus,
457
+ detail: vertexAdcDetail(adc, location),
458
+ location,
459
+ locationSource,
460
+ projectId: adc?.projectId || String(configured.projectId || '') || null,
461
+ ...(adc ? { adc } : {}),
462
+ };
463
+ }
464
+ if (p.id === 'vertex-ai') {
465
+ const { location, locationSource } = vertexRowLocation(configured);
466
+ // An express-mode API key, or the service-account key.
467
+ const express = configured.authMode === VERTEX_API_KEY_MODE;
468
+ // The connect form offers the gcloud login too; its status line reads this.
469
+ const adc = checkSecrets && !authenticated ? describeVertexAdc({ projectId: configured.projectId }) : null;
470
+ let projectId = String(configured.projectId || '');
471
+ if (!projectId && authenticated && checkSecrets && !express) {
472
+ try {
473
+ projectId = parseVertexServiceAccount(getAgentApiKey(p.id)).projectId;
474
+ } catch {
475
+ // An unreadable key leaves the project id empty; the status line then shows the location only.
476
+ }
477
+ }
478
+ if (!rowIssue) {
479
+ if (express) detail = `API key (express mode) · ${location}`;
480
+ else detail = projectId ? `${projectId} · ${location}` : `Location: ${location}`;
481
+ }
482
+ return {
483
+ ...p,
484
+ ...(rowIssue ? { keychainIssue: rowIssue } : {}),
485
+ group: 'api',
486
+ type: 'api-key',
487
+ authKind: express ? 'api-key' : 'service-account',
488
+ authMode: express ? VERTEX_API_KEY_MODE : 'service-account',
489
+ ...(adc ? { adc } : {}),
490
+ enabled: configuredEnabled || authenticated,
491
+ authenticated,
492
+ stored,
493
+ env: false,
494
+ envName: null,
495
+ status,
496
+ detail,
497
+ location,
498
+ locationSource,
499
+ projectId: projectId || null,
500
+ ...(credentialSource ? { credentialSource } : {}),
501
+ };
502
+ }
405
503
  return {
406
504
  ...p,
407
505
  ...(rowIssue ? { keychainIssue: rowIssue } : {}),
@@ -561,8 +659,12 @@ function customProviderRow(id, entry, checkSecrets = true) {
561
659
  row.auth = keyless ? 'none' : 'key';
562
660
  row.discovery = structuredClone(config?.discovery ?? entry.discovery ?? { newModelsHidden: false });
563
661
  row.modelOverrides = structuredClone(config?.modelOverrides ?? entry.modelOverrides ?? {});
662
+ if (config?.headers) row.headers = { ...config.headers };
564
663
  if (config?.wires) row.wires = [...config.wires];
565
664
  if (config?.modelWires) row.modelWires = { ...config.modelWires };
665
+ // Additional API keys by id only; their values never leave the keychain.
666
+ const extraKeyIds = keyless ? [] : customProviderKeyIds(id);
667
+ if (extraKeyIds.length) row.extraApiKeys = extraKeyIds.map((keyId) => ({ id: keyId }));
566
668
  // A stored config that does not normalize cannot run (the registry skips
567
669
  // it): say so explicitly instead of listing it as connected.
568
670
  // Every readiness flag consumers read says "not ready" (`stored` stays the
@@ -660,6 +762,20 @@ async function modelProxyProviderSetup(options) {
660
762
 
661
763
  function apiProviderStatusRow(p, config) {
662
764
  const configured = config.providers?.[p.id] || {};
765
+ if (p.id === 'vertex-ai' && configured.authMode === VERTEX_ADC_MODE) {
766
+ const adc = describeVertexAdc({ projectId: configured.projectId });
767
+ return {
768
+ id: p.id,
769
+ type: 'api-key',
770
+ enabled: configured.enabled === true,
771
+ authenticated: configured.enabled === true && adc.state === 'ready',
772
+ stored: false,
773
+ env: false,
774
+ envName: null,
775
+ label: p.name,
776
+ detail: vertexAdcDetail(adc, vertexRowLocation(configured).location),
777
+ };
778
+ }
663
779
  const envName = AGENT_PROVIDER_ENV[p.id] || p.env;
664
780
  const env = Boolean(envName && process.env[envName]);
665
781
  const stored = hasStoredSecret(SECRET_ACCOUNTS.agentApiKey(p.id));
@@ -720,6 +836,7 @@ export function renderProviderStatus(config = {}) {
720
836
  if (row.type === 'oauth') source = row.detail || 'oauth';
721
837
  else if (row.env) source = `env:${row.envName}`;
722
838
  else if (row.stored) source = 'keychain';
839
+ else if (row.detail) source = row.detail;
723
840
  const enabled = row.enabled ? 'enabled' : 'disabled';
724
841
  return `${row.id.padEnd(width)} ${row.type.padEnd(7)} ${auth.padEnd(8)} ${enabled.padEnd(8)} ${source}`;
725
842
  })
@@ -984,15 +1101,68 @@ export async function updateProviderAccounts(provider, change) {
984
1101
  return listProviderAccounts(provider);
985
1102
  }
986
1103
 
987
- export async function saveProviderApiKey(cfgMod, provider, secret) {
1104
+ export async function saveProviderApiKey(cfgMod, provider, secret, options) {
988
1105
  requireLocalProviderManagement();
989
1106
  const id = String(provider || '').trim();
990
1107
  if (!API_PROVIDER_IDS.has(id)) throw new Error(`unknown API-key provider "${id}"`);
991
1108
  const value = String(secret || '').trim();
992
- if (!value) throw new Error(`API key is required for ${id}`);
1109
+ const adc = id === 'vertex-ai' && options?.authMode === VERTEX_ADC_MODE;
1110
+ const express = id === 'vertex-ai' && options?.authMode === VERTEX_API_KEY_MODE;
1111
+ if (!value && !adc) throw new Error(`API key is required for ${id}`);
1112
+ let patch = { enabled: true };
1113
+ if (id === 'vertex-ai') {
1114
+ if (adc && value) throw new Error('Vertex AI gcloud login takes no key');
1115
+ if (express && /[\s{]/.test(value)) throw new Error('Vertex AI express mode takes an API key, not a JSON key file');
1116
+ if (!adc && !express) parseVertexServiceAccount(value);
1117
+ // Only a location the user chose is saved: an empty one is unset (the
1118
+ // runtime then follows the environment's region, then global). None given
1119
+ // at all (the terminal setup) keeps a saved one; express mode never keeps
1120
+ // one, as it serves global only.
1121
+ const location = String(options?.location ?? '')
1122
+ .trim()
1123
+ .toLowerCase();
1124
+ const projectId = String(options?.projectId || '').trim();
1125
+ if (location && !/^[a-z0-9-]{1,63}$/.test(location)) throw new Error('Vertex AI location is invalid');
1126
+ if (express && location && location !== 'global') {
1127
+ throw new Error('Vertex AI express mode serves only the global location');
1128
+ }
1129
+ const locationPatch =
1130
+ location || express || options?.location !== undefined ? { location: location || undefined } : {};
1131
+ if (projectId && (!/^[a-zA-Z0-9._:-]{1,128}$/.test(projectId) || projectId.includes('/'))) {
1132
+ throw new Error('Vertex AI project ID override is invalid');
1133
+ }
1134
+ if (adc) {
1135
+ // gcloud login: nothing secret is stored, and the login must already be usable.
1136
+ let login = describeVertexAdc({ projectId });
1137
+ // No login file: a GCE / Cloud Run / GKE host's metadata server.
1138
+ if (login.state === 'missing' && (await probeVertexMetadata())) login = describeVertexAdc({ projectId });
1139
+ if (login.state !== 'ready') throw new Error(login.message);
1140
+ if (!login.projectId) {
1141
+ throw new Error(
1142
+ 'No Google Cloud project found for the gcloud login. Enter a project ID override, or run `gcloud config set project PROJECT_ID`.'
1143
+ );
1144
+ }
1145
+ // The login replaces a key saved earlier rather than sitting beside it.
1146
+ const account = SECRET_ACCOUNTS.agentApiKey(id);
1147
+ if (hasStoredSecret(account)) await deleteSecretAsync(account);
1148
+ updateConfigProvider(cfgMod, id, {
1149
+ enabled: true,
1150
+ ...locationPatch,
1151
+ projectId: projectId || undefined,
1152
+ authMode: VERTEX_ADC_MODE,
1153
+ });
1154
+ return { provider: id, type: 'adc', authenticated: true };
1155
+ }
1156
+ patch = {
1157
+ enabled: true,
1158
+ ...locationPatch,
1159
+ projectId: projectId || undefined,
1160
+ authMode: express ? VERTEX_API_KEY_MODE : 'service-account',
1161
+ };
1162
+ }
993
1163
  await saveSecretAsync(SECRET_ACCOUNTS.agentApiKey(id), value);
994
- updateConfigProvider(cfgMod, id, { enabled: true });
995
- return { provider: id, type: 'api-key', authenticated: true };
1164
+ updateConfigProvider(cfgMod, id, patch);
1165
+ return { provider: id, type: id === 'vertex-ai' && !express ? 'service-account' : 'api-key', authenticated: true };
996
1166
  }
997
1167
 
998
1168
  function sanitizeCustomError(error, secrets = []) {
@@ -1049,6 +1219,63 @@ function validateCustomTransportFields(input) {
1049
1219
  if (typeof input.apiKey === 'string' && input.apiKey !== '')
1050
1220
  throw new TypeError('custom provider apiKey and apiKeyEnv are mutually exclusive');
1051
1221
  }
1222
+ if (input.extraApiKeys !== undefined) validateExtraApiKeys(input.extraApiKeys);
1223
+ }
1224
+
1225
+ const CUSTOM_KEY_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
1226
+
1227
+ // Additional API keys in use order, beside the primary key (MAX_ACCOUNTS in
1228
+ // all): `{ id }` keeps a saved key, `{ apiKey }` adds one and `{ id, apiKey }`
1229
+ // replaces a saved key's value; a blank `apiKey` keeps the saved key.
1230
+ function validateExtraApiKeys(rows) {
1231
+ const invalid = () => new TypeError('custom provider extraApiKeys are invalid');
1232
+ if (!Array.isArray(rows) || rows.length >= MAX_ACCOUNTS) throw invalid();
1233
+ const ids = new Set();
1234
+ for (const row of rows) {
1235
+ if (!row || typeof row !== 'object' || Array.isArray(row)) throw invalid();
1236
+ if (Object.keys(row).some((key) => key !== 'id' && key !== 'apiKey')) throw invalid();
1237
+ if (row.id !== undefined && (typeof row.id !== 'string' || !CUSTOM_KEY_ID_RE.test(row.id) || ids.has(row.id)))
1238
+ throw new TypeError('custom provider extraApiKeys id is invalid');
1239
+ if (row.apiKey !== undefined && (typeof row.apiKey !== 'string' || row.apiKey.length > CUSTOM_API_KEY_MAX))
1240
+ throw new TypeError('custom provider extraApiKeys apiKey is invalid');
1241
+ if (row.id === undefined && !row.apiKey?.trim()) throw new TypeError('custom provider additional API key is empty');
1242
+ if (row.id !== undefined) ids.add(row.id);
1243
+ }
1244
+ }
1245
+
1246
+ // The additional-key change a save makes over the `saved` key ids: `rows`
1247
+ // absent keeps them; a typed key is stored under a new id, so a replaced key
1248
+ // starts without the old one's cooldown. A keyless provider keeps none.
1249
+ function extraKeyPlan(saved, rows, keyless) {
1250
+ if (keyless) return { saved, ids: [], added: [], removed: saved };
1251
+ if (rows === undefined) return { saved, ids: saved, added: [], removed: [] };
1252
+ const ids = [];
1253
+ const added = [];
1254
+ for (const row of rows) {
1255
+ if (row.id !== undefined && !saved.includes(row.id)) throw new Error('An additional API key is no longer saved.');
1256
+ const typed = typeof row.apiKey === 'string' ? row.apiKey.trim() : '';
1257
+ if (!typed) {
1258
+ ids.push(row.id);
1259
+ continue;
1260
+ }
1261
+ const keyId = randomUUID();
1262
+ ids.push(keyId);
1263
+ added.push({ keyId, key: typed });
1264
+ }
1265
+ return { saved, ids, added, removed: saved.filter((keyId) => !ids.includes(keyId)) };
1266
+ }
1267
+
1268
+ const extraKeysChanged = (plan) => plan.ids.join() !== plan.saved.join();
1269
+
1270
+ async function applyExtraKeys(id, plan) {
1271
+ for (const { keyId, key } of plan.added) await saveSecretAsync(customProviderKeyAccount(id, keyId), key);
1272
+ if (extraKeysChanged(plan)) await setCustomProviderKeyIds(id, plan.ids);
1273
+ }
1274
+
1275
+ // A failed save puts the saved roster back and drops the keys it added.
1276
+ async function revertExtraKeys(id, plan) {
1277
+ if (extraKeysChanged(plan)) await setCustomProviderKeyIds(id, plan.saved);
1278
+ for (const { keyId } of plan.added) await deleteSecretAsync(customProviderKeyAccount(id, keyId));
1052
1279
  }
1053
1280
 
1054
1281
  /** Whether the named environment variable is set to a non-empty value. */
@@ -1064,7 +1291,7 @@ function inputObject(input) {
1064
1291
  }
1065
1292
 
1066
1293
  // An edit that omits a stored setting keeps it: `auth` for every input shape,
1067
- // and `discovery` / `modelOverrides` for a v2 input (a legacy `models` input
1294
+ // and `discovery` / `modelOverrides` / `headers` for a v2 input (a legacy `models` input
1068
1295
  // states the whole manual model list itself).
1069
1296
  function withStoredSettings(input, entry) {
1070
1297
  const stored = storedCustomConfig(entry);
@@ -1079,6 +1306,8 @@ function withStoredSettings(input, entry) {
1079
1306
  if (out.schemaVersion === stored.schemaVersion) {
1080
1307
  if (out.discovery === undefined) out.discovery = stored.discovery;
1081
1308
  if (out.modelOverrides === undefined) out.modelOverrides = stored.modelOverrides;
1309
+ // `headers: {}` clears them; an omitted field keeps the stored ones.
1310
+ if (out.headers === undefined && stored.headers) out.headers = stored.headers;
1082
1311
  // Served wires and per-model wires have no setup field yet: an edit on
1083
1312
  // the same protocol keeps them (another protocol serves other wires).
1084
1313
  if ((out.protocol ?? stored.protocol) === stored.protocol) {
@@ -1095,7 +1324,9 @@ function withStoredSettings(input, entry) {
1095
1324
  // the config. Synchronous, so a caller can merge and commit one snapshot.
1096
1325
  function customInputAt(snapshot, input, normalizeCustomProviderConfig, options) {
1097
1326
  const id = input.id === undefined ? null : input.id;
1098
- const merged = id ? withStoredSettings(input, existingCustomEntry(snapshot, id)) : input;
1327
+ // Additional keys are secrets, applied by the save itself (extraKeyPlan).
1328
+ const { extraApiKeys: _extraKeys, ...settings } = input;
1329
+ const merged = id ? withStoredSettings(settings, existingCustomEntry(snapshot, id)) : settings;
1099
1330
  const config = normalizeCustomProviderConfig(merged, options);
1100
1331
  const typed = typeof merged.apiKey === 'string' ? merged.apiKey.trim() : '';
1101
1332
  const keyless = config.auth === 'none';
@@ -1147,9 +1378,16 @@ export async function saveCustomProvider(cfgMod, rawInput) {
1147
1378
  const commit = async () => {
1148
1379
  const account = SECRET_ACCOUNTS.agentApiKey(id);
1149
1380
  const previousKey = typed && existingId ? getAgentApiKey(id) : null;
1381
+ // Auth as of this save's turn in the key queue: a no-auth save queued
1382
+ // earlier may have landed since the input was resolved.
1383
+ const keyless = existingId
1384
+ ? customInputAt(cfgMod.loadConfig(), rawInput, normalizeCustomProviderConfig, { requireModels: false }).keyless
1385
+ : resolved.keyless;
1386
+ const extra = extraKeyPlan(existingId ? customProviderKeyIds(id) : [], rawInput.extraApiKeys, keyless);
1150
1387
  if (typed) await saveSecretAsync(account, typed);
1151
1388
  let entry;
1152
1389
  try {
1390
+ await applyExtraKeys(id, extra);
1153
1391
  // Synchronous from here: omitted settings come from the config this
1154
1392
  // save commits over, so an edit that landed during the awaits above (a
1155
1393
  // model's visibility, a peer save, a removal) is never reverted.
@@ -1162,15 +1400,29 @@ export async function saveCustomProvider(cfgMod, rawInput) {
1162
1400
  { baseConfig: current }
1163
1401
  );
1164
1402
  } catch (error) {
1403
+ await revertExtraKeys(id, extra);
1165
1404
  if (typed) {
1166
1405
  if (previousKey) await saveSecretAsync(account, previousKey);
1167
1406
  else await deleteSecretAsync(account);
1168
1407
  }
1169
1408
  throw error;
1170
1409
  }
1410
+ // A removed key is dropped once the save holds; a keychain refusal then
1411
+ // leaves an unused secret behind (reported), never a failed save that did commit.
1412
+ for (const keyId of extra.removed) {
1413
+ await deleteSecretAsync(customProviderKeyAccount(id, keyId)).catch((error) => {
1414
+ process.stderr.write(
1415
+ `[provider-admin] could not delete additional API key ${keyId} of ${id}: ${error?.message || error}\n`
1416
+ );
1417
+ });
1418
+ }
1171
1419
  return customProviderRow(id, entry);
1172
1420
  };
1173
- return typed ? serializeCustomKeySave(id, commit) : commit();
1421
+ // Every save that may change the keys runs in the provider's key queue: a
1422
+ // typed key, an additional-key list, or a no-auth save (which drops them),
1423
+ // decided from the input alone, never from a roster read outside the queue.
1424
+ const keysChange = typed || rawInput.extraApiKeys !== undefined || (existingId && resolved.keyless);
1425
+ return keysChange ? serializeCustomKeySave(id, commit) : commit();
1174
1426
  }
1175
1427
 
1176
1428
  // Replaces only the stored key of an existing custom provider. The provider's
@@ -1399,6 +1651,9 @@ export async function removeCustomProvider(cfgMod, rawId) {
1399
1651
  // provider registered so the removal can be retried. A missing secret
1400
1652
  // (keyless provider) is not an error.
1401
1653
  await deleteSecretAsync(SECRET_ACCOUNTS.agentApiKey(id));
1654
+ const extraKeyIds = customProviderKeyIds(id);
1655
+ for (const keyId of extraKeyIds) await deleteSecretAsync(customProviderKeyAccount(id, keyId));
1656
+ if (extraKeyIds.length) await setCustomProviderKeyIds(id, []);
1402
1657
  const current = cfgMod.loadConfig();
1403
1658
  const { [id]: _removed, ...providers } = current.providers || {};
1404
1659
  cfgMod.saveConfig(withoutProviderReferences({ ...current, providers }, id), { baseConfig: current });
@@ -1425,13 +1680,29 @@ export async function testCustomProvider(cfgMod, rawInput) {
1425
1680
  error: { kind: 'empty', message: 'No models were found for this provider' },
1426
1681
  };
1427
1682
  const { createCustomProvider } = await loadCustomProviderModule();
1428
- const provider = await createCustomProvider(id || 'custom-test', { ...config, apiKey });
1429
- await withTimeout(
1683
+ const primary = await createCustomProvider(id || 'custom-test', { ...config, apiKey });
1684
+ // A provider with additional keys tests through the same key pool as a
1685
+ // real request: an explicit quota refusal moves on to the next key.
1686
+ const keyIds = id && !config.apiKeyEnv && config.auth !== 'none' ? customProviderKeyIds(id) : [];
1687
+ let provider = primary;
1688
+ let routingKey;
1689
+ if (keyIds.length) {
1690
+ const [pool, keys] = await Promise.all([
1691
+ import('../../runtime/agent/orchestrator/providers/account-pool.mjs'),
1692
+ import('../../runtime/agent/orchestrator/providers/custom-provider-keys.mjs'),
1693
+ ]);
1694
+ routingKey = pool.ROUTING_METADATA_KEY;
1695
+ provider = pool.createCustomKeyPoolProvider(id, primary, (keyId) => keys.customKeyEngine(primary, id, keyId));
1696
+ }
1697
+ const answer = await withTimeout(
1430
1698
  (signal) => provider.send([{ role: 'user', content: 'Reply with OK.' }], model, [], { signal, maxTokens: 16 }),
1431
1699
  CUSTOM_TEST_TIMEOUT_MS,
1432
1700
  'connection test'
1433
1701
  );
1434
- return { ok: true };
1702
+ // Key numbers count the primary key as 1.
1703
+ const served = routingKey ? answer?.providerMetadata?.[routingKey]?.accountId : undefined;
1704
+ const index = keyIds.indexOf(served);
1705
+ return index < 0 ? { ok: true } : { ok: true, key: { id: served, number: index + 2 } };
1435
1706
  } catch (error) {
1436
1707
  throw sanitizeCustomError(error, customSecrets(apiKey, config));
1437
1708
  }
@@ -127,6 +127,13 @@ export function retireSeededPackCopies({ rootDir, dataDir, backup = makeBackup(d
127
127
  if (![bundled, ...(history.outputStyles[name] || [])].includes(fileHash(copy))) continue;
128
128
  if (backup.move(copy)) retired.push(`output-styles/${name}`);
129
129
  }
130
+ for (const name of childNames(join(dataDir, 'orchestration'), 'md')) {
131
+ const bundled = fileHash(join(rootDir, 'orchestration', name));
132
+ if (!bundled) continue;
133
+ const copy = join(dataDir, 'orchestration', name);
134
+ if (![bundled, ...(history.orchestration[name] || [])].includes(fileHash(copy))) continue;
135
+ if (backup.move(copy)) retired.push(`orchestration/${name}`);
136
+ }
130
137
  return retired;
131
138
  }
132
139
 
@@ -24,8 +24,11 @@
24
24
  import { billableInputTokensForProvider } from '../../runtime/shared/llm/cost.mjs';
25
25
  import { hourlySeries } from './usage-stats-hours.mjs';
26
26
  import {
27
+ FAST_KEY,
27
28
  isConversationUsageSource,
29
+ isFastCall,
28
30
  knownCostTurns,
31
+ sortFastBesideModel,
29
32
  usageRollupDayKey,
30
33
  } from '../../runtime/shared/llm/usage-rollup.mjs';
31
34
 
@@ -132,11 +135,14 @@ function providerBucket(state, provider, kind) {
132
135
  return bucket;
133
136
  }
134
137
 
135
- function modelBucket(provider, model) {
136
- let bucket = provider.models.get(model);
138
+ // A model's Fast-mode calls are their own row beside its normal row.
139
+ function modelBucket(provider, model, fast = false) {
140
+ const key = fast ? model + FAST_KEY : model;
141
+ let bucket = provider.models.get(key);
137
142
  if (!bucket) {
138
143
  bucket = {
139
144
  model,
145
+ fast,
140
146
  turns: 0,
141
147
  input: 0,
142
148
  output: 0,
@@ -146,7 +152,7 @@ function modelBucket(provider, model) {
146
152
  sessions: new Set(),
147
153
  sessionsComplete: true,
148
154
  };
149
- provider.models.set(model, bucket);
155
+ provider.models.set(key, bucket);
150
156
  }
151
157
  return bucket;
152
158
  }
@@ -166,9 +172,9 @@ function addUsage(target, usage) {
166
172
  target.speedMs = (target.speedMs || 0) + (usage.speedMs || 0);
167
173
  }
168
174
 
169
- function foldRoute(state, providerId, modelId, kind, usage) {
175
+ function foldRoute(state, providerId, modelId, kind, usage, fast = false) {
170
176
  const provider = providerBucket(state, providerId, kind);
171
- const model = modelBucket(provider, modelId);
177
+ const model = modelBucket(provider, modelId, fast);
172
178
  for (const bucket of [provider, model]) {
173
179
  addUsage(bucket, usage);
174
180
  if (usage.turns > 0 && (!usage.sessions || usage.sessionsComplete === false)) {
@@ -258,7 +264,7 @@ function foldRollupDay(state, key, day, conversationOnly) {
258
264
  speedOutput: num(raw?.speedOutput),
259
265
  speedMs: num(raw?.speedMs),
260
266
  };
261
- foldRoute(state, providerId, modelId, text(raw?.kind), usage);
267
+ foldRoute(state, providerId, modelId, text(raw?.kind), usage, raw?.fast === true);
262
268
  addDaily(state, key, usage, providerId);
263
269
  }
264
270
 
@@ -313,7 +319,14 @@ function foldEvent(state, key, event, conversationOnly) {
313
319
  speedOutput: timed ? output : 0,
314
320
  speedMs: timed ? durationMs : 0,
315
321
  };
316
- foldRoute(state, providerId, modelId, text(event?.providerKind), usage);
322
+ // Tiers are kept on the record's rates (see makeUsageRecord), not top level.
323
+ const kind = text(event?.providerKind);
324
+ const fast = isFastCall({
325
+ kind,
326
+ requestServiceTier: event?.rates?.requestServiceTier,
327
+ serviceTier: event?.rates?.serviceTier,
328
+ });
329
+ foldRoute(state, providerId, modelId, kind, usage, fast);
317
330
  addDaily(state, key, usage, providerId);
318
331
 
319
332
  if (durationMs > 0) {
@@ -513,9 +526,12 @@ function exportRoute(bucket, totalTokens) {
513
526
  function exportProviders(state, { totalTokens, modelLimit }) {
514
527
  return [...state.providers.values()]
515
528
  .map((bucket) => {
516
- const models = [...bucket.models.values()]
517
- .map((model) => ({ model: model.model, ...exportRoute(model, totalTokens) }))
518
- .sort((a, b) => b.tokens - a.tokens || b.costUsd - a.costUsd);
529
+ const exported = [...bucket.models.values()].map((model) => ({
530
+ model: model.model,
531
+ ...(model.fast ? { fast: true } : {}),
532
+ ...exportRoute(model, totalTokens),
533
+ }));
534
+ const models = sortFastBesideModel(exported, (row) => row.model, ['tokens', 'costUsd']);
519
535
  return {
520
536
  provider: bucket.provider,
521
537
  providerKind: bucket.providerKind,
@@ -535,7 +551,12 @@ function exportUnpricedModels(state) {
535
551
  const rows = [];
536
552
  for (const provider of state.providers.values()) {
537
553
  for (const model of provider.models.values()) {
538
- if (model.turns > 0 && model.costKnownTurns < model.turns)
554
+ // A model's Fast bucket is the same identity as its normal one.
555
+ if (
556
+ model.turns > 0 &&
557
+ model.costKnownTurns < model.turns &&
558
+ !rows.some((row) => row.provider === provider.provider && row.model === model.model)
559
+ )
539
560
  rows.push({ provider: provider.provider, model: model.model });
540
561
  }
541
562
  }
@@ -12,7 +12,7 @@ import { sessionOptions } from './session-options.mjs';
12
12
  * time. A boot connect still mid-handshake is caught on the first user
13
13
  * turn by refreshInitialDeferredMcpSurface (session-turn-api), which
14
14
  * re-folds the live registry before the prompt renders. */
15
- function seedToolSurface(deps, reason) {
15
+ function seedToolSurface(deps, reason, coreMemoryContext) {
16
16
  const { rt, mcpClient, modelStandaloneTools, applyPreSessionToolSelection } = deps;
17
17
  let connectedMcpTools = [];
18
18
  try {
@@ -37,6 +37,8 @@ function seedToolSurface(deps, reason) {
37
37
  // process-wide firstTurnCompleted.
38
38
  rt.session.deferredInitialRefreshPending = !/resume/i.test(String(reason || ''));
39
39
  applyPreSessionToolSelection();
40
+ // Built from the settings as they stand: its first turn need not rebuild it.
41
+ deps.noteToolAvailability?.(rt.session, coreMemoryContext);
40
42
  }
41
43
 
42
44
  /** Adopt the provider session and publish it to hooks and statusline. */
@@ -45,7 +47,7 @@ export function materializeSession(deps, reason, coreMemoryContext) {
45
47
  // adoptSession attaches the hook bridge (boot/infrastructure.mjs sessionAdopter).
46
48
  adoptSession(mgr.createSession(sessionOptions(deps, coreMemoryContext)));
47
49
  rt.reservedSessionId = null;
48
- seedToolSurface(deps, reason);
50
+ seedToolSurface(deps, reason, coreMemoryContext);
49
51
  writeStatuslineRoute(statusRoutes, rt.session, rt.route);
50
52
  hooks.emit('session:create', {
51
53
  sessionId: rt.session.id,
@@ -111,6 +111,8 @@ export function sessionOptions(deps, coreMemoryContext) {
111
111
  cwd: rt.currentCwd,
112
112
  ...(rt.desktopSession && typeof rt.desktopSession === 'object' ? { desktopSession: rt.desktopSession } : {}),
113
113
  coreMemoryContext,
114
+ // Prompt settings from the in-memory config (its disk copy trails it).
115
+ promptConfig: rt.config,
114
116
  workflow,
115
117
  workflowContext,
116
118
  ...(leadWorkflowParts ? { leadWorkflowParts } : {}),
@@ -36,6 +36,8 @@ export function createSessionTurnApi(deps) {
36
36
  agentControl: agent.agentControl,
37
37
  taskControl: agent.taskControl,
38
38
  stopShellJob: agent.stopShellJob,
39
+ listStoppableShellJobs: agent.listStoppableShellJobs,
40
+ stopShellJobs: agent.stopShellJobs,
39
41
  releaseShellJob: agent.releaseShellJob,
40
42
  listShellJobs: agent.listShellJobs,
41
43
  onNotification: agent.onNotification,
@@ -8,6 +8,7 @@ import {
8
8
  setBuiltinInstalledInConfig,
9
9
  } from '../runtime/agent/orchestrator/runtime-core/builtin-features.mjs';
10
10
  import { featureEnvOverride, moduleEnabled } from '../runtime/agent/orchestrator/runtime-core/config-helpers.mjs';
11
+ import { noteCacheWarmingEnabled } from '../runtime/agent/orchestrator/session/cache-warm.mjs';
11
12
  import { normalizeAgentAvatar } from '../runtime/shared/agent-avatar.mjs';
12
13
  import { LOCAL_PROVIDER_ID } from '../runtime/local-provider/managed-runtime.mjs';
13
14
  import { INSTRUCTION_FILES_MODES, normalizeInstructionFilesMode } from '../runtime/shared/instruction-files-mode.mjs';
@@ -66,7 +67,6 @@ export function createBuiltinToolSettings(
66
67
  webSearchEnabled,
67
68
  invalidateContextStatusCache,
68
69
  invalidatePreSessionToolSurface,
69
- refreshEmptySessionToolPolicy,
70
70
  },
71
71
  localSettings
72
72
  ) {
@@ -100,11 +100,13 @@ export function createBuiltinToolSettings(
100
100
  // default on. The warmer reads the saved value at each
101
101
  // warm, so a change applies without a restart.
102
102
  getCacheWarmingSettings() {
103
- return { enabled: getConfig()?.promptCacheWarming !== false };
103
+ return { enabled: getConfig()?.promptCacheWarming === true };
104
104
  },
105
105
  setCacheWarmingEnabled(enabled) {
106
106
  if (typeof enabled !== 'boolean') throw new TypeError('cache warming must be on or off (a boolean)');
107
107
  saveConfigAndAdopt({ ...getConfig(), promptCacheWarming: enabled });
108
+ // The warmer's synchronous state follows at once (off cancels chains).
109
+ noteCacheWarmingEnabled(enabled);
108
110
  return this.getCacheWarmingSettings();
109
111
  },
110
112
  // The one pixel face every Lead row on the bot page wears, shared by every
@@ -198,19 +200,15 @@ export function createBuiltinToolSettings(
198
200
  async setWebSearchEnabled(enabled) {
199
201
  const config = getConfig();
200
202
  saveConfigAndAdopt(setModuleEnabledInConfig({ ...config }, 'webSearch', enabled !== false));
201
- // Empty/reserved sessions rebuild now so session entry does not still
202
- // advertise web_search. A conversation keeps its frozen schema.
203
- await refreshEmptySessionToolPolicy?.();
204
203
  return this.getToolModuleSettings();
205
204
  },
206
205
  /** Which user instruction files (AGENTS.md / CLAUDE.md) new sessions load:
207
- * 'all' | 'agents' | 'claude' | 'off'. The empty session rebuilds now. */
206
+ * 'all' | 'agents' | 'claude' | 'off'. An empty session rebuilds at its next turn. */
208
207
  async setInstructionFiles(mode) {
209
208
  if (!INSTRUCTION_FILES_MODES.includes(mode)) {
210
209
  throw new TypeError(`Instruction files must be one of ${INSTRUCTION_FILES_MODES.join(', ')}.`);
211
210
  }
212
211
  saveConfigAndAdopt({ ...getConfig(), instructionFiles: mode });
213
- await refreshEmptySessionToolPolicy?.();
214
212
  return this.getToolModuleSettings();
215
213
  },
216
214
  /** The global "Auto reasoning base": the effort Auto works around. */
@@ -235,7 +233,6 @@ export function createBuiltinToolSettings(
235
233
  if (memoryEnabled) nextConfig = setBuiltinInstalledInConfig(nextConfig, 'memory', true);
236
234
  saveConfigAndAdopt(nextConfig);
237
235
  invalidateContextStatusCache();
238
- await refreshEmptySessionToolPolicy?.();
239
236
  return this.getToolModuleSettings();
240
237
  },
241
238
  async setBuiltinToolEnabled(name, enabled) {
@@ -265,7 +262,6 @@ export function createBuiltinToolSettings(
265
262
  }
266
263
  // Turning Auto on loads nothing: the judge starts on its first turn.
267
264
  if (name === 'autoEffort' && enabled === false) await shutdownEffortJudge();
268
- await refreshEmptySessionToolPolicy?.();
269
265
  return this.getToolModuleSettings();
270
266
  },
271
267
  /** Extensions → Built-in Install: run the feature's preparation adapter
@@ -297,7 +293,6 @@ export function createBuiltinToolSettings(
297
293
  await syncLocalProviderRegistry?.(true);
298
294
  }
299
295
  if (name === 'memory') invalidateContextStatusCache();
300
- await refreshEmptySessionToolPolicy?.();
301
296
  return this.getToolModuleSettings();
302
297
  },
303
298
  /** Extensions → Code Tidy: which engines exist, where each one comes from,