mixdog 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (493) hide show
  1. package/package.json +3 -2
  2. package/scripts/build-shipped-history.mjs +115 -33
  3. package/scripts/check-voice-runtime-inputs.mjs +25 -0
  4. package/scripts/gate-local.mjs +183 -63
  5. package/scripts/latest-guard.mjs +21 -9
  6. package/scripts/lib/gate-scheduler.mjs +138 -32
  7. package/scripts/lib/gate-timing-reporter.mjs +16 -0
  8. package/scripts/lib/isolated-test-env.mjs +10 -5
  9. package/scripts/lib/run-node-tests.mjs +91 -66
  10. package/scripts/lib/scoped-temp.d.mts +16 -0
  11. package/scripts/lib/scoped-temp.mjs +124 -0
  12. package/scripts/lib/stale-temp.mjs +44 -0
  13. package/scripts/lib/test-failure-records.mjs +14 -1
  14. package/scripts/lib/test-failure-summary.mjs +16 -4
  15. package/scripts/lib/test-spawn-ledger.mjs +12 -3
  16. package/scripts/post-release-check.mjs +1 -6
  17. package/scripts/pptx-kit-index.mjs +17 -5
  18. package/scripts/suite-health.mjs +115 -24
  19. package/scripts/test-data-dir.mjs +10 -7
  20. package/scripts/test.mjs +9 -14
  21. package/src/agents/advisor/AGENT.md +4 -4
  22. package/src/agents/advisor/agent.json +1 -1
  23. package/src/agents/explore/AGENT.md +22 -0
  24. package/src/agents/explore/agent.json +6 -0
  25. package/src/app.mjs +4 -0
  26. package/src/cli.mjs +7 -0
  27. package/src/defaults/agents.json +7 -0
  28. package/src/defaults/shipped-history.json +23 -2
  29. package/src/defaults/skills/browser-use/SKILL.md +10 -5
  30. package/src/defaults/skills/code-tidy/SKILL.md +71 -102
  31. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
  32. package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
  33. package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
  34. package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
  35. package/src/defaults/skills/computer-use/SKILL.md +16 -4
  36. package/src/defaults/skills/goal-management/SKILL.md +1 -1
  37. package/src/defaults/skills/setup/references/actions.md +12 -6
  38. package/src/defaults/skills/setup/references/surfaces.md +2 -2
  39. package/src/defaults/skills/setup-guide/SKILL.md +5 -2
  40. package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
  41. package/src/defaults/skills/skill-creator/SKILL.md +85 -190
  42. package/src/defaults/skills/skill-creator/references/design.md +70 -162
  43. package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
  44. package/src/defaults/skills/test-suite/SKILL.md +194 -0
  45. package/src/defaults/skills/test-suite/references/case-management.md +51 -0
  46. package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
  47. package/src/defaults/skills/test-suite/references/reliability.md +49 -0
  48. package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
  49. package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
  50. package/src/defaults/skills/visualize/SKILL.md +6 -2
  51. package/src/lib/rules-builder.cjs +35 -42
  52. package/src/output-styles/common.md +2 -2
  53. package/src/output-styles/simple.md +1 -1
  54. package/src/rules/agent/AGENT.md +5 -4
  55. package/src/rules/lead/LEAD.md +12 -7
  56. package/src/rules/shared/10-tool-workflow.md +3 -1
  57. package/src/rules/shared/20-research.md +3 -6
  58. package/src/rules/shared/40-editing.md +1 -0
  59. package/src/rules/shared/45-destructive.md +0 -2
  60. package/src/rules/shared/50-execution.md +2 -0
  61. package/src/rules/shared/60-verification.md +10 -9
  62. package/src/rules/shared/70-delivery.md +8 -9
  63. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
  64. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -1
  65. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +156 -24
  66. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -0
  67. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
  69. package/src/runtime/agent/orchestrator/config.mjs +12 -7
  70. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +8 -8
  71. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +5 -26
  72. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +3 -1
  73. package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
  74. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +122 -12
  75. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -3
  76. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +13 -2
  77. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +152 -58
  78. package/src/runtime/agent/orchestrator/mcp/client.mjs +51 -18
  79. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +88 -54
  80. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +42 -26
  81. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +54 -8
  82. package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
  83. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +37 -31
  84. package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
  85. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
  86. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
  87. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  88. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
  89. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
  90. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +14 -3
  91. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +6 -0
  92. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
  93. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
  94. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
  95. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  96. package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
  97. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
  98. package/src/runtime/agent/orchestrator/providers/cursor.mjs +3 -0
  99. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
  100. package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
  101. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
  102. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
  103. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
  104. package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
  105. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
  106. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
  107. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +248 -41
  108. package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
  109. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
  110. package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
  111. package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
  112. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
  113. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
  114. package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
  115. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
  116. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
  117. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
  118. package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
  119. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
  120. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
  121. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
  122. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
  123. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
  124. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
  125. package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
  126. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
  127. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
  128. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
  129. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
  130. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
  131. package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
  132. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
  133. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +160 -31
  134. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +22 -12
  135. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
  136. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +49 -22
  137. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
  138. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
  139. package/src/runtime/agent/orchestrator/providers/registry.mjs +45 -2
  140. package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
  141. package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
  142. package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
  143. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +567 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +41 -13
  145. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
  146. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -6
  147. package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +7 -3
  148. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  149. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -1
  150. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +14 -5
  151. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
  152. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
  153. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
  154. package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
  155. package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
  156. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +102 -12
  157. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
  158. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
  159. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
  160. package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
  161. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +160 -36
  162. package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
  163. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +164 -23
  164. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +139 -19
  165. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
  166. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
  167. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +100 -22
  168. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
  169. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -6
  170. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +33 -3
  171. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +9 -2
  172. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
  173. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
  174. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +14 -0
  175. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +13 -1
  176. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +23 -4
  177. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +2 -0
  178. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
  179. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +39 -21
  180. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
  181. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +50 -28
  182. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
  183. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
  184. package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +2 -2
  185. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +1 -0
  186. package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +2 -1
  187. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +30 -13
  188. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +63 -6
  189. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +7 -0
  190. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
  191. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +35 -13
  192. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +24 -14
  193. package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
  194. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
  195. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +10 -6
  196. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
  197. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +3 -0
  198. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +56 -29
  199. package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
  200. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +11 -5
  201. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +5 -1
  202. package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +30 -7
  203. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
  204. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
  205. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
  206. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
  207. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +37 -8
  208. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +252 -39
  209. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
  210. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +164 -4
  211. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
  212. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +61 -2
  213. package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
  214. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
  215. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
  216. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
  217. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -1
  218. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +46 -20
  219. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
  220. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +67 -31
  221. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +25 -13
  222. package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
  223. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
  224. package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
  225. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
  226. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
  227. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
  228. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
  229. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
  230. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
  231. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +96 -20
  232. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
  233. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
  234. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
  235. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  236. package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
  237. package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
  238. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
  239. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +103 -13
  240. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
  241. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
  242. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
  243. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +34 -10
  244. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +28 -4
  245. package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
  246. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -2
  247. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  248. package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
  249. package/src/runtime/channels/lib/whisper-port.mjs +29 -11
  250. package/src/runtime/channels/lib/whisper-server.mjs +10 -1
  251. package/src/runtime/computer-bridge/action-schema.mjs +2 -2
  252. package/src/runtime/computer-bridge/core-actions.mjs +2 -2
  253. package/src/runtime/computer-bridge/error-recovery.mjs +5 -4
  254. package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
  255. package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
  256. package/src/runtime/connectors/connector-accounts-mcp.mjs +236 -103
  257. package/src/runtime/connectors/gmail-app-password.mjs +3 -3
  258. package/src/runtime/explore/explorer.mjs +93 -0
  259. package/src/runtime/explore/tool-defs.mjs +35 -0
  260. package/src/runtime/explore/tool.mjs +123 -0
  261. package/src/runtime/local-provider/server-process.mjs +2 -1
  262. package/src/runtime/media/adapters/gemini-video.mjs +4 -1
  263. package/src/runtime/media/adapters/xai-media.mjs +2 -1
  264. package/src/runtime/memory/index.mjs +4 -0
  265. package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
  266. package/src/runtime/memory/lib/embedding-worker.mjs +10 -3
  267. package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
  268. package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
  269. package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
  270. package/src/runtime/office/design/design-art-direction.mjs +29 -27
  271. package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
  272. package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
  273. package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
  274. package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
  275. package/src/runtime/office/quality/assurance-structure-docx.mjs +4 -2
  276. package/src/runtime/office/quality/design-review.mjs +1 -5
  277. package/src/runtime/office/quality/document-brief.mjs +1 -5
  278. package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
  279. package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
  280. package/src/runtime/shared/agent-route-config.mjs +17 -2
  281. package/src/runtime/shared/atomic-file.mjs +103 -2
  282. package/src/runtime/shared/background-tasks.mjs +15 -6
  283. package/src/runtime/shared/bot-owned-work.mjs +56 -0
  284. package/src/runtime/shared/connector-accounts.mjs +5 -5
  285. package/src/runtime/shared/connector-catalog.d.mts +11 -4
  286. package/src/runtime/shared/connector-catalog.mjs +60 -52
  287. package/src/runtime/shared/custom-provider-keys.mjs +20 -0
  288. package/src/runtime/shared/defaults-separation.mjs +1 -4
  289. package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
  290. package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
  291. package/src/runtime/shared/file-has-data.mjs +26 -2
  292. package/src/runtime/shared/file-lock.mjs +13 -15
  293. package/src/runtime/shared/git-launch.d.mts +9 -0
  294. package/src/runtime/shared/git-launch.mjs +213 -0
  295. package/src/runtime/shared/git-runner-worker.mjs +2 -1
  296. package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
  297. package/src/runtime/shared/handoff-artifacts.mjs +18 -8
  298. package/src/runtime/shared/idle-auto-clear-gate.mjs +29 -7
  299. package/src/runtime/shared/llm/cost.mjs +11 -2
  300. package/src/runtime/shared/llm/http-agent.mjs +313 -29
  301. package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
  302. package/src/runtime/shared/llm/model-catalog.mjs +46 -6
  303. package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
  304. package/src/runtime/shared/llm/system-proxy.mjs +452 -0
  305. package/src/runtime/shared/loopback-listener.mjs +25 -2
  306. package/src/runtime/shared/model-route-chain.d.mts +7 -2
  307. package/src/runtime/shared/model-route-chain.mjs +22 -4
  308. package/src/runtime/shared/open-url.mjs +10 -0
  309. package/src/runtime/shared/provider-accounts.mjs +52 -2
  310. package/src/runtime/shared/session-activity-signal.mjs +14 -0
  311. package/src/runtime/shared/session-scratch.mjs +37 -0
  312. package/src/runtime/shared/staged-install-worker.mjs +5 -0
  313. package/src/runtime/shared/staged-update.mjs +47 -2
  314. package/src/runtime/shared/tool-card-model/agent-surface.mjs +1 -3
  315. package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
  316. package/src/runtime/shared/tool-result-summary.mjs +1 -1
  317. package/src/runtime/shared/tool-surface.mjs +113 -36
  318. package/src/runtime/shared/tool-work-units.mjs +6 -0
  319. package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
  320. package/src/runtime/shared/turn-worktree-snapshot.mjs +414 -54
  321. package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
  322. package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
  323. package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
  324. package/src/runtime/shared/worktrees/branch-management.mjs +9 -3
  325. package/src/runtime/shared/worktrees/contract.mjs +4 -1
  326. package/src/runtime/shared/worktrees/git.mjs +72 -0
  327. package/src/runtime/shared/worktrees/manager.mjs +285 -168
  328. package/src/runtime/shared/worktrees/test-support.mjs +6 -10
  329. package/src/runtime/tidy/install.mjs +95 -15
  330. package/src/runtime/tidy/languages.mjs +17 -15
  331. package/src/runtime/tidy/process.mjs +7 -4
  332. package/src/runtime/tidy/resolve.mjs +19 -16
  333. package/src/runtime/tidy/runners/biome.mjs +3 -3
  334. package/src/runtime/tidy/tool.mjs +1 -1
  335. package/src/runtime/tidy/worktree.mjs +10 -6
  336. package/src/runtime/visualize-bridge/client.mjs +6 -1
  337. package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
  338. package/src/runtime/web-search/index.mjs +1 -1
  339. package/src/session-runtime/agent-home-delivery.mjs +41 -0
  340. package/src/session-runtime/agent-task-sessions.mjs +458 -312
  341. package/src/session-runtime/agent-tool-routing.mjs +8 -41
  342. package/src/session-runtime/boot/tools.mjs +7 -1
  343. package/src/session-runtime/bot-status.mjs +107 -101
  344. package/src/session-runtime/bot-target.mjs +38 -0
  345. package/src/session-runtime/channel-config-api.mjs +6 -1
  346. package/src/session-runtime/connector-merge-migration.mjs +18 -15
  347. package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
  348. package/src/session-runtime/conversation-import/discovery.mjs +401 -36
  349. package/src/session-runtime/conversation-import/service.mjs +35 -8
  350. package/src/session-runtime/handoff-attachments.mjs +82 -31
  351. package/src/session-runtime/held-requests.mjs +3 -1
  352. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +12 -13
  353. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +1 -0
  354. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -0
  355. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
  356. package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
  357. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +145 -112
  358. package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
  359. package/src/session-runtime/lifecycle/session-catalog.mjs +9 -1
  360. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -1
  361. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  362. package/src/session-runtime/mcp-glue/server-catalog.mjs +16 -10
  363. package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
  364. package/src/session-runtime/mixy-heartbeat.mjs +1 -1
  365. package/src/session-runtime/model-route/set-route.mjs +11 -2
  366. package/src/session-runtime/provider-auth/login.mjs +2 -2
  367. package/src/session-runtime/provider-catalog-cache.mjs +82 -36
  368. package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
  369. package/src/session-runtime/provider-models.mjs +4 -2
  370. package/src/session-runtime/resource-mcp-api.mjs +98 -35
  371. package/src/session-runtime/resource-mcp-connector-accounts.mjs +44 -31
  372. package/src/session-runtime/resource-mcp-secrets.mjs +28 -11
  373. package/src/session-runtime/resource-mcp-servers.mjs +5 -4
  374. package/src/session-runtime/resource-recall-api.mjs +6 -1
  375. package/src/session-runtime/runtime-feature-gates.mjs +5 -1
  376. package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
  377. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
  378. package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
  379. package/src/session-runtime/services/agent-tool/render.mjs +71 -17
  380. package/src/session-runtime/services/agent-tool/send-flow.mjs +10 -2
  381. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
  382. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +4 -1
  383. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +6 -2
  384. package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
  385. package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
  386. package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
  387. package/src/session-runtime/services/daemon-candidate.mjs +4 -1
  388. package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
  389. package/src/session-runtime/services/plugin-admin.mjs +10 -6
  390. package/src/session-runtime/services/provider-admin.mjs +283 -11
  391. package/src/session-runtime/session-turn-api.mjs +2 -0
  392. package/src/session-runtime/settings-builtin-tools-api.mjs +4 -1
  393. package/src/session-runtime/settings-system-api.mjs +1 -1
  394. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
  395. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
  396. package/src/session-runtime/setup-tool/executor.mjs +6 -2
  397. package/src/session-runtime/setup-tool/tool-defs.mjs +2 -1
  398. package/src/session-runtime/tool-policy/policy-stage.mjs +1 -0
  399. package/src/session-runtime/turn/agent-ops.mjs +23 -0
  400. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +49 -11
  401. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
  402. package/src/session-runtime/workflow-agents-api/agent-route.mjs +25 -5
  403. package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
  404. package/src/session-runtime/workspace/activity-guards.mjs +176 -0
  405. package/src/session-runtime/workspace/session-view.mjs +149 -0
  406. package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
  407. package/src/session-runtime/workspace/transition-runner.mjs +188 -0
  408. package/src/session-runtime/workspace/transitions.mjs +108 -1041
  409. package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
  410. package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
  411. package/src/session-runtime/workspace/worktree-maintenance.mjs +80 -0
  412. package/src/session-runtime/workspace/worktree-setup.mjs +85 -0
  413. package/src/session-runtime/workspace/worktree-tool.mjs +73 -56
  414. package/src/standalone/daemon-desktop-runtime.mjs +2 -0
  415. package/src/standalone/daemon-session-control.mjs +169 -138
  416. package/src/standalone/daemon.mjs +7 -0
  417. package/src/standalone/desktop-service-registry.mjs +9 -0
  418. package/src/standalone/local-session-runtime.mjs +5 -1
  419. package/src/standalone/session-client/daemon-unavailable.mjs +3 -0
  420. package/src/standalone/session-client.mjs +5 -1
  421. package/src/standalone/session-frame-stream.mjs +83 -11
  422. package/src/standalone/session-protocol.mjs +4 -0
  423. package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
  424. package/src/standalone/session-service/agent-tree.mjs +45 -9
  425. package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
  426. package/src/standalone/session-service/session-calls/session-action.mjs +10 -3
  427. package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
  428. package/src/standalone/session-service/stored-reader.mjs +127 -40
  429. package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
  430. package/src/tui/App.jsx +154 -164
  431. package/src/tui/app/app-view/floating-panel.jsx +10 -4
  432. package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
  433. package/src/tui/app/clipboard.mjs +21 -10
  434. package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
  435. package/src/tui/app/model-picker/route-selection.mjs +5 -6
  436. package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
  437. package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
  438. package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
  439. package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
  440. package/src/tui/app/provider-setup/oauth-actions.mjs +58 -21
  441. package/src/tui/app/provider-setup/provider-items.mjs +8 -2
  442. package/src/tui/app/provider-setup-picker.mjs +29 -18
  443. package/src/tui/app/shell-layout/row-budgets.mjs +12 -10
  444. package/src/tui/app/slash-commands.mjs +1 -0
  445. package/src/tui/app/slash-dispatch/session-commands.mjs +46 -0
  446. package/src/tui/app/slash-dispatch.mjs +1 -1
  447. package/src/tui/app/use-btw-panel.mjs +29 -0
  448. package/src/tui/app/use-context-panel-refresh.mjs +31 -0
  449. package/src/tui/app/use-model-catalog-cache.mjs +13 -10
  450. package/src/tui/app/use-mouse-input.mjs +11 -0
  451. package/src/tui/app/use-onboarding-start.mjs +8 -3
  452. package/src/tui/app/use-panel-transition.mjs +10 -1
  453. package/src/tui/app/use-pasted-buffers.mjs +28 -20
  454. package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
  455. package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
  456. package/src/tui/app/use-prompt-queue-history.mjs +3 -2
  457. package/src/tui/app/use-selection-focus.mjs +11 -2
  458. package/src/tui/app/use-selection-geometry.mjs +18 -9
  459. package/src/tui/app/use-selection-paint.mjs +4 -4
  460. package/src/tui/app/use-selection-stitch.mjs +3 -3
  461. package/src/tui/app/use-slash-palette.mjs +62 -0
  462. package/src/tui/app/use-terminal-chrome.mjs +2 -2
  463. package/src/tui/app/use-transcript-activity.mjs +47 -32
  464. package/src/tui/app/use-transcript-follow.mjs +12 -4
  465. package/src/tui/app/use-transcript-scroll.mjs +46 -17
  466. package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
  467. package/src/tui/app/use-transcript-window/geometry.mjs +19 -5
  468. package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
  469. package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
  470. package/src/tui/app/use-transcript-window.mjs +21 -11
  471. package/src/tui/app/use-tui-ready.mjs +18 -0
  472. package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
  473. package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
  474. package/src/tui/components/Picker.jsx +27 -3
  475. package/src/tui/components/QuestionPanel.jsx +13 -4
  476. package/src/tui/components/SignInUrl.jsx +68 -0
  477. package/src/tui/components/TextEntryPanel.jsx +76 -46
  478. package/src/tui/components/sign-in-url-layout.mjs +24 -0
  479. package/src/tui/dist/index.mjs +1963 -1361
  480. package/src/tui/session/goal-turn-state.mjs +6 -2
  481. package/src/tui/session/session-api/controls.mjs +4 -0
  482. package/src/tui/session/session-api/extensions.mjs +8 -0
  483. package/src/tui/session/session-api/intake/abort.mjs +2 -1
  484. package/src/tui/session/session-api/intake.mjs +2 -0
  485. package/src/tui/session/session-api/integrations.mjs +2 -2
  486. package/src/tui/session/session-api/routes-agent-definitions.mjs +1 -0
  487. package/src/tui/session/session-api/settings.mjs +2 -2
  488. package/src/tui/session/session-flow/queue/take-entries.mjs +11 -0
  489. package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
  490. package/src/tui/session/transcript-spill.mjs +92 -4
  491. package/src/tui/session/transcript-store.mjs +2 -0
  492. package/src/ui/statusline-agents.mjs +1 -3
  493. package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
@@ -22,7 +22,12 @@ import {
22
22
  expiryFromAccessToken,
23
23
  isDefinitiveOAuthFailure,
24
24
  normalizeAccountIdentity,
25
+ oauthBodySummary,
25
26
  oauthCredentialStatus,
27
+ oauthFailureReason,
28
+ oauthPublicError,
29
+ oauthRequestError,
30
+ oauthResponseJson,
26
31
  scrubOAuthSecrets,
27
32
  } from './lib/oauth-token-utils.mjs';
28
33
  import { createOAuthPkce, parseOAuthCodeInput } from './lib/oauth-pkce.mjs';
@@ -271,7 +276,7 @@ export function _scrubTokens(text, secretValues = []) {
271
276
  }
272
277
 
273
278
  function _tokenEndpointError(operation, status, text, secretValues = []) {
274
- const safeDetail = _scrubTokens(text, secretValues).replace(/\s+/g, ' ').trim().slice(0, 500);
279
+ const safeDetail = oauthBodySummary(text, secretValues);
275
280
  const detail = safeDetail ? `: ${safeDetail}` : '';
276
281
  const compatibility =
277
282
  status === 403
@@ -282,7 +287,7 @@ function _tokenEndpointError(operation, status, text, secretValues = []) {
282
287
  ' update Mixdog or set MIXDOG_CLI_VERSION to the installed official Claude Code version;' +
283
288
  ' then retry sign-in via /providers without an intercepting network layer if applicable.'
284
289
  : '';
285
- return new Error(`${operation} ${status}${detail}.${compatibility}`);
290
+ return oauthPublicError(new Error(`${operation} ${status}${detail}.${compatibility}`));
286
291
  }
287
292
 
288
293
  export function isAnthropicOAuthRefreshDisabled() {
@@ -578,21 +583,26 @@ async function exchangeAuthorizationCode({ pkce, code, state, redirectUri, signa
578
583
  const cleanCode = String(code || '').trim();
579
584
  if (!cleanCode) throw new Error('[anthropic-oauth] authorization code is required');
580
585
  const timeoutSignal = AbortSignal.timeout(OAUTH_TOKEN_TIMEOUT_MS);
581
- const tokenRes = await fetch(TOKEN_URL, {
582
- method: 'POST',
583
- headers: tokenEndpointHeaders(),
584
- body: JSON.stringify({
585
- grant_type: 'authorization_code',
586
- code: cleanCode,
587
- redirect_uri: redirectUri,
588
- client_id: CLAUDE_CODE_CLIENT_ID,
589
- code_verifier: pkce.verifier,
590
- state,
591
- }),
592
- redirect: 'error',
593
- signal: signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal,
594
- dispatcher: getLlmDispatcher(),
595
- });
586
+ let tokenRes;
587
+ try {
588
+ tokenRes = await fetch(TOKEN_URL, {
589
+ method: 'POST',
590
+ headers: tokenEndpointHeaders(),
591
+ body: JSON.stringify({
592
+ grant_type: 'authorization_code',
593
+ code: cleanCode,
594
+ redirect_uri: redirectUri,
595
+ client_id: CLAUDE_CODE_CLIENT_ID,
596
+ code_verifier: pkce.verifier,
597
+ state,
598
+ }),
599
+ redirect: 'error',
600
+ signal: signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal,
601
+ dispatcher: getLlmDispatcher(),
602
+ });
603
+ } catch (err) {
604
+ throw oauthRequestError('[anthropic-oauth] token exchange', err);
605
+ }
596
606
  if (!tokenRes.ok) {
597
607
  const text = await tokenRes.text().catch(() => '');
598
608
  throw _tokenEndpointError('[anthropic-oauth] token exchange', tokenRes.status, text, [
@@ -601,7 +611,7 @@ async function exchangeAuthorizationCode({ pkce, code, state, redirectUri, signa
601
611
  state,
602
612
  ]);
603
613
  }
604
- const json = await tokenRes.json();
614
+ const json = await oauthResponseJson(tokenRes, '[anthropic-oauth] token exchange');
605
615
  const accessToken = json?.access_token || json?.accessToken;
606
616
  const refreshToken = json?.refresh_token || json?.refreshToken;
607
617
  if (!accessToken || !refreshToken) {
@@ -727,10 +737,10 @@ export async function beginOAuthLogin({ openBrowserFn = null, openBrowser = true
727
737
  await acceptCode(code, OAUTH_REDIRECT_URI);
728
738
  res.writeHead(200, { 'Content-Type': OAUTH_PAGE_CONTENT_TYPE, Connection: 'close' });
729
739
  res.end(oauthSuccessHtml('Claude'));
730
- } catch {
731
- // The shared exchange reports its error through waitForCallback.
740
+ } catch (err) {
741
+ // The shared exchange also reports its error through waitForCallback.
732
742
  res.writeHead(500, { 'Content-Type': OAUTH_PAGE_CONTENT_TYPE, Connection: 'close' });
733
- res.end(oauthErrorHtml('Claude could not complete the token exchange.'));
743
+ res.end(oauthErrorHtml(oauthFailureReason('Claude could not complete the token exchange.', err)));
734
744
  }
735
745
  });
736
746
  timeout = setTimeout(() => finish(null), OAUTH_LOGIN_TIMEOUT_MS);
@@ -50,7 +50,9 @@ export function anthropicQuotaError(status, headers, bodyText = '') {
50
50
  const detail = bodyText ? `: ${String(bodyText).slice(0, 200)}` : '';
51
51
  const retry = retryAfter ? ` retryAfter=${retryAfter}` : '';
52
52
  const quota = hasQuotaHeaders(headers);
53
- const err = new Error(`Anthropic OAuth API ${status} ${quota ? 'quota/rate limit' : 'request rejected'}${retry}${detail}`);
53
+ const err = new Error(
54
+ `Anthropic OAuth API ${status} ${quota ? 'quota/rate limit' : 'request rejected'}${retry}${detail}`
55
+ );
54
56
  err.name = quota ? 'ProviderQuotaError' : 'ProviderRequestRejectedError';
55
57
  err.headers = headers;
56
58
  err.response = { status, headers };
@@ -8,6 +8,7 @@
8
8
  import { traceAgentSse, traceAgentUsage } from '../agent-trace.mjs';
9
9
  import {
10
10
  anthropicPrefixFingerprint,
11
+ anthropicPrefixSessionId,
11
12
  latestAnthropicPrefix,
12
13
  recordAnthropicPrefix,
13
14
  } from './lib/anthropic-prefix-trace.mjs';
@@ -555,7 +556,7 @@ export class AnthropicOAuthProvider {
555
556
  const body = buildRequestBody(messages, useModel, tools, sendOpts);
556
557
  body.messages = await prepareAnthropicImages(body.messages, { signal: externalSignal });
557
558
  // Diagnostic: per-block prefix hashes of exactly what is sent.
558
- recordAnthropicPrefix(opts.sessionId || null, anthropicPrefixFingerprint(body));
559
+ recordAnthropicPrefix(anthropicPrefixSessionId(opts), anthropicPrefixFingerprint(body));
559
560
  if (body.speed === 'fast') {
560
561
  this.fastModeBetaHeaderLatched = true;
561
562
  }
@@ -652,6 +653,7 @@ export class AnthropicOAuthProvider {
652
653
  iteration,
653
654
  useModel,
654
655
  requestKind: opts.requestKind || null,
656
+ prefixSessionId: anthropicPrefixSessionId(opts),
655
657
  });
656
658
  tagMidstreamRetries(result, attemptIndex);
657
659
  return result;
@@ -887,7 +889,16 @@ export class AnthropicOAuthProvider {
887
889
  }
888
890
 
889
891
  // Traces + catalog upkeep for a streamed turn, then the empty-stream guard.
890
- _settleStreamedTurn({ result, midState, sseStartedAt, sessionId, iteration, useModel, requestKind }) {
892
+ _settleStreamedTurn({
893
+ result,
894
+ midState,
895
+ sseStartedAt,
896
+ sessionId,
897
+ iteration,
898
+ useModel,
899
+ requestKind,
900
+ prefixSessionId,
901
+ }) {
891
902
  const ttftMs = midState.ttftAt ? midState.ttftAt - sseStartedAt : null;
892
903
  const liveModel = result.model || useModel;
893
904
  traceAgentSse({
@@ -912,7 +923,7 @@ export class AnthropicOAuthProvider {
912
923
  rawUsage: result.usage?.raw || null,
913
924
  provider: 'anthropic-oauth',
914
925
  requestKind,
915
- prefixBlocks: latestAnthropicPrefix(sessionId),
926
+ prefixBlocks: latestAnthropicPrefix(prefixSessionId),
916
927
  });
917
928
 
918
929
  // Phase I: if the live response surfaced a model id we don't know
@@ -161,6 +161,12 @@ function applyAnthropicSseEvent(framedEvent, { turn, watchdogs, state, progress,
161
161
  return false;
162
162
  case 'message_delta':
163
163
  return turn.onMessageDelta(event);
164
+ case 'ping':
165
+ // Anthropic bridges long generation gaps (adaptive thinking, a buffered
166
+ // tool input) with `ping` events. A distinct kind, not 'semantic': the
167
+ // agent watchdog decides how far a keepalive may extend liveness.
168
+ progress('keepalive');
169
+ return false;
164
170
  case 'message_stop':
165
171
  turn.onMessageStop();
166
172
  // Anthropic streams can keep emitting `:ping` keepalive frames after
@@ -11,7 +11,7 @@
11
11
  */
12
12
  import { traceAgentUsage } from '../agent-trace.mjs';
13
13
  import { reportedCostUsd } from './lib/usage-primitives.mjs';
14
- import { latestAnthropicPrefix } from './lib/anthropic-prefix-trace.mjs';
14
+ import { anthropicPrefixSessionId, latestAnthropicPrefix } from './lib/anthropic-prefix-trace.mjs';
15
15
 
16
16
  /**
17
17
  * @param {object} parseResult the assembled turn (streaming or normalized non-streaming)
@@ -48,7 +48,7 @@ export function buildAnthropicTurnResult(parseResult, { provider, useModel, opts
48
48
  // Anthropic usage is additive at this inner transport
49
49
  // boundary, even when OpenCode Go supplies the provider id.
50
50
  inputTokensInclusive: false,
51
- prefixBlocks: latestAnthropicPrefix(opts.sessionId || opts.session?.id || null),
51
+ prefixBlocks: latestAnthropicPrefix(anthropicPrefixSessionId(opts)),
52
52
  });
53
53
  }
54
54
 
@@ -266,7 +266,9 @@ export async function exchangeAuthorizationCode({ code, verifier, fetchFn = fetc
266
266
  });
267
267
  if (!res.ok) {
268
268
  const text = await res.text().catch(() => '');
269
- throw new Error(`[antigravity-oauth] token exchange ${res.status}: ${_scrubTokens(text).slice(0, 300)}`);
269
+ // The authorization code is redacted by value: `code` alone is not a secret field.
270
+ const detail = _scrubTokens(text, [cleanCode, verifier]).slice(0, 300);
271
+ throw new Error(`[antigravity-oauth] token exchange ${res.status}: ${detail}`);
270
272
  }
271
273
  const json = await res.json();
272
274
  if (!json?.access_token || !json?.refresh_token) {
@@ -231,8 +231,8 @@ export function saveTokens(tokens) {
231
231
  );
232
232
  }
233
233
 
234
- export function _scrubTokens(text) {
235
- return scrubOAuthSecrets(text);
234
+ export function _scrubTokens(text, secretValues = []) {
235
+ return scrubOAuthSecrets(text, secretValues);
236
236
  }
237
237
 
238
238
  export function hasAntigravityOAuthCredentials() {
@@ -20,7 +20,7 @@ import { createNpmVersionSource, maxSemver } from './npm-cli-version.mjs';
20
20
  // version (gpt-6.1-sol requires >= 0.159.0, measured 2026-10-09), so the
21
21
  // release workflow raises this to the published CLI version on every release
22
22
  // (scripts/sync-client-version-floors.mjs).
23
- export const CODEX_CLIENT_VERSION_FLOOR = '0.164.0';
23
+ export const CODEX_CLIENT_VERSION_FLOOR = '0.165.0';
24
24
  export const CODEX_CLI_NPM_PACKAGE = '@openai/codex';
25
25
  const live = createNpmVersionSource(CODEX_CLI_NPM_PACKAGE, { persistKey: 'codex-cli' });
26
26
 
@@ -3,6 +3,7 @@
3
3
  // A pasted key or pasted callback JSON completes the same login by hand. The
4
4
  // first sign-in on a machine adopts an existing Command Code CLI login instead.
5
5
  import { createServer } from 'node:http';
6
+ import { listenOn } from './lib/listen-on.mjs';
6
7
  import { randomBytes } from 'node:crypto';
7
8
  import { readFileSync } from 'node:fs';
8
9
  import { homedir } from 'node:os';
@@ -95,16 +96,6 @@ function readLocalAuth(path) {
95
96
  }
96
97
  }
97
98
 
98
- function listenOn(server, port, host) {
99
- return new Promise((resolve, reject) => {
100
- server.once('error', reject);
101
- server.listen(port, host, () => {
102
- server.off('error', reject);
103
- resolve();
104
- });
105
- });
106
- }
107
-
108
99
  function readBody(req) {
109
100
  return new Promise((resolve, reject) => {
110
101
  const chunks = [];
@@ -361,7 +361,7 @@ export class CommandCodeOAuthProvider {
361
361
  if (Array.isArray(body?.data)) list = body.data;
362
362
  else if (Array.isArray(body)) list = body;
363
363
  const items = list.filter((item) => modelWire(item));
364
- publish(items.map(rosterRow));
364
+ await publish(items.map(rosterRow));
365
365
  if (this.tokens?.apiKey === apiKey) {
366
366
  // Rows accumulate for one key: a later roster that misses a model
367
367
  // leaves the endpoints it was last listed with.
@@ -677,6 +677,9 @@ class CursorProviderBase {
677
677
  return await consumeCompatChatCompletionStream(responseSseEvents(response, signal), {
678
678
  signal,
679
679
  label: this.name,
680
+ // The wrapper below always exists; the stream joins the session's
681
+ // logical request only when the caller reports progress into it.
682
+ sessionId: typeof sendOpts.onStreamDelta === 'function' ? sendOpts.sessionId : null,
680
683
  onStreamDelta: (delta) => {
681
684
  sendOpts.onStreamDelta?.(delta);
682
685
  },
@@ -12,13 +12,21 @@ export const CUSTOM_REASONING_LEVELS = CUSTOM_EFFORT_LEVELS;
12
12
  export const CUSTOM_REASONING_WIRE_FORMATS = Object.freeze(['standard', 'deepseek', 'together', 'vllm']);
13
13
  export const CUSTOM_PROVIDER_AUTH_MODES = Object.freeze(['key', 'none']);
14
14
  export const CUSTOM_MODEL_OVERRIDE_LIMIT = 500;
15
+ export const CUSTOM_HEADER_LIMIT = 64;
15
16
 
16
17
  const UNSAFE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
17
18
  const MAX_MODEL_ID = 256;
18
19
  const MAX_NAME = 200;
19
20
  const MAX_WIRE_VALUE = 64;
21
+ const MAX_HEADER_TEXT = 4096;
20
22
  // biome-ignore lint/suspicious/noControlCharactersInRegex: rejecting control characters is the point.
21
23
  const CONTROL_CHARS = /[\u0000-\u001f\u007f]/;
24
+ // RFC 9110 field-name token, and a field value of visible ASCII, space, tab and
25
+ // obs-text (what a fetch Headers value can carry).
26
+ const HEADER_NAME = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
27
+ const HEADER_VALUE = /^[\t\x20-\x7e\x80-\xff]*$/;
28
+ // The API key field owns authentication; a header may not carry a credential.
29
+ const AUTH_HEADERS = new Set(['authorization', 'x-api-key', 'api-key']);
22
30
 
23
31
  function fail(message) {
24
32
  throw new Error(`[custom-provider] ${message}`);
@@ -84,6 +92,7 @@ const V2_TOP_LEVEL_KEYS = new Set([
84
92
  'modelOverrides',
85
93
  'wires',
86
94
  'modelWires',
95
+ 'headers',
87
96
  'id',
88
97
  'apiKey',
89
98
  'apiKeyEnv',
@@ -295,6 +304,34 @@ function normalizeModelWires(raw, protocol, wires) {
295
304
  return out;
296
305
  }
297
306
 
307
+ // `headers`: extra HTTP headers sent with every request to the endpoint
308
+ // (inference, model discovery, connection test). Names are case-insensitive
309
+ // tokens; the credential headers belong to the API key field.
310
+ function normalizeHeaders(raw) {
311
+ if (raw === undefined) return {};
312
+ if (!isPlainObject(raw)) fail('headers must be an object of header names to string values');
313
+ const names = Object.keys(raw);
314
+ if (names.length > CUSTOM_HEADER_LIMIT) fail(`at most ${CUSTOM_HEADER_LIMIT} headers are allowed`);
315
+ const seen = new Set();
316
+ const entries = [];
317
+ for (const name of names) {
318
+ if (name.length > MAX_HEADER_TEXT || !HEADER_NAME.test(name))
319
+ fail(`headers has an invalid header name: ${JSON.stringify(name.slice(0, 64))}`);
320
+ const lower = name.toLowerCase();
321
+ if (AUTH_HEADERS.has(lower)) fail(`headers must not set ${name}: authentication belongs to the API key field`);
322
+ if (seen.has(lower)) fail(`headers has duplicate header: ${name}`);
323
+ seen.add(lower);
324
+ if (typeof raw[name] !== 'string') fail(`headers.${name} must be a string`);
325
+ // Validate before trimming, and trim only HTTP whitespace (space, tab), so
326
+ // CR/LF is refused rather than stripped and other characters are kept.
327
+ if (!HEADER_VALUE.test(raw[name])) fail(`headers.${name} has an invalid value`);
328
+ const value = raw[name].replace(/^[ \t]+|[ \t]+$/g, '');
329
+ if (value.length > MAX_HEADER_TEXT) fail(`headers.${name} has an invalid value`);
330
+ entries.push([name, value]);
331
+ }
332
+ return Object.fromEntries(entries);
333
+ }
334
+
298
335
  // Legacy (pre-v2) `models: [{ id, name?, contextWindow?, maxOutputTokens? }]`
299
336
  // become manual, visible overrides; their presence hides newly discovered ids.
300
337
  function migrateLegacy(input) {
@@ -336,6 +373,7 @@ export function normalizeCustomProviderConfig(input) {
336
373
  fail('modelOverrides and discovery require schemaVersion 2');
337
374
  if (input.wires !== undefined || input.modelWires !== undefined)
338
375
  fail('wires and modelWires require schemaVersion 2');
376
+ if (input.headers !== undefined) fail('headers require schemaVersion 2');
339
377
  source = migrateLegacy(input);
340
378
  } else if (Number.isInteger(version) && version > CUSTOM_PROVIDER_SCHEMA_VERSION)
341
379
  fail(`unsupported schemaVersion ${version}; update mixdog to use this provider`);
@@ -368,6 +406,7 @@ export function normalizeCustomProviderConfig(input) {
368
406
  const newModelsHidden = optionalBoolean(discovery.newModelsHidden, 'discovery.newModelsHidden') ?? false;
369
407
  const wires = normalizeWires(source.wires, protocol);
370
408
  const modelWires = normalizeModelWires(source.modelWires, protocol, wires);
409
+ const headers = normalizeHeaders(source.headers);
371
410
  return {
372
411
  type: 'custom',
373
412
  schemaVersion: CUSTOM_PROVIDER_SCHEMA_VERSION,
@@ -377,6 +416,7 @@ export function normalizeCustomProviderConfig(input) {
377
416
  enabled: source.enabled !== false,
378
417
  auth,
379
418
  ...(apiKeyEnv && auth === 'key' ? { apiKeyEnv } : {}),
419
+ ...(Object.keys(headers).length ? { headers } : {}),
380
420
  discovery: { newModelsHidden },
381
421
  modelOverrides: normalizeOverrides(source.modelOverrides, protocol, legacy),
382
422
  ...(wires ? { wires } : {}),
@@ -0,0 +1,34 @@
1
+ // The engine a custom provider sends with when one of its additional API keys
2
+ // serves (account-pool.mjs `createCustomKeyPoolProvider`). Every key reaches
3
+ // the same endpoint, so the engine is a view of the primary instance: the
4
+ // catalog, discovered models, wire routes and settings stay the primary's,
5
+ // and only the credential and the client built from it are the key's own.
6
+
7
+ import { readCustomProviderKey } from '../../../shared/custom-provider-keys.mjs';
8
+
9
+ function keyView(engine, providerId, keyId, key) {
10
+ const view = Object.create(engine);
11
+ const rekey = (value) => {
12
+ // The key is the only source: an environment variable names the primary key alone.
13
+ view.config = { ...engine.config, apiKey: value, apiKeyEnv: undefined };
14
+ view.apiKey = value;
15
+ view.client = view._createClient(value);
16
+ };
17
+ rekey(key);
18
+ // An auth retry re-reads this key, never the primary's keychain entry.
19
+ view.reloadApiKey = () => {
20
+ const fresh = readCustomProviderKey(providerId, keyId);
21
+ if (fresh) rekey(fresh);
22
+ };
23
+ return view;
24
+ }
25
+
26
+ /** `primary` sending with additional key `keyId` of custom provider `providerId`. */
27
+ export function customKeyEngine(primary, providerId, keyId) {
28
+ const key = readCustomProviderKey(providerId, keyId);
29
+ if (!key) throw new Error(`An additional API key of ${providerId} is not readable; enter it again in its settings.`);
30
+ const engine = keyView(primary, providerId, keyId, key);
31
+ // A Messages-wire route sends through the bound Anthropic engine.
32
+ if (primary.messagesEngine) engine.messagesEngine = keyView(primary.messagesEngine, providerId, keyId, key);
33
+ return engine;
34
+ }
@@ -120,6 +120,7 @@ async function discoverAnthropicModels(provider, signal, timeoutMs = DISCOVERY_T
120
120
  headers: {
121
121
  ...(provider._customKeyless ? {} : { 'x-api-key': provider._customKey() }),
122
122
  'anthropic-version': ANTHROPIC_VERSION,
123
+ ...(provider.config.extraHeaders || {}),
123
124
  },
124
125
  });
125
126
  if (!res.ok) throw Object.assign(new Error(`${provider.name} models ${res.status}`), { status: res.status });
@@ -153,6 +154,8 @@ export async function createCustomProvider(id, config) {
153
154
  apiKey: apiKey || undefined,
154
155
  ...(cfg.apiKeyEnv ? { apiKeyEnv: cfg.apiKeyEnv } : {}),
155
156
  ...(keyless ? { keyless: true } : {}),
157
+ // User-defined headers ride the engines' existing `extraHeaders` path.
158
+ ...(cfg.headers ? { extraHeaders: cfg.headers } : {}),
156
159
  ...(config.preconnect === false ? { preconnect: false } : {}),
157
160
  };
158
161
  let provider;
@@ -14,6 +14,10 @@ import {
14
14
  decodeJwtPayload,
15
15
  expiryFromAccessToken,
16
16
  normalizeAccountIdentity,
17
+ OAUTH_NETWORK_HINT,
18
+ oauthFailureReason,
19
+ oauthNetworkCause,
20
+ oauthPublicError,
17
21
  } from './lib/oauth-token-utils.mjs';
18
22
 
19
23
  const AUTHORIZE_URL = 'https://app.devin.ai/auth/cli/continue';
@@ -46,9 +50,11 @@ export const DEVIN_OAUTH_FAILURE_CODES = Object.freeze([
46
50
  'DEVIN_OAUTH_TOKEN_EXCHANGE_FAILED',
47
51
  ]);
48
52
 
53
+ // Built from fixed text, statuses and error codes only, so a failure page may
54
+ // show it; response bodies are never quoted (they may carry the login token).
49
55
  function loginFailure(code, text, props = {}) {
50
56
  const failureCode = `DEVIN_OAUTH_${code}`;
51
- return Object.assign(new Error(`${failureCode}: ${text}`), { failureCode }, props);
57
+ return oauthPublicError(Object.assign(new Error(`${failureCode}: ${text}`), { failureCode }, props));
52
58
  }
53
59
 
54
60
  function credentialsPath() {
@@ -175,12 +181,13 @@ export async function exchangeDevinCode(code, verifier, { fetchFn = fetch, signa
175
181
  });
176
182
  } catch (error) {
177
183
  // A cancelled login keeps its own abort; any other failure to get an
178
- // answer (network, timeout) is a coded exchange failure. The cause is not
179
- // quoted: only its kind is.
184
+ // answer (network, timeout) is a coded exchange failure. Its message is
185
+ // not quoted: only its error code.
180
186
  if (signal?.aborted) throw error;
187
+ const cause = oauthNetworkCause(error) || 'network error';
181
188
  throw loginFailure(
182
189
  'TOKEN_EXCHANGE_FAILED',
183
- error?.name === 'TimeoutError' ? 'Devin token exchange timed out' : 'Devin token exchange request failed'
190
+ `Devin token exchange request failed (${cause}). ${OAUTH_NETWORK_HINT}`
184
191
  );
185
192
  }
186
193
  // Response bodies may carry the login token itself, so none is ever quoted
@@ -341,9 +348,9 @@ async function startDevinOAuthLogin({ openBrowser = true, timeoutMs = LOGIN_TIME
341
348
  try {
342
349
  await acceptCode(code);
343
350
  reply(res, 200, oauthSuccessHtml('Devin'));
344
- } catch {
345
- // The shared exchange reports its error through waitForCallback.
346
- reply(res, 500, oauthErrorHtml('Devin could not complete the token exchange.'));
351
+ } catch (error) {
352
+ // The shared exchange also reports its error through waitForCallback.
353
+ reply(res, 500, oauthErrorHtml(oauthFailureReason('Devin could not complete the token exchange.', error)));
347
354
  }
348
355
  };
349
356
 
@@ -190,10 +190,11 @@ function connectError(
190
190
  const finalCode = tooLarge ? 'request_too_large' : mixdogCode;
191
191
  const head = `Devin ${operation} ${code || 'error'}${status ? ` (HTTP ${status})` : ''}`;
192
192
  const text = [head, detail].filter(Boolean).join(': ') + (detailsSummary ? ` [details: ${detailsSummary}]` : '');
193
+ // A reworded throttle reports its throttle status, not the carrier's.
194
+ const carrierStatus = reworded ? mappedStatus : status || mappedStatus;
193
195
  const error = new DevinWireError(text, {
194
196
  code: finalCode,
195
- // A reworded throttle reports its throttle status, not the carrier's.
196
- status: tooLarge ? 413 : (reworded ? mappedStatus : status || mappedStatus),
197
+ status: tooLarge ? 413 : carrierStatus,
197
198
  retryable: tooLarge ? false : retryable,
198
199
  connectCode: code,
199
200
  detail: [detail, detailsSummary].filter(Boolean).join(' '),
@@ -405,6 +405,9 @@ export class DevinOAuthProvider {
405
405
  signal,
406
406
  label: this.name,
407
407
  providerName: this.name,
408
+ // The wrapper below always exists; the stream joins the session's
409
+ // logical request only when the caller reports progress into it.
410
+ sessionId: typeof sendOpts.onStreamDelta === 'function' ? sendOpts.sessionId : null,
408
411
  onStreamDelta: (delta) => {
409
412
  if (!streaming) {
410
413
  streaming = true;
@@ -115,7 +115,7 @@ export function geminiFailureUsage(opts, cachedContent, useModel) {
115
115
  };
116
116
  }
117
117
 
118
- export function resolveGeminiUsage(response, opts, cachedContent, useModel) {
118
+ export function resolveGeminiUsage(response, opts, cachedContent, useModel, provider = 'gemini') {
119
119
  const um = response.usageMetadata || null;
120
120
  if (!um) return null;
121
121
  const iteration = Number.isFinite(Number(opts.iteration)) ? Number(opts.iteration) : null;
@@ -143,7 +143,7 @@ export function resolveGeminiUsage(response, opts, cachedContent, useModel) {
143
143
  model: useModel,
144
144
  modelDisplay: useModel,
145
145
  rawUsage: um,
146
- provider: 'gemini',
146
+ provider,
147
147
  });
148
148
  return resolvedUsage;
149
149
  }
@@ -589,6 +589,9 @@ export async function consumeGeminiRestStreamResponse(
589
589
  onChunk = null,
590
590
  failureUsage = null,
591
591
  firstByteTimeoutMs = GEMINI_FIRST_BYTE_TIMEOUT_MS,
592
+ // A first-byte window longer than the idle window must govern alone until
593
+ // the first payload, or the idle timer would cut the wait short.
594
+ idleAfterFirstChunk = false,
592
595
  }
593
596
  ) {
594
597
  const unwrap =
@@ -649,7 +652,7 @@ export async function consumeGeminiRestStreamResponse(
649
652
  }
650
653
 
651
654
  try {
652
- watchdogs.resetIdle();
655
+ if (!idleAfterFirstChunk) watchdogs.resetIdle();
653
656
  while (true) {
654
657
  let chunk;
655
658
  try {