@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,65 @@
1
+ import { SUPPORTED_NATIVE_OPENAI_SLUGS } from "../codex/catalog/native-models";
2
+ import { redactSecretString } from "../lib/redact";
3
+
4
+ const RESERVED_OBJECT_KEYS = new Set(["__proto__", "constructor", "prototype"]);
5
+
6
+ function positiveSafeInteger(value: unknown): value is number {
7
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
8
+ }
9
+
10
+ /**
11
+ * Resolve a client-facing soft compaction budget without changing any hard
12
+ * model limit. Configuration and measured input ceilings may only lower the
13
+ * default 90% envelope.
14
+ */
15
+ export function clampAutoCompactTokenLimit(
16
+ contextWindow: number,
17
+ maxInputTokens?: number,
18
+ configuredLimit?: number,
19
+ ): number {
20
+ const candidates = [Math.floor(contextWindow * 0.9), contextWindow];
21
+ if (positiveSafeInteger(maxInputTokens)) candidates.push(maxInputTokens);
22
+ if (positiveSafeInteger(configuredLimit)) candidates.push(configuredLimit);
23
+ return Math.min(...candidates);
24
+ }
25
+
26
+ export type AutoCompactBudgetValidationOptions = Readonly<{
27
+ /** PATCH accepts null for whole-map and per-key deletion. */
28
+ allowTombstones?: boolean;
29
+ /** The canonical ChatGPT provider accepts only exact supported native ids. */
30
+ requireNativeIds?: boolean;
31
+ }>;
32
+
33
+ /** Shared config/load/management boundary for per-model soft budgets. */
34
+ export function modelAutoCompactTokenLimitsConfigError(
35
+ value: unknown,
36
+ options: AutoCompactBudgetValidationOptions = {},
37
+ ): string | null {
38
+ const field = "modelAutoCompactTokenLimits";
39
+ if (value === undefined || (options.allowTombstones && value === null)) return null;
40
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
41
+ return `${field} must be a plain object${options.allowTombstones ? " or null" : ""}`;
42
+ }
43
+ const prototype = Object.getPrototypeOf(value);
44
+ if (prototype !== Object.prototype && prototype !== null) {
45
+ return `${field} must be a plain object with own properties`;
46
+ }
47
+ for (const [modelId, entry] of Object.entries(value as Record<string, unknown>)) {
48
+ const safeModelId = JSON.stringify(redactSecretString(modelId));
49
+ if (!modelId.trim()) return `${field} keys must be nonblank model ids`;
50
+ if (RESERVED_OBJECT_KEYS.has(modelId)) {
51
+ return `${field} key ${safeModelId} is reserved`;
52
+ }
53
+ if (options.requireNativeIds
54
+ && (modelId.includes("/") || !SUPPORTED_NATIVE_OPENAI_SLUGS.has(modelId))) {
55
+ return `${field} key ${safeModelId} must be an exact supported native model id`;
56
+ }
57
+ if (options.allowTombstones && entry === null) continue;
58
+ if (!positiveSafeInteger(entry)) {
59
+ return `${field}[${safeModelId}] must be a positive safe integer${
60
+ options.allowTombstones ? " or null" : ""
61
+ }`;
62
+ }
63
+ }
64
+ return null;
65
+ }
@@ -62,3 +62,13 @@ export function matchBaseUrlChoice(
62
62
  }
63
63
  return choices.some(c => c.id === "custom") ? "custom" : choices[0]!.id;
64
64
  }
65
+
66
+ /** Moonshot/Kimi API endpoint presets (international default; China selectable). */
67
+ export const MOONSHOT_INTL_BASE_URL = "https://api.moonshot.ai/v1";
68
+ export const MOONSHOT_CN_BASE_URL = "https://api.moonshot.cn/v1";
69
+
70
+ export const MOONSHOT_BASE_URL_CHOICES: readonly ProviderBaseUrlChoice[] = [
71
+ { id: "international", label: "International (.ai)", baseUrl: MOONSHOT_INTL_BASE_URL },
72
+ { id: "china", label: "China (.cn)", baseUrl: MOONSHOT_CN_BASE_URL },
73
+ { id: "custom", label: "Custom" },
74
+ ];
@@ -0,0 +1,292 @@
1
+ import { codexPlanKey, codexPlanValue } from "../codex/plan";
2
+
3
+ export const CODEX_CONFIGURED_CAPACITY_WEIGHTS = {
4
+ plus: 1,
5
+ team: 1,
6
+ business: 1,
7
+ prolite: 5,
8
+ pro: 20,
9
+ } as const;
10
+
11
+ /** Match the provider-report last-good freshness bound. */
12
+ export const CODEX_CAPACITY_MAX_QUOTA_AGE_MS = 30 * 60_000;
13
+
14
+ export type CodexCapacityQuota = {
15
+ fiveHourPercent?: number;
16
+ fiveHourResetAt?: number;
17
+ weeklyPercent?: number;
18
+ weeklyResetAt?: number;
19
+ monthlyPercent?: number;
20
+ monthlyResetAt?: number;
21
+ customWindows?: Array<{ label: string; percent: number; resetAt?: number }>;
22
+ updatedAt: number;
23
+ };
24
+
25
+ export interface CodexCapacityAccount {
26
+ isMain: boolean;
27
+ active?: boolean;
28
+ plan?: unknown;
29
+ paused: boolean;
30
+ needsReauth?: boolean;
31
+ quota: CodexCapacityQuota | null;
32
+ }
33
+
34
+ export interface CodexCapacityWindowAggregation {
35
+ usedPercent: number;
36
+ includedAccounts: number;
37
+ excludedAccounts: number;
38
+ incomplete: boolean;
39
+ /** Internal calculation evidence; stripped from the management API response. */
40
+ totalWeight?: number;
41
+ /** Internal calculation evidence; stripped from the management API response. */
42
+ consumedWeight?: number;
43
+ /** Internal calculation evidence; stripped from the management API response. */
44
+ remainingWeight?: number;
45
+ updatedAt: number;
46
+ nextRecoveryAt?: number;
47
+ nextRecoveryPercent?: number;
48
+ }
49
+
50
+ export interface CodexCapacityAggregation {
51
+ kind: "capacity-weighted-v1";
52
+ scope: "routable-known";
53
+ includedAccounts: number;
54
+ excludedAccounts: number;
55
+ unknownPlanAccounts: number;
56
+ missingQuotaAccounts: number;
57
+ pausedAccounts: number;
58
+ reauthAccounts: number;
59
+ staleQuotaAccounts: number;
60
+ partialWindowAccounts: number;
61
+ incomplete: boolean;
62
+ presentation?: "aggregate" | "effective-account-fallback" | "coverage-only";
63
+ fiveHour?: CodexCapacityWindowAggregation;
64
+ weekly?: CodexCapacityWindowAggregation;
65
+ monthly?: CodexCapacityWindowAggregation;
66
+ customWindows?: Array<CodexCapacityWindowAggregation & { label: string }>;
67
+ currentAccount?: {
68
+ isMain: boolean;
69
+ plan?: string | null;
70
+ quota: CodexCapacityQuota | null;
71
+ };
72
+ }
73
+
74
+ export interface CodexCapacityResult {
75
+ quota: CodexCapacityQuota | null;
76
+ aggregation: CodexCapacityAggregation | null;
77
+ currentAccount?: CodexCapacityAggregation["currentAccount"];
78
+ }
79
+
80
+ type MutableWindow = {
81
+ totalWeight: number;
82
+ consumedWeight: number;
83
+ includedAccounts: number;
84
+ recoveries: Map<number, number>;
85
+ oldestUpdatedAt: number;
86
+ };
87
+
88
+ function configuredWeight(plan: unknown): number | undefined {
89
+ const normalized = codexPlanKey(plan);
90
+ return normalized && Object.hasOwn(CODEX_CONFIGURED_CAPACITY_WEIGHTS, normalized)
91
+ ? CODEX_CONFIGURED_CAPACITY_WEIGHTS[normalized as keyof typeof CODEX_CONFIGURED_CAPACITY_WEIGHTS]
92
+ : undefined;
93
+ }
94
+
95
+ function normalizedPercent(value: unknown): number | undefined {
96
+ return typeof value === "number" && Number.isFinite(value)
97
+ ? Math.max(0, Math.min(100, value))
98
+ : undefined;
99
+ }
100
+
101
+ function futureResetMs(value: unknown, now: number): number | undefined {
102
+ if (typeof value !== "number" || !Number.isFinite(value)) return undefined;
103
+ const milliseconds = value > 10_000_000_000 ? value : value * 1000;
104
+ return milliseconds > now ? milliseconds : undefined;
105
+ }
106
+
107
+ function hasKnownQuotaWindow(quota: CodexCapacityQuota | null): quota is CodexCapacityQuota {
108
+ if (!quota) return false;
109
+ return normalizedPercent(quota.fiveHourPercent) !== undefined
110
+ || normalizedPercent(quota.weeklyPercent) !== undefined
111
+ || normalizedPercent(quota.monthlyPercent) !== undefined
112
+ || !!quota.customWindows?.some(window => normalizedPercent(window.percent) !== undefined);
113
+ }
114
+
115
+ function currentQuotaForDisplay(account: CodexCapacityAccount, now: number): CodexCapacityQuota | null {
116
+ const quota = account.quota;
117
+ const fresh = !!quota
118
+ && Number.isFinite(quota.updatedAt)
119
+ && now - quota.updatedAt <= CODEX_CAPACITY_MAX_QUOTA_AGE_MS;
120
+ return !account.paused && !account.needsReauth && fresh && hasKnownQuotaWindow(quota) ? quota : null;
121
+ }
122
+
123
+ function addWindow(
124
+ windows: Map<string, MutableWindow>,
125
+ key: string,
126
+ weight: number,
127
+ percent: number,
128
+ resetAt: number | undefined,
129
+ updatedAt: number,
130
+ ): void {
131
+ const window = windows.get(key) ?? {
132
+ totalWeight: 0,
133
+ consumedWeight: 0,
134
+ includedAccounts: 0,
135
+ recoveries: new Map<number, number>(),
136
+ oldestUpdatedAt: updatedAt,
137
+ };
138
+ const consumed = weight * percent / 100;
139
+ window.totalWeight += weight;
140
+ window.consumedWeight += consumed;
141
+ window.includedAccounts += 1;
142
+ window.oldestUpdatedAt = Math.min(window.oldestUpdatedAt, updatedAt);
143
+ if (resetAt !== undefined && consumed > 0) {
144
+ window.recoveries.set(resetAt, (window.recoveries.get(resetAt) ?? 0) + consumed);
145
+ }
146
+ windows.set(key, window);
147
+ }
148
+
149
+ function finalizeWindow(window: MutableWindow, totalAccounts: number): CodexCapacityWindowAggregation {
150
+ const nextRecoveryAt = [...window.recoveries.keys()].sort((a, b) => a - b)[0];
151
+ const recovered = nextRecoveryAt === undefined ? undefined : window.recoveries.get(nextRecoveryAt);
152
+ return {
153
+ usedPercent: window.consumedWeight / window.totalWeight * 100,
154
+ includedAccounts: window.includedAccounts,
155
+ excludedAccounts: totalAccounts - window.includedAccounts,
156
+ incomplete: window.includedAccounts < totalAccounts,
157
+ totalWeight: window.totalWeight,
158
+ consumedWeight: window.consumedWeight,
159
+ remainingWeight: window.totalWeight - window.consumedWeight,
160
+ updatedAt: window.oldestUpdatedAt,
161
+ ...(nextRecoveryAt !== undefined ? { nextRecoveryAt } : {}),
162
+ ...(recovered !== undefined ? { nextRecoveryPercent: recovered / window.totalWeight * 100 } : {}),
163
+ };
164
+ }
165
+
166
+ /** Display-only configured-weight estimate. It never participates in account selection or routing. */
167
+ export function aggregateCodexPoolCapacity(
168
+ accounts: readonly CodexCapacityAccount[],
169
+ now = Date.now(),
170
+ ): CodexCapacityResult {
171
+ const current = accounts.find(account => account.active)
172
+ ?? accounts.find(account => account.isMain)
173
+ ?? accounts[0];
174
+ const currentPlan = codexPlanValue(current?.plan);
175
+ const currentAccount = current ? {
176
+ isMain: current.isMain,
177
+ ...(currentPlan !== undefined ? { plan: currentPlan } : {}),
178
+ quota: currentQuotaForDisplay(current, now),
179
+ } : undefined;
180
+ const windows = new Map<string, MutableWindow>();
181
+ const included = new Set<CodexCapacityAccount>();
182
+ const contributions = new Map<CodexCapacityAccount, Set<string>>();
183
+ let unknownPlanAccounts = 0;
184
+ let missingQuotaAccounts = 0;
185
+ let pausedAccounts = 0;
186
+ let reauthAccounts = 0;
187
+ let staleQuotaAccounts = 0;
188
+
189
+ for (const account of accounts) {
190
+ const weight = configuredWeight(account.plan);
191
+ if (weight === undefined) unknownPlanAccounts += 1;
192
+ if (account.paused) pausedAccounts += 1;
193
+ if (account.needsReauth) reauthAccounts += 1;
194
+ const quota = account.quota;
195
+ const quotaFresh = !!quota
196
+ && Number.isFinite(quota.updatedAt)
197
+ && now - quota.updatedAt <= CODEX_CAPACITY_MAX_QUOTA_AGE_MS;
198
+ if (quota && !quotaFresh) staleQuotaAccounts += 1;
199
+ const standard = quota ? [
200
+ ["fiveHour", quota.fiveHourPercent, quota.fiveHourResetAt],
201
+ ["weekly", quota.weeklyPercent, quota.weeklyResetAt],
202
+ ["monthly", quota.monthlyPercent, quota.monthlyResetAt],
203
+ ] as const : [];
204
+ const custom = quota?.customWindows ?? [];
205
+ const hasQuota = hasKnownQuotaWindow(quota);
206
+ if (!hasQuota) missingQuotaAccounts += 1;
207
+ if (account.paused || account.needsReauth || weight === undefined || !quota || !hasQuota || !quotaFresh) continue;
208
+
209
+ let contributed = false;
210
+ const contributionKeys = new Set<string>();
211
+ for (const [key, rawPercent, rawReset] of standard) {
212
+ const percent = normalizedPercent(rawPercent);
213
+ if (percent === undefined) continue;
214
+ addWindow(windows, key, weight, percent, futureResetMs(rawReset, now), quota.updatedAt);
215
+ contributionKeys.add(key);
216
+ contributed = true;
217
+ }
218
+ for (const customWindow of custom) {
219
+ const percent = normalizedPercent(customWindow.percent);
220
+ if (percent === undefined) continue;
221
+ addWindow(windows, `custom:${customWindow.label}`, weight, percent, futureResetMs(customWindow.resetAt, now), quota.updatedAt);
222
+ contributionKeys.add(`custom:${customWindow.label}`);
223
+ contributed = true;
224
+ }
225
+ if (contributed) {
226
+ included.add(account);
227
+ contributions.set(account, contributionKeys);
228
+ }
229
+ }
230
+
231
+ if (windows.size === 0) {
232
+ if (accounts.length === 0) return { quota: null, aggregation: null, ...(currentAccount ? { currentAccount } : {}) };
233
+ const aggregation: CodexCapacityAggregation = {
234
+ kind: "capacity-weighted-v1",
235
+ scope: "routable-known",
236
+ includedAccounts: 0,
237
+ excludedAccounts: accounts.length,
238
+ unknownPlanAccounts,
239
+ missingQuotaAccounts,
240
+ pausedAccounts,
241
+ reauthAccounts,
242
+ staleQuotaAccounts,
243
+ partialWindowAccounts: 0,
244
+ incomplete: true,
245
+ ...(currentAccount ? { currentAccount } : {}),
246
+ };
247
+ return { quota: null, aggregation, ...(currentAccount ? { currentAccount } : {}) };
248
+ }
249
+ const fiveHour = windows.get("fiveHour") ? finalizeWindow(windows.get("fiveHour")!, accounts.length) : undefined;
250
+ const weekly = windows.get("weekly") ? finalizeWindow(windows.get("weekly")!, accounts.length) : undefined;
251
+ const monthly = windows.get("monthly") ? finalizeWindow(windows.get("monthly")!, accounts.length) : undefined;
252
+ const customWindows = [...windows.entries()].flatMap(([key, window]) => key.startsWith("custom:")
253
+ ? [{ label: key.slice("custom:".length), ...finalizeWindow(window, accounts.length) }]
254
+ : []);
255
+ const quota: CodexCapacityQuota = {
256
+ ...(fiveHour ? { fiveHourPercent: fiveHour.usedPercent } : {}),
257
+ ...(weekly ? { weeklyPercent: weekly.usedPercent } : {}),
258
+ ...(monthly ? { monthlyPercent: monthly.usedPercent } : {}),
259
+ ...(customWindows.length > 0 ? {
260
+ customWindows: customWindows.map(window => ({ label: window.label, percent: window.usedPercent })),
261
+ } : {}),
262
+ updatedAt: Math.min(
263
+ ...[fiveHour, weekly, monthly, ...customWindows]
264
+ .flatMap(window => window ? [window.updatedAt] : []),
265
+ ),
266
+ };
267
+ const visibleWindowKeys = [...windows.keys()];
268
+ const partialWindowAccounts = accounts.filter(account => {
269
+ const keys = contributions.get(account);
270
+ return !!keys && visibleWindowKeys.some(key => !keys.has(key));
271
+ }).length;
272
+ const excludedAccounts = accounts.length - included.size;
273
+ const aggregation: CodexCapacityAggregation = {
274
+ kind: "capacity-weighted-v1",
275
+ scope: "routable-known",
276
+ includedAccounts: included.size,
277
+ excludedAccounts,
278
+ unknownPlanAccounts,
279
+ missingQuotaAccounts,
280
+ pausedAccounts,
281
+ reauthAccounts,
282
+ staleQuotaAccounts,
283
+ partialWindowAccounts,
284
+ incomplete: excludedAccounts > 0 || partialWindowAccounts > 0,
285
+ ...(fiveHour ? { fiveHour } : {}),
286
+ ...(weekly ? { weekly } : {}),
287
+ ...(monthly ? { monthly } : {}),
288
+ ...(customWindows.length > 0 ? { customWindows } : {}),
289
+ ...(currentAccount ? { currentAccount } : {}),
290
+ };
291
+ return { quota, aggregation, ...(currentAccount ? { currentAccount } : {}) };
292
+ }
@@ -0,0 +1,176 @@
1
+ import { readBoundedResponseBody } from "../lib/bounded-body";
2
+
3
+ const COMMAND_CODE_MODEL_EFFORTS = {
4
+ "deepseek/deepseek-v4-pro": {
5
+ efforts: ["high", "max"],
6
+ profileUrl: "https://commandcode.ai/models/deepseek-v4-pro",
7
+ },
8
+ "deepseek/deepseek-v4-flash": {
9
+ efforts: ["high", "max"],
10
+ profileUrl: "https://commandcode.ai/models/deepseek-v4-flash",
11
+ },
12
+ /*
13
+ * Three live routes that reached the catalog without an effort ladder (#2647).
14
+ * Without a row here the model advertises no efforts at all, so a client that
15
+ * sends one gets it stripped or rejected rather than honored.
16
+ *
17
+ * PROVENANCE, stated plainly: these three ladders are the reporter's
18
+ * (darwintree, #2647), recorded as reported and NOT independently verified.
19
+ * All three profileUrls return HTTP 200, but commandcode.ai renders these
20
+ * pages client-side and ships the ladder inside a serialized React payload
21
+ * whose `reasoningEfforts` array is EMPTY in the delivered HTML. There is no
22
+ * fetchable statement of these ladders to check them against.
23
+ *
24
+ * Do not assume the refresh path launders this. It does not:
25
+ * `parsedProfileEfforts` below matches prose of the form
26
+ * "Reasoning efforts ... are supported;", and `grep -c -i 'reasoning efforts'`
27
+ * against the live pages returns 0 — for these three AND for the older rows
28
+ * (deepseek-v4-pro, GLM-5.3, muse-spark-1.2 all measured 0 on 2026-08-27).
29
+ * So `refreshCommandCodeReasoningEfforts` returns undefined and the caller
30
+ * keeps whatever is written here, indefinitely. The self-correction mechanism
31
+ * is currently dead for EVERY row in this table, which is a pre-existing
32
+ * defect worth its own fix (teach the parser to read the embedded payload),
33
+ * not something these three rows introduced.
34
+ *
35
+ * The practical consequence: a wrong ladder here stays wrong until a human
36
+ * changes it. It degrades safely — an effort the upstream rejects surfaces as
37
+ * an error rather than silent corruption — but it does not self-heal.
38
+ */
39
+ "deepseek/deepseek-v4-flash-vision-exp": {
40
+ efforts: ["high", "max"],
41
+ profileUrl: "https://commandcode.ai/models/deepseek-v4-flash-vision-exp",
42
+ },
43
+ "gpt-5.6-luna": {
44
+ efforts: ["low", "medium", "high", "xhigh", "max"],
45
+ profileUrl: "https://commandcode.ai/models/gpt-5-6-luna",
46
+ },
47
+ "google/gemini-3.7-flash": {
48
+ efforts: ["low", "medium", "high"],
49
+ profileUrl: "https://commandcode.ai/models/gemini-3-7-flash",
50
+ },
51
+ // Keys must match the EXACT upstream /provider/v1/models ids (GLM ships as
52
+ // `zai-org/GLM-5.3`, not `zai-org/glm-5.3`). The table doubles as the router's
53
+ // known-ids decode source (via `knownModelIdsForProvider`), so a case mismatch
54
+ // makes the Codex-facing slug `commandcode/zai-org-GLM-5.3` pass through
55
+ // undecoded and upstream rejects it with `unsupported_model`.
56
+ "zai-org/GLM-5": {
57
+ efforts: ["high", "max"],
58
+ profileUrl: "https://commandcode.ai/models/glm-5",
59
+ },
60
+ "zai-org/GLM-5.1": {
61
+ efforts: ["high", "max"],
62
+ profileUrl: "https://commandcode.ai/models/glm-5-1",
63
+ },
64
+ "zai-org/GLM-5.2": {
65
+ efforts: ["high", "max"],
66
+ profileUrl: "https://commandcode.ai/models/glm-5-2",
67
+ },
68
+ "zai-org/GLM-5.2-Fast": {
69
+ efforts: ["high", "max"],
70
+ profileUrl: "https://commandcode.ai/models/glm-5-2-fast",
71
+ },
72
+ "zai-org/GLM-5.3": {
73
+ efforts: ["low", "high", "max"],
74
+ profileUrl: "https://commandcode.ai/models/glm-5-3",
75
+ },
76
+ // Muse Spark: CLI currently prints "has no adjustable reasoning effort" and
77
+ // blocks --effort locally, but the upstream /alpha/generate endpoint accepts
78
+ // reasoning_effort low..max for meta/muse-spark-1.2-contributor (verified
79
+ // 2026-08-13: direct upstream POST with low/medium/high/xhigh/max all 200,
80
+ // ultra 400; reasoningTokens differentiated 114..253; proxy previously stripped
81
+ // the field so effort changes had no effect).
82
+ "meta/muse-spark-1.2": {
83
+ efforts: ["low", "medium", "high", "xhigh", "max"],
84
+ profileUrl: "https://commandcode.ai/models/meta-muse-spark-1.2",
85
+ },
86
+ "meta/muse-spark-1.2-contributor": {
87
+ efforts: ["low", "medium", "high", "xhigh", "max"],
88
+ profileUrl: "https://commandcode.ai/models/meta-muse-spark-1.2-contributor",
89
+ },
90
+ "meta/muse-spark-1.1": {
91
+ efforts: ["low", "medium", "high", "xhigh", "max"],
92
+ profileUrl: "https://commandcode.ai/models/meta-muse-spark-1.1",
93
+ },
94
+ } as const;
95
+
96
+ /**
97
+ * Official Command Code model-profile facts, not a model catalog. Models remain
98
+ * account-scoped and come exclusively from the authenticated /provider/v1/models endpoint.
99
+ */
100
+ export const COMMAND_CODE_MODEL_REASONING_EFFORTS: Record<string, string[]> = Object.fromEntries(
101
+ Object.entries(COMMAND_CODE_MODEL_EFFORTS).map(([id, row]) => [id, [...row.efforts]]),
102
+ );
103
+
104
+ const refreshedEfforts = new Map<string, string[]>();
105
+
106
+ function keyFor(modelId: string): string {
107
+ return modelId.trim().toLowerCase();
108
+ }
109
+
110
+ export function commandCodeReasoningEfforts(modelId: string): readonly string[] | undefined {
111
+ const key = keyFor(modelId);
112
+ const refreshed = refreshedEfforts.get(key);
113
+ if (refreshed !== undefined) return refreshed;
114
+ // Case-insensitive: the table keys match the EXACT upstream ids (e.g. `zai-org/GLM-5.3`),
115
+ // but callers may pass either case.
116
+ for (const [id, efforts] of Object.entries(COMMAND_CODE_MODEL_REASONING_EFFORTS)) {
117
+ if (keyFor(id) === key) return efforts;
118
+ }
119
+ return undefined;
120
+ }
121
+
122
+ function parsedProfileEfforts(page: string): string[] | undefined {
123
+ const match = page.match(/Reasoning efforts\s+([^.;]+?)\s+are supported;\s*([^.]*)/i);
124
+ if (!match) return undefined;
125
+ const listed = match[1]!.toLowerCase().match(/\b(?:low|medium|high|xhigh|max)\b/g) ?? [];
126
+ const mapped = match[2]!.toLowerCase().match(/\b(?:low|medium|high|xhigh|max)\s+maps to\s+(?:low|medium|high|xhigh|max)\b/g) ?? [];
127
+ const normalized = new Set(listed);
128
+ for (const mapping of mapped) {
129
+ const [, source, target] = mapping.match(/(low|medium|high|xhigh|max)\s+maps to\s+(low|medium|high|xhigh|max)/) ?? [];
130
+ if (source && target) {
131
+ normalized.delete(source);
132
+ normalized.add(target);
133
+ }
134
+ }
135
+ return normalized.size > 0 ? [...normalized] : [];
136
+ }
137
+
138
+ /**
139
+ * Refresh one stale effort record only after the upstream rejects an effort request.
140
+ * A failed or unparseable public profile deliberately leaves the known table unchanged.
141
+ */
142
+ export async function refreshCommandCodeReasoningEfforts(
143
+ modelId: string,
144
+ fetchFn: typeof globalThis.fetch = globalThis.fetch,
145
+ ): Promise<readonly string[] | undefined> {
146
+ const key = keyFor(modelId);
147
+ let profile: { efforts: readonly string[]; profileUrl: string } | undefined;
148
+ for (const [id, row] of Object.entries(COMMAND_CODE_MODEL_EFFORTS)) {
149
+ if (keyFor(id) === key) {
150
+ profile = row;
151
+ break;
152
+ }
153
+ }
154
+ if (!profile) return undefined;
155
+ try {
156
+ const response = await fetchFn(profile.profileUrl, {
157
+ headers: { Accept: "text/html" },
158
+ signal: AbortSignal.timeout(10_000),
159
+ });
160
+ if (!response.ok) return undefined;
161
+ // Bound the profile page before parsing: a large or malformed page must not
162
+ // allocate unbounded memory on the request path.
163
+ const observed = await readBoundedResponseBody(response, { maxBytes: 256 * 1024 });
164
+ if (!observed.displaySafe) return undefined;
165
+ const efforts = parsedProfileEfforts(observed.text);
166
+ if (efforts === undefined) return undefined;
167
+ refreshedEfforts.set(key, efforts);
168
+ return efforts;
169
+ } catch {
170
+ return undefined;
171
+ }
172
+ }
173
+
174
+ export function resetCommandCodeReasoningEffortsForTest(): void {
175
+ refreshedEfforts.clear();
176
+ }
@@ -1,4 +1,5 @@
1
1
  import type { OcxConfig } from "../types";
2
+ import { deleteConfigTopLevelKey } from "../config/rebase-provenance";
2
3
 
3
4
  export const DEFAULT_PROVIDER_CONTEXT_CAP = 350_000;
4
5
 
@@ -27,25 +28,42 @@ export function applyProviderContextCap(contextWindow: number | undefined, cap:
27
28
  return contextWindow > cap ? cap : contextWindow;
28
29
  }
29
30
 
31
+ /**
32
+ * 上游没报窗口时,已开启的 Context cap 就是实际窗口。
33
+ * 128k 只是 Codex 解析器的兼容底线,不能当成“已发现窗口”再拿去和 cap 做 min。
34
+ */
35
+ export function resolveUnknownRoutedContextWindow(cap: number | undefined): number {
36
+ const window = isValidContextCap(cap) ? Math.floor(cap) : 0;
37
+ return window > 0 ? window : 128_000;
38
+ }
39
+
30
40
  /** Effective global cap value: explicit config value, else the built-in default. */
31
41
  export function globalContextCapValue(config: Pick<OcxConfig, "contextCapValue">): number {
32
42
  const value = config.contextCapValue;
33
43
  return isValidContextCap(value) ? Math.floor(value) : DEFAULT_PROVIDER_CONTEXT_CAP;
34
44
  }
35
45
 
36
- export function setProviderContextCap(config: OcxConfig, provider: string, enabled: boolean): void {
46
+ export function setProviderContextCap(config: OcxConfig, provider: string, enabled: boolean, value?: number): void {
37
47
  const next = providerContextCaps(config);
38
- if (enabled) next[provider] = globalContextCapValue(config);
39
- else delete next[provider];
48
+ if (enabled) {
49
+ next[provider] = isValidContextCap(value) ? Math.floor(value) : globalContextCapValue(config);
50
+ } else {
51
+ delete next[provider];
52
+ }
40
53
  if (Object.keys(next).length > 0) config.providerContextCaps = next;
41
- else delete config.providerContextCaps;
54
+ else deleteConfigTopLevelKey(config, "providerContextCaps");
42
55
  }
43
56
 
44
- /** Set the global cap value and re-point every already-enabled provider to it. */
45
- export function setGlobalContextCapValue(config: OcxConfig, value: number): void {
57
+ /**
58
+ * Set the global cap value (the default used by per-provider toggles and "set all").
59
+ * Re-points every already-enabled provider only when `applyToAll` is true (the dashboard's
60
+ * "apply to every routed provider" toggle); otherwise each provider keeps its own cap value.
61
+ */
62
+ export function setGlobalContextCapValue(config: OcxConfig, value: number, applyToAll: boolean): void {
46
63
  if (!isValidContextCap(value)) return;
47
64
  const next = Math.floor(value);
48
65
  config.contextCapValue = next;
66
+ if (!applyToAll) return;
49
67
  const caps = providerContextCaps(config);
50
68
  for (const provider of Object.keys(caps)) caps[provider] = next;
51
69
  if (Object.keys(caps).length > 0) config.providerContextCaps = caps;
@@ -54,12 +72,12 @@ export function setGlobalContextCapValue(config: OcxConfig, value: number): void
54
72
  /** Enable the cap for every named provider at the current value, or clear all caps. */
55
73
  export function setAllProviderContextCaps(config: OcxConfig, providerNames: string[], enabled: boolean): void {
56
74
  if (!enabled) {
57
- delete config.providerContextCaps;
75
+ deleteConfigTopLevelKey(config, "providerContextCaps");
58
76
  return;
59
77
  }
60
78
  const value = globalContextCapValue(config);
61
79
  const next: Record<string, number> = {};
62
80
  for (const name of providerNames) next[name] = value;
63
81
  if (Object.keys(next).length > 0) config.providerContextCaps = next;
64
- else delete config.providerContextCaps;
82
+ else deleteConfigTopLevelKey(config, "providerContextCaps");
65
83
  }