mixdog 1.0.11 → 1.1.0

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 (471) hide show
  1. package/NOTICE.md +20 -0
  2. package/README.md +75 -181
  3. package/package.json +9 -4
  4. package/scripts/build-shipped-history.mjs +131 -0
  5. package/scripts/check-changelog-locales.mjs +203 -0
  6. package/scripts/computer-task-cost-report.mjs +0 -4
  7. package/scripts/lib/run-node-tests.mjs +235 -13
  8. package/scripts/lib/test-failure-records.mjs +5 -0
  9. package/scripts/lib/test-failure-summary.mjs +9 -3
  10. package/scripts/lib/test-spawn-ledger.mjs +19 -0
  11. package/scripts/prune-embedding-runtime.mjs +9 -5
  12. package/scripts/sync-client-version-floors.mjs +100 -0
  13. package/scripts/test-direct.mjs +16 -1
  14. package/src/agents/advisor/AGENT.md +38 -0
  15. package/src/agents/advisor/agent.json +6 -0
  16. package/src/agents/reviewer/AGENT.md +5 -2
  17. package/src/agents/reviewer/agent.json +1 -1
  18. package/src/defaults/shipped-history.json +381 -0
  19. package/src/defaults/skills/docx/SKILL.md +7 -5
  20. package/src/defaults/skills/docx/references/html.md +9 -8
  21. package/src/defaults/skills/docx/references/native-authoring.md +28 -18
  22. package/src/defaults/skills/goal-management/SKILL.md +11 -5
  23. package/src/defaults/skills/local-provider/SKILL.md +2 -1
  24. package/src/defaults/skills/pdf/SKILL.md +9 -6
  25. package/src/defaults/skills/pdf/references/html.md +17 -12
  26. package/src/defaults/skills/pptx/SKILL.md +8 -6
  27. package/src/defaults/skills/pptx/references/composition.md +4 -4
  28. package/src/defaults/skills/pptx/references/concepts.md +168 -0
  29. package/src/defaults/skills/pptx/references/direction.md +5 -4
  30. package/src/defaults/skills/pptx/references/html.md +6 -29
  31. package/src/defaults/skills/pptx/references/kit-index.md +11 -3
  32. package/src/defaults/skills/pptx/references/kit.md +27 -5
  33. package/src/defaults/skills/pptx/references/review.md +6 -5
  34. package/src/defaults/skills/setup/SKILL.md +5 -8
  35. package/src/defaults/skills/setup/references/actions.md +61 -31
  36. package/src/defaults/skills/setup/references/surfaces.md +12 -10
  37. package/src/defaults/skills/xlsx/SKILL.md +8 -6
  38. package/src/defaults/skills/xlsx/references/html.md +8 -4
  39. package/src/defaults/skills/xlsx/references/model-conventions.md +2 -0
  40. package/src/defaults/skills/xlsx/references/report-design.md +32 -16
  41. package/src/help.mjs +1 -1
  42. package/src/lib/rules-builder.cjs +1 -1
  43. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +3 -1
  44. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +4 -0
  45. package/src/runtime/agent/orchestrator/config-presets.d.mts +1 -0
  46. package/src/runtime/agent/orchestrator/config-presets.mjs +44 -0
  47. package/src/runtime/agent/orchestrator/config-providers-merge.mjs +9 -1
  48. package/src/runtime/agent/orchestrator/config.mjs +102 -21
  49. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +3 -2
  50. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +90 -26
  51. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +44 -14
  52. package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +4 -4
  53. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +5 -3
  54. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +79 -8
  55. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +29 -4
  56. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn.mjs +3 -0
  57. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +10 -1
  58. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +11 -2
  59. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +9 -5
  60. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +9 -1
  61. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +2 -0
  62. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +30 -22
  63. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +2 -0
  64. package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +28 -10
  65. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +14 -72
  66. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +19 -3
  67. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +20 -10
  68. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-sink.mjs +36 -9
  69. package/src/runtime/agent/orchestrator/providers/cursor.mjs +11 -17
  70. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +388 -0
  71. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +92 -109
  72. package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +107 -0
  73. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +138 -30
  74. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +32 -15
  75. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +2 -0
  76. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +39 -5
  77. package/src/runtime/agent/orchestrator/providers/gemini.mjs +9 -2
  78. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +3 -2
  79. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +6 -1
  80. package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +10 -1
  81. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +3 -2
  82. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +5 -1
  83. package/src/runtime/agent/orchestrator/providers/lib/note-error-usage.mjs +7 -0
  84. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +57 -0
  85. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +12 -5
  86. package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +20 -15
  87. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +14 -9
  88. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +56 -11
  89. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +2 -1
  90. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +28 -1
  91. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +27 -3
  92. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +7 -5
  93. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +12 -0
  94. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +23 -8
  95. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +26 -6
  96. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +7 -1
  97. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +34 -15
  98. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -2
  99. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +12 -2
  100. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +0 -6
  101. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +0 -19
  102. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +12 -43
  103. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +6 -0
  104. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +39 -9
  105. package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +31 -9
  106. package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +13 -38
  107. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +5 -2
  108. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +40 -9
  109. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +7 -39
  110. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +28 -101
  111. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +8 -4
  112. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +3 -6
  113. package/src/runtime/agent/orchestrator/providers/openai-service-tier.mjs +19 -0
  114. package/src/runtime/agent/orchestrator/providers/openai-startup-prewarm.mjs +5 -195
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +9 -18
  116. package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +4 -66
  117. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +11 -5
  118. package/src/runtime/agent/orchestrator/providers/openai-ws-send/acquire-attempt.mjs +3 -15
  119. package/src/runtime/agent/orchestrator/providers/openai-ws-send/attempt-request.mjs +6 -56
  120. package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +1 -19
  121. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +2 -2
  122. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +2 -1
  123. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +3 -0
  124. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure-stamps.mjs +0 -1
  125. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +3 -1
  126. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts.mjs +3 -5
  127. package/src/runtime/agent/orchestrator/providers/openai-ws-send-outcome.mjs +10 -89
  128. package/src/runtime/agent/orchestrator/providers/openai-ws-send-span.mjs +1 -1
  129. package/src/runtime/agent/orchestrator/providers/openai-ws-send-trace.mjs +0 -6
  130. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +34 -11
  131. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +0 -1
  132. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +3 -7
  133. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +44 -19
  134. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +40 -12
  135. package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +70 -0
  136. package/src/runtime/agent/orchestrator/providers/registry.mjs +38 -3
  137. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +4 -0
  138. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +1 -0
  139. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +2 -0
  140. package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +11 -0
  141. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +31 -41
  142. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +5 -0
  143. package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +0 -17
  144. package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +0 -3
  145. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +0 -1
  146. package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +1 -1
  147. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +1 -1
  148. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +1 -2
  149. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +18 -4
  150. package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +8 -1
  151. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +7 -1
  152. package/src/runtime/agent/orchestrator/runtime-core/session-route-policy.mjs +16 -0
  153. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +2 -0
  154. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -2
  155. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +7 -7
  156. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +6 -0
  157. package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +45 -2
  158. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +5 -3
  159. package/src/runtime/agent/orchestrator/session/eager-dispatch/entry.mjs +5 -0
  160. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +6 -13
  161. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +6 -2
  162. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +114 -0
  163. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +2 -0
  164. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +5 -9
  165. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +51 -18
  166. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +7 -4
  167. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -1
  168. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +0 -2
  169. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +6 -9
  170. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +63 -3
  171. package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +10 -28
  172. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +4 -4
  173. package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +13 -0
  174. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +10 -19
  175. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +7 -1
  176. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +1 -0
  177. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +1 -3
  178. package/src/runtime/agent/orchestrator/stall-policy.mjs +0 -1
  179. package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +18 -8
  180. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +19 -20
  181. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +6 -11
  182. package/src/runtime/agent/orchestrator/tools/builtin/file-version-test-helpers.mjs +11 -0
  183. package/src/runtime/agent/orchestrator/tools/builtin/file-version.mjs +13 -0
  184. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-single-file-rescue.mjs +8 -5
  185. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +25 -12
  186. package/src/runtime/agent/orchestrator/tools/builtin/raw-content-publication.mjs +17 -0
  187. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +136 -76
  188. package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +15 -17
  189. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +4 -2
  190. package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +11 -10
  191. package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +5 -3
  192. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +30 -16
  193. package/src/runtime/agent/orchestrator/tools/builtin/shell-lossless-compact.mjs +2 -2
  194. package/src/runtime/agent/orchestrator/tools/builtin/snapshot-helpers.mjs +4 -11
  195. package/src/runtime/agent/orchestrator/tools/builtin/snapshot-store.mjs +7 -3
  196. package/src/runtime/agent/orchestrator/tools/builtin/snapshot-validation.mjs +16 -19
  197. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  198. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background.mjs +4 -1
  199. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +14 -4
  200. package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +58 -8
  201. package/src/runtime/agent/orchestrator/tools/patch/content-guard.mjs +47 -0
  202. package/src/runtime/agent/orchestrator/tools/patch/delete-quarantine.mjs +155 -0
  203. package/src/runtime/agent/orchestrator/tools/patch/dispatch/native-proofs.mjs +6 -2
  204. package/src/runtime/agent/orchestrator/tools/patch/dispatch/native-snapshots.mjs +6 -2
  205. package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +19 -16
  206. package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +13 -44
  207. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +2 -2
  208. package/src/runtime/agent/orchestrator/tools/patch/post-patch-excerpts.mjs +5 -2
  209. package/src/runtime/agent/orchestrator/tools/patch/replay-capture.mjs +47 -7
  210. package/src/runtime/agent/orchestrator/tools/patch/rollback-state.mjs +72 -8
  211. package/src/runtime/agent/orchestrator/tools/patch/section-coalesce.mjs +3 -2
  212. package/src/runtime/agent/orchestrator/tools/patch/sequence/run.mjs +9 -1
  213. package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +9 -1
  214. package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +6 -6
  215. package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +16 -4
  216. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +35 -14
  217. package/src/runtime/agent/orchestrator/tools/patch/wave.mjs +42 -4
  218. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +2 -0
  219. package/src/runtime/agent/orchestrator/tools/shell-codepage.mjs +296 -0
  220. package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +75 -24
  221. package/src/runtime/browser-bridge/tool-defs.mjs +1 -0
  222. package/src/runtime/channels/lib/config.mjs +3 -8
  223. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +7 -3
  224. package/src/{tui → runtime/channels}/lib/voice-setup.mjs +38 -22
  225. package/src/runtime/channels/lib/webhook/request-handler.mjs +42 -8
  226. package/src/runtime/computer-bridge/actions.mjs +2 -0
  227. package/src/runtime/effort-judge/judge-client.mjs +125 -25
  228. package/src/runtime/effort-judge/judge-input.mjs +96 -0
  229. package/src/runtime/effort-judge/judge-worker.mjs +52 -20
  230. package/src/runtime/effort-judge/model-install.mjs +74 -0
  231. package/src/runtime/effort-judge/model-manifest.json +21 -0
  232. package/src/runtime/effort-judge/previous-human-request.mjs +162 -0
  233. package/src/runtime/effort-judge/verified-context-input.mjs +10 -0
  234. package/src/runtime/github/tool.mjs +214 -14
  235. package/src/runtime/local-provider/context-settings.mjs +15 -6
  236. package/src/runtime/local-provider/gguf-header.mjs +13 -5
  237. package/src/runtime/local-provider/hugging-face.mjs +27 -5
  238. package/src/runtime/local-provider/install-progress.mjs +7 -0
  239. package/src/runtime/local-provider/managed-runtime.mjs +2 -1
  240. package/src/runtime/local-provider/model-maintenance.mjs +15 -6
  241. package/src/runtime/local-provider/resumable-installations.mjs +40 -1
  242. package/src/runtime/local-provider/server.mjs +2 -0
  243. package/src/runtime/memory/lib/embedding-provider.mjs +12 -0
  244. package/src/runtime/memory/lib/http-router/session-routes.mjs +2 -1
  245. package/src/runtime/memory/lib/memory-config-flags.mjs +3 -2
  246. package/src/runtime/memory/lib/memory-embed.mjs +5 -0
  247. package/src/runtime/memory/lib/pg/process.mjs +57 -5
  248. package/src/runtime/office/README.md +13 -7
  249. package/src/runtime/office/authoring/docx-html-build.mjs +4 -4
  250. package/src/runtime/office/authoring/docx-html-measure.mjs +60 -0
  251. package/src/runtime/office/authoring/pdf-author-action.mjs +6 -1
  252. package/src/runtime/office/authoring/pptx-brief.mjs +40 -1
  253. package/src/runtime/office/authoring/pptx-html-build.mjs +1 -1
  254. package/src/runtime/office/authoring/pptx-html-measure.mjs +1 -1
  255. package/src/runtime/office/bench/deck-bench.mjs +1 -1
  256. package/src/runtime/office/com/office-com-host.ps1 +8 -0
  257. package/src/runtime/office/core/office-actions-render.mjs +2 -0
  258. package/src/runtime/office/design/design-art-direction.mjs +10 -2
  259. package/src/runtime/office/design/design-discipline.mjs +4 -5
  260. package/src/runtime/office/design/design-tokens.mjs +20 -1
  261. package/src/runtime/office/design/docx/design-docx/front-matter.mjs +7 -4
  262. package/src/runtime/office/design/docx/design-docx/section.mjs +3 -1
  263. package/src/runtime/office/design/docx/design-docx/writer.mjs +1 -0
  264. package/src/runtime/office/design/docx/design-docx-components.mjs +19 -15
  265. package/src/runtime/office/design/docx/design-docx.mjs +5 -6
  266. package/src/runtime/office/design/docx/document-typography.mjs +20 -6
  267. package/src/runtime/office/design/xlsx/design-xlsx.mjs +9 -2
  268. package/src/runtime/office/pdf/document-preview.mjs +133 -12
  269. package/src/runtime/office/pdf/pdf-writer.mjs +56 -22
  270. package/src/runtime/office/portable/portable-snapshot-docx.mjs +46 -3
  271. package/src/runtime/office/portable/portable-snapshot-shared.mjs +27 -1
  272. package/src/runtime/office/quality/assurance-rendered.mjs +21 -5
  273. package/src/runtime/office/quality/assurance-structure-docx.mjs +41 -9
  274. package/src/runtime/office/quality/design-aesthetics.mjs +4 -2
  275. package/src/runtime/office/quality/design-deck-diversity.mjs +15 -3
  276. package/src/runtime/office/quality/design-review.mjs +13 -5
  277. package/src/runtime/office/quality/document-brief.mjs +8 -2
  278. package/src/runtime/office/quality/forced-break-pages.mjs +203 -0
  279. package/src/runtime/office/quality/pptx-deck-rubric.mjs +21 -3
  280. package/src/runtime/office/quality/quality-pipeline.mjs +14 -17
  281. package/src/runtime/session-search/session-search-db.mjs +183 -0
  282. package/src/runtime/session-search/session-search-ingest.mjs +106 -0
  283. package/src/runtime/shared/agent-route-config.mjs +50 -2
  284. package/src/runtime/shared/bounded-file-read.mjs +166 -0
  285. package/src/runtime/shared/builtin-grandfathering.mjs +37 -0
  286. package/src/runtime/shared/config.mjs +24 -4
  287. package/src/runtime/shared/defaults-separation.mjs +263 -0
  288. package/src/runtime/shared/error-presentation.mjs +8 -1
  289. package/src/runtime/shared/llm/anthropic-effort.mjs +4 -0
  290. package/src/runtime/shared/llm/cost.mjs +4 -2
  291. package/src/runtime/shared/llm/model-catalog-projection.mjs +1 -1
  292. package/src/runtime/shared/llm/model-catalog.mjs +25 -0
  293. package/src/runtime/shared/llm/reasoning-usage.mjs +1 -2
  294. package/src/runtime/shared/llm/usage-accounting.mjs +14 -4
  295. package/src/runtime/shared/llm/usage-context.mjs +11 -1
  296. package/src/runtime/shared/llm/usage-ledger-repair.mjs +3 -1
  297. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +105 -1
  298. package/src/runtime/shared/llm/usage-ledger-worker.mjs +2 -1
  299. package/src/runtime/shared/llm/usage-ledger.mjs +72 -5
  300. package/src/runtime/shared/onnx-runtime-support.mjs +6 -0
  301. package/src/runtime/shared/orchestration.mjs +14 -6
  302. package/src/runtime/shared/pristine-execution-contract.json +7 -2
  303. package/src/runtime/shared/projects.mjs +65 -48
  304. package/src/runtime/shared/provider-accounts.mjs +47 -6
  305. package/src/runtime/shared/quota-resume-store.mjs +255 -0
  306. package/src/runtime/shared/shipped-definitions.mjs +275 -0
  307. package/src/runtime/shared/tool-card-model/agent-surface.mjs +30 -9
  308. package/src/runtime/shared/tool-card-model/aggregate-card.mjs +7 -3
  309. package/src/runtime/shared/tool-card-model/background-task.mjs +17 -1
  310. package/src/runtime/shared/tool-card-model/card-detail.mjs +10 -4
  311. package/src/runtime/shared/tool-card-model/card-header.mjs +10 -4
  312. package/src/runtime/shared/tool-card-model/card-status.mjs +22 -5
  313. package/src/runtime/shared/tool-card-model/displayed-result.mjs +6 -1
  314. package/src/runtime/shared/tool-card-model/media-result.mjs +53 -0
  315. package/src/runtime/shared/tool-card-model/terminal-status.mjs +17 -1
  316. package/src/runtime/shared/tool-card-model.golden-cases.mjs +1 -1
  317. package/src/runtime/shared/tool-card-model.golden.json +75 -66
  318. package/src/runtime/shared/tool-card-model.mjs +1 -0
  319. package/src/runtime/shared/tool-output-limit.mjs +3 -0
  320. package/src/runtime/shared/tool-primitives.mjs +24 -18
  321. package/src/runtime/shared/tool-result-summary.mjs +128 -17
  322. package/src/runtime/shared/tool-status.mjs +20 -7
  323. package/src/runtime/shared/tool-surface.mjs +105 -28
  324. package/src/runtime/shared/tool-work-units.mjs +221 -18
  325. package/src/runtime/shared/transcript-metadata.mjs +2 -0
  326. package/src/runtime/shared/turn-review-reply.mjs +2 -0
  327. package/src/runtime/shared/turn-snapshot.mjs +65 -6
  328. package/src/runtime/shared/turn-worktree-snapshot.mjs +202 -22
  329. package/src/runtime/shared/worker-requests.mjs +14 -2
  330. package/src/runtime/terminal-bridge/client.mjs +311 -0
  331. package/src/runtime/terminal-bridge/tool-defs.mjs +36 -0
  332. package/src/runtime/web-search/lib/ssrf-guard.mjs +12 -56
  333. package/src/runtime/web-search/tool-defs.mjs +2 -0
  334. package/src/session-runtime/boot/apis.mjs +30 -5
  335. package/src/session-runtime/boot/config.mjs +4 -0
  336. package/src/session-runtime/boot/facade.mjs +4 -1
  337. package/src/session-runtime/boot/infrastructure.mjs +21 -2
  338. package/src/session-runtime/boot/session.mjs +5 -5
  339. package/src/session-runtime/boot/tools.mjs +2 -0
  340. package/src/session-runtime/builtin-features.d.mts +1 -0
  341. package/src/session-runtime/channel-config-api.mjs +5 -0
  342. package/src/session-runtime/config-lifecycle/config-writers.mjs +3 -0
  343. package/src/session-runtime/config-lifecycle.mjs +31 -6
  344. package/src/session-runtime/goal-facade-api.mjs +4 -0
  345. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +15 -3
  346. package/src/session-runtime/lifecycle/inheritance.mjs +28 -6
  347. package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +3 -0
  348. package/src/session-runtime/lifecycle/session-switch/resume.mjs +7 -1
  349. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +9 -0
  350. package/src/session-runtime/lifecycle/teardown/session-close.mjs +14 -2
  351. package/src/session-runtime/lifecycle/teardown.mjs +5 -0
  352. package/src/session-runtime/local-provider-settings.mjs +10 -0
  353. package/src/session-runtime/media-api.mjs +32 -22
  354. package/src/session-runtime/model-recency.mjs +14 -0
  355. package/src/session-runtime/model-route/route-persist.mjs +17 -2
  356. package/src/session-runtime/model-route/route-tuning.mjs +16 -5
  357. package/src/session-runtime/model-route/set-route.mjs +55 -22
  358. package/src/session-runtime/model-route/web-search-route.mjs +2 -2
  359. package/src/session-runtime/model-route-api.mjs +2 -1
  360. package/src/session-runtime/notification-bus.mjs +31 -6
  361. package/src/session-runtime/provider-auth/login.mjs +6 -0
  362. package/src/session-runtime/provider-models/catalog-load.mjs +3 -1
  363. package/src/session-runtime/provider-models/row-hydration.mjs +36 -10
  364. package/src/session-runtime/quick-model-rows/model-meta.mjs +26 -0
  365. package/src/session-runtime/quick-model-rows/provider-rows.mjs +40 -14
  366. package/src/session-runtime/resource-api.mjs +8 -1
  367. package/src/session-runtime/route-state.mjs +9 -0
  368. package/src/session-runtime/runtime-core.mjs +4 -0
  369. package/src/session-runtime/runtime-facade.mjs +20 -1
  370. package/src/session-runtime/runtime-feature-gates.mjs +2 -0
  371. package/src/session-runtime/runtime-review-api.mjs +12 -1
  372. package/src/session-runtime/services/agent-tool/helpers.mjs +14 -1
  373. package/src/session-runtime/services/agent-tool/index-write-queue.mjs +10 -15
  374. package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +6 -1
  375. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +20 -2
  376. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +14 -6
  377. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +2 -0
  378. package/src/session-runtime/services/agent-tool/tag-registry.mjs +12 -1
  379. package/src/session-runtime/services/agent-tool/worker-index.mjs +17 -1
  380. package/src/session-runtime/services/agent-tool.mjs +1 -0
  381. package/src/session-runtime/services/channel-admin.mjs +87 -13
  382. package/src/session-runtime/services/provider-admin.mjs +306 -66
  383. package/src/session-runtime/services/seeds.mjs +73 -142
  384. package/src/session-runtime/services/usage-dashboard-model.mjs +29 -0
  385. package/src/session-runtime/services/usage-dashboard.mjs +7 -0
  386. package/src/session-runtime/session-address.mjs +125 -0
  387. package/src/session-runtime/session-create.mjs +57 -2
  388. package/src/session-runtime/settings-api.mjs +1 -0
  389. package/src/session-runtime/settings-builtin-tools-api.mjs +15 -10
  390. package/src/session-runtime/settings-compaction-api.mjs +13 -0
  391. package/src/session-runtime/setup-tool/executor.mjs +93 -40
  392. package/src/session-runtime/setup-tool/extended-actions.mjs +64 -5
  393. package/src/session-runtime/setup-tool/settings-contract.mjs +46 -3
  394. package/src/session-runtime/setup-tool/tool-defs.mjs +14 -6
  395. package/src/session-runtime/tool-surface.mjs +16 -9
  396. package/src/session-runtime/turn/session-ops.mjs +3 -0
  397. package/src/session-runtime/turn/share-ops.mjs +4 -1
  398. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +6 -0
  399. package/src/session-runtime/usage-stats-api.mjs +43 -3
  400. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +31 -5
  401. package/src/session-runtime/workflow-agents-api/agent-route.mjs +6 -2
  402. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +27 -7
  403. package/src/standalone/daemon-boot-coordinator.mjs +10 -0
  404. package/src/standalone/daemon-desktop-runtime.mjs +1 -0
  405. package/src/standalone/daemon-drain-policy.mjs +9 -0
  406. package/src/standalone/daemon-stored-session-views.mjs +7 -8
  407. package/src/standalone/daemon.mjs +36 -8
  408. package/src/standalone/local-session-runtime.mjs +11 -0
  409. package/src/standalone/session-client.mjs +52 -7
  410. package/src/standalone/session-protocol.mjs +9 -0
  411. package/src/standalone/session-service/agent-tree/agent-child.mjs +2 -0
  412. package/src/standalone/session-service/entries/lifecycle.mjs +2 -0
  413. package/src/standalone/session-service/entries/session-loads.mjs +9 -0
  414. package/src/standalone/session-service/projection/revisions.mjs +28 -4
  415. package/src/standalone/session-service/projection.mjs +1 -0
  416. package/src/standalone/session-service/quota-resume.mjs +140 -0
  417. package/src/standalone/session-service/session-calls/session-action.mjs +2 -2
  418. package/src/standalone/session-service/session-calls.mjs +10 -2
  419. package/src/standalone/session-service/stored-reader.mjs +26 -1
  420. package/src/standalone/session-service.mjs +21 -0
  421. package/src/standalone/session-transport/routes.mjs +2 -0
  422. package/src/tui/app/doctor.mjs +7 -11
  423. package/src/tui/app/maintenance-pickers/auto-clear-picker.mjs +3 -5
  424. package/src/tui/app/model-picker/model-footer.mjs +2 -2
  425. package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +21 -2
  426. package/src/tui/app/model-picker/route-selection.mjs +6 -1
  427. package/src/tui/app/settings-picker/settings-rows.mjs +4 -6
  428. package/src/tui/app/settings-picker/settings-toggles/store-toggles.mjs +1 -1
  429. package/src/tui/app/slash-commands.mjs +1 -1
  430. package/src/tui/app/slash-dispatch/route-commands.mjs +5 -3
  431. package/src/tui/app/transcript-row-estimate.mjs +17 -5
  432. package/src/tui/components/ContextPanel.jsx +5 -1
  433. package/src/tui/components/Spinner.jsx +34 -319
  434. package/src/tui/components/SpinnerByline.jsx +256 -0
  435. package/src/tui/components/tool-execution/aggregate-card.jsx +4 -2
  436. package/src/tui/components/tool-execution/text-format.mjs +1 -0
  437. package/src/tui/components/use-spinner-progress.mjs +113 -0
  438. package/src/tui/dist/index.mjs +15896 -14452
  439. package/src/tui/session/agent-job-feed/execution-delivery.mjs +13 -1
  440. package/src/tui/session/agent-job-feed/notification-router.mjs +3 -0
  441. package/src/tui/session/agent-job-feed/pending-resume.mjs +14 -1
  442. package/src/tui/session/agent-job-feed.mjs +4 -0
  443. package/src/tui/session/context-state.mjs +13 -1
  444. package/src/tui/session/initial-state.mjs +6 -0
  445. package/src/tui/session/quota-resume.mjs +263 -0
  446. package/src/tui/session/session-api/intake/abort.mjs +39 -35
  447. package/src/tui/session/session-api/intake/submission.mjs +13 -21
  448. package/src/tui/session/session-api/intake.mjs +3 -3
  449. package/src/tui/session/session-api/integrations.mjs +5 -1
  450. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  451. package/src/tui/session/session-api/lifecycle/inheritance.mjs +2 -2
  452. package/src/tui/session/session-api/lifecycle/session-reset.mjs +4 -0
  453. package/src/tui/session/session-api/lifecycle.mjs +71 -2
  454. package/src/tui/session/session-api/media.mjs +2 -2
  455. package/src/tui/session/session-api/quota-resume.mjs +21 -0
  456. package/src/tui/session/session-api/routes.mjs +5 -2
  457. package/src/tui/session/session-api/settings.mjs +2 -0
  458. package/src/tui/session/session-api.mjs +2 -0
  459. package/src/tui/session/session-flow/auto-clear.mjs +14 -6
  460. package/src/tui/session/session-flow/drain.mjs +52 -5
  461. package/src/tui/session/session-flow/queue/take-entries.mjs +9 -4
  462. package/src/tui/session/session-flow/queue.mjs +4 -0
  463. package/src/tui/session/session-flow/steering.mjs +11 -0
  464. package/src/tui/session/session-flow.mjs +1 -0
  465. package/src/tui/session/tool-approval.mjs +7 -2
  466. package/src/tui/session/transcript-intake.mjs +1 -0
  467. package/src/tui/session/turn-tool-cards.mjs +4 -6
  468. package/src/tui/session/turn.mjs +40 -4
  469. package/src/vendor/statusline/bin/statusline-route.mjs +3 -2
  470. package/src/vendor/statusline/src/gateway/route-meta.mjs +1 -1
  471. package/src/runtime/agent/orchestrator/providers/openai-ws-warmup.mjs +0 -165
@@ -4,9 +4,29 @@ import { mergeStoredProviders } from './config-providers-merge.mjs';
4
4
  import { normalizeExtensionScopes } from '../../shared/extension-scopes.mjs';
5
5
  import { applyConfigPatch, diffConfig } from '../../shared/config-patch.mjs';
6
6
  import { normalizeWorkflowSelection } from '../../shared/orchestration.mjs';
7
- import { DEFAULT_DISABLED_AGENT_IDS, canonicalizeAgentRouteStorage } from '../../shared/agent-route-config.mjs';
7
+ import {
8
+ DEFAULT_DISABLED_AGENT_ROSTER,
9
+ canonicalizeAgentRouteStorage,
10
+ disabledAgentDelta,
11
+ disabledAgentIds,
12
+ effectiveDisabledAgents,
13
+ withEffectiveDisabledAgents,
14
+ withStoredDisabledAgents,
15
+ } from '../../shared/agent-route-config.mjs';
16
+ import {
17
+ DEFAULTS_VERSION,
18
+ ensureDefaultsSeparated,
19
+ storedDefaultsVersion,
20
+ stripAgentSectionDefaults,
21
+ } from '../../shared/defaults-separation.mjs';
8
22
  import profileConfig from '../../shared/profile-config.cjs';
9
- import { DEFAULT_MAINTENANCE, DEFAULT_PRESETS, normalizePreset } from './config-presets.mjs';
23
+ import {
24
+ DEFAULT_MAINTENANCE,
25
+ DEFAULT_PRESETS,
26
+ normalizePreset,
27
+ stripStoredRouteDefaults,
28
+ withDefaultPresets,
29
+ } from './config-presets.mjs';
10
30
  import {
11
31
  agentConfigStorageNeedsMigration,
12
32
  canonicalizeAgentStorage,
@@ -100,11 +120,10 @@ export function buildDefaultConfig(options = {}) {
100
120
  providers['mixdog-local'] = { enabled: false };
101
121
  return {
102
122
  providers,
103
- // The Maintainer also starts off: background upkeep spends model calls, so
104
- // it runs only once the user turns it on and picks its model.
105
- disabledAgents: [...DEFAULT_DISABLED_AGENT_IDS, 'maintainer'],
123
+ // Effective roster; the file stores only the user's delta against it.
124
+ disabledAgents: [...DEFAULT_DISABLED_AGENT_ROSTER],
106
125
  workflow: { active: 'default' },
107
- orchestrationMode: 'none',
126
+ orchestrationMode: 'balanced',
108
127
  };
109
128
  }
110
129
 
@@ -170,9 +189,17 @@ function normalizeRecapConfig(rawRecap) {
170
189
 
171
190
  export function loadConfig(options = {}) {
172
191
  const includeSecrets = options.secrets !== false;
192
+ try {
193
+ ensureDefaultsSeparated({ stripRouteDefaults: separateStoredAgent });
194
+ } catch (err) {
195
+ process.stderr.write(`[config] defaults separation failed: ${err?.message}\n`);
196
+ }
173
197
  const sectionRaw = readSection('agent');
174
198
  if (hasKeys(sectionRaw)) {
175
199
  try {
200
+ // A file that could not be separated still holds the legacy form:
201
+ // before version 1 `disabledAgents` is the full list, not a delta.
202
+ const legacyDisabledAgents = storedDefaultsVersion() < 1;
176
203
  let raw = sectionRaw;
177
204
  const storageNeedsMigration = agentConfigStorageNeedsMigration(raw);
178
205
  raw = canonicalizeAgentStorage(raw);
@@ -206,7 +233,7 @@ export function loadConfig(options = {}) {
206
233
  const loaded = canonicalizeAgentRouteStorage({
207
234
  providers: mergedProviders,
208
235
  mcpServers,
209
- presets: normalizedPresets,
236
+ presets: withDefaultPresets(normalizedPresets),
210
237
  default: raw.default || null,
211
238
  maintenance: { ...DEFAULT_MAINTENANCE, ...normalizedMaint },
212
239
  workflowRoutes,
@@ -214,9 +241,10 @@ export function loadConfig(options = {}) {
214
241
  modelSettings,
215
242
  onboarding: raw.onboarding && typeof raw.onboarding === 'object' ? raw.onboarding : {},
216
243
  agents: raw.agents && typeof raw.agents === 'object' ? raw.agents : {},
217
- // Explicit "off" roster. canonicalizeAgentRouteStorage normalizes
218
- // and drops it when empty, so an all-enabled config stays clean.
219
- disabledAgents: Array.isArray(raw.disabledAgents) ? raw.disabledAgents : [],
244
+ // Effective "off" roster = code defaults + the stored user delta.
245
+ // canonicalizeAgentRouteStorage drops it when empty.
246
+ disabledAgents: legacyDisabledAgents ? disabledAgentIds(raw) : effectiveDisabledAgents(raw),
247
+ ...(raw.memoryTools && typeof raw.memoryTools === 'object' ? { memoryTools: { ...raw.memoryTools } } : {}),
220
248
  ...normalizeWorkflowSelection(raw),
221
249
  profile: normalizeProfileConfig(raw.profile),
222
250
  skills: normalizeSkillsConfig(raw.skills),
@@ -241,7 +269,7 @@ export function loadConfig(options = {}) {
241
269
  // Retired cross-section fields are no longer migrated by
242
270
  // the shared config layer. Normalize only the locked
243
271
  // current section; stale reads must not undo deletions.
244
- persistAgentConfig(canonicalizeAgentStorage);
272
+ persistAgentConfig((current) => storedAgentForm(canonicalizeAgentStorage(current)));
245
273
  } catch (err) {
246
274
  process.stderr.write(`[config] persist canonical agent config failed: ${err?.message}\n`);
247
275
  }
@@ -263,7 +291,7 @@ export function loadConfig(options = {}) {
263
291
  onboarding: {},
264
292
  agents: {},
265
293
  workflow: { active: 'default' },
266
- orchestrationMode: 'none',
294
+ orchestrationMode: 'balanced',
267
295
  profile: normalizeProfileConfig(null),
268
296
  skills: normalizeSkillsConfig(null),
269
297
  extensionScopes: normalizeExtensionScopes(null),
@@ -383,28 +411,81 @@ function buildAgentSaveBuilder(config) {
383
411
  // Developer options (developer-options.mjs); an empty set stays absent.
384
412
  if (Object.keys(developer).length) next.developer = developer;
385
413
  else if (Object.hasOwn(config, 'developer')) delete next.developer;
386
- if (canonicalRoutes.disabledAgents) {
387
- next.disabledAgents = canonicalRoutes.disabledAgents;
388
- } else {
389
- delete next.disabledAgents;
390
- }
414
+ // Only the user's delta against the default roster is stored.
415
+ delete next.disabledAgents;
416
+ delete next.enabledAgents;
417
+ // An unseparated file keeps the legacy full list until the pass succeeds.
418
+ if (storedDefaultsVersion() < 1) {
419
+ if (canonicalRoutes.disabledAgents?.length) next.disabledAgents = canonicalRoutes.disabledAgents;
420
+ } else Object.assign(next, disabledAgentDelta(canonicalRoutes.disabledAgents));
421
+ if (config.memoryTools && typeof config.memoryTools === 'object') next.memoryTools = { ...config.memoryTools };
422
+ else delete next.memoryTools;
391
423
  delete next.workflowRoutes;
392
- return removeRetiredAgentFields(next);
424
+ // Defaults live in code: values equal to the current default are not stored.
425
+ return storedAgentForm(removeRetiredAgentFields(next));
393
426
  };
394
427
  }
428
+
429
+ /** A numeric `default` is a preset index; store the preset id it points at (index into the effective list). */
430
+ function resolveNumericDefault(agent) {
431
+ const value = agent?.default;
432
+ // The loader reads a falsy default (including 0) as "none".
433
+ if (!value || !(typeof value === 'number' || /^\d+$/.test(String(value)))) return agent;
434
+ const stored = (Array.isArray(agent.presets) ? agent.presets : [])
435
+ .map((preset) => normalizePreset(preset))
436
+ .filter(Boolean)
437
+ .filter((preset) => preset.id !== 'workflow-search');
438
+ const { presets } = canonicalizeAgentRouteStorage({ presets: withDefaultPresets(stored) });
439
+ const preset = presets[Number(value)];
440
+ return preset ? { ...agent, default: preset.id } : agent;
441
+ }
442
+
443
+ /** The agent section as stored: defaults dropped. Route defaults go only once the file is separated. */
444
+ function storedAgentForm(agent) {
445
+ const stripped = stripAgentSectionDefaults(resolveNumericDefault(agent));
446
+ return storedDefaultsVersion() >= DEFAULTS_VERSION ? stripStoredRouteDefaults(stripped) : stripped;
447
+ }
448
+
449
+ /** Separation pass: normalize the compared sections first, then drop every default. */
450
+ function separateStoredAgent(agent) {
451
+ const full = canonicalizeAgentStorage(agent);
452
+ const next = { ...agent };
453
+ for (const key of ['autoClear', 'compaction', 'modules']) {
454
+ if (!Object.hasOwn(agent, key)) continue;
455
+ if (full[key] === undefined) delete next[key];
456
+ else next[key] = full[key];
457
+ }
458
+ return stripStoredRouteDefaults(stripAgentSectionDefaults(resolveNumericDefault(next)));
459
+ }
460
+
461
+ /** Patch the stored section; unseparated data keeps its form, a numeric default becomes an id first. */
462
+ function applyStoredPatch(current, changes) {
463
+ const base = resolveNumericDefault(current);
464
+ if (storedDefaultsVersion() >= 1) return applyConfigPatch(base, changes);
465
+ const delta = withStoredDisabledAgents({ ...base, disabledAgents: disabledAgentIds(base) });
466
+ return withEffectiveDisabledAgents(applyConfigPatch(delta, changes));
467
+ }
395
468
  // Diff the persisted schema, not runtime defaults, aliases, or secret overlays.
469
+ // Patches always speak the delta domain; an unseparated file's full list is
470
+ // converted here and back in applyStoredPatch.
471
+ function patchForm(agent) {
472
+ if (storedDefaultsVersion() >= 1) return agent;
473
+ const { disabledAgents, ...rest } = agent;
474
+ return { ...rest, ...disabledAgentDelta(disabledAgents || []) };
475
+ }
476
+
396
477
  export function createConfigPatch(before, after) {
397
- return diffConfig(buildAgentSaveBuilder(before)({}), buildAgentSaveBuilder(after)({}));
478
+ return diffConfig(patchForm(buildAgentSaveBuilder(before)({})), patchForm(buildAgentSaveBuilder(after)({})));
398
479
  }
399
480
 
400
481
  export function saveConfigPatch(changes) {
401
482
  if (!changes.length) return;
402
- persistAgentConfig((current) => applyConfigPatch(current, changes));
483
+ persistAgentConfig((current) => applyStoredPatch(current, changes));
403
484
  }
404
485
 
405
486
  export async function saveConfigPatchAsync(changes) {
406
487
  if (!changes.length) return;
407
- await persistAgentConfigAsync((current) => applyConfigPatch(current, changes));
488
+ await persistAgentConfigAsync((current) => applyStoredPatch(current, changes));
408
489
  }
409
490
 
410
491
  // Whole-section replacement is reserved for explicit full saves. Read/edit/save
@@ -76,7 +76,7 @@ export function buildDeferredToolManifest(entries) {
76
76
  list.sort((a, b) => a.name.localeCompare(b.name));
77
77
  return [
78
78
  '<available-deferred-tools>',
79
- 'Deferred tool names and purposes; schemas load on demand.',
79
+ 'Deferred tool names and selection triggers; schemas load on demand.',
80
80
  ...list.map((entry) => (entry.description ? `- ${entry.name}: ${entry.description}` : `- ${entry.name}`)),
81
81
  '</available-deferred-tools>',
82
82
  ].join('\n');
@@ -156,7 +156,8 @@ function deferredManifestEntries(session, pool) {
156
156
  const descByName = new Map();
157
157
  for (const tool of Array.isArray(session?.deferredToolCatalog) ? session.deferredToolCatalog : []) {
158
158
  const name = String(tool?.name || '').trim();
159
- if (name && !descByName.has(name)) descByName.set(name, String(tool?.description || ''));
159
+ // Skill-style selection trigger when the tool declares one; else its description.
160
+ if (name && !descByName.has(name)) descByName.set(name, String(tool?.trigger || tool?.description || ''));
160
161
  }
161
162
  const skillRoutedNames = skillRoutedToolNames(session.messages);
162
163
  return pool.map((name) => ({
@@ -6,10 +6,11 @@ import {
6
6
  changeProviderAccounts,
7
7
  blockProviderAccount,
8
8
  providerAccountExhausted,
9
+ providerAccountsResetAt,
9
10
  } from '../../../shared/provider-accounts.mjs';
10
11
  import { withProviderAccount, hasExplicitProviderAuthBinding } from '../../../shared/provider-auth-binding.mjs';
11
12
  import { retryAfterMsFromError, isExplicitUserAbortError, typedErrorCode } from './retry-classifier.mjs';
12
- import { fetchOAuthUsageSnapshot } from './oauth-usage.mjs';
13
+ import { fetchOAuthUsageSnapshot, readCachedOAuthUsageSnapshot } from './oauth-usage.mjs';
13
14
 
14
15
  // Only an explicit quota refusal advances the roster; a generic 429, auth
15
16
  // refusal, policy denial or transport failure retains its existing recovery.
@@ -49,7 +50,7 @@ export function resetAccountProbePacing() {
49
50
  async function probeRefusedAccounts(providerName, pool, model, account) {
50
51
  const now = Date.now();
51
52
  const due = pool.accounts
52
- .filter((row) => providerAccountExhausted(row, now, model))
53
+ .filter((row) => providerAccountExhausted(row, now, model, { useCredits: pool.useCredits === true }))
53
54
  .filter((row) => now - (lastProbeAt.get(`${providerName}:${row.id}`) || 0) >= PROBE_INTERVAL_MS)
54
55
  .sort((a, b) => (a.usage?.checkedAt || 0) - (b.usage?.checkedAt || 0));
55
56
  if (!due.length) return false;
@@ -64,12 +65,29 @@ async function probeRefusedAccounts(providerName, pool, model, account) {
64
65
  return true;
65
66
  }
66
67
 
67
- function accountsExhaustedError() {
68
- const error = new Error('All connected accounts have exhausted their quota. Check account usage and reset times.');
68
+ function accountsExhaustedError(useCredits) {
69
+ const error = new Error(
70
+ useCredits
71
+ ? 'All connected accounts have exhausted their quota. Check account usage and reset times.'
72
+ : 'The plan limit is reached and credit use is off. Turn on credit use or wait for the limit to reset.'
73
+ );
69
74
  error.code = 'provider_accounts_exhausted';
70
75
  return error;
71
76
  }
72
77
 
78
+ // Structured proof that the send ended because no account can serve `model`
79
+ // (not merely because a generic 429 or a stopped loop surfaced an error).
80
+ function quotaExhausted(error, providerName, model, rows, options = {}) {
81
+ if (error && typeof error === 'object') {
82
+ error.quotaExhausted = {
83
+ provider: providerName,
84
+ model: String(model || ''),
85
+ resetAt: providerAccountsResetAt(rows, Date.now(), model, options),
86
+ };
87
+ }
88
+ return error;
89
+ }
90
+
73
91
  // The send bound to one account: output callbacks are observed even when the
74
92
  // caller does not subscribe, and account-bound connection/delta state stays
75
93
  // apart without changing the visible Mixdog session, so no stale server state
@@ -114,18 +132,22 @@ function commitFallbackAccount(providerName, pool, row) {
114
132
  async function accountQuotaExhausted(providerName, row, model, error, account) {
115
133
  const status = Number(error?.status || error?.httpStatus || error?.response?.status || 0);
116
134
  const delay = retryAfterMsFromError(error);
117
- let exhausted = isAccountQuotaError(error) || (status === 429 && delay > QUOTA_WINDOW_RETRY_AFTER_MS);
118
- if (!exhausted && status === 429) {
135
+ const typed = isAccountQuotaError(error);
136
+ let exhausted = typed || (status === 429 && delay > QUOTA_WINDOW_RETRY_AFTER_MS);
137
+ // Proof of a spent quota: a typed quota refusal or an exhausted usage window
138
+ // (a long Retry-After alone only rotates the roster, it proves nothing).
139
+ let evidence = typed;
140
+ if (!typed && status === 429) {
119
141
  await fetchOAuthUsageSnapshot({ provider: providerName, accountId: row.id }, account(row.id), () => {}, {
120
142
  force: true,
121
143
  });
122
- exhausted = providerAccountExhausted(
123
- readProviderAccountPool(providerName).accounts.find((entry) => entry.id === row.id),
124
- Date.now(),
125
- model
126
- );
144
+ const pool = readProviderAccountPool(providerName);
145
+ const entry = pool.accounts.find((item) => item.id === row.id);
146
+ const options = { useCredits: pool.useCredits === true };
147
+ evidence = providerAccountExhausted({ ...entry, blockedUntil: 0 }, Date.now(), model, options);
148
+ exhausted = exhausted || evidence || providerAccountExhausted(entry, Date.now(), model, options);
127
149
  }
128
- return { exhausted, delay };
150
+ return { exhausted, delay, evidence };
129
151
  }
130
152
 
131
153
  // The pool's send: walks the eligible accounts until one answers, blocking
@@ -135,10 +157,43 @@ function poolSend(providerName, account) {
135
157
  const attempted = new Set();
136
158
  let lastError;
137
159
  let probed = false;
160
+ const evidenced = new Set();
161
+ // Mark `error` only when every account in `ids` (default: the roster) is
162
+ // exhausted with quota evidence: observed in this send, or a full window.
163
+ const markExhausted = (error, ids) => {
164
+ const pool = readProviderAccountPool(providerName);
165
+ // Auto switching off: the eligible set is the selected account alone.
166
+ const scope = ids || (pool.auto === false ? [pool.selectedId] : null);
167
+ const rows = scope ? pool.accounts.filter((entry) => scope.includes(entry.id)) : pool.accounts;
168
+ const opts = { useCredits: pool.useCredits === true };
169
+ const now = Date.now();
170
+ const all =
171
+ rows.length > 0 &&
172
+ rows.every((entry) =>
173
+ providerAccountExhausted(
174
+ evidenced.has(entry.id) || entry.blockedQuota === true ? entry : { ...entry, blockedUntil: 0 },
175
+ now,
176
+ model,
177
+ opts
178
+ )
179
+ );
180
+ return all ? quotaExhausted(error, providerName, model, rows, opts) : error;
181
+ };
138
182
  while (attempted.size < 20) {
139
183
  options.signal?.throwIfAborted();
140
184
  const pool = readProviderAccountPool(providerName);
141
- if (!pool.accounts.length) return account('default').send(messages, model, tools, options);
185
+ if (!pool.accounts.length) {
186
+ if (pool.useCredits !== true) {
187
+ const stored = readCachedOAuthUsageSnapshot({ provider: providerName, model: '' });
188
+ if (stored?.quotaWindows?.length) {
189
+ const row = { usage: { windows: stored.quotaWindows, checkedAt: stored.cachedAt } };
190
+ if (providerAccountExhausted(row, Date.now(), model)) {
191
+ throw quotaExhausted(accountsExhaustedError(false), providerName, model, [row]);
192
+ }
193
+ }
194
+ }
195
+ return account('default').send(messages, model, tools, options);
196
+ }
142
197
  const row = chooseProviderAccount(pool, attempted, Date.now(), model);
143
198
  if (!row) {
144
199
  // Once per send: a refusal built on a stale meter must not outlive the
@@ -148,8 +203,7 @@ function poolSend(providerName, account) {
148
203
  probed = true;
149
204
  if (await probeRefusedAccounts(providerName, pool, model, account)) continue;
150
205
  }
151
- if (lastError) throw lastError;
152
- throw accountsExhaustedError();
206
+ throw markExhausted(lastError || accountsExhaustedError(pool.useCredits === true));
153
207
  }
154
208
  attempted.add(row.id);
155
209
  const bound = boundAccountSend(providerName, row, messages, options);
@@ -174,28 +228,38 @@ function poolSend(providerName, account) {
174
228
  return result;
175
229
  } catch (error) {
176
230
  if (options.signal?.aborted) throw error;
177
- const { exhausted, delay } = await accountQuotaExhausted(providerName, row, model, error, account);
231
+ if (error?.reauthRequired === true) {
232
+ if (
233
+ pool.auto === false ||
234
+ bound.emitted() ||
235
+ error.unsafeToRetry ||
236
+ error.liveTextEmitted ||
237
+ error.emittedToolCall
238
+ )
239
+ throw error;
240
+ lastError = error;
241
+ options.onStageChange?.('reconnecting', { message: 'Sign-in expired — switching to the next account' });
242
+ continue;
243
+ }
244
+ const { exhausted, delay, evidence } = await accountQuotaExhausted(providerName, row, model, error, account);
178
245
  if (options.signal?.aborted || !exhausted) throw error;
246
+ if (evidence) evidenced.add(row.id);
179
247
  blockProviderAccount(
180
248
  providerName,
181
249
  row.id,
182
250
  Date.now() + (delay > 0 ? delay : 5 * 60_000),
183
251
  model,
184
- delay > 0 ? 'retry-after' : 'inferred'
252
+ delay > 0 ? 'retry-after' : 'inferred',
253
+ { quota: evidence === true }
185
254
  );
186
- if (
187
- pool.auto === false ||
188
- bound.emitted() ||
189
- error.unsafeToRetry ||
190
- error.liveTextEmitted ||
191
- error.emittedToolCall
192
- )
193
- throw error;
255
+ if (bound.emitted() || error.unsafeToRetry || error.liveTextEmitted || error.emittedToolCall) throw error;
256
+ // Auto switching off: the eligible set is the selected account alone.
257
+ if (pool.auto === false) throw markExhausted(error, [row.id]);
194
258
  lastError = error;
195
259
  options.onStageChange?.('reconnecting', { message: 'Quota exhausted — switching to the next account' });
196
260
  }
197
261
  }
198
- throw lastError || new Error('Provider account attempts exhausted.');
262
+ throw markExhausted(lastError || new Error('Provider account attempts exhausted.'));
199
263
  };
200
264
  }
201
265
 
@@ -14,6 +14,7 @@ import { buildAnthropicBetaHeaders, supportsAnthropicFastMode } from './anthropi
14
14
  import { applyAnthropicServerFallback } from './anthropic-server-fallback.mjs';
15
15
  import { fastModeAvailable } from './anthropic-fast-mode.mjs';
16
16
  import { applyAnthropicEffortToBody, shouldIncludeEffortBeta } from './anthropic-effort.mjs';
17
+ import { isCustomProviderName, resolveCustomReasoning } from './custom-reasoning.mjs';
17
18
  import {
18
19
  applyAnthropicCacheMarkers,
19
20
  clampAnthropicThinkingBudget as clampThinkingBudgetTokens,
@@ -44,7 +45,20 @@ import {
44
45
  * @param {boolean} deps.fastModeLatched the provider's sticky fast-mode beta latch
45
46
  * @returns {Promise<{ params: object, requestHeaders: object|null, knownToolNames: Set<string>, fastModeLatched: boolean }>}
46
47
  */
47
- export async function buildAnthropicApiRequest({ name, config, messages, useModel, tools, opts, fastModeLatched }) {
48
+ export async function buildAnthropicApiRequest({
49
+ name,
50
+ config,
51
+ messages,
52
+ useModel,
53
+ tools,
54
+ opts,
55
+ fastModeLatched,
56
+ modelInfo = null,
57
+ }) {
58
+ // A user-defined provider's reasoning comes from its own model row only:
59
+ // the global by-model-id capability index and the Claude-id ladders are
60
+ // first-party knowledge and must not leak onto (or from) a custom endpoint.
61
+ const isCustom = isCustomProviderName(name);
48
62
  const maxTokens = resolveMaxTokens(useModel);
49
63
  const effortProjection = projectEffortConfiguration(messages, name, useModel, {
50
64
  ...config,
@@ -81,8 +95,10 @@ export async function buildAnthropicApiRequest({ name, config, messages, useMode
81
95
  system: systemBlocks.length ? systemBlocks : undefined,
82
96
  messages: await prepareAnthropicImages(anthropicMessages, { signal: opts.signal }),
83
97
  };
98
+ // Server-side fallback and fast mode are decided from Claude model ids:
99
+ // first-party knowledge, never applied to a custom endpoint.
84
100
  applyAnthropicServerFallback(params, useModel, {
85
- enabled: config?.disableBetaHeaders !== true && opts.serverFallback !== false,
101
+ enabled: !isCustom && config?.disableBetaHeaders !== true && opts.serverFallback !== false,
86
102
  });
87
103
  if (requestTools.length) {
88
104
  // No cache_control on tools — the system BP covers tools via
@@ -105,18 +121,28 @@ export async function buildAnthropicApiRequest({ name, config, messages, useMode
105
121
  .map((t) => (t && typeof t.name === 'string' ? t.name : null))
106
122
  .filter(Boolean)
107
123
  );
108
- applyAnthropicEffortToBody(params, {
109
- model: useModel,
110
- opts: effortProjection ? { ...opts, effort: effortProjection.initialEffort } : opts,
111
- maxTokens,
112
- clampThinkingBudgetTokens,
113
- logTag: name,
114
- progressUpdates: config?.disableBetaHeaders !== true,
115
- });
124
+ if (isCustom) {
125
+ const { fields } = resolveCustomReasoning({
126
+ protocol: 'anthropic',
127
+ model: modelInfo,
128
+ effort: opts.effort ?? config?.reasoningEffort,
129
+ });
130
+ if (fields.thinking) params.thinking = fields.thinking;
131
+ if (fields.output_config) params.output_config = { ...(params.output_config || {}), ...fields.output_config };
132
+ } else {
133
+ applyAnthropicEffortToBody(params, {
134
+ model: useModel,
135
+ opts: effortProjection ? { ...opts, effort: effortProjection.initialEffort } : opts,
136
+ maxTokens,
137
+ clampThinkingBudgetTokens,
138
+ logTag: name,
139
+ progressUpdates: config?.disableBetaHeaders !== true,
140
+ });
141
+ }
116
142
  // Fast mode → speed: "fast" on models Anthropic marks as speed-capable.
117
143
  // Suppressed while the fast capacity pool is cooling down.
118
144
  let fastLatched = fastModeLatched;
119
- if (opts.fast === true && supportsAnthropicFastMode(useModel) && fastModeAvailable()) {
145
+ if (!isCustom && opts.fast === true && supportsAnthropicFastMode(useModel) && fastModeAvailable()) {
120
146
  params.speed = 'fast';
121
147
  fastLatched = true;
122
148
  }
@@ -133,19 +159,23 @@ export async function buildAnthropicApiRequest({ name, config, messages, useMode
133
159
  // too — otherwise opencode-go's anthropic-compatible routing
134
160
  // (disableBetaHeaders:true) would still send beta strings that a
135
161
  // third-party endpoint may reject.
162
+ // A custom endpoint gets no first-party base betas; only those its own
163
+ // request body needs (row-driven effort, deferred tools).
136
164
  let betaHeaders = null;
137
165
  if (!config?.disableBetaHeaders) {
138
166
  const betas = [
139
167
  buildAnthropicBetaHeaders({
168
+ ...(isCustom ? { base: '' } : {}),
140
169
  fastMode: fastLatched,
141
170
  toolSearch: hasDeferredTools,
142
- effort: shouldIncludeEffortBeta(useModel, opts),
171
+ // Custom: the beta follows the resolver's output, not the model id.
172
+ effort: isCustom ? Boolean(params.output_config?.effort) : shouldIncludeEffortBeta(useModel, opts),
143
173
  serverFallback: params.fallbacks === 'default',
144
174
  thinkingDisplayUpdates: params.thinking?.display === 'updates',
145
175
  }),
146
176
  ...(effortProjection ? [EFFORT_CONFIGURATION_BETA] : []),
147
- ];
148
- betaHeaders = { 'anthropic-beta': betas.join(',') };
177
+ ].filter(Boolean);
178
+ if (betas.length) betaHeaders = { 'anthropic-beta': betas.join(',') };
149
179
  }
150
180
  const requestHeaders =
151
181
  betaHeaders || opts.requestHeaders ? { ...(betaHeaders || {}), ...(opts.requestHeaders || {}) } : null;
@@ -310,12 +310,12 @@ export function createAnthropicMidstreamRecovery({
310
310
  throw err;
311
311
  };
312
312
 
313
- // A thrown error carries its partial usage to the send's accounting; an
314
- // attempt replaced by a retry or a non-streaming replay is noted here.
313
+ // Every failed attempt's reported usage is noted once, whatever follows: a
314
+ // retry or replay replaces it, recovery may fail, and an error re-thrown
315
+ // later (this one or an earlier attempt's) is not recorded again.
315
316
  const onStreamError = async (args) => {
316
- const decision = await decideStreamError(args);
317
317
  noteAbandonedUsage(args.err?.partialUsage, args.err?.partialModel);
318
- return decision;
318
+ return decideStreamError(args);
319
319
  };
320
320
 
321
321
  const exhaustedError = () => firstAttemptError || new Error(unreachableMessage);
@@ -8,8 +8,10 @@ import { createNpmVersionSource, maxSemver } from './npm-cli-version.mjs';
8
8
  // requests. This floor ships with Mixdog, while a newer server-advertised
9
9
  // minimum is learned and persisted so future model launches do not require a
10
10
  // source release just to advance the user-agent version.
11
- // Claude Opus 5.5 requires 2.1.280 or newer.
12
- const DEFAULT_CLI_VERSION = '2.1.280';
11
+ // Claude Opus 5.5 requires 2.1.280 or newer. The release workflow raises this
12
+ // to the published CLI version (scripts/sync-client-version-floors.mjs).
13
+ export const DEFAULT_CLI_VERSION = '2.1.296';
14
+ export const CLAUDE_CLI_NPM_PACKAGE = '@anthropic-ai/claude-code';
13
15
 
14
16
  const CACHE_SCHEMA_VERSION = 1;
15
17
  const CACHE_FILE_NAME = 'anthropic-oauth-cli-version.json';
@@ -17,7 +19,7 @@ const VERSION_GATE_PATTERN =
17
19
  /Claude Code\s+(\d{1,4}\.\d{1,4}\.\d{1,6})\s+does not support this model;\s*version\s+(\d{1,4}\.\d{1,4}\.\d{1,6})\s+or newer is required\b/i;
18
20
 
19
21
  // Effective version = max(floor, learned minimum, live @anthropic-ai/claude-code).
20
- const liveCliVersion = createNpmVersionSource('@anthropic-ai/claude-code', { persistKey: 'claude-cli' });
22
+ const liveCliVersion = createNpmVersionSource(CLAUDE_CLI_NPM_PACKAGE, { persistKey: 'claude-cli' });
21
23
 
22
24
  let learnedCliVersion = null;
23
25
  let learnedCliVersionLoaded = false;