@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,10 +9,10 @@ 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
- import { applyProviderContextCap, providerContextCap } from "../../providers/context-cap";
15
+ import { applyProviderContextCap, providerContextCap, resolveUnknownRoutedContextWindow } from "../../providers/context-cap";
16
16
  import { routedSlug, slugEquals, slugsEquivalent } from "../../providers/slug-codec";
17
17
  import { CODEX_GPT5_IDENTITY_LINE } from "../../adapters/identity";
18
18
  import { filterCursorConfiguredModelsByLiveDiscovery } from "../../adapters/cursor/discovery";
@@ -31,11 +31,12 @@ import { redactSecretString, redactUserPath } from "../../lib/redact";
31
31
  import upstreamModelsSnapshot from "../data/upstream-models.json";
32
32
 
33
33
 
34
- import { readCatalog, readCodexCatalogPath } from "./parsing";
34
+ import { generatedModelMetadata, readCatalog, readCodexCatalogPath } from "./parsing";
35
35
  import type { CatalogModel, RawEntry } from "./parsing";
36
36
  import { UPSTREAM_NATIVE_ENTRIES } from "./metadata";
37
+ import { nativeOpenAiCapabilitySourceSlug } from "./native-models";
37
38
  import { loadBundledCodexCatalog } from "./bundled";
38
- import type { BundledCatalogDeps } from "./bundled";
39
+ import type { BundledCatalogDeps, ReadonlyRawCatalog } from "./bundled";
39
40
  import { deriveEntry } from "./sync";
40
41
  import {
41
42
  formatClampLogLines,
@@ -116,17 +117,19 @@ export function applyCatalogModelMetadata(entry: RawEntry, model?: CatalogModel)
116
117
  if (model.provider === COMBO_NAMESPACE) entry.owned_by = model.owned_by ?? COMBO_NAMESPACE;
117
118
  // displayName is DISPLAY-ONLY: it relabels the picker row but never touches the routing
118
119
  // slug, alias, or provider. deriveEntry already stamped the slug as display_name; a
119
- // configured displayName overrides just the label. The `/` separator is rejected at every
120
- // input boundary (CLI `ocx models add`, management API), so the catalog trusts its source.
121
- // Combos carry no displayName, and natives never reach here (no CatalogModel), so genuine
122
- // upstream marketing names and combo alias labels are preserved untouched.
120
+ // configured displayName overrides just the label. Custom-model inputs reject `/`; combos
121
+ // validate their bounded display label independently. Natives never reach here (no CatalogModel),
122
+ // so genuine upstream marketing names are preserved untouched.
123
123
  const displayName = typeof model.displayName === "string" ? model.displayName.trim() : "";
124
124
  if (displayName) entry.display_name = displayName;
125
- if (typeof model.contextWindow === "number" && model.contextWindow > 0) {
126
- entry.context_window = model.contextWindow;
127
- entry.max_context_window = model.contextWindow;
125
+ const resolvedContext = typeof model.contextWindow === "number" && model.contextWindow > 0
126
+ ? model.contextWindow
127
+ : (model.contextCap !== undefined ? resolveUnknownRoutedContextWindow(model.contextCap) : undefined);
128
+ if (typeof resolvedContext === "number" && resolvedContext > 0) {
129
+ entry.context_window = resolvedContext;
130
+ entry.max_context_window = resolvedContext;
128
131
  entry.auto_compact_token_limit = Math.min(
129
- Math.floor(model.contextWindow * 0.9),
132
+ Math.floor(resolvedContext * 0.9),
130
133
  model.maxInputTokens ?? Number.POSITIVE_INFINITY,
131
134
  );
132
135
  }
@@ -139,6 +142,63 @@ export function applyCatalogModelMetadata(entry: RawEntry, model?: CatalogModel)
139
142
  if (typeof model.supportsReasoningSummaries === "boolean") {
140
143
  entry.supports_reasoning_summaries = model.supportsReasoningSummaries;
141
144
  }
145
+ if (model.supportsServiceTier === true) {
146
+ entry.default_service_tier = null;
147
+ entry.service_tiers = [{
148
+ id: "priority",
149
+ name: "Fast",
150
+ description: model.fastTierDescription ?? "1.5x speed, increased usage",
151
+ }];
152
+ entry.additional_speed_tiers = ["fast"];
153
+ }
154
+ stampCapabilityProvenance(entry, model);
155
+ }
156
+
157
+ /**
158
+ * Record which capability values a real source actually asserted (#1796).
159
+ *
160
+ * `ensureStrictCatalogFields` fills `context_window` and `input_modalities` with
161
+ * compatibility defaults so Codex's strict parser accepts the file, which means
162
+ * an entry ALWAYS carries both and their presence proves nothing. Routing has to
163
+ * tell "the provider said text-only" apart from "nobody said anything", so it
164
+ * reads this block and never the entry itself ("unknown is not zero",
165
+ * src/routing/capability.ts).
166
+ *
167
+ * Two real sources exist and both are consulted here, in the same precedence the
168
+ * writers use (`applyCatalogMetadata` runs first, the model's own fields
169
+ * overwrite it): the `CatalogModel` and the generated jawcode metadata table.
170
+ * Reading only the model would silently drop every provider whose capabilities
171
+ * live in that table.
172
+ */
173
+ function stampCapabilityProvenance(entry: RawEntry, model: CatalogModel): void {
174
+ // Virtual combo rows are synthesized from last-resort defaults (a generic 128k
175
+ // context and a `["text"]` modality), so their values are placeholders rather
176
+ // than assertions. Stamping them would reintroduce the exact false-evidence
177
+ // defect this block exists to prevent.
178
+ if (model.provider === COMBO_NAMESPACE) return;
179
+
180
+ const meta = generatedModelMetadata(model.provider, model.id);
181
+ const metaContext = typeof meta?.contextWindow === "number" && meta.contextWindow > 0
182
+ // The generated context is capped before it reaches the entry, so provenance
183
+ // must apply the same cap or routing would advertise a window the cap refused.
184
+ ? applyProviderContextCap(meta.contextWindow, model.contextCap) ?? meta.contextWindow
185
+ : undefined;
186
+ const contextWindow = typeof model.contextWindow === "number" && model.contextWindow > 0
187
+ ? model.contextWindow
188
+ : metaContext;
189
+ const inputModalities = Array.isArray(model.inputModalities) && model.inputModalities.length > 0
190
+ ? model.inputModalities
191
+ : (Array.isArray(meta?.input) && meta.input.length > 0 ? meta.input : undefined);
192
+
193
+ entry.opencodex_capability_provenance = {
194
+ provider: model.provider,
195
+ model_id: model.id,
196
+ ...(contextWindow !== undefined ? { context_window: contextWindow } : {}),
197
+ ...(inputModalities !== undefined ? { input_modalities: [...inputModalities] } : {}),
198
+ ...(Array.isArray(model.capabilities) && model.capabilities.length > 0
199
+ ? { capabilities: [...model.capabilities] }
200
+ : {}),
201
+ };
142
202
  }
143
203
 
144
204
  export function applyReasoningLevels(
@@ -153,8 +213,9 @@ export function applyReasoningLevels(
153
213
  // (no ultra->max client conversion) and codex-rs validates it by catalog membership,
154
214
  // so a missing max rung hard-fails spawn_agent effort overrides. The wire stays honest:
155
215
  // routed adapters clamp via clampToSupportedCodexEffort and natives via
156
- // nativeEffortClamp (max -> the model's real top rung).
157
- if (!preserveExact && efforts.length > 0) {
216
+ // nativeEffortClamp (max -> the model's real top rung). A `none`-only ladder is NOT
217
+ // reasoning-capable, so it must not grow synthetic top rungs.
218
+ if (!preserveExact && efforts.length > 0 && efforts.some(effort => effort !== "none" && effort !== "minimal")) {
158
219
  const additions: string[] = [];
159
220
  if (!efforts.includes("max")) additions.push("max");
160
221
  if (!efforts.includes("ultra")) additions.push("ultra");
@@ -177,11 +238,13 @@ export function applyReasoningLevels(
177
238
  }
178
239
  entry.default_reasoning_level = defaultOverride && efforts.includes(defaultOverride)
179
240
  ? defaultOverride
180
- : efforts.includes("medium") ? "medium" : efforts.includes("high") ? "high" : efforts[0];
241
+ : efforts.includes("medium") ? "medium" : efforts.includes("high") ? "high"
242
+ // Sentinels never become the implicit default when real rungs are declared.
243
+ : efforts.find(effort => effort !== "none" && effort !== "minimal") ?? efforts[0];
181
244
  }
182
245
 
183
246
  export function isGpt56NativeSlug(slug: string): boolean {
184
- return !slug.includes("/") && slug.startsWith("gpt-5.6-");
247
+ return !slug.includes("/") && nativeOpenAiCapabilitySourceSlug(slug).startsWith("gpt-5.6-");
185
248
  }
186
249
 
187
250
  export function ensureGpt56ReasoningLevels(entry: RawEntry): void {
@@ -214,11 +277,13 @@ export function ensureUltraReasoningLevel(entry: RawEntry): void {
214
277
  entry.supported_reasoning_levels = levels;
215
278
  }
216
279
 
217
- export function codexSupportedReasoningEfforts(deps: BundledCatalogDeps = {}): Set<string> | null {
218
- const bundled = loadBundledCodexCatalog(deps);
219
- if (!bundled) return null;
280
+ /** Derive the installed Codex effort vocabulary from caller-observed bundled catalog bytes. */
281
+ export function supportedCodexReasoningEffortsFromObservedCatalog(
282
+ catalog: ReadonlyRawCatalog | null,
283
+ ): ReadonlySet<string> | null {
284
+ if (!catalog) return null;
220
285
  const efforts = new Set<string>();
221
- for (const model of bundled.models ?? []) {
286
+ for (const model of catalog.models ?? []) {
222
287
  if (typeof model.slug !== "string" || model.slug.includes("/")) continue;
223
288
  const levels = Array.isArray(model.supported_reasoning_levels) ? model.supported_reasoning_levels : [];
224
289
  for (const level of levels) {
@@ -230,6 +295,10 @@ export function codexSupportedReasoningEfforts(deps: BundledCatalogDeps = {}): S
230
295
  return efforts.size > 0 ? efforts : null;
231
296
  }
232
297
 
298
+ export function codexSupportedReasoningEfforts(deps: BundledCatalogDeps = {}): ReadonlySet<string> | null {
299
+ return supportedCodexReasoningEffortsFromObservedCatalog(loadBundledCodexCatalog(deps));
300
+ }
301
+
233
302
  export function clampedDefaultEffort(original: string, surviving: readonly string[]): string {
234
303
  if (surviving.length === 0) return "medium";
235
304
  const ranked = [...surviving]
@@ -240,7 +309,10 @@ export function clampedDefaultEffort(original: string, surviving: readonly strin
240
309
  return (atOrBelow.at(-1) ?? ranked[0]!).effort;
241
310
  }
242
311
 
243
- export function clampEntryToCodexSupportedEfforts(entry: RawEntry, supported: Set<string> | null): void {
312
+ export function clampEntryToCodexSupportedEfforts(
313
+ entry: RawEntry,
314
+ supported: ReadonlySet<string> | null,
315
+ ): void {
244
316
  if (!supported) return;
245
317
  const levels = Array.isArray(entry.supported_reasoning_levels)
246
318
  ? entry.supported_reasoning_levels as Array<{ effort?: string }>
@@ -263,12 +335,17 @@ export function clampEntryToCodexSupportedEfforts(entry: RawEntry, supported: Se
263
335
  }
264
336
  }
265
337
 
266
- export function clampCatalogModelsToCodexSupport(models: RawEntry[], deps: BundledCatalogDeps = {}): RawEntry[] {
267
- const supported = codexSupportedReasoningEfforts(deps);
268
- if (!supported) {
269
- if (!deps.commandCandidates) persistEffortClamp(null, { configDir: deps.configDir });
270
- return models;
271
- }
338
+ export interface ObservedCatalogEffortClamp {
339
+ readonly removedEfforts: readonly string[];
340
+ readonly affectedModels: readonly string[];
341
+ }
342
+
343
+ /** Apply an already-observed runtime ladder without probing, logging, or writing diagnostics. */
344
+ export function clampCatalogModelsToObservedCodexSupport(
345
+ models: RawEntry[],
346
+ supported: ReadonlySet<string> | null,
347
+ ): ObservedCatalogEffortClamp {
348
+ if (!supported) return { removedEfforts: [], affectedModels: [] };
272
349
 
273
350
  const removed = new Set<string>();
274
351
  const affected: string[] = [];
@@ -301,6 +378,20 @@ export function clampCatalogModelsToCodexSupport(models: RawEntry[], deps: Bundl
301
378
  }
302
379
  }
303
380
 
381
+ return {
382
+ removedEfforts: [...removed].sort(),
383
+ affectedModels: affected,
384
+ };
385
+ }
386
+
387
+ export function clampCatalogModelsToCodexSupport(models: RawEntry[], deps: BundledCatalogDeps = {}): RawEntry[] {
388
+ const supported = codexSupportedReasoningEfforts(deps);
389
+ if (!supported) {
390
+ if (!deps.commandCandidates) persistEffortClamp(null, { configDir: deps.configDir });
391
+ return models;
392
+ }
393
+ const clamp = clampCatalogModelsToObservedCodexSupport(models, supported);
394
+
304
395
  let runtimePath = "codex";
305
396
  let runtimeVersion: string | null = null;
306
397
  if (!deps.commandCandidates) {
@@ -337,12 +428,12 @@ export function clampCatalogModelsToCodexSupport(models: RawEntry[], deps: Bundl
337
428
  }
338
429
  }
339
430
 
340
- if (removed.size > 0) {
431
+ if (clamp.removedEfforts.length > 0) {
341
432
  const diagnostic: EffortClampDiagnostic = {
342
433
  runtimePath,
343
434
  runtimeVersion,
344
- removedEfforts: [...removed].sort(),
345
- affectedModels: affected,
435
+ removedEfforts: [...clamp.removedEfforts],
436
+ affectedModels: [...clamp.affectedModels],
346
437
  };
347
438
  for (const line of formatClampLogLines(diagnostic)) console.warn(line);
348
439
  if (!deps.commandCandidates) persistEffortClamp(diagnostic, { configDir: deps.configDir });
@@ -0,0 +1,302 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFileSync, realpathSync, statSync } from "node:fs";
3
+ import { basename, dirname, resolve } from "node:path";
4
+
5
+ import { expandUserPath } from "../../config";
6
+ import type {
7
+ CatalogConditionalSourceObservations,
8
+ CatalogConditionalSourceRole,
9
+ CatalogFilesystemIdentity,
10
+ CatalogHomeSelectionObservation,
11
+ CatalogRequiredSourceObservations,
12
+ CatalogRequiredSourceRole,
13
+ CatalogSourceEvidence,
14
+ CatalogSourceObservation,
15
+ CatalogSourceRole,
16
+ } from "../convergence-types";
17
+ import { defaultCodexHome } from "../home";
18
+
19
+ export type CatalogGatherReadableSourceRole =
20
+ | "active-catalog-merge"
21
+ | "hashed-backup-fallback"
22
+ | "legacy-backup-fallback"
23
+ | "models-cache-fallback"
24
+ | "runtime-selection";
25
+
26
+ /** The minimal observe-only source interface consumed by bundled catalog selection. */
27
+ export interface CatalogGatherEvidenceSession {
28
+ readSource(role: CatalogGatherReadableSourceRole): Uint8Array | null;
29
+ }
30
+
31
+ /** The exact observe-only auth input consumed by provider discovery. */
32
+ export interface CatalogGatherProviderAuthEvidence {
33
+ readonly authStoreBuffer: Uint8Array | null;
34
+ }
35
+
36
+ export type CatalogFilesystemEvidenceSession = CatalogGatherEvidenceSession
37
+ & CatalogGatherProviderAuthEvidence;
38
+
39
+ const CONDITIONAL_SOURCE_ROLES = [
40
+ "bundled-catalog-template",
41
+ "active-catalog-merge",
42
+ "hashed-backup-fallback",
43
+ "legacy-backup-fallback",
44
+ "models-cache-fallback",
45
+ "native-catalog-selection",
46
+ "runtime-selection",
47
+ "provider-auth-selection",
48
+ ] as const satisfies readonly CatalogConditionalSourceRole[];
49
+
50
+ interface MutableSessionState {
51
+ homeSelection: CatalogHomeSelectionObservation | null;
52
+ readonly sourcePaths: Map<CatalogSourceRole, string>;
53
+ requiredTargetSelection: CatalogSourceObservation<CatalogRequiredSourceRole> | null;
54
+ readonly conditional: Record<CatalogConditionalSourceRole, CatalogSourceObservation[]>;
55
+ sealed: boolean;
56
+ }
57
+
58
+ const sessionStates = new WeakMap<object, MutableSessionState>();
59
+
60
+ function filesystemIdentity(
61
+ entry: Readonly<{ dev: bigint; ino: bigint }>,
62
+ ): CatalogFilesystemIdentity {
63
+ return Object.freeze({ volume: String(entry.dev), fileId: String(entry.ino) });
64
+ }
65
+
66
+ function sessionState(session: CatalogFilesystemEvidenceSession): MutableSessionState {
67
+ const state = sessionStates.get(session);
68
+ if (!state) {
69
+ throw new TypeError("Catalog filesystem evidence session was not created by its owner.");
70
+ }
71
+ return state;
72
+ }
73
+
74
+ function assertOpen(state: MutableSessionState): void {
75
+ if (state.sealed) throw new Error("Catalog filesystem evidence session is already sealed.");
76
+ }
77
+
78
+ function observedHomeSelection(): CatalogHomeSelectionObservation {
79
+ const environmentSelector = process.env.CODEX_HOME?.trim();
80
+ const selector = environmentSelector
81
+ ? { kind: "environment" as const, raw: environmentSelector }
82
+ : { kind: "default" as const, raw: defaultCodexHome() };
83
+ const selectedPath = selector.kind === "environment"
84
+ ? resolve(expandUserPath(selector.raw))
85
+ : resolve(selector.raw);
86
+ const canonicalCodexHome = realpathSync.native(selectedPath);
87
+ const root = statSync(canonicalCodexHome, { bigint: true });
88
+ if (!root.isDirectory()) {
89
+ throw new Error(`Codex home is not a directory: ${selectedPath}`);
90
+ }
91
+ return Object.freeze({
92
+ selector: Object.freeze(selector),
93
+ canonicalCodexHome,
94
+ rootIdentity: filesystemIdentity(root),
95
+ });
96
+ }
97
+
98
+ /** Capture and freeze the selector/root authority before any derived path is admitted. */
99
+ export function captureAndSealCatalogHomeSelection(
100
+ session: CatalogFilesystemEvidenceSession,
101
+ ): CatalogHomeSelectionObservation {
102
+ const state = sessionState(session);
103
+ assertOpen(state);
104
+ if (state.homeSelection) return state.homeSelection;
105
+ state.homeSelection = observedHomeSelection();
106
+ return state.homeSelection;
107
+ }
108
+
109
+ /** Bind the next consultation for a closed role without exposing the evidence arrays. */
110
+ export function acceptCatalogGatherSourcePath(
111
+ session: CatalogFilesystemEvidenceSession,
112
+ role: CatalogSourceRole,
113
+ logicalPath: string,
114
+ ): void {
115
+ const state = sessionState(session);
116
+ assertOpen(state);
117
+ if (!state.homeSelection) {
118
+ throw new Error("Catalog home selection must be sealed before accepting a derived path.");
119
+ }
120
+ state.sourcePaths.set(role, resolve(logicalPath));
121
+ }
122
+
123
+ function isMissing(error: unknown): boolean {
124
+ return Boolean(error && typeof error === "object" && "code" in error && error.code === "ENOENT");
125
+ }
126
+
127
+ function observeSource<R extends CatalogSourceRole>(
128
+ role: R,
129
+ logicalPath: string,
130
+ ): Readonly<{ bytes: Uint8Array | null; observation: CatalogSourceObservation<R> }> {
131
+ const canonicalParent = realpathSync.native(dirname(logicalPath));
132
+ const parent = statSync(canonicalParent, { bigint: true });
133
+ if (!parent.isDirectory()) {
134
+ throw new Error(`Catalog source parent is not a directory: ${dirname(logicalPath)}`);
135
+ }
136
+ const parentIdentity = Object.freeze({
137
+ canonicalPath: canonicalParent,
138
+ ...filesystemIdentity(parent),
139
+ });
140
+
141
+ let bytes: Uint8Array;
142
+ try {
143
+ bytes = Uint8Array.from(readFileSync(logicalPath));
144
+ } catch (error) {
145
+ if (!isMissing(error)) throw error;
146
+ return Object.freeze({
147
+ bytes: null,
148
+ observation: Object.freeze({
149
+ state: "absent" as const,
150
+ role,
151
+ logicalPath,
152
+ canonicalPath: resolve(canonicalParent, basename(logicalPath)),
153
+ parentIdentity,
154
+ fileIdentity: null,
155
+ }),
156
+ });
157
+ }
158
+
159
+ const canonicalPath = realpathSync.native(logicalPath);
160
+ const file = statSync(canonicalPath, { bigint: true });
161
+ if (!file.isFile()) throw new Error(`Catalog source is not a regular file: ${logicalPath}`);
162
+ return Object.freeze({
163
+ bytes,
164
+ observation: Object.freeze({
165
+ state: "present" as const,
166
+ role,
167
+ logicalPath,
168
+ canonicalPath,
169
+ parentIdentity,
170
+ fileIdentity: filesystemIdentity(file),
171
+ sha256: createHash("sha256").update(bytes).digest("hex"),
172
+ }),
173
+ });
174
+ }
175
+
176
+ /** Read once, record PRESENT/ABSENT first, then return the exact hashed buffer. */
177
+ export function readCatalogGatherSource<R extends CatalogSourceRole>(
178
+ session: CatalogFilesystemEvidenceSession,
179
+ role: R,
180
+ ): Uint8Array | null {
181
+ const state = sessionState(session);
182
+ assertOpen(state);
183
+ const logicalPath = state.sourcePaths.get(role);
184
+ if (!logicalPath) throw new Error(`No catalog source path was accepted for role ${role}.`);
185
+ if (role === "catalog-target-selection" && state.requiredTargetSelection) {
186
+ throw new Error(`Required catalog source role ${role} was already observed.`);
187
+ }
188
+
189
+ const observed = observeSource(role, logicalPath);
190
+ if (role === "catalog-target-selection") {
191
+ state.requiredTargetSelection = observed.observation as CatalogSourceObservation<"catalog-target-selection">;
192
+ } else {
193
+ state.conditional[role as CatalogConditionalSourceRole].push(observed.observation);
194
+ }
195
+ return observed.bytes;
196
+ }
197
+
198
+ function optionalFileIdentity(path: string): Readonly<{ device: string; inode: string }> | null {
199
+ try {
200
+ const entry = statSync(path, { bigint: true });
201
+ return { device: String(entry.dev), inode: String(entry.ino) };
202
+ } catch (error) {
203
+ if (isMissing(error)) return null;
204
+ throw error;
205
+ }
206
+ }
207
+
208
+ /** Probe a candidate write target without allowing filesystem mutation. */
209
+ export function captureCatalogGatherTargetIdentity(
210
+ session: CatalogFilesystemEvidenceSession,
211
+ path: string,
212
+ ): string {
213
+ const state = sessionState(session);
214
+ assertOpen(state);
215
+ if (!state.homeSelection) {
216
+ throw new Error("Catalog home selection must be sealed before accepting a derived path.");
217
+ }
218
+ const textualPath = resolve(path);
219
+ const canonicalParent = realpathSync.native(dirname(textualPath));
220
+ const parent = statSync(canonicalParent, { bigint: true });
221
+ return JSON.stringify({
222
+ path: textualPath,
223
+ canonicalParent,
224
+ parentIdentity: { device: String(parent.dev), inode: String(parent.ino) },
225
+ fileIdentity: optionalFileIdentity(textualPath),
226
+ });
227
+ }
228
+
229
+ function cloneObservation<R extends CatalogSourceRole>(
230
+ observation: CatalogSourceObservation<R>,
231
+ ): CatalogSourceObservation<R> {
232
+ if (observation.state === "absent") {
233
+ return Object.freeze({
234
+ ...observation,
235
+ parentIdentity: Object.freeze({ ...observation.parentIdentity }),
236
+ fileIdentity: null,
237
+ });
238
+ }
239
+ return Object.freeze({
240
+ ...observation,
241
+ parentIdentity: Object.freeze({ ...observation.parentIdentity }),
242
+ fileIdentity: Object.freeze({ ...observation.fileIdentity }),
243
+ });
244
+ }
245
+
246
+ /** Seal one complete owner-created session into detached, recursively frozen evidence. */
247
+ export function sealCatalogGatherEvidenceSession(
248
+ session: CatalogFilesystemEvidenceSession,
249
+ ): CatalogSourceEvidence {
250
+ const state = sessionState(session);
251
+ assertOpen(state);
252
+ if (!state.homeSelection) throw new Error("Catalog home selection is required before sealing.");
253
+ const targetSelection = state.requiredTargetSelection;
254
+ if (!targetSelection) {
255
+ throw new Error("Required catalog source role catalog-target-selection was not observed.");
256
+ }
257
+ for (const role of CONDITIONAL_SOURCE_ROLES) {
258
+ if (!Object.hasOwn(state.conditional, role)) {
259
+ throw new Error(`Conditional catalog source role ${role} is missing.`);
260
+ }
261
+ }
262
+
263
+ const conditional = Object.fromEntries(CONDITIONAL_SOURCE_ROLES.map(role => [
264
+ role,
265
+ Object.freeze(state.conditional[role].map(observation => cloneObservation(observation))),
266
+ ])) as unknown as CatalogConditionalSourceObservations;
267
+ const required = Object.freeze({
268
+ "catalog-target-selection": cloneObservation(targetSelection),
269
+ }) as CatalogRequiredSourceObservations;
270
+ const evidence = Object.freeze({
271
+ homeSelection: Object.freeze({
272
+ ...state.homeSelection,
273
+ selector: Object.freeze({ ...state.homeSelection.selector }),
274
+ rootIdentity: Object.freeze({ ...state.homeSelection.rootIdentity }),
275
+ }),
276
+ required,
277
+ conditional: Object.freeze(conditional),
278
+ });
279
+ state.sealed = true;
280
+ return evidence;
281
+ }
282
+
283
+ /** Create an opaque session; all mutable evidence state remains module-private. */
284
+ export function createCatalogGatherEvidenceSession(): CatalogFilesystemEvidenceSession {
285
+ let session: CatalogFilesystemEvidenceSession;
286
+ session = Object.freeze({
287
+ readSource: (role: CatalogGatherReadableSourceRole) => readCatalogGatherSource(session, role),
288
+ get authStoreBuffer(): Uint8Array | null {
289
+ return readCatalogGatherSource(session, "provider-auth-selection");
290
+ },
291
+ });
292
+ sessionStates.set(session, {
293
+ homeSelection: null,
294
+ sourcePaths: new Map(),
295
+ requiredTargetSelection: null,
296
+ conditional: Object.fromEntries(
297
+ CONDITIONAL_SOURCE_ROLES.map(role => [role, [] as CatalogSourceObservation[]]),
298
+ ) as unknown as MutableSessionState["conditional"],
299
+ sealed: false,
300
+ });
301
+ return session;
302
+ }
@@ -0,0 +1,2 @@
1
+ /** Stable ownership marker for a routed combo that deliberately owns a bare native slug. */
2
+ export const CODEX_NATIVE_ALIAS_CATALOG_KIND = "combo-native-alias-v1";