@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
@@ -19,24 +19,34 @@
19
19
  * - `GET /v1/live/{callId}` — Frameless
20
20
  * - `GET /v1/realtime/calls/{callId}` — path-form join
21
21
  * - `GET /v1/realtime?call_id=` — Realtime v1/v2 join
22
+ *
23
+ * Inbound standalone session WebSocket (no call-create; codex-rs `thread/realtime/start`
24
+ * with the standalone WebSocket transport — the desktop voice path since 0.147.x):
25
+ * - `GET /v1/realtime?intent=quicksilver&model=` — Realtime v1 standalone
26
+ * - `GET /v1/realtime?model=` — RealtimeV2 standalone (no intent)
27
+ * - `GET /v1/live?model=` — Frameless standalone
22
28
  */
23
29
  import { appendFileSync } from "node:fs";
24
30
  import { formatErrorResponse } from "../bridge";
25
31
  import {
26
32
  CodexAccountCooldownError,
33
+ codexMainProfileDrainingResponse,
27
34
  cooldownErrorResponse,
28
35
  CodexAuthContextError,
36
+ CodexMainProfileDrainingError,
29
37
  CodexPoolAuthenticationError,
30
38
  CodexThreadAffinityExpiredError,
31
39
  } from "../codex/auth-context";
32
40
  import { formatCodexProviderForLog } from "../codex/routing";
33
- import { signalWithTimeout } from "../lib/abort";
41
+ import { cancelBodyOnAbort, signalWithTimeout } from "../lib/abort";
34
42
  import { sidecarEnter } from "../lib/sidecar-tracker";
35
43
  import type { OcxConfig } from "../types";
36
44
  import { resolveFirstUsableOpenAiSidecar, selectOpenAiImagesProvider } from "../providers/openai-sidecar";
37
45
  import { ForwardAdmissionCredentialError, validateForwardAdmissionCredential } from "./auth-cors";
38
46
  import type { RequestLogContext } from "./request-log";
39
47
  import { codexLogAccountId } from "./responses";
48
+ import type { AdmissionLease } from "../lib/admission";
49
+ import { codexAccountSelectionForTurn } from "./lifecycle";
40
50
 
41
51
  /** Voice call create can wait on SDP negotiation; bound a hung upstream. */
42
52
  const LIVE_UPSTREAM_TIMEOUT_MS = 120_000;
@@ -137,10 +147,59 @@ function clientProtocolHeaders(reqHeaders: Headers): Record<string, string> {
137
147
 
138
148
  const LIVE_CALL_ID_RE = /^[A-Za-z0-9_-]{1,128}$/;
139
149
 
150
+ /**
151
+ * Credential-shaped query keys never forwarded upstream on a standalone realtime
152
+ * relay. Auth on the upstream socket is proxy-owned (headers resolved by
153
+ * `resolveLiveRelay`); a caller that puts `access_token=`/`api_key=`/... in the
154
+ * URL must not get it relayed to the configured upstream. Compared case-folded on
155
+ * both the raw and percent-decoded key. Everything else — `intent`, `model`,
156
+ * duplicates, protocol extensions — passes through verbatim, matching codex-rs
157
+ * client behavior of constructing those fields itself.
158
+ */
159
+ const STANDALONE_QUERY_DENYLIST = new Set([
160
+ "access_token",
161
+ "api_key",
162
+ "apikey",
163
+ "token",
164
+ "key",
165
+ "authorization",
166
+ "auth",
167
+ "signature",
168
+ "sig",
169
+ ]);
170
+
171
+ /**
172
+ * Filter a raw query string (no leading `?`) for standalone upstream relay: drop
173
+ * denylisted credential-shaped pairs, preserve the rest byte-for-byte (including
174
+ * ordering, duplicates, noncanonical encodings, and bare keys).
175
+ */
176
+ export function sanitizeStandaloneRealtimeQuery(rawQuery: string): string {
177
+ if (!rawQuery) return "";
178
+ const kept: string[] = [];
179
+ for (const pair of rawQuery.split("&")) {
180
+ const eq = pair.indexOf("=");
181
+ const rawKey = eq === -1 ? pair : pair.slice(0, eq);
182
+ let decodedKey = rawKey;
183
+ try {
184
+ decodedKey = decodeURIComponent(rawKey);
185
+ } catch {
186
+ // Leave undecodable keys as-is; the raw comparison still applies.
187
+ }
188
+ if (STANDALONE_QUERY_DENYLIST.has(rawKey.toLowerCase()) || STANDALONE_QUERY_DENYLIST.has(decodedKey.toLowerCase())) {
189
+ console.warn(`[live] standalone realtime relay dropping credential-shaped query param: ${decodedKey}`);
190
+ continue;
191
+ }
192
+ kept.push(pair);
193
+ }
194
+ return kept.join("&");
195
+ }
196
+
140
197
  export type LiveSidebandTarget =
141
198
  | { style: "frameless-path"; callId: string }
142
199
  | { style: "realtime-calls-path"; callId: string }
143
- | { style: "realtime-query"; callId: string };
200
+ | { style: "realtime-query"; callId: string }
201
+ | { style: "realtime-standalone"; query: string }
202
+ | { style: "frameless-standalone"; query: string };
144
203
 
145
204
  export type LiveRelayTarget = {
146
205
  headers: Record<string, string>;
@@ -164,7 +223,7 @@ export function keyedLiveUrl(baseUrl: string): string {
164
223
  }
165
224
 
166
225
  export function forwardLiveUrl(baseUrl: string, usesBackendShape: boolean): string {
167
- const root = baseUrl.replace(/\/$/, "");
226
+ const root = baseUrl.replace(/\/+$/, "");
168
227
  if (usesBackendShape) return withAvasQuery(`${root}/realtime/calls`);
169
228
  // Frameless API shape posts to /live without the AVAS query (codex RealtimeCallClient).
170
229
  return `${root}/live`;
@@ -176,13 +235,17 @@ function httpsToWss(httpUrl: string): string {
176
235
  return httpUrl;
177
236
  }
178
237
 
179
- export function parseLiveSidebandTarget(pathname: string, searchParams: URLSearchParams): LiveSidebandTarget | null {
238
+ export function parseLiveSidebandTarget(pathname: string, searchParams: URLSearchParams, rawQuery = ""): LiveSidebandTarget | null {
180
239
  const liveMatch = pathname.match(/^\/v1\/live\/([^/]+)\/?$/);
181
240
  if (liveMatch) {
182
241
  const callId = decodeURIComponent(liveMatch[1]!);
183
242
  if (!LIVE_CALL_ID_RE.test(callId)) return null;
184
243
  return { style: "frameless-path", callId };
185
244
  }
245
+ // Standalone Frameless session (no call-create): `GET /v1/live?model=`.
246
+ if (pathname === "/v1/live" || pathname === "/v1/live/") {
247
+ return { style: "frameless-standalone", query: sanitizeStandaloneRealtimeQuery(rawQuery) };
248
+ }
186
249
  const callsMatch = pathname.match(/^\/v1\/realtime\/calls\/([^/]+)\/?$/);
187
250
  if (callsMatch) {
188
251
  const callId = decodeURIComponent(callsMatch[1]!);
@@ -190,9 +253,17 @@ export function parseLiveSidebandTarget(pathname: string, searchParams: URLSearc
190
253
  return { style: "realtime-calls-path", callId };
191
254
  }
192
255
  if (pathname === "/v1/realtime" || pathname === "/v1/realtime/") {
193
- const callId = searchParams.get("call_id")?.trim() ?? "";
194
- if (!LIVE_CALL_ID_RE.test(callId)) return null;
195
- return { style: "realtime-query", callId };
256
+ // A present-but-invalid `call_id` is a malformed join, not a standalone
257
+ // session keep rejecting it instead of silently changing the request's
258
+ // meaning.
259
+ if (searchParams.has("call_id")) {
260
+ const callId = searchParams.get("call_id")?.trim() ?? "";
261
+ if (!LIVE_CALL_ID_RE.test(callId)) return null;
262
+ return { style: "realtime-query", callId };
263
+ }
264
+ // Standalone Realtime session (codex-rs thread/realtime/start, WebSocket
265
+ // transport): v1 sends `intent=quicksilver&model=`, v2 sends `model=` only.
266
+ return { style: "realtime-standalone", query: sanitizeStandaloneRealtimeQuery(rawQuery) };
196
267
  }
197
268
  return null;
198
269
  }
@@ -203,8 +274,12 @@ export function parseLiveSidebandTarget(pathname: string, searchParams: URLSearc
203
274
  */
204
275
  function isLoopbackHost(hostname: string): boolean {
205
276
  const lower = hostname.toLowerCase();
277
+ const ipv4 = lower.split(".");
278
+ const ipv4Loopback = ipv4.length === 4
279
+ && ipv4[0] === "127"
280
+ && ipv4.every(part => /^\d{1,3}$/.test(part) && Number(part) <= 255);
206
281
  return lower === "localhost" || lower.endsWith(".localhost")
207
- || lower === "127.0.0.1" || lower.startsWith("127.")
282
+ || ipv4Loopback
208
283
  || lower === "::1" || lower === "[::1]";
209
284
  }
210
285
 
@@ -278,6 +353,12 @@ export function buildLiveSidebandUpstreamWsUrl(
278
353
  if (target.style === "frameless-path") {
279
354
  return httpsToWss(`${sidebandRoot}/live/${target.callId}`);
280
355
  }
356
+ if (target.style === "frameless-standalone") {
357
+ return httpsToWss(`${sidebandRoot}/live${target.query ? `?${target.query}` : ""}`);
358
+ }
359
+ if (target.style === "realtime-standalone") {
360
+ return httpsToWss(`${sidebandRoot}/realtime${target.query ? `?${target.query}` : ""}`);
361
+ }
281
362
  if (target.style === "realtime-calls-path") {
282
363
  return httpsToWss(`${sidebandRoot}/realtime/calls/${target.callId}`);
283
364
  }
@@ -356,8 +437,18 @@ export async function readBodyCapped(
356
437
  }
357
438
  chunks.push(value);
358
439
  }
440
+ } catch (err) {
441
+ // A read that throws leaves the stream neither drained nor cancelled, and releasing the
442
+ // lock alone hands back an unsettled body. Cancel first, then rethrow so the caller's
443
+ // existing classification (client abort / timeout / connect error) is unchanged. The
444
+ // cancel itself can reject with the stream's stored error — that is expected and must not
445
+ // mask the original failure, so it is swallowed here.
446
+ await reader.cancel(err).catch(() => {});
447
+ throw err;
359
448
  } finally {
360
449
  try {
450
+ // Always release: `reader.cancel()` does NOT drop the lock, and holding it would leave
451
+ // the stream permanently locked for any later consumer (audit R-WP5-2).
361
452
  reader.releaseLock();
362
453
  } catch {
363
454
  // already released / cancelled
@@ -409,6 +500,7 @@ export async function resolveLiveRelay(
409
500
  req: Request,
410
501
  config: OcxConfig,
411
502
  logCtx: RequestLogContext,
503
+ turnAdmissionLease?: AdmissionLease,
412
504
  ): Promise<LiveRelayTarget | Response> {
413
505
  try {
414
506
  validateForwardAdmissionCredential(req.headers, config);
@@ -433,7 +525,9 @@ export async function resolveLiveRelay(
433
525
  let forwardAuthError: Response | undefined;
434
526
  if (candidates.forwardCandidates.length > 0) {
435
527
  try {
436
- forward = await resolveFirstUsableOpenAiSidecar(candidates.forwardCandidates, req.headers, config);
528
+ forward = await resolveFirstUsableOpenAiSidecar(candidates.forwardCandidates, req.headers, config, {
529
+ beginCodexAccountSelection: codexAccountSelectionForTurn(turnAdmissionLease),
530
+ });
437
531
  if (forward) {
438
532
  logCtx.provider = formatCodexProviderForLog(
439
533
  forward.providerName,
@@ -444,6 +538,8 @@ export async function resolveLiveRelay(
444
538
  } catch (err) {
445
539
  if (err instanceof CodexAccountCooldownError) {
446
540
  forwardAuthError = cooldownErrorResponse(err);
541
+ } else if (err instanceof CodexMainProfileDrainingError) {
542
+ forwardAuthError = codexMainProfileDrainingResponse();
447
543
  } else if (err instanceof CodexThreadAffinityExpiredError) {
448
544
  forwardAuthError = formatErrorResponse(
449
545
  409,
@@ -506,13 +602,14 @@ export async function handleLive(
506
602
  req: Request,
507
603
  config: OcxConfig,
508
604
  logCtx: RequestLogContext,
605
+ turnAdmissionLease?: AdmissionLease,
509
606
  ): Promise<Response> {
510
607
  const inboundContentType = req.headers.get("content-type") ?? "application/octet-stream";
511
608
  const inboundBodyOrError = await readRequestBodyCapped(req, LIVE_REQUEST_MAX_BYTES);
512
609
  if (inboundBodyOrError instanceof Response) return inboundBodyOrError;
513
610
  const inboundBody = inboundBodyOrError;
514
611
 
515
- const relay = await resolveLiveRelay(req, config, logCtx);
612
+ const relay = await resolveLiveRelay(req, config, logCtx, turnAdmissionLease);
516
613
  if (relay instanceof Response) return relay;
517
614
 
518
615
  const headers: Record<string, string> = { ...relay.headers };
@@ -532,7 +629,12 @@ export async function handleLive(
532
629
  outboundContentType = rewritten.contentType;
533
630
  }
534
631
  } else {
535
- url = keyedLiveUrl(relay.providerBaseUrl);
632
+ // Frameless API-shape call-create posts to `{base}/live` without the AVAS
633
+ // query (openai/codex RealtimeCallClient, realtime_call.rs); only the
634
+ // realtime/calls inbound shape keeps the legacy keyed AVAS endpoint.
635
+ url = new URL(req.url).pathname === "/v1/live"
636
+ ? forwardLiveUrl(relay.providerBaseUrl, /* usesBackendShape */ false)
637
+ : keyedLiveUrl(relay.providerBaseUrl);
536
638
  }
537
639
 
538
640
  headers["content-type"] = outboundContentType;
@@ -545,15 +647,31 @@ export async function handleLive(
545
647
  headers,
546
648
  body: outboundBody,
547
649
  signal: linkedSignal.signal,
650
+ // Credential-bearing: do not follow a cross-origin 3xx. Bun strips `Authorization`
651
+ // across origins but forwards nonstandard headers such as `chatgpt-account-id`,
652
+ // `session_id`, and `x-codex-turn-metadata` to the redirect target.
653
+ redirect: "manual",
548
654
  });
549
655
  // Record every completed upstream response before body size handling so account health /
550
656
  // cooldown still updates when we reject an oversized payload.
551
657
  relay.recordOutcome?.(upstreamResponse.status);
552
- const payload = await readBodyCapped(
553
- upstreamResponse.body,
554
- LIVE_RESPONSE_MAX_BYTES,
555
- total => `live response too large (${total} bytes)`,
556
- );
658
+ // Settle the body on abort before the reader attaches. Without this, a client cancel or the
659
+ // linked timeout landing between fetch resolution and `readBodyCapped`'s `getReader()`
660
+ // leaves Bun's internal read rejection orphaned off the awaited path, where no caller
661
+ // try/catch can intercept it (src/lib/abort.ts). The guard covers the window BEFORE the
662
+ // reader exists; once a reader holds the lock only the reader can cancel, which is why
663
+ // readBodyCapped also cancels on a failed read. Found while investigating #1419.
664
+ const detachBodyGuard = cancelBodyOnAbort(upstreamResponse.body, linkedSignal.signal);
665
+ let payload: ArrayBuffer | Response;
666
+ try {
667
+ payload = await readBodyCapped(
668
+ upstreamResponse.body,
669
+ LIVE_RESPONSE_MAX_BYTES,
670
+ total => `live response too large (${total} bytes)`,
671
+ );
672
+ } finally {
673
+ detachBodyGuard();
674
+ }
557
675
  if (payload instanceof Response) return payload;
558
676
  const relayHeaders: Record<string, string> = {};
559
677
  for (const name of LIVE_RELAY_HEADERS) {
@@ -587,8 +705,9 @@ export async function resolveLiveSidebandUpgrade(
587
705
  config: OcxConfig,
588
706
  logCtx: RequestLogContext,
589
707
  target: LiveSidebandTarget,
708
+ turnAdmissionLease?: AdmissionLease,
590
709
  ): Promise<{ headers: Record<string, string>; upstreamWsUrl: string; recordOutcome?: LiveRelayTarget["recordOutcome"] } | Response> {
591
- const relay = await resolveLiveRelay(req, config, logCtx);
710
+ const relay = await resolveLiveRelay(req, config, logCtx, turnAdmissionLease);
592
711
  if (relay instanceof Response) return relay;
593
712
  return {
594
713
  headers: relay.headers,
@@ -0,0 +1,90 @@
1
+ import { readRuntimePort, type RuntimePortState } from "../config/process-state";
2
+ import { createLocalAttestationChallenge } from "../lib/local-management-attestation";
3
+ import {
4
+ LOCAL_MANAGEMENT_CAPABILITY_HEADER,
5
+ LOCAL_MANAGEMENT_CAPABILITY_EXPIRES_AT_HEADER,
6
+ LOCAL_MANAGEMENT_CAPABILITY_TTL_MS,
7
+ LOCAL_MANAGEMENT_EXPECTED_PID_HEADER,
8
+ LOCAL_MANAGEMENT_NONCE_HEADER,
9
+ createLocalManagementReadCapability,
10
+ type LocalManagementReadPath,
11
+ } from "../lib/local-management-capability";
12
+ import { directLocalHttpFetch } from "./direct-local-http";
13
+ import { probeHostname, type LiveProxy } from "./proxy-liveness";
14
+
15
+ export type LocalManagementReadResult =
16
+ | { kind: "response"; response: Response; targetPid: number }
17
+ | { kind: "unavailable"; reason: "unattested-target" | "runtime-mismatch" | "capability-unavailable" | "transport" };
18
+
19
+ export interface LocalManagementReadDeps {
20
+ fetchImpl?: typeof fetch;
21
+ readRuntime?: (pid: number) => RuntimePortState | null;
22
+ createNonce?: () => string;
23
+ now?: () => number;
24
+ }
25
+
26
+ export interface LocalManagementReadRequestDeps extends LocalManagementReadDeps {
27
+ timeoutMs?: number;
28
+ }
29
+
30
+ /**
31
+ * Read one exact local management endpoint without sending a reusable admin credential.
32
+ *
33
+ * The runtime record is the protected source of the per-process key. The server proves
34
+ * it owns that key by accepting a single-use capability bound to this GET, path, PID,
35
+ * port, and short expiry.
36
+ */
37
+ export async function fetchBoundLocalManagementRead(
38
+ target: LiveProxy,
39
+ path: LocalManagementReadPath,
40
+ deps: LocalManagementReadRequestDeps = {},
41
+ ): Promise<LocalManagementReadResult> {
42
+ if (
43
+ target.source !== "runtime"
44
+ || target.pid === null
45
+ || !Number.isSafeInteger(target.pid)
46
+ || target.pid <= 0
47
+ ) {
48
+ return { kind: "unavailable", reason: "unattested-target" };
49
+ }
50
+ const readRuntime = deps.readRuntime ?? readRuntimePort;
51
+ const runtime = readRuntime(target.pid);
52
+ if (
53
+ !runtime?.attestationSecret
54
+ || runtime.pid !== target.pid
55
+ || runtime.port !== target.port
56
+ ) {
57
+ return { kind: "unavailable", reason: "runtime-mismatch" };
58
+ }
59
+
60
+ const nonce = (deps.createNonce ?? createLocalAttestationChallenge)();
61
+ const expiresAt = (deps.now ?? Date.now)() + LOCAL_MANAGEMENT_CAPABILITY_TTL_MS;
62
+ const capability = createLocalManagementReadCapability(
63
+ runtime.attestationSecret,
64
+ nonce,
65
+ "GET",
66
+ path,
67
+ target.pid,
68
+ target.port,
69
+ expiresAt,
70
+ );
71
+ if (!capability) return { kind: "unavailable", reason: "capability-unavailable" };
72
+
73
+ try {
74
+ const response = await (deps.fetchImpl ?? directLocalHttpFetch)(
75
+ `http://${probeHostname(target.hostname)}:${target.port}${path}`,
76
+ {
77
+ headers: {
78
+ [LOCAL_MANAGEMENT_EXPECTED_PID_HEADER]: String(target.pid),
79
+ [LOCAL_MANAGEMENT_NONCE_HEADER]: nonce,
80
+ [LOCAL_MANAGEMENT_CAPABILITY_EXPIRES_AT_HEADER]: String(expiresAt),
81
+ [LOCAL_MANAGEMENT_CAPABILITY_HEADER]: capability,
82
+ },
83
+ signal: AbortSignal.timeout(deps.timeoutMs ?? 4_000),
84
+ },
85
+ );
86
+ return { kind: "response", response, targetPid: target.pid };
87
+ } catch {
88
+ return { kind: "unavailable", reason: "transport" };
89
+ }
90
+ }
@@ -0,0 +1,137 @@
1
+ import { readRuntimePort, type RuntimePortState } from "../config/process-state";
2
+ import {
3
+ LOCAL_ATTESTATION_CHALLENGE_HEADER,
4
+ LOCAL_ATTESTATION_PROOF_HEADER,
5
+ createLocalAttestationChallenge,
6
+ verifyLocalAttestationProof,
7
+ } from "../lib/local-management-attestation";
8
+ import {
9
+ LOCAL_PROVIDER_RELOAD_CAPABILITY_HEADER,
10
+ LOCAL_PROVIDER_RELOAD_CAPABILITY_TTL_MS,
11
+ LOCAL_PROVIDER_RELOAD_CAPABILITY_VERSION,
12
+ LOCAL_PROVIDER_RELOAD_EXPECTED_PID_HEADER,
13
+ LOCAL_PROVIDER_RELOAD_EXPIRES_AT_HEADER,
14
+ LOCAL_PROVIDER_RELOAD_METHOD,
15
+ LOCAL_PROVIDER_RELOAD_NAME_HEADER,
16
+ LOCAL_PROVIDER_RELOAD_NONCE_HEADER,
17
+ LOCAL_PROVIDER_RELOAD_PATH,
18
+ createLocalProviderReloadCapability,
19
+ isLocalProviderReloadName,
20
+ } from "../lib/local-provider-reload-contract";
21
+ import { directLocalHttpFetch } from "./direct-local-http";
22
+ import { isOpencodexHealthz, probeHostname, type HealthzIdentity, type LiveProxy } from "./proxy-liveness";
23
+
24
+ export type LocalProviderReloadResult =
25
+ | { kind: "reloaded" }
26
+ | { kind: "unavailable"; reason: "invalid-name" | "unattested-target" | "runtime-mismatch" | "attestation" | "capability" | "transport" | "rejected" };
27
+
28
+ export interface LocalProviderReloadDeps {
29
+ fetchImpl?: typeof fetch;
30
+ readRuntime?: (pid: number) => RuntimePortState | null;
31
+ createNonce?: () => string;
32
+ now?: () => number;
33
+ timeoutMs?: number;
34
+ }
35
+
36
+ const LOCAL_PROVIDER_RELOAD_TIMEOUT_MS = 10_000;
37
+
38
+ /**
39
+ * Ask the exact runtime proxy to reload one already-persisted provider.
40
+ *
41
+ * No provider object, API key, OAuth token, custom header, or reusable management
42
+ * credential crosses the socket. The request is bodyless and its one-shot capability
43
+ * binds the provider name to the attested process, method, path, PID, port, and expiry.
44
+ */
45
+ export async function requestBoundLocalProviderReload(
46
+ target: LiveProxy,
47
+ name: string,
48
+ deps: LocalProviderReloadDeps = {},
49
+ ): Promise<LocalProviderReloadResult> {
50
+ if (!isLocalProviderReloadName(name)) return { kind: "unavailable", reason: "invalid-name" };
51
+ if (target.source !== "runtime" || target.pid === null || target.pid <= 0) {
52
+ return { kind: "unavailable", reason: "unattested-target" };
53
+ }
54
+ const readRuntime = deps.readRuntime ?? readRuntimePort;
55
+ const runtime = readRuntime(target.pid);
56
+ if (
57
+ !runtime?.attestationSecret
58
+ || runtime.pid !== target.pid
59
+ || runtime.port !== target.port
60
+ ) {
61
+ return { kind: "unavailable", reason: "runtime-mismatch" };
62
+ }
63
+
64
+ const fetchImpl = deps.fetchImpl ?? directLocalHttpFetch;
65
+ const timeoutMs = deps.timeoutMs ?? LOCAL_PROVIDER_RELOAD_TIMEOUT_MS;
66
+ const nonce = (deps.createNonce ?? createLocalAttestationChallenge)();
67
+ const baseUrl = `http://${probeHostname(target.hostname)}:${target.port}`;
68
+ let proofResponse: Response;
69
+ try {
70
+ proofResponse = await fetchImpl(`${baseUrl}/healthz`, {
71
+ headers: { [LOCAL_ATTESTATION_CHALLENGE_HEADER]: nonce },
72
+ signal: AbortSignal.timeout(timeoutMs),
73
+ });
74
+ } catch {
75
+ return { kind: "unavailable", reason: "transport" };
76
+ }
77
+ const body = await proofResponse.json().catch(() => null) as HealthzIdentity | null;
78
+ if (
79
+ !proofResponse.ok
80
+ || !isOpencodexHealthz(body)
81
+ || body?.pid !== target.pid
82
+ || body?.port !== target.port
83
+ || body?.providerReloadCapability !== LOCAL_PROVIDER_RELOAD_CAPABILITY_VERSION
84
+ || !verifyLocalAttestationProof(
85
+ runtime.attestationSecret,
86
+ nonce,
87
+ target.pid,
88
+ target.port,
89
+ proofResponse.headers.get(LOCAL_ATTESTATION_PROOF_HEADER),
90
+ )
91
+ ) {
92
+ return { kind: "unavailable", reason: "attestation" };
93
+ }
94
+
95
+ const currentRuntime = readRuntime(target.pid);
96
+ if (
97
+ !currentRuntime?.attestationSecret
98
+ || currentRuntime.pid !== runtime.pid
99
+ || currentRuntime.port !== runtime.port
100
+ || currentRuntime.hostname !== runtime.hostname
101
+ || currentRuntime.attestationSecret !== runtime.attestationSecret
102
+ ) {
103
+ return { kind: "unavailable", reason: "runtime-mismatch" };
104
+ }
105
+
106
+ const expiresAt = (deps.now ?? Date.now)() + LOCAL_PROVIDER_RELOAD_CAPABILITY_TTL_MS;
107
+ const capability = createLocalProviderReloadCapability(
108
+ runtime.attestationSecret,
109
+ nonce,
110
+ LOCAL_PROVIDER_RELOAD_METHOD,
111
+ LOCAL_PROVIDER_RELOAD_PATH,
112
+ name,
113
+ target.pid,
114
+ target.port,
115
+ expiresAt,
116
+ );
117
+ if (!capability) return { kind: "unavailable", reason: "capability" };
118
+
119
+ try {
120
+ const response = await fetchImpl(`${baseUrl}${LOCAL_PROVIDER_RELOAD_PATH}`, {
121
+ method: LOCAL_PROVIDER_RELOAD_METHOD,
122
+ headers: {
123
+ [LOCAL_PROVIDER_RELOAD_EXPECTED_PID_HEADER]: String(target.pid),
124
+ [LOCAL_PROVIDER_RELOAD_NONCE_HEADER]: nonce,
125
+ [LOCAL_PROVIDER_RELOAD_EXPIRES_AT_HEADER]: String(expiresAt),
126
+ [LOCAL_PROVIDER_RELOAD_NAME_HEADER]: name,
127
+ [LOCAL_PROVIDER_RELOAD_CAPABILITY_HEADER]: capability,
128
+ },
129
+ signal: AbortSignal.timeout(timeoutMs),
130
+ });
131
+ return response.ok
132
+ ? { kind: "reloaded" }
133
+ : { kind: "unavailable", reason: "rejected" };
134
+ } catch {
135
+ return { kind: "unavailable", reason: "transport" };
136
+ }
137
+ }