mixdog 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (415) hide show
  1. package/README.md +18 -0
  2. package/package.json +2 -1
  3. package/scripts/provider-pingpong-live.mjs +509 -0
  4. package/src/agents/advisor/AGENT.md +1 -1
  5. package/src/agents/advisor/agent.json +1 -1
  6. package/src/defaults/shipped-history.json +5 -0
  7. package/src/defaults/skills/setup/SKILL.md +6 -1
  8. package/src/defaults/skills/setup/references/actions.md +44 -22
  9. package/src/defaults/skills/setup/references/surfaces.md +10 -8
  10. package/src/headless-exec.mjs +15 -8
  11. package/src/lib/keychain-cjs.cjs +7 -4
  12. package/src/output-styles/common.md +11 -10
  13. package/src/rules/agent/AGENT.md +5 -5
  14. package/src/rules/lead/LEAD.md +5 -5
  15. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
  16. package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
  17. package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
  18. package/src/runtime/agent/orchestrator/config.mjs +5 -0
  19. package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
  20. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
  21. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
  22. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
  23. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +2 -0
  24. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +24 -17
  25. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +7 -6
  26. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  27. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +29 -10
  28. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
  29. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
  30. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
  31. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
  32. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
  33. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
  34. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
  35. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -0
  36. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
  37. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +6 -0
  38. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +58 -7
  39. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +29 -10
  40. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +16 -3
  41. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +10 -61
  42. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +12 -6
  43. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  44. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +114 -72
  45. package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
  46. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +37 -5
  47. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  48. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +1 -0
  49. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +43 -2
  50. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +3 -0
  51. package/src/runtime/agent/orchestrator/providers/cursor.mjs +9 -2
  52. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +64 -1
  53. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +70 -6
  54. package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
  55. package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
  56. package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
  57. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -1
  58. package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
  59. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +25 -8
  60. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +87 -5
  61. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
  62. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +13 -13
  63. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +355 -37
  64. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -2
  65. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +93 -47
  66. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +55 -10
  67. package/src/runtime/agent/orchestrator/providers/gemini.mjs +26 -8
  68. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  69. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -0
  70. package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
  71. package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
  72. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +246 -42
  73. package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
  74. package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
  75. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +388 -0
  76. package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
  77. package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
  78. package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
  79. package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
  80. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +48 -22
  81. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +119 -18
  82. package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
  83. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
  84. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  85. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +33 -1
  86. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -0
  87. package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
  88. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +121 -61
  89. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
  90. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +5 -2
  91. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +37 -7
  92. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
  93. package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +1 -1
  94. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +47 -2
  95. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
  96. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
  97. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +151 -0
  98. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +42 -24
  99. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +63 -25
  100. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
  101. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +172 -0
  102. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +53 -5
  103. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -1
  104. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
  105. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +103 -26
  106. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +23 -4
  107. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +11 -6
  108. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +6 -1
  109. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +15 -23
  110. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
  111. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +25 -4
  112. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
  113. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
  114. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +4 -0
  115. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +5 -0
  116. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
  117. package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
  118. package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +3 -1
  119. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +7 -0
  120. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +7 -1
  121. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +71 -24
  122. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
  123. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +44 -16
  124. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -16
  125. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
  126. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -35
  127. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
  128. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
  129. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
  130. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +11 -3
  131. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +170 -0
  132. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +75 -70
  133. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +75 -0
  134. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +147 -8
  135. package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -1
  136. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +5 -0
  137. package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
  138. package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
  139. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +157 -0
  140. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +512 -0
  141. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
  142. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +183 -0
  143. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +100 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +21 -0
  145. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
  146. package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
  147. package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
  148. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +14 -3
  149. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
  150. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  151. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
  152. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +176 -71
  153. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +62 -10
  154. package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
  155. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -1
  156. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
  157. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +14 -93
  158. package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
  159. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +120 -0
  160. package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
  161. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
  162. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +2 -1
  163. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
  164. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +91 -1
  165. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
  166. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
  167. package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
  168. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -0
  169. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +21 -10
  170. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +132 -0
  171. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +30 -0
  172. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +63 -20
  173. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +2 -1
  174. package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
  175. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
  176. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -4
  177. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
  178. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +150 -0
  179. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +4 -1
  180. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -1
  181. package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
  182. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +16 -0
  183. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
  184. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
  185. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
  186. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
  187. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +208 -14
  188. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +15 -3
  189. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +25 -3
  190. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
  191. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +19 -2
  192. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
  193. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
  194. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -1
  195. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
  196. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +13 -0
  197. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
  198. package/src/runtime/agent/orchestrator/session/side-question.mjs +192 -0
  199. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +17 -3
  200. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
  201. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +58 -2
  202. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +41 -28
  203. package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
  204. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +12 -1
  205. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +3 -1
  206. package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
  207. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
  208. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +8 -0
  209. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +10 -1
  210. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +10 -2
  211. package/src/runtime/agent/orchestrator/session/store.mjs +19 -3
  212. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +1 -0
  213. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +1 -1
  214. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
  215. package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
  216. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
  217. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +77 -0
  218. package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
  219. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
  220. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
  221. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +14 -10
  222. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +49 -34
  223. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
  224. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
  225. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
  226. package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
  227. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
  228. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
  229. package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
  230. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
  231. package/src/runtime/computer-bridge/action-schema.mjs +44 -21
  232. package/src/runtime/github/tool.mjs +92 -2
  233. package/src/runtime/memory/index.mjs +1 -0
  234. package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
  235. package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
  236. package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
  237. package/src/runtime/memory/lib/pg/process.mjs +31 -26
  238. package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
  239. package/src/runtime/memory/lib/pg/supervisor.mjs +108 -3
  240. package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
  241. package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
  242. package/src/runtime/office/README.md +1 -1
  243. package/src/runtime/office/authoring/html-document-author.mjs +2 -0
  244. package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
  245. package/src/runtime/office/authoring/pptx-html-measure.mjs +2 -0
  246. package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
  247. package/src/runtime/office/authoring/xlsx-html-runner.mjs +2 -0
  248. package/src/runtime/office/core/office-actions-read.mjs +3 -0
  249. package/src/runtime/office/core/office-render-preview.mjs +2 -0
  250. package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
  251. package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
  252. package/src/runtime/office/core/office-sessions.mjs +5 -0
  253. package/src/runtime/office/core/office-transactions.mjs +3 -0
  254. package/src/runtime/office/core/office-write-ledger.mjs +98 -0
  255. package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
  256. package/src/runtime/office/index.mjs +30 -0
  257. package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
  258. package/src/runtime/office/pdf/pdf-render.mjs +23 -7
  259. package/src/runtime/office/pdf/pdf-security.mjs +2 -0
  260. package/src/runtime/office/portable/portable-opc.mjs +4 -1
  261. package/src/runtime/office/quality/visual-diff.mjs +2 -0
  262. package/src/runtime/shared/bounded-file-read.mjs +13 -0
  263. package/src/runtime/shared/bounded-line-diff.mjs +182 -0
  264. package/src/runtime/shared/buffered-appender.mjs +18 -0
  265. package/src/runtime/shared/config.mjs +78 -18
  266. package/src/runtime/shared/err-text.mjs +6 -0
  267. package/src/runtime/shared/file-permissions.d.mts +6 -1
  268. package/src/runtime/shared/file-permissions.mjs +54 -6
  269. package/src/runtime/shared/llm/anthropic-effort.mjs +6 -0
  270. package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
  271. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
  272. package/src/runtime/shared/loopback-listener.mjs +9 -0
  273. package/src/runtime/shared/provider-api-key.mjs +2 -0
  274. package/src/runtime/shared/review-diff.mjs +52 -0
  275. package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
  276. package/src/runtime/shared/session-sidebar-host.mjs +38 -0
  277. package/src/runtime/shared/slow-span.mjs +114 -0
  278. package/src/runtime/shared/statusline/statusline-segments.mjs +28 -4
  279. package/src/runtime/shared/tool-card-model/card-header.mjs +6 -1
  280. package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
  281. package/src/runtime/shared/tool-card-model.mjs +5 -2
  282. package/src/runtime/shared/tool-output-limit.mjs +4 -0
  283. package/src/runtime/shared/tool-primitives.mjs +13 -0
  284. package/src/runtime/shared/tool-result-summary.mjs +8 -1
  285. package/src/runtime/shared/tool-surface.mjs +18 -3
  286. package/src/runtime/shared/tool-work-units.mjs +40 -4
  287. package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
  288. package/src/runtime/shared/transcript-writer.mjs +10 -2
  289. package/src/runtime/shared/turn-changes.mjs +268 -100
  290. package/src/runtime/shared/turn-review-reply.mjs +8 -39
  291. package/src/runtime/shared/turn-snapshot-store.mjs +19 -108
  292. package/src/runtime/shared/turn-snapshot.mjs +857 -683
  293. package/src/runtime/shared/turn-worktree-snapshot.mjs +183 -255
  294. package/src/runtime/shared/user-data-guard.mjs +262 -49
  295. package/src/runtime/shared/worktrees/carry.mjs +531 -0
  296. package/src/runtime/shared/worktrees/contract.mjs +34 -0
  297. package/src/runtime/shared/worktrees/file-recovery.mjs +68 -0
  298. package/src/runtime/shared/worktrees/git-head.mjs +205 -0
  299. package/src/runtime/shared/worktrees/git.mjs +8 -3
  300. package/src/runtime/shared/worktrees/maintenance.mjs +1 -1
  301. package/src/runtime/shared/worktrees/manager.mjs +156 -8
  302. package/src/runtime/shared/worktrees/merge.mjs +31 -21
  303. package/src/runtime/shared/worktrees/paths.d.mts +6 -0
  304. package/src/runtime/terminal-bridge/client.mjs +44 -11
  305. package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
  306. package/src/runtime/tidy/apply.mjs +47 -2
  307. package/src/runtime/tidy/run-engines.mjs +11 -5
  308. package/src/session-runtime/agent-tool-routing.mjs +19 -13
  309. package/src/session-runtime/boot/apis.mjs +13 -5
  310. package/src/session-runtime/boot/facade.mjs +1 -0
  311. package/src/session-runtime/boot/infrastructure.mjs +6 -1
  312. package/src/session-runtime/boot/session.mjs +0 -1
  313. package/src/session-runtime/boot/tools.mjs +4 -1
  314. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
  315. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +65 -0
  316. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
  317. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +11 -4
  318. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +115 -18
  319. package/src/session-runtime/internal-tool-executor.mjs +6 -2
  320. package/src/session-runtime/lifecycle/cold-heir.mjs +188 -0
  321. package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
  322. package/src/session-runtime/lifecycle/session-catalog.mjs +12 -3
  323. package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
  324. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +29 -6
  325. package/src/session-runtime/lifecycle/teardown.mjs +72 -7
  326. package/src/session-runtime/lifecycle-api.mjs +1 -0
  327. package/src/session-runtime/mcp-glue/connect.mjs +17 -5
  328. package/src/session-runtime/model-route/set-route.mjs +2 -2
  329. package/src/session-runtime/native-web-search-usage.mjs +51 -0
  330. package/src/session-runtime/native-web-search.mjs +10 -1
  331. package/src/session-runtime/new-session-config.mjs +4 -2
  332. package/src/session-runtime/provider-auth/login.mjs +4 -0
  333. package/src/session-runtime/resource-scope-decorate.mjs +10 -3
  334. package/src/session-runtime/runtime-review-api.mjs +8 -2
  335. package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
  336. package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
  337. package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
  338. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +73 -7
  339. package/src/session-runtime/services/agent-tool/tag-registry.mjs +15 -1
  340. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
  341. package/src/session-runtime/services/agent-tool/worker-index.mjs +46 -7
  342. package/src/session-runtime/services/agent-tool.mjs +3 -0
  343. package/src/session-runtime/services/channel-admin.mjs +19 -3
  344. package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
  345. package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
  346. package/src/session-runtime/services/provider-admin.mjs +81 -15
  347. package/src/session-runtime/session-transcript-purge.mjs +32 -0
  348. package/src/session-runtime/session-turn-api.mjs +14 -5
  349. package/src/session-runtime/settings-builtin-tools-api.mjs +9 -0
  350. package/src/session-runtime/setup-tool/executor.mjs +36 -6
  351. package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
  352. package/src/session-runtime/setup-tool/settings-contract.mjs +13 -3
  353. package/src/session-runtime/setup-tool/tool-defs.mjs +13 -4
  354. package/src/session-runtime/skills-api.mjs +3 -5
  355. package/src/session-runtime/tool-surface.mjs +5 -1
  356. package/src/session-runtime/turn/compaction-gate.mjs +25 -0
  357. package/src/session-runtime/turn/session-ops.mjs +7 -5
  358. package/src/session-runtime/turn/side-question-ops.mjs +22 -0
  359. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +5 -1
  360. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +8 -3
  361. package/src/session-runtime/turn/turn-run/turn-settle.mjs +10 -0
  362. package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
  363. package/src/session-runtime/turn/turn-run.mjs +25 -9
  364. package/src/session-runtime/usage-stats-api.mjs +43 -11
  365. package/src/session-runtime/workspace/project-branches.mjs +7 -5
  366. package/src/session-runtime/workspace/transition-steps.mjs +129 -31
  367. package/src/session-runtime/workspace/transitions.mjs +190 -15
  368. package/src/standalone/daemon-agent-control.mjs +9 -1
  369. package/src/standalone/daemon-local-session-bridge.mjs +14 -1
  370. package/src/standalone/daemon-owner.mjs +17 -4
  371. package/src/standalone/daemon-pg-stop.mjs +51 -0
  372. package/src/standalone/daemon-stop-budget.d.mts +2 -0
  373. package/src/standalone/daemon-stop-budget.mjs +18 -0
  374. package/src/standalone/daemon-stored-session-views.mjs +2 -0
  375. package/src/standalone/daemon-telemetry.mjs +19 -0
  376. package/src/standalone/daemon.mjs +61 -1
  377. package/src/standalone/desktop-service-registry.mjs +5 -0
  378. package/src/standalone/local-session-runtime.mjs +70 -19
  379. package/src/standalone/session-client.mjs +42 -0
  380. package/src/standalone/session-protocol.mjs +7 -0
  381. package/src/standalone/session-proxy/projection.mjs +41 -4
  382. package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
  383. package/src/standalone/session-runtime-inline-host.mjs +1 -0
  384. package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
  385. package/src/standalone/session-service-api.mjs +6 -1
  386. package/src/standalone/session-state-patch.d.mts +2 -1
  387. package/src/standalone/session-state-patch.mjs +41 -1
  388. package/src/tui/App.jsx +25 -0
  389. package/src/tui/app/app-view/floating-panel.jsx +26 -1
  390. package/src/tui/app/btw-controller.mjs +118 -0
  391. package/src/tui/app/create-app-pickers.mjs +2 -0
  392. package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
  393. package/src/tui/app/shell-layout/surfaces.mjs +3 -1
  394. package/src/tui/app/slash-commands.mjs +13 -3
  395. package/src/tui/app/slash-dispatch/session-commands.mjs +19 -6
  396. package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
  397. package/src/tui/app/use-global-key-input.mjs +5 -12
  398. package/src/tui/app/use-prompt-handlers.mjs +11 -0
  399. package/src/tui/components/BtwPanel.jsx +53 -0
  400. package/src/tui/components/QuestionPanel.jsx +275 -0
  401. package/src/tui/components/question-panel-model.mjs +156 -0
  402. package/src/tui/dist/index.mjs +2413 -1465
  403. package/src/tui/session/context-state.mjs +4 -2
  404. package/src/tui/session/session-api/commands.mjs +10 -0
  405. package/src/tui/session/session-api/controls.mjs +2 -2
  406. package/src/tui/session/session-api/integrations.mjs +9 -2
  407. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  408. package/src/tui/session/session-api/lifecycle.mjs +2 -1
  409. package/src/tui/session/session-api/settings.mjs +6 -0
  410. package/src/tui/session/session-api.mjs +1 -0
  411. package/src/tui/session/tool-approval.mjs +10 -7
  412. package/src/tui/session/transcript-spill.mjs +14 -7
  413. package/src/tui/session/turn-stream.mjs +174 -31
  414. package/src/tui/session/turn.mjs +12 -5
  415. package/src/workflows/default/WORKFLOW.md +3 -1
@@ -11,12 +11,16 @@ export const OPENAI_COMPAT_PRESETS = {
11
11
  },
12
12
  // OpenCode Go - low-cost coding-model subscription gateway.
13
13
  'opencode-go': {
14
- baseURL: 'https://opencode.ai/zen/go/v1',
14
+ baseURL: 'https://opencode.ai/inference/go/v1',
15
15
  defaultModel: 'glm-5.2',
16
+ // The gateway expects an application User-Agent (not the SDK default).
17
+ extraHeaders: { 'User-Agent': 'mixdog' },
16
18
  },
17
19
  openrouter: {
18
20
  baseURL: 'https://openrouter.ai/api/v1',
19
21
  defaultModel: 'openrouter/auto',
22
+ // OpenRouter documents cache_control on Chat content blocks.
23
+ chatCacheControl: true,
20
24
  extraHeaders: {
21
25
  'HTTP-Referer': 'https://github.com/tribgames/mixdog',
22
26
  'X-OpenRouter-Title': 'mixdog',
@@ -0,0 +1,151 @@
1
+ /**
2
+ * openai-compat-reasoning-field.mjs — provider-specific reasoning shapes on the
3
+ * Chat Completions wire that the plain `reasoning_content` string path misses.
4
+ *
5
+ * Together AI (docs.together.ai/docs/inference/chat/reasoning): the chain of
6
+ * thought arrives on `reasoning` OR `reasoning_content` (model dependent), on
7
+ * the message and on each streaming delta, and must be passed back "under the
8
+ * same key" on prior assistant turns. vLLM reports it on `reasoning` (formerly
9
+ * `reasoning_content`), Groq on `message.reasoning` (reasoning_format parsed).
10
+ * OpenRouter reports plain text on `reasoning` next to `reasoning_details`.
11
+ *
12
+ * Mistral (docs.mistral.ai/studio/conversations/reasoning): with reasoning on,
13
+ * `message.content` / `delta.content` is a list of typed chunks —
14
+ * `{type:'thinking', thinking:[{type:'text', text}]}` and `{type:'text', text}`
15
+ * — and the full assistant message, thinking chunk included, goes back in the
16
+ * history. Receiving is by the response shape (an array), never by model name.
17
+ */
18
+
19
+ /** `message.providerMetadata[key].reasoningField`: the key a reply's reasoning arrived on. */
20
+ export const COMPAT_REASONING_METADATA_KEY = 'openaiCompat';
21
+
22
+ const TOGETHER_HOSTS = ['together.xyz', 'together.ai'];
23
+ const GROQ_HOSTS = ['groq.com'];
24
+ const MISTRAL_HOSTS = ['mistral.ai'];
25
+
26
+ function hostMatches(baseURL, domains) {
27
+ let host;
28
+ try {
29
+ host = new URL(String(baseURL || '')).hostname.toLowerCase();
30
+ } catch {
31
+ return false;
32
+ }
33
+ return domains.some((domain) => host === domain || host.endsWith(`.${domain}`));
34
+ }
35
+
36
+ export function isTogetherBaseURL(baseURL) {
37
+ return hostMatches(baseURL, TOGETHER_HOSTS);
38
+ }
39
+
40
+ /**
41
+ * Where an endpoint family reports reasoning and how a prior turn's reasoning
42
+ * goes back. `readsReasoningAlias`: the `reasoning` key is a reasoning field
43
+ * (otherwise only `reasoning_content` is). `resend`:
44
+ * same_key — back under the key it arrived on (Together, vLLM)
45
+ * reasoning — plain text as `reasoning`; reasoning_details win (OpenRouter)
46
+ * content_chunks — as a `thinking` chunk in the assistant content (Mistral)
47
+ * none — never echoed; the docs do not ask for it (Groq)
48
+ */
49
+ const SHAPES = Object.freeze({
50
+ together: Object.freeze({ id: 'together', readsReasoningAlias: true, resend: 'same_key' }),
51
+ vllm: Object.freeze({ id: 'vllm', readsReasoningAlias: true, resend: 'same_key' }),
52
+ groq: Object.freeze({ id: 'groq', readsReasoningAlias: true, resend: 'none' }),
53
+ mistral: Object.freeze({ id: 'mistral', readsReasoningAlias: false, resend: 'content_chunks' }),
54
+ openrouter: Object.freeze({ id: 'openrouter', readsReasoningAlias: true, resend: 'reasoning' }),
55
+ });
56
+
57
+ /**
58
+ * The reasoning shape of a provider, or null for the plain `reasoning_content`
59
+ * path. OpenRouter is by provider name, Together/Groq/Mistral by the provider's
60
+ * own base URL, vLLM (no fixed host) by the model row's `vllm` wire format.
61
+ */
62
+ export function compatReasoningShape({ providerName, baseURL, wireFormat } = {}) {
63
+ if (providerName === 'openrouter') return SHAPES.openrouter;
64
+ if (wireFormat === 'together' || isTogetherBaseURL(baseURL)) return SHAPES.together;
65
+ if (wireFormat === 'vllm') return SHAPES.vllm;
66
+ if (hostMatches(baseURL, GROQ_HOSTS)) return SHAPES.groq;
67
+ if (hostMatches(baseURL, MISTRAL_HOSTS)) return SHAPES.mistral;
68
+ return null;
69
+ }
70
+
71
+ /**
72
+ * The receive field worth recording for replay: `reasoning` (non-default key)
73
+ * or `content_chunks` (Mistral), per shape; `reasoning_content` is the default
74
+ * and needs no record. Null when nothing needs remembering.
75
+ */
76
+ export function replayReasoningField(shape, source) {
77
+ if (!shape) return null;
78
+ if (shape.resend === 'same_key' && source === 'reasoning') return 'reasoning';
79
+ if (shape.resend === 'content_chunks' && source === 'content_chunks') return 'content_chunks';
80
+ return null;
81
+ }
82
+
83
+ /** Whether a reply's reasoning source is captured under this shape. */
84
+ export function capturesShapeReasoning(shape, source) {
85
+ if (!shape) return source === 'content_chunks';
86
+ if (source === 'content_chunks') return true;
87
+ return source === 'reasoning_content' || (shape.readsReasoningAlias && source === 'reasoning');
88
+ }
89
+
90
+ /** Assistant content with the prior reasoning replayed as a leading `thinking` chunk. */
91
+ export function contentWithThinkingChunk(content, reasoning) {
92
+ const thinking = { type: 'thinking', thinking: [{ type: 'text', text: reasoning }] };
93
+ if (Array.isArray(content)) return [thinking, ...content];
94
+ return typeof content === 'string' && content ? [thinking, { type: 'text', text: content }] : [thinking];
95
+ }
96
+
97
+ function thinkingText(thinking) {
98
+ if (typeof thinking === 'string') return thinking;
99
+ if (!Array.isArray(thinking)) return '';
100
+ return thinking
101
+ .map((inner) => (typeof inner === 'string' ? inner : typeof inner?.text === 'string' ? inner.text : ''))
102
+ .join('');
103
+ }
104
+
105
+ /**
106
+ * Ordered `{kind:'reasoning'|'text', text}` parts of an array-shaped `content`,
107
+ * or null when `content` is not an array (the plain string/absent shape).
108
+ */
109
+ export function chatContentParts(content) {
110
+ if (!Array.isArray(content)) return null;
111
+ const parts = [];
112
+ for (const chunk of content) {
113
+ if (typeof chunk === 'string') {
114
+ parts.push({ kind: 'text', text: chunk });
115
+ } else if (chunk?.type === 'thinking') {
116
+ parts.push({ kind: 'reasoning', text: thinkingText(chunk.thinking) });
117
+ } else if (chunk?.type === 'text' && typeof chunk.text === 'string') {
118
+ parts.push({ kind: 'text', text: chunk.text });
119
+ }
120
+ }
121
+ return parts;
122
+ }
123
+
124
+ /**
125
+ * Content text, reasoning and reasoning source of one non-streaming message.
126
+ * `reasoning_content` keeps priority; the `reasoning` alias is read only under
127
+ * a shape that reports reasoning there; thinking chunks fill in when no field
128
+ * carried reasoning.
129
+ */
130
+ export function readChatMessage(message, { shape = null } = {}) {
131
+ const parts = chatContentParts(message?.content);
132
+ const content = parts
133
+ ? parts
134
+ .filter((part) => part.kind === 'text')
135
+ .map((part) => part.text)
136
+ .join('')
137
+ : typeof message?.content === 'string'
138
+ ? message.content
139
+ : '';
140
+ if (typeof message?.reasoning_content === 'string') {
141
+ return { content, reasoningContent: message.reasoning_content, reasoningSource: 'reasoning_content' };
142
+ }
143
+ if (shape?.readsReasoningAlias && typeof message?.reasoning === 'string') {
144
+ return { content, reasoningContent: message.reasoning, reasoningSource: 'reasoning' };
145
+ }
146
+ const thinking = parts?.filter((part) => part.kind === 'reasoning');
147
+ if (thinking?.length) {
148
+ return { content, reasoningContent: thinking.map((part) => part.text).join(''), reasoningSource: 'content_chunks' };
149
+ }
150
+ return { content, reasoningContent: null, reasoningSource: null };
151
+ }
@@ -7,20 +7,20 @@ import {
7
7
  writeXaiResponsesCacheTrace,
8
8
  } from './openai-compat-xai.mjs';
9
9
  import { createProviderReplay } from './lib/provider-replay.mjs';
10
+ import { reportedCostUsd } from './lib/usage-primitives.mjs';
10
11
  import { stampStreamOutcome, STREAM_TRANSPORTS } from './lib/stream-outcome.mjs';
11
12
  import { failingFinishReasonError } from './openai-compat-stream-common.mjs';
12
-
13
- const reportedNumber = (value) =>
14
- value == null || (typeof value === 'string' && value.trim() === '') ? Number.NaN : Number(value);
13
+ import {
14
+ COMPAT_REASONING_METADATA_KEY,
15
+ capturesShapeReasoning,
16
+ replayReasoningField,
17
+ } from './openai-compat-reasoning-field.mjs';
15
18
 
16
19
  export function compatReportedCostUsd(providerName, usage) {
17
- if (providerName === 'openrouter') {
18
- const cost = reportedNumber(usage?.cost);
19
- return Number.isFinite(cost) && cost >= 0 ? cost : undefined;
20
- }
20
+ if (providerName === 'openrouter') return reportedCostUsd(usage?.cost);
21
21
  if (providerName === 'xai') {
22
- const ticks = reportedNumber(usage?.cost_in_usd_ticks);
23
- return Number.isFinite(ticks) && ticks >= 0 ? Number((ticks * 1e-10).toFixed(8)) : undefined;
22
+ const ticks = reportedCostUsd(usage?.cost_in_usd_ticks);
23
+ return ticks === undefined ? undefined : Number((ticks * 1e-10).toFixed(8));
24
24
  }
25
25
  return undefined;
26
26
  }
@@ -79,12 +79,11 @@ export function traceCompatResponseUsage({
79
79
  });
80
80
  }
81
81
 
82
- // Responses-wire reported cost: a gateway `cost` (decimal USD) when present,
83
- // else xAI ticks. null/empty/negative is "not reported", never a reported $0.
82
+ // Responses-wire reported cost: xAI `cost_in_usd_ticks` when present, else a
83
+ // gateway `cost` (decimal USD). null/empty/negative is "not reported", never a
84
+ // reported $0.
84
85
  export function responsesReportedCostUsd(usage) {
85
- const cost = reportedNumber(usage?.cost);
86
- if (Number.isFinite(cost) && cost >= 0) return cost;
87
- return costUsdFromTicks(usage?.cost_in_usd_ticks);
86
+ return costUsdFromTicks(usage?.cost_in_usd_ticks) ?? reportedCostUsd(usage?.cost);
88
87
  }
89
88
 
90
89
  export function chatCompletionUsage(providerName, usage) {
@@ -138,6 +137,7 @@ export function normalizeCompatChatResponse({
138
137
  cacheRoutingKey,
139
138
  cacheRouting,
140
139
  replaysReasoningContent,
140
+ reasoningShape = null,
141
141
  }) {
142
142
  const response = assembled.response;
143
143
  const choice = response.choices[0];
@@ -146,7 +146,7 @@ export function normalizeCompatChatResponse({
146
146
  const failingFinish = failingFinishReasonError(stopReason, providerName);
147
147
  if (failingFinish) {
148
148
  const err = failingFinish;
149
- const partialContent = choice?.message?.content || '';
149
+ const partialContent = assembled.content || '';
150
150
  Object.assign(err, {
151
151
  partialContent,
152
152
  partialToolCalls: Array.isArray(toolCalls) && toolCalls.length ? toolCalls : undefined,
@@ -173,7 +173,7 @@ export function normalizeCompatChatResponse({
173
173
  code: 'PROVIDER_INCOMPLETE',
174
174
  providerIncomplete: true,
175
175
  finishReason: stopReason,
176
- partialContent: choice?.message?.content || '',
176
+ partialContent: assembled.content || '',
177
177
  partialToolCalls: toolCalls,
178
178
  model: response.model || useModel,
179
179
  responseId: response.id || null,
@@ -205,14 +205,30 @@ export function normalizeCompatChatResponse({
205
205
  cachedTokens: extractCompatCachedTokens(response.usage),
206
206
  });
207
207
  }
208
+ // Together/vLLM/Groq/OpenRouter report reasoning on `reasoning` or
209
+ // `reasoning_content`; Mistral reports it as thinking chunks inside
210
+ // `content`. Both are captured by the provider's own shape / the response
211
+ // shape, whatever the replay flag says.
212
+ const reasoningField = replayReasoningField(reasoningShape, assembled.reasoningSource);
208
213
  const capturesReasoningContent =
209
- providerName === 'deepseek' || providerName === 'xai' || providerName === 'mixdog-local' || replaysReasoningContent;
214
+ providerName === 'deepseek' ||
215
+ providerName === 'xai' ||
216
+ providerName === 'mixdog-local' ||
217
+ replaysReasoningContent ||
218
+ capturesShapeReasoning(reasoningShape, assembled.reasoningSource);
210
219
  const reasoningContent =
211
220
  capturesReasoningContent && typeof assembled.reasoningContent === 'string' ? assembled.reasoningContent : null;
212
221
  const reasoningDetails =
213
222
  providerName === 'openrouter' && Array.isArray(choice?.message?.reasoning_details)
214
223
  ? choice.message.reasoning_details
215
224
  : null;
225
+ // Replay sends reasoning back under the field it arrived on.
226
+ const providerMetadata = {
227
+ ...(reasoningDetails?.length ? { openrouter: { reasoning_details: reasoningDetails } } : {}),
228
+ ...(reasoningContent !== null && reasoningField
229
+ ? { [COMPAT_REASONING_METADATA_KEY]: { reasoningField } }
230
+ : {}),
231
+ };
216
232
  return {
217
233
  content: assembled.content || '',
218
234
  // Streamed chunks can omit `model`; fall back to the requested
@@ -228,11 +244,7 @@ export function normalizeCompatChatResponse({
228
244
  // instead of silently treating a truncated answer as complete.
229
245
  ...(stopReason === 'length' && (assembled.content || '').length > 0 ? { truncated: true } : {}),
230
246
  ...(reasoningContent !== null ? { reasoningContent } : {}),
231
- ...(reasoningDetails?.length
232
- ? {
233
- providerMetadata: { openrouter: { reasoning_details: reasoningDetails } },
234
- }
235
- : {}),
247
+ ...(Object.keys(providerMetadata).length ? { providerMetadata } : {}),
236
248
  usage: response.usage ? chatCompletionUsage(providerName, response.usage) : undefined,
237
249
  };
238
250
  }
@@ -332,8 +344,14 @@ export function normalizeXaiResponsesWebSocket({
332
344
  cacheLane,
333
345
  }) {
334
346
  const responseId = result.responseId || previousResponseId || null;
335
- const encryptedReasoningItems = encryptedXaiReasoningItems(result.responseItems);
336
- const providerReplay = createProviderReplay('xai-responses', result.responseItems);
347
+ // The WS send result drops the collector's `responseItems`; its own
348
+ // owner-tagged `providerReplay` (traceProvider 'xai') still carries every
349
+ // output item in order: encrypted reasoning and server-executed tool_search
350
+ // call/output pairs. Always taken, so they survive to the next turn as xAI
351
+ // requires.
352
+ const responseItems = result.responseItems ?? result.providerReplay?.items;
353
+ const encryptedReasoningItems = encryptedXaiReasoningItems(responseItems);
354
+ const providerReplay = createProviderReplay('xai-responses', responseItems);
337
355
  const encryptedReasoningHistory = xaiEncryptedReasoningHistory(opts, messages, encryptedReasoningItems);
338
356
  const rawUsage = result.usage?.raw || result.usage || null;
339
357
  const response = {
@@ -3,11 +3,17 @@
3
3
  // carries the label, the caller callbacks and the leaked-text relay.
4
4
  import { typedStatusFrom } from './retry-classifier.mjs';
5
5
  import { applyCompatErrorContract } from './openai-compat-error-contract.mjs';
6
- import { customToolCallFromResponseItem, nativeToolSearchCallFromArguments } from './custom-tool-wire.mjs';
6
+ import {
7
+ customToolCallFromResponseItem,
8
+ nativeToolSearchCallFromArguments,
9
+ withToolCallNamespace,
10
+ } from './custom-tool-wire.mjs';
11
+ import { createRefusals } from './openai-ws-response-state/refusals.mjs';
7
12
  import { emitCompatToolCallOnce } from './openai-compat-stream-common.mjs';
8
13
  import { truncatedCompatStreamError, parseCompletedToolCallArgumentsJson } from './lib/openai-tool-args.mjs';
9
14
  import { incompleteReasonFromEvent, isMaxOutputIncompleteReason } from './lib/responses-terminal-fields.mjs';
10
15
  import { responsesUsage } from './openai-compat-response-normalization.mjs';
16
+ import { normalizeGatewayErrorDetail } from './provider-error-kind.mjs';
11
17
 
12
18
  // An incomplete response was still billed: carry its reported usage on the
13
19
  // error so the provider-boundary accounting records it.
@@ -35,7 +41,9 @@ function signal(ctx, kind) {
35
41
  // through the fatal-code deny-list / default-retry classification.
36
42
  function typedResponsesFailure(message, event) {
37
43
  const err = new Error(message);
38
- const detail = event?.response?.error || event?.error || null;
44
+ // A gateway's canonical error_type (OpenRouter's top-level `error_type`)
45
+ // replaces the lossy native code before anything classifies it.
46
+ const detail = normalizeGatewayErrorDetail(event?.response?.error || event?.error || null, event);
39
47
  const typed = typedStatusFrom(detail, event);
40
48
  if (typed) err.httpStatus = typed;
41
49
  const code = detail?.code ?? detail?.type ?? event?.code ?? null;
@@ -61,18 +69,22 @@ function reconcileCompatFunctionCallItem(state, item, label, onToolCall) {
61
69
  if (tc) {
62
70
  if (!tc.id && item.call_id) tc.id = item.call_id;
63
71
  if (!tc.name && item.name) tc.name = item.name;
72
+ withToolCallNamespace(tc, item);
64
73
  if (tc.id && tc.name) delete tc._pendingItemId;
65
74
  emitCompatToolCallOnce(state, tc, onToolCall);
66
75
  } else if (item.call_id && item.name) {
67
- const call = {
68
- id: item.call_id,
69
- name: item.name,
70
- arguments: parseCompletedToolCallArgumentsJson(item.arguments, label, {
76
+ const call = withToolCallNamespace(
77
+ {
71
78
  id: item.call_id,
72
79
  name: item.name,
73
- finishReason: 'done',
74
- }),
75
- };
80
+ arguments: parseCompletedToolCallArgumentsJson(item.arguments, label, {
81
+ id: item.call_id,
82
+ name: item.name,
83
+ finishReason: 'done',
84
+ }),
85
+ },
86
+ item
87
+ );
76
88
  state.toolCalls.push(call);
77
89
  emitCompatToolCallOnce(state, call, onToolCall);
78
90
  }
@@ -81,6 +93,9 @@ function reconcileCompatFunctionCallItem(state, item, label, onToolCall) {
81
93
 
82
94
  function pushToolSearchCall(state, item, ctx) {
83
95
  if (item?.type !== 'tool_search_call') return;
96
+ // Server-executed search already ran inside the response; it stays in
97
+ // providerReplay only and is never a local load_tool dispatch.
98
+ if (item.execution === 'server') return;
84
99
  const callId = item.call_id || item.id || '';
85
100
  if (!callId || state.toolCalls.some((call) => call.id === callId)) return;
86
101
  const searchArgs =
@@ -165,10 +180,10 @@ function onReasoningDelta(event, state, ctx) {
165
180
  function onOutputItemAdded(event, state, ctx) {
166
181
  const type = event.item?.type;
167
182
  if (type === 'function_call') {
168
- state.pendingCalls.set(event.item.id || '', {
169
- name: event.item.name || '',
170
- callId: event.item.call_id || '',
171
- });
183
+ state.pendingCalls.set(
184
+ event.item.id || '',
185
+ withToolCallNamespace({ name: event.item.name || '', callId: event.item.call_id || '' }, event.item)
186
+ );
172
187
  state.toolTracker?.mark(event.item);
173
188
  state.toolInFlight = true;
174
189
  } else if (type === 'custom_tool_call' || type === 'tool_search_call') {
@@ -194,26 +209,47 @@ function onToolInputDelta(event, state, ctx) {
194
209
  function onFunctionCallArgumentsDone(event, state, ctx) {
195
210
  const itemId = event.item_id || '';
196
211
  const pending = state.pendingCalls.get(itemId);
197
- const call = {
198
- id: pending?.callId || event.call_id || '',
199
- name: pending?.name || event.name || '',
200
- // `*.done` ⇒ arguments are complete; a parse failure is
201
- // deterministic bad JSON (permanent), not stream truncation.
202
- arguments: parseCompletedToolCallArgumentsJson(event.arguments, ctx.label, {
203
- id: pending?.callId || event.call_id,
204
- name: pending?.name || event.name,
205
- finishReason: 'done',
206
- }),
207
- _pendingItemId: itemId,
208
- };
212
+ const call = withToolCallNamespace(
213
+ {
214
+ id: pending?.callId || event.call_id || '',
215
+ name: pending?.name || event.name || '',
216
+ // `*.done` ⇒ arguments are complete; a parse failure is
217
+ // deterministic bad JSON (permanent), not stream truncation.
218
+ arguments: parseCompletedToolCallArgumentsJson(event.arguments, ctx.label, {
219
+ id: pending?.callId || event.call_id,
220
+ name: pending?.name || event.name,
221
+ finishReason: 'done',
222
+ }),
223
+ _pendingItemId: itemId,
224
+ },
225
+ pending
226
+ );
209
227
  state.toolCalls.push(call);
210
228
  if (call.id && call.name) delete call._pendingItemId;
211
229
  emitCompatToolCallOnce(state, call, ctx.onToolCall);
212
230
  signal(ctx, 'tool');
213
231
  }
214
232
 
233
+ // Refusal parts (streamed deltas, done text, final message parts) fold into
234
+ // one typed refusal on state.refusals; the stream collector turns it into a
235
+ // `stopReason:'refusal'` result instead of an empty success.
236
+ const refusalsOf = (state) => (state.refusals ||= createRefusals());
237
+
238
+ function onRefusalDelta(event, state, ctx) {
239
+ state.sawOutput = true;
240
+ refusalsOf(state).delta(event);
241
+ signal(ctx, 'semantic');
242
+ }
243
+
244
+ function onRefusalDone(event, state, ctx) {
245
+ state.sawOutput = true;
246
+ refusalsOf(state).done(event);
247
+ signal(ctx, 'semantic');
248
+ }
249
+
215
250
  function onOutputItemDone(event, state, ctx) {
216
251
  const item = event.item || {};
252
+ if (item.type === 'message') refusalsOf(state).absorbMessage(item);
217
253
  if (item.type === 'function_call') {
218
254
  const itemId = reconcileCompatFunctionCallItem(state, item, ctx.label, ctx.onToolCall);
219
255
  // Drop the resolved function item from pendingCalls before
@@ -342,6 +378,8 @@ const RESPONSES_EVENT_HANDLERS = new Map([
342
378
  ['response.output_text.delta', onOutputTextDelta],
343
379
  ['response.reasoning_text.delta', onReasoningDelta],
344
380
  ['response.reasoning_summary_text.delta', onReasoningDelta],
381
+ ['response.refusal.delta', onRefusalDelta],
382
+ ['response.refusal.done', onRefusalDone],
345
383
  ['response.output_item.added', onOutputItemAdded],
346
384
  ['response.function_call_arguments.delta', onToolInputDelta],
347
385
  ['response.custom_tool_call_input.delta', onToolInputDelta],