@bitkyc08/opencodex 2.84.0 → 2.87.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 (518) hide show
  1. package/README.md +0 -4
  2. package/bin/ocx.mjs +61 -3
  3. package/gui/dist/assets/App-ZfYbLHkB.js +58 -0
  4. package/gui/dist/assets/App-wT3mXqFz.css +1 -0
  5. package/gui/dist/assets/{Tray-C9TGtwad.js → Tray-DCd-A1az.js} +1 -1
  6. package/gui/dist/assets/index-CfYDMj34.js +94 -0
  7. package/gui/dist/assets/index-DPeB9HpV.css +1 -0
  8. package/gui/dist/assets/quota-summary-ChvmKGOk.js +1 -0
  9. package/gui/dist/index.html +2 -2
  10. package/package.json +1 -2
  11. package/src/adapters/anthropic/beta-allowlist.ts +91 -11
  12. package/src/adapters/anthropic/beta-body-pairs.ts +93 -0
  13. package/src/adapters/anthropic/client-identity.ts +1 -1
  14. package/src/adapters/anthropic/passthrough.ts +16 -3
  15. package/src/adapters/anthropic-progress.ts +84 -0
  16. package/src/adapters/anthropic.ts +108 -21
  17. package/src/adapters/azure.ts +19 -1
  18. package/src/adapters/base.ts +2 -0
  19. package/src/adapters/claude-cli/adapter.ts +111 -23
  20. package/src/adapters/claude-cli/profiles.ts +2 -1
  21. package/src/adapters/claude-cli/stable-replay.ts +108 -0
  22. package/src/adapters/claude-cli/usage-admission.ts +230 -0
  23. package/src/adapters/client-fingerprint.ts +24 -0
  24. package/src/adapters/coding-agent/protocol.ts +1 -1
  25. package/src/adapters/coding-agent/turn.ts +40 -11
  26. package/src/adapters/cursor/arg-codec.ts +17 -5
  27. package/src/adapters/cursor/catalog.ts +8 -0
  28. package/src/adapters/cursor/effort-map.ts +3 -0
  29. package/src/adapters/cursor/freeform-args.ts +75 -0
  30. package/src/adapters/cursor/protobuf-events.ts +36 -23
  31. package/src/adapters/dsh-account.ts +97 -0
  32. package/src/adapters/google-antigravity-wire.ts +22 -1
  33. package/src/adapters/google.ts +37 -10
  34. package/src/adapters/openai-chat/messages.ts +4 -3
  35. package/src/adapters/openai-chat/passthrough.ts +8 -2
  36. package/src/adapters/openai-chat/reasoning-replay.ts +52 -0
  37. package/src/adapters/openai-chat/response-events.ts +59 -1
  38. package/src/adapters/openai-chat.ts +8 -5
  39. package/src/adapters/openai-responses/compaction-search-history.ts +14 -7
  40. package/src/adapters/openai-responses/passthrough.ts +57 -125
  41. package/src/adapters/openai-responses/request-strips.ts +25 -3
  42. package/src/adapters/openai-responses/transport.ts +81 -0
  43. package/src/adapters/qoder/adapter.ts +44 -3
  44. package/src/adapters/registry.ts +5 -0
  45. package/src/adapters/zed.ts +26 -1
  46. package/src/advisor/activity.ts +55 -0
  47. package/src/advisor/budget.ts +62 -0
  48. package/src/advisor/consult.ts +223 -0
  49. package/src/advisor/context.ts +238 -0
  50. package/src/advisor/disclosure.ts +20 -0
  51. package/src/advisor/evidence-tool.ts +21 -0
  52. package/src/advisor/evidence.ts +117 -0
  53. package/src/advisor/runtime.ts +353 -0
  54. package/src/advisor/settings.ts +144 -0
  55. package/src/advisor/state.ts +369 -0
  56. package/src/advisor/synthetic-tool.ts +33 -0
  57. package/src/bridge/errors.ts +24 -1
  58. package/src/bridge/internal.ts +3 -1
  59. package/src/bridge/response-json.ts +18 -3
  60. package/src/bridge/sse.ts +58 -8
  61. package/src/bridge/terminal-refusal.ts +59 -0
  62. package/src/chat/inbound.ts +30 -6
  63. package/src/chat/outbound.ts +5 -0
  64. package/src/claude/desktop-3p-library.ts +72 -7
  65. package/src/claude/desktop-3p.ts +75 -19
  66. package/src/claude/desktop-first-party.ts +1 -1
  67. package/src/claude/desktop-picker-platform.ts +4 -0
  68. package/src/claude/desktop-picker-profile.ts +11 -4
  69. package/src/claude/desktop-picker.ts +15 -8
  70. package/src/claude/desktop-profile.ts +10 -1
  71. package/src/claude/desktop-remote-store-io.ts +5 -3
  72. package/src/claude/desktop-system-proxy.ts +50 -4
  73. package/src/claude/inbound-content-options.ts +11 -0
  74. package/src/claude/inbound.ts +154 -50
  75. package/src/claude/intercept/local-ca.ts +8 -1
  76. package/src/claude/intercept/picker-ca-startup.ts +2 -1
  77. package/src/claude/intercept/picker-runtime.ts +6 -5
  78. package/src/claude/intercept/picker-trust-windows.ts +338 -0
  79. package/src/claude/intercept/picker-trust.ts +19 -0
  80. package/src/claude/intercept/port-policy.ts +30 -0
  81. package/src/claude/intercept/runtime.ts +97 -94
  82. package/src/claude/model-default-settings.ts +154 -0
  83. package/src/claude/model-info.ts +7 -7
  84. package/src/claude/outbound.ts +51 -19
  85. package/src/cli/account-api.ts +1 -0
  86. package/src/cli/account-policy-dto.ts +6 -0
  87. package/src/cli/account-policy.ts +34 -5
  88. package/src/cli/account-preservation.ts +44 -0
  89. package/src/cli/account.ts +8 -2
  90. package/src/cli/advisor.ts +165 -0
  91. package/src/cli/auxiliary-listener-preflight.ts +37 -0
  92. package/src/cli/capabilities-accounts.ts +20 -1
  93. package/src/cli/capabilities-agents-routing.ts +23 -2
  94. package/src/cli/capabilities-base.ts +39 -11
  95. package/src/cli/capabilities-observe-system.ts +63 -3
  96. package/src/cli/capabilities-provider-models.ts +11 -0
  97. package/src/cli/chatgpt-command.ts +35 -14
  98. package/src/cli/claude.ts +46 -6
  99. package/src/cli/codex-cli-update.ts +151 -41
  100. package/src/cli/codex-provider.ts +44 -0
  101. package/src/cli/combo-input.ts +10 -1
  102. package/src/cli/combo-result.ts +1 -1
  103. package/src/cli/combo.ts +2 -1
  104. package/src/cli/cross-home-owner.ts +17 -14
  105. package/src/cli/dispatch.ts +30 -5
  106. package/src/cli/doctor.ts +15 -1
  107. package/src/cli/ensure-desktop-cold-start.ts +382 -0
  108. package/src/cli/export-command.ts +1 -1
  109. package/src/cli/help.ts +4 -2
  110. package/src/cli/index.ts +14 -5
  111. package/src/cli/integration-plan-dto.ts +3 -0
  112. package/src/cli/log-history.ts +172 -0
  113. package/src/cli/models-runtime-subcommands.ts +1 -0
  114. package/src/cli/models-runtime.ts +72 -8
  115. package/src/cli/observe-stream.ts +2 -0
  116. package/src/cli/observe.ts +16 -4
  117. package/src/cli/provider.ts +27 -5
  118. package/src/cli/registry.ts +41 -9
  119. package/src/cli/restart-scope.ts +3 -1
  120. package/src/cli/runtime-api.ts +5 -3
  121. package/src/cli/system-command.ts +40 -8
  122. package/src/cli/uninstall-client-state.ts +32 -0
  123. package/src/cli/usage-compare.ts +309 -0
  124. package/src/cli/usage-model-search.ts +4 -4
  125. package/src/cli/usage-report.ts +2 -2
  126. package/src/cli/v2.ts +1 -1
  127. package/src/client/machine-listener.ts +1 -3
  128. package/src/client/runtime.ts +1 -0
  129. package/src/clients/client-path.ts +51 -0
  130. package/src/clients/config-export/contracts.ts +3 -1
  131. package/src/clients/config-export/model-metadata.ts +3 -2
  132. package/src/clients/config-export/qoder.ts +93 -0
  133. package/src/clients/config-export.ts +35 -48
  134. package/src/clients/gentle-shell-path.ts +87 -0
  135. package/src/codex/account-auto-switch.ts +2 -0
  136. package/src/codex/account-identity.ts +29 -0
  137. package/src/codex/account-label.ts +1 -1
  138. package/src/codex/account-lifecycle.ts +21 -5
  139. package/src/codex/account-preservation.ts +28 -0
  140. package/src/codex/account-use-remaining.ts +23 -0
  141. package/src/codex/app-server-processes.ts +97 -7
  142. package/src/codex/app-server-restart-service.ts +55 -4
  143. package/src/codex/auth-api/account-list.ts +4 -0
  144. package/src/codex/auth-api/account-pause-group.ts +6 -50
  145. package/src/codex/auth-api/account-preservation.ts +57 -0
  146. package/src/codex/auth-api/pool-mode-gate.ts +5 -2
  147. package/src/codex/auth-api/routes.ts +8 -0
  148. package/src/codex/auth-api/use-remaining-route.ts +36 -0
  149. package/src/codex/auth-api.ts +0 -1
  150. package/src/codex/auth-context.ts +81 -7
  151. package/src/codex/autostart-health.ts +4 -0
  152. package/src/codex/catalog/auto-review.ts +20 -3
  153. package/src/codex/catalog/build-entries.ts +19 -2
  154. package/src/codex/catalog/combo-member.ts +14 -5
  155. package/src/codex/catalog/configured-tiers.ts +50 -0
  156. package/src/codex/catalog/effort.ts +4 -1
  157. package/src/codex/catalog/gather-capture.ts +2 -0
  158. package/src/codex/catalog/metadata.ts +11 -9
  159. package/src/codex/catalog/model-hints.ts +42 -19
  160. package/src/codex/catalog/model-visibility.ts +3 -1
  161. package/src/codex/catalog/native-ultrafast.ts +106 -0
  162. package/src/codex/catalog/parsing.ts +35 -86
  163. package/src/codex/catalog/provider-models.ts +40 -34
  164. package/src/codex/catalog/retained-sync.ts +2 -0
  165. package/src/codex/catalog/routed-gather.ts +33 -16
  166. package/src/codex/catalog/vendor-context.ts +82 -0
  167. package/src/codex/cli-install-provenance.ts +105 -17
  168. package/src/codex/cli-update-plan.ts +545 -0
  169. package/src/codex/config-write-lock.ts +63 -4
  170. package/src/codex/convergence.ts +2 -0
  171. package/src/codex/desktop-app/picker-freshness.ts +96 -0
  172. package/src/codex/desktop-app/types.ts +2 -0
  173. package/src/codex/desktop-app/windows.ts +29 -16
  174. package/src/codex/desktop-app-restart.ts +25 -2
  175. package/src/codex/desktop-compatibility/certificate-service.ts +99 -0
  176. package/src/codex/desktop-compatibility/certificate-store.ts +193 -0
  177. package/src/codex/desktop-compatibility/connection-store.ts +87 -0
  178. package/src/codex/desktop-compatibility/installed-build.ts +73 -0
  179. package/src/codex/desktop-compatibility/json-body.ts +29 -0
  180. package/src/codex/desktop-compatibility/native-identity.ts +62 -0
  181. package/src/codex/desktop-compatibility/relay-listener.ts +93 -0
  182. package/src/codex/desktop-compatibility/routing-binding.ts +10 -0
  183. package/src/codex/desktop-compatibility/routing-preflight.ts +69 -0
  184. package/src/codex/desktop-compatibility/runtime-ownership.ts +28 -0
  185. package/src/codex/desktop-compatibility/runtime.ts +182 -0
  186. package/src/codex/desktop-compatibility/service.ts +30 -0
  187. package/src/codex/desktop-compatibility/startup-settings.ts +50 -0
  188. package/src/codex/desktop-compatibility/usage-activation.ts +86 -0
  189. package/src/codex/desktop-compatibility/usage-controlled-fetch.ts +59 -0
  190. package/src/codex/desktop-compatibility/usage-controller.ts +107 -0
  191. package/src/codex/desktop-compatibility/usage-policy.ts +59 -0
  192. package/src/codex/desktop-compatibility/usage-refresh.ts +33 -0
  193. package/src/codex/desktop-compatibility/usage-sse-controller.ts +86 -0
  194. package/src/codex/desktop-compatibility/windows-activation-source.ts +44 -0
  195. package/src/codex/desktop-compatibility/windows-certificate-trust.ts +81 -0
  196. package/src/codex/desktop-compatibility/windows-key-protection.ts +165 -0
  197. package/src/codex/desktop-compatibility/windows-package-command.ts +86 -0
  198. package/src/codex/desktop-compatibility/windows-package-launch.ts +28 -0
  199. package/src/codex/features.ts +85 -45
  200. package/src/codex/history-provider.ts +1 -1
  201. package/src/codex/inject/config-write-section.ts +4 -1
  202. package/src/codex/inject/history-failure.ts +27 -0
  203. package/src/codex/inject/remove.ts +18 -6
  204. package/src/codex/inject/restore.ts +24 -2
  205. package/src/codex/inject/routing-classify.ts +4 -3
  206. package/src/codex/inject.ts +18 -27
  207. package/src/codex/journal.ts +16 -1
  208. package/src/codex/main-account-hard-lock.ts +30 -1
  209. package/src/codex/main-account.ts +99 -15
  210. package/src/codex/native-main-refresh-mode.ts +217 -0
  211. package/src/codex/native-profile-startup.ts +1 -1
  212. package/src/codex/ocx-compaction-history.ts +12 -10
  213. package/src/codex/paths.ts +86 -1
  214. package/src/codex/provider-routing.ts +174 -0
  215. package/src/codex/refresh.ts +2 -2
  216. package/src/codex/routing/health-store.ts +2 -2
  217. package/src/codex/routing/pool-recovery.ts +79 -0
  218. package/src/codex/routing/selection.ts +4 -3
  219. package/src/codex/routing/thread-affinity.ts +1 -1
  220. package/src/codex/shim-diagnostics.ts +6 -0
  221. package/src/codex/shim-overlay.ts +7 -2
  222. package/src/codex/signed-in-identity.ts +43 -0
  223. package/src/codex/subagent-model-fallback.ts +1 -1
  224. package/src/codex/sync.ts +6 -1
  225. package/src/codex/user-identity.ts +16 -5
  226. package/src/codex/windows-local-appdata.ts +84 -0
  227. package/src/combos/failover.ts +6 -1
  228. package/src/combos/index.ts +1 -0
  229. package/src/combos/resolve.ts +46 -10
  230. package/src/combos/types.ts +15 -0
  231. package/src/config/diagnostics.ts +35 -7
  232. package/src/config/live-reconcile.ts +51 -2
  233. package/src/config/load-degrade.ts +23 -1
  234. package/src/config/opencode-wire-upgrade.ts +54 -0
  235. package/src/config/opencode-zen-upgrade.ts +52 -0
  236. package/src/config/owner-registry.ts +22 -17
  237. package/src/config/paths.ts +10 -3
  238. package/src/config/provider-validation.ts +45 -2
  239. package/src/config/schema/config-schema.ts +39 -0
  240. package/src/config/schema/desktop-compatibility.ts +9 -0
  241. package/src/config/schema/leaf-validators.ts +39 -9
  242. package/src/config/schema/main-account-hard-lock-fallback.ts +26 -0
  243. package/src/config/schema/native-reasoning-retention.ts +26 -0
  244. package/src/config.ts +2 -0
  245. package/src/generated/compatibility-version.json +962 -350
  246. package/src/generated/model-metadata.ts +1 -1
  247. package/src/grok/sync.ts +1 -1
  248. package/src/images/loop.ts +46 -8
  249. package/src/integrations/catalog-refresh.ts +1 -1
  250. package/src/integrations/config-io.ts +20 -2
  251. package/src/integrations/journal.ts +15 -1
  252. package/src/integrations/mutation-plan.ts +2 -0
  253. package/src/integrations/registry.ts +15 -0
  254. package/src/integrations/store.ts +3 -0
  255. package/src/integrations/writer.ts +10 -1
  256. package/src/lib/advisor-activation.ts +16 -0
  257. package/src/lib/background-work.ts +65 -0
  258. package/src/lib/bounded-file-read.ts +58 -0
  259. package/src/lib/bun-path-runtime.d.mts +10 -1
  260. package/src/lib/bun-path-runtime.mjs +62 -3
  261. package/src/lib/codex-restart-contract.ts +15 -0
  262. package/src/lib/desktop-proxy-route.ts +30 -0
  263. package/src/lib/desktop-upstream-tunnel.ts +72 -0
  264. package/src/lib/empty-tool-catalog.ts +62 -0
  265. package/src/lib/errors.ts +26 -3
  266. package/src/lib/gcp-adc.ts +96 -9
  267. package/src/lib/gcp-credential-input.ts +12 -0
  268. package/src/lib/lab-live-route-production.ts +5 -0
  269. package/src/lib/local-internal-call-capability.ts +55 -0
  270. package/src/lib/opaque-proxy-tunnel.ts +217 -0
  271. package/src/lib/package-tree-integrity.ts +2 -2
  272. package/src/lib/redact.ts +2 -2
  273. package/src/lib/socks5-fetch.ts +48 -71
  274. package/src/lib/socks5-handshake.ts +112 -0
  275. package/src/lib/translator-budget.ts +7 -1
  276. package/src/oauth/account-quota-rank.ts +69 -2
  277. package/src/oauth/anthropic-account-refusal.ts +20 -2
  278. package/src/oauth/anthropic-oauth-definitions.ts +3 -1
  279. package/src/oauth/anthropic-routing.ts +1 -21
  280. package/src/oauth/anthropic.ts +38 -7
  281. package/src/oauth/callback-server.ts +27 -1
  282. package/src/oauth/chatgpt-device.ts +1 -1
  283. package/src/oauth/chatgpt-shared.ts +83 -0
  284. package/src/oauth/chatgpt.ts +8 -72
  285. package/src/oauth/dsh.ts +203 -0
  286. package/src/oauth/generic-account-failover.ts +62 -12
  287. package/src/oauth/generic-session-affinity.ts +125 -0
  288. package/src/oauth/index.ts +188 -111
  289. package/src/oauth/kiro-device-login.ts +2 -1
  290. package/src/oauth/kiro.ts +7 -1
  291. package/src/oauth/local-token-detect.ts +21 -1
  292. package/src/oauth/login-cli-errors.ts +44 -0
  293. package/src/oauth/login-cli.ts +69 -7
  294. package/src/oauth/login-flow-state.ts +371 -23
  295. package/src/oauth/meta-muse-errors.ts +41 -0
  296. package/src/oauth/meta-muse-keychain.ts +52 -0
  297. package/src/oauth/meta-muse.ts +51 -84
  298. package/src/oauth/model-discovery-auth.ts +3 -0
  299. package/src/oauth/pool-settings-capability.ts +4 -2
  300. package/src/oauth/refresh-flight-retirement.ts +48 -0
  301. package/src/oauth/session-affinity-key.ts +23 -0
  302. package/src/oauth/store-anthropic-instance.ts +9 -2
  303. package/src/oauth/store.ts +12 -5
  304. package/src/protocols/codecs/chat-ir.ts +467 -0
  305. package/src/protocols/codecs/chat.ts +10 -1
  306. package/src/protocols/codecs/messages-ir.ts +500 -0
  307. package/src/protocols/encoders/adapter-events.ts +5 -4
  308. package/src/protocols/encoders/messages.ts +9 -6
  309. package/src/protocols/features.ts +10 -2
  310. package/src/protocols/path.ts +11 -1
  311. package/src/protocols/plan-snapshot.ts +39 -16
  312. package/src/protocols/plan.ts +9 -1
  313. package/src/protocols/provider-summary.ts +2 -1
  314. package/src/protocols/settings.ts +8 -0
  315. package/src/providers/antigravity-account-roster.ts +102 -0
  316. package/src/providers/antigravity-models.ts +85 -7
  317. package/src/providers/api-key-cooldowns.ts +49 -0
  318. package/src/providers/api-key-resolve.ts +11 -6
  319. package/src/providers/api-key-response-ownership.ts +57 -0
  320. package/src/providers/api-key-selection.ts +31 -6
  321. package/src/providers/api-keys.ts +214 -3
  322. package/src/providers/claude-cli-usage.ts +96 -0
  323. package/src/providers/dsh-account-destination.ts +31 -0
  324. package/src/providers/dsh-account-models.ts +41 -0
  325. package/src/providers/gcp-credential-cleanup.ts +59 -0
  326. package/src/providers/key-failover.ts +54 -50
  327. package/src/providers/key-store.ts +7 -2
  328. package/src/providers/model-rename-fields.ts +5 -0
  329. package/src/providers/model-rename-migration.ts +7 -5
  330. package/src/providers/openai-tiers-destination.ts +11 -2
  331. package/src/providers/openai-tiers.ts +5 -12
  332. package/src/providers/opencode-go-transport.ts +3 -1
  333. package/src/providers/quota/account-cache.ts +6 -5
  334. package/src/providers/quota/account-row.ts +34 -0
  335. package/src/providers/quota/antigravity.ts +28 -7
  336. package/src/providers/quota/dsh-account.ts +70 -0
  337. package/src/providers/quota/vendor-probes-oauth.ts +1 -93
  338. package/src/providers/quota-types.ts +2 -0
  339. package/src/providers/quota.ts +14 -20
  340. package/src/providers/registry/entries-core.ts +44 -14
  341. package/src/providers/registry/entries-extended.ts +19 -0
  342. package/src/providers/registry/types.ts +1 -1
  343. package/src/providers/request-pacing.ts +77 -19
  344. package/src/providers/routed-config.ts +339 -0
  345. package/src/providers/service-tier.ts +2 -1
  346. package/src/quota/window-mapping.ts +5 -2
  347. package/src/responses/anthropic-progress.ts +34 -0
  348. package/src/responses/assistant-replay.ts +35 -0
  349. package/src/responses/compaction-history-framing.ts +65 -0
  350. package/src/responses/compaction.ts +6 -1
  351. package/src/responses/incomplete-reason.ts +31 -0
  352. package/src/responses/parser.ts +78 -22
  353. package/src/responses/reasoning-envelope.ts +4 -0
  354. package/src/responses/reasoning-replay-cache.ts +24 -2
  355. package/src/responses/reasoning-retention.ts +173 -0
  356. package/src/responses/retained-compaction.ts +46 -0
  357. package/src/responses/schema.ts +23 -0
  358. package/src/responses/state.ts +32 -29
  359. package/src/router.ts +8 -321
  360. package/src/routing/health.ts +37 -22
  361. package/src/routing/history/build-file.ts +92 -0
  362. package/src/routing/history/indexer.ts +254 -221
  363. package/src/routing/history/ingest.ts +242 -0
  364. package/src/routing/history/rebuild-job.ts +111 -0
  365. package/src/routing/history/rebuild-protocol.ts +15 -0
  366. package/src/routing/history/rebuild-worker.ts +34 -0
  367. package/src/routing/profile.ts +1 -1
  368. package/src/server/admission-model-scope.ts +21 -1
  369. package/src/server/antigravity-direct-eligibility.ts +208 -0
  370. package/src/server/auth-cors.ts +15 -0
  371. package/src/server/chat-completions.ts +82 -10
  372. package/src/server/chat-native-reasoning.ts +123 -0
  373. package/src/server/chat-native-sse.ts +110 -7
  374. package/src/server/chat-native.ts +76 -17
  375. package/src/server/claude-messages.ts +164 -433
  376. package/src/server/effort-policy.ts +1 -1
  377. package/src/server/images.ts +15 -2
  378. package/src/server/index/desktop-compatibility-startup.ts +56 -0
  379. package/src/server/index/model-alias-id.ts +36 -0
  380. package/src/server/index/optional-listeners.ts +2 -0
  381. package/src/server/index/serve-options.ts +11 -3
  382. package/src/server/index/startup-warnings.ts +11 -0
  383. package/src/server/index/websocket-handler.ts +9 -0
  384. package/src/server/index.ts +14 -11
  385. package/src/server/inference/advisor-diagnostics.ts +31 -0
  386. package/src/server/inference/client-encoder-delivery.ts +6 -5
  387. package/src/server/login-shell-path.ts +146 -0
  388. package/src/server/management/advisor-routes.ts +202 -0
  389. package/src/server/management/agent-settings-routes.ts +22 -4
  390. package/src/server/management/claude-desktop-picker-routes.ts +1 -1
  391. package/src/server/management/combo-routes.ts +176 -50
  392. package/src/server/management/companion-routes.ts +4 -0
  393. package/src/server/management/config-routes.ts +77 -6
  394. package/src/server/management/context.ts +4 -0
  395. package/src/server/management/cursor-integration-routes.ts +1 -1
  396. package/src/server/management/desktop-compatibility-routes.ts +46 -0
  397. package/src/server/management/desktop-compatibility-runtime-routes.ts +46 -0
  398. package/src/server/management/desktop-compatibility-settings-routes.ts +27 -0
  399. package/src/server/management/model-routes.ts +13 -8
  400. package/src/server/management/model-rows.ts +14 -0
  401. package/src/server/management/native-integration-routes.ts +2 -7
  402. package/src/server/management/native-reasoning-retention-routes.ts +41 -0
  403. package/src/server/management/oauth-account-routes.ts +87 -14
  404. package/src/server/management/protocol-settings-patch.ts +1 -0
  405. package/src/server/management/provider-gcp-credential-routes.ts +29 -0
  406. package/src/server/management/provider-key-pacing-routes.ts +31 -0
  407. package/src/server/management/provider-overwrite-carry.ts +7 -0
  408. package/src/server/management/provider-routes.ts +25 -30
  409. package/src/server/management/route-registry.ts +21 -1
  410. package/src/server/management/sibling-guard.ts +1 -0
  411. package/src/server/management-api.ts +9 -1
  412. package/src/server/messages-antigravity-direct.ts +195 -0
  413. package/src/server/messages-native-tool-guard.ts +185 -0
  414. package/src/server/messages-native.ts +106 -22
  415. package/src/server/messages-shared.ts +431 -0
  416. package/src/server/relay.ts +1 -1
  417. package/src/server/request-log-terminal-status.ts +1 -1
  418. package/src/server/request-log.ts +13 -1
  419. package/src/server/responses/account-change-state.ts +8 -2
  420. package/src/server/responses/adapter-continuation.ts +48 -19
  421. package/src/server/responses/adapter-delivery.ts +43 -8
  422. package/src/server/responses/adapter-dispatch.ts +48 -4
  423. package/src/server/responses/advisor-plan-slot.ts +27 -0
  424. package/src/server/responses/advisor-retention.ts +117 -0
  425. package/src/server/responses/advisor-slot.ts +368 -0
  426. package/src/server/responses/code-mode-collab-surface.ts +116 -8
  427. package/src/server/responses/codex-ws-wire.ts +15 -8
  428. package/src/server/responses/compact.ts +303 -125
  429. package/src/server/responses/compaction-recovery.ts +18 -10
  430. package/src/server/responses/compaction-retention.ts +61 -0
  431. package/src/server/responses/context-overflow.ts +11 -6
  432. package/src/server/responses/core-auth.ts +6 -0
  433. package/src/server/responses/core-codex-account.ts +11 -1
  434. package/src/server/responses/core-combo-failure.ts +12 -1
  435. package/src/server/responses/core-combo.ts +141 -36
  436. package/src/server/responses/core-errors.ts +3 -3
  437. package/src/server/responses/core-lifetime.ts +7 -2
  438. package/src/server/responses/core-normalize.ts +11 -0
  439. package/src/server/responses/core-opaque-recovery.ts +35 -0
  440. package/src/server/responses/core-options.ts +51 -0
  441. package/src/server/responses/core-pipeline.ts +141 -0
  442. package/src/server/responses/core-replay.ts +25 -6
  443. package/src/server/responses/core.ts +3 -116
  444. package/src/server/responses/fetch-helpers.ts +73 -19
  445. package/src/server/responses/main-hard-lock-routing.ts +109 -0
  446. package/src/server/responses/native-response-control.ts +4 -2
  447. package/src/server/responses/passthrough-delivery.ts +19 -11
  448. package/src/server/responses/passthrough-dispatch.ts +29 -16
  449. package/src/server/responses/request-prepare.ts +144 -17
  450. package/src/server/responses/request-sidecar-auth.ts +2 -2
  451. package/src/server/responses/request-transport.ts +120 -27
  452. package/src/server/responses/response-effects.ts +1 -0
  453. package/src/server/responses/run-turn-execution.ts +166 -38
  454. package/src/server/responses/sidecar-execution.ts +98 -5
  455. package/src/server/responses/terminal-guard.ts +4 -17
  456. package/src/server/responses-undeclared-tool-guard.ts +30 -9
  457. package/src/server/startup-action-control.ts +16 -2
  458. package/src/server/startup-health-cache.ts +1 -0
  459. package/src/service/auth-preflight.ts +71 -0
  460. package/src/service/cli.ts +4 -2
  461. package/src/service/definition.ts +97 -0
  462. package/src/service/desktop-startup.ts +14 -0
  463. package/src/service/guards.ts +1 -61
  464. package/src/service/health-sentinel-linux.ts +112 -0
  465. package/src/service/health-sentinel-main.ts +99 -61
  466. package/src/service/health-sentinel-probe.ts +24 -7
  467. package/src/service/health.ts +5 -89
  468. package/src/service/launchd.ts +27 -7
  469. package/src/service/logging.ts +135 -0
  470. package/src/service/repair.ts +2 -1
  471. package/src/service/state.ts +7 -8
  472. package/src/service/systemd.ts +1 -1
  473. package/src/service/windows-guarded-manager.ts +2 -1
  474. package/src/service/windows-ops.ts +1 -1
  475. package/src/service/windows-scheduler.ts +2 -7
  476. package/src/service/windows-taskxml.ts +2 -2
  477. package/src/service/windows-wscript.ts +14 -0
  478. package/src/service.ts +4 -2
  479. package/src/sidecar/auth.ts +2 -0
  480. package/src/tray/windows-tray.ps1 +43 -24
  481. package/src/types/config.ts +124 -6
  482. package/src/types/opencode-go.ts +61 -0
  483. package/src/types/opencode-zen.ts +29 -0
  484. package/src/types/provider.ts +39 -6
  485. package/src/types/request.ts +38 -2
  486. package/src/types/tools.ts +2 -0
  487. package/src/types/wire.ts +29 -37
  488. package/src/types.ts +1 -0
  489. package/src/update/async-check.ts +1 -1
  490. package/src/update/badge.ts +2 -2
  491. package/src/update/index.ts +88 -15
  492. package/src/update/job-supervised-restart.ts +107 -0
  493. package/src/update/job.ts +32 -32
  494. package/src/update/notify.ts +1 -1
  495. package/src/update/npm-invocation.mjs +12 -2
  496. package/src/update/refresh-scheduler.ts +2 -2
  497. package/src/update/supervised-recovery.d.mts +27 -0
  498. package/src/update/supervised-recovery.mjs +157 -0
  499. package/src/usage/cache-diagnostic.ts +2 -0
  500. package/src/usage/cost.ts +48 -12
  501. package/src/usage/expected-prices.ts +15 -0
  502. package/src/usage/ledger-retention.ts +2 -1
  503. package/src/usage/ledger-scanner.ts +6 -5
  504. package/src/usage/log.ts +17 -8
  505. package/src/usage/summary.ts +22 -9
  506. package/src/usage/user-cost-overlays.ts +14 -19
  507. package/src/usage/user-cost-validation.ts +38 -0
  508. package/src/vision/eligibility.ts +13 -0
  509. package/src/web-search/gemini-executor.ts +2 -2
  510. package/src/web-search/loop.ts +55 -5
  511. package/src/web-search/progress-stream.ts +4 -1
  512. package/src/web-search/run-turn-loop.ts +9 -1
  513. package/assets/sponsors/packycode.png +0 -0
  514. package/gui/dist/assets/App-CSJvmjNs.css +0 -1
  515. package/gui/dist/assets/App-CZtqiGcw.js +0 -56
  516. package/gui/dist/assets/index-BB6uK6tU.css +0 -1
  517. package/gui/dist/assets/index-CTm4l-HQ.js +0 -94
  518. package/gui/dist/assets/quota-summary-BbEeRfPY.js +0 -1
@@ -1,8 +1,12 @@
1
1
  import { MAIN_ACCOUNT_HARD_LOCK_MIN_PERCENT } from "../../codex/quota-types";
2
+ import { validRemainingQuotaAccountIds } from "../../codex/account-use-remaining";
2
3
  import * as z from "zod/v4";
3
4
  import { anthropicAccountPoolSchema } from "./anthropic-account-pool";
4
5
  import { compactionRecoverySchema } from "./compaction-recovery";
6
+ import { nativeReasoningRetentionSchema } from "./native-reasoning-retention";
7
+ import { desktopCompatibilitySchema } from "./desktop-compatibility";
5
8
  import { blockedModelRedirectsSchema } from "./blocked-model-redirects";
9
+ import { mainAccountHardLockFallbackSchema } from "./main-account-hard-lock-fallback";
6
10
  import {
7
11
  agentTaskRecoverySchema,
8
12
  catalogAutoRefreshSchema,
@@ -28,7 +32,9 @@ import {
28
32
  CODEX_ACCOUNT_NAMESPACE_ACCOUNT_ID_COLLISION_ERROR,
29
33
  codexAccountNamespacesSchema,
30
34
  modelPinnedEffortsSchema,
35
+ autoReviewOverrideSchema,
31
36
  compactionRoutingSchema,
37
+ reasoningRetentionSchema,
32
38
  memoryModelSettingSchema,
33
39
  memoryModelsSchema,
34
40
  modelPreferHostedToolsConfigError,
@@ -48,6 +54,7 @@ import {
48
54
  providerHeadersConfigError,
49
55
  providerForwardClientHeadersConfigError,
50
56
  reasoningSummaryDeliveryRecordConfigError,
57
+ credentialPinnedProviderConfigError,
51
58
  } from "../provider-validation";
52
59
  import {
53
60
  CODEX_ACCOUNT_NAMESPACE_COMBO_ALIAS_COLLISION_ERROR,
@@ -83,6 +90,7 @@ export const protocolConfigSchema = z.object({
83
90
  managedMessagesNative: z.boolean().optional(),
84
91
  managedMessagesNativeOAuth: z.boolean().optional(),
85
92
  directEncoders: z.boolean().optional(),
93
+ antigravityDirect: z.boolean().optional(),
86
94
  shadowPlan: z.boolean().optional(),
87
95
  }).strict().optional(),
88
96
  }).strict();
@@ -124,6 +132,7 @@ export const configSchema = z.object({
124
132
  managedMessagesNative: false,
125
133
  managedMessagesNativeOAuth: false,
126
134
  directEncoders: fields.directEncoders === true,
135
+ antigravityDirect: fields.antigravityDirect === true,
127
136
  shadowPlan: fields.shadowPlan === true,
128
137
  },
129
138
  };
@@ -187,9 +196,16 @@ export const configSchema = z.object({
187
196
  z.object({ enabled: z.literal(true), port: z.number().int().min(1).max(65535).optional() }),
188
197
  ]).optional().catch(undefined),
189
198
  providers: z.record(z.string(), providerConfigSchema),
199
+ // Models settings panel writes the global reviewer override; an invalid hand edit is
200
+ // stripped by load degradation so it cannot reject the providers that carry it.
201
+ autoReviewOverride: autoReviewOverrideSchema.optional(),
190
202
  modelPinnedEfforts: modelPinnedEffortsSchema.optional(),
191
203
  compactionRouting: compactionRoutingSchema.optional().catch(undefined),
192
204
  compactionRecovery: compactionRecoverySchema.optional().catch(undefined),
205
+ // A bad hand edit disables only this block; writes validate the catch-free leaf first.
206
+ reasoningRetention: reasoningRetentionSchema.optional().catch(undefined),
207
+ nativeReasoningRetention: nativeReasoningRetentionSchema.optional().catch(undefined),
208
+ desktopCompatibility: desktopCompatibilitySchema.optional().catch(undefined),
193
209
  // A hand-edited malformed phase disables only that phase instead of rejecting
194
210
  // providers/apiKeys, matching the load-time degradation notice; the management write
195
211
  // boundary (validateConfigCandidate) still refuses the bad value through the shared,
@@ -203,6 +219,7 @@ export const configSchema = z.object({
203
219
  .catch(undefined),
204
220
  defaultProvider: z.string().min(1).default("openai"),
205
221
  defaultModelAliases: z.boolean().optional(),
222
+ preferModelAliasIds: z.boolean().optional().catch(false),
206
223
  // Malformed hand edits disable this opt-in projection without rejecting providers.
207
224
  cursorEffortRows: z.boolean().optional().catch(false),
208
225
  // Fast selectors default on; malformed hand edits disable them without rejecting providers.
@@ -217,6 +234,11 @@ export const configSchema = z.object({
217
234
  short: z.number().int().min(MAIN_ACCOUNT_HARD_LOCK_MIN_PERCENT).max(100).optional().catch(undefined),
218
235
  long: z.number().int().min(MAIN_ACCOUNT_HARD_LOCK_MIN_PERCENT).max(100).optional().catch(undefined),
219
236
  }).optional().catch(undefined),
237
+ // A malformed fallback section disables only the reroute, never the lock's refusal
238
+ // behavior; the management write boundary still rejects the bad value.
239
+ codexMainAccountHardLockFallback: mainAccountHardLockFallbackSchema.optional().catch(undefined),
240
+ // #2999: a malformed hand edit falls back to auto detection rather than rejecting the config.
241
+ nativeMainRefresh: z.enum(["codex", "opencodex"]).optional().catch(undefined),
220
242
  // Future versions remain opaque through passthrough-compatible whole-config saves.
221
243
  // Only version 1 grants deletion authority in the rebase path.
222
244
  configRebaseProvenance: z.unknown().optional(),
@@ -286,6 +308,7 @@ export const configSchema = z.object({
286
308
  // so a hand-edited typo cannot trip the backup-and-defaults repair path; the write path rejects
287
309
  // it (creditCodexAccountIdsError in diagnostics).
288
310
  creditCodexAccountIds: z.array(z.string().regex(/^[a-zA-Z0-9._-]{1,64}$/)).optional().catch(undefined),
311
+ codexUseRemainingQuotaAccountIds: z.custom<string[]>(validRemainingQuotaAccountIds).optional().catch(undefined),
289
312
  // A malformed policy degrades to "no policy" rather than failing the parse, so a hand-edited
290
313
  // typo cannot trip the backup-and-defaults repair path and wipe providers or pool accounts.
291
314
  // Silently ignoring it would be its own trap, so the write path rejects it and loadConfig warns.
@@ -301,6 +324,7 @@ export const configSchema = z.object({
301
324
  codexAccountAutoSwitchThresholds: z.unknown().optional().transform(salvageCodexAccountAutoSwitchThresholds),
302
325
  // An invalid optional preference must not discard providers or credential rows.
303
326
  codexAccountPriorityFailback: z.boolean().optional().catch(false),
327
+ codexPreserveSignedInAccount: z.boolean().optional().catch(false),
304
328
  // Absent or invalid keeps the sliding window on. Explicit false restores consecutive-only steering.
305
329
  codexFailureWindow: z.boolean().optional().catch(undefined),
306
330
  codexPinnedTransientPolicy: z.enum(["hold", "detour-new-threads"]).optional().catch("hold"),
@@ -588,6 +612,10 @@ export const configSchema = z.object({
588
612
  message: modelAdaptersError,
589
613
  });
590
614
  }
615
+ const credentialPinError = credentialPinnedProviderConfigError(name, provider);
616
+ if (credentialPinError) {
617
+ ctx.addIssue({ code: "custom", path: ["providers", redactSecretString(name)], message: credentialPinError });
618
+ }
591
619
  const preferHostedToolsError = modelPreferHostedToolsConfigError(
592
620
  (provider as { modelPreferHostedTools?: unknown }).modelPreferHostedTools,
593
621
  "modelPreferHostedTools",
@@ -678,6 +706,17 @@ export const configSchema = z.object({
678
706
  message: reasoningSummaryDeliveryError,
679
707
  });
680
708
  }
709
+ const minMaxOutputError = positiveIntegerConfigError(
710
+ (provider as { minMaxOutputTokens?: unknown }).minMaxOutputTokens,
711
+ "minMaxOutputTokens",
712
+ );
713
+ if (minMaxOutputError) {
714
+ ctx.addIssue({
715
+ code: "custom",
716
+ path: ["providers", redactSecretString(name), "minMaxOutputTokens"],
717
+ message: minMaxOutputError,
718
+ });
719
+ }
681
720
  const defaultMaxOutputError = positiveIntegerConfigError(
682
721
  (provider as { defaultMaxOutputTokens?: unknown }).defaultMaxOutputTokens,
683
722
  "defaultMaxOutputTokens",
@@ -0,0 +1,9 @@
1
+ import * as z from "zod/v4";
2
+ /** Startup resumes observation only. Certificate trust, app launch and Apply are never saved here. */
3
+ export const desktopCompatibilitySchema = z.object({ startOnProxyStart: z.boolean() }).strict();
4
+ export function desktopCompatibilityConfigError(value: unknown): string | null {
5
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
6
+ const setting = (value as Record<string, unknown>).desktopCompatibility;
7
+ return setting === undefined || desktopCompatibilitySchema.safeParse(setting).success
8
+ ? null : "schema_invalid: desktopCompatibility: requires only boolean startOnProxyStart";
9
+ }
@@ -6,6 +6,7 @@ import {
6
6
  modelPinnedEffortsConfigError,
7
7
  pinnedReasoningEffortConfigError,
8
8
  modelDisplayNamesConfigError,
9
+ autoReviewOverrideConfigError,
9
10
  autoReviewModelOverridesConfigError,
10
11
  autoReviewModelTargetConfigError,
11
12
  normalizeNonBlankStringArray,
@@ -28,13 +29,14 @@ import {
28
29
  PROVIDER_WEB_SEARCH_BRIDGE_BACKENDS,
29
30
  UPSTREAM_HTTP_VERSION_VALUES,
30
31
  type OcxProviderConfig,
32
+ type OcxConfig,
31
33
  type FastWire,
32
34
  type ProviderCostOverlay,
33
35
  } from "../../types";
34
36
  import { fastWireDeclarationError } from "../../providers/fastwire";
35
37
  import { getProviderRegistryEntry, providerMatchesRegistryTransport, providerModelWireDefault } from "../../providers/registry";
36
38
  import { resolveOpenAiVirtualModel } from "../../providers/openai-virtual-models";
37
- import { COST4_RATE_KEYS, isValidCost4Rate } from "../../usage/user-cost-overlays";
39
+ import { COST4_RATE_KEYS, isValidCost4Rate, isValidPromptLengthPricing, copyPromptLengthPricing } from "../../usage/user-cost-overlays";
38
40
  import { MAX_COST4_RATE } from "../../usage/expected-prices";
39
41
  import {
40
42
  DECLARABLE_HOSTED_TOOL_TYPES,
@@ -63,6 +65,12 @@ export const compactionRoutingSchema = z.object({
63
65
  .optional(),
64
66
  }).strict();
65
67
 
68
+ export const reasoningRetentionSchema = z.object({
69
+ enabled: z.boolean().optional(),
70
+ maxContextPercent: z.number().gt(0).max(100).optional(),
71
+ maxTokens: z.number().int().positive().optional(),
72
+ }).strict();
73
+
66
74
  /**
67
75
  * One phase of Codex's memory pipeline. A present phase must name a model: the GUI's "Off"
68
76
  * removes the phase instead of blanking it, so an empty entry would only ever come from a
@@ -133,12 +141,15 @@ const requestPacingSchema = z.object({
133
141
  minIntervalMs: z.number().int().min(1).max(3_600_000).optional(),
134
142
  maxConcurrentRequests: z.number().int().min(1).optional(),
135
143
  models: z.record(z.string().trim().min(1), requestPacingRuleSchema).optional(),
144
+ keySelection: z.enum(["active", "round-robin"]).optional(),
145
+ keys: requestPacingRuleSchema.optional(),
136
146
  }).strict().refine(value => value.enabled === false
137
147
  || value.requestsPerMinute !== undefined
138
148
  || value.minIntervalMs !== undefined
139
149
  || value.maxConcurrentRequests !== undefined
150
+ || value.keys !== undefined || value.keySelection === "round-robin"
140
151
  || (value.models !== undefined && Object.keys(value.models).length > 0), {
141
- message: "enabled request pacing needs a provider rule or model override",
152
+ message: "enabled request pacing needs a provider, model, or key rule, or round-robin selection",
142
153
  });
143
154
 
144
155
  export function requestPacingConfigError(value: unknown): string | null {
@@ -257,6 +268,12 @@ const autoReviewModelOverridesSchema = z.unknown().superRefine((value, ctx) => {
257
268
  if (error) ctx.addIssue({ code: "custom", message: error });
258
269
  }).transform(value => normalizeAutoReviewModelOverrides(value));
259
270
 
271
+ /** Global auto-review override block; a malformed hand edit is stripped by load degradation. */
272
+ export const autoReviewOverrideSchema = z.unknown().superRefine((value, ctx) => {
273
+ const error = autoReviewOverrideConfigError(value, "autoReviewOverride");
274
+ if (error) ctx.addIssue({ code: "custom", message: error });
275
+ }).transform(value => value as NonNullable<OcxConfig["autoReviewOverride"]>);
276
+
260
277
  const modelCapabilitiesSchema = z.unknown().superRefine((value, ctx) => {
261
278
  const error = modelCapabilitiesConfigError(value);
262
279
  if (error) ctx.addIssue({ code: "custom", message: error });
@@ -331,14 +348,18 @@ export const providerConfigSchema = z.object({
331
348
  responseTierAuthoritative: z.boolean().optional(),
332
349
  fastEnabled: z.boolean().optional(),
333
350
  supportsServiceTier: z.boolean().optional(),
351
+ inferContextWindow: z.boolean().optional(),
334
352
  modelSupportsServiceTier: z.record(z.string().min(1), z.boolean()).optional(),
335
353
  modelSuppressSyntheticMax: z.record(z.string().min(1), z.boolean()).optional(),
336
354
  preserveResponsesReasoningContent: z.boolean().optional(),
337
355
  preserveResponsesInputItemIds: z.boolean().optional(),
338
356
  preserveResponsesMessageMetadata: z.boolean().optional(),
357
+ projectResponsesLiteHostedSearchHistory: z.boolean().optional(),
339
358
  dropResponsesReasoningItems: z.boolean().optional(),
340
359
  modelReasoningEffortsAuthoritative: z.boolean().optional(),
341
360
  decodesNativeCompactionBlobs: z.boolean().optional(),
361
+ supportsNativeCompactionTrigger: z.boolean().optional(),
362
+ supportsNativeCompactEndpoint: z.boolean().optional(),
342
363
  allowEncryptedV2AgentTasks: z.boolean().optional(),
343
364
  allowPrivateNetwork: z.boolean().optional(),
344
365
  // Per-provider egress (#2894): absent inherits the global proxy decision, "direct"/null
@@ -422,7 +443,7 @@ export { providerRelativeSendPathConfigError } from "../provider-relative-send-p
422
443
 
423
444
  /**
424
445
  * Validate `providers.<name>.modelCosts`: a plain object keyed by exact model
425
- * id, each value a 4-tuple of non-negative finite USD-per-1M-token rates.
446
+ * id, each value four USD-per-1M-token rates and an optional prompt-length policy.
426
447
  * Returns null when valid/absent, else a human-readable error.
427
448
  */
428
449
  export function providerModelCostsConfigError(value: unknown, field = "modelCosts"): string | null {
@@ -442,25 +463,28 @@ export function providerModelCostsConfigError(value: unknown, field = "modelCost
442
463
  const rates = entry as Record<string, unknown>;
443
464
  for (const key of COST4_RATE_KEYS) {
444
465
  const rate = rates[key];
445
- if (!isValidCost4Rate(rate)) {
466
+ if (!Object.hasOwn(rates, key) || !isValidCost4Rate(rate)) {
446
467
  return `${field}.${safeModelId}.${key} must be a non-negative finite number at most ${MAX_COST4_RATE} (USD per 1M tokens)`;
447
468
  }
448
469
  }
470
+ if (Object.hasOwn(rates, "promptLengthPricing") && !isValidPromptLengthPricing(rates.promptLengthPricing)) {
471
+ return `${field}.${safeModelId}.promptLengthPricing must be automatic, flat, or a complete custom policy with a positive safe-integer thresholdTokens, gt/gte comparison, and four valid rates`;
472
+ }
449
473
  // Reject unknown fields: a misplaced apiKey/apiKeyPool under a cost row
450
474
  // would otherwise be persisted and echoed verbatim by display paths that
451
475
  // mask only top-level provider secrets.
452
476
  const extraKeys = Object.keys(rates)
453
- .filter((key) => !(COST4_RATE_KEYS as readonly string[]).includes(key));
477
+ .filter((key) => key !== "promptLengthPricing" && !(COST4_RATE_KEYS as readonly string[]).includes(key));
454
478
  if (extraKeys.length > 0) {
455
- return `${field}.${safeModelId} has unexpected fields ${JSON.stringify(extraKeys.map(redactSecretString).join(", "))} — only input, output, cacheRead, and cacheWrite are allowed (USD per 1M tokens)`;
479
+ return `${field}.${safeModelId} has unexpected fields ${JSON.stringify(extraKeys.map(redactSecretString).join(", "))} — only input, output, cacheRead, cacheWrite, and promptLengthPricing are allowed (USD per 1M tokens)`;
456
480
  }
457
481
  }
458
482
  return null;
459
483
  }
460
484
 
461
485
  /**
462
- * Serialize `providers.<name>.modelCosts` for display: copy ONLY the four
463
- * numeric rate fields per model and DROP secret-shaped model ids, so a pasted
486
+ * Serialize `providers.<name>.modelCosts` for display: copy the four validated
487
+ * rates and complete validated policy and DROP secret-shaped model ids, so a pasted
464
488
  * API key in a key position cannot be echoed back by CLI/DTO display paths.
465
489
  * The result uses a null prototype so "__proto__" remains an own row.
466
490
  */
@@ -470,6 +494,7 @@ export function sanitizeModelCostsForDisplay(costs: unknown): Record<string, Pro
470
494
  for (const [modelId, entry] of Object.entries(costs)) {
471
495
  if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
472
496
  const rates = entry as Record<string, unknown>;
497
+ if (Object.hasOwn(rates, "promptLengthPricing") && !isValidPromptLengthPricing(rates.promptLengthPricing)) continue;
473
498
  const input = rates.input;
474
499
  const output = rates.output;
475
500
  const cacheRead = rates.cacheRead;
@@ -483,7 +508,10 @@ export function sanitizeModelCostsForDisplay(costs: unknown): Record<string, Pro
483
508
  // Secret-shaped ids are DROPPED rather than mapped to "[REDACTED]" so
484
509
  // distinct rows cannot collapse into one placeholder key.
485
510
  if (redactSecretString(modelId) !== modelId) continue;
486
- out[modelId] = { input, output, cacheRead, cacheWrite };
511
+ const policy = isValidPromptLengthPricing(rates.promptLengthPricing)
512
+ ? copyPromptLengthPricing(rates.promptLengthPricing) : undefined;
513
+ out[modelId] = { input, output, cacheRead, cacheWrite,
514
+ ...(policy ? { promptLengthPricing: policy } : {}) };
487
515
  }
488
516
  }
489
517
  return Object.keys(out).length > 0 ? out : undefined;
@@ -793,6 +821,8 @@ export const apiKeyEntrySchema = z.object({
793
821
  // rather than promoting it.
794
822
  allowedProviders: z.array(z.string().trim().min(1).max(256)).optional(),
795
823
  allowedModels: z.array(z.string().trim().min(1).max(256)).optional(),
824
+ // Not `.catch`ed for the same reason: a damaged value must not grant metered spend.
825
+ allowMeteredComboTargets: z.boolean().optional(),
796
826
  }).passthrough();
797
827
 
798
828
  /**
@@ -0,0 +1,26 @@
1
+ import * as z from "zod/v4";
2
+ import { pinnedReasoningEffortConfigError } from "../provider-validation";
3
+
4
+ /**
5
+ * Extended settings of the main-account hard lock (`codexMainAccountHardLockFallback`):
6
+ * while the lock blocks, a qualifying Codex-native request reroutes to `model` instead of
7
+ * failing. The dashboard row keeps the configured model when the switch is off, so
8
+ * `enabled: false` is a remembered pause, not a cleared setting; an absent section, an
9
+ * absent model, and a malformed section all mean the same thing — the lock refuses,
10
+ * exactly as it does today.
11
+ */
12
+ export const mainAccountHardLockFallbackSchema = z.object({
13
+ enabled: z.boolean().optional(),
14
+ model: z.string().refine(model => model.length > 0 && model === model.trim() && !/\s/.test(model)),
15
+ reasoningEffort: z.string().refine(value => pinnedReasoningEffortConfigError(value) === null).optional(),
16
+ }).strict();
17
+
18
+ /** Candidate writes must reject sections the read schema would silently discard. */
19
+ export function mainAccountHardLockFallbackError(value: unknown): string | undefined {
20
+ if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
21
+ const raw = (value as Record<string, unknown>).codexMainAccountHardLockFallback;
22
+ if (raw === undefined) return undefined;
23
+ return mainAccountHardLockFallbackSchema.safeParse(raw).success
24
+ ? undefined
25
+ : "schema_invalid: codexMainAccountHardLockFallback requires a nonblank model selector and an optional declared reasoningEffort";
26
+ }
@@ -0,0 +1,26 @@
1
+ import * as z from "zod/v4";
2
+ import type { OcxConfig } from "../../types";
3
+
4
+ /** Opt-in allowances for canonical ChatGPT reasoning replay; absence keeps existing cleanup. */
5
+ export const nativeReasoningRetentionSchema = z.object({
6
+ modelSwitch: z.boolean().optional(),
7
+ accountSwitch: z.boolean().optional(),
8
+ }).strict();
9
+
10
+ export function nativeReasoningRetentionConfigError(value: unknown): string | null {
11
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
12
+ const retention = (value as Record<string, unknown>).nativeReasoningRetention;
13
+ return retention === undefined || nativeReasoningRetentionSchema.safeParse(retention).success
14
+ ? null : "schema_invalid: nativeReasoningRetention: accepts only optional boolean modelSwitch and accountSwitch fields";
15
+ }
16
+
17
+ /** Resolve malformed synthetic inputs the same way as degraded disk config: both off. */
18
+ export function resolveNativeReasoningRetention(
19
+ config: Pick<OcxConfig, "nativeReasoningRetention">,
20
+ ): { modelSwitch: boolean; accountSwitch: boolean } {
21
+ const parsed = nativeReasoningRetentionSchema.safeParse(config.nativeReasoningRetention);
22
+ return {
23
+ modelSwitch: parsed.success && parsed.data.modelSwitch === true,
24
+ accountSwitch: parsed.success && parsed.data.accountSwitch === true,
25
+ };
26
+ }
package/src/config.ts CHANGED
@@ -162,6 +162,7 @@ import { persistConfigUnlocked, readRawConfigJson } from "./config/persist-unloc
162
162
  import { withConfigMutationLockSync, bumpGenerationForCooperatingConfigWrite } from "./config/mutation-lock";
163
163
  import { getDefaultConfig } from "./config/proxy-env";
164
164
  import { configSchema } from "./config/schema/config-schema";
165
+ import { sanitizeOpenCodeOverridesForLoad } from "./config/opencode-wire-upgrade";
165
166
  import {
166
167
  hardenExistingSecret,
167
168
  normalizeApiKeyIds,
@@ -222,6 +223,7 @@ export function loadConfig(): OcxConfig {
222
223
  try {
223
224
  const raw = readFileSync(configPath, "utf-8").replace(/^\uFEFF/, "");
224
225
  const parsed = JSON.parse(raw);
226
+ sanitizeOpenCodeOverridesForLoad(parsed);
225
227
  sanitizeAliasesForLoad(parsed);
226
228
  sanitizeReasoningPinsForLoad(parsed);
227
229
  sanitizeModelDisplayNamesForLoad(parsed);