@bitkyc08/opencodex 2.88.0 → 2.90.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 (291) hide show
  1. package/README.md +11 -1
  2. package/bin/ocx.mjs +15 -4
  3. package/gui/dist/assets/App-DgxkE6Md.js +58 -0
  4. package/gui/dist/assets/App-dnkJ85te.css +1 -0
  5. package/gui/dist/assets/{Tray-B5bC7AWL.js → Tray-DbTNc_88.js} +1 -1
  6. package/gui/dist/assets/{index-B5bsvxor.js → index-TmaHa54u.js} +15 -15
  7. package/gui/dist/assets/quota-summary-B16x5DZZ.js +1 -0
  8. package/gui/dist/index.html +1 -1
  9. package/package.json +2 -2
  10. package/src/adapters/anthropic/cache-retention.ts +117 -0
  11. package/src/adapters/anthropic/passthrough.ts +7 -4
  12. package/src/adapters/anthropic.ts +10 -3
  13. package/src/adapters/base.ts +4 -0
  14. package/src/adapters/claude-cli/adapter.ts +13 -7
  15. package/src/adapters/claude-cli/usage-admission.ts +14 -2
  16. package/src/adapters/coding-agent/protocol.ts +6 -0
  17. package/src/adapters/coding-agent/turn.ts +14 -4
  18. package/src/adapters/cursor/protobuf-request.ts +3 -0
  19. package/src/adapters/google-http.ts +3 -2
  20. package/src/adapters/google-progress-history.ts +19 -1
  21. package/src/adapters/google-vertex-endpoint.ts +67 -0
  22. package/src/adapters/google.ts +62 -37
  23. package/src/adapters/image.ts +5 -3
  24. package/src/adapters/input-media-guard.ts +5 -2
  25. package/src/adapters/kiro-refusal.ts +41 -1
  26. package/src/adapters/ollama-native.ts +1 -0
  27. package/src/adapters/openai-chat/messages.ts +34 -4
  28. package/src/adapters/openai-chat/passthrough.ts +37 -4
  29. package/src/adapters/openai-chat/reasoning-replay.ts +98 -13
  30. package/src/adapters/openai-chat/serialized-tool-call-content.ts +95 -134
  31. package/src/adapters/openai-chat/serialized-tool-call-markup.ts +108 -0
  32. package/src/adapters/openai-chat/standalone-bare-tool-calls.ts +136 -0
  33. package/src/adapters/openai-chat.ts +7 -6
  34. package/src/adapters/openai-responses/compaction-search-history.ts +27 -0
  35. package/src/adapters/openai-responses/opengateway-input.ts +139 -0
  36. package/src/adapters/openai-responses/passthrough.ts +22 -13
  37. package/src/adapters/openai-responses/reasoning.ts +68 -1
  38. package/src/adapters/openai-responses/transport.ts +13 -1
  39. package/src/adapters/registry.ts +1 -1
  40. package/src/adapters/upstream-http-error.ts +3 -2
  41. package/src/adapters/zed.ts +7 -4
  42. package/src/bridge/internal.ts +11 -1
  43. package/src/bridge/response-json.ts +2 -2
  44. package/src/bridge/sse.ts +10 -4
  45. package/src/claude/desktop-3p-library.ts +43 -3
  46. package/src/claude/desktop-3p.ts +20 -10
  47. package/src/claude/desktop-picker-profile.ts +18 -9
  48. package/src/claude/desktop-remote-store-io.ts +2 -2
  49. package/src/claude/inbound.ts +12 -26
  50. package/src/claude/outbound.ts +5 -0
  51. package/src/cli/account-api.ts +13 -1
  52. package/src/cli/account-extended.ts +17 -5
  53. package/src/cli/account-key-quota.ts +4 -1
  54. package/src/cli/account.ts +1 -1
  55. package/src/cli/capabilities-agents-routing.ts +45 -8
  56. package/src/cli/capabilities-base.ts +5 -5
  57. package/src/cli/capabilities-provider-models.ts +5 -4
  58. package/src/cli/combo-result.ts +8 -2
  59. package/src/cli/combo.ts +17 -0
  60. package/src/cli/ensure-desktop-cold-start.ts +2 -2
  61. package/src/cli/help.ts +1 -1
  62. package/src/cli/message-command.ts +4 -1
  63. package/src/cli/message-remote-args.ts +69 -0
  64. package/src/cli/message-remote-command.ts +77 -0
  65. package/src/cli/provider-runtime.ts +69 -1
  66. package/src/cli/registry.ts +3 -3
  67. package/src/codex/account-lifecycle.ts +19 -6
  68. package/src/codex/account-pause.ts +6 -1
  69. package/src/codex/account-runtime-state.ts +5 -0
  70. package/src/codex/account-store.ts +55 -9
  71. package/src/codex/account-usability.ts +4 -1
  72. package/src/codex/auth-api/account-list.ts +13 -5
  73. package/src/codex/auth-api/account-pause-group.ts +2 -22
  74. package/src/codex/auth-api/login-collision.ts +59 -0
  75. package/src/codex/auth-api/login-flow.ts +12 -7
  76. package/src/codex/auth-api/main-account-probe.ts +3 -2
  77. package/src/codex/auth-api/pool-mode-gate.ts +81 -13
  78. package/src/codex/auth-collision.ts +31 -4
  79. package/src/codex/auth-context.ts +57 -10
  80. package/src/codex/catalog/aggregation.ts +15 -0
  81. package/src/codex/catalog/auto-review.ts +2 -1
  82. package/src/codex/catalog/build-entries.ts +17 -7
  83. package/src/codex/catalog/derive-entry.ts +3 -1
  84. package/src/codex/catalog/metadata.ts +2 -0
  85. package/src/codex/catalog/model-visibility.ts +0 -2
  86. package/src/codex/catalog/ownership.ts +71 -0
  87. package/src/codex/catalog/parsing.ts +12 -3
  88. package/src/codex/catalog/retained-sync.ts +2 -1
  89. package/src/codex/catalog/routed-removal.ts +4 -4
  90. package/src/codex/cli-update-plan.ts +18 -3
  91. package/src/codex/collision-identity.ts +78 -0
  92. package/src/codex/convergence.ts +2 -1
  93. package/src/codex/low-quota-desktop-notifier.ts +125 -0
  94. package/src/codex/low-quota-protection.ts +57 -31
  95. package/src/codex/main-account-cache.ts +77 -3
  96. package/src/codex/main-account-hard-lock.ts +14 -0
  97. package/src/codex/main-account.ts +6 -2
  98. package/src/codex/native-residue.ts +2 -3
  99. package/src/codex/quota.ts +26 -2
  100. package/src/codex/routing/cooldown-math.ts +5 -0
  101. package/src/codex/routing/failure-window.ts +61 -9
  102. package/src/codex/routing.ts +4 -3
  103. package/src/codex/shim-diagnostics.ts +2 -1
  104. package/src/codex/shim-fingerprint.ts +11 -2
  105. package/src/codex/shim-templates.ts +16 -5
  106. package/src/codex/shim-windows-refresh.ts +224 -0
  107. package/src/codex/shim.ts +45 -21
  108. package/src/combos/failover.ts +10 -2
  109. package/src/combos/jev-model-backend.ts +30 -7
  110. package/src/combos/jev-model-request.ts +20 -0
  111. package/src/combos/jev-quota-activation.ts +153 -0
  112. package/src/combos/jev-quota-config.ts +62 -0
  113. package/src/combos/jev-quota-route.ts +26 -0
  114. package/src/combos/jev-quota.ts +88 -0
  115. package/src/combos/jev.ts +25 -12
  116. package/src/combos/types.ts +27 -0
  117. package/src/compatibility/index.ts +3 -0
  118. package/src/compatibility/openai-responses.ts +8 -1
  119. package/src/compatibility/opengateway-responses.ts +61 -0
  120. package/src/config/account-auto-pause-revisions.ts +136 -0
  121. package/src/config/diagnostics.ts +13 -0
  122. package/src/config/live-reconcile.ts +9 -0
  123. package/src/config/persist-unlocked.ts +10 -1
  124. package/src/config/provider-validation.ts +7 -2
  125. package/src/config/removed-opencode-free.ts +135 -0
  126. package/src/config/schema/account-auto-pause.ts +14 -0
  127. package/src/config/schema/config-schema.ts +15 -0
  128. package/src/config/schema/leaf-validators.ts +7 -0
  129. package/src/config.ts +10 -3
  130. package/src/generated/compatibility-version.json +476 -216
  131. package/src/generated/model-metadata.ts +1 -1
  132. package/src/images/loop.ts +34 -11
  133. package/src/lib/account-auto-pause-response.ts +16 -0
  134. package/src/lib/bun-runtime.ts +18 -1
  135. package/src/lib/bun-transpiler-cache-scope.d.mts +8 -0
  136. package/src/lib/bun-transpiler-cache-scope.mjs +82 -0
  137. package/src/lib/decision-quota-sink.ts +76 -0
  138. package/src/lib/provider-admission-wait.ts +14 -0
  139. package/src/lib/service-secrets.ts +37 -2
  140. package/src/lib/state-store-registrations.ts +25 -0
  141. package/src/lib/translator-budget.ts +1 -1
  142. package/src/lib/upstream-retry.ts +15 -0
  143. package/src/link/ssh-argv.ts +3 -0
  144. package/src/messaging/envelope.ts +6 -3
  145. package/src/messaging/remote-auth.ts +83 -0
  146. package/src/messaging/remote-bridge.ts +270 -0
  147. package/src/messaging/remote-contract.ts +108 -0
  148. package/src/messaging/remote-enrollment-recovery.ts +59 -0
  149. package/src/messaging/remote-enrollment.ts +244 -0
  150. package/src/messaging/remote-envelope.ts +40 -0
  151. package/src/messaging/remote-files.ts +117 -0
  152. package/src/messaging/remote-owner.ts +169 -0
  153. package/src/messaging/remote-ports.ts +56 -0
  154. package/src/messaging/remote-process.ts +131 -0
  155. package/src/messaging/remote-replies.ts +98 -0
  156. package/src/messaging/remote-rpc-admission.ts +32 -0
  157. package/src/messaging/remote-send.ts +72 -0
  158. package/src/messaging/remote-store.ts +111 -0
  159. package/src/messaging/remote-tunnels.ts +65 -0
  160. package/src/messaging/rpc.ts +13 -1
  161. package/src/oauth/account-auto-pause-policy.ts +66 -0
  162. package/src/oauth/account-auto-pause.ts +171 -0
  163. package/src/oauth/account-import/google-antigravity-adapter.ts +38 -2
  164. package/src/oauth/account-import/parser.ts +15 -2
  165. package/src/oauth/account-import/types.ts +7 -0
  166. package/src/oauth/account-quota-rank.ts +2 -1
  167. package/src/oauth/anthropic-account-refusal.ts +6 -0
  168. package/src/oauth/anthropic-model-family.ts +8 -0
  169. package/src/oauth/anthropic-model-quota.ts +2 -6
  170. package/src/oauth/api-key-pool-preserve.ts +37 -0
  171. package/src/oauth/chatgpt-shared.ts +10 -1
  172. package/src/oauth/dsh.ts +45 -2
  173. package/src/oauth/index.ts +5 -35
  174. package/src/oauth/kiro.ts +44 -1
  175. package/src/oauth/login-flow-state.ts +11 -2
  176. package/src/oauth/store.ts +35 -8
  177. package/src/oauth/types.ts +2 -0
  178. package/src/plugins/upstream-hooks.ts +14 -1
  179. package/src/providers/api-key-pause.ts +32 -0
  180. package/src/providers/api-key-resolve.ts +10 -4
  181. package/src/providers/api-key-selection.ts +6 -1
  182. package/src/providers/api-keys.ts +8 -4
  183. package/src/providers/claude-cli-usage.ts +25 -5
  184. package/src/providers/initial-model-selection.ts +2 -2
  185. package/src/providers/key-failover.ts +21 -13
  186. package/src/providers/key-store.ts +8 -3
  187. package/src/providers/mistral-transport.ts +207 -0
  188. package/src/providers/model-rename-fields.ts +1 -0
  189. package/src/providers/openai-sidecar.ts +5 -0
  190. package/src/providers/opencode-zen-rate-limit.ts +6 -72
  191. package/src/providers/quota/account-cache.ts +15 -1
  192. package/src/providers/quota/anthropic-account-quota.ts +20 -7
  193. package/src/providers/quota/anthropic-cooldown-recovery.ts +22 -4
  194. package/src/providers/quota/anthropic-decision-windows.ts +47 -0
  195. package/src/providers/quota/antigravity.ts +45 -8
  196. package/src/providers/quota/failure-codes.ts +18 -0
  197. package/src/providers/quota/report-cache.ts +14 -0
  198. package/src/providers/quota/vendor-probes-oauth.ts +15 -6
  199. package/src/providers/quota-decision-publication.ts +77 -0
  200. package/src/providers/quota-decision-snapshot.ts +145 -0
  201. package/src/providers/quota-routing-cache.ts +4 -1
  202. package/src/providers/quota-types.ts +6 -1
  203. package/src/providers/quota.ts +8 -3
  204. package/src/providers/registry/entries-extended.ts +14 -53
  205. package/src/providers/registry/model-seeds.ts +1 -1
  206. package/src/providers/registry.ts +1 -2
  207. package/src/providers/routed-config.ts +1 -1
  208. package/src/providers/stale-vision-classification-migration.ts +1 -1
  209. package/src/providers/xai-transport.ts +2 -1
  210. package/src/responses/audio.ts +46 -0
  211. package/src/responses/input-media.ts +37 -15
  212. package/src/responses/parser-content.ts +22 -27
  213. package/src/responses/parser.ts +18 -10
  214. package/src/responses/reasoning-retention.ts +218 -11
  215. package/src/responses/schema.ts +3 -4
  216. package/src/responses/web-search-replay.ts +147 -0
  217. package/src/routing/compatibility/behavior.ts +4 -1
  218. package/src/server/auth-cors.ts +7 -0
  219. package/src/server/background-lifecycle.ts +2 -1
  220. package/src/server/chat-native.ts +36 -20
  221. package/src/server/claude-messages.ts +2 -1
  222. package/src/server/index/optional-listeners.ts +6 -0
  223. package/src/server/index/serve-options.ts +8 -2
  224. package/src/server/index/websocket-handler.ts +10 -0
  225. package/src/server/lifecycle.ts +17 -1
  226. package/src/server/management/combo-routes.ts +17 -2
  227. package/src/server/management/oauth-account-routes.ts +12 -2
  228. package/src/server/management/provider-completion-test.ts +289 -0
  229. package/src/server/management/provider-routes.ts +9 -1
  230. package/src/server/management/route-registry.ts +2 -0
  231. package/src/server/messages-native.ts +29 -4
  232. package/src/server/messages-shared.ts +4 -1
  233. package/src/server/request-log.ts +23 -9
  234. package/src/server/responses/account-auto-pause-recovery.ts +26 -0
  235. package/src/server/responses/adapter-continuation.ts +2 -2
  236. package/src/server/responses/adapter-dispatch.ts +79 -30
  237. package/src/server/responses/codex-ws-exchange.ts +3 -0
  238. package/src/server/responses/codex-ws-metadata.ts +44 -0
  239. package/src/server/responses/codex-ws-session.ts +21 -1
  240. package/src/server/responses/combo-session-recall.ts +25 -0
  241. package/src/server/responses/combo-stream-preflight.ts +10 -3
  242. package/src/server/responses/combo-tool-loop-pin.ts +70 -0
  243. package/src/server/responses/compact.ts +10 -5
  244. package/src/server/responses/context-overflow.ts +141 -2
  245. package/src/server/responses/core-auth.ts +20 -0
  246. package/src/server/responses/core-codex-account.ts +28 -15
  247. package/src/server/responses/core-combo.ts +34 -5
  248. package/src/server/responses/core-opaque-recovery.ts +20 -11
  249. package/src/server/responses/core.ts +12 -9
  250. package/src/server/responses/deepseek-image-files.ts +121 -0
  251. package/src/server/responses/empty-completion-guard.ts +10 -0
  252. package/src/server/responses/fetch-helpers.ts +65 -14
  253. package/src/server/responses/input-admission.ts +6 -2
  254. package/src/server/responses/jev-model-invoke.ts +13 -14
  255. package/src/server/responses/main-hard-lock-routing.ts +33 -8
  256. package/src/server/responses/native-steering-log.ts +2 -2
  257. package/src/server/responses/opengateway-completion-guard.ts +232 -0
  258. package/src/server/responses/passthrough-completion.ts +41 -0
  259. package/src/server/responses/passthrough-delivery.ts +5 -2
  260. package/src/server/responses/passthrough-dispatch.ts +42 -45
  261. package/src/server/responses/passthrough-key-rotation.ts +40 -0
  262. package/src/server/responses/passthrough-observations.ts +38 -0
  263. package/src/server/responses/reasoning-archive-error.ts +21 -0
  264. package/src/server/responses/request-compression.ts +98 -0
  265. package/src/server/responses/request-prepare.ts +11 -1
  266. package/src/server/responses/request-transport.ts +92 -5
  267. package/src/server/responses/run-turn-execution.ts +2 -0
  268. package/src/server/responses/sidecar-execution.ts +16 -3
  269. package/src/server/responses/terminal-guard.ts +2 -0
  270. package/src/server/startup-action-control.ts +2 -2
  271. package/src/server/startup-health-cache.ts +2 -2
  272. package/src/server/windows-tray-control.ts +2 -2
  273. package/src/service/definition.ts +9 -1
  274. package/src/service/orchestration.ts +17 -0
  275. package/src/types/account-auto-pause.ts +15 -0
  276. package/src/types/config.ts +23 -1
  277. package/src/types/provider.ts +11 -5
  278. package/src/types/request.ts +36 -3
  279. package/src/types.ts +2 -0
  280. package/src/usage/cost.ts +17 -1
  281. package/src/usage/expected-prices.ts +3 -1
  282. package/src/usage/jev-stats.ts +4 -0
  283. package/src/usage/log.ts +2 -0
  284. package/src/usage/summary.ts +7 -0
  285. package/src/web-search/loop.ts +39 -13
  286. package/src/web-search/progress-stream.ts +4 -1
  287. package/src/web-search/run-turn-loop.ts +9 -3
  288. package/src/web-search/sidecar-search-replay.ts +96 -0
  289. package/gui/dist/assets/App-CHC89EXQ.js +0 -58
  290. package/gui/dist/assets/App-wT3mXqFz.css +0 -1
  291. package/gui/dist/assets/quota-summary-D8y2wTsB.js +0 -1
@@ -0,0 +1 @@
1
+ import{n as e,w as t,y as n}from"./index-TmaHa54u.js";var r=e(),i=e=>({viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:2,strokeLinecap:`round`,strokeLinejoin:`round`,...e}),a=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`rect`,{x:`3`,y:`3`,width:`7`,height:`7`,rx:`1.5`}),(0,r.jsx)(`rect`,{x:`14`,y:`3`,width:`7`,height:`7`,rx:`1.5`}),(0,r.jsx)(`rect`,{x:`3`,y:`14`,width:`7`,height:`7`,rx:`1.5`}),(0,r.jsx)(`rect`,{x:`14`,y:`14`,width:`7`,height:`7`,rx:`1.5`})]}),o=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`rect`,{x:`3`,y:`4`,width:`18`,height:`7`,rx:`2`}),(0,r.jsx)(`rect`,{x:`3`,y:`13`,width:`18`,height:`7`,rx:`2`}),(0,r.jsx)(`path`,{d:`M7 7.5h.01M7 16.5h.01`})]}),s=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`path`,{d:`M12 2 4 6v6l8 4 8-4V6l-8-4Z`}),(0,r.jsx)(`path`,{d:`m4 6 8 4 8-4M12 10v8`})]}),c=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`rect`,{x:`4`,y:`8`,width:`16`,height:`11`,rx:`3`}),(0,r.jsx)(`path`,{d:`M12 8V4M8 2h8`}),(0,r.jsx)(`circle`,{cx:`9`,cy:`13`,r:`1`}),(0,r.jsx)(`circle`,{cx:`15`,cy:`13`,r:`1`})]}),l=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01`})}),u=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M4 6h16M4 12h16M4 18h16`})}),d=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`rect`,{x:`3`,y:`4`,width:`18`,height:`16`,rx:`2`}),(0,r.jsx)(`path`,{d:`M9 4v16`})]}),f=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`path`,{d:`m4 17 6-5-6-5`}),(0,r.jsx)(`path`,{d:`M12 19h8`})]}),p=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M22 12h-4l-3 9L9 3l-3 9H2`})}),m=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`path`,{d:`M22 12H2`}),(0,r.jsx)(`path`,{d:`M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11Z`}),(0,r.jsx)(`path`,{d:`M6 16h.01M10 16h.01`})]}),h=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`m20 6-11 11-5-5`})}),g=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M18 6 6 18M6 6l12 12`})}),ee=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M12 5v14M5 12h14`})}),_=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M5 12h14`})}),te=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M21 12a9 9 0 0 1-9 9 9.8 9.8 0 0 1-6.7-2.7L3 16M3 21v-5h5M3 12a9 9 0 0 1 9-9 9.8 9.8 0 0 1 6.7 2.7L21 8M21 3v5h-5`})}),ne=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M8 5v14M16 5v14`})}),re=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`m7 4 13 8-13 8Z`})}),ie=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6`})}),ae=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`m3 3 18 18M10.6 10.6a2 2 0 0 0 2.8 2.8M9.9 4.2A10.8 10.8 0 0 1 12 4c5 0 9 4 10 8a12.7 12.7 0 0 1-2 4.1M6.6 6.6A12.4 12.4 0 0 0 2 12c1 4 5 8 10 8 1.5 0 2.9-.4 4.1-1`})}),oe=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`path`,{d:`M12 20h9`}),(0,r.jsx)(`path`,{d:`M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4Z`})]}),se=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`path`,{d:`M10.3 3.7 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.7a2 2 0 0 0-3.4 0Z`}),(0,r.jsx)(`path`,{d:`M12 9v4M12 17h.01`})]}),ce=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`circle`,{cx:`12`,cy:`12`,r:`10`}),(0,r.jsx)(`path`,{d:`M12 16v-4M12 8h.01`})]}),le=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`circle`,{cx:`11`,cy:`11`,r:`7`}),(0,r.jsx)(`path`,{d:`m21 21-4.3-4.3`})]}),ue=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M12 19V5M5 12l7-7 7 7`})}),de=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M12 5v14M19 12l-7 7-7-7`})}),fe=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3`})}),pe=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`m9 18 6-6-6-6`})}),me=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M9 19c-5 1.5-5-2.5-7-3m14 6v-3.9a3.4 3.4 0 0 0-.9-2.6c3-.3 6.2-1.5 6.2-6.7A5.2 5.2 0 0 0 20 4.8 4.9 4.9 0 0 0 19.9 1S18.7.6 16 2.5a13.4 13.4 0 0 0-7 0C6.3.6 5.1 1 5.1 1A4.9 4.9 0 0 0 5 4.8a5.2 5.2 0 0 0-1.4 3.7c0 5.1 3.1 6.4 6.1 6.7a3.4 3.4 0 0 0-.9 2.5V22`})}),he=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`path`,{d:`M18.4 5.6a9 9 0 1 1-12.8 0`}),(0,r.jsx)(`path`,{d:`M12 2v10`})]}),ge=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M15 3h6v6M10 14 21 3M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6`})}),_e=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`circle`,{cx:`7.5`,cy:`15.5`,r:`4.5`}),(0,r.jsx)(`path`,{d:`m10.7 12.3 9.6-9.6M16 7l3 3M14 9l2 2`})]}),ve=e=>(0,r.jsx)(`svg`,{viewBox:`0 0 32 32`,fill:`none`,stroke:`currentColor`,strokeWidth:2.484,strokeLinecap:`round`,...e,children:(0,r.jsx)(`path`,{d:`M22.356 19.797H17.17M9.662 12.29l1.979 3.576a.511.511 0 0 1-.005.504l-1.974 3.409M30.758 16c0 8.15-6.607 14.758-14.758 14.758-8.15 0-14.758-6.607-14.758-14.758C1.242 7.85 7.85 1.242 16 1.242c8.15 0 14.758 6.608 14.758 14.758Z`})}),ye=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`rect`,{x:`4`,y:`11`,width:`16`,height:`10`,rx:`2`}),(0,r.jsx)(`path`,{d:`M8 11V7a4 4 0 0 1 8 0v4`})]}),be=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`path`,{d:`M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z`}),(0,r.jsx)(`path`,{d:`M13 5v2`}),(0,r.jsx)(`path`,{d:`M13 17v2`}),(0,r.jsx)(`path`,{d:`M13 11v2`})]}),xe=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M9 17H7A5 5 0 0 1 7 7h2M15 7h2a5 5 0 0 1 0 10h-2M8 12h8`})}),Se=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`circle`,{cx:`12`,cy:`12`,r:`4`}),(0,r.jsx)(`path`,{d:`M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4`})]}),Ce=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M21 12.8A9 9 0 1 1 11.2 3 7 7 0 0 0 21 12.8Z`})}),we=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`rect`,{x:`2`,y:`3`,width:`20`,height:`14`,rx:`2`}),(0,r.jsx)(`path`,{d:`M8 21h8M12 17v4`})]}),Te=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`circle`,{cx:`12`,cy:`12`,r:`9`}),(0,r.jsx)(`path`,{d:`M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18`})]}),Ee=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`path`,{d:`m18 14 4 4-4 4`}),(0,r.jsx)(`path`,{d:`m18 2 4 4-4 4`}),(0,r.jsx)(`path`,{d:`M2 18h1.973a4 4 0 0 0 3.3-1.7l5.454-8.6a4 4 0 0 1 3.3-1.7H22`}),(0,r.jsx)(`path`,{d:`M2 6h1.972a4 4 0 0 1 3.6 2.2`}),(0,r.jsx)(`path`,{d:`M22 18h-6.041a4 4 0 0 1-3.3-1.8l-.359-.45`})]}),De=e=>(0,r.jsxs)(`svg`,{...i(e),children:[(0,r.jsx)(`circle`,{cx:`9`,cy:`6`,r:`1`,fill:`currentColor`,stroke:`none`}),(0,r.jsx)(`circle`,{cx:`15`,cy:`6`,r:`1`,fill:`currentColor`,stroke:`none`}),(0,r.jsx)(`circle`,{cx:`9`,cy:`12`,r:`1`,fill:`currentColor`,stroke:`none`}),(0,r.jsx)(`circle`,{cx:`15`,cy:`12`,r:`1`,fill:`currentColor`,stroke:`none`}),(0,r.jsx)(`circle`,{cx:`9`,cy:`18`,r:`1`,fill:`currentColor`,stroke:`none`}),(0,r.jsx)(`circle`,{cx:`15`,cy:`18`,r:`1`,fill:`currentColor`,stroke:`none`})]}),v=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`m12 2 3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z`})}),Oe=e=>(0,r.jsx)(`svg`,{...i(e),children:(0,r.jsx)(`path`,{d:`M4 5h16l-6 7v5l-4 2v-7L4 5z`})}),y={anthropic:`claude-color.svg`,anthropic2:`claude-green.svg`,"anthropic-apikey":`claude-color.svg`,"claude-cli":`claude-color.svg`,"azure-openai":`openai.svg`,chatgpt:`openai.svg`,"cloudflare-ai-gateway":`cloudflare-ai-gateway-color.svg`,"cloudflare-workers-ai":`cloudflare-ai-gateway-color.svg`,cline:`cline-color.svg`,"cline-pass":`cline-color.svg`,"command-code":`commandcode-color.svg`,commandcode:`commandcode-color.svg`,cursor:`cursor-color.svg`,deepseek:`deepseek-color.svg`,"dsh-account":`deepseek-color.svg`,devin:`devin.svg`,firepass:`firepass-color.svg`,fireworks:`fireworks-color.svg`,github:`github-copilot-color.svg`,"github-copilot":`copilot-color.svg`,"gitlab-duo":`gitlab-duo-color.svg`,google:`gemini-color.svg`,"google-antigravity":`antigravity-color.svg`,"google-vertex":`gemini-color.svg`,groq:`groq-color.svg`,huggingface:`huggingface-color.svg`,kimi:`kimi-color.svg`,"kimi-code":`kimi-color.svg`,"kimi-responses":`kimi-color.svg`,kiro:`kiro-color.svg`,"lm-studio":`lm-studio-color.svg`,"meta-model":`meta.svg`,"meta-muse":`meta.svg`,mistral:`mistral-color.svg`,minimax:`minimax.svg`,"minimax-cn":`minimax.svg`,moonshot:`moonshot-color.svg`,nvidia:`nvidia-color.svg`,ollama:`ollama-color.svg`,"ollama-cloud":`ollama-color.svg`,openai:`openai.svg`,"openai-apikey":`openai.svg`,"opencode-free":`opencode.svg`,"opencode-go":`opencode.svg`,"opencode-zen":`opencode.svg`,openrouter:`openrouter-color.svg`,opengateway:`opengateway.svg`,opper:`opper.svg`,qianfan:`qianfan-color.svg`,qoder:`qoder.svg`,"qoder-cn":`qoder.svg`,alibaba:`alibaba-color.svg`,"alibaba-token-plan":`alibaba-color.svg`,"alibaba-token-plan-intl":`alibaba-color.svg`,baseten:`baseten.svg`,bizrouter:`bizrouter.svg`,cerebras:`cerebras.svg`,crusoe:`crusoe.svg`,deepinfra:`deepinfra.svg`,digitalocean:`digitalocean.svg`,featherless:`featherless.svg`,hyperbolic:`hyperbolic.svg`,kilo:`kilo.svg`,nanogpt:`nanogpt.svg`,nebius:`nebius.svg`,neuralwatt:`neuralwatt.svg`,nous:`nous.svg`,novita:`novita.svg`,orcarouter:`orcarouter.svg`,"orcarouter-oauth":`orcarouter.svg`,packycode:`packycode.svg`,tokenlab:`tokenlab.svg`,parallel:`parallel.svg`,sambanova:`sambanova.svg`,scaleway:`scaleway.svg`,stepfun:`stepfun-color.svg`,siliconflow:`siliconflow.svg`,synthetic:`synthetic.svg`,together:`together.svg`,umans:`umans.svg`,venice:`venice.svg`,vultr:`vultr.svg`,litellm:`litellm.svg`,zenmux:`zenmux.svg`,zai:`zai.svg`,"zhipu-bigmodel":`zai.svg`,"zhipu-bigmodel-coding":`zai.svg`,"qwen-cloud":`qwen-portal-color.svg`,"vercel-ai-gateway":`vercel-ai-gateway-color.svg`,vllm:`vllm-color.svg`,xai:`grok.svg`,"mimo-free":`xiaomi-color.svg`,mimo:`xiaomi-color.svg`,xiaomi:`xiaomi-color.svg`,"xiaomi-mimo":`xiaomi-color.svg`},b={anthropic:`Anthropic Claude`,"anthropic-apikey":`Anthropic Claude`,chatgpt:`ChatGPT`,openai:`OpenAI (Codex login)`,"openai-apikey":`OpenAI API`,"azure-openai":`Azure OpenAI`,"cloudflare-ai-gateway":`Cloudflare AI Gateway`,"cloudflare-workers-ai":`Cloudflare Workers AI`,cline:`Cline`,"cline-pass":`ClinePass`,nvidia:`NVIDIA NIM`,ollama:`Ollama`,"ollama-cloud":`Ollama Cloud`,xai:`xAI Grok`,"mimo-free":`MiMo Free`,xiaomi:`Xiaomi`,cursor:`Cursor`,deepseek:`DeepSeek`,zed:`Zed`,"dsh-account":`DeepSeek Account (DSH)`,devin:`Devin`,github:`GitHub`,"github-copilot":`GitHub Copilot`,"gitlab-duo":`GitLab Duo`,openrouter:`OpenRouter`,opengateway:`OpenGateway`,opper:`Opper`,"opencode-go":`OpenCode Go`,"opencode-free":`OpenCode Free`,"opencode-zen":`OpenCode Zen`,orcarouter:`OrcaRouter - API`,"orcarouter-oauth":`OrcaRouter - Auth`,packycode:`PackyCode`,tokenlab:`TokenLab`,mistral:`Mistral`,groq:`Groq`,"meta-model":`Meta Model API`,"meta-muse":`Muse Code`,alibaba:`Alibaba Coding Plan`,"alibaba-token-plan":`Alibaba Token Plan`,"alibaba-token-plan-intl":`Alibaba Token Plan (Intl)`,kimi:`Kimi`,"kimi-code":`Kimi`,"kimi-responses":`Kimi`,moonshot:`Moonshot`,google:`Google`,"google-vertex":`Google Vertex`,"lm-studio":`LM Studio`,huggingface:`Hugging Face`,"qwen-cloud":`Qwen Cloud`,siliconflow:`SiliconFlow`,stepfun:`StepFun`,"tencent-coding-plan":`Tencent Cloud Coding Plan`,codebuddy:`CodeBuddy`,"codebuddy-cn":`CodeBuddy CN`,qoder:`Qoder`,"qoder-cn":`Qoder CN`,"vercel-ai-gateway":`Vercel AI Gateway`,vllm:`vLLM`,litellm:`LiteLLM`},x={anthropic2:`provider.name.anthropic2`,"command-code":`provider.name.commandCodeAuth`,commandcode:`provider.name.commandCodeApi`,orcarouter:`provider.name.orcaRouterApi`,"orcarouter-oauth":`provider.name.orcaRouterAuth`,volcengine:`provider.name.volcengine`,"volcengine-coding-plan":`provider.name.volcengineCodingPlan`,"volcengine-agent-plan":`provider.name.volcengineAgentPlan`},ke=new Set([...Object.keys(b),...Object.keys(x)]);function Ae(e){let t=e.toLowerCase();return Object.hasOwn(y,t)?y[t]:void 0}function je(e,t){let n=Ae(e);return n?`/provider-icons/${n}`:void 0}var Me=new Set([`cerebras.svg`,`deepinfra.svg`,`neuralwatt.svg`,`nous.svg`,`novita.svg`,`packycode.svg`,`tokenlab.svg`,`opper.svg`,`opengateway.svg`,`siliconflow.svg`,`synthetic.svg`,`zenmux.svg`,`grok.svg`,`kimi-color.svg`,`ollama-color.svg`,`opencode.svg`,`vercel-ai-gateway-color.svg`]),Ne=new Set([`baseten.svg`,`kilo.svg`,`sambanova.svg`,`venice.svg`,`zai.svg`]),Pe=new Set([`bizrouter.svg`,`featherless.svg`,`hyperbolic.svg`,`nebius.svg`,`parallel.svg`,`umans.svg`]);function Fe(e){if(!e)return`image`;let t=e.split(`/`).pop()??``;return Me.has(t)?`mask`:Ne.has(t)?`plate`:Pe.has(t)?`dark-plate`:`image`}function S(e,t){let n=e.toLowerCase(),r=Object.hasOwn(x,n)?x[n]:void 0;return r?t(r):(Object.hasOwn(b,n)?b[n]:void 0)||(e===n&&/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(e)?e.split(`-`).map(e=>e&&e[0].toUpperCase()+e.slice(1)).join(` `):e)}function Ie(e){return ke.has(e.toLowerCase())}function Le(e){return e===`command-code`?`commandcode-auth`:e===`commandcode`?`commandcode-api`:e}function Re(e,t){let n=e.indexOf(`/`);if(n<=0)return e;let r=e.slice(0,n),i=e.slice(n+1);if(r===`command-code`||r===`commandcode`){let e=i.match(/^([a-z0-9]+)-([a-z0-9]+(?:-[a-z0-9]+)+)$/i);return e&&i.startsWith(`${e[1]}-${e[1]}-`)&&(i=i.slice(e[1].length+1)),`${r===`command-code`?`commandcode-auth`:`commandcode-api`}/${i}`}return e}var ze={ko:[{v:0x2386f26fc10000,s:`경`},{v:0xe8d4a51000,s:`조`},{v:1e8,s:`억`},{v:1e4,s:`만`}],zh:[{v:0x2386f26fc10000,s:`京`},{v:0xe8d4a51000,s:`兆`},{v:1e8,s:`亿`},{v:1e4,s:`万`}],"zh-TW":[{v:0x2386f26fc10000,s:`京`},{v:0xe8d4a51000,s:`兆`},{v:1e8,s:`億`},{v:1e4,s:`萬`}]};function C(e){return e.replace(/\.0+$/,``).replace(/(\.\d*?)0+$/,`$1`)}function Be(e,t){let n=ze[t];if(n){for(let t of n)if(e>=t.v)return`${C((e/t.v).toFixed(1))}${t.s}`;return String(e)}return e<1e4?String(e):e<1e6?`${C((e/1e3).toFixed(1))}K`:e<1e9?`${C((e/1e6).toFixed(1))}M`:e<0xe8d4a51000?`${C((e/1e9).toFixed(1))}B`:`${C((e/0xe8d4a51000).toFixed(1))}T`}var Ve=new Set([`claude-cli`]),He=`anthropic-apikey`;function w(e){return Ve.has((e.adapter??``).trim())}var T=`https://chatgpt.com/backend-api/codex`,Ue=`openai`;function E(e){try{let t=new URL(e.trim());if(t.username||t.password||t.search||t.hash)return;let n=t.pathname.replace(/\/+$/,``);return`${t.origin}${n}`}catch{return}}var We=new URL(T).protocol;function D(e,...t){return`${We}//${e}/${t.join(`/`)}`}var Ge={"cline-pass":{adapter:`openai-chat`,baseUrl:D(`api.cline.bot`,`api`,`v1`)},"mimo-free":{adapter:`mimo-free`,baseUrl:D(`api.xiaomimimo.com`,`api`,`free-ai`,`openai`,`chat`)}};function Ke(e,t){let n=Ge[e];return!n||t.adapter!==n.adapter||E(t.baseUrl)!==E(n.baseUrl)}function O(e){try{let t=new URL(e).hostname.replace(/^\[|\]$/g,``).toLowerCase();return t===`localhost`||t===`127.0.0.1`||t===`::1`}catch{return!1}}function k(e){return e.keyOptional===!0||w(e)||e.authMode===`oauth`||e.authMode===`forward`||e.authMode===`local`||O(e.baseUrl)||e.hasApiKey===!0}function A(e){return e.adapter===`openai-responses`&&e.authMode===`forward`&&E(e.baseUrl)===T}function j(e,t){return e===Ue&&A(t)}function M(e){return w(e)?!1:e.freeTier===!0||e.keyOptional===!0||e.authMode===`local`||O(e.baseUrl)}function N(e,t){return j(e,t)?`accounts`:M(t)?`free`:`paid`}function qe(e,t){let n=[...e],r=(e,t)=>e.name.localeCompare(t.name,void 0,{sensitivity:`base`}),i=e=>e.tier??N(e.name,e);switch(t){case`az`:return n.sort(r);case`za`:return n.sort((e,t)=>r(t,e));case`free-paid`:return n.sort((e,t)=>(i(e)===`free`?0:1)-(i(t)===`free`?0:1)||r(e,t));case`paid-free`:return n.sort((e,t)=>+(i(e)===`free`)-(i(t)===`free`)||r(e,t));case`accounts-first`:return n.sort((e,t)=>{let n=e=>{let t=i(e);return t===`accounts`?0:t===`free`?1:2};return n(e)-n(t)||r(e,t)});default:return n}}function Je(e){let t=[],n=[],r=[];for(let[i,a]of Object.entries(e))a.disabled?r.push({name:i,...a}):k(a)?t.push({name:i,...a,tier:N(i,a)}):n.push({name:i,...a});return{ready:t,needsSetup:n,disabled:r}}function Ye(e,t){let n=new Set(Object.entries(t).filter(([,e])=>e).map(([e])=>e));if(n.size===0)return e;let r=e=>e.map(e=>n.has(e.name)?{...e,activeNeedsReauth:!0}:e);return{ready:r(e.ready),needsSetup:r(e.needsSetup),disabled:e.disabled}}function P(e){return e.disabled?`disabled`:`activeNeedsReauth`in e&&e.activeNeedsReauth?`needs-setup`:k(e)?`ready`:`needs-setup`}function Xe(e){let t=e.openai,n=e.chatgpt;if(!t||!n||!j(`openai`,t)||!A(n))return e;let r={...e};return delete r.chatgpt,r}function F(e){return e.authMode===`local`||O(e.baseUrl)}var Ze=[`ollama`,`vllm`,`lm-studio`,`lmstudio`,`litellm`,`localai`];function Qe(e){let t=(e.authMode??``).toLowerCase();if(t===`oauth`||t===`forward`)return`login`;if(F(e))return`local`;let n=`${e.name??``} ${e.adapter} ${e.baseUrl}`.toLowerCase();return Ze.some(e=>n.includes(e))?`selfHosted`:`cloud`}function I(e,t){if(!e||typeof e!=`object`||Array.isArray(e))return null;let n=e;if(typeof n.updatedAt!=`number`||!Number.isFinite(n.updatedAt))return null;let r=n.observed===!0;return!r&&t-n.updatedAt>=18e5||!(`quota`in n)||n.label!==void 0&&typeof n.label!=`string`||n.source!==void 0&&typeof n.source!=`string`?null:{...typeof n.label==`string`?{label:n.label}:{},...typeof n.source==`string`?{source:n.source}:{},updatedAt:n.updatedAt,quota:n.quota,...r?{observed:!0}:{},...n.aggregation===void 0?{}:{aggregation:n.aggregation}}}function $e(e,t=Date.now()){if(!e||typeof e!=`object`||Array.isArray(e))return null;let n={};for(let[r,i]of Object.entries(e)){let e=I(i,t);r.trim()&&e&&(n[r]=e)}return n}function et(e,t=Date.now()){if(!Array.isArray(e))return{};let n={};for(let r of e){if(!r||typeof r!=`object`||Array.isArray(r))continue;let e=r.provider,i=I(r,t);typeof e==`string`&&e.trim()&&i&&(n[e]=i)}return n}function tt(e){return e?.observed===!0&&typeof e.updatedAt==`number`?e.updatedAt:void 0}var L=e=>typeof e==`number`&&Number.isFinite(e)?e:void 0,nt=e=>{let t=L(e);if(t===void 0)return;let n=t>1e10?t:t*1e3;return Number.isFinite(new Date(n).getTime())?t:void 0};function R(e,t){if(!e||typeof e!=`object`||Array.isArray(e))return null;let n=e,r=Array.isArray(n.customWindows)?n.customWindows.flatMap(e=>{if(!e||typeof e!=`object`)return[];let t=e;return typeof t.label!=`string`||L(t.percent)===void 0?[]:[{label:t.label,percent:t.percent,...L(t.resetAt)===void 0?{}:{resetAt:t.resetAt},...typeof t.modelId==`string`&&t.modelId.length<=128?{modelId:t.modelId}:{}}]}):[],i=n.creditsUsd&&typeof n.creditsUsd==`object`&&!Array.isArray(n.creditsUsd)?n.creditsUsd:null,a=L(i?.used),o=L(i?.limit),s=L(i?.remaining),c=L(i?.percent),l=nt(i?.expiresAt),u=a!==void 0&&o!==void 0&&s!==void 0&&c!==void 0?{used:a,limit:o,remaining:s,percent:c,...l===void 0?{}:{expiresAt:l},...typeof i?.unlimited==`boolean`?{unlimited:i.unlimited}:{}}:void 0,d={...L(n.fiveHourPercent)===void 0?{}:{fiveHourPercent:n.fiveHourPercent},...L(n.fiveHourResetAt)===void 0?{}:{fiveHourResetAt:n.fiveHourResetAt},...L(n.weeklyPercent)===void 0?{}:{weeklyPercent:n.weeklyPercent},...L(n.weeklyResetAt)===void 0?{}:{weeklyResetAt:n.weeklyResetAt},...L(n.monthlyPercent)===void 0?{}:{monthlyPercent:n.monthlyPercent},...L(n.monthlyResetAt)===void 0?{}:{monthlyResetAt:n.monthlyResetAt},...r.length>0?{customWindows:r}:{},...u?{creditsUsd:u}:{},updatedAt:L(n.updatedAt)??t??Date.now()};return d.fiveHourPercent!==void 0||d.weeklyPercent!==void 0||d.monthlyPercent!==void 0||(d.customWindows?.length??0)>0||d.creditsUsd!==void 0?d:null}function z(e){return R(e?.quota,e?.updatedAt)}function rt(e){if(!e)return;if(e.aggregation===void 0)return e;let t=V(e)?.currentAccount?.quota??null;return{...e,aggregation:void 0,quota:t,updatedAt:t?.updatedAt}}function B(e){if(!e||typeof e!=`object`||Array.isArray(e))return;let t=e,n=L(t.usedPercent);if(n!==void 0)return{usedPercent:n,...typeof t.incomplete==`boolean`?{incomplete:t.incomplete}:{},...L(t.excludedAccounts)===void 0?{}:{excludedAccounts:t.excludedAccounts},...L(t.nextRecoveryAt)===void 0?{}:{nextRecoveryAt:t.nextRecoveryAt},...L(t.nextRecoveryPercent)===void 0?{}:{nextRecoveryPercent:t.nextRecoveryPercent}}}function V(e){let t=e?.aggregation;if(!t||typeof t!=`object`||Array.isArray(t))return null;let n=t;if(n.kind!==`capacity-weighted-v1`||n.scope!==`routable-known`)return null;let r=L(n.excludedAccounts),i=L(n.unknownPlanAccounts);if(r===void 0||i===void 0||typeof n.incomplete!=`boolean`)return null;let a=n.currentAccount&&typeof n.currentAccount==`object`&&!Array.isArray(n.currentAccount)?n.currentAccount:null,o=Array.isArray(n.customWindows)?n.customWindows.flatMap(e=>{if(!e||typeof e!=`object`||Array.isArray(e))return[];let t=e,n=B(t);return typeof t.label==`string`&&n?[{label:t.label,...n}]:[]}):[],s=B(n.fiveHour),c=B(n.weekly),l=B(n.monthly),u=!!s||!!c||!!l||o.length>0;return{presentation:n.presentation===`aggregate`||n.presentation===`effective-account-fallback`||n.presentation===`coverage-only`?n.presentation:u?`aggregate`:`coverage-only`,incomplete:n.incomplete,excludedAccounts:r,unknownPlanAccounts:i,partialWindowAccounts:L(n.partialWindowAccounts)??0,...s?{fiveHour:s}:{},...c?{weekly:c}:{},...l?{monthly:l}:{},...o.length>0?{customWindows:o}:{},...a?{currentAccount:{...typeof a.plan==`string`||a.plan===null?{plan:a.plan}:{},quota:R(a.quota)}}:{}}}function it(e){if(!e?.trim())return``;let[t,n]=e.split(`:`,2);return n?`${t} · ${n.replace(/-/g,` `)}`:e}function at(e,t){let n=P(e);return n===`disabled`?t(`prov.disabledBadge`):n===`ready`?t(`pws.status.ready`):`activeNeedsReauth`in e&&e.activeNeedsReauth?t(`pws.status.needsAttention`):t(`pws.status.needsSetup`)}function ot(e,t){if(w(e))return t(`modal.badge.subscriptionCli`);switch(e.authMode){case`oauth`:return t(`modal.badge.oauth`);case`forward`:return t(`pws.auth.chatgptPassthrough`);case`local`:return t(`modal.badge.local`);case`key`:return t(`modal.badge.apiKey`);default:return e.authMode??(e.keyOptional?t(`pws.auth.noKey`):t(`modal.badge.apiKey`))}}function st(e){let t=P(e);return t===`disabled`?`providers-workspace-rail-status providers-workspace-rail-status--inactive`:t===`ready`?`providers-workspace-rail-status providers-workspace-rail-status--active`:`providers-workspace-rail-status providers-workspace-rail-status--warning`}function H({name:e,adapter:n,baseUrl:i,cls:a}){let o=t(),s=je(e,{adapter:n,baseUrl:i}),c=Fe(s),l=c===`plate`?`${a} provider-icon--plate`:c===`dark-plate`?`${a} provider-icon--plate-dark`:a;return(0,r.jsx)(`span`,{className:l,children:s&&c===`mask`?(0,r.jsx)(`span`,{className:`provider-icon-mask`,style:{maskImage:`url(${s})`,WebkitMaskImage:`url(${s})`},"aria-hidden":`true`}):s?(0,r.jsx)(`img`,{src:s,alt:``,"aria-hidden":`true`}):(0,r.jsx)(ct,{name:e,label:S(e,o)})})}function ct({name:e,label:t}){let n=[...e].reduce((e,t)=>e+t.charCodeAt(0),0)%360,i=(t.trim()[0]??e[0]??`?`).toUpperCase();return(0,r.jsx)(`span`,{className:`provider-icon-fallback`,style:{background:`hsl(${n} 55% 90%)`,color:`hsl(${n} 65% 32%)`},"aria-hidden":`true`,children:i})}function lt({item:e,selected:n,tabbable:i,modelCount:a,isDefault:o,showConfigId:s,onClick:c,onFocus:l}){let u=t(),d=M(e),f=F(e),p=at(e,u),m=S(e.name,u),h=s?`${m} (${e.name})`:m,g=`${o?u(`pws.rail.suffixDefault`):``}${f?u(`pws.rail.suffixLocal`):d?u(`pws.rail.suffixFree`):``}`,ee=a!==void 0&&a>0?a===1?u(`pws.modelCountOne`):u(`pws.modelCount`,{count:a}):``,_=[s?e.name:``,ee].filter(Boolean).join(` · `);return(0,r.jsxs)(`button`,{type:`button`,className:`providers-workspace-rail-row${n?` providers-workspace-rail-row--selected`:``}`,onClick:c,role:`option`,"aria-selected":n,tabIndex:i?0:-1,"aria-label":u(`pws.rail.selectAria`,{name:h,status:p,suffix:g}),title:h,onFocus:l,children:[(0,r.jsx)(H,{name:e.name,adapter:e.adapter,baseUrl:e.baseUrl,cls:`providers-workspace-rail-icon`}),(0,r.jsxs)(`span`,{className:`providers-workspace-rail-copy`,children:[(0,r.jsxs)(`span`,{className:`providers-workspace-rail-primary`,children:[(0,r.jsx)(`span`,{className:`providers-workspace-rail-name-label`,title:m,children:m}),f?(0,r.jsx)(`span`,{className:`pwi-rail-badge pwi-rail-badge--local`,title:u(`pws.localTitle`),children:u(`modal.badge.local`)}):d?(0,r.jsx)(`span`,{className:`pwi-rail-badge pwi-rail-badge--free`,title:u(`pws.freeTitle`),children:u(`modal.badge.free`)}):null]}),(0,r.jsx)(`span`,{className:`providers-workspace-rail-secondary`,title:_||void 0,children:_||`\xA0`})]}),(0,r.jsxs)(`span`,{className:`providers-workspace-rail-trail`,children:[o&&(0,r.jsx)(`span`,{className:`pwi-default-star`,title:u(`prov.defaultBadge`),"aria-label":u(`prov.defaultBadge`),children:(0,r.jsx)(v,{width:17,height:17,"aria-hidden":`true`})}),(0,r.jsx)(`span`,{className:st(e),title:p,"aria-hidden":`true`})]})]})}var ut=1e10;function dt(e){return e<ut?e*1e3:e}function ft(e,t){let n=e=>typeof e==`number`&&Number.isFinite(e);if(!n(e.shortPercent)||e.shortPercent<100)return!1;let r=e.shortResetAt;if(!n(r)||r<=0){let r=e.shortObservedAt;if(!n(r))return!1;let i=t-r;return i>=0&&i<=3e5}return dt(r)>t}function pt(e){return{fiveHourAvailable:e?.shortWindowSeconds===18e3&&typeof e.shortResetAt==`number`,weeklyAvailable:typeof e?.weeklyResetAt==`number`}}function U(e){let t=e?.trim().toLowerCase();return t===`go`||t===`free`}function W(e,t){if(!e)return null;let n=e.shortPercent===void 0&&e.shortResetAt===void 0?e:{...e,fiveHourPercent:e.fiveHourPercent??e.shortPercent,fiveHourResetAt:e.fiveHourResetAt??e.shortResetAt};return U(t)?{...n.monthlyPercent===void 0?{}:{monthlyPercent:n.monthlyPercent},...n.monthlyResetAt===void 0?{}:{monthlyResetAt:n.monthlyResetAt},...n.creditsUsd===void 0?{}:{creditsUsd:n.creditsUsd},...n.resetCredits===void 0?{}:{resetCredits:n.resetCredits},updatedAt:n.updatedAt}:n}function mt(e,t,n=Date.now()){if(!e)return null;let r=e=>typeof e==`number`&&Number.isFinite(e),i=r(e.fiveHourPercent)?e.fiveHourPercent:r(e.shortPercent)?e.shortPercent:void 0,a=(U(t)?[e.monthlyPercent]:[e.weeklyPercent,e.monthlyPercent]).filter(r);if(a.length===0)return ft({...r(i)?{shortPercent:i}:{},...r(e.fiveHourResetAt??e.shortResetAt)?{shortResetAt:e.fiveHourResetAt??e.shortResetAt}:{},...r(e.shortObservedAt)?{shortObservedAt:e.shortObservedAt}:{}},n)?100:null;let o=r(i)?[...a,i]:a;return o.length?Math.max(...o):null}function ht(e){let t=new URLSearchParams({hours:String(e.chartHours),bucketMinutes:String(e.bucketMinutes),metric:e.tokenMetric,aggregation:e.aggregation,grouping:e.chartGrouping});e.models?.length&&t.set(`models`,e.models.join(`,`));for(let n of e.hiddenProviders)t.append(`hiddenProvider`,n);return t}function G(e){return Array.isArray(e)&&e.length<=100&&e.every(e=>typeof e==`string`)?JSON.stringify([...new Set(e)].sort()):void 0}function gt(e,t){let n=new Set(t.hiddenProviders),r=e.availableModels.filter(e=>!n.has(e.slice(0,e.indexOf(`/`))));if(t.models?.length===0)return{...e,series:[],availableModels:r};let i=t.models===null?null:new Set(t.models),a=i!==null||n.size>0,o=e.appliedFilters,s=!!o&&G(o.hiddenProviders)===G(t.hiddenProviders)&&(t.models===null?o.models===null:G(o.models)===G(t.models)),c=e.series.filter(e=>e.id===`other`&&e.provider===``?!a||s:!n.has(e.provider)&&(i===null||i.has(`${e.provider}/${e.model}`)||i.has(e.model)));return{...e,series:c,availableModels:r,truncated:e.truncated||(a||o!==void 0)&&!s}}var _t={6:15,24:60,72:180,168:360};function vt(e){return _t[e]}function K(e){if(e<1e3)return String(Math.round(e));let t=[[0xe8d4a51000,`T`],[1e9,`B`],[1e6,`M`],[1e3,`K`]];for(let n=0;n<t.length;n+=1){let[r,i]=t[n];if(e>=r){let a=Math.round(e/r);if(a>=1e3&&n>0){let[r,i]=t[n-1];return`${Math.round(e/r)}${i}`}return`${a}${i}`}}return String(Math.round(e))}function yt(e,t){let n=new Map;for(let r of e){let e=r.includes(`/`)?r.slice(0,r.indexOf(`/`)):r,i=n.get(e)??{provider:e,models:[],total:0},a=t.get(r)??0;i.models.push({id:r,total:a}),i.total+=a,n.set(e,i)}return Array.from(n.values()).map(e=>({...e,models:e.models.toSorted((e,t)=>t.total-e.total||e.id.localeCompare(t.id))})).toSorted((e,t)=>t.total-e.total||e.provider.localeCompare(t.provider))}function bt(e,t,n,r){let i=new Set(t),a=new Set((e??t).filter(e=>i.has(e)));for(let e of n)r?a.add(e):a.delete(e);return t.length>0&&t.every(e=>a.has(e))?null:t.filter(e=>a.has(e))}function xt(e,t=[]){let n={...e};if(typeof n.menuBarTemplate==`string`&&n.menuBarTemplate.trim()===``&&(n.menuBarTemplate=null),n.models!==void 0&&t.length>0){let e=n.models??[],r=new Set(e);e.length===t.length&&t.every(e=>r.has(e))&&(n.models=null)}return n}function St(e,t,n,r,i=8){let a=Math.max(0,t-i*2),o=Math.max(0,n-i*2),s=Math.max(r,1),c=Math.max(e.length-1,1);return e.map((e,t)=>`${i+a*t/c},${i+o*(1-Math.max(0,e)/s)}`).join(` `)}function Ct(e,t,n,r,i=8){let a=e[0]?.points.length??0;if(a===0)return[];let o=Math.max(0,t-i*2),s=Math.max(0,n-i*2),c=Math.max(r,1),l=Math.min(3,o/Math.max(a*8,1)),u=Math.max(0,o/a-l),d=[];for(let t=0;t<a;t+=1){let n=0;for(let r=0;r<e.length;r+=1){let f=s*Math.max(0,e[r]?.points[t]??0)/c;f>0&&d.push({x:i+o/a*t+l/2,y:i+s-n-f,width:u,height:f,seriesIndex:r,bucketIndex:t}),n+=f}}return d}var q=[`#0A84FF`,`#FF9F0A`,`#30D158`,`#BF5AF2`,`#FF453A`,`#64D2FF`],wt=640,Tt=160,J=28;function Et(e,t){return Math.max(...t===`stackedBar`?Array.from({length:e.buckets},(t,n)=>e.series.reduce((e,t)=>e+(t.points[n]??0),0)):e.series.flatMap(e=>e.points),0)}function Dt(e,t){let n=new Intl.DateTimeFormat(t,{month:`short`,day:`numeric`}),r=Math.max(1,Math.floor((e.buckets-1)/3));return[0,1,2,3].map(t=>{let i=Math.min(e.buckets-1,t*r);return n.format(new Date((e.start+i*e.bucketSeconds)*1e3))})}function Ot({timeline:e,chartStyle:t,hours:n,loading:i,error:a,onRetry:o,locale:s,t:c}){if(i)return(0,r.jsx)(`div`,{className:`usage-companion-chart-skeleton`,"aria-busy":`true`,"aria-label":c(`usage.companion.loading`)});if(a)return(0,r.jsxs)(`div`,{className:`usage-companion-chart-state`,role:`alert`,children:[(0,r.jsx)(`span`,{children:c(`usage.companion.timelineUnavailable`)}),(0,r.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:o,children:c(`common.retry`)})]});if(!e||e.series.length===0)return(0,r.jsx)(`div`,{className:`usage-companion-chart-state`,children:c(`usage.companion.empty`,{hours:e?.buckets?Math.round(e.buckets*e.bucketSeconds/3600):n})});let l=Et(e,t),u=Dt(e,s),d=J,f=u.map((e,t)=>(0,r.jsx)(`text`,{x:J+584*t/3,y:156,textAnchor:t===0?`start`:t===3?`end`:`middle`,className:`usage-companion-axis-label`,children:e},`${e}-${t}`)),p=t===`line`?e.series.map((e,t)=>(0,r.jsx)(`polyline`,{points:St(e.points,584,104,l,0),transform:`translate(${J},${J})`,fill:`none`,stroke:q[t%q.length],strokeWidth:`2`,strokeLinejoin:`round`,strokeLinecap:`round`},e.id)):Ct(e.series,584,104,l,0).map(e=>(0,r.jsx)(`rect`,{x:J+e.x,y:J+e.y,width:e.width,height:e.height,fill:q[e.seriesIndex%q.length],rx:`1`},`${e.bucketIndex}-${e.seriesIndex}`));return(0,r.jsxs)(`div`,{className:`usage-companion-chart`,children:[(0,r.jsxs)(`svg`,{viewBox:`0 0 ${wt} ${Tt}`,role:`img`,"aria-label":c(`usage.companion.chartLabel`),children:[(0,r.jsx)(`line`,{x1:J,y1:d,x2:J,y2:132,className:`usage-companion-axis`}),(0,r.jsx)(`line`,{x1:J,y1:132,x2:612,y2:132,className:`usage-companion-axis`}),(0,r.jsx)(`text`,{x:24,y:32,textAnchor:`end`,className:`usage-companion-axis-label`,children:K(l)}),p,f]}),(0,r.jsx)(`div`,{className:`usage-companion-legend`,children:e.series.map((e,t)=>(0,r.jsxs)(`span`,{className:`usage-companion-legend-item`,children:[(0,r.jsx)(`span`,{className:`usage-companion-swatch`,style:{background:q[t%q.length]},"aria-hidden":`true`}),(0,r.jsx)(`span`,{children:e.id})]},e.id))}),e.truncated&&(0,r.jsx)(`p`,{className:`muted text-caption`,children:c(`usage.companion.olderRecordsSkipped`)})]})}var Y=e=>typeof e==`number`&&Number.isFinite(e)&&e>=0,X=e=>typeof e==`object`&&e&&!Array.isArray(e)?e:{};function kt(e){return Object.entries(X(X(e).providers)).flatMap(([e,t])=>{let n=X(t);return n.disabled===!0?[]:e===`openai`?[{name:e,path:`/api/codex-auth/accounts`,switchKind:`codex`}]:n.authMode===`oauth`?[{name:e,path:`/api/oauth/accounts?${new URLSearchParams({provider:e,quota:`1`})}`,switchKind:`oauth`}]:n.hasApiKey===!0&&n.authMode!==`forward`?[{name:e,path:`/api/providers/keys?${new URLSearchParams({name:e,quota:`1`})}`,switchKind:`apiKey`}]:[{name:e,path:null,switchKind:null}]})}function At(e,t,n){return t===`codex`?{path:`/api/codex-auth/active`,body:{accountId:n}}:t===`oauth`?{path:`/api/oauth/accounts/active`,body:{provider:e,accountId:n}}:{path:`/api/providers/keys/active`,body:{name:e,id:n}}}function jt(e,t){return t?{switchState:`active`}:X(e.mainAccountHardLock).state===`blocked`?{switchState:`blocked`,blockedReason:`mainHardLock`}:e.paused===!0?{switchState:`blocked`,blockedReason:`paused`}:X(e.health).reason===`validation_pending`?{switchState:`blocked`,blockedReason:`validationPending`}:{switchState:`available`}}function Mt(e,t){let n=[`go`,`free`].includes((t??``).trim().toLowerCase()),r=e.fiveHourPercent??e.shortPercent;return(n?[e.monthlyPercent,r]:[e.weeklyPercent,e.monthlyPercent,r]).some(e=>typeof e==`number`&&Number.isFinite(e)&&e>=100)}function Nt(e){let t=X(e),n=t.accounts??t.keys;if(!Array.isArray(n))throw Error(`Invalid account roster`);return n.map(e=>{let n=X(e);if(typeof n.id!=`string`)throw Error(`Invalid account identifier`);let r=typeof n.email==`string`?Pt(n.email):void 0,i=[n.alias,n.label,r,n.logLabel,n.id].find(e=>typeof e==`string`&&e.length),a=n.quotaUnavailable===!0||n.quotaMode===`unsupported`||!n.quota?null:X(n.quota),o=typeof n.plan==`string`?n.plan:void 0,s=t.activeAccountId??t.activeId??t.activeCodexAccountId,c=typeof s==`string`?s===n.id:n.active===!0;return{id:n.id,label:i,email:r,plan:o,unavailable:n.quotaUnavailable===!0,active:c,...jt(n,c),exhausted:a!==null&&Mt(X(n.quota),o),status:typeof X(n.health).status==`string`?X(n.health).status:void 0,quotaFailure:typeof n.quotaFailure==`string`?n.quotaFailure:void 0,quota:W(a,o)}})}function Z(e){if(!Y(e)||e===0)return null;let t=e<0xe8d4a51000?e*1e3:e;return Number.isFinite(new Date(t).getTime())?t:null}function Pt(e){let[t,n]=e.split(`@`);if(!n)return`•••`;let r=n.includes(`.`)?n.slice(n.lastIndexOf(`.`)):``;return`${t?.slice(0,1)||`•`}•••@${n.slice(0,1)}•••${r}`}function Ft(e,t,n=Date.now()){let r=Z(e);if(r===null||r<=n)return{text:`—`};let i=Math.ceil((r-n)/6e4),a=(e,n)=>new Intl.NumberFormat(t,{style:`unit`,unit:n,unitDisplay:`narrow`}).format(e);return{text:i<60?a(i,`minute`):i<1440?`${a(Math.floor(i/60),`hour`)} ${a(i%60,`minute`)}`:i<10080?`${a(Math.floor(i/1440),`day`)} ${a(Math.floor(i%1440/60),`hour`)}`:new Intl.DateTimeFormat(t,{month:`short`,day:`numeric`}).format(r),exact:new Date(r).toLocaleString(t)}}function It(e){if(!e)return[];let t=[{id:`quota.fiveHourLimit`,key:`quota.fiveHourLimit`,percent:e.fiveHourPercent??e.shortPercent,reset:e.fiveHourResetAt??e.shortResetAt},{id:`quota.weeklyLimit`,key:`quota.weeklyLimit`,percent:e.weeklyPercent,reset:e.weeklyResetAt},{id:`quota.monthlyLimit`,key:`quota.monthlyLimit`,percent:e.monthlyPercent,reset:e.monthlyResetAt},...Array.isArray(e.customWindows)?e.customWindows.filter(e=>e&&typeof e.label==`string`).map(e=>({id:e.label,label:e.label,modelId:e.modelId,percent:e.percent,reset:e.resetAt})):[]].filter(e=>Y(e.percent)||Z(e.reset)!==null),n=new Map;return t.map(e=>{let t=n.get(e.id)??0;return n.set(e.id,t+1),t===0?e:{...e,id:`${e.id}#${t}`}})}function Lt(e,t){let n=new Set(t.hiddenProviders),r=t.models===null?null:new Set(t.models),i=e.models.filter(e=>!n.has(e.provider)&&(r===null||r.has(`${e.provider}/${e.model}`)||r.has(e.model)));if(t.models===null&&t.hiddenProviders.length===0)return{...e,models:i};if(t.models?.length!==0&&e.models.some(e=>!e.provider||!e.model||e.provider===`other`&&e.model===`other`))return{...e,models:i.filter(e=>e.provider!==`other`||e.model!==`other`),summary:{},usageIncomplete:!0};let a={};for(let e of[`requests`,`totalTokens`,`inputTokens`,`outputTokens`,`cachedInputTokens`,`cacheReadInputTokens`,`estimatedCostUsd`,`measuredRequests`,`pricedRequests`])i.length&&i.every(t=>Y(t[e]))&&(a[e]=i.reduce((t,n)=>t+n[e],0));return{...e,models:i,summary:a}}function Rt(e){let t={...e};if((e.requests??0)>0&&(e.measuredRequests===0||e.coverageRatio===0))for(let e of[`totalTokens`,`inputTokens`,`outputTokens`,`cachedInputTokens`,`cacheReadInputTokens`])delete t[e];return(e.requests??0)>0&&e.pricedRequests===0&&delete t.estimatedCostUsd,t}async function zt(e,t){let r=n(2e4),i=()=>r.controller.abort();t.aborted&&i(),t.addEventListener(`abort`,i,{once:!0});try{let t=await fetch(e,{signal:r.signal,cache:`no-store`});if(!t.ok)throw Error(String(t.status));let n=await t.json();if(r.signal.aborted)throw Error(`Tray request cancelled`);return n}finally{r.clear(),t.removeEventListener(`abort`,i)}}function Bt(e){let t=X(e);if(t.error||!t.summary||typeof t.summary!=`object`||Array.isArray(t.summary)||!Array.isArray(t.models))throw Error(`Invalid usage`);return t}var Q=e=>typeof e==`number`&&Number.isFinite(e);function $(e){return Q(e)?e>=90?`critical`:e>=70?`warn`:`normal`:`normal`}function Vt(e){return Q(e)?`${Math.floor(e)}%`:`-`}var Ht=[`quota.weeklyLimit`,`quota.monthlyLimit`,`quota.fiveHourLimit`];function Ut(e){let t=It(e).map(e=>{let t=Q(e.percent)?e.percent:void 0,n=Z(e.reset),r=`modelId`in e?e.modelId:void 0;return{id:e.id,...r===void 0?{}:{modelId:r},...`key`in e&&e.key?{labelKey:e.key}:{},...`label`in e&&typeof e.label==`string`?{label:e.label}:{},...t===void 0?{}:{percent:t},...n===null?{}:{resetAt:n},severity:r===void 0?$(t):`normal`}}),n=e.creditsUsd;if(n&&n.unlimited!==!0&&Q(n.percent)){let e=Z(n.expiresAt);t.push({id:`quotaSummary.credits`,labelKey:`quotaSummary.credits`,percent:n.percent,...e===null?{}:{resetAt:e},severity:$(n.percent)})}return t}function Wt(e){let t=e.filter(e=>e.modelId===void 0&&e.percent!==void 0),n=new Map(t.map(e=>[e.id,e]));for(let e of Ht){let t=n.get(e);if(t)return t}return t[0]}function Gt(e,t){let n=[];for(let[r,i]of Object.entries(e)){let e=z(i);if(!e)continue;let a=Ut(e),o=Wt(a);o&&n.push({provider:r,label:i.label?.trim()||t(r),headline:o,windows:a,...Q(i.updatedAt)?{updatedAt:i.updatedAt}:{},observed:i.observed===!0,severity:o.severity})}return n}export{p as $,rt as A,ee as At,Xe as B,ie as Bt,W as C,_ as Ct,ot as D,ne as Dt,lt as E,d as Et,F,Ee as Ft,qe as G,M as H,Qe as I,v as It,Be as J,He as K,Ye as L,Se as Lt,$e as M,te as Mt,et as N,le as Nt,z as O,oe as Ot,tt as P,o as Pt,Le as Q,P as R,f as Rt,mt as S,u as St,H as T,Ce as Tt,Ke as U,j as V,g as Vt,N as W,S as X,Re as Y,Ie as Z,gt as _,ce as _t,zt as a,h as at,yt as b,l as bt,Rt as c,fe as ct,kt as d,Oe as dt,se as et,It as f,me as ft,xt as g,m as gt,vt as h,De as ht,At as i,s as it,it as j,he as jt,V as k,re as kt,Nt as l,ge as lt,Ot as m,a as mt,Vt as n,ue as nt,Lt as o,pe as ot,Ft as p,Te as pt,w as q,$ as r,c as rt,Y as s,ve as st,Gt as t,de as tt,Bt as u,ae as ut,ht as v,_e as vt,pt as w,we as wt,bt as x,ye as xt,K as y,xe as yt,Je as z,be as zt};
@@ -36,7 +36,7 @@
36
36
  document.documentElement.lang = langMap[locale];
37
37
  })();
38
38
  </script>
39
- <script type="module" crossorigin src="/assets/index-B5bsvxor.js"></script>
39
+ <script type="module" crossorigin src="/assets/index-TmaHa54u.js"></script>
40
40
  <link rel="stylesheet" crossorigin href="/assets/index-DPeB9HpV.css">
41
41
  </head>
42
42
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitkyc08/opencodex",
3
- "version": "2.88.0",
3
+ "version": "2.90.0",
4
4
  "description": "Universal provider proxy for OpenAI Codex & Claude Code — use any LLM with Codex CLI/App/SDK and Claude Code",
5
5
  "type": "module",
6
6
  "main": "./bin/package-main.mjs",
@@ -80,7 +80,7 @@
80
80
  },
81
81
  "dependencies": {
82
82
  "@bufbuild/protobuf": "^2.14.0",
83
- "@modelcontextprotocol/sdk": "^1.30.0",
83
+ "@modelcontextprotocol/sdk": "^1.32.1",
84
84
  "@napi-rs/keyring": "1.3.0",
85
85
  "bun": "1.4.2",
86
86
  "zod": "4.4.3"
@@ -0,0 +1,117 @@
1
+ import { credentialDomainFor } from "../../protocols/opaque-state";
2
+ import type { OcxProviderConfig } from "../../types";
3
+
4
+ export type AnthropicCacheRetention = "none" | "short" | "long";
5
+
6
+ /**
7
+ * The retention an omitted `cacheRetention` resolves to for one destination.
8
+ *
9
+ * First-party Anthropic (API key or OAuth pool) defaults to the 1-hour TTL: agentic turns often
10
+ * pause longer than five minutes, a 5-minute entry then expires and the next turn rewrites the
11
+ * whole prefix, and the 1h write (2x base input vs 1.25x) pays for itself on a single reuse.
12
+ * Anthropic-compatible endpoints (gateways, vendor /anthropic surfaces) keep the 5-minute
13
+ * default: none of them documents ttl "1h", and an unknown TTL is either rejected or billed on
14
+ * terms we cannot see. An explicit cacheRetention "long" still sends 1h anywhere.
15
+ */
16
+ export function defaultAnthropicCacheRetention(provider: Pick<OcxProviderConfig, "baseUrl" | "authMode">): "short" | "long" {
17
+ return credentialDomainFor(provider)?.firstPartyAnthropic ? "long" : "short";
18
+ }
19
+
20
+ /** Explicit configuration always wins; otherwise the destination default applies. */
21
+ export function resolveAnthropicCacheRetention(
22
+ retention: AnthropicCacheRetention | undefined,
23
+ provider: Pick<OcxProviderConfig, "baseUrl" | "authMode">,
24
+ ): AnthropicCacheRetention {
25
+ return retention ?? defaultAnthropicCacheRetention(provider);
26
+ }
27
+
28
+ type Rec = Record<string, unknown>;
29
+ const isRec = (value: unknown): value is Rec => typeof value === "object" && value !== null && !Array.isArray(value);
30
+
31
+ /**
32
+ * The 1-hour share of a reported cache write, from Anthropic's `usage.cache_creation` split
33
+ * (`ephemeral_1h_input_tokens`). Undefined when the split is absent or malformed, which prices
34
+ * the whole write at the 5-minute tier as before; clamped to the reported write total.
35
+ */
36
+ export function anthropicCacheWrite1hTokens(usage: Rec, write: number): number | undefined {
37
+ const split = usage.cache_creation;
38
+ if (!isRec(split)) return undefined;
39
+ const value = split.ephemeral_1h_input_tokens;
40
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return undefined;
41
+ return Math.min(value, write);
42
+ }
43
+ const MAX_DEPTH = 16;
44
+ /** Tool inputs, schemas and examples are caller data, not blocks: a cache_control key there is no breakpoint. */
45
+ const isDataKey = (key: string): boolean => key === "cache_control" || key === "input" || key === "input_schema"
46
+ || key === "input_examples";
47
+
48
+ /**
49
+ * Every caller cache_control breakpoint TTL in a Messages body: top-level automatic caching plus
50
+ * blocks in system, tools and messages, including nested containers (tool_result,
51
+ * search_result, document sources).
52
+ */
53
+ export function collectAnthropicCacheTtls(body: unknown): unknown[] {
54
+ if (!isRec(body)) return [];
55
+ const ttls: unknown[] = [];
56
+ const visit = (node: unknown, depth: number): void => {
57
+ if (depth > MAX_DEPTH) return;
58
+ if (Array.isArray(node)) { for (const item of node) visit(item, depth + 1); return; }
59
+ if (!isRec(node)) return;
60
+ if (isRec(node.cache_control)) ttls.push(node.cache_control.ttl);
61
+ for (const [key, value] of Object.entries(node)) {
62
+ if (!isDataKey(key) && (Array.isArray(value) || isRec(value))) visit(value, depth + 1);
63
+ }
64
+ };
65
+ if (isRec(body.cache_control)) ttls.push(body.cache_control.ttl);
66
+ visit(body.system, 0);
67
+ visit(body.tools, 0);
68
+ visit(body.messages, 0);
69
+ return ttls;
70
+ }
71
+
72
+ /**
73
+ * Native Messages passthrough: give the caller's TTL-less breakpoints the 1-hour default.
74
+ *
75
+ * Applies only when the resolved retention is "long". A caller that pinned any breakpoint to a
76
+ * TTL other than 1h ("5m") chose its own scheme and the body is returned untouched; upgrading
77
+ * only its unset breakpoints could also put a 1h entry after a 5m one, which Anthropic rejects.
78
+ * With no explicit non-1h TTL every breakpoint ends up 1h, so ordering stays valid. The body is
79
+ * copied on write: the caller's object graph is never mutated.
80
+ */
81
+ export function applyAnthropicNativeCacheTtlDefault(body: Rec, retention: AnthropicCacheRetention): Rec {
82
+ if (retention !== "long") return body;
83
+ const ttls = collectAnthropicCacheTtls(body);
84
+ if (!ttls.includes(undefined)) return body;
85
+ if (ttls.some(ttl => ttl !== undefined && ttl !== "1h")) return body;
86
+ const upgrade = (node: unknown, depth: number): unknown => {
87
+ if (depth > MAX_DEPTH) return node;
88
+ if (Array.isArray(node)) {
89
+ let changed = false;
90
+ const out = node.map(item => {
91
+ const next = upgrade(item, depth + 1);
92
+ if (next !== item) changed = true;
93
+ return next;
94
+ });
95
+ return changed ? out : node;
96
+ }
97
+ if (!isRec(node)) return node;
98
+ let out: Rec | undefined;
99
+ if (isRec(node.cache_control) && node.cache_control.ttl === undefined) {
100
+ out = { ...node, cache_control: { ...node.cache_control, ttl: "1h" } };
101
+ }
102
+ for (const [key, value] of Object.entries(node)) {
103
+ if (isDataKey(key) || !(Array.isArray(value) || isRec(value))) continue;
104
+ const next = upgrade(value, depth + 1);
105
+ if (next !== value) (out ??= { ...node })[key] = next;
106
+ }
107
+ return out ?? node;
108
+ };
109
+ const out: Rec = { ...body };
110
+ if (isRec(body.cache_control) && body.cache_control.ttl === undefined) {
111
+ out.cache_control = { ...body.cache_control, ttl: "1h" };
112
+ }
113
+ for (const key of ["system", "tools", "messages"] as const) {
114
+ if (body[key] !== undefined) out[key] = upgrade(body[key], 0);
115
+ }
116
+ return out;
117
+ }
@@ -32,6 +32,7 @@ import { bindAnthropicAccountMetadata } from "./account-metadata";
32
32
  import { shouldPreserveNativeClientPreamble } from "./native-client-preamble";
33
33
  import { allowlistAnthropicBetas } from "./beta-allowlist";
34
34
  import { pairAnthropicBetaBody } from "./beta-body-pairs";
35
+ import { applyAnthropicNativeCacheTtlDefault, resolveAnthropicCacheRetention } from "./cache-retention";
35
36
  export { contextManagementForWire } from "./beta-body-pairs";
36
37
 
37
38
  /**
@@ -268,14 +269,14 @@ export function anthropicMessagesNativeWireBody(
268
269
  /**
269
270
  * Build the upstream request. Throws the adapter's own errors for a missing credential or a
270
271
  * malformed or unresolved base URL, and refuses an OAuth credential for any destination other
271
- * than first-party Anthropic. `config` is accepted for parity with the other passthrough
272
- * builders; no config key changes the wire today.
272
+ * than first-party Anthropic. `config.cacheRetention` decides the TTL of caller breakpoints
273
+ * that carry none (see applyAnthropicNativeCacheTtlDefault).
273
274
  */
274
275
  export function buildAnthropicMessagesPassthroughRequest(
275
276
  provider: OcxProviderConfig,
276
277
  modelId: string,
277
278
  body: Readonly<Record<string, unknown>>,
278
- _config?: OcxConfig,
279
+ config?: OcxConfig,
279
280
  options: AnthropicMessagesPassthroughOptions = {},
280
281
  ): AnthropicMessagesPassthroughRequest {
281
282
  const oauth = provider.authMode === "oauth";
@@ -294,7 +295,9 @@ export function buildAnthropicMessagesPassthroughRequest(
294
295
  const url = resolveAnthropicMessagesUrl(provider);
295
296
  const native = anthropicMessagesNativeWireBody(provider, modelId, body, options);
296
297
  const { strippedOpaqueState, oauthToolNames } = native;
297
- const wireBody = oauth ? bindAnthropicAccountMetadata(native.wireBody, options.providerAccountUuid) : native.wireBody;
298
+ const ttlBody = applyAnthropicNativeCacheTtlDefault(
299
+ native.wireBody, resolveAnthropicCacheRetention(config?.cacheRetention, provider));
300
+ const wireBody = oauth ? bindAnthropicAccountMetadata(ttlBody, options.providerAccountUuid) : ttlBody;
298
301
  const headers = anthropicBaseRequestHeaders(wireBody.stream === true);
299
302
  if (oauth) applyAnthropicOAuthAuth(headers, provider.apiKey);
300
303
  else applyAnthropicKeyAuth(headers, provider);
@@ -35,6 +35,7 @@ import { decodeServerSentEvents } from "../lib/sse-decoder";
35
35
  import { isTranslatorBudgetExceededError, retainTranslatedEventBatch, type TranslatorBudget } from "../lib/translator-budget";
36
36
  import { isReasoningEffortOmitted, modelRecordValue } from "../reasoning-effort";
37
37
  import { applyAgentRouterLanguageFraming, isAgentRouterEndpoint } from "./agentrouter";
38
+ import { anthropicCacheWrite1hTokens, resolveAnthropicCacheRetention, type AnthropicCacheRetention } from "./anthropic/cache-retention";
38
39
  import { claudeFamilyVersion, rejectsCombinedSampling, rejectsForcedToolChoice, rejectsSamplingParameters, supportsExplicitThinkingDisable, usesAdaptiveThinking, usesBetweenToolsFloor } from "./anthropic-model-contract";
39
40
 
40
41
  /** Map a user content part to an Anthropic content block (text or image source). */
@@ -76,8 +77,12 @@ const COMPAT_TOOL_PREFIX = "cx_";
76
77
  type CacheControl = { type: "ephemeral"; ttl?: "1h" | "5m" };
77
78
  const MAX_CACHE_BREAKPOINTS = 4;
78
79
 
79
- function resolveCacheControl(retention: "none" | "short" | "long" | undefined): CacheControl | undefined {
80
- const r = retention ?? "short";
80
+ /** Omitted retention follows the destination default (1h on first-party Anthropic, else 5m). */
81
+ function resolveCacheControl(
82
+ retention: AnthropicCacheRetention | undefined,
83
+ provider: OcxProviderConfig,
84
+ ): CacheControl | undefined {
85
+ const r = resolveAnthropicCacheRetention(retention, provider);
81
86
  if (r === "none") return undefined;
82
87
  return r === "long" ? { type: "ephemeral", ttl: "1h" } : { type: "ephemeral" };
83
88
  }
@@ -643,6 +648,7 @@ function usageFromAnthropic(usage: unknown): OcxUsage | undefined {
643
648
  // estimate from visible summaries. Invalid optional detail leaves totals intact.
644
649
  const thinking = isAnthropicRecord(usage.output_tokens_details) ? usage.output_tokens_details.thinking_tokens : undefined;
645
650
  const reasoningOutputTokens = typeof thinking === "number" && Number.isFinite(thinking) && thinking >= 0 && thinking <= output ? thinking : undefined;
651
+ const write1h = anthropicCacheWrite1hTokens(usage, write);
646
652
  return {
647
653
  inputTokens,
648
654
  outputTokens: output,
@@ -651,6 +657,7 @@ function usageFromAnthropic(usage: unknown): OcxUsage | undefined {
651
657
  cachedInputTokens: read,
652
658
  cacheReadInputTokens: read,
653
659
  cacheCreationInputTokens: write,
660
+ ...(write1h !== undefined ? { cacheCreation1hInputTokens: write1h } : {}),
654
661
  } : {}),
655
662
  };
656
663
  }
@@ -1223,7 +1230,7 @@ export function createAnthropicAdapter(provider: OcxProviderConfig, cacheRetenti
1223
1230
 
1224
1231
  // Prompt caching: native Anthropic supports top-level automatic caching, which
1225
1232
  // follows the moving final block across turns. Keep one breakpoint slot free for it.
1226
- const cc = resolveCacheControl(cacheRetention);
1233
+ const cc = resolveCacheControl(cacheRetention, provider);
1227
1234
  const automaticPromptCaching = cc && usesNativeAnthropicEndpoint(provider);
1228
1235
  if (automaticPromptCaching) body.cache_control = cc;
1229
1236
  const explicitLimit = automaticPromptCaching ? MAX_CACHE_BREAKPOINTS - 1 : MAX_CACHE_BREAKPOINTS;
@@ -14,6 +14,8 @@ export interface IncomingMeta {
14
14
  abortSignal?: AbortSignal;
15
15
  /** Lease acquired before the response is committed; the physical send transfers it to its body. */
16
16
  pacingSlot?: ProviderRequestSlot;
17
+ /** Internal queued rebuild already owns the outer provider fetch admission. */
18
+ dispatchPacingHeld?: boolean;
17
19
  /** Combo children must surface a pre-output refusal so the selector can try the next target. */
18
20
  comboAttempt?: boolean;
19
21
  /**
@@ -127,6 +129,8 @@ export interface AdapterRequest {
127
129
  method: string;
128
130
  headers: Record<string, string>;
129
131
  body: string;
132
+ /** Exact final wire model, captured before serialization for model-scoped transport gates. */
133
+ outboundModelId?: string;
130
134
  /** Final upstream wire names of custom tools lowered to functions while building this request. */
131
135
  convertedRoutedCustomToolNames?: ReadonlySet<string>;
132
136
  /** Native custom-tool wire names authorized for representation-only response repair. */
@@ -15,7 +15,7 @@ import {
15
15
  CODEBUDDY_TOOL_LIMITS,
16
16
  } from "../codebuddy/tool-bridge";
17
17
  import { CLAUDE_CLI_PROFILES, type ClaudeCliProfile } from "./profiles";
18
- import { checkClaudeUsageAdmission, recordClaudeUsageRefusal, type ClaudeAdmission } from "./usage-admission";
18
+ import { checkClaudeUsageAdmission, containsClaudeResetClock, recordClaudeUsageRefusal, type ClaudeAdmission } from "./usage-admission";
19
19
  import { buildStableClaudeConversationInput, CLAUDE_REPLAY_SYSTEM_PROMPT, stableClaudeToolBridge } from "./stable-replay";
20
20
 
21
21
  // The coding-agent bridge is protocol-level infrastructure shared with CodeBuddy. Its MCP server
@@ -286,12 +286,18 @@ export function createClaudeCliAdapter(provider: OcxProviderConfig, deps: Claude
286
286
  provider,
287
287
  parsed,
288
288
  incoming,
289
- emit: withClaudeLoginHint(event => {
290
- if (event.type === "error") {
291
- void Promise.resolve((deps.usageRefusal ?? recordClaudeUsageRefusal)(event.message)).catch(() => {});
292
- }
293
- emit(event);
294
- }),
289
+ emit: withClaudeLoginHint(emit),
290
+ onCliOutputError: message => {
291
+ // The model id is caller input that reaches the CLI verbatim, and the CLI may reflect it
292
+ // inside its own error wording. When the model id itself carries the reset-clock
293
+ // phrase the refusal parser honors, a parsed reset cannot be attributed to the
294
+ // account — it may be the model string echoed back rather than a limit Claude
295
+ // reported — so this turn's output records nothing. The error still reaches the
296
+ // client and limits the preflight already knows still gate; a genuine limit seen
297
+ // only on such a turn is delivered but deliberately not cached.
298
+ if (containsClaudeResetClock(parsed.modelId)) return;
299
+ void Promise.resolve().then(() => (deps.usageRefusal ?? recordClaudeUsageRefusal)(message)).catch(() => {});
300
+ },
295
301
  ...(toolBridge ? { toolBridge } : {}),
296
302
  conversationInput: buildStableClaudeConversationInput,
297
303
  buildArgs: (profile, req, prov) => buildArgs(profile as ClaudeCliProfile, req, prov, promptFile),
@@ -188,11 +188,23 @@ export function claudeUsagePreflight(model: string): Promise<ClaudeAdmission> {
188
188
  return (preflightOverride ?? checkClaudeUsageAdmission)(model);
189
189
  }
190
190
 
191
+ // Claude prints "resets 3pm (Europe/Paris)" or "resets 3:30pm (...)"; minutes are optional.
192
+ const CLAUDE_RESET_CLOCK = /resets?\s+(?:at\s+)?(\d{1,2})(?::(\d{2}))?\s*(am|pm)\s*\(([^)]+)\)/i;
193
+
194
+ /**
195
+ * Whether text carries the reset-clock wording the refusal parser honors. The check is lexical
196
+ * only — no "limit" keyword and no clock resolution against the current time — because the phrase
197
+ * matters wherever it appears: a caller-controlled model id can carry the clock while the CLI's
198
+ * own error wording supplies the limit keyword around it.
199
+ */
200
+ export function containsClaudeResetClock(text: string): boolean {
201
+ return CLAUDE_RESET_CLOCK.test(text);
202
+ }
203
+
191
204
  /** Parse Claude's explicit next-clock reset, including its IANA timezone. */
192
205
  export function parseClaudeReset(message: string, now = Date.now()): number | undefined {
193
206
  if (!/hit.*limit|usage limit|rate limit/i.test(message)) return;
194
- // Claude prints "resets 3pm (Europe/Paris)" or "resets 3:30pm (...)"; minutes are optional.
195
- const match = /resets?\s+(?:at\s+)?(\d{1,2})(?::(\d{2}))?\s*(am|pm)\s*\(([^)]+)\)/i.exec(message);
207
+ const match = CLAUDE_RESET_CLOCK.exec(message);
196
208
  if (!match) return;
197
209
  const hour = Number(match[1]); const minute = Number(match[2] ?? 0);
198
210
  if (hour < 1 || hour > 12 || minute > 59) return;
@@ -1,6 +1,7 @@
1
1
  import { namespacedToolName, type AdapterEvent, type OcxMessage, type OcxParsedRequest, type OcxUsage } from "../../types";
2
2
  import type { TranslatorBudget } from "../../lib/translator-budget";
3
3
  import { isValidCodingAgentToolNamePart } from "./tool-catalog";
4
+ import { anthropicCacheWrite1hTokens } from "../anthropic/cache-retention";
4
5
 
5
6
  /**
6
7
  * Shared stream-json protocol for official coding-agent CLIs (CodeBuddy Code and Qoder CLI).
@@ -165,6 +166,7 @@ function usageFromAnthropicShape(usage: Record<string, unknown>): OcxUsage | und
165
166
  // that could carry those tokens instead, so the turn under-reported usage and cost.
166
167
  const cacheReadTotal = count(usage.cache_read_input_tokens);
167
168
  const cacheCreationTotal = count(usage.cache_creation_input_tokens);
169
+ const cacheCreation1h = anthropicCacheWrite1hTokens(usage, cacheCreationTotal);
168
170
  const inputTokens = freshInputTokens + cacheReadTotal + cacheCreationTotal;
169
171
  if (inputTokens === 0 && outputTokens === 0 && cacheReadTotal === 0 && cacheCreationTotal === 0) {
170
172
  return undefined;
@@ -175,6 +177,7 @@ function usageFromAnthropicShape(usage: Record<string, unknown>): OcxUsage | und
175
177
  totalTokens: inputTokens + outputTokens,
176
178
  ...(cacheReadTotal > 0 ? { cachedInputTokens: cacheReadTotal, cacheReadInputTokens: cacheReadTotal } : {}),
177
179
  ...(cacheCreationTotal > 0 ? { cacheCreationInputTokens: cacheCreationTotal } : {}),
180
+ ...(cacheCreationTotal > 0 && cacheCreation1h !== undefined ? { cacheCreation1hInputTokens: cacheCreation1h } : {}),
178
181
  };
179
182
  }
180
183
 
@@ -204,6 +207,8 @@ function mergePartialUsage(previous: OcxUsage | undefined, next: OcxUsage): OcxU
204
207
  next.cacheReadInputTokens ?? next.cachedInputTokens ?? 0,
205
208
  );
206
209
  const cacheCreation = Math.max(previous.cacheCreationInputTokens ?? 0, next.cacheCreationInputTokens ?? 0);
210
+ const cacheCreation1h = Math.min(cacheCreation,
211
+ Math.max(previous.cacheCreation1hInputTokens ?? 0, next.cacheCreation1hInputTokens ?? 0));
207
212
  // Inclusive inputs: fold each snapshot's fresh part, then add the folded cache counters once.
208
213
  const freshInput = (usage: OcxUsage) => Math.max(0, usage.inputTokens
209
214
  - (usage.cacheReadInputTokens ?? usage.cachedInputTokens ?? 0) - (usage.cacheCreationInputTokens ?? 0));
@@ -214,6 +219,7 @@ function mergePartialUsage(previous: OcxUsage | undefined, next: OcxUsage): OcxU
214
219
  totalTokens: inputTokens + outputTokens,
215
220
  ...(cacheRead > 0 ? { cachedInputTokens: cacheRead, cacheReadInputTokens: cacheRead } : {}),
216
221
  ...(cacheCreation > 0 ? { cacheCreationInputTokens: cacheCreation } : {}),
222
+ ...(cacheCreation1h > 0 ? { cacheCreation1hInputTokens: cacheCreation1h } : {}),
217
223
  };
218
224
  }
219
225
 
@@ -121,6 +121,8 @@ export interface CodingAgentTurnInput {
121
121
  parsed: OcxParsedRequest;
122
122
  incoming: IncomingMeta;
123
123
  emit: (event: AdapterEvent) => void;
124
+ /** Observes accepted CLI result/stderr failures, before client-side error decoration. */
125
+ onCliOutputError?: (message: string) => void;
124
126
  /** Family-specific headless argument builder (tools disabled, model, reasoning, system prompt). */
125
127
  buildArgs: (profile: CodingAgentProviderProfile, parsed: OcxParsedRequest, provider: OcxProviderConfig) => string[];
126
128
  /** Family-specific scoped env builder (credential + region switch on top of baseScopedEnv). */
@@ -368,11 +370,18 @@ export async function runCodingAgentTurn(input: CodingAgentTurnInput): Promise<v
368
370
  });
369
371
 
370
372
  let terminalEmitted = false;
371
- const emitOnce = (event: AdapterEvent): void => {
373
+ const emitOnce = (event: AdapterEvent, cliOutputError?: string): void => {
372
374
  if (event.type === "done" || event.type === "error" || event.type === "incomplete") {
373
375
  if (terminalEmitted) return;
374
376
  terminalEmitted = true;
375
377
  }
378
+ if (event.type === "error" && cliOutputError !== undefined) {
379
+ try {
380
+ input.onCliOutputError?.(cliOutputError);
381
+ } catch {
382
+ // An observer failure must never drop the client's terminal event or turn it into a rejection.
383
+ }
384
+ }
376
385
  emit(event);
377
386
  };
378
387
 
@@ -648,7 +657,8 @@ export async function runCodingAgentTurn(input: CodingAgentTurnInput): Promise<v
648
657
  }
649
658
  emitOnce(event.type === "error"
650
659
  ? { ...event, message: redactSecrets(event.message, profile.tokenEnv, apiKey) }
651
- : event);
660
+ : event, event.type === "error" && message.type === "result"
661
+ ? redactSecrets(event.message, profile.tokenEnv, apiKey) : undefined);
652
662
  }
653
663
  if (failClosed) break;
654
664
  const sawToolTurnStop = sawSelectedToolTurnStop();
@@ -762,7 +772,7 @@ export async function runCodingAgentTurn(input: CodingAgentTurnInput): Promise<v
762
772
  };
763
773
  emitOnce(input.classifyFailure
764
774
  ? input.classifyFailure({ source: "process-exit", exitCode: child.exitCode, stderr, error, profile })
765
- : error);
775
+ : error, stderr || undefined);
766
776
  } else if (toolBridge && deferredResultDone !== undefined && !sawSelectedToolTurnStop()) {
767
777
  emitOnce({
768
778
  type: "error",
@@ -783,7 +793,7 @@ export async function runCodingAgentTurn(input: CodingAgentTurnInput): Promise<v
783
793
  errorType: "upstream_error",
784
794
  code: "protocol_error",
785
795
  retryable: false,
786
- });
796
+ }, stderr || undefined);
787
797
  }
788
798
  }
789
799
  } finally {
@@ -869,6 +869,9 @@ function decodeResultParts(message: OcxToolResultMessage): DecodedResultPart[] |
869
869
  // Without this the document falls through to decodeInlineImage(part.imageUrl) below and is
870
870
  // treated as an image it is not.
871
871
  if (part.type === "document") return { kind: "text", text: part.text };
872
+ // The translated-adapter guard rejects audio before this wire; retain its marker if this
873
+ // decoder is ever called directly.
874
+ if (part.type === "audio") return { kind: "text", text: part.text };
872
875
  const decoded = decodeInlineImage(part.imageUrl);
873
876
  return decoded ? { kind: "image", ...decoded } : { kind: "undecodable" };
874
877
  });
@@ -1,3 +1,4 @@
1
+ import { inheritAccountAutoPauseResponse } from "../lib/account-auto-pause-response";
1
2
  import type { AdapterFetchContext, AdapterRequest } from "./base";
2
3
  import { createAdapterPhysicalSend } from "./physical-send";
3
4
  import type { SendClass } from "../lib/request-execution-budget";
@@ -38,10 +39,10 @@ async function normalizeFinalGoogleError(label: string, res: Response, signal?:
38
39
  const headers = new Headers(res.headers);
39
40
  headers.delete("content-encoding");
40
41
  headers.delete("content-length");
41
- return new Response(safeGoogleHttpErrorMessage(label, res.status,
42
+ return inheritAccountAutoPauseResponse(res, new Response(safeGoogleHttpErrorMessage(label, res.status,
42
43
  body.displaySafe && !body.truncated ? body.text : ""), {
43
44
  status: res.status, statusText: res.statusText, headers,
44
- });
45
+ }));
45
46
  }
46
47
  return normalizeUpstreamHttpErrorResponse(res, {
47
48
  signal,
@@ -27,6 +27,7 @@ const SENTENCE_END = /[.!?]["'\u201D\u2019)\]*_`]*(?=\s|$)|[\u3002\uFF01\uFF1F\u
27
27
 
28
28
  /** A boundary that only closes a leading list marker ("1.", "a.") or a common abbreviation ("e.g."). */
29
29
  const NOT_A_SENTENCE = /^(?:\d{1,3}|[a-z])\.$|(?:^|\s)(?:e\.g|i\.e|etc|vs)\.$/i;
30
+ const WHITESPACE = /\s/;
30
31
 
31
32
  /** Whether replayed progress text for this model is trimmed to its lead sentence. */
32
33
  export function trimsGeminiProgressHistory(modelId: string): boolean {
@@ -42,9 +43,26 @@ export function geminiProgressLead(text: string): string | undefined {
42
43
  if (trimmed.length === 0) return undefined;
43
44
  SENTENCE_END.lastIndex = 0;
44
45
  let end = trimmed.length;
46
+ let checked = 0;
47
+ let contentEnd = 0;
45
48
  for (let match = SENTENCE_END.exec(trimmed); match; match = SENTENCE_END.exec(trimmed)) {
46
49
  const boundary = match.index + match[0].length;
47
- if (!NOT_A_SENTENCE.test(trimmed.slice(0, boundary).trim())) { end = boundary; break; }
50
+ // Only a newline boundary can end in whitespace. Scan its new interval once; repeated
51
+ // blank lines retain the previous content end without rescanning the preceding text.
52
+ if (match[0] === "\n") {
53
+ for (let index = checked; index < boundary; index++) {
54
+ if (!WHITESPACE.test(trimmed[index])) contentEnd = index + 1;
55
+ }
56
+ } else {
57
+ contentEnd = boundary;
58
+ }
59
+ checked = boundary;
60
+ // The longest exception is four characters plus its preceding whitespace. The list
61
+ // marker alternative is anchored to the whole prefix, so allow it only at the start.
62
+ const start = Math.max(0, contentEnd - 5);
63
+ const suffix = trimmed.slice(start, contentEnd);
64
+ const exception = NOT_A_SENTENCE.exec(suffix);
65
+ if (!exception || (exception.index === 0 && start > 0 && !/^\s/.test(suffix))) { end = boundary; break; }
48
66
  }
49
67
  const lead = trimmed.slice(0, end).trim();
50
68
  // A code-fence opener is not a sentence; replaying it alone would leave an unclosed fence.
@@ -0,0 +1,67 @@
1
+ import { googleVertexLocationConfigError } from "../providers/google-vertex-location";
2
+
3
+ /**
4
+ * Vertex endpoint selection, shared by inference and replay identity.
5
+ *
6
+ * API keys follow explicit provider configuration only: `provider.project` selects the project
7
+ * endpoint (location defaults to `global`), otherwise the projectless express endpoint is used.
8
+ * Ambient GOOGLE_CLOUD_PROJECT / GCLOUD_PROJECT / GOOGLE_CLOUD_LOCATION belong to ADC, so an
9
+ * unrelated gcloud default in the shell cannot move an express-mode key onto another project.
10
+ */
11
+ export type VertexEndpointSelection =
12
+ | { kind: "express" }
13
+ | { kind: "project"; project: string; location: string };
14
+
15
+ type VertexEndpointConfig = { project?: string; location?: string };
16
+
17
+ export function selectVertexEndpoint(
18
+ provider: VertexEndpointConfig,
19
+ hasApiKey: boolean,
20
+ env: NodeJS.ProcessEnv = process.env,
21
+ ): VertexEndpointSelection {
22
+ // A blank or whitespace-only project is unset: it must not select a /projects/%20/ endpoint.
23
+ const configuredProject = provider.project?.trim() || undefined;
24
+ if (hasApiKey) {
25
+ if (!configuredProject) return { kind: "express" };
26
+ return { kind: "project", project: configuredProject, location: provider.location || "global" };
27
+ }
28
+ const project = configuredProject || env.GOOGLE_CLOUD_PROJECT || env.GCLOUD_PROJECT;
29
+ if (!project) throw new Error("Vertex AI requires a project id (provider.project or GOOGLE_CLOUD_PROJECT/GCLOUD_PROJECT).");
30
+ const location = provider.location || env.GOOGLE_CLOUD_LOCATION;
31
+ if (!location) throw new Error("Vertex AI requires a location (provider.location or GOOGLE_CLOUD_LOCATION).");
32
+ return { kind: "project", project, location };
33
+ }
34
+
35
+ /**
36
+ * Replay namespace for thought-signature continuation; mirrors the endpoint actually used.
37
+ * The endpoint kind is part of the key and the project is encoded, so no configured project
38
+ * (for example one literally named "api-key" or containing ":") can share express mode's space.
39
+ */
40
+ export function vertexReplayModelKey(selection: VertexEndpointSelection, modelId: string): string {
41
+ return selection.kind === "express"
42
+ ? `vertex:express:${modelId}`
43
+ : `vertex:project:${encodeURIComponent(selection.project)}:${selection.location}:${modelId}`;
44
+ }
45
+
46
+ const VERTEX_MODEL_PATH_REJECT = /[/?#\\%]/;
47
+
48
+ /** The model id is interpolated as one URL path segment after a fixed Google authority. */
49
+ export function vertexModelPathError(modelId: string): string | undefined {
50
+ if (!modelId || VERTEX_MODEL_PATH_REJECT.test(modelId) || modelId.includes("..")) {
51
+ return "Vertex AI model id must be a single path segment without '/', '?', '#', '\\', '%' or '..'.";
52
+ }
53
+ return undefined;
54
+ }
55
+
56
+ /** Builds the inference URL for a selection; validates location before any authority is formed. */
57
+ export function vertexInferenceUrl(selection: VertexEndpointSelection, modelId: string, method: string, streamParam: string): string {
58
+ const modelError = vertexModelPathError(modelId);
59
+ if (modelError) throw new Error(modelError);
60
+ if (selection.kind === "express") {
61
+ return `https://aiplatform.googleapis.com/v1/publishers/google/models/${modelId}:${method}${streamParam}`;
62
+ }
63
+ const locationError = googleVertexLocationConfigError(selection.location);
64
+ if (locationError) throw new Error(locationError);
65
+ const host = selection.location === "global" ? "aiplatform.googleapis.com" : `${selection.location}-aiplatform.googleapis.com`;
66
+ return `https://${host}/v1/projects/${encodeURIComponent(selection.project)}/locations/${selection.location}/publishers/google/models/${modelId}:${method}${streamParam}`;
67
+ }