@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.
- package/README.md +11 -1
- package/bin/ocx.mjs +15 -4
- package/gui/dist/assets/App-DgxkE6Md.js +58 -0
- package/gui/dist/assets/App-dnkJ85te.css +1 -0
- package/gui/dist/assets/{Tray-B5bC7AWL.js → Tray-DbTNc_88.js} +1 -1
- package/gui/dist/assets/{index-B5bsvxor.js → index-TmaHa54u.js} +15 -15
- package/gui/dist/assets/quota-summary-B16x5DZZ.js +1 -0
- package/gui/dist/index.html +1 -1
- package/package.json +2 -2
- package/src/adapters/anthropic/cache-retention.ts +117 -0
- package/src/adapters/anthropic/passthrough.ts +7 -4
- package/src/adapters/anthropic.ts +10 -3
- package/src/adapters/base.ts +4 -0
- package/src/adapters/claude-cli/adapter.ts +13 -7
- package/src/adapters/claude-cli/usage-admission.ts +14 -2
- package/src/adapters/coding-agent/protocol.ts +6 -0
- package/src/adapters/coding-agent/turn.ts +14 -4
- package/src/adapters/cursor/protobuf-request.ts +3 -0
- package/src/adapters/google-http.ts +3 -2
- package/src/adapters/google-progress-history.ts +19 -1
- package/src/adapters/google-vertex-endpoint.ts +67 -0
- package/src/adapters/google.ts +62 -37
- package/src/adapters/image.ts +5 -3
- package/src/adapters/input-media-guard.ts +5 -2
- package/src/adapters/kiro-refusal.ts +41 -1
- package/src/adapters/ollama-native.ts +1 -0
- package/src/adapters/openai-chat/messages.ts +34 -4
- package/src/adapters/openai-chat/passthrough.ts +37 -4
- package/src/adapters/openai-chat/reasoning-replay.ts +98 -13
- package/src/adapters/openai-chat/serialized-tool-call-content.ts +95 -134
- package/src/adapters/openai-chat/serialized-tool-call-markup.ts +108 -0
- package/src/adapters/openai-chat/standalone-bare-tool-calls.ts +136 -0
- package/src/adapters/openai-chat.ts +7 -6
- package/src/adapters/openai-responses/compaction-search-history.ts +27 -0
- package/src/adapters/openai-responses/opengateway-input.ts +139 -0
- package/src/adapters/openai-responses/passthrough.ts +22 -13
- package/src/adapters/openai-responses/reasoning.ts +68 -1
- package/src/adapters/openai-responses/transport.ts +13 -1
- package/src/adapters/registry.ts +1 -1
- package/src/adapters/upstream-http-error.ts +3 -2
- package/src/adapters/zed.ts +7 -4
- package/src/bridge/internal.ts +11 -1
- package/src/bridge/response-json.ts +2 -2
- package/src/bridge/sse.ts +10 -4
- package/src/claude/desktop-3p-library.ts +43 -3
- package/src/claude/desktop-3p.ts +20 -10
- package/src/claude/desktop-picker-profile.ts +18 -9
- package/src/claude/desktop-remote-store-io.ts +2 -2
- package/src/claude/inbound.ts +12 -26
- package/src/claude/outbound.ts +5 -0
- package/src/cli/account-api.ts +13 -1
- package/src/cli/account-extended.ts +17 -5
- package/src/cli/account-key-quota.ts +4 -1
- package/src/cli/account.ts +1 -1
- package/src/cli/capabilities-agents-routing.ts +45 -8
- package/src/cli/capabilities-base.ts +5 -5
- package/src/cli/capabilities-provider-models.ts +5 -4
- package/src/cli/combo-result.ts +8 -2
- package/src/cli/combo.ts +17 -0
- package/src/cli/ensure-desktop-cold-start.ts +2 -2
- package/src/cli/help.ts +1 -1
- package/src/cli/message-command.ts +4 -1
- package/src/cli/message-remote-args.ts +69 -0
- package/src/cli/message-remote-command.ts +77 -0
- package/src/cli/provider-runtime.ts +69 -1
- package/src/cli/registry.ts +3 -3
- package/src/codex/account-lifecycle.ts +19 -6
- package/src/codex/account-pause.ts +6 -1
- package/src/codex/account-runtime-state.ts +5 -0
- package/src/codex/account-store.ts +55 -9
- package/src/codex/account-usability.ts +4 -1
- package/src/codex/auth-api/account-list.ts +13 -5
- package/src/codex/auth-api/account-pause-group.ts +2 -22
- package/src/codex/auth-api/login-collision.ts +59 -0
- package/src/codex/auth-api/login-flow.ts +12 -7
- package/src/codex/auth-api/main-account-probe.ts +3 -2
- package/src/codex/auth-api/pool-mode-gate.ts +81 -13
- package/src/codex/auth-collision.ts +31 -4
- package/src/codex/auth-context.ts +57 -10
- package/src/codex/catalog/aggregation.ts +15 -0
- package/src/codex/catalog/auto-review.ts +2 -1
- package/src/codex/catalog/build-entries.ts +17 -7
- package/src/codex/catalog/derive-entry.ts +3 -1
- package/src/codex/catalog/metadata.ts +2 -0
- package/src/codex/catalog/model-visibility.ts +0 -2
- package/src/codex/catalog/ownership.ts +71 -0
- package/src/codex/catalog/parsing.ts +12 -3
- package/src/codex/catalog/retained-sync.ts +2 -1
- package/src/codex/catalog/routed-removal.ts +4 -4
- package/src/codex/cli-update-plan.ts +18 -3
- package/src/codex/collision-identity.ts +78 -0
- package/src/codex/convergence.ts +2 -1
- package/src/codex/low-quota-desktop-notifier.ts +125 -0
- package/src/codex/low-quota-protection.ts +57 -31
- package/src/codex/main-account-cache.ts +77 -3
- package/src/codex/main-account-hard-lock.ts +14 -0
- package/src/codex/main-account.ts +6 -2
- package/src/codex/native-residue.ts +2 -3
- package/src/codex/quota.ts +26 -2
- package/src/codex/routing/cooldown-math.ts +5 -0
- package/src/codex/routing/failure-window.ts +61 -9
- package/src/codex/routing.ts +4 -3
- package/src/codex/shim-diagnostics.ts +2 -1
- package/src/codex/shim-fingerprint.ts +11 -2
- package/src/codex/shim-templates.ts +16 -5
- package/src/codex/shim-windows-refresh.ts +224 -0
- package/src/codex/shim.ts +45 -21
- package/src/combos/failover.ts +10 -2
- package/src/combos/jev-model-backend.ts +30 -7
- package/src/combos/jev-model-request.ts +20 -0
- package/src/combos/jev-quota-activation.ts +153 -0
- package/src/combos/jev-quota-config.ts +62 -0
- package/src/combos/jev-quota-route.ts +26 -0
- package/src/combos/jev-quota.ts +88 -0
- package/src/combos/jev.ts +25 -12
- package/src/combos/types.ts +27 -0
- package/src/compatibility/index.ts +3 -0
- package/src/compatibility/openai-responses.ts +8 -1
- package/src/compatibility/opengateway-responses.ts +61 -0
- package/src/config/account-auto-pause-revisions.ts +136 -0
- package/src/config/diagnostics.ts +13 -0
- package/src/config/live-reconcile.ts +9 -0
- package/src/config/persist-unlocked.ts +10 -1
- package/src/config/provider-validation.ts +7 -2
- package/src/config/removed-opencode-free.ts +135 -0
- package/src/config/schema/account-auto-pause.ts +14 -0
- package/src/config/schema/config-schema.ts +15 -0
- package/src/config/schema/leaf-validators.ts +7 -0
- package/src/config.ts +10 -3
- package/src/generated/compatibility-version.json +476 -216
- package/src/generated/model-metadata.ts +1 -1
- package/src/images/loop.ts +34 -11
- package/src/lib/account-auto-pause-response.ts +16 -0
- package/src/lib/bun-runtime.ts +18 -1
- package/src/lib/bun-transpiler-cache-scope.d.mts +8 -0
- package/src/lib/bun-transpiler-cache-scope.mjs +82 -0
- package/src/lib/decision-quota-sink.ts +76 -0
- package/src/lib/provider-admission-wait.ts +14 -0
- package/src/lib/service-secrets.ts +37 -2
- package/src/lib/state-store-registrations.ts +25 -0
- package/src/lib/translator-budget.ts +1 -1
- package/src/lib/upstream-retry.ts +15 -0
- package/src/link/ssh-argv.ts +3 -0
- package/src/messaging/envelope.ts +6 -3
- package/src/messaging/remote-auth.ts +83 -0
- package/src/messaging/remote-bridge.ts +270 -0
- package/src/messaging/remote-contract.ts +108 -0
- package/src/messaging/remote-enrollment-recovery.ts +59 -0
- package/src/messaging/remote-enrollment.ts +244 -0
- package/src/messaging/remote-envelope.ts +40 -0
- package/src/messaging/remote-files.ts +117 -0
- package/src/messaging/remote-owner.ts +169 -0
- package/src/messaging/remote-ports.ts +56 -0
- package/src/messaging/remote-process.ts +131 -0
- package/src/messaging/remote-replies.ts +98 -0
- package/src/messaging/remote-rpc-admission.ts +32 -0
- package/src/messaging/remote-send.ts +72 -0
- package/src/messaging/remote-store.ts +111 -0
- package/src/messaging/remote-tunnels.ts +65 -0
- package/src/messaging/rpc.ts +13 -1
- package/src/oauth/account-auto-pause-policy.ts +66 -0
- package/src/oauth/account-auto-pause.ts +171 -0
- package/src/oauth/account-import/google-antigravity-adapter.ts +38 -2
- package/src/oauth/account-import/parser.ts +15 -2
- package/src/oauth/account-import/types.ts +7 -0
- package/src/oauth/account-quota-rank.ts +2 -1
- package/src/oauth/anthropic-account-refusal.ts +6 -0
- package/src/oauth/anthropic-model-family.ts +8 -0
- package/src/oauth/anthropic-model-quota.ts +2 -6
- package/src/oauth/api-key-pool-preserve.ts +37 -0
- package/src/oauth/chatgpt-shared.ts +10 -1
- package/src/oauth/dsh.ts +45 -2
- package/src/oauth/index.ts +5 -35
- package/src/oauth/kiro.ts +44 -1
- package/src/oauth/login-flow-state.ts +11 -2
- package/src/oauth/store.ts +35 -8
- package/src/oauth/types.ts +2 -0
- package/src/plugins/upstream-hooks.ts +14 -1
- package/src/providers/api-key-pause.ts +32 -0
- package/src/providers/api-key-resolve.ts +10 -4
- package/src/providers/api-key-selection.ts +6 -1
- package/src/providers/api-keys.ts +8 -4
- package/src/providers/claude-cli-usage.ts +25 -5
- package/src/providers/initial-model-selection.ts +2 -2
- package/src/providers/key-failover.ts +21 -13
- package/src/providers/key-store.ts +8 -3
- package/src/providers/mistral-transport.ts +207 -0
- package/src/providers/model-rename-fields.ts +1 -0
- package/src/providers/openai-sidecar.ts +5 -0
- package/src/providers/opencode-zen-rate-limit.ts +6 -72
- package/src/providers/quota/account-cache.ts +15 -1
- package/src/providers/quota/anthropic-account-quota.ts +20 -7
- package/src/providers/quota/anthropic-cooldown-recovery.ts +22 -4
- package/src/providers/quota/anthropic-decision-windows.ts +47 -0
- package/src/providers/quota/antigravity.ts +45 -8
- package/src/providers/quota/failure-codes.ts +18 -0
- package/src/providers/quota/report-cache.ts +14 -0
- package/src/providers/quota/vendor-probes-oauth.ts +15 -6
- package/src/providers/quota-decision-publication.ts +77 -0
- package/src/providers/quota-decision-snapshot.ts +145 -0
- package/src/providers/quota-routing-cache.ts +4 -1
- package/src/providers/quota-types.ts +6 -1
- package/src/providers/quota.ts +8 -3
- package/src/providers/registry/entries-extended.ts +14 -53
- package/src/providers/registry/model-seeds.ts +1 -1
- package/src/providers/registry.ts +1 -2
- package/src/providers/routed-config.ts +1 -1
- package/src/providers/stale-vision-classification-migration.ts +1 -1
- package/src/providers/xai-transport.ts +2 -1
- package/src/responses/audio.ts +46 -0
- package/src/responses/input-media.ts +37 -15
- package/src/responses/parser-content.ts +22 -27
- package/src/responses/parser.ts +18 -10
- package/src/responses/reasoning-retention.ts +218 -11
- package/src/responses/schema.ts +3 -4
- package/src/responses/web-search-replay.ts +147 -0
- package/src/routing/compatibility/behavior.ts +4 -1
- package/src/server/auth-cors.ts +7 -0
- package/src/server/background-lifecycle.ts +2 -1
- package/src/server/chat-native.ts +36 -20
- package/src/server/claude-messages.ts +2 -1
- package/src/server/index/optional-listeners.ts +6 -0
- package/src/server/index/serve-options.ts +8 -2
- package/src/server/index/websocket-handler.ts +10 -0
- package/src/server/lifecycle.ts +17 -1
- package/src/server/management/combo-routes.ts +17 -2
- package/src/server/management/oauth-account-routes.ts +12 -2
- package/src/server/management/provider-completion-test.ts +289 -0
- package/src/server/management/provider-routes.ts +9 -1
- package/src/server/management/route-registry.ts +2 -0
- package/src/server/messages-native.ts +29 -4
- package/src/server/messages-shared.ts +4 -1
- package/src/server/request-log.ts +23 -9
- package/src/server/responses/account-auto-pause-recovery.ts +26 -0
- package/src/server/responses/adapter-continuation.ts +2 -2
- package/src/server/responses/adapter-dispatch.ts +79 -30
- package/src/server/responses/codex-ws-exchange.ts +3 -0
- package/src/server/responses/codex-ws-metadata.ts +44 -0
- package/src/server/responses/codex-ws-session.ts +21 -1
- package/src/server/responses/combo-session-recall.ts +25 -0
- package/src/server/responses/combo-stream-preflight.ts +10 -3
- package/src/server/responses/combo-tool-loop-pin.ts +70 -0
- package/src/server/responses/compact.ts +10 -5
- package/src/server/responses/context-overflow.ts +141 -2
- package/src/server/responses/core-auth.ts +20 -0
- package/src/server/responses/core-codex-account.ts +28 -15
- package/src/server/responses/core-combo.ts +34 -5
- package/src/server/responses/core-opaque-recovery.ts +20 -11
- package/src/server/responses/core.ts +12 -9
- package/src/server/responses/deepseek-image-files.ts +121 -0
- package/src/server/responses/empty-completion-guard.ts +10 -0
- package/src/server/responses/fetch-helpers.ts +65 -14
- package/src/server/responses/input-admission.ts +6 -2
- package/src/server/responses/jev-model-invoke.ts +13 -14
- package/src/server/responses/main-hard-lock-routing.ts +33 -8
- package/src/server/responses/native-steering-log.ts +2 -2
- package/src/server/responses/opengateway-completion-guard.ts +232 -0
- package/src/server/responses/passthrough-completion.ts +41 -0
- package/src/server/responses/passthrough-delivery.ts +5 -2
- package/src/server/responses/passthrough-dispatch.ts +42 -45
- package/src/server/responses/passthrough-key-rotation.ts +40 -0
- package/src/server/responses/passthrough-observations.ts +38 -0
- package/src/server/responses/reasoning-archive-error.ts +21 -0
- package/src/server/responses/request-compression.ts +98 -0
- package/src/server/responses/request-prepare.ts +11 -1
- package/src/server/responses/request-transport.ts +92 -5
- package/src/server/responses/run-turn-execution.ts +2 -0
- package/src/server/responses/sidecar-execution.ts +16 -3
- package/src/server/responses/terminal-guard.ts +2 -0
- package/src/server/startup-action-control.ts +2 -2
- package/src/server/startup-health-cache.ts +2 -2
- package/src/server/windows-tray-control.ts +2 -2
- package/src/service/definition.ts +9 -1
- package/src/service/orchestration.ts +17 -0
- package/src/types/account-auto-pause.ts +15 -0
- package/src/types/config.ts +23 -1
- package/src/types/provider.ts +11 -5
- package/src/types/request.ts +36 -3
- package/src/types.ts +2 -0
- package/src/usage/cost.ts +17 -1
- package/src/usage/expected-prices.ts +3 -1
- package/src/usage/jev-stats.ts +4 -0
- package/src/usage/log.ts +2 -0
- package/src/usage/summary.ts +7 -0
- package/src/web-search/loop.ts +39 -13
- package/src/web-search/progress-stream.ts +4 -1
- package/src/web-search/run-turn-loop.ts +9 -3
- package/src/web-search/sidecar-search-replay.ts +96 -0
- package/gui/dist/assets/App-CHC89EXQ.js +0 -58
- package/gui/dist/assets/App-wT3mXqFz.css +0 -1
- 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};
|
package/gui/dist/index.html
CHANGED
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
document.documentElement.lang = langMap[locale];
|
|
37
37
|
})();
|
|
38
38
|
</script>
|
|
39
|
-
<script type="module" crossorigin src="/assets/index-
|
|
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.
|
|
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.
|
|
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`
|
|
272
|
-
*
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
80
|
-
|
|
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;
|
package/src/adapters/base.ts
CHANGED
|
@@ -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(
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
}
|