@iislee/opencodex 2.11.0 → 2.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (733) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +117 -22
  3. package/bin/ocx.mjs +245 -88
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-Be1sDpWw.css +1 -0
  6. package/gui/dist/assets/index-D4OKgUV4.js +114 -0
  7. package/gui/dist/index.html +2 -2
  8. package/gui/dist/provider-icons/alibaba-color.svg +1 -1
  9. package/gui/dist/provider-icons/antigravity-color.svg +1 -1
  10. package/gui/dist/provider-icons/claude-color.svg +1 -1
  11. package/gui/dist/provider-icons/cline-color.svg +16 -0
  12. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
  13. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  14. package/gui/dist/provider-icons/copilot-color.svg +1 -1
  15. package/gui/dist/provider-icons/cursor-color.svg +1 -1
  16. package/gui/dist/provider-icons/deepseek-color.svg +1 -1
  17. package/gui/dist/provider-icons/firepass-color.svg +1 -1
  18. package/gui/dist/provider-icons/fireworks-color.svg +1 -1
  19. package/gui/dist/provider-icons/gemini-color.svg +1 -1
  20. package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
  21. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
  22. package/gui/dist/provider-icons/grok.svg +1 -1
  23. package/gui/dist/provider-icons/groq-color.svg +1 -1
  24. package/gui/dist/provider-icons/huggingface-color.svg +1 -1
  25. package/gui/dist/provider-icons/kimi-color.svg +1 -1
  26. package/gui/dist/provider-icons/kiro-color.svg +2 -2
  27. package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
  28. package/gui/dist/provider-icons/mistral-color.svg +1 -1
  29. package/gui/dist/provider-icons/moonshot-color.svg +1 -1
  30. package/gui/dist/provider-icons/nvidia-color.svg +1 -1
  31. package/gui/dist/provider-icons/ollama-color.svg +1 -1
  32. package/gui/dist/provider-icons/openai.svg +1 -1
  33. package/gui/dist/provider-icons/opencode.svg +2 -1
  34. package/gui/dist/provider-icons/openrouter-color.svg +1 -1
  35. package/gui/dist/provider-icons/pi.svg +2 -2
  36. package/gui/dist/provider-icons/qianfan-color.svg +1 -1
  37. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
  38. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
  39. package/gui/dist/provider-icons/vllm-color.svg +1 -1
  40. package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
  41. package/package.json +21 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +475 -62
  44. package/src/adapters/base.ts +82 -7
  45. package/src/adapters/client-fingerprint.ts +18 -12
  46. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  47. package/src/adapters/command-code.ts +637 -0
  48. package/src/adapters/cursor/call-id.ts +44 -0
  49. package/src/adapters/cursor/catalog.ts +541 -0
  50. package/src/adapters/cursor/checkpoint-store.ts +308 -0
  51. package/src/adapters/cursor/cursor-errors.ts +144 -6
  52. package/src/adapters/cursor/discovery.ts +122 -14
  53. package/src/adapters/cursor/effort-map.ts +106 -4
  54. package/src/adapters/cursor/envelope-echo.ts +290 -0
  55. package/src/adapters/cursor/framing.ts +39 -0
  56. package/src/adapters/cursor/h2-pool.ts +123 -0
  57. package/src/adapters/cursor/http1-bidi.ts +361 -0
  58. package/src/adapters/cursor/images.ts +704 -0
  59. package/src/adapters/cursor/live-models.ts +180 -59
  60. package/src/adapters/cursor/live-transport.ts +623 -170
  61. package/src/adapters/cursor/message-mapper.ts +4 -1
  62. package/src/adapters/cursor/native-exec-common.ts +23 -2
  63. package/src/adapters/cursor/native-exec-desktop.ts +23 -0
  64. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  65. package/src/adapters/cursor/native-exec-network.ts +1 -1
  66. package/src/adapters/cursor/native-exec-shell.ts +5 -3
  67. package/src/adapters/cursor/native-exec.ts +121 -14
  68. package/src/adapters/cursor/protobuf-events.ts +829 -11
  69. package/src/adapters/cursor/protobuf-request.ts +447 -75
  70. package/src/adapters/cursor/request-builder.ts +271 -35
  71. package/src/adapters/cursor/tool-definitions.ts +252 -12
  72. package/src/adapters/cursor/tool-result-normalize.ts +115 -0
  73. package/src/adapters/cursor/transport.ts +22 -0
  74. package/src/adapters/cursor/types.ts +48 -1
  75. package/src/adapters/cursor.ts +336 -39
  76. package/src/adapters/exec-tool-result-normalize.ts +99 -0
  77. package/src/adapters/google-antigravity-replay.ts +713 -41
  78. package/src/adapters/google-antigravity-wire.ts +48 -10
  79. package/src/adapters/google-errors.ts +44 -12
  80. package/src/adapters/google-http.ts +38 -10
  81. package/src/adapters/google-tool-schema.ts +80 -15
  82. package/src/adapters/google-truncation.ts +11 -0
  83. package/src/adapters/google.ts +742 -86
  84. package/src/adapters/identity.ts +39 -6
  85. package/src/adapters/image.ts +1 -1
  86. package/src/adapters/kiro-constants.ts +27 -0
  87. package/src/adapters/kiro-errors.ts +11 -0
  88. package/src/adapters/kiro-events.ts +19 -1
  89. package/src/adapters/kiro-thinking.ts +18 -2
  90. package/src/adapters/kiro-tools.ts +65 -17
  91. package/src/adapters/kiro.ts +270 -73
  92. package/src/adapters/mimo-free.ts +17 -0
  93. package/src/adapters/openai-chat-url.ts +11 -0
  94. package/src/adapters/openai-chat.ts +1377 -344
  95. package/src/adapters/openai-responses-url.ts +16 -0
  96. package/src/adapters/openai-responses.ts +1164 -64
  97. package/src/adapters/registry.ts +175 -0
  98. package/src/adapters/responses-tool-schema.ts +67 -0
  99. package/src/adapters/run-turn-queue.ts +36 -1
  100. package/src/adapters/tool-call-id.ts +119 -0
  101. package/src/adapters/tool-catalog-nudge.ts +105 -21
  102. package/src/adapters/xai-tool-schema.ts +436 -0
  103. package/src/adapters/xai-web-search.ts +186 -0
  104. package/src/bridge.ts +512 -92
  105. package/src/chat/inbound.ts +57 -20
  106. package/src/chat/outbound.ts +97 -33
  107. package/src/claude/agents-inject.ts +40 -10
  108. package/src/claude/context-windows.ts +37 -14
  109. package/src/claude/desktop-3p.ts +243 -9
  110. package/src/claude/gateway-cache.ts +41 -4
  111. package/src/claude/inbound.ts +72 -3
  112. package/src/claude/model-info.ts +38 -15
  113. package/src/claude/outbound.ts +88 -21
  114. package/src/cli/access.ts +46 -3
  115. package/src/cli/account-api.ts +150 -19
  116. package/src/cli/account-auth.ts +33 -6
  117. package/src/cli/account-catalog-refresh.ts +14 -0
  118. package/src/cli/account-extended.ts +648 -28
  119. package/src/cli/account-main.ts +317 -0
  120. package/src/cli/account.ts +97 -19
  121. package/src/cli/agent.ts +53 -2
  122. package/src/cli/alias.ts +66 -0
  123. package/src/cli/capabilities-command.ts +94 -0
  124. package/src/cli/capabilities.ts +496 -0
  125. package/src/cli/claude-agent-startup-sync.ts +73 -0
  126. package/src/cli/claude-desktop.ts +60 -15
  127. package/src/cli/claude.ts +129 -35
  128. package/src/cli/codex-log-guard-doctor.ts +103 -0
  129. package/src/cli/codex-shim-autorestore.ts +2 -0
  130. package/src/cli/codex-shim-readiness.ts +76 -0
  131. package/src/cli/combo.ts +8 -0
  132. package/src/cli/config-command.ts +74 -10
  133. package/src/cli/dispatch.ts +821 -0
  134. package/src/cli/doctor.ts +440 -56
  135. package/src/cli/ensure-desired-integrations.ts +152 -0
  136. package/src/cli/export-command.ts +46 -20
  137. package/src/cli/help.ts +34 -274
  138. package/src/cli/index.ts +417 -528
  139. package/src/cli/init.ts +5 -17
  140. package/src/cli/inspect.ts +230 -0
  141. package/src/cli/integrations.ts +120 -2
  142. package/src/cli/lab.ts +607 -0
  143. package/src/cli/launcher-context.ts +77 -0
  144. package/src/cli/minimax.ts +497 -0
  145. package/src/cli/models-runtime.ts +130 -2
  146. package/src/cli/models.ts +118 -16
  147. package/src/cli/observe.ts +123 -11
  148. package/src/cli/opencode.ts +4 -2
  149. package/src/cli/provider-runtime.ts +34 -3
  150. package/src/cli/provider.ts +25 -3
  151. package/src/cli/ready.ts +301 -0
  152. package/src/cli/registry.ts +476 -0
  153. package/src/cli/root.ts +86 -0
  154. package/src/cli/route-policy.ts +92 -0
  155. package/src/cli/runtime-api.ts +57 -10
  156. package/src/cli/star-prompt.ts +71 -15
  157. package/src/cli/status.ts +51 -4
  158. package/src/cli/storage.ts +234 -0
  159. package/src/cli/system-command.ts +16 -0
  160. package/src/cli/system-restart-client.ts +146 -0
  161. package/src/cli/tray-proxy.ts +153 -6
  162. package/src/cli/usage-report.ts +184 -0
  163. package/src/cli/v2.ts +137 -18
  164. package/src/cli/version-skew.ts +46 -0
  165. package/src/cli.ts +1 -1
  166. package/src/clients/config-export.ts +1442 -23
  167. package/src/clients/effective-status.ts +30 -2
  168. package/src/clients/probes/cline.ts +81 -0
  169. package/src/codex/account-label.ts +35 -1
  170. package/src/codex/account-lifecycle.ts +130 -13
  171. package/src/codex/account-namespaces.ts +49 -3
  172. package/src/codex/account-pause.ts +2 -1
  173. package/src/codex/account-priority.ts +84 -0
  174. package/src/codex/account-store.ts +29 -2
  175. package/src/codex/account-usability.ts +25 -2
  176. package/src/codex/admission.ts +256 -0
  177. package/src/codex/affinity-debug.ts +162 -0
  178. package/src/codex/app-server-processes.ts +570 -107
  179. package/src/codex/app-server-restart-service.ts +232 -0
  180. package/src/codex/auth-api.ts +893 -246
  181. package/src/codex/auth-collision.ts +5 -3
  182. package/src/codex/auth-context.ts +348 -32
  183. package/src/codex/autostart-health.ts +24 -1
  184. package/src/codex/catalog/account-models.ts +67 -0
  185. package/src/codex/catalog/aggregation.ts +86 -10
  186. package/src/codex/catalog/bundled.ts +331 -33
  187. package/src/codex/catalog/effort.ts +138 -32
  188. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  189. package/src/codex/catalog/kinds.ts +2 -0
  190. package/src/codex/catalog/metadata.ts +555 -45
  191. package/src/codex/catalog/native-models.ts +75 -0
  192. package/src/codex/catalog/parsing.ts +269 -30
  193. package/src/codex/catalog/provider-fetch.ts +1626 -144
  194. package/src/codex/catalog/sync.ts +1576 -187
  195. package/src/codex/catalog-admission.ts +199 -0
  196. package/src/codex/catalog-refresh-status.ts +105 -0
  197. package/src/codex/catalog-write-serialization.ts +242 -0
  198. package/src/codex/catalog.ts +6 -3
  199. package/src/codex/codex-write-lock.ts +386 -0
  200. package/src/codex/convergence-types.ts +614 -0
  201. package/src/codex/convergence.ts +676 -0
  202. package/src/codex/coordinator-doctor.ts +332 -0
  203. package/src/codex/custom-model-catalog-migration.ts +176 -0
  204. package/src/codex/desired-state.ts +230 -0
  205. package/src/codex/desktop-app-restart.ts +355 -0
  206. package/src/codex/features.ts +636 -39
  207. package/src/codex/generation.ts +202 -0
  208. package/src/codex/history-job.ts +436 -0
  209. package/src/codex/history-lock.ts +242 -0
  210. package/src/codex/history-manifest.ts +112 -0
  211. package/src/codex/history-migration-guardian.ts +30 -24
  212. package/src/codex/history-provider.ts +1016 -235
  213. package/src/codex/history-transition.ts +105 -0
  214. package/src/codex/history-worker.ts +223 -0
  215. package/src/codex/inject-coordination.ts +373 -0
  216. package/src/codex/inject.ts +1114 -152
  217. package/src/codex/injected-marker.ts +37 -3
  218. package/src/codex/integration-record.ts +266 -0
  219. package/src/codex/internal/catalog-writer.ts +203 -0
  220. package/src/codex/internal/history-writer.ts +81 -0
  221. package/src/codex/journal.ts +66 -4
  222. package/src/codex/log-guard/inspect.ts +524 -0
  223. package/src/codex/log-guard/lock.ts +150 -0
  224. package/src/codex/log-guard/maintenance.ts +403 -0
  225. package/src/codex/log-guard/path-safety.ts +88 -0
  226. package/src/codex/log-guard/policy.ts +44 -0
  227. package/src/codex/log-guard/processes.ts +205 -0
  228. package/src/codex/log-guard/protection.ts +489 -0
  229. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  230. package/src/codex/main-account-cache.ts +24 -0
  231. package/src/codex/main-account.ts +29 -1
  232. package/src/codex/management-convergence.ts +167 -0
  233. package/src/codex/model-cache.ts +56 -10
  234. package/src/codex/model-entitlements.ts +360 -0
  235. package/src/codex/native-main-admission.ts +47 -0
  236. package/src/codex/native-main-auth-temp.ts +187 -0
  237. package/src/codex/native-main-claim.ts +178 -0
  238. package/src/codex/native-main-lock-file.ts +162 -0
  239. package/src/codex/native-main-owner.ts +329 -0
  240. package/src/codex/native-profile-api.ts +247 -0
  241. package/src/codex/native-profile-manager.ts +1531 -0
  242. package/src/codex/native-profile-processes.ts +121 -0
  243. package/src/codex/native-profile-recovery.ts +99 -0
  244. package/src/codex/native-profile-stage-store.ts +387 -0
  245. package/src/codex/native-profile-startup.ts +622 -0
  246. package/src/codex/native-profile-store.ts +855 -0
  247. package/src/codex/native-profile-types.ts +120 -0
  248. package/src/codex/native-residue.ts +675 -0
  249. package/src/codex/paths.ts +80 -1
  250. package/src/codex/plan-from-token.ts +140 -0
  251. package/src/codex/plan.ts +40 -0
  252. package/src/codex/plugins-doctor.ts +1 -1
  253. package/src/codex/pool-rotation.ts +74 -4
  254. package/src/codex/project-config-warnings.ts +20 -6
  255. package/src/codex/prompt-journal.ts +352 -0
  256. package/src/codex/prompt-layers.ts +1313 -0
  257. package/src/codex/prompt-lock.ts +143 -0
  258. package/src/codex/prompt-text-probe.ts +238 -0
  259. package/src/codex/quota-rejection.ts +298 -0
  260. package/src/codex/quota.ts +264 -21
  261. package/src/codex/refresh.ts +11 -2
  262. package/src/codex/reset-credit-recovery.ts +1044 -0
  263. package/src/codex/routing.ts +514 -94
  264. package/src/codex/runtime.ts +159 -38
  265. package/src/codex/shim.ts +1065 -31
  266. package/src/codex/subagent-model-fallback.ts +437 -43
  267. package/src/codex/sync.ts +191 -2
  268. package/src/codex/transition-state.ts +720 -0
  269. package/src/codex/upstream-host-health.ts +368 -0
  270. package/src/codex/user-identity.ts +557 -0
  271. package/src/codex/warmup.ts +187 -81
  272. package/src/codex/write-coordination.ts +114 -0
  273. package/src/combos/failover.ts +47 -0
  274. package/src/combos/index.ts +4 -0
  275. package/src/combos/request.ts +32 -0
  276. package/src/combos/types.ts +91 -9
  277. package/src/compatibility/index.ts +26 -0
  278. package/src/compatibility/manifest.ts +253 -0
  279. package/src/compatibility/openai-responses.ts +121 -0
  280. package/src/config/atomic-write.ts +219 -0
  281. package/src/config/paths.ts +40 -0
  282. package/src/config/process-state.ts +309 -0
  283. package/src/config/provider-name.ts +24 -0
  284. package/src/config/provider-validation.ts +177 -0
  285. package/src/config/rebase-provenance.ts +68 -0
  286. package/src/config.ts +1713 -709
  287. package/src/generated/compatibility-version.json +3324 -0
  288. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  289. package/src/grok/inject.ts +16 -5
  290. package/src/grok/inspect.ts +45 -0
  291. package/src/grok/sync.ts +2 -2
  292. package/src/images/loop.ts +157 -33
  293. package/src/images/plan.ts +24 -13
  294. package/src/integrations/config-io.ts +269 -0
  295. package/src/integrations/journal.ts +315 -0
  296. package/src/integrations/merge.ts +135 -0
  297. package/src/integrations/mutation-flight.ts +71 -0
  298. package/src/integrations/native/ownership-preflight.ts +202 -0
  299. package/src/integrations/omp-yaml-source.ts +358 -0
  300. package/src/integrations/owned-refresh.ts +74 -0
  301. package/src/integrations/ownership-policy.ts +160 -0
  302. package/src/integrations/ownership.ts +155 -0
  303. package/src/integrations/registry.ts +166 -0
  304. package/src/integrations/serialize.ts +314 -0
  305. package/src/integrations/state.ts +433 -0
  306. package/src/integrations/store.ts +103 -0
  307. package/src/integrations/writer-lock.ts +98 -0
  308. package/src/integrations/writer.ts +715 -0
  309. package/src/lab/artifacts/sanitize.ts +586 -0
  310. package/src/lab/artifacts/secure-fs.ts +475 -0
  311. package/src/lab/artifacts/store.ts +310 -0
  312. package/src/lab/automation/budgets.ts +78 -0
  313. package/src/lab/automation/config-persistence.ts +256 -0
  314. package/src/lab/automation/constants.ts +39 -0
  315. package/src/lab/automation/cooldown.ts +103 -0
  316. package/src/lab/automation/dispatch.ts +211 -0
  317. package/src/lab/automation/index.ts +13 -0
  318. package/src/lab/automation/orchestrator.ts +499 -0
  319. package/src/lab/automation/persistence.ts +512 -0
  320. package/src/lab/automation/planner.ts +371 -0
  321. package/src/lab/automation/policy.ts +136 -0
  322. package/src/lab/automation/queue.ts +191 -0
  323. package/src/lab/automation/recovery.ts +24 -0
  324. package/src/lab/automation/route-context.ts +21 -0
  325. package/src/lab/automation/run-key.ts +44 -0
  326. package/src/lab/automation/runs-query.ts +34 -0
  327. package/src/lab/automation/types.ts +160 -0
  328. package/src/lab/conformance/assertion.ts +325 -0
  329. package/src/lab/conformance/digest.ts +22 -0
  330. package/src/lab/conformance/executor.ts +741 -0
  331. package/src/lab/conformance/fixture-provider.ts +27 -0
  332. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  333. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  334. package/src/lab/conformance/harness-budget.ts +47 -0
  335. package/src/lab/conformance/index.ts +5 -0
  336. package/src/lab/conformance/jcs.ts +64 -0
  337. package/src/lab/conformance/json-pointer.ts +39 -0
  338. package/src/lab/conformance/manifest.ts +180 -0
  339. package/src/lab/conformance/mcp-stub.ts +179 -0
  340. package/src/lab/conformance/negative-controls.ts +164 -0
  341. package/src/lab/conformance/observation.ts +355 -0
  342. package/src/lab/conformance/runner.ts +68 -0
  343. package/src/lab/conformance/sse-normalize.ts +59 -0
  344. package/src/lab/conformance/suite-manifest.ts +78 -0
  345. package/src/lab/conformance/types.ts +214 -0
  346. package/src/lab/constants.ts +126 -0
  347. package/src/lab/digest.ts +64 -0
  348. package/src/lab/events/errors.ts +9 -0
  349. package/src/lab/events/limits.ts +117 -0
  350. package/src/lab/events/types.ts +229 -0
  351. package/src/lab/events/validate.ts +781 -0
  352. package/src/lab/fabric/constants.ts +40 -0
  353. package/src/lab/fabric/executor.ts +492 -0
  354. package/src/lab/fabric/index.ts +80 -0
  355. package/src/lab/fabric/manifest.ts +222 -0
  356. package/src/lab/fabric/observe.ts +489 -0
  357. package/src/lab/fabric/patch.ts +79 -0
  358. package/src/lab/fabric/producer-child.ts +139 -0
  359. package/src/lab/fabric/producer-isolate.ts +276 -0
  360. package/src/lab/fabric/producer-protocol.ts +61 -0
  361. package/src/lab/fabric/scratch.ts +439 -0
  362. package/src/lab/fabric/subject.ts +106 -0
  363. package/src/lab/fabric/types.ts +134 -0
  364. package/src/lab/fabric/verifier.ts +98 -0
  365. package/src/lab/index.ts +54 -0
  366. package/src/lab/ledger/artifact-refs.ts +127 -0
  367. package/src/lab/ledger/invalidation.ts +136 -0
  368. package/src/lab/ledger/purge.ts +310 -0
  369. package/src/lab/ledger/store.ts +532 -0
  370. package/src/lab/live/credential-lease.ts +53 -0
  371. package/src/lab/live/destination.ts +155 -0
  372. package/src/lab/live/executor.ts +336 -0
  373. package/src/lab/live/inert-tools.ts +56 -0
  374. package/src/lab/live/manifest.ts +85 -0
  375. package/src/lab/live/mcp-loopback.ts +57 -0
  376. package/src/lab/live/runner.ts +19 -0
  377. package/src/lab/live/sandbox.ts +61 -0
  378. package/src/lab/live/suite-manifest.ts +41 -0
  379. package/src/lab/live/transport.ts +118 -0
  380. package/src/lab/live/types.ts +197 -0
  381. package/src/lab/observe/from-conformance.ts +301 -0
  382. package/src/lab/observe/from-live.ts +117 -0
  383. package/src/lab/paths.ts +153 -0
  384. package/src/lab/projection/rebuild.ts +495 -0
  385. package/src/lab/projection/schema.ts +135 -0
  386. package/src/lab/projection/verdicts.ts +474 -0
  387. package/src/lab/projection/verification.ts +412 -0
  388. package/src/lab/public/bundle.ts +217 -0
  389. package/src/lab/public/community-authority.ts +175 -0
  390. package/src/lab/public/community-files.ts +29 -0
  391. package/src/lab/public/community.ts +479 -0
  392. package/src/lab/public/file-safety.ts +155 -0
  393. package/src/lab/public/ids.ts +26 -0
  394. package/src/lab/public/index.ts +16 -0
  395. package/src/lab/public/mutation-lock.ts +424 -0
  396. package/src/lab/public/operator.ts +353 -0
  397. package/src/lab/public/origin-purge.ts +79 -0
  398. package/src/lab/public/origin.ts +203 -0
  399. package/src/lab/public/privacy.ts +143 -0
  400. package/src/lab/public/private-file.ts +261 -0
  401. package/src/lab/public/project.ts +124 -0
  402. package/src/lab/public/purge-test-fault.ts +21 -0
  403. package/src/lab/public/purge.ts +223 -0
  404. package/src/lab/public/registry.ts +44 -0
  405. package/src/lab/public/revocation.ts +252 -0
  406. package/src/lab/public/signature.ts +243 -0
  407. package/src/lab/public/storage.ts +105 -0
  408. package/src/lab/public/strict-json.ts +206 -0
  409. package/src/lab/public/time.ts +26 -0
  410. package/src/lab/public/types.ts +172 -0
  411. package/src/lab/public/validate.ts +391 -0
  412. package/src/lab/query/catalog.ts +101 -0
  413. package/src/lab/query/connection.ts +107 -0
  414. package/src/lab/query/constants.ts +4 -0
  415. package/src/lab/query/cursor.ts +132 -0
  416. package/src/lab/query/dto-map.ts +277 -0
  417. package/src/lab/query/errors.ts +22 -0
  418. package/src/lab/query/freshness.ts +53 -0
  419. package/src/lab/query/index.ts +45 -0
  420. package/src/lab/query/latest-observation.ts +59 -0
  421. package/src/lab/query/passive-production.ts +159 -0
  422. package/src/lab/query/queries.ts +444 -0
  423. package/src/lab/query/types.ts +266 -0
  424. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  425. package/src/lab/subject/installation-salt.ts +112 -0
  426. package/src/lab/subject/protocol-subject.ts +80 -0
  427. package/src/lab/subject/route-subject.ts +74 -0
  428. package/src/lib/admin-secrets.ts +24 -0
  429. package/src/lib/app-owned-memory-stores.ts +22 -0
  430. package/src/lib/bounded-body.ts +167 -11
  431. package/src/lib/bun-runtime.ts +125 -12
  432. package/src/lib/bun-stream-caps.ts +13 -9
  433. package/src/lib/codex-restart-contract.ts +120 -0
  434. package/src/lib/config-ownership.ts +26 -2
  435. package/src/lib/destination-policy.ts +65 -1
  436. package/src/lib/errors.ts +80 -5
  437. package/src/lib/fabric-task-execution-authority.ts +7 -0
  438. package/src/lib/fabric-task-host.ts +29 -0
  439. package/src/lib/lab-activation.ts +223 -0
  440. package/src/lib/lab-live-execution-authority.ts +13 -0
  441. package/src/lib/lab-live-host.ts +30 -0
  442. package/src/lib/lab-live-pinned-sender.ts +56 -0
  443. package/src/lib/lab-live-route-production.ts +130 -0
  444. package/src/lib/lab-passive-linker-registration.ts +26 -0
  445. package/src/lib/local-management-attestation.ts +51 -0
  446. package/src/lib/local-management-capability.ts +100 -0
  447. package/src/lib/local-provider-reload-contract.ts +100 -0
  448. package/src/lib/optional-shutdown-hooks.ts +57 -0
  449. package/src/lib/package-tree-integrity.ts +101 -0
  450. package/src/lib/pinned-http.ts +145 -26
  451. package/src/lib/process-control.ts +6 -2
  452. package/src/lib/provider-outbound.ts +49 -9
  453. package/src/lib/redact.ts +419 -3
  454. package/src/lib/self-launch-argv.ts +15 -0
  455. package/src/lib/server-resource-ownership.ts +71 -0
  456. package/src/lib/service-secrets.ts +15 -0
  457. package/src/lib/shadow-call.ts +35 -4
  458. package/src/lib/sse-decoder.ts +41 -0
  459. package/src/lib/state-store-registrations.ts +10 -2
  460. package/src/lib/system-restart-contract.ts +73 -0
  461. package/src/lib/token-estimate.ts +19 -2
  462. package/src/lib/tool-argument-integers.ts +253 -0
  463. package/src/lib/translator-budget.ts +44 -0
  464. package/src/lib/upstream-http-version.ts +57 -0
  465. package/src/lib/upstream-reachability.ts +95 -0
  466. package/src/lib/upstream-retry.ts +156 -3
  467. package/src/lib/windows-atomic-replace.ts +155 -0
  468. package/src/lib/windows-elevation.ts +70 -2
  469. package/src/lib/windows-secret-acl.ts +409 -69
  470. package/src/lib/windows-service-wrappers.ts +72 -0
  471. package/src/lib/windows-text.ts +106 -0
  472. package/src/lib/windows-user-principal.ts +341 -0
  473. package/src/lib/winsw.ts +33 -5
  474. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  475. package/src/oauth/account-import/index.ts +15 -0
  476. package/src/oauth/account-import/parser.ts +83 -0
  477. package/src/oauth/account-import/registry.ts +18 -0
  478. package/src/oauth/account-import/service.ts +75 -0
  479. package/src/oauth/account-import/types.ts +91 -0
  480. package/src/oauth/anthropic.ts +12 -1
  481. package/src/oauth/callback-server.ts +30 -4
  482. package/src/oauth/chatgpt.ts +12 -1
  483. package/src/oauth/cline.ts +203 -0
  484. package/src/oauth/command-code.ts +239 -0
  485. package/src/oauth/cursor.ts +46 -5
  486. package/src/oauth/generic-account-failover.ts +231 -0
  487. package/src/oauth/google-antigravity.ts +35 -3
  488. package/src/oauth/health.ts +20 -12
  489. package/src/oauth/index.ts +462 -71
  490. package/src/oauth/key-providers.ts +25 -0
  491. package/src/oauth/kimi.ts +25 -3
  492. package/src/oauth/kiro.ts +95 -6
  493. package/src/oauth/local-token-detect.ts +13 -2
  494. package/src/oauth/log.ts +3 -1
  495. package/src/oauth/login-cli.ts +88 -28
  496. package/src/oauth/nous.ts +798 -0
  497. package/src/oauth/open-browser-choice.ts +26 -0
  498. package/src/oauth/store.ts +133 -26
  499. package/src/oauth/token-guardian.ts +9 -3
  500. package/src/oauth/types.ts +15 -0
  501. package/src/pi/models.ts +2 -2
  502. package/src/providers/alibaba-region-migration.ts +1 -1
  503. package/src/providers/antigravity-models.ts +521 -31
  504. package/src/providers/auto-compact-budget.ts +65 -0
  505. package/src/providers/base-url-choices.ts +10 -0
  506. package/src/providers/codex-capacity.ts +292 -0
  507. package/src/providers/command-code-efforts.ts +176 -0
  508. package/src/providers/context-cap.ts +26 -8
  509. package/src/providers/cursor-pool.ts +72 -0
  510. package/src/providers/default-aliases.ts +65 -0
  511. package/src/providers/derive.ts +281 -6
  512. package/src/providers/fastwire.ts +507 -0
  513. package/src/providers/free-directory.ts +10 -7
  514. package/src/providers/google-vertex-location.ts +14 -0
  515. package/src/providers/key-failover.ts +71 -3
  516. package/src/providers/label.ts +35 -2
  517. package/src/providers/model-discovery-limits.ts +16 -0
  518. package/src/providers/model-discovery.ts +115 -22
  519. package/src/providers/model-presets.ts +119 -0
  520. package/src/providers/model-rename-migration.ts +255 -0
  521. package/src/providers/model-rename-startup.ts +28 -0
  522. package/src/providers/new-model-policy.ts +146 -0
  523. package/src/providers/openai-sidecar.ts +72 -4
  524. package/src/providers/openai-tier-startup.ts +31 -2
  525. package/src/providers/openai-tiers.ts +119 -4
  526. package/src/providers/openai-virtual-models.ts +1 -0
  527. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  528. package/src/providers/provider-id-rewrite.ts +30 -0
  529. package/src/providers/quota.ts +1379 -40
  530. package/src/providers/registry.ts +1545 -112
  531. package/src/providers/request-pacing.ts +310 -0
  532. package/src/providers/service-tier.ts +277 -0
  533. package/src/providers/slug-codec.ts +94 -6
  534. package/src/providers/static-model-discovery.ts +86 -0
  535. package/src/providers/xai-responses-opt-in.ts +15 -0
  536. package/src/providers/xai-transport.ts +32 -4
  537. package/src/reasoning-effort.ts +68 -3
  538. package/src/responses/apply-patch-envelope.ts +63 -0
  539. package/src/responses/code-mode-helper-compat.ts +50 -0
  540. package/src/responses/compaction.ts +26 -1
  541. package/src/responses/custom-tool-compat.ts +384 -0
  542. package/src/responses/hosted-tool-policy.ts +9 -0
  543. package/src/responses/namespace-tool-compat.ts +435 -0
  544. package/src/responses/parser.ts +225 -38
  545. package/src/responses/provider-continuation.ts +98 -0
  546. package/src/responses/provider-opaque-metadata.ts +73 -0
  547. package/src/responses/reasoning-envelope.ts +9 -1
  548. package/src/responses/reasoning-replay-cache.ts +504 -0
  549. package/src/responses/schema.ts +12 -2
  550. package/src/responses/spill-store.ts +75 -10
  551. package/src/responses/state.ts +659 -31
  552. package/src/responses/thought-signature-replay.ts +364 -0
  553. package/src/responses/tool-search-compat.ts +301 -0
  554. package/src/responses/truncated-stop-reason.ts +60 -0
  555. package/src/responses/turn-termination.ts +107 -0
  556. package/src/router.ts +405 -31
  557. package/src/routing/analytics.ts +379 -0
  558. package/src/routing/capability.ts +244 -0
  559. package/src/routing/compatibility/assemble.ts +73 -0
  560. package/src/routing/compatibility/behavior.ts +278 -0
  561. package/src/routing/compatibility/catalog.ts +99 -0
  562. package/src/routing/compatibility/endpoint.ts +52 -0
  563. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  564. package/src/routing/compatibility/policy.ts +181 -0
  565. package/src/routing/compatibility/provider-slot.ts +56 -0
  566. package/src/routing/compatibility/reader.ts +110 -0
  567. package/src/routing/compatibility/subject.ts +191 -0
  568. package/src/routing/compatibility/types.ts +64 -0
  569. package/src/routing/compatibility/version.ts +104 -0
  570. package/src/routing/cost.ts +77 -0
  571. package/src/routing/evaluator.ts +495 -0
  572. package/src/routing/health.ts +412 -0
  573. package/src/routing/history/cursor.ts +43 -0
  574. package/src/routing/history/indexer.ts +605 -0
  575. package/src/routing/history/schema.ts +72 -0
  576. package/src/routing/profile-namespace.ts +15 -0
  577. package/src/routing/profile.ts +547 -0
  578. package/src/routing/quota.ts +155 -0
  579. package/src/routing/request-evidence.ts +45 -0
  580. package/src/routing/trace.ts +776 -0
  581. package/src/server/adapter-resolve.ts +2 -29
  582. package/src/server/auth-cors.ts +289 -48
  583. package/src/server/background-lifecycle.ts +182 -0
  584. package/src/server/chat-completions.ts +154 -72
  585. package/src/server/chat-native-sse.ts +331 -0
  586. package/src/server/chat-native.ts +445 -0
  587. package/src/server/claude-messages.ts +160 -44
  588. package/src/server/direct-local-http.ts +347 -0
  589. package/src/server/effort-policy.ts +18 -0
  590. package/src/server/github-copilot-responses-repair.ts +338 -0
  591. package/src/server/gui-static.ts +39 -10
  592. package/src/server/images.ts +94 -12
  593. package/src/server/index.ts +1021 -190
  594. package/src/server/lifecycle.ts +336 -14
  595. package/src/server/live.ts +136 -17
  596. package/src/server/local-management-read-client.ts +90 -0
  597. package/src/server/local-provider-reload-client.ts +137 -0
  598. package/src/server/management/agent-settings-routes.ts +433 -116
  599. package/src/server/management/api-key-usage.ts +31 -5
  600. package/src/server/management/body.ts +6 -0
  601. package/src/server/management/codex-prompt-routes.ts +570 -0
  602. package/src/server/management/combo-routes.ts +64 -25
  603. package/src/server/management/config-routes.ts +511 -51
  604. package/src/server/management/context.ts +89 -2
  605. package/src/server/management/integration-routes.ts +498 -0
  606. package/src/server/management/lab-automation-routes.ts +206 -0
  607. package/src/server/management/lab-routes.ts +563 -0
  608. package/src/server/management/logs-usage-routes.ts +127 -52
  609. package/src/server/management/model-routes.ts +461 -133
  610. package/src/server/management/model-rows.ts +167 -0
  611. package/src/server/management/native-integration-routes.ts +770 -0
  612. package/src/server/management/oauth-account-routes.ts +90 -8
  613. package/src/server/management/provider-capability-config.ts +48 -0
  614. package/src/server/management/provider-routes.ts +836 -159
  615. package/src/server/management/request-history-routes.ts +191 -0
  616. package/src/server/management/route-registry.ts +332 -0
  617. package/src/server/management/routing-analytics-routes.ts +74 -0
  618. package/src/server/management/routing-profile-routes.ts +380 -0
  619. package/src/server/management/shared.ts +27 -11
  620. package/src/server/management/sidebar-routes.ts +47 -31
  621. package/src/server/management/storage-log-guard-routes.ts +186 -0
  622. package/src/server/management/sync-response.ts +69 -0
  623. package/src/server/management/system-restart.ts +289 -33
  624. package/src/server/management/system-routes.ts +77 -0
  625. package/src/server/management/usage-summary-cache.ts +9 -1
  626. package/src/server/management/vision-sidecar-options.ts +167 -0
  627. package/src/server/management/web-search-sidecar-options.ts +120 -0
  628. package/src/server/management-api.ts +126 -23
  629. package/src/server/management-auth.ts +220 -5
  630. package/src/server/passive-route-linker.ts +66 -0
  631. package/src/server/port-reclaim.ts +1 -1
  632. package/src/server/ports.ts +41 -1
  633. package/src/server/proxy-liveness.ts +161 -10
  634. package/src/server/readiness.ts +99 -0
  635. package/src/server/relay-eager.ts +221 -54
  636. package/src/server/relay.ts +479 -87
  637. package/src/server/request-decompress.ts +113 -6
  638. package/src/server/request-log-conversation.ts +51 -0
  639. package/src/server/request-log.ts +298 -31
  640. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  641. package/src/server/responses/agent-task-recovery.ts +465 -0
  642. package/src/server/responses/codex-auth-error.ts +55 -0
  643. package/src/server/responses/collaboration.ts +239 -36
  644. package/src/server/responses/combo-stream-preflight.ts +178 -0
  645. package/src/server/responses/compact.ts +444 -72
  646. package/src/server/responses/core.ts +3579 -436
  647. package/src/server/responses/empty-completion-guard.ts +333 -0
  648. package/src/server/responses/encrypted-payload.ts +62 -39
  649. package/src/server/responses/fetch-helpers.ts +89 -99
  650. package/src/server/responses/input-admission.ts +187 -0
  651. package/src/server/responses/pacing-overload.ts +13 -0
  652. package/src/server/responses/passthrough-error.ts +33 -9
  653. package/src/server/responses/policy-fallback.ts +178 -0
  654. package/src/server/responses/responses-field-backfill.ts +343 -0
  655. package/src/server/responses/terminal-guard.ts +26 -5
  656. package/src/server/responses/upstream-error.ts +5 -0
  657. package/src/server/responses/ws-upstream.ts +381 -0
  658. package/src/server/responses-custom-tool-repair.ts +363 -0
  659. package/src/server/responses-item-id-repair.ts +54 -6
  660. package/src/server/responses-json-events.ts +90 -0
  661. package/src/server/responses-model-rewrite.ts +29 -0
  662. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  663. package/src/server/responses-snapshot-repair.ts +621 -0
  664. package/src/server/responses-terminal-repair.ts +363 -0
  665. package/src/server/responses-tool-search-repair.ts +267 -0
  666. package/src/server/responses-undeclared-tool-guard.ts +376 -0
  667. package/src/server/responses.ts +18 -2
  668. package/src/server/search.ts +78 -13
  669. package/src/server/sse-frame-buffer.ts +319 -0
  670. package/src/server/sse-payload-rewrite.ts +110 -22
  671. package/src/server/startup-action-control.ts +8 -1
  672. package/src/server/startup-health-cache.ts +19 -1
  673. package/src/server/system-env.ts +80 -9
  674. package/src/server/ws-bridge.ts +53 -40
  675. package/src/service-manager-probe.ts +892 -0
  676. package/src/service.ts +1153 -94
  677. package/src/sidecar/auth.ts +92 -0
  678. package/src/sidecar/candidates.ts +83 -0
  679. package/src/storage/cleanup.ts +2 -2
  680. package/src/storage/policy-job.ts +14 -4
  681. package/src/storage/policy.ts +88 -23
  682. package/src/storage/scanner.ts +1 -1
  683. package/src/storage/worker-lifecycle.ts +14 -14
  684. package/src/tray/windows-tray.ps1 +83 -9
  685. package/src/tray/windows.ts +43 -16
  686. package/src/types/accounts.ts +37 -0
  687. package/src/types/config.ts +911 -0
  688. package/src/types/provider.ts +614 -0
  689. package/src/types/request.ts +397 -0
  690. package/src/types/tools.ts +236 -0
  691. package/src/types/wire.ts +80 -0
  692. package/src/types.ts +107 -1237
  693. package/src/update/index.ts +37 -23
  694. package/src/update/job.ts +445 -68
  695. package/src/update/notify.ts +12 -6
  696. package/src/update/npm-cache-preflight.d.mts +47 -0
  697. package/src/update/npm-cache-preflight.mjs +201 -0
  698. package/src/update/transactional-install.d.mts +22 -0
  699. package/src/update/transactional-install.mjs +266 -0
  700. package/src/usage/cost.ts +0 -0
  701. package/src/usage/expected-prices.ts +287 -16
  702. package/src/usage/log.ts +666 -50
  703. package/src/usage/summary.ts +388 -17
  704. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  705. package/src/usage/user-cost-overlays.ts +314 -0
  706. package/src/vision/anthropic-describe.ts +10 -6
  707. package/src/vision/backends.ts +97 -0
  708. package/src/vision/describe.ts +27 -16
  709. package/src/vision/eligibility.ts +250 -0
  710. package/src/vision/index.ts +238 -24
  711. package/src/vision/reasoning.ts +55 -0
  712. package/src/vision/routed-describe.ts +175 -0
  713. package/src/vision/timeout-bounds.ts +9 -0
  714. package/src/web-search/anthropic-executor.ts +13 -7
  715. package/src/web-search/backends.ts +108 -0
  716. package/src/web-search/exa-executor.ts +119 -0
  717. package/src/web-search/executor.ts +21 -6
  718. package/src/web-search/gemini-executor.ts +141 -0
  719. package/src/web-search/index.ts +150 -15
  720. package/src/web-search/loop.ts +284 -54
  721. package/src/web-search/parse.ts +125 -30
  722. package/src/web-search/sources.ts +60 -0
  723. package/src/web-search/xai-executor.ts +219 -0
  724. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  725. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  726. package/gui/dist/provider-icons/antigravity.svg +0 -1
  727. package/gui/dist/provider-icons/claude.svg +0 -1
  728. package/gui/dist/provider-icons/copilot.svg +0 -1
  729. package/gui/dist/provider-icons/cursor.svg +0 -2
  730. package/gui/dist/provider-icons/gemini.svg +0 -1
  731. package/gui/dist/provider-icons/grok-color.svg +0 -1
  732. package/gui/dist/provider-icons/kiro.svg +0 -14
  733. package/src/cli/internal-dispatch.ts +0 -20
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Which backends may DESCRIBE images for the vision sidecar, and which
3
+ * candidate rows each can describe through (#2188 vision rules; roadmap 170
4
+ * REVISED: the "routed" backend).
5
+ *
6
+ * A SIBLING of WEB_SEARCH_BACKENDS, not a shared table: vision has no
7
+ * per-model probe (rule 2 is "− provably text-only", enforced by
8
+ * modelAcceptsImageInput, not here), carries per-side baseline models, and
9
+ * excludes non-LLM backends like exa.
10
+ *
11
+ * Three backends, not one per provider: "openai" and "anthropic" carry auth
12
+ * semantics loopback routing cannot replicate (forwarded ChatGPT headers,
13
+ * OAuth beta fences) and their defaults must not drift. Every OTHER
14
+ * picker-visible provider row reaches the describer through "routed" — a
15
+ * loopback self-fetch of the proxy's own /v1/chat/completions, where the
16
+ * router and adapters already speak each provider's wire. That is what makes
17
+ * this table closed under provider growth: a new provider needs no new
18
+ * describe executor.
19
+ */
20
+ import type { OcxConfig } from "../types";
21
+ import type { SidecarAuthState } from "../sidecar/auth";
22
+ import { listOpenAiForwardSidecarCandidates } from "../providers/openai-sidecar";
23
+ import type { VisionCandidateModel, VisionSidecarBackend } from "./eligibility";
24
+
25
+ export interface VisionBackendDescriptor {
26
+ backend: VisionSidecarBackend;
27
+ /** Liveness signal for this backend. */
28
+ isActive(auth: SidecarAuthState, config: OcxConfig): boolean;
29
+ /** Which candidate rows this backend's describe executor can actually run. */
30
+ candidateMatch(candidate: VisionCandidateModel, auth: SidecarAuthState): boolean;
31
+ /**
32
+ * Default entry for this side: cheap, image-capable, present in every
33
+ * deployment. Only the two universal sides carry one — "routed" has no
34
+ * universal model to name.
35
+ */
36
+ baseline?: string;
37
+ /** Stable option ordering (baselines first within a side). */
38
+ rank: number;
39
+ }
40
+
41
+ export const VISION_BACKENDS: readonly VisionBackendDescriptor[] = [
42
+ {
43
+ backend: "openai",
44
+ // The OpenAI describer needs a CANONICAL ChatGPT forward provider, not
45
+ // merely a provider keyed "openai" — same predicate the runtime sidecar
46
+ // resolver uses. Deliberately NOT auth.isCodexAuth: tightening to a live
47
+ // credential here would change which options a fresh install sees, and
48
+ // the options list is a suggestion surface, not the write gate.
49
+ isActive: (_auth, config) => listOpenAiForwardSidecarCandidates(config).length > 0,
50
+ candidateMatch: candidate => candidate.native === true || candidate.provider === "openai",
51
+ baseline: "gpt-5.6-luna",
52
+ rank: 0,
53
+ },
54
+ {
55
+ backend: "anthropic",
56
+ isActive: auth => auth.isAnthropicAuth,
57
+ // The runtime dispatches through exactly ONE Anthropic provider — the
58
+ // resolved OAuth row. Same-adapter keyed rows are unreachable (see
59
+ // visionBackendForCandidate's original stance).
60
+ candidateMatch: (candidate, auth) => candidate.provider === auth.anthropicProviderName,
61
+ baseline: "claude-haiku-4-5",
62
+ rank: 1,
63
+ },
64
+ {
65
+ backend: "routed",
66
+ // Always offered: options only materialize when a matching picker row
67
+ // exists, and the row's own provider config is the liveness signal — the
68
+ // loopback request fails closed through ordinary routing errors.
69
+ isActive: () => true,
70
+ // Any row the other two executors do NOT own. Auth-slot rows are
71
+ // entitlements of the openai/anthropic sides and never route here.
72
+ candidateMatch: (candidate, auth) =>
73
+ candidate.native !== true
74
+ && candidate.provider !== "openai"
75
+ && candidate.provider !== auth.anthropicProviderName,
76
+ rank: 2,
77
+ },
78
+ ];
79
+
80
+ export function visionBackendDescriptor(backend: VisionSidecarBackend): VisionBackendDescriptor {
81
+ const descriptor = VISION_BACKENDS.find(entry => entry.backend === backend);
82
+ if (!descriptor) throw new Error(`unknown vision backend "${backend}"`);
83
+ return descriptor;
84
+ }
85
+
86
+ /**
87
+ * The active backend set for option generation. Falls back to the two
88
+ * UNIVERSAL sides when neither is active (fresh install: picker stays
89
+ * populated, permissive-unknown rule); "routed" is active by construction.
90
+ */
91
+ export function activeVisionBackends(auth: SidecarAuthState, config: OcxConfig): VisionSidecarBackend[] {
92
+ const active = VISION_BACKENDS.filter(entry => entry.isActive(auth, config)).map(entry => entry.backend);
93
+ return active.includes("openai") || active.includes("anthropic")
94
+ ? active
95
+ : ["openai", "anthropic", ...active.filter(backend => backend === "routed")];
96
+ }
97
+
@@ -1,4 +1,5 @@
1
1
  import type { OcxProviderConfig } from "../types";
2
+ import type { VisionReasoningEffort } from "../reasoning-effort";
2
3
  import { FORWARD_HEADERS } from "../adapters/openai-responses";
3
4
  import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
4
5
  import { redactSecretString } from "../lib/redact";
@@ -9,6 +10,7 @@ import type { SidecarOutcomeRecorder } from "../web-search/executor";
9
10
 
10
11
  export interface VisionSettings {
11
12
  model: string;
13
+ reasoning: VisionReasoningEffort;
12
14
  timeoutMs: number;
13
15
  }
14
16
 
@@ -77,9 +79,9 @@ export async function describeImage(
77
79
  "verbatim, and note UI/layout, colors, branding/logos, charts, and notable details. Focus on " +
78
80
  "what's relevant to the user's request. Output only the description.",
79
81
  input: [{ type: "message", role: "user", content }],
80
- reasoning: { effort: "low" },
81
- // The ChatGPT (codex) backend rejects `max_output_tokens` ("Unsupported parameter"); the
82
- // description is clamped downstream (DESC_MAX_CHARS) instead.
82
+ reasoning: { effort: settings.reasoning },
83
+ // The ChatGPT (codex) backend rejects `max_output_tokens` ("Unsupported parameter"); the shared
84
+ // SSE parser bounds raw response bytes before DESC_MAX_CHARS applies its display clamp.
83
85
  store: false,
84
86
  stream: true,
85
87
  };
@@ -93,29 +95,38 @@ export async function describeImage(
93
95
  headers,
94
96
  body: JSON.stringify(body),
95
97
  signal: linkedSignal.signal,
98
+ // Credential-bearing: do not follow a cross-origin 3xx. Bun strips `Authorization`
99
+ // across origins but forwards nonstandard headers such as `chatgpt-account-id`,
100
+ // `session_id`, and `x-codex-turn-metadata` to the redirect target.
101
+ redirect: "manual",
96
102
  }),
97
103
  { abortSignal: linkedSignal.signal, label: "vision-sidecar" },
98
104
  );
99
- recordOutcome?.(res.status);
100
- if (!res.ok) {
101
- const t = await res.text().catch(() => "");
102
- console.warn(`[vision] sidecar HTTP ${res.status} (${Date.now() - t0}ms)`);
103
- return { text: "", error: `vision sidecar HTTP ${res.status}: ${redactSecretString(t.slice(0, 200))}` };
104
- }
105
105
  const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
106
- let parsed;
107
106
  try {
108
- parsed = await parseSidecarSSE(res);
107
+ if (!res.ok) {
108
+ recordOutcome?.(res.status);
109
+ const t = await res.text().catch(() => "");
110
+ console.warn(`[vision] sidecar HTTP ${res.status} (${Date.now() - t0}ms)`);
111
+ return { text: "", error: `vision sidecar HTTP ${res.status}: ${redactSecretString(t.slice(0, 200))}` };
112
+ }
113
+ const parsed = await parseSidecarSSE(res);
114
+ if (linkedSignal.signal.aborted) throw linkedSignal.signal.reason;
115
+ recordOutcome?.(res.status);
116
+ // The backend can return HTTP 200 then stream a `response.failed`/`error` event with no text;
117
+ // surface that as a describe error instead of an empty (silently-blank) description.
118
+ if (!parsed.text.trim() && parsed.error) return { text: "", error: parsed.error };
119
+ return { text: parsed.text };
109
120
  } finally {
110
121
  detachBodyGuard();
111
122
  }
112
- // The backend can return HTTP 200 then stream a `response.failed`/`error` event with no text;
113
- // surface that as a describe error instead of an empty (silently-blank) description.
114
- if (!parsed.text.trim() && parsed.error) return { text: "", error: parsed.error };
115
- return { text: parsed.text };
116
123
  } catch (e) {
117
- recordOutcome?.(e instanceof Error && e.name === "TimeoutError" ? "timeout" : "connect_error");
118
124
  const kind = e instanceof Error && e.name === "TimeoutError" ? "timeout" : "connect_error";
125
+ const callerAborted = abortSignal?.aborted === true
126
+ && linkedSignal.signal.aborted
127
+ && linkedSignal.signal.reason === abortSignal.reason
128
+ && e === linkedSignal.signal.reason;
129
+ recordOutcome?.(callerAborted ? "connect_neutral" : kind);
119
130
  console.warn(`[vision] sidecar ${kind} (${Date.now() - t0}ms)`);
120
131
  return { text: "", error: e instanceof Error ? e.message : String(e) };
121
132
  } finally {
@@ -0,0 +1,250 @@
1
+ /**
2
+ * Which models may serve AS the vision sidecar (the describer), as opposed to the
3
+ * models the sidecar describes FOR.
4
+ *
5
+ * Three rules make this non-obvious, and all are load-bearing:
6
+ *
7
+ * 1. `provider.noVisionModels` marks models the proxy describes images for, and
8
+ * `applyProviderConfigHints` deliberately ADDS "image" to their advertised
9
+ * input modalities so the Codex app does not block the attachment client-side.
10
+ * A blind model therefore advertises image input. Membership in that list is a
11
+ * hard disqualifier here, checked BEFORE the modality list it rewrote.
12
+ * 2. The catalog enriches configured providers from the registry before it
13
+ * applies that rule. Eligibility must use the same effective provider policy,
14
+ * including a `noVisionModels` list learned after the config was persisted.
15
+ * 3. Catalog rows frequently omit `inputModalities` entirely (the live
16
+ * `/api/models` response carries none for either openai or anthropic rows).
17
+ * Unknown is not zero: when no source can speak, the model stays eligible
18
+ * rather than silently vanishing from the picker.
19
+ * Native OpenAI metadata is likewise authoritative only for a native row or
20
+ * the canonical OpenAI provider; a routed row with the same id owns its own
21
+ * explicit modalities.
22
+ */
23
+ import { modelInList, type OcxConfig, type OcxProviderConfig } from "../types";
24
+ import { getModelMetadataCaseInsensitive, resolveMetadataProvider } from "../generated/model-metadata";
25
+ import { nativeInputModalities } from "../codex/catalog/metadata";
26
+ import { SUPPORTED_NATIVE_OPENAI_SLUGS } from "../codex/catalog/native-models";
27
+ import { enrichProviderFromRegistry } from "../providers/derive";
28
+
29
+ /**
30
+ * The wire protocols `planVisionSidecar` can dispatch to (#2188 roadmap 170
31
+ * REVISED). "routed" describes through the proxy's OWN router via loopback —
32
+ * one executor for every non-forward, non-OAuth-Anthropic provider row.
33
+ */
34
+ export type VisionSidecarBackend = "openai" | "anthropic" | "routed";
35
+
36
+ /** The two sides every deployment has; also the empty-auth fallback set. */
37
+ export type UniversalVisionBackend = "openai" | "anthropic";
38
+
39
+ /**
40
+ * Default entry per backend: cheap, image-capable, and present in every deployment. Offered
41
+ * whenever its side is enabled, and withheld only when that provider explicitly lists it as a
42
+ * model the sidecar describes FOR — never merely because a metadata table stayed silent.
43
+ *
44
+ * Keyed by the UNIVERSAL subset on purpose (roadmap 170, audit blocker A):
45
+ * xai/gemini are auth-gated sides whose catalogs are present whenever the side
46
+ * is, so they carry no baseline, and a narrow-key total record documents that
47
+ * without sprinkling non-null assertions at the consumers.
48
+ */
49
+ export const BASELINE_VISION_MODELS: Record<UniversalVisionBackend, string> = {
50
+ openai: "gpt-5.6-luna",
51
+ anthropic: "claude-haiku-4-5",
52
+ };
53
+
54
+ export interface VisionCandidateModel {
55
+ provider: string;
56
+ id: string;
57
+ inputModalities?: string[];
58
+ native?: boolean;
59
+ }
60
+
61
+ export interface VisionModelOption {
62
+ value: string;
63
+ label: string;
64
+ backend: VisionSidecarBackend;
65
+ /** True when the row is a guaranteed baseline rather than a catalog discovery. */
66
+ baseline?: boolean;
67
+ }
68
+
69
+ type EnrichedProviderCache = Map<string, OcxProviderConfig>;
70
+
71
+ function advertisesImageInput(modalities: readonly string[] | undefined): boolean | undefined {
72
+ if (!modalities || modalities.length === 0) return undefined;
73
+ return modalities.includes("image");
74
+ }
75
+
76
+ /** Vendor-table modalities for a routed row, or undefined when the table has no opinion. */
77
+ function metadataImageInput(provider: string, modelId: string): boolean | undefined {
78
+ const resolved = resolveMetadataProvider(provider) ?? provider;
79
+ const meta = getModelMetadataCaseInsensitive(resolved, modelId);
80
+ return advertisesImageInput(meta?.input);
81
+ }
82
+
83
+ /**
84
+ * Mirrors the catalog's registry enrichment without mutating saved configuration. The picker
85
+ * checks many rows from one provider, so its caller shares this small call-local cache.
86
+ */
87
+ function enrichedProviderForVision(
88
+ config: Pick<OcxConfig, "providers">,
89
+ providerName: string,
90
+ cache: EnrichedProviderCache,
91
+ ): OcxProviderConfig | undefined {
92
+ const cached = cache.get(providerName);
93
+ if (cached) return cached;
94
+ const configured = config.providers?.[providerName];
95
+ if (!configured) return undefined;
96
+ const enriched = structuredClone(configured);
97
+ enrichProviderFromRegistry(providerName, enriched);
98
+ cache.set(providerName, enriched);
99
+ return enriched;
100
+ }
101
+
102
+ function isVisionSidecarConsumerWithCache(
103
+ config: Pick<OcxConfig, "providers">,
104
+ providerName: string,
105
+ modelId: string,
106
+ cache: EnrichedProviderCache,
107
+ ): boolean {
108
+ return modelInList(enrichedProviderForVision(config, providerName, cache)?.noVisionModels, modelId);
109
+ }
110
+
111
+ /**
112
+ * Is this model listed as one the sidecar describes FOR? Such a model cannot be
113
+ * the describer, and its advertised modalities are untrustworthy.
114
+ */
115
+ export function isVisionSidecarConsumer(config: Pick<OcxConfig, "providers">, providerName: string, modelId: string): boolean {
116
+ return isVisionSidecarConsumerWithCache(config, providerName, modelId, new Map());
117
+ }
118
+
119
+ /**
120
+ * Can this model accept an image on the wire? Sources are consulted in descending
121
+ * trustworthiness; the first that speaks wins. `undefined` means nothing knows,
122
+ * which callers treat as eligible.
123
+ */
124
+ export function modelAcceptsImageInput(
125
+ config: Pick<OcxConfig, "providers">,
126
+ candidate: VisionCandidateModel,
127
+ ): boolean | undefined {
128
+ return modelAcceptsImageInputWithCache(config, candidate, new Map());
129
+ }
130
+
131
+ function modelAcceptsImageInputWithCache(
132
+ config: Pick<OcxConfig, "providers">,
133
+ candidate: VisionCandidateModel,
134
+ cache: EnrichedProviderCache,
135
+ ): boolean | undefined {
136
+ if (isVisionSidecarConsumerWithCache(config, candidate.provider, candidate.id, cache)) return false;
137
+ if (candidate.native === true || (candidate.provider === "openai" && SUPPORTED_NATIVE_OPENAI_SLUGS.has(candidate.id))) {
138
+ return advertisesImageInput(nativeInputModalities(candidate.id)) ?? true;
139
+ }
140
+ const fromRow = advertisesImageInput(candidate.inputModalities);
141
+ if (fromRow !== undefined) return fromRow;
142
+ return metadataImageInput(candidate.provider, candidate.id);
143
+ }
144
+
145
+ /** Eligible = not a sidecar consumer, and not positively known to be text-only. */
146
+ export function isVisionEligibleModel(
147
+ config: Pick<OcxConfig, "providers">,
148
+ candidate: VisionCandidateModel,
149
+ ): boolean {
150
+ return isVisionEligibleModelWithCache(config, candidate, new Map());
151
+ }
152
+
153
+ function isVisionEligibleModelWithCache(
154
+ config: Pick<OcxConfig, "providers">,
155
+ candidate: VisionCandidateModel,
156
+ cache: EnrichedProviderCache,
157
+ ): boolean {
158
+ return modelAcceptsImageInputWithCache(config, candidate, cache) !== false;
159
+ }
160
+
161
+ /** Which executor can describe through this row. */
162
+ export function visionBackendForCandidate(
163
+ config: Pick<OcxConfig, "providers">,
164
+ candidate: VisionCandidateModel,
165
+ anthropicProviderName?: string,
166
+ ): VisionSidecarBackend | undefined {
167
+ if (candidate.native || candidate.provider === "openai") return "openai";
168
+ // The runtime dispatches through exactly ONE Anthropic provider — the enabled OAuth row
169
+ // with a healthy active account that `findAnthropicVisionProvider` picks. Speaking the
170
+ // Messages wire is not enough: a key-auth row of the same adapter is unreachable, and an
171
+ // option that cannot be dispatched is worse than a missing one, because selecting it fails
172
+ // at describe time rather than at pick time.
173
+ if (anthropicProviderName !== undefined && candidate.provider === anthropicProviderName) {
174
+ return "anthropic";
175
+ }
176
+ // EVERY other provider row describes through the proxy's own router
177
+ // (roadmap 170 revised): the loopback executor covers all provider wires,
178
+ // so no row is left without an executor.
179
+ return "routed";
180
+ }
181
+
182
+ function baselineCandidate(
183
+ backend: UniversalVisionBackend,
184
+ anthropicProviderName: string | undefined,
185
+ ): VisionCandidateModel {
186
+ return {
187
+ provider: backend === "openai" ? "openai" : anthropicProviderName ?? "anthropic",
188
+ id: BASELINE_VISION_MODELS[backend],
189
+ // Both baselines are known image-capable. This makes their only exclusion path the
190
+ // provider's explicit consumer list, never a silent or stale metadata table.
191
+ inputModalities: ["text", "image"],
192
+ };
193
+ }
194
+
195
+ /**
196
+ * The picker's option list: every eligible row reachable by an enabled
197
+ * executor, plus each enabled universal side's baseline unless that baseline
198
+ * is explicitly excluded, de-duplicated and stably ordered (side rank order,
199
+ * baselines first within a side). Anthropic rows must belong to the OAuth
200
+ * provider that would actually execute them, so `anthropicProviderName` is
201
+ * what makes that side's catalog rows eligible at all; xai/gemini rows map by
202
+ * provider identity and appear only when the caller enabled those backends.
203
+ *
204
+ * This is the SUGGESTION list (narrow): it emits only rows an executor can reach
205
+ * and some source has heard of. It is deliberately NOT the same set as the write
206
+ * gate. `modelAcceptsImageInput` answers "can we prove this model cannot see?"
207
+ * and is the only input to rejection. Absence from this list must never imply
208
+ * rejection — an unknown id stays eligible via the undefined → eligible fallback.
209
+ *
210
+ * De-duplication is by BARE model id, first eligible row wins. Two providers of
211
+ * the same adapter family can expose the same id; they resolve to the same
212
+ * backend, and only `value` reaches the client, so first-wins costs nothing.
213
+ */
214
+ export function visionEligibleModelOptions(
215
+ config: Pick<OcxConfig, "providers">,
216
+ candidates: readonly VisionCandidateModel[],
217
+ enabledBackends: readonly VisionSidecarBackend[],
218
+ anthropicProviderName?: string,
219
+ ): VisionModelOption[] {
220
+ const enabled = new Set(enabledBackends);
221
+ const byValue = new Map<string, VisionModelOption>();
222
+ const enrichedProviders: EnrichedProviderCache = new Map();
223
+
224
+ for (const backend of Object.keys(BASELINE_VISION_MODELS) as UniversalVisionBackend[]) {
225
+ if (!enabled.has(backend)) continue;
226
+ const candidate = baselineCandidate(backend, anthropicProviderName);
227
+ if (!isVisionEligibleModelWithCache(config, candidate, enrichedProviders)) continue;
228
+ const id = candidate.id;
229
+ byValue.set(id, { value: id, label: id, backend, baseline: true });
230
+ }
231
+ for (const candidate of candidates) {
232
+ const backend = visionBackendForCandidate(config, candidate, anthropicProviderName);
233
+ if (!backend || !enabled.has(backend)) continue;
234
+ if (!isVisionEligibleModelWithCache(config, candidate, enrichedProviders)) continue;
235
+ // Routed rows carry NAMESPACED values ("provider/model") so the loopback
236
+ // dispatch is unambiguous under routeModel; the legacy sides keep bare ids
237
+ // (GUI current-value compatibility, and the forward/OAuth executors POST
238
+ // the string verbatim). De-dup stays keyed by the emitted value.
239
+ const value = backend === "routed" ? `${candidate.provider}/${candidate.id}` : candidate.id;
240
+ if (byValue.has(value)) continue;
241
+ byValue.set(value, { value, label: value, backend });
242
+ }
243
+
244
+ // Two slots per side (baseline first), ranked openai < anthropic < routed
245
+ // so widening the union appends rather than interleaves (roadmap 170).
246
+ const sideRank: Record<VisionSidecarBackend, number> = { openai: 0, anthropic: 2, routed: 4 };
247
+ const order = (option: VisionModelOption) =>
248
+ sideRank[option.backend] + (option.baseline ? 0 : 1);
249
+ return [...byValue.values()].sort((a, b) => order(a) - order(b) || a.value.localeCompare(b.value));
250
+ }