@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,245 @@
1
+ import {
2
+ CliUsageError,
3
+ csv,
4
+ printData,
5
+ rejectArgs,
6
+ runCliAction,
7
+ runtimeRequest,
8
+ summaryLines,
9
+ takeBooleanOption,
10
+ takeFlag,
11
+ takeIntegerOption,
12
+ takeOption,
13
+ type RuntimeApiDeps,
14
+ } from "./runtime-api";
15
+
16
+ const USAGE = `Usage:
17
+ ocx models live [--provider <name>] [--json]
18
+ ocx models edit <custom-id> [--model-id <id>] [--display-name <name|->]
19
+ [--context-window <tokens|0>] [--modalities <text,image,audio|->]
20
+ [--reasoning-efforts <none,minimal,low,medium,high,xhigh,max,ultra|->]
21
+ [--default-reasoning-effort <level|->] [--json]
22
+ ocx models <enable|disable> <provider/model|native-model> [--native] [--json]
23
+ ocx models provider <name> <on|off> [--json]
24
+ ocx models selected <provider> [--set <id,id...>|--clear] [--json]
25
+ ocx models context <status|value <tokens> [--set-all]|provider <name> on [--value <tokens>]|provider <name> off|all <on|off>> [--json]
26
+ ocx models shadow <status|set> [model|-] [--enabled <on|off>] [--json]`;
27
+
28
+ type ModelRow = {
29
+ provider?: string;
30
+ id?: string;
31
+ namespaced?: string;
32
+ native?: boolean;
33
+ disabled?: boolean;
34
+ custom?: boolean;
35
+ customId?: string;
36
+ displayName?: string;
37
+ };
38
+
39
+ async function live(argv: string[], deps: RuntimeApiDeps): Promise<void> {
40
+ const args = [...argv];
41
+ const wantsJson = takeFlag(args, "--json");
42
+ const provider = takeOption(args, "--provider");
43
+ rejectArgs(args, USAGE);
44
+ const rows = await runtimeRequest<ModelRow[]>("/api/models", {}, deps);
45
+ const filtered = provider ? rows.filter(row => row.provider === provider) : rows;
46
+ printData(filtered, wantsJson, filtered.map(row => {
47
+ const flags = [row.native ? "native" : "routed", row.custom ? "custom" : "", row.disabled ? "disabled" : "enabled"].filter(Boolean);
48
+ return `${row.namespaced ?? `${row.provider}/${row.id}`} [${flags.join(", ")}]`;
49
+ }));
50
+ }
51
+
52
+ async function edit(argv: string[], deps: RuntimeApiDeps): Promise<void> {
53
+ const args = [...argv];
54
+ const id = args.shift()?.trim();
55
+ const wantsJson = takeFlag(args, "--json");
56
+ if (!id) throw new CliUsageError("custom model id is required", USAGE);
57
+ const patch: Record<string, unknown> = {};
58
+ const modelId = takeOption(args, "--model-id");
59
+ const displayName = takeOption(args, "--display-name");
60
+ const contextRaw = takeOption(args, "--context-window");
61
+ const modalitiesRaw = takeOption(args, "--modalities");
62
+ const reasoningEffortsRaw = takeOption(args, "--reasoning-efforts");
63
+ const defaultEffortRaw = takeOption(args, "--default-reasoning-effort");
64
+ rejectArgs(args, USAGE);
65
+ if (modelId !== undefined) patch.modelId = modelId;
66
+ if (displayName !== undefined) patch.displayName = displayName === "-" ? "" : displayName;
67
+ if (contextRaw !== undefined) {
68
+ const value = Number(contextRaw.replace(/[_,]/g, ""));
69
+ if (!Number.isInteger(value) || value < 0) throw new CliUsageError("--context-window must be an integer >= 0", USAGE);
70
+ patch.contextWindow = value === 0 ? null : value;
71
+ }
72
+ if (modalitiesRaw !== undefined) patch.inputModalities = modalitiesRaw === "-" ? [] : csv(modalitiesRaw);
73
+ // "-" restores inheritance by clearing the stored ladder (null); "" stores an explicit
74
+ // empty ladder (the "no reasoning" override, same as the dashboard's uncheck-all).
75
+ // Embedded blank CSV members (`low,,high`, `,,`) are malformed and must be rejected, not
76
+ // silently normalized by csv().
77
+ if (reasoningEffortsRaw !== undefined) {
78
+ if (reasoningEffortsRaw === "-") {
79
+ patch.reasoningEfforts = null;
80
+ } else {
81
+ const trimmed = reasoningEffortsRaw.trim();
82
+ const values = trimmed === "" ? [] : trimmed.split(",").map(value => value.trim());
83
+ if (values.some(value => value === "")) {
84
+ throw new CliUsageError("--reasoning-efforts must be comma-separated values from none, minimal, low, medium, high, xhigh, max, ultra (\"\" for no reasoning, \"-\" to inherit)", USAGE);
85
+ }
86
+ patch.reasoningEfforts = values;
87
+ }
88
+ }
89
+ if (defaultEffortRaw !== undefined) patch.defaultReasoningEffort = defaultEffortRaw === "-" ? null : defaultEffortRaw;
90
+ if (Object.keys(patch).length === 0) throw new CliUsageError("at least one edit option is required", USAGE);
91
+ const result = await runtimeRequest(`/api/custom-models/${encodeURIComponent(id)}`, {
92
+ method: "PUT",
93
+ body: JSON.stringify(patch),
94
+ }, deps);
95
+ printData(result, wantsJson, [`Updated custom model ${id}.`]);
96
+ }
97
+
98
+ function parseSelector(selector: string, forceNative: boolean): { provider: string; id: string; native: boolean } {
99
+ if (forceNative || !selector.includes("/")) return { provider: "openai", id: selector, native: true };
100
+ const slash = selector.indexOf("/");
101
+ const provider = selector.slice(0, slash);
102
+ const id = selector.slice(slash + 1);
103
+ if (!provider || !id) throw new CliUsageError("model selector must be provider/model or a native model id", USAGE);
104
+ return { provider, id, native: false };
105
+ }
106
+
107
+ async function visibility(enabled: boolean, argv: string[], deps: RuntimeApiDeps): Promise<void> {
108
+ const args = [...argv];
109
+ const selector = args.shift()?.trim();
110
+ const wantsJson = takeFlag(args, "--json");
111
+ const native = takeFlag(args, "--native");
112
+ if (!selector) throw new CliUsageError("model selector is required", USAGE);
113
+ rejectArgs(args, USAGE);
114
+ const target = parseSelector(selector, native);
115
+ const result = await runtimeRequest("/api/model-visibility", {
116
+ method: "PUT",
117
+ body: JSON.stringify({ scope: "models", provider: target.provider, enabled, targets: [{ id: target.id, native: target.native }] }),
118
+ }, deps);
119
+ printData(result, wantsJson, [`${enabled ? "Enabled" : "Disabled"} ${selector}.`]);
120
+ }
121
+
122
+ async function providerVisibility(argv: string[], deps: RuntimeApiDeps): Promise<void> {
123
+ const args = [...argv];
124
+ const provider = args.shift()?.trim();
125
+ const state = args.shift()?.toLowerCase();
126
+ const wantsJson = takeFlag(args, "--json");
127
+ if (!provider || (state !== "on" && state !== "off")) throw new CliUsageError("provider and on|off are required", USAGE);
128
+ rejectArgs(args, USAGE);
129
+ const rows = await runtimeRequest<ModelRow[]>("/api/models", {}, deps);
130
+ const targets = rows.filter(row => row.provider === provider && typeof row.id === "string")
131
+ .map(row => ({ id: row.id!, native: row.native === true }));
132
+ if (targets.length === 0) throw new CliUsageError(`no models are available for provider ${provider}`);
133
+ const result = await runtimeRequest("/api/model-visibility", {
134
+ method: "PUT",
135
+ body: JSON.stringify({ scope: "provider", provider, enabled: state === "on", targets }),
136
+ }, deps);
137
+ printData(result, wantsJson, [`${provider}: ${state}`]);
138
+ }
139
+
140
+ async function selected(argv: string[], deps: RuntimeApiDeps): Promise<void> {
141
+ const args = [...argv];
142
+ const provider = args.shift()?.trim();
143
+ const wantsJson = takeFlag(args, "--json");
144
+ const selectedModels = csv(takeOption(args, "--set"));
145
+ const clear = takeFlag(args, "--clear");
146
+ if (!provider) throw new CliUsageError("provider is required", USAGE);
147
+ if (selectedModels !== undefined && clear) throw new CliUsageError("--set and --clear cannot be combined", USAGE);
148
+ rejectArgs(args, USAGE);
149
+ if (selectedModels === undefined && !clear) {
150
+ const result = await runtimeRequest<Record<string, unknown>>("/api/selected-models", {}, deps);
151
+ const map = result.selected as Record<string, string[]> | undefined;
152
+ const available = result.available as Record<string, string[]> | undefined;
153
+ const view = { provider, selected: map?.[provider] ?? [], available: available?.[provider] ?? [] };
154
+ printData(view, wantsJson, [`${provider}: ${view.selected.join(", ") || "all models"}`]);
155
+ return;
156
+ }
157
+ const models = clear ? [] : selectedModels!;
158
+ const result = await runtimeRequest("/api/selected-models", {
159
+ method: "PUT",
160
+ body: JSON.stringify({ provider, models }),
161
+ }, deps);
162
+ printData(result, wantsJson, [`${provider}: ${models.length ? models.join(", ") : "all models"}`]);
163
+ }
164
+
165
+ async function context(argv: string[], deps: RuntimeApiDeps): Promise<void> {
166
+ const args = [...argv];
167
+ const action = (args.shift() ?? "status").toLowerCase();
168
+ const wantsJson = takeFlag(args, "--json");
169
+ if (action === "status") {
170
+ rejectArgs(args, USAGE);
171
+ const result = await runtimeRequest("/api/provider-context-caps", {}, deps);
172
+ printData(result, wantsJson, summaryLines(result));
173
+ return;
174
+ }
175
+ let body: Record<string, unknown>;
176
+ if (action === "value") {
177
+ const raw = args.shift();
178
+ if (!raw) throw new CliUsageError("context value is required", USAGE);
179
+ const value = Number(raw.replace(/[_,]/g, ""));
180
+ if (!Number.isInteger(value) || value <= 0) throw new CliUsageError("context value must be a positive integer", USAGE);
181
+ body = { value };
182
+ // Explicit apply-to-all switch for headless use: re-points every routed provider to
183
+ // the new value, mirroring the dashboard's "apply to every routed provider" toggle.
184
+ // Without it the value only becomes the default for future toggles.
185
+ if (takeFlag(args, "--set-all")) body.setAll = true;
186
+ } else if (action === "provider") {
187
+ const provider = args.shift()?.trim();
188
+ const state = args.shift()?.toLowerCase();
189
+ if (!provider || (state !== "on" && state !== "off")) throw new CliUsageError("provider and on|off are required", USAGE);
190
+ body = { provider, enabled: state === "on" };
191
+ // Optional explicit cap value for this provider only (`ocx models context provider
192
+ // openai on --value 128000`). Mirrors the dashboard's per-provider cap picker; the
193
+ // value never leaks to other providers.
194
+ const value = takeIntegerOption(args, "--value", { min: 1 });
195
+ if (value !== undefined && state !== "on") {
196
+ throw new CliUsageError("--value can only be used with on", USAGE);
197
+ }
198
+ if (value !== undefined) body.value = value;
199
+ } else if (action === "all") {
200
+ const state = args.shift()?.toLowerCase();
201
+ if (state !== "on" && state !== "off") throw new CliUsageError("all requires on|off", USAGE);
202
+ body = { setAll: state === "on" };
203
+ } else throw new CliUsageError(`unknown context action ${action}`, USAGE);
204
+ rejectArgs(args, USAGE);
205
+ const result = await runtimeRequest("/api/provider-context-caps", { method: "PUT", body: JSON.stringify(body) }, deps);
206
+ printData(result, wantsJson, ["Context cap settings updated."]);
207
+ }
208
+
209
+ async function shadow(argv: string[], deps: RuntimeApiDeps): Promise<void> {
210
+ const args = [...argv];
211
+ const action = (args.shift() ?? "status").toLowerCase();
212
+ const wantsJson = takeFlag(args, "--json");
213
+ if (action === "status") {
214
+ rejectArgs(args, USAGE);
215
+ const result = await runtimeRequest("/api/shadow-call-settings", {}, deps);
216
+ printData(result, wantsJson);
217
+ return;
218
+ }
219
+ if (action !== "set") throw new CliUsageError(`unknown shadow action ${action}`, USAGE);
220
+ const modelRaw = args[0] && !args[0].startsWith("--") ? args.shift() : undefined;
221
+ const enabled = takeBooleanOption(args, "--enabled");
222
+ rejectArgs(args, USAGE);
223
+ const body: Record<string, unknown> = {};
224
+ if (modelRaw !== undefined) body.model = modelRaw === "-" ? "" : modelRaw;
225
+ if (enabled !== undefined) body.enabled = enabled;
226
+ if (Object.keys(body).length === 0) throw new CliUsageError("model and/or --enabled is required", USAGE);
227
+ const result = await runtimeRequest("/api/shadow-call-settings", { method: "PUT", body: JSON.stringify(body) }, deps);
228
+ printData(result, wantsJson, ["Shadow-call settings updated."]);
229
+ }
230
+
231
+ export async function handleModelsRuntimeCommand(sub: string, argv: string[], deps: RuntimeApiDeps = {}): Promise<number | null> {
232
+ let action: (() => Promise<void>) | undefined;
233
+ if (sub === "live") action = () => live(argv, deps);
234
+ else if (sub === "edit") action = () => edit(argv, deps);
235
+ else if (sub === "enable") action = () => visibility(true, argv, deps);
236
+ else if (sub === "disable") action = () => visibility(false, argv, deps);
237
+ else if (sub === "provider") action = () => providerVisibility(argv, deps);
238
+ else if (sub === "selected") action = () => selected(argv, deps);
239
+ else if (sub === "context") action = () => context(argv, deps);
240
+ else if (sub === "shadow") action = () => shadow(argv, deps);
241
+ if (!action) return null;
242
+ return runCliAction(action);
243
+ }
244
+
245
+ export const MODELS_RUNTIME_USAGE = USAGE;
@@ -0,0 +1,422 @@
1
+ /**
2
+ * `ocx models` subcommand — list configured models and manage custom models.
3
+ */
4
+ import { randomUUID } from "node:crypto";
5
+ import { createInterface } from "node:readline/promises";
6
+ import { syncModelsToCodex } from "../codex/sync";
7
+ import { hasOwnProvider, isValidProviderName, loadConfig, saveConfig } from "../config";
8
+ import { canonicalizeReasoningEfforts, isDeclaredReasoningEffort, modelRecordValue } from "../reasoning-effort";
9
+ import { encodedModelIdCollides, routedSlug, slugEquals } from "../providers/slug-codec";
10
+ import { knownModelIdsForProvider } from "../router";
11
+ import { findLiveProxy } from "../server/proxy-liveness";
12
+ import { modelInList, type OcxConfig, type OcxCustomModel } from "../types";
13
+
14
+ const ADD_USAGE = "Usage: ocx models add <provider> <modelId> [--display-name <name>] [--context-window <tokens>] [--modalities text,image,audio] [--reasoning-efforts <none,minimal,low,medium,high,xhigh,max,ultra>] [--default-reasoning-effort <level>]";
15
+ const REMOVE_USAGE = "Usage: ocx models remove <customId|provider/modelId> [--yes]";
16
+ const LIST_CUSTOM_USAGE = "Usage: ocx models list-custom [--json]";
17
+ const ALLOWED_MODALITIES = new Set(["text", "image", "audio"]);
18
+
19
+ /**
20
+ * Parse and validate the reasoning flags shared by `ocx models add` (offline path).
21
+ * "-" means "inherit" and omits the field entirely; "" means an explicit empty ladder
22
+ * ("no reasoning" override, the same state the dashboard stores for the toggle-off
23
+ * checkbox set). Malformed CSV like `low,,high` or `,,` is rejected instead of being
24
+ * silently normalized. Values are canonicalized into Codex ladder order so the stored
25
+ * config matches what the API stores.
26
+ */
27
+ export function parseReasoningArgs(
28
+ reasoningEffortsValue: string | undefined,
29
+ defaultEffortValue: string | undefined,
30
+ ): { reasoningEfforts?: string[]; defaultReasoningEffort?: string; error?: string } {
31
+ if (reasoningEffortsValue === undefined && defaultEffortValue === undefined) return {};
32
+ let reasoningEfforts: string[] | undefined;
33
+ if (reasoningEffortsValue !== undefined) {
34
+ const trimmed = reasoningEffortsValue.trim();
35
+ if (trimmed === "-") {
36
+ reasoningEfforts = undefined;
37
+ } else if (trimmed === "") {
38
+ // Explicit no-reasoning override, exactly like the API's [] / the dashboard's
39
+ // uncheck-all state.
40
+ reasoningEfforts = [];
41
+ } else {
42
+ const parts = trimmed.split(",").map(value => value.trim());
43
+ if (parts.some(part => part === "")) {
44
+ return { error: "--reasoning-efforts must be comma-separated values from none, minimal, low, medium, high, xhigh, max, ultra (\"\" for no reasoning, \"-\" to inherit)" };
45
+ }
46
+ const invalid = parts.filter(value => !isDeclaredReasoningEffort(value));
47
+ if (invalid.length > 0) {
48
+ return { error: `unsupported reasoning effort: ${invalid.join(", ")} (allowed: none, minimal, low, medium, high, xhigh, max, ultra)` };
49
+ }
50
+ reasoningEfforts = canonicalizeReasoningEfforts(parts);
51
+ }
52
+ }
53
+ let defaultReasoningEffort: string | undefined;
54
+ if (defaultEffortValue !== undefined) {
55
+ const trimmed = defaultEffortValue.trim();
56
+ if (trimmed === "-") {
57
+ defaultReasoningEffort = undefined;
58
+ } else {
59
+ if (!isDeclaredReasoningEffort(trimmed)) {
60
+ return { error: `unsupported reasoning effort: ${trimmed} (allowed: none, minimal, low, medium, high, xhigh, max, ultra)` };
61
+ }
62
+ if (!reasoningEfforts || reasoningEfforts.length === 0) {
63
+ return { error: "--default-reasoning-effort requires --reasoning-efforts" };
64
+ }
65
+ if (!reasoningEfforts.includes(trimmed)) {
66
+ return { error: `--default-reasoning-effort "${trimmed}" is not in the declared reasoning efforts` };
67
+ }
68
+ defaultReasoningEffort = trimmed;
69
+ }
70
+ }
71
+ return { reasoningEfforts, defaultReasoningEffort };
72
+ }
73
+
74
+ interface ModelEntry {
75
+ provider: string;
76
+ model: string;
77
+ isDefault: boolean;
78
+ contextWindow: number | null;
79
+ inputModalities: string[] | null;
80
+ reasoningEfforts: string[] | null;
81
+ }
82
+
83
+ function collectModels(config: OcxConfig, providerFilter?: string): ModelEntry[] {
84
+ const entries: ModelEntry[] = [];
85
+ const providers = providerFilter
86
+ ? { [providerFilter]: config.providers[providerFilter] }
87
+ : config.providers;
88
+
89
+ for (const [provName, prov] of Object.entries(providers)) {
90
+ if (!prov) continue;
91
+ const seen = new Set<string>();
92
+ const contextWindows = prov.modelContextWindows ?? {};
93
+ const inputModalities = prov.modelInputModalities ?? {};
94
+ const reasoningEfforts = prov.modelReasoningEfforts ?? {};
95
+ const globalContext = prov.contextWindow ?? null;
96
+
97
+ const addModel = (model: string, isDefault: boolean) => {
98
+ if (seen.has(model)) return;
99
+ seen.add(model);
100
+
101
+ // Resolve exactly as the runtime does, or this command reports capabilities the
102
+ // proxy will not honour: `isModelTextOnly` matches noVisionModels with modelInList
103
+ // and reads modelInputModalities with modelRecordValue, so a `gpt-oss` entry covers
104
+ // `gpt-oss:120b`. A bare lookup reported that model as unclassified on every field.
105
+ // noVisionModels is checked first because `isModelTextOnly` returns true on that
106
+ // match before it ever reads modelInputModalities: a `gpt-oss` noVision entry beats
107
+ // an exact `gpt-oss:120b` entry that lists "image", and the proxy rejects the image.
108
+ const noVision = modelInList(prov.noVisionModels, model);
109
+ const modalities = noVision ? ["text"] : (modelRecordValue(inputModalities, model) ?? null);
110
+ const efforts = modelRecordValue(reasoningEfforts, model) ?? prov.reasoningEfforts ?? null;
111
+
112
+ entries.push({
113
+ provider: provName,
114
+ model,
115
+ isDefault,
116
+ contextWindow: modelRecordValue(contextWindows, model) ?? globalContext,
117
+ inputModalities: modalities,
118
+ reasoningEfforts: efforts,
119
+ });
120
+ };
121
+
122
+ // defaultModel first
123
+ if (prov.defaultModel) addModel(prov.defaultModel, true);
124
+
125
+ // models array
126
+ if (prov.models) {
127
+ for (const m of prov.models) addModel(m, m === prov.defaultModel);
128
+ }
129
+ }
130
+
131
+ return entries;
132
+ }
133
+
134
+ function consumeFlag(args: string[], flag: string): boolean {
135
+ const idx = args.indexOf(flag);
136
+ if (idx === -1) return false;
137
+ args.splice(idx, 1);
138
+ return true;
139
+ }
140
+
141
+ function consumeFlagValue(args: string[], flag: string): string | undefined {
142
+ const idx = args.indexOf(flag);
143
+ if (idx === -1 || idx + 1 >= args.length) return undefined;
144
+ const value = args[idx + 1];
145
+ args.splice(idx, 2);
146
+ return value;
147
+ }
148
+
149
+ function fail(message: string, usage?: string): never {
150
+ console.error(`Error: ${message}`);
151
+ if (usage) console.error(usage);
152
+ process.exit(1);
153
+ }
154
+
155
+ function rejectUnexpectedArgs(args: string[], usage: string): void {
156
+ if (args.length === 0) return;
157
+ const unknown = args.filter(arg => arg.startsWith("-"));
158
+ fail(
159
+ unknown.length > 0
160
+ ? `Unknown flag(s): ${unknown.join(", ")}`
161
+ : `Unexpected argument(s): ${args.join(", ")}`,
162
+ usage,
163
+ );
164
+ }
165
+
166
+ async function syncCustomModelsIfLive(): Promise<void> {
167
+ const live = await findLiveProxy();
168
+ if (!live) return;
169
+ const synced = await syncModelsToCodex(live.port).catch(error => {
170
+ console.error(`Warning: custom model saved, but catalog sync failed: ${error instanceof Error ? error.message : String(error)}`);
171
+ return null;
172
+ });
173
+ if (synced?.status === "skipped") {
174
+ console.log("Custom model saved; Codex integration is OFF, so its catalog was not changed.");
175
+ }
176
+ }
177
+
178
+ async function handleCustomAdd(args: string[]): Promise<void> {
179
+ const rest = [...args];
180
+ const provider = rest.shift()?.trim() ?? "";
181
+ const modelId = rest.shift()?.trim() ?? "";
182
+ const displayNameValue = consumeFlagValue(rest, "--display-name");
183
+ const contextWindowValue = consumeFlagValue(rest, "--context-window");
184
+ const modalitiesValue = consumeFlagValue(rest, "--modalities");
185
+ const reasoningEffortsValue = consumeFlagValue(rest, "--reasoning-efforts");
186
+ const defaultEffortValue = consumeFlagValue(rest, "--default-reasoning-effort");
187
+ rejectUnexpectedArgs(rest, ADD_USAGE);
188
+
189
+ if (!provider || !modelId) fail("provider and modelId are required", ADD_USAGE);
190
+ if (!isValidProviderName(provider)) fail(`invalid provider name "${provider}"`);
191
+
192
+ const config = loadConfig();
193
+ if (!hasOwnProvider(config.providers, provider)) {
194
+ fail(`provider "${provider}" is not configured. See: ocx provider list`);
195
+ }
196
+
197
+ const displayName = displayNameValue?.trim() || undefined;
198
+ if (displayName?.includes("/")) fail("displayName must not contain /");
199
+
200
+ let contextWindow: number | undefined;
201
+ if (contextWindowValue !== undefined) {
202
+ contextWindow = Number(contextWindowValue);
203
+ if (!Number.isInteger(contextWindow) || contextWindow <= 0) {
204
+ fail("context window must be a positive integer");
205
+ }
206
+ }
207
+
208
+ let inputModalities: string[] | undefined;
209
+ if (modalitiesValue !== undefined) {
210
+ inputModalities = modalitiesValue.split(",").map(value => value.trim());
211
+ const invalid = inputModalities.filter(value => !ALLOWED_MODALITIES.has(value));
212
+ if (inputModalities.length === 0 || invalid.length > 0) {
213
+ fail("modalities must be comma-separated values from text|image|audio");
214
+ }
215
+ inputModalities = [...new Set(inputModalities)];
216
+ }
217
+
218
+ const parsed = parseReasoningArgs(reasoningEffortsValue, defaultEffortValue);
219
+ if (parsed.error) fail(parsed.error);
220
+
221
+ const existing = config.customModels ?? [];
222
+ const slug = routedSlug(provider, modelId);
223
+ if (existing.some(model => routedSlug(model.provider, model.modelId) === slug)) {
224
+ fail(`custom model "${slug}" already exists`);
225
+ }
226
+ const known = knownModelIdsForProvider(provider, config.providers[provider], config);
227
+ if (encodedModelIdCollides(modelId, known)) {
228
+ fail(`custom model "${slug}" is ambiguous; it encodes to an existing model id`);
229
+ }
230
+
231
+ const entry: OcxCustomModel = {
232
+ id: randomUUID(),
233
+ provider,
234
+ modelId,
235
+ ...(displayName ? { displayName } : {}),
236
+ ...(contextWindow ? { contextWindow } : {}),
237
+ ...(inputModalities ? { inputModalities } : {}),
238
+ ...(parsed.reasoningEfforts ? { reasoningEfforts: parsed.reasoningEfforts } : {}),
239
+ ...(parsed.defaultReasoningEffort ? { defaultReasoningEffort: parsed.defaultReasoningEffort } : {}),
240
+ addedAt: new Date().toISOString(),
241
+ };
242
+ config.customModels = [...existing, entry];
243
+ saveConfig(config);
244
+ await syncCustomModelsIfLive();
245
+ console.log(`Added custom model ${slug} (${entry.id}).`);
246
+ }
247
+
248
+ async function confirmCustomRemoval(model: OcxCustomModel): Promise<boolean> {
249
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
250
+ fail("remove requires --yes in non-interactive mode");
251
+ }
252
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
253
+ try {
254
+ const answer = (await rl.question(`Remove custom model ${routedSlug(model.provider, model.modelId)}? [y/N] `)).trim().toLowerCase();
255
+ return answer === "y" || answer === "yes";
256
+ } finally {
257
+ rl.close();
258
+ }
259
+ }
260
+
261
+ async function handleCustomRemove(args: string[]): Promise<void> {
262
+ const rest = [...args];
263
+ const confirmed = consumeFlag(rest, "--yes");
264
+ const target = rest.shift()?.trim() ?? "";
265
+ rejectUnexpectedArgs(rest, REMOVE_USAGE);
266
+ if (!target) fail("custom model id or provider/modelId is required", REMOVE_USAGE);
267
+
268
+ const config = loadConfig();
269
+ const existing = config.customModels ?? [];
270
+ const matchingIndexes = existing.flatMap((model, index) => (
271
+ target.includes("/")
272
+ ? slugEquals(target, model.provider, model.modelId)
273
+ : model.id === target
274
+ ) ? [index] : []);
275
+ if (matchingIndexes.length === 0) fail(`custom model "${target}" not found`);
276
+ if (matchingIndexes.length > 1) {
277
+ fail(`custom model selector "${target}" is ambiguous; use the custom model id`);
278
+ }
279
+ const index = matchingIndexes[0]!;
280
+
281
+ const model = existing[index];
282
+ if (!confirmed && !(await confirmCustomRemoval(model))) {
283
+ console.log("Cancelled.");
284
+ return;
285
+ }
286
+
287
+ const next = existing.filter((_, modelIndex) => modelIndex !== index);
288
+ config.customModels = next.length > 0 ? next : undefined;
289
+ saveConfig(config);
290
+ await syncCustomModelsIfLive();
291
+ console.log(`Removed custom model ${routedSlug(model.provider, model.modelId)}.`);
292
+ }
293
+
294
+ function customModelCells(model: OcxCustomModel): string[] {
295
+ return [
296
+ model.id.slice(0, 8),
297
+ model.modelId,
298
+ model.displayName ?? "-",
299
+ model.contextWindow ? `${Math.round(model.contextWindow / 1000)}k` : "-",
300
+ model.inputModalities?.join(",") ?? "-",
301
+ model.reasoningEfforts?.join(",") ?? "-",
302
+ model.defaultReasoningEffort ?? "-",
303
+ ];
304
+ }
305
+
306
+ function printCustomModelGroup(provider: string, models: OcxCustomModel[]): void {
307
+ const rows = models.map(customModelCells);
308
+ const headers = ["ID", "MODEL", "DISPLAY NAME", "CONTEXT", "MODALITIES", "EFFORTS", "DEFAULT EFFORT"];
309
+ const widths = headers.map((header, column) => Math.max(header.length, ...rows.map(row => row[column].length)));
310
+ const line = (cells: string[]) => cells.map((cell, column) => cell.padEnd(widths[column])).join(" ");
311
+ console.log(`${provider}:`);
312
+ console.log(` ${line(headers)}`);
313
+ for (const row of rows) console.log(` ${line(row)}`);
314
+ console.log();
315
+ }
316
+
317
+ function handleCustomList(args: string[]): void {
318
+ const rest = [...args];
319
+ const wantsJson = consumeFlag(rest, "--json");
320
+ rejectUnexpectedArgs(rest, LIST_CUSTOM_USAGE);
321
+ const models = loadConfig().customModels ?? [];
322
+ if (wantsJson) {
323
+ console.log(JSON.stringify(models, null, 2));
324
+ return;
325
+ }
326
+ if (models.length === 0) {
327
+ console.log("No custom models registered.");
328
+ return;
329
+ }
330
+ const byProvider = new Map<string, OcxCustomModel[]>();
331
+ for (const model of models) {
332
+ const group = byProvider.get(model.provider) ?? [];
333
+ group.push(model);
334
+ byProvider.set(model.provider, group);
335
+ }
336
+ for (const [provider, providerModels] of byProvider) printCustomModelGroup(provider, providerModels);
337
+ }
338
+
339
+ function handleConfiguredModels(args: string[]): void {
340
+ const restArgs = [...args];
341
+ const wantsJson = consumeFlag(restArgs, "--json");
342
+ const providerFilter = consumeFlagValue(restArgs, "--provider");
343
+
344
+ if (restArgs.length > 0) {
345
+ const unknown = restArgs.filter(a => a.startsWith("-"));
346
+ if (unknown.length > 0) {
347
+ console.error(`Unknown flag(s): ${unknown.join(", ")}`);
348
+ } else {
349
+ console.error(`Unexpected argument(s): ${restArgs.join(", ")}`);
350
+ }
351
+ console.error("Usage: ocx models [--provider <name>] [--json]");
352
+ process.exit(1);
353
+ }
354
+
355
+ const config = loadConfig();
356
+
357
+ if (providerFilter && !hasOwnProvider(config.providers, providerFilter)) {
358
+ console.error(`Provider "${providerFilter}" is not configured. See: ocx provider list`);
359
+ process.exit(1);
360
+ }
361
+
362
+ const models = collectModels(config, providerFilter ?? undefined);
363
+
364
+ if (wantsJson) {
365
+ console.log(JSON.stringify({
366
+ models,
367
+ note: "Static config models only. Providers with liveModels=true may have additional models at runtime.",
368
+ }, null, 2));
369
+ return;
370
+ }
371
+
372
+ if (models.length === 0) {
373
+ console.log("No models found in configured providers.");
374
+ if (!providerFilter) console.log("Providers may discover models dynamically at runtime (liveModels).");
375
+ return;
376
+ }
377
+
378
+ // Group by provider
379
+ const byProvider = new Map<string, ModelEntry[]>();
380
+ for (const entry of models) {
381
+ const list = byProvider.get(entry.provider) ?? [];
382
+ list.push(entry);
383
+ byProvider.set(entry.provider, list);
384
+ }
385
+
386
+ for (const [provName, provModels] of byProvider) {
387
+ const isDefaultProv = provName === config.defaultProvider ? " (default provider)" : "";
388
+ console.log(`${provName}${isDefaultProv}:`);
389
+ for (const m of provModels) {
390
+ const marker = m.isDefault ? " *" : "";
391
+ const ctx = m.contextWindow ? ` (${Math.round(m.contextWindow / 1000)}k)` : "";
392
+ console.log(` ${m.model}${marker}${ctx}`);
393
+ }
394
+ console.log();
395
+ }
396
+
397
+ console.log("* = default model for provider");
398
+ console.log("Note: providers with liveModels may have additional models at runtime.");
399
+ }
400
+
401
+ export async function handleModels(args: string[]): Promise<void> {
402
+ const [subcommand, ...rest] = args;
403
+ if (subcommand === "add") {
404
+ await handleCustomAdd(rest);
405
+ return;
406
+ }
407
+ if (subcommand === "remove") {
408
+ await handleCustomRemove(rest);
409
+ return;
410
+ }
411
+ if (subcommand === "list-custom") {
412
+ handleCustomList(rest);
413
+ return;
414
+ }
415
+ if (["live", "edit", "enable", "disable", "provider", "selected", "context", "shadow"].includes(subcommand ?? "")) {
416
+ const { handleModelsRuntimeCommand } = await import("./models-runtime");
417
+ const code = await handleModelsRuntimeCommand(subcommand!, rest);
418
+ if (code !== null) process.exitCode = code;
419
+ return;
420
+ }
421
+ handleConfiguredModels(subcommand === "list" ? rest : args);
422
+ }