mixdog 0.9.63 → 0.9.65

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 (408) hide show
  1. package/README.md +3 -0
  2. package/package.json +9 -2
  3. package/scripts/code-graph-description-contract.mjs +3 -3
  4. package/scripts/verify-release-assets.mjs +2 -2
  5. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +11 -14
  6. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +6 -6
  7. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -2
  8. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
  9. package/src/runtime/agent/orchestrator/config.mjs +19 -124
  10. package/src/runtime/agent/orchestrator/context/collect.mjs +6 -6
  11. package/src/runtime/agent/orchestrator/dispatch-persist.mjs +2 -2
  12. package/src/runtime/agent/orchestrator/internal-agents.mjs +2 -2
  13. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +1 -1
  14. package/src/runtime/agent/orchestrator/mcp/client.mjs +4 -4
  15. package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +2 -2
  16. package/src/runtime/agent/orchestrator/providers/anthropic-betas.mjs +4 -4
  17. package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +2 -2
  18. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +4 -4
  19. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +333 -0
  20. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +2 -2
  21. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -4
  22. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +1 -1
  23. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +3 -277
  24. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +2 -2
  25. package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +1 -1
  26. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +2 -2
  27. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +6 -6
  28. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +196 -0
  29. package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +460 -0
  30. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +14 -593
  31. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +1 -1
  32. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +1 -1
  33. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +1 -1
  34. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +4 -4
  35. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +2 -2
  36. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +5 -280
  37. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +357 -0
  38. package/src/runtime/agent/orchestrator/providers/openai-ws-headers.mjs +216 -0
  39. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +2 -188
  40. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +2 -2
  41. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +2 -2
  42. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +1 -1
  43. package/src/runtime/agent/orchestrator/providers/provider-catalog-cache.mjs +1 -1
  44. package/src/runtime/agent/orchestrator/providers/registry.mjs +1 -1
  45. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -2
  46. package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +1 -1
  47. package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.mjs +1 -1
  48. package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +3 -3
  49. package/src/runtime/agent/orchestrator/session/compact/budget.mjs +2 -2
  50. package/src/runtime/agent/orchestrator/session/compact/file-reattach.mjs +2 -2
  51. package/src/runtime/agent/orchestrator/session/compact/summary-schema.mjs +1 -1
  52. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +1 -1
  53. package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +2 -2
  54. package/src/runtime/agent/orchestrator/session/context-utils.mjs +4 -4
  55. package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +1 -1
  56. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +17 -0
  57. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +1 -1
  58. package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +18 -26
  59. package/src/runtime/agent/orchestrator/session/loop/termination.mjs +1 -1
  60. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +3 -3
  61. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +1 -0
  62. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
  63. package/src/runtime/agent/orchestrator/session/manager/delivered-completions.mjs +1 -1
  64. package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +1 -1
  65. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +49 -0
  66. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +49 -0
  67. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +260 -0
  68. package/src/runtime/agent/orchestrator/session/store/serialize.mjs +72 -0
  69. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +163 -0
  70. package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +1 -1
  71. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +1 -1
  72. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +4 -1
  73. package/src/runtime/agent/orchestrator/session/store.mjs +9 -561
  74. package/src/runtime/agent/orchestrator/session/tool-envelope.mjs +1 -1
  75. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +2 -2
  76. package/src/runtime/agent/orchestrator/stall-policy.mjs +11 -11
  77. package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +1 -1
  78. package/src/runtime/agent/orchestrator/tools/bash-session.mjs +2 -2
  79. package/src/runtime/agent/orchestrator/tools/builtin/advisory-lock.mjs +1 -1
  80. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
  81. package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +1 -1
  82. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +2 -154
  83. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +1 -1
  84. package/src/runtime/agent/orchestrator/tools/builtin/cwd-utils.mjs +1 -1
  85. package/src/runtime/agent/orchestrator/tools/builtin/fs-reachability.mjs +1 -1
  86. package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +1 -1
  87. package/src/runtime/agent/orchestrator/tools/builtin/glob-walk.mjs +1 -1
  88. package/src/runtime/agent/orchestrator/tools/builtin/path-locks.mjs +1 -1
  89. package/src/runtime/agent/orchestrator/tools/builtin/path-utils.mjs +1 -1
  90. package/src/runtime/agent/orchestrator/tools/builtin/read-args.mjs +2 -2
  91. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +2 -3
  92. package/src/runtime/agent/orchestrator/tools/builtin/read-image-resize.mjs +4 -4
  93. package/src/runtime/agent/orchestrator/tools/builtin/read-open.mjs +1 -1
  94. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +1 -1
  95. package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +2 -2
  96. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +5 -5
  97. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +1 -1
  98. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +2 -2
  99. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +2 -2
  100. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-spawn.mjs +519 -0
  101. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +5 -449
  102. package/src/runtime/agent/orchestrator/tools/builtin/snapshot-helpers.mjs +1 -1
  103. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +212 -0
  104. package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -1
  105. package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +1 -7
  106. package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +9 -36
  107. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +15 -3
  108. package/src/runtime/agent/orchestrator/tools/code-graph/search-references.mjs +429 -0
  109. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +2 -395
  110. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +2 -2
  111. package/src/runtime/agent/orchestrator/tools/code-graph/text-mask.mjs +1 -1
  112. package/src/runtime/agent/orchestrator/tools/code-graph/trusted-roots.mjs +1 -1
  113. package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
  114. package/src/runtime/agent/orchestrator/tools/code-graph-state.mjs +3 -3
  115. package/src/runtime/agent/orchestrator/tools/mutation-planner.mjs +5 -5
  116. package/src/runtime/agent/orchestrator/tools/next-call-utils.mjs +1 -1
  117. package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +1 -1
  118. package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +7 -7
  119. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +72 -9
  120. package/src/runtime/agent/orchestrator/tools/patch/parsing.mjs +4 -4
  121. package/src/runtime/agent/orchestrator/tools/patch/paths.mjs +1 -1
  122. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +1 -1
  123. package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +4 -4
  124. package/src/runtime/agent/orchestrator/tools/patch.mjs +1 -1
  125. package/src/runtime/agent/orchestrator/tools/result-compression.mjs +3 -3
  126. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +2 -444
  127. package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +505 -0
  128. package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +2 -2
  129. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +1 -1
  130. package/src/runtime/channels/lib/backend-dispatch.mjs +20 -5
  131. package/src/runtime/channels/lib/scheduler.mjs +1 -1
  132. package/src/runtime/channels/lib/telegram-format.mjs +1 -1
  133. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +4 -4
  134. package/src/runtime/channels/tool-defs.mjs +2 -3
  135. package/src/runtime/memory/index.mjs +1 -5
  136. package/src/runtime/memory/lib/core-memory-candidates.mjs +357 -0
  137. package/src/runtime/memory/lib/core-memory-store.mjs +7 -357
  138. package/src/runtime/memory/lib/cycle-signatures.mjs +1 -1
  139. package/src/runtime/memory/lib/embedding-model-config.mjs +1 -1
  140. package/src/runtime/memory/lib/embedding-provider.mjs +1 -5
  141. package/src/runtime/memory/lib/embedding-worker.mjs +1 -5
  142. package/src/runtime/memory/lib/ko-morph.mjs +2 -2
  143. package/src/runtime/memory/lib/memory-config-flags.mjs +2 -5
  144. package/src/runtime/memory/lib/memory-cycle-requests.mjs +3 -7
  145. package/src/runtime/memory/lib/memory-cycle1.mjs +4 -8
  146. package/src/runtime/memory/lib/memory-cycle2-gate.mjs +1 -1
  147. package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +1 -1
  148. package/src/runtime/memory/lib/memory-cycle2-shared.mjs +2 -5
  149. package/src/runtime/memory/lib/memory-cycle3.mjs +1 -5
  150. package/src/runtime/memory/lib/memory-embed.mjs +2 -6
  151. package/src/runtime/memory/lib/memory-log.mjs +8 -0
  152. package/src/runtime/memory/lib/memory-ops-policy.mjs +4 -8
  153. package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +1 -1
  154. package/src/runtime/memory/lib/memory-recall-store.mjs +2 -193
  155. package/src/runtime/memory/lib/memory-score.mjs +1 -1
  156. package/src/runtime/memory/lib/memory-text-utils.mjs +2 -2
  157. package/src/runtime/memory/lib/memory.mjs +2 -6
  158. package/src/runtime/memory/lib/pg/adapter.mjs +2 -6
  159. package/src/runtime/memory/lib/pg/process.mjs +1 -5
  160. package/src/runtime/memory/lib/pg/supervisor.mjs +1 -5
  161. package/src/runtime/memory/lib/recall-format.mjs +2 -2
  162. package/src/runtime/memory/lib/recall-scoring.mjs +195 -0
  163. package/src/runtime/memory/lib/runtime-fetcher.mjs +1 -5
  164. package/src/runtime/memory/lib/trace-store.mjs +2 -6
  165. package/src/runtime/search/lib/http-fetch.mjs +6 -6
  166. package/src/runtime/search/lib/web-tools.mjs +2 -2
  167. package/src/runtime/shared/buffered-appender.mjs +1 -1
  168. package/src/runtime/shared/child-guardian.mjs +1 -1
  169. package/src/runtime/shared/child-spawn-gate.mjs +1 -1
  170. package/src/runtime/shared/config.mjs +4 -4
  171. package/src/runtime/shared/launcher-control.mjs +9 -10
  172. package/src/runtime/shared/llm/index.mjs +5 -20
  173. package/src/runtime/shared/markdown-frontmatter.mjs +1 -1
  174. package/src/runtime/shared/memory-snapshot.mjs +4 -4
  175. package/src/runtime/shared/pristine-execution.mjs +1 -1
  176. package/src/runtime/shared/process-lifecycle.mjs +0 -1
  177. package/src/runtime/shared/process-shutdown.mjs +1 -1
  178. package/src/runtime/shared/resource-admission.mjs +2 -2
  179. package/src/runtime/shared/schedule-session-run.mjs +1 -1
  180. package/src/runtime/shared/schedules-db.mjs +1 -1
  181. package/src/runtime/shared/service-discovery.mjs +2 -2
  182. package/src/runtime/shared/staged-update.mjs +6 -6
  183. package/src/runtime/shared/tool-execution-contract.mjs +1 -1
  184. package/src/runtime/shared/tool-primitives.mjs +1 -1
  185. package/src/runtime/shared/tool-surface.mjs +2 -2
  186. package/src/runtime/shared/turn-snapshot.mjs +184 -0
  187. package/src/runtime/shared/update-checker.mjs +1 -1
  188. package/src/runtime/shared/user-cwd.mjs +3 -3
  189. package/src/runtime/shared/user-data-guard.mjs +4 -4
  190. package/src/runtime/shared/workspace-router.mjs +5 -5
  191. package/src/session-runtime/config-helpers.mjs +2 -3
  192. package/src/session-runtime/config-lifecycle.mjs +1 -1
  193. package/src/session-runtime/hitch-profile.mjs +1 -1
  194. package/src/session-runtime/lifecycle-api.mjs +6 -4
  195. package/src/session-runtime/model-recency.mjs +5 -5
  196. package/src/session-runtime/plugin-mcp.mjs +1 -1
  197. package/src/session-runtime/provider-request-snapshot.mjs +338 -0
  198. package/src/session-runtime/runtime-core.mjs +4 -0
  199. package/src/session-runtime/session-text.mjs +4 -4
  200. package/src/session-runtime/session-turn-api.mjs +7 -0
  201. package/src/session-runtime/tool-catalog-schema.mjs +197 -0
  202. package/src/session-runtime/tool-catalog.mjs +6 -483
  203. package/src/session-runtime/tool-defs.mjs +1 -1
  204. package/src/standalone/agent-task-status.mjs +1 -1
  205. package/src/standalone/agent-tool/helpers.mjs +2 -2
  206. package/src/standalone/channel-admin.mjs +4 -4
  207. package/src/standalone/explore-tool.mjs +3 -3
  208. package/src/standalone/hook-bus/config.mjs +1 -1
  209. package/src/standalone/hook-bus/constants.mjs +1 -1
  210. package/src/standalone/hook-bus/rules.mjs +1 -1
  211. package/src/standalone/projects.mjs +1 -1
  212. package/src/standalone/provider-admin.mjs +2 -2
  213. package/src/tui/App.jsx +1 -1
  214. package/src/tui/app/app-format.mjs +2 -2
  215. package/src/tui/app/clipboard.mjs +3 -3
  216. package/src/tui/app/input-parsers.mjs +1 -1
  217. package/src/tui/app/text-layout.mjs +1 -1
  218. package/src/tui/app/transcript-row-estimate.mjs +360 -0
  219. package/src/tui/app/transcript-window.mjs +5 -347
  220. package/src/tui/app/use-mouse-input.mjs +1 -1
  221. package/src/tui/app/use-prompt-handlers.mjs +1 -1
  222. package/src/tui/components/tool-execution/surface-detail.mjs +9 -9
  223. package/src/tui/components/tool-execution/text-format.mjs +2 -2
  224. package/src/tui/components/tool-output-format.mjs +7 -7
  225. package/src/tui/display-width.mjs +4 -4
  226. package/src/tui/dist/index.mjs +187 -99
  227. package/src/tui/engine/agent-envelope.mjs +5 -5
  228. package/src/tui/engine/live-share.mjs +100 -0
  229. package/src/tui/engine/notification-plan.mjs +1 -1
  230. package/src/tui/engine/queue-helpers.mjs +3 -3
  231. package/src/tui/engine/render-timing.mjs +4 -5
  232. package/src/tui/engine/session-api-ext.mjs +6 -3
  233. package/src/tui/engine/tool-result-status.mjs +5 -5
  234. package/src/tui/engine/tool-result-text.mjs +1 -1
  235. package/src/tui/engine/transcript-spill.mjs +585 -0
  236. package/src/tui/engine/tui-steering-persist.mjs +1 -1
  237. package/src/tui/engine.mjs +29 -474
  238. package/src/tui/lib/voice-setup.mjs +1 -1
  239. package/src/tui/markdown/format-token.mjs +1 -1
  240. package/src/tui/markdown/render-ansi.mjs +1 -1
  241. package/src/tui/markdown/table-layout.mjs +4 -4
  242. package/src/tui/paste-attachments.mjs +1 -1
  243. package/src/tui/prompt-history-store.mjs +3 -3
  244. package/src/tui/statusline-ansi-bridge.mjs +2 -2
  245. package/src/tui/theme.mjs +1 -1
  246. package/src/tui/transcript-tool-failures.mjs +2 -2
  247. package/src/ui/ansi.mjs +0 -9
  248. package/src/ui/statusline-format.mjs +2 -4
  249. package/scripts/_bench-cwc.json +0 -20
  250. package/scripts/_jitter-fuzz.jsx +0 -42
  251. package/scripts/_jitter-fuzz2.jsx +0 -30
  252. package/scripts/_jitter-probe.jsx +0 -35
  253. package/scripts/_jp2.jsx +0 -16
  254. package/scripts/_smoke_wd.mjs +0 -7
  255. package/scripts/abort-recovery-test.mjs +0 -175
  256. package/scripts/agent-dispatch-abort-compose-test.mjs +0 -31
  257. package/scripts/agent-live-arg-guard-smoke.mjs +0 -20
  258. package/scripts/agent-live-path-suffix-smoke.mjs +0 -34
  259. package/scripts/agent-live-toolcall-args-smoke.mjs +0 -45
  260. package/scripts/agent-loop-policy-test.mjs +0 -37
  261. package/scripts/agent-model-liveness-test.mjs +0 -763
  262. package/scripts/agent-parallel-smoke.mjs +0 -435
  263. package/scripts/agent-route-batch-test.mjs +0 -40
  264. package/scripts/agent-tag-reuse-smoke.mjs +0 -441
  265. package/scripts/agent-terminal-reap-test.mjs +0 -252
  266. package/scripts/agent-trace-io-test.mjs +0 -133
  267. package/scripts/ansi-color-capability-test.mjs +0 -90
  268. package/scripts/anthropic-admission-retry-integration-test.mjs +0 -119
  269. package/scripts/anthropic-maxtokens-test.mjs +0 -119
  270. package/scripts/anthropic-oauth-refresh-race-test.mjs +0 -397
  271. package/scripts/anthropic-transport-policy-test.mjs +0 -726
  272. package/scripts/apply-patch-edit-smoke.mjs +0 -71
  273. package/scripts/arg-guard-test.mjs +0 -93
  274. package/scripts/async-notify-settlement-test.mjs +0 -99
  275. package/scripts/atomic-lock-tryonce-test.mjs +0 -125
  276. package/scripts/background-task-meta-smoke.mjs +0 -38
  277. package/scripts/bench-run.mjs +0 -508
  278. package/scripts/boot-smoke.mjs +0 -137
  279. package/scripts/build-runtime-windows.ps1 +0 -242
  280. package/scripts/channel-daemon-smoke.mjs +0 -1103
  281. package/scripts/code-graph-aggregate-cwd-test.mjs +0 -158
  282. package/scripts/code-graph-disk-hit-test.mjs +0 -290
  283. package/scripts/code-graph-dispatch-test.mjs +0 -96
  284. package/scripts/code-graph-root-federation-test.mjs +0 -273
  285. package/scripts/compact-active-turn-test.mjs +0 -68
  286. package/scripts/compact-file-reattach-test.mjs +0 -88
  287. package/scripts/compact-pressure-test.mjs +0 -788
  288. package/scripts/compact-prior-context-flatten-test.mjs +0 -252
  289. package/scripts/compact-recall-digest-test.mjs +0 -57
  290. package/scripts/compact-smoke.mjs +0 -1017
  291. package/scripts/compact-trigger-migration-smoke.mjs +0 -261
  292. package/scripts/compacted-placeholder-scrub-test.mjs +0 -63
  293. package/scripts/context-mcp-metering-test.mjs +0 -1406
  294. package/scripts/debounced-skills-async-save-test.mjs +0 -57
  295. package/scripts/deferred-tool-loading-test.mjs +0 -250
  296. package/scripts/desktop-session-bridge-test.mjs +0 -1013
  297. package/scripts/dispatch-persist-recovery-test.mjs +0 -141
  298. package/scripts/embedding-worker-exit-test.mjs +0 -76
  299. package/scripts/execution-completion-dedup-test.mjs +0 -205
  300. package/scripts/execution-pending-resume-kick-test.mjs +0 -151
  301. package/scripts/execution-resume-esc-integration-test.mjs +0 -176
  302. package/scripts/explore-bench-tmp.mjs +0 -36
  303. package/scripts/explore-bench.mjs +0 -248
  304. package/scripts/explore-prompt-policy-test.mjs +0 -256
  305. package/scripts/explore-timeout-cancel-test.mjs +0 -345
  306. package/scripts/find-fuzzy-hidden-test.mjs +0 -267
  307. package/scripts/forwarder-rebind-tail-test.mjs +0 -67
  308. package/scripts/freevar-smoke.mjs +0 -98
  309. package/scripts/gemini-provider-test.mjs +0 -1448
  310. package/scripts/generate-oc-icons.mjs +0 -11
  311. package/scripts/grok-oauth-refresh-race-test.mjs +0 -273
  312. package/scripts/headless-pristine-execution-test.mjs +0 -614
  313. package/scripts/hook-bus-test.mjs +0 -552
  314. package/scripts/ingest-pure-conversation-smoke.mjs +0 -175
  315. package/scripts/internal-comms-bench-test.mjs +0 -226
  316. package/scripts/internal-comms-bench.mjs +0 -853
  317. package/scripts/internal-comms-smoke.mjs +0 -277
  318. package/scripts/internal-tools-normalization-test.mjs +0 -62
  319. package/scripts/interrupted-turn-history-test.mjs +0 -399
  320. package/scripts/lead-workflow-smoke.mjs +0 -592
  321. package/scripts/lifecycle-api-test.mjs +0 -137
  322. package/scripts/live-share-test.mjs +0 -148
  323. package/scripts/live-worker-smoke.mjs +0 -333
  324. package/scripts/log-writer-guard-smoke.mjs +0 -131
  325. package/scripts/maintenance-default-routes-test.mjs +0 -164
  326. package/scripts/max-output-recovery-persist-test.mjs +0 -81
  327. package/scripts/max-output-recovery-test.mjs +0 -368
  328. package/scripts/mcp-client-normalization-test.mjs +0 -45
  329. package/scripts/mcp-grace-deferred-test.mjs +0 -225
  330. package/scripts/memory-core-input-test.mjs +0 -167
  331. package/scripts/memory-cycle-routing-test.mjs +0 -111
  332. package/scripts/memory-meta-concurrency-test.mjs +0 -20
  333. package/scripts/memory-pg-recovery-test.mjs +0 -59
  334. package/scripts/memory-rule-contract-test.mjs +0 -93
  335. package/scripts/model-list-sanitize-test.mjs +0 -37
  336. package/scripts/mouse-tracking-restore-smoke.mjs +0 -107
  337. package/scripts/native-edit-wire-test.mjs +0 -152
  338. package/scripts/notify-completion-mirror-test.mjs +0 -73
  339. package/scripts/openai-oauth-refresh-race-test.mjs +0 -120
  340. package/scripts/openai-oauth-ws-1006-retry-test.mjs +0 -954
  341. package/scripts/openai-ws-early-settle-test.mjs +0 -216
  342. package/scripts/output-style-bench.mjs +0 -292
  343. package/scripts/output-style-smoke.mjs +0 -145
  344. package/scripts/parent-abort-link-test.mjs +0 -90
  345. package/scripts/patch-binary-cache-test.mjs +0 -181
  346. package/scripts/path-suffix-test.mjs +0 -57
  347. package/scripts/pending-completion-drop-test.mjs +0 -239
  348. package/scripts/pending-messages-lock-nonblocking-test.mjs +0 -62
  349. package/scripts/pretool-ask-runtime-test.mjs +0 -54
  350. package/scripts/process-lifecycle-test.mjs +0 -461
  351. package/scripts/prompt-immediate-render-test.mjs +0 -89
  352. package/scripts/prompt-input-parity-test.mjs +0 -145
  353. package/scripts/provider-admission-scheduler-test.mjs +0 -681
  354. package/scripts/provider-contract-test.mjs +0 -632
  355. package/scripts/provider-stream-stall-test.mjs +0 -276
  356. package/scripts/provider-toolcall-test.mjs +0 -3063
  357. package/scripts/reactive-compact-persist-smoke.mjs +0 -203
  358. package/scripts/recall-bench.mjs +0 -359
  359. package/scripts/resource-admission-test.mjs +0 -792
  360. package/scripts/result-classification-test.mjs +0 -75
  361. package/scripts/rg-runner-test.mjs +0 -240
  362. package/scripts/routing-corpus-test.mjs +0 -349
  363. package/scripts/sanitize-tool-pairs-test.mjs +0 -260
  364. package/scripts/session-bench-cache-break-test.mjs +0 -102
  365. package/scripts/session-bench.mjs +0 -1708
  366. package/scripts/session-context-bench.mjs +0 -344
  367. package/scripts/session-heartbeat-lifecycle-test.mjs +0 -68
  368. package/scripts/session-ingest-compaction-smoke.mjs +0 -279
  369. package/scripts/session-ingest-smoke.mjs +0 -177
  370. package/scripts/session-orphan-sweep-test.mjs +0 -109
  371. package/scripts/set-effort-config-test.mjs +0 -41
  372. package/scripts/shell-failure-diagnostics-test.mjs +0 -280
  373. package/scripts/shell-hardening-test.mjs +0 -209
  374. package/scripts/shell-jobs-windows-hide-test.mjs +0 -164
  375. package/scripts/ship-mode-test.mjs +0 -98
  376. package/scripts/smoke-loop-failure-summary-test.mjs +0 -38
  377. package/scripts/smoke-loop-failure-summary.mjs +0 -16
  378. package/scripts/smoke-loop-report.mjs +0 -221
  379. package/scripts/smoke-loop.mjs +0 -202
  380. package/scripts/smoke-runtime-negative.ps1 +0 -106
  381. package/scripts/statusline-quota-hysteresis-test.mjs +0 -62
  382. package/scripts/steering-drain-buckets-test.mjs +0 -467
  383. package/scripts/steering-fold-provenance-test.mjs +0 -71
  384. package/scripts/streaming-tail-window-test.mjs +0 -175
  385. package/scripts/submit-commandbusy-race-test.mjs +0 -257
  386. package/scripts/task-bench.mjs +0 -205
  387. package/scripts/terminal-bench-isolation-guards-test.mjs +0 -102
  388. package/scripts/termio-input-smoke.mjs +0 -199
  389. package/scripts/tool-result-hook-test.mjs +0 -48
  390. package/scripts/tool-smoke.mjs +0 -2453
  391. package/scripts/tool-tui-presentation-test.mjs +0 -286
  392. package/scripts/toolcall-args-test.mjs +0 -239
  393. package/scripts/tui-ambiguous-width-test.mjs +0 -113
  394. package/scripts/tui-background-failure-smoke.mjs +0 -73
  395. package/scripts/tui-perf-run.ps1 +0 -26
  396. package/scripts/tui-render-smoke.mjs +0 -90
  397. package/scripts/tui-runtime-load-bench-entry.jsx +0 -608
  398. package/scripts/tui-runtime-load-bench.mjs +0 -50
  399. package/scripts/tui-store-frame-batch-test.mjs +0 -99
  400. package/scripts/tui-transcript-jitter-harness-entry.jsx +0 -383
  401. package/scripts/tui-transcript-perf-test.mjs +0 -934
  402. package/scripts/usage-metrics-epoch-smoke.mjs +0 -114
  403. package/scripts/verify-release-assets-test.mjs +0 -281
  404. package/scripts/web-fetch-routing-test.mjs +0 -158
  405. package/scripts/webhook-smoke.mjs +0 -201
  406. package/scripts/windows-hide-spawn-options-test.mjs +0 -19
  407. package/scripts/worker-notify-rejection-test.mjs +0 -51
  408. package/scripts/write-backpressure-test.mjs +0 -147
@@ -0,0 +1,357 @@
1
+ // ChatGPT-backend Responses payload builders, extracted from openai-oauth.mjs.
2
+ /**
3
+ * OpenAI ChatGPT OAuth subscription provider.
4
+ *
5
+ * Dispatches over the WebSocket upgrade of chatgpt.com/backend-api/codex/
6
+ * responses (responses_websockets=2026-02-06 beta). Authenticates via PKCE
7
+ * OAuth using Mixdog-owned token storage. Streaming/framing lives in
8
+ * openai-oauth-ws.mjs; this file owns auth, model catalog, request-body
9
+ * shape, and HTTP/SSE fallback when WebSocket transport is unhealthy.
10
+ */
11
+ import { createHash } from 'crypto';
12
+ import { readFileSync, existsSync, mkdirSync, statSync, unlinkSync } from 'fs';
13
+ import { join, resolve } from 'path';
14
+ import { getPluginData } from '../config.mjs';
15
+ import { enrichModels } from './model-catalog.mjs';
16
+ import { sanitizeModelList } from './model-list-sanitize.mjs';
17
+ import { writeJsonAtomicSync, withFileLock } from '../../../shared/atomic-file.mjs';
18
+ import { boundProviderAuthPath } from '../../../shared/provider-auth-binding.mjs';
19
+ import { makeModelCache } from './model-cache.mjs';
20
+
21
+ import { sendViaWebSocket } from './openai-oauth-ws.mjs';
22
+ import { _combineUsageWithWarmup } from './openai-ws-events.mjs';
23
+ import { resolveOpenAiTransportPolicy } from './openai-transport-policy.mjs';
24
+ import {
25
+ buildStableProviderPromptCacheKey,
26
+ resolveProviderPromptCacheLane,
27
+ resolveProviderCacheKey,
28
+ } from '../agent-runtime/cache-strategy.mjs';
29
+ import {
30
+ appendAgentTrace,
31
+ traceAgentFetch,
32
+ traceAgentSse,
33
+ traceAgentUsage,
34
+ } from '../agent-trace.mjs';
35
+ import {
36
+ PROVIDER_HTTP_RESPONSE_TIMEOUT_MS,
37
+ PROVIDER_SEMANTIC_IDLE_TIMEOUT_MS,
38
+ PROVIDER_SSE_IDLE_WATCHDOG_ENABLED,
39
+ streamStalledError,
40
+ createTimeoutSignal,
41
+ createPassthroughSignal,
42
+ } from '../stall-policy.mjs';
43
+ import { populateHttpStatusFromMessage, shouldFallbackTransport } from './retry-classifier.mjs';
44
+ import { getLlmDispatcher, preconnect } from '../../../shared/llm/http-agent.mjs';
45
+ import { makeInvalidToolArgsMarker } from './openai-compat-stream.mjs';
46
+ import { createLeakGuard, createToolCallDedupe, dedupeToolCallList } from './anthropic-leaked-toolcall.mjs';
47
+ import {
48
+ normalizeContentForOpenAIResponses,
49
+ splitToolContentForOpenAIResponses,
50
+ } from './media-normalization.mjs';
51
+ import {
52
+ customToolCallFromResponseItem,
53
+ customToolInputFromArguments,
54
+ isCustomToolCallRecord,
55
+ isResponsesFreeformTool,
56
+ nativeToolSearchCallInput,
57
+ nativeToolSearchOutputInput,
58
+ toResponsesCustomTool,
59
+ } from './custom-tool-wire.mjs';
60
+ import {
61
+ sendViaHttpSse,
62
+ _envFlag,
63
+ _shouldUseOpenAIHttpFallback,
64
+ } from './openai-oauth-http-sse.mjs';
65
+ import { createOpenAIOAuthLogin } from './openai-oauth-login.mjs';
66
+ import { warmCodexClientVersion } from './codex-client-meta.mjs';
67
+ import {
68
+ _displayCodexModel,
69
+ _codexFamily,
70
+ _normalizeCodexModel,
71
+ _compareVersion,
72
+ _isMainCodexFamily,
73
+ _markLatestCodex,
74
+ } from './openai-codex-model.mjs';
75
+
76
+ // Public test/integration entry retained alongside the transport module export.
77
+ // --- Constants ---
78
+
79
+ import { _findCachedCodexModel, codexModelSupportsServiceTier } from './openai-oauth.mjs';
80
+
81
+ function _contentTextParts(content, type = 'input_text') {
82
+ if (typeof content === 'string') return content ? [{ type, text: content }] : [];
83
+ if (!Array.isArray(content)) {
84
+ const text = content == null ? '' : JSON.stringify(content);
85
+ return text ? [{ type, text }] : [];
86
+ }
87
+ const out = [];
88
+ for (const item of content) {
89
+ if (!item || typeof item !== 'object') continue;
90
+ if (typeof item.text === 'string') {
91
+ out.push({ type: item.type === 'output_text' ? 'output_text' : type, text: item.text });
92
+ } else if (typeof item.content === 'string') {
93
+ out.push({ type, text: item.content });
94
+ }
95
+ }
96
+ return out;
97
+ }
98
+
99
+ /**
100
+ * Convert a message slice to Responses API input items.
101
+ */
102
+ export function convertMessagesToResponsesInput(messages, opts = {}) {
103
+ const out = [];
104
+ const pendingToolMedia = [];
105
+ const customToolCallNameById = new Map();
106
+ const wireParity = process.env.MIXDOG_OAI_CODEX_WIRE_PARITY === '1';
107
+ const wireMessage = (role, content) => (wireParity
108
+ ? { type: 'message', role, content, internal_chat_message_metadata_passthrough: {} }
109
+ : { role, content });
110
+ const flushToolMedia = () => {
111
+ if (!pendingToolMedia.length) return;
112
+ out.push(wireMessage('user', pendingToolMedia.splice(0)));
113
+ };
114
+ for (const m of messages) {
115
+ if (!m || m.role === 'system') continue;
116
+ if (m.role === 'tool') {
117
+ const { output, mediaContent } = splitToolContentForOpenAIResponses(m.content);
118
+ if (customToolCallNameById.has(m.toolCallId || '')) {
119
+ out.push({
120
+ type: 'custom_tool_call_output',
121
+ call_id: m.toolCallId || '',
122
+ name: customToolCallNameById.get(m.toolCallId || '') || undefined,
123
+ output,
124
+ });
125
+ if (mediaContent) pendingToolMedia.push(...mediaContent);
126
+ continue;
127
+ }
128
+ const nativeSearchOutput = nativeToolSearchOutputInput(
129
+ m,
130
+ opts.nativeToolSearchProvider || 'openai-oauth',
131
+ );
132
+ if (nativeSearchOutput) {
133
+ out.push(nativeSearchOutput);
134
+ if (mediaContent) pendingToolMedia.push(...mediaContent);
135
+ continue;
136
+ }
137
+ out.push({
138
+ type: 'function_call_output',
139
+ call_id: m.toolCallId || '',
140
+ output,
141
+ });
142
+ if (mediaContent) pendingToolMedia.push(...mediaContent);
143
+ continue;
144
+ }
145
+ flushToolMedia();
146
+ if (m.role === 'assistant' && Array.isArray(m.toolCalls) && m.toolCalls.length) {
147
+ // Reasoning replay deliberately omitted: openai-oauth rejects an
148
+ // `rs_*` reasoning item with the same id across the same
149
+ // handshake session_id (in-memory conversation state lives
150
+ // for the WS_IDLE_MS window even after a socket close).
151
+ // Server-side state already preserves the prefix; sending
152
+ // reasoning in `input` triggers "Duplicate item".
153
+ if (m.content) out.push(wireMessage('assistant', normalizeContentForOpenAIResponses(m.content, { role: 'assistant' })));
154
+ for (const tc of m.toolCalls) {
155
+ const nativeSearchCall = nativeToolSearchCallInput(tc);
156
+ if (nativeSearchCall) {
157
+ out.push(nativeSearchCall);
158
+ } else if (isCustomToolCallRecord(tc)) {
159
+ if (tc.id) customToolCallNameById.set(tc.id, tc.name || '');
160
+ out.push({
161
+ type: 'custom_tool_call',
162
+ call_id: tc.id,
163
+ name: tc.name,
164
+ input: customToolInputFromArguments(tc.name, tc.arguments),
165
+ });
166
+ } else {
167
+ out.push({
168
+ type: 'function_call',
169
+ call_id: tc.id,
170
+ name: tc.name === 'tool_search' ? 'load_tool' : tc.name,
171
+ arguments: JSON.stringify(tc.arguments),
172
+ });
173
+ }
174
+ }
175
+ continue;
176
+ }
177
+ out.push(wireMessage(
178
+ m.role === 'assistant' ? 'assistant' : 'user',
179
+ normalizeContentForOpenAIResponses(m.content, { role: m.role }),
180
+ ));
181
+ }
182
+ flushToolMedia();
183
+ return out;
184
+ }
185
+
186
+ export function toOpenAIResponsesTool(t) {
187
+ if (t?.name === 'load_tool' || t?.name === 'tool_search') {
188
+ return {
189
+ type: 'tool_search',
190
+ execution: 'client',
191
+ description: t.description,
192
+ parameters: t.inputSchema,
193
+ };
194
+ }
195
+ if (isResponsesFreeformTool(t)) return toResponsesCustomTool(t);
196
+ return {
197
+ type: 'function',
198
+ name: t.name,
199
+ description: t.description,
200
+ parameters: t.inputSchema,
201
+ };
202
+ }
203
+
204
+ export const _convertMessagesToResponsesInputForTest = convertMessagesToResponsesInput;
205
+
206
+ // codex build_reasoning() (core/src/client.rs:785-805) only attaches the
207
+ // reasoning object when model_info.supports_reasoning_summaries; models
208
+ // without summary support get NO reasoning field at all. Mirror that via the
209
+ // cached codex catalog; unknown models default to true (gpt-5 family all
210
+ // support summaries) so a cold catalog cannot strip reasoning from the wire.
211
+ function _codexModelSupportsReasoningSummaries(id) {
212
+ const info = _findCachedCodexModel(id);
213
+ if (!info) return true;
214
+ const flags = [info.supportsReasoningSummaries, info.supports_reasoning_summaries, info.supportsReasoning, info.supports_reasoning];
215
+ for (const flag of flags) {
216
+ if (typeof flag === 'boolean') return flag;
217
+ }
218
+ return true;
219
+ }
220
+
221
+ // codex reasoning_effort_for_request (core/src/client.rs): `ultra` collapses to
222
+ // `max` on the wire — the openai-oauth backend does not accept `ultra`. Every
223
+ // other effort passes through unchanged; empty/unknown falls back to medium.
224
+ export function _normalizeReasoningEffort(effort) {
225
+ const e = String(effort || '').trim().toLowerCase();
226
+ if (!e) return 'medium';
227
+ if (e === 'ultra') return 'max';
228
+ return e;
229
+ }
230
+
231
+ export function buildRequestBody(messages, model, tools, sendOpts) {
232
+ // codex reasoning_effort_for_request: `ultra` collapses to `max` on the
233
+ // wire (the only remap; every other effort passes through). Default medium.
234
+ // Kept inline (not a module const) so buildRequestBody stays self-contained.
235
+ // Extract system/instructions
236
+ const systemMsgs = messages.filter(m => m.role === 'system');
237
+ const instructions = systemMsgs.map(m => m.content).join('\n\n') || 'You are a helpful assistant.';
238
+ const opts = sendOpts || {};
239
+ const input = convertMessagesToResponsesInput(messages, {
240
+ providerState: opts.providerState,
241
+ model,
242
+ nativeToolSearchProvider: opts.promptCacheProvider || 'openai-oauth',
243
+ });
244
+ // Match the request body shape the OAuth backend expects so the
245
+ // server-side auto-cache routes correctly. text.verbosity / include /
246
+ // tool_choice / parallel_tool_calls are all inert without side effects
247
+ // for most callers but their presence affects how the OAuth backend classifies the
248
+ // request (and therefore whether the prompt cache is consulted).
249
+ const include = ['reasoning.encrypted_content'];
250
+ for (const item of Array.isArray(opts.nativeInclude) ? opts.nativeInclude : []) {
251
+ const value = String(item || '').trim();
252
+ if (value && !include.includes(value)) include.push(value);
253
+ }
254
+ // Field order MIRRORS codex-rs ResponsesApiRequest (common.rs struct order):
255
+ // model, instructions, input, tools, tool_choice, parallel_tool_calls,
256
+ // reasoning, store, stream, include, service_tier, prompt_cache_key, text.
257
+ // JSON serialization order is load-bearing for the server prompt cache
258
+ // (exact-prefix match): matching codex's byte layout keeps our requests on
259
+ // the same cache-routing shape codex warms. tools/service_tier/
260
+ // prompt_cache_key are appended below in the same relative order.
261
+ const body = {
262
+ model,
263
+ instructions,
264
+ input,
265
+ tool_choice: opts.toolChoice || 'auto',
266
+ parallel_tool_calls: true,
267
+ // codex build_reasoning() sends { effort, summary } — summary defaults to
268
+ // ReasoningSummary::Auto (protocol config_types.rs), serialized lowercase
269
+ // as "auto". Matching this keeps our reasoning object byte-identical to
270
+ // codex so the server prompt-cache prefix hash lines up. codex also
271
+ // normalizes `ultra` -> `max` on the wire (reasoning_effort_for_request
272
+ // in core/src/client.rs); the openai-oauth backend does not accept
273
+ // `ultra` as a wire value, so mirror that mapping here.
274
+ // WIRE-VERIFIED (codex desktop logs_2.sqlite, 40 response.create
275
+ // captures, 2026-07-03): codex sends reasoning as {"effort":"..."}
276
+ // with NO summary field on gpt-5.5, regardless of what the repo's
277
+ // build_reasoning() suggests. Match the observed bytes.
278
+ reasoning: { effort: _normalizeReasoningEffort(opts.effort) },
279
+ store: process.env.MIXDOG_OAI_STORE === 'true' ? true : false,
280
+ stream: true,
281
+ include,
282
+ };
283
+ const maxOutputTokens = Number(opts.maxOutputTokens ?? opts.outputTokens ?? opts.max_output_tokens);
284
+ if (_envFlag('MIXDOG_OPENAI_OAUTH_SEND_MAX_OUTPUT_TOKENS', false)
285
+ && Number.isFinite(maxOutputTokens)
286
+ && maxOutputTokens > 0) {
287
+ body.max_output_tokens = Math.floor(maxOutputTokens);
288
+ }
289
+ if (opts.fast === true) {
290
+ // 'priority' is the only fast-class value the OpenAI OAuth backend
291
+ // accepts on the wire: 'fast' is hard-rejected ("Unsupported
292
+ // service_tier: fast", probed 2026-06-11). Only send the request value
293
+ // when the model catalog advertises it.
294
+ if (codexModelSupportsServiceTier(model, 'priority')) {
295
+ body.service_tier = 'priority';
296
+ }
297
+ }
298
+ // Add tools. `nativeTools` are server-hosted Responses tools (for
299
+ // example web_search) and must be passed through without wrapping them as
300
+ // function tools. codex places `tools` right after `input` (before
301
+ // tool_choice); we insert it there via a rebuilt object so serialization
302
+ // order matches, rather than appending it last.
303
+ const functionTools = tools?.length ? tools.map(toOpenAIResponsesTool) : [];
304
+ const nativeTools = Array.isArray(opts.nativeTools)
305
+ ? opts.nativeTools.filter(t => t && typeof t === 'object')
306
+ : [];
307
+ const toolsList = (functionTools.length || nativeTools.length)
308
+ ? [...nativeTools, ...functionTools]
309
+ : null;
310
+ const promptCacheProvider = opts.promptCacheProvider || 'openai-oauth';
311
+ const promptCacheLane = opts.promptCacheLane || resolveProviderPromptCacheLane(promptCacheProvider, opts);
312
+ const promptCacheKey = buildStableProviderPromptCacheKey(promptCacheProvider, opts, {
313
+ model,
314
+ instructions,
315
+ tools: toolsList || [],
316
+ effort: body.reasoning?.effort,
317
+ fast: opts.fast === true,
318
+ serviceTier: body.service_tier || '',
319
+ toolChoice: body.tool_choice,
320
+ parallelToolCalls: body.parallel_tool_calls,
321
+ cacheLaneSlot: promptCacheLane.slot,
322
+ cacheLaneShards: promptCacheLane.shards,
323
+ });
324
+ // WIRE-VERIFIED (codex desktop logs, 2026-07-03): every live gpt-5.5
325
+ // response.create carries text:{"verbosity":"low"} (or a schema variant);
326
+ // none omit the field. Default to codex's observed "low", allow override.
327
+ const verbosity = (typeof opts.verbosity === 'string' && opts.verbosity.trim()
328
+ ? opts.verbosity.trim().toLowerCase()
329
+ : null) || 'low';
330
+ // Rebuild the body in codex struct order so JSON serialization is
331
+ // byte-compatible with codex: ... input, tools, tool_choice,
332
+ // parallel_tool_calls, reasoning, store, stream, include, service_tier,
333
+ // prompt_cache_key, text. service_tier is only present when fast set it.
334
+ const ordered = {
335
+ model: body.model,
336
+ instructions: body.instructions,
337
+ input: body.input,
338
+ ...(toolsList ? { tools: toolsList } : {}),
339
+ tool_choice: body.tool_choice,
340
+ parallel_tool_calls: body.parallel_tool_calls,
341
+ reasoning: body.reasoning,
342
+ store: body.store,
343
+ stream: body.stream,
344
+ include: body.include,
345
+ ...(body.service_tier ? { service_tier: body.service_tier } : {}),
346
+ prompt_cache_key: promptCacheKey,
347
+ text: { verbosity },
348
+ ...(body.max_output_tokens ? { max_output_tokens: body.max_output_tokens } : {}),
349
+ };
350
+ // NOTE: prompt_cache_retention is a public OpenAI Responses API parameter,
351
+ // but the openai-oauth endpoint still rejects it ("Unsupported parameter:
352
+ // prompt_cache_retention", re-probed 2026-06-22). Leave retention on the
353
+ // openai-oauth server default; public OpenAI direct injects 24h separately.
354
+ return ordered;
355
+ }
356
+
357
+ // --- Provider ---
@@ -0,0 +1,216 @@
1
+ // Codex WS handshake helpers: CF cookie jar, id parity, debug dump redaction. Extracted from openai-ws-pool.mjs.
2
+ /**
3
+ * openai-ws-pool.mjs — WebSocket connection pool for the OpenAI OAuth provider.
4
+ *
5
+ * Extracted from openai-oauth-ws.mjs. Owns the socket pool singleton
6
+ * (_wsPool), handshake/open/acquire/release lifecycle, idle-close timers and
7
+ * the process-exit drain fence. openai-oauth-ws.mjs imports acquire/release/
8
+ * _sendFrame and re-exports the drain hooks for legacy import paths.
9
+ */
10
+ import WebSocket from 'ws';
11
+ import { errText } from '../../../shared/err-text.mjs';
12
+ import { createHash, randomBytes } from 'crypto';
13
+ import { performance } from 'node:perf_hooks';
14
+ import { appendFileSync, mkdirSync, writeFileSync } from 'node:fs';
15
+ import { join } from 'node:path';
16
+ import { codexOriginator, codexUserAgent, codexVersionHeader } from './codex-client-meta.mjs';
17
+ import {
18
+ PROVIDER_WS_ACQUIRE_TIMEOUT_MS,
19
+ PROVIDER_WS_HANDSHAKE_TIMEOUT_MS,
20
+ PROVIDER_WS_PING_ENABLED,
21
+ PROVIDER_WS_PING_INTERVAL_MS,
22
+ PROVIDER_WS_PONG_TIMEOUT_MS,
23
+ PROVIDER_WS_LIVENESS_STALE_MS,
24
+ resolveTimeoutMs,
25
+ } from '../stall-policy.mjs';
26
+
27
+ // Human-readable transport label for handshake/acquire error messages. Shared
28
+ // with openai-oauth-ws.mjs (stream-side errors use the same labels).
29
+ import { _wsPool, _sendFrame } from './openai-ws-pool.mjs';
30
+
31
+ const _cfCookieJar = new Map(); // accountKey -> { name -> value }
32
+ const _CF_COOKIE_ALLOWLIST = new Set(['__cf_bm', '_cfuvid']);
33
+
34
+ export function _envOn(name) {
35
+ const v = String(process.env[name] || '').trim().toLowerCase();
36
+ return ['1', 'true', 'yes', 'on'].includes(v);
37
+ }
38
+
39
+ // --- Opt-in Codex fingerprint/id parity knobs ------------------------------
40
+ // All default OFF; unset envs leave the winning combo
41
+ // (MIXDOG_OAI_CODEX_WIRE_PARITY=1 + ws-delta + underscore session_id) exactly
42
+ // as-is. These add EXTRA parity dimensions for backend fingerprint probes.
43
+
44
+ // codex sends dashed RFC-4122 UUIDs as session-id/thread-id (client.rs:1033-
45
+ // 1057); we key those dashed handshake headers off the underscore cacheKey by
46
+ // default. Opt in with MIXDOG_OAI_CODEX_WIRE_PARITY_UUID_IDS to reshape ONLY
47
+ // the dashed pair (session-id/thread-id/x-client-request-id) into codex's UUID
48
+ // format. The value is derived deterministically from the id so it stays
49
+ // stable per cache key (prefix-cache continuity preserved), and the underscore
50
+ // `session_id` header (the backend prefix-dedupe key) is left untouched.
51
+ export function _codexUuidIdParity() {
52
+ const v = String(process.env.MIXDOG_OAI_CODEX_WIRE_PARITY_UUID_IDS || '').trim().toLowerCase();
53
+ return ['1', 'true', 'yes', 'on', 'uuid', 'dashed'].includes(v);
54
+ }
55
+
56
+ export function _codexDashedId(value) {
57
+ const h = createHash('sha256').update(String(value)).digest();
58
+ const b = Buffer.from(h.subarray(0, 16));
59
+ b[6] = (b[6] & 0x0f) | 0x50; // version 5 nibble
60
+ b[8] = (b[8] & 0x3f) | 0x80; // RFC-4122 variant
61
+ const hex = b.toString('hex');
62
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
63
+ }
64
+
65
+ // Opt-in turn-state gate experiment bundle (MIXDOG_OAI_CODEX_TURN_STATE_GATE).
66
+ // The debugger's working hypothesis for what gates x-codex-turn-state issuance
67
+ // is a specific wire shape: Codex-shaped UUIDv7 session/thread ids + dashed-only
68
+ // handshake headers (drop the underscore session_id) + NO duplicated
69
+ // x-client-request-id + a parent-thread header (added in openai-oauth-ws.mjs).
70
+ // This env ties those dimensions together as ONE experiment so operators can
71
+ // A/B the whole gate shape without hand-composing four flags. Default OFF; it
72
+ // leaves MIXDOG_OAI_CODEX_WIRE_PARITY_UUID_IDS / _SESSION_ID and every existing
73
+ // flag intact and only reshapes the wire when explicitly enabled.
74
+ export function _codexTurnStateGate() {
75
+ const v = String(process.env.MIXDOG_OAI_CODEX_TURN_STATE_GATE || '').trim().toLowerCase();
76
+ return ['1', 'true', 'yes', 'on'].includes(v);
77
+ }
78
+
79
+ // Same derivation as _codexDashedId but stamps the version-7 nibble so the
80
+ // dashed pair reads as a Codex-shaped UUIDv7. Deterministic per id (prefix
81
+ // cache continuity preserved); only used under the turn-state gate bundle.
82
+ export function _codexDashedIdV7(value) {
83
+ const h = createHash('sha256').update(String(value)).digest();
84
+ const b = Buffer.from(h.subarray(0, 16));
85
+ b[6] = (b[6] & 0x0f) | 0x70; // version 7 nibble
86
+ b[8] = (b[8] & 0x3f) | 0x80; // RFC-4122 variant
87
+ const hex = b.toString('hex');
88
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
89
+ }
90
+
91
+ // codex advertises enabled beta features on the WS handshake; the backend
92
+ // plausibly gates x-codex-turn-state issuance on that list (see the
93
+ // x-codex-beta-features comment below). MIXDOG_CODEX_BETA_FEATURES replaces the
94
+ // whole list; MIXDOG_OAI_CODEX_TURN_STATE_FEATURES is a safe ADD-ONLY opt-in
95
+ // that appends turn-state-gating feature token(s) (comma-separated, de-duped)
96
+ // without dropping the default `remote_compaction_v2`. Unset = default list.
97
+ export function _codexBetaFeatures() {
98
+ const base = process.env.MIXDOG_CODEX_BETA_FEATURES || 'remote_compaction_v2';
99
+ const extra = String(process.env.MIXDOG_OAI_CODEX_TURN_STATE_FEATURES || '').trim();
100
+ if (!extra) return base;
101
+ const seen = new Set();
102
+ const out = [];
103
+ for (const tok of `${base},${extra}`.split(',').map((s) => s.trim()).filter(Boolean)) {
104
+ if (seen.has(tok)) continue;
105
+ seen.add(tok);
106
+ out.push(tok);
107
+ }
108
+ return out.join(',');
109
+ }
110
+
111
+ // --- Opt-in raw WS capture for byte-diff against codex-rs -------------------
112
+ // Enabled ONLY when MIXDOG_OAI_WS_DUMP_DIR names a directory. Persists the
113
+ // (redacted) handshake header metadata and the exact serialized
114
+ // response.create frame bytes so our wire format can be byte-diffed against
115
+ // codex. Secrets (Authorization / Cookie / account-id / routing tokens) are
116
+ // hashed, never written in clear. When the env is unset both helpers are
117
+ // no-ops, so there is no default behavior change.
118
+ const _WS_DUMP_SECRET_RE = /^(authorization|proxy-authorization|cookie|set-cookie|chatgpt-account-id|x-codex-turn-state|session_id|session-id|thread-id|x-codex-parent-thread-id|x-client-request-id|x-session-affinity)$/i;
119
+
120
+ function _wsDumpDir() {
121
+ const dir = String(process.env.MIXDOG_OAI_WS_DUMP_DIR || '').trim();
122
+ return dir || null;
123
+ }
124
+
125
+ function _redactHeaderValue(key, value) {
126
+ const v = String(value ?? '');
127
+ if (_WS_DUMP_SECRET_RE.test(String(key))) {
128
+ if (!v) return '';
129
+ return `<redacted:sha256:${createHash('sha256').update(v).digest('hex').slice(0, 12)}:len${v.length}>`;
130
+ }
131
+ return v;
132
+ }
133
+
134
+ function _redactDumpUrl(url) {
135
+ try {
136
+ const parsed = new URL(String(url));
137
+ for (const [key, value] of parsed.searchParams.entries()) {
138
+ if (_WS_DUMP_SECRET_RE.test(String(key))) {
139
+ parsed.searchParams.set(key, _redactHeaderValue(key, value));
140
+ }
141
+ }
142
+ return parsed.toString();
143
+ } catch {
144
+ return String(url || '');
145
+ }
146
+ }
147
+
148
+ export function _dumpHandshakeHeaders(url, headers) {
149
+ const dir = _wsDumpDir();
150
+ if (!dir) return;
151
+ try {
152
+ mkdirSync(dir, { recursive: true });
153
+ const redacted = {};
154
+ for (const [k, v] of Object.entries(headers || {})) redacted[k] = _redactHeaderValue(k, v);
155
+ const rec = {
156
+ ts: new Date().toISOString(),
157
+ kind: 'ws_handshake',
158
+ url: _redactDumpUrl(url),
159
+ // Header order matters for the codex byte-diff; keep it explicit.
160
+ headerOrder: Object.keys(headers || {}),
161
+ headers: redacted,
162
+ };
163
+ const stamp = `${Date.now()}-${randomBytes(4).toString('hex')}`;
164
+ writeFileSync(join(dir, `handshake-${stamp}.json`), JSON.stringify(rec, null, 2));
165
+ } catch {}
166
+ }
167
+
168
+ export function _dumpFrame(payload) {
169
+ const dir = _wsDumpDir();
170
+ if (!dir) return;
171
+ try {
172
+ mkdirSync(dir, { recursive: true });
173
+ const stamp = `${Date.now()}-${randomBytes(4).toString('hex')}`;
174
+ // Persist the serialized response.create bytes for codex byte-diff,
175
+ // but never dump x-codex-turn-state in clear. That token is a
176
+ // per-turn credential-like routing secret; header dumps already hash
177
+ // it, so frame dumps must do the same when client_metadata carries it.
178
+ let out = payload;
179
+ try {
180
+ const frame = JSON.parse(String(payload));
181
+ const meta = frame?.client_metadata;
182
+ if (meta && typeof meta === 'object' && typeof meta['x-codex-turn-state'] === 'string') {
183
+ meta['x-codex-turn-state'] = _redactHeaderValue('x-codex-turn-state', meta['x-codex-turn-state']);
184
+ out = JSON.stringify(frame);
185
+ }
186
+ } catch {}
187
+ writeFileSync(join(dir, `frame-${stamp}.json`), out);
188
+ } catch {}
189
+ }
190
+
191
+ function _cfCookieAccountKey(auth) {
192
+ return String(auth?.account_id || auth?.apiKey || 'default');
193
+ }
194
+
195
+ export function _cfCookieHeader(auth) {
196
+ if (!_envOn('MIXDOG_OAI_CF_COOKIES')) return null;
197
+ const jar = _cfCookieJar.get(_cfCookieAccountKey(auth));
198
+ if (!jar || !jar.size) return null;
199
+ return [...jar.entries()].map(([k, v]) => `${k}=${v}`).join('; ');
200
+ }
201
+
202
+ export function _cfCookieCapture(auth, setCookieHeaders) {
203
+ if (!_envOn('MIXDOG_OAI_CF_COOKIES')) return;
204
+ const list = Array.isArray(setCookieHeaders) ? setCookieHeaders : (setCookieHeaders ? [setCookieHeaders] : []);
205
+ if (!list.length) return;
206
+ const key = _cfCookieAccountKey(auth);
207
+ let jar = _cfCookieJar.get(key);
208
+ if (!jar) { jar = new Map(); _cfCookieJar.set(key, jar); }
209
+ for (const raw of list) {
210
+ const pair = String(raw || '').split(';', 1)[0];
211
+ const eq = pair.indexOf('=');
212
+ if (eq <= 0) continue;
213
+ const name = pair.slice(0, eq).trim();
214
+ if (_CF_COOKIE_ALLOWLIST.has(name)) jar.set(name, pair.slice(eq + 1).trim());
215
+ }
216
+ }