@iislee/opencodex 2.11.0 → 2.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (733) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +117 -22
  3. package/bin/ocx.mjs +245 -88
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-Be1sDpWw.css +1 -0
  6. package/gui/dist/assets/index-D4OKgUV4.js +114 -0
  7. package/gui/dist/index.html +2 -2
  8. package/gui/dist/provider-icons/alibaba-color.svg +1 -1
  9. package/gui/dist/provider-icons/antigravity-color.svg +1 -1
  10. package/gui/dist/provider-icons/claude-color.svg +1 -1
  11. package/gui/dist/provider-icons/cline-color.svg +16 -0
  12. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
  13. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  14. package/gui/dist/provider-icons/copilot-color.svg +1 -1
  15. package/gui/dist/provider-icons/cursor-color.svg +1 -1
  16. package/gui/dist/provider-icons/deepseek-color.svg +1 -1
  17. package/gui/dist/provider-icons/firepass-color.svg +1 -1
  18. package/gui/dist/provider-icons/fireworks-color.svg +1 -1
  19. package/gui/dist/provider-icons/gemini-color.svg +1 -1
  20. package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
  21. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
  22. package/gui/dist/provider-icons/grok.svg +1 -1
  23. package/gui/dist/provider-icons/groq-color.svg +1 -1
  24. package/gui/dist/provider-icons/huggingface-color.svg +1 -1
  25. package/gui/dist/provider-icons/kimi-color.svg +1 -1
  26. package/gui/dist/provider-icons/kiro-color.svg +2 -2
  27. package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
  28. package/gui/dist/provider-icons/mistral-color.svg +1 -1
  29. package/gui/dist/provider-icons/moonshot-color.svg +1 -1
  30. package/gui/dist/provider-icons/nvidia-color.svg +1 -1
  31. package/gui/dist/provider-icons/ollama-color.svg +1 -1
  32. package/gui/dist/provider-icons/openai.svg +1 -1
  33. package/gui/dist/provider-icons/opencode.svg +2 -1
  34. package/gui/dist/provider-icons/openrouter-color.svg +1 -1
  35. package/gui/dist/provider-icons/pi.svg +2 -2
  36. package/gui/dist/provider-icons/qianfan-color.svg +1 -1
  37. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
  38. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
  39. package/gui/dist/provider-icons/vllm-color.svg +1 -1
  40. package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
  41. package/package.json +21 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +475 -62
  44. package/src/adapters/base.ts +82 -7
  45. package/src/adapters/client-fingerprint.ts +18 -12
  46. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  47. package/src/adapters/command-code.ts +637 -0
  48. package/src/adapters/cursor/call-id.ts +44 -0
  49. package/src/adapters/cursor/catalog.ts +541 -0
  50. package/src/adapters/cursor/checkpoint-store.ts +308 -0
  51. package/src/adapters/cursor/cursor-errors.ts +144 -6
  52. package/src/adapters/cursor/discovery.ts +122 -14
  53. package/src/adapters/cursor/effort-map.ts +106 -4
  54. package/src/adapters/cursor/envelope-echo.ts +290 -0
  55. package/src/adapters/cursor/framing.ts +39 -0
  56. package/src/adapters/cursor/h2-pool.ts +123 -0
  57. package/src/adapters/cursor/http1-bidi.ts +361 -0
  58. package/src/adapters/cursor/images.ts +704 -0
  59. package/src/adapters/cursor/live-models.ts +180 -59
  60. package/src/adapters/cursor/live-transport.ts +623 -170
  61. package/src/adapters/cursor/message-mapper.ts +4 -1
  62. package/src/adapters/cursor/native-exec-common.ts +23 -2
  63. package/src/adapters/cursor/native-exec-desktop.ts +23 -0
  64. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  65. package/src/adapters/cursor/native-exec-network.ts +1 -1
  66. package/src/adapters/cursor/native-exec-shell.ts +5 -3
  67. package/src/adapters/cursor/native-exec.ts +121 -14
  68. package/src/adapters/cursor/protobuf-events.ts +829 -11
  69. package/src/adapters/cursor/protobuf-request.ts +447 -75
  70. package/src/adapters/cursor/request-builder.ts +271 -35
  71. package/src/adapters/cursor/tool-definitions.ts +252 -12
  72. package/src/adapters/cursor/tool-result-normalize.ts +115 -0
  73. package/src/adapters/cursor/transport.ts +22 -0
  74. package/src/adapters/cursor/types.ts +48 -1
  75. package/src/adapters/cursor.ts +336 -39
  76. package/src/adapters/exec-tool-result-normalize.ts +99 -0
  77. package/src/adapters/google-antigravity-replay.ts +713 -41
  78. package/src/adapters/google-antigravity-wire.ts +48 -10
  79. package/src/adapters/google-errors.ts +44 -12
  80. package/src/adapters/google-http.ts +38 -10
  81. package/src/adapters/google-tool-schema.ts +80 -15
  82. package/src/adapters/google-truncation.ts +11 -0
  83. package/src/adapters/google.ts +742 -86
  84. package/src/adapters/identity.ts +39 -6
  85. package/src/adapters/image.ts +1 -1
  86. package/src/adapters/kiro-constants.ts +27 -0
  87. package/src/adapters/kiro-errors.ts +11 -0
  88. package/src/adapters/kiro-events.ts +19 -1
  89. package/src/adapters/kiro-thinking.ts +18 -2
  90. package/src/adapters/kiro-tools.ts +65 -17
  91. package/src/adapters/kiro.ts +270 -73
  92. package/src/adapters/mimo-free.ts +17 -0
  93. package/src/adapters/openai-chat-url.ts +11 -0
  94. package/src/adapters/openai-chat.ts +1377 -344
  95. package/src/adapters/openai-responses-url.ts +16 -0
  96. package/src/adapters/openai-responses.ts +1164 -64
  97. package/src/adapters/registry.ts +175 -0
  98. package/src/adapters/responses-tool-schema.ts +67 -0
  99. package/src/adapters/run-turn-queue.ts +36 -1
  100. package/src/adapters/tool-call-id.ts +119 -0
  101. package/src/adapters/tool-catalog-nudge.ts +105 -21
  102. package/src/adapters/xai-tool-schema.ts +436 -0
  103. package/src/adapters/xai-web-search.ts +186 -0
  104. package/src/bridge.ts +512 -92
  105. package/src/chat/inbound.ts +57 -20
  106. package/src/chat/outbound.ts +97 -33
  107. package/src/claude/agents-inject.ts +40 -10
  108. package/src/claude/context-windows.ts +37 -14
  109. package/src/claude/desktop-3p.ts +243 -9
  110. package/src/claude/gateway-cache.ts +41 -4
  111. package/src/claude/inbound.ts +72 -3
  112. package/src/claude/model-info.ts +38 -15
  113. package/src/claude/outbound.ts +88 -21
  114. package/src/cli/access.ts +46 -3
  115. package/src/cli/account-api.ts +150 -19
  116. package/src/cli/account-auth.ts +33 -6
  117. package/src/cli/account-catalog-refresh.ts +14 -0
  118. package/src/cli/account-extended.ts +648 -28
  119. package/src/cli/account-main.ts +317 -0
  120. package/src/cli/account.ts +97 -19
  121. package/src/cli/agent.ts +53 -2
  122. package/src/cli/alias.ts +66 -0
  123. package/src/cli/capabilities-command.ts +94 -0
  124. package/src/cli/capabilities.ts +496 -0
  125. package/src/cli/claude-agent-startup-sync.ts +73 -0
  126. package/src/cli/claude-desktop.ts +60 -15
  127. package/src/cli/claude.ts +129 -35
  128. package/src/cli/codex-log-guard-doctor.ts +103 -0
  129. package/src/cli/codex-shim-autorestore.ts +2 -0
  130. package/src/cli/codex-shim-readiness.ts +76 -0
  131. package/src/cli/combo.ts +8 -0
  132. package/src/cli/config-command.ts +74 -10
  133. package/src/cli/dispatch.ts +821 -0
  134. package/src/cli/doctor.ts +440 -56
  135. package/src/cli/ensure-desired-integrations.ts +152 -0
  136. package/src/cli/export-command.ts +46 -20
  137. package/src/cli/help.ts +34 -274
  138. package/src/cli/index.ts +417 -528
  139. package/src/cli/init.ts +5 -17
  140. package/src/cli/inspect.ts +230 -0
  141. package/src/cli/integrations.ts +120 -2
  142. package/src/cli/lab.ts +607 -0
  143. package/src/cli/launcher-context.ts +77 -0
  144. package/src/cli/minimax.ts +497 -0
  145. package/src/cli/models-runtime.ts +130 -2
  146. package/src/cli/models.ts +118 -16
  147. package/src/cli/observe.ts +123 -11
  148. package/src/cli/opencode.ts +4 -2
  149. package/src/cli/provider-runtime.ts +34 -3
  150. package/src/cli/provider.ts +25 -3
  151. package/src/cli/ready.ts +301 -0
  152. package/src/cli/registry.ts +476 -0
  153. package/src/cli/root.ts +86 -0
  154. package/src/cli/route-policy.ts +92 -0
  155. package/src/cli/runtime-api.ts +57 -10
  156. package/src/cli/star-prompt.ts +71 -15
  157. package/src/cli/status.ts +51 -4
  158. package/src/cli/storage.ts +234 -0
  159. package/src/cli/system-command.ts +16 -0
  160. package/src/cli/system-restart-client.ts +146 -0
  161. package/src/cli/tray-proxy.ts +153 -6
  162. package/src/cli/usage-report.ts +184 -0
  163. package/src/cli/v2.ts +137 -18
  164. package/src/cli/version-skew.ts +46 -0
  165. package/src/cli.ts +1 -1
  166. package/src/clients/config-export.ts +1442 -23
  167. package/src/clients/effective-status.ts +30 -2
  168. package/src/clients/probes/cline.ts +81 -0
  169. package/src/codex/account-label.ts +35 -1
  170. package/src/codex/account-lifecycle.ts +130 -13
  171. package/src/codex/account-namespaces.ts +49 -3
  172. package/src/codex/account-pause.ts +2 -1
  173. package/src/codex/account-priority.ts +84 -0
  174. package/src/codex/account-store.ts +29 -2
  175. package/src/codex/account-usability.ts +25 -2
  176. package/src/codex/admission.ts +256 -0
  177. package/src/codex/affinity-debug.ts +162 -0
  178. package/src/codex/app-server-processes.ts +570 -107
  179. package/src/codex/app-server-restart-service.ts +232 -0
  180. package/src/codex/auth-api.ts +893 -246
  181. package/src/codex/auth-collision.ts +5 -3
  182. package/src/codex/auth-context.ts +348 -32
  183. package/src/codex/autostart-health.ts +24 -1
  184. package/src/codex/catalog/account-models.ts +67 -0
  185. package/src/codex/catalog/aggregation.ts +86 -10
  186. package/src/codex/catalog/bundled.ts +331 -33
  187. package/src/codex/catalog/effort.ts +138 -32
  188. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  189. package/src/codex/catalog/kinds.ts +2 -0
  190. package/src/codex/catalog/metadata.ts +555 -45
  191. package/src/codex/catalog/native-models.ts +75 -0
  192. package/src/codex/catalog/parsing.ts +269 -30
  193. package/src/codex/catalog/provider-fetch.ts +1626 -144
  194. package/src/codex/catalog/sync.ts +1576 -187
  195. package/src/codex/catalog-admission.ts +199 -0
  196. package/src/codex/catalog-refresh-status.ts +105 -0
  197. package/src/codex/catalog-write-serialization.ts +242 -0
  198. package/src/codex/catalog.ts +6 -3
  199. package/src/codex/codex-write-lock.ts +386 -0
  200. package/src/codex/convergence-types.ts +614 -0
  201. package/src/codex/convergence.ts +676 -0
  202. package/src/codex/coordinator-doctor.ts +332 -0
  203. package/src/codex/custom-model-catalog-migration.ts +176 -0
  204. package/src/codex/desired-state.ts +230 -0
  205. package/src/codex/desktop-app-restart.ts +355 -0
  206. package/src/codex/features.ts +636 -39
  207. package/src/codex/generation.ts +202 -0
  208. package/src/codex/history-job.ts +436 -0
  209. package/src/codex/history-lock.ts +242 -0
  210. package/src/codex/history-manifest.ts +112 -0
  211. package/src/codex/history-migration-guardian.ts +30 -24
  212. package/src/codex/history-provider.ts +1016 -235
  213. package/src/codex/history-transition.ts +105 -0
  214. package/src/codex/history-worker.ts +223 -0
  215. package/src/codex/inject-coordination.ts +373 -0
  216. package/src/codex/inject.ts +1114 -152
  217. package/src/codex/injected-marker.ts +37 -3
  218. package/src/codex/integration-record.ts +266 -0
  219. package/src/codex/internal/catalog-writer.ts +203 -0
  220. package/src/codex/internal/history-writer.ts +81 -0
  221. package/src/codex/journal.ts +66 -4
  222. package/src/codex/log-guard/inspect.ts +524 -0
  223. package/src/codex/log-guard/lock.ts +150 -0
  224. package/src/codex/log-guard/maintenance.ts +403 -0
  225. package/src/codex/log-guard/path-safety.ts +88 -0
  226. package/src/codex/log-guard/policy.ts +44 -0
  227. package/src/codex/log-guard/processes.ts +205 -0
  228. package/src/codex/log-guard/protection.ts +489 -0
  229. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  230. package/src/codex/main-account-cache.ts +24 -0
  231. package/src/codex/main-account.ts +29 -1
  232. package/src/codex/management-convergence.ts +167 -0
  233. package/src/codex/model-cache.ts +56 -10
  234. package/src/codex/model-entitlements.ts +360 -0
  235. package/src/codex/native-main-admission.ts +47 -0
  236. package/src/codex/native-main-auth-temp.ts +187 -0
  237. package/src/codex/native-main-claim.ts +178 -0
  238. package/src/codex/native-main-lock-file.ts +162 -0
  239. package/src/codex/native-main-owner.ts +329 -0
  240. package/src/codex/native-profile-api.ts +247 -0
  241. package/src/codex/native-profile-manager.ts +1531 -0
  242. package/src/codex/native-profile-processes.ts +121 -0
  243. package/src/codex/native-profile-recovery.ts +99 -0
  244. package/src/codex/native-profile-stage-store.ts +387 -0
  245. package/src/codex/native-profile-startup.ts +622 -0
  246. package/src/codex/native-profile-store.ts +855 -0
  247. package/src/codex/native-profile-types.ts +120 -0
  248. package/src/codex/native-residue.ts +675 -0
  249. package/src/codex/paths.ts +80 -1
  250. package/src/codex/plan-from-token.ts +140 -0
  251. package/src/codex/plan.ts +40 -0
  252. package/src/codex/plugins-doctor.ts +1 -1
  253. package/src/codex/pool-rotation.ts +74 -4
  254. package/src/codex/project-config-warnings.ts +20 -6
  255. package/src/codex/prompt-journal.ts +352 -0
  256. package/src/codex/prompt-layers.ts +1313 -0
  257. package/src/codex/prompt-lock.ts +143 -0
  258. package/src/codex/prompt-text-probe.ts +238 -0
  259. package/src/codex/quota-rejection.ts +298 -0
  260. package/src/codex/quota.ts +264 -21
  261. package/src/codex/refresh.ts +11 -2
  262. package/src/codex/reset-credit-recovery.ts +1044 -0
  263. package/src/codex/routing.ts +514 -94
  264. package/src/codex/runtime.ts +159 -38
  265. package/src/codex/shim.ts +1065 -31
  266. package/src/codex/subagent-model-fallback.ts +437 -43
  267. package/src/codex/sync.ts +191 -2
  268. package/src/codex/transition-state.ts +720 -0
  269. package/src/codex/upstream-host-health.ts +368 -0
  270. package/src/codex/user-identity.ts +557 -0
  271. package/src/codex/warmup.ts +187 -81
  272. package/src/codex/write-coordination.ts +114 -0
  273. package/src/combos/failover.ts +47 -0
  274. package/src/combos/index.ts +4 -0
  275. package/src/combos/request.ts +32 -0
  276. package/src/combos/types.ts +91 -9
  277. package/src/compatibility/index.ts +26 -0
  278. package/src/compatibility/manifest.ts +253 -0
  279. package/src/compatibility/openai-responses.ts +121 -0
  280. package/src/config/atomic-write.ts +219 -0
  281. package/src/config/paths.ts +40 -0
  282. package/src/config/process-state.ts +309 -0
  283. package/src/config/provider-name.ts +24 -0
  284. package/src/config/provider-validation.ts +177 -0
  285. package/src/config/rebase-provenance.ts +68 -0
  286. package/src/config.ts +1713 -709
  287. package/src/generated/compatibility-version.json +3324 -0
  288. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  289. package/src/grok/inject.ts +16 -5
  290. package/src/grok/inspect.ts +45 -0
  291. package/src/grok/sync.ts +2 -2
  292. package/src/images/loop.ts +157 -33
  293. package/src/images/plan.ts +24 -13
  294. package/src/integrations/config-io.ts +269 -0
  295. package/src/integrations/journal.ts +315 -0
  296. package/src/integrations/merge.ts +135 -0
  297. package/src/integrations/mutation-flight.ts +71 -0
  298. package/src/integrations/native/ownership-preflight.ts +202 -0
  299. package/src/integrations/omp-yaml-source.ts +358 -0
  300. package/src/integrations/owned-refresh.ts +74 -0
  301. package/src/integrations/ownership-policy.ts +160 -0
  302. package/src/integrations/ownership.ts +155 -0
  303. package/src/integrations/registry.ts +166 -0
  304. package/src/integrations/serialize.ts +314 -0
  305. package/src/integrations/state.ts +433 -0
  306. package/src/integrations/store.ts +103 -0
  307. package/src/integrations/writer-lock.ts +98 -0
  308. package/src/integrations/writer.ts +715 -0
  309. package/src/lab/artifacts/sanitize.ts +586 -0
  310. package/src/lab/artifacts/secure-fs.ts +475 -0
  311. package/src/lab/artifacts/store.ts +310 -0
  312. package/src/lab/automation/budgets.ts +78 -0
  313. package/src/lab/automation/config-persistence.ts +256 -0
  314. package/src/lab/automation/constants.ts +39 -0
  315. package/src/lab/automation/cooldown.ts +103 -0
  316. package/src/lab/automation/dispatch.ts +211 -0
  317. package/src/lab/automation/index.ts +13 -0
  318. package/src/lab/automation/orchestrator.ts +499 -0
  319. package/src/lab/automation/persistence.ts +512 -0
  320. package/src/lab/automation/planner.ts +371 -0
  321. package/src/lab/automation/policy.ts +136 -0
  322. package/src/lab/automation/queue.ts +191 -0
  323. package/src/lab/automation/recovery.ts +24 -0
  324. package/src/lab/automation/route-context.ts +21 -0
  325. package/src/lab/automation/run-key.ts +44 -0
  326. package/src/lab/automation/runs-query.ts +34 -0
  327. package/src/lab/automation/types.ts +160 -0
  328. package/src/lab/conformance/assertion.ts +325 -0
  329. package/src/lab/conformance/digest.ts +22 -0
  330. package/src/lab/conformance/executor.ts +741 -0
  331. package/src/lab/conformance/fixture-provider.ts +27 -0
  332. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  333. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  334. package/src/lab/conformance/harness-budget.ts +47 -0
  335. package/src/lab/conformance/index.ts +5 -0
  336. package/src/lab/conformance/jcs.ts +64 -0
  337. package/src/lab/conformance/json-pointer.ts +39 -0
  338. package/src/lab/conformance/manifest.ts +180 -0
  339. package/src/lab/conformance/mcp-stub.ts +179 -0
  340. package/src/lab/conformance/negative-controls.ts +164 -0
  341. package/src/lab/conformance/observation.ts +355 -0
  342. package/src/lab/conformance/runner.ts +68 -0
  343. package/src/lab/conformance/sse-normalize.ts +59 -0
  344. package/src/lab/conformance/suite-manifest.ts +78 -0
  345. package/src/lab/conformance/types.ts +214 -0
  346. package/src/lab/constants.ts +126 -0
  347. package/src/lab/digest.ts +64 -0
  348. package/src/lab/events/errors.ts +9 -0
  349. package/src/lab/events/limits.ts +117 -0
  350. package/src/lab/events/types.ts +229 -0
  351. package/src/lab/events/validate.ts +781 -0
  352. package/src/lab/fabric/constants.ts +40 -0
  353. package/src/lab/fabric/executor.ts +492 -0
  354. package/src/lab/fabric/index.ts +80 -0
  355. package/src/lab/fabric/manifest.ts +222 -0
  356. package/src/lab/fabric/observe.ts +489 -0
  357. package/src/lab/fabric/patch.ts +79 -0
  358. package/src/lab/fabric/producer-child.ts +139 -0
  359. package/src/lab/fabric/producer-isolate.ts +276 -0
  360. package/src/lab/fabric/producer-protocol.ts +61 -0
  361. package/src/lab/fabric/scratch.ts +439 -0
  362. package/src/lab/fabric/subject.ts +106 -0
  363. package/src/lab/fabric/types.ts +134 -0
  364. package/src/lab/fabric/verifier.ts +98 -0
  365. package/src/lab/index.ts +54 -0
  366. package/src/lab/ledger/artifact-refs.ts +127 -0
  367. package/src/lab/ledger/invalidation.ts +136 -0
  368. package/src/lab/ledger/purge.ts +310 -0
  369. package/src/lab/ledger/store.ts +532 -0
  370. package/src/lab/live/credential-lease.ts +53 -0
  371. package/src/lab/live/destination.ts +155 -0
  372. package/src/lab/live/executor.ts +336 -0
  373. package/src/lab/live/inert-tools.ts +56 -0
  374. package/src/lab/live/manifest.ts +85 -0
  375. package/src/lab/live/mcp-loopback.ts +57 -0
  376. package/src/lab/live/runner.ts +19 -0
  377. package/src/lab/live/sandbox.ts +61 -0
  378. package/src/lab/live/suite-manifest.ts +41 -0
  379. package/src/lab/live/transport.ts +118 -0
  380. package/src/lab/live/types.ts +197 -0
  381. package/src/lab/observe/from-conformance.ts +301 -0
  382. package/src/lab/observe/from-live.ts +117 -0
  383. package/src/lab/paths.ts +153 -0
  384. package/src/lab/projection/rebuild.ts +495 -0
  385. package/src/lab/projection/schema.ts +135 -0
  386. package/src/lab/projection/verdicts.ts +474 -0
  387. package/src/lab/projection/verification.ts +412 -0
  388. package/src/lab/public/bundle.ts +217 -0
  389. package/src/lab/public/community-authority.ts +175 -0
  390. package/src/lab/public/community-files.ts +29 -0
  391. package/src/lab/public/community.ts +479 -0
  392. package/src/lab/public/file-safety.ts +155 -0
  393. package/src/lab/public/ids.ts +26 -0
  394. package/src/lab/public/index.ts +16 -0
  395. package/src/lab/public/mutation-lock.ts +424 -0
  396. package/src/lab/public/operator.ts +353 -0
  397. package/src/lab/public/origin-purge.ts +79 -0
  398. package/src/lab/public/origin.ts +203 -0
  399. package/src/lab/public/privacy.ts +143 -0
  400. package/src/lab/public/private-file.ts +261 -0
  401. package/src/lab/public/project.ts +124 -0
  402. package/src/lab/public/purge-test-fault.ts +21 -0
  403. package/src/lab/public/purge.ts +223 -0
  404. package/src/lab/public/registry.ts +44 -0
  405. package/src/lab/public/revocation.ts +252 -0
  406. package/src/lab/public/signature.ts +243 -0
  407. package/src/lab/public/storage.ts +105 -0
  408. package/src/lab/public/strict-json.ts +206 -0
  409. package/src/lab/public/time.ts +26 -0
  410. package/src/lab/public/types.ts +172 -0
  411. package/src/lab/public/validate.ts +391 -0
  412. package/src/lab/query/catalog.ts +101 -0
  413. package/src/lab/query/connection.ts +107 -0
  414. package/src/lab/query/constants.ts +4 -0
  415. package/src/lab/query/cursor.ts +132 -0
  416. package/src/lab/query/dto-map.ts +277 -0
  417. package/src/lab/query/errors.ts +22 -0
  418. package/src/lab/query/freshness.ts +53 -0
  419. package/src/lab/query/index.ts +45 -0
  420. package/src/lab/query/latest-observation.ts +59 -0
  421. package/src/lab/query/passive-production.ts +159 -0
  422. package/src/lab/query/queries.ts +444 -0
  423. package/src/lab/query/types.ts +266 -0
  424. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  425. package/src/lab/subject/installation-salt.ts +112 -0
  426. package/src/lab/subject/protocol-subject.ts +80 -0
  427. package/src/lab/subject/route-subject.ts +74 -0
  428. package/src/lib/admin-secrets.ts +24 -0
  429. package/src/lib/app-owned-memory-stores.ts +22 -0
  430. package/src/lib/bounded-body.ts +167 -11
  431. package/src/lib/bun-runtime.ts +125 -12
  432. package/src/lib/bun-stream-caps.ts +13 -9
  433. package/src/lib/codex-restart-contract.ts +120 -0
  434. package/src/lib/config-ownership.ts +26 -2
  435. package/src/lib/destination-policy.ts +65 -1
  436. package/src/lib/errors.ts +80 -5
  437. package/src/lib/fabric-task-execution-authority.ts +7 -0
  438. package/src/lib/fabric-task-host.ts +29 -0
  439. package/src/lib/lab-activation.ts +223 -0
  440. package/src/lib/lab-live-execution-authority.ts +13 -0
  441. package/src/lib/lab-live-host.ts +30 -0
  442. package/src/lib/lab-live-pinned-sender.ts +56 -0
  443. package/src/lib/lab-live-route-production.ts +130 -0
  444. package/src/lib/lab-passive-linker-registration.ts +26 -0
  445. package/src/lib/local-management-attestation.ts +51 -0
  446. package/src/lib/local-management-capability.ts +100 -0
  447. package/src/lib/local-provider-reload-contract.ts +100 -0
  448. package/src/lib/optional-shutdown-hooks.ts +57 -0
  449. package/src/lib/package-tree-integrity.ts +101 -0
  450. package/src/lib/pinned-http.ts +145 -26
  451. package/src/lib/process-control.ts +6 -2
  452. package/src/lib/provider-outbound.ts +49 -9
  453. package/src/lib/redact.ts +419 -3
  454. package/src/lib/self-launch-argv.ts +15 -0
  455. package/src/lib/server-resource-ownership.ts +71 -0
  456. package/src/lib/service-secrets.ts +15 -0
  457. package/src/lib/shadow-call.ts +35 -4
  458. package/src/lib/sse-decoder.ts +41 -0
  459. package/src/lib/state-store-registrations.ts +10 -2
  460. package/src/lib/system-restart-contract.ts +73 -0
  461. package/src/lib/token-estimate.ts +19 -2
  462. package/src/lib/tool-argument-integers.ts +253 -0
  463. package/src/lib/translator-budget.ts +44 -0
  464. package/src/lib/upstream-http-version.ts +57 -0
  465. package/src/lib/upstream-reachability.ts +95 -0
  466. package/src/lib/upstream-retry.ts +156 -3
  467. package/src/lib/windows-atomic-replace.ts +155 -0
  468. package/src/lib/windows-elevation.ts +70 -2
  469. package/src/lib/windows-secret-acl.ts +409 -69
  470. package/src/lib/windows-service-wrappers.ts +72 -0
  471. package/src/lib/windows-text.ts +106 -0
  472. package/src/lib/windows-user-principal.ts +341 -0
  473. package/src/lib/winsw.ts +33 -5
  474. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  475. package/src/oauth/account-import/index.ts +15 -0
  476. package/src/oauth/account-import/parser.ts +83 -0
  477. package/src/oauth/account-import/registry.ts +18 -0
  478. package/src/oauth/account-import/service.ts +75 -0
  479. package/src/oauth/account-import/types.ts +91 -0
  480. package/src/oauth/anthropic.ts +12 -1
  481. package/src/oauth/callback-server.ts +30 -4
  482. package/src/oauth/chatgpt.ts +12 -1
  483. package/src/oauth/cline.ts +203 -0
  484. package/src/oauth/command-code.ts +239 -0
  485. package/src/oauth/cursor.ts +46 -5
  486. package/src/oauth/generic-account-failover.ts +231 -0
  487. package/src/oauth/google-antigravity.ts +35 -3
  488. package/src/oauth/health.ts +20 -12
  489. package/src/oauth/index.ts +462 -71
  490. package/src/oauth/key-providers.ts +25 -0
  491. package/src/oauth/kimi.ts +25 -3
  492. package/src/oauth/kiro.ts +95 -6
  493. package/src/oauth/local-token-detect.ts +13 -2
  494. package/src/oauth/log.ts +3 -1
  495. package/src/oauth/login-cli.ts +88 -28
  496. package/src/oauth/nous.ts +798 -0
  497. package/src/oauth/open-browser-choice.ts +26 -0
  498. package/src/oauth/store.ts +133 -26
  499. package/src/oauth/token-guardian.ts +9 -3
  500. package/src/oauth/types.ts +15 -0
  501. package/src/pi/models.ts +2 -2
  502. package/src/providers/alibaba-region-migration.ts +1 -1
  503. package/src/providers/antigravity-models.ts +521 -31
  504. package/src/providers/auto-compact-budget.ts +65 -0
  505. package/src/providers/base-url-choices.ts +10 -0
  506. package/src/providers/codex-capacity.ts +292 -0
  507. package/src/providers/command-code-efforts.ts +176 -0
  508. package/src/providers/context-cap.ts +26 -8
  509. package/src/providers/cursor-pool.ts +72 -0
  510. package/src/providers/default-aliases.ts +65 -0
  511. package/src/providers/derive.ts +281 -6
  512. package/src/providers/fastwire.ts +507 -0
  513. package/src/providers/free-directory.ts +10 -7
  514. package/src/providers/google-vertex-location.ts +14 -0
  515. package/src/providers/key-failover.ts +71 -3
  516. package/src/providers/label.ts +35 -2
  517. package/src/providers/model-discovery-limits.ts +16 -0
  518. package/src/providers/model-discovery.ts +115 -22
  519. package/src/providers/model-presets.ts +119 -0
  520. package/src/providers/model-rename-migration.ts +255 -0
  521. package/src/providers/model-rename-startup.ts +28 -0
  522. package/src/providers/new-model-policy.ts +146 -0
  523. package/src/providers/openai-sidecar.ts +72 -4
  524. package/src/providers/openai-tier-startup.ts +31 -2
  525. package/src/providers/openai-tiers.ts +119 -4
  526. package/src/providers/openai-virtual-models.ts +1 -0
  527. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  528. package/src/providers/provider-id-rewrite.ts +30 -0
  529. package/src/providers/quota.ts +1379 -40
  530. package/src/providers/registry.ts +1545 -112
  531. package/src/providers/request-pacing.ts +310 -0
  532. package/src/providers/service-tier.ts +277 -0
  533. package/src/providers/slug-codec.ts +94 -6
  534. package/src/providers/static-model-discovery.ts +86 -0
  535. package/src/providers/xai-responses-opt-in.ts +15 -0
  536. package/src/providers/xai-transport.ts +32 -4
  537. package/src/reasoning-effort.ts +68 -3
  538. package/src/responses/apply-patch-envelope.ts +63 -0
  539. package/src/responses/code-mode-helper-compat.ts +50 -0
  540. package/src/responses/compaction.ts +26 -1
  541. package/src/responses/custom-tool-compat.ts +384 -0
  542. package/src/responses/hosted-tool-policy.ts +9 -0
  543. package/src/responses/namespace-tool-compat.ts +435 -0
  544. package/src/responses/parser.ts +225 -38
  545. package/src/responses/provider-continuation.ts +98 -0
  546. package/src/responses/provider-opaque-metadata.ts +73 -0
  547. package/src/responses/reasoning-envelope.ts +9 -1
  548. package/src/responses/reasoning-replay-cache.ts +504 -0
  549. package/src/responses/schema.ts +12 -2
  550. package/src/responses/spill-store.ts +75 -10
  551. package/src/responses/state.ts +659 -31
  552. package/src/responses/thought-signature-replay.ts +364 -0
  553. package/src/responses/tool-search-compat.ts +301 -0
  554. package/src/responses/truncated-stop-reason.ts +60 -0
  555. package/src/responses/turn-termination.ts +107 -0
  556. package/src/router.ts +405 -31
  557. package/src/routing/analytics.ts +379 -0
  558. package/src/routing/capability.ts +244 -0
  559. package/src/routing/compatibility/assemble.ts +73 -0
  560. package/src/routing/compatibility/behavior.ts +278 -0
  561. package/src/routing/compatibility/catalog.ts +99 -0
  562. package/src/routing/compatibility/endpoint.ts +52 -0
  563. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  564. package/src/routing/compatibility/policy.ts +181 -0
  565. package/src/routing/compatibility/provider-slot.ts +56 -0
  566. package/src/routing/compatibility/reader.ts +110 -0
  567. package/src/routing/compatibility/subject.ts +191 -0
  568. package/src/routing/compatibility/types.ts +64 -0
  569. package/src/routing/compatibility/version.ts +104 -0
  570. package/src/routing/cost.ts +77 -0
  571. package/src/routing/evaluator.ts +495 -0
  572. package/src/routing/health.ts +412 -0
  573. package/src/routing/history/cursor.ts +43 -0
  574. package/src/routing/history/indexer.ts +605 -0
  575. package/src/routing/history/schema.ts +72 -0
  576. package/src/routing/profile-namespace.ts +15 -0
  577. package/src/routing/profile.ts +547 -0
  578. package/src/routing/quota.ts +155 -0
  579. package/src/routing/request-evidence.ts +45 -0
  580. package/src/routing/trace.ts +776 -0
  581. package/src/server/adapter-resolve.ts +2 -29
  582. package/src/server/auth-cors.ts +289 -48
  583. package/src/server/background-lifecycle.ts +182 -0
  584. package/src/server/chat-completions.ts +154 -72
  585. package/src/server/chat-native-sse.ts +331 -0
  586. package/src/server/chat-native.ts +445 -0
  587. package/src/server/claude-messages.ts +160 -44
  588. package/src/server/direct-local-http.ts +347 -0
  589. package/src/server/effort-policy.ts +18 -0
  590. package/src/server/github-copilot-responses-repair.ts +338 -0
  591. package/src/server/gui-static.ts +39 -10
  592. package/src/server/images.ts +94 -12
  593. package/src/server/index.ts +1021 -190
  594. package/src/server/lifecycle.ts +336 -14
  595. package/src/server/live.ts +136 -17
  596. package/src/server/local-management-read-client.ts +90 -0
  597. package/src/server/local-provider-reload-client.ts +137 -0
  598. package/src/server/management/agent-settings-routes.ts +433 -116
  599. package/src/server/management/api-key-usage.ts +31 -5
  600. package/src/server/management/body.ts +6 -0
  601. package/src/server/management/codex-prompt-routes.ts +570 -0
  602. package/src/server/management/combo-routes.ts +64 -25
  603. package/src/server/management/config-routes.ts +511 -51
  604. package/src/server/management/context.ts +89 -2
  605. package/src/server/management/integration-routes.ts +498 -0
  606. package/src/server/management/lab-automation-routes.ts +206 -0
  607. package/src/server/management/lab-routes.ts +563 -0
  608. package/src/server/management/logs-usage-routes.ts +127 -52
  609. package/src/server/management/model-routes.ts +461 -133
  610. package/src/server/management/model-rows.ts +167 -0
  611. package/src/server/management/native-integration-routes.ts +770 -0
  612. package/src/server/management/oauth-account-routes.ts +90 -8
  613. package/src/server/management/provider-capability-config.ts +48 -0
  614. package/src/server/management/provider-routes.ts +836 -159
  615. package/src/server/management/request-history-routes.ts +191 -0
  616. package/src/server/management/route-registry.ts +332 -0
  617. package/src/server/management/routing-analytics-routes.ts +74 -0
  618. package/src/server/management/routing-profile-routes.ts +380 -0
  619. package/src/server/management/shared.ts +27 -11
  620. package/src/server/management/sidebar-routes.ts +47 -31
  621. package/src/server/management/storage-log-guard-routes.ts +186 -0
  622. package/src/server/management/sync-response.ts +69 -0
  623. package/src/server/management/system-restart.ts +289 -33
  624. package/src/server/management/system-routes.ts +77 -0
  625. package/src/server/management/usage-summary-cache.ts +9 -1
  626. package/src/server/management/vision-sidecar-options.ts +167 -0
  627. package/src/server/management/web-search-sidecar-options.ts +120 -0
  628. package/src/server/management-api.ts +126 -23
  629. package/src/server/management-auth.ts +220 -5
  630. package/src/server/passive-route-linker.ts +66 -0
  631. package/src/server/port-reclaim.ts +1 -1
  632. package/src/server/ports.ts +41 -1
  633. package/src/server/proxy-liveness.ts +161 -10
  634. package/src/server/readiness.ts +99 -0
  635. package/src/server/relay-eager.ts +221 -54
  636. package/src/server/relay.ts +479 -87
  637. package/src/server/request-decompress.ts +113 -6
  638. package/src/server/request-log-conversation.ts +51 -0
  639. package/src/server/request-log.ts +298 -31
  640. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  641. package/src/server/responses/agent-task-recovery.ts +465 -0
  642. package/src/server/responses/codex-auth-error.ts +55 -0
  643. package/src/server/responses/collaboration.ts +239 -36
  644. package/src/server/responses/combo-stream-preflight.ts +178 -0
  645. package/src/server/responses/compact.ts +444 -72
  646. package/src/server/responses/core.ts +3579 -436
  647. package/src/server/responses/empty-completion-guard.ts +333 -0
  648. package/src/server/responses/encrypted-payload.ts +62 -39
  649. package/src/server/responses/fetch-helpers.ts +89 -99
  650. package/src/server/responses/input-admission.ts +187 -0
  651. package/src/server/responses/pacing-overload.ts +13 -0
  652. package/src/server/responses/passthrough-error.ts +33 -9
  653. package/src/server/responses/policy-fallback.ts +178 -0
  654. package/src/server/responses/responses-field-backfill.ts +343 -0
  655. package/src/server/responses/terminal-guard.ts +26 -5
  656. package/src/server/responses/upstream-error.ts +5 -0
  657. package/src/server/responses/ws-upstream.ts +381 -0
  658. package/src/server/responses-custom-tool-repair.ts +363 -0
  659. package/src/server/responses-item-id-repair.ts +54 -6
  660. package/src/server/responses-json-events.ts +90 -0
  661. package/src/server/responses-model-rewrite.ts +29 -0
  662. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  663. package/src/server/responses-snapshot-repair.ts +621 -0
  664. package/src/server/responses-terminal-repair.ts +363 -0
  665. package/src/server/responses-tool-search-repair.ts +267 -0
  666. package/src/server/responses-undeclared-tool-guard.ts +376 -0
  667. package/src/server/responses.ts +18 -2
  668. package/src/server/search.ts +78 -13
  669. package/src/server/sse-frame-buffer.ts +319 -0
  670. package/src/server/sse-payload-rewrite.ts +110 -22
  671. package/src/server/startup-action-control.ts +8 -1
  672. package/src/server/startup-health-cache.ts +19 -1
  673. package/src/server/system-env.ts +80 -9
  674. package/src/server/ws-bridge.ts +53 -40
  675. package/src/service-manager-probe.ts +892 -0
  676. package/src/service.ts +1153 -94
  677. package/src/sidecar/auth.ts +92 -0
  678. package/src/sidecar/candidates.ts +83 -0
  679. package/src/storage/cleanup.ts +2 -2
  680. package/src/storage/policy-job.ts +14 -4
  681. package/src/storage/policy.ts +88 -23
  682. package/src/storage/scanner.ts +1 -1
  683. package/src/storage/worker-lifecycle.ts +14 -14
  684. package/src/tray/windows-tray.ps1 +83 -9
  685. package/src/tray/windows.ts +43 -16
  686. package/src/types/accounts.ts +37 -0
  687. package/src/types/config.ts +911 -0
  688. package/src/types/provider.ts +614 -0
  689. package/src/types/request.ts +397 -0
  690. package/src/types/tools.ts +236 -0
  691. package/src/types/wire.ts +80 -0
  692. package/src/types.ts +107 -1237
  693. package/src/update/index.ts +37 -23
  694. package/src/update/job.ts +445 -68
  695. package/src/update/notify.ts +12 -6
  696. package/src/update/npm-cache-preflight.d.mts +47 -0
  697. package/src/update/npm-cache-preflight.mjs +201 -0
  698. package/src/update/transactional-install.d.mts +22 -0
  699. package/src/update/transactional-install.mjs +266 -0
  700. package/src/usage/cost.ts +0 -0
  701. package/src/usage/expected-prices.ts +287 -16
  702. package/src/usage/log.ts +666 -50
  703. package/src/usage/summary.ts +388 -17
  704. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  705. package/src/usage/user-cost-overlays.ts +314 -0
  706. package/src/vision/anthropic-describe.ts +10 -6
  707. package/src/vision/backends.ts +97 -0
  708. package/src/vision/describe.ts +27 -16
  709. package/src/vision/eligibility.ts +250 -0
  710. package/src/vision/index.ts +238 -24
  711. package/src/vision/reasoning.ts +55 -0
  712. package/src/vision/routed-describe.ts +175 -0
  713. package/src/vision/timeout-bounds.ts +9 -0
  714. package/src/web-search/anthropic-executor.ts +13 -7
  715. package/src/web-search/backends.ts +108 -0
  716. package/src/web-search/exa-executor.ts +119 -0
  717. package/src/web-search/executor.ts +21 -6
  718. package/src/web-search/gemini-executor.ts +141 -0
  719. package/src/web-search/index.ts +150 -15
  720. package/src/web-search/loop.ts +284 -54
  721. package/src/web-search/parse.ts +125 -30
  722. package/src/web-search/sources.ts +60 -0
  723. package/src/web-search/xai-executor.ts +219 -0
  724. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  725. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  726. package/gui/dist/provider-icons/antigravity.svg +0 -1
  727. package/gui/dist/provider-icons/claude.svg +0 -1
  728. package/gui/dist/provider-icons/copilot.svg +0 -1
  729. package/gui/dist/provider-icons/cursor.svg +0 -2
  730. package/gui/dist/provider-icons/gemini.svg +0 -1
  731. package/gui/dist/provider-icons/grok-color.svg +0 -1
  732. package/gui/dist/provider-icons/kiro.svg +0 -14
  733. package/src/cli/internal-dispatch.ts +0 -20
@@ -0,0 +1,75 @@
1
+ /** ChatGPT/Codex wire id observed for the account-native Daybreak Blue surface. */
2
+ export const NATIVE_DAYBREAK_BLUE_MODEL = "gpt-daybreak-blue-latest";
3
+
4
+ /** Native ChatGPT/Codex ids whose availability is proven per authenticated account. */
5
+ export const ACCOUNT_GATED_NATIVE_OPENAI_MODELS: ReadonlySet<string> = new Set([
6
+ "gpt-5.6-sol",
7
+ "gpt-5.6-terra",
8
+ "gpt-5.6-luna",
9
+ NATIVE_DAYBREAK_BLUE_MODEL,
10
+ ]);
11
+
12
+ /**
13
+ * Account-native aliases whose Codex capabilities track another pinned native row.
14
+ *
15
+ * This is catalog metadata inheritance only. Routing always preserves the requested
16
+ * wire id for the separately billed API-key `daybreak-*-latest` surface, so the two never
17
+ * collapse into each other.
18
+ *
19
+ * The ChatGPT/Codex surface is different: an account-gated request IS rewritten to its
20
+ * canonical wire model before it leaves the process (`applyCodexAccountGatedWireNormalization`
21
+ * in src/server/responses/core.ts), because the authenticated backend rejects the gated slug
22
+ * on shards that do not carry it. The catalog keeps the product identity; only the wire moves.
23
+ */
24
+ const NATIVE_OPENAI_CAPABILITY_SOURCES: Readonly<Record<string, string>> = Object.freeze({
25
+ [NATIVE_DAYBREAK_BLUE_MODEL]: "gpt-5.6-sol",
26
+ });
27
+
28
+ /**
29
+ * Native ids whose capability metadata is inherited from another pinned native row.
30
+ *
31
+ * Membership here is about METADATA INHERITANCE only, and is independent of whether the
32
+ * slug is also present in `NATIVE_OPENAI_MODELS`. `gpt-daybreak-blue-latest` is now in BOTH:
33
+ * it inherits Sol's capability shape AND is a supported account-gated native id (owner decision,
34
+ * devlog 260816_codexrs_multiagent_v2_and_history_perf/011).
35
+ *
36
+ * The maps that consume the union of these two lists (`PINNED_NATIVE_CAPABILITY_ENTRIES`,
37
+ * `UPSTREAM_NATIVE_ENTRIES`) are keyed by slug, so an overlapping id collapses to one
38
+ * entry. Catalog row generation iterates `NATIVE_OPENAI_MODELS`, then entitlement evidence limits
39
+ * it to at most one bare row and one row per entitled account selector.
40
+ */
41
+ export const NATIVE_OPENAI_CAPABILITY_ALIAS_MODELS = Object.freeze(
42
+ Object.keys(NATIVE_OPENAI_CAPABILITY_SOURCES),
43
+ );
44
+
45
+ export function isNativeOpenAiCapabilityAliasModel(slug: string): boolean {
46
+ return Object.hasOwn(NATIVE_OPENAI_CAPABILITY_SOURCES, slug);
47
+ }
48
+
49
+ export function nativeOpenAiCapabilitySourceSlug(slug: string): string {
50
+ return NATIVE_OPENAI_CAPABILITY_SOURCES[slug] ?? slug;
51
+ }
52
+
53
+ /**
54
+ * Native OpenAI model ids that this release can route and restore with authoritative metadata.
55
+ *
56
+ * `gpt-daybreak-blue-latest` is entitlement-gated upstream: it is absent from codex-rs's
57
+ * bundled catalog and reaches a client only through an authenticated `/models` response.
58
+ * It is listed here by explicit owner decision so the capability template exists without waiting
59
+ * for an observation, because opencodex injects `model_catalog_json` and codex-rs therefore builds
60
+ * a `StaticModelsManager` whose refresh is a no-op — an entitled account had no way to
61
+ * discover it on a clean install.
62
+ *
63
+ * Availability is not static: catalog sync and Pool routing require the account's authenticated
64
+ * `/models` roster to contain account-gated slugs. An unconfirmed or unentitled account never
65
+ * receives the request. `disabledModels` remains the independent user visibility control.
66
+ *
67
+ * Devlog: 260816_codexrs_multiagent_v2_and_history_perf/011 §4-bis.
68
+ */
69
+ export const NATIVE_OPENAI_MODELS = [
70
+ "gpt-5.5", "gpt-5.4", "gpt-5.4-mini", "gpt-5.3-codex-spark",
71
+ "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna",
72
+ NATIVE_DAYBREAK_BLUE_MODEL,
73
+ ];
74
+
75
+ export const SUPPORTED_NATIVE_OPENAI_SLUGS = new Set(NATIVE_OPENAI_MODELS);
@@ -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";
@@ -31,7 +31,10 @@ import { redactSecretString } from "../../lib/redact";
31
31
  import upstreamModelsSnapshot from "../data/upstream-models.json";
32
32
 
33
33
 
34
- import { NATIVE_OPENAI_CONTEXT_OVERRIDES, SUPPORTED_NATIVE_OPENAI_SLUGS, UPSTREAM_NATIVE_ENTRIES } from "./metadata";
34
+ import { NATIVE_OPENAI_CONTEXT_OVERRIDES, SUPPORTED_NATIVE_OPENAI_SLUGS, UPSTREAM_NATIVE_ENTRIES, isNativeOpenAiCapabilityAliasModel, nativeMultiAgentVersion, nativeOpenAiAutoCompactTokenLimit, nativeOpenAiContextWindow, nativeOpenAiMaxInputTokens, type NativeContextLimitsInput } from "./metadata";
35
+ import { clampAutoCompactTokenLimit } from "../../providers/auto-compact-budget";
36
+ import { trustedAccountBoundNativeCatalogSlug } from "./account-models";
37
+ import { CODEX_NATIVE_ALIAS_CATALOG_KIND } from "./kinds";
35
38
 
36
39
  export function legacyCatalogBackupPath(): string {
37
40
  return join(getConfigDir(), "catalog-backup.json");
@@ -84,11 +87,18 @@ export function isDefaultCatalogPath(path: string): boolean {
84
87
  return samePath(path, activeDefaultCatalogPath());
85
88
  }
86
89
 
90
+ /** Stable nonsemantic ownership marker for rows projected from config.customModels. */
91
+ export const CODEX_CUSTOM_MODEL_CATALOG_KIND = "custom-model-v1";
92
+ /** A formerly ambiguous slug was authoritatively observed as an ordinary provider row. */
93
+ export const CODEX_PROVIDER_MODEL_CATALOG_KIND = "provider-model-v1";
94
+
87
95
  export interface CatalogModel {
88
96
  id: string;
89
97
  provider: string;
90
98
  /** Public Codex-facing slug override (used by combo aliases). */
91
99
  alias?: string;
100
+ /** Explicit combo takeover of a bare OpenAI-native catalog id. */
101
+ nativeAlias?: boolean;
92
102
  /**
93
103
  * Display-only Codex catalog `display_name` override. Relabels the picker row ONLY — it never
94
104
  * affects the routing slug, alias-collision order, native marketing-name precedence, or provider
@@ -102,27 +112,49 @@ export interface CatalogModel {
102
112
  defaultReasoningEffort?: string;
103
113
  contextWindow?: number;
104
114
  maxInputTokens?: number;
115
+ /** Soft client compaction threshold; hard context/input limits remain authoritative. */
116
+ autoCompactTokenLimit?: number;
105
117
  contextCap?: number;
106
118
  contextCapped?: boolean;
107
119
  inputModalities?: string[];
108
120
  /** Provider opted into parallel tool calls (OcxProviderConfig.parallelToolCalls). */
109
121
  parallelToolCalls?: boolean;
122
+ /**
123
+ * This routed row is an explicitly configured account-native alias on the canonical ChatGPT
124
+ * forward provider. It may inherit pinned native Codex metadata without changing its wire id.
125
+ */
126
+ codexForwardNativeCapabilityAlias?: boolean;
110
127
  /** Whether Codex may send Responses text.verbosity for this routed model. */
111
128
  supportsVerbosity?: boolean;
129
+ /** Whether this exact routed model has a verified OpenAI-compatible service tier. */
130
+ supportsServiceTier?: boolean;
131
+ /** Optional provider-specific copy for the advertised Fast tier. */
132
+ fastTierDescription?: string;
112
133
  supportsReasoningSummaries?: boolean;
134
+ /**
135
+ * Codex tool calling mode for this routed model.
136
+ * "code_mode_only" (default) sets entry.tool_mode = "code_mode_only".
137
+ * "shell" leaves tool_mode unset so Codex declares top-level shell tools (exec_command).
138
+ */
139
+ codexToolMode?: "code_mode_only" | "shell";
113
140
  /** Normalized upstream capability names retained for management/API consumers (#485 follow-up). */
114
141
  capabilities?: string[];
142
+ /** OpenCodex-only catalog ownership marker; Codex ignores the serialized extension field. */
143
+ catalogKind?: typeof CODEX_CUSTOM_MODEL_CATALOG_KIND | typeof CODEX_PROVIDER_MODEL_CATALOG_KIND;
115
144
  }
116
145
 
117
146
  export type RawEntry = Record<string, unknown>;
118
147
 
119
148
  export type RawCatalog = { models?: RawEntry[]; [k: string]: unknown };
120
149
 
121
- export const JAWCODE_CATALOG_AUGMENT_PROVIDERS = new Set(["opencode-go"]);
150
+ export const JAWCODE_CATALOG_AUGMENT_PROVIDERS = new Set(["opencode-go", "deepseek"]);
122
151
 
123
152
  export const ROUTED_MODEL_COMPATIBILITY_EXCLUSIONS = new Set([
124
153
  // Issue #82: Zen Go /models advertises HY3, but Console Go rejects it as outside the lite list.
125
154
  "opencode-go/hy3-preview",
155
+ // Issue #2330: OpenCode Go models absent from current documentation or returning terminal HTTP 400 errors.
156
+ "opencode-go/mimo-v2-omni",
157
+ "opencode-go/mimo-v2-pro",
126
158
  ]);
127
159
 
128
160
  export function isRoutedModelCompatibilityExcluded(slug: string): boolean {
@@ -165,6 +197,8 @@ export function shouldExposeRoutedModel(model: CatalogModel): boolean {
165
197
  }
166
198
 
167
199
  export function readCodexCatalogPath(): string {
200
+ const home = activeCodexHome();
201
+ if (home) return readCodexCatalogPathForHome(home);
168
202
  try {
169
203
  const configPath = activeCodexConfigPath();
170
204
  if (existsSync(configPath)) {
@@ -176,6 +210,35 @@ export function readCodexCatalogPath(): string {
176
210
  return activeDefaultCatalogPath();
177
211
  }
178
212
 
213
+ /** Resolve the configured catalog without consulting ambient CODEX_HOME again. */
214
+ export function readCodexCatalogPathForHome(codexHome: string): string {
215
+ try {
216
+ const configPath = join(codexHome, "config.toml");
217
+ if (existsSync(configPath)) {
218
+ const toml = readFileSync(configPath, "utf-8");
219
+ const path = readRootTomlString(toml, "model_catalog_json");
220
+ if (path) return resolve(codexHome, path);
221
+ }
222
+ } catch { /* ignore */ }
223
+ return join(codexHome, "opencodex-catalog.json");
224
+ }
225
+
226
+ /**
227
+ * Read the configured auto-review model from the root of Codex's config.toml (issue #1225).
228
+ * Stamped onto catalog entries as `auto_review_model_override` during sync so the auto-review
229
+ * subagent uses the operator's chosen model across catalog regenerations.
230
+ */
231
+ export function readConfiguredAutoReviewModel(): string | null {
232
+ try {
233
+ const configPath = activeCodexConfigPath();
234
+ if (existsSync(configPath)) {
235
+ const toml = readFileSync(configPath, "utf-8");
236
+ return readRootTomlString(toml, "auto_review_model");
237
+ }
238
+ } catch { /* ignore */ }
239
+ return null;
240
+ }
241
+
179
242
  export function parseCatalogJson(raw: string): RawCatalog | null {
180
243
  try {
181
244
  const cat = JSON.parse(raw);
@@ -192,7 +255,12 @@ export function readCatalog(path: string): RawCatalog | null {
192
255
 
193
256
  export function findNativeTemplate(catalog: RawCatalog | null): RawEntry | null {
194
257
  return catalog?.models?.find(
195
- m => typeof m.slug === "string" && !m.slug.includes("/") && "base_instructions" in m,
258
+ m => typeof m.slug === "string"
259
+ && !m.slug.includes("/")
260
+ && "base_instructions" in m
261
+ && m.opencodex_catalog_kind !== CODEX_NATIVE_ALIAS_CATALOG_KIND
262
+ && m.owned_by !== COMBO_NAMESPACE
263
+ && !(typeof m.description === "string" && m.description.startsWith("Routed via opencodex → ")),
196
264
  ) ?? null;
197
265
  }
198
266
 
@@ -243,16 +311,91 @@ export function isNativeOpenAiEntry(entry: RawEntry): boolean {
243
311
  return typeof entry.slug === "string" && !entry.slug.includes("/");
244
312
  }
245
313
 
246
- export function applyNativeOpenAiContextOverride(entry: RawEntry): void {
247
- if (!isNativeOpenAiEntry(entry)) return;
248
- const override = NATIVE_OPENAI_CONTEXT_OVERRIDES[entry.slug as string];
249
- if (!override) return;
250
- if (typeof override.contextWindow === "number") {
251
- entry.context_window = override.contextWindow;
252
- entry.auto_compact_token_limit = Math.floor(override.contextWindow * 0.9);
314
+ /**
315
+ * Narrow any already-resolved native window by the user levers.
316
+ *
317
+ * Used for the fields the accessors do not own (`max_context_window`, and preserved rows
318
+ * that carry no static override) so every field on a row lands at the same width.
319
+ */
320
+ function narrowNativeMaxContextWindow(
321
+ slug: string,
322
+ value: number | undefined,
323
+ limits?: NativeContextLimitsInput,
324
+ ): number | undefined {
325
+ if (typeof value !== "number" || value <= 0) return value;
326
+ const resolved = nativeOpenAiContextWindow(slug, limits);
327
+ const authoritative = nativeOpenAiContextWindow(slug);
328
+ // The accessor pair tells us how far the levers moved this slug; apply the same delta to a
329
+ // field the accessor does not model, without ever raising it.
330
+ if (resolved === undefined || authoritative === undefined) return value;
331
+ return Math.min(value, Math.max(resolved, 1));
332
+ }
333
+
334
+ export function applyNativeOpenAiContextOverride(entry: RawEntry, limits?: NativeContextLimitsInput): void {
335
+ const nativeSlug = trustedAccountBoundNativeCatalogSlug(entry)
336
+ ?? (isNativeOpenAiEntry(entry) ? entry.slug as string : undefined);
337
+ if (!nativeSlug) return;
338
+ const override = NATIVE_OPENAI_CONTEXT_OVERRIDES[nativeSlug];
339
+ // Captured before any override/cap rewrites the row: a retained compaction threshold only
340
+ // describes the window it arrived with.
341
+ const incomingContextWindow = typeof entry.context_window === "number" ? entry.context_window : undefined;
342
+ if (override) {
343
+ // Read the effective values through the accessors rather than re-deriving them from the
344
+ // static table: this function used to apply only the provider cap, so a per-model window
345
+ // the dashboard had already accepted was silently written back at full width here.
346
+ if (typeof override.contextWindow === "number") {
347
+ const contextWindow = nativeOpenAiContextWindow(nativeSlug, limits) ?? override.contextWindow;
348
+ entry.context_window = contextWindow;
349
+ }
350
+ if (typeof override.maxContextWindow === "number") {
351
+ const maxContextWindow = narrowNativeMaxContextWindow(nativeSlug, override.maxContextWindow, limits);
352
+ entry.max_context_window = maxContextWindow;
353
+ }
253
354
  }
254
- if (typeof override.maxContextWindow === "number") {
255
- entry.max_context_window = override.maxContextWindow;
355
+ // providerContextCaps.openai is a ceiling for native OpenAI rows regardless of where the
356
+ // advertised window came from (#1430): preserved rows without a hardcoded override (e.g.
357
+ // gpt-5.4-mini) must stay under the cap too, and auto-compaction follows the capped window.
358
+ // The per-model window narrows the same rows for the same reason.
359
+ const currentContext = typeof entry.context_window === "number" ? entry.context_window : undefined;
360
+ const cappedContext = narrowNativeMaxContextWindow(nativeSlug, currentContext, limits);
361
+ if (cappedContext !== currentContext && typeof cappedContext === "number") {
362
+ entry.context_window = cappedContext;
363
+ }
364
+ const currentMax = typeof entry.max_context_window === "number" ? entry.max_context_window : undefined;
365
+ const cappedMax = narrowNativeMaxContextWindow(nativeSlug, currentMax, limits);
366
+ if (cappedMax !== currentMax) {
367
+ entry.max_context_window = cappedMax;
368
+ }
369
+ const effectiveContext = typeof entry.context_window === "number" && entry.context_window > 0
370
+ ? entry.context_window
371
+ : undefined;
372
+ if (effectiveContext !== undefined) {
373
+ const derivedAutoCompactTokenLimit = nativeOpenAiAutoCompactTokenLimit(nativeSlug, limits);
374
+ // Only trust a retained threshold that still describes THIS window. When sync corrects the
375
+ // window, the old number is an artifact of the old one: a 115_200 limit retained from a
376
+ // 128k row would pin a corrected 272k model to 42% of its real window and compact every
377
+ // long turn early. Lower-is-policy still holds whenever the window is unchanged.
378
+ const retainedDescribesCurrentContext = incomingContextWindow === undefined
379
+ || incomingContextWindow === effectiveContext;
380
+ const retainedAutoCompactTokenLimit = retainedDescribesCurrentContext
381
+ && isNativeOpenAiEntry(entry)
382
+ && typeof entry.auto_compact_token_limit === "number"
383
+ && Number.isSafeInteger(entry.auto_compact_token_limit)
384
+ && entry.auto_compact_token_limit > 0
385
+ ? entry.auto_compact_token_limit
386
+ : undefined;
387
+ // A smaller threshold retained from Codex is policy evidence too. Configuration may
388
+ // lower it further, but catalog sync must never replace it with a larger default.
389
+ const loweringAutoCompactTokenLimit = retainedAutoCompactTokenLimit === undefined
390
+ ? derivedAutoCompactTokenLimit
391
+ : derivedAutoCompactTokenLimit === undefined
392
+ ? retainedAutoCompactTokenLimit
393
+ : Math.min(retainedAutoCompactTokenLimit, derivedAutoCompactTokenLimit);
394
+ entry.auto_compact_token_limit = clampAutoCompactTokenLimit(
395
+ effectiveContext,
396
+ nativeOpenAiMaxInputTokens(nativeSlug, limits) ?? override?.maxInputTokens,
397
+ loweringAutoCompactTokenLimit,
398
+ );
256
399
  }
257
400
  }
258
401
 
@@ -300,6 +443,51 @@ export function ensureStrictCatalogFields(
300
443
 
301
444
  export type MultiAgentMode = "v1" | "default" | "v2";
302
445
 
446
+ export interface MultiAgentModeOptions {
447
+ /**
448
+ * When the catalog is in v2 mode, stamp ChatGPT-native rows as v1 instead.
449
+ * Routed parents get v2 (plaintext child tasks). Native Sol/Terra stay on v1
450
+ * so they can still spawn Grok/Claude — ChatGPT encrypts v2 NEW_TASK bodies.
451
+ */
452
+ keepNativeChatGptOnV1?: boolean;
453
+ }
454
+
455
+ /** Catalog rows that run on the ChatGPT backend (encrypt v2 child tasks). */
456
+ export function catalogEntryIsNativeChatGpt(entry: RawEntry): boolean {
457
+ const slug = typeof entry.slug === "string" ? entry.slug : "";
458
+ // combo-native-alias-v1 occupies a bare native slug but is routed through
459
+ // OpenCodex. Keep those on v2 unless the row still carries the ChatGPT-forward
460
+ // contract (`use_responses_lite`).
461
+ if (entry.opencodex_catalog_kind === CODEX_NATIVE_ALIAS_CATALOG_KIND) {
462
+ return entry.use_responses_lite === true;
463
+ }
464
+ if (trustedAccountBoundNativeCatalogSlug(entry)) return true;
465
+ const routedNativeSlug = slug.startsWith(`${OPENAI_CODEX_PROVIDER_ID}/`)
466
+ ? slug.slice(OPENAI_CODEX_PROVIDER_ID.length + 1)
467
+ : "";
468
+ if (
469
+ entry.opencodex_catalog_kind === CODEX_CUSTOM_MODEL_CATALOG_KIND
470
+ && entry.use_responses_lite === true
471
+ && isNativeOpenAiCapabilityAliasModel(routedNativeSlug)
472
+ ) return true;
473
+ if (UPSTREAM_NATIVE_ENTRIES.has(slug) || SUPPORTED_NATIVE_OPENAI_SLUGS.has(slug)) return true;
474
+ return false;
475
+ }
476
+
477
+ export const ROUTED_CODEX_TOOL_MODE = "code_mode_only";
478
+
479
+ export function applyRoutedCodexToolMode(
480
+ entry: RawEntry,
481
+ toolMode?: "code_mode_only" | "shell" | string,
482
+ ): RawEntry {
483
+ if (toolMode === "shell") {
484
+ delete entry.tool_mode;
485
+ return entry;
486
+ }
487
+ entry.tool_mode = ROUTED_CODEX_TOOL_MODE;
488
+ return entry;
489
+ }
490
+
303
491
  /**
304
492
  * @param v2FeatureEnabled When the native multi_agent_v2 feature is on, "default"
305
493
  * mode stamps unpinned entries as "v2" instead of deleting the key. The native
@@ -310,15 +498,42 @@ export type MultiAgentMode = "v1" | "default" | "v2";
310
498
  * 260730_codex_rs_upstream_v2_live_handoff/060). Upstream pins are always
311
499
  * preserved: a genuine "v1" pin is a real capability statement and stays excluded.
312
500
  * With the feature off the output is byte-identical to the historical behavior.
501
+ *
502
+ * `keepNativeChatGptOnV1` only applies when `mode === "v2"`. It leaves Sol/Terra
503
+ * (and other ChatGPT-native rows) on v1 so a native parent can still spawn a
504
+ * routed child. See issue #92.
313
505
  */
314
- export function applyMultiAgentMode(entries: RawEntry[], mode: MultiAgentMode, v2FeatureEnabled = false): RawEntry[] {
506
+ export function applyMultiAgentMode(
507
+ entries: RawEntry[],
508
+ mode: MultiAgentMode,
509
+ v2FeatureEnabled = false,
510
+ options: MultiAgentModeOptions = {},
511
+ ): RawEntry[] {
512
+ if (mode === "v2" && options.keepNativeChatGptOnV1 === true) {
513
+ for (const entry of entries) {
514
+ entry.multi_agent_version = catalogEntryIsNativeChatGpt(entry) ? "v1" : "v2";
515
+ }
516
+ return entries;
517
+ }
315
518
  if (mode === "default") {
316
519
  // Restore upstream defaults: clear any stale forced multi_agent_version and
317
520
  // re-apply upstream pins from the snapshot for native entries that have one.
318
521
  for (const entry of entries) {
319
522
  const slug = typeof entry.slug === "string" ? entry.slug : "";
320
- const upstream = UPSTREAM_NATIVE_ENTRIES.get(slug);
321
- const upstreamPin = upstream?.multi_agent_version;
523
+ const nativeAlias = entry.opencodex_catalog_kind === CODEX_NATIVE_ALIAS_CATALOG_KIND;
524
+ const routedNativeSlug = slug.startsWith(`${OPENAI_CODEX_PROVIDER_ID}/`)
525
+ ? slug.slice(OPENAI_CODEX_PROVIDER_ID.length + 1)
526
+ : "";
527
+ const codexForwardCapabilityAlias = entry.opencodex_catalog_kind === CODEX_CUSTOM_MODEL_CATALOG_KIND
528
+ && entry.use_responses_lite === true
529
+ && isNativeOpenAiCapabilityAliasModel(routedNativeSlug)
530
+ ? routedNativeSlug
531
+ : undefined;
532
+ const upstreamPin = nativeAlias
533
+ ? nativeMultiAgentVersion(slug)
534
+ : codexForwardCapabilityAlias
535
+ ? nativeMultiAgentVersion(codexForwardCapabilityAlias)
536
+ : UPSTREAM_NATIVE_ENTRIES.get(trustedAccountBoundNativeCatalogSlug(entry) ?? slug)?.multi_agent_version;
322
537
  if (typeof upstreamPin === "string") {
323
538
  entry.multi_agent_version = upstreamPin;
324
539
  } else if (v2FeatureEnabled) {
@@ -335,9 +550,14 @@ export function applyMultiAgentMode(entries: RawEntry[], mode: MultiAgentMode, v
335
550
  return entries;
336
551
  }
337
552
 
338
- export function normalizeRoutedCatalogEntry(entry: RawEntry, parallelToolCalls = false): RawEntry {
553
+ export function normalizeRoutedCatalogEntry(
554
+ entry: RawEntry,
555
+ parallelToolCalls = false,
556
+ toolMode?: "code_mode_only" | "shell" | string,
557
+ ): RawEntry {
339
558
  delete entry.model_messages;
340
559
  delete entry.tool_mode;
560
+ applyRoutedCodexToolMode(entry, toolMode);
341
561
  delete entry.multi_agent_version;
342
562
  delete entry.use_responses_lite;
343
563
  delete entry.supports_websockets;
@@ -346,20 +566,24 @@ export function normalizeRoutedCatalogEntry(entry: RawEntry, parallelToolCalls =
346
566
  delete entry.service_tiers;
347
567
  delete entry.default_service_tier;
348
568
  // Routed rows cloned from native templates must not inherit OpenAI-only summary delivery.
349
- // Per-model routed opt-ins can be added once provider metadata exposes this capability.
569
+ // Explicit provider/model metadata is re-applied after this normalization step.
350
570
  delete entry.supports_reasoning_summaries;
351
571
  const isCursorEntry = typeof entry.slug === "string" && entry.slug.startsWith("cursor/");
352
- // Routed providers use opencodex sidecars and client-executed tool discovery. The sidecar
353
- // runs through native gpt-5.4-mini, so image search is available and verbalized for text-only
354
- // models. EXCEPT cursor: its runTurn transport bypasses the web-search plan entirely and
355
- // rejects server search queries advertising the tool would make models call into a void.
572
+ // `supports_search_tool` selects Codex's deferred tool-discovery surface; it is not the hosted
573
+ // web-search capability. Routed rows also carry tool_mode=code_mode_only (below), and under code
574
+ // mode DEFERRED MCP tools remain callable through exec's `tools` global / ALL_TOOLS without any
575
+ // tool_search round-trip (upstream codex-rs code_mode suite; live canary 2026-08-13: routed
576
+ // kimi/k3 called tools.mcp__node_repl__js → isError:false). Stamping false here instead forces
577
+ // every MCP declaration into exec.description — a measured 2.7x turn-1 payload regression
578
+ // (96,699 → 258,929 chars; devlog/_plan/260813_tool_catalog_deferral/010). So every routed
579
+ // code-mode row advertises deferred discovery. Cursor still omits hosted web-search metadata below,
580
+ // but disabling this separate exposure bit can inflate `exec` past Cursor's 120 KB wire cap (#1830).
356
581
  if (isCursorEntry) {
357
582
  delete entry.web_search_tool_type;
358
- entry.supports_search_tool = false;
359
583
  } else {
360
584
  entry.web_search_tool_type = "text_and_image";
361
- entry.supports_search_tool = true;
362
585
  }
586
+ entry.supports_search_tool = true;
363
587
  // Cursor's transport already serializes overlapping tool calls into atomic Responses tool events.
364
588
  // Advertising parallel calls lets Codex send the same native capability bit it sends for OpenAI.
365
589
  // Opt-in providers (OcxProviderConfig.parallelToolCalls, e.g. xAI) advertise it too: the
@@ -389,11 +613,25 @@ export function catalogModelSupportsReasoningSummaries(modelId: string): boolean
389
613
  return values.size === 1 ? values.values().next().value : undefined;
390
614
  }
391
615
 
392
- export function applyJawcodeCatalogMetadata(entry: RawEntry, provider: string, modelId: string, contextCap?: number): void {
393
- const jawcodeProvider = resolveJawcodeProvider(provider);
394
- if (!jawcodeProvider) return;
395
- const meta = getJawcodeModelMetadata(jawcodeProvider, modelId)
396
- ?? (shouldCaseFoldMetadataModelId(provider) ? getJawcodeModelMetadataCaseInsensitive(jawcodeProvider, modelId) : undefined);
616
+ /**
617
+ * Resolve the generated jawcode metadata row for a provider/model pair.
618
+ *
619
+ * Exported because it is the SECOND source of real capability assertions:
620
+ * `applyCatalogMetadata` writes context/modalities from it without ever
621
+ * touching a `CatalogModel`, so the routing-evidence provenance stamp in
622
+ * `applyCatalogModelMetadata` has to consult the same table. Both callers share
623
+ * this one lookup rather than duplicating the resolve/case-fold rules, which is
624
+ * what keeps the serialized entry and its provenance from drifting apart.
625
+ */
626
+ export function generatedModelMetadata(provider: string, modelId: string) {
627
+ const jawcodeProvider = resolveMetadataProvider(provider);
628
+ if (!jawcodeProvider) return undefined;
629
+ return getModelMetadata(jawcodeProvider, modelId)
630
+ ?? (shouldCaseFoldMetadataModelId(provider) ? getModelMetadataCaseInsensitive(jawcodeProvider, modelId) : undefined);
631
+ }
632
+
633
+ export function applyCatalogMetadata(entry: RawEntry, provider: string, modelId: string, contextCap?: number): void {
634
+ const meta = generatedModelMetadata(provider, modelId);
397
635
  if (!meta) return;
398
636
  if (typeof meta.contextWindow === "number" && meta.contextWindow > 0) {
399
637
  const contextWindow = applyProviderContextCap(meta.contextWindow, contextCap) ?? meta.contextWindow;
@@ -422,7 +660,8 @@ export function readCatalogBackup(catalogPath: string): RawCatalog | null {
422
660
  }
423
661
 
424
662
  export function catalogHasRoutedEntries(catalog: RawCatalog | null): boolean {
425
- return (catalog?.models ?? []).some(m => typeof m.slug === "string" && m.slug.includes("/"));
663
+ return (catalog?.models ?? []).some(m => typeof m.slug === "string"
664
+ && (m.slug.includes("/") || m.opencodex_catalog_kind === CODEX_NATIVE_ALIAS_CATALOG_KIND));
426
665
  }
427
666
 
428
667
  export function writePristineCatalogBackup(backupPath: string, catalogPath: string, catalog: RawCatalog): void {