@iislee/opencodex 2.11.0 → 2.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (675) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +114 -19
  3. package/bin/ocx.mjs +164 -36
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-BF38heuV.js +104 -0
  6. package/gui/dist/assets/index-DMiI18Kv.css +1 -0
  7. package/gui/dist/index.html +2 -2
  8. package/gui/dist/provider-icons/alibaba-color.svg +1 -1
  9. package/gui/dist/provider-icons/antigravity-color.svg +1 -1
  10. package/gui/dist/provider-icons/claude-color.svg +1 -1
  11. package/gui/dist/provider-icons/cline-color.svg +16 -0
  12. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
  13. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  14. package/gui/dist/provider-icons/copilot-color.svg +1 -1
  15. package/gui/dist/provider-icons/cursor-color.svg +1 -1
  16. package/gui/dist/provider-icons/deepseek-color.svg +1 -1
  17. package/gui/dist/provider-icons/firepass-color.svg +1 -1
  18. package/gui/dist/provider-icons/fireworks-color.svg +1 -1
  19. package/gui/dist/provider-icons/gemini-color.svg +1 -1
  20. package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
  21. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
  22. package/gui/dist/provider-icons/grok.svg +1 -1
  23. package/gui/dist/provider-icons/groq-color.svg +1 -1
  24. package/gui/dist/provider-icons/huggingface-color.svg +1 -1
  25. package/gui/dist/provider-icons/kimi-color.svg +1 -1
  26. package/gui/dist/provider-icons/kiro-color.svg +2 -2
  27. package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
  28. package/gui/dist/provider-icons/mistral-color.svg +1 -1
  29. package/gui/dist/provider-icons/moonshot-color.svg +1 -1
  30. package/gui/dist/provider-icons/nvidia-color.svg +1 -1
  31. package/gui/dist/provider-icons/ollama-color.svg +1 -1
  32. package/gui/dist/provider-icons/openai.svg +1 -1
  33. package/gui/dist/provider-icons/opencode.svg +2 -1
  34. package/gui/dist/provider-icons/openrouter-color.svg +1 -1
  35. package/gui/dist/provider-icons/pi.svg +2 -2
  36. package/gui/dist/provider-icons/qianfan-color.svg +1 -1
  37. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
  38. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
  39. package/gui/dist/provider-icons/vllm-color.svg +1 -1
  40. package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
  41. package/package.json +19 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +376 -52
  44. package/src/adapters/base.ts +54 -7
  45. package/src/adapters/client-fingerprint.ts +18 -12
  46. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  47. package/src/adapters/command-code.ts +601 -0
  48. package/src/adapters/cursor/checkpoint-store.ts +303 -0
  49. package/src/adapters/cursor/cursor-errors.ts +129 -6
  50. package/src/adapters/cursor/discovery.ts +61 -4
  51. package/src/adapters/cursor/effort-map.ts +27 -3
  52. package/src/adapters/cursor/framing.ts +39 -0
  53. package/src/adapters/cursor/h2-pool.ts +123 -0
  54. package/src/adapters/cursor/http1-bidi.ts +361 -0
  55. package/src/adapters/cursor/images.ts +704 -0
  56. package/src/adapters/cursor/live-models.ts +174 -58
  57. package/src/adapters/cursor/live-transport.ts +609 -170
  58. package/src/adapters/cursor/native-exec-common.ts +23 -2
  59. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  60. package/src/adapters/cursor/native-exec-network.ts +1 -1
  61. package/src/adapters/cursor/native-exec-shell.ts +0 -1
  62. package/src/adapters/cursor/native-exec.ts +101 -14
  63. package/src/adapters/cursor/protobuf-events.ts +829 -11
  64. package/src/adapters/cursor/protobuf-request.ts +383 -65
  65. package/src/adapters/cursor/request-builder.ts +237 -31
  66. package/src/adapters/cursor/tool-definitions.ts +242 -12
  67. package/src/adapters/cursor/tool-result-normalize.ts +92 -0
  68. package/src/adapters/cursor/transport.ts +22 -0
  69. package/src/adapters/cursor/types.ts +28 -1
  70. package/src/adapters/cursor.ts +133 -7
  71. package/src/adapters/google-antigravity-replay.ts +558 -34
  72. package/src/adapters/google-antigravity-wire.ts +43 -10
  73. package/src/adapters/google-http.ts +38 -10
  74. package/src/adapters/google-tool-schema.ts +80 -15
  75. package/src/adapters/google-truncation.ts +11 -0
  76. package/src/adapters/google.ts +618 -74
  77. package/src/adapters/identity.ts +39 -6
  78. package/src/adapters/kiro-errors.ts +11 -0
  79. package/src/adapters/kiro-events.ts +19 -1
  80. package/src/adapters/kiro-thinking.ts +18 -2
  81. package/src/adapters/kiro-tools.ts +10 -1
  82. package/src/adapters/kiro.ts +92 -54
  83. package/src/adapters/mimo-free.ts +17 -0
  84. package/src/adapters/openai-chat-url.ts +11 -0
  85. package/src/adapters/openai-chat.ts +1311 -336
  86. package/src/adapters/openai-responses-url.ts +16 -0
  87. package/src/adapters/openai-responses.ts +830 -56
  88. package/src/adapters/registry.ts +175 -0
  89. package/src/adapters/responses-tool-schema.ts +67 -0
  90. package/src/adapters/tool-call-id.ts +119 -0
  91. package/src/adapters/tool-catalog-nudge.ts +104 -21
  92. package/src/adapters/xai-web-search.ts +185 -0
  93. package/src/bridge.ts +428 -61
  94. package/src/chat/inbound.ts +43 -19
  95. package/src/chat/outbound.ts +82 -26
  96. package/src/claude/agents-inject.ts +32 -9
  97. package/src/claude/context-windows.ts +21 -5
  98. package/src/claude/desktop-3p.ts +243 -9
  99. package/src/claude/gateway-cache.ts +41 -4
  100. package/src/claude/inbound.ts +72 -3
  101. package/src/claude/model-info.ts +38 -15
  102. package/src/claude/outbound.ts +70 -16
  103. package/src/cli/account-api.ts +35 -1
  104. package/src/cli/account-auth.ts +33 -6
  105. package/src/cli/account-catalog-refresh.ts +14 -0
  106. package/src/cli/account-extended.ts +389 -2
  107. package/src/cli/account-main.ts +317 -0
  108. package/src/cli/account.ts +30 -6
  109. package/src/cli/agent.ts +45 -1
  110. package/src/cli/claude-agent-startup-sync.ts +73 -0
  111. package/src/cli/claude-desktop.ts +29 -4
  112. package/src/cli/claude.ts +103 -34
  113. package/src/cli/codex-log-guard-doctor.ts +103 -0
  114. package/src/cli/codex-shim-autorestore.ts +2 -0
  115. package/src/cli/codex-shim-readiness.ts +76 -0
  116. package/src/cli/combo.ts +8 -0
  117. package/src/cli/config-command.ts +74 -10
  118. package/src/cli/dispatch.ts +593 -0
  119. package/src/cli/doctor.ts +315 -43
  120. package/src/cli/ensure-desired-integrations.ts +152 -0
  121. package/src/cli/export-command.ts +46 -20
  122. package/src/cli/help.ts +20 -271
  123. package/src/cli/index.ts +378 -519
  124. package/src/cli/init.ts +4 -17
  125. package/src/cli/integrations.ts +120 -2
  126. package/src/cli/lab.ts +607 -0
  127. package/src/cli/launcher-context.ts +77 -0
  128. package/src/cli/minimax.ts +497 -0
  129. package/src/cli/models-runtime.ts +35 -2
  130. package/src/cli/models.ts +100 -14
  131. package/src/cli/observe.ts +92 -3
  132. package/src/cli/opencode.ts +4 -2
  133. package/src/cli/provider-runtime.ts +18 -1
  134. package/src/cli/provider.ts +24 -3
  135. package/src/cli/ready.ts +301 -0
  136. package/src/cli/registry.ts +437 -0
  137. package/src/cli/root.ts +86 -0
  138. package/src/cli/route-policy.ts +92 -0
  139. package/src/cli/runtime-api.ts +6 -3
  140. package/src/cli/star-prompt.ts +71 -15
  141. package/src/cli/status.ts +10 -3
  142. package/src/cli/system-restart-client.ts +146 -0
  143. package/src/cli/tray-proxy.ts +153 -6
  144. package/src/cli/v2.ts +105 -10
  145. package/src/cli.ts +1 -1
  146. package/src/clients/config-export.ts +1358 -21
  147. package/src/codex/account-label.ts +14 -1
  148. package/src/codex/account-lifecycle.ts +130 -13
  149. package/src/codex/account-namespaces.ts +49 -3
  150. package/src/codex/account-priority.ts +83 -0
  151. package/src/codex/account-store.ts +29 -2
  152. package/src/codex/account-usability.ts +25 -2
  153. package/src/codex/admission.ts +256 -0
  154. package/src/codex/affinity-debug.ts +162 -0
  155. package/src/codex/app-server-processes.ts +493 -106
  156. package/src/codex/app-server-restart-service.ts +232 -0
  157. package/src/codex/auth-api.ts +849 -242
  158. package/src/codex/auth-collision.ts +5 -3
  159. package/src/codex/auth-context.ts +345 -32
  160. package/src/codex/autostart-health.ts +8 -1
  161. package/src/codex/catalog/account-models.ts +67 -0
  162. package/src/codex/catalog/aggregation.ts +68 -10
  163. package/src/codex/catalog/bundled.ts +331 -33
  164. package/src/codex/catalog/effort.ts +121 -30
  165. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  166. package/src/codex/catalog/kinds.ts +2 -0
  167. package/src/codex/catalog/metadata.ts +529 -45
  168. package/src/codex/catalog/native-models.ts +72 -0
  169. package/src/codex/catalog/parsing.ts +224 -30
  170. package/src/codex/catalog/provider-fetch.ts +1460 -134
  171. package/src/codex/catalog/sync.ts +1449 -186
  172. package/src/codex/catalog-admission.ts +199 -0
  173. package/src/codex/catalog-refresh-status.ts +105 -0
  174. package/src/codex/catalog-write-serialization.ts +242 -0
  175. package/src/codex/catalog.ts +6 -3
  176. package/src/codex/codex-write-lock.ts +384 -0
  177. package/src/codex/convergence-types.ts +614 -0
  178. package/src/codex/convergence.ts +651 -0
  179. package/src/codex/coordinator-doctor.ts +332 -0
  180. package/src/codex/custom-model-catalog-migration.ts +176 -0
  181. package/src/codex/desired-state.ts +230 -0
  182. package/src/codex/features.ts +636 -39
  183. package/src/codex/generation.ts +202 -0
  184. package/src/codex/history-job.ts +407 -0
  185. package/src/codex/history-lock.ts +242 -0
  186. package/src/codex/history-migration-guardian.ts +26 -20
  187. package/src/codex/history-provider.ts +231 -28
  188. package/src/codex/history-transition.ts +105 -0
  189. package/src/codex/history-worker.ts +220 -0
  190. package/src/codex/inject-coordination.ts +290 -0
  191. package/src/codex/inject.ts +1073 -152
  192. package/src/codex/injected-marker.ts +37 -3
  193. package/src/codex/integration-record.ts +266 -0
  194. package/src/codex/internal/catalog-writer.ts +203 -0
  195. package/src/codex/internal/history-writer.ts +80 -0
  196. package/src/codex/journal.ts +66 -4
  197. package/src/codex/log-guard/inspect.ts +506 -0
  198. package/src/codex/log-guard/lock.ts +150 -0
  199. package/src/codex/log-guard/maintenance.ts +403 -0
  200. package/src/codex/log-guard/path-safety.ts +88 -0
  201. package/src/codex/log-guard/policy.ts +44 -0
  202. package/src/codex/log-guard/processes.ts +205 -0
  203. package/src/codex/log-guard/protection.ts +489 -0
  204. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  205. package/src/codex/main-account-cache.ts +24 -0
  206. package/src/codex/main-account.ts +29 -1
  207. package/src/codex/management-convergence.ts +167 -0
  208. package/src/codex/model-cache.ts +56 -10
  209. package/src/codex/model-entitlements.ts +353 -0
  210. package/src/codex/native-main-admission.ts +47 -0
  211. package/src/codex/native-main-auth-temp.ts +187 -0
  212. package/src/codex/native-main-claim.ts +178 -0
  213. package/src/codex/native-main-lock-file.ts +162 -0
  214. package/src/codex/native-main-owner.ts +329 -0
  215. package/src/codex/native-profile-api.ts +247 -0
  216. package/src/codex/native-profile-manager.ts +1531 -0
  217. package/src/codex/native-profile-processes.ts +121 -0
  218. package/src/codex/native-profile-recovery.ts +99 -0
  219. package/src/codex/native-profile-stage-store.ts +387 -0
  220. package/src/codex/native-profile-startup.ts +492 -0
  221. package/src/codex/native-profile-store.ts +855 -0
  222. package/src/codex/native-profile-types.ts +120 -0
  223. package/src/codex/native-residue.ts +682 -0
  224. package/src/codex/paths.ts +80 -1
  225. package/src/codex/plan-from-token.ts +140 -0
  226. package/src/codex/plan.ts +40 -0
  227. package/src/codex/plugins-doctor.ts +1 -1
  228. package/src/codex/pool-rotation.ts +74 -4
  229. package/src/codex/project-config-warnings.ts +20 -6
  230. package/src/codex/prompt-journal.ts +352 -0
  231. package/src/codex/prompt-layers.ts +967 -0
  232. package/src/codex/prompt-lock.ts +143 -0
  233. package/src/codex/quota-rejection.ts +298 -0
  234. package/src/codex/quota.ts +175 -13
  235. package/src/codex/refresh.ts +11 -2
  236. package/src/codex/reset-credit-recovery.ts +1044 -0
  237. package/src/codex/routing.ts +505 -94
  238. package/src/codex/runtime.ts +159 -38
  239. package/src/codex/shim.ts +1009 -28
  240. package/src/codex/subagent-model-fallback.ts +350 -35
  241. package/src/codex/sync.ts +191 -2
  242. package/src/codex/transition-state.ts +612 -0
  243. package/src/codex/upstream-host-health.ts +368 -0
  244. package/src/codex/user-identity.ts +557 -0
  245. package/src/codex/warmup.ts +187 -81
  246. package/src/codex/write-coordination.ts +114 -0
  247. package/src/combos/failover.ts +20 -0
  248. package/src/combos/index.ts +4 -0
  249. package/src/combos/request.ts +32 -0
  250. package/src/combos/types.ts +81 -9
  251. package/src/config/provider-name.ts +24 -0
  252. package/src/config.ts +1762 -140
  253. package/src/generated/compatibility-version.json +3164 -0
  254. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  255. package/src/grok/inject.ts +16 -5
  256. package/src/grok/inspect.ts +45 -0
  257. package/src/grok/sync.ts +2 -2
  258. package/src/images/loop.ts +152 -29
  259. package/src/images/plan.ts +23 -13
  260. package/src/integrations/config-io.ts +269 -0
  261. package/src/integrations/journal.ts +315 -0
  262. package/src/integrations/merge.ts +135 -0
  263. package/src/integrations/mutation-flight.ts +71 -0
  264. package/src/integrations/native/ownership-preflight.ts +202 -0
  265. package/src/integrations/omp-yaml-source.ts +358 -0
  266. package/src/integrations/owned-refresh.ts +74 -0
  267. package/src/integrations/ownership.ts +111 -0
  268. package/src/integrations/registry.ts +159 -0
  269. package/src/integrations/serialize.ts +314 -0
  270. package/src/integrations/state.ts +361 -0
  271. package/src/integrations/store.ts +103 -0
  272. package/src/integrations/writer-lock.ts +98 -0
  273. package/src/integrations/writer.ts +691 -0
  274. package/src/lab/artifacts/sanitize.ts +586 -0
  275. package/src/lab/artifacts/secure-fs.ts +475 -0
  276. package/src/lab/artifacts/store.ts +310 -0
  277. package/src/lab/automation/budgets.ts +78 -0
  278. package/src/lab/automation/config-persistence.ts +256 -0
  279. package/src/lab/automation/constants.ts +39 -0
  280. package/src/lab/automation/cooldown.ts +103 -0
  281. package/src/lab/automation/dispatch.ts +211 -0
  282. package/src/lab/automation/index.ts +13 -0
  283. package/src/lab/automation/orchestrator.ts +499 -0
  284. package/src/lab/automation/persistence.ts +512 -0
  285. package/src/lab/automation/planner.ts +371 -0
  286. package/src/lab/automation/policy.ts +136 -0
  287. package/src/lab/automation/queue.ts +191 -0
  288. package/src/lab/automation/recovery.ts +24 -0
  289. package/src/lab/automation/route-context.ts +21 -0
  290. package/src/lab/automation/run-key.ts +44 -0
  291. package/src/lab/automation/runs-query.ts +34 -0
  292. package/src/lab/automation/types.ts +160 -0
  293. package/src/lab/conformance/assertion.ts +325 -0
  294. package/src/lab/conformance/digest.ts +22 -0
  295. package/src/lab/conformance/executor.ts +741 -0
  296. package/src/lab/conformance/fixture-provider.ts +27 -0
  297. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  298. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  299. package/src/lab/conformance/harness-budget.ts +47 -0
  300. package/src/lab/conformance/index.ts +5 -0
  301. package/src/lab/conformance/jcs.ts +64 -0
  302. package/src/lab/conformance/json-pointer.ts +39 -0
  303. package/src/lab/conformance/manifest.ts +180 -0
  304. package/src/lab/conformance/mcp-stub.ts +179 -0
  305. package/src/lab/conformance/negative-controls.ts +164 -0
  306. package/src/lab/conformance/observation.ts +355 -0
  307. package/src/lab/conformance/runner.ts +68 -0
  308. package/src/lab/conformance/sse-normalize.ts +59 -0
  309. package/src/lab/conformance/suite-manifest.ts +78 -0
  310. package/src/lab/conformance/types.ts +214 -0
  311. package/src/lab/constants.ts +126 -0
  312. package/src/lab/digest.ts +64 -0
  313. package/src/lab/events/errors.ts +9 -0
  314. package/src/lab/events/limits.ts +117 -0
  315. package/src/lab/events/types.ts +229 -0
  316. package/src/lab/events/validate.ts +781 -0
  317. package/src/lab/fabric/constants.ts +40 -0
  318. package/src/lab/fabric/executor.ts +492 -0
  319. package/src/lab/fabric/index.ts +80 -0
  320. package/src/lab/fabric/manifest.ts +222 -0
  321. package/src/lab/fabric/observe.ts +489 -0
  322. package/src/lab/fabric/patch.ts +79 -0
  323. package/src/lab/fabric/producer-child.ts +139 -0
  324. package/src/lab/fabric/producer-isolate.ts +276 -0
  325. package/src/lab/fabric/producer-protocol.ts +61 -0
  326. package/src/lab/fabric/scratch.ts +439 -0
  327. package/src/lab/fabric/subject.ts +106 -0
  328. package/src/lab/fabric/types.ts +134 -0
  329. package/src/lab/fabric/verifier.ts +98 -0
  330. package/src/lab/index.ts +54 -0
  331. package/src/lab/ledger/artifact-refs.ts +127 -0
  332. package/src/lab/ledger/invalidation.ts +136 -0
  333. package/src/lab/ledger/purge.ts +310 -0
  334. package/src/lab/ledger/store.ts +532 -0
  335. package/src/lab/live/credential-lease.ts +53 -0
  336. package/src/lab/live/destination.ts +155 -0
  337. package/src/lab/live/executor.ts +336 -0
  338. package/src/lab/live/inert-tools.ts +56 -0
  339. package/src/lab/live/manifest.ts +85 -0
  340. package/src/lab/live/mcp-loopback.ts +57 -0
  341. package/src/lab/live/runner.ts +19 -0
  342. package/src/lab/live/sandbox.ts +61 -0
  343. package/src/lab/live/suite-manifest.ts +41 -0
  344. package/src/lab/live/transport.ts +118 -0
  345. package/src/lab/live/types.ts +197 -0
  346. package/src/lab/observe/from-conformance.ts +301 -0
  347. package/src/lab/observe/from-live.ts +117 -0
  348. package/src/lab/paths.ts +153 -0
  349. package/src/lab/projection/rebuild.ts +495 -0
  350. package/src/lab/projection/schema.ts +135 -0
  351. package/src/lab/projection/verdicts.ts +474 -0
  352. package/src/lab/projection/verification.ts +412 -0
  353. package/src/lab/public/bundle.ts +217 -0
  354. package/src/lab/public/community-authority.ts +175 -0
  355. package/src/lab/public/community-files.ts +29 -0
  356. package/src/lab/public/community.ts +479 -0
  357. package/src/lab/public/file-safety.ts +155 -0
  358. package/src/lab/public/ids.ts +26 -0
  359. package/src/lab/public/index.ts +16 -0
  360. package/src/lab/public/mutation-lock.ts +424 -0
  361. package/src/lab/public/operator.ts +353 -0
  362. package/src/lab/public/origin-purge.ts +79 -0
  363. package/src/lab/public/origin.ts +203 -0
  364. package/src/lab/public/privacy.ts +143 -0
  365. package/src/lab/public/private-file.ts +261 -0
  366. package/src/lab/public/project.ts +124 -0
  367. package/src/lab/public/purge-test-fault.ts +21 -0
  368. package/src/lab/public/purge.ts +223 -0
  369. package/src/lab/public/registry.ts +44 -0
  370. package/src/lab/public/revocation.ts +252 -0
  371. package/src/lab/public/signature.ts +243 -0
  372. package/src/lab/public/storage.ts +105 -0
  373. package/src/lab/public/strict-json.ts +206 -0
  374. package/src/lab/public/time.ts +26 -0
  375. package/src/lab/public/types.ts +172 -0
  376. package/src/lab/public/validate.ts +391 -0
  377. package/src/lab/query/catalog.ts +101 -0
  378. package/src/lab/query/connection.ts +107 -0
  379. package/src/lab/query/constants.ts +4 -0
  380. package/src/lab/query/cursor.ts +132 -0
  381. package/src/lab/query/dto-map.ts +277 -0
  382. package/src/lab/query/errors.ts +22 -0
  383. package/src/lab/query/freshness.ts +53 -0
  384. package/src/lab/query/index.ts +45 -0
  385. package/src/lab/query/latest-observation.ts +59 -0
  386. package/src/lab/query/passive-production.ts +159 -0
  387. package/src/lab/query/queries.ts +444 -0
  388. package/src/lab/query/types.ts +266 -0
  389. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  390. package/src/lab/subject/installation-salt.ts +112 -0
  391. package/src/lab/subject/protocol-subject.ts +80 -0
  392. package/src/lab/subject/route-subject.ts +74 -0
  393. package/src/lib/app-owned-memory-stores.ts +22 -0
  394. package/src/lib/bounded-body.ts +153 -9
  395. package/src/lib/bun-runtime.ts +125 -12
  396. package/src/lib/bun-stream-caps.ts +13 -9
  397. package/src/lib/codex-restart-contract.ts +120 -0
  398. package/src/lib/config-ownership.ts +6 -2
  399. package/src/lib/destination-policy.ts +65 -1
  400. package/src/lib/errors.ts +44 -2
  401. package/src/lib/fabric-task-execution-authority.ts +7 -0
  402. package/src/lib/fabric-task-host.ts +29 -0
  403. package/src/lib/lab-activation.ts +223 -0
  404. package/src/lib/lab-live-execution-authority.ts +13 -0
  405. package/src/lib/lab-live-host.ts +30 -0
  406. package/src/lib/lab-live-pinned-sender.ts +56 -0
  407. package/src/lib/lab-live-route-production.ts +130 -0
  408. package/src/lib/lab-passive-linker-registration.ts +26 -0
  409. package/src/lib/local-management-attestation.ts +51 -0
  410. package/src/lib/local-management-capability.ts +100 -0
  411. package/src/lib/local-provider-reload-contract.ts +100 -0
  412. package/src/lib/optional-shutdown-hooks.ts +57 -0
  413. package/src/lib/pinned-http.ts +145 -26
  414. package/src/lib/process-control.ts +4 -1
  415. package/src/lib/provider-outbound.ts +49 -9
  416. package/src/lib/redact.ts +419 -3
  417. package/src/lib/self-launch-argv.ts +15 -0
  418. package/src/lib/server-resource-ownership.ts +71 -0
  419. package/src/lib/shadow-call.ts +35 -4
  420. package/src/lib/sse-decoder.ts +41 -0
  421. package/src/lib/state-store-registrations.ts +10 -2
  422. package/src/lib/system-restart-contract.ts +73 -0
  423. package/src/lib/token-estimate.ts +19 -2
  424. package/src/lib/tool-argument-integers.ts +202 -0
  425. package/src/lib/translator-budget.ts +44 -0
  426. package/src/lib/upstream-http-version.ts +57 -0
  427. package/src/lib/upstream-reachability.ts +95 -0
  428. package/src/lib/upstream-retry.ts +156 -3
  429. package/src/lib/windows-atomic-replace.ts +155 -0
  430. package/src/lib/windows-elevation.ts +70 -2
  431. package/src/lib/windows-secret-acl.ts +409 -69
  432. package/src/lib/windows-service-wrappers.ts +72 -0
  433. package/src/lib/windows-text.ts +106 -0
  434. package/src/lib/windows-user-principal.ts +341 -0
  435. package/src/lib/winsw.ts +33 -5
  436. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  437. package/src/oauth/account-import/index.ts +15 -0
  438. package/src/oauth/account-import/parser.ts +83 -0
  439. package/src/oauth/account-import/registry.ts +18 -0
  440. package/src/oauth/account-import/service.ts +75 -0
  441. package/src/oauth/account-import/types.ts +91 -0
  442. package/src/oauth/anthropic.ts +12 -1
  443. package/src/oauth/callback-server.ts +8 -2
  444. package/src/oauth/chatgpt.ts +12 -1
  445. package/src/oauth/command-code.ts +239 -0
  446. package/src/oauth/cursor.ts +46 -5
  447. package/src/oauth/google-antigravity.ts +35 -3
  448. package/src/oauth/health.ts +20 -12
  449. package/src/oauth/index.ts +398 -66
  450. package/src/oauth/key-providers.ts +16 -0
  451. package/src/oauth/kimi.ts +16 -2
  452. package/src/oauth/kiro.ts +50 -6
  453. package/src/oauth/local-token-detect.ts +11 -2
  454. package/src/oauth/log.ts +3 -1
  455. package/src/oauth/login-cli.ts +88 -28
  456. package/src/oauth/nous.ts +798 -0
  457. package/src/oauth/store.ts +119 -21
  458. package/src/oauth/token-guardian.ts +9 -3
  459. package/src/pi/models.ts +2 -2
  460. package/src/providers/alibaba-region-migration.ts +1 -1
  461. package/src/providers/antigravity-models.ts +521 -31
  462. package/src/providers/base-url-choices.ts +10 -0
  463. package/src/providers/codex-capacity.ts +292 -0
  464. package/src/providers/command-code-efforts.ts +144 -0
  465. package/src/providers/context-cap.ts +22 -5
  466. package/src/providers/cursor-pool.ts +72 -0
  467. package/src/providers/derive.ts +253 -6
  468. package/src/providers/fastwire.ts +501 -0
  469. package/src/providers/free-directory.ts +10 -7
  470. package/src/providers/google-vertex-location.ts +14 -0
  471. package/src/providers/key-failover.ts +71 -3
  472. package/src/providers/label.ts +1 -1
  473. package/src/providers/model-discovery-limits.ts +16 -0
  474. package/src/providers/model-discovery.ts +115 -22
  475. package/src/providers/model-rename-migration.ts +255 -0
  476. package/src/providers/model-rename-startup.ts +28 -0
  477. package/src/providers/openai-sidecar.ts +72 -4
  478. package/src/providers/openai-tier-startup.ts +31 -2
  479. package/src/providers/openai-tiers.ts +119 -4
  480. package/src/providers/openai-virtual-models.ts +1 -0
  481. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  482. package/src/providers/provider-id-rewrite.ts +29 -0
  483. package/src/providers/quota.ts +1319 -38
  484. package/src/providers/registry.ts +1429 -111
  485. package/src/providers/request-pacing.ts +310 -0
  486. package/src/providers/service-tier.ts +277 -0
  487. package/src/providers/slug-codec.ts +42 -6
  488. package/src/providers/static-model-discovery.ts +86 -0
  489. package/src/providers/xai-responses-opt-in.ts +15 -0
  490. package/src/providers/xai-transport.ts +11 -4
  491. package/src/reasoning-effort.ts +49 -1
  492. package/src/responses/compaction.ts +26 -1
  493. package/src/responses/custom-tool-compat.ts +266 -0
  494. package/src/responses/hosted-tool-policy.ts +9 -0
  495. package/src/responses/namespace-tool-compat.ts +355 -0
  496. package/src/responses/parser.ts +220 -38
  497. package/src/responses/provider-continuation.ts +98 -0
  498. package/src/responses/provider-opaque-metadata.ts +73 -0
  499. package/src/responses/reasoning-envelope.ts +9 -1
  500. package/src/responses/reasoning-replay-cache.ts +426 -0
  501. package/src/responses/schema.ts +7 -1
  502. package/src/responses/spill-store.ts +75 -10
  503. package/src/responses/state.ts +565 -27
  504. package/src/responses/thought-signature-replay.ts +347 -0
  505. package/src/responses/tool-search-compat.ts +301 -0
  506. package/src/responses/truncated-stop-reason.ts +60 -0
  507. package/src/router.ts +366 -30
  508. package/src/routing/analytics.ts +378 -0
  509. package/src/routing/capability.ts +244 -0
  510. package/src/routing/compatibility/assemble.ts +73 -0
  511. package/src/routing/compatibility/behavior.ts +278 -0
  512. package/src/routing/compatibility/catalog.ts +99 -0
  513. package/src/routing/compatibility/endpoint.ts +52 -0
  514. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  515. package/src/routing/compatibility/policy.ts +181 -0
  516. package/src/routing/compatibility/provider-slot.ts +56 -0
  517. package/src/routing/compatibility/reader.ts +110 -0
  518. package/src/routing/compatibility/subject.ts +191 -0
  519. package/src/routing/compatibility/types.ts +64 -0
  520. package/src/routing/compatibility/version.ts +104 -0
  521. package/src/routing/cost.ts +77 -0
  522. package/src/routing/evaluator.ts +495 -0
  523. package/src/routing/health.ts +412 -0
  524. package/src/routing/history/cursor.ts +43 -0
  525. package/src/routing/history/indexer.ts +605 -0
  526. package/src/routing/history/schema.ts +72 -0
  527. package/src/routing/profile-namespace.ts +15 -0
  528. package/src/routing/profile.ts +547 -0
  529. package/src/routing/quota.ts +145 -0
  530. package/src/routing/request-evidence.ts +45 -0
  531. package/src/routing/trace.ts +776 -0
  532. package/src/server/adapter-resolve.ts +2 -29
  533. package/src/server/auth-cors.ts +267 -46
  534. package/src/server/background-lifecycle.ts +182 -0
  535. package/src/server/chat-completions.ts +130 -56
  536. package/src/server/chat-native-sse.ts +331 -0
  537. package/src/server/chat-native.ts +426 -0
  538. package/src/server/claude-messages.ts +159 -43
  539. package/src/server/direct-local-http.ts +347 -0
  540. package/src/server/effort-policy.ts +18 -0
  541. package/src/server/github-copilot-responses-repair.ts +338 -0
  542. package/src/server/gui-static.ts +39 -10
  543. package/src/server/images.ts +94 -12
  544. package/src/server/index.ts +865 -181
  545. package/src/server/lifecycle.ts +284 -13
  546. package/src/server/live.ts +136 -17
  547. package/src/server/local-management-read-client.ts +90 -0
  548. package/src/server/local-provider-reload-client.ts +137 -0
  549. package/src/server/management/agent-settings-routes.ts +398 -103
  550. package/src/server/management/api-key-usage.ts +31 -5
  551. package/src/server/management/body.ts +6 -0
  552. package/src/server/management/combo-routes.ts +62 -24
  553. package/src/server/management/config-routes.ts +464 -51
  554. package/src/server/management/context.ts +80 -2
  555. package/src/server/management/integration-routes.ts +498 -0
  556. package/src/server/management/lab-automation-routes.ts +206 -0
  557. package/src/server/management/lab-routes.ts +563 -0
  558. package/src/server/management/logs-usage-routes.ts +101 -32
  559. package/src/server/management/model-routes.ts +189 -131
  560. package/src/server/management/model-rows.ts +163 -0
  561. package/src/server/management/native-integration-routes.ts +769 -0
  562. package/src/server/management/oauth-account-routes.ts +80 -4
  563. package/src/server/management/provider-capability-config.ts +48 -0
  564. package/src/server/management/provider-routes.ts +764 -157
  565. package/src/server/management/request-history-routes.ts +191 -0
  566. package/src/server/management/routing-analytics-routes.ts +74 -0
  567. package/src/server/management/routing-profile-routes.ts +380 -0
  568. package/src/server/management/shared.ts +27 -11
  569. package/src/server/management/sidebar-routes.ts +47 -31
  570. package/src/server/management/storage-log-guard-routes.ts +186 -0
  571. package/src/server/management/sync-response.ts +69 -0
  572. package/src/server/management/system-restart.ts +288 -32
  573. package/src/server/management/system-routes.ts +77 -0
  574. package/src/server/management/usage-summary-cache.ts +9 -1
  575. package/src/server/management/vision-sidecar-options.ts +167 -0
  576. package/src/server/management/web-search-sidecar-options.ts +120 -0
  577. package/src/server/management-api.ts +115 -14
  578. package/src/server/management-auth.ts +220 -5
  579. package/src/server/passive-route-linker.ts +66 -0
  580. package/src/server/ports.ts +41 -1
  581. package/src/server/proxy-liveness.ts +132 -5
  582. package/src/server/readiness.ts +99 -0
  583. package/src/server/relay-eager.ts +82 -42
  584. package/src/server/relay.ts +236 -76
  585. package/src/server/request-decompress.ts +113 -6
  586. package/src/server/request-log.ts +235 -22
  587. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  588. package/src/server/responses/agent-task-recovery.ts +465 -0
  589. package/src/server/responses/collaboration.ts +204 -35
  590. package/src/server/responses/compact.ts +442 -55
  591. package/src/server/responses/core.ts +2872 -331
  592. package/src/server/responses/empty-completion-guard.ts +276 -0
  593. package/src/server/responses/encrypted-payload.ts +62 -39
  594. package/src/server/responses/fetch-helpers.ts +79 -4
  595. package/src/server/responses/input-admission.ts +185 -0
  596. package/src/server/responses/pacing-overload.ts +13 -0
  597. package/src/server/responses/policy-fallback.ts +178 -0
  598. package/src/server/responses/responses-field-backfill.ts +251 -0
  599. package/src/server/responses/terminal-guard.ts +26 -5
  600. package/src/server/responses/upstream-error.ts +5 -0
  601. package/src/server/responses/ws-upstream.ts +308 -0
  602. package/src/server/responses-custom-tool-repair.ts +282 -0
  603. package/src/server/responses-item-id-repair.ts +54 -6
  604. package/src/server/responses-json-events.ts +90 -0
  605. package/src/server/responses-model-rewrite.ts +29 -0
  606. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  607. package/src/server/responses-snapshot-repair.ts +621 -0
  608. package/src/server/responses-terminal-repair.ts +342 -0
  609. package/src/server/responses-tool-search-repair.ts +267 -0
  610. package/src/server/responses-undeclared-tool-guard.ts +153 -0
  611. package/src/server/responses.ts +18 -2
  612. package/src/server/search.ts +78 -13
  613. package/src/server/sse-frame-buffer.ts +292 -0
  614. package/src/server/sse-payload-rewrite.ts +110 -22
  615. package/src/server/startup-action-control.ts +8 -1
  616. package/src/server/startup-health-cache.ts +19 -1
  617. package/src/server/system-env.ts +80 -9
  618. package/src/server/ws-bridge.ts +39 -38
  619. package/src/service-manager-probe.ts +892 -0
  620. package/src/service.ts +1111 -90
  621. package/src/sidecar/auth.ts +92 -0
  622. package/src/sidecar/candidates.ts +83 -0
  623. package/src/storage/cleanup.ts +2 -2
  624. package/src/storage/scanner.ts +1 -1
  625. package/src/storage/worker-lifecycle.ts +14 -14
  626. package/src/tray/windows-tray.ps1 +83 -9
  627. package/src/tray/windows.ts +43 -16
  628. package/src/types/accounts.ts +37 -0
  629. package/src/types/config.ts +845 -0
  630. package/src/types/provider.ts +545 -0
  631. package/src/types/request.ts +384 -0
  632. package/src/types/tools.ts +131 -0
  633. package/src/types/wire.ts +80 -0
  634. package/src/types.ts +104 -1236
  635. package/src/update/index.ts +32 -19
  636. package/src/update/job.ts +442 -67
  637. package/src/update/notify.ts +12 -6
  638. package/src/update/npm-cache-preflight.d.mts +47 -0
  639. package/src/update/npm-cache-preflight.mjs +201 -0
  640. package/src/update/transactional-install.d.mts +22 -0
  641. package/src/update/transactional-install.mjs +259 -0
  642. package/src/usage/cost.ts +0 -0
  643. package/src/usage/expected-prices.ts +268 -16
  644. package/src/usage/log.ts +606 -41
  645. package/src/usage/summary.ts +177 -9
  646. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  647. package/src/usage/user-cost-overlays.ts +314 -0
  648. package/src/vision/anthropic-describe.ts +10 -6
  649. package/src/vision/backends.ts +97 -0
  650. package/src/vision/describe.ts +9 -3
  651. package/src/vision/eligibility.ts +250 -0
  652. package/src/vision/index.ts +238 -24
  653. package/src/vision/reasoning.ts +55 -0
  654. package/src/vision/routed-describe.ts +175 -0
  655. package/src/vision/timeout-bounds.ts +9 -0
  656. package/src/web-search/anthropic-executor.ts +13 -7
  657. package/src/web-search/backends.ts +108 -0
  658. package/src/web-search/exa-executor.ts +88 -0
  659. package/src/web-search/executor.ts +11 -3
  660. package/src/web-search/gemini-executor.ts +141 -0
  661. package/src/web-search/index.ts +150 -15
  662. package/src/web-search/loop.ts +279 -50
  663. package/src/web-search/parse.ts +125 -30
  664. package/src/web-search/sources.ts +60 -0
  665. package/src/web-search/xai-executor.ts +219 -0
  666. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  667. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  668. package/gui/dist/provider-icons/antigravity.svg +0 -1
  669. package/gui/dist/provider-icons/claude.svg +0 -1
  670. package/gui/dist/provider-icons/copilot.svg +0 -1
  671. package/gui/dist/provider-icons/cursor.svg +0 -2
  672. package/gui/dist/provider-icons/gemini.svg +0 -1
  673. package/gui/dist/provider-icons/grok-color.svg +0 -1
  674. package/gui/dist/provider-icons/kiro.svg +0 -14
  675. package/src/cli/internal-dispatch.ts +0 -20
@@ -0,0 +1,167 @@
1
+ /**
2
+ * The one place that decides which models the management API offers as vision
3
+ * describers, and which it refuses to persist.
4
+ *
5
+ * Two routes write a vision sidecar model — `PUT /api/sidecar-settings` and the
6
+ * `visionSidecar` override in `PUT /api/claude-code`. They share this module so
7
+ * the policy cannot drift: a gate on one route and a stale copy on the other is
8
+ * the same as no gate at all.
9
+ */
10
+ import type { OcxConfig } from "../../types";
11
+ import { findAnthropicVisionProvider, type AnthropicVisionProvider } from "../../vision";
12
+ import { VISION_BACKENDS } from "../../vision/backends";
13
+ import {
14
+ modelAcceptsImageInput,
15
+ visionEligibleModelOptions,
16
+ type VisionCandidateModel,
17
+ type VisionModelOption,
18
+ type VisionSidecarBackend,
19
+ } from "../../vision/eligibility";
20
+ import { pickerVisibleSidecarCandidates } from "../../sidecar/candidates";
21
+ import { resolveSidecarAuth } from "../../sidecar/auth";
22
+
23
+ /**
24
+ * Backends whose executor could actually run (#2188 roadmap 170): openai
25
+ * forward, anthropic OAuth, xai OAuth, Antigravity OAuth — resolved by the
26
+ * VISION_BACKENDS descriptor table so this module and the options path cannot
27
+ * drift on what "active" means.
28
+ *
29
+ * `anthropicSidecar` is REQUIRED rather than defaulted. `findAnthropicVisionProvider`
30
+ * reads the OAuth account store from disk, and a default argument made every helper
31
+ * in this chain re-resolve it whenever a caller passed an explicit `undefined` —
32
+ * which is exactly the no-executor case. Passing it in keeps one read per request.
33
+ * The descriptor table re-derives the anthropic flag from the shared auth
34
+ * module; asserting the caller's resolution stays consistent with it is the
35
+ * job of the shared module, not this file.
36
+ */
37
+ export function enabledVisionBackends(
38
+ config: OcxConfig,
39
+ anthropicSidecar: AnthropicVisionProvider | undefined,
40
+ ): VisionSidecarBackend[] {
41
+ const auth = resolveSidecarAuth(config);
42
+ // Preserve the caller's resolution for the anthropic side: the descriptor
43
+ // reads the shared auth module, but a caller that already resolved "no
44
+ // executor" must not see anthropic options it cannot dispatch. The filter
45
+ // applies to the ACTIVE set only — the fresh-install fallback below stays
46
+ // both universal sides, exactly the pre-widening behavior (test 6 pins it).
47
+ const active = VISION_BACKENDS
48
+ .filter(descriptor => descriptor.isActive(auth, config))
49
+ .map(descriptor => descriptor.backend)
50
+ .filter(backend => backend !== "anthropic" || anthropicSidecar !== undefined);
51
+ // "routed" is active by construction, so the fresh-install fallback keys on
52
+ // the UNIVERSAL sides: when neither resolves, both are offered so the picker
53
+ // stays populated (permissive-unknown rule; test 6 pins it).
54
+ if (!active.includes("openai") && !active.includes("anthropic")) {
55
+ return ["openai", "anthropic", ...active];
56
+ }
57
+ return active;
58
+ }
59
+
60
+ /**
61
+ * Visible catalog rows in the shape the eligibility predicate consumes.
62
+ * Sourced from the unified picker set (#2188): picker-visible rows ∪ auth
63
+ * slots, UNFILTERED. Rule 2 (− provably text-only) belongs to the OPTIONS
64
+ * path only (visionEligibleModelOptions already applies it). The PUT gate
65
+ * consumes this list as EVIDENCE: a picker row proving an id text-only is
66
+ * exactly what visionDescriberIsProvablyBlind needs to reject that id, so
67
+ * pre-filtering here would deaden the gate (review F1: reject → allow flip).
68
+ */
69
+ export async function visionCandidateRows(config: OcxConfig): Promise<VisionCandidateModel[]> {
70
+ const auth = resolveSidecarAuth(config);
71
+ const all = await pickerVisibleSidecarCandidates(config, auth);
72
+ return all.map(candidate => ({
73
+ provider: candidate.provider,
74
+ id: candidate.id,
75
+ ...(candidate.inputModalities ? { inputModalities: candidate.inputModalities } : {}),
76
+ ...(candidate.native ? { native: true } : {}),
77
+ }));
78
+ }
79
+
80
+ export function visionModelOptionsFrom(
81
+ config: OcxConfig,
82
+ candidates: readonly VisionCandidateModel[],
83
+ anthropicSidecar: AnthropicVisionProvider | undefined,
84
+ ): VisionModelOption[] {
85
+ return visionEligibleModelOptions(
86
+ config,
87
+ candidates,
88
+ enabledVisionBackends(config, anthropicSidecar),
89
+ anthropicSidecar?.providerName,
90
+ );
91
+ }
92
+
93
+ /** Convenience for read paths that have no candidate list in hand yet. */
94
+ export async function visionModelOptionsFor(
95
+ config: OcxConfig,
96
+ anthropicSidecar: AnthropicVisionProvider | undefined,
97
+ ): Promise<VisionModelOption[]> {
98
+ return visionModelOptionsFrom(config, await visionCandidateRows(config), anthropicSidecar);
99
+ }
100
+
101
+ /**
102
+ * Can we PROVE the requested describer is blind?
103
+ *
104
+ * Only a positive `false` rejects. An id no source knows stays allowed, because
105
+ * the runtime never required catalog membership and an operator may be ahead of
106
+ * our tables.
107
+ *
108
+ * When no catalog row matches, the caller's `backend` is only a HINT, never the
109
+ * authority. Trusting it let a client launder a known-blind OpenAI model past the
110
+ * gate by claiming `backend: "anthropic"`, since the id is absent from the
111
+ * Anthropic table and absence reads as "unknown".
112
+ *
113
+ * A NAMESPACED id ("provider/model", the routed-backend option shape) names
114
+ * its provider outright, so that provider's config row and metadata family
115
+ * are probed directly. A BARE id probes ALL configured provider families and
116
+ * any positive text-only verdict wins (roadmap 170: a bare `grok-4` is
117
+ * provably text-only in the xai vendor table and must not slip through a
118
+ * two-family probe). That is safe precisely because the vendor tables share
119
+ * no bare model id (collision scan in roadmap 160: openai 48, anthropic 26,
120
+ * xai 32, google 43, zero overlaps), so they can never disagree about one.
121
+ */
122
+ export function visionDescriberIsProvablyBlind(
123
+ config: OcxConfig,
124
+ requested: string,
125
+ candidates: readonly VisionCandidateModel[],
126
+ backendHint: VisionSidecarBackend | undefined,
127
+ ): boolean {
128
+ // Catalog rows can carry operator-authored modalities. A positive claim from one
129
+ // must not hide another row or canonical metadata that proves this id is blind.
130
+ if (candidates.some(candidate => candidate.id === requested
131
+ && modelAcceptsImageInput(config, candidate) === false)) return true;
132
+
133
+ // Namespaced routed id: the provider is named, probe it directly (config
134
+ // row enrichment + its metadata family both flow through the predicate).
135
+ const sep = requested.indexOf("/");
136
+ if (sep > 0) {
137
+ const provider = requested.slice(0, sep);
138
+ const id = requested.slice(sep + 1);
139
+ if (modelAcceptsImageInput(config, { provider, id }) === false) return true;
140
+ // A namespaced candidate row (value shape) may also carry the proof.
141
+ return candidates.some(candidate => candidate.provider === provider && candidate.id === id
142
+ && modelAcceptsImageInput(config, candidate) === false);
143
+ }
144
+
145
+ // Bare id: probe the base vendor families plus every configured provider —
146
+ // a positive text-only verdict from any source wins.
147
+ const families = new Set(["openai", "anthropic", "xai", "google-antigravity", ...Object.keys(config.providers ?? {})]);
148
+ const ordered = backendHint === "anthropic"
149
+ ? ["anthropic", ...[...families].filter(family => family !== "anthropic")]
150
+ : ["openai", ...[...families].filter(family => family !== "openai")];
151
+ return ordered.some(provider => modelAcceptsImageInput(config, { provider, id: requested }) === false);
152
+ }
153
+
154
+ /** The 400 body both routes return, so the two errors cannot diverge either. */
155
+ export function visionDescriberRejection(
156
+ field: "vision.model" | "visionSidecar.model",
157
+ requested: string,
158
+ config: OcxConfig,
159
+ candidates: readonly VisionCandidateModel[],
160
+ ): { error: string; allowed: string[] } {
161
+ return {
162
+ error: `${field} "${requested}" cannot describe images: it has no image input support, or it is a model the vision sidecar describes FOR.`,
163
+ // The rejection path is not hot, so it resolves the executor itself rather than
164
+ // making every 400 caller thread one through.
165
+ allowed: visionModelOptionsFrom(config, candidates, findAnthropicVisionProvider(config)).map(option => option.value),
166
+ };
167
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * The one place that decides which models the management API offers as the
3
+ * web-search sidecar, and which it refuses to persist (#2188).
4
+ *
5
+ * Two routes write `webSearchSidecar.model` — `PUT /api/sidecar-settings`
6
+ * and the `webSearchSidecar` override in `PUT /api/claude-code`. They share
7
+ * this module for the same reason the vision routes share
8
+ * vision-sidecar-options.ts: a gate on one route and a stale copy on the
9
+ * other is the same as no gate at all. `ocx config set` raw JSON writes
10
+ * bypass management gates by design (operator escape hatch, same as vision).
11
+ *
12
+ * Unlike vision's provably-blind gate (reject only on positive proof), the
13
+ * web-search gate is MEMBERSHIP: the executor set is closed and known, so an
14
+ * id outside (candidates ∪ auth slots) can never run and is refused.
15
+ */
16
+ import type { OcxConfig } from "../../types";
17
+ import { AUTH_SLOT_MODELS, resolveSidecarAuth } from "../../sidecar/auth";
18
+ import { pickerVisibleSidecarCandidates, type SidecarCandidate } from "../../sidecar/candidates";
19
+ import { WEB_SEARCH_BACKENDS, webSearchSidecarCandidates } from "../../web-search/backends";
20
+ import type { WebSearchBackendId } from "../../web-search/index";
21
+
22
+ // The full configured union. Rows only ever materialize for backends whose
23
+ // executor admits the candidate, so inert arms (gemini/exa without config)
24
+ // simply never produce rows.
25
+ export type WebSearchBackend = WebSearchBackendId;
26
+
27
+ export interface WebSearchCandidateRow extends SidecarCandidate {
28
+ /** Executor backend that admitted this exact candidate row. */
29
+ backend: WebSearchBackend;
30
+ }
31
+
32
+ export interface WebSearchModelOption {
33
+ value: string;
34
+ label: string;
35
+ /** Exact runnable pair represented by this picker row. */
36
+ backend: WebSearchBackend;
37
+ model: string;
38
+ /** True when the row is an auth-slot entitlement rather than a picker row. */
39
+ authSlot?: boolean;
40
+ }
41
+
42
+ /** The candidate rows the web-search executors can actually run right now. */
43
+ export async function webSearchCandidateRows(config: OcxConfig): Promise<WebSearchCandidateRow[]> {
44
+ const auth = resolveSidecarAuth(config);
45
+ const all = await pickerVisibleSidecarCandidates(config, auth);
46
+ return webSearchSidecarCandidates(config, auth, all).flatMap(candidate => {
47
+ const descriptor = WEB_SEARCH_BACKENDS.find(entry =>
48
+ entry.isActive(auth, config) && entry.eligibleModel(candidate, auth));
49
+ return descriptor ? [{ ...candidate, backend: descriptor.backend }] : [];
50
+ });
51
+ }
52
+
53
+ /**
54
+ * The GUI/CLI option list. The persisted model is display-grandfathered so an
55
+ * operator can SEE a now-illegal setting in the picker (parity with the vision
56
+ * GET); new writes of such an id are still rejected by the gate below.
57
+ */
58
+ export function webSearchModelOptionsFrom(
59
+ config: Pick<OcxConfig, "webSearchSidecar">,
60
+ candidates: readonly WebSearchCandidateRow[],
61
+ ): WebSearchModelOption[] {
62
+ const byValue = new Map<string, WebSearchModelOption>();
63
+ for (const candidate of candidates) {
64
+ if (byValue.has(candidate.id)) continue;
65
+ byValue.set(candidate.id, {
66
+ value: candidate.id,
67
+ label: candidate.id,
68
+ backend: candidate.backend,
69
+ model: candidate.id,
70
+ ...(candidate.authSlot ? { authSlot: true } : {}),
71
+ });
72
+ }
73
+ const persisted = config.webSearchSidecar?.model;
74
+ if (persisted && !byValue.has(persisted)) {
75
+ byValue.set(persisted, {
76
+ value: persisted,
77
+ label: persisted,
78
+ backend: config.webSearchSidecar?.backend ?? "openai",
79
+ model: persisted,
80
+ });
81
+ }
82
+ return [...byValue.values()].sort((a, b) => a.value.localeCompare(b.value));
83
+ }
84
+
85
+ /**
86
+ * Membership gate: reject when the id is neither a runnable candidate nor an
87
+ * auth-slot model. Auth slots pass even when the matching login is currently
88
+ * absent — the slot is a legal setting whose executor simply is not live yet,
89
+ * and refusing it would make settings order-dependent on login state.
90
+ */
91
+ export function webSearchModelIsRejected(
92
+ backend: WebSearchBackend,
93
+ requested: string,
94
+ candidates: readonly WebSearchCandidateRow[],
95
+ ): boolean {
96
+ if (requested === AUTH_SLOT_MODELS.codex) return backend !== "openai";
97
+ if (requested === AUTH_SLOT_MODELS.anthropic) return backend !== "anthropic";
98
+ return !candidates.some(candidate => candidate.backend === backend && candidate.id === requested);
99
+ }
100
+
101
+ /** Uniform 400 payload naming the filter, mirroring visionDescriberRejection's shape. */
102
+ export function webSearchModelRejection(
103
+ field: string,
104
+ backend: WebSearchBackend,
105
+ requested: string,
106
+ candidates: readonly WebSearchCandidateRow[],
107
+ ): { error: string; allowedModels: string[] } {
108
+ const allowed = new Set(candidates
109
+ .filter(candidate => candidate.backend === backend)
110
+ .map(candidate => candidate.id));
111
+ // Preserve the response contract: allowedModels lists both always-configurable
112
+ // auth-slot ids even though the pair gate below binds each to its own backend.
113
+ allowed.add(AUTH_SLOT_MODELS.codex);
114
+ allowed.add(AUTH_SLOT_MODELS.anthropic);
115
+ return {
116
+ error: `${field}: backend/model pair "${backend}/${requested}" is not a web-search sidecar candidate — ` +
117
+ "the model must be picker-visible and runnable by that executor-backed backend (or its auth-slot model)",
118
+ allowedModels: [...allowed].sort(),
119
+ };
120
+ }
@@ -1,7 +1,7 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { readFileSync } from "node:fs";
3
3
  import type { CatalogModel } from "../codex/catalog";
4
- import { catalogModelSlug, invalidateCodexModelsCache, nativeModelRows, uniqueCatalogModelsForPublicList } from "../codex/catalog";
4
+ import { catalogModelSlug, invalidateCodexModelsCache, nativeContextLimits, nativeModelRows, uniqueCatalogModelsForPublicList } from "../codex/catalog";
5
5
  import {
6
6
  DEFAULT_SUBAGENT_MODELS,
7
7
  codexAutoStartEnabled,
@@ -28,7 +28,7 @@ import { deriveProviderPresets } from "../providers/derive";
28
28
  import { providerCodexAccountMode } from "../providers/registry";
29
29
  import { routedSlug, slugEquals } from "../providers/slug-codec";
30
30
  import { clearProviderQuotaCache, fetchProviderQuotaReports } from "../providers/quota";
31
- import { isCanonicalOpenAiForwardProvider } from "../providers/openai-tiers";
31
+ import { isCanonicalOpenAiForwardProvider, OPENAI_CODEX_PROVIDER_ID } from "../providers/openai-tiers";
32
32
  import { clearThreadAccountMap } from "../codex/routing";
33
33
  import { primeCodexPoolQuotas } from "../codex/auth-api";
34
34
  import { DEFAULT_PROVIDER_CONTEXT_CAP, globalContextCapValue, providerContextCap, providerContextCaps, setAllProviderContextCaps, setGlobalContextCapValue, setProviderContextCap } from "../providers/context-cap";
@@ -59,6 +59,9 @@ import { applySystemEnvToggle } from "./system-env";
59
59
  import type { ManagementApiDeps } from "./management/context";
60
60
  import { handleConfigRoutes } from "./management/config-routes";
61
61
  import { handleLogsUsageRoutes } from "./management/logs-usage-routes";
62
+ import { handleStorageLogGuardRoutes } from "./management/storage-log-guard-routes";
63
+ import { handleRequestHistoryRoutes } from "./management/request-history-routes";
64
+ import { handleRoutingAnalyticsRoutes } from "./management/routing-analytics-routes";
62
65
  import { handleProviderRoutes } from "./management/provider-routes";
63
66
  import { handleModelRoutes } from "./management/model-routes";
64
67
  import { handleAgentSettingsRoutes } from "./management/agent-settings-routes";
@@ -68,10 +71,15 @@ import { handleComboRoutes } from "./management/combo-routes";
68
71
  import { handleSystemRoutes } from "./management/system-routes";
69
72
  import { handleCloudSyncRoutes } from "./management/cloud-sync-routes";
70
73
  import { handleSidebarRoutes } from "./management/sidebar-routes";
74
+ import { handleIntegrationRoutes } from "./management/integration-routes";
75
+ import { handleNativeIntegrationRoutes } from "./management/native-integration-routes";
71
76
  import type { ManagementContext } from "./management/context";
77
+ import type { ManagementPrincipal } from "./management-auth";
72
78
  export type { ManagementApiDeps } from "./management/context";
73
79
  import { fetchAllModels } from "./management/shared";
74
80
  import { CatalogGatherBusyError } from "../codex/catalog/provider-fetch";
81
+ import type { CatalogDisposition, ConvergeCodex } from "../codex/convergence-types";
82
+ import { normalizeCatalogDisposition } from "../codex/catalog-refresh-status";
75
83
  import { managementBodyTooLargeResponse } from "./management/body";
76
84
 
77
85
  // installed npm version instead of a stale hardcode.
@@ -83,7 +91,53 @@ export const VERSION = (() => {
83
91
  }
84
92
  })();
85
93
 
86
- export async function handleManagementAPI(req: Request, url: URL, config: OcxConfig, deps: ManagementApiDeps = {}): Promise<Response | null> {
94
+ const managementConvergenceBindings = new WeakMap<object, Readonly<{
95
+ factory: (config: Readonly<OcxConfig>) => ConvergeCodex;
96
+ converge: ConvergeCodex;
97
+ }>>();
98
+
99
+ /**
100
+ * Namespace match for management route prefixes: exact hit or a child path, never a
101
+ * prefix collision (`/api/labfoo` must not match `/api/lab`).
102
+ */
103
+ function pathInManagementNamespace(pathname: string, prefix: string): boolean {
104
+ return pathname === prefix || pathname.startsWith(`${prefix}/`);
105
+ }
106
+
107
+ /**
108
+ * Routing-profile and Compatibility Lab handlers statically import the Lab module graph,
109
+ * so mounting them eagerly would pull ~70 `src/lab/` modules into every management
110
+ * request -- including installs that never opted into Lab. Loading them per namespace
111
+ * keeps `management-api.ts` on the same footing as the three protected core files.
112
+ *
113
+ * Cherry-picked from @Wibias's PR #1676, which solved this before the boundary work
114
+ * reached it. See devlog/_fin/260814_lab_core_decoupling/.
115
+ */
116
+ async function handleRoutingProfileRoutesOnDemand(ctx: ManagementContext): Promise<Response | null> {
117
+ if (!pathInManagementNamespace(ctx.url.pathname, "/api/routing-profiles")) return null;
118
+ const { handleRoutingProfileRoutes } = await import("./management/routing-profile-routes");
119
+ return handleRoutingProfileRoutes(ctx);
120
+ }
121
+
122
+ async function handleLabRoutesOnDemand(ctx: ManagementContext): Promise<Response | null> {
123
+ if (!pathInManagementNamespace(ctx.url.pathname, "/api/lab")) return null;
124
+ // Automation is checked first so its narrower namespace keeps its own handler, matching
125
+ // the eager chain's ordering.
126
+ if (pathInManagementNamespace(ctx.url.pathname, "/api/lab/automation")) {
127
+ const { handleLabAutomationRoutes } = await import("./management/lab-automation-routes");
128
+ return handleLabAutomationRoutes(ctx);
129
+ }
130
+ const { handleLabRoutes } = await import("./management/lab-routes");
131
+ return handleLabRoutes(ctx);
132
+ }
133
+
134
+ export async function handleManagementAPI(
135
+ req: Request,
136
+ url: URL,
137
+ config: OcxConfig,
138
+ deps: ManagementApiDeps = {},
139
+ principal?: ManagementPrincipal,
140
+ ): Promise<Response | null> {
87
141
  if (!isAllowedManagementOrigin(req, config)) {
88
142
  return jsonResponse({ error: "cross-origin request blocked" }, 403, req, config);
89
143
  }
@@ -95,13 +149,48 @@ export async function handleManagementAPI(req: Request, url: URL, config: OcxCon
95
149
  return jsonResponse({ error: "request body too large" }, 413, req, config);
96
150
  }
97
151
  }
98
- async function refreshCodexCatalogBestEffort(): Promise<void> {
99
- if (deps.refreshCodexCatalog) return deps.refreshCodexCatalog();
152
+ async function convergeCodexCatalog(): Promise<CatalogDisposition> {
153
+ let convergenceInvoked = false;
154
+ let managementConvergeCodex: ConvergeCodex | undefined;
100
155
  try {
101
- const { refreshCodexModelCatalog } = await import("../codex/refresh");
102
- await refreshCodexModelCatalog(config);
103
- } catch {
104
- /* catalog absent */
156
+ if (!managementConvergeCodex) {
157
+ const factory = deps.createManagementConvergeCodex
158
+ ?? (await import("../codex/management-convergence")).createManagementConvergeCodex;
159
+ if (typeof factory !== "function") throw new TypeError("Catalog convergence factory is unavailable.");
160
+ let binding = managementConvergenceBindings.get(config);
161
+ if (!binding || binding.factory !== factory) {
162
+ const created = factory(config);
163
+ if (typeof created !== "function") throw new TypeError("Catalog convergence factory returned no function.");
164
+ binding = { factory, converge: created };
165
+ managementConvergenceBindings.set(config, binding);
166
+ }
167
+ managementConvergeCodex = binding.converge;
168
+ }
169
+ const { createCatalogConvergeRequest } = await import("../codex/catalog-admission");
170
+ convergenceInvoked = true;
171
+ const outcome = await managementConvergeCodex(createCatalogConvergeRequest({ deadlineMs: 1_000 }));
172
+ const catalogRefresh = outcome?.kind === "catalog-only"
173
+ ? normalizeCatalogDisposition(outcome.catalogRefresh)
174
+ : null;
175
+ if (!catalogRefresh) {
176
+ throw new TypeError("Catalog convergence returned an invalid outcome.");
177
+ }
178
+ return catalogRefresh;
179
+ } catch (error) {
180
+ // #1784: this used to manufacture `reason: "disk"` for every escaping error, so a
181
+ // programming fault and a full filesystem were indistinguishable and both reported
182
+ // non-retryable. Classify honestly and keep the cause allowlisted.
183
+ const invalidRequest = error instanceof TypeError
184
+ || error instanceof RangeError
185
+ || error instanceof SyntaxError;
186
+ return {
187
+ status: "failed",
188
+ reason: invalidRequest ? "request-invalid" : "internal",
189
+ phase: convergenceInvoked ? "commit" : "gather",
190
+ retryable: false,
191
+ partialWrite: convergenceInvoked,
192
+ cause: { kind: invalidRequest ? "invalid-request" : "unknown" },
193
+ };
105
194
  }
106
195
  }
107
196
 
@@ -118,7 +207,7 @@ export async function handleManagementAPI(req: Request, url: URL, config: OcxCon
118
207
  import("../claude/context-windows"),
119
208
  import("../codex/catalog"),
120
209
  ]);
121
- injectClaudeAgentDefs(config, buildClaudeContextWindows([...visibleNativeSlugs(config)], models));
210
+ injectClaudeAgentDefs(config, buildClaudeContextWindows([...visibleNativeSlugs(config)], models, nativeContextLimits(config)));
122
211
  } catch {
123
212
  // Keep routes available through a provider-discovery blip. A later
124
213
  // launch-time sync restores any context markers missing from this pass.
@@ -126,19 +215,26 @@ export async function handleManagementAPI(req: Request, url: URL, config: OcxCon
126
215
  }
127
216
  } catch { /* best-effort */ }
128
217
  }
129
- const ctx: ManagementContext = { req, url, config, deps, refreshCodexCatalogBestEffort, syncClaudeAgentDefsBestEffort };
218
+ const ctx: ManagementContext = { req, url, config, deps, principal, convergeCodexCatalog, syncClaudeAgentDefsBestEffort };
130
219
  let routed: Response | null;
131
220
  try {
132
221
  routed = (await handleConfigRoutes(ctx))
222
+ ?? (await handleStorageLogGuardRoutes(ctx))
133
223
  ?? (await handleLogsUsageRoutes(ctx))
224
+ ?? (await handleRequestHistoryRoutes(ctx))
225
+ ?? (await handleRoutingAnalyticsRoutes(ctx))
226
+ ?? (await handleRoutingProfileRoutesOnDemand(ctx))
134
227
  ?? (await handleProviderRoutes(ctx))
135
228
  ?? (await handleModelRoutes(ctx))
229
+ ?? (await handleIntegrationRoutes(ctx))
230
+ ?? (await handleNativeIntegrationRoutes(ctx))
136
231
  ?? (await handleAgentSettingsRoutes(ctx))
137
232
  ?? (await handleClientsRoutes(ctx))
138
233
  ?? (await handleOauthAccountRoutes(ctx))
139
234
  ?? (await handleComboRoutes(ctx))
140
235
  ?? (await handleSystemRoutes(ctx))
141
236
  ?? (await handleCloudSyncRoutes(ctx))
237
+ ?? (await handleLabRoutesOnDemand(ctx))
142
238
  ?? (await handleSidebarRoutes(ctx));
143
239
  } catch (error) {
144
240
  const tooLarge = managementBodyTooLargeResponse(error, req, config);
@@ -158,7 +254,7 @@ export async function handleManagementAPI(req: Request, url: URL, config: OcxCon
158
254
  if (routed) return routed;
159
255
 
160
256
  if (url.pathname === "/api/stop" && req.method === "POST") {
161
- const { restoreNativeCodex } = await import("../codex/inject");
257
+ const { restoreNativeCodexAsync } = await import("../codex/inject");
162
258
  const { stopServiceIfInstalled, isServiceOwnershipError } = await import("../service");
163
259
  try {
164
260
  stopServiceIfInstalled();
@@ -171,7 +267,7 @@ export async function handleManagementAPI(req: Request, url: URL, config: OcxCon
171
267
  }
172
268
  throw err;
173
269
  }
174
- const restore = restoreNativeCodex();
270
+ const restore = await restoreNativeCodexAsync();
175
271
  // Both managed configs come down together on an explicit teardown. The daemon's own
176
272
  // syncCleanup skips this when OCX_SERVICE is set (so a crash/respawn keeps the fence),
177
273
  // which is exactly why an intentional stop has to do it here.
@@ -187,12 +283,17 @@ export async function handleManagementAPI(req: Request, url: URL, config: OcxCon
187
283
  : { success: false, message: `Proxy stopping, but native Codex restore failed: ${restore.message}. Run \`ocx restore\`.${grokNote}` });
188
284
  }
189
285
 
286
+ if (url.pathname.startsWith("/api/native-main-profiles")) {
287
+ const { handleNativeProfileAPI } = await import("../codex/native-profile-api");
288
+ return handleNativeProfileAPI(req, url, config, deps.nativeProfileApi);
289
+ }
290
+
190
291
  if (url.pathname.startsWith("/api/codex-auth/")) {
191
292
  const { handleCodexAuthAPI } = await import("../codex/auth-api");
192
293
  const { ConfigMutationLockError } = await import("../config");
193
294
  const { CodexCredentialRefreshLockTimeoutError } = await import("../codex/account-store");
194
295
  try {
195
- return await handleCodexAuthAPI(req, url, config);
296
+ return await handleCodexAuthAPI(req, url, config, convergeCodexCatalog);
196
297
  } catch (error) {
197
298
  // Credential writers remap ConfigMutationLockError to CodexCredentialRefreshLockTimeoutError;
198
299
  // treat both as the same retryable busy response.