@iislee/opencodex 2.11.0 → 2.31.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 (675) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +114 -19
  3. package/bin/ocx.mjs +164 -36
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-BF38heuV.js +104 -0
  6. package/gui/dist/assets/index-DMiI18Kv.css +1 -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 +19 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +376 -52
  44. package/src/adapters/base.ts +54 -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 +601 -0
  48. package/src/adapters/cursor/checkpoint-store.ts +303 -0
  49. package/src/adapters/cursor/cursor-errors.ts +129 -6
  50. package/src/adapters/cursor/discovery.ts +61 -4
  51. package/src/adapters/cursor/effort-map.ts +27 -3
  52. package/src/adapters/cursor/framing.ts +39 -0
  53. package/src/adapters/cursor/h2-pool.ts +123 -0
  54. package/src/adapters/cursor/http1-bidi.ts +361 -0
  55. package/src/adapters/cursor/images.ts +704 -0
  56. package/src/adapters/cursor/live-models.ts +174 -58
  57. package/src/adapters/cursor/live-transport.ts +609 -170
  58. package/src/adapters/cursor/native-exec-common.ts +23 -2
  59. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  60. package/src/adapters/cursor/native-exec-network.ts +1 -1
  61. package/src/adapters/cursor/native-exec-shell.ts +0 -1
  62. package/src/adapters/cursor/native-exec.ts +101 -14
  63. package/src/adapters/cursor/protobuf-events.ts +829 -11
  64. package/src/adapters/cursor/protobuf-request.ts +383 -65
  65. package/src/adapters/cursor/request-builder.ts +237 -31
  66. package/src/adapters/cursor/tool-definitions.ts +242 -12
  67. package/src/adapters/cursor/tool-result-normalize.ts +92 -0
  68. package/src/adapters/cursor/transport.ts +22 -0
  69. package/src/adapters/cursor/types.ts +28 -1
  70. package/src/adapters/cursor.ts +133 -7
  71. package/src/adapters/google-antigravity-replay.ts +558 -34
  72. package/src/adapters/google-antigravity-wire.ts +43 -10
  73. package/src/adapters/google-http.ts +38 -10
  74. package/src/adapters/google-tool-schema.ts +80 -15
  75. package/src/adapters/google-truncation.ts +11 -0
  76. package/src/adapters/google.ts +618 -74
  77. package/src/adapters/identity.ts +39 -6
  78. package/src/adapters/kiro-errors.ts +11 -0
  79. package/src/adapters/kiro-events.ts +19 -1
  80. package/src/adapters/kiro-thinking.ts +18 -2
  81. package/src/adapters/kiro-tools.ts +10 -1
  82. package/src/adapters/kiro.ts +92 -54
  83. package/src/adapters/mimo-free.ts +17 -0
  84. package/src/adapters/openai-chat-url.ts +11 -0
  85. package/src/adapters/openai-chat.ts +1311 -336
  86. package/src/adapters/openai-responses-url.ts +16 -0
  87. package/src/adapters/openai-responses.ts +830 -56
  88. package/src/adapters/registry.ts +175 -0
  89. package/src/adapters/responses-tool-schema.ts +67 -0
  90. package/src/adapters/tool-call-id.ts +119 -0
  91. package/src/adapters/tool-catalog-nudge.ts +104 -21
  92. package/src/adapters/xai-web-search.ts +185 -0
  93. package/src/bridge.ts +428 -61
  94. package/src/chat/inbound.ts +43 -19
  95. package/src/chat/outbound.ts +82 -26
  96. package/src/claude/agents-inject.ts +32 -9
  97. package/src/claude/context-windows.ts +21 -5
  98. package/src/claude/desktop-3p.ts +243 -9
  99. package/src/claude/gateway-cache.ts +41 -4
  100. package/src/claude/inbound.ts +72 -3
  101. package/src/claude/model-info.ts +38 -15
  102. package/src/claude/outbound.ts +70 -16
  103. package/src/cli/account-api.ts +35 -1
  104. package/src/cli/account-auth.ts +33 -6
  105. package/src/cli/account-catalog-refresh.ts +14 -0
  106. package/src/cli/account-extended.ts +389 -2
  107. package/src/cli/account-main.ts +317 -0
  108. package/src/cli/account.ts +30 -6
  109. package/src/cli/agent.ts +45 -1
  110. package/src/cli/claude-agent-startup-sync.ts +73 -0
  111. package/src/cli/claude-desktop.ts +29 -4
  112. package/src/cli/claude.ts +103 -34
  113. package/src/cli/codex-log-guard-doctor.ts +103 -0
  114. package/src/cli/codex-shim-autorestore.ts +2 -0
  115. package/src/cli/codex-shim-readiness.ts +76 -0
  116. package/src/cli/combo.ts +8 -0
  117. package/src/cli/config-command.ts +74 -10
  118. package/src/cli/dispatch.ts +593 -0
  119. package/src/cli/doctor.ts +315 -43
  120. package/src/cli/ensure-desired-integrations.ts +152 -0
  121. package/src/cli/export-command.ts +46 -20
  122. package/src/cli/help.ts +20 -271
  123. package/src/cli/index.ts +378 -519
  124. package/src/cli/init.ts +4 -17
  125. package/src/cli/integrations.ts +120 -2
  126. package/src/cli/lab.ts +607 -0
  127. package/src/cli/launcher-context.ts +77 -0
  128. package/src/cli/minimax.ts +497 -0
  129. package/src/cli/models-runtime.ts +35 -2
  130. package/src/cli/models.ts +100 -14
  131. package/src/cli/observe.ts +92 -3
  132. package/src/cli/opencode.ts +4 -2
  133. package/src/cli/provider-runtime.ts +18 -1
  134. package/src/cli/provider.ts +24 -3
  135. package/src/cli/ready.ts +301 -0
  136. package/src/cli/registry.ts +437 -0
  137. package/src/cli/root.ts +86 -0
  138. package/src/cli/route-policy.ts +92 -0
  139. package/src/cli/runtime-api.ts +6 -3
  140. package/src/cli/star-prompt.ts +71 -15
  141. package/src/cli/status.ts +10 -3
  142. package/src/cli/system-restart-client.ts +146 -0
  143. package/src/cli/tray-proxy.ts +153 -6
  144. package/src/cli/v2.ts +105 -10
  145. package/src/cli.ts +1 -1
  146. package/src/clients/config-export.ts +1358 -21
  147. package/src/codex/account-label.ts +14 -1
  148. package/src/codex/account-lifecycle.ts +130 -13
  149. package/src/codex/account-namespaces.ts +49 -3
  150. package/src/codex/account-priority.ts +83 -0
  151. package/src/codex/account-store.ts +29 -2
  152. package/src/codex/account-usability.ts +25 -2
  153. package/src/codex/admission.ts +256 -0
  154. package/src/codex/affinity-debug.ts +162 -0
  155. package/src/codex/app-server-processes.ts +493 -106
  156. package/src/codex/app-server-restart-service.ts +232 -0
  157. package/src/codex/auth-api.ts +849 -242
  158. package/src/codex/auth-collision.ts +5 -3
  159. package/src/codex/auth-context.ts +345 -32
  160. package/src/codex/autostart-health.ts +8 -1
  161. package/src/codex/catalog/account-models.ts +67 -0
  162. package/src/codex/catalog/aggregation.ts +68 -10
  163. package/src/codex/catalog/bundled.ts +331 -33
  164. package/src/codex/catalog/effort.ts +121 -30
  165. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  166. package/src/codex/catalog/kinds.ts +2 -0
  167. package/src/codex/catalog/metadata.ts +529 -45
  168. package/src/codex/catalog/native-models.ts +72 -0
  169. package/src/codex/catalog/parsing.ts +224 -30
  170. package/src/codex/catalog/provider-fetch.ts +1460 -134
  171. package/src/codex/catalog/sync.ts +1449 -186
  172. package/src/codex/catalog-admission.ts +199 -0
  173. package/src/codex/catalog-refresh-status.ts +105 -0
  174. package/src/codex/catalog-write-serialization.ts +242 -0
  175. package/src/codex/catalog.ts +6 -3
  176. package/src/codex/codex-write-lock.ts +384 -0
  177. package/src/codex/convergence-types.ts +614 -0
  178. package/src/codex/convergence.ts +651 -0
  179. package/src/codex/coordinator-doctor.ts +332 -0
  180. package/src/codex/custom-model-catalog-migration.ts +176 -0
  181. package/src/codex/desired-state.ts +230 -0
  182. package/src/codex/features.ts +636 -39
  183. package/src/codex/generation.ts +202 -0
  184. package/src/codex/history-job.ts +407 -0
  185. package/src/codex/history-lock.ts +242 -0
  186. package/src/codex/history-migration-guardian.ts +26 -20
  187. package/src/codex/history-provider.ts +231 -28
  188. package/src/codex/history-transition.ts +105 -0
  189. package/src/codex/history-worker.ts +220 -0
  190. package/src/codex/inject-coordination.ts +290 -0
  191. package/src/codex/inject.ts +1073 -152
  192. package/src/codex/injected-marker.ts +37 -3
  193. package/src/codex/integration-record.ts +266 -0
  194. package/src/codex/internal/catalog-writer.ts +203 -0
  195. package/src/codex/internal/history-writer.ts +80 -0
  196. package/src/codex/journal.ts +66 -4
  197. package/src/codex/log-guard/inspect.ts +506 -0
  198. package/src/codex/log-guard/lock.ts +150 -0
  199. package/src/codex/log-guard/maintenance.ts +403 -0
  200. package/src/codex/log-guard/path-safety.ts +88 -0
  201. package/src/codex/log-guard/policy.ts +44 -0
  202. package/src/codex/log-guard/processes.ts +205 -0
  203. package/src/codex/log-guard/protection.ts +489 -0
  204. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  205. package/src/codex/main-account-cache.ts +24 -0
  206. package/src/codex/main-account.ts +29 -1
  207. package/src/codex/management-convergence.ts +167 -0
  208. package/src/codex/model-cache.ts +56 -10
  209. package/src/codex/model-entitlements.ts +353 -0
  210. package/src/codex/native-main-admission.ts +47 -0
  211. package/src/codex/native-main-auth-temp.ts +187 -0
  212. package/src/codex/native-main-claim.ts +178 -0
  213. package/src/codex/native-main-lock-file.ts +162 -0
  214. package/src/codex/native-main-owner.ts +329 -0
  215. package/src/codex/native-profile-api.ts +247 -0
  216. package/src/codex/native-profile-manager.ts +1531 -0
  217. package/src/codex/native-profile-processes.ts +121 -0
  218. package/src/codex/native-profile-recovery.ts +99 -0
  219. package/src/codex/native-profile-stage-store.ts +387 -0
  220. package/src/codex/native-profile-startup.ts +492 -0
  221. package/src/codex/native-profile-store.ts +855 -0
  222. package/src/codex/native-profile-types.ts +120 -0
  223. package/src/codex/native-residue.ts +682 -0
  224. package/src/codex/paths.ts +80 -1
  225. package/src/codex/plan-from-token.ts +140 -0
  226. package/src/codex/plan.ts +40 -0
  227. package/src/codex/plugins-doctor.ts +1 -1
  228. package/src/codex/pool-rotation.ts +74 -4
  229. package/src/codex/project-config-warnings.ts +20 -6
  230. package/src/codex/prompt-journal.ts +352 -0
  231. package/src/codex/prompt-layers.ts +967 -0
  232. package/src/codex/prompt-lock.ts +143 -0
  233. package/src/codex/quota-rejection.ts +298 -0
  234. package/src/codex/quota.ts +175 -13
  235. package/src/codex/refresh.ts +11 -2
  236. package/src/codex/reset-credit-recovery.ts +1044 -0
  237. package/src/codex/routing.ts +505 -94
  238. package/src/codex/runtime.ts +159 -38
  239. package/src/codex/shim.ts +1009 -28
  240. package/src/codex/subagent-model-fallback.ts +350 -35
  241. package/src/codex/sync.ts +191 -2
  242. package/src/codex/transition-state.ts +612 -0
  243. package/src/codex/upstream-host-health.ts +368 -0
  244. package/src/codex/user-identity.ts +557 -0
  245. package/src/codex/warmup.ts +187 -81
  246. package/src/codex/write-coordination.ts +114 -0
  247. package/src/combos/failover.ts +20 -0
  248. package/src/combos/index.ts +4 -0
  249. package/src/combos/request.ts +32 -0
  250. package/src/combos/types.ts +81 -9
  251. package/src/config/provider-name.ts +24 -0
  252. package/src/config.ts +1762 -140
  253. package/src/generated/compatibility-version.json +3164 -0
  254. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  255. package/src/grok/inject.ts +16 -5
  256. package/src/grok/inspect.ts +45 -0
  257. package/src/grok/sync.ts +2 -2
  258. package/src/images/loop.ts +152 -29
  259. package/src/images/plan.ts +23 -13
  260. package/src/integrations/config-io.ts +269 -0
  261. package/src/integrations/journal.ts +315 -0
  262. package/src/integrations/merge.ts +135 -0
  263. package/src/integrations/mutation-flight.ts +71 -0
  264. package/src/integrations/native/ownership-preflight.ts +202 -0
  265. package/src/integrations/omp-yaml-source.ts +358 -0
  266. package/src/integrations/owned-refresh.ts +74 -0
  267. package/src/integrations/ownership.ts +111 -0
  268. package/src/integrations/registry.ts +159 -0
  269. package/src/integrations/serialize.ts +314 -0
  270. package/src/integrations/state.ts +361 -0
  271. package/src/integrations/store.ts +103 -0
  272. package/src/integrations/writer-lock.ts +98 -0
  273. package/src/integrations/writer.ts +691 -0
  274. package/src/lab/artifacts/sanitize.ts +586 -0
  275. package/src/lab/artifacts/secure-fs.ts +475 -0
  276. package/src/lab/artifacts/store.ts +310 -0
  277. package/src/lab/automation/budgets.ts +78 -0
  278. package/src/lab/automation/config-persistence.ts +256 -0
  279. package/src/lab/automation/constants.ts +39 -0
  280. package/src/lab/automation/cooldown.ts +103 -0
  281. package/src/lab/automation/dispatch.ts +211 -0
  282. package/src/lab/automation/index.ts +13 -0
  283. package/src/lab/automation/orchestrator.ts +499 -0
  284. package/src/lab/automation/persistence.ts +512 -0
  285. package/src/lab/automation/planner.ts +371 -0
  286. package/src/lab/automation/policy.ts +136 -0
  287. package/src/lab/automation/queue.ts +191 -0
  288. package/src/lab/automation/recovery.ts +24 -0
  289. package/src/lab/automation/route-context.ts +21 -0
  290. package/src/lab/automation/run-key.ts +44 -0
  291. package/src/lab/automation/runs-query.ts +34 -0
  292. package/src/lab/automation/types.ts +160 -0
  293. package/src/lab/conformance/assertion.ts +325 -0
  294. package/src/lab/conformance/digest.ts +22 -0
  295. package/src/lab/conformance/executor.ts +741 -0
  296. package/src/lab/conformance/fixture-provider.ts +27 -0
  297. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  298. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  299. package/src/lab/conformance/harness-budget.ts +47 -0
  300. package/src/lab/conformance/index.ts +5 -0
  301. package/src/lab/conformance/jcs.ts +64 -0
  302. package/src/lab/conformance/json-pointer.ts +39 -0
  303. package/src/lab/conformance/manifest.ts +180 -0
  304. package/src/lab/conformance/mcp-stub.ts +179 -0
  305. package/src/lab/conformance/negative-controls.ts +164 -0
  306. package/src/lab/conformance/observation.ts +355 -0
  307. package/src/lab/conformance/runner.ts +68 -0
  308. package/src/lab/conformance/sse-normalize.ts +59 -0
  309. package/src/lab/conformance/suite-manifest.ts +78 -0
  310. package/src/lab/conformance/types.ts +214 -0
  311. package/src/lab/constants.ts +126 -0
  312. package/src/lab/digest.ts +64 -0
  313. package/src/lab/events/errors.ts +9 -0
  314. package/src/lab/events/limits.ts +117 -0
  315. package/src/lab/events/types.ts +229 -0
  316. package/src/lab/events/validate.ts +781 -0
  317. package/src/lab/fabric/constants.ts +40 -0
  318. package/src/lab/fabric/executor.ts +492 -0
  319. package/src/lab/fabric/index.ts +80 -0
  320. package/src/lab/fabric/manifest.ts +222 -0
  321. package/src/lab/fabric/observe.ts +489 -0
  322. package/src/lab/fabric/patch.ts +79 -0
  323. package/src/lab/fabric/producer-child.ts +139 -0
  324. package/src/lab/fabric/producer-isolate.ts +276 -0
  325. package/src/lab/fabric/producer-protocol.ts +61 -0
  326. package/src/lab/fabric/scratch.ts +439 -0
  327. package/src/lab/fabric/subject.ts +106 -0
  328. package/src/lab/fabric/types.ts +134 -0
  329. package/src/lab/fabric/verifier.ts +98 -0
  330. package/src/lab/index.ts +54 -0
  331. package/src/lab/ledger/artifact-refs.ts +127 -0
  332. package/src/lab/ledger/invalidation.ts +136 -0
  333. package/src/lab/ledger/purge.ts +310 -0
  334. package/src/lab/ledger/store.ts +532 -0
  335. package/src/lab/live/credential-lease.ts +53 -0
  336. package/src/lab/live/destination.ts +155 -0
  337. package/src/lab/live/executor.ts +336 -0
  338. package/src/lab/live/inert-tools.ts +56 -0
  339. package/src/lab/live/manifest.ts +85 -0
  340. package/src/lab/live/mcp-loopback.ts +57 -0
  341. package/src/lab/live/runner.ts +19 -0
  342. package/src/lab/live/sandbox.ts +61 -0
  343. package/src/lab/live/suite-manifest.ts +41 -0
  344. package/src/lab/live/transport.ts +118 -0
  345. package/src/lab/live/types.ts +197 -0
  346. package/src/lab/observe/from-conformance.ts +301 -0
  347. package/src/lab/observe/from-live.ts +117 -0
  348. package/src/lab/paths.ts +153 -0
  349. package/src/lab/projection/rebuild.ts +495 -0
  350. package/src/lab/projection/schema.ts +135 -0
  351. package/src/lab/projection/verdicts.ts +474 -0
  352. package/src/lab/projection/verification.ts +412 -0
  353. package/src/lab/public/bundle.ts +217 -0
  354. package/src/lab/public/community-authority.ts +175 -0
  355. package/src/lab/public/community-files.ts +29 -0
  356. package/src/lab/public/community.ts +479 -0
  357. package/src/lab/public/file-safety.ts +155 -0
  358. package/src/lab/public/ids.ts +26 -0
  359. package/src/lab/public/index.ts +16 -0
  360. package/src/lab/public/mutation-lock.ts +424 -0
  361. package/src/lab/public/operator.ts +353 -0
  362. package/src/lab/public/origin-purge.ts +79 -0
  363. package/src/lab/public/origin.ts +203 -0
  364. package/src/lab/public/privacy.ts +143 -0
  365. package/src/lab/public/private-file.ts +261 -0
  366. package/src/lab/public/project.ts +124 -0
  367. package/src/lab/public/purge-test-fault.ts +21 -0
  368. package/src/lab/public/purge.ts +223 -0
  369. package/src/lab/public/registry.ts +44 -0
  370. package/src/lab/public/revocation.ts +252 -0
  371. package/src/lab/public/signature.ts +243 -0
  372. package/src/lab/public/storage.ts +105 -0
  373. package/src/lab/public/strict-json.ts +206 -0
  374. package/src/lab/public/time.ts +26 -0
  375. package/src/lab/public/types.ts +172 -0
  376. package/src/lab/public/validate.ts +391 -0
  377. package/src/lab/query/catalog.ts +101 -0
  378. package/src/lab/query/connection.ts +107 -0
  379. package/src/lab/query/constants.ts +4 -0
  380. package/src/lab/query/cursor.ts +132 -0
  381. package/src/lab/query/dto-map.ts +277 -0
  382. package/src/lab/query/errors.ts +22 -0
  383. package/src/lab/query/freshness.ts +53 -0
  384. package/src/lab/query/index.ts +45 -0
  385. package/src/lab/query/latest-observation.ts +59 -0
  386. package/src/lab/query/passive-production.ts +159 -0
  387. package/src/lab/query/queries.ts +444 -0
  388. package/src/lab/query/types.ts +266 -0
  389. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  390. package/src/lab/subject/installation-salt.ts +112 -0
  391. package/src/lab/subject/protocol-subject.ts +80 -0
  392. package/src/lab/subject/route-subject.ts +74 -0
  393. package/src/lib/app-owned-memory-stores.ts +22 -0
  394. package/src/lib/bounded-body.ts +153 -9
  395. package/src/lib/bun-runtime.ts +125 -12
  396. package/src/lib/bun-stream-caps.ts +13 -9
  397. package/src/lib/codex-restart-contract.ts +120 -0
  398. package/src/lib/config-ownership.ts +6 -2
  399. package/src/lib/destination-policy.ts +65 -1
  400. package/src/lib/errors.ts +44 -2
  401. package/src/lib/fabric-task-execution-authority.ts +7 -0
  402. package/src/lib/fabric-task-host.ts +29 -0
  403. package/src/lib/lab-activation.ts +223 -0
  404. package/src/lib/lab-live-execution-authority.ts +13 -0
  405. package/src/lib/lab-live-host.ts +30 -0
  406. package/src/lib/lab-live-pinned-sender.ts +56 -0
  407. package/src/lib/lab-live-route-production.ts +130 -0
  408. package/src/lib/lab-passive-linker-registration.ts +26 -0
  409. package/src/lib/local-management-attestation.ts +51 -0
  410. package/src/lib/local-management-capability.ts +100 -0
  411. package/src/lib/local-provider-reload-contract.ts +100 -0
  412. package/src/lib/optional-shutdown-hooks.ts +57 -0
  413. package/src/lib/pinned-http.ts +145 -26
  414. package/src/lib/process-control.ts +4 -1
  415. package/src/lib/provider-outbound.ts +49 -9
  416. package/src/lib/redact.ts +419 -3
  417. package/src/lib/self-launch-argv.ts +15 -0
  418. package/src/lib/server-resource-ownership.ts +71 -0
  419. package/src/lib/shadow-call.ts +35 -4
  420. package/src/lib/sse-decoder.ts +41 -0
  421. package/src/lib/state-store-registrations.ts +10 -2
  422. package/src/lib/system-restart-contract.ts +73 -0
  423. package/src/lib/token-estimate.ts +19 -2
  424. package/src/lib/tool-argument-integers.ts +202 -0
  425. package/src/lib/translator-budget.ts +44 -0
  426. package/src/lib/upstream-http-version.ts +57 -0
  427. package/src/lib/upstream-reachability.ts +95 -0
  428. package/src/lib/upstream-retry.ts +156 -3
  429. package/src/lib/windows-atomic-replace.ts +155 -0
  430. package/src/lib/windows-elevation.ts +70 -2
  431. package/src/lib/windows-secret-acl.ts +409 -69
  432. package/src/lib/windows-service-wrappers.ts +72 -0
  433. package/src/lib/windows-text.ts +106 -0
  434. package/src/lib/windows-user-principal.ts +341 -0
  435. package/src/lib/winsw.ts +33 -5
  436. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  437. package/src/oauth/account-import/index.ts +15 -0
  438. package/src/oauth/account-import/parser.ts +83 -0
  439. package/src/oauth/account-import/registry.ts +18 -0
  440. package/src/oauth/account-import/service.ts +75 -0
  441. package/src/oauth/account-import/types.ts +91 -0
  442. package/src/oauth/anthropic.ts +12 -1
  443. package/src/oauth/callback-server.ts +8 -2
  444. package/src/oauth/chatgpt.ts +12 -1
  445. package/src/oauth/command-code.ts +239 -0
  446. package/src/oauth/cursor.ts +46 -5
  447. package/src/oauth/google-antigravity.ts +35 -3
  448. package/src/oauth/health.ts +20 -12
  449. package/src/oauth/index.ts +398 -66
  450. package/src/oauth/key-providers.ts +16 -0
  451. package/src/oauth/kimi.ts +16 -2
  452. package/src/oauth/kiro.ts +50 -6
  453. package/src/oauth/local-token-detect.ts +11 -2
  454. package/src/oauth/log.ts +3 -1
  455. package/src/oauth/login-cli.ts +88 -28
  456. package/src/oauth/nous.ts +798 -0
  457. package/src/oauth/store.ts +119 -21
  458. package/src/oauth/token-guardian.ts +9 -3
  459. package/src/pi/models.ts +2 -2
  460. package/src/providers/alibaba-region-migration.ts +1 -1
  461. package/src/providers/antigravity-models.ts +521 -31
  462. package/src/providers/base-url-choices.ts +10 -0
  463. package/src/providers/codex-capacity.ts +292 -0
  464. package/src/providers/command-code-efforts.ts +144 -0
  465. package/src/providers/context-cap.ts +22 -5
  466. package/src/providers/cursor-pool.ts +72 -0
  467. package/src/providers/derive.ts +253 -6
  468. package/src/providers/fastwire.ts +501 -0
  469. package/src/providers/free-directory.ts +10 -7
  470. package/src/providers/google-vertex-location.ts +14 -0
  471. package/src/providers/key-failover.ts +71 -3
  472. package/src/providers/label.ts +1 -1
  473. package/src/providers/model-discovery-limits.ts +16 -0
  474. package/src/providers/model-discovery.ts +115 -22
  475. package/src/providers/model-rename-migration.ts +255 -0
  476. package/src/providers/model-rename-startup.ts +28 -0
  477. package/src/providers/openai-sidecar.ts +72 -4
  478. package/src/providers/openai-tier-startup.ts +31 -2
  479. package/src/providers/openai-tiers.ts +119 -4
  480. package/src/providers/openai-virtual-models.ts +1 -0
  481. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  482. package/src/providers/provider-id-rewrite.ts +29 -0
  483. package/src/providers/quota.ts +1319 -38
  484. package/src/providers/registry.ts +1429 -111
  485. package/src/providers/request-pacing.ts +310 -0
  486. package/src/providers/service-tier.ts +277 -0
  487. package/src/providers/slug-codec.ts +42 -6
  488. package/src/providers/static-model-discovery.ts +86 -0
  489. package/src/providers/xai-responses-opt-in.ts +15 -0
  490. package/src/providers/xai-transport.ts +11 -4
  491. package/src/reasoning-effort.ts +49 -1
  492. package/src/responses/compaction.ts +26 -1
  493. package/src/responses/custom-tool-compat.ts +266 -0
  494. package/src/responses/hosted-tool-policy.ts +9 -0
  495. package/src/responses/namespace-tool-compat.ts +355 -0
  496. package/src/responses/parser.ts +220 -38
  497. package/src/responses/provider-continuation.ts +98 -0
  498. package/src/responses/provider-opaque-metadata.ts +73 -0
  499. package/src/responses/reasoning-envelope.ts +9 -1
  500. package/src/responses/reasoning-replay-cache.ts +426 -0
  501. package/src/responses/schema.ts +7 -1
  502. package/src/responses/spill-store.ts +75 -10
  503. package/src/responses/state.ts +565 -27
  504. package/src/responses/thought-signature-replay.ts +347 -0
  505. package/src/responses/tool-search-compat.ts +301 -0
  506. package/src/responses/truncated-stop-reason.ts +60 -0
  507. package/src/router.ts +366 -30
  508. package/src/routing/analytics.ts +378 -0
  509. package/src/routing/capability.ts +244 -0
  510. package/src/routing/compatibility/assemble.ts +73 -0
  511. package/src/routing/compatibility/behavior.ts +278 -0
  512. package/src/routing/compatibility/catalog.ts +99 -0
  513. package/src/routing/compatibility/endpoint.ts +52 -0
  514. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  515. package/src/routing/compatibility/policy.ts +181 -0
  516. package/src/routing/compatibility/provider-slot.ts +56 -0
  517. package/src/routing/compatibility/reader.ts +110 -0
  518. package/src/routing/compatibility/subject.ts +191 -0
  519. package/src/routing/compatibility/types.ts +64 -0
  520. package/src/routing/compatibility/version.ts +104 -0
  521. package/src/routing/cost.ts +77 -0
  522. package/src/routing/evaluator.ts +495 -0
  523. package/src/routing/health.ts +412 -0
  524. package/src/routing/history/cursor.ts +43 -0
  525. package/src/routing/history/indexer.ts +605 -0
  526. package/src/routing/history/schema.ts +72 -0
  527. package/src/routing/profile-namespace.ts +15 -0
  528. package/src/routing/profile.ts +547 -0
  529. package/src/routing/quota.ts +145 -0
  530. package/src/routing/request-evidence.ts +45 -0
  531. package/src/routing/trace.ts +776 -0
  532. package/src/server/adapter-resolve.ts +2 -29
  533. package/src/server/auth-cors.ts +267 -46
  534. package/src/server/background-lifecycle.ts +182 -0
  535. package/src/server/chat-completions.ts +130 -56
  536. package/src/server/chat-native-sse.ts +331 -0
  537. package/src/server/chat-native.ts +426 -0
  538. package/src/server/claude-messages.ts +159 -43
  539. package/src/server/direct-local-http.ts +347 -0
  540. package/src/server/effort-policy.ts +18 -0
  541. package/src/server/github-copilot-responses-repair.ts +338 -0
  542. package/src/server/gui-static.ts +39 -10
  543. package/src/server/images.ts +94 -12
  544. package/src/server/index.ts +865 -181
  545. package/src/server/lifecycle.ts +284 -13
  546. package/src/server/live.ts +136 -17
  547. package/src/server/local-management-read-client.ts +90 -0
  548. package/src/server/local-provider-reload-client.ts +137 -0
  549. package/src/server/management/agent-settings-routes.ts +398 -103
  550. package/src/server/management/api-key-usage.ts +31 -5
  551. package/src/server/management/body.ts +6 -0
  552. package/src/server/management/combo-routes.ts +62 -24
  553. package/src/server/management/config-routes.ts +464 -51
  554. package/src/server/management/context.ts +80 -2
  555. package/src/server/management/integration-routes.ts +498 -0
  556. package/src/server/management/lab-automation-routes.ts +206 -0
  557. package/src/server/management/lab-routes.ts +563 -0
  558. package/src/server/management/logs-usage-routes.ts +101 -32
  559. package/src/server/management/model-routes.ts +189 -131
  560. package/src/server/management/model-rows.ts +163 -0
  561. package/src/server/management/native-integration-routes.ts +769 -0
  562. package/src/server/management/oauth-account-routes.ts +80 -4
  563. package/src/server/management/provider-capability-config.ts +48 -0
  564. package/src/server/management/provider-routes.ts +764 -157
  565. package/src/server/management/request-history-routes.ts +191 -0
  566. package/src/server/management/routing-analytics-routes.ts +74 -0
  567. package/src/server/management/routing-profile-routes.ts +380 -0
  568. package/src/server/management/shared.ts +27 -11
  569. package/src/server/management/sidebar-routes.ts +47 -31
  570. package/src/server/management/storage-log-guard-routes.ts +186 -0
  571. package/src/server/management/sync-response.ts +69 -0
  572. package/src/server/management/system-restart.ts +288 -32
  573. package/src/server/management/system-routes.ts +77 -0
  574. package/src/server/management/usage-summary-cache.ts +9 -1
  575. package/src/server/management/vision-sidecar-options.ts +167 -0
  576. package/src/server/management/web-search-sidecar-options.ts +120 -0
  577. package/src/server/management-api.ts +115 -14
  578. package/src/server/management-auth.ts +220 -5
  579. package/src/server/passive-route-linker.ts +66 -0
  580. package/src/server/ports.ts +41 -1
  581. package/src/server/proxy-liveness.ts +132 -5
  582. package/src/server/readiness.ts +99 -0
  583. package/src/server/relay-eager.ts +82 -42
  584. package/src/server/relay.ts +236 -76
  585. package/src/server/request-decompress.ts +113 -6
  586. package/src/server/request-log.ts +235 -22
  587. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  588. package/src/server/responses/agent-task-recovery.ts +465 -0
  589. package/src/server/responses/collaboration.ts +204 -35
  590. package/src/server/responses/compact.ts +442 -55
  591. package/src/server/responses/core.ts +2872 -331
  592. package/src/server/responses/empty-completion-guard.ts +276 -0
  593. package/src/server/responses/encrypted-payload.ts +62 -39
  594. package/src/server/responses/fetch-helpers.ts +79 -4
  595. package/src/server/responses/input-admission.ts +185 -0
  596. package/src/server/responses/pacing-overload.ts +13 -0
  597. package/src/server/responses/policy-fallback.ts +178 -0
  598. package/src/server/responses/responses-field-backfill.ts +251 -0
  599. package/src/server/responses/terminal-guard.ts +26 -5
  600. package/src/server/responses/upstream-error.ts +5 -0
  601. package/src/server/responses/ws-upstream.ts +308 -0
  602. package/src/server/responses-custom-tool-repair.ts +282 -0
  603. package/src/server/responses-item-id-repair.ts +54 -6
  604. package/src/server/responses-json-events.ts +90 -0
  605. package/src/server/responses-model-rewrite.ts +29 -0
  606. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  607. package/src/server/responses-snapshot-repair.ts +621 -0
  608. package/src/server/responses-terminal-repair.ts +342 -0
  609. package/src/server/responses-tool-search-repair.ts +267 -0
  610. package/src/server/responses-undeclared-tool-guard.ts +153 -0
  611. package/src/server/responses.ts +18 -2
  612. package/src/server/search.ts +78 -13
  613. package/src/server/sse-frame-buffer.ts +292 -0
  614. package/src/server/sse-payload-rewrite.ts +110 -22
  615. package/src/server/startup-action-control.ts +8 -1
  616. package/src/server/startup-health-cache.ts +19 -1
  617. package/src/server/system-env.ts +80 -9
  618. package/src/server/ws-bridge.ts +39 -38
  619. package/src/service-manager-probe.ts +892 -0
  620. package/src/service.ts +1111 -90
  621. package/src/sidecar/auth.ts +92 -0
  622. package/src/sidecar/candidates.ts +83 -0
  623. package/src/storage/cleanup.ts +2 -2
  624. package/src/storage/scanner.ts +1 -1
  625. package/src/storage/worker-lifecycle.ts +14 -14
  626. package/src/tray/windows-tray.ps1 +83 -9
  627. package/src/tray/windows.ts +43 -16
  628. package/src/types/accounts.ts +37 -0
  629. package/src/types/config.ts +845 -0
  630. package/src/types/provider.ts +545 -0
  631. package/src/types/request.ts +384 -0
  632. package/src/types/tools.ts +131 -0
  633. package/src/types/wire.ts +80 -0
  634. package/src/types.ts +104 -1236
  635. package/src/update/index.ts +32 -19
  636. package/src/update/job.ts +442 -67
  637. package/src/update/notify.ts +12 -6
  638. package/src/update/npm-cache-preflight.d.mts +47 -0
  639. package/src/update/npm-cache-preflight.mjs +201 -0
  640. package/src/update/transactional-install.d.mts +22 -0
  641. package/src/update/transactional-install.mjs +259 -0
  642. package/src/usage/cost.ts +0 -0
  643. package/src/usage/expected-prices.ts +268 -16
  644. package/src/usage/log.ts +606 -41
  645. package/src/usage/summary.ts +177 -9
  646. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  647. package/src/usage/user-cost-overlays.ts +314 -0
  648. package/src/vision/anthropic-describe.ts +10 -6
  649. package/src/vision/backends.ts +97 -0
  650. package/src/vision/describe.ts +9 -3
  651. package/src/vision/eligibility.ts +250 -0
  652. package/src/vision/index.ts +238 -24
  653. package/src/vision/reasoning.ts +55 -0
  654. package/src/vision/routed-describe.ts +175 -0
  655. package/src/vision/timeout-bounds.ts +9 -0
  656. package/src/web-search/anthropic-executor.ts +13 -7
  657. package/src/web-search/backends.ts +108 -0
  658. package/src/web-search/exa-executor.ts +88 -0
  659. package/src/web-search/executor.ts +11 -3
  660. package/src/web-search/gemini-executor.ts +141 -0
  661. package/src/web-search/index.ts +150 -15
  662. package/src/web-search/loop.ts +279 -50
  663. package/src/web-search/parse.ts +125 -30
  664. package/src/web-search/sources.ts +60 -0
  665. package/src/web-search/xai-executor.ts +219 -0
  666. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  667. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  668. package/gui/dist/provider-icons/antigravity.svg +0 -1
  669. package/gui/dist/provider-icons/claude.svg +0 -1
  670. package/gui/dist/provider-icons/copilot.svg +0 -1
  671. package/gui/dist/provider-icons/cursor.svg +0 -2
  672. package/gui/dist/provider-icons/gemini.svg +0 -1
  673. package/gui/dist/provider-icons/grok-color.svg +0 -1
  674. package/gui/dist/provider-icons/kiro.svg +0 -14
  675. package/src/cli/internal-dispatch.ts +0 -20
@@ -9,17 +9,18 @@ import { buildModelsRequest, resolveModelsAuthToken } from "../../oauth";
9
9
  import type { OcxConfig, OcxProviderConfig } from "../../types";
10
10
  import { modelInList } from "../../types";
11
11
  import { CODEX_REASONING_LEVELS, codexEffortRank, configuredReasoningEfforts, modelRecordValue, sanitizeCodexReasoningEfforts } from "../../reasoning-effort";
12
- import { getJawcodeModelMetadata, getJawcodeModelMetadataCaseInsensitive, listJawcodeModelMetadata, resolveJawcodeProvider } from "../../generated/jawcode-model-metadata";
12
+ import { getModelMetadata, getModelMetadataCaseInsensitive, listModelMetadata, resolveMetadataProvider } from "../../generated/model-metadata";
13
13
  import { enrichProviderFromRegistry, shouldCaseFoldMetadataModelId } from "../../providers/derive";
14
14
  import { getProviderRegistryEntry } from "../../providers/registry";
15
15
  import { applyProviderContextCap, providerContextCap } from "../../providers/context-cap";
16
- import { routedSlug, slugEquals, slugsEquivalent } from "../../providers/slug-codec";
16
+ import { routedSlug, slugEquals, slugEquivalenceKey, slugsEquivalent } from "../../providers/slug-codec";
17
17
  import { CODEX_GPT5_IDENTITY_LINE } from "../../adapters/identity";
18
18
  import { filterCursorConfiguredModelsByLiveDiscovery } from "../../adapters/cursor/discovery";
19
19
  import { fetchCursorUsableModels } from "../../adapters/cursor/live-models";
20
20
  import { isCanonicalOpenAiForwardProvider, OPENAI_API_PROVIDER_ID, OPENAI_CODEX_PROVIDER_ID } from "../../providers/openai-tiers";
21
21
  import {
22
22
  COMBO_NAMESPACE,
23
+ comboDisabledModelSelectors,
23
24
  comboModelId,
24
25
  getCombo,
25
26
  listComboIds,
@@ -128,13 +129,30 @@ export function deriveComboCatalogModel(
128
129
  ): CatalogModel | null {
129
130
  if (comboCatalogOmissionReason(combo, members) !== null) return null;
130
131
 
131
- const inputModalities = intersectStrings(
132
+ const derivedInputModalities = intersectStrings(
132
133
  members.map(member => member.inputModalities ?? ["text"]),
133
134
  );
134
- const reasoningEfforts = intersectStrings(
135
- members.map(member => member.reasoningEfforts ?? []),
136
- );
135
+ const inputModalities = combo.imageInput === "disabled"
136
+ ? derivedInputModalities.filter(modality => modality !== "image")
137
+ : derivedInputModalities;
138
+ if (inputModalities.length === 0) return null;
139
+ // Unknown ladders (`undefined`) are wildcards for catalog derivation — same
140
+ // boundary as the GUI picker. An explicit empty ladder still constrains.
141
+ const advertisedLadders = members
142
+ .map(member => member.reasoningEfforts)
143
+ .filter((ladder): ladder is string[] => ladder !== undefined);
144
+ const reasoningEfforts = advertisedLadders.length === 0
145
+ ? []
146
+ : intersectStrings(advertisedLadders);
137
147
  const contextWindow = Math.min(...members.map(member => member.contextWindow!));
148
+ const limitingMembers = members.filter(member => member.contextWindow === contextWindow);
149
+ const hasLimitingContextCapMetadata = limitingMembers.some(
150
+ member => typeof member.contextCapped === "boolean",
151
+ );
152
+ // A combo is cap-limited only when every member defining its effective minimum was
153
+ // itself reduced by a provider cap. An uncapped member at the same minimum means the
154
+ // combo would have the same window even without the cap.
155
+ const contextCapped = limitingMembers.every(member => member.contextCapped === true);
138
156
  const maxInputTokens = Math.min(
139
157
  ...members.map(member => member.maxInputTokens ?? member.contextWindow!),
140
158
  );
@@ -149,14 +167,25 @@ export function deriveComboCatalogModel(
149
167
  owned_by: COMBO_NAMESPACE,
150
168
  contextWindow,
151
169
  maxInputTokens,
170
+ ...(hasLimitingContextCapMetadata ? { contextCapped } : {}),
152
171
  inputModalities,
153
172
  reasoningEfforts,
154
173
  ...(combo.alias ? { alias: combo.alias } : {}),
174
+ ...(combo.nativeAlias ? { nativeAlias: true } : {}),
175
+ ...(combo.displayName ? { displayName: combo.displayName } : {}),
155
176
  ...(defaultReasoningEffort ? { defaultReasoningEffort } : {}),
156
177
  ...(members.every(member => member.parallelToolCalls === true)
157
178
  ? { parallelToolCalls: true }
158
179
  : {}),
180
+ ...(members.every(member => member.supportsServiceTier === true)
181
+ ? { supportsServiceTier: true }
182
+ : members.some(member => member.supportsServiceTier === false)
183
+ ? { supportsServiceTier: false }
184
+ : {}),
159
185
  ...(members.some(member => member.supportsReasoningSummaries === false) ? { supportsReasoningSummaries: false } : {}),
186
+ ...(members.every(member => member.codexToolMode === "shell")
187
+ ? { codexToolMode: "shell" as const }
188
+ : {}),
160
189
  };
161
190
  }
162
191
 
@@ -252,12 +281,15 @@ export function exactComboCatalogSlugs(
252
281
  ): Set<string> {
253
282
  const disabled = new Set(config.disabledModels ?? []);
254
283
  return new Set(listComboIds(config).flatMap(id => {
255
- const alias = typeof config.combos?.[id]?.alias === "string"
256
- ? config.combos[id]!.alias!.trim()
284
+ const raw = config.combos?.[id];
285
+ const alias = typeof raw?.alias === "string"
286
+ ? raw.alias.trim()
257
287
  : "";
258
288
  const canonical = comboModelId(id);
259
289
  const publicSlug = alias || canonical;
260
- return disabled.has(publicSlug) || disabled.has(canonical) ? [] : [publicSlug];
290
+ const comboDisabled = comboDisabledModelSelectors(id, raw ?? {})
291
+ .some(selector => disabled.has(selector));
292
+ return comboDisabled ? [] : [publicSlug];
261
293
  }));
262
294
  }
263
295
 
@@ -281,6 +313,10 @@ export function resetOpenAiApiCatalogWarningStateForTests(): void {
281
313
  export const slugAliasCollisionWarnings = new Set<string>();
282
314
 
283
315
  export const comboMasqueradeCollisionWarnings = new Set<string>();
316
+
317
+ export const comboUnrestorableShadowWarnings = new Set<string>();
318
+
319
+ export const accountSelectorShadowCollisionWarnings = new Set<string>();
284
320
  let lastWarningReconciledGeneration = 0;
285
321
 
286
322
  export function reconcileCatalogWarningMemos(generation: number): number {
@@ -288,11 +324,15 @@ export function reconcileCatalogWarningMemos(generation: number): number {
288
324
  const removed = openAiApiCollisionWarnings.size
289
325
  + comboCatalogWarningSignatures.size
290
326
  + slugAliasCollisionWarnings.size
291
- + comboMasqueradeCollisionWarnings.size;
327
+ + comboMasqueradeCollisionWarnings.size
328
+ + comboUnrestorableShadowWarnings.size
329
+ + accountSelectorShadowCollisionWarnings.size;
292
330
  openAiApiCollisionWarnings.clear();
293
331
  comboCatalogWarningSignatures.clear();
294
332
  slugAliasCollisionWarnings.clear();
295
333
  comboMasqueradeCollisionWarnings.clear();
334
+ comboUnrestorableShadowWarnings.clear();
335
+ accountSelectorShadowCollisionWarnings.clear();
296
336
  lastWarningReconciledGeneration = generation;
297
337
  return removed;
298
338
  }
@@ -305,6 +345,24 @@ export function warnComboMasqueradeCollisionOnce(slug: string): void {
305
345
  );
306
346
  }
307
347
 
348
+ export function warnComboUnrestorableShadowOnce(slug: string): void {
349
+ const key = slugEquivalenceKey(slug);
350
+ if (comboUnrestorableShadowWarnings.has(key)) return;
351
+ comboUnrestorableShadowWarnings.add(key);
352
+ console.warn(
353
+ `[opencodex] combo alias collision on "${safeCatalogWarningLabel(slug)}": the existing user-managed or foreign catalog row is retained because no pristine backup can restore it. Rename the combo alias to expose both models.`,
354
+ );
355
+ }
356
+
357
+ /** Warn once when a live provider row loses its reserved slug to an account selector. */
358
+ export function warnAccountSelectorShadowedProviderOnce(slug: string): void {
359
+ if (accountSelectorShadowCollisionWarnings.has(slug)) return;
360
+ accountSelectorShadowCollisionWarnings.add(slug);
361
+ console.warn(
362
+ `[opencodex] account selector collision on "${safeCatalogWarningLabel(slug)}": the account-bound native model wins and the shadowed provider model is omitted from the catalog. Rename the provider or account selector.`,
363
+ );
364
+ }
365
+
308
366
  export function resolveSlugAliasCollisions(goModels: CatalogModel[]): Set<CatalogModel> {
309
367
  const skipped = new Set<CatalogModel>();
310
368
  const winnerByAlias = new Map<string, CatalogModel>();
@@ -9,7 +9,7 @@ import { buildModelsRequest, resolveModelsAuthToken } from "../../oauth";
9
9
  import type { OcxConfig, OcxProviderConfig } from "../../types";
10
10
  import { modelInList } from "../../types";
11
11
  import { CODEX_REASONING_LEVELS, codexEffortRank, configuredReasoningEfforts, modelRecordValue, sanitizeCodexReasoningEfforts } from "../../reasoning-effort";
12
- import { getJawcodeModelMetadata, getJawcodeModelMetadataCaseInsensitive, listJawcodeModelMetadata, resolveJawcodeProvider } from "../../generated/jawcode-model-metadata";
12
+ import { getModelMetadata, getModelMetadataCaseInsensitive, listModelMetadata, resolveMetadataProvider } from "../../generated/model-metadata";
13
13
  import { enrichProviderFromRegistry, shouldCaseFoldMetadataModelId } from "../../providers/derive";
14
14
  import { getProviderRegistryEntry } from "../../providers/registry";
15
15
  import { applyProviderContextCap, providerContextCap } from "../../providers/context-cap";
@@ -34,28 +34,121 @@ import upstreamModelsSnapshot from "../data/upstream-models.json";
34
34
  import { activeCodexModelsCachePath, catalogBackupPathFor, findNativeTemplate, isDefaultCatalogPath, legacyCatalogBackupPath, parseCatalogJson, readCatalog, readCatalogBackup, readCodexCatalogPath } from "./parsing";
35
35
  import type { RawCatalog, RawEntry } from "./parsing";
36
36
  import { codexExecInvocation, isSpawnableCodexCandidate } from "../exec-invocation";
37
- import { resolveAndPersistCodexRuntime } from "../runtime";
38
- import type { EffortClampDiagnostic } from "../runtime";
37
+ import {
38
+ parsePersistedCodexRuntime,
39
+ peekCodexRuntimeProcessCache,
40
+ resolveAndPersistCodexRuntime,
41
+ } from "../runtime";
42
+ import type {
43
+ DeepReadonly,
44
+ EffortClampDiagnostic,
45
+ ResolvedCodexRuntime,
46
+ } from "../runtime";
47
+ import type {
48
+ CatalogGatherEvidenceSession,
49
+ CatalogGatherReadableSourceRole,
50
+ } from "./filesystem-evidence";
39
51
 
40
52
  export { isSpawnableCodexCandidate, codexExecInvocation } from "../exec-invocation";
53
+ export type {
54
+ CatalogGatherEvidenceSession,
55
+ CatalogGatherReadableSourceRole,
56
+ } from "./filesystem-evidence";
41
57
 
42
58
  export const BUNDLED_CATALOG_CACHE_MS = 60_000;
43
59
 
44
- export let bundledCatalogCache: {
60
+ export type ReadonlyRawCatalog = DeepReadonly<RawCatalog>;
61
+
62
+ interface BundledCatalogMemo {
45
63
  /** Selected runtime identity; must change when doctor/sync picks a different binary. */
46
- key: string;
47
- expiresAt: number;
48
- value: RawCatalog | null;
49
- } | null = null;
64
+ readonly key: string;
65
+ readonly expiresAt: number;
66
+ readonly epoch: number;
67
+ readonly valueIdentity: string;
68
+ readonly value: ReadonlyRawCatalog | null;
69
+ }
70
+
71
+ export interface BundledCatalogCacheState {
72
+ readonly epoch: number;
73
+ readonly valueIdentity: string | null;
74
+ }
75
+
76
+ let bundledCatalogEpoch = 0;
77
+ let bundledCatalogCache: BundledCatalogMemo | null = null;
78
+
79
+ function cloneAndDeepFreeze<T>(value: T): DeepReadonly<T> {
80
+ const clone = (current: unknown): unknown => {
81
+ if (Array.isArray(current)) return current.map(clone);
82
+ if (current && typeof current === "object") {
83
+ const out: Record<string, unknown> = {};
84
+ for (const [key, child] of Object.entries(current)) out[key] = clone(child);
85
+ return out;
86
+ }
87
+ return current;
88
+ };
89
+ const freeze = (current: unknown): unknown => {
90
+ if (!current || typeof current !== "object" || Object.isFrozen(current)) return current;
91
+ for (const child of Object.values(current)) freeze(child);
92
+ return Object.freeze(current);
93
+ };
94
+ return freeze(clone(value)) as DeepReadonly<T>;
95
+ }
96
+
97
+ function bundledRuntimeKey(
98
+ runtime: Pick<ResolvedCodexRuntime, "command" | "version">,
99
+ opencodexHome: string = process.env.OPENCODEX_HOME ?? "",
100
+ ): string {
101
+ return [runtime.command, runtime.version ?? "", opencodexHome].join("\0");
102
+ }
103
+
104
+ function publishBundledCatalogCache(
105
+ key: string,
106
+ expiresAt: number,
107
+ value: RawCatalog | null,
108
+ ): void {
109
+ const epoch = ++bundledCatalogEpoch;
110
+ bundledCatalogCache = {
111
+ key,
112
+ expiresAt,
113
+ epoch,
114
+ valueIdentity: `bundled:${epoch}`,
115
+ value: value === null ? null : cloneAndDeepFreeze(value),
116
+ };
117
+ }
118
+
119
+ function clearBundledCatalogCache(): void {
120
+ bundledCatalogEpoch += 1;
121
+ bundledCatalogCache = null;
122
+ }
123
+
124
+ export function bundledCatalogCacheState(): Readonly<BundledCatalogCacheState> {
125
+ return Object.freeze({
126
+ epoch: bundledCatalogEpoch,
127
+ valueIdentity: bundledCatalogCache?.valueIdentity ?? null,
128
+ });
129
+ }
50
130
 
51
131
  /** Test-only: clear the bundled-catalog cache (owned here; sync.ts calls this instead of assigning the import). */
52
132
  export function resetBundledCatalogCacheForTests(): void {
53
- bundledCatalogCache = null;
133
+ clearBundledCatalogCache();
54
134
  }
55
135
 
56
136
  /** Drop the process-local bundled catalog memo (e.g. after runtime selection changes). */
57
137
  export function invalidateBundledCatalogCache(): void {
58
- bundledCatalogCache = null;
138
+ clearBundledCatalogCache();
139
+ }
140
+
141
+ /** Test-only owner mutation seam; input is cloned and frozen before publication. */
142
+ export function setBundledCatalogCacheForTests(
143
+ runtime: Pick<ResolvedCodexRuntime, "command" | "version">,
144
+ value: RawCatalog | null,
145
+ options: Readonly<{ expiresAt?: number; opencodexHome?: string }> = {},
146
+ ): void {
147
+ publishBundledCatalogCache(
148
+ bundledRuntimeKey(runtime, options.opencodexHome),
149
+ options.expiresAt ?? Date.now() + BUNDLED_CATALOG_CACHE_MS,
150
+ value,
151
+ );
59
152
  }
60
153
 
61
154
  export type ExecFile = (
@@ -143,7 +236,7 @@ export function runCodexDebugModels(
143
236
  });
144
237
  }
145
238
 
146
- export function loadBundledCodexCatalog(deps: BundledCatalogDeps = {}): RawCatalog | null {
239
+ export function loadBundledCodexCatalog(deps: BundledCatalogDeps = {}): ReadonlyRawCatalog | null {
147
240
  const useCache = !deps.commandCandidates && !deps.execFileSync && !deps.configDir && !deps.env;
148
241
  const execFile = deps.execFileSync ?? (execFileSync as unknown as ExecFile);
149
242
  // Prefer the single resolved runtime so sync/clamp never probe a different binary
@@ -168,11 +261,7 @@ export function loadBundledCodexCatalog(deps: BundledCatalogDeps = {}): RawCatal
168
261
  discoverAlternatives: deps.discoverAlternatives ?? false,
169
262
  });
170
263
  if (useCache) {
171
- cacheKey = [
172
- resolved.runtime.command,
173
- resolved.runtime.version ?? "",
174
- process.env.OPENCODEX_HOME ?? "",
175
- ].join("\0");
264
+ cacheKey = bundledRuntimeKey(resolved.runtime);
176
265
  }
177
266
  return [resolved.runtime.command];
178
267
  })();
@@ -183,33 +272,225 @@ export function loadBundledCodexCatalog(deps: BundledCatalogDeps = {}): RawCatal
183
272
  && bundledCatalogCache.key === cacheKey
184
273
  && bundledCatalogCache.expiresAt > Date.now()
185
274
  ) {
186
- return bundledCatalogCache.value;
275
+ return bundledCatalogCache.value === null
276
+ ? null
277
+ : cloneAndDeepFreeze(bundledCatalogCache.value);
187
278
  }
188
279
  for (const command of unique(candidates)) {
189
280
  try {
190
281
  const catalog = parseCatalogJson(runCodexDebugModels(command, execFile, deps));
191
282
  if (catalog && findNativeTemplate(catalog)) {
192
283
  if (useCache && cacheKey) {
193
- bundledCatalogCache = {
194
- key: cacheKey,
195
- expiresAt: Date.now() + BUNDLED_CATALOG_CACHE_MS,
196
- value: catalog,
197
- };
284
+ publishBundledCatalogCache(
285
+ cacheKey,
286
+ Date.now() + BUNDLED_CATALOG_CACHE_MS,
287
+ catalog,
288
+ );
289
+ return cloneAndDeepFreeze(bundledCatalogCache!.value!);
198
290
  }
199
- return catalog;
291
+ return cloneAndDeepFreeze(catalog);
200
292
  }
201
293
  } catch { /* try next candidate */ }
202
294
  }
203
295
  if (useCache && cacheKey) {
204
- bundledCatalogCache = {
205
- key: cacheKey,
206
- expiresAt: Date.now() + BUNDLED_CATALOG_CACHE_MS,
207
- value: null,
208
- };
296
+ publishBundledCatalogCache(
297
+ cacheKey,
298
+ Date.now() + BUNDLED_CATALOG_CACHE_MS,
299
+ null,
300
+ );
209
301
  }
210
302
  return null;
211
303
  }
212
304
 
305
+ export type CatalogGatherProcessLocalObservation =
306
+ | Readonly<{ state: "unused" }>
307
+ | Readonly<{ state: "used"; epoch: number; valueIdentity: string }>;
308
+
309
+ export type CodexRuntimeForCatalogGather =
310
+ | Readonly<{
311
+ kind: "available";
312
+ origin: "process-cache" | "persisted";
313
+ runtime: DeepReadonly<ResolvedCodexRuntime>;
314
+ processLocal: CatalogGatherProcessLocalObservation;
315
+ }>
316
+ | Readonly<{
317
+ kind: "runtime-unavailable";
318
+ processLocal: Readonly<{ state: "unused" }>;
319
+ }>;
320
+
321
+ export type CatalogSourceForGather =
322
+ | Readonly<{
323
+ kind: "available";
324
+ source:
325
+ | "bundled-catalog-template"
326
+ | "active-catalog-merge"
327
+ | "hashed-backup-fallback"
328
+ | "legacy-backup-fallback"
329
+ | "models-cache-fallback";
330
+ catalog: ReadonlyRawCatalog;
331
+ runtimeSupport:
332
+ | Readonly<{ kind: "available"; catalog: ReadonlyRawCatalog }>
333
+ | Readonly<{ kind: "unavailable" }>;
334
+ processLocal: Readonly<{
335
+ runtime: CatalogGatherProcessLocalObservation;
336
+ bundledCatalog: CatalogGatherProcessLocalObservation;
337
+ }>;
338
+ }>
339
+ | Readonly<{
340
+ kind: "catalog-unavailable";
341
+ processLocal: Readonly<{
342
+ runtime: Readonly<{ state: "unused" }>;
343
+ bundledCatalog: Readonly<{ state: "unused" }>;
344
+ }>;
345
+ }>;
346
+
347
+ export type CatalogGatherPathKind = "default" | "custom";
348
+
349
+ const UNUSED_PROCESS_LOCAL = Object.freeze({ state: "unused" as const });
350
+
351
+ function sameRuntimeIdentity(
352
+ left: Pick<ResolvedCodexRuntime, "command" | "version">,
353
+ right: Pick<ResolvedCodexRuntime, "command" | "version">,
354
+ ): boolean {
355
+ return left.command === right.command && (left.version ?? null) === (right.version ?? null);
356
+ }
357
+
358
+ /**
359
+ * Observe an already-resolved runtime only. The evidence owner supplies the
360
+ * exact persisted bytes (or observed absence); this path never probes or writes.
361
+ */
362
+ export function peekCodexRuntimeForCatalogGather(
363
+ evidenceSession: CatalogGatherEvidenceSession,
364
+ ): CodexRuntimeForCatalogGather {
365
+ const persistedBytes = evidenceSession.readSource("runtime-selection");
366
+ const persisted = persistedBytes === null
367
+ ? null
368
+ : parsePersistedCodexRuntime(persistedBytes);
369
+ const processMemo = peekCodexRuntimeProcessCache();
370
+
371
+ if (processMemo.kind === "available") {
372
+ const runtime = processMemo.value.runtime;
373
+ if (persistedBytes === null || (persisted && sameRuntimeIdentity(runtime, {
374
+ command: persisted.command,
375
+ version: persisted.selectedVersion ?? null,
376
+ }))) {
377
+ return cloneAndDeepFreeze({
378
+ kind: "available" as const,
379
+ origin: "process-cache" as const,
380
+ runtime,
381
+ processLocal: {
382
+ state: "used" as const,
383
+ epoch: processMemo.epoch,
384
+ valueIdentity: processMemo.valueIdentity,
385
+ },
386
+ });
387
+ }
388
+ }
389
+
390
+ if (persisted) {
391
+ return cloneAndDeepFreeze({
392
+ kind: "available" as const,
393
+ origin: "persisted" as const,
394
+ runtime: {
395
+ command: persisted.command,
396
+ version: persisted.selectedVersion ?? null,
397
+ source: persisted.source,
398
+ },
399
+ processLocal: UNUSED_PROCESS_LOCAL,
400
+ });
401
+ }
402
+
403
+ return Object.freeze({
404
+ kind: "runtime-unavailable" as const,
405
+ processLocal: UNUSED_PROCESS_LOCAL,
406
+ });
407
+ }
408
+
409
+ /**
410
+ * Resolve only already-observed catalog sources. A cold process cache falls
411
+ * through to evidence-owned persisted sources and never becomes probe authority.
412
+ */
413
+ export function resolveCatalogSourceForGather(
414
+ evidenceSession: CatalogGatherEvidenceSession,
415
+ pathKind: CatalogGatherPathKind,
416
+ ): CatalogSourceForGather {
417
+ const bundledMemo = bundledCatalogCache;
418
+ let runtimeSupport:
419
+ | Readonly<{ kind: "available"; catalog: ReadonlyRawCatalog }>
420
+ | Readonly<{ kind: "unavailable" }> = Object.freeze({ kind: "unavailable" });
421
+ let processLocal: Readonly<{
422
+ runtime: CatalogGatherProcessLocalObservation;
423
+ bundledCatalog: CatalogGatherProcessLocalObservation;
424
+ }> = {
425
+ runtime: UNUSED_PROCESS_LOCAL,
426
+ bundledCatalog: UNUSED_PROCESS_LOCAL,
427
+ };
428
+ if (bundledMemo?.value && bundledMemo.expiresAt > Date.now()) {
429
+ const runtime = peekCodexRuntimeForCatalogGather(evidenceSession);
430
+ if (runtime.kind === "available" && bundledMemo.key === bundledRuntimeKey(runtime.runtime)) {
431
+ runtimeSupport = Object.freeze({
432
+ kind: "available" as const,
433
+ catalog: bundledMemo.value,
434
+ });
435
+ processLocal = {
436
+ runtime: runtime.processLocal,
437
+ bundledCatalog: {
438
+ state: "used" as const,
439
+ epoch: bundledMemo.epoch,
440
+ valueIdentity: bundledMemo.valueIdentity,
441
+ },
442
+ };
443
+ if (pathKind === "default") {
444
+ return cloneAndDeepFreeze({
445
+ kind: "available" as const,
446
+ source: "bundled-catalog-template" as const,
447
+ catalog: bundledMemo.value,
448
+ runtimeSupport,
449
+ processLocal,
450
+ });
451
+ }
452
+ }
453
+ }
454
+
455
+ const roles = pathKind === "default"
456
+ ? [
457
+ "active-catalog-merge",
458
+ "hashed-backup-fallback",
459
+ "legacy-backup-fallback",
460
+ "models-cache-fallback",
461
+ ] as const
462
+ : [
463
+ "active-catalog-merge",
464
+ "hashed-backup-fallback",
465
+ "models-cache-fallback",
466
+ ] as const;
467
+ for (const role of roles) {
468
+ const bytes = evidenceSession.readSource(role);
469
+ if (bytes === null) continue;
470
+ const catalog = parseCatalogJson(Buffer.from(bytes).toString("utf8"));
471
+ if (!catalog) continue;
472
+ // Custom catalogs may intentionally contain only routed rows. Keep their existing source
473
+ // priority (active, then backup/cache) without imposing the default catalog's native-template
474
+ // requirement; a valid active custom file therefore remains authoritative over stale fallbacks.
475
+ if (pathKind === "default" && !findNativeTemplate(catalog)) continue;
476
+ return cloneAndDeepFreeze({
477
+ kind: "available" as const,
478
+ source: role,
479
+ catalog,
480
+ runtimeSupport,
481
+ processLocal,
482
+ });
483
+ }
484
+
485
+ return Object.freeze({
486
+ kind: "catalog-unavailable" as const,
487
+ processLocal: Object.freeze({
488
+ runtime: UNUSED_PROCESS_LOCAL,
489
+ bundledCatalog: UNUSED_PROCESS_LOCAL,
490
+ }),
491
+ });
492
+ }
493
+
213
494
  export function materializeBundledCodexCatalog(path: string, deps: BundledCatalogDeps = {}): RawCatalog | null {
214
495
  const catalog = loadBundledCodexCatalog(deps);
215
496
  if (!catalog) return null;
@@ -219,7 +500,7 @@ export function materializeBundledCodexCatalog(path: string, deps: BundledCatalo
219
500
  } catch {
220
501
  return null;
221
502
  }
222
- return catalog;
503
+ return JSON.parse(JSON.stringify(catalog)) as RawCatalog;
223
504
  }
224
505
 
225
506
  export function loadCatalogForSync(path: string): RawCatalog | null {
@@ -236,16 +517,33 @@ export function loadCatalogForSync(path: string): RawCatalog | null {
236
517
 
237
518
  export function readCurrentCatalogOrCache(): RawCatalog | null {
238
519
  const path = readCodexCatalogPath();
239
- return (isDefaultCatalogPath(path) ? loadBundledCodexCatalog() : null)
240
- ?? readCatalog(path)
241
- ?? readCatalog(activeCodexModelsCachePath());
520
+ const bundled = isDefaultCatalogPath(path) ? loadBundledCodexCatalog() : null;
521
+ if (bundled) return JSON.parse(JSON.stringify(bundled)) as RawCatalog;
522
+ return readCatalog(path) ?? readCatalog(activeCodexModelsCachePath());
523
+ }
524
+
525
+ /**
526
+ * Read the user-owned Codex catalog surfaces without substituting the bundled catalog.
527
+ *
528
+ * The bundled catalog is intentionally the authority for static native metadata on the default
529
+ * path. Account-qualified discovery needs the opposite view: an exact model id that Codex has
530
+ * observed in the user's catalog/cache may be account-scoped even when this release does not know
531
+ * it statically yet.
532
+ */
533
+ export function readCurrentCodexCatalog(): RawCatalog | null {
534
+ return readCatalog(readCodexCatalogPath());
535
+ }
536
+
537
+ export function readCurrentCodexModelsCache(): RawCatalog | null {
538
+ return readCatalog(activeCodexModelsCachePath());
242
539
  }
243
540
 
244
541
  export function loadCatalogTemplate(): RawEntry | null {
245
542
  const catalogPath = readCodexCatalogPath();
543
+ const bundled = loadBundledCodexCatalog();
246
544
  const native = findNativeTemplate(readCatalog(catalogPath))
247
545
  ?? findNativeTemplate(readCatalogBackup(catalogPath))
248
546
  ?? findNativeTemplate(readCatalog(activeCodexModelsCachePath()))
249
- ?? findNativeTemplate(loadBundledCodexCatalog());
547
+ ?? findNativeTemplate(bundled ? JSON.parse(JSON.stringify(bundled)) as RawCatalog : null);
250
548
  return native ? JSON.parse(JSON.stringify(native)) : null;
251
549
  }