@iislee/opencodex 2.11.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 (476) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +225 -0
  3. package/assets/architecture.png +0 -0
  4. package/assets/banner.png +0 -0
  5. package/assets/claude-code-models.gif +0 -0
  6. package/assets/codex-app-picker.png +0 -0
  7. package/bin/ocx.mjs +451 -0
  8. package/bin/package-main.mjs +9 -0
  9. package/gui/dist/assets/index-DTpMHS4F.js +67 -0
  10. package/gui/dist/assets/index-ZNVDE3C7.css +1 -0
  11. package/gui/dist/favicon.png +0 -0
  12. package/gui/dist/icons.svg +24 -0
  13. package/gui/dist/index.html +25 -0
  14. package/gui/dist/logo.png +0 -0
  15. package/gui/dist/provider-icons/alibaba-color.svg +1 -0
  16. package/gui/dist/provider-icons/antigravity-color.svg +1 -0
  17. package/gui/dist/provider-icons/antigravity.svg +1 -0
  18. package/gui/dist/provider-icons/claude-color.svg +1 -0
  19. package/gui/dist/provider-icons/claude.svg +1 -0
  20. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
  21. package/gui/dist/provider-icons/copilot-color.svg +1 -0
  22. package/gui/dist/provider-icons/copilot.svg +1 -0
  23. package/gui/dist/provider-icons/cursor-color.svg +2 -0
  24. package/gui/dist/provider-icons/cursor.svg +2 -0
  25. package/gui/dist/provider-icons/deepseek-color.svg +1 -0
  26. package/gui/dist/provider-icons/discord.svg +1 -0
  27. package/gui/dist/provider-icons/firepass-color.svg +1 -0
  28. package/gui/dist/provider-icons/fireworks-color.svg +1 -0
  29. package/gui/dist/provider-icons/gemini-color.svg +1 -0
  30. package/gui/dist/provider-icons/gemini.svg +1 -0
  31. package/gui/dist/provider-icons/github-copilot-color.svg +1 -0
  32. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -0
  33. package/gui/dist/provider-icons/grok-color.svg +1 -0
  34. package/gui/dist/provider-icons/grok.svg +1 -0
  35. package/gui/dist/provider-icons/groq-color.svg +1 -0
  36. package/gui/dist/provider-icons/huggingface-color.svg +1 -0
  37. package/gui/dist/provider-icons/kimi-color.svg +1 -0
  38. package/gui/dist/provider-icons/kiro-color.svg +15 -0
  39. package/gui/dist/provider-icons/kiro.svg +14 -0
  40. package/gui/dist/provider-icons/lm-studio-color.svg +1 -0
  41. package/gui/dist/provider-icons/mistral-color.svg +1 -0
  42. package/gui/dist/provider-icons/moonshot-color.svg +1 -0
  43. package/gui/dist/provider-icons/nvidia-color.svg +1 -0
  44. package/gui/dist/provider-icons/ollama-color.svg +1 -0
  45. package/gui/dist/provider-icons/openai.svg +1 -0
  46. package/gui/dist/provider-icons/opencode.svg +1 -0
  47. package/gui/dist/provider-icons/openrouter-color.svg +1 -0
  48. package/gui/dist/provider-icons/pi.svg +21 -0
  49. package/gui/dist/provider-icons/qianfan-color.svg +1 -0
  50. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -0
  51. package/gui/dist/provider-icons/telegram.svg +1 -0
  52. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -0
  53. package/gui/dist/provider-icons/vllm-color.svg +1 -0
  54. package/gui/dist/provider-icons/xiaomi-color.svg +1 -0
  55. package/package.json +102 -0
  56. package/src/AGENTS.md +28 -0
  57. package/src/adapters/anthropic-image-guard.ts +251 -0
  58. package/src/adapters/anthropic-image-normalize.ts +518 -0
  59. package/src/adapters/anthropic.ts +1003 -0
  60. package/src/adapters/azure.ts +36 -0
  61. package/src/adapters/base.ts +72 -0
  62. package/src/adapters/client-fingerprint.ts +59 -0
  63. package/src/adapters/cursor/arg-codec.ts +38 -0
  64. package/src/adapters/cursor/arg-normalize.ts +104 -0
  65. package/src/adapters/cursor/cursor-errors.ts +165 -0
  66. package/src/adapters/cursor/discovery.ts +276 -0
  67. package/src/adapters/cursor/effort-map.ts +127 -0
  68. package/src/adapters/cursor/exec-policy.ts +88 -0
  69. package/src/adapters/cursor/framing.ts +211 -0
  70. package/src/adapters/cursor/gen/agent_pb.ts +15274 -0
  71. package/src/adapters/cursor/kv-store.ts +52 -0
  72. package/src/adapters/cursor/live-models.ts +153 -0
  73. package/src/adapters/cursor/live-smoke-gate.ts +41 -0
  74. package/src/adapters/cursor/live-transport.ts +1214 -0
  75. package/src/adapters/cursor/mcp-config.ts +42 -0
  76. package/src/adapters/cursor/mcp-manager.ts +333 -0
  77. package/src/adapters/cursor/message-mapper.ts +49 -0
  78. package/src/adapters/cursor/native-exec-common.ts +55 -0
  79. package/src/adapters/cursor/native-exec-desktop.ts +184 -0
  80. package/src/adapters/cursor/native-exec-fs.ts +329 -0
  81. package/src/adapters/cursor/native-exec-mcp.ts +153 -0
  82. package/src/adapters/cursor/native-exec-network.ts +43 -0
  83. package/src/adapters/cursor/native-exec-shell.ts +548 -0
  84. package/src/adapters/cursor/native-exec-tools.ts +118 -0
  85. package/src/adapters/cursor/native-exec.ts +576 -0
  86. package/src/adapters/cursor/protobuf-events.ts +563 -0
  87. package/src/adapters/cursor/protobuf-request.ts +714 -0
  88. package/src/adapters/cursor/request-builder.ts +255 -0
  89. package/src/adapters/cursor/thread-continuity.ts +67 -0
  90. package/src/adapters/cursor/tool-definitions.ts +505 -0
  91. package/src/adapters/cursor/transport-retry.ts +132 -0
  92. package/src/adapters/cursor/transport.ts +57 -0
  93. package/src/adapters/cursor/types.ts +52 -0
  94. package/src/adapters/cursor.ts +196 -0
  95. package/src/adapters/google-antigravity-replay.ts +303 -0
  96. package/src/adapters/google-antigravity-wire.ts +108 -0
  97. package/src/adapters/google-errors.ts +85 -0
  98. package/src/adapters/google-http.ts +100 -0
  99. package/src/adapters/google-tool-schema.ts +173 -0
  100. package/src/adapters/google-truncation.ts +13 -0
  101. package/src/adapters/google-wire-compiler.ts +232 -0
  102. package/src/adapters/google.ts +758 -0
  103. package/src/adapters/identity.ts +44 -0
  104. package/src/adapters/image.ts +23 -0
  105. package/src/adapters/kiro-constants.ts +16 -0
  106. package/src/adapters/kiro-errors.ts +197 -0
  107. package/src/adapters/kiro-events.ts +179 -0
  108. package/src/adapters/kiro-images.ts +129 -0
  109. package/src/adapters/kiro-retry.ts +312 -0
  110. package/src/adapters/kiro-thinking.ts +96 -0
  111. package/src/adapters/kiro-tool-fallback.ts +36 -0
  112. package/src/adapters/kiro-tools.ts +215 -0
  113. package/src/adapters/kiro-truncation.ts +33 -0
  114. package/src/adapters/kiro-wire.ts +129 -0
  115. package/src/adapters/kiro.ts +1898 -0
  116. package/src/adapters/mimo-free.ts +263 -0
  117. package/src/adapters/openai-chat.ts +1005 -0
  118. package/src/adapters/openai-responses.ts +1137 -0
  119. package/src/adapters/run-turn-queue.ts +114 -0
  120. package/src/adapters/tool-catalog-nudge.ts +71 -0
  121. package/src/adapters/upstream-http-error.ts +48 -0
  122. package/src/bridge.ts +1619 -0
  123. package/src/chat/inbound.ts +295 -0
  124. package/src/chat/outbound.ts +765 -0
  125. package/src/claude/agents-inject.ts +243 -0
  126. package/src/claude/alias.ts +149 -0
  127. package/src/claude/auth-detect.ts +229 -0
  128. package/src/claude/auth-mode-migration.ts +32 -0
  129. package/src/claude/auth-mode.ts +62 -0
  130. package/src/claude/context-windows.ts +189 -0
  131. package/src/claude/desktop-3p-guard.ts +35 -0
  132. package/src/claude/desktop-3p-paths.ts +84 -0
  133. package/src/claude/desktop-3p.ts +381 -0
  134. package/src/claude/desktop-health.ts +26 -0
  135. package/src/claude/desktop-profile.ts +263 -0
  136. package/src/claude/gateway-cache.ts +70 -0
  137. package/src/claude/inbound-debug.ts +163 -0
  138. package/src/claude/inbound.ts +509 -0
  139. package/src/claude/model-info.ts +151 -0
  140. package/src/claude/outbound.ts +872 -0
  141. package/src/cli/access.ts +108 -0
  142. package/src/cli/account-api.ts +268 -0
  143. package/src/cli/account-auth.ts +223 -0
  144. package/src/cli/account-extended.ts +350 -0
  145. package/src/cli/account.ts +275 -0
  146. package/src/cli/agent-driven.ts +70 -0
  147. package/src/cli/agent.ts +184 -0
  148. package/src/cli/catalog-prewarm.ts +27 -0
  149. package/src/cli/claude-desktop.ts +188 -0
  150. package/src/cli/claude.ts +286 -0
  151. package/src/cli/codex-shim-autorestore.ts +45 -0
  152. package/src/cli/combo.ts +119 -0
  153. package/src/cli/config-command.ts +145 -0
  154. package/src/cli/debug.ts +228 -0
  155. package/src/cli/doctor.ts +930 -0
  156. package/src/cli/export-command.ts +187 -0
  157. package/src/cli/help.ts +354 -0
  158. package/src/cli/index.ts +1113 -0
  159. package/src/cli/init.ts +224 -0
  160. package/src/cli/integrations.ts +142 -0
  161. package/src/cli/interactive-confirm.ts +133 -0
  162. package/src/cli/internal-dispatch.ts +20 -0
  163. package/src/cli/models-runtime.ts +212 -0
  164. package/src/cli/models.ts +336 -0
  165. package/src/cli/observe.ts +117 -0
  166. package/src/cli/opencode.ts +586 -0
  167. package/src/cli/pi.ts +188 -0
  168. package/src/cli/provider-runtime.ts +162 -0
  169. package/src/cli/provider.ts +463 -0
  170. package/src/cli/runtime-api.ts +325 -0
  171. package/src/cli/star-prompt.ts +155 -0
  172. package/src/cli/status-oauth.ts +78 -0
  173. package/src/cli/status.ts +321 -0
  174. package/src/cli/sync-cloud.ts +283 -0
  175. package/src/cli/system-command.ts +112 -0
  176. package/src/cli/tray-proxy.ts +52 -0
  177. package/src/cli/v2.ts +173 -0
  178. package/src/cli.ts +10 -0
  179. package/src/clients/config-export.ts +377 -0
  180. package/src/clients/effective-status.ts +385 -0
  181. package/src/clients/probes/agy.ts +55 -0
  182. package/src/clients/probes/cc-switch.ts +110 -0
  183. package/src/clients/probes/claude.ts +90 -0
  184. package/src/clients/probes/codex.ts +125 -0
  185. package/src/clients/probes/grok.ts +29 -0
  186. package/src/clients/probes/opencode.ts +109 -0
  187. package/src/clients/probes/paseo.ts +55 -0
  188. package/src/clients/probes/pi.ts +55 -0
  189. package/src/cloud/onedrive-auth.ts +666 -0
  190. package/src/cloud/onedrive-graph.ts +108 -0
  191. package/src/cloud/settings.ts +75 -0
  192. package/src/cloud/sync.ts +212 -0
  193. package/src/cloud/types.ts +56 -0
  194. package/src/cloud/vault.ts +89 -0
  195. package/src/codex/account-id.ts +34 -0
  196. package/src/codex/account-label.ts +34 -0
  197. package/src/codex/account-lifecycle.ts +55 -0
  198. package/src/codex/account-namespace-match.ts +63 -0
  199. package/src/codex/account-namespaces.ts +149 -0
  200. package/src/codex/account-pause.ts +20 -0
  201. package/src/codex/account-runtime-state.ts +31 -0
  202. package/src/codex/account-store.ts +517 -0
  203. package/src/codex/account-usability.ts +20 -0
  204. package/src/codex/app-server-processes.ts +756 -0
  205. package/src/codex/auth-api.ts +1540 -0
  206. package/src/codex/auth-collision.ts +107 -0
  207. package/src/codex/auth-context.ts +352 -0
  208. package/src/codex/autostart-health.ts +149 -0
  209. package/src/codex/catalog/aggregation.ts +378 -0
  210. package/src/codex/catalog/bundled.ts +251 -0
  211. package/src/codex/catalog/effort.ts +355 -0
  212. package/src/codex/catalog/metadata.ts +180 -0
  213. package/src/codex/catalog/parsing.ts +456 -0
  214. package/src/codex/catalog/provider-fetch.ts +902 -0
  215. package/src/codex/catalog/sync.ts +620 -0
  216. package/src/codex/catalog.ts +12 -0
  217. package/src/codex/data/upstream-models.json +830 -0
  218. package/src/codex/exec-invocation.ts +22 -0
  219. package/src/codex/features.ts +969 -0
  220. package/src/codex/history-migration-guardian.ts +102 -0
  221. package/src/codex/history-provider.ts +776 -0
  222. package/src/codex/home.ts +206 -0
  223. package/src/codex/inject.ts +799 -0
  224. package/src/codex/injected-marker.ts +72 -0
  225. package/src/codex/journal.ts +163 -0
  226. package/src/codex/main-account-cache.ts +32 -0
  227. package/src/codex/main-account.ts +40 -0
  228. package/src/codex/model-cache.ts +227 -0
  229. package/src/codex/paths.ts +65 -0
  230. package/src/codex/plugins-doctor.ts +242 -0
  231. package/src/codex/pool-rotation.ts +225 -0
  232. package/src/codex/project-config-warnings.ts +411 -0
  233. package/src/codex/quota.ts +411 -0
  234. package/src/codex/refresh.ts +53 -0
  235. package/src/codex/routing.ts +1477 -0
  236. package/src/codex/runtime.ts +538 -0
  237. package/src/codex/shim.ts +1189 -0
  238. package/src/codex/subagent-defaults.ts +550 -0
  239. package/src/codex/subagent-model-fallback.ts +469 -0
  240. package/src/codex/sync.ts +130 -0
  241. package/src/codex/warmup.ts +192 -0
  242. package/src/codex/websocket-registry.ts +100 -0
  243. package/src/combos/failover.ts +140 -0
  244. package/src/combos/index.ts +41 -0
  245. package/src/combos/request.ts +62 -0
  246. package/src/combos/resolve.ts +232 -0
  247. package/src/combos/types.ts +326 -0
  248. package/src/config.ts +2356 -0
  249. package/src/generated/jawcode-model-metadata.ts +104 -0
  250. package/src/github/star-state.ts +203 -0
  251. package/src/grok/inject.ts +545 -0
  252. package/src/grok/status.ts +121 -0
  253. package/src/grok/sync.ts +103 -0
  254. package/src/grok/usage-hook/report.mjs +348 -0
  255. package/src/grok/usage-hook.ts +278 -0
  256. package/src/images/artifacts.ts +516 -0
  257. package/src/images/fulfill-video.ts +163 -0
  258. package/src/images/fulfill.ts +149 -0
  259. package/src/images/index.ts +4 -0
  260. package/src/images/loop.ts +829 -0
  261. package/src/images/plan.ts +133 -0
  262. package/src/images/synthetic-tool.ts +133 -0
  263. package/src/images/types.ts +41 -0
  264. package/src/images/xai-client.ts +141 -0
  265. package/src/images/xai-video-client.ts +163 -0
  266. package/src/index.ts +22 -0
  267. package/src/lib/abort.ts +146 -0
  268. package/src/lib/admin-secrets.ts +25 -0
  269. package/src/lib/admission.ts +83 -0
  270. package/src/lib/app-owned-memory-stores.ts +173 -0
  271. package/src/lib/app-owned-memory.ts +265 -0
  272. package/src/lib/bounded-body.ts +202 -0
  273. package/src/lib/bun-binary-validator.d.mts +3 -0
  274. package/src/lib/bun-binary-validator.mjs +18 -0
  275. package/src/lib/bun-runtime.ts +71 -0
  276. package/src/lib/bun-stream-caps.ts +126 -0
  277. package/src/lib/config-ownership.ts +360 -0
  278. package/src/lib/crash-guard.ts +344 -0
  279. package/src/lib/debug-log-buffer.ts +83 -0
  280. package/src/lib/debug-settings.ts +108 -0
  281. package/src/lib/debug.ts +31 -0
  282. package/src/lib/destination-policy.ts +316 -0
  283. package/src/lib/errors.ts +364 -0
  284. package/src/lib/eventstream-decoder.ts +253 -0
  285. package/src/lib/gcp-adc.ts +341 -0
  286. package/src/lib/injection-debug-log.ts +58 -0
  287. package/src/lib/open-url.ts +25 -0
  288. package/src/lib/pinned-http.ts +151 -0
  289. package/src/lib/privacy.ts +20 -0
  290. package/src/lib/process-control.ts +165 -0
  291. package/src/lib/provider-outbound.ts +170 -0
  292. package/src/lib/provider-url.ts +14 -0
  293. package/src/lib/proxy-env.ts +18 -0
  294. package/src/lib/redact.ts +105 -0
  295. package/src/lib/retry-after.ts +55 -0
  296. package/src/lib/service-secrets.ts +25 -0
  297. package/src/lib/shadow-call.ts +30 -0
  298. package/src/lib/sidecar-tracker.ts +52 -0
  299. package/src/lib/sse-decoder.ts +323 -0
  300. package/src/lib/state-store-registrations.ts +109 -0
  301. package/src/lib/state-store-sweeper.ts +184 -0
  302. package/src/lib/test-home-guard.ts +90 -0
  303. package/src/lib/token-estimate.ts +69 -0
  304. package/src/lib/translator-budget.ts +356 -0
  305. package/src/lib/upstream-retry.ts +239 -0
  306. package/src/lib/win-exec.ts +115 -0
  307. package/src/lib/win-paths.ts +68 -0
  308. package/src/lib/windows-elevation.ts +705 -0
  309. package/src/lib/windows-secret-acl.ts +514 -0
  310. package/src/lib/winsw.ts +375 -0
  311. package/src/oauth/anthropic-routing.ts +594 -0
  312. package/src/oauth/anthropic.ts +177 -0
  313. package/src/oauth/callback-server.ts +294 -0
  314. package/src/oauth/chatgpt.ts +150 -0
  315. package/src/oauth/cursor.ts +211 -0
  316. package/src/oauth/github-copilot.ts +428 -0
  317. package/src/oauth/google-antigravity.ts +230 -0
  318. package/src/oauth/health.ts +399 -0
  319. package/src/oauth/index.ts +1174 -0
  320. package/src/oauth/key-providers.ts +108 -0
  321. package/src/oauth/kimi.ts +213 -0
  322. package/src/oauth/kiro-credentials.ts +726 -0
  323. package/src/oauth/kiro.ts +577 -0
  324. package/src/oauth/local-token-detect.ts +121 -0
  325. package/src/oauth/log.ts +48 -0
  326. package/src/oauth/login-cli.ts +163 -0
  327. package/src/oauth/pkce.ts +15 -0
  328. package/src/oauth/store.ts +630 -0
  329. package/src/oauth/token-guardian.ts +303 -0
  330. package/src/oauth/types.ts +62 -0
  331. package/src/oauth/xai.ts +241 -0
  332. package/src/pi/extensions.ts +72 -0
  333. package/src/pi/home.ts +42 -0
  334. package/src/pi/index.ts +40 -0
  335. package/src/pi/models.ts +278 -0
  336. package/src/pi/packages.ts +219 -0
  337. package/src/pi/settings.ts +365 -0
  338. package/src/pi/status.ts +68 -0
  339. package/src/pi/sync.ts +75 -0
  340. package/src/providers/alibaba-region-backup.ts +75 -0
  341. package/src/providers/alibaba-region-migration.ts +156 -0
  342. package/src/providers/alibaba-region-startup.ts +36 -0
  343. package/src/providers/antigravity-models.ts +205 -0
  344. package/src/providers/api-keys.ts +140 -0
  345. package/src/providers/base-url-choices.ts +64 -0
  346. package/src/providers/context-cap.ts +65 -0
  347. package/src/providers/derive.ts +339 -0
  348. package/src/providers/free-directory.ts +184 -0
  349. package/src/providers/github-copilot-transport.ts +56 -0
  350. package/src/providers/key-failover.ts +203 -0
  351. package/src/providers/kiro-models.ts +67 -0
  352. package/src/providers/label.ts +19 -0
  353. package/src/providers/model-discovery.ts +356 -0
  354. package/src/providers/openai-sidecar.ts +175 -0
  355. package/src/providers/openai-tier-startup.ts +27 -0
  356. package/src/providers/openai-tiers.ts +301 -0
  357. package/src/providers/openai-virtual-models.ts +82 -0
  358. package/src/providers/openrouter-routing.ts +102 -0
  359. package/src/providers/provider-id-rewrite.ts +150 -0
  360. package/src/providers/quota.ts +1260 -0
  361. package/src/providers/registry.ts +1600 -0
  362. package/src/providers/slug-codec.ts +67 -0
  363. package/src/providers/xai-transport.ts +141 -0
  364. package/src/reasoning-effort.ts +135 -0
  365. package/src/responses/compaction.ts +117 -0
  366. package/src/responses/parser.ts +656 -0
  367. package/src/responses/reasoning-envelope.ts +52 -0
  368. package/src/responses/schema.ts +159 -0
  369. package/src/responses/spill-store.ts +394 -0
  370. package/src/responses/state.ts +895 -0
  371. package/src/responses/tool-groups.ts +19 -0
  372. package/src/router.ts +425 -0
  373. package/src/server/adapter-resolve.ts +80 -0
  374. package/src/server/auth-cors.ts +530 -0
  375. package/src/server/chat-completions.ts +368 -0
  376. package/src/server/claude-messages.ts +914 -0
  377. package/src/server/effort-policy.ts +172 -0
  378. package/src/server/gui-static.ts +123 -0
  379. package/src/server/image-retry.ts +42 -0
  380. package/src/server/images.ts +476 -0
  381. package/src/server/index.ts +1126 -0
  382. package/src/server/lifecycle.ts +227 -0
  383. package/src/server/live.ts +598 -0
  384. package/src/server/management/agent-settings-routes.ts +1169 -0
  385. package/src/server/management/api-access.ts +141 -0
  386. package/src/server/management/api-key-usage.ts +167 -0
  387. package/src/server/management/body.ts +35 -0
  388. package/src/server/management/clients-routes.ts +63 -0
  389. package/src/server/management/cloud-sync-routes.ts +266 -0
  390. package/src/server/management/combo-routes.ts +220 -0
  391. package/src/server/management/config-routes.ts +422 -0
  392. package/src/server/management/context.ts +31 -0
  393. package/src/server/management/logs-usage-routes.ts +707 -0
  394. package/src/server/management/model-routes.ts +525 -0
  395. package/src/server/management/oauth-account-routes.ts +563 -0
  396. package/src/server/management/provider-routes.ts +556 -0
  397. package/src/server/management/shared.ts +277 -0
  398. package/src/server/management/sidebar-routes.ts +90 -0
  399. package/src/server/management/system-restart.ts +179 -0
  400. package/src/server/management/system-routes.ts +117 -0
  401. package/src/server/management/usage-summary-cache.ts +86 -0
  402. package/src/server/management-api.ts +215 -0
  403. package/src/server/management-auth.ts +267 -0
  404. package/src/server/memory-watchdog.ts +156 -0
  405. package/src/server/port-reclaim.ts +307 -0
  406. package/src/server/ports.ts +116 -0
  407. package/src/server/proxy-liveness.ts +201 -0
  408. package/src/server/relay-eager.ts +313 -0
  409. package/src/server/relay.ts +1049 -0
  410. package/src/server/request-decompress.ts +132 -0
  411. package/src/server/request-log-conversation.ts +168 -0
  412. package/src/server/request-log.ts +1046 -0
  413. package/src/server/responses/collaboration.ts +354 -0
  414. package/src/server/responses/compact.ts +384 -0
  415. package/src/server/responses/core.ts +2758 -0
  416. package/src/server/responses/encrypted-payload.ts +308 -0
  417. package/src/server/responses/fetch-helpers.ts +157 -0
  418. package/src/server/responses/passthrough-error.ts +78 -0
  419. package/src/server/responses/terminal-guard.ts +230 -0
  420. package/src/server/responses/upstream-error.ts +48 -0
  421. package/src/server/responses-image-gen-repair.ts +132 -0
  422. package/src/server/responses-item-id-repair.ts +224 -0
  423. package/src/server/responses.ts +9 -0
  424. package/src/server/search.ts +136 -0
  425. package/src/server/sse-payload-rewrite.ts +175 -0
  426. package/src/server/startup-action-control.ts +308 -0
  427. package/src/server/startup-health-cache.ts +113 -0
  428. package/src/server/system-env.ts +413 -0
  429. package/src/server/windows-tcp-drop.ts +184 -0
  430. package/src/server/windows-tray-control.ts +41 -0
  431. package/src/server/ws-bridge.ts +471 -0
  432. package/src/service.ts +2554 -0
  433. package/src/stall-timeout.ts +20 -0
  434. package/src/storage/cleanup-job.ts +57 -0
  435. package/src/storage/cleanup.ts +3085 -0
  436. package/src/storage/policy-job.ts +457 -0
  437. package/src/storage/policy-scheduler.ts +40 -0
  438. package/src/storage/policy-worker.ts +59 -0
  439. package/src/storage/policy.ts +527 -0
  440. package/src/storage/restore-job.ts +299 -0
  441. package/src/storage/restore-worker.ts +58 -0
  442. package/src/storage/scanner.ts +238 -0
  443. package/src/storage/storage-mutation-coordinator.ts +139 -0
  444. package/src/storage/worker-lifecycle.ts +215 -0
  445. package/src/tray/assets/opencodex-tray-offline.ico +0 -0
  446. package/src/tray/assets/opencodex-tray-online.ico +0 -0
  447. package/src/tray/assets/opencodex-tray-warning.ico +0 -0
  448. package/src/tray/assets/opencodex-tray.png +0 -0
  449. package/src/tray/windows-tray.ps1 +290 -0
  450. package/src/tray/windows.ts +730 -0
  451. package/src/types.ts +1237 -0
  452. package/src/update/badge.ts +72 -0
  453. package/src/update/index.ts +407 -0
  454. package/src/update/job.ts +1520 -0
  455. package/src/update/notify.ts +257 -0
  456. package/src/update/npm-invocation.d.mts +23 -0
  457. package/src/update/npm-invocation.mjs +94 -0
  458. package/src/update/tray-update-plan.d.mts +18 -0
  459. package/src/update/tray-update-plan.mjs +38 -0
  460. package/src/usage/cost.ts +0 -0
  461. package/src/usage/debug.ts +97 -0
  462. package/src/usage/expected-prices.ts +164 -0
  463. package/src/usage/log.ts +658 -0
  464. package/src/usage/summary.ts +585 -0
  465. package/src/usage/totals.ts +14 -0
  466. package/src/vision/anthropic-describe.ts +185 -0
  467. package/src/vision/describe.ts +125 -0
  468. package/src/vision/index.ts +467 -0
  469. package/src/web-search/anthropic-executor.ts +189 -0
  470. package/src/web-search/executor.ts +105 -0
  471. package/src/web-search/format-result.ts +89 -0
  472. package/src/web-search/index.ts +196 -0
  473. package/src/web-search/loop.ts +664 -0
  474. package/src/web-search/parse.ts +220 -0
  475. package/src/web-search/progress-stream.ts +342 -0
  476. package/src/web-search/synthetic-tool.ts +47 -0
@@ -0,0 +1,355 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { createHash } from "node:crypto";
3
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, realpathSync } from "node:fs";
4
+ import { delimiter, dirname, join, resolve } from "node:path";
5
+ import { atomicWriteFile, expandUserPath, getConfigDir, websocketsEnabled } from "../../config";
6
+ import { CODEX_CONFIG_PATH, CODEX_MODELS_CACHE_PATH, DEFAULT_CATALOG_PATH, readRootTomlString, resolveCodexConfigPath } from "../paths";
7
+ import { clearModelCache, DEFAULT_MODEL_CACHE_TTL_MS, getFreshCached, getStaleCached, isModelsFetchCoolingDown, markModelsFetchFailure, setCached } from "../model-cache";
8
+ import { buildModelsRequest, resolveModelsAuthToken } from "../../oauth";
9
+ import type { OcxConfig, OcxProviderConfig } from "../../types";
10
+ import { modelInList } from "../../types";
11
+ import { CODEX_REASONING_LEVELS, codexEffortRank, configuredReasoningEfforts, modelRecordValue, sanitizeCodexReasoningEfforts } from "../../reasoning-effort";
12
+ import { getJawcodeModelMetadata, getJawcodeModelMetadataCaseInsensitive, listJawcodeModelMetadata, resolveJawcodeProvider } from "../../generated/jawcode-model-metadata";
13
+ import { enrichProviderFromRegistry, shouldCaseFoldMetadataModelId } from "../../providers/derive";
14
+ import { getProviderRegistryEntry } from "../../providers/registry";
15
+ import { applyProviderContextCap, providerContextCap } from "../../providers/context-cap";
16
+ import { routedSlug, slugEquals, slugsEquivalent } from "../../providers/slug-codec";
17
+ import { CODEX_GPT5_IDENTITY_LINE } from "../../adapters/identity";
18
+ import { filterCursorConfiguredModelsByLiveDiscovery } from "../../adapters/cursor/discovery";
19
+ import { fetchCursorUsableModels } from "../../adapters/cursor/live-models";
20
+ import { isCanonicalOpenAiForwardProvider, OPENAI_API_PROVIDER_ID, OPENAI_CODEX_PROVIDER_ID } from "../../providers/openai-tiers";
21
+ import {
22
+ COMBO_NAMESPACE,
23
+ comboModelId,
24
+ getCombo,
25
+ listComboIds,
26
+ targetKey,
27
+ } from "../../combos";
28
+ import type { NormalizedComboConfig } from "../../combos/types";
29
+ import { providerDestinationResolvedError } from "../../lib/destination-policy";
30
+ import { redactSecretString, redactUserPath } from "../../lib/redact";
31
+ import upstreamModelsSnapshot from "../data/upstream-models.json";
32
+
33
+
34
+ import { readCatalog, readCodexCatalogPath } from "./parsing";
35
+ import type { CatalogModel, RawEntry } from "./parsing";
36
+ import { UPSTREAM_NATIVE_ENTRIES } from "./metadata";
37
+ import { loadBundledCodexCatalog } from "./bundled";
38
+ import type { BundledCatalogDeps } from "./bundled";
39
+ import { deriveEntry } from "./sync";
40
+ import {
41
+ formatClampLogLines,
42
+ formatRuntimeLogLine,
43
+ displayCodexRuntimePath,
44
+ persistEffortClamp,
45
+ resolveAndPersistCodexRuntime,
46
+ type EffortClampDiagnostic,
47
+ } from "../runtime";
48
+
49
+ export function nativeEffortClamp(slug: string, effort: string | undefined): string | null {
50
+ if (!effort || (effort !== "max" && effort !== "ultra")) return null;
51
+ if (slug.includes("/")) return null; // routed models map efforts in their adapters
52
+ const entry = UPSTREAM_NATIVE_ENTRIES.get(slug);
53
+ const levels = Array.isArray(entry?.supported_reasoning_levels)
54
+ ? entry.supported_reasoning_levels as Array<{ effort?: string }>
55
+ : [];
56
+ if (levels.length === 0) {
57
+ // Not snapshot-covered. gpt-5.6 natives have a REAL max rung (ensureGpt56ReasoningLevels
58
+ // restores it even off-snapshot) -> never clamp. Every other bare native (gpt-5.5/5.4/
59
+ // 5.4-mini/5.3-codex-spark and future old-ladder slugs) really stops at xhigh — the
60
+ // ChatGPT backend error names exactly none..xhigh — so clamp the synthetic top tier.
61
+ return isGpt56NativeSlug(slug) ? null : "xhigh";
62
+ }
63
+ const supported = levels.flatMap(l => typeof l.effort === "string" ? [l.effort] : []);
64
+ if (supported.includes(effort)) return null;
65
+ const rank = ["minimal", "low", "medium", "high", "xhigh", "max"];
66
+ const highest = supported
67
+ .filter(e => rank.includes(e))
68
+ .sort((a, b) => rank.indexOf(a) - rank.indexOf(b))
69
+ .at(-1);
70
+ return highest ?? null;
71
+ }
72
+
73
+ export function shouldApplyNativeEffortClamp(
74
+ providerName: string,
75
+ provider: OcxProviderConfig,
76
+ requestedModelId: string,
77
+ ): boolean {
78
+ return !requestedModelId.includes("/")
79
+ && providerName === OPENAI_CODEX_PROVIDER_ID
80
+ && isCanonicalOpenAiForwardProvider(provider);
81
+ }
82
+
83
+ export function catalogModelEfforts(slugs: readonly string[]): Map<string, string[]> {
84
+ const out = new Map<string, string[]>();
85
+ if (slugs.length === 0) return out;
86
+ const catalog = readCatalog(readCodexCatalogPath());
87
+ if (!catalog) return out;
88
+ for (const entry of catalog.models ?? []) {
89
+ if (typeof entry.slug !== "string") continue;
90
+ // Tolerate raw legacy config slugs (`provider/vendor/model`) against the
91
+ // Codex-facing encoded catalog slug (`provider/vendor-model`).
92
+ const callerSlug = slugs.find(s => slugsEquivalent(s, entry.slug as string));
93
+ if (callerSlug === undefined) continue;
94
+ const levels = Array.isArray(entry.supported_reasoning_levels)
95
+ ? entry.supported_reasoning_levels as Array<{ effort?: string }>
96
+ : [];
97
+ const efforts = levels.flatMap(l => typeof l.effort === "string" ? [l.effort] : []);
98
+ if (efforts.length > 0) out.set(callerSlug, efforts);
99
+ }
100
+ return out;
101
+ }
102
+
103
+ export function catalogEntryEfforts(entry: RawEntry): string[] {
104
+ const levels = Array.isArray(entry.supported_reasoning_levels)
105
+ ? entry.supported_reasoning_levels as Array<{ effort?: string }>
106
+ : [];
107
+ return levels.flatMap(level => typeof level.effort === "string" ? [level.effort] : []);
108
+ }
109
+
110
+ export const ROUTED_REASONING_LEVELS = [...CODEX_REASONING_LEVELS];
111
+
112
+ export function applyCatalogModelMetadata(entry: RawEntry, model?: CatalogModel): void {
113
+ if (!model) return;
114
+ // This marker survives strict catalog normalization and lets sync distinguish a stale
115
+ // bare combo alias from a genuine native model row.
116
+ if (model.provider === COMBO_NAMESPACE) entry.owned_by = model.owned_by ?? COMBO_NAMESPACE;
117
+ // displayName is DISPLAY-ONLY: it relabels the picker row but never touches the routing
118
+ // 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.
123
+ const displayName = typeof model.displayName === "string" ? model.displayName.trim() : "";
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;
128
+ entry.auto_compact_token_limit = Math.min(
129
+ Math.floor(model.contextWindow * 0.9),
130
+ model.maxInputTokens ?? Number.POSITIVE_INFINITY,
131
+ );
132
+ }
133
+ if (Array.isArray(model.inputModalities) && model.inputModalities.length > 0) {
134
+ entry.input_modalities = model.inputModalities;
135
+ }
136
+ if (typeof model.supportsVerbosity === "boolean") {
137
+ entry.support_verbosity = model.supportsVerbosity;
138
+ }
139
+ if (typeof model.supportsReasoningSummaries === "boolean") {
140
+ entry.supports_reasoning_summaries = model.supportsReasoningSummaries;
141
+ }
142
+ }
143
+
144
+ export function applyReasoningLevels(
145
+ entry: RawEntry,
146
+ effortsOverride?: string[],
147
+ defaultOverride?: string,
148
+ preserveExact = false,
149
+ ): void {
150
+ let efforts = sanitizeCodexReasoningEfforts(effortsOverride) ?? ROUTED_REASONING_LEVELS.map(l => l.effort);
151
+ // Mock top tiers (user decision 260709): every reasoning-capable model advertises `max`
152
+ // even when the provider ladder stops lower — subagent spawns pass `max` DIRECTLY
153
+ // (no ultra->max client conversion) and codex-rs validates it by catalog membership,
154
+ // so a missing max rung hard-fails spawn_agent effort overrides. The wire stays honest:
155
+ // routed adapters clamp via clampToSupportedCodexEffort and natives via
156
+ // nativeEffortClamp (max -> the model's real top rung).
157
+ if (!preserveExact && efforts.length > 0) {
158
+ const additions: string[] = [];
159
+ if (!efforts.includes("max")) additions.push("max");
160
+ if (!efforts.includes("ultra")) additions.push("ultra");
161
+ if (additions.length > 0) efforts = sanitizeCodexReasoningEfforts([...efforts, ...additions]) ?? efforts;
162
+ }
163
+ const byEffort = new Map(
164
+ (Array.isArray(entry.supported_reasoning_levels) ? entry.supported_reasoning_levels : [])
165
+ .map((l: { effort?: string }) => [l.effort, l]),
166
+ );
167
+ entry.supported_reasoning_levels = efforts.map(effort => {
168
+ const native = byEffort.get(effort);
169
+ if (native) return native;
170
+ // Description lookup uses the FULL ladder so an opt-in effort outside the routed default
171
+ // (e.g. "ultra") still renders its canonical description.
172
+ return CODEX_REASONING_LEVELS.find(l => l.effort === effort) ?? { effort, description: `${effort} reasoning` };
173
+ });
174
+ if (efforts.length === 0) {
175
+ delete entry.default_reasoning_level;
176
+ return;
177
+ }
178
+ entry.default_reasoning_level = defaultOverride && efforts.includes(defaultOverride)
179
+ ? defaultOverride
180
+ : efforts.includes("medium") ? "medium" : efforts.includes("high") ? "high" : efforts[0];
181
+ }
182
+
183
+ export function isGpt56NativeSlug(slug: string): boolean {
184
+ return !slug.includes("/") && slug.startsWith("gpt-5.6-");
185
+ }
186
+
187
+ export function ensureGpt56ReasoningLevels(entry: RawEntry): void {
188
+ const levels = Array.isArray(entry.supported_reasoning_levels)
189
+ ? entry.supported_reasoning_levels as Array<{ effort?: string }>
190
+ : [];
191
+ const out = [...levels];
192
+ // max is a real native rung on the 5.6 family — always restored; ultra always advertised.
193
+ for (const effort of ["max", "ultra"]) {
194
+ if (out.some(level => level.effort === effort)) continue;
195
+ out.push(CODEX_REASONING_LEVELS.find(level => level.effort === effort)
196
+ ?? { effort, description: `${effort} reasoning` });
197
+ }
198
+ entry.supported_reasoning_levels = out;
199
+ }
200
+
201
+ export function ensureUltraReasoningLevel(entry: RawEntry): void {
202
+ const levels = Array.isArray(entry.supported_reasoning_levels)
203
+ ? entry.supported_reasoning_levels as Array<{ effort?: string }>
204
+ : [];
205
+ if (levels.length === 0) return;
206
+ const wanted = ["max", "ultra"];
207
+ for (const effort of wanted) {
208
+ if (levels.some(level => level.effort === effort)) continue;
209
+ levels.push(
210
+ CODEX_REASONING_LEVELS.find(level => level.effort === effort)
211
+ ?? { effort, description: `${effort} reasoning` },
212
+ );
213
+ }
214
+ entry.supported_reasoning_levels = levels;
215
+ }
216
+
217
+ export function codexSupportedReasoningEfforts(deps: BundledCatalogDeps = {}): Set<string> | null {
218
+ const bundled = loadBundledCodexCatalog(deps);
219
+ if (!bundled) return null;
220
+ const efforts = new Set<string>();
221
+ for (const model of bundled.models ?? []) {
222
+ if (typeof model.slug !== "string" || model.slug.includes("/")) continue;
223
+ const levels = Array.isArray(model.supported_reasoning_levels) ? model.supported_reasoning_levels : [];
224
+ for (const level of levels) {
225
+ const effort = (level as { effort?: unknown })?.effort;
226
+ if (typeof effort === "string") efforts.add(effort);
227
+ }
228
+ if (typeof model.default_reasoning_level === "string") efforts.add(model.default_reasoning_level);
229
+ }
230
+ return efforts.size > 0 ? efforts : null;
231
+ }
232
+
233
+ export function clampedDefaultEffort(original: string, surviving: readonly string[]): string {
234
+ if (surviving.length === 0) return "medium";
235
+ const ranked = [...surviving]
236
+ .map(effort => ({ effort, rank: codexEffortRank(effort) }))
237
+ .sort((a, b) => a.rank - b.rank);
238
+ const originalRank = codexEffortRank(original);
239
+ const atOrBelow = ranked.filter(item => item.rank >= 0 && item.rank <= originalRank);
240
+ return (atOrBelow.at(-1) ?? ranked[0]!).effort;
241
+ }
242
+
243
+ export function clampEntryToCodexSupportedEfforts(entry: RawEntry, supported: Set<string> | null): void {
244
+ if (!supported) return;
245
+ const levels = Array.isArray(entry.supported_reasoning_levels)
246
+ ? entry.supported_reasoning_levels as Array<{ effort?: string }>
247
+ : null;
248
+ if (levels && levels.length > 0) {
249
+ const kept = levels.filter(level => typeof level?.effort === "string" && supported.has(level.effort));
250
+ entry.supported_reasoning_levels = kept.length > 0
251
+ ? kept
252
+ : CODEX_REASONING_LEVELS
253
+ .filter(level => level.effort === "low" || level.effort === "medium" || level.effort === "high")
254
+ .map(level => ({ ...level }));
255
+ }
256
+ const currentDefault = entry.default_reasoning_level;
257
+ if (typeof currentDefault === "string" && !supported.has(currentDefault)) {
258
+ const surviving = (Array.isArray(entry.supported_reasoning_levels) ? entry.supported_reasoning_levels : [])
259
+ .flatMap(level => typeof (level as { effort?: string })?.effort === "string"
260
+ ? [(level as { effort: string }).effort]
261
+ : []);
262
+ entry.default_reasoning_level = clampedDefaultEffort(currentDefault, surviving);
263
+ }
264
+ }
265
+
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
+ }
272
+
273
+ const removed = new Set<string>();
274
+ const affected: string[] = [];
275
+ for (const entry of models) {
276
+ const before = new Set(
277
+ (Array.isArray(entry.supported_reasoning_levels) ? entry.supported_reasoning_levels : [])
278
+ .flatMap(level => typeof (level as { effort?: string })?.effort === "string"
279
+ ? [(level as { effort: string }).effort]
280
+ : []),
281
+ );
282
+ const beforeDefault = typeof entry.default_reasoning_level === "string"
283
+ ? entry.default_reasoning_level
284
+ : null;
285
+ clampEntryToCodexSupportedEfforts(entry, supported);
286
+ const after = new Set(
287
+ (Array.isArray(entry.supported_reasoning_levels) ? entry.supported_reasoning_levels : [])
288
+ .flatMap(level => typeof (level as { effort?: string })?.effort === "string"
289
+ ? [(level as { effort: string }).effort]
290
+ : []),
291
+ );
292
+ const afterDefault = typeof entry.default_reasoning_level === "string"
293
+ ? entry.default_reasoning_level
294
+ : null;
295
+ const lost = [...before].filter(effort => !after.has(effort));
296
+ const defaultClamped = Boolean(beforeDefault && beforeDefault !== afterDefault);
297
+ if (lost.length > 0 || defaultClamped) {
298
+ for (const effort of lost) removed.add(effort);
299
+ if (defaultClamped && beforeDefault) removed.add(beforeDefault);
300
+ if (typeof entry.slug === "string") affected.push(entry.slug);
301
+ }
302
+ }
303
+
304
+ let runtimePath = "codex";
305
+ let runtimeVersion: string | null = null;
306
+ if (!deps.commandCandidates) {
307
+ try {
308
+ const resolved = resolveAndPersistCodexRuntime({
309
+ execFileSync: deps.execFileSync,
310
+ configDir: deps.configDir,
311
+ env: deps.env,
312
+ platform: deps.platform,
313
+ existsSync: deps.existsSync,
314
+ readFileSync: deps.readFileSync,
315
+ now: deps.now,
316
+ discoverAlternatives: deps.discoverAlternatives,
317
+ });
318
+ runtimePath = resolved.runtime.command;
319
+ runtimeVersion = resolved.runtime.version;
320
+ process.stderr.write(`${formatRuntimeLogLine(resolved.runtime)}\n`);
321
+ if (resolved.persistError) {
322
+ console.warn(`[opencodex] Codex runtime selection could not be persisted; a later sync may pick a different binary.`);
323
+ }
324
+ if (
325
+ resolved.replacedConfigured
326
+ && resolved.replacedConfigured.from.command !== resolved.runtime.command
327
+ ) {
328
+ console.warn(`[opencodex] Preferred Codex runtime is unavailable.`);
329
+ console.warn(
330
+ `[opencodex] Falling back from ${displayCodexRuntimePath(resolved.replacedConfigured.from.command)} to ${displayCodexRuntimePath(runtimePath)}.`,
331
+ );
332
+ }
333
+ } catch (error) {
334
+ const message = error instanceof Error ? error.message : String(error);
335
+ const redacted = redactUserPath(redactSecretString(message)).slice(0, 200);
336
+ console.warn(`[opencodex] Codex runtime resolve failed during catalog clamp: ${redacted}`);
337
+ }
338
+ }
339
+
340
+ if (removed.size > 0) {
341
+ const diagnostic: EffortClampDiagnostic = {
342
+ runtimePath,
343
+ runtimeVersion,
344
+ removedEfforts: [...removed].sort(),
345
+ affectedModels: affected,
346
+ };
347
+ for (const line of formatClampLogLines(diagnostic)) console.warn(line);
348
+ if (!deps.commandCandidates) persistEffortClamp(diagnostic, { configDir: deps.configDir });
349
+ deps.onEffortClamp?.(diagnostic);
350
+ } else if (!deps.commandCandidates) {
351
+ persistEffortClamp(null, { configDir: deps.configDir });
352
+ }
353
+
354
+ return models;
355
+ }
@@ -0,0 +1,180 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { createHash } from "node:crypto";
3
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, realpathSync } from "node:fs";
4
+ import { delimiter, dirname, join, resolve } from "node:path";
5
+ import { atomicWriteFile, expandUserPath, getConfigDir, websocketsEnabled } from "../../config";
6
+ import { CODEX_CONFIG_PATH, CODEX_MODELS_CACHE_PATH, DEFAULT_CATALOG_PATH, readRootTomlString, resolveCodexConfigPath } from "../paths";
7
+ import { clearModelCache, DEFAULT_MODEL_CACHE_TTL_MS, getFreshCached, getStaleCached, isModelsFetchCoolingDown, markModelsFetchFailure, setCached } from "../model-cache";
8
+ import { buildModelsRequest, resolveModelsAuthToken } from "../../oauth";
9
+ import type { OcxConfig, OcxProviderConfig } from "../../types";
10
+ import { modelInList } from "../../types";
11
+ import { CODEX_REASONING_LEVELS, codexEffortRank, configuredReasoningEfforts, modelRecordValue, sanitizeCodexReasoningEfforts } from "../../reasoning-effort";
12
+ import { getJawcodeModelMetadata, getJawcodeModelMetadataCaseInsensitive, listJawcodeModelMetadata, resolveJawcodeProvider } from "../../generated/jawcode-model-metadata";
13
+ import { enrichProviderFromRegistry, shouldCaseFoldMetadataModelId } from "../../providers/derive";
14
+ import { getProviderRegistryEntry } from "../../providers/registry";
15
+ import { applyProviderContextCap, providerContextCap } from "../../providers/context-cap";
16
+ import { routedSlug, slugEquals, slugsEquivalent } from "../../providers/slug-codec";
17
+ import { CODEX_GPT5_IDENTITY_LINE } from "../../adapters/identity";
18
+ import { filterCursorConfiguredModelsByLiveDiscovery } from "../../adapters/cursor/discovery";
19
+ import { fetchCursorUsableModels } from "../../adapters/cursor/live-models";
20
+ import { isCanonicalOpenAiForwardProvider, OPENAI_API_PROVIDER_ID, OPENAI_CODEX_PROVIDER_ID } from "../../providers/openai-tiers";
21
+ import {
22
+ COMBO_NAMESPACE,
23
+ comboModelId,
24
+ getCombo,
25
+ listComboIds,
26
+ targetKey,
27
+ } from "../../combos";
28
+ import type { NormalizedComboConfig } from "../../combos/types";
29
+ import { providerDestinationResolvedError } from "../../lib/destination-policy";
30
+ import { redactSecretString } from "../../lib/redact";
31
+ import upstreamModelsSnapshot from "../data/upstream-models.json";
32
+
33
+
34
+ import { filterSupportedNativeSlugs } from "./parsing";
35
+ import type { RawEntry } from "./parsing";
36
+ import { readCurrentCatalogOrCache, unique } from "./bundled";
37
+
38
+ export const NATIVE_OPENAI_MODELS = [
39
+ "gpt-5.5", "gpt-5.4", "gpt-5.4-mini", "gpt-5.3-codex-spark",
40
+ "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna",
41
+ ];
42
+
43
+ export const DOCUMENTED_NATIVE_OPENAI_ADDITIONS = [
44
+ "gpt-5.3-codex-spark",
45
+ "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna",
46
+ ];
47
+
48
+ export const SUPPORTED_NATIVE_OPENAI_SLUGS = new Set(NATIVE_OPENAI_MODELS);
49
+
50
+ export function isUnsupportedOpenAiNativeSlug(slug: string): boolean {
51
+ if (slug.includes("/")) return false;
52
+ if (SUPPORTED_NATIVE_OPENAI_SLUGS.has(slug)) return false;
53
+ return /^(?:gpt|codex)-/.test(slug);
54
+ }
55
+
56
+ export const NATIVE_GPT56_CONTEXT_WINDOW = 372_000;
57
+
58
+ export const NATIVE_OPENAI_CONTEXT_OVERRIDES: Record<string, { contextWindow?: number; maxContextWindow?: number }> = {
59
+ "gpt-5.5": { contextWindow: 272_000, maxContextWindow: 272_000 },
60
+ "gpt-5.4": { contextWindow: 1_000_000, maxContextWindow: 1_000_000 },
61
+ "gpt-5.3-codex-spark": { contextWindow: 100_000, maxContextWindow: 100_000 },
62
+ "gpt-5.6-sol": { contextWindow: NATIVE_GPT56_CONTEXT_WINDOW, maxContextWindow: NATIVE_GPT56_CONTEXT_WINDOW },
63
+ "gpt-5.6-terra": { contextWindow: NATIVE_GPT56_CONTEXT_WINDOW, maxContextWindow: NATIVE_GPT56_CONTEXT_WINDOW },
64
+ "gpt-5.6-luna": { contextWindow: NATIVE_GPT56_CONTEXT_WINDOW, maxContextWindow: NATIVE_GPT56_CONTEXT_WINDOW },
65
+ };
66
+
67
+ export function nativeOpenAiContextWindow(slug: string): number | undefined {
68
+ return NATIVE_OPENAI_CONTEXT_OVERRIDES[slug]?.contextWindow
69
+ ?? (typeof UPSTREAM_NATIVE_ENTRIES.get(slug)?.context_window === "number"
70
+ ? UPSTREAM_NATIVE_ENTRIES.get(slug)!.context_window as number
71
+ : undefined);
72
+ }
73
+
74
+ export function nativeInputModalities(slug: string): string[] {
75
+ const upstream = UPSTREAM_NATIVE_ENTRIES.get(slug);
76
+ if (Array.isArray(upstream?.input_modalities) && upstream!.input_modalities!.length > 0) {
77
+ return [...upstream!.input_modalities as string[]];
78
+ }
79
+ // gpt-5.3-codex-spark is not in the upstream snapshot; all supported natives are
80
+ // text+image capable, so default to the family baseline rather than text-only.
81
+ return ["text", "image"];
82
+ }
83
+
84
+ export function nativeReasoningEfforts(slug: string): string[] {
85
+ const upstream = UPSTREAM_NATIVE_ENTRIES.get(slug);
86
+ const levels = Array.isArray(upstream?.supported_reasoning_levels)
87
+ ? upstream!.supported_reasoning_levels as Array<{ effort?: string }>
88
+ : [];
89
+ if (levels.length > 0) {
90
+ // Preserve the exact pinned per-model ladder. In particular, GPT-5.6 Sol and Terra
91
+ // include ultra while Luna intentionally ends at max.
92
+ return levels.flatMap(l => typeof l.effort === "string" ? [l.effort] : []);
93
+ }
94
+ // gpt-5.3-codex-spark is not in upstream snapshot — use the standard old-ladder default.
95
+ return ["low", "medium", "high", "xhigh"];
96
+ }
97
+
98
+ /** Upstream-pinned default for a native slug, when present and non-empty. */
99
+ export function nativeDefaultReasoningEffort(slug: string): string | undefined {
100
+ const level = UPSTREAM_NATIVE_ENTRIES.get(slug)?.default_reasoning_level;
101
+ return typeof level === "string" && level.length > 0 ? level : undefined;
102
+ }
103
+
104
+ export function nativeParallelToolCalls(slug: string): boolean {
105
+ return UPSTREAM_NATIVE_ENTRIES.get(slug)?.supports_parallel_tool_calls === true
106
+ || false;
107
+ }
108
+
109
+ export function hasComboTargets(config: { combos?: Record<string, { targets?: unknown[] }> }): boolean {
110
+ const combos = config.combos;
111
+ if (!combos) return false;
112
+ return Object.values(combos).some(c => Array.isArray(c?.targets) && c!.targets!.length > 0);
113
+ }
114
+
115
+ export function disabledNativeSlugs(config: Pick<OcxConfig, "disabledModels">): Set<string> {
116
+ return new Set((config.disabledModels ?? []).filter(id => !id.includes("/")));
117
+ }
118
+
119
+ export function visibleNativeSlugs(config: Pick<OcxConfig, "disabledModels">): string[] {
120
+ const disabled = disabledNativeSlugs(config);
121
+ return nativeOpenAiSlugs().filter(slug => !disabled.has(slug));
122
+ }
123
+
124
+ /** Native slugs exposed to Claude Desktop show/export/apply (opt-out via claudeCode.desktopNativeModels). */
125
+ export function desktopVisibleNativeSlugs(config: Pick<OcxConfig, "claudeCode" | "disabledModels">): string[] {
126
+ if (config.claudeCode?.desktopNativeModels === false) return [];
127
+ return visibleNativeSlugs(config);
128
+ }
129
+
130
+ export function nativeModelRows(config: Pick<OcxConfig, "disabledModels">): Array<{ slug: string; disabled: boolean; contextWindow?: number }> {
131
+ const disabled = disabledNativeSlugs(config);
132
+ return NATIVE_OPENAI_MODELS.map(slug => {
133
+ const contextWindow = nativeOpenAiContextWindow(slug);
134
+ return { slug, disabled: disabled.has(slug), ...(contextWindow !== undefined ? { contextWindow } : {}) };
135
+ });
136
+ }
137
+
138
+ export function applyNativeVisibility(entries: RawEntry[], disabledNative: Set<string>): RawEntry[] {
139
+ for (const entry of entries) {
140
+ const slug = typeof entry.slug === "string" ? entry.slug : "";
141
+ if (!slug || slug.includes("/") || !SUPPORTED_NATIVE_OPENAI_SLUGS.has(slug)) continue;
142
+ entry.visibility = disabledNative.has(slug) ? "hide" : "list";
143
+ }
144
+ return entries;
145
+ }
146
+
147
+ export const UPSTREAM_NATIVE_ENTRIES: Map<string, RawEntry> = new Map(
148
+ ((upstreamModelsSnapshot as unknown as { models?: RawEntry[] }).models ?? [])
149
+ .filter(m => typeof m.slug === "string"
150
+ && SUPPORTED_NATIVE_OPENAI_SLUGS.has(m.slug as string)
151
+ && (m.slug as string).startsWith("gpt-5.6-"))
152
+ .map(m => [m.slug as string, m]),
153
+ );
154
+
155
+ export function upstreamNativeEntry(slug: string): RawEntry | null {
156
+ const entry = UPSTREAM_NATIVE_ENTRIES.get(slug);
157
+ if (!entry) return null;
158
+ const clone = JSON.parse(JSON.stringify(entry)) as RawEntry;
159
+ delete clone.minimal_client_version;
160
+ return clone;
161
+ }
162
+
163
+ export function shouldUpgradeToUpstreamEntry(entry: RawEntry): boolean {
164
+ return typeof entry.slug === "string"
165
+ && UPSTREAM_NATIVE_ENTRIES.has(entry.slug)
166
+ && entry.display_name === entry.slug;
167
+ }
168
+
169
+ export function nativeOpenAiSlugs(): string[] {
170
+ const live = listCatalogNativeSlugs();
171
+ return live.length > 0 ? unique([...live, ...DOCUMENTED_NATIVE_OPENAI_ADDITIONS]) : NATIVE_OPENAI_MODELS;
172
+ }
173
+
174
+ export function listCatalogNativeSlugs(): string[] {
175
+ const cat = readCurrentCatalogOrCache();
176
+ const live = filterSupportedNativeSlugs(cat?.models ?? []);
177
+ // Ensure documented additions (e.g. gpt-5.3-codex-spark) appear even when the bundled catalog
178
+ // predates the slug — mirrors nativeOpenAiSlugs() which already merges them for /v1/models.
179
+ return unique([...live, ...DOCUMENTED_NATIVE_OPENAI_ADDITIONS]);
180
+ }