@iislee/opencodex 2.11.0 → 2.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (733) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +117 -22
  3. package/bin/ocx.mjs +245 -88
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-Be1sDpWw.css +1 -0
  6. package/gui/dist/assets/index-D4OKgUV4.js +114 -0
  7. package/gui/dist/index.html +2 -2
  8. package/gui/dist/provider-icons/alibaba-color.svg +1 -1
  9. package/gui/dist/provider-icons/antigravity-color.svg +1 -1
  10. package/gui/dist/provider-icons/claude-color.svg +1 -1
  11. package/gui/dist/provider-icons/cline-color.svg +16 -0
  12. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
  13. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  14. package/gui/dist/provider-icons/copilot-color.svg +1 -1
  15. package/gui/dist/provider-icons/cursor-color.svg +1 -1
  16. package/gui/dist/provider-icons/deepseek-color.svg +1 -1
  17. package/gui/dist/provider-icons/firepass-color.svg +1 -1
  18. package/gui/dist/provider-icons/fireworks-color.svg +1 -1
  19. package/gui/dist/provider-icons/gemini-color.svg +1 -1
  20. package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
  21. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
  22. package/gui/dist/provider-icons/grok.svg +1 -1
  23. package/gui/dist/provider-icons/groq-color.svg +1 -1
  24. package/gui/dist/provider-icons/huggingface-color.svg +1 -1
  25. package/gui/dist/provider-icons/kimi-color.svg +1 -1
  26. package/gui/dist/provider-icons/kiro-color.svg +2 -2
  27. package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
  28. package/gui/dist/provider-icons/mistral-color.svg +1 -1
  29. package/gui/dist/provider-icons/moonshot-color.svg +1 -1
  30. package/gui/dist/provider-icons/nvidia-color.svg +1 -1
  31. package/gui/dist/provider-icons/ollama-color.svg +1 -1
  32. package/gui/dist/provider-icons/openai.svg +1 -1
  33. package/gui/dist/provider-icons/opencode.svg +2 -1
  34. package/gui/dist/provider-icons/openrouter-color.svg +1 -1
  35. package/gui/dist/provider-icons/pi.svg +2 -2
  36. package/gui/dist/provider-icons/qianfan-color.svg +1 -1
  37. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
  38. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
  39. package/gui/dist/provider-icons/vllm-color.svg +1 -1
  40. package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
  41. package/package.json +21 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +475 -62
  44. package/src/adapters/base.ts +82 -7
  45. package/src/adapters/client-fingerprint.ts +18 -12
  46. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  47. package/src/adapters/command-code.ts +637 -0
  48. package/src/adapters/cursor/call-id.ts +44 -0
  49. package/src/adapters/cursor/catalog.ts +541 -0
  50. package/src/adapters/cursor/checkpoint-store.ts +308 -0
  51. package/src/adapters/cursor/cursor-errors.ts +144 -6
  52. package/src/adapters/cursor/discovery.ts +122 -14
  53. package/src/adapters/cursor/effort-map.ts +106 -4
  54. package/src/adapters/cursor/envelope-echo.ts +290 -0
  55. package/src/adapters/cursor/framing.ts +39 -0
  56. package/src/adapters/cursor/h2-pool.ts +123 -0
  57. package/src/adapters/cursor/http1-bidi.ts +361 -0
  58. package/src/adapters/cursor/images.ts +704 -0
  59. package/src/adapters/cursor/live-models.ts +180 -59
  60. package/src/adapters/cursor/live-transport.ts +623 -170
  61. package/src/adapters/cursor/message-mapper.ts +4 -1
  62. package/src/adapters/cursor/native-exec-common.ts +23 -2
  63. package/src/adapters/cursor/native-exec-desktop.ts +23 -0
  64. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  65. package/src/adapters/cursor/native-exec-network.ts +1 -1
  66. package/src/adapters/cursor/native-exec-shell.ts +5 -3
  67. package/src/adapters/cursor/native-exec.ts +121 -14
  68. package/src/adapters/cursor/protobuf-events.ts +829 -11
  69. package/src/adapters/cursor/protobuf-request.ts +447 -75
  70. package/src/adapters/cursor/request-builder.ts +271 -35
  71. package/src/adapters/cursor/tool-definitions.ts +252 -12
  72. package/src/adapters/cursor/tool-result-normalize.ts +115 -0
  73. package/src/adapters/cursor/transport.ts +22 -0
  74. package/src/adapters/cursor/types.ts +48 -1
  75. package/src/adapters/cursor.ts +336 -39
  76. package/src/adapters/exec-tool-result-normalize.ts +99 -0
  77. package/src/adapters/google-antigravity-replay.ts +713 -41
  78. package/src/adapters/google-antigravity-wire.ts +48 -10
  79. package/src/adapters/google-errors.ts +44 -12
  80. package/src/adapters/google-http.ts +38 -10
  81. package/src/adapters/google-tool-schema.ts +80 -15
  82. package/src/adapters/google-truncation.ts +11 -0
  83. package/src/adapters/google.ts +742 -86
  84. package/src/adapters/identity.ts +39 -6
  85. package/src/adapters/image.ts +1 -1
  86. package/src/adapters/kiro-constants.ts +27 -0
  87. package/src/adapters/kiro-errors.ts +11 -0
  88. package/src/adapters/kiro-events.ts +19 -1
  89. package/src/adapters/kiro-thinking.ts +18 -2
  90. package/src/adapters/kiro-tools.ts +65 -17
  91. package/src/adapters/kiro.ts +270 -73
  92. package/src/adapters/mimo-free.ts +17 -0
  93. package/src/adapters/openai-chat-url.ts +11 -0
  94. package/src/adapters/openai-chat.ts +1377 -344
  95. package/src/adapters/openai-responses-url.ts +16 -0
  96. package/src/adapters/openai-responses.ts +1164 -64
  97. package/src/adapters/registry.ts +175 -0
  98. package/src/adapters/responses-tool-schema.ts +67 -0
  99. package/src/adapters/run-turn-queue.ts +36 -1
  100. package/src/adapters/tool-call-id.ts +119 -0
  101. package/src/adapters/tool-catalog-nudge.ts +105 -21
  102. package/src/adapters/xai-tool-schema.ts +436 -0
  103. package/src/adapters/xai-web-search.ts +186 -0
  104. package/src/bridge.ts +512 -92
  105. package/src/chat/inbound.ts +57 -20
  106. package/src/chat/outbound.ts +97 -33
  107. package/src/claude/agents-inject.ts +40 -10
  108. package/src/claude/context-windows.ts +37 -14
  109. package/src/claude/desktop-3p.ts +243 -9
  110. package/src/claude/gateway-cache.ts +41 -4
  111. package/src/claude/inbound.ts +72 -3
  112. package/src/claude/model-info.ts +38 -15
  113. package/src/claude/outbound.ts +88 -21
  114. package/src/cli/access.ts +46 -3
  115. package/src/cli/account-api.ts +150 -19
  116. package/src/cli/account-auth.ts +33 -6
  117. package/src/cli/account-catalog-refresh.ts +14 -0
  118. package/src/cli/account-extended.ts +648 -28
  119. package/src/cli/account-main.ts +317 -0
  120. package/src/cli/account.ts +97 -19
  121. package/src/cli/agent.ts +53 -2
  122. package/src/cli/alias.ts +66 -0
  123. package/src/cli/capabilities-command.ts +94 -0
  124. package/src/cli/capabilities.ts +496 -0
  125. package/src/cli/claude-agent-startup-sync.ts +73 -0
  126. package/src/cli/claude-desktop.ts +60 -15
  127. package/src/cli/claude.ts +129 -35
  128. package/src/cli/codex-log-guard-doctor.ts +103 -0
  129. package/src/cli/codex-shim-autorestore.ts +2 -0
  130. package/src/cli/codex-shim-readiness.ts +76 -0
  131. package/src/cli/combo.ts +8 -0
  132. package/src/cli/config-command.ts +74 -10
  133. package/src/cli/dispatch.ts +821 -0
  134. package/src/cli/doctor.ts +440 -56
  135. package/src/cli/ensure-desired-integrations.ts +152 -0
  136. package/src/cli/export-command.ts +46 -20
  137. package/src/cli/help.ts +34 -274
  138. package/src/cli/index.ts +417 -528
  139. package/src/cli/init.ts +5 -17
  140. package/src/cli/inspect.ts +230 -0
  141. package/src/cli/integrations.ts +120 -2
  142. package/src/cli/lab.ts +607 -0
  143. package/src/cli/launcher-context.ts +77 -0
  144. package/src/cli/minimax.ts +497 -0
  145. package/src/cli/models-runtime.ts +130 -2
  146. package/src/cli/models.ts +118 -16
  147. package/src/cli/observe.ts +123 -11
  148. package/src/cli/opencode.ts +4 -2
  149. package/src/cli/provider-runtime.ts +34 -3
  150. package/src/cli/provider.ts +25 -3
  151. package/src/cli/ready.ts +301 -0
  152. package/src/cli/registry.ts +476 -0
  153. package/src/cli/root.ts +86 -0
  154. package/src/cli/route-policy.ts +92 -0
  155. package/src/cli/runtime-api.ts +57 -10
  156. package/src/cli/star-prompt.ts +71 -15
  157. package/src/cli/status.ts +51 -4
  158. package/src/cli/storage.ts +234 -0
  159. package/src/cli/system-command.ts +16 -0
  160. package/src/cli/system-restart-client.ts +146 -0
  161. package/src/cli/tray-proxy.ts +153 -6
  162. package/src/cli/usage-report.ts +184 -0
  163. package/src/cli/v2.ts +137 -18
  164. package/src/cli/version-skew.ts +46 -0
  165. package/src/cli.ts +1 -1
  166. package/src/clients/config-export.ts +1442 -23
  167. package/src/clients/effective-status.ts +30 -2
  168. package/src/clients/probes/cline.ts +81 -0
  169. package/src/codex/account-label.ts +35 -1
  170. package/src/codex/account-lifecycle.ts +130 -13
  171. package/src/codex/account-namespaces.ts +49 -3
  172. package/src/codex/account-pause.ts +2 -1
  173. package/src/codex/account-priority.ts +84 -0
  174. package/src/codex/account-store.ts +29 -2
  175. package/src/codex/account-usability.ts +25 -2
  176. package/src/codex/admission.ts +256 -0
  177. package/src/codex/affinity-debug.ts +162 -0
  178. package/src/codex/app-server-processes.ts +570 -107
  179. package/src/codex/app-server-restart-service.ts +232 -0
  180. package/src/codex/auth-api.ts +893 -246
  181. package/src/codex/auth-collision.ts +5 -3
  182. package/src/codex/auth-context.ts +348 -32
  183. package/src/codex/autostart-health.ts +24 -1
  184. package/src/codex/catalog/account-models.ts +67 -0
  185. package/src/codex/catalog/aggregation.ts +86 -10
  186. package/src/codex/catalog/bundled.ts +331 -33
  187. package/src/codex/catalog/effort.ts +138 -32
  188. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  189. package/src/codex/catalog/kinds.ts +2 -0
  190. package/src/codex/catalog/metadata.ts +555 -45
  191. package/src/codex/catalog/native-models.ts +75 -0
  192. package/src/codex/catalog/parsing.ts +269 -30
  193. package/src/codex/catalog/provider-fetch.ts +1626 -144
  194. package/src/codex/catalog/sync.ts +1576 -187
  195. package/src/codex/catalog-admission.ts +199 -0
  196. package/src/codex/catalog-refresh-status.ts +105 -0
  197. package/src/codex/catalog-write-serialization.ts +242 -0
  198. package/src/codex/catalog.ts +6 -3
  199. package/src/codex/codex-write-lock.ts +386 -0
  200. package/src/codex/convergence-types.ts +614 -0
  201. package/src/codex/convergence.ts +676 -0
  202. package/src/codex/coordinator-doctor.ts +332 -0
  203. package/src/codex/custom-model-catalog-migration.ts +176 -0
  204. package/src/codex/desired-state.ts +230 -0
  205. package/src/codex/desktop-app-restart.ts +355 -0
  206. package/src/codex/features.ts +636 -39
  207. package/src/codex/generation.ts +202 -0
  208. package/src/codex/history-job.ts +436 -0
  209. package/src/codex/history-lock.ts +242 -0
  210. package/src/codex/history-manifest.ts +112 -0
  211. package/src/codex/history-migration-guardian.ts +30 -24
  212. package/src/codex/history-provider.ts +1016 -235
  213. package/src/codex/history-transition.ts +105 -0
  214. package/src/codex/history-worker.ts +223 -0
  215. package/src/codex/inject-coordination.ts +373 -0
  216. package/src/codex/inject.ts +1114 -152
  217. package/src/codex/injected-marker.ts +37 -3
  218. package/src/codex/integration-record.ts +266 -0
  219. package/src/codex/internal/catalog-writer.ts +203 -0
  220. package/src/codex/internal/history-writer.ts +81 -0
  221. package/src/codex/journal.ts +66 -4
  222. package/src/codex/log-guard/inspect.ts +524 -0
  223. package/src/codex/log-guard/lock.ts +150 -0
  224. package/src/codex/log-guard/maintenance.ts +403 -0
  225. package/src/codex/log-guard/path-safety.ts +88 -0
  226. package/src/codex/log-guard/policy.ts +44 -0
  227. package/src/codex/log-guard/processes.ts +205 -0
  228. package/src/codex/log-guard/protection.ts +489 -0
  229. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  230. package/src/codex/main-account-cache.ts +24 -0
  231. package/src/codex/main-account.ts +29 -1
  232. package/src/codex/management-convergence.ts +167 -0
  233. package/src/codex/model-cache.ts +56 -10
  234. package/src/codex/model-entitlements.ts +360 -0
  235. package/src/codex/native-main-admission.ts +47 -0
  236. package/src/codex/native-main-auth-temp.ts +187 -0
  237. package/src/codex/native-main-claim.ts +178 -0
  238. package/src/codex/native-main-lock-file.ts +162 -0
  239. package/src/codex/native-main-owner.ts +329 -0
  240. package/src/codex/native-profile-api.ts +247 -0
  241. package/src/codex/native-profile-manager.ts +1531 -0
  242. package/src/codex/native-profile-processes.ts +121 -0
  243. package/src/codex/native-profile-recovery.ts +99 -0
  244. package/src/codex/native-profile-stage-store.ts +387 -0
  245. package/src/codex/native-profile-startup.ts +622 -0
  246. package/src/codex/native-profile-store.ts +855 -0
  247. package/src/codex/native-profile-types.ts +120 -0
  248. package/src/codex/native-residue.ts +675 -0
  249. package/src/codex/paths.ts +80 -1
  250. package/src/codex/plan-from-token.ts +140 -0
  251. package/src/codex/plan.ts +40 -0
  252. package/src/codex/plugins-doctor.ts +1 -1
  253. package/src/codex/pool-rotation.ts +74 -4
  254. package/src/codex/project-config-warnings.ts +20 -6
  255. package/src/codex/prompt-journal.ts +352 -0
  256. package/src/codex/prompt-layers.ts +1313 -0
  257. package/src/codex/prompt-lock.ts +143 -0
  258. package/src/codex/prompt-text-probe.ts +238 -0
  259. package/src/codex/quota-rejection.ts +298 -0
  260. package/src/codex/quota.ts +264 -21
  261. package/src/codex/refresh.ts +11 -2
  262. package/src/codex/reset-credit-recovery.ts +1044 -0
  263. package/src/codex/routing.ts +514 -94
  264. package/src/codex/runtime.ts +159 -38
  265. package/src/codex/shim.ts +1065 -31
  266. package/src/codex/subagent-model-fallback.ts +437 -43
  267. package/src/codex/sync.ts +191 -2
  268. package/src/codex/transition-state.ts +720 -0
  269. package/src/codex/upstream-host-health.ts +368 -0
  270. package/src/codex/user-identity.ts +557 -0
  271. package/src/codex/warmup.ts +187 -81
  272. package/src/codex/write-coordination.ts +114 -0
  273. package/src/combos/failover.ts +47 -0
  274. package/src/combos/index.ts +4 -0
  275. package/src/combos/request.ts +32 -0
  276. package/src/combos/types.ts +91 -9
  277. package/src/compatibility/index.ts +26 -0
  278. package/src/compatibility/manifest.ts +253 -0
  279. package/src/compatibility/openai-responses.ts +121 -0
  280. package/src/config/atomic-write.ts +219 -0
  281. package/src/config/paths.ts +40 -0
  282. package/src/config/process-state.ts +309 -0
  283. package/src/config/provider-name.ts +24 -0
  284. package/src/config/provider-validation.ts +177 -0
  285. package/src/config/rebase-provenance.ts +68 -0
  286. package/src/config.ts +1713 -709
  287. package/src/generated/compatibility-version.json +3324 -0
  288. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  289. package/src/grok/inject.ts +16 -5
  290. package/src/grok/inspect.ts +45 -0
  291. package/src/grok/sync.ts +2 -2
  292. package/src/images/loop.ts +157 -33
  293. package/src/images/plan.ts +24 -13
  294. package/src/integrations/config-io.ts +269 -0
  295. package/src/integrations/journal.ts +315 -0
  296. package/src/integrations/merge.ts +135 -0
  297. package/src/integrations/mutation-flight.ts +71 -0
  298. package/src/integrations/native/ownership-preflight.ts +202 -0
  299. package/src/integrations/omp-yaml-source.ts +358 -0
  300. package/src/integrations/owned-refresh.ts +74 -0
  301. package/src/integrations/ownership-policy.ts +160 -0
  302. package/src/integrations/ownership.ts +155 -0
  303. package/src/integrations/registry.ts +166 -0
  304. package/src/integrations/serialize.ts +314 -0
  305. package/src/integrations/state.ts +433 -0
  306. package/src/integrations/store.ts +103 -0
  307. package/src/integrations/writer-lock.ts +98 -0
  308. package/src/integrations/writer.ts +715 -0
  309. package/src/lab/artifacts/sanitize.ts +586 -0
  310. package/src/lab/artifacts/secure-fs.ts +475 -0
  311. package/src/lab/artifacts/store.ts +310 -0
  312. package/src/lab/automation/budgets.ts +78 -0
  313. package/src/lab/automation/config-persistence.ts +256 -0
  314. package/src/lab/automation/constants.ts +39 -0
  315. package/src/lab/automation/cooldown.ts +103 -0
  316. package/src/lab/automation/dispatch.ts +211 -0
  317. package/src/lab/automation/index.ts +13 -0
  318. package/src/lab/automation/orchestrator.ts +499 -0
  319. package/src/lab/automation/persistence.ts +512 -0
  320. package/src/lab/automation/planner.ts +371 -0
  321. package/src/lab/automation/policy.ts +136 -0
  322. package/src/lab/automation/queue.ts +191 -0
  323. package/src/lab/automation/recovery.ts +24 -0
  324. package/src/lab/automation/route-context.ts +21 -0
  325. package/src/lab/automation/run-key.ts +44 -0
  326. package/src/lab/automation/runs-query.ts +34 -0
  327. package/src/lab/automation/types.ts +160 -0
  328. package/src/lab/conformance/assertion.ts +325 -0
  329. package/src/lab/conformance/digest.ts +22 -0
  330. package/src/lab/conformance/executor.ts +741 -0
  331. package/src/lab/conformance/fixture-provider.ts +27 -0
  332. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  333. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  334. package/src/lab/conformance/harness-budget.ts +47 -0
  335. package/src/lab/conformance/index.ts +5 -0
  336. package/src/lab/conformance/jcs.ts +64 -0
  337. package/src/lab/conformance/json-pointer.ts +39 -0
  338. package/src/lab/conformance/manifest.ts +180 -0
  339. package/src/lab/conformance/mcp-stub.ts +179 -0
  340. package/src/lab/conformance/negative-controls.ts +164 -0
  341. package/src/lab/conformance/observation.ts +355 -0
  342. package/src/lab/conformance/runner.ts +68 -0
  343. package/src/lab/conformance/sse-normalize.ts +59 -0
  344. package/src/lab/conformance/suite-manifest.ts +78 -0
  345. package/src/lab/conformance/types.ts +214 -0
  346. package/src/lab/constants.ts +126 -0
  347. package/src/lab/digest.ts +64 -0
  348. package/src/lab/events/errors.ts +9 -0
  349. package/src/lab/events/limits.ts +117 -0
  350. package/src/lab/events/types.ts +229 -0
  351. package/src/lab/events/validate.ts +781 -0
  352. package/src/lab/fabric/constants.ts +40 -0
  353. package/src/lab/fabric/executor.ts +492 -0
  354. package/src/lab/fabric/index.ts +80 -0
  355. package/src/lab/fabric/manifest.ts +222 -0
  356. package/src/lab/fabric/observe.ts +489 -0
  357. package/src/lab/fabric/patch.ts +79 -0
  358. package/src/lab/fabric/producer-child.ts +139 -0
  359. package/src/lab/fabric/producer-isolate.ts +276 -0
  360. package/src/lab/fabric/producer-protocol.ts +61 -0
  361. package/src/lab/fabric/scratch.ts +439 -0
  362. package/src/lab/fabric/subject.ts +106 -0
  363. package/src/lab/fabric/types.ts +134 -0
  364. package/src/lab/fabric/verifier.ts +98 -0
  365. package/src/lab/index.ts +54 -0
  366. package/src/lab/ledger/artifact-refs.ts +127 -0
  367. package/src/lab/ledger/invalidation.ts +136 -0
  368. package/src/lab/ledger/purge.ts +310 -0
  369. package/src/lab/ledger/store.ts +532 -0
  370. package/src/lab/live/credential-lease.ts +53 -0
  371. package/src/lab/live/destination.ts +155 -0
  372. package/src/lab/live/executor.ts +336 -0
  373. package/src/lab/live/inert-tools.ts +56 -0
  374. package/src/lab/live/manifest.ts +85 -0
  375. package/src/lab/live/mcp-loopback.ts +57 -0
  376. package/src/lab/live/runner.ts +19 -0
  377. package/src/lab/live/sandbox.ts +61 -0
  378. package/src/lab/live/suite-manifest.ts +41 -0
  379. package/src/lab/live/transport.ts +118 -0
  380. package/src/lab/live/types.ts +197 -0
  381. package/src/lab/observe/from-conformance.ts +301 -0
  382. package/src/lab/observe/from-live.ts +117 -0
  383. package/src/lab/paths.ts +153 -0
  384. package/src/lab/projection/rebuild.ts +495 -0
  385. package/src/lab/projection/schema.ts +135 -0
  386. package/src/lab/projection/verdicts.ts +474 -0
  387. package/src/lab/projection/verification.ts +412 -0
  388. package/src/lab/public/bundle.ts +217 -0
  389. package/src/lab/public/community-authority.ts +175 -0
  390. package/src/lab/public/community-files.ts +29 -0
  391. package/src/lab/public/community.ts +479 -0
  392. package/src/lab/public/file-safety.ts +155 -0
  393. package/src/lab/public/ids.ts +26 -0
  394. package/src/lab/public/index.ts +16 -0
  395. package/src/lab/public/mutation-lock.ts +424 -0
  396. package/src/lab/public/operator.ts +353 -0
  397. package/src/lab/public/origin-purge.ts +79 -0
  398. package/src/lab/public/origin.ts +203 -0
  399. package/src/lab/public/privacy.ts +143 -0
  400. package/src/lab/public/private-file.ts +261 -0
  401. package/src/lab/public/project.ts +124 -0
  402. package/src/lab/public/purge-test-fault.ts +21 -0
  403. package/src/lab/public/purge.ts +223 -0
  404. package/src/lab/public/registry.ts +44 -0
  405. package/src/lab/public/revocation.ts +252 -0
  406. package/src/lab/public/signature.ts +243 -0
  407. package/src/lab/public/storage.ts +105 -0
  408. package/src/lab/public/strict-json.ts +206 -0
  409. package/src/lab/public/time.ts +26 -0
  410. package/src/lab/public/types.ts +172 -0
  411. package/src/lab/public/validate.ts +391 -0
  412. package/src/lab/query/catalog.ts +101 -0
  413. package/src/lab/query/connection.ts +107 -0
  414. package/src/lab/query/constants.ts +4 -0
  415. package/src/lab/query/cursor.ts +132 -0
  416. package/src/lab/query/dto-map.ts +277 -0
  417. package/src/lab/query/errors.ts +22 -0
  418. package/src/lab/query/freshness.ts +53 -0
  419. package/src/lab/query/index.ts +45 -0
  420. package/src/lab/query/latest-observation.ts +59 -0
  421. package/src/lab/query/passive-production.ts +159 -0
  422. package/src/lab/query/queries.ts +444 -0
  423. package/src/lab/query/types.ts +266 -0
  424. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  425. package/src/lab/subject/installation-salt.ts +112 -0
  426. package/src/lab/subject/protocol-subject.ts +80 -0
  427. package/src/lab/subject/route-subject.ts +74 -0
  428. package/src/lib/admin-secrets.ts +24 -0
  429. package/src/lib/app-owned-memory-stores.ts +22 -0
  430. package/src/lib/bounded-body.ts +167 -11
  431. package/src/lib/bun-runtime.ts +125 -12
  432. package/src/lib/bun-stream-caps.ts +13 -9
  433. package/src/lib/codex-restart-contract.ts +120 -0
  434. package/src/lib/config-ownership.ts +26 -2
  435. package/src/lib/destination-policy.ts +65 -1
  436. package/src/lib/errors.ts +80 -5
  437. package/src/lib/fabric-task-execution-authority.ts +7 -0
  438. package/src/lib/fabric-task-host.ts +29 -0
  439. package/src/lib/lab-activation.ts +223 -0
  440. package/src/lib/lab-live-execution-authority.ts +13 -0
  441. package/src/lib/lab-live-host.ts +30 -0
  442. package/src/lib/lab-live-pinned-sender.ts +56 -0
  443. package/src/lib/lab-live-route-production.ts +130 -0
  444. package/src/lib/lab-passive-linker-registration.ts +26 -0
  445. package/src/lib/local-management-attestation.ts +51 -0
  446. package/src/lib/local-management-capability.ts +100 -0
  447. package/src/lib/local-provider-reload-contract.ts +100 -0
  448. package/src/lib/optional-shutdown-hooks.ts +57 -0
  449. package/src/lib/package-tree-integrity.ts +101 -0
  450. package/src/lib/pinned-http.ts +145 -26
  451. package/src/lib/process-control.ts +6 -2
  452. package/src/lib/provider-outbound.ts +49 -9
  453. package/src/lib/redact.ts +419 -3
  454. package/src/lib/self-launch-argv.ts +15 -0
  455. package/src/lib/server-resource-ownership.ts +71 -0
  456. package/src/lib/service-secrets.ts +15 -0
  457. package/src/lib/shadow-call.ts +35 -4
  458. package/src/lib/sse-decoder.ts +41 -0
  459. package/src/lib/state-store-registrations.ts +10 -2
  460. package/src/lib/system-restart-contract.ts +73 -0
  461. package/src/lib/token-estimate.ts +19 -2
  462. package/src/lib/tool-argument-integers.ts +253 -0
  463. package/src/lib/translator-budget.ts +44 -0
  464. package/src/lib/upstream-http-version.ts +57 -0
  465. package/src/lib/upstream-reachability.ts +95 -0
  466. package/src/lib/upstream-retry.ts +156 -3
  467. package/src/lib/windows-atomic-replace.ts +155 -0
  468. package/src/lib/windows-elevation.ts +70 -2
  469. package/src/lib/windows-secret-acl.ts +409 -69
  470. package/src/lib/windows-service-wrappers.ts +72 -0
  471. package/src/lib/windows-text.ts +106 -0
  472. package/src/lib/windows-user-principal.ts +341 -0
  473. package/src/lib/winsw.ts +33 -5
  474. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  475. package/src/oauth/account-import/index.ts +15 -0
  476. package/src/oauth/account-import/parser.ts +83 -0
  477. package/src/oauth/account-import/registry.ts +18 -0
  478. package/src/oauth/account-import/service.ts +75 -0
  479. package/src/oauth/account-import/types.ts +91 -0
  480. package/src/oauth/anthropic.ts +12 -1
  481. package/src/oauth/callback-server.ts +30 -4
  482. package/src/oauth/chatgpt.ts +12 -1
  483. package/src/oauth/cline.ts +203 -0
  484. package/src/oauth/command-code.ts +239 -0
  485. package/src/oauth/cursor.ts +46 -5
  486. package/src/oauth/generic-account-failover.ts +231 -0
  487. package/src/oauth/google-antigravity.ts +35 -3
  488. package/src/oauth/health.ts +20 -12
  489. package/src/oauth/index.ts +462 -71
  490. package/src/oauth/key-providers.ts +25 -0
  491. package/src/oauth/kimi.ts +25 -3
  492. package/src/oauth/kiro.ts +95 -6
  493. package/src/oauth/local-token-detect.ts +13 -2
  494. package/src/oauth/log.ts +3 -1
  495. package/src/oauth/login-cli.ts +88 -28
  496. package/src/oauth/nous.ts +798 -0
  497. package/src/oauth/open-browser-choice.ts +26 -0
  498. package/src/oauth/store.ts +133 -26
  499. package/src/oauth/token-guardian.ts +9 -3
  500. package/src/oauth/types.ts +15 -0
  501. package/src/pi/models.ts +2 -2
  502. package/src/providers/alibaba-region-migration.ts +1 -1
  503. package/src/providers/antigravity-models.ts +521 -31
  504. package/src/providers/auto-compact-budget.ts +65 -0
  505. package/src/providers/base-url-choices.ts +10 -0
  506. package/src/providers/codex-capacity.ts +292 -0
  507. package/src/providers/command-code-efforts.ts +176 -0
  508. package/src/providers/context-cap.ts +26 -8
  509. package/src/providers/cursor-pool.ts +72 -0
  510. package/src/providers/default-aliases.ts +65 -0
  511. package/src/providers/derive.ts +281 -6
  512. package/src/providers/fastwire.ts +507 -0
  513. package/src/providers/free-directory.ts +10 -7
  514. package/src/providers/google-vertex-location.ts +14 -0
  515. package/src/providers/key-failover.ts +71 -3
  516. package/src/providers/label.ts +35 -2
  517. package/src/providers/model-discovery-limits.ts +16 -0
  518. package/src/providers/model-discovery.ts +115 -22
  519. package/src/providers/model-presets.ts +119 -0
  520. package/src/providers/model-rename-migration.ts +255 -0
  521. package/src/providers/model-rename-startup.ts +28 -0
  522. package/src/providers/new-model-policy.ts +146 -0
  523. package/src/providers/openai-sidecar.ts +72 -4
  524. package/src/providers/openai-tier-startup.ts +31 -2
  525. package/src/providers/openai-tiers.ts +119 -4
  526. package/src/providers/openai-virtual-models.ts +1 -0
  527. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  528. package/src/providers/provider-id-rewrite.ts +30 -0
  529. package/src/providers/quota.ts +1379 -40
  530. package/src/providers/registry.ts +1545 -112
  531. package/src/providers/request-pacing.ts +310 -0
  532. package/src/providers/service-tier.ts +277 -0
  533. package/src/providers/slug-codec.ts +94 -6
  534. package/src/providers/static-model-discovery.ts +86 -0
  535. package/src/providers/xai-responses-opt-in.ts +15 -0
  536. package/src/providers/xai-transport.ts +32 -4
  537. package/src/reasoning-effort.ts +68 -3
  538. package/src/responses/apply-patch-envelope.ts +63 -0
  539. package/src/responses/code-mode-helper-compat.ts +50 -0
  540. package/src/responses/compaction.ts +26 -1
  541. package/src/responses/custom-tool-compat.ts +384 -0
  542. package/src/responses/hosted-tool-policy.ts +9 -0
  543. package/src/responses/namespace-tool-compat.ts +435 -0
  544. package/src/responses/parser.ts +225 -38
  545. package/src/responses/provider-continuation.ts +98 -0
  546. package/src/responses/provider-opaque-metadata.ts +73 -0
  547. package/src/responses/reasoning-envelope.ts +9 -1
  548. package/src/responses/reasoning-replay-cache.ts +504 -0
  549. package/src/responses/schema.ts +12 -2
  550. package/src/responses/spill-store.ts +75 -10
  551. package/src/responses/state.ts +659 -31
  552. package/src/responses/thought-signature-replay.ts +364 -0
  553. package/src/responses/tool-search-compat.ts +301 -0
  554. package/src/responses/truncated-stop-reason.ts +60 -0
  555. package/src/responses/turn-termination.ts +107 -0
  556. package/src/router.ts +405 -31
  557. package/src/routing/analytics.ts +379 -0
  558. package/src/routing/capability.ts +244 -0
  559. package/src/routing/compatibility/assemble.ts +73 -0
  560. package/src/routing/compatibility/behavior.ts +278 -0
  561. package/src/routing/compatibility/catalog.ts +99 -0
  562. package/src/routing/compatibility/endpoint.ts +52 -0
  563. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  564. package/src/routing/compatibility/policy.ts +181 -0
  565. package/src/routing/compatibility/provider-slot.ts +56 -0
  566. package/src/routing/compatibility/reader.ts +110 -0
  567. package/src/routing/compatibility/subject.ts +191 -0
  568. package/src/routing/compatibility/types.ts +64 -0
  569. package/src/routing/compatibility/version.ts +104 -0
  570. package/src/routing/cost.ts +77 -0
  571. package/src/routing/evaluator.ts +495 -0
  572. package/src/routing/health.ts +412 -0
  573. package/src/routing/history/cursor.ts +43 -0
  574. package/src/routing/history/indexer.ts +605 -0
  575. package/src/routing/history/schema.ts +72 -0
  576. package/src/routing/profile-namespace.ts +15 -0
  577. package/src/routing/profile.ts +547 -0
  578. package/src/routing/quota.ts +155 -0
  579. package/src/routing/request-evidence.ts +45 -0
  580. package/src/routing/trace.ts +776 -0
  581. package/src/server/adapter-resolve.ts +2 -29
  582. package/src/server/auth-cors.ts +289 -48
  583. package/src/server/background-lifecycle.ts +182 -0
  584. package/src/server/chat-completions.ts +154 -72
  585. package/src/server/chat-native-sse.ts +331 -0
  586. package/src/server/chat-native.ts +445 -0
  587. package/src/server/claude-messages.ts +160 -44
  588. package/src/server/direct-local-http.ts +347 -0
  589. package/src/server/effort-policy.ts +18 -0
  590. package/src/server/github-copilot-responses-repair.ts +338 -0
  591. package/src/server/gui-static.ts +39 -10
  592. package/src/server/images.ts +94 -12
  593. package/src/server/index.ts +1021 -190
  594. package/src/server/lifecycle.ts +336 -14
  595. package/src/server/live.ts +136 -17
  596. package/src/server/local-management-read-client.ts +90 -0
  597. package/src/server/local-provider-reload-client.ts +137 -0
  598. package/src/server/management/agent-settings-routes.ts +433 -116
  599. package/src/server/management/api-key-usage.ts +31 -5
  600. package/src/server/management/body.ts +6 -0
  601. package/src/server/management/codex-prompt-routes.ts +570 -0
  602. package/src/server/management/combo-routes.ts +64 -25
  603. package/src/server/management/config-routes.ts +511 -51
  604. package/src/server/management/context.ts +89 -2
  605. package/src/server/management/integration-routes.ts +498 -0
  606. package/src/server/management/lab-automation-routes.ts +206 -0
  607. package/src/server/management/lab-routes.ts +563 -0
  608. package/src/server/management/logs-usage-routes.ts +127 -52
  609. package/src/server/management/model-routes.ts +461 -133
  610. package/src/server/management/model-rows.ts +167 -0
  611. package/src/server/management/native-integration-routes.ts +770 -0
  612. package/src/server/management/oauth-account-routes.ts +90 -8
  613. package/src/server/management/provider-capability-config.ts +48 -0
  614. package/src/server/management/provider-routes.ts +836 -159
  615. package/src/server/management/request-history-routes.ts +191 -0
  616. package/src/server/management/route-registry.ts +332 -0
  617. package/src/server/management/routing-analytics-routes.ts +74 -0
  618. package/src/server/management/routing-profile-routes.ts +380 -0
  619. package/src/server/management/shared.ts +27 -11
  620. package/src/server/management/sidebar-routes.ts +47 -31
  621. package/src/server/management/storage-log-guard-routes.ts +186 -0
  622. package/src/server/management/sync-response.ts +69 -0
  623. package/src/server/management/system-restart.ts +289 -33
  624. package/src/server/management/system-routes.ts +77 -0
  625. package/src/server/management/usage-summary-cache.ts +9 -1
  626. package/src/server/management/vision-sidecar-options.ts +167 -0
  627. package/src/server/management/web-search-sidecar-options.ts +120 -0
  628. package/src/server/management-api.ts +126 -23
  629. package/src/server/management-auth.ts +220 -5
  630. package/src/server/passive-route-linker.ts +66 -0
  631. package/src/server/port-reclaim.ts +1 -1
  632. package/src/server/ports.ts +41 -1
  633. package/src/server/proxy-liveness.ts +161 -10
  634. package/src/server/readiness.ts +99 -0
  635. package/src/server/relay-eager.ts +221 -54
  636. package/src/server/relay.ts +479 -87
  637. package/src/server/request-decompress.ts +113 -6
  638. package/src/server/request-log-conversation.ts +51 -0
  639. package/src/server/request-log.ts +298 -31
  640. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  641. package/src/server/responses/agent-task-recovery.ts +465 -0
  642. package/src/server/responses/codex-auth-error.ts +55 -0
  643. package/src/server/responses/collaboration.ts +239 -36
  644. package/src/server/responses/combo-stream-preflight.ts +178 -0
  645. package/src/server/responses/compact.ts +444 -72
  646. package/src/server/responses/core.ts +3579 -436
  647. package/src/server/responses/empty-completion-guard.ts +333 -0
  648. package/src/server/responses/encrypted-payload.ts +62 -39
  649. package/src/server/responses/fetch-helpers.ts +89 -99
  650. package/src/server/responses/input-admission.ts +187 -0
  651. package/src/server/responses/pacing-overload.ts +13 -0
  652. package/src/server/responses/passthrough-error.ts +33 -9
  653. package/src/server/responses/policy-fallback.ts +178 -0
  654. package/src/server/responses/responses-field-backfill.ts +343 -0
  655. package/src/server/responses/terminal-guard.ts +26 -5
  656. package/src/server/responses/upstream-error.ts +5 -0
  657. package/src/server/responses/ws-upstream.ts +381 -0
  658. package/src/server/responses-custom-tool-repair.ts +363 -0
  659. package/src/server/responses-item-id-repair.ts +54 -6
  660. package/src/server/responses-json-events.ts +90 -0
  661. package/src/server/responses-model-rewrite.ts +29 -0
  662. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  663. package/src/server/responses-snapshot-repair.ts +621 -0
  664. package/src/server/responses-terminal-repair.ts +363 -0
  665. package/src/server/responses-tool-search-repair.ts +267 -0
  666. package/src/server/responses-undeclared-tool-guard.ts +376 -0
  667. package/src/server/responses.ts +18 -2
  668. package/src/server/search.ts +78 -13
  669. package/src/server/sse-frame-buffer.ts +319 -0
  670. package/src/server/sse-payload-rewrite.ts +110 -22
  671. package/src/server/startup-action-control.ts +8 -1
  672. package/src/server/startup-health-cache.ts +19 -1
  673. package/src/server/system-env.ts +80 -9
  674. package/src/server/ws-bridge.ts +53 -40
  675. package/src/service-manager-probe.ts +892 -0
  676. package/src/service.ts +1153 -94
  677. package/src/sidecar/auth.ts +92 -0
  678. package/src/sidecar/candidates.ts +83 -0
  679. package/src/storage/cleanup.ts +2 -2
  680. package/src/storage/policy-job.ts +14 -4
  681. package/src/storage/policy.ts +88 -23
  682. package/src/storage/scanner.ts +1 -1
  683. package/src/storage/worker-lifecycle.ts +14 -14
  684. package/src/tray/windows-tray.ps1 +83 -9
  685. package/src/tray/windows.ts +43 -16
  686. package/src/types/accounts.ts +37 -0
  687. package/src/types/config.ts +911 -0
  688. package/src/types/provider.ts +614 -0
  689. package/src/types/request.ts +397 -0
  690. package/src/types/tools.ts +236 -0
  691. package/src/types/wire.ts +80 -0
  692. package/src/types.ts +107 -1237
  693. package/src/update/index.ts +37 -23
  694. package/src/update/job.ts +445 -68
  695. package/src/update/notify.ts +12 -6
  696. package/src/update/npm-cache-preflight.d.mts +47 -0
  697. package/src/update/npm-cache-preflight.mjs +201 -0
  698. package/src/update/transactional-install.d.mts +22 -0
  699. package/src/update/transactional-install.mjs +266 -0
  700. package/src/usage/cost.ts +0 -0
  701. package/src/usage/expected-prices.ts +287 -16
  702. package/src/usage/log.ts +666 -50
  703. package/src/usage/summary.ts +388 -17
  704. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  705. package/src/usage/user-cost-overlays.ts +314 -0
  706. package/src/vision/anthropic-describe.ts +10 -6
  707. package/src/vision/backends.ts +97 -0
  708. package/src/vision/describe.ts +27 -16
  709. package/src/vision/eligibility.ts +250 -0
  710. package/src/vision/index.ts +238 -24
  711. package/src/vision/reasoning.ts +55 -0
  712. package/src/vision/routed-describe.ts +175 -0
  713. package/src/vision/timeout-bounds.ts +9 -0
  714. package/src/web-search/anthropic-executor.ts +13 -7
  715. package/src/web-search/backends.ts +108 -0
  716. package/src/web-search/exa-executor.ts +119 -0
  717. package/src/web-search/executor.ts +21 -6
  718. package/src/web-search/gemini-executor.ts +141 -0
  719. package/src/web-search/index.ts +150 -15
  720. package/src/web-search/loop.ts +284 -54
  721. package/src/web-search/parse.ts +125 -30
  722. package/src/web-search/sources.ts +60 -0
  723. package/src/web-search/xai-executor.ts +219 -0
  724. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  725. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  726. package/gui/dist/provider-icons/antigravity.svg +0 -1
  727. package/gui/dist/provider-icons/claude.svg +0 -1
  728. package/gui/dist/provider-icons/copilot.svg +0 -1
  729. package/gui/dist/provider-icons/cursor.svg +0 -2
  730. package/gui/dist/provider-icons/gemini.svg +0 -1
  731. package/gui/dist/provider-icons/grok-color.svg +0 -1
  732. package/gui/dist/provider-icons/kiro.svg +0 -14
  733. package/src/cli/internal-dispatch.ts +0 -20
@@ -0,0 +1,504 @@
1
+ /**
2
+ * In-process fallback store pairing raw reasoning text with the tool call it
3
+ * preceded (issue #950).
4
+ *
5
+ * DeepSeek thinking mode requires the assistant's original `reasoning_content`
6
+ * to be replayed on every continuation of a tool-call turn. The bridge records
7
+ * the raw reasoning here when it closes a reasoning block and a tool call
8
+ * follows; the openai-chat adapter re-attaches it when a `tool_calls`
9
+ * assistant message is about to serialize without thinking parts (compacted
10
+ * history, lost assistant turn, orphan-repaired tool results).
11
+ *
12
+ * Entries require a conversation identity in addition to the call id:
13
+ * provider-generated ids like `call_1` are not globally unique, so an
14
+ * unscoped process-wide key would let one conversation's reasoning bleed into
15
+ * another when ids collide (CodeRabbit P1 on #971).
16
+ *
17
+ * Privacy: entries hold reasoning text in memory only — never logged,
18
+ * serialized, or exported. Bounded by entry count, total bytes, and TTL, so a
19
+ * long-lived proxy cannot grow without limit.
20
+ */
21
+
22
+ import { createHash, createHmac, randomBytes } from "node:crypto";
23
+ import type {
24
+ OcxProviderConfig,
25
+ OcxReasoningReplayIdentity,
26
+ OcxReasoningReplayScopeRef,
27
+ } from "../types";
28
+
29
+ const MAX_ENTRIES = 64;
30
+ const MAX_TOTAL_BYTES = 256 * 1024;
31
+ const TTL_MS = 60 * 60 * 1000;
32
+ const OPAQUE_BLOB_REJECTION_TTL_MS = 5 * 60 * 1000;
33
+ const replayIdentityKey = randomBytes(32);
34
+ const CREDENTIAL_HEADER_NAMES = new Set([
35
+ "authorization",
36
+ "api-key",
37
+ "chatgpt-account-id",
38
+ "cookie",
39
+ "openai-organization",
40
+ "openai-project",
41
+ "proxy-authorization",
42
+ "x-api-key",
43
+ "x-api-token",
44
+ "x-auth-token",
45
+ "x-goog-api-key",
46
+ "x-openai-organization",
47
+ "x-openai-project",
48
+ ]);
49
+
50
+ interface CacheEntry {
51
+ text: string;
52
+ bytes: number;
53
+ at: number;
54
+ }
55
+
56
+ interface ServingIdentityEntry {
57
+ identity: string;
58
+ bytes: number;
59
+ at: number;
60
+ }
61
+
62
+ interface OpaqueBlobRejectionEntry {
63
+ bytes: number;
64
+ at: number;
65
+ }
66
+
67
+ const entries = new Map<string, CacheEntry>();
68
+ const servingIdentities = new Map<string, ServingIdentityEntry>();
69
+ const opaqueBlobRejections = new Map<string, OpaqueBlobRejectionEntry>();
70
+ let totalBytes = 0;
71
+ let servingIdentityTotalBytes = 0;
72
+ let opaqueBlobRejectionTotalBytes = 0;
73
+ let clockForTests: (() => number) | null = null;
74
+
75
+ const now = (): number => clockForTests?.() ?? Date.now();
76
+
77
+ function nonEmpty(value: unknown): value is string {
78
+ return typeof value === "string" && value.trim().length > 0;
79
+ }
80
+
81
+ type ReasoningReplayIdentityTuple = readonly [string, string, string, string, string];
82
+
83
+ function tupleForIdentity(
84
+ identity: Readonly<OcxReasoningReplayIdentity> | undefined,
85
+ ): ReasoningReplayIdentityTuple | undefined {
86
+ if (
87
+ !nonEmpty(identity?.providerName)
88
+ || !nonEmpty(identity?.providerDestinationIdentity)
89
+ || !nonEmpty(identity?.adapterName)
90
+ || !nonEmpty(identity?.modelId)
91
+ || !nonEmpty(identity?.credentialIdentity)
92
+ ) return undefined;
93
+ return [
94
+ identity.providerName,
95
+ identity.providerDestinationIdentity,
96
+ identity.adapterName,
97
+ identity.modelId,
98
+ identity.credentialIdentity,
99
+ ];
100
+ }
101
+
102
+ function tupleForServingIdentity(
103
+ identity: Readonly<OcxReasoningReplayIdentity> | undefined,
104
+ ): ReasoningReplayIdentityTuple | undefined {
105
+ if (
106
+ !nonEmpty(identity?.providerName)
107
+ || !nonEmpty(identity?.providerDestinationDurableIdentity)
108
+ || !nonEmpty(identity?.adapterName)
109
+ || !nonEmpty(identity?.modelId)
110
+ || !nonEmpty(identity?.credentialDurableIdentity)
111
+ ) return undefined;
112
+ return [
113
+ identity.providerName,
114
+ identity.providerDestinationDurableIdentity,
115
+ identity.adapterName,
116
+ identity.modelId,
117
+ identity.credentialDurableIdentity,
118
+ ];
119
+ }
120
+
121
+ function keyFor(callId: string, scope: OcxReasoningReplayScopeRef | undefined): string | undefined {
122
+ const identity = tupleForIdentity(scope?.current);
123
+ if (!nonEmpty(callId) || !nonEmpty(scope?.clientThreadId) || !identity) return undefined;
124
+ return JSON.stringify([
125
+ scope.clientThreadId,
126
+ ...identity,
127
+ callId,
128
+ ]);
129
+ }
130
+
131
+ function deleteServingIdentity(threadId: string): void {
132
+ const entry = servingIdentities.get(threadId);
133
+ if (!entry) return;
134
+ servingIdentities.delete(threadId);
135
+ servingIdentityTotalBytes -= entry.bytes;
136
+ }
137
+
138
+ function sweepExpiredServingIdentities(at: number): void {
139
+ for (const [threadId, entry] of servingIdentities) {
140
+ if (at - entry.at >= TTL_MS) deleteServingIdentity(threadId);
141
+ }
142
+ }
143
+
144
+ function servingIdentityFor(
145
+ scope: OcxReasoningReplayScopeRef | undefined,
146
+ ): { threadId: string; identity: string } | undefined {
147
+ const threadId = scope?.clientThreadId;
148
+ const identityTuple = tupleForServingIdentity(scope?.current);
149
+ if (!nonEmpty(threadId) || !identityTuple) return undefined;
150
+ return { threadId, identity: JSON.stringify(identityTuple) };
151
+ }
152
+
153
+ function opaqueBlobRejectionKeyFor(
154
+ scope: OcxReasoningReplayScopeRef | undefined,
155
+ ): string | undefined {
156
+ const current = servingIdentityFor(scope);
157
+ return current ? JSON.stringify([current.threadId, current.identity]) : undefined;
158
+ }
159
+
160
+ function deleteOpaqueBlobRejection(key: string): void {
161
+ const entry = opaqueBlobRejections.get(key);
162
+ if (!entry) return;
163
+ opaqueBlobRejections.delete(key);
164
+ opaqueBlobRejectionTotalBytes -= entry.bytes;
165
+ }
166
+
167
+ function sweepExpiredOpaqueBlobRejections(at: number): void {
168
+ for (const [key, entry] of opaqueBlobRejections) {
169
+ if (at - entry.at >= OPAQUE_BLOB_REJECTION_TTL_MS) deleteOpaqueBlobRejection(key);
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Compare this request's route with the last successfully serving route for its conversation.
175
+ * A live mismatch means replayed opaque reasoning was minted by another backend and must not be
176
+ * forwarded to this one. Comparison deliberately does not refresh or replace the recorded route:
177
+ * a failed candidate request did not serve the conversation.
178
+ *
179
+ * Serving provenance uses restart-stable destination and credential dimensions so token
180
+ * generations and other volatile credential material cannot create false route changes. Missing
181
+ * durable identity, expired, or evicted state is deliberately unknown rather than a mismatch.
182
+ * This store is process-local, so a backend switch spanning a proxy restart is not detected.
183
+ */
184
+ export function reasoningReplayServingIdentityChanged(
185
+ scope: OcxReasoningReplayScopeRef | undefined,
186
+ ): boolean {
187
+ const current = servingIdentityFor(scope);
188
+ if (!current) return false;
189
+ const at = now();
190
+ sweepExpiredServingIdentities(at);
191
+ const previous = servingIdentities.get(current.threadId);
192
+ return previous !== undefined && previous.identity !== current.identity;
193
+ }
194
+
195
+ /** Record the route only after it has successfully served the conversation. */
196
+ export function commitReasoningReplayServingIdentity(
197
+ scope: OcxReasoningReplayScopeRef | undefined,
198
+ ): void {
199
+ const current = servingIdentityFor(scope);
200
+ if (!current) return;
201
+ const at = now();
202
+ sweepExpiredServingIdentities(at);
203
+ const previous = servingIdentities.get(current.threadId);
204
+ const { threadId, identity } = current;
205
+ const bytes = Buffer.byteLength(JSON.stringify([threadId, identity]), "utf8");
206
+ if (bytes > MAX_TOTAL_BYTES) {
207
+ deleteServingIdentity(threadId);
208
+ return;
209
+ }
210
+
211
+ if (previous) deleteServingIdentity(threadId);
212
+ servingIdentities.set(threadId, { identity, bytes, at });
213
+ servingIdentityTotalBytes += bytes;
214
+ while (
215
+ (servingIdentityTotalBytes > MAX_TOTAL_BYTES || servingIdentities.size > MAX_ENTRIES)
216
+ && servingIdentities.size > 1
217
+ ) {
218
+ let oldestThreadId: string | undefined;
219
+ let oldestAt = Infinity;
220
+ for (const [candidateThreadId, entry] of servingIdentities) {
221
+ if (entry.at < oldestAt) {
222
+ oldestAt = entry.at;
223
+ oldestThreadId = candidateThreadId;
224
+ }
225
+ }
226
+ if (oldestThreadId === undefined) break;
227
+ deleteServingIdentity(oldestThreadId);
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Whether this exact conversation and durable serving identity previously rejected opaque replay.
233
+ *
234
+ * The five serving dimensions deliberately match the serving record. Missing durable destination
235
+ * or credential identity is unknown and never falls back to process-local dimensions. The five
236
+ * minute TTL is shorter than the serving record's hour: a stale memo silently degrades reasoning,
237
+ * while expiry costs one visible recovery round trip and can safely re-establish the memo.
238
+ */
239
+ export function reasoningReplayOpaqueBlobRejectionMemoized(
240
+ scope: OcxReasoningReplayScopeRef | undefined,
241
+ ): boolean {
242
+ const key = opaqueBlobRejectionKeyFor(scope);
243
+ if (!key) return false;
244
+ const at = now();
245
+ sweepExpiredOpaqueBlobRejections(at);
246
+ return opaqueBlobRejections.has(key);
247
+ }
248
+
249
+ /** Record only after a blobless retry succeeded for this durable serving identity. */
250
+ export function rememberReasoningReplayOpaqueBlobRejection(
251
+ scope: OcxReasoningReplayScopeRef | undefined,
252
+ ): void {
253
+ const key = opaqueBlobRejectionKeyFor(scope);
254
+ if (!key) return;
255
+ const bytes = Buffer.byteLength(key, "utf8");
256
+ if (bytes > MAX_TOTAL_BYTES) return;
257
+ const at = now();
258
+ sweepExpiredOpaqueBlobRejections(at);
259
+ if (opaqueBlobRejections.has(key)) deleteOpaqueBlobRejection(key);
260
+ opaqueBlobRejections.set(key, { bytes, at });
261
+ opaqueBlobRejectionTotalBytes += bytes;
262
+ while (
263
+ (opaqueBlobRejectionTotalBytes > MAX_TOTAL_BYTES || opaqueBlobRejections.size > MAX_ENTRIES)
264
+ && opaqueBlobRejections.size > 1
265
+ ) {
266
+ let oldestKey: string | undefined;
267
+ let oldestAt = Infinity;
268
+ for (const [candidateKey, entry] of opaqueBlobRejections) {
269
+ if (entry.at < oldestAt) {
270
+ oldestAt = entry.at;
271
+ oldestKey = candidateKey;
272
+ }
273
+ }
274
+ if (oldestKey === undefined) break;
275
+ deleteOpaqueBlobRejection(oldestKey);
276
+ }
277
+ }
278
+
279
+ function processLocalIdentity(domain: string, material: string): string {
280
+ return createHmac("sha256", replayIdentityKey)
281
+ .update(domain)
282
+ .update("\0")
283
+ .update(material)
284
+ .digest("hex");
285
+ }
286
+
287
+ function credentialHeaderOverrides(headers: Record<string, string> | undefined): [string, string][] {
288
+ return Object.entries(headers ?? {})
289
+ .filter(([name, value]) => CREDENTIAL_HEADER_NAMES.has(name.trim().toLowerCase()) && nonEmpty(value))
290
+ .map(([name, value]) => [name.trim().toLowerCase(), value] as [string, string])
291
+ .sort(([leftName, leftValue], [rightName, rightValue]) => (
292
+ leftName.localeCompare(rightName) || leftValue.localeCompare(rightValue)
293
+ ));
294
+ }
295
+
296
+ /** Produce a non-reversible process-local identity for an exact upstream destination. */
297
+ export function reasoningReplayDestinationIdentity(baseUrl: string | undefined): string | undefined {
298
+ if (!nonEmpty(baseUrl)) return undefined;
299
+ const canonical = baseUrl.trim().replace(/\/+$/, "");
300
+ return `destination:${processLocalIdentity("destination", canonical)}`;
301
+ }
302
+
303
+ /**
304
+ * The same destination identity, but stable across restarts.
305
+ *
306
+ * The process-local form above is keyed by `randomBytes(32)` minted at module load, which
307
+ * is correct for an in-memory cache and fatal for a durable one: every key would change on
308
+ * restart and the store would silently stop matching anything. A plain digest of the same
309
+ * canonical URL is equally non-reversible for this purpose — the input is a configured
310
+ * endpoint, not a secret — and needs no persisted salt or new on-disk state.
311
+ */
312
+ export function durableReplayDestinationIdentity(baseUrl: string | undefined): string | undefined {
313
+ if (!nonEmpty(baseUrl)) return undefined;
314
+ const canonical = baseUrl.trim().replace(/\/+$/, "");
315
+ return `destination:${createHash("sha256").update("destination\0").update(canonical).digest("hex")}`;
316
+ }
317
+
318
+ /**
319
+ * Restart-stable credential identity for the DURABLE thought-signature store (#1926).
320
+ *
321
+ * Unlike the destination, credential material may be secret (an API key), so a plain
322
+ * unsalted digest would turn the store file into an offline verifier for candidate keys.
323
+ * The identity is therefore an HMAC under a random salt persisted NEXT TO the store: the
324
+ * salt is not a secret escrow (it holds no credential material) but it makes every digest
325
+ * useless outside this installation. Full 256-bit output — no truncation.
326
+ *
327
+ * OAuth accounts use the persisted account-slot id (not the rotating token/generation):
328
+ * relinking a slot to a different upstream account keeps the id, but the upstream then
329
+ * validates signatures against the new credential and rejects stale ones — the same
330
+ * fail-closed backstop the destination identity relies on. Credential-scoped header
331
+ * overrides participate so two provider entries sharing one key but different
332
+ * authorization headers stay distinct, mirroring the process-local identity.
333
+ */
334
+ export function durableReplayCredentialIdentity(
335
+ kind: "key" | "oauth" | "codex",
336
+ material: string | undefined,
337
+ headers: Record<string, string> | undefined,
338
+ salt: Buffer | undefined,
339
+ ): string | undefined {
340
+ if (!nonEmpty(material) || !salt || salt.length < 16) return undefined;
341
+ const overrides = credentialHeaderOverrides(headers);
342
+ return `credential:${createHmac("sha256", salt)
343
+ .update(`credential\0${kind}\0`)
344
+ .update(JSON.stringify([material, overrides]))
345
+ .digest("hex")}`;
346
+ }
347
+
348
+ /** Produce a non-reversible process-local identity for credential material. */
349
+ export function reasoningReplayCredentialIdentity(
350
+ kind: "key" | "oauth" | "codex",
351
+ material: string | undefined,
352
+ headers?: Record<string, string>,
353
+ ): string | undefined {
354
+ if (!nonEmpty(material)) return undefined;
355
+ const overrides = credentialHeaderOverrides(headers);
356
+ return `${kind}:${processLocalIdentity(`credential:${kind}`, JSON.stringify([material, overrides]))}`;
357
+ }
358
+
359
+ /** Bind Codex forwarding to the effective bearer/account and selected physical pool slot. */
360
+ export function reasoningReplayCodexCredentialIdentity(args: {
361
+ authorization?: string | null;
362
+ chatgptAccountId?: string | null;
363
+ accountId?: string | null;
364
+ credentialGeneration?: number | string | null;
365
+ writerGeneration?: number | string | null;
366
+ headers?: Record<string, string>;
367
+ }): string | undefined {
368
+ const configuredAuthorization = credentialHeaderOverrides(args.headers)
369
+ .find(([name]) => name === "authorization")?.[1];
370
+ const authorization = nonEmpty(args.authorization) ? args.authorization : configuredAuthorization;
371
+ if (!authorization) return undefined;
372
+ const material = JSON.stringify([
373
+ authorization,
374
+ nonEmpty(args.chatgptAccountId) ? args.chatgptAccountId : "",
375
+ nonEmpty(args.accountId) ? args.accountId : "",
376
+ args.credentialGeneration === null || args.credentialGeneration === undefined
377
+ ? ""
378
+ : String(args.credentialGeneration),
379
+ args.writerGeneration === null || args.writerGeneration === undefined
380
+ ? ""
381
+ : String(args.writerGeneration),
382
+ ]);
383
+ return reasoningReplayCredentialIdentity("codex", material, args.headers);
384
+ }
385
+
386
+ /** Bind OAuth replay to one persisted credential slot and exact token generation. */
387
+ export function reasoningReplayOAuthCredentialIdentity(
388
+ snapshot: Readonly<{ accountId: string; generation: string }> | undefined,
389
+ headers?: Record<string, string>,
390
+ ): string | undefined {
391
+ if (!snapshot || !nonEmpty(snapshot.accountId) || !nonEmpty(snapshot.generation)) return undefined;
392
+ return reasoningReplayCredentialIdentity(
393
+ "oauth",
394
+ `${snapshot.accountId}\0${snapshot.generation}`,
395
+ headers,
396
+ );
397
+ }
398
+
399
+ /** Bind key-auth provider material without putting raw secrets in the replay key. */
400
+ export function reasoningReplayKeyCredentialIdentity(
401
+ provider: Pick<OcxProviderConfig, "apiKey" | "headers">,
402
+ ): string | undefined {
403
+ const apiKey = nonEmpty(provider.apiKey) ? provider.apiKey : undefined;
404
+ // Public/static headers do not establish a physical credential boundary.
405
+ // Header-only/key-optional providers therefore fail closed for replay.
406
+ if (!apiKey) return undefined;
407
+ return reasoningReplayCredentialIdentity("key", apiKey, provider.headers);
408
+ }
409
+
410
+ /** Replace only the holder snapshot so parsed-request copies observe rotations. */
411
+ export function bindReasoningReplayScope(
412
+ scope: OcxReasoningReplayScopeRef | undefined,
413
+ identity: OcxReasoningReplayIdentity | undefined,
414
+ ): void {
415
+ if (!scope) return;
416
+ if (!identity || !keyFor("binding-check", { ...scope, current: identity })) {
417
+ delete scope.current;
418
+ return;
419
+ }
420
+ scope.current = { ...identity };
421
+ }
422
+
423
+ /**
424
+ * Record the raw reasoning text that preceded the given tool call.
425
+ *
426
+ * Expired entries are swept on insert so the TTL bound holds even when a call
427
+ * id is never read again.
428
+ */
429
+ export function rememberReasoningForCall(
430
+ callId: string,
431
+ text: string,
432
+ scope?: OcxReasoningReplayScopeRef,
433
+ ): void {
434
+ // Never fall back to a process-wide namespace. Call ids are supplied by
435
+ // clients/providers and are therefore neither unique nor trustworthy; an
436
+ // unscoped entry could be recovered by an unrelated request that reuses the
437
+ // same id.
438
+ // Empty provider deltas are absence of new reasoning, not a request to erase a candidate.
439
+ const key = keyFor(callId, scope);
440
+ if (!key || typeof text !== "string" || text.length === 0) return;
441
+ const bytes = Buffer.byteLength(text, "utf8");
442
+ // A single entry larger than the whole budget would immediately evict itself.
443
+ if (bytes > MAX_TOTAL_BYTES) return;
444
+ const at = now();
445
+ // Delete every due entry first so expired reasoning cannot linger until a
446
+ // later peek or capacity eviction.
447
+ for (const [key, entry] of entries) {
448
+ if (at - entry.at >= TTL_MS) {
449
+ entries.delete(key);
450
+ totalBytes -= entry.bytes;
451
+ }
452
+ }
453
+ const previous = entries.get(key);
454
+ if (previous) totalBytes -= previous.bytes;
455
+ entries.set(key, { text, bytes, at });
456
+ totalBytes += bytes;
457
+ // Evict oldest-first until both caps hold (never evict the entry just written
458
+ // while it is the only one — the loop guards on size > 1).
459
+ while ((totalBytes > MAX_TOTAL_BYTES || entries.size > MAX_ENTRIES) && entries.size > 1) {
460
+ let oldestKey: string | undefined;
461
+ let oldestAt = Infinity;
462
+ for (const [candidateKey, entry] of entries) {
463
+ if (entry.at < oldestAt) {
464
+ oldestAt = entry.at;
465
+ oldestKey = candidateKey;
466
+ }
467
+ }
468
+ if (oldestKey === undefined) break;
469
+ const evicted = entries.get(oldestKey)!;
470
+ totalBytes -= evicted.bytes;
471
+ entries.delete(oldestKey);
472
+ }
473
+ }
474
+
475
+ /**
476
+ * Read the recorded reasoning for a call id without removing it: retries after
477
+ * a failed continuation reuse the same fallback.
478
+ */
479
+ export function peekReasoningForCall(
480
+ callId: string,
481
+ scope?: OcxReasoningReplayScopeRef,
482
+ ): string | undefined {
483
+ const key = keyFor(callId, scope);
484
+ if (!key) return undefined;
485
+ const entry = entries.get(key);
486
+ if (!entry) return undefined;
487
+ if (now() - entry.at >= TTL_MS) {
488
+ entries.delete(key);
489
+ totalBytes -= entry.bytes;
490
+ return undefined;
491
+ }
492
+ return entry.text;
493
+ }
494
+
495
+ /** Test-only: reset the cache and optionally pin the clock. */
496
+ export function clearReasoningReplayCacheForTests(clock?: (() => number) | null): void {
497
+ entries.clear();
498
+ servingIdentities.clear();
499
+ opaqueBlobRejections.clear();
500
+ totalBytes = 0;
501
+ servingIdentityTotalBytes = 0;
502
+ opaqueBlobRejectionTotalBytes = 0;
503
+ clockForTests = clock ?? null;
504
+ }
@@ -11,6 +11,10 @@ const inputImageBlockSchema = z.object({
11
11
  }).refine(v => typeof v.image_url === "string" || typeof v.file_id === "string", {
12
12
  message: "input_image requires at least one of image_url or file_id",
13
13
  });
14
+ const inputVideoBlockSchema = z.object({
15
+ type: z.literal("input_video"),
16
+ video_url: z.string().min(1),
17
+ });
14
18
  const inputFileBlockSchema = z.object({
15
19
  type: z.literal("input_file"),
16
20
  file_id: z.string().optional(),
@@ -24,7 +28,7 @@ const reasoningTextSchema = z.object({ type: z.literal("reasoning_text"), text:
24
28
  // codex-rs FunctionCallOutputContentItem (protocol/src/models.rs): input_text | input_image | encrypted_content.
25
29
  const encryptedContentBlockSchema = z.object({ type: z.literal("encrypted_content"), encrypted_content: z.string() });
26
30
 
27
- const inputContentBlockSchema = z.union([inputTextSchema, plainTextSchema, inputImageBlockSchema, inputFileBlockSchema]);
31
+ const inputContentBlockSchema = z.union([inputTextSchema, plainTextSchema, inputImageBlockSchema, inputVideoBlockSchema, inputFileBlockSchema]);
28
32
  const outputContentBlockSchema = z.union([outputTextSchema, plainTextSchema, outputRefusalSchema]);
29
33
  // Tool outputs on the wire mix codex-rs FunctionCallOutputContentItem with legacy output blocks.
30
34
  const toolOutputContentBlockSchema = z.union([
@@ -64,6 +68,12 @@ const functionCallItemSchema = z.object({
64
68
  name: z.string().min(1),
65
69
  namespace: z.string().optional(),
66
70
  arguments: z.string().optional(),
71
+ // Provider-opaque metadata that must survive the round trip verbatim (issue #1735). The shape
72
+ // is bounded on purpose: only the one nested key we round-trip is modeled, so an unexpected
73
+ // payload cannot ride through as arbitrary passthrough state.
74
+ extra_content: z.object({
75
+ google: z.object({ thought_signature: z.string().optional() }).optional(),
76
+ }).optional(),
67
77
  });
68
78
  const functionCallOutputItemSchema = z.object({
69
79
  type: z.literal("function_call_output"),
@@ -107,7 +117,7 @@ export const toolSchema = z.object({
107
117
  const builtinToolSchema = z.object({ type: z.string() }).loose();
108
118
 
109
119
  const hostedToolType = z.enum([
110
- "web_search_preview", "file_search", "computer_use_preview",
120
+ "web_search", "web_search_preview", "file_search", "computer_use_preview",
111
121
  "code_interpreter", "image_generation", "mcp",
112
122
  ]);
113
123