@bitkyc08/opencodex 2.80.0 → 2.82.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 (376) hide show
  1. package/README.md +3 -3
  2. package/bin/ocx.mjs +166 -73
  3. package/gui/dist/assets/App-Ds_qL7o8.js +54 -0
  4. package/gui/dist/assets/Tray-BqHF5Trd.js +1 -0
  5. package/gui/dist/assets/{index-Brk6F3fn.css → index-BAbcj51J.css} +1 -1
  6. package/gui/dist/assets/index-D3FBCNiP.js +94 -0
  7. package/gui/dist/assets/quota-summary-DTBC8n7-.js +1 -0
  8. package/gui/dist/index.html +2 -2
  9. package/gui/dist/provider-icons/claude-green.svg +1 -0
  10. package/package.json +3 -2
  11. package/src/adapters/anthropic-model-contract.ts +8 -2
  12. package/src/adapters/anthropic.ts +8 -3
  13. package/src/adapters/codebuddy/mcp-server.ts +2 -25
  14. package/src/adapters/codebuddy/tool-bridge.ts +1 -7
  15. package/src/adapters/coding-agent/mcp-server.ts +33 -0
  16. package/src/adapters/coding-agent/protocol.ts +122 -17
  17. package/src/adapters/coding-agent/tool-catalog.ts +75 -0
  18. package/src/adapters/coding-agent/turn.ts +101 -44
  19. package/src/adapters/cursor/catalog.ts +8 -0
  20. package/src/adapters/cursor/effort-map.ts +2 -0
  21. package/src/adapters/devin/live-models.ts +2 -0
  22. package/src/adapters/kiro-retry.ts +9 -4
  23. package/src/adapters/openai-chat/messages.ts +7 -6
  24. package/src/adapters/openai-responses/compaction-search-history.ts +109 -0
  25. package/src/adapters/openai-responses/passthrough.ts +9 -4
  26. package/src/adapters/openai-responses/tool-output-recovery.ts +20 -0
  27. package/src/adapters/physical-send.ts +8 -5
  28. package/src/adapters/qoder/adapter.ts +41 -6
  29. package/src/adapters/qoder/scaffold-guard.ts +2 -3
  30. package/src/adapters/zed.ts +16 -1
  31. package/src/claude/agents-inject.ts +14 -3
  32. package/src/claude/context-windows.ts +19 -17
  33. package/src/claude/desktop-3p.ts +88 -12
  34. package/src/claude/desktop-profile.ts +2 -1
  35. package/src/claude/gateway-cache.ts +18 -1
  36. package/src/claude/inbound-cache-stabilize.ts +4 -9
  37. package/src/claude/inbound.ts +78 -3
  38. package/src/claude/intercept/cli-catalog.ts +3 -0
  39. package/src/claude/intercept/model-bindings.ts +1 -0
  40. package/src/claude/intercept/picker-ca-persistence.ts +7 -6
  41. package/src/claude/intercept/picker-listener.ts +71 -4
  42. package/src/claude/intercept/picker-models.ts +14 -6
  43. package/src/claude/intercept/settings.ts +3 -0
  44. package/src/claude/long-context.ts +66 -0
  45. package/src/claude/model-info.ts +19 -16
  46. package/src/claude/outbound.ts +94 -9
  47. package/src/claude/subagent-model.ts +40 -11
  48. package/src/cli/account-anthropic-threshold.ts +14 -5
  49. package/src/cli/account-api.ts +3 -1
  50. package/src/cli/account-extended.ts +13 -9
  51. package/src/cli/account-policy-dto.ts +1 -1
  52. package/src/cli/account-policy.ts +13 -4
  53. package/src/cli/account.ts +3 -3
  54. package/src/cli/agent.ts +9 -5
  55. package/src/cli/aside-profile-recovery.ts +33 -0
  56. package/src/cli/capabilities-accounts.ts +2 -2
  57. package/src/cli/capabilities-agents-routing.ts +24 -0
  58. package/src/cli/capabilities-base.ts +5 -5
  59. package/src/cli/capabilities-integrations.ts +18 -2
  60. package/src/cli/cli-path-diagnostics.ts +132 -0
  61. package/src/cli/codex-shim-autorestore.ts +3 -0
  62. package/src/cli/desktop-runtime-guidance.ts +65 -0
  63. package/src/cli/dispatch.ts +15 -1
  64. package/src/cli/doctor.ts +16 -3
  65. package/src/cli/help.ts +4 -1
  66. package/src/cli/index.ts +25 -14
  67. package/src/cli/integration-aside-sync.ts +2 -1
  68. package/src/cli/integration-plan-dto.ts +1 -0
  69. package/src/cli/integration-preview.ts +8 -1
  70. package/src/cli/integrations.ts +48 -6
  71. package/src/cli/message-args.ts +34 -0
  72. package/src/cli/message-command.ts +43 -0
  73. package/src/cli/message-runtime.ts +6 -0
  74. package/src/cli/observe.ts +3 -1
  75. package/src/cli/provider.ts +29 -6
  76. package/src/cli/registry.ts +24 -2
  77. package/src/cli/resolve.ts +25 -2
  78. package/src/cli/root.ts +4 -2
  79. package/src/cli/status.ts +64 -12
  80. package/src/cli/update-restart-child.ts +4 -2
  81. package/src/cli/update-restart-home.ts +28 -10
  82. package/src/cli/update-restart-service-record.ts +116 -0
  83. package/src/cli/update-restart-supervision.ts +96 -0
  84. package/src/cli/update-restart.ts +59 -13
  85. package/src/cli/v2.ts +27 -20
  86. package/src/cli/version-skew-notice.ts +77 -0
  87. package/src/clients/config-export/commandcode.ts +131 -0
  88. package/src/clients/config-export/contracts.ts +12 -0
  89. package/src/clients/config-export.ts +64 -1
  90. package/src/clients/lazycodex.ts +1 -1
  91. package/src/clients/omo-role-models.ts +32 -7
  92. package/src/codex/auth-api/account-list.ts +11 -3
  93. package/src/codex/auth-api/account-selection.ts +107 -0
  94. package/src/codex/auth-api/main-account-probe.ts +25 -8
  95. package/src/codex/auth-api/pool-mode-gate.ts +33 -9
  96. package/src/codex/auth-api/pool-quota-probe.ts +15 -1
  97. package/src/codex/auth-api/routes.ts +11 -49
  98. package/src/codex/auth-context.ts +20 -1
  99. package/src/codex/autostart-health.ts +12 -3
  100. package/src/codex/catalog/auto-review.ts +13 -6
  101. package/src/codex/catalog/build-entries.ts +33 -7
  102. package/src/codex/catalog/bundled.ts +155 -26
  103. package/src/codex/catalog/combo-member.ts +3 -2
  104. package/src/codex/catalog/control-plane.ts +45 -0
  105. package/src/codex/catalog/effort.ts +37 -6
  106. package/src/codex/catalog/gather-capture.ts +10 -3
  107. package/src/codex/catalog/model-hints.ts +15 -8
  108. package/src/codex/catalog/model-visibility.ts +3 -1
  109. package/src/codex/catalog/operator-tiers.ts +38 -0
  110. package/src/codex/catalog/parsing.ts +2 -1
  111. package/src/codex/catalog/provider-models.ts +58 -44
  112. package/src/codex/catalog/retained-sync.ts +7 -5
  113. package/src/codex/catalog/routed-gather.ts +15 -1
  114. package/src/codex/catalog-auto-refresh-sources.ts +3 -4
  115. package/src/codex/catalog-auto-refresh.ts +19 -0
  116. package/src/codex/catalog.ts +1 -1
  117. package/src/codex/codex-home-owner.ts +3 -0
  118. package/src/codex/config-write-lock.ts +333 -0
  119. package/src/codex/control-plane-models.ts +6 -0
  120. package/src/codex/convergence.ts +2 -1
  121. package/src/codex/features.ts +257 -200
  122. package/src/codex/inject/config-write-section.ts +34 -0
  123. package/src/codex/inject/multi-agent-v2.ts +14 -6
  124. package/src/codex/inject/remove.ts +36 -11
  125. package/src/codex/inject/restore.ts +85 -20
  126. package/src/codex/inject-coordination.ts +15 -6
  127. package/src/codex/inject.ts +62 -20
  128. package/src/codex/journal.ts +62 -17
  129. package/src/codex/main-account-cache.ts +43 -0
  130. package/src/codex/paths.ts +2 -0
  131. package/src/codex/prepared-home.ts +18 -0
  132. package/src/codex/prompt-journal.ts +25 -12
  133. package/src/codex/prompt-layers.ts +49 -26
  134. package/src/codex/prompt-lock-claim.ts +134 -0
  135. package/src/codex/prompt-lock-evidence.ts +26 -0
  136. package/src/codex/prompt-lock-io.ts +16 -0
  137. package/src/codex/prompt-lock-owner.ts +130 -0
  138. package/src/codex/prompt-lock.ts +84 -53
  139. package/src/codex/routing/failure-window.ts +146 -0
  140. package/src/codex/routing/selection.ts +4 -1
  141. package/src/codex/routing.ts +13 -17
  142. package/src/codex/runtime.ts +106 -18
  143. package/src/codex/shim.ts +45 -19
  144. package/src/combos/jev-decision-contract.ts +25 -2
  145. package/src/combos/jev-service-exchange.ts +281 -0
  146. package/src/combos/jev.ts +34 -219
  147. package/src/combos/types.ts +1 -1
  148. package/src/config/atomic-write.ts +1 -1
  149. package/src/config/codex-ws-reuse-setting.ts +10 -0
  150. package/src/config/diagnostics.ts +27 -16
  151. package/src/config/live-reconcile.ts +17 -0
  152. package/src/config/load-degrade.ts +42 -0
  153. package/src/config/rebase-provenance.ts +11 -0
  154. package/src/config/schema/anthropic-account-pool.ts +143 -0
  155. package/src/config/schema/config-schema.ts +11 -1
  156. package/src/config/schema/leaf-validators.ts +4 -0
  157. package/src/config.ts +2 -0
  158. package/src/generated/compatibility-version.json +566 -298
  159. package/src/generated/model-metadata.ts +7 -6
  160. package/src/grok/inject.ts +50 -4
  161. package/src/grok/sync.ts +2 -1
  162. package/src/images/loop.ts +30 -11
  163. package/src/integrations/aside-profiles.ts +10 -3
  164. package/src/integrations/catalog-refresh.ts +19 -3
  165. package/src/integrations/mutation-plan.ts +7 -0
  166. package/src/integrations/registry.ts +8 -0
  167. package/src/integrations/state.ts +9 -2
  168. package/src/integrations/writer.ts +17 -5
  169. package/src/lib/bun-path-runtime.d.mts +32 -0
  170. package/src/lib/bun-path-runtime.mjs +95 -0
  171. package/src/lib/bun-runtime-preflight.ts +140 -0
  172. package/src/lib/desktop-cli-handoff.d.mts +20 -0
  173. package/src/lib/desktop-cli-handoff.mjs +92 -0
  174. package/src/lib/desktop-cli-record.d.mts +29 -0
  175. package/src/lib/desktop-cli-record.mjs +102 -0
  176. package/src/lib/lab-live-route-production.ts +9 -1
  177. package/src/lib/request-execution-budget.ts +244 -58
  178. package/src/lib/spend-pool-alias-validation.ts +79 -0
  179. package/src/lib/spend-pool-continuity.ts +34 -0
  180. package/src/lib/spend-reservation-ledger.ts +412 -50
  181. package/src/lib/state-store-registrations.ts +20 -3
  182. package/src/lib/synced-state-location.ts +46 -6
  183. package/src/lib/test-home-guard.ts +87 -1
  184. package/src/lib/translator-budget.ts +17 -4
  185. package/src/lib/upstream-retry.ts +17 -5
  186. package/src/lib/windows-atomic-replace.ts +38 -16
  187. package/src/lib/windows-elevation.ts +6 -0
  188. package/src/lib/windows-secret-acl.ts +92 -25
  189. package/src/lib/winsw.ts +2 -3
  190. package/src/lib/workflow-budget.ts +53 -11
  191. package/src/messaging/budget.ts +45 -0
  192. package/src/messaging/discovery.ts +57 -0
  193. package/src/messaging/envelope.ts +49 -0
  194. package/src/messaging/input.ts +37 -0
  195. package/src/messaging/rpc.ts +196 -0
  196. package/src/messaging/send.ts +58 -0
  197. package/src/messaging/socket.ts +72 -0
  198. package/src/messaging/types.ts +29 -0
  199. package/src/oauth/anthropic-account-refusal.ts +90 -18
  200. package/src/oauth/anthropic-account-threshold.ts +8 -2
  201. package/src/oauth/anthropic-continuity.ts +15 -1
  202. package/src/oauth/anthropic-model-quota.ts +120 -48
  203. package/src/oauth/anthropic-model-routes.ts +11 -3
  204. package/src/oauth/anthropic-oauth-definitions.ts +98 -0
  205. package/src/oauth/anthropic-pool-config.ts +30 -0
  206. package/src/oauth/anthropic-rate-limit-policy.ts +64 -9
  207. package/src/oauth/anthropic-routing.ts +1202 -866
  208. package/src/oauth/anthropic-send-ownership.ts +41 -0
  209. package/src/oauth/anthropic.ts +4 -1
  210. package/src/oauth/chatgpt.ts +113 -41
  211. package/src/oauth/generic-account-failover.ts +3 -1
  212. package/src/oauth/health.ts +8 -6
  213. package/src/oauth/index.ts +96 -175
  214. package/src/oauth/kiro.ts +22 -9
  215. package/src/oauth/login-cli.ts +2 -0
  216. package/src/oauth/model-discovery-auth.ts +43 -0
  217. package/src/oauth/pool-kernel.ts +11 -5
  218. package/src/oauth/pool-settings-capability.ts +5 -3
  219. package/src/oauth/store-anthropic-instance.ts +87 -0
  220. package/src/oauth/store.ts +68 -10
  221. package/src/oauth/token-guardian.ts +2 -0
  222. package/src/oauth/types.ts +2 -0
  223. package/src/protocols/plan-snapshot.ts +5 -0
  224. package/src/protocols/settings.ts +20 -5
  225. package/src/providers/anthropic-instance-id.ts +47 -0
  226. package/src/providers/anthropic-instance.ts +48 -0
  227. package/src/providers/anthropic-reset-grant-ledger.ts +11 -1
  228. package/src/providers/azure-model-metadata.ts +115 -0
  229. package/src/providers/derive.ts +23 -0
  230. package/src/providers/kiro-models.ts +3 -0
  231. package/src/providers/label.ts +1 -1
  232. package/src/providers/model-rename-fields.ts +2 -0
  233. package/src/providers/quota/account-cache.ts +37 -11
  234. package/src/providers/quota/anthropic-account-quota.ts +93 -0
  235. package/src/providers/quota/anthropic-cooldown-recovery.ts +222 -111
  236. package/src/providers/quota/report-cache.ts +24 -1
  237. package/src/providers/quota/vendor-probes-key.ts +127 -17
  238. package/src/providers/quota/vendor-probes-oauth.ts +46 -14
  239. package/src/providers/quota.ts +23 -33
  240. package/src/providers/registry/entries-core.ts +35 -30
  241. package/src/providers/registry/model-ids.ts +1 -0
  242. package/src/providers/registry/model-seeds.ts +7 -4
  243. package/src/providers/registry/types.ts +3 -0
  244. package/src/providers/registry.ts +3 -3
  245. package/src/responses/reasoning-envelope.ts +29 -1
  246. package/src/responses/reasoning-replay-cache.ts +17 -1
  247. package/src/responses/spill-store.ts +20 -3
  248. package/src/responses/state/metrics.ts +95 -0
  249. package/src/responses/state/snapshot-codec.ts +6 -0
  250. package/src/responses/state/spill-failure.ts +12 -0
  251. package/src/responses/state/spill-queue.ts +13 -5
  252. package/src/responses/state/unforced-store-false.ts +55 -0
  253. package/src/responses/state.ts +68 -76
  254. package/src/responses/task-input.ts +17 -0
  255. package/src/router.ts +28 -4
  256. package/src/routing/compatibility/assemble.ts +1 -1
  257. package/src/routing/quota.ts +7 -3
  258. package/src/server/auth-cors.ts +5 -0
  259. package/src/server/background-lifecycle.ts +27 -0
  260. package/src/server/chat-completions.ts +7 -1
  261. package/src/server/chat-native.ts +64 -28
  262. package/src/server/claude-messages.ts +59 -8
  263. package/src/server/gui-static.ts +38 -4
  264. package/src/server/inbound-body-admission.ts +1 -0
  265. package/src/server/index/claude-intercept-lifecycle.ts +3 -1
  266. package/src/server/index/serve-options.ts +10 -2
  267. package/src/server/index/spend-ledger-lifecycle.ts +12 -5
  268. package/src/server/index/startup-warnings.ts +19 -0
  269. package/src/server/index.ts +5 -2
  270. package/src/server/inference/context.ts +1 -1
  271. package/src/server/lifecycle.ts +1 -1
  272. package/src/server/management/agent-settings-routes.ts +123 -38
  273. package/src/server/management/anthropic-account-threshold.ts +12 -9
  274. package/src/server/management/anthropic-pool-settings.ts +72 -0
  275. package/src/server/management/anthropic-reset-grant-routes.ts +98 -39
  276. package/src/server/management/codex-agent-role-routes.ts +4 -2
  277. package/src/server/management/codex-prompt-routes.ts +1 -0
  278. package/src/server/management/codex-role-auto-assign.ts +13 -2
  279. package/src/server/management/config-routes.ts +85 -14
  280. package/src/server/management/context.ts +2 -2
  281. package/src/server/management/decision-routes.ts +2 -1
  282. package/src/server/management/integration-routes.ts +25 -2
  283. package/src/server/management/oauth-account-routes.ts +79 -98
  284. package/src/server/management/provider-instance-ownership.ts +44 -0
  285. package/src/server/management/provider-routes.ts +21 -28
  286. package/src/server/management/route-registry.ts +3 -1
  287. package/src/server/management/routing-profile-routes.ts +4 -4
  288. package/src/server/management/shared.ts +3 -3
  289. package/src/server/management/system-restart.ts +44 -14
  290. package/src/server/management/system-routes.ts +24 -2
  291. package/src/server/management/vision-sidecar-options.ts +9 -6
  292. package/src/server/management/web-search-sidecar-options.ts +51 -2
  293. package/src/server/management-auth.ts +6 -0
  294. package/src/server/messages-native-eligibility.ts +3 -2
  295. package/src/server/messages-native-oauth.ts +91 -45
  296. package/src/server/messages-native-selector.ts +39 -0
  297. package/src/server/messages-native.ts +133 -38
  298. package/src/server/messages-response-headers.ts +14 -0
  299. package/src/server/request-log-conversation.ts +48 -5
  300. package/src/server/request-log.ts +36 -2
  301. package/src/server/responses/adapter-continuation.ts +31 -19
  302. package/src/server/responses/adapter-dispatch.ts +75 -24
  303. package/src/server/responses/antigravity-validation-refusal.ts +20 -6
  304. package/src/server/responses/codex-ws-exchange.ts +17 -2
  305. package/src/server/responses/codex-ws-pool.ts +100 -13
  306. package/src/server/responses/codex-ws-wire.ts +9 -0
  307. package/src/server/responses/combo-requested-effort.ts +3 -1
  308. package/src/server/responses/compact.ts +25 -8
  309. package/src/server/responses/compaction-recovery.ts +1 -1
  310. package/src/server/responses/core-codex-account.ts +22 -1
  311. package/src/server/responses/core-combo-native.ts +24 -4
  312. package/src/server/responses/core-combo.ts +38 -25
  313. package/src/server/responses/core-lifetime.ts +3 -36
  314. package/src/server/responses/core-normalize.ts +1 -0
  315. package/src/server/responses/core-options.ts +8 -1
  316. package/src/server/responses/core-replay.ts +78 -0
  317. package/src/server/responses/core.ts +3 -3
  318. package/src/server/responses/fetch-helpers.ts +26 -3
  319. package/src/server/responses/passthrough-delivery.ts +30 -4
  320. package/src/server/responses/passthrough-dispatch.ts +39 -9
  321. package/src/server/responses/request-prepare.ts +41 -5
  322. package/src/server/responses/request-send-budget.ts +150 -50
  323. package/src/server/responses/request-spend.ts +325 -33
  324. package/src/server/responses/request-transport.ts +132 -52
  325. package/src/server/responses/response-effects.ts +1 -0
  326. package/src/server/responses/run-turn-execution.ts +13 -3
  327. package/src/server/responses/sidecar-execution.ts +113 -22
  328. package/src/server/responses/sidecar-send-budget.ts +58 -0
  329. package/src/server/responses/ws-upstream.ts +19 -6
  330. package/src/server/responses-undeclared-tool-guard.ts +5 -1
  331. package/src/server/startup-health-cache.ts +2 -1
  332. package/src/server/workflow-refusal.ts +33 -0
  333. package/src/service/cli.ts +20 -4
  334. package/src/service/desktop-command-guard.ts +32 -0
  335. package/src/service/desktop-startup.ts +66 -40
  336. package/src/service/desktop-supervision.d.mts +26 -0
  337. package/src/service/desktop-supervision.mjs +140 -0
  338. package/src/service/managing-cli.ts +1 -0
  339. package/src/service/orchestration.ts +46 -20
  340. package/src/service/ownership-mutation-lease.d.mts +1 -1
  341. package/src/service/ownership-mutation-lease.mjs +5 -7
  342. package/src/service/repair.ts +25 -9
  343. package/src/service/state.ts +4 -3
  344. package/src/service/systemd.ts +17 -8
  345. package/src/service/windows-ops.ts +61 -22
  346. package/src/sidecar/anthropic-binding.ts +79 -0
  347. package/src/sidecar/auth.ts +76 -2
  348. package/src/storage/policy-job.ts +5 -1
  349. package/src/storage/policy-worker.ts +3 -1
  350. package/src/storage/policy.ts +9 -0
  351. package/src/types/anthropic-account-pool.ts +33 -0
  352. package/src/types/config.ts +33 -28
  353. package/src/types/provider.ts +5 -0
  354. package/src/types/request.ts +5 -0
  355. package/src/types/tools.ts +7 -0
  356. package/src/types/wire.ts +1 -0
  357. package/src/types.ts +4 -0
  358. package/src/update/index.ts +57 -9
  359. package/src/update/restart-ownership.ts +10 -3
  360. package/src/update/runtime-ownership.d.mts +6 -0
  361. package/src/update/runtime-ownership.mjs +23 -7
  362. package/src/usage/cost.ts +3 -2
  363. package/src/usage/expected-prices.ts +66 -14
  364. package/src/vision/anthropic-describe.ts +16 -3
  365. package/src/vision/index.ts +3 -0
  366. package/src/vision/plan.ts +19 -6
  367. package/src/web-search/alpha-search.ts +7 -1
  368. package/src/web-search/anthropic-executor.ts +16 -4
  369. package/src/web-search/index.ts +7 -3
  370. package/src/web-search/loop.ts +32 -7
  371. package/src/web-search/passthrough-bridge.ts +4 -1
  372. package/src/web-search/sidecar-providers.ts +4 -3
  373. package/gui/dist/assets/App-MbDVfUeC.js +0 -54
  374. package/gui/dist/assets/Tray-CzkxK82A.js +0 -1
  375. package/gui/dist/assets/index-UJt6npXk.js +0 -94
  376. package/gui/dist/assets/quota-summary-DU3sD6Z-.js +0 -1
@@ -4,7 +4,7 @@ export { isMediaGenerationModelId, shouldExposeRoutedModel, readCodexCatalogPath
4
4
  export type { CatalogModel, MultiAgentMode } from "./catalog/parsing";
5
5
  export { accountBoundNativeOpenAiSlugs, accountBoundNativeOpenAiSlugsBySelector, CODEX_NATIVE_ALIAS_CATALOG_KIND, NATIVE_DAYBREAK_BLUE_MODEL, NATIVE_GPT6_ASTRA_MODEL, NATIVE_GPT56_CONTEXT_WINDOW, NATIVE_GPT56_MAX_INPUT_TOKENS, NATIVE_GPT56_OPT_IN_CONTEXT_WINDOW, NATIVE_OPENAI_CAPABILITY_ALIAS_MODELS, NATIVE_OPENAI_MODELS, configuredNativeAliasSlugs, desktopAllowlistSuppressedNativeSlugs, isNativeAliasCatalogEntry, isNativeOpenAiCapabilityAliasModel, nativeContextLimits, nativeOpenAiCapabilitySourceSlug, nativeOpenAiContextWindow, nativeOpenAiMaxInputTokens, nativeOpenAiMaxOutputTokens, nativeOpenAiContextTier, disabledNativeSlugs, visibleNativeSlugs, desktopVisibleNativeSlugs, nativeModelRows, applyNativeVisibility, observedAccountBoundNativeEntries, observedAccountBoundNativeOpenAiSlugs, upstreamNativeEntry, nativeOpenAiSlugs, listCatalogNativeSlugs, nativeInputModalities, nativeReasoningEfforts, nativeDefaultReasoningEffort, shouldIncludeAccountBoundNativeOpenAi, shouldIncludeNativeOpenAi, type NativeContextLimits, type NativeContextLimitsInput } from "./catalog/metadata";
6
6
  export { isSpawnableCodexCandidate, codexExecInvocation, loadBundledCodexCatalog, materializeBundledCodexCatalog, loadCatalogTemplate } from "./catalog/bundled";
7
- export { nativeEffortClamp, shouldApplyNativeEffortClamp, catalogModelEfforts, codexSupportedReasoningEfforts, clampedDefaultEffort, clampEntryToCodexSupportedEfforts, clampCatalogModelsToCodexSupport } from "./catalog/effort";
7
+ export { nativeEffortClamp, shouldApplyNativeEffortClamp, catalogModelEfforts, catalogModelLadders, codexSupportedReasoningEfforts, clampedDefaultEffort, clampEntryToCodexSupportedEfforts, clampCatalogModelsToCodexSupport } from "./catalog/effort";
8
8
  export { applyProviderConfigHints, isDatedVariantId, filterCatalogVisibleModels, gatherRoutedModels, clearGatherRoutedModelsInflight, augmentRoutedModelsWithRegistryOpenAiApiRows, augmentRoutedModelsWithMetadata, resolveComboCatalogMember, configuredComboTargetModelsByProvider } from "./catalog/provider-fetch";
9
9
  export { deriveComboCatalogModel, exactComboCatalogSlugs, getLastComboCatalogOmissions, resetOpenAiApiCatalogWarningStateForTests, uniqueCatalogModelsForPublicList, uniqueCatalogModelsForRawPublicList, buildComboCatalogOmission, comboCatalogOmissionReason, summarizeComboCatalogOmissions } from "./catalog/aggregation";
10
10
  export type { ComboCatalogOmission, ComboCatalogOmissionReason } from "./catalog/aggregation";
@@ -39,6 +39,9 @@ function provenAbsent(path: string): boolean {
39
39
  catch (error) { return absent(error) && provenAbsent(parent); }
40
40
  }
41
41
 
42
+ /** A missing directory entry is a no-op; dangling links and unreadable homes are not. */
43
+ export function codexHomeIsAbsent(home: string): boolean { return provenAbsent(home); }
44
+
42
45
  function validJournal(value: unknown): value is Record<string, unknown> {
43
46
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
44
47
  const journal = value as Record<string, unknown>;
@@ -0,0 +1,333 @@
1
+ /**
2
+ * config-write-lock.ts — one advisory lock for every opencodex-originated
3
+ * `config.toml` write.
4
+ *
5
+ * Why a second lock next to the existing two: the injector's SQLite lock N
6
+ * serializes injection against injection, and the prompt-layers lock serializes
7
+ * prompt edits against prompt edits. Neither covers the writers BETWEEN them —
8
+ * the feature scalars in `features.ts`, the `ocx restore`/`removeCodexConfig`
9
+ * transforms, and the journal replay each did their own unlocked read → edit →
10
+ * `atomicWriteFile`. Each write is individually atomic, but a foreign rewrite
11
+ * landing between any writer's read and its rename was silently discarded:
12
+ * a features edit could drop an injection's freshly-written routing keys, a
13
+ * remove could drop a prompt projection committed a millisecond earlier.
14
+ *
15
+ * This lock closes that class at its source rather than per call site: every
16
+ * opencodex writer reads `config.toml` and renames over it while holding
17
+ * `<config>.ocx-write.lock`, so no cooperating writer can be computed against
18
+ * stale bytes and none can land mid-section.
19
+ *
20
+ * What it deliberately does NOT cover:
21
+ * - Codex itself knows nothing about the file; upstream's own rewrites cannot
22
+ * be serialized from here. That residual is why the injector's witness and
23
+ * the drift healer still exist.
24
+ * - Lock ordering: prompt-layers commit() takes the prompt store lock first,
25
+ * then this one; the injector takes this one first, then N, then C — and the
26
+ * coordinated restore path follows that same file-first order
27
+ * (`restoreNativeCodexAsyncImpl` acquires this lock before its `withCodexWriteLock`
28
+ * journal replay), so no cross-lock inversion remains. Synchronous
29
+ * acquisition fails fast; asynchronous acquisition has a bounded wait.
30
+ * - The injector's held section contains awaits (`withCodexWriteLock` is
31
+ * async), so the lock must NOT be implicitly reentrant — a same-process
32
+ * writer that slipped inside on a process-global check would interleave
33
+ * mid-section. Reentrancy is explicit instead: a caller that already holds
34
+ * the file passes its handle (`heldConfigWriteLock`) to the writer it
35
+ * calls.
36
+ * - Acquisition is a single attempt for synchronous writers: the section under
37
+ * this lock is a handful of file operations, so a busy result means the
38
+ * caller reports "locked" and the operator retries — the same contract the
39
+ * prompt store lock already exposes. Async callers (the injector) use the
40
+ * bounded wait in `acquireConfigWriteLock`.
41
+ */
42
+ import { atomicWriteFileStreamed, type AtomicWriteHooks } from "../config/atomic-write";
43
+ import { lstatSync, readFileSync, realpathSync, statSync, unlinkSync, writeFileSync } from "node:fs";
44
+ import { randomUUID } from "node:crypto";
45
+ import { basename, dirname, join, resolve } from "node:path";
46
+ import { release, stillHeld, tryAcquire, type AcquireResult, type LockHandle } from "./prompt-lock";
47
+
48
+ interface Destination { canonical: string; inode: string | null }
49
+ const destinations = new WeakMap<LockHandle, Destination>();
50
+ interface ConfigWriteRecovery {
51
+ canonical: string;
52
+ preimage: Buffer | null;
53
+ identity: string | null;
54
+ refreshBeforeSpawn: boolean;
55
+ }
56
+ const recoveries = new WeakMap<LockHandle, ConfigWriteRecovery>();
57
+ export class ConfigWriteParentMissing extends Error {
58
+ constructor(readonly path: string) { super(`Codex configuration parent is missing or unresolved at ${path}`); }
59
+ }
60
+ type ConfigWriteAcquireResult = AcquireResult | { ok: false; error: "missing-parent"; detail: string };
61
+ function destination(path: string): Destination {
62
+ const absolute = resolve(path);
63
+ let canonical: string;
64
+ try { canonical = realpathSync.native(absolute); }
65
+ catch (error) {
66
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
67
+ try { canonical = join(realpathSync.native(dirname(absolute)), basename(absolute)); }
68
+ catch (parentError) {
69
+ if ((parentError as NodeJS.ErrnoException).code === "ENOENT") throw new ConfigWriteParentMissing(dirname(absolute));
70
+ throw parentError;
71
+ }
72
+ }
73
+ try {
74
+ const stat = statSync(canonical, { bigint: true });
75
+ return { canonical, inode: `${stat.dev}:${stat.ino}` };
76
+ } catch (error) {
77
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
78
+ return { canonical, inode: null };
79
+ }
80
+ }
81
+ /** Symlink aliases share the lock beside their canonical write destination. */
82
+ export function configWriteLockPath(configPath: string): string {
83
+ return `${destination(configPath).canonical}.ocx-write.lock`;
84
+ }
85
+ export const CONFIG_WRITE_LOCKED_MESSAGE =
86
+ "another opencodex process is writing Codex configuration — retry shortly";
87
+ export type ConfigWriteLockOutcome<T> =
88
+ | { ok: true; value: T }
89
+ | Exclude<ConfigWriteAcquireResult, { ok: true }>;
90
+
91
+ function acquire(configPath: string): ConfigWriteAcquireResult {
92
+ let target: Destination;
93
+ try { target = destination(configPath); }
94
+ catch (error) {
95
+ if (error instanceof ConfigWriteParentMissing) return { ok: false, error: "missing-parent", detail: error.path };
96
+ throw error;
97
+ }
98
+ const acquired = tryAcquire(`${target.canonical}.ocx-write.lock`);
99
+ if (acquired.ok) destinations.set(acquired.handle, target);
100
+ return acquired;
101
+ }
102
+ export function withConfigWriteLock<T>(configPath: string, run: (handle: LockHandle) => T): ConfigWriteLockOutcome<T> {
103
+ const acquired = acquire(configPath);
104
+ if (!acquired.ok) return acquired;
105
+ try { return { ok: true, value: run(acquired.handle) }; }
106
+ finally { release(acquired.handle); }
107
+ }
108
+ export function configWriteLockHeld(handle: LockHandle): boolean { return stillHeld(handle); }
109
+ export function releaseConfigWriteLock(handle: LockHandle): void { release(handle); }
110
+ export type { LockHandle };
111
+
112
+ export function assertConfigWriteDestination(configPath: string, held: LockHandle): string {
113
+ const current = destination(configPath);
114
+ const expected = destinations.get(held);
115
+ if (!stillHeld(held) || held.path !== `${current.canonical}.ocx-write.lock`
116
+ || (expected && (current.canonical !== expected.canonical || current.inode !== expected.inode))) {
117
+ throw new Error("Codex configuration destination changed; files and recovery evidence were preserved.");
118
+ }
119
+ if (!expected) destinations.set(held, current);
120
+ return current.canonical;
121
+ }
122
+ /** A writer advances the witness only through its confirmed publication hook. */
123
+ export function publishConfigWrite<T>(configPath: string, held: LockHandle, run: (destination: string, hooks: AtomicWriteHooks) => T): T {
124
+ const canonical = assertConfigWriteDestination(configPath, held);
125
+ return run(canonical, {
126
+ validateBeforeRename: () => { assertConfigWriteDestination(configPath, held); },
127
+ afterRename: () => {
128
+ const recovery = recoveries.get(held);
129
+ if (recovery?.canonical === canonical) recovery.identity = canonicalFileIdentity(canonical);
130
+ const after = destination(configPath);
131
+ if (!stillHeld(held) || after.canonical !== canonical) throw new Error("Codex configuration destination changed; recovery evidence was preserved.");
132
+ destinations.set(held, after);
133
+ const watched = targets.get(held);
134
+ if (watched) for (const [path, expected] of watched) if (expected.canonical === canonical) watched.set(path, after);
135
+ },
136
+ });
137
+ }
138
+ /** Native children use the acquisition witness, never a fresh home resolution. */
139
+ export class ConfigWriteDestinationChanged extends Error {
140
+ readonly retryable = false;
141
+ constructor(message = "Codex configuration destination changed; files and recovery evidence were preserved.") { super(message); }
142
+ }
143
+ /** Refuse before transition staging: native Codex always writes home/config.toml. */
144
+ export function assertNativeConfigWriteDestination(configPath: string, held: LockHandle): string {
145
+ let canonical: string;
146
+ try { canonical = assertConfigWriteDestination(configPath, held); }
147
+ catch { throw new ConfigWriteDestinationChanged(); }
148
+ const home = realpathSync.native(dirname(canonical));
149
+ if (basename(canonical) !== "config.toml" || canonical !== join(home, "config.toml")) {
150
+ throw new ConfigWriteDestinationChanged("Native feature changes are unavailable when config.toml is a symlink to a differently named file.");
151
+ }
152
+ return canonical;
153
+ }
154
+ function canonicalFileIdentity(canonical: string): string | null {
155
+ const current = destination(canonical);
156
+ if (current.canonical !== canonical) throw new Error("canonical configuration target was redirected");
157
+ let stat;
158
+ try { stat = lstatSync(canonical, { bigint: true }); }
159
+ catch (error) {
160
+ if ((error as NodeJS.ErrnoException).code === "ENOENT" && current.inode === null) return null;
161
+ throw error;
162
+ }
163
+ if (!stat.isFile() || `${stat.dev}:${stat.ino}` !== current.inode) throw new Error("canonical configuration target is not the observed regular file");
164
+ return `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeNs}:${stat.ctimeNs}`;
165
+ }
166
+ /** Capture before the first write; nested native children share the same recovery scope. */
167
+ export function withConfigWriteRecovery<T>(
168
+ configPath: string, held: LockHandle, run: () => T,
169
+ options: { refreshBeforeSpawn?: boolean; preimage?: Buffer } = {},
170
+ ): T {
171
+ if (recoveries.has(held)) return run();
172
+ let canonical: string;
173
+ try { canonical = assertConfigWriteDestination(configPath, held); }
174
+ catch { throw new ConfigWriteDestinationChanged(); }
175
+ const identity = canonicalFileIdentity(canonical);
176
+ const preimage = identity === null ? null : readFileSync(canonical);
177
+ if (canonicalFileIdentity(canonical) !== identity) throw new ConfigWriteDestinationChanged();
178
+ const recovery: ConfigWriteRecovery = {
179
+ canonical, identity, preimage: options.preimage ?? preimage,
180
+ refreshBeforeSpawn: options.refreshBeforeSpawn === true && options.preimage === undefined,
181
+ };
182
+ recoveries.set(held, recovery);
183
+ try {
184
+ const value = run();
185
+ assertConfigWriteDestination(configPath, held);
186
+ return value;
187
+ } catch (error) {
188
+ let changed = error instanceof ConfigWriteDestinationChanged;
189
+ try { assertConfigWriteDestination(configPath, held); } catch { changed = true; }
190
+ try {
191
+ const validateRecovery = (targetPath = canonical) => {
192
+ if (targetPath !== canonical || !stillHeld(held) || held.path !== `${canonical}.ocx-write.lock`
193
+ || canonicalFileIdentity(canonical) !== recovery.identity) {
194
+ throw new Error("canonical configuration target changed before recovery");
195
+ }
196
+ };
197
+ validateRecovery();
198
+ // A pre-write refusal leaves the original entry intact, including its inode.
199
+ const unchanged = recovery.identity === identity && (recovery.preimage === preimage
200
+ || (recovery.preimage !== null && preimage !== null && recovery.preimage.equals(preimage)));
201
+ if (!unchanged) {
202
+ if (recovery.preimage === null) { validateRecovery(); if (recovery.identity !== null) unlinkSync(canonical); }
203
+ else atomicWriteFileStreamed(canonical, fd => writeFileSync(fd, recovery.preimage!), { validateBeforeRename: validateRecovery });
204
+ }
205
+ destinations.set(held, destination(canonical));
206
+ } catch (recoveryError) {
207
+ let evidence = "recovery evidence could not be persisted";
208
+ try {
209
+ const recoveryPath = `${canonical}.ocx-native-preimage.${randomUUID()}`;
210
+ atomicWriteFileStreamed(recoveryPath, fd => writeFileSync(fd, recovery.preimage ?? Buffer.from('{"preimage":"absent"}\n')));
211
+ evidence = `recovery evidence retained at ${recoveryPath}`;
212
+ } catch { /* Preserve the refusal and diagnostic even when evidence storage fails. */ }
213
+ throw new ConfigWriteDestinationChanged(`Codex configuration destination changed; canonical preimage recovery refused: ${recoveryError instanceof Error ? recoveryError.message : String(recoveryError)}; ${evidence}.`);
214
+ }
215
+ if (changed) throw new ConfigWriteDestinationChanged(`${error instanceof Error ? error.message : String(error)}; canonical preimage restored and recovery evidence preserved.`);
216
+ throw error;
217
+ } finally { recoveries.delete(held); }
218
+ }
219
+ export function runConfigWriteChild(
220
+ configPath: string, held: LockHandle,
221
+ run: (env: NodeJS.ProcessEnv, validateBeforeSpawn: () => void) => void,
222
+ transitionPreimage?: Buffer,
223
+ ): void {
224
+ withConfigWriteRecovery(configPath, held, () => {
225
+ const canonical = assertNativeConfigWriteDestination(configPath, held);
226
+ const recovery = recoveries.get(held)!;
227
+ let readyToSpawn = false;
228
+ const validateBeforeSpawn = () => {
229
+ readyToSpawn = false;
230
+ assertNativeConfigWriteDestination(configPath, held);
231
+ const identity = canonicalFileIdentity(canonical);
232
+ const bytes = identity === null ? null : readFileSync(canonical);
233
+ if (canonicalFileIdentity(canonical) !== identity) throw new ConfigWriteDestinationChanged();
234
+ if (recovery.refreshBeforeSpawn) { recovery.preimage = bytes; recovery.identity = identity; }
235
+ readyToSpawn = true;
236
+ };
237
+ publishConfigWrite(configPath, held, (_canonical, hooks) => {
238
+ const env = { ...process.env };
239
+ // Windows env names are case-insensitive; wrappers may honor Orca's override.
240
+ for (const key of Object.keys(env)) {
241
+ if (["CODEX_HOME", "ORCA_CODEX_HOME"].includes(key.toUpperCase())) delete env[key];
242
+ }
243
+ env.CODEX_HOME = realpathSync.native(dirname(canonical));
244
+ validateBeforeSpawn();
245
+ try { run(env, validateBeforeSpawn); }
246
+ // Even a failed child can replace config.toml. Observe only after it entered.
247
+ finally {
248
+ try { if (readyToSpawn) hooks.afterRename?.(canonical); }
249
+ catch { throw new ConfigWriteDestinationChanged(); }
250
+ }
251
+ });
252
+ }, { refreshBeforeSpawn: true, preimage: transitionPreimage });
253
+ }
254
+ export function withConfigWriteLockHeld<T>(
255
+ configPath: string, held: LockHandle | undefined, run: (handle: LockHandle) => T,
256
+ ): ConfigWriteLockOutcome<T> {
257
+ if (held !== undefined) {
258
+ try { assertConfigWriteDestination(configPath, held); }
259
+ catch { return { ok: false, error: "unsafe", detail: held.path }; }
260
+ return { ok: true, value: run(held) };
261
+ }
262
+ return withConfigWriteLock(configPath, run);
263
+ }
264
+ const RETRY_MIN_MS = 25;
265
+ const RETRY_MAX_MS = 75;
266
+ export const CONFIG_WRITE_LOCK_WAIT_MS = 2_000;
267
+ export async function acquireConfigWriteLock(
268
+ configPath: string,
269
+ options: { timeoutMs?: number; nowMs?: () => number; sleep?: (ms: number) => Promise<void> } = {},
270
+ ): Promise<ConfigWriteAcquireResult> {
271
+ const timeoutMs = options.timeoutMs ?? CONFIG_WRITE_LOCK_WAIT_MS;
272
+ if (!Number.isInteger(timeoutMs) || timeoutMs < 0 || timeoutMs > 10_000) throw new RangeError("Invalid config lock timeout");
273
+ const now = options.nowMs ?? (() => performance.now());
274
+ const sleep = options.sleep ?? (ms => new Promise(done => setTimeout(done, ms)));
275
+ const deadline = now() + timeoutMs;
276
+ for (;;) {
277
+ const acquired = acquire(configPath);
278
+ if (acquired.ok || acquired.error !== "locked") return acquired;
279
+ const remaining = deadline - now();
280
+ if (timeoutMs === 0 || remaining <= 0) return { ok: false, error: "locked" };
281
+ await sleep(Math.max(1, Math.min(remaining,
282
+ RETRY_MIN_MS + Math.floor(Math.random() * (RETRY_MAX_MS - RETRY_MIN_MS + 1)))));
283
+ }
284
+ }
285
+
286
+ const targets = new WeakMap<LockHandle, Map<string, Destination>>();
287
+ export function watchConfigWriteTargets(held: LockHandle, paths: readonly string[]): void {
288
+ let watched = targets.get(held);
289
+ if (!watched) { watched = new Map(); targets.set(held, watched); }
290
+ for (const path of paths) if (!watched.has(path)) watched.set(path, destination(path));
291
+ }
292
+ export function publishConfigWriteTarget<T>(
293
+ configPath: string, held: LockHandle, path: string, run: (destination: string, hooks: AtomicWriteHooks) => T,
294
+ ): T {
295
+ assertConfigWriteDestination(configPath, held);
296
+ watchConfigWriteTargets(held, [path]);
297
+ const watched = targets.get(held)!, expected = watched.get(path)!, current = destination(path);
298
+ if (expected.canonical !== current.canonical || expected.inode !== current.inode) {
299
+ throw new Error("Codex artifact destination changed; files and recovery evidence were preserved.");
300
+ }
301
+ if (path === configPath) {
302
+ const value = publishConfigWrite(configPath, held, run);
303
+ return value;
304
+ }
305
+ return run(current.canonical, {
306
+ validateBeforeRename: () => {
307
+ assertConfigWriteDestination(configPath, held);
308
+ const now = destination(path);
309
+ if (expected.canonical !== now.canonical || expected.inode !== now.inode) throw new Error("Codex artifact destination changed; files and recovery evidence were preserved.");
310
+ },
311
+ afterRename: () => {
312
+ assertConfigWriteDestination(configPath, held);
313
+ const after = destination(path);
314
+ if (after.canonical !== current.canonical) throw new Error("Codex artifact destination changed; recovery evidence was preserved.");
315
+ watched.set(path, after);
316
+ },
317
+ });
318
+ }
319
+
320
+ export function configWriteLockFailureMessage(failure: Exclude<ConfigWriteAcquireResult, { ok: true }>): string {
321
+ if (failure.error === "missing-parent") return `Codex configuration parent is missing or unresolved at ${failure.detail}; no files were changed.`;
322
+ return failure.error === "unsafe"
323
+ ? `Unsafe Codex configuration lock at ${failure.detail}; deliberate removal is required. Files and recovery evidence were preserved.`
324
+ : CONFIG_WRITE_LOCKED_MESSAGE;
325
+ }
326
+
327
+ export class ConfigWriteLockRefusal extends Error {
328
+ readonly retryable: boolean;
329
+ constructor(failure: Exclude<ConfigWriteAcquireResult, { ok: true }>) {
330
+ super(configWriteLockFailureMessage(failure));
331
+ this.retryable = failure.error === "locked";
332
+ }
333
+ }
@@ -0,0 +1,6 @@
1
+ /** Exact Codex control-plane ids routed to canonical OpenAI, outside the public native roster. */
2
+ export const CODEX_INTERNAL_OPENAI_MODELS: ReadonlySet<string> = new Set(["codex-auto-review"]);
3
+
4
+ export function isCodexControlPlaneModel(slug: unknown): boolean {
5
+ return typeof slug === "string" && CODEX_INTERNAL_OPENAI_MODELS.has(slug);
6
+ }
@@ -2,7 +2,7 @@ import { projectAntigravitySelectedModels } from "../providers/antigravity-effor
2
2
  import { join } from "node:path";
3
3
  import { sameCatalogHealPath } from "./catalog/heal-observation";
4
4
 
5
- import { getConfigDir, saveConfigPreservingClaudeCode, websocketsEnabled, withExpectedConfigGenerationSync } from "../config";
5
+ import { getConfigDir, saveConfigPreservingClaudeCode, ultraFastTierEnabled, websocketsEnabled, withExpectedConfigGenerationSync } from "../config";
6
6
  import { reconcileSuccessfulModelDiscoveries } from "../providers/new-model-policy";
7
7
  import { pendingModelSelectionProviders } from "../providers/initial-model-selection";
8
8
  import { COMBO_NAMESPACE } from "../combos";
@@ -370,6 +370,7 @@ function prepareCatalog(
370
370
  )),
371
371
  );
372
372
  const mergedModels = mergeCatalogEntriesFromObservedState({
373
+ ultraFastTier: ultraFastTierEnabled(config),
373
374
  modelPickerOrder,
374
375
  accountSelectors,
375
376
  catalogModels,