cartethyia 2.4.5 → 2.5.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/.env.example +4 -1
- package/README.md +63 -13
- package/dist/dashboard/assets/AccountCooldown-ChpdzxRH.js.gz +0 -0
- package/dist/dashboard/assets/BannedPage-9igfctfZ.js +1 -0
- package/dist/dashboard/assets/BannedPage-9igfctfZ.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-BzGevuql.js → CliToolDetailPage-ZRr2K2sF.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-ZRr2K2sF.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-BaRM_7We.js → CliToolsPage-D3xqZbN-.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-D3xqZbN-.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-CVnQPBBz.js +1 -0
- package/dist/dashboard/assets/CombosPage-CVnQPBBz.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-u6W1UXSc.js +1 -0
- package/dist/dashboard/assets/ConsoleLogPage-u6W1UXSc.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-DqUGcoH0.js → CustomizationPage-CTTpCb25.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-CTTpCb25.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-C5XpWlvy.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-C5XpWlvy.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-DbhTGfhb.js → LoginPage-DHoB3Agn.js} +1 -1
- package/dist/dashboard/assets/LoginPage-DHoB3Agn.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-oQ-SDXp8.js +1 -0
- package/dist/dashboard/assets/ModelPicker-oQ-SDXp8.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-BrY4SgIt.js +1 -0
- package/dist/dashboard/assets/OverviewPage-BrY4SgIt.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-D9VSt7T_.js +3 -0
- package/dist/dashboard/assets/ProviderDetailPage-D9VSt7T_.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-CmfzxpVM.js +1 -0
- package/dist/dashboard/assets/ProviderIcon-CmfzxpVM.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-Df77V5I5.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-Df77V5I5.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-CDfxP7AC.js +7 -0
- package/dist/dashboard/assets/ProxyPage-CDfxP7AC.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-CY4o2t4p.js +1 -0
- package/dist/dashboard/assets/QuotaPage-CY4o2t4p.js.gz +0 -0
- package/dist/dashboard/assets/{SettingsPage-YxRml8AT.js → SettingsPage-CvjZxHE4.js} +1 -1
- package/dist/dashboard/assets/SettingsPage-CvjZxHE4.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-D3nza7LH.js +1 -0
- package/dist/dashboard/assets/SetupPage-D3nza7LH.js.gz +0 -0
- package/dist/dashboard/assets/{SortableList-Bol1ASmI.js → SortableList-Dtt12WT1.js} +1 -1
- package/dist/dashboard/assets/SortableList-Dtt12WT1.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-CbK3hXvU.js +31 -0
- package/dist/dashboard/assets/StudioPage-CbK3hXvU.js.gz +0 -0
- package/dist/dashboard/assets/ToolIcon-K1ckcDKg.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-BQlWbWg2.js +56 -0
- package/dist/dashboard/assets/UsagePage-BQlWbWg2.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-BmDbsior.js +1 -0
- package/dist/dashboard/assets/api-keys-BmDbsior.js.gz +0 -0
- package/dist/dashboard/assets/app-BbpSarVV.css +2 -0
- package/dist/dashboard/assets/app-BbpSarVV.css.gz +0 -0
- package/dist/dashboard/assets/{app-BDJWMThu.js → app-C-Y4oZT0.js} +3 -3
- package/dist/dashboard/assets/app-C-Y4oZT0.js.gz +0 -0
- package/dist/dashboard/assets/arrow-left-CpBxkoxI.js.gz +0 -0
- package/dist/dashboard/assets/arrow-right-Dl5yKnp8.js.gz +0 -0
- package/dist/dashboard/assets/assert-BHfaei-X.js +1 -0
- package/dist/dashboard/assets/assert-BHfaei-X.js.gz +0 -0
- package/dist/dashboard/assets/backup-file-gdKIlg8U.js.gz +0 -0
- package/dist/dashboard/assets/{badge-BwmwEOgA.js → badge-DpXT4Ixt.js} +1 -1
- package/dist/dashboard/assets/badge-DpXT4Ixt.js.gz +0 -0
- package/dist/dashboard/assets/{banner-BKBfKTqn.js → banner-CSAAWLJv.js} +1 -1
- package/dist/dashboard/assets/banner-CSAAWLJv.js.gz +0 -0
- package/dist/dashboard/assets/brain-Cwed_72z.js.gz +0 -0
- package/dist/dashboard/assets/{card-BTdbRFFg.js → card-DEhRXXw4.js} +1 -1
- package/dist/dashboard/assets/card-DEhRXXw4.js.gz +0 -0
- package/dist/dashboard/assets/check-D69FzdvC.js.gz +0 -0
- package/dist/dashboard/assets/chevron-right-BXIy5l3h.js.gz +0 -0
- package/dist/dashboard/assets/circle-alert-CntYHV5v.js.gz +0 -0
- package/dist/dashboard/assets/circle-check-BU3v_mFW.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-B0wBq-RL.js +1 -0
- package/dist/dashboard/assets/cli-tools-B0wBq-RL.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-DOo6EU8O.js +1 -0
- package/dist/dashboard/assets/clipboard-button-DOo6EU8O.js.gz +0 -0
- package/dist/dashboard/assets/cog-CdWhsajs.js.gz +0 -0
- package/dist/dashboard/assets/copy-ngmQ9zcZ.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-iocKA3jr.js → dialog-BvQeBMfP.js} +1 -1
- package/dist/dashboard/assets/dialog-BvQeBMfP.js.gz +0 -0
- package/dist/dashboard/assets/dialog-actions-B1axpEg7.js.gz +0 -0
- package/dist/dashboard/assets/download-A0SW9OCW.js.gz +0 -0
- package/dist/dashboard/assets/download-dRFo5_Wu.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-CDKOTZdY.js → drawer-CMwPXwQB.js} +1 -1
- package/dist/dashboard/assets/drawer-CMwPXwQB.js.gz +0 -0
- package/dist/dashboard/assets/entry-D4O2229X.js +1 -0
- package/dist/dashboard/assets/entry-D4O2229X.js.gz +0 -0
- package/dist/dashboard/assets/entry-DKvr5Q9K.js +1 -0
- package/dist/dashboard/assets/entry-DKvr5Q9K.js.gz +0 -0
- package/dist/dashboard/assets/entry-FQCejoDY.js +4 -0
- package/dist/dashboard/assets/entry-FQCejoDY.js.gz +0 -0
- package/dist/dashboard/assets/eye-C_hawfH4.js.gz +0 -0
- package/dist/dashboard/assets/eye-off-Bk5g2luF.js.gz +0 -0
- package/dist/dashboard/assets/fingerprint-pattern-BWuHtbW4.js.gz +0 -0
- package/dist/dashboard/assets/gauge-BbIMy7MB.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-zliLvBwr.js +1 -0
- package/dist/dashboard/assets/github-badge-zliLvBwr.js.gz +0 -0
- package/dist/dashboard/assets/image-BPaouViG.js.gz +0 -0
- package/dist/dashboard/assets/{index-C4hXfAMs.js → index-CXm3FIyt.js} +2 -2
- package/dist/dashboard/assets/index-CXm3FIyt.js.gz +0 -0
- package/dist/dashboard/assets/{inline-DCejSLlA.js → inline-D1IlZZ8H.js} +1 -1
- package/dist/dashboard/assets/inline-D1IlZZ8H.js.gz +0 -0
- package/dist/dashboard/assets/{input-Bn4_kNav.js → input-BpVZdrbc.js} +1 -1
- package/dist/dashboard/assets/input-BpVZdrbc.js.gz +0 -0
- package/dist/dashboard/assets/jsx-runtime-CXUMngI_.js.gz +0 -0
- package/dist/dashboard/assets/key-round-UkavsGxp.js.gz +0 -0
- package/dist/dashboard/assets/layers-2-glBbjl.js.gz +0 -0
- package/dist/dashboard/assets/{layout-Bv-NxqZ5.js → layout-BioLW7gN.js} +1 -1
- package/dist/dashboard/assets/layout-BioLW7gN.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-BLA0sldD.js → list-row-CwVcGAIc.js} +1 -1
- package/dist/dashboard/assets/list-row-CwVcGAIc.js.gz +0 -0
- package/dist/dashboard/assets/{live-YlifPYox.js → live-yfEJFF9T.js} +1 -1
- package/dist/dashboard/assets/live-yfEJFF9T.js.gz +0 -0
- package/dist/dashboard/assets/log-in-BmRjy60c.js.gz +0 -0
- package/dist/dashboard/assets/message-circle-CCxGwRvv.js.gz +0 -0
- package/dist/dashboard/assets/model-bans-CT-TxSNX.js +1 -0
- package/dist/dashboard/assets/model-bans-CT-TxSNX.js.gz +0 -0
- package/dist/dashboard/assets/mutation-BkoLM5Ba.js +1 -0
- package/dist/dashboard/assets/mutation-BkoLM5Ba.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CFL4_Dqc.js.gz +0 -0
- package/dist/dashboard/assets/pencil-768ysRAr.js.gz +0 -0
- package/dist/dashboard/assets/plus-DIdX_g-x.js.gz +0 -0
- package/dist/dashboard/assets/power-off-Yjw9GMJh.js +1 -0
- package/dist/dashboard/assets/power-off-Yjw9GMJh.js.gz +0 -0
- package/dist/dashboard/assets/privacy-mode-GM8bej85.js +1 -0
- package/dist/dashboard/assets/privacy-mode-GM8bej85.js.gz +0 -0
- package/dist/dashboard/assets/providers/agentrouter.svg.gz +0 -0
- package/dist/dashboard/assets/providers/aihubmix.svg.gz +0 -0
- package/dist/dashboard/assets/providers/alibaba-coding-plan.svg.gz +0 -0
- package/dist/dashboard/assets/providers/alibaba.svg.gz +0 -0
- package/dist/dashboard/assets/providers/antigravity.svg.gz +0 -0
- package/dist/dashboard/assets/providers/bai.svg.gz +0 -0
- package/dist/dashboard/assets/providers/blackbox.svg.gz +0 -0
- package/dist/dashboard/assets/providers/claude-code.svg.gz +0 -0
- package/dist/dashboard/assets/providers/cursor.webp +0 -0
- package/dist/dashboard/assets/providers/exa.svg.gz +0 -0
- package/dist/dashboard/assets/providers/gmi-cloud.svg.gz +0 -0
- package/dist/dashboard/assets/providers/inferhub.svg.gz +0 -0
- package/dist/dashboard/assets/providers/muse.svg.gz +0 -0
- package/dist/dashboard/assets/providers/nous-research.svg.gz +0 -0
- package/dist/dashboard/assets/providers/openai-light.svg.gz +0 -0
- package/dist/dashboard/assets/providers/parallel.svg.gz +0 -0
- package/dist/dashboard/assets/providers/tokenharbor.svg.gz +0 -0
- package/dist/dashboard/assets/providers/trae.webp +0 -0
- package/dist/dashboard/assets/providers/zai-coding-plan.svg.gz +0 -0
- package/dist/dashboard/assets/{query-keys-ROf-g1Wi.js → query-keys-D7wX2vM5.js} +1 -1
- package/dist/dashboard/assets/query-keys-D7wX2vM5.js.gz +0 -0
- package/dist/dashboard/assets/quota-DZGyp0N5.js.gz +0 -0
- package/dist/dashboard/assets/refresh-cw-BqJFk4sU.js.gz +0 -0
- package/dist/dashboard/assets/rotate-ccw-CufcqITi.js.gz +0 -0
- package/dist/dashboard/assets/route-CNSNj9Zm.js.gz +0 -0
- package/dist/dashboard/assets/routing-Cs6jl49L.js +1 -0
- package/dist/dashboard/assets/routing-Cs6jl49L.js.gz +0 -0
- package/dist/dashboard/assets/scaling-nWE4Cx8f.js.gz +0 -0
- package/dist/dashboard/assets/search-JOKus9rb.js.gz +0 -0
- package/dist/dashboard/assets/select-C0Rer3gF.js +41 -0
- package/dist/dashboard/assets/select-C0Rer3gF.js.gz +0 -0
- package/dist/dashboard/assets/settings-CfcTcOyU.js +1 -0
- package/dist/dashboard/assets/settings-CfcTcOyU.js.gz +0 -0
- package/dist/dashboard/assets/shield-check-DVS0Foqh.js.gz +0 -0
- package/dist/dashboard/assets/sparkles-BRaRUxAU.js.gz +0 -0
- package/dist/dashboard/assets/{stack-C1kTcOmP.js → stack-C9_uUjaA.js} +1 -1
- package/dist/dashboard/assets/stack-C9_uUjaA.js.gz +0 -0
- package/dist/dashboard/assets/{state-DHKdg-pm.js → state-DA0B95UQ.js} +1 -1
- package/dist/dashboard/assets/state-DA0B95UQ.js.gz +0 -0
- package/dist/dashboard/assets/stream-retry-5QnVuSSo.js.gz +0 -0
- package/dist/dashboard/assets/{switch-DIDeAiz9.js → switch-Cittxy-x.js} +1 -1
- package/dist/dashboard/assets/switch-Cittxy-x.js.gz +0 -0
- package/dist/dashboard/assets/terminal-Bd4ee8TA.js +1 -0
- package/dist/dashboard/assets/terminal-Bd4ee8TA.js.gz +0 -0
- package/dist/dashboard/assets/toast-CNt_jzO4.js +2 -0
- package/dist/dashboard/assets/toast-CNt_jzO4.js.gz +0 -0
- package/dist/dashboard/assets/tokens-DDxMbSRL.js.gz +0 -0
- package/dist/dashboard/assets/trash-Cppn5c3R.js.gz +0 -0
- package/dist/dashboard/assets/use-clipboard-B0Sy03fE.js.gz +0 -0
- package/dist/dashboard/assets/use-presence-BSZEBx7U.js.gz +0 -0
- package/dist/dashboard/assets/use-reduced-motion-C4B0R6Sz.js.gz +0 -0
- package/dist/dashboard/assets/use-timeout-BwcBBRrT.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-DVmwOKU-.js → useMutation-BQKMcJ1H.js} +1 -1
- package/dist/dashboard/assets/useMutation-BQKMcJ1H.js.gz +0 -0
- package/dist/dashboard/assets/wrench-B6E1oEuY.js.gz +0 -0
- package/dist/dashboard/index.html +1 -1
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +122 -0
- package/migrations/full-postgres/0013_add_providers_tenant_id_index.sql +22 -0
- package/migrations/full-postgres/0014_add_provider_accounts_tenant_id_index.sql +21 -0
- package/migrations/full-postgres/0015_add_payload_stages.sql +18 -0
- package/migrations/full-postgres/0016_add_share_link_slug.sql +20 -0
- package/migrations/full-postgres/0017_add_models_pro_only.sql +18 -0
- package/migrations/full-postgres/0018_add_accounts_quota_plan.sql +18 -0
- package/migrations/full-postgres/0019_add_models_free_tier.sql +15 -0
- package/migrations/lite-sqlite3/0000_baseline.sql +4 -2
- package/migrations/lite-sqlite3/0013_add_providers_tenant_id_index.sql +4 -0
- package/migrations/lite-sqlite3/0014_add_provider_accounts_tenant_id_index.sql +4 -0
- package/migrations/lite-sqlite3/0015_add_payload_stages.sql +18 -0
- package/migrations/lite-sqlite3/0016_add_share_link_slug.sql +20 -0
- package/migrations/lite-sqlite3/0017_add_models_pro_only.sql +18 -0
- package/migrations/lite-sqlite3/0018_add_accounts_quota_plan.sql +18 -0
- package/migrations/lite-sqlite3/0019_add_models_free_tier.sql +15 -0
- package/package.json +26 -30
- package/scripts/cli/{carte-launcher.cjs → bin/carte.cjs} +8 -8
- package/scripts/cli/{cli-launcher.cjs → bin/cartethyia.cjs} +167 -134
- package/scripts/cli/command/admin.ts +65 -0
- package/scripts/cli/command/console-menu.ts +246 -0
- package/scripts/cli/{doctor.ts → command/doctor.ts} +257 -258
- package/scripts/cli/{setup.ts → command/setup.ts} +8 -12
- package/scripts/cli/command/start.ts +77 -0
- package/scripts/cli/command/tray.ts +165 -0
- package/scripts/cli/command/update.ts +23 -0
- package/scripts/cli/{runtime-state.ts → gateway/drain-token.ts} +78 -78
- package/scripts/cli/gateway/instance-lock.ts +105 -0
- package/scripts/cli/gateway/spawn.ts +173 -0
- package/scripts/cli/gateway/stop.ts +51 -0
- package/scripts/cli/main.ts +94 -0
- package/scripts/cli/support/bun.ts +27 -0
- package/scripts/cli/support/env.ts +99 -0
- package/scripts/cli/support/platform.ts +64 -0
- package/scripts/cli/support/services.ts +88 -0
- package/scripts/cli/support/startup-signal.ts +23 -0
- package/scripts/cli/{version.ts → support/version.ts} +1 -1
- package/scripts/cli/tray/hidden-window.vbs +28 -0
- package/scripts/cli/{tray.ts → tray/index.ts} +3 -3
- package/scripts/cli/{tray.ps1 → tray/windows.ps1} +107 -98
- package/scripts/cli/ui/background.ts +110 -0
- package/src/boot/app.ts +23 -7
- package/src/boot/dependencies.ts +55 -13
- package/src/boot/elysia-typebox-bridge.ts +37 -0
- package/src/boot/lifecycle.ts +2 -0
- package/src/config/cooldowns.ts +138 -138
- package/src/config/providers.ts +31 -5
- package/src/config/runtime.ts +19 -3
- package/src/config/spec.ts +20 -0
- package/src/console/api-keys/contracts.ts +414 -391
- package/src/console/api-keys/routes.ts +880 -870
- package/src/console/auth/account-reset-store.ts +14 -0
- package/src/console/auth/account-reset.ts +3 -2
- package/src/console/auth/setup-service.ts +6 -3
- package/src/console/backup/routes.ts +8 -0
- package/src/console/cli-tools/contracts.ts +6 -6
- package/src/console/console-router.ts +5 -3
- package/src/console/dashboard-assets.ts +81 -11
- package/src/console/domain-registration.ts +9 -2
- package/src/console/observability/contracts.ts +475 -423
- package/src/console/observability/routes.ts +31 -6
- package/src/console/observability/store.ts +1015 -912
- package/src/console/providers/catalog/contracts.ts +31 -0
- package/src/console/providers/catalog/provider-operations.ts +8 -0
- package/src/console/providers/catalog/public-model-store.ts +91 -60
- package/src/console/providers/catalog/store.ts +1532 -1521
- package/src/console/providers/oauth/callback-listener.ts +18 -3
- package/src/console/providers/oauth/routes.ts +38 -15
- package/src/console/quota/account-quota-tenant.ts +9 -6
- package/src/console/quota/refresh.ts +19 -0
- package/src/console/response-compression.ts +69 -2
- package/src/console/routing/pools/probe-verdict.ts +72 -0
- package/src/console/share/share-router.ts +7 -4
- package/src/console/share/share-stats.ts +12 -5
- package/src/console/shared/read-through-cache.ts +133 -7
- package/src/console/updates/repository-updates.ts +39 -34
- package/src/console/updates/routes.ts +162 -4
- package/src/main.ts +3 -0
- package/src/network/http2-bidi.ts +85 -0
- package/src/network/outbound-fetch.ts +87 -24
- package/src/network/pool/agent.ts +478 -460
- package/src/network/pool/resolver.ts +1104 -544
- package/src/network/pool-health-machine.ts +12 -5
- package/src/observability/event-log.ts +29 -8
- package/src/observability/metrics.ts +40 -13
- package/src/observability/payload-capture.ts +344 -324
- package/src/observability/runtime-metrics.ts +7 -0
- package/src/persistence/db-pg.ts +9 -3
- package/src/persistence/db-sqlite.ts +497 -495
- package/src/persistence/health-event-flush.ts +137 -0
- package/src/persistence/migrate.ts +181 -129
- package/src/persistence/schema.ts +1360 -1257
- package/src/persistence/settings-revision.ts +25 -0
- package/src/persistence/shared-cache.ts +217 -0
- package/src/persistence/stores/share-store.ts +556 -528
- package/src/persistence/usage-flush.ts +61 -1
- package/src/protocol/canonical-model.ts +23 -1
- package/src/protocol/response/chat.ts +143 -10
- package/src/protocol/response/codex.ts +9 -75
- package/src/protocol/response/omp-tool-call-markup.ts +221 -0
- package/src/protocol/tool-identity.ts +43 -9
- package/src/providers/authentication/jwt-validator.ts +130 -187
- package/src/providers/authentication/oauth-flow-store.ts +16 -9
- package/src/providers/default-registry.ts +177 -1
- package/src/providers/discovery/catalog/catalog-format.ts +20 -0
- package/src/providers/discovery/models-dev-catalog.ts +39 -22
- package/src/providers/discovery/openai-model-discovery.ts +39 -3
- package/src/providers/discovery/openrouter-free-roster.ts +98 -0
- package/src/providers/discovery/probe-wire.ts +29 -5
- package/src/providers/discovery/probing-service.ts +1022 -1001
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +42 -2
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +913 -914
- package/src/providers/integrations/buddy/buddy-cli-headers.ts +88 -0
- package/src/providers/integrations/buddy/buddy-conversation-headers.ts +22 -5
- package/src/providers/integrations/buddy/buddy-discovery-shared.ts +33 -1
- package/src/providers/integrations/buddy/buddy-identity.ts +46 -0
- package/src/providers/integrations/buddy/buddy-oauth-shared.ts +37 -1
- package/src/providers/integrations/buddy/buddy-usage-store.ts +40 -5
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +4 -0
- package/src/providers/integrations/buddy/codebuddy/provider.ts +180 -175
- package/src/providers/integrations/buddy/codebuddy/shared.ts +115 -73
- package/src/providers/integrations/buddy/workbuddy/cn-provider.ts +5 -2
- package/src/providers/integrations/buddy/workbuddy/provider.ts +206 -204
- package/src/providers/integrations/buddy/workbuddy/quota.ts +172 -159
- package/src/providers/integrations/buddy/workbuddy/shared.ts +200 -171
- package/src/providers/integrations/claude/claude.ts +606 -582
- package/src/providers/integrations/cline/cline-quota.ts +18 -16
- package/src/providers/integrations/cline/cline.ts +539 -468
- package/src/providers/integrations/codex/codex.ts +5 -8
- package/src/providers/integrations/commandcode/commandcode.ts +675 -541
- package/src/providers/integrations/commandcode/discovery.ts +116 -0
- package/src/providers/integrations/commandcode/quota.ts +160 -0
- package/src/providers/integrations/cursor/cursor-auth.ts +418 -0
- package/src/providers/integrations/cursor/cursor-catalog.ts +368 -0
- package/src/providers/integrations/cursor/cursor-http2.ts +300 -0
- package/src/providers/integrations/cursor/cursor-identity.ts +92 -0
- package/src/providers/integrations/cursor/cursor-request.ts +471 -0
- package/src/providers/integrations/cursor/cursor-session-manager.ts +281 -0
- package/src/providers/integrations/cursor/cursor-shared.ts +108 -0
- package/src/providers/integrations/cursor/cursor.ts +960 -0
- package/src/providers/integrations/cursor/protocol/framing.ts +129 -0
- package/src/providers/integrations/cursor/protocol/messages.ts +2355 -0
- package/src/providers/integrations/cursor/protocol/struct.ts +305 -0
- package/src/providers/integrations/factory/factory-oauth.ts +7 -11
- package/src/providers/integrations/github/github.ts +4 -4
- package/src/providers/integrations/hermes.ts +79 -8
- package/src/providers/integrations/kilo/kilo-discovery.ts +10 -1
- package/src/providers/integrations/kilo/kilo.ts +153 -146
- package/src/providers/integrations/opencode/opencode-go-quota.ts +130 -0
- package/src/providers/integrations/opencode/provider.ts +532 -499
- package/src/providers/integrations/openrouter/provider.ts +139 -281
- package/src/providers/integrations/qoder/qoder-catalog.ts +450 -0
- package/src/providers/integrations/qoder/qoder-oauth.ts +310 -263
- package/src/providers/integrations/qoder/qoder-realm.ts +106 -0
- package/src/providers/integrations/qoder/qoder-virtual.ts +77 -0
- package/src/providers/integrations/qoder/qoder.ts +865 -730
- package/src/providers/integrations/shared/install-id.ts +29 -2
- package/src/providers/integrations/trae/trae-catalog.ts +190 -0
- package/src/providers/integrations/trae/trae-headers.ts +149 -0
- package/src/providers/integrations/trae/trae-oauth.ts +773 -0
- package/src/providers/integrations/trae/trae-protocol.ts +400 -0
- package/src/providers/integrations/trae/trae-realm.ts +220 -0
- package/src/providers/integrations/trae/trae.ts +458 -0
- package/src/providers/operations/account-health-service.ts +107 -10
- package/src/providers/operations/client-versions.ts +143 -6
- package/src/providers/operations/model-catalog-cache.ts +18 -3
- package/src/providers/operations/provider-catalog-seeder.ts +95 -86
- package/src/providers/operations/provider-catalog-service.ts +76 -0
- package/src/providers/operations/provider-credential-service.ts +46 -7
- package/src/providers/provider-contracts.ts +76 -0
- package/src/providers/provider-metadata.ts +78 -6
- package/src/providers/provider-model-definition.ts +373 -349
- package/src/security/api-key-auth.ts +126 -8
- package/src/transport/contracts.ts +3 -0
- package/src/transport/dispatch/attempt-finalize.ts +39 -2
- package/src/transport/dispatch/attempt-loop.ts +530 -513
- package/src/transport/dispatch/empty-stream.ts +17 -26
- package/src/transport/dispatch/generation.ts +88 -21
- package/src/transport/dispatch/leases.ts +99 -2
- package/src/transport/dispatch/proxy-request.ts +60 -3
- package/src/transport/dispatch/streaming/finalize.ts +16 -1
- package/src/transport/dispatch/streaming/stream.ts +22 -2
- package/src/transport/dispatch/upstream.ts +19 -1
- package/src/transport/failure-policy.ts +20 -0
- package/src/transport/guards/auth-guard.ts +26 -1
- package/src/transport/guards/body-policy.ts +5 -4
- package/src/transport/request/preparer.ts +103 -0
- package/src/transport/request/state.ts +14 -0
- package/src/transport/routing/plan-gate.ts +45 -0
- package/src/transport/routing/route-catalog.ts +799 -738
- package/src/transport/routing/route-model.ts +52 -1
- package/src/transport/routing/router.ts +51 -0
- package/src/transport/surface/chat/encode.ts +18 -31
- package/src/transport/surface/messages/stream.ts +3 -2
- package/src/transport/translation/tool-repair.ts +37 -16
- package/src/workers/account-identity-sweep.ts +14 -12
- package/src/workers/daily-checkin.ts +62 -0
- package/src/workers/quota-refresh-sweep.ts +27 -2
- package/dist/dashboard/assets/BannedPage-DUrXpp-X.js +0 -1
- package/dist/dashboard/assets/CombosPage-B7ETkfVH.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-AisQzCI1.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-BNflDm_f.js +0 -1
- package/dist/dashboard/assets/ModelPicker-CAiPR5Vd.js +0 -1
- package/dist/dashboard/assets/OverviewPage-C3NIzsDx.js +0 -1
- package/dist/dashboard/assets/ProviderDetailPage-BK8i5B5X.js +0 -3
- package/dist/dashboard/assets/ProviderIcon-paOCq8I0.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-CvCVgm1e.js +0 -1
- package/dist/dashboard/assets/ProxyPage-DjabkuzP.js +0 -7
- package/dist/dashboard/assets/QuotaPage-Dxe0B0iu.js +0 -1
- package/dist/dashboard/assets/SetupPage-BaD4P_jW.js +0 -1
- package/dist/dashboard/assets/StudioPage-CLP4le3U.js +0 -31
- package/dist/dashboard/assets/UsagePage-Djes-Epy.js +0 -56
- package/dist/dashboard/assets/api-keys-CjIGQhe7.js +0 -1
- package/dist/dashboard/assets/app-Cjgo4-Lf.css +0 -2
- package/dist/dashboard/assets/assert-Bwh6DJTK.js +0 -1
- package/dist/dashboard/assets/cli-tools-DccaOfhX.js +0 -1
- package/dist/dashboard/assets/clipboard-button-DQmMikNQ.js +0 -1
- package/dist/dashboard/assets/entry-Cpi0rph1.js +0 -4
- package/dist/dashboard/assets/entry-Dm3PpDCO.js +0 -1
- package/dist/dashboard/assets/entry-keNDZ_Wz.js +0 -1
- package/dist/dashboard/assets/github-badge-BuAJr8oU.js +0 -1
- package/dist/dashboard/assets/model-bans-CVvHZ-qz.js +0 -1
- package/dist/dashboard/assets/mutation-BIizFZav.js +0 -1
- package/dist/dashboard/assets/privacy-mode-CQjbZ3xk.js +0 -1
- package/dist/dashboard/assets/routing-jntw9-Ui.js +0 -1
- package/dist/dashboard/assets/select-CGUuTQmj.js +0 -41
- package/dist/dashboard/assets/settings-BAS6QbmJ.js +0 -1
- package/dist/dashboard/assets/sliders-horizontal-ClG7dBeJ.js +0 -1
- package/dist/dashboard/assets/terminal-C9mZ4Ugm.js +0 -1
- package/dist/dashboard/assets/toast-DKAdP2mo.js +0 -2
- package/scripts/cli/cli.ts +0 -771
- package/scripts/operations/probe-egress.ts +0 -335
- package/scripts/operations/restart.ts +0 -120
- package/scripts/shared/env.ts +0 -269
- /package/{tray-assets → scripts/cli/tray/assets}/cartethyia.ico +0 -0
- /package/{tray-assets → scripts/cli/tray/assets}/cartethyia.png +0 -0
- /package/scripts/cli/{menu.ts → ui/prompt.ts} +0 -0
- /package/scripts/cli/{wordmark.ts → ui/wordmark.ts} +0 -0
|
@@ -1,146 +1,153 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Kilo Code adapter.
|
|
3
|
-
*
|
|
4
|
-
* Kilo Code resells the OpenRouter catalog behind a bearer device token on an
|
|
5
|
-
* OpenAI-compatible chat surface, so this adapter reuses the shared factory for
|
|
6
|
-
* payload translation, transport, and SSE decoding.
|
|
7
|
-
*
|
|
8
|
-
* One thing sits outside the declarative `ApiKeyProviderSpec`: the stored
|
|
9
|
-
* credential is a JSON envelope (`{ accessToken, orgId }`) because the gateway
|
|
10
|
-
* scopes every request to the account's organization and the console stores one
|
|
11
|
-
* opaque string per account. The factory forwards that string as the bearer
|
|
12
|
-
* verbatim, so the envelope is decoded at the auth boundary here — the same
|
|
13
|
-
* arrangement `kimi/kimi.ts` uses for its own envelope credential.
|
|
14
|
-
*
|
|
15
|
-
* The base URL is the completions path itself, because that is the path Kilo
|
|
16
|
-
* Code publishes (`/api/openrouter/chat/completions`) and it is not derivable
|
|
17
|
-
* from an origin plus a wire-family suffix.
|
|
18
|
-
*/
|
|
19
|
-
import { defineModel } from "../../provider-model-definition";
|
|
20
|
-
import
|
|
21
|
-
import type {
|
|
22
|
-
import type {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
export const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
readonly
|
|
42
|
-
readonly
|
|
43
|
-
readonly
|
|
44
|
-
readonly
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
kiloModel("
|
|
89
|
-
kiloModel("
|
|
90
|
-
kiloModel("
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Kilo Code adapter.
|
|
3
|
+
*
|
|
4
|
+
* Kilo Code resells the OpenRouter catalog behind a bearer device token on an
|
|
5
|
+
* OpenAI-compatible chat surface, so this adapter reuses the shared factory for
|
|
6
|
+
* payload translation, transport, and SSE decoding.
|
|
7
|
+
*
|
|
8
|
+
* One thing sits outside the declarative `ApiKeyProviderSpec`: the stored
|
|
9
|
+
* credential is a JSON envelope (`{ accessToken, orgId }`) because the gateway
|
|
10
|
+
* scopes every request to the account's organization and the console stores one
|
|
11
|
+
* opaque string per account. The factory forwards that string as the bearer
|
|
12
|
+
* verbatim, so the envelope is decoded at the auth boundary here — the same
|
|
13
|
+
* arrangement `kimi/kimi.ts` uses for its own envelope credential.
|
|
14
|
+
*
|
|
15
|
+
* The base URL is the completions path itself, because that is the path Kilo
|
|
16
|
+
* Code publishes (`/api/openrouter/chat/completions`) and it is not derivable
|
|
17
|
+
* from an origin plus a wire-family suffix.
|
|
18
|
+
*/
|
|
19
|
+
import { defineModel } from "../../provider-model-definition";
|
|
20
|
+
import { openrouterFreeRoster } from "../../discovery/openrouter-free-roster";
|
|
21
|
+
import type { ModelDefinition } from "../../provider-model-definition";
|
|
22
|
+
import type { ProviderAdapter, ProviderDispatchContext, ProviderDispatchTarget } from "../../provider-contracts";
|
|
23
|
+
import type { CanonicalRequest } from "../../../protocol/canonical-model";
|
|
24
|
+
import { OpenAICompatibleAdapter, withBearerAuthentication } from "../../adapters/compatible-adapter";
|
|
25
|
+
import { providerBaseUrl } from "../../provider-metadata";
|
|
26
|
+
import { decodeKiloCredential } from "../../../security/credential-codec";
|
|
27
|
+
|
|
28
|
+
export const KILO_PROVIDER_ID = "kilo" as const;
|
|
29
|
+
export const KILO_BASE_URL = providerBaseUrl("kilo");
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Endpoint path recorded on this provider's model rows and used by the adapter.
|
|
33
|
+
*
|
|
34
|
+
* The base URL carries Kilo Code's API prefix (`/api/openrouter`), so this is
|
|
35
|
+
* the wire suffix that completes it — the same split Cline uses for
|
|
36
|
+
* `/api/v1` + `/chat/completions`.
|
|
37
|
+
*/
|
|
38
|
+
export const KILO_ENDPOINT_PATH = "/chat/completions" as const;
|
|
39
|
+
|
|
40
|
+
interface KiloModelOptions {
|
|
41
|
+
readonly vision?: boolean;
|
|
42
|
+
readonly document?: boolean;
|
|
43
|
+
readonly audio?: boolean;
|
|
44
|
+
readonly reasoning?: boolean;
|
|
45
|
+
readonly toolCall?: boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function kiloModel(
|
|
49
|
+
modelId: string,
|
|
50
|
+
contextLimit: number,
|
|
51
|
+
outputLimit: number,
|
|
52
|
+
options: KiloModelOptions = {},
|
|
53
|
+
): ModelDefinition {
|
|
54
|
+
return defineModel({
|
|
55
|
+
id: modelId,
|
|
56
|
+
providerId: KILO_PROVIDER_ID,
|
|
57
|
+
wireFamily: "chat",
|
|
58
|
+
endpoint: KILO_ENDPOINT_PATH,
|
|
59
|
+
ctx: contextLimit,
|
|
60
|
+
out: outputLimit,
|
|
61
|
+
vision: options.vision ?? false,
|
|
62
|
+
document: options.document ?? false,
|
|
63
|
+
audio: options.audio ?? false,
|
|
64
|
+
reasoning: options.reasoning ?? false,
|
|
65
|
+
toolCall: options.toolCall ?? true,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Static fallback catalog, read from the live `/api/gateway/models` directory.
|
|
71
|
+
*
|
|
72
|
+
* Live discovery replaces this list whenever an account is available, so these
|
|
73
|
+
* rows are the offline floor: the gateway's own routing aliases plus one
|
|
74
|
+
* current model per family it resells. Limits and capability come from the
|
|
75
|
+
* directory entry's own `top_provider` / `architecture` /
|
|
76
|
+
* `supported_parameters` fields rather than from the base catalog, which prices
|
|
77
|
+
* the underlying model and not this reseller's serving.
|
|
78
|
+
*/
|
|
79
|
+
export const KILO_MODELS: readonly ModelDefinition[] = [
|
|
80
|
+
// Three routers, and nothing else. A committed catalog of specific ids was a
|
|
81
|
+
// snapshot of one afternoon: this provider resells the OpenRouter catalog,
|
|
82
|
+
// which adds and pulls models within days, so discovery is the authority and
|
|
83
|
+
// every hand-kept row outside these drifts out of truth.
|
|
84
|
+
//
|
|
85
|
+
// `kilo-auto/free` bills zero and `kilo-auto/small` bills a fraction of a
|
|
86
|
+
// cent; both route on the provider's own side, so their limits are the
|
|
87
|
+
// window the router may select into rather than one model's.
|
|
88
|
+
kiloModel("kilo-auto/free", 256_000, 32_768, { reasoning: true }),
|
|
89
|
+
kiloModel("kilo-auto/small", 262_144, 32_768, { vision: true, reasoning: true }),
|
|
90
|
+
kiloModel("openrouter/auto", 2_000_000, 128_000, { reasoning: true }),
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The shared free roster, spelled for this provider's endpoint.
|
|
95
|
+
*
|
|
96
|
+
* The same 17 `:free` ids Cline and OpenRouter serve, because this is the same
|
|
97
|
+
* catalog behind a different origin. Kept separate from `KILO_MODELS` so the
|
|
98
|
+
* free tier is its own statement: those three rows are routers, these are the
|
|
99
|
+
* zero-cost models, and the model list groups them differently.
|
|
100
|
+
*/
|
|
101
|
+
export const KILO_FREE_MODELS: readonly ModelDefinition[] = openrouterFreeRoster({
|
|
102
|
+
providerId: KILO_PROVIDER_ID,
|
|
103
|
+
endpoint: KILO_ENDPOINT_PATH,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Adapter that decodes the credential envelope before the shared pipeline
|
|
108
|
+
* authenticates the request.
|
|
109
|
+
*
|
|
110
|
+
* `prepareHeaders` is corrected rather than rebuilt: every other header the
|
|
111
|
+
* factory contributes (content type, gateway identity, operator custom headers,
|
|
112
|
+
* route user-agent) stays exactly as every other provider gets it.
|
|
113
|
+
*/
|
|
114
|
+
class KiloAdapter extends OpenAICompatibleAdapter {
|
|
115
|
+
constructor(fetchImpl?: typeof fetch) {
|
|
116
|
+
super(
|
|
117
|
+
withBearerAuthentication({
|
|
118
|
+
provider_id: KILO_PROVIDER_ID,
|
|
119
|
+
base_url: KILO_BASE_URL,
|
|
120
|
+
endpoint_paths_by_wire_family: { chat: KILO_ENDPOINT_PATH },
|
|
121
|
+
...(fetchImpl ? { fetchImpl } : {}),
|
|
122
|
+
}),
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
protected override async prepareHeaders(
|
|
127
|
+
context: ProviderDispatchContext,
|
|
128
|
+
request: CanonicalRequest,
|
|
129
|
+
candidate: ProviderDispatchTarget,
|
|
130
|
+
): Promise<Record<string, string>> {
|
|
131
|
+
const headers = await super.prepareHeaders(context, request, candidate);
|
|
132
|
+
const secret = context.credential.secret;
|
|
133
|
+
if (secret === undefined || secret.length === 0) return headers;
|
|
134
|
+
// A credential that does not decode is left as the factory sent it: the
|
|
135
|
+
// request then fails closed at the upstream auth boundary, and the parse
|
|
136
|
+
// error belongs to the credential boundary rather than to this hook.
|
|
137
|
+
let credential: ReturnType<typeof decodeKiloCredential>;
|
|
138
|
+
try {
|
|
139
|
+
credential = decodeKiloCredential(secret);
|
|
140
|
+
} catch {
|
|
141
|
+
return headers;
|
|
142
|
+
}
|
|
143
|
+
headers.authorization = `Bearer ${credential.accessToken}`;
|
|
144
|
+
// The upstream's own header name, not ours: renaming the Cartethyia
|
|
145
|
+
// provider id does not rename a field the upstream reads.
|
|
146
|
+
if (credential.orgId !== undefined) headers["X-Kilocode-OrganizationID"] = credential.orgId;
|
|
147
|
+
return headers;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** Kilo Code provider adapter. */
|
|
152
|
+
export const kiloAdapter: ProviderAdapter = new KiloAdapter();
|
|
153
|
+
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getJson,
|
|
3
|
+
type FetchLike,
|
|
4
|
+
type ProviderQuotaResult,
|
|
5
|
+
type ProviderQuotaWindow,
|
|
6
|
+
} from "../../quota/quota-contracts";
|
|
7
|
+
import type { QuotaCollectionContext } from "../../quota/quota-support";
|
|
8
|
+
|
|
9
|
+
const SOURCE = "opencode-go";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The Go plan's `/v1/usage` answer.
|
|
13
|
+
*
|
|
14
|
+
* `usage` carries exactly three windows in the reference implementation —
|
|
15
|
+
* `rolling`, `weekly`, `monthly` — each with a `percent` and a `resetsAt`.
|
|
16
|
+
* The shape is read defensively: an unknown window name is still reported
|
|
17
|
+
* rather than dropped, since a new window is more useful to an operator than
|
|
18
|
+
* a silently narrower view.
|
|
19
|
+
*/
|
|
20
|
+
interface GoUsageWindow {
|
|
21
|
+
readonly percent?: number | null;
|
|
22
|
+
readonly resetsAt?: string | null;
|
|
23
|
+
readonly status?: string | null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface GoUsagePayload {
|
|
27
|
+
readonly usage?: Readonly<Record<string, GoUsageWindow | undefined>> | null;
|
|
28
|
+
readonly plan?: string | null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Windows whose meaning the reference names, in the order it lists them. */
|
|
32
|
+
const KNOWN_WINDOWS: readonly (readonly [string, string])[] = [
|
|
33
|
+
["rolling", "Rolling"],
|
|
34
|
+
["weekly", "Weekly"],
|
|
35
|
+
["monthly", "Monthly"],
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
function labelFor(kind: string): string {
|
|
39
|
+
for (const [name, label] of KNOWN_WINDOWS) {
|
|
40
|
+
if (name === kind) return label;
|
|
41
|
+
}
|
|
42
|
+
return kind.charAt(0).toUpperCase() + kind.slice(1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function resetIso(value: string | null | undefined): string | null {
|
|
46
|
+
if (typeof value !== "string" || value.trim() === "") return null;
|
|
47
|
+
const parsed = Date.parse(value);
|
|
48
|
+
if (!Number.isFinite(parsed)) return null;
|
|
49
|
+
return new Date(parsed).toISOString();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* One window, or `undefined` when the upstream omitted what makes it usable.
|
|
54
|
+
*
|
|
55
|
+
* A window with no percentage is not a zero-percent window — it is an absent
|
|
56
|
+
* measurement, and reporting it as `0` would tell the operator the plan is
|
|
57
|
+
* exhausted when the upstream simply did not say.
|
|
58
|
+
*/
|
|
59
|
+
function windowFor(
|
|
60
|
+
kind: string,
|
|
61
|
+
raw: GoUsageWindow | undefined,
|
|
62
|
+
): ProviderQuotaWindow | undefined {
|
|
63
|
+
if (!raw) return undefined;
|
|
64
|
+
const percent = typeof raw.percent === "number" && Number.isFinite(raw.percent)
|
|
65
|
+
? Math.min(100, Math.max(0, raw.percent))
|
|
66
|
+
: null;
|
|
67
|
+
if (percent === null) return undefined;
|
|
68
|
+
return {
|
|
69
|
+
kind,
|
|
70
|
+
label: labelFor(kind),
|
|
71
|
+
// The endpoint reports subscription-wide percentages, never per-key or
|
|
72
|
+
// per-model balances. Every window of one subscription reads the same
|
|
73
|
+
// budget, so adding them would double-count: they are independent, and
|
|
74
|
+
// the lowest gates the account.
|
|
75
|
+
accounting: "independent",
|
|
76
|
+
usedPercent: percent,
|
|
77
|
+
remainingPercent: 100 - percent,
|
|
78
|
+
resetsAt: resetIso(raw.resetsAt),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function parseWindows(payload: GoUsagePayload): readonly ProviderQuotaWindow[] {
|
|
83
|
+
const usage = payload.usage;
|
|
84
|
+
if (!usage) return [];
|
|
85
|
+
const windows: ProviderQuotaWindow[] = [];
|
|
86
|
+
const seen = new Set<string>();
|
|
87
|
+
// Known windows first, in their documented order, so the dashboard is
|
|
88
|
+
// stable across refreshes; anything novel is appended.
|
|
89
|
+
for (const [name] of KNOWN_WINDOWS) {
|
|
90
|
+
seen.add(name);
|
|
91
|
+
const window = windowFor(name, usage[name]);
|
|
92
|
+
if (window) windows.push(window);
|
|
93
|
+
}
|
|
94
|
+
for (const [name, raw] of Object.entries(usage)) {
|
|
95
|
+
if (seen.has(name)) continue;
|
|
96
|
+
const window = windowFor(name, raw);
|
|
97
|
+
if (window) windows.push(window);
|
|
98
|
+
}
|
|
99
|
+
return windows;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Fetches the OpenCode Go plan's subscription quota from `/v1/usage`.
|
|
104
|
+
*
|
|
105
|
+
* The anonymous free tier has no usage surface — it is rate-limited by egress
|
|
106
|
+
* IP, not by an account balance — so this is the keyed `opencode-go` tier
|
|
107
|
+
* only. The endpoint reports percentages for a *shared* subscription: several
|
|
108
|
+
* Go keys can draw on one plan, so no window here may be summed against
|
|
109
|
+
* another account's.
|
|
110
|
+
*/
|
|
111
|
+
export async function fetchOpenCodeGoQuota(
|
|
112
|
+
credential: string,
|
|
113
|
+
fetcher: FetchLike,
|
|
114
|
+
_context?: QuotaCollectionContext,
|
|
115
|
+
): Promise<ProviderQuotaResult> {
|
|
116
|
+
const token = credential.trim();
|
|
117
|
+
const payload = (await getJson(
|
|
118
|
+
`https://opencode.ai/zen/go/v1/usage`,
|
|
119
|
+
{
|
|
120
|
+
authorization: `Bearer ${token}`,
|
|
121
|
+
accept: "application/json",
|
|
122
|
+
"x-opencode-client": "cli",
|
|
123
|
+
},
|
|
124
|
+
fetcher,
|
|
125
|
+
)) as GoUsagePayload;
|
|
126
|
+
const windows = parseWindows(payload);
|
|
127
|
+
const plan =
|
|
128
|
+
(typeof payload.plan === "string" && payload.plan.trim()) || "OpenCode Go";
|
|
129
|
+
return { source: SOURCE, plan, windows, error: null };
|
|
130
|
+
}
|