@bitkyc08/opencodex 2.86.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 (378) hide show
  1. package/gui/dist/assets/App-ZfYbLHkB.js +58 -0
  2. package/gui/dist/assets/App-wT3mXqFz.css +1 -0
  3. package/gui/dist/assets/{Tray-DyR9yBee.js → Tray-DCd-A1az.js} +1 -1
  4. package/gui/dist/assets/index-CfYDMj34.js +94 -0
  5. package/gui/dist/assets/index-DPeB9HpV.css +1 -0
  6. package/gui/dist/assets/quota-summary-ChvmKGOk.js +1 -0
  7. package/gui/dist/index.html +2 -2
  8. package/package.json +1 -1
  9. package/src/adapters/anthropic/beta-allowlist.ts +9 -8
  10. package/src/adapters/anthropic/beta-body-pairs.ts +93 -0
  11. package/src/adapters/anthropic/passthrough.ts +7 -23
  12. package/src/adapters/anthropic-progress.ts +84 -0
  13. package/src/adapters/anthropic.ts +108 -21
  14. package/src/adapters/base.ts +2 -0
  15. package/src/adapters/claude-cli/adapter.ts +111 -23
  16. package/src/adapters/claude-cli/profiles.ts +2 -1
  17. package/src/adapters/claude-cli/stable-replay.ts +108 -0
  18. package/src/adapters/claude-cli/usage-admission.ts +230 -0
  19. package/src/adapters/coding-agent/protocol.ts +1 -1
  20. package/src/adapters/coding-agent/turn.ts +18 -2
  21. package/src/adapters/dsh-account.ts +97 -0
  22. package/src/adapters/google.ts +35 -8
  23. package/src/adapters/openai-chat/messages.ts +4 -3
  24. package/src/adapters/openai-chat/passthrough.ts +8 -2
  25. package/src/adapters/openai-chat/reasoning-replay.ts +52 -0
  26. package/src/adapters/openai-responses/compaction-search-history.ts +14 -7
  27. package/src/adapters/openai-responses/passthrough.ts +57 -125
  28. package/src/adapters/openai-responses/request-strips.ts +25 -3
  29. package/src/adapters/openai-responses/transport.ts +81 -0
  30. package/src/adapters/qoder/adapter.ts +4 -2
  31. package/src/adapters/registry.ts +5 -0
  32. package/src/adapters/zed.ts +26 -1
  33. package/src/advisor/activity.ts +55 -0
  34. package/src/advisor/budget.ts +62 -0
  35. package/src/advisor/consult.ts +4 -1
  36. package/src/advisor/context.ts +16 -4
  37. package/src/advisor/evidence-tool.ts +21 -0
  38. package/src/advisor/evidence.ts +117 -0
  39. package/src/advisor/runtime.ts +79 -31
  40. package/src/advisor/settings.ts +11 -2
  41. package/src/bridge/errors.ts +19 -1
  42. package/src/bridge/internal.ts +3 -1
  43. package/src/bridge/response-json.ts +18 -3
  44. package/src/bridge/sse.ts +58 -8
  45. package/src/bridge/terminal-refusal.ts +59 -0
  46. package/src/claude/desktop-3p-library.ts +32 -7
  47. package/src/claude/desktop-3p.ts +55 -13
  48. package/src/claude/desktop-first-party.ts +1 -1
  49. package/src/claude/desktop-picker-platform.ts +4 -0
  50. package/src/claude/desktop-picker.ts +15 -8
  51. package/src/claude/desktop-system-proxy.ts +50 -4
  52. package/src/claude/inbound-content-options.ts +11 -0
  53. package/src/claude/inbound.ts +33 -0
  54. package/src/claude/intercept/picker-ca-startup.ts +2 -1
  55. package/src/claude/intercept/picker-runtime.ts +6 -5
  56. package/src/claude/intercept/picker-trust-windows.ts +338 -0
  57. package/src/claude/intercept/picker-trust.ts +19 -0
  58. package/src/claude/intercept/port-policy.ts +30 -0
  59. package/src/claude/intercept/runtime.ts +97 -94
  60. package/src/claude/outbound.ts +38 -13
  61. package/src/cli/account-api.ts +1 -0
  62. package/src/cli/account-policy-dto.ts +6 -0
  63. package/src/cli/account-policy.ts +34 -5
  64. package/src/cli/account-preservation.ts +44 -0
  65. package/src/cli/account.ts +8 -2
  66. package/src/cli/advisor.ts +17 -3
  67. package/src/cli/capabilities-accounts.ts +20 -1
  68. package/src/cli/capabilities-agents-routing.ts +5 -2
  69. package/src/cli/capabilities-base.ts +38 -10
  70. package/src/cli/capabilities-observe-system.ts +63 -3
  71. package/src/cli/capabilities-provider-models.ts +11 -0
  72. package/src/cli/codex-cli-update.ts +151 -41
  73. package/src/cli/codex-provider.ts +44 -0
  74. package/src/cli/combo-input.ts +10 -1
  75. package/src/cli/combo-result.ts +1 -1
  76. package/src/cli/combo.ts +2 -1
  77. package/src/cli/cross-home-owner.ts +17 -14
  78. package/src/cli/dispatch.ts +25 -4
  79. package/src/cli/doctor.ts +6 -1
  80. package/src/cli/ensure-desktop-cold-start.ts +60 -7
  81. package/src/cli/help.ts +3 -2
  82. package/src/cli/index.ts +1 -1
  83. package/src/cli/integration-plan-dto.ts +1 -0
  84. package/src/cli/log-history.ts +172 -0
  85. package/src/cli/models-runtime-subcommands.ts +1 -0
  86. package/src/cli/models-runtime.ts +72 -8
  87. package/src/cli/observe-stream.ts +2 -0
  88. package/src/cli/observe.ts +16 -4
  89. package/src/cli/provider.ts +27 -5
  90. package/src/cli/registry.ts +28 -8
  91. package/src/cli/runtime-api.ts +5 -3
  92. package/src/cli/system-command.ts +40 -8
  93. package/src/cli/uninstall-client-state.ts +32 -0
  94. package/src/cli/usage-compare.ts +309 -0
  95. package/src/cli/usage-model-search.ts +4 -4
  96. package/src/cli/usage-report.ts +2 -2
  97. package/src/cli/v2.ts +1 -1
  98. package/src/client/machine-listener.ts +1 -3
  99. package/src/client/runtime.ts +1 -0
  100. package/src/clients/client-path.ts +51 -0
  101. package/src/clients/config-export/contracts.ts +2 -1
  102. package/src/clients/config-export.ts +18 -44
  103. package/src/clients/gentle-shell-path.ts +87 -0
  104. package/src/codex/account-auto-switch.ts +2 -0
  105. package/src/codex/account-identity.ts +29 -0
  106. package/src/codex/account-label.ts +1 -1
  107. package/src/codex/account-lifecycle.ts +21 -5
  108. package/src/codex/account-preservation.ts +28 -0
  109. package/src/codex/account-use-remaining.ts +23 -0
  110. package/src/codex/app-server-processes.ts +97 -7
  111. package/src/codex/app-server-restart-service.ts +55 -4
  112. package/src/codex/auth-api/account-list.ts +4 -0
  113. package/src/codex/auth-api/account-pause-group.ts +6 -50
  114. package/src/codex/auth-api/account-preservation.ts +57 -0
  115. package/src/codex/auth-api/routes.ts +8 -0
  116. package/src/codex/auth-api/use-remaining-route.ts +36 -0
  117. package/src/codex/auth-api.ts +0 -1
  118. package/src/codex/auth-context.ts +2 -2
  119. package/src/codex/catalog/auto-review.ts +20 -3
  120. package/src/codex/catalog/build-entries.ts +9 -1
  121. package/src/codex/catalog/combo-member.ts +14 -5
  122. package/src/codex/catalog/configured-tiers.ts +1 -1
  123. package/src/codex/catalog/gather-capture.ts +2 -0
  124. package/src/codex/catalog/metadata.ts +11 -9
  125. package/src/codex/catalog/model-hints.ts +21 -16
  126. package/src/codex/catalog/model-visibility.ts +3 -1
  127. package/src/codex/catalog/parsing.ts +30 -86
  128. package/src/codex/catalog/provider-models.ts +36 -34
  129. package/src/codex/catalog/routed-gather.ts +12 -13
  130. package/src/codex/cli-install-provenance.ts +105 -17
  131. package/src/codex/cli-update-plan.ts +545 -0
  132. package/src/codex/config-write-lock.ts +23 -2
  133. package/src/codex/desktop-app/picker-freshness.ts +96 -0
  134. package/src/codex/desktop-app-restart.ts +21 -0
  135. package/src/codex/desktop-compatibility/installed-build.ts +24 -6
  136. package/src/codex/desktop-compatibility/routing-preflight.ts +1 -1
  137. package/src/codex/desktop-compatibility/runtime.ts +12 -3
  138. package/src/codex/desktop-compatibility/windows-key-protection.ts +115 -9
  139. package/src/codex/features.ts +85 -45
  140. package/src/codex/inject/history-failure.ts +27 -0
  141. package/src/codex/inject/restore.ts +24 -2
  142. package/src/codex/inject/routing-classify.ts +4 -3
  143. package/src/codex/inject.ts +18 -27
  144. package/src/codex/main-account-hard-lock.ts +30 -1
  145. package/src/codex/native-profile-startup.ts +1 -1
  146. package/src/codex/ocx-compaction-history.ts +12 -10
  147. package/src/codex/paths.ts +86 -1
  148. package/src/codex/provider-routing.ts +174 -0
  149. package/src/codex/refresh.ts +2 -2
  150. package/src/codex/routing/health-store.ts +1 -1
  151. package/src/codex/routing/selection.ts +4 -3
  152. package/src/codex/routing/thread-affinity.ts +1 -1
  153. package/src/codex/signed-in-identity.ts +43 -0
  154. package/src/codex/subagent-model-fallback.ts +1 -1
  155. package/src/codex/sync.ts +6 -1
  156. package/src/codex/user-identity.ts +16 -5
  157. package/src/codex/windows-local-appdata.ts +84 -0
  158. package/src/combos/failover.ts +6 -1
  159. package/src/combos/index.ts +1 -0
  160. package/src/combos/resolve.ts +46 -10
  161. package/src/combos/types.ts +15 -0
  162. package/src/config/diagnostics.ts +33 -6
  163. package/src/config/live-reconcile.ts +38 -2
  164. package/src/config/load-degrade.ts +17 -0
  165. package/src/config/opencode-wire-upgrade.ts +54 -0
  166. package/src/config/opencode-zen-upgrade.ts +52 -0
  167. package/src/config/owner-registry.ts +22 -17
  168. package/src/config/provider-validation.ts +45 -2
  169. package/src/config/schema/config-schema.ts +22 -0
  170. package/src/config/schema/leaf-validators.ts +38 -9
  171. package/src/config/schema/main-account-hard-lock-fallback.ts +26 -0
  172. package/src/config/schema/native-reasoning-retention.ts +26 -0
  173. package/src/config.ts +2 -0
  174. package/src/generated/compatibility-version.json +608 -284
  175. package/src/grok/sync.ts +1 -1
  176. package/src/images/loop.ts +46 -8
  177. package/src/integrations/catalog-refresh.ts +1 -1
  178. package/src/integrations/mutation-plan.ts +1 -0
  179. package/src/integrations/registry.ts +8 -0
  180. package/src/lib/codex-restart-contract.ts +15 -0
  181. package/src/lib/desktop-upstream-tunnel.ts +18 -53
  182. package/src/lib/empty-tool-catalog.ts +62 -0
  183. package/src/lib/errors.ts +19 -3
  184. package/src/lib/gcp-adc.ts +96 -9
  185. package/src/lib/gcp-credential-input.ts +12 -0
  186. package/src/lib/lab-live-route-production.ts +5 -0
  187. package/src/lib/opaque-proxy-tunnel.ts +217 -0
  188. package/src/lib/redact.ts +2 -2
  189. package/src/oauth/account-quota-rank.ts +69 -2
  190. package/src/oauth/anthropic-account-refusal.ts +20 -2
  191. package/src/oauth/anthropic-oauth-definitions.ts +3 -1
  192. package/src/oauth/anthropic-routing.ts +1 -21
  193. package/src/oauth/anthropic.ts +38 -7
  194. package/src/oauth/callback-server.ts +27 -1
  195. package/src/oauth/chatgpt-device.ts +1 -1
  196. package/src/oauth/chatgpt-shared.ts +83 -0
  197. package/src/oauth/chatgpt.ts +8 -72
  198. package/src/oauth/dsh.ts +203 -0
  199. package/src/oauth/generic-account-failover.ts +33 -7
  200. package/src/oauth/generic-session-affinity.ts +125 -0
  201. package/src/oauth/index.ts +184 -109
  202. package/src/oauth/local-token-detect.ts +21 -1
  203. package/src/oauth/login-cli-errors.ts +44 -0
  204. package/src/oauth/login-cli.ts +69 -7
  205. package/src/oauth/login-flow-state.ts +371 -23
  206. package/src/oauth/meta-muse-errors.ts +41 -0
  207. package/src/oauth/meta-muse-keychain.ts +52 -0
  208. package/src/oauth/meta-muse.ts +51 -84
  209. package/src/oauth/model-discovery-auth.ts +3 -0
  210. package/src/oauth/pool-settings-capability.ts +4 -2
  211. package/src/oauth/refresh-flight-retirement.ts +48 -0
  212. package/src/oauth/session-affinity-key.ts +23 -0
  213. package/src/oauth/store-anthropic-instance.ts +9 -2
  214. package/src/oauth/store.ts +12 -5
  215. package/src/protocols/encoders/adapter-events.ts +5 -4
  216. package/src/protocols/encoders/messages.ts +9 -6
  217. package/src/protocols/provider-summary.ts +2 -1
  218. package/src/providers/api-key-cooldowns.ts +49 -0
  219. package/src/providers/api-key-resolve.ts +11 -6
  220. package/src/providers/api-key-response-ownership.ts +57 -0
  221. package/src/providers/api-key-selection.ts +31 -6
  222. package/src/providers/api-keys.ts +214 -3
  223. package/src/providers/claude-cli-usage.ts +96 -0
  224. package/src/providers/dsh-account-destination.ts +31 -0
  225. package/src/providers/dsh-account-models.ts +41 -0
  226. package/src/providers/gcp-credential-cleanup.ts +59 -0
  227. package/src/providers/key-failover.ts +54 -50
  228. package/src/providers/key-store.ts +7 -2
  229. package/src/providers/model-rename-fields.ts +3 -0
  230. package/src/providers/model-rename-migration.ts +2 -2
  231. package/src/providers/openai-tiers-destination.ts +11 -2
  232. package/src/providers/openai-tiers.ts +5 -12
  233. package/src/providers/opencode-go-transport.ts +3 -1
  234. package/src/providers/quota/account-cache.ts +6 -5
  235. package/src/providers/quota/account-row.ts +34 -0
  236. package/src/providers/quota/antigravity.ts +28 -7
  237. package/src/providers/quota/dsh-account.ts +70 -0
  238. package/src/providers/quota/vendor-probes-oauth.ts +1 -93
  239. package/src/providers/quota-types.ts +2 -0
  240. package/src/providers/quota.ts +14 -20
  241. package/src/providers/registry/entries-core.ts +37 -8
  242. package/src/providers/registry/types.ts +1 -1
  243. package/src/providers/request-pacing.ts +77 -19
  244. package/src/providers/routed-config.ts +339 -0
  245. package/src/providers/service-tier.ts +2 -1
  246. package/src/quota/window-mapping.ts +5 -2
  247. package/src/responses/anthropic-progress.ts +34 -0
  248. package/src/responses/assistant-replay.ts +35 -0
  249. package/src/responses/compaction-history-framing.ts +65 -0
  250. package/src/responses/compaction.ts +6 -1
  251. package/src/responses/incomplete-reason.ts +31 -0
  252. package/src/responses/parser.ts +50 -5
  253. package/src/responses/reasoning-envelope.ts +4 -0
  254. package/src/responses/reasoning-replay-cache.ts +24 -2
  255. package/src/responses/reasoning-retention.ts +173 -0
  256. package/src/responses/retained-compaction.ts +46 -0
  257. package/src/responses/schema.ts +23 -0
  258. package/src/router.ts +8 -321
  259. package/src/routing/health.ts +37 -22
  260. package/src/routing/history/indexer.ts +6 -5
  261. package/src/routing/history/ingest.ts +6 -2
  262. package/src/routing/profile.ts +1 -1
  263. package/src/server/admission-model-scope.ts +17 -0
  264. package/src/server/auth-cors.ts +11 -0
  265. package/src/server/chat-completions.ts +7 -1
  266. package/src/server/chat-native-reasoning.ts +123 -0
  267. package/src/server/chat-native-sse.ts +110 -7
  268. package/src/server/chat-native.ts +76 -17
  269. package/src/server/claude-messages.ts +55 -414
  270. package/src/server/effort-policy.ts +1 -1
  271. package/src/server/images.ts +15 -2
  272. package/src/server/index/model-alias-id.ts +36 -0
  273. package/src/server/index/optional-listeners.ts +2 -0
  274. package/src/server/index/serve-options.ts +9 -1
  275. package/src/server/index/startup-warnings.ts +2 -0
  276. package/src/server/index.ts +1 -1
  277. package/src/server/inference/advisor-diagnostics.ts +31 -0
  278. package/src/server/management/advisor-routes.ts +15 -4
  279. package/src/server/management/claude-desktop-picker-routes.ts +1 -1
  280. package/src/server/management/combo-routes.ts +176 -50
  281. package/src/server/management/companion-routes.ts +1 -1
  282. package/src/server/management/config-routes.ts +75 -4
  283. package/src/server/management/cursor-integration-routes.ts +1 -1
  284. package/src/server/management/model-routes.ts +11 -6
  285. package/src/server/management/model-rows.ts +14 -0
  286. package/src/server/management/native-integration-routes.ts +2 -7
  287. package/src/server/management/native-reasoning-retention-routes.ts +41 -0
  288. package/src/server/management/oauth-account-routes.ts +87 -14
  289. package/src/server/management/provider-gcp-credential-routes.ts +29 -0
  290. package/src/server/management/provider-key-pacing-routes.ts +31 -0
  291. package/src/server/management/provider-overwrite-carry.ts +7 -0
  292. package/src/server/management/provider-routes.ts +25 -30
  293. package/src/server/management/route-registry.ts +10 -1
  294. package/src/server/management-api.ts +3 -1
  295. package/src/server/messages-native-tool-guard.ts +185 -0
  296. package/src/server/messages-native.ts +101 -21
  297. package/src/server/messages-shared.ts +431 -0
  298. package/src/server/relay.ts +1 -1
  299. package/src/server/request-log-terminal-status.ts +1 -1
  300. package/src/server/request-log.ts +6 -1
  301. package/src/server/responses/account-change-state.ts +8 -2
  302. package/src/server/responses/adapter-continuation.ts +13 -1
  303. package/src/server/responses/adapter-delivery.ts +19 -6
  304. package/src/server/responses/adapter-dispatch.ts +19 -2
  305. package/src/server/responses/advisor-retention.ts +117 -0
  306. package/src/server/responses/advisor-slot.ts +73 -41
  307. package/src/server/responses/codex-ws-wire.ts +15 -8
  308. package/src/server/responses/compact.ts +303 -125
  309. package/src/server/responses/compaction-recovery.ts +18 -10
  310. package/src/server/responses/compaction-retention.ts +61 -0
  311. package/src/server/responses/context-overflow.ts +11 -6
  312. package/src/server/responses/core-auth.ts +6 -0
  313. package/src/server/responses/core-codex-account.ts +11 -1
  314. package/src/server/responses/core-combo-failure.ts +2 -0
  315. package/src/server/responses/core-combo.ts +120 -36
  316. package/src/server/responses/core-errors.ts +3 -3
  317. package/src/server/responses/core-lifetime.ts +5 -2
  318. package/src/server/responses/core-opaque-recovery.ts +35 -0
  319. package/src/server/responses/core-options.ts +5 -0
  320. package/src/server/responses/core-pipeline.ts +141 -0
  321. package/src/server/responses/core-replay.ts +18 -2
  322. package/src/server/responses/core.ts +2 -115
  323. package/src/server/responses/fetch-helpers.ts +73 -19
  324. package/src/server/responses/main-hard-lock-routing.ts +109 -0
  325. package/src/server/responses/native-response-control.ts +4 -2
  326. package/src/server/responses/passthrough-delivery.ts +3 -1
  327. package/src/server/responses/passthrough-dispatch.ts +15 -13
  328. package/src/server/responses/request-prepare.ts +76 -12
  329. package/src/server/responses/request-sidecar-auth.ts +2 -2
  330. package/src/server/responses/request-transport.ts +104 -27
  331. package/src/server/responses/response-effects.ts +1 -0
  332. package/src/server/responses/run-turn-execution.ts +96 -30
  333. package/src/server/responses/sidecar-execution.ts +20 -2
  334. package/src/server/responses/terminal-guard.ts +2 -16
  335. package/src/service/auth-preflight.ts +71 -0
  336. package/src/service/cli.ts +4 -2
  337. package/src/service/definition.ts +97 -0
  338. package/src/service/guards.ts +1 -61
  339. package/src/service/health-sentinel-linux.ts +112 -0
  340. package/src/service/health-sentinel-main.ts +76 -57
  341. package/src/service/health.ts +5 -89
  342. package/src/service/launchd.ts +27 -7
  343. package/src/service/logging.ts +72 -9
  344. package/src/service/repair.ts +2 -1
  345. package/src/service/state.ts +7 -8
  346. package/src/service/systemd.ts +1 -1
  347. package/src/service/windows-guarded-manager.ts +2 -1
  348. package/src/service/windows-ops.ts +1 -1
  349. package/src/service/windows-scheduler.ts +2 -7
  350. package/src/service/windows-taskxml.ts +2 -2
  351. package/src/service/windows-wscript.ts +14 -0
  352. package/src/service.ts +4 -2
  353. package/src/sidecar/auth.ts +2 -0
  354. package/src/types/config.ts +64 -3
  355. package/src/types/opencode-go.ts +61 -0
  356. package/src/types/opencode-zen.ts +29 -0
  357. package/src/types/provider.ts +32 -6
  358. package/src/types/request.ts +23 -2
  359. package/src/types/wire.ts +29 -37
  360. package/src/types.ts +1 -0
  361. package/src/update/npm-invocation.mjs +12 -2
  362. package/src/usage/cost.ts +48 -12
  363. package/src/usage/expected-prices.ts +3 -0
  364. package/src/usage/ledger-retention.ts +2 -1
  365. package/src/usage/ledger-scanner.ts +6 -5
  366. package/src/usage/log.ts +17 -8
  367. package/src/usage/summary.ts +22 -9
  368. package/src/usage/user-cost-overlays.ts +14 -19
  369. package/src/usage/user-cost-validation.ts +38 -0
  370. package/src/vision/eligibility.ts +13 -0
  371. package/src/web-search/loop.ts +55 -5
  372. package/src/web-search/progress-stream.ts +4 -1
  373. package/src/web-search/run-turn-loop.ts +9 -1
  374. package/gui/dist/assets/App-BjlttVLy.js +0 -58
  375. package/gui/dist/assets/App-CSJvmjNs.css +0 -1
  376. package/gui/dist/assets/index-BB6uK6tU.css +0 -1
  377. package/gui/dist/assets/index-BMssP4k3.js +0 -94
  378. package/gui/dist/assets/quota-summary-D8M1bc_R.js +0 -1
@@ -349,6 +349,12 @@ export interface OcxApiKeyEntry {
349
349
  * that is the only point at which the model about to be billed is known.
350
350
  */
351
351
  allowedModels?: string[];
352
+ /**
353
+ * Lets this key reach combo targets marked `metered`. Absent means no: an issued key stops
354
+ * at the last unmetered target. The environment token never qualifies. A loopback bind
355
+ * reads no key; local operator consent is instead declared on the combo.
356
+ */
357
+ allowMeteredComboTargets?: boolean;
352
358
  }
353
359
 
354
360
  export interface OcxPendingApiKeyRotation {
@@ -569,6 +575,21 @@ export interface OcxConfig {
569
575
  };
570
576
  /** Enable the shipped model alias patterns for providers without an override. */
571
577
  defaultModelAliases?: boolean;
578
+ /**
579
+ * When `true`, the raw OpenAI-compatible `/v1/models` list publishes a safe alias (e.g.
580
+ * `SEK-glm-4.7-flash`) as the row `id` instead of `provider/nativeId`
581
+ * (e.g. `Seek/glm-4.7-flash`). The original `provider/nativeId` moves to a
582
+ * new `native_id` field so clients that need it can still read it.
583
+ *
584
+ * **Default: `false`** — the historical `provider/nativeId` form remains the
585
+ * published `id`, and the alias is in the informational `alias_of` field.
586
+ *
587
+ * Codex (`client_version`) and Anthropic-specific discovery retain their own
588
+ * identities and are unchanged. Ambiguous or shadowed short aliases retain the
589
+ * qualified ID, as do aliases with unparseable synthetic Fast siblings.
590
+ * Existing requests using `provider/nativeId` continue to work unchanged.
591
+ */
592
+ preferModelAliasIds?: boolean;
572
593
  /**
573
594
  * Opt-in Cursor Private Inference compatibility rows. When true, `/v1/models`
574
595
  * adds `<base-id>--<effort>` selectors for reasoning-capable model ids absent
@@ -605,6 +626,13 @@ export interface OcxConfig {
605
626
  codexMainAccountHardLock?: boolean;
606
627
  /** Per-window percentages: short defaults to 90, long to 98; integers 80..100, short <= long. */
607
628
  codexMainAccountHardLockThresholds?: { short?: number; long?: number };
629
+ /**
630
+ * Extended hard-lock settings: while the lock blocks and no Codex account can serve a
631
+ * qualifying request, the request reroutes to `model` (with `reasoningEffort` when set)
632
+ * instead of failing. The lock itself stays on and releases on its own as before; an
633
+ * absent section or model means the refusal behavior is unchanged.
634
+ */
635
+ codexMainAccountHardLockFallback?: { enabled?: boolean; model?: string; reasoningEffort?: string };
608
636
  /**
609
637
  * Who refreshes the native main ChatGPT login in CODEX_HOME (#2999). "codex" asks the Codex
610
638
  * binary through app-server `getAuthStatus` and never writes auth.json; "opencodex" keeps the
@@ -612,6 +640,8 @@ export interface OcxConfig {
612
640
  * is found, otherwise "opencodex". "codex" also falls back when no such binary exists.
613
641
  */
614
642
  nativeMainRefresh?: "codex" | "opencodex";
643
+ /** Use included quota to 100% for these accounts; preserves thresholds and credit-spending policy. */
644
+ codexUseRemainingQuotaAccountIds?: string[];
615
645
  /** Explicit top-level deletion intent used by stale whole-config rebases. */
616
646
  configRebaseProvenance?: OcxConfigRebaseProvenance | Record<string, unknown>;
617
647
  /** OpenAI provider-contract migration marker (v2 = single `openai` provider with account mode). */
@@ -783,6 +813,13 @@ export interface OcxConfig {
783
813
  };
784
814
  /** Opt-in failure-only recovery; never replaces the initial compaction model. */
785
815
  compactionRecovery?: { enabled: boolean; model: string; allowDevinInvalidArgument?: boolean };
816
+ /** Explicit opt-in (enabled === true), default off, for routed v1/v2 readable reasoning retention.
817
+ * Defaults: 20% of the compacting model's context window and 100,000 tokens (the smaller limit).
818
+ * Unknown windows use maxTokens alone; overflow is archived locally with a path notice.
819
+ * Native and opaque compaction output keep their existing protocols. */
820
+ reasoningRetention?: { enabled?: boolean; maxContextPercent?: number; maxTokens?: number };
821
+ /** Canonical ChatGPT reasoning replay allowances; both default off. */
822
+ nativeReasoningRetention?: { modelSwitch?: boolean; accountSwitch?: boolean };
786
823
  /** Explicit opt-in; resumes Observe only using an existing trusted certificate and endpoints. */
787
824
  desktopCompatibility?: { startOnProxyStart: boolean };
788
825
  /**
@@ -842,6 +879,19 @@ export interface OcxConfig {
842
879
  /** Optional override of intercepted source-model prefixes (default: gpt-6-luna, gpt-5.6-luna). */
843
880
  sourceModels?: string[];
844
881
  };
882
+ /**
883
+ * Global auto-review (approval reviewer) selector for every catalog row, written by the
884
+ * Models settings panel. During catalog sync OpenCodex stamps it as
885
+ * `auto_review_model_override` on rows that carry no provider-scoped stamp, so an enabled block
886
+ * wins over Codex's own root `auto_review_model`; disabling it restores that fallback.
887
+ * `autoReviewModel` keeps its precedence on its own provider's rows.
888
+ */
889
+ autoReviewOverride?: {
890
+ /** When true, the configured model replaces the reviewer on every unowned row. */
891
+ enabled?: boolean;
892
+ /** Public catalog selector in `provider/model` form; blank or absent clears the override. */
893
+ model?: string;
894
+ };
845
895
  /**
846
896
  * Optional map of blocked model IDs to their replacement model IDs.
847
897
  * When configured, incoming requests targeting a blocked model (including
@@ -1207,6 +1257,8 @@ export interface OcxConfig {
1207
1257
  autoSwitchThreshold?: number;
1208
1258
  /** Opt-in: return bound quota-strategy tasks to recovered higher-priority accounts. */
1209
1259
  codexAccountPriorityFailback?: boolean;
1260
+ /** Prefer other identities, reserving the current native sign-in as pool fallback. */
1261
+ codexPreserveSignedInAccount?: boolean;
1210
1262
  /** New-session account rotation strategy for the Codex pool. Default quota (today's behaviour). */
1211
1263
  accountPoolStrategy?: OcxAccountPoolRotationStrategy | "reset-first";
1212
1264
  /** Successful new-session binds retained on one round-robin selection. Default 1; range 1..100. */
@@ -1338,10 +1390,18 @@ export interface OcxComboTarget {
1338
1390
  * see `OcxComboConfig.cooldownWaitPolicy` (#5691).
1339
1391
  */
1340
1392
  lastResort?: boolean;
1393
+ /**
1394
+ * Pay-per-use target (for example an API-key row behind subscription targets). Only the
1395
+ * configured keys with `allowMeteredComboTargets: true`, or a loopback-only combo
1396
+ * with `allowMeteredTargets: true`, may reach it.
1397
+ */
1398
+ metered?: boolean;
1341
1399
  }
1342
1400
 
1343
1401
  export interface OcxComboConfig {
1344
1402
  targets: OcxComboTarget[];
1403
+ /** Operator consent for metered targets on a loopback-only proxy. Default false; public listeners still require key consent. */
1404
+ allowMeteredTargets?: boolean;
1345
1405
  /** Ordered failover (default), round-robin, weighted random, least-used, or quota reset-window selection. */
1346
1406
  strategy?: OcxComboStrategy;
1347
1407
  /** Successful requests retained on one RR selection batch. Default 1; range 1..100. */
@@ -1578,8 +1638,7 @@ export interface OcxVisionSidecarConfig {
1578
1638
  }
1579
1639
 
1580
1640
  /**
1581
- * Advisor sidecar configuration. Kept deliberately small for PR1: no adaptive trigger knobs
1582
- * (failedValidations / noProgressCycles / semanticClassifier) — those belong to a later PR.
1641
+ * Advisor sidecar configuration. Automatic triggers require deterministic task evidence.
1583
1642
  */
1584
1643
  export interface OcxAdvisorConfig {
1585
1644
  /** Master switch. Default: false — the advisor stays off the request path entirely. */
@@ -1598,7 +1657,9 @@ export interface OcxAdvisorConfig {
1598
1657
  * consultation per task once the task has produced orientation evidence (an assistant tool call
1599
1658
  * or a tool result after the latest user message).
1600
1659
  */
1601
- policy?: "manual" | "preflight";
1660
+ policy?: "manual" | "preflight" | "adaptive";
1661
+ /** Adaptive task consultation attempts (manual + automatic). Integer 1–3, default 3. */
1662
+ maxConsultationsPerTask?: number;
1602
1663
  /** Advisor fetch timeout (ms). Default 120000. */
1603
1664
  timeoutMs?: number;
1604
1665
  /**
@@ -0,0 +1,61 @@
1
+ /** Exact-model protocols from https://opencode.ai/v2/docs/console/go/#endpoints (2026-10-15).
2
+ * Unknown models retain Chat. Responses entries are overridable registry defaults;
3
+ * the native wires are hard pins because modelAdapters cannot select those adapters.
4
+ */
5
+ export const OPENCODE_GO_BASE_URL = "https://opencode.ai/zen/go/v1";
6
+
7
+ export const OPENCODE_GO_MODEL_WIRES: Readonly<Record<string, "google" | "anthropic" | "openai-responses">> = Object.freeze({
8
+ "gemini-4-argon-contributor": "google",
9
+ "claude-haiku-5-5": "anthropic",
10
+ "minimax-m2.7": "anthropic",
11
+ "minimax-m3": "anthropic",
12
+ "qwen3.7-plus": "anthropic",
13
+ "qwen3.8-max": "anthropic",
14
+ "qwen3.8-flash": "anthropic",
15
+ "gpt-6-luna": "openai-responses",
16
+ "gpt-5.6-luna": "openai-responses",
17
+ "grok-4.6": "openai-responses",
18
+ "grok-4.7": "openai-responses",
19
+ "muse-spark-1.2-contributor": "openai-responses",
20
+ "muse-spark-1.3-contributor": "openai-responses",
21
+ // Retain previously supported Go models absent from the current endpoint table (#4847).
22
+ "minimax-m2.5": "anthropic",
23
+ "union-alpha": "anthropic",
24
+ });
25
+
26
+ /** Compatibility: these five pins predate destination scoping. New native pins require Go. */
27
+ export const OPENCODE_GO_LEGACY_NAME_PINS: ReadonlySet<string> = new Set([
28
+ "claude-haiku-5-5", "minimax-m2.5", "minimax-m2.7", "minimax-m3", "union-alpha",
29
+ ]);
30
+
31
+ export const OPENCODE_GO_RESPONSES_DEFAULTS = Object.freeze(Object.fromEntries(
32
+ Object.entries(OPENCODE_GO_MODEL_WIRES).filter(([, wire]) => wire === "openai-responses"),
33
+ ));
34
+
35
+ export interface OpenCodeGoDestination {
36
+ readonly baseUrl?: unknown;
37
+ readonly authMode?: unknown;
38
+ readonly googleMode?: unknown;
39
+ }
40
+
41
+ /** A provider name alone must never authorize redirecting a credential to OpenCode. */
42
+ export function isOpenCodeGoGeminiDestination(provider: OpenCodeGoDestination | undefined): boolean {
43
+ if (!provider || typeof provider.baseUrl !== "string") return false;
44
+ if (provider.authMode !== undefined && provider.authMode !== "key") return false;
45
+ if (provider.googleMode !== undefined && provider.googleMode !== "ai-studio") return false;
46
+ try {
47
+ const url = new URL(provider.baseUrl.trim());
48
+ return url.origin === "https://opencode.ai"
49
+ && !url.username && !url.password && !url.search && !url.hash
50
+ && ["/zen/go/v1", "/inference/go/v1"].includes(url.pathname.replace(/\/+$/, ""));
51
+ } catch {
52
+ return false;
53
+ }
54
+ }
55
+
56
+ /** Return the fixed Gemini endpoint only for the exact model and an eligible Go destination. */
57
+ export function openCodeGoGeminiEndpoint(provider: OpenCodeGoDestination, modelId: string): string | undefined {
58
+ return Object.hasOwn(OPENCODE_GO_MODEL_WIRES, modelId) && OPENCODE_GO_MODEL_WIRES[modelId] === "google" && isOpenCodeGoGeminiDestination(provider)
59
+ ? `https://opencode.ai/inference/go/v1/models/${encodeURIComponent(modelId)}`
60
+ : undefined;
61
+ }
@@ -0,0 +1,29 @@
1
+ /** Fixed-key OpenCode Zen destinations exposing the native Gemini endpoint. */
2
+ export interface OpenCodeZenDestination {
3
+ readonly baseUrl?: unknown;
4
+ readonly authMode?: unknown;
5
+ readonly googleMode?: unknown;
6
+ }
7
+
8
+ export function openCodeZenBaseUrl(provider: OpenCodeZenDestination | undefined): string | undefined {
9
+ if (!provider || typeof provider.baseUrl !== "string") return undefined;
10
+ if (provider.authMode !== undefined && provider.authMode !== "key") return undefined;
11
+ if (provider.googleMode !== undefined && provider.googleMode !== "ai-studio") return undefined;
12
+ try {
13
+ const url = new URL(provider.baseUrl.trim());
14
+ const pathname = url.pathname.replace(/\/+$/, "");
15
+ if (url.origin !== "https://opencode.ai" || url.username || url.password || url.search || url.hash) return undefined;
16
+ if (pathname !== "/zen/v1" && pathname !== "/inference/v1") return undefined;
17
+ return url.origin + pathname;
18
+ } catch {
19
+ return undefined;
20
+ }
21
+ }
22
+
23
+ /** Keep the selected destination; Zen omits AI Studio's /v1beta segment. */
24
+ export function openCodeZenGeminiEndpoint(provider: OpenCodeZenDestination, modelId: string): string | undefined {
25
+ const baseUrl = openCodeZenBaseUrl(provider);
26
+ return baseUrl && modelId.toLowerCase().startsWith("gemini-")
27
+ ? baseUrl + "/models/" + encodeURIComponent(modelId)
28
+ : undefined;
29
+ }
@@ -14,6 +14,8 @@ export interface ProviderApiKeySelection {
14
14
  entryId?: string;
15
15
  reference?: string;
16
16
  revision?: string;
17
+ /** Request-local allocation; does not replace the saved active key. */
18
+ distributed?: boolean;
17
19
  }
18
20
 
19
21
  export interface OpenRouterProviderRouting {
@@ -164,16 +166,25 @@ export interface ProviderWebSearchBridgeConfig {
164
166
  endpoint?: string;
165
167
  }
166
168
 
167
- /**
168
- * User-configured display price for one model (USD per 1M tokens).
169
- * Mirrors the `Cost4` shape used by the usage cost estimator; structurally
170
- * compatible so config rows can be lifted directly into price overlays.
171
- */
169
+ /** Optional user-owned prompt-length policy; rates are USD per 1M tokens. */
170
+ export type PromptLengthPricing =
171
+ | { mode: "automatic" }
172
+ | { mode: "flat" }
173
+ | {
174
+ mode: "custom";
175
+ thresholdTokens: number;
176
+ comparison: "gt" | "gte";
177
+ rates: { input: number; output: number; cacheRead: number; cacheWrite: number };
178
+ };
179
+
180
+ /** Complete base rates for one model, with automatic pricing when policy is absent. */
172
181
  export interface ProviderCostOverlay {
173
182
  input: number;
174
183
  output: number;
175
184
  cacheRead: number;
176
185
  cacheWrite: number;
186
+ /** Absent means automatic vendor prompt-length pricing. */
187
+ promptLengthPricing?: PromptLengthPricing;
177
188
  }
178
189
 
179
190
  export interface RequestPacingRule {
@@ -190,6 +201,10 @@ export interface ProviderRequestPacingConfig extends RequestPacingRule {
190
201
  enabled: boolean;
191
202
  /** Exact upstream model-id overrides; other models inherit the provider rule. */
192
203
  models?: Record<string, RequestPacingRule>;
204
+ /** Normal request allocation, separate from cooldown recovery ordering. */
205
+ keySelection?: "active" | "round-robin";
206
+ /** Additional uniform limits per pool credential, across all models. */
207
+ keys?: RequestPacingRule;
193
208
  }
194
209
 
195
210
  export interface FastWire {
@@ -432,6 +447,11 @@ export interface OcxProviderConfig {
432
447
  * to extract turn provenance (#6220).
433
448
  */
434
449
  preserveResponsesMessageMetadata?: boolean;
450
+ /**
451
+ * Opt in to lossy hosted-search history notes on ordinary canonical Codex Lite requests.
452
+ * Default off; only literal true enables it, and non-Lite/native compact stay unchanged.
453
+ */
454
+ projectResponsesLiteHostedSearchHistory?: boolean;
435
455
  /**
436
456
  * Treat this provider's `modelReasoningEfforts` as authoritative at the wire, not only in the
437
457
  * catalog. Adapters that ship their own per-model effort table (currently `command-code`)
@@ -453,6 +473,10 @@ export interface OcxProviderConfig {
453
473
  * compaction blobs. Absent or false degrades foreign blobs to an opaque note.
454
474
  */
455
475
  decodesNativeCompactionBlobs?: boolean;
476
+ /** Accept native Responses v2 `input` compaction_trigger items. Responses adapter only. */
477
+ supportsNativeCompactionTrigger?: boolean;
478
+ /** Serve native Responses v1 /responses/compact. Responses adapter only; no auth authority. */
479
+ supportsNativeCompactEndpoint?: boolean;
456
480
  /**
457
481
  * Trust this direct key-auth Responses provider to consume or relay opaque encrypted
458
482
  * V2 agent tasks. OpenCodex does not decrypt, translate, or recover an eligible task.
@@ -712,12 +736,14 @@ export interface OcxProviderConfig {
712
736
  /** Kiro OAuth only: active serving requests per account, 1..100. */
713
737
  maxConcurrentPerAccount?: number;
714
738
  enabled?: boolean;
739
+ /** Opt-in process-local conversation ownership; requires proactive enablement. */
740
+ sessionAffinity?: "conversation" | "none";
715
741
  /**
716
742
  * Generic OAuth pool selection strategy (#695). Persisted through the pool-settings
717
743
  * contract. Consumed by the selector only while `pool.kernel` is on; with the flag off
718
744
  * it is still merely persisted, so omitted and set behave the same.
719
745
  */
720
- strategy?: "quota" | "round-robin" | "fill-first" | "least-loaded";
746
+ strategy?: "quota" | "round-robin" | "fill-first" | "reset-first" | "least-loaded";
721
747
  /**
722
748
  * 0-100 usage percent at which fill-first advances off the active account (#695).
723
749
  * Read only under `pool.kernel` with `strategy: "fill-first"`; 80 when unset, matching
@@ -2,6 +2,7 @@ import type { KiroOAuthMetadata } from "../oauth/types";
2
2
  import type { NativeReasoningOwner } from "../responses/reasoning-replay-cache";
3
3
  import type { OcxTool, OcxToolChoice } from "./tools";
4
4
  import type { TierDecision, TierObservationContext } from "./provider";
5
+ import type { TranslatorBudget } from "../lib/translator-budget";
5
6
 
6
7
  /** Exact provider/credential namespace for process-local reasoning replay. */
7
8
  export interface OcxReasoningReplayIdentity {
@@ -62,6 +63,11 @@ export interface OcxParsedRequest {
62
63
  _nativeReasoningReplay?: ReadonlyMap<string, string>;
63
64
  _nativeReasoningBoundOwner?: NativeReasoningOwner;
64
65
  _nativeReasoningMint?: { owner?: NativeReasoningOwner };
66
+ /**
67
+ * The Claude client's typed Anthropic web tools, as declared. Only the anthropic adapter reads
68
+ * them, and only for api.anthropic.com; every other destination never sees them.
69
+ */
70
+ _anthropicServerTools?: readonly Record<string, unknown>[];
65
71
  /**
66
72
  * Boundary between replayed history and this turn's newly appended input. Usually the
67
73
  * items the proxy restored from local previous_response_id state; also set when the
@@ -92,11 +98,17 @@ export interface OcxParsedRequest {
92
98
  _cursorClientThreadId?: string;
93
99
  /** Conversation/provider/account/model-bound namespace for reasoning replay state. */
94
100
  _reasoningReplayScope?: OcxReasoningReplayScopeRef;
101
+ /** Trusted configuration snapshot; never read from the client's request body. */
102
+ _nativeReasoningRetention?: Readonly<{ modelSwitch: boolean; accountSwitch: boolean }>;
95
103
  /**
96
104
  * Set by bindRouteReasoningReplayScope after a proven serving-identity change, or by
97
105
  * prepareOpaqueBlobRecovery after an authoritative rejection; consumers strip replayed blobs.
98
106
  */
99
107
  _stripReasoningEncryptedContent?: boolean;
108
+ /** Native compaction remains nonportable even when reasoning-only retention is enabled. */
109
+ _stripNativeCompactionEncryptedContent?: boolean;
110
+ /** Retention kept reasoning ciphertext across a model/account change; arms streamed rejection recovery. */
111
+ _nativeReasoningRetainedAcrossRoute?: boolean;
100
112
  /**
101
113
  * Set when replayed reasoning item ids name items in a store this destination cannot read: by
102
114
  * prepareOpaqueBlobRecovery before the one recovery rebuild, and by bindRouteReasoningReplayScope
@@ -150,6 +162,8 @@ export interface OcxParsedRequest {
150
162
  * (see src/responses/compaction.ts).
151
163
  */
152
164
  _compactionRequest?: boolean;
165
+ /** Request-owned encoding of readable routed v2 retention; never used for native ciphertext. */
166
+ _compactionRetention?: { encode(summary: string): string; commit(): void };
153
167
  /** Manual compaction moved to another provider: summarize portably even on a canonical ChatGPT target. */
154
168
  _portableCompaction?: boolean;
155
169
  /**
@@ -173,6 +187,7 @@ export interface OcxParsedRequest {
173
187
  */
174
188
  _advisorGuard?: (options: {
175
189
  parsed: OcxParsedRequest;
190
+ translatorBudget?: TranslatorBudget;
176
191
  firstEvents: AsyncIterable<AdapterEvent>;
177
192
  /** One bounded worker continuation re-dispatch (same machinery as the terminal guard). */
178
193
  continuation: (parsed: OcxParsedRequest) => AsyncIterable<AdapterEvent> | Promise<AsyncIterable<AdapterEvent>>;
@@ -401,7 +416,9 @@ export interface OcxProviderContinuationState {
401
416
 
402
417
  export type AdapterEvent =
403
418
  | { type: "heartbeat"; replayUnsafe?: true; preflightReady?: true }
404
- | { type: "text_delta"; text: string; phase?: OcxMessagePhase }
419
+ | { type: "text_delta"; text: string; phase?: OcxMessagePhase;
420
+ /** Complete documented Anthropic progress block: text remains signed thinking on replay. */
421
+ anthropicThinkingSignature?: string }
405
422
  | { type: "thinking_delta"; thinking: string }
406
423
  // Anthropic extended-thinking round-trip: signature_delta for the current thinking block, and
407
424
  // opaque redacted_thinking blocks. Both must be replayed verbatim or tool-use turns 400.
@@ -424,7 +441,11 @@ export type AdapterEvent =
424
441
  // output_item.added(in_progress) and end → the matching output_item.done(completed|failed) under
425
442
  // the SAME output index, so the activity animates instead of flashing completed instantly.
426
443
  | { type: "web_search_call_begin"; id: string }
427
- | { type: "web_search_call_end"; id: string; queries: string[]; status?: "completed" | "failed"; sources?: OcxUrlCitation[] }
444
+ | {
445
+ type: "web_search_call_end"; id: string; queries: string[]; status?: "completed" | "failed"; sources?: OcxUrlCitation[];
446
+ /** Anthropic's server-side web_fetch (adapters/anthropic.ts): the opened page and its `web_fetch_tool_result` content, verbatim. */
447
+ fetch?: { url: string; result: unknown };
448
+ }
428
449
  | {
429
450
  type: "done";
430
451
  usage?: OcxUsage;
package/src/types/wire.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import { isOpenCodeGoGeminiDestination, OPENCODE_GO_BASE_URL, OPENCODE_GO_MODEL_WIRES, OPENCODE_GO_LEGACY_NAME_PINS, type OpenCodeGoDestination } from "./opencode-go";
2
+ import { openCodeZenBaseUrl, type OpenCodeZenDestination } from "./opencode-zen";
3
+
1
4
  /**
2
5
  * Accepted values for the per-provider upstream HTTP-version pin (#1668). Shared by the
3
6
  * zod load schema, the management write boundary (POST/PATCH), and the fetch runtime, so
@@ -40,35 +43,16 @@ export const MODEL_ADAPTER_OVERRIDE_ALLOWED: ReadonlySet<string> = new Set([
40
43
  "openai-responses",
41
44
  ]);
42
45
 
43
- /**
44
- * Providers whose listed model ids must be driven over the Anthropic wire even when
45
- * the provider's configured adapter says otherwise — the upstream only speaks
46
- * Anthropic for these models.
47
- */
48
- const ANTHROPIC_WIRE_MODELS: Record<string, ReadonlySet<string>> = {
49
- "opencode-go": new Set([
50
- "claude-haiku-5-5",
51
- "minimax-m2.5",
52
- "minimax-m2.7",
53
- "minimax-m3",
54
- // OpenCode's catalog identifies Union Alpha as @ai-sdk/anthropic while the
55
- // provider defaults to OpenAI-compatible; direct Chat returns 500 and direct
56
- // Messages reaches the session check (#4847).
57
- "union-alpha",
58
- ]),
59
- };
60
-
61
- function anthropicWireModelsForProvider(providerName: string): ReadonlySet<string> | undefined {
62
- return Object.hasOwn(ANTHROPIC_WIRE_MODELS, providerName)
63
- ? ANTHROPIC_WIRE_MODELS[providerName]
64
- : undefined;
65
- }
66
-
67
- /** Detached provider-local hard-pin table for pure wire-policy resolution. */
68
- export function captureWireAdapterHardPins(providerName: string): Readonly<Record<string, string>> {
69
- const models = anthropicWireModelsForProvider(providerName);
70
- if (!models) return Object.freeze({});
71
- return Object.freeze(Object.fromEntries([...models].map(modelId => [modelId, "anthropic"])));
46
+ /** Native Go wire pins share the exact-model table with registry Responses defaults. */
47
+ export function captureWireAdapterHardPins(providerName: string, provider?: WirePinProvider): Readonly<Record<string, string>> {
48
+ if (providerName !== "opencode-go") return Object.freeze({});
49
+ // The existing Go preset pins saved URLs to this endpoint before dispatch. Pure policy
50
+ // captures must use that same destination even when handed an unnormalized config row.
51
+ const destination = provider && { ...provider, baseUrl: OPENCODE_GO_BASE_URL };
52
+ return Object.freeze(Object.fromEntries(Object.entries(OPENCODE_GO_MODEL_WIRES).filter(([modelId, wire]) =>
53
+ (wire === "anthropic" && OPENCODE_GO_LEGACY_NAME_PINS.has(modelId))
54
+ || (wire !== "openai-responses" && isOpenCodeGoGeminiDestination(destination)),
55
+ )));
72
56
  }
73
57
 
74
58
  interface WirePinPrefixRule {
@@ -98,9 +82,7 @@ const WIRE_ADAPTER_PIN_PREFIXES: Readonly<Record<string, WirePinPrefixRule>> = O
98
82
  });
99
83
 
100
84
  /** Just enough of a provider config to tell whether it still points at the pinned endpoint. */
101
- export interface WirePinProvider {
102
- readonly baseUrl?: unknown;
103
- }
85
+ export interface WirePinProvider extends OpenCodeGoDestination, OpenCodeZenDestination {}
104
86
 
105
87
  function normalizedEndpoint(value: unknown): string | undefined {
106
88
  if (typeof value !== "string") return undefined;
@@ -112,7 +94,19 @@ function normalizedEndpoint(value: unknown): string | undefined {
112
94
  }
113
95
  }
114
96
 
97
+ /**
98
+ * Providers whose adapter is their credential boundary: the adapter alone pins the destination and
99
+ * the auth header for an account token. No model may switch wires, whatever `baseUrl` or the row's
100
+ * own `adapter` says, because a generic wire would send that token as a Bearer key to the configured
101
+ * URL. The empty prefix covers every model id.
102
+ */
103
+ const CREDENTIAL_PINNED_ADAPTERS: Readonly<Record<string, Readonly<Record<string, string>>>> = Object.freeze({
104
+ "dsh-account": Object.freeze({ "": "dsh-account" }),
105
+ });
106
+
115
107
  function prefixPinsFor(providerName: string, provider: WirePinProvider | undefined): Readonly<Record<string, string>> | undefined {
108
+ if (Object.hasOwn(CREDENTIAL_PINNED_ADAPTERS, providerName)) return CREDENTIAL_PINNED_ADAPTERS[providerName];
109
+ if (providerName === "opencode-zen" && openCodeZenBaseUrl(provider)) return { "gemini-": "google" };
116
110
  if (!provider || !Object.hasOwn(WIRE_ADAPTER_PIN_PREFIXES, providerName)) return undefined;
117
111
  const rule = WIRE_ADAPTER_PIN_PREFIXES[providerName]!;
118
112
  return normalizedEndpoint(provider.baseUrl) === rule.endpoint ? rule.prefixes : undefined;
@@ -148,13 +142,11 @@ function prefixedWireAdapter(providerName: string, modelId: string, provider: Wi
148
142
  * adapter" would pass on the first pass and then let the override win on the second.
149
143
  */
150
144
  export function isWirePinnedModel(providerName: string, modelId: string, provider?: WirePinProvider): boolean {
151
- return (anthropicWireModelsForProvider(providerName)?.has(modelId) ?? false)
152
- || prefixedWireAdapter(providerName, modelId, provider) !== undefined;
145
+ return pinnedWireAdapter(providerName, modelId, provider) !== undefined;
153
146
  }
154
147
 
155
148
  /** The wire a pinned model must use, or undefined when the model is not pinned. */
156
149
  export function pinnedWireAdapter(providerName: string, modelId: string, provider?: WirePinProvider): string | undefined {
157
- return anthropicWireModelsForProvider(providerName)?.has(modelId)
158
- ? "anthropic"
159
- : prefixedWireAdapter(providerName, modelId, provider);
150
+ const pins = captureWireAdapterHardPins(providerName, provider);
151
+ return Object.hasOwn(pins, modelId) ? pins[modelId] : prefixedWireAdapter(providerName, modelId, provider);
160
152
  }
package/src/types.ts CHANGED
@@ -122,6 +122,7 @@ export type {
122
122
  ProviderWebSearchBridgeBackend,
123
123
  ProviderWebSearchBridgeConfig,
124
124
  ProviderCostOverlay,
125
+ PromptLengthPricing,
125
126
  RequestPacingRule,
126
127
  ProviderRequestPacingConfig,
127
128
  FastWire,
@@ -95,12 +95,22 @@ export function resolveNpmCommand(
95
95
  return null;
96
96
  }
97
97
 
98
+ function shellEnvValue(env, name) {
99
+ // Copying process.env loses Windows' case-insensitive property access. Keep
100
+ // the existing exact-key precedence; do not choose between conflicting aliases.
101
+ if (env[name] !== undefined) return env[name];
102
+ const values = new Set(Object.entries(env)
103
+ .filter(([key, value]) => key.toLowerCase() === name.toLowerCase() && value !== undefined)
104
+ .map(([, value]) => value));
105
+ return values.size === 1 ? values.values().next().value : undefined;
106
+ }
107
+
98
108
  function systemCommandProcessor(env) {
99
- const systemRoot = env.SystemRoot ?? env.windir;
109
+ const systemRoot = shellEnvValue(env, "SystemRoot") ?? shellEnvValue(env, "windir");
100
110
  if (systemRoot && win32.isAbsolute(systemRoot)) {
101
111
  return win32.join(systemRoot, "System32", "cmd.exe");
102
112
  }
103
- const comSpec = env.ComSpec;
113
+ const comSpec = shellEnvValue(env, "ComSpec");
104
114
  return comSpec && win32.isAbsolute(comSpec) ? win32.resolve(comSpec) : null;
105
115
  }
106
116