@yansigit/opencodex 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 (826) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/LICENSE +21 -0
  3. package/README.md +303 -0
  4. package/assets/architecture.png +0 -0
  5. package/assets/banner.png +0 -0
  6. package/assets/claude-code-models.gif +0 -0
  7. package/assets/codex-app-picker.png +0 -0
  8. package/bin/ocx.mjs +587 -0
  9. package/bin/package-main.mjs +9 -0
  10. package/gui/dist/assets/index-BNJ7r4Gd.js +102 -0
  11. package/gui/dist/assets/index-CGoDO3uO.css +1 -0
  12. package/gui/dist/favicon.png +0 -0
  13. package/gui/dist/icons.svg +24 -0
  14. package/gui/dist/index.html +25 -0
  15. package/gui/dist/logo.png +0 -0
  16. package/gui/dist/provider-icons/alibaba-color.svg +1 -0
  17. package/gui/dist/provider-icons/antigravity-color.svg +1 -0
  18. package/gui/dist/provider-icons/claude-color.svg +1 -0
  19. package/gui/dist/provider-icons/cline-color.svg +16 -0
  20. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
  21. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  22. package/gui/dist/provider-icons/copilot-color.svg +1 -0
  23. package/gui/dist/provider-icons/cursor-color.svg +2 -0
  24. package/gui/dist/provider-icons/deepseek-color.svg +1 -0
  25. package/gui/dist/provider-icons/discord.svg +1 -0
  26. package/gui/dist/provider-icons/firepass-color.svg +1 -0
  27. package/gui/dist/provider-icons/fireworks-color.svg +1 -0
  28. package/gui/dist/provider-icons/gemini-color.svg +1 -0
  29. package/gui/dist/provider-icons/github-copilot-color.svg +1 -0
  30. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -0
  31. package/gui/dist/provider-icons/grok.svg +1 -0
  32. package/gui/dist/provider-icons/groq-color.svg +1 -0
  33. package/gui/dist/provider-icons/huggingface-color.svg +1 -0
  34. package/gui/dist/provider-icons/kimi-color.svg +1 -0
  35. package/gui/dist/provider-icons/kiro-color.svg +15 -0
  36. package/gui/dist/provider-icons/lm-studio-color.svg +1 -0
  37. package/gui/dist/provider-icons/mistral-color.svg +1 -0
  38. package/gui/dist/provider-icons/moonshot-color.svg +1 -0
  39. package/gui/dist/provider-icons/nvidia-color.svg +1 -0
  40. package/gui/dist/provider-icons/ollama-color.svg +1 -0
  41. package/gui/dist/provider-icons/openai.svg +1 -0
  42. package/gui/dist/provider-icons/opencode.svg +2 -0
  43. package/gui/dist/provider-icons/openrouter-color.svg +1 -0
  44. package/gui/dist/provider-icons/pi.svg +21 -0
  45. package/gui/dist/provider-icons/qianfan-color.svg +1 -0
  46. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -0
  47. package/gui/dist/provider-icons/telegram.svg +1 -0
  48. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -0
  49. package/gui/dist/provider-icons/vllm-color.svg +1 -0
  50. package/gui/dist/provider-icons/xiaomi-color.svg +1 -0
  51. package/package.json +108 -0
  52. package/src/AGENTS.md +28 -0
  53. package/src/adapters/anthropic-image-guard.ts +251 -0
  54. package/src/adapters/anthropic-image-normalize.ts +518 -0
  55. package/src/adapters/anthropic-output-schema.ts +137 -0
  56. package/src/adapters/anthropic.ts +1327 -0
  57. package/src/adapters/azure.ts +36 -0
  58. package/src/adapters/base.ts +121 -0
  59. package/src/adapters/client-fingerprint.ts +65 -0
  60. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  61. package/src/adapters/command-code.ts +601 -0
  62. package/src/adapters/cursor/arg-codec.ts +38 -0
  63. package/src/adapters/cursor/arg-normalize.ts +104 -0
  64. package/src/adapters/cursor/checkpoint-store.ts +303 -0
  65. package/src/adapters/cursor/cursor-errors.ts +288 -0
  66. package/src/adapters/cursor/discovery.ts +333 -0
  67. package/src/adapters/cursor/effort-map.ts +151 -0
  68. package/src/adapters/cursor/exec-policy.ts +88 -0
  69. package/src/adapters/cursor/framing.ts +250 -0
  70. package/src/adapters/cursor/gen/agent_pb.ts +15274 -0
  71. package/src/adapters/cursor/h2-pool.ts +123 -0
  72. package/src/adapters/cursor/http1-bidi.ts +361 -0
  73. package/src/adapters/cursor/images.ts +704 -0
  74. package/src/adapters/cursor/kv-store.ts +52 -0
  75. package/src/adapters/cursor/live-models.ts +269 -0
  76. package/src/adapters/cursor/live-smoke-gate.ts +41 -0
  77. package/src/adapters/cursor/live-transport.ts +1653 -0
  78. package/src/adapters/cursor/mcp-config.ts +42 -0
  79. package/src/adapters/cursor/mcp-manager.ts +333 -0
  80. package/src/adapters/cursor/message-mapper.ts +49 -0
  81. package/src/adapters/cursor/native-exec-common.ts +76 -0
  82. package/src/adapters/cursor/native-exec-desktop.ts +184 -0
  83. package/src/adapters/cursor/native-exec-fs.ts +332 -0
  84. package/src/adapters/cursor/native-exec-mcp.ts +153 -0
  85. package/src/adapters/cursor/native-exec-network.ts +43 -0
  86. package/src/adapters/cursor/native-exec-shell.ts +547 -0
  87. package/src/adapters/cursor/native-exec-tools.ts +118 -0
  88. package/src/adapters/cursor/native-exec.ts +663 -0
  89. package/src/adapters/cursor/protobuf-events.ts +1381 -0
  90. package/src/adapters/cursor/protobuf-request.ts +1032 -0
  91. package/src/adapters/cursor/request-builder.ts +461 -0
  92. package/src/adapters/cursor/thread-continuity.ts +67 -0
  93. package/src/adapters/cursor/tool-definitions.ts +735 -0
  94. package/src/adapters/cursor/tool-result-normalize.ts +92 -0
  95. package/src/adapters/cursor/transport-retry.ts +132 -0
  96. package/src/adapters/cursor/transport.ts +79 -0
  97. package/src/adapters/cursor/types.ts +79 -0
  98. package/src/adapters/cursor.ts +322 -0
  99. package/src/adapters/google-antigravity-hosts.ts +48 -0
  100. package/src/adapters/google-antigravity-replay.ts +827 -0
  101. package/src/adapters/google-antigravity-tools.ts +105 -0
  102. package/src/adapters/google-antigravity-wire.ts +141 -0
  103. package/src/adapters/google-errors.ts +92 -0
  104. package/src/adapters/google-http.ts +460 -0
  105. package/src/adapters/google-tool-schema.ts +238 -0
  106. package/src/adapters/google-truncation.ts +24 -0
  107. package/src/adapters/google-wire-compiler.ts +232 -0
  108. package/src/adapters/google.ts +1377 -0
  109. package/src/adapters/identity.ts +77 -0
  110. package/src/adapters/image.ts +23 -0
  111. package/src/adapters/kiro-constants.ts +16 -0
  112. package/src/adapters/kiro-errors.ts +208 -0
  113. package/src/adapters/kiro-events.ts +197 -0
  114. package/src/adapters/kiro-images.ts +129 -0
  115. package/src/adapters/kiro-retry.ts +312 -0
  116. package/src/adapters/kiro-thinking.ts +112 -0
  117. package/src/adapters/kiro-tool-fallback.ts +36 -0
  118. package/src/adapters/kiro-tools.ts +224 -0
  119. package/src/adapters/kiro-truncation.ts +33 -0
  120. package/src/adapters/kiro-wire.ts +129 -0
  121. package/src/adapters/kiro.ts +1936 -0
  122. package/src/adapters/mimo-free.ts +280 -0
  123. package/src/adapters/openai-chat-url.ts +11 -0
  124. package/src/adapters/openai-chat.ts +1980 -0
  125. package/src/adapters/openai-responses-url.ts +16 -0
  126. package/src/adapters/openai-responses.ts +1911 -0
  127. package/src/adapters/registry.ts +175 -0
  128. package/src/adapters/responses-tool-schema.ts +67 -0
  129. package/src/adapters/run-turn-queue.ts +114 -0
  130. package/src/adapters/tool-call-id.ts +119 -0
  131. package/src/adapters/tool-catalog-nudge.ts +154 -0
  132. package/src/adapters/upstream-http-error.ts +48 -0
  133. package/src/adapters/xai-web-search.ts +185 -0
  134. package/src/bridge.ts +1986 -0
  135. package/src/chat/inbound.ts +319 -0
  136. package/src/chat/outbound.ts +821 -0
  137. package/src/claude/agents-inject.ts +266 -0
  138. package/src/claude/alias.ts +149 -0
  139. package/src/claude/auth-detect.ts +229 -0
  140. package/src/claude/auth-mode-migration.ts +32 -0
  141. package/src/claude/auth-mode.ts +62 -0
  142. package/src/claude/context-windows.ts +205 -0
  143. package/src/claude/desktop-3p-guard.ts +35 -0
  144. package/src/claude/desktop-3p-paths.ts +84 -0
  145. package/src/claude/desktop-3p.ts +615 -0
  146. package/src/claude/desktop-health.ts +26 -0
  147. package/src/claude/desktop-profile.ts +263 -0
  148. package/src/claude/gateway-cache.ts +107 -0
  149. package/src/claude/inbound-debug.ts +163 -0
  150. package/src/claude/inbound.ts +578 -0
  151. package/src/claude/model-info.ts +174 -0
  152. package/src/claude/outbound.ts +926 -0
  153. package/src/cli/access.ts +108 -0
  154. package/src/cli/account-api.ts +302 -0
  155. package/src/cli/account-auth.ts +250 -0
  156. package/src/cli/account-catalog-refresh.ts +14 -0
  157. package/src/cli/account-extended.ts +737 -0
  158. package/src/cli/account-main.ts +317 -0
  159. package/src/cli/account.ts +299 -0
  160. package/src/cli/agent-driven.ts +70 -0
  161. package/src/cli/agent.ts +290 -0
  162. package/src/cli/catalog-prewarm.ts +27 -0
  163. package/src/cli/claude-agent-startup-sync.ts +73 -0
  164. package/src/cli/claude-desktop.ts +213 -0
  165. package/src/cli/claude.ts +355 -0
  166. package/src/cli/codex-log-guard-doctor.ts +103 -0
  167. package/src/cli/codex-shim-autorestore.ts +47 -0
  168. package/src/cli/codex-shim-readiness.ts +76 -0
  169. package/src/cli/combo.ts +127 -0
  170. package/src/cli/config-command.ts +209 -0
  171. package/src/cli/debug.ts +228 -0
  172. package/src/cli/dispatch.ts +585 -0
  173. package/src/cli/doctor.ts +1202 -0
  174. package/src/cli/ensure-desired-integrations.ts +152 -0
  175. package/src/cli/export-command.ts +213 -0
  176. package/src/cli/help.ts +101 -0
  177. package/src/cli/index.ts +973 -0
  178. package/src/cli/init.ts +211 -0
  179. package/src/cli/integrations.ts +260 -0
  180. package/src/cli/interactive-confirm.ts +133 -0
  181. package/src/cli/lab.ts +607 -0
  182. package/src/cli/launcher-context.ts +77 -0
  183. package/src/cli/minimax.ts +497 -0
  184. package/src/cli/models-runtime.ts +245 -0
  185. package/src/cli/models.ts +422 -0
  186. package/src/cli/observe.ts +206 -0
  187. package/src/cli/opencode.ts +588 -0
  188. package/src/cli/provider-replit.ts +232 -0
  189. package/src/cli/provider-runtime.ts +179 -0
  190. package/src/cli/provider.ts +492 -0
  191. package/src/cli/ready.ts +301 -0
  192. package/src/cli/registry.ts +422 -0
  193. package/src/cli/replit-gateway-key-input.ts +138 -0
  194. package/src/cli/root.ts +86 -0
  195. package/src/cli/route-policy.ts +92 -0
  196. package/src/cli/runtime-api.ts +328 -0
  197. package/src/cli/star-prompt.ts +211 -0
  198. package/src/cli/status-oauth.ts +78 -0
  199. package/src/cli/status.ts +328 -0
  200. package/src/cli/system-command.ts +112 -0
  201. package/src/cli/system-restart-client.ts +146 -0
  202. package/src/cli/tray-proxy.ts +199 -0
  203. package/src/cli/v2.ts +268 -0
  204. package/src/cli.ts +10 -0
  205. package/src/clients/config-export.ts +1704 -0
  206. package/src/codex/account-id.ts +34 -0
  207. package/src/codex/account-label.ts +47 -0
  208. package/src/codex/account-lifecycle.ts +172 -0
  209. package/src/codex/account-namespace-match.ts +63 -0
  210. package/src/codex/account-namespaces.ts +195 -0
  211. package/src/codex/account-pause.ts +20 -0
  212. package/src/codex/account-priority.ts +83 -0
  213. package/src/codex/account-runtime-state.ts +31 -0
  214. package/src/codex/account-store.ts +544 -0
  215. package/src/codex/account-usability.ts +43 -0
  216. package/src/codex/admission.ts +256 -0
  217. package/src/codex/affinity-debug.ts +162 -0
  218. package/src/codex/agent-roles-sync.ts +225 -0
  219. package/src/codex/agent-roles.ts +238 -0
  220. package/src/codex/app-server-processes.ts +1143 -0
  221. package/src/codex/app-server-restart-service.ts +232 -0
  222. package/src/codex/auth-api.ts +2147 -0
  223. package/src/codex/auth-collision.ts +109 -0
  224. package/src/codex/auth-context.ts +665 -0
  225. package/src/codex/autostart-health.ts +156 -0
  226. package/src/codex/catalog/account-models.ts +67 -0
  227. package/src/codex/catalog/aggregation.ts +436 -0
  228. package/src/codex/catalog/bundled.ts +549 -0
  229. package/src/codex/catalog/effort.ts +446 -0
  230. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  231. package/src/codex/catalog/kinds.ts +2 -0
  232. package/src/codex/catalog/metadata.ts +664 -0
  233. package/src/codex/catalog/native-models.ts +72 -0
  234. package/src/codex/catalog/parsing.ts +650 -0
  235. package/src/codex/catalog/provider-fetch.ts +2064 -0
  236. package/src/codex/catalog/sync.ts +1883 -0
  237. package/src/codex/catalog-admission.ts +199 -0
  238. package/src/codex/catalog-refresh-status.ts +105 -0
  239. package/src/codex/catalog-write-serialization.ts +242 -0
  240. package/src/codex/catalog.ts +14 -0
  241. package/src/codex/codex-write-lock.ts +384 -0
  242. package/src/codex/convergence-types.ts +614 -0
  243. package/src/codex/convergence.ts +651 -0
  244. package/src/codex/coordinator-doctor.ts +332 -0
  245. package/src/codex/custom-model-catalog-migration.ts +176 -0
  246. package/src/codex/data/upstream-models.json +830 -0
  247. package/src/codex/desired-state.ts +230 -0
  248. package/src/codex/exec-invocation.ts +22 -0
  249. package/src/codex/features.ts +1566 -0
  250. package/src/codex/generation.ts +202 -0
  251. package/src/codex/history-job.ts +407 -0
  252. package/src/codex/history-lock.ts +242 -0
  253. package/src/codex/history-migration-guardian.ts +108 -0
  254. package/src/codex/history-provider.ts +979 -0
  255. package/src/codex/history-transition.ts +105 -0
  256. package/src/codex/history-worker.ts +220 -0
  257. package/src/codex/home.ts +206 -0
  258. package/src/codex/inject-coordination.ts +290 -0
  259. package/src/codex/inject.ts +1733 -0
  260. package/src/codex/injected-marker.ts +106 -0
  261. package/src/codex/integration-record.ts +266 -0
  262. package/src/codex/internal/catalog-writer.ts +203 -0
  263. package/src/codex/internal/history-writer.ts +80 -0
  264. package/src/codex/journal.ts +225 -0
  265. package/src/codex/log-guard/inspect.ts +506 -0
  266. package/src/codex/log-guard/lock.ts +150 -0
  267. package/src/codex/log-guard/maintenance.ts +403 -0
  268. package/src/codex/log-guard/path-safety.ts +88 -0
  269. package/src/codex/log-guard/policy.ts +44 -0
  270. package/src/codex/log-guard/processes.ts +205 -0
  271. package/src/codex/log-guard/protection.ts +489 -0
  272. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  273. package/src/codex/main-account-cache.ts +56 -0
  274. package/src/codex/main-account.ts +68 -0
  275. package/src/codex/management-convergence.ts +167 -0
  276. package/src/codex/model-cache.ts +273 -0
  277. package/src/codex/model-entitlements.ts +353 -0
  278. package/src/codex/native-main-admission.ts +47 -0
  279. package/src/codex/native-main-auth-temp.ts +187 -0
  280. package/src/codex/native-main-claim.ts +178 -0
  281. package/src/codex/native-main-lock-file.ts +162 -0
  282. package/src/codex/native-main-owner.ts +329 -0
  283. package/src/codex/native-profile-api.ts +247 -0
  284. package/src/codex/native-profile-manager.ts +1531 -0
  285. package/src/codex/native-profile-processes.ts +121 -0
  286. package/src/codex/native-profile-recovery.ts +99 -0
  287. package/src/codex/native-profile-stage-store.ts +387 -0
  288. package/src/codex/native-profile-startup.ts +492 -0
  289. package/src/codex/native-profile-store.ts +855 -0
  290. package/src/codex/native-profile-types.ts +120 -0
  291. package/src/codex/native-residue.ts +682 -0
  292. package/src/codex/paths.ts +144 -0
  293. package/src/codex/plan-from-token.ts +140 -0
  294. package/src/codex/plan.ts +40 -0
  295. package/src/codex/plugins-doctor.ts +242 -0
  296. package/src/codex/pool-rotation.ts +295 -0
  297. package/src/codex/project-config-warnings.ts +425 -0
  298. package/src/codex/prompt-journal.ts +352 -0
  299. package/src/codex/prompt-layers.ts +967 -0
  300. package/src/codex/prompt-lock.ts +143 -0
  301. package/src/codex/quota-rejection.ts +298 -0
  302. package/src/codex/quota.ts +573 -0
  303. package/src/codex/refresh.ts +62 -0
  304. package/src/codex/reset-credit-recovery.ts +1044 -0
  305. package/src/codex/routing.ts +1888 -0
  306. package/src/codex/runtime.ts +659 -0
  307. package/src/codex/shim.ts +2170 -0
  308. package/src/codex/subagent-defaults.ts +550 -0
  309. package/src/codex/subagent-model-fallback.ts +784 -0
  310. package/src/codex/sync.ts +319 -0
  311. package/src/codex/transition-state.ts +612 -0
  312. package/src/codex/upstream-host-health.ts +368 -0
  313. package/src/codex/user-identity.ts +557 -0
  314. package/src/codex/warmup.ts +298 -0
  315. package/src/codex/websocket-registry.ts +100 -0
  316. package/src/codex/write-coordination.ts +114 -0
  317. package/src/combos/failover.ts +160 -0
  318. package/src/combos/index.ts +45 -0
  319. package/src/combos/request.ts +94 -0
  320. package/src/combos/resolve.ts +232 -0
  321. package/src/combos/types.ts +398 -0
  322. package/src/config/provider-name.ts +24 -0
  323. package/src/config.ts +4041 -0
  324. package/src/fork/register.ts +3 -0
  325. package/src/generated/compatibility-version.json +3116 -0
  326. package/src/generated/model-metadata.ts +106 -0
  327. package/src/github/star-state.ts +203 -0
  328. package/src/grok/inject.ts +530 -0
  329. package/src/grok/inspect.ts +45 -0
  330. package/src/grok/status.ts +121 -0
  331. package/src/grok/sync.ts +66 -0
  332. package/src/images/artifacts.ts +516 -0
  333. package/src/images/fulfill-video.ts +163 -0
  334. package/src/images/fulfill.ts +149 -0
  335. package/src/images/index.ts +4 -0
  336. package/src/images/loop.ts +955 -0
  337. package/src/images/plan.ts +143 -0
  338. package/src/images/synthetic-tool.ts +133 -0
  339. package/src/images/types.ts +41 -0
  340. package/src/images/xai-client.ts +141 -0
  341. package/src/images/xai-video-client.ts +163 -0
  342. package/src/index.ts +22 -0
  343. package/src/integrations/config-io.ts +269 -0
  344. package/src/integrations/journal.ts +315 -0
  345. package/src/integrations/merge.ts +135 -0
  346. package/src/integrations/mutation-flight.ts +71 -0
  347. package/src/integrations/native/ownership-preflight.ts +202 -0
  348. package/src/integrations/omp-yaml-source.ts +358 -0
  349. package/src/integrations/owned-refresh.ts +74 -0
  350. package/src/integrations/ownership.ts +111 -0
  351. package/src/integrations/registry.ts +159 -0
  352. package/src/integrations/serialize.ts +314 -0
  353. package/src/integrations/state.ts +361 -0
  354. package/src/integrations/store.ts +103 -0
  355. package/src/integrations/writer-lock.ts +98 -0
  356. package/src/integrations/writer.ts +691 -0
  357. package/src/lab/artifacts/sanitize.ts +586 -0
  358. package/src/lab/artifacts/secure-fs.ts +475 -0
  359. package/src/lab/artifacts/store.ts +310 -0
  360. package/src/lab/automation/budgets.ts +78 -0
  361. package/src/lab/automation/config-persistence.ts +256 -0
  362. package/src/lab/automation/constants.ts +39 -0
  363. package/src/lab/automation/cooldown.ts +103 -0
  364. package/src/lab/automation/dispatch.ts +211 -0
  365. package/src/lab/automation/index.ts +13 -0
  366. package/src/lab/automation/orchestrator.ts +499 -0
  367. package/src/lab/automation/persistence.ts +512 -0
  368. package/src/lab/automation/planner.ts +371 -0
  369. package/src/lab/automation/policy.ts +136 -0
  370. package/src/lab/automation/queue.ts +191 -0
  371. package/src/lab/automation/recovery.ts +24 -0
  372. package/src/lab/automation/route-context.ts +21 -0
  373. package/src/lab/automation/run-key.ts +44 -0
  374. package/src/lab/automation/runs-query.ts +34 -0
  375. package/src/lab/automation/types.ts +160 -0
  376. package/src/lab/conformance/assertion.ts +325 -0
  377. package/src/lab/conformance/digest.ts +22 -0
  378. package/src/lab/conformance/executor.ts +741 -0
  379. package/src/lab/conformance/fixture-provider.ts +27 -0
  380. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  381. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  382. package/src/lab/conformance/harness-budget.ts +47 -0
  383. package/src/lab/conformance/index.ts +5 -0
  384. package/src/lab/conformance/jcs.ts +64 -0
  385. package/src/lab/conformance/json-pointer.ts +39 -0
  386. package/src/lab/conformance/manifest.ts +180 -0
  387. package/src/lab/conformance/mcp-stub.ts +179 -0
  388. package/src/lab/conformance/negative-controls.ts +164 -0
  389. package/src/lab/conformance/observation.ts +355 -0
  390. package/src/lab/conformance/runner.ts +68 -0
  391. package/src/lab/conformance/sse-normalize.ts +59 -0
  392. package/src/lab/conformance/suite-manifest.ts +78 -0
  393. package/src/lab/conformance/types.ts +214 -0
  394. package/src/lab/constants.ts +126 -0
  395. package/src/lab/digest.ts +64 -0
  396. package/src/lab/events/errors.ts +9 -0
  397. package/src/lab/events/limits.ts +117 -0
  398. package/src/lab/events/types.ts +229 -0
  399. package/src/lab/events/validate.ts +781 -0
  400. package/src/lab/fabric/constants.ts +40 -0
  401. package/src/lab/fabric/executor.ts +492 -0
  402. package/src/lab/fabric/index.ts +80 -0
  403. package/src/lab/fabric/manifest.ts +222 -0
  404. package/src/lab/fabric/observe.ts +489 -0
  405. package/src/lab/fabric/patch.ts +79 -0
  406. package/src/lab/fabric/producer-child.ts +139 -0
  407. package/src/lab/fabric/producer-isolate.ts +276 -0
  408. package/src/lab/fabric/producer-protocol.ts +61 -0
  409. package/src/lab/fabric/scratch.ts +439 -0
  410. package/src/lab/fabric/subject.ts +106 -0
  411. package/src/lab/fabric/types.ts +134 -0
  412. package/src/lab/fabric/verifier.ts +98 -0
  413. package/src/lab/index.ts +54 -0
  414. package/src/lab/ledger/artifact-refs.ts +127 -0
  415. package/src/lab/ledger/invalidation.ts +136 -0
  416. package/src/lab/ledger/purge.ts +310 -0
  417. package/src/lab/ledger/store.ts +532 -0
  418. package/src/lab/live/credential-lease.ts +53 -0
  419. package/src/lab/live/destination.ts +155 -0
  420. package/src/lab/live/executor.ts +336 -0
  421. package/src/lab/live/inert-tools.ts +56 -0
  422. package/src/lab/live/manifest.ts +85 -0
  423. package/src/lab/live/mcp-loopback.ts +57 -0
  424. package/src/lab/live/runner.ts +19 -0
  425. package/src/lab/live/sandbox.ts +61 -0
  426. package/src/lab/live/suite-manifest.ts +41 -0
  427. package/src/lab/live/transport.ts +118 -0
  428. package/src/lab/live/types.ts +197 -0
  429. package/src/lab/observe/from-conformance.ts +301 -0
  430. package/src/lab/observe/from-live.ts +117 -0
  431. package/src/lab/paths.ts +153 -0
  432. package/src/lab/projection/rebuild.ts +495 -0
  433. package/src/lab/projection/schema.ts +135 -0
  434. package/src/lab/projection/verdicts.ts +474 -0
  435. package/src/lab/projection/verification.ts +412 -0
  436. package/src/lab/public/bundle.ts +217 -0
  437. package/src/lab/public/community-authority.ts +175 -0
  438. package/src/lab/public/community-files.ts +29 -0
  439. package/src/lab/public/community.ts +479 -0
  440. package/src/lab/public/file-safety.ts +155 -0
  441. package/src/lab/public/ids.ts +26 -0
  442. package/src/lab/public/index.ts +16 -0
  443. package/src/lab/public/mutation-lock.ts +424 -0
  444. package/src/lab/public/operator.ts +353 -0
  445. package/src/lab/public/origin-purge.ts +79 -0
  446. package/src/lab/public/origin.ts +203 -0
  447. package/src/lab/public/privacy.ts +143 -0
  448. package/src/lab/public/private-file.ts +261 -0
  449. package/src/lab/public/project.ts +124 -0
  450. package/src/lab/public/purge-test-fault.ts +21 -0
  451. package/src/lab/public/purge.ts +223 -0
  452. package/src/lab/public/registry.ts +44 -0
  453. package/src/lab/public/revocation.ts +252 -0
  454. package/src/lab/public/signature.ts +243 -0
  455. package/src/lab/public/storage.ts +105 -0
  456. package/src/lab/public/strict-json.ts +206 -0
  457. package/src/lab/public/time.ts +26 -0
  458. package/src/lab/public/types.ts +172 -0
  459. package/src/lab/public/validate.ts +391 -0
  460. package/src/lab/query/catalog.ts +101 -0
  461. package/src/lab/query/connection.ts +107 -0
  462. package/src/lab/query/constants.ts +4 -0
  463. package/src/lab/query/cursor.ts +132 -0
  464. package/src/lab/query/dto-map.ts +277 -0
  465. package/src/lab/query/errors.ts +22 -0
  466. package/src/lab/query/freshness.ts +53 -0
  467. package/src/lab/query/index.ts +45 -0
  468. package/src/lab/query/latest-observation.ts +59 -0
  469. package/src/lab/query/passive-production.ts +159 -0
  470. package/src/lab/query/queries.ts +444 -0
  471. package/src/lab/query/types.ts +266 -0
  472. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  473. package/src/lab/subject/installation-salt.ts +112 -0
  474. package/src/lab/subject/protocol-subject.ts +80 -0
  475. package/src/lab/subject/route-subject.ts +74 -0
  476. package/src/lib/abort.ts +146 -0
  477. package/src/lib/admin-secrets.ts +25 -0
  478. package/src/lib/admission.ts +83 -0
  479. package/src/lib/app-owned-memory-stores.ts +195 -0
  480. package/src/lib/app-owned-memory.ts +265 -0
  481. package/src/lib/bounded-body.ts +346 -0
  482. package/src/lib/bun-binary-validator.d.mts +3 -0
  483. package/src/lib/bun-binary-validator.mjs +18 -0
  484. package/src/lib/bun-runtime.ts +184 -0
  485. package/src/lib/bun-stream-caps.ts +130 -0
  486. package/src/lib/codex-restart-contract.ts +120 -0
  487. package/src/lib/config-ownership.ts +364 -0
  488. package/src/lib/crash-guard.ts +344 -0
  489. package/src/lib/debug-log-buffer.ts +83 -0
  490. package/src/lib/debug-settings.ts +108 -0
  491. package/src/lib/debug.ts +31 -0
  492. package/src/lib/destination-policy.ts +380 -0
  493. package/src/lib/errors.ts +406 -0
  494. package/src/lib/eventstream-decoder.ts +253 -0
  495. package/src/lib/fabric-task-execution-authority.ts +7 -0
  496. package/src/lib/fabric-task-host.ts +29 -0
  497. package/src/lib/gcp-adc.ts +341 -0
  498. package/src/lib/injection-debug-log.ts +58 -0
  499. package/src/lib/lab-activation.ts +223 -0
  500. package/src/lib/lab-live-execution-authority.ts +13 -0
  501. package/src/lib/lab-live-host.ts +30 -0
  502. package/src/lib/lab-live-pinned-sender.ts +56 -0
  503. package/src/lib/lab-live-route-production.ts +130 -0
  504. package/src/lib/lab-passive-linker-registration.ts +26 -0
  505. package/src/lib/local-management-attestation.ts +51 -0
  506. package/src/lib/local-management-capability.ts +100 -0
  507. package/src/lib/local-provider-reload-contract.ts +100 -0
  508. package/src/lib/open-url.ts +25 -0
  509. package/src/lib/optional-shutdown-hooks.ts +57 -0
  510. package/src/lib/pinned-http.ts +270 -0
  511. package/src/lib/privacy.ts +20 -0
  512. package/src/lib/process-control.ts +168 -0
  513. package/src/lib/provider-outbound.ts +210 -0
  514. package/src/lib/provider-url.ts +14 -0
  515. package/src/lib/proxy-env.ts +18 -0
  516. package/src/lib/redact.ts +521 -0
  517. package/src/lib/retry-after.ts +55 -0
  518. package/src/lib/self-launch-argv.ts +15 -0
  519. package/src/lib/server-resource-ownership.ts +71 -0
  520. package/src/lib/service-secrets.ts +25 -0
  521. package/src/lib/shadow-call.ts +61 -0
  522. package/src/lib/sidecar-tracker.ts +52 -0
  523. package/src/lib/sse-decoder.ts +364 -0
  524. package/src/lib/state-store-registrations.ts +119 -0
  525. package/src/lib/state-store-sweeper.ts +184 -0
  526. package/src/lib/system-restart-contract.ts +73 -0
  527. package/src/lib/test-home-guard.ts +90 -0
  528. package/src/lib/token-estimate.ts +86 -0
  529. package/src/lib/tool-argument-integers.ts +202 -0
  530. package/src/lib/translator-budget.ts +400 -0
  531. package/src/lib/upstream-http-version.ts +57 -0
  532. package/src/lib/upstream-reachability.ts +95 -0
  533. package/src/lib/upstream-retry.ts +392 -0
  534. package/src/lib/win-exec.ts +115 -0
  535. package/src/lib/win-paths.ts +68 -0
  536. package/src/lib/windows-atomic-replace.ts +156 -0
  537. package/src/lib/windows-elevation.ts +773 -0
  538. package/src/lib/windows-secret-acl.ts +854 -0
  539. package/src/lib/windows-service-wrappers.ts +72 -0
  540. package/src/lib/windows-text.ts +106 -0
  541. package/src/lib/windows-user-principal.ts +341 -0
  542. package/src/lib/winsw.ts +403 -0
  543. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  544. package/src/oauth/account-import/index.ts +15 -0
  545. package/src/oauth/account-import/parser.ts +83 -0
  546. package/src/oauth/account-import/registry.ts +18 -0
  547. package/src/oauth/account-import/service.ts +75 -0
  548. package/src/oauth/account-import/types.ts +91 -0
  549. package/src/oauth/anthropic-routing.ts +594 -0
  550. package/src/oauth/anthropic.ts +188 -0
  551. package/src/oauth/antigravity-routing.ts +151 -0
  552. package/src/oauth/callback-server.ts +300 -0
  553. package/src/oauth/chatgpt.ts +161 -0
  554. package/src/oauth/command-code.ts +239 -0
  555. package/src/oauth/cursor.ts +252 -0
  556. package/src/oauth/github-copilot.ts +428 -0
  557. package/src/oauth/google-antigravity.ts +262 -0
  558. package/src/oauth/health.ts +407 -0
  559. package/src/oauth/index.ts +1504 -0
  560. package/src/oauth/key-providers.ts +124 -0
  561. package/src/oauth/kimi.ts +227 -0
  562. package/src/oauth/kiro-credentials.ts +726 -0
  563. package/src/oauth/kiro.ts +621 -0
  564. package/src/oauth/local-token-detect.ts +130 -0
  565. package/src/oauth/log.ts +50 -0
  566. package/src/oauth/login-cli.ts +223 -0
  567. package/src/oauth/nous.ts +798 -0
  568. package/src/oauth/pkce.ts +15 -0
  569. package/src/oauth/store.ts +728 -0
  570. package/src/oauth/token-guardian.ts +309 -0
  571. package/src/oauth/types.ts +62 -0
  572. package/src/oauth/xai.ts +241 -0
  573. package/src/providers/alibaba-region-backup.ts +75 -0
  574. package/src/providers/alibaba-region-migration.ts +156 -0
  575. package/src/providers/alibaba-region-startup.ts +36 -0
  576. package/src/providers/antigravity-models.ts +695 -0
  577. package/src/providers/antigravity-quota.ts +216 -0
  578. package/src/providers/api-keys.ts +140 -0
  579. package/src/providers/base-url-choices.ts +74 -0
  580. package/src/providers/codex-capacity.ts +292 -0
  581. package/src/providers/command-code-efforts.ts +144 -0
  582. package/src/providers/context-cap.ts +82 -0
  583. package/src/providers/cursor-pool.ts +72 -0
  584. package/src/providers/derive.ts +586 -0
  585. package/src/providers/fastwire.ts +501 -0
  586. package/src/providers/free-directory.ts +187 -0
  587. package/src/providers/github-copilot-transport.ts +56 -0
  588. package/src/providers/google-vertex-location.ts +14 -0
  589. package/src/providers/key-failover.ts +271 -0
  590. package/src/providers/kiro-models.ts +67 -0
  591. package/src/providers/label.ts +19 -0
  592. package/src/providers/model-discovery-limits.ts +16 -0
  593. package/src/providers/model-discovery.ts +449 -0
  594. package/src/providers/model-rename-migration.ts +255 -0
  595. package/src/providers/model-rename-startup.ts +28 -0
  596. package/src/providers/openai-sidecar.ts +243 -0
  597. package/src/providers/openai-tier-startup.ts +56 -0
  598. package/src/providers/openai-tiers.ts +423 -0
  599. package/src/providers/openai-virtual-models.ts +83 -0
  600. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  601. package/src/providers/openrouter-routing.ts +102 -0
  602. package/src/providers/provider-id-rewrite.ts +185 -0
  603. package/src/providers/quota.ts +2345 -0
  604. package/src/providers/registry.ts +2918 -0
  605. package/src/providers/replit/constants.ts +27 -0
  606. package/src/providers/replit/derive.ts +85 -0
  607. package/src/providers/replit/headers.ts +28 -0
  608. package/src/providers/replit/origin.ts +55 -0
  609. package/src/providers/replit/pair-install-response.ts +72 -0
  610. package/src/providers/replit/probe.ts +199 -0
  611. package/src/providers/replit/setup.ts +350 -0
  612. package/src/providers/request-pacing.ts +310 -0
  613. package/src/providers/service-tier.ts +277 -0
  614. package/src/providers/slug-codec.ts +103 -0
  615. package/src/providers/static-model-discovery.ts +86 -0
  616. package/src/providers/xai-responses-opt-in.ts +15 -0
  617. package/src/providers/xai-transport.ts +148 -0
  618. package/src/reasoning-effort.ts +183 -0
  619. package/src/responses/compaction.ts +142 -0
  620. package/src/responses/custom-tool-compat.ts +266 -0
  621. package/src/responses/hosted-tool-policy.ts +9 -0
  622. package/src/responses/namespace-tool-compat.ts +355 -0
  623. package/src/responses/parser.ts +838 -0
  624. package/src/responses/provider-continuation.ts +98 -0
  625. package/src/responses/provider-opaque-metadata.ts +73 -0
  626. package/src/responses/reasoning-envelope.ts +60 -0
  627. package/src/responses/reasoning-replay-cache.ts +426 -0
  628. package/src/responses/schema.ts +165 -0
  629. package/src/responses/spill-store.ts +459 -0
  630. package/src/responses/state.ts +1433 -0
  631. package/src/responses/thought-signature-replay.ts +347 -0
  632. package/src/responses/tool-groups.ts +19 -0
  633. package/src/responses/tool-search-compat.ts +301 -0
  634. package/src/responses/truncated-stop-reason.ts +60 -0
  635. package/src/router.ts +761 -0
  636. package/src/routing/analytics.ts +378 -0
  637. package/src/routing/capability.ts +244 -0
  638. package/src/routing/compatibility/assemble.ts +73 -0
  639. package/src/routing/compatibility/behavior.ts +278 -0
  640. package/src/routing/compatibility/catalog.ts +99 -0
  641. package/src/routing/compatibility/endpoint.ts +52 -0
  642. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  643. package/src/routing/compatibility/policy.ts +181 -0
  644. package/src/routing/compatibility/provider-slot.ts +56 -0
  645. package/src/routing/compatibility/reader.ts +110 -0
  646. package/src/routing/compatibility/subject.ts +191 -0
  647. package/src/routing/compatibility/types.ts +64 -0
  648. package/src/routing/compatibility/version.ts +104 -0
  649. package/src/routing/cost.ts +77 -0
  650. package/src/routing/evaluator.ts +495 -0
  651. package/src/routing/health.ts +412 -0
  652. package/src/routing/history/cursor.ts +43 -0
  653. package/src/routing/history/indexer.ts +605 -0
  654. package/src/routing/history/schema.ts +72 -0
  655. package/src/routing/profile-namespace.ts +15 -0
  656. package/src/routing/profile.ts +547 -0
  657. package/src/routing/quota.ts +145 -0
  658. package/src/routing/request-evidence.ts +45 -0
  659. package/src/routing/trace.ts +776 -0
  660. package/src/server/adapter-resolve.ts +53 -0
  661. package/src/server/auth-cors.ts +751 -0
  662. package/src/server/background-lifecycle.ts +182 -0
  663. package/src/server/chat-completions.ts +442 -0
  664. package/src/server/chat-native-sse.ts +331 -0
  665. package/src/server/chat-native.ts +426 -0
  666. package/src/server/claude-messages.ts +1030 -0
  667. package/src/server/direct-local-http.ts +347 -0
  668. package/src/server/effort-policy.ts +190 -0
  669. package/src/server/github-copilot-responses-repair.ts +338 -0
  670. package/src/server/gui-static.ts +152 -0
  671. package/src/server/image-retry.ts +42 -0
  672. package/src/server/images.ts +568 -0
  673. package/src/server/index.ts +1813 -0
  674. package/src/server/lifecycle.ts +498 -0
  675. package/src/server/live.ts +717 -0
  676. package/src/server/local-management-read-client.ts +90 -0
  677. package/src/server/local-provider-reload-client.ts +137 -0
  678. package/src/server/management/agent-settings-routes.ts +1433 -0
  679. package/src/server/management/api-access.ts +141 -0
  680. package/src/server/management/api-key-usage.ts +193 -0
  681. package/src/server/management/body.ts +41 -0
  682. package/src/server/management/combo-routes.ts +263 -0
  683. package/src/server/management/config-routes.ts +835 -0
  684. package/src/server/management/context.ts +113 -0
  685. package/src/server/management/integration-routes.ts +498 -0
  686. package/src/server/management/lab-automation-routes.ts +206 -0
  687. package/src/server/management/lab-routes.ts +563 -0
  688. package/src/server/management/logs-usage-routes.ts +586 -0
  689. package/src/server/management/model-routes.ts +560 -0
  690. package/src/server/management/model-rows.ts +163 -0
  691. package/src/server/management/native-integration-routes.ts +769 -0
  692. package/src/server/management/oauth-account-routes.ts +637 -0
  693. package/src/server/management/provider-capability-config.ts +48 -0
  694. package/src/server/management/provider-routes.ts +1033 -0
  695. package/src/server/management/replit-provider-routes.ts +86 -0
  696. package/src/server/management/request-history-routes.ts +191 -0
  697. package/src/server/management/routing-analytics-routes.ts +74 -0
  698. package/src/server/management/routing-profile-routes.ts +385 -0
  699. package/src/server/management/shared.ts +286 -0
  700. package/src/server/management/sidebar-routes.ts +106 -0
  701. package/src/server/management/storage-log-guard-routes.ts +186 -0
  702. package/src/server/management/sync-response.ts +69 -0
  703. package/src/server/management/system-restart.ts +435 -0
  704. package/src/server/management/system-routes.ts +194 -0
  705. package/src/server/management/usage-summary-cache.ts +94 -0
  706. package/src/server/management/vision-sidecar-options.ts +167 -0
  707. package/src/server/management/web-search-sidecar-options.ts +120 -0
  708. package/src/server/management-api.ts +314 -0
  709. package/src/server/management-auth.ts +482 -0
  710. package/src/server/memory-watchdog.ts +156 -0
  711. package/src/server/passive-route-linker.ts +66 -0
  712. package/src/server/port-reclaim.ts +307 -0
  713. package/src/server/ports.ts +156 -0
  714. package/src/server/proxy-liveness.ts +328 -0
  715. package/src/server/readiness.ts +99 -0
  716. package/src/server/relay-eager.ts +353 -0
  717. package/src/server/relay.ts +1209 -0
  718. package/src/server/request-decompress.ts +239 -0
  719. package/src/server/request-log-conversation.ts +168 -0
  720. package/src/server/request-log.ts +1259 -0
  721. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  722. package/src/server/responses/agent-task-recovery.ts +465 -0
  723. package/src/server/responses/collaboration.ts +551 -0
  724. package/src/server/responses/compact.ts +771 -0
  725. package/src/server/responses/core.ts +5389 -0
  726. package/src/server/responses/empty-completion-guard.ts +276 -0
  727. package/src/server/responses/encrypted-payload.ts +331 -0
  728. package/src/server/responses/fetch-helpers.ts +232 -0
  729. package/src/server/responses/input-admission.ts +185 -0
  730. package/src/server/responses/pacing-overload.ts +13 -0
  731. package/src/server/responses/passthrough-error.ts +78 -0
  732. package/src/server/responses/policy-fallback.ts +178 -0
  733. package/src/server/responses/responses-field-backfill.ts +251 -0
  734. package/src/server/responses/terminal-guard.ts +251 -0
  735. package/src/server/responses/upstream-error.ts +53 -0
  736. package/src/server/responses/ws-upstream.ts +308 -0
  737. package/src/server/responses-custom-tool-repair.ts +282 -0
  738. package/src/server/responses-image-gen-repair.ts +132 -0
  739. package/src/server/responses-item-id-repair.ts +272 -0
  740. package/src/server/responses-json-events.ts +90 -0
  741. package/src/server/responses-model-rewrite.ts +29 -0
  742. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  743. package/src/server/responses-snapshot-repair.ts +621 -0
  744. package/src/server/responses-terminal-repair.ts +342 -0
  745. package/src/server/responses-tool-search-repair.ts +267 -0
  746. package/src/server/responses-undeclared-tool-guard.ts +153 -0
  747. package/src/server/responses.ts +25 -0
  748. package/src/server/search.ts +201 -0
  749. package/src/server/sse-frame-buffer.ts +292 -0
  750. package/src/server/sse-payload-rewrite.ts +263 -0
  751. package/src/server/startup-action-control.ts +315 -0
  752. package/src/server/startup-health-cache.ts +131 -0
  753. package/src/server/system-env.ts +484 -0
  754. package/src/server/windows-tcp-drop.ts +184 -0
  755. package/src/server/windows-tray-control.ts +41 -0
  756. package/src/server/ws-bridge.ts +472 -0
  757. package/src/service-manager-probe.ts +892 -0
  758. package/src/service.ts +3575 -0
  759. package/src/sidecar/auth.ts +92 -0
  760. package/src/sidecar/candidates.ts +83 -0
  761. package/src/stall-timeout.ts +20 -0
  762. package/src/storage/cleanup-job.ts +57 -0
  763. package/src/storage/cleanup.ts +3085 -0
  764. package/src/storage/policy-job.ts +457 -0
  765. package/src/storage/policy-scheduler.ts +40 -0
  766. package/src/storage/policy-worker.ts +59 -0
  767. package/src/storage/policy.ts +527 -0
  768. package/src/storage/restore-job.ts +299 -0
  769. package/src/storage/restore-worker.ts +58 -0
  770. package/src/storage/scanner.ts +238 -0
  771. package/src/storage/storage-mutation-coordinator.ts +139 -0
  772. package/src/storage/worker-lifecycle.ts +215 -0
  773. package/src/tray/assets/opencodex-tray-offline.ico +0 -0
  774. package/src/tray/assets/opencodex-tray-online.ico +0 -0
  775. package/src/tray/assets/opencodex-tray-warning.ico +0 -0
  776. package/src/tray/assets/opencodex-tray.png +0 -0
  777. package/src/tray/windows-tray.ps1 +364 -0
  778. package/src/tray/windows.ts +757 -0
  779. package/src/types/accounts.ts +37 -0
  780. package/src/types/config.ts +876 -0
  781. package/src/types/provider.ts +545 -0
  782. package/src/types/request.ts +384 -0
  783. package/src/types/tools.ts +131 -0
  784. package/src/types/wire.ts +80 -0
  785. package/src/types.ts +106 -0
  786. package/src/update/badge.ts +72 -0
  787. package/src/update/index.ts +415 -0
  788. package/src/update/job.ts +1887 -0
  789. package/src/update/notify.ts +263 -0
  790. package/src/update/npm-cache-preflight.d.mts +47 -0
  791. package/src/update/npm-cache-preflight.mjs +201 -0
  792. package/src/update/npm-invocation.d.mts +23 -0
  793. package/src/update/npm-invocation.mjs +94 -0
  794. package/src/update/transactional-install.d.mts +22 -0
  795. package/src/update/transactional-install.mjs +259 -0
  796. package/src/update/tray-update-plan.d.mts +18 -0
  797. package/src/update/tray-update-plan.mjs +38 -0
  798. package/src/usage/cost.ts +625 -0
  799. package/src/usage/debug.ts +97 -0
  800. package/src/usage/expected-prices.ts +416 -0
  801. package/src/usage/log.ts +1223 -0
  802. package/src/usage/summary.ts +753 -0
  803. package/src/usage/totals.ts +14 -0
  804. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  805. package/src/usage/user-cost-overlays.ts +314 -0
  806. package/src/vision/anthropic-describe.ts +189 -0
  807. package/src/vision/backends.ts +97 -0
  808. package/src/vision/describe.ts +131 -0
  809. package/src/vision/eligibility.ts +250 -0
  810. package/src/vision/index.ts +681 -0
  811. package/src/vision/reasoning.ts +55 -0
  812. package/src/vision/routed-describe.ts +175 -0
  813. package/src/vision/timeout-bounds.ts +9 -0
  814. package/src/web-search/anthropic-executor.ts +195 -0
  815. package/src/web-search/backends.ts +108 -0
  816. package/src/web-search/exa-executor.ts +88 -0
  817. package/src/web-search/executor.ts +113 -0
  818. package/src/web-search/format-result.ts +89 -0
  819. package/src/web-search/gemini-executor.ts +141 -0
  820. package/src/web-search/index.ts +331 -0
  821. package/src/web-search/loop.ts +896 -0
  822. package/src/web-search/parse.ts +315 -0
  823. package/src/web-search/progress-stream.ts +342 -0
  824. package/src/web-search/sources.ts +60 -0
  825. package/src/web-search/synthetic-tool.ts +47 -0
  826. package/src/web-search/xai-executor.ts +219 -0
@@ -0,0 +1,423 @@
1
+ import type { CodexAccountMode, OcxConfig, OcxProviderConfig, ProviderCostOverlay } from "../types";
2
+ import { OPENAI_PROVIDER_TIER_VERSION } from "../types";
3
+ import { openaiResponsesUrl } from "../adapters/openai-responses-url";
4
+ import { MAX_COST4_RATE } from "../usage/expected-prices";
5
+
6
+ export const OPENAI_CODEX_PROVIDER_ID = "openai";
7
+ export const LEGACY_OPENAI_MULTI_PROVIDER_ID = "openai-multi";
8
+ export const OPENAI_API_PROVIDER_ID = "openai-apikey";
9
+ export const LEGACY_CHATGPT_PROVIDER_ID = "chatgpt";
10
+
11
+ export const CODEX_FORWARD_BASE_URL = "https://chatgpt.com/backend-api/codex";
12
+ const LEGACY_OPENAI_MULTI_PREFIX = `${LEGACY_OPENAI_MULTI_PROVIDER_ID}/`;
13
+
14
+ function canonicalCodexForwardProvider(mode: CodexAccountMode): OcxProviderConfig {
15
+ return {
16
+ adapter: "openai-responses",
17
+ baseUrl: CODEX_FORWARD_BASE_URL,
18
+ authMode: "forward",
19
+ codexAccountMode: mode,
20
+ };
21
+ }
22
+
23
+ function normalizedBaseUrl(value: string): string | undefined {
24
+ try {
25
+ const url = new URL(value.trim());
26
+ if (url.username || url.password || url.search || url.hash) return undefined;
27
+ const path = url.pathname.replace(/\/+$/, "");
28
+ return `${url.origin}${path}`;
29
+ } catch {
30
+ return undefined;
31
+ }
32
+ }
33
+
34
+ export function isCanonicalOpenAiForwardProvider(provider: OcxProviderConfig): boolean {
35
+ return provider.adapter === "openai-responses"
36
+ && provider.authMode === "forward"
37
+ && normalizedBaseUrl(provider.baseUrl) === CODEX_FORWARD_BASE_URL;
38
+ }
39
+
40
+ const OPENAI_API_ORIGIN = "https://api.openai.com";
41
+ const OPENAI_API_BASE_URL = `${OPENAI_API_ORIGIN}/v1`;
42
+ const OPENAI_API_RESPONSES_URL = `${OPENAI_API_BASE_URL}/responses`;
43
+
44
+ /**
45
+ * The Responses endpoint the adapter would actually POST key-auth traffic to, normalized.
46
+ *
47
+ * Mirrors the adapter's own construction (`src/adapters/openai-responses.ts`): a configured
48
+ * `responsesPath` is appended to the base verbatim, and only the default branch runs the
49
+ * `/v1/responses` suffix normalization. Classifying on the base URL alone would call
50
+ * `baseUrl: "https://api.openai.com"` with `responsesPath: "/other"` official even though that
51
+ * request never reaches the official Responses endpoint.
52
+ */
53
+ function resolvedResponsesEndpoint(provider: OcxProviderConfig): string | undefined {
54
+ try {
55
+ const raw = provider.responsesPath === undefined
56
+ ? openaiResponsesUrl(provider.baseUrl)
57
+ : `${provider.baseUrl.replace(/\/$/, "")}${provider.responsesPath}`;
58
+ return normalizedBaseUrl(raw);
59
+ } catch {
60
+ return undefined;
61
+ }
62
+ }
63
+
64
+ function isOfficialOpenAiResponsesDestination(provider: OcxProviderConfig): boolean {
65
+ // Exact normalized URL keeps lookalike/suffix hosts out of this set: `api.openai.com.evil.test`
66
+ // resolves to its own origin, never to the official one.
67
+ return resolvedResponsesEndpoint(provider) === OPENAI_API_RESPONSES_URL;
68
+ }
69
+
70
+ /**
71
+ * Whether this provider can serve `POST /responses/compact`. The canonical ChatGPT
72
+ * backend can, and so can the official OpenAI API — but an arbitrary gateway that
73
+ * merely speaks the Responses wire cannot, and calling it there fails compaction
74
+ * with an unhelpful error instead of falling back to a routed summary (#422).
75
+ */
76
+ export function supportsNativeResponsesCompactEndpoint(
77
+ providerName: string,
78
+ provider: OcxProviderConfig,
79
+ ): boolean {
80
+ if (isCanonicalOpenAiForwardProvider(provider)) return true;
81
+ return providerName === OPENAI_API_PROVIDER_ID
82
+ && provider.adapter === "openai-responses"
83
+ && normalizedBaseUrl(provider.baseUrl) === OPENAI_API_BASE_URL;
84
+ }
85
+
86
+ /**
87
+ * Whether this destination is an OpenAI-operated Responses backend — the canonical ChatGPT Codex
88
+ * surface or the official OpenAI API.
89
+ *
90
+ * Deliberately not keyed on `authMode === "forward"`: a noncanonical forward provider does not
91
+ * receive the caller's credentials (see the forward-header gate in the Responses adapter), so
92
+ * forward auth says nothing about which backend is on the other end.
93
+ */
94
+ export function isOpenAiOperatedResponsesDestination(provider: OcxProviderConfig): boolean {
95
+ if (isCanonicalOpenAiForwardProvider(provider)) return true;
96
+ return provider.adapter === "openai-responses"
97
+ && isOfficialOpenAiResponsesDestination(provider);
98
+ }
99
+
100
+ /**
101
+ * Whether this destination can decode a native (non-`ocx1:`) compaction blob.
102
+ *
103
+ * Only the backend that minted a blob can decode it. `authMode: "forward"` alone is not a signal:
104
+ * the adapter forwards caller credentials only to the canonical ChatGPT Codex surface, while a
105
+ * noncanonical forward provider receives no caller credentials and may point at any backend.
106
+ *
107
+ * Relay only to an OpenAI-operated destination or a destination whose operator explicitly opts in.
108
+ * Keyed by destination rather than provider id: a blob's issuer is the URL that produced it, not the
109
+ * local config key a replay travels under.
110
+ */
111
+ export function destinationDecodesNativeCompactionBlob(provider: OcxProviderConfig): boolean {
112
+ return isOpenAiOperatedResponsesDestination(provider)
113
+ || provider.decodesNativeCompactionBlobs === true;
114
+ }
115
+
116
+ export interface OpenAiTierMigrationProjection {
117
+ config: OcxConfig;
118
+ changed: boolean;
119
+ resolvedMode: CodexAccountMode;
120
+ warnings: string[];
121
+ }
122
+
123
+ export class OpenAiTierMigrationCollisionError extends Error {
124
+ readonly providerName = LEGACY_OPENAI_MULTI_PROVIDER_ID;
125
+
126
+ constructor() {
127
+ super(`Reserved provider id "${LEGACY_OPENAI_MULTI_PROVIDER_ID}" is already configured with a noncanonical shape`);
128
+ this.name = "OpenAiTierMigrationCollisionError";
129
+ }
130
+ }
131
+
132
+ function managedLegacyMultiOverlay(
133
+ provider: OcxProviderConfig,
134
+ ): Pick<OcxProviderConfig, "disabled" | "selectedModels" | "modelCosts"> | null {
135
+ const allowed = new Set(["adapter", "authMode", "baseUrl", "disabled", "selectedModels", "modelCosts"]);
136
+ if (!Object.keys(provider).every(key => allowed.has(key))) return null;
137
+ if (!isCanonicalOpenAiForwardProvider(provider)) return null;
138
+ if (provider.disabled !== undefined && typeof provider.disabled !== "boolean") return null;
139
+ // Keep the migration self-contained: a malformed overlay is a collision, not
140
+ // something to carry into the canonical row (importing config.ts here would
141
+ // create an import cycle — config.ts already imports this module).
142
+ if (provider.modelCosts !== undefined && !validLegacyOverlayCosts(provider.modelCosts)) return null;
143
+ if (provider.selectedModels !== undefined && (
144
+ !Array.isArray(provider.selectedModels)
145
+ || provider.selectedModels.some(model => typeof model !== "string")
146
+ )) return null;
147
+ return {
148
+ ...(provider.disabled !== undefined ? { disabled: provider.disabled } : {}),
149
+ ...(provider.selectedModels !== undefined ? { selectedModels: [...provider.selectedModels] } : {}),
150
+ ...(provider.modelCosts !== undefined ? { modelCosts: provider.modelCosts } : {}),
151
+ };
152
+ }
153
+
154
+ /** Shape check for a legacy overlay: a plain record of complete non-negative finite Cost4 rows. */
155
+ function validLegacyOverlayCosts(value: unknown): boolean {
156
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
157
+ const fields = ["input", "output", "cacheRead", "cacheWrite"] as const;
158
+ return Object.values(value as Record<string, unknown>).every(entry => {
159
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) return false;
160
+ const rates = entry as Record<string, unknown>;
161
+ return Object.keys(rates).length === fields.length
162
+ && fields.every(key => Object.hasOwn(rates, key)
163
+ && typeof rates[key] === "number"
164
+ && Number.isFinite(rates[key])
165
+ && (rates[key] as number) >= 0
166
+ && (rates[key] as number) <= MAX_COST4_RATE);
167
+ });
168
+ }
169
+
170
+ function rewriteLegacyOpenAiSelectedId(value: string): string {
171
+ return value.startsWith(LEGACY_OPENAI_MULTI_PREFIX)
172
+ ? value.slice(LEGACY_OPENAI_MULTI_PREFIX.length)
173
+ : value;
174
+ }
175
+
176
+ function rewriteLegacyOpenAiModelList(values: string[] | undefined): string[] | undefined {
177
+ if (!values) return undefined;
178
+ return [...new Set(values.map(rewriteLegacyOpenAiSelectedId))];
179
+ }
180
+
181
+ /**
182
+ * Rewrite legacy `openai-multi/<model>` keys in a modelCosts overlay so the
183
+ * prices still match after the migration resolves logs as provider `openai`
184
+ * with the bare model id. Keys without the legacy prefix pass through.
185
+ */
186
+ function rewriteLegacyOpenAiCostKeys(costs: Record<string, ProviderCostOverlay> | undefined): Record<string, ProviderCostOverlay> {
187
+ // Null-prototype map so prototype-named model ids (e.g. "__proto__") are
188
+ // stored as own properties instead of invoking the inherited setter.
189
+ const rewritten = Object.create(null) as Record<string, ProviderCostOverlay>;
190
+ if (costs) {
191
+ for (const [key, value] of Object.entries(costs)) {
192
+ const canonicalKey = rewriteLegacyOpenAiSelectedId(key);
193
+ // A bare <model> key always wins over its openai-multi/<model> equivalent
194
+ // inside the same row, regardless of JSON property order.
195
+ if (key === canonicalKey || !Object.hasOwn(rewritten, canonicalKey)) {
196
+ rewritten[canonicalKey] = value;
197
+ }
198
+ }
199
+ }
200
+ return rewritten;
201
+ }
202
+
203
+ function mergeLegacyOpenAiProviderRows(
204
+ openai: OcxProviderConfig | undefined,
205
+ legacyMulti: OcxProviderConfig | undefined,
206
+ mode: CodexAccountMode,
207
+ ): OcxProviderConfig {
208
+ const selectedModels = rewriteLegacyOpenAiModelList([
209
+ ...(openai?.selectedModels ?? []),
210
+ ...(legacyMulti?.selectedModels ?? []),
211
+ ]);
212
+ // Both rows can carry disjoint overlays; merge them (canonical openai wins on
213
+ // key conflicts) so legacy Multi prices are not silently dropped. Keys are
214
+ // rewritten first so `openai-multi/<model>` entries still resolve after the
215
+ // provider is canonicalized to `openai`.
216
+ const modelCosts = {
217
+ ...rewriteLegacyOpenAiCostKeys(legacyMulti?.modelCosts),
218
+ ...rewriteLegacyOpenAiCostKeys(openai?.modelCosts),
219
+ };
220
+ const hasModelCosts = Object.keys(modelCosts).length > 0;
221
+ const formerRows = [openai, legacyMulti].filter((row): row is OcxProviderConfig => row !== undefined);
222
+ const disabled = formerRows.length > 0 && formerRows.every(row => row.disabled === true);
223
+ return {
224
+ ...canonicalCodexForwardProvider(mode),
225
+ ...(disabled ? { disabled: true } : {}),
226
+ ...(selectedModels && selectedModels.length > 0 ? { selectedModels } : {}),
227
+ ...(hasModelCosts ? { modelCosts } : {}),
228
+ };
229
+ }
230
+
231
+ function hasKnownLegacyOpenAiReference(config: OcxConfig): boolean {
232
+ const matches = (value: unknown): boolean => typeof value === "string" && value.startsWith(LEGACY_OPENAI_MULTI_PREFIX);
233
+ const matchesList = (value: unknown): boolean => Array.isArray(value) && value.some(matches);
234
+ const claude = config.claudeCode;
235
+ return config.defaultProvider === LEGACY_OPENAI_MULTI_PROVIDER_ID
236
+ || matchesList(config.disabledModels)
237
+ || matchesList(config.subagentModels)
238
+ || (config.subagentRoles ?? []).some(role => matches(role.model))
239
+ || matches(config.injectionModel)
240
+ || matches(config.shadowCallIntercept?.model)
241
+ || matches(config.webSearchSidecar?.model)
242
+ || matches(config.visionSidecar?.model)
243
+ || matches(claude?.webSearchSidecar?.model)
244
+ || matches(claude?.visionSidecar?.model)
245
+ || matches(claude?.model)
246
+ || matches(claude?.smallFastModel)
247
+ || Object.values(claude?.tierModels ?? {}).some(matches)
248
+ || Object.values(claude?.modelMap ?? {}).some(matches)
249
+ || matchesList(config.providers[OPENAI_CODEX_PROVIDER_ID]?.selectedModels)
250
+ || matchesList(config.providers[LEGACY_OPENAI_MULTI_PROVIDER_ID]?.selectedModels)
251
+ || config.providerContextCaps?.[LEGACY_OPENAI_MULTI_PROVIDER_ID] !== undefined;
252
+ }
253
+
254
+ function rewriteLegacyOpenAiReferences(config: OcxConfig, warnings: string[]): void {
255
+ config.disabledModels = rewriteLegacyOpenAiModelList(config.disabledModels);
256
+ config.subagentModels = rewriteLegacyOpenAiModelList(config.subagentModels);
257
+ if (config.subagentRoles) {
258
+ for (const role of config.subagentRoles) {
259
+ role.model = rewriteLegacyOpenAiSelectedId(role.model);
260
+ }
261
+ }
262
+ if (config.injectionModel) config.injectionModel = rewriteLegacyOpenAiSelectedId(config.injectionModel);
263
+ if (config.shadowCallIntercept?.model) {
264
+ config.shadowCallIntercept.model = rewriteLegacyOpenAiSelectedId(config.shadowCallIntercept.model);
265
+ }
266
+ if (config.webSearchSidecar?.model) config.webSearchSidecar.model = rewriteLegacyOpenAiSelectedId(config.webSearchSidecar.model);
267
+ if (config.visionSidecar?.model) config.visionSidecar.model = rewriteLegacyOpenAiSelectedId(config.visionSidecar.model);
268
+
269
+ const claude = config.claudeCode;
270
+ if (claude?.webSearchSidecar?.model) claude.webSearchSidecar.model = rewriteLegacyOpenAiSelectedId(claude.webSearchSidecar.model);
271
+ if (claude?.visionSidecar?.model) claude.visionSidecar.model = rewriteLegacyOpenAiSelectedId(claude.visionSidecar.model);
272
+ if (claude?.model) claude.model = rewriteLegacyOpenAiSelectedId(claude.model);
273
+ if (claude?.smallFastModel) claude.smallFastModel = rewriteLegacyOpenAiSelectedId(claude.smallFastModel);
274
+ if (claude?.tierModels) {
275
+ for (const tier of ["opus", "sonnet", "haiku", "fable"] as const) {
276
+ const value = claude.tierModels[tier];
277
+ if (value) claude.tierModels[tier] = rewriteLegacyOpenAiSelectedId(value);
278
+ }
279
+ }
280
+ if (claude?.modelMap) {
281
+ for (const key of Object.keys(claude.modelMap)) {
282
+ claude.modelMap[key] = rewriteLegacyOpenAiSelectedId(claude.modelMap[key]!);
283
+ }
284
+ }
285
+
286
+ const caps = config.providerContextCaps;
287
+ const legacyCap = caps?.[LEGACY_OPENAI_MULTI_PROVIDER_ID];
288
+ if (caps && legacyCap !== undefined) {
289
+ const currentCap = caps[OPENAI_CODEX_PROVIDER_ID];
290
+ if (currentCap !== undefined) {
291
+ caps[OPENAI_CODEX_PROVIDER_ID] = Math.min(currentCap, legacyCap);
292
+ warnings.push("providerContextCaps.openai + providerContextCaps.openai-multi: kept lower positive cap");
293
+ } else {
294
+ caps[OPENAI_CODEX_PROVIDER_ID] = legacyCap;
295
+ }
296
+ delete caps[LEGACY_OPENAI_MULTI_PROVIDER_ID];
297
+ }
298
+ }
299
+
300
+ function isKnownLegacyValuePath(path: readonly string[]): boolean {
301
+ const joined = path.join(".");
302
+ if (joined === "defaultProvider") return true;
303
+ if (/^(disabledModels|subagentModels)\.\d+$/.test(joined)) return true;
304
+ if (/^subagentRoles\.\d+\.model$/.test(joined)) return true;
305
+ if (/^providers\.(openai|openai-multi)\.selectedModels\.\d+$/.test(joined)) return true;
306
+ return new Set([
307
+ "injectionModel",
308
+ "shadowCallIntercept.model",
309
+ "webSearchSidecar.model",
310
+ "visionSidecar.model",
311
+ "claudeCode.webSearchSidecar.model",
312
+ "claudeCode.visionSidecar.model",
313
+ "claudeCode.model",
314
+ "claudeCode.smallFastModel",
315
+ "claudeCode.tierModels.opus",
316
+ "claudeCode.tierModels.sonnet",
317
+ "claudeCode.tierModels.haiku",
318
+ "claudeCode.tierModels.fable",
319
+ ]).has(joined) || /^claudeCode\.modelMap\..+$/.test(joined);
320
+ }
321
+
322
+ function unknownLegacyOpenAiWarnings(config: OcxConfig): string[] {
323
+ const warnings = new Set<string>();
324
+ const visit = (value: unknown, path: string[]): void => {
325
+ if (typeof value === "string") {
326
+ if (value.includes(LEGACY_OPENAI_MULTI_PROVIDER_ID) && !isKnownLegacyValuePath(path)) {
327
+ warnings.add(`${path.join(".")}: legacy OpenAI provider id left unchanged`);
328
+ }
329
+ return;
330
+ }
331
+ if (!value || typeof value !== "object") return;
332
+ if (Array.isArray(value)) {
333
+ value.forEach((item, index) => visit(item, [...path, String(index)]));
334
+ return;
335
+ }
336
+ for (const [key, item] of Object.entries(value as Record<string, unknown>)) {
337
+ visit(item, [...path, key]);
338
+ }
339
+ };
340
+ visit(config, []);
341
+ return [...warnings];
342
+ }
343
+
344
+ function resolvedOpenAiMode(
345
+ config: OcxConfig,
346
+ openai: OcxProviderConfig | undefined,
347
+ legacyMulti: OcxProviderConfig | undefined,
348
+ knownLegacyReference: boolean,
349
+ ): CodexAccountMode {
350
+ if (openai?.codexAccountMode === "pool" || openai?.codexAccountMode === "direct") {
351
+ return openai.codexAccountMode;
352
+ }
353
+ if (
354
+ (legacyMulti && legacyMulti.disabled !== true)
355
+ || config.defaultProvider === LEGACY_OPENAI_MULTI_PROVIDER_ID
356
+ || knownLegacyReference
357
+ ) return "pool";
358
+ if (config.openaiProviderTierVersion === 1 && openai) return "direct";
359
+ if (config.openaiProviderTierVersion === 1 && legacyMulti) return "pool";
360
+ return "pool";
361
+ }
362
+
363
+ export function projectOpenAiTierMigration(config: OcxConfig): OpenAiTierMigrationProjection {
364
+ const projected = structuredClone(config);
365
+ const legacyMulti = projected.providers[LEGACY_OPENAI_MULTI_PROVIDER_ID];
366
+ if (legacyMulti && !managedLegacyMultiOverlay(legacyMulti)) {
367
+ throw new OpenAiTierMigrationCollisionError();
368
+ }
369
+
370
+ const openai = projected.providers[OPENAI_CODEX_PROVIDER_ID];
371
+ const knownLegacyReference = hasKnownLegacyOpenAiReference(projected);
372
+ const resolvedMode = resolvedOpenAiMode(projected, openai, legacyMulti, knownLegacyReference);
373
+ if (
374
+ projected.openaiProviderTierVersion === OPENAI_PROVIDER_TIER_VERSION
375
+ && !legacyMulti
376
+ && !Object.hasOwn(projected.providers, LEGACY_CHATGPT_PROVIDER_ID)
377
+ && projected.defaultProvider !== LEGACY_OPENAI_MULTI_PROVIDER_ID
378
+ && !knownLegacyReference
379
+ ) {
380
+ return { config: projected, changed: false, resolvedMode, warnings: [] };
381
+ }
382
+
383
+ const warnings = unknownLegacyOpenAiWarnings(projected);
384
+ const referencesCodexForward = !!openai
385
+ || !!legacyMulti
386
+ || Object.hasOwn(projected.providers, LEGACY_CHATGPT_PROVIDER_ID)
387
+ || projected.defaultProvider === OPENAI_CODEX_PROVIDER_ID
388
+ || projected.defaultProvider === LEGACY_OPENAI_MULTI_PROVIDER_ID
389
+ || projected.defaultProvider === LEGACY_CHATGPT_PROVIDER_ID
390
+ || knownLegacyReference;
391
+ const mergedOpenAi = referencesCodexForward
392
+ ? mergeLegacyOpenAiProviderRows(openai, legacyMulti, resolvedMode)
393
+ : undefined;
394
+
395
+ const nextProviders: Array<[string, OcxProviderConfig]> = [];
396
+ let inserted = false;
397
+ for (const [name, provider] of Object.entries(projected.providers)) {
398
+ if (name === OPENAI_CODEX_PROVIDER_ID) {
399
+ if (mergedOpenAi && !inserted) nextProviders.push([OPENAI_CODEX_PROVIDER_ID, mergedOpenAi]);
400
+ inserted = true;
401
+ continue;
402
+ }
403
+ if (name === LEGACY_OPENAI_MULTI_PROVIDER_ID || name === LEGACY_CHATGPT_PROVIDER_ID) {
404
+ if (mergedOpenAi && !inserted && !openai) {
405
+ nextProviders.push([OPENAI_CODEX_PROVIDER_ID, mergedOpenAi]);
406
+ inserted = true;
407
+ }
408
+ continue;
409
+ }
410
+ nextProviders.push([name, provider]);
411
+ }
412
+ if (mergedOpenAi && !inserted) nextProviders.push([OPENAI_CODEX_PROVIDER_ID, mergedOpenAi]);
413
+ projected.providers = Object.fromEntries(nextProviders);
414
+
415
+ if (
416
+ projected.defaultProvider === LEGACY_OPENAI_MULTI_PROVIDER_ID
417
+ || projected.defaultProvider === LEGACY_CHATGPT_PROVIDER_ID
418
+ ) projected.defaultProvider = OPENAI_CODEX_PROVIDER_ID;
419
+
420
+ rewriteLegacyOpenAiReferences(projected, warnings);
421
+ projected.openaiProviderTierVersion = OPENAI_PROVIDER_TIER_VERSION;
422
+ return { config: projected, changed: true, resolvedMode, warnings: [...new Set(warnings)] };
423
+ }
@@ -0,0 +1,83 @@
1
+ import { PROVIDER_REGISTRY } from "./registry";
2
+ import { OPENAI_API_PROVIDER_ID } from "./openai-tiers";
3
+ import type { OcxParsedRequest } from "../types";
4
+ import type { RouteResult } from "../router";
5
+ import type { RequestLogContext } from "../server/request-log";
6
+
7
+ export interface OpenAiVirtualModelResolution {
8
+ selectedModelId: string;
9
+ wireModelId: string;
10
+ reasoningMode: "pro";
11
+ }
12
+
13
+ export class InvalidOpenAiVirtualModelRegistryError extends Error {
14
+ constructor(selectedModelId: string) {
15
+ super(`Invalid OpenAI virtual model registry definition: ${selectedModelId}`);
16
+ this.name = "InvalidOpenAiVirtualModelRegistryError";
17
+ }
18
+ }
19
+
20
+ export function validateOpenAiVirtualModelDefinition(
21
+ selectedModelId: string,
22
+ definition: unknown,
23
+ ): OpenAiVirtualModelResolution {
24
+ if (!definition || typeof definition !== "object" || Array.isArray(definition)) {
25
+ throw new InvalidOpenAiVirtualModelRegistryError(selectedModelId);
26
+ }
27
+ const raw = definition as { wireModelId?: unknown; reasoningMode?: unknown };
28
+ if (
29
+ typeof raw.wireModelId !== "string"
30
+ || raw.wireModelId.trim() !== raw.wireModelId
31
+ || raw.wireModelId.length === 0
32
+ || raw.wireModelId.includes("/")
33
+ || raw.wireModelId === selectedModelId
34
+ || raw.reasoningMode !== "pro"
35
+ ) {
36
+ throw new InvalidOpenAiVirtualModelRegistryError(selectedModelId);
37
+ }
38
+ return { selectedModelId, wireModelId: raw.wireModelId, reasoningMode: "pro" };
39
+ }
40
+
41
+ export function resolveOpenAiVirtualModel(
42
+ providerName: string,
43
+ selectedModelId: string,
44
+ ): OpenAiVirtualModelResolution | undefined {
45
+ if (providerName !== OPENAI_API_PROVIDER_ID) return undefined;
46
+ const entry = PROVIDER_REGISTRY.find(row => row.id === OPENAI_API_PROVIDER_ID);
47
+ if (!entry?.virtualModels || !Object.hasOwn(entry.virtualModels, selectedModelId)) return undefined;
48
+ const definition = entry.virtualModels[selectedModelId];
49
+ return validateOpenAiVirtualModelDefinition(selectedModelId, definition);
50
+ }
51
+
52
+ export function applyOpenAiVirtualModel(
53
+ parsed: OcxParsedRequest,
54
+ route: RouteResult,
55
+ logCtx: RequestLogContext,
56
+ ): OpenAiVirtualModelResolution | undefined {
57
+ const selectedModelId = logCtx.model && logCtx.model !== route.modelId ? logCtx.model : route.modelId;
58
+ const resolution = resolveOpenAiVirtualModel(route.providerName, selectedModelId);
59
+ if (!resolution) return undefined;
60
+
61
+ logCtx.model = resolution.selectedModelId;
62
+ logCtx.resolvedModel = resolution.wireModelId;
63
+ route.modelId = resolution.wireModelId;
64
+ parsed.modelId = resolution.wireModelId;
65
+ parsed._openAiVirtualSelectedModelId = resolution.selectedModelId;
66
+
67
+ if (parsed._rawBody && typeof parsed._rawBody === "object" && !Array.isArray(parsed._rawBody)) {
68
+ const raw = parsed._rawBody as Record<string, unknown>;
69
+ raw.model = resolution.wireModelId;
70
+ const existing = raw.reasoning;
71
+ raw.reasoning = existing && typeof existing === "object" && !Array.isArray(existing)
72
+ ? { ...(existing as Record<string, unknown>), mode: resolution.reasoningMode }
73
+ : { mode: resolution.reasoningMode };
74
+ }
75
+ return resolution;
76
+ }
77
+
78
+ export function resolveOpenAiCompactModel(
79
+ providerName: string,
80
+ selectedModelId: string,
81
+ ): OpenAiVirtualModelResolution | undefined {
82
+ return resolveOpenAiVirtualModel(providerName, selectedModelId);
83
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * OpenCode Zen short-window rate-limit guidance (#1145 / OCX-56).
3
+ *
4
+ * OpenCode's keyed and keyless Zen chat endpoints share `https://opencode.ai/zen/v1`.
5
+ * Free-model traffic can hit a short-window burst ceiling around 15–20 RPM
6
+ * (community-measured). Zen often answers with opaque `429 Rate limit exceeded`
7
+ * bodies and may omit `Retry-After` / `X-RateLimit-*`; when those headers are
8
+ * present they still take precedence. Distinct from the keyless desktop
9
+ * ~200 requests / 5h quota documented on `opencode-free`.
10
+ */
11
+ import { validateClientRetryAfterHeader } from "../lib/retry-after";
12
+ import { registryEntryForProviderDestination } from "./registry";
13
+
14
+ const OPENCODE_ZEN_PROVIDER_IDS = new Set(["opencode-zen", "opencode-free"]);
15
+
16
+ /** Observed free-model burst ceiling on Zen (not an official OpenCode figure). */
17
+ export const OPENCODE_ZEN_OBSERVED_RPM_HINT = "roughly 15-20 requests per minute";
18
+
19
+ /**
20
+ * Synthetic client backoff when Zen omits Retry-After after a rate-limit 429.
21
+ * Longer than the generic 2s default so Codex-shaped clients do not immediately
22
+ * re-hammer a ~15-20 RPM window.
23
+ */
24
+ export const OPENCODE_ZEN_SYNTHETIC_RETRY_AFTER_SEC = 15;
25
+
26
+ const ENRICHMENT_MARKER = "15-20 requests per minute";
27
+
28
+ export function isOpenCodeZenRateLimitProvider(opts: {
29
+ providerName?: string;
30
+ baseUrl?: string;
31
+ adapter?: string;
32
+ }): boolean {
33
+ const name = opts.providerName?.trim();
34
+ if (name && OPENCODE_ZEN_PROVIDER_IDS.has(name)) return true;
35
+ const baseUrl = opts.baseUrl?.trim();
36
+ if (!baseUrl) return false;
37
+ const entry = registryEntryForProviderDestination({
38
+ baseUrl,
39
+ adapter: opts.adapter?.trim() || "openai-chat",
40
+ authMode: "key",
41
+ });
42
+ return entry !== undefined && OPENCODE_ZEN_PROVIDER_IDS.has(entry.id);
43
+ }
44
+
45
+ /**
46
+ * Same-key `retryOn429` only applies on key-authenticated HTTP paths — not
47
+ * keyless `opencode-free` traffic and not custom `runTurn` transports.
48
+ */
49
+ export function supportsOpenCodeZenRetryOn429Guidance(opts: {
50
+ authMode?: string;
51
+ hasApiKey?: boolean;
52
+ supportsHttpSameKeyRetry?: boolean;
53
+ }): boolean {
54
+ if (opts.supportsHttpSameKeyRetry === false) return false;
55
+ if (opts.authMode !== undefined && opts.authMode !== "key") return false;
56
+ return opts.hasApiKey === true;
57
+ }
58
+
59
+ /**
60
+ * Append actionable Zen rate-limit context to a generic upstream 429 message and
61
+ * embed a parseable `try again in Ns` hint so {@link resolveClientRetryAfter}
62
+ * surfaces a useful Retry-After when the gateway sent none.
63
+ */
64
+ export function enrichOpenCodeZenRateLimitMessage(
65
+ message: string,
66
+ opts: {
67
+ status: number;
68
+ providerName?: string;
69
+ baseUrl?: string;
70
+ adapter?: string;
71
+ authMode?: string;
72
+ hasApiKey?: boolean;
73
+ /** Upstream Retry-After header; when valid, skip the synthetic 15s text hint. */
74
+ upstreamRetryAfter?: string | null;
75
+ /** False for custom `runTurn` transports outside the HTTP retry loop. */
76
+ supportsHttpSameKeyRetry?: boolean;
77
+ now?: number;
78
+ },
79
+ ): string {
80
+ if (opts.status !== 429) return message;
81
+ if (!isOpenCodeZenRateLimitProvider(opts)) return message;
82
+ if (!/rate\s*limit/i.test(message)) return message;
83
+ if (message.includes(ENRICHMENT_MARKER)) return message;
84
+
85
+ const upstreamRetry = validateClientRetryAfterHeader(
86
+ opts.upstreamRetryAfter,
87
+ opts.now ?? Date.now(),
88
+ );
89
+ const retryHint = upstreamRetry || /try again in \d/i.test(message)
90
+ ? ""
91
+ : ` Try again in ${OPENCODE_ZEN_SYNTHETIC_RETRY_AFTER_SEC}s.`;
92
+ const paceHint = supportsOpenCodeZenRetryOn429Guidance(opts)
93
+ ? " Slow the request pace, or set providers.opencode-zen.retryOn429 for same-key backoff."
94
+ : " Slow the request pace.";
95
+ return (
96
+ `${message}`
97
+ + ` OpenCode Zen free-model traffic is often limited to ${OPENCODE_ZEN_OBSERVED_RPM_HINT}`
98
+ + ` (observed; OpenCode does not publish this RPM, and may omit rate-limit headers).`
99
+ + `${retryHint}`
100
+ + paceHint
101
+ );
102
+ }