mixdog 1.2.0 → 1.2.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 (386) hide show
  1. package/README.md +7 -5
  2. package/package.json +1 -1
  3. package/scripts/gate-local.mjs +19 -3
  4. package/scripts/model-catalog-audit.mjs +1 -15
  5. package/src/agents/reviewer/AGENT.md +3 -3
  6. package/src/agents/reviewer/agent.json +1 -1
  7. package/src/defaults/shipped-history.json +5 -0
  8. package/src/defaults/skills/pptx/SKILL.md +6 -6
  9. package/src/defaults/skills/pptx/references/review.md +6 -4
  10. package/src/defaults/skills/pptx/scripts/source-extract.mjs +1 -1
  11. package/src/defaults/skills/setup/references/actions.md +13 -3
  12. package/src/defaults/skills/visualize/SKILL.md +12 -9
  13. package/src/repl/slash-commands.mjs +16 -1
  14. package/src/rules/shared/60-verification.md +3 -1
  15. package/src/rules/shared/70-delivery.md +4 -2
  16. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -4
  17. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +10 -0
  18. package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
  19. package/src/runtime/agent/orchestrator/config.mjs +10 -4
  20. package/src/runtime/agent/orchestrator/context/collect.mjs +2 -1
  21. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +11 -5
  22. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +74 -21
  23. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +122 -15
  24. package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +54 -11
  25. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +104 -9
  26. package/src/runtime/agent/orchestrator/mcp/client.mjs +358 -140
  27. package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
  28. package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +103 -0
  29. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +150 -0
  30. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +111 -0
  31. package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +87 -0
  32. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +95 -0
  33. package/src/runtime/agent/orchestrator/mcp/oauth-request.mjs +122 -0
  34. package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +9 -0
  35. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +229 -0
  36. package/src/runtime/agent/orchestrator/mcp/plugin-placeholders.mjs +54 -0
  37. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +294 -44
  38. package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
  39. package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
  40. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +96 -0
  41. package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.mjs +39 -18
  42. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +55 -0
  43. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +25 -21
  44. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +3 -1
  45. package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +18 -4
  46. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +13 -1
  47. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  48. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-midstream.mjs +10 -1
  49. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-recovery.mjs +23 -9
  50. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +46 -20
  51. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request.mjs +14 -9
  52. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +73 -35
  53. package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +69 -0
  54. package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.mjs +4 -0
  55. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +8 -1
  56. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +53 -18
  57. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +30 -9
  58. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +7 -0
  59. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +30 -14
  60. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +2 -1
  61. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +93 -0
  62. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +82 -9
  63. package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +9 -0
  64. package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +337 -0
  65. package/src/runtime/agent/orchestrator/providers/command-code-oauth-tokens.mjs +159 -0
  66. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +447 -0
  67. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +38 -5
  68. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  69. package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +97 -2
  70. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +102 -23
  71. package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
  72. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +29 -6
  73. package/src/runtime/agent/orchestrator/providers/cursor.mjs +18 -1
  74. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
  75. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +86 -19
  76. package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +1 -1
  77. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +29 -8
  78. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +191 -0
  79. package/src/runtime/agent/orchestrator/providers/gemini-family.mjs +9 -0
  80. package/src/runtime/agent/orchestrator/providers/gemini-history-signatures.mjs +9 -4
  81. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +3 -1
  82. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +180 -0
  83. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +21 -82
  84. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +4 -1
  85. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -12
  86. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +21 -20
  87. package/src/runtime/agent/orchestrator/providers/gemini.mjs +97 -51
  88. package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
  89. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +68 -19
  90. package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
  91. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +3 -0
  92. package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +2 -1
  93. package/src/runtime/agent/orchestrator/providers/model-proxy-bridge.mjs +1080 -0
  94. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +15 -0
  95. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +35 -0
  96. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
  97. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +12 -0
  98. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
  99. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +5 -3
  100. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +22 -0
  101. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +1 -0
  102. package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +50 -0
  103. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +6 -2
  104. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +11 -0
  105. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +23 -0
  106. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +16 -8
  107. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
  108. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +94 -13
  109. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +193 -0
  110. package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +66 -2
  111. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -1
  112. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +6 -0
  113. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +6 -3
  114. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +23 -14
  115. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +26 -6
  116. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +42 -25
  117. package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +274 -0
  118. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +72 -32
  119. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +18 -11
  120. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +1 -2
  121. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-stamps.mjs +2 -2
  122. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +2 -3
  123. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +2 -2
  124. package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +1 -3
  125. package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +34 -3
  126. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +5 -1
  127. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
  128. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +5 -0
  129. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +5 -9
  130. package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
  131. package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
  132. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +1 -2
  133. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +25 -14
  134. package/src/runtime/agent/orchestrator/providers/openai-ws-terminal.mjs +18 -11
  135. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +35 -24
  136. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +581 -0
  137. package/src/runtime/agent/orchestrator/providers/registry.mjs +35 -9
  138. package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
  139. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +118 -219
  140. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -0
  141. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +148 -45
  142. package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +81 -16
  143. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +3 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +3 -0
  145. package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +15 -55
  146. package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +15 -2
  147. package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +0 -18
  148. package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +57 -28
  149. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +19 -16
  150. package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +268 -181
  151. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +4 -1
  152. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +21 -0
  153. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +54 -3
  154. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
  155. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +270 -0
  156. package/src/runtime/agent/orchestrator/session/catalog-db/sqlite-gate.mjs +27 -0
  157. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +628 -0
  158. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +6 -2
  159. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +184 -0
  160. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +136 -0
  161. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +128 -0
  162. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +127 -0
  163. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +101 -0
  164. package/src/runtime/agent/orchestrator/session/explicit-skills.mjs +83 -5
  165. package/src/runtime/agent/orchestrator/session/imported-message.mjs +11 -0
  166. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +2 -1
  167. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -1
  168. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +3 -2
  169. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -4
  170. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +4 -3
  171. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +102 -18
  172. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
  173. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -1
  174. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +42 -5
  175. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +14 -3
  176. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +20 -12
  177. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +50 -23
  178. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +4 -0
  179. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +22 -14
  180. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +1 -1
  181. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
  182. package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
  183. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +4 -3
  184. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +155 -29
  185. package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
  186. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
  187. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
  188. package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +16 -0
  189. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +22 -10
  190. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +819 -0
  191. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +12 -0
  192. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +22 -12
  193. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +158 -0
  194. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +183 -374
  195. package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +3 -1
  196. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +1 -1
  197. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +41 -3
  198. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +38 -17
  199. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
  200. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
  201. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +17 -1
  202. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -0
  203. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
  204. package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +2 -2
  205. package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +6 -6
  206. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +173 -22
  207. package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
  208. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +5 -4
  209. package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +15 -2
  210. package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +13 -10
  211. package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +1 -1
  212. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +17 -12
  213. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +2 -2
  214. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
  215. package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +4 -4
  216. package/src/runtime/agent/orchestrator/tools/patch/apply-patch/route.mjs +2 -2
  217. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +1 -1
  218. package/src/runtime/agent/orchestrator/tools/patch/read-redirects.mjs +34 -30
  219. package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +7 -7
  220. package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +1 -1
  221. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
  222. package/src/runtime/attachments/store.d.mts +3 -0
  223. package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +1 -1
  224. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +16 -4
  225. package/src/runtime/channels/lib/worker-main.mjs +17 -14
  226. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -2
  227. package/src/runtime/effort-judge/judge-client.mjs +56 -18
  228. package/src/runtime/memory/lib/memory.mjs +1 -1
  229. package/src/runtime/memory/lib/pg/process.mjs +34 -24
  230. package/src/runtime/memory/lib/pg/supervisor.mjs +16 -13
  231. package/src/runtime/memory/lib/session-ingest.mjs +2 -2
  232. package/src/runtime/office/README.md +1 -1
  233. package/src/runtime/office/shared/values.mjs +0 -5
  234. package/src/runtime/shared/atomic-file.mjs +25 -4
  235. package/src/runtime/shared/background-tasks.mjs +92 -14
  236. package/src/runtime/shared/err-text.mjs +25 -0
  237. package/src/runtime/shared/error-presentation.mjs +159 -19
  238. package/src/runtime/shared/extension-scopes.mjs +5 -3
  239. package/src/runtime/shared/file-lock.mjs +37 -11
  240. package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
  241. package/src/runtime/shared/llm/anthropic-effort.mjs +134 -131
  242. package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
  243. package/src/runtime/shared/llm/model-catalog.mjs +53 -52
  244. package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
  245. package/src/runtime/shared/llm/provider-catalog-registry.mjs +17 -0
  246. package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
  247. package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
  248. package/src/runtime/shared/model-display.mjs +13 -0
  249. package/src/runtime/shared/plugin-manifest.mjs +18 -9
  250. package/src/runtime/shared/pristine-execution-contract.json +9 -2
  251. package/src/runtime/shared/pristine-execution.mjs +28 -4
  252. package/src/runtime/shared/provider-accounts.mjs +124 -20
  253. package/src/runtime/shared/provider-api-key.mjs +12 -0
  254. package/src/runtime/shared/quota-resume-store.mjs +11 -0
  255. package/src/runtime/shared/session-baseline-store.mjs +960 -0
  256. package/src/runtime/shared/shell-display.mjs +9 -3
  257. package/src/runtime/shared/skill-mentions.d.mts +10 -0
  258. package/src/runtime/shared/skill-mentions.mjs +133 -0
  259. package/src/runtime/shared/skill-script-runtime.mjs +264 -0
  260. package/src/runtime/shared/statusline/statusline-format.mjs +4 -4
  261. package/src/runtime/shared/task-notification-envelope.mjs +2 -2
  262. package/src/runtime/shared/tool-primitives.mjs +35 -2
  263. package/src/runtime/shared/turn-changes.mjs +447 -219
  264. package/src/runtime/shared/turn-snapshot-store.mjs +182 -1
  265. package/src/runtime/shared/turn-snapshot.mjs +170 -48
  266. package/src/runtime/shared/turn-worktree-snapshot.mjs +160 -51
  267. package/src/runtime/shared/worker-requests.mjs +15 -2
  268. package/src/runtime/shared/worktrees/contract.mjs +0 -24
  269. package/src/runtime/shared/worktrees/test-support.mjs +19 -4
  270. package/src/session-runtime/automation-agents.mjs +8 -2
  271. package/src/session-runtime/boot/apis.mjs +61 -0
  272. package/src/session-runtime/boot/config.mjs +5 -2
  273. package/src/session-runtime/boot/facade.mjs +1 -0
  274. package/src/session-runtime/boot/infrastructure.mjs +35 -18
  275. package/src/session-runtime/conversation-import/discovery.mjs +698 -0
  276. package/src/session-runtime/conversation-import/service.mjs +369 -0
  277. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +10 -5
  278. package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
  279. package/src/session-runtime/lifecycle/session-catalog.mjs +2 -0
  280. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  281. package/src/session-runtime/mcp-glue/connect.mjs +83 -16
  282. package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
  283. package/src/session-runtime/mcp-glue/server-catalog.mjs +135 -33
  284. package/src/session-runtime/mcp-glue.mjs +25 -2
  285. package/src/session-runtime/mcp-oauth-login.mjs +174 -0
  286. package/src/session-runtime/model-route/model-switch-target.mjs +34 -0
  287. package/src/session-runtime/model-route/set-route.mjs +83 -15
  288. package/src/session-runtime/model-route/web-search-route.mjs +1 -1
  289. package/src/session-runtime/native-web-search/routes.mjs +22 -3
  290. package/src/session-runtime/new-session-config.mjs +3 -2
  291. package/src/session-runtime/notification-bus.mjs +9 -2
  292. package/src/session-runtime/provider-auth/accounts.mjs +33 -15
  293. package/src/session-runtime/provider-models/model-meta.mjs +12 -3
  294. package/src/session-runtime/provider-models/web-search-catalog.mjs +5 -1
  295. package/src/session-runtime/provider-readiness.mjs +16 -10
  296. package/src/session-runtime/quick-model-rows/web-search-rows.mjs +13 -8
  297. package/src/session-runtime/quick-web-search-models.mjs +13 -38
  298. package/src/session-runtime/resource-extension-sync.mjs +24 -5
  299. package/src/session-runtime/resource-mcp-api.mjs +198 -78
  300. package/src/session-runtime/resource-plugins-api.mjs +29 -41
  301. package/src/session-runtime/resource-scope-decorate.mjs +6 -8
  302. package/src/session-runtime/resource-skills-api.mjs +23 -2
  303. package/src/session-runtime/runtime-review-api.mjs +13 -0
  304. package/src/session-runtime/schedule-session-run.mjs +1 -1
  305. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +13 -1
  306. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +7 -2
  307. package/src/session-runtime/services/agent-tool/send-flow.mjs +22 -4
  308. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +2 -0
  309. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +22 -5
  310. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -1
  311. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -2
  312. package/src/session-runtime/services/agent-tool/worker-rows.mjs +17 -0
  313. package/src/session-runtime/services/channel-session-router.mjs +4 -1
  314. package/src/session-runtime/services/hook-bus/command-handler.mjs +4 -1
  315. package/src/session-runtime/services/hook-bus/handlers.mjs +7 -3
  316. package/src/session-runtime/services/provider-admin.mjs +64 -18
  317. package/src/session-runtime/services/usage-dashboard-model.mjs +3 -0
  318. package/src/session-runtime/settings-compaction-api.mjs +1 -0
  319. package/src/session-runtime/setup-tool/executor.mjs +12 -1
  320. package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
  321. package/src/session-runtime/setup-tool/settings-contract.mjs +1 -0
  322. package/src/session-runtime/setup-tool/tool-defs.mjs +7 -1
  323. package/src/session-runtime/skills-api.mjs +7 -3
  324. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
  325. package/src/session-runtime/webhook-session-run.mjs +16 -4
  326. package/src/skill-script-entry.mjs +36 -0
  327. package/src/standalone/daemon-drain-policy.mjs +8 -0
  328. package/src/standalone/daemon-stored-session-views.mjs +11 -3
  329. package/src/standalone/daemon-telemetry.mjs +55 -0
  330. package/src/standalone/daemon.mjs +44 -11
  331. package/src/standalone/session-protocol.mjs +12 -0
  332. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +33 -2
  333. package/src/standalone/session-service/agent-tree/agent-turns.mjs +26 -10
  334. package/src/standalone/session-service/agent-tree.mjs +12 -0
  335. package/src/standalone/session-service/quota-resume.mjs +8 -0
  336. package/src/standalone/session-service/retention/busy.mjs +15 -1
  337. package/src/standalone/session-service/session-calls/session-action.mjs +6 -1
  338. package/src/standalone/session-service-api.mjs +5 -0
  339. package/src/standalone/session-service.mjs +1 -0
  340. package/src/tui/App.jsx +9 -1
  341. package/src/tui/app/app-view/floating-panel.jsx +9 -1
  342. package/src/tui/app/app-view.jsx +7 -0
  343. package/src/tui/app/create-app-pickers.mjs +4 -0
  344. package/src/tui/app/extension-pickers/mcp-login.mjs +107 -0
  345. package/src/tui/app/extension-pickers/mcp-servers-picker.mjs +2 -1
  346. package/src/tui/app/extension-pickers/plugins-pickers.mjs +35 -16
  347. package/src/tui/app/extension-pickers.mjs +2 -1
  348. package/src/tui/app/model-options.mjs +13 -16
  349. package/src/tui/app/skill-mention-palette.mjs +88 -0
  350. package/src/tui/app/slash-commands.mjs +7 -2
  351. package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
  352. package/src/tui/app/slash-palette.mjs +23 -7
  353. package/src/tui/app/transcript-row-estimate.mjs +11 -3
  354. package/src/tui/app/use-prompt-draft-flow.mjs +7 -2
  355. package/src/tui/app/use-prompt-state.mjs +5 -0
  356. package/src/tui/components/Message.jsx +22 -1
  357. package/src/tui/components/PromptInput.jsx +21 -3
  358. package/src/tui/components/SlashCommandPalette.jsx +12 -3
  359. package/src/tui/components/StatusLine.jsx +2 -0
  360. package/src/tui/components/TranscriptItem.jsx +9 -1
  361. package/src/tui/components/prompt-input/key-handler.mjs +21 -8
  362. package/src/tui/components/status-line/local-line.mjs +5 -2
  363. package/src/tui/components/status-line/use-statusline-text.mjs +7 -1
  364. package/src/tui/components/user-message-skills.mjs +38 -0
  365. package/src/tui/dist/index.mjs +1323 -214
  366. package/src/tui/session/queue-helpers.mjs +7 -2
  367. package/src/tui/session/quota-resume.mjs +46 -14
  368. package/src/tui/session/session-api/commands.mjs +33 -24
  369. package/src/tui/session/session-api/extensions.mjs +26 -2
  370. package/src/tui/session/session-api/integrations.mjs +7 -0
  371. package/src/tui/session/session-api/lifecycle.mjs +5 -1
  372. package/src/tui/session/session-api/routes.mjs +71 -7
  373. package/src/tui/session/session-api/settings.mjs +12 -14
  374. package/src/tui/session/session-flow/drain.mjs +21 -5
  375. package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
  376. package/src/tui/session/tui-steering-persist.mjs +25 -9
  377. package/src/tui/session/turn.mjs +55 -15
  378. package/src/tui/statusline-ansi-bridge.mjs +1 -1
  379. package/src/ui/statusline-agents.mjs +15 -4
  380. package/src/ui/statusline.mjs +7 -3
  381. package/src/ui/streaming-markdown-heal.mjs +34 -3
  382. package/src/vendor/statusline/src/gateway/claude-current.mjs +14 -4
  383. package/src/runtime/effort-judge/previous-human-request.mjs +0 -162
  384. package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
  385. package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
  386. package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
@@ -50,6 +50,7 @@ export class ModelProxyChannel {
50
50
  attachPublisher(publish: (snapshot: ModelProxySnapshot) => void): () => void;
51
51
  disconnect(reason?: string): void;
52
52
  setClientPresent(present: boolean): void;
53
+ onStateChange(listener: () => void): () => void;
53
54
  request(
54
55
  call: Record<string, unknown>,
55
56
  options?: { signal?: AbortSignal | null; callbacks?: Record<string, (...args: unknown[]) => unknown> }
@@ -65,3 +66,17 @@ export class ModelProxyChannel {
65
66
  }
66
67
 
67
68
  export function getModelProxyChannel(): ModelProxyChannel;
69
+
70
+ /** The channel surface model-proxy providers use; the bridge child implements only this. */
71
+ export interface ModelProxyChannelLike {
72
+ readonly connected: boolean;
73
+ readonly generation: number;
74
+ whenConnected(timeoutMs: number): Promise<boolean>;
75
+ request(
76
+ call: Record<string, unknown>,
77
+ options?: { signal?: AbortSignal | null; callbacks?: Record<string, (...args: unknown[]) => unknown> }
78
+ ): Promise<unknown>;
79
+ }
80
+
81
+ /** Swap the process-wide channel; the returned function restores the previous one. */
82
+ export function installModelProxyChannel(channel: ModelProxyChannel | ModelProxyChannelLike): () => void;
@@ -243,8 +243,24 @@ export class ModelProxyChannel {
243
243
  });
244
244
  }
245
245
 
246
+ #stateListeners = new Set();
247
+
248
+ /** `listener()` runs after every presence/generation change (the model
249
+ * proxy bridge pushes it to its clients). Returns the unsubscribe. */
250
+ onStateChange(listener) {
251
+ this.#stateListeners.add(listener);
252
+ return () => this.#stateListeners.delete(listener);
253
+ }
254
+
246
255
  #connectionChanged() {
247
256
  this.#generation += 1;
257
+ for (const listener of [...this.#stateListeners]) {
258
+ try {
259
+ listener();
260
+ } catch {
261
+ /* a listener never breaks the transport that reported the change */
262
+ }
263
+ }
248
264
  if (!this.connected) return;
249
265
  for (const waiter of [...this.#connectionWaiters]) waiter(true);
250
266
  }
@@ -519,3 +535,22 @@ export function getModelProxyChannel() {
519
535
  globalThis[CHANNEL_KEY] ??= new ModelProxyChannel();
520
536
  return globalThis[CHANNEL_KEY];
521
537
  }
538
+
539
+ /**
540
+ * Make `channel` the process-wide channel (a headless child talks through the
541
+ * daemon's model proxy bridge instead). The returned restore puts the previous
542
+ * channel back once, unless another install replaced this one since.
543
+ */
544
+ export function installModelProxyChannel(channel) {
545
+ const hadPrevious = Object.hasOwn(globalThis, CHANNEL_KEY);
546
+ const previous = globalThis[CHANNEL_KEY];
547
+ globalThis[CHANNEL_KEY] = channel;
548
+ let restored = false;
549
+ return () => {
550
+ if (restored) return;
551
+ restored = true;
552
+ if (globalThis[CHANNEL_KEY] !== channel) return;
553
+ if (hadPrevious) globalThis[CHANNEL_KEY] = previous;
554
+ else delete globalThis[CHANNEL_KEY];
555
+ };
556
+ }
@@ -10,8 +10,10 @@ import { createHash } from 'node:crypto';
10
10
  import { noteErrorUsage } from './lib/note-error-usage.mjs';
11
11
  import { fileMtimeMs } from './lib/oauth-token-utils.mjs';
12
12
  import { OpenAICompatProvider, preloadOpenAICompatRuntime } from './openai-compat.mjs';
13
+ import { COMPAT_RETRY_POLICY } from './openai-compat-retry-profile.mjs';
13
14
  import { getModelMetadataSync } from './model-catalog.mjs';
14
15
  import { makeModelCache } from './model-cache.mjs';
16
+ import { normalizeCacheKey } from '../agent-runtime/cache-strategy.mjs';
15
17
  import { PRICING_RATE_KEYS } from '../../../shared/llm/model-pricing-rates.mjs';
16
18
  import {
17
19
  MUSE_DEFAULT_EFFORT_LEVELS as FIVE_LEVELS,
@@ -100,15 +102,6 @@ function museRow(id, discovered = null) {
100
102
  const EFFORT_DOWNGRADE = { max: 'xhigh' };
101
103
  const SUMMARY_MODES = new Set(['auto', 'detailed', 'concise']);
102
104
 
103
- // Cache identities beyond the wire limit become a bounded hash identity.
104
- function normalizeCacheKey(value) {
105
- const text = String(value ?? '').trim();
106
- if (!text) return '';
107
- const wellFormed = text.toWellFormed();
108
- if (wellFormed.length <= 64) return wellFormed;
109
- return `pc_${createHash('sha256').update(wellFormed).digest('hex').slice(0, 32)}`;
110
- }
111
-
112
105
  // Final request shaping on the Responses wire (installed through the shared
113
106
  // transport's opt-in params hook).
114
107
  function shapeResponsesParams(params, { opts, modelInfo }, config = {}) {
@@ -321,6 +314,8 @@ export class MuseCodeOAuthProvider {
321
314
  nativePdf = false;
322
315
  static inputExcludesCache = false;
323
316
  name = 'muse-code-oauth';
317
+ // The retry profile's limits are final: no loop-level recovery cycles on top.
318
+ retryPolicy = COMPAT_RETRY_POLICY;
324
319
  config;
325
320
  tokens = null;
326
321
  _inner = null;
@@ -181,6 +181,17 @@ function mimoOAuthState() {
181
181
  );
182
182
  }
183
183
 
184
+ function commandCodeOAuthState() {
185
+ const paths = [
186
+ boundProviderAuthPath('command-code-oauth') ||
187
+ process.env.COMMAND_CODE_OAUTH_CREDENTIALS_PATH ||
188
+ join(resolvePluginData(), 'command-code-oauth.json'),
189
+ ];
190
+ return memoProbe('command-code-oauth', paths, () =>
191
+ resolveProbeState(paths, (docs) => docs.some((own) => typeof own?.apiKey === 'string' && !!own.apiKey.trim()))
192
+ );
193
+ }
194
+
184
195
  function museCodeOAuthState() {
185
196
  const paths = [
186
197
  boundProviderAuthPath('muse-code-oauth') ||
@@ -255,6 +266,7 @@ const OAUTH_PROBE_STATES = new Map([
255
266
  ['openai-oauth', openAIOAuthState],
256
267
  ['grok-oauth', grokOAuthState],
257
268
  ['muse-code-oauth', museCodeOAuthState],
269
+ ['command-code-oauth', commandCodeOAuthState],
258
270
  ['mimo-oauth', mimoOAuthState],
259
271
  ['cursor-oauth', cursorOAuthState],
260
272
  ['antigravity-oauth', antigravityOAuthState],
@@ -868,7 +868,8 @@ async function measureUsage(provider, providerObj, routeInfo) {
868
868
  (provider === 'cursor-oauth' ||
869
869
  provider === 'cursor-api' ||
870
870
  provider === 'antigravity-oauth' ||
871
- provider === 'muse-code-oauth') &&
871
+ provider === 'muse-code-oauth' ||
872
+ provider === 'command-code-oauth') &&
872
873
  typeof providerObj?.getUsageSnapshot === 'function'
873
874
  ) {
874
875
  return await providerObj.getUsageSnapshot();
@@ -893,12 +894,12 @@ async function measureUsageWithAuthRetry(provider, providerObj, routeInfo) {
893
894
  // refresh cannot vouch for the reading it last produced: keeping a 100% meter
894
895
  // earned by a dead token would hold the account out of the roster until its
895
896
  // reset time, so the recorded quota goes with the credential.
896
- function usageAfterFailure(err, provider, accountId, log) {
897
+ async function usageAfterFailure(err, provider, accountId, log) {
897
898
  const snapshot = provider === 'anthropic-oauth' && accountId === 'default' ? latestClaudeStatuslineUsage() : null;
898
899
  if (snapshot) return snapshot;
899
900
  if (isUsageAuthRejection(err) && ACCOUNT_PROVIDERS.includes(provider)) {
900
901
  try {
901
- clearProviderAccountQuotaState(provider, accountId);
902
+ await clearProviderAccountQuotaState(provider, accountId);
902
903
  } catch (error) {
903
904
  log(`Account usage could not be cleared: ${error.message}`);
904
905
  }
@@ -952,7 +953,7 @@ export async function fetchOAuthUsageSnapshot(routeInfo, providerObj, log = () =
952
953
  try {
953
954
  snapshot = await measureUsageWithAuthRetry(provider, providerObj, routeInfo);
954
955
  } catch (err) {
955
- snapshot = usageAfterFailure(err, provider, accountId, log);
956
+ snapshot = await usageAfterFailure(err, provider, accountId, log);
956
957
  }
957
958
  if (!isContentfulSnapshot(snapshot)) {
958
959
  cacheNegative(key, 'empty');
@@ -961,7 +962,7 @@ export async function fetchOAuthUsageSnapshot(routeInfo, providerObj, log = () =
961
962
  }
962
963
  if (ACCOUNT_PROVIDERS.includes(provider)) {
963
964
  try {
964
- recordProviderAccountUsage(provider, accountId, snapshot);
965
+ await recordProviderAccountUsage(provider, accountId, snapshot);
965
966
  } catch (error) {
966
967
  log(`Account usage could not be saved: ${error.message}`);
967
968
  }
@@ -21,6 +21,7 @@ import { normalizeCompatChatResponse } from './openai-compat-response-normalizat
21
21
  import { applyCompatToolChoice, compatStreamRetryReporter } from './compat-request-policy.mjs';
22
22
  import { ensureChatToolPairs } from './lib/wire-pairing.mjs';
23
23
  import { xaiCacheRouting } from './openai-compat-xai.mjs';
24
+ import { compatRetryOptions, withCompatRetryProfile } from './openai-compat-retry-profile.mjs';
24
25
  import { preparePdfTextForProvider } from './media-normalization.mjs';
25
26
  import { isCustomProviderName, resolveCustomReasoning } from './custom-reasoning.mjs';
26
27
 
@@ -38,7 +39,7 @@ export async function sendCompatChat(provider, messages, useModel, tools, opts)
38
39
  // global catalog must not shape a user-defined endpoint's request.
39
40
  let modelInfo = null;
40
41
  if (isCustom) modelInfo = provider.getCachedModelInfo(useModel) || null;
41
- else if (provider.name === 'opencode-go')
42
+ else if (provider.name === 'opencode-go' || provider.name === 'command-code-oauth')
42
43
  modelInfo = provider.getCachedModelInfo(useModel) || getModelMetadataSync(useModel, provider.name);
43
44
  else if (profile?.resolveModelInfo) modelInfo = profile.resolveModelInfo(provider, useModel) || null;
44
45
  // Resolved before lowering: replay eligibility depends on the snapped level
@@ -85,7 +86,7 @@ export async function sendCompatChat(provider, messages, useModel, tools, opts)
85
86
  try {
86
87
  try {
87
88
  assembled = await withRetry(
88
- refineAttemptErrors(profile, async ({ signal: attemptSignal }) => {
89
+ withCompatRetryProfile(provider.name, refineAttemptErrors(profile, async ({ signal: attemptSignal }) => {
89
90
  try {
90
91
  opts.onStageChange?.('requesting');
91
92
  } catch {
@@ -139,11 +140,12 @@ export async function sendCompatChat(provider, messages, useModel, tools, opts)
139
140
  }
140
141
  throw error;
141
142
  }
142
- }),
143
+ })),
143
144
  {
144
145
  signal: totalSignal.signal,
145
146
  onRetry: compatStreamRetryReporter(provider.name, opts),
146
147
  retry529: opts.retry529,
148
+ ...compatRetryOptions(provider.name),
147
149
  }
148
150
  );
149
151
  } catch (streamErr) {
@@ -8,6 +8,7 @@ import { truncatedCompatStreamError } from '../lib/openai-tool-args.mjs';
8
8
  import {
9
9
  emitCompatToolCallOnce,
10
10
  firstByteCompatStreamError,
11
+ failingFinishReasonError,
11
12
  markErrorLiveTextEmitted,
12
13
  markUnsafeRetryIfToolEmitted,
13
14
  } from '../openai-compat-stream-common.mjs';
@@ -61,7 +62,28 @@ function parseAccumulatedToolCalls(state, { label, parseToolCalls }) {
61
62
  }
62
63
  }
63
64
 
65
+ // A gateway-reported failing finish_reason (`network_error`, `error`) is an
66
+ // interruption: the stream carries no terminal, so exposure keeps its replay
67
+ // gates.
68
+ function finishReasonInterruption(state, err) {
69
+ attachPartial(state, err);
70
+ if (state.emittedText) {
71
+ markErrorLiveTextEmitted(err);
72
+ try {
73
+ err.streamStalled = true;
74
+ } catch {
75
+ /* best-effort */
76
+ }
77
+ }
78
+ return stampCompatOutcome(state, markUnsafeRetryIfToolEmitted(err, state.streamEmitState), {
79
+ terminalObserved: false,
80
+ continuation: true,
81
+ });
82
+ }
83
+
64
84
  export function settleCompatStream(state, { label, parseToolCalls }) {
85
+ const failing = failingFinishReasonError(state.stopReason, label);
86
+ if (failing) throw finishReasonInterruption(state, failing);
65
87
  const response = buildResponse(state);
66
88
  let toolCalls = parseAccumulatedToolCalls(state, { label, parseToolCalls });
67
89
  if (Array.isArray(toolCalls) && toolCalls.length) {
@@ -71,6 +71,7 @@ export async function consumeCompatChatCompletionStream(
71
71
  idleDeadlineAt: state.semanticIdleDeadlineAt,
72
72
  idleEnabled: state.sawFirstEvent && idleEnabled && state.semanticIdleDeadlineAt > 0,
73
73
  idleLabel: `${label} SSE idle`,
74
+ streamLabel: label,
74
75
  emittedToolCall: () => toolWorkStarted(state),
75
76
  });
76
77
  if (done) {
@@ -0,0 +1,50 @@
1
+ /**
2
+ * openai-compat-error-contract.mjs — the error contract of the OpenAI-compatible
3
+ * provider boundary: `status`, lowercased `code` (from the wire error's `code`
4
+ * or `type`), `headers`, `retryAfterMs` and `resetAt` when the provider sent
5
+ * them. Evidence is structural only; message text is never parsed.
6
+ */
7
+ import { retryAfterMsFromError, typedStatusFrom } from './retry-classifier.mjs';
8
+
9
+ const lowered = (value) => (typeof value === 'string' && value.trim() ? value.trim().toLowerCase() : '');
10
+
11
+ // Epoch seconds, epoch ms or an ISO date → epoch ms; `resets_in_seconds` is relative.
12
+ function resetAtFrom(wire, now) {
13
+ const inSeconds = Number(wire?.resets_in_seconds);
14
+ if (wire?.resets_in_seconds != null && Number.isFinite(inSeconds) && inSeconds >= 0) {
15
+ return now + Math.ceil(inSeconds * 1000);
16
+ }
17
+ const raw = wire?.resets_at ?? wire?.reset_at;
18
+ if (raw == null || raw === '') return null;
19
+ const numeric = Number(raw);
20
+ if (Number.isFinite(numeric) && numeric > 0) return numeric < 1e12 ? Math.round(numeric * 1000) : Math.round(numeric);
21
+ const parsed = Date.parse(String(raw));
22
+ return Number.isNaN(parsed) ? null : parsed;
23
+ }
24
+
25
+ /** Stamp the boundary contract onto a provider error in place and return it. */
26
+ export function applyCompatErrorContract(err, detail = err?.error ?? err?.providerError, now = Date.now()) {
27
+ if (!err || typeof err !== 'object') return err;
28
+ try {
29
+ const wire = detail && typeof detail === 'object' ? detail : null;
30
+ const status = typedStatusFrom(err, err.response, wire);
31
+ if (status && !(Number(err.status) >= 100)) err.status = status;
32
+ const wireCode = lowered(wire?.code) || lowered(wire?.type) || lowered(err.type);
33
+ // Keep an errno / SDK-local code (ECONNRESET, ...) that is not the wire code.
34
+ if (wireCode && (typeof err.code !== 'string' || !err.code.trim() || lowered(err.code) === wireCode)) {
35
+ err.code = wireCode;
36
+ }
37
+ if (!err.headers && err.response?.headers) err.headers = err.response.headers;
38
+ if (!Number.isFinite(err.retryAfterMs)) {
39
+ const retryAfterMs = retryAfterMsFromError(err);
40
+ if (retryAfterMs != null) err.retryAfterMs = retryAfterMs;
41
+ }
42
+ if (!Number.isFinite(err.resetAt)) {
43
+ const resetAt = resetAtFrom(wire, now);
44
+ if (resetAt) err.resetAt = resetAt;
45
+ }
46
+ } catch {
47
+ /* the contract is best-effort; the original error stays authoritative */
48
+ }
49
+ return err;
50
+ }
@@ -1,3 +1,4 @@
1
+ import { resolveProviderApiKey } from '../../../shared/provider-api-key.mjs';
1
2
  import { enrichModels } from './model-catalog.mjs';
2
3
  import { sanitizeModelList } from './model-list-sanitize.mjs';
3
4
  import { PROVIDER_GENERATE_TOTAL_TIMEOUT_MS, createTimeoutSignal, resolveTimeoutMs } from '../stall-policy.mjs';
@@ -10,12 +11,15 @@ const MODEL_LIST_TIMEOUT_MS = resolveTimeoutMs('MIXDOG_COMPAT_MODEL_LIST_TIMEOUT
10
11
  // `keyless` omits the Authorization header entirely (keyless endpoints);
11
12
  // `signal` aborts the request together with the list timeout.
12
13
  export async function fetchCompatModelItems(provider, { signal = null, keyless = false } = {}) {
13
- const timeout = createTimeoutSignal(signal, MODEL_LIST_TIMEOUT_MS, `${provider.name} model list`);
14
+ const name = provider.name;
15
+ const timeout = createTimeoutSignal(signal, MODEL_LIST_TIMEOUT_MS, `${name} model list`);
14
16
  try {
15
17
  const res = await fetch(`${String(provider.baseURL || '').replace(/\/+$/, '')}/models`, {
16
18
  method: 'GET',
17
19
  headers: {
18
- ...(keyless ? {} : { Authorization: `Bearer ${provider.apiKey || 'no-key'}` }),
20
+ ...(keyless
21
+ ? {}
22
+ : { Authorization: `Bearer ${resolveProviderApiKey(name, provider.config || provider) || 'no-key'}` }),
19
23
  ...(provider.defaultHeaders || {}),
20
24
  },
21
25
  signal: timeout.signal,
@@ -74,6 +74,17 @@ export function applyCompatProviderChatOptions(params, providerName, opts = {},
74
74
  }
75
75
  return params;
76
76
  }
77
+ if (providerName === 'command-code-oauth') {
78
+ // The API's field is undocumented; mirror the common `reasoning_effort`
79
+ // (levels the catalog row declares, else low/medium/high).
80
+ const rawEffort = opts.effort ?? config?.reasoningEffort;
81
+ const declared = modelInfo?.reasoningOptions?.some((option) => option?.type === 'effort');
82
+ const effort = declared
83
+ ? normalizeOpencodeGoReasoningEffort(rawEffort, modelInfo)
84
+ : normalizeReasoningEffort(rawEffort, ['low', 'medium', 'high']);
85
+ if (effort) params.reasoning_effort = effort;
86
+ return params;
87
+ }
77
88
  if (providerName === 'opencode-go') {
78
89
  const reasoningEffort = normalizeOpencodeGoReasoningEffort(opts.effort ?? config?.reasoningEffort, modelInfo);
79
90
  // OpenCode Go's OpenAI-compatible contract exposes reasoning_effort,
@@ -7,6 +7,8 @@ import {
7
7
  writeXaiResponsesCacheTrace,
8
8
  } from './openai-compat-xai.mjs';
9
9
  import { createProviderReplay } from './lib/provider-replay.mjs';
10
+ import { stampStreamOutcome, STREAM_TRANSPORTS } from './lib/stream-outcome.mjs';
11
+ import { failingFinishReasonError } from './openai-compat-stream-common.mjs';
10
12
 
11
13
  const reportedNumber = (value) =>
12
14
  value == null || (typeof value === 'string' && value.trim() === '') ? Number.NaN : Number(value);
@@ -141,6 +143,27 @@ export function normalizeCompatChatResponse({
141
143
  const choice = response.choices[0];
142
144
  const toolCalls = assembled.toolCalls;
143
145
  const stopReason = choice?.finish_reason || null;
146
+ const failingFinish = failingFinishReasonError(stopReason, providerName);
147
+ if (failingFinish) {
148
+ const err = failingFinish;
149
+ const partialContent = choice?.message?.content || '';
150
+ Object.assign(err, {
151
+ partialContent,
152
+ partialToolCalls: Array.isArray(toolCalls) && toolCalls.length ? toolCalls : undefined,
153
+ pendingToolUse: false,
154
+ partialModel: response.model || useModel,
155
+ ...(response.usage ? { partialUsage: chatCompletionUsage(providerName, response.usage) } : {}),
156
+ });
157
+ stampStreamOutcome(err, {
158
+ transport: STREAM_TRANSPORTS.NON_STREAMING,
159
+ provider: 'openai-compat',
160
+ terminalObserved: false,
161
+ continuation: true,
162
+ textObservedChars: partialContent.length,
163
+ toolCallsComplete: err.partialToolCalls?.length || 0,
164
+ });
165
+ throw err;
166
+ }
144
167
  if (
145
168
  (stopReason === 'length' && Array.isArray(toolCalls) && toolCalls.length > 0) ||
146
169
  stopReason === 'content_filter'
@@ -2,6 +2,7 @@
2
2
  // wire event type maps to one handler over the shared stream `state`; `ctx`
3
3
  // carries the label, the caller callbacks and the leaked-text relay.
4
4
  import { typedStatusFrom } from './retry-classifier.mjs';
5
+ import { applyCompatErrorContract } from './openai-compat-error-contract.mjs';
5
6
  import { customToolCallFromResponseItem, nativeToolSearchCallFromArguments } from './custom-tool-wire.mjs';
6
7
  import { emitCompatToolCallOnce } from './openai-compat-stream-common.mjs';
7
8
  import { truncatedCompatStreamError, parseCompletedToolCallArgumentsJson } from './lib/openai-tool-args.mjs';
@@ -41,9 +42,11 @@ function typedResponsesFailure(message, event) {
41
42
  if (code != null && code !== '') err.providerErrorCode = String(code);
42
43
  if (detail) err.providerError = detail;
43
44
  err.providerWireError = true;
44
- return err;
45
+ return applyCompatErrorContract(err, detail || (event?.code != null ? { code: event.code } : null));
45
46
  }
46
47
 
48
+ const streamLabel = (ctx) => ctx?.label || 'compat Responses';
49
+
47
50
  // Reconcile a COMPLETED function_call item into state.toolCalls: fill in the
48
51
  // id/name a streamed call may still be missing, or adopt the item as a new
49
52
  // call. `response.output_item.done` and the `response.completed` sweep see the
@@ -289,6 +292,7 @@ function onCompleted(event, state, ctx) {
289
292
  }
290
293
 
291
294
  function onDone(event, state, ctx) {
295
+ const label = streamLabel(ctx);
292
296
  if (!event.response || event.response.status === 'completed') {
293
297
  state.completed = true;
294
298
  // A stream that never emits response.completed: this frame carries usage.
@@ -298,7 +302,7 @@ function onDone(event, state, ctx) {
298
302
  if (event.response.status === 'failed') {
299
303
  const msg = event.response?.error?.message || 'response.done failed';
300
304
  throw withIncompleteUsage(
301
- typedResponsesFailure(`xAI Responses stream response.done failed: ${msg}`, event),
305
+ typedResponsesFailure(`${label} stream response.done failed: ${msg}`, event),
302
306
  event,
303
307
  state
304
308
  );
@@ -306,27 +310,31 @@ function onDone(event, state, ctx) {
306
310
  if (event.response.status === 'incomplete') {
307
311
  const reason = incompleteReasonFromEvent(event);
308
312
  if (isMaxOutputIncompleteReason(reason)) return settleMaxOutputIncomplete(event, state, ctx, reason);
309
- throw withIncompleteUsage(new Error(`xAI Responses stream response.done incomplete: ${reason}`), event, state);
313
+ throw withIncompleteUsage(new Error(`${label} stream response.done incomplete: ${reason}`), event, state);
310
314
  }
311
315
  }
312
316
 
313
- function onFailed(event, state) {
317
+ function onFailed(event, state, ctx) {
314
318
  const msg = event.response?.error?.message || event.error?.message || event.message || 'response.failed';
315
319
  // The wire event's OWN typed status/code is preserved verbatim. A
316
320
  // forbidden/unknown failure is never coerced into a synthetic 500:
317
321
  // without typed evidence it stays unclassified and is surfaced.
318
- throw withIncompleteUsage(typedResponsesFailure(`xAI Responses stream response.failed: ${msg}`, event), event, state);
322
+ throw withIncompleteUsage(
323
+ typedResponsesFailure(`${streamLabel(ctx)} stream response.failed: ${msg}`, event),
324
+ event,
325
+ state
326
+ );
319
327
  }
320
328
 
321
329
  function onIncomplete(event, state, ctx) {
322
330
  const reason = incompleteReasonFromEvent(event);
323
331
  if (isMaxOutputIncompleteReason(reason)) return settleMaxOutputIncomplete(event, state, ctx, reason);
324
- throw withIncompleteUsage(new Error(`xAI Responses stream response.incomplete: ${reason}`), event, state);
332
+ throw withIncompleteUsage(new Error(`${streamLabel(ctx)} stream response.incomplete: ${reason}`), event, state);
325
333
  }
326
334
 
327
- function onError(event) {
335
+ function onError(event, _state, ctx) {
328
336
  const msg = event.message || event.error?.message || 'unknown';
329
- throw typedResponsesFailure(`xAI Responses stream error: ${msg}`, event);
337
+ throw typedResponsesFailure(`${streamLabel(ctx)} stream error: ${msg}`, event);
330
338
  }
331
339
 
332
340
  const RESPONSES_EVENT_HANDLERS = new Map([
@@ -139,11 +139,11 @@ export function createResponsesOutcomeStamper(state, leakedCalls) {
139
139
  }
140
140
 
141
141
  /** A streamed function_call whose id/name never arrived cannot be dispatched. */
142
- export function unresolvedSalvageError(state) {
142
+ export function unresolvedSalvageError(state, label) {
143
143
  const unresolved = state.toolCalls.find((t) => t._pendingItemId);
144
144
  if (!unresolved) return null;
145
145
  return new Error(
146
- `xAI Responses stream function_call salvage failed: missing call_id/name for item_id=${unresolved._pendingItemId || '?'}`
146
+ `${label || 'compat Responses'} stream function_call salvage failed: missing call_id/name for item_id=${unresolved._pendingItemId || '?'}`
147
147
  );
148
148
  }
149
149
 
@@ -169,5 +169,6 @@ export function finalizeResponsesStream(state, { leakedCalls, parseResponsesTool
169
169
  model: state.model || response.model || null,
170
170
  responseId: state.responseId || response.id || null,
171
171
  stopReason: state.stopReason || null,
172
+ reasoningEmitted: state.emittedReasoning === true,
172
173
  };
173
174
  }