cartethyia 2.7.8 → 2.8.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 +3 -3
- package/README.md +29 -59
- package/dist/dashboard/assets/BannedPage-Cc0vKpMG.js +1 -0
- package/dist/dashboard/assets/BannedPage-Cc0vKpMG.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-BRWKPQPf.js → CliToolDetailPage-Bqj2aa1T.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-Bqj2aa1T.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-BP-Y5iHN.js → CliToolsPage-CXsaOAO2.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-CXsaOAO2.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-BeLpJ4ma.js +1 -0
- package/dist/dashboard/assets/CombosPage-BeLpJ4ma.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-DnV0uZ3m.js +1 -0
- package/dist/dashboard/assets/ConsoleLogPage-DnV0uZ3m.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-CBxAjo63.js +1 -0
- package/dist/dashboard/assets/CustomizationPage-CBxAjo63.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-B5yEE0k6.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-B5yEE0k6.js.gz +0 -0
- package/dist/dashboard/assets/{InjectSystemPromptPanel-Cv-2Ol_K.js → InjectSystemPromptPanel-BWFLECmz.js} +2 -2
- package/dist/dashboard/assets/InjectSystemPromptPanel-BWFLECmz.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-bKfz_b1K.js → LoginPage-CgoPc5B9.js} +1 -1
- package/dist/dashboard/assets/LoginPage-CgoPc5B9.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-B-WQxx_H.js → ModelPicker-D9bFQern.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-D9bFQern.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-B_p4tL8k.js +1 -0
- package/dist/dashboard/assets/OverviewPage-B_p4tL8k.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-rs5E2rxv.js +8 -0
- package/dist/dashboard/assets/ProviderDetailPage-rs5E2rxv.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-D_0PiZtg.js +1 -0
- package/dist/dashboard/assets/ProviderIcon-D_0PiZtg.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-CLI2bJTK.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-CLI2bJTK.js.gz +0 -0
- package/dist/dashboard/assets/{ProxyPage-emlTuxz6.js → ProxyPage-BwNC_-Cx.js} +1 -1
- package/dist/dashboard/assets/ProxyPage-BwNC_-Cx.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-DA-a1iSN.js +1 -0
- package/dist/dashboard/assets/QuotaPage-DA-a1iSN.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CctTga2C.js +1 -0
- package/dist/dashboard/assets/SettingsPage-CctTga2C.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-CUZrKs9r.js → SetupPage-febLU4r1.js} +1 -1
- package/dist/dashboard/assets/SetupPage-febLU4r1.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-jWmUdDpy.js → StudioPage-M6fvR5Wz.js} +1 -1
- package/dist/dashboard/assets/StudioPage-M6fvR5Wz.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-nyeuRqz9.js +56 -0
- package/dist/dashboard/assets/UsagePage-nyeuRqz9.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-BFOlvrJC.js +1 -0
- package/dist/dashboard/assets/api-keys-BFOlvrJC.js.gz +0 -0
- package/dist/dashboard/assets/app-Dx2QgsNj.css +2 -0
- package/dist/dashboard/assets/app-Dx2QgsNj.css.gz +0 -0
- package/dist/dashboard/assets/{assert-CidQVoNo.js → assert-CqTLw5e7.js} +1 -1
- package/dist/dashboard/assets/assert-CqTLw5e7.js.gz +0 -0
- package/dist/dashboard/assets/{badge-DyI_mJfi.js → badge-C83EqLB0.js} +1 -1
- package/dist/dashboard/assets/badge-C83EqLB0.js.gz +0 -0
- package/dist/dashboard/assets/ban-durations-B58FyRxC.js +1 -0
- package/dist/dashboard/assets/ban-durations-B58FyRxC.js.gz +0 -0
- package/dist/dashboard/assets/{banner-B-yXtCqb.js → banner-D1xn7pIe.js} +1 -1
- package/dist/dashboard/assets/banner-D1xn7pIe.js.gz +0 -0
- package/dist/dashboard/assets/brand/bansos_page.webp +0 -0
- package/dist/dashboard/assets/brand/denia_bansos.webp +0 -0
- package/dist/dashboard/assets/brand/favicon.webp +0 -0
- package/dist/dashboard/assets/brand/login_register.webp +0 -0
- package/dist/dashboard/assets/brand/login_register_initial.webp +0 -0
- package/dist/dashboard/assets/brand/og_bansos.webp +0 -0
- package/dist/dashboard/assets/brand/og_image.webp +0 -0
- package/dist/dashboard/assets/brand/sidebar_ico.webp +0 -0
- package/dist/dashboard/assets/{card-_HwAEqFF.js → card-DU3Lq5Lm.js} +1 -1
- package/dist/dashboard/assets/card-DU3Lq5Lm.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-Dw1U_drK.js +1 -0
- package/dist/dashboard/assets/cli-tools-Dw1U_drK.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-ByjCk0o9.js → clipboard-button-CEL5Sg_J.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-CEL5Sg_J.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-BZhOlfz-.js → dialog-BjFR5UHy.js} +1 -1
- package/dist/dashboard/assets/dialog-BjFR5UHy.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-BADqIRYP.js → drawer-HvBW0AjI.js} +1 -1
- package/dist/dashboard/assets/drawer-HvBW0AjI.js.gz +0 -0
- package/dist/dashboard/assets/entry-BSu3gFlt.js +4 -0
- package/dist/dashboard/assets/entry-BSu3gFlt.js.gz +0 -0
- package/dist/dashboard/assets/{entry-COaC-irN.js → entry-CECVELyy.js} +1 -1
- package/dist/dashboard/assets/entry-CECVELyy.js.gz +0 -0
- package/dist/dashboard/assets/entry-DYYofQ7W.js +1 -0
- package/dist/dashboard/assets/entry-DYYofQ7W.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-DcHJyRiu.js → formatters-DLW4i8zK.js} +1 -1
- package/dist/dashboard/assets/formatters-DLW4i8zK.js.gz +0 -0
- package/dist/dashboard/assets/{index-CgKmFngv.js → index-1-fCqe64.js} +2 -2
- package/dist/dashboard/assets/index-1-fCqe64.js.gz +0 -0
- package/dist/dashboard/assets/{inline-B2BirKry.js → inline-DGvU2oLK.js} +1 -1
- package/dist/dashboard/assets/inline-DGvU2oLK.js.gz +0 -0
- package/dist/dashboard/assets/{input-D-qV9dKY.js → input-iNnO1X2K.js} +1 -1
- package/dist/dashboard/assets/input-iNnO1X2K.js.gz +0 -0
- package/dist/dashboard/assets/{layout-B7tVWhtV.js → layout-0q8UGypb.js} +1 -1
- package/dist/dashboard/assets/layout-0q8UGypb.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-CtkGE3bF.js → list-row-C0w2bQjJ.js} +1 -1
- package/dist/dashboard/assets/list-row-C0w2bQjJ.js.gz +0 -0
- package/dist/dashboard/assets/{live-DGizF06-.js → live-M5aJ_xCa.js} +1 -1
- package/dist/dashboard/assets/live-M5aJ_xCa.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-GU7XdEjz.js → mutation-BQ0ccH_A.js} +1 -1
- package/dist/dashboard/assets/mutation-BQ0ccH_A.js.gz +0 -0
- package/dist/dashboard/assets/{network-C9UE-bOr.js → network-BKeQGT3K.js} +1 -1
- package/dist/dashboard/assets/network-BKeQGT3K.js.gz +0 -0
- package/dist/dashboard/assets/{numbers-BnAd22a_.js → numbers-CivAk3da.js} +1 -1
- package/dist/dashboard/assets/numbers-CivAk3da.js.gz +0 -0
- package/dist/dashboard/assets/{pagination-BAywyMzS.js → pagination-CpzvI5ep.js} +1 -1
- package/dist/dashboard/assets/pagination-CpzvI5ep.js.gz +0 -0
- package/dist/dashboard/assets/providers/devin.svg +9 -0
- package/dist/dashboard/assets/providers/devin.svg.gz +0 -0
- package/dist/dashboard/assets/providers/windsurf.svg +10 -0
- package/dist/dashboard/assets/providers/windsurf.svg.gz +0 -0
- package/dist/dashboard/assets/providers/zro.svg +3 -0
- package/dist/dashboard/assets/providers/zro.svg.gz +0 -0
- package/dist/dashboard/assets/{query-keys-YSoQOUh6.js → query-keys-IKLh0YFd.js} +1 -1
- package/dist/dashboard/assets/query-keys-IKLh0YFd.js.gz +0 -0
- package/dist/dashboard/assets/quota-DiPD6UKH.js +1 -0
- package/dist/dashboard/assets/quota-DiPD6UKH.js.gz +0 -0
- package/dist/dashboard/assets/routing-BFQX2VBc.js +1 -0
- package/dist/dashboard/assets/routing-BFQX2VBc.js.gz +0 -0
- package/dist/dashboard/assets/{select-BCOcv8WK.js → select-CXbck0jG.js} +2 -2
- package/dist/dashboard/assets/select-CXbck0jG.js.gz +0 -0
- package/dist/dashboard/assets/settings-C_XvMHh9.js +1 -0
- package/dist/dashboard/assets/settings-C_XvMHh9.js.gz +0 -0
- package/dist/dashboard/assets/{stack-ByKt3Q1g.js → stack-DggRiCxE.js} +1 -1
- package/dist/dashboard/assets/stack-DggRiCxE.js.gz +0 -0
- package/dist/dashboard/assets/{state-DXbGTx7N.js → state-ClFzfbYp.js} +1 -1
- package/dist/dashboard/assets/state-ClFzfbYp.js.gz +0 -0
- package/dist/dashboard/assets/story/25817331.webp +0 -0
- package/dist/dashboard/assets/story/Shorekeeper.webp +0 -0
- package/dist/dashboard/assets/story/cartethyia-god.webp +0 -0
- package/dist/dashboard/assets/story/fleurdelys_plus.webp +0 -0
- package/dist/dashboard/assets/story/jinhsi-blossom.webp +0 -0
- package/dist/dashboard/assets/story/phrolova-a.webp +0 -0
- package/dist/dashboard/assets/story/requestdeniawokkjpg.webp +0 -0
- package/dist/dashboard/assets/story/wuthering-waves-hiyuki-aemeath-hiyuki-rover.webp +0 -0
- package/dist/dashboard/assets/{switch-ZeTsW623.js → switch-CTIFxKqS.js} +1 -1
- package/dist/dashboard/assets/switch-CTIFxKqS.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-CbCP4w1o.js → useMutation-BClG3yWj.js} +1 -1
- package/dist/dashboard/assets/useMutation-BClG3yWj.js.gz +0 -0
- package/dist/dashboard/console-backgrounds.webp +0 -0
- package/dist/dashboard/console-backgrounds_initial.webp +0 -0
- package/dist/dashboard/donation/qris-risun-marke.webp +0 -0
- package/dist/dashboard/index.html +3 -3
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +59 -56
- package/migrations/full-postgres/0044_add_models_warning_metadata.sql +10 -0
- package/migrations/full-postgres/0045_migrate_workbuddy_to_codebuddy.sql +156 -0
- package/migrations/full-postgres/0046_add_accounts_quota_plan_fetched_at.sql +7 -0
- package/migrations/lite-sqlite3/0044_add_models_warning_metadata.sql +11 -0
- package/migrations/lite-sqlite3/0045_migrate_workbuddy_to_codebuddy.sql +156 -0
- package/migrations/lite-sqlite3/0046_add_accounts_quota_plan_fetched_at.sql +4 -0
- package/package.json +1 -1
- package/src/boot/app.ts +10 -13
- package/src/boot/dependencies.ts +12 -4
- package/src/boot/flush.ts +20 -0
- package/src/boot/lifecycle.ts +7 -5
- package/src/config/cooldowns.ts +1 -1
- package/src/config/routing.ts +26 -0
- package/src/config/spec-metadata.ts +72 -0
- package/src/config/spec.ts +20 -6
- package/src/console/api-keys/contracts.ts +12 -1
- package/src/console/api-keys/routes.ts +50 -31
- package/src/console/auth/account-reset.ts +7 -9
- package/src/console/backup/contracts.ts +4 -0
- package/src/console/backup/export-endpoint.ts +7 -5
- package/src/console/cli-tools/service.ts +6 -12
- package/src/console/console-router-guards.ts +23 -16
- package/src/console/console-router.ts +7 -0
- package/src/console/dashboard-assets.ts +5 -5
- package/src/console/domain-registration.ts +27 -2
- package/src/console/inferhub/normalize.ts +24 -28
- package/src/console/inferhub/types.ts +3 -0
- package/src/console/ip-bans/routes.ts +93 -0
- package/src/console/observability/store.ts +0 -53
- package/src/console/providers/catalog/catalog-projections.ts +5 -2
- package/src/console/providers/catalog/contracts.ts +123 -0
- package/src/console/providers/catalog/discover-constants.ts +6 -0
- package/src/console/providers/catalog/model-operations.ts +122 -10
- package/src/console/providers/catalog/provider-operations.ts +116 -8
- package/src/console/providers/catalog/public-model-store.ts +0 -0
- package/src/console/providers/catalog/routes.ts +65 -4
- package/src/console/providers/catalog/store-helpers.ts +30 -1
- package/src/console/providers/catalog/store.ts +249 -4
- package/src/console/quota/account-quota-global.ts +97 -19
- package/src/console/quota/account-quota-shared.ts +49 -0
- package/src/console/quota/account-quota-tenant.ts +6 -18
- package/src/console/quota/native-identity.ts +2 -0
- package/src/console/quota/quota-view.ts +19 -3
- package/src/console/routing/pools/operations.ts +31 -46
- package/src/console/settings/contracts.ts +18 -0
- package/src/console/settings/store.ts +32 -0
- package/src/console/shared/errors.ts +33 -6
- package/src/console/system-prompt/contracts.ts +0 -1
- package/src/main.ts +3 -3
- package/src/network/pool/byte-accounting.ts +3 -2
- package/src/network/pool/selector.ts +182 -39
- package/src/network/pool-cooldown-store.ts +89 -14
- package/src/network/pool-health.ts +49 -61
- package/src/network/rate-limit-verdict.ts +1 -1
- package/src/network/ssrf.ts +6 -6
- package/src/observability/event-log.ts +7 -361
- package/src/observability/event-query.ts +18 -4
- package/src/observability/performance-metrics.ts +9 -0
- package/src/observability/runtime-metrics.ts +14 -9
- package/src/observability/telemetry-buffer.ts +15 -25
- package/src/observability/telemetry-reconciliation.ts +9 -37
- package/src/observability/telemetry-row.ts +125 -0
- package/src/persistence/db-mode.ts +4 -1
- package/src/persistence/dialect.ts +30 -0
- package/src/persistence/migrate.ts +6 -3
- package/src/persistence/schema.ts +28 -2
- package/src/persistence/ttl-cache.ts +20 -2
- package/src/protocol/codecs.ts +1 -1
- package/src/protocol/dsml.ts +35 -87
- package/src/protocol/gateway-error.ts +1 -0
- package/src/protocol/markup-stream-parser.ts +195 -0
- package/src/protocol/reasoning-text.ts +19 -0
- package/src/protocol/reasoning.ts +1 -1
- package/src/protocol/request/chat.ts +14 -14
- package/src/protocol/request/gemini.ts +8 -2
- package/src/protocol/request/messages.ts +4 -5
- package/src/protocol/response/chat.ts +12 -20
- package/src/protocol/response/gemini.ts +6 -1
- package/src/protocol/response/omp-tool-call-markup.ts +43 -86
- package/src/protocol/response/responses.ts +18 -2
- package/src/protocol/sse-decoder.ts +25 -8
- package/src/protocol/stop-reason.ts +23 -1
- package/src/protocol/stream-error-frames.ts +13 -3
- package/src/protocol/think-split.ts +112 -0
- package/src/protocol/translation/dialect/qwen.ts +26 -58
- package/src/protocol/translation/quirks.ts +1 -1
- package/src/protocol/translation/tool-repair.ts +2 -2
- package/src/protocol/upstream/send-claude-messages.ts +15 -4
- package/src/protocol/upstream-parsing.ts +1 -1
- package/src/providers/adapters/compatible-adapter.ts +78 -17
- package/src/providers/authentication/oauth-client.ts +1 -1
- package/src/providers/authentication/oauth-device-flow.ts +98 -8
- package/src/providers/authentication/oauth-refresh-service.ts +153 -59
- package/src/providers/configured-provider.ts +148 -0
- package/src/providers/default-registry.ts +117 -27
- package/src/providers/discovery/discovery-types.ts +12 -0
- package/src/providers/discovery/probe-phases.ts +74 -33
- package/src/providers/discovery/probing-service.ts +293 -165
- package/src/providers/integrations/alibabacp/alibabacp-models.ts +1 -2
- package/src/providers/integrations/{dashscope-models.ts → alibabacp/dashscope-models.ts} +2 -2
- package/src/providers/integrations/antigravity/antigravity-protocol.ts +121 -2
- package/src/providers/integrations/antigravity/antigravity.ts +13 -2
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +72 -34
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +191 -35
- package/src/providers/integrations/buddy/buddy-checkin.ts +17 -39
- package/src/providers/integrations/buddy/buddy-conversation-headers.ts +2 -2
- package/src/providers/integrations/buddy/buddy-discovery-shared.ts +5 -5
- package/src/providers/integrations/buddy/buddy-identity.ts +89 -6
- package/src/providers/integrations/buddy/buddy-media.ts +4 -5
- package/src/providers/integrations/buddy/buddy-oauth-shared.ts +2 -2
- package/src/providers/integrations/buddy/buddy-quota-shared.ts +1 -1
- package/src/providers/integrations/buddy/buddy-usage-shared.ts +1 -3
- package/src/providers/integrations/buddy/capabilities.ts +6 -43
- package/src/providers/integrations/buddy/codebuddy/cn-catalog.ts +2 -1
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +23 -1
- package/src/providers/integrations/buddy/codebuddy/provider.ts +6 -2
- package/src/providers/integrations/buddy/codebuddy/shared.ts +38 -27
- package/src/providers/integrations/claude/claude-quota.ts +14 -17
- package/src/providers/integrations/cline/cline.ts +2 -2
- package/src/providers/integrations/commandcode/quota.ts +22 -28
- package/src/providers/integrations/cursor/cursor-auth.ts +0 -8
- package/src/providers/integrations/cursor/cursor-catalog.ts +2 -0
- package/src/providers/integrations/cursor/cursor-exec.ts +745 -0
- package/src/providers/integrations/cursor/cursor-http2.ts +2 -0
- package/src/providers/integrations/cursor/cursor-request.ts +35 -20
- package/src/providers/integrations/cursor/cursor-shared.ts +26 -5
- package/src/providers/integrations/cursor/cursor.ts +139 -70
- package/src/providers/integrations/cursor/protocol/messages.ts +22 -29
- package/src/providers/integrations/cursor/protocol/protobuf-schema.ts +37 -0
- package/src/providers/integrations/cursor/protocol/tool-canonical.ts +26 -100
- package/src/providers/integrations/devin/devin-auth.ts +353 -0
- package/src/providers/integrations/devin/devin-catalog.ts +207 -0
- package/src/providers/integrations/devin/devin-http.ts +91 -0
- package/src/providers/integrations/devin/devin-quota.ts +214 -0
- package/src/providers/integrations/devin/devin-shared.ts +111 -0
- package/src/providers/integrations/devin/devin.ts +539 -0
- package/src/providers/integrations/devin/protocol/devin-proto.ts +558 -0
- package/src/providers/integrations/devin/protocol/framing.ts +124 -0
- package/src/providers/integrations/factory/factory-oauth.ts +17 -44
- package/src/providers/integrations/factory/factory.ts +2 -2
- package/src/providers/integrations/freebuff/assets/official-system-manager.txt +88 -0
- package/src/providers/integrations/freebuff/assets/official-system-worker.txt +57 -0
- package/src/providers/integrations/freebuff/assets/official-tools.json +1070 -0
- package/src/providers/integrations/freebuff/freebuff-catalog.ts +120 -0
- package/src/providers/integrations/freebuff/freebuff-constants.ts +1233 -0
- package/src/providers/integrations/freebuff/freebuff-discovery.ts +108 -0
- package/src/providers/integrations/freebuff/freebuff-oauth.ts +240 -0
- package/src/providers/integrations/freebuff/freebuff-quota.ts +260 -0
- package/src/providers/integrations/freebuff/freebuff-virtual.ts +89 -0
- package/src/providers/integrations/freebuff/freebuff.ts +682 -0
- package/src/providers/integrations/freepi/freepi-catalog.ts +60 -0
- package/src/providers/integrations/freepi/freepi-discovery.ts +82 -0
- package/src/providers/integrations/freepi/freepi-headers.ts +21 -0
- package/src/providers/integrations/freepi/freepi-oauth.ts +142 -0
- package/src/providers/integrations/freepi/freepi-protocol.ts +242 -0
- package/src/providers/integrations/freepi/freepi-quota.ts +126 -0
- package/src/providers/integrations/freepi/freepi-realm.ts +35 -0
- package/src/providers/integrations/freepi/freepi.ts +292 -0
- package/src/providers/integrations/gemini.ts +2 -2
- package/src/providers/integrations/grok/grok-oauth.ts +48 -45
- package/src/providers/integrations/grok/grok-ratelimit-store.ts +10 -17
- package/src/providers/integrations/grok/grok-turn-index.ts +11 -16
- package/src/providers/integrations/hermes/hermes-oauth.ts +94 -0
- package/src/providers/integrations/{hermes.ts → hermes/hermes.ts} +13 -21
- package/src/providers/integrations/hermes/index.ts +2 -0
- package/src/providers/integrations/kiro/kiro-catalog.ts +17 -1
- package/src/providers/integrations/kiro/kiro-discovery.ts +10 -12
- package/src/providers/integrations/kiro/kiro-quota.ts +8 -4
- package/src/providers/integrations/kiro/kiro.ts +15 -19
- package/src/providers/integrations/ollamacloud/index.ts +2 -0
- package/src/providers/integrations/{ollamacloud-models.ts → ollamacloud/models.ts} +2 -2
- package/src/providers/integrations/{ollamacloud-quota.ts → ollamacloud/quota.ts} +3 -3
- package/src/providers/integrations/opencode/fingerprint.ts +1 -1
- package/src/providers/integrations/opencode/opencode-go-quota.ts +2 -8
- package/src/providers/integrations/perch/perch-catalog.ts +105 -0
- package/src/providers/integrations/perch/perch-credential.ts +25 -0
- package/src/providers/integrations/perch/perch-oauth.ts +170 -0
- package/src/providers/integrations/perch/perch-protocol.ts +208 -0
- package/src/providers/integrations/perch/perch-quota.ts +123 -0
- package/src/providers/integrations/perch/perch-realm.ts +82 -0
- package/src/providers/integrations/perch/perch-system-prompt.ts +13 -0
- package/src/providers/integrations/perch/perch.ts +305 -0
- package/src/providers/integrations/perch/saffron-system-prompt.txt +8 -0
- package/src/providers/integrations/qoder/chat-proto.ts +328 -328
- package/src/providers/integrations/qoder/claim-qoder-credits.ts +19 -60
- package/src/providers/integrations/qoder/qoder-adapter.ts +90 -40
- package/src/providers/integrations/qoder/qoder-auth.ts +101 -29
- package/src/providers/integrations/qoder/qoder-cache.ts +32 -0
- package/src/providers/integrations/qoder/qoder-catalog.ts +26 -6
- package/src/providers/integrations/qoder/qoder-chat.ts +7 -21
- package/src/providers/integrations/qoder/qoder-checkin.ts +6 -6
- package/src/providers/integrations/qoder/qoder-grpc.ts +210 -7
- package/src/providers/integrations/qoder/qoder-ide.ts +5 -108
- package/src/providers/integrations/qoder/qoder-identity-cache.ts +184 -0
- package/src/providers/integrations/qoder/qoder-native-identity-store.ts +83 -18
- package/src/providers/integrations/qoder/qoder-realm.ts +9 -6
- package/src/providers/integrations/qoder/qoder-umid.ts +109 -342
- package/src/providers/integrations/qoder/qoder-virtual.ts +33 -1
- package/src/providers/integrations/qoder/qoder.ts +3 -7
- package/src/providers/integrations/trae/trae-catalog.ts +9 -14
- package/src/providers/integrations/trae/trae-headers.ts +36 -11
- package/src/providers/integrations/trae/trae-oauth.ts +14 -17
- package/src/providers/integrations/trae/trae-protocol.ts +12 -11
- package/src/providers/integrations/trae/trae-quota.ts +96 -36
- package/src/providers/integrations/trae/trae-realm.ts +74 -15
- package/src/providers/integrations/trae/trae.ts +99 -26
- package/src/providers/integrations/zcode-start-plan/provider.ts +226 -23
- package/src/providers/integrations/zcode-start-plan/quota.ts +19 -2
- package/src/providers/integrations/zro/zro.ts +204 -0
- package/src/providers/operations/account-error-classification.ts +235 -278
- package/src/providers/operations/account-health-service.ts +273 -26
- package/src/providers/operations/account-refresh-status.ts +269 -0
- package/src/providers/operations/account-tier.ts +66 -0
- package/src/providers/operations/client-version-resolver.ts +1 -1
- package/src/providers/operations/client-versions.ts +42 -150
- package/src/providers/operations/cooldown-rules.ts +56 -0
- package/src/providers/operations/{model-catalog-cache.ts → provider-caches.ts} +68 -16
- package/src/providers/operations/provider-catalog-seeder.ts +4 -0
- package/src/providers/operations/provider-catalog-service.ts +1 -1
- package/src/providers/operations/provider-credential-service.ts +102 -32
- package/src/providers/operations/provider-rules/github.ts +48 -0
- package/src/providers/operations/provider-rules/grok.ts +33 -0
- package/src/providers/operations/provider-rules/inception.ts +49 -0
- package/src/providers/operations/provider-rules/index.ts +32 -0
- package/src/providers/operations/provider-rules/perch.ts +37 -0
- package/src/providers/operations/provider-rules/qoder.ts +70 -0
- package/src/providers/operations/provider-rules/trae.ts +81 -0
- package/src/providers/provider-contracts.ts +33 -2
- package/src/providers/{provider-credential-resolver.ts → provider-credentials.ts} +40 -3
- package/src/providers/provider-metadata.ts +99 -14
- package/src/providers/provider-model-definition.ts +36 -0
- package/src/providers/provider-probe.ts +15 -1
- package/src/providers/provider-registry.ts +42 -33
- package/src/providers/quota/quota-limit-windows.ts +16 -5
- package/src/providers/quota/quota-support.ts +1 -1
- package/src/providers/quota/quota-window-parser.ts +90 -18
- package/src/providers/quota/refresh.ts +96 -18
- package/src/security/abuse.ts +71 -0
- package/src/security/api-key-auth-cache.ts +1 -1
- package/src/security/api-key-auth.ts +6 -2
- package/src/transport/dispatch/attempt-finalize.ts +14 -13
- package/src/transport/dispatch/attempt-loop.ts +71 -17
- package/src/transport/dispatch/generation.ts +2 -8
- package/src/transport/dispatch/native-shared.ts +25 -0
- package/src/transport/dispatch/proxy-request.ts +9 -46
- package/src/transport/dispatch/responses-compact.ts +2 -8
- package/src/transport/dispatch/streaming/finalize.ts +9 -6
- package/src/transport/dispatch/streaming/stream.ts +9 -36
- package/src/transport/dispatch/systemone.ts +2 -8
- package/src/transport/dispatch/token-count.ts +2 -6
- package/src/transport/dispatch/upstream.ts +67 -1
- package/src/transport/drain-endpoint.ts +31 -4
- package/src/transport/failure-policy.ts +129 -37
- package/src/transport/guards/body-policy.ts +7 -1
- package/src/transport/guards/error-lifecycle.ts +13 -1
- package/src/transport/guards/request-context.ts +22 -14
- package/src/transport/request/preparer.ts +81 -71
- package/src/transport/routing/bounded-lru.ts +14 -0
- package/src/transport/routing/drain-reserve.ts +129 -0
- package/src/transport/routing/plan-gate.ts +7 -1
- package/src/transport/routing/round-robin.ts +60 -0
- package/src/transport/routing/route-catalog.ts +123 -111
- package/src/transport/routing/route-model.ts +51 -9
- package/src/transport/routing/router.ts +418 -33
- package/src/transport/surface/adapters.ts +11 -2
- package/src/transport/surface/chat/adapter.ts +2 -2
- package/src/transport/surface/chat/encode.ts +47 -4
- package/src/transport/surface/chat/parse.ts +2 -12
- package/src/transport/surface/completion.ts +44 -33
- package/src/transport/surface/content-parts.ts +21 -0
- package/src/transport/surface/messages/adapter.ts +9 -2
- package/src/transport/surface/messages/encode.ts +11 -3
- package/src/transport/surface/messages/parse.ts +2 -1
- package/src/transport/surface/messages/stream.ts +33 -17
- package/src/transport/surface/responses/encode.ts +34 -6
- package/src/transport/surface/responses/parse.ts +3 -11
- package/src/workers/daily-checkin.ts +1 -1
- package/src/workers/quota-refresh-sweep.ts +1 -1
- package/src/workers/scheduler.ts +22 -4
- package/dist/dashboard/assets/BannedPage-DeIbIiBU.js +0 -1
- package/dist/dashboard/assets/BannedPage-DeIbIiBU.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-BRWKPQPf.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-BP-Y5iHN.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-B7JHozVa.js +0 -1
- package/dist/dashboard/assets/CombosPage-B7JHozVa.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-GX7iGGcu.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-GX7iGGcu.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-HVonbGEa.js +0 -1
- package/dist/dashboard/assets/CustomizationPage-HVonbGEa.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-xaut4OJ9.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-xaut4OJ9.js.gz +0 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-Cv-2Ol_K.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-bKfz_b1K.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-B-WQxx_H.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-Z9pJZFo8.js +0 -1
- package/dist/dashboard/assets/OverviewPage-Z9pJZFo8.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-CMeDBxR1.js +0 -7
- package/dist/dashboard/assets/ProviderDetailPage-CMeDBxR1.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js +0 -1
- package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-BXPdOpG4.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-BXPdOpG4.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-emlTuxz6.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-CMJKNYWb.js +0 -1
- package/dist/dashboard/assets/QuotaPage-CMJKNYWb.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-BSy7EwGo.js +0 -1
- package/dist/dashboard/assets/SettingsPage-BSy7EwGo.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-CUZrKs9r.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-jWmUdDpy.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-5F9tGVGG.js +0 -56
- package/dist/dashboard/assets/UsagePage-5F9tGVGG.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-KvX83mRe.js +0 -1
- package/dist/dashboard/assets/api-keys-KvX83mRe.js.gz +0 -0
- package/dist/dashboard/assets/app-BEsU8hKs.css +0 -2
- package/dist/dashboard/assets/app-BEsU8hKs.css.gz +0 -0
- package/dist/dashboard/assets/assert-CidQVoNo.js.gz +0 -0
- package/dist/dashboard/assets/badge-DyI_mJfi.js.gz +0 -0
- package/dist/dashboard/assets/banner-B-yXtCqb.js.gz +0 -0
- package/dist/dashboard/assets/brand/bansos_page.png +0 -0
- package/dist/dashboard/assets/brand/denia_bansos.jpg +0 -0
- package/dist/dashboard/assets/brand/favicon.jpg +0 -0
- package/dist/dashboard/assets/brand/login_register.jpg +0 -0
- package/dist/dashboard/assets/brand/login_register_initial.jpg +0 -0
- package/dist/dashboard/assets/brand/og_bansos.jpg +0 -0
- package/dist/dashboard/assets/brand/og_image.jpg +0 -0
- package/dist/dashboard/assets/brand/sidebar_ico.jpg +0 -0
- package/dist/dashboard/assets/card-_HwAEqFF.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js +0 -1
- package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-ByjCk0o9.js.gz +0 -0
- package/dist/dashboard/assets/dialog-BZhOlfz-.js.gz +0 -0
- package/dist/dashboard/assets/drawer-BADqIRYP.js.gz +0 -0
- package/dist/dashboard/assets/entry-COaC-irN.js.gz +0 -0
- package/dist/dashboard/assets/entry-Ca7LSCet.js +0 -4
- package/dist/dashboard/assets/entry-Ca7LSCet.js.gz +0 -0
- package/dist/dashboard/assets/entry-PDd27uCd.js +0 -1
- package/dist/dashboard/assets/entry-PDd27uCd.js.gz +0 -0
- package/dist/dashboard/assets/formatters-DcHJyRiu.js.gz +0 -0
- package/dist/dashboard/assets/index-CgKmFngv.js.gz +0 -0
- package/dist/dashboard/assets/inline-B2BirKry.js.gz +0 -0
- package/dist/dashboard/assets/input-D-qV9dKY.js.gz +0 -0
- package/dist/dashboard/assets/layout-B7tVWhtV.js.gz +0 -0
- package/dist/dashboard/assets/list-row-CtkGE3bF.js.gz +0 -0
- package/dist/dashboard/assets/live-DGizF06-.js.gz +0 -0
- package/dist/dashboard/assets/minimize-2-BTmMTK4o.js +0 -1
- package/dist/dashboard/assets/minimize-2-BTmMTK4o.js.gz +0 -0
- package/dist/dashboard/assets/mutation-GU7XdEjz.js.gz +0 -0
- package/dist/dashboard/assets/network-C9UE-bOr.js.gz +0 -0
- package/dist/dashboard/assets/numbers-BnAd22a_.js.gz +0 -0
- package/dist/dashboard/assets/pagination-BAywyMzS.js.gz +0 -0
- package/dist/dashboard/assets/query-keys-YSoQOUh6.js.gz +0 -0
- package/dist/dashboard/assets/quota-DJ1QlAOq.js +0 -1
- package/dist/dashboard/assets/quota-DJ1QlAOq.js.gz +0 -0
- package/dist/dashboard/assets/routing-fnCsxgNO.js +0 -1
- package/dist/dashboard/assets/routing-fnCsxgNO.js.gz +0 -0
- package/dist/dashboard/assets/select-BCOcv8WK.js.gz +0 -0
- package/dist/dashboard/assets/settings-BxslsErn.js +0 -1
- package/dist/dashboard/assets/settings-BxslsErn.js.gz +0 -0
- package/dist/dashboard/assets/stack-ByKt3Q1g.js.gz +0 -0
- package/dist/dashboard/assets/state-DXbGTx7N.js.gz +0 -0
- package/dist/dashboard/assets/switch-ZeTsW623.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-CbCP4w1o.js.gz +0 -0
- package/dist/dashboard/console-backgrounds.jpg +0 -0
- package/dist/dashboard/console-backgrounds_initial.jpg +0 -0
- package/dist/dashboard/donation/qris-risun-marke.png +0 -0
- package/src/providers/bundled-discovery-providers.ts +0 -98
- package/src/providers/configured-openai-providers.ts +0 -120
- package/src/providers/integrations/buddy/turing-device-token.ts +0 -262
- package/src/providers/integrations/buddy/workbuddy/cn-oauth.ts +0 -30
- package/src/providers/integrations/buddy/workbuddy/cn-provider.ts +0 -58
- package/src/providers/integrations/buddy/workbuddy/oauth.ts +0 -31
- package/src/providers/integrations/buddy/workbuddy/provider.ts +0 -209
- package/src/providers/integrations/buddy/workbuddy/quota.ts +0 -161
- package/src/providers/integrations/buddy/workbuddy/shared.ts +0 -285
- package/src/providers/operations/model-discovery-cache.ts +0 -34
- package/src/providers/operations/probe-fetch.ts +0 -15
- package/src/providers/operations/provider-version-cache.ts +0 -30
- package/src/providers/provider-capabilities.ts +0 -33
- package/src/providers/provider-credential-envelope.ts +0 -43
- /package/dist/dashboard/assets/{app-CTxoqyYB.js → app-DIXLjojg.js} +0 -0
- /package/dist/dashboard/assets/{app-CTxoqyYB.js.gz → app-DIXLjojg.js.gz} +0 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Hermes / Nous Portal OAuth client — RFC 8628 device flow + refresh.
|
|
2
|
+
//
|
|
3
|
+
// The Hermes Agent (Nous Research) offers a portal subscription via OAuth:
|
|
4
|
+
// `hermes setup --portal` runs a device-code flow against Nous Portal, and
|
|
5
|
+
// the resulting access token is an inference-scoped JWT spent on the
|
|
6
|
+
// OpenAI-compatible inference API. API keys still work for the free roster;
|
|
7
|
+
// this OAuth path is the subscription route (300+ models + paid tiers).
|
|
8
|
+
//
|
|
9
|
+
// Wire sourced from the official Hermes Agent source:
|
|
10
|
+
// - start: POST {portal}/api/oauth/device/code (form: client_id, scope)
|
|
11
|
+
// - poll: POST {portal}/api/oauth/token (form: grant_type=device_code,
|
|
12
|
+
// client_id, device_code) → {access_token, refresh_token, …}
|
|
13
|
+
// - refresh: POST {portal}/api/oauth/token (form: grant_type=refresh_token,
|
|
14
|
+
// client_id, refresh_token)
|
|
15
|
+
|
|
16
|
+
import { OAuthDeviceFlow } from "../../authentication/oauth-device-flow";
|
|
17
|
+
import type {
|
|
18
|
+
OAuthDeviceFlowContext,
|
|
19
|
+
OAuthDevicePollResult,
|
|
20
|
+
OAuthDeviceStartResult,
|
|
21
|
+
} from "../../authentication/oauth-flow-store";
|
|
22
|
+
import type { OAuthTokenRefreshResult } from "../../authentication/oauth-refresh-service";
|
|
23
|
+
import { postFormTokenRequest } from "../../authentication/oauth-flow-store";
|
|
24
|
+
|
|
25
|
+
const NOUS_PORTAL_URL = "https://portal.nousresearch.com";
|
|
26
|
+
const NOUS_CLIENT_ID = "hermes-cli";
|
|
27
|
+
const NOUS_SCOPE = "inference:invoke";
|
|
28
|
+
const NOUS_DEVICE_CODE_PATH = "/api/oauth/device/code";
|
|
29
|
+
const NOUS_TOKEN_PATH = "/api/oauth/token";
|
|
30
|
+
|
|
31
|
+
const FORM_HEADERS = { "content-type": "application/x-www-form-urlencoded", accept: "application/json" };
|
|
32
|
+
|
|
33
|
+
export class HermesOAuthClient extends OAuthDeviceFlow {
|
|
34
|
+
readonly supportsDeviceCode = true;
|
|
35
|
+
readonly supportsBrowserCode = false;
|
|
36
|
+
protected readonly providerLabel = "Hermes / Nous Portal";
|
|
37
|
+
protected readonly clientId = NOUS_CLIENT_ID;
|
|
38
|
+
protected readonly tokenUrl = `${NOUS_PORTAL_URL}${NOUS_TOKEN_PATH}`;
|
|
39
|
+
protected readonly scopes = NOUS_SCOPE;
|
|
40
|
+
|
|
41
|
+
override async startDeviceAuth(context?: OAuthDeviceFlowContext): Promise<OAuthDeviceStartResult> {
|
|
42
|
+
const started = await this.startGenericDeviceAuth({
|
|
43
|
+
tokenUrl: this.tokenUrl,
|
|
44
|
+
deviceAuthUrl: `${NOUS_PORTAL_URL}${NOUS_DEVICE_CODE_PATH}`,
|
|
45
|
+
clientId: NOUS_CLIENT_ID,
|
|
46
|
+
scope: NOUS_SCOPE,
|
|
47
|
+
formHeaders: FORM_HEADERS,
|
|
48
|
+
startParams: context?.parameters ?? {},
|
|
49
|
+
});
|
|
50
|
+
return { ...started, providerState: JSON.stringify({ device_code: started.deviceAuthId }) };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
override async pollDeviceAuth(
|
|
54
|
+
deviceAuthId: string,
|
|
55
|
+
_context?: OAuthDeviceFlowContext,
|
|
56
|
+
): Promise<OAuthDevicePollResult> {
|
|
57
|
+
// The generic poll posts the device code and parses RFC 8628 error codes
|
|
58
|
+
// (`authorization_pending`/`slow_down` → pending). Its `complete` result
|
|
59
|
+
// is already a normalized OAuthExchangeResult.
|
|
60
|
+
return this.pollGenericDeviceAuth(deviceAuthId, {
|
|
61
|
+
tokenUrl: this.tokenUrl,
|
|
62
|
+
deviceAuthUrl: `${NOUS_PORTAL_URL}${NOUS_DEVICE_CODE_PATH}`,
|
|
63
|
+
clientId: NOUS_CLIENT_ID,
|
|
64
|
+
scope: NOUS_SCOPE,
|
|
65
|
+
formHeaders: FORM_HEADERS,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
override async refresh(refreshToken: string, signal?: AbortSignal): Promise<OAuthTokenRefreshResult> {
|
|
70
|
+
const payload = await postFormTokenRequest({
|
|
71
|
+
url: this.tokenUrl,
|
|
72
|
+
fetchFn: this.fetchFn,
|
|
73
|
+
params: {
|
|
74
|
+
grant_type: "refresh_token",
|
|
75
|
+
client_id: NOUS_CLIENT_ID,
|
|
76
|
+
refresh_token: refreshToken,
|
|
77
|
+
},
|
|
78
|
+
headers: FORM_HEADERS,
|
|
79
|
+
signal,
|
|
80
|
+
label: "Hermes / Nous Portal token refresh",
|
|
81
|
+
});
|
|
82
|
+
const record = payload as Record<string, unknown>;
|
|
83
|
+
const access = typeof record["access_token"] === "string" ? record["access_token"] : "";
|
|
84
|
+
if (!access) throw new Error("Hermes / Nous Portal refresh returned no access_token");
|
|
85
|
+
const expiresIn = typeof record["expires_in"] === "number" ? record["expires_in"] : 3600;
|
|
86
|
+
return {
|
|
87
|
+
access,
|
|
88
|
+
...(typeof record["refresh_token"] === "string" ? { refresh: record["refresh_token"] as string } : {}),
|
|
89
|
+
expiresAt: new Date(Date.now() + expiresIn * 1000),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export const hermesOAuthClient = new HermesOAuthClient();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { CanonicalRequest } from "
|
|
2
|
-
import type { ProviderDispatchTarget } from "
|
|
3
|
-
import type { ApiKeyProviderSpec } from "
|
|
4
|
-
import { isRecord } from "
|
|
5
|
-
import { boundedUpstreamArray, boundedUpstreamNumber, sanitizeUpstreamLabel } from "
|
|
6
|
-
import { getHermesVersion } from "
|
|
7
|
-
import { clineReasoningReplayPrepares } from "
|
|
1
|
+
import type { CanonicalRequest } from "../../../protocol/canonical-model";
|
|
2
|
+
import type { ProviderDispatchTarget } from "../../provider-contracts";
|
|
3
|
+
import type { ApiKeyProviderSpec } from "../../configured-provider";
|
|
4
|
+
import { isRecord } from "../../../protocol/codecs";
|
|
5
|
+
import { boundedUpstreamArray, boundedUpstreamNumber, sanitizeUpstreamLabel } from "../../provider-sanitize";
|
|
6
|
+
import { getHermesVersion } from "../../operations/client-versions";
|
|
7
|
+
import { clineReasoningReplayPrepares } from "../buddy/buddy-chat-shared";
|
|
8
8
|
|
|
9
9
|
const HERMES_PROVIDER_ID = "hermes" as const;
|
|
10
10
|
|
|
@@ -57,8 +57,8 @@ function injectHermesTags(
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
import { defineModel } from "
|
|
61
|
-
import type { ModelDefinition } from "
|
|
60
|
+
import { defineModel } from "../../provider-model-definition";
|
|
61
|
+
import type { ModelDefinition } from "../../provider-model-definition";
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
64
|
* Offline fallback: the free rows as the live catalog last reported them.
|
|
@@ -78,28 +78,20 @@ export const HERMES_MODELS: readonly ModelDefinition[] = [
|
|
|
78
78
|
//
|
|
79
79
|
// `meituan/longcat-2.0:free` is excluded: the catalog still lists the id, but
|
|
80
80
|
// dispatching it answers 404 "This model is no longer free", so listing it
|
|
81
|
-
// would be a card that can only ever fail. `meituan/longcat-2.5
|
|
81
|
+
// would be a card that can only ever fail. `meituan/longcat-2.5:free`
|
|
82
82
|
// is listed instead and answers 200.
|
|
83
83
|
//
|
|
84
84
|
// `stepfun/step-5-preview:free` is excluded: it is absent from the live catalog
|
|
85
85
|
// entirely and dispatching it answers 404 "This model's free period has
|
|
86
86
|
// ended" — a retired row, not a capacity blip, so it cannot be left in.
|
|
87
87
|
//
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
// sibling `laguna-s` is 131072, so a uniform value overstates one of them.
|
|
91
|
-
defineModel({ id: "poolside/laguna-s-2.1:free", ctx: 262144, out: 131072, reasoning: true, free: true, freeTier: true }),
|
|
92
|
-
defineModel({ id: "poolside/laguna-xs-2.1:free", ctx: 262144, out: 32768, reasoning: true, free: true, freeTier: true }),
|
|
93
|
-
defineModel({ id: "stepfun/step-3.7-flash:free", ctx: 262144, out: 256000, vision: true, reasoning: true, free: true, freeTier: true }),
|
|
88
|
+
// `poolside/laguna-s-2.1:free`, `poolside/laguna-xs-2.1:free`, and
|
|
89
|
+
// `stepfun/step-3.7-flash:free` are removed too: they fail at dispatch.
|
|
94
90
|
defineModel({ id: "upstage/solar-mini4:free", ctx: 524288, out: 131072, reasoning: true, free: true, freeTier: true }),
|
|
95
91
|
defineModel({ id: "reflection/beam-1.0-501b-a23b:free", ctx: 262144, out: 131072, reasoning: true, free: true, freeTier: true }),
|
|
96
92
|
// Vision-corrected against the live catalog: `architecture.input_modalities`
|
|
97
93
|
// lists `image` for this row, so it was published without vision it has.
|
|
98
|
-
defineModel({ id: "meituan/longcat-2.5
|
|
99
|
-
// Added after a live read: the catalog carries it, it is free, and a dispatch
|
|
100
|
-
// answers 200 — it was simply absent from this list, so a client asking for
|
|
101
|
-
// it resolved to nothing. 262144 out is the catalog's own cap.
|
|
102
|
-
defineModel({ id: "ornith/ornith-1.5-122b:free", ctx: 262144, out: 262144, vision: true, reasoning: true, free: true, freeTier: true }),
|
|
94
|
+
defineModel({ id: "meituan/longcat-2.5:free", ctx: 1048576, out: 131072, vision: true, reasoning: true, free: true, freeTier: true }),
|
|
103
95
|
];
|
|
104
96
|
|
|
105
97
|
|
|
@@ -15,6 +15,22 @@ export const KIRO_GENERATE_PATH = "/generateAssistantResponse" as const;
|
|
|
15
15
|
/** AWS region shape, checked before a region is interpolated into a URL. */
|
|
16
16
|
export const AWS_REGION_PATTERN = /^[a-z]{2}-[a-z]+-\d{1,2}$/;
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Maps an auth method onto the `TokenType` header the 1.4.62 client sends.
|
|
20
|
+
*
|
|
21
|
+
* Observed map (`qje`): `api_key → API_KEY`, `external_idp → EXTERNAL_IDP`,
|
|
22
|
+
* `idc → SSO_OIDC`, `machine_token → KIRO_MACHINE_TOKEN`. Google/GitHub/
|
|
23
|
+
* Builder-ID sessions send no `TokenType` header. Every surface (dispatch,
|
|
24
|
+
* usage, discovery) must classify the same account identically or the upstream
|
|
25
|
+
* sees one credential as different token types across surfaces.
|
|
26
|
+
*/
|
|
27
|
+
export function kiroTokenTypeHeader(authMethod: string | undefined): string | undefined {
|
|
28
|
+
if (authMethod === "api_key") return "API_KEY";
|
|
29
|
+
if (authMethod === "external_idp") return "EXTERNAL_IDP";
|
|
30
|
+
if (authMethod === "idc") return "SSO_OIDC";
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
18
34
|
/** Fallback region when no (or an invalid) region is configured. */
|
|
19
35
|
export const KIRO_DEFAULT_REGION = "us-east-1" as const;
|
|
20
36
|
|
|
@@ -37,7 +53,7 @@ export const KIRO_MANAGEMENT_HOST_TEMPLATE = "https://management.{region}.kiro.d
|
|
|
37
53
|
* The upstream has no `minimal` or `max` tier on either schema, so the ladder
|
|
38
54
|
* stops at `xhigh` and the builder maps the canonical extremes onto it.
|
|
39
55
|
*/
|
|
40
|
-
const KIRO_EFFORTS = ["low", "medium", "high", "xhigh"] as const;
|
|
56
|
+
export const KIRO_EFFORTS = ["low", "medium", "high", "xhigh"] as const;
|
|
41
57
|
|
|
42
58
|
/**
|
|
43
59
|
* One Kiro model row.
|
|
@@ -22,14 +22,19 @@ import {
|
|
|
22
22
|
} from "../../operations/client-versions";
|
|
23
23
|
import { machineIdForAuthState } from "./kiro-machine-id";
|
|
24
24
|
import { resolveKiroProfileArn } from "./kiro-profile";
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
AWS_REGION_PATTERN,
|
|
27
|
+
KIRO_DEFAULT_REGION,
|
|
28
|
+
KIRO_EFFORTS,
|
|
29
|
+
KIRO_GENERATE_PATH,
|
|
30
|
+
KIRO_MODELS,
|
|
31
|
+
KIRO_MANAGEMENT_HOST_TEMPLATE,
|
|
32
|
+
kiroTokenTypeHeader,
|
|
33
|
+
} from "./kiro-catalog";
|
|
26
34
|
|
|
27
35
|
/** Longest model list this will read; the upstream sends a few dozen at most. */
|
|
28
36
|
const MAX_DISCOVERED_MODELS = 500;
|
|
29
37
|
|
|
30
|
-
/** Effort tiers the models that accept an effort field advertise. */
|
|
31
|
-
const KIRO_EFFORTS = ["low", "medium", "high", "xhigh"] as const;
|
|
32
|
-
|
|
33
38
|
/** The management service target used in `x-amz-target`. */
|
|
34
39
|
const KIRO_MANAGEMENT_TARGET = "KiroControlPlaneBearerService.ListAvailableModels" as const;
|
|
35
40
|
|
|
@@ -105,14 +110,7 @@ export async function fetchKiroModels(
|
|
|
105
110
|
// `TokenType`; social/Builder-ID sessions send none. Mirror the client's
|
|
106
111
|
// `qje` map and the probe verified against the live service.
|
|
107
112
|
const authMethod = options.authState?.["authMethod"];
|
|
108
|
-
const tokenType =
|
|
109
|
-
authMethod === "api_key"
|
|
110
|
-
? "API_KEY"
|
|
111
|
-
: authMethod === "external_idp"
|
|
112
|
-
? "EXTERNAL_IDP"
|
|
113
|
-
: authMethod === "idc"
|
|
114
|
-
? "SSO_OIDC"
|
|
115
|
-
: undefined;
|
|
113
|
+
const tokenType = kiroTokenTypeHeader(typeof authMethod === "string" ? authMethod : undefined);
|
|
116
114
|
if (tokenType !== undefined) headers["TokenType"] = tokenType;
|
|
117
115
|
response = await fetcher(`${host}/List-Available-Models?${params.toString()}`, {
|
|
118
116
|
headers,
|
|
@@ -34,7 +34,12 @@ import {
|
|
|
34
34
|
} from "../../operations/client-versions";
|
|
35
35
|
import { machineIdForAuthState } from "./kiro-machine-id";
|
|
36
36
|
import { resolveKiroProfileArn } from "./kiro-profile";
|
|
37
|
-
import {
|
|
37
|
+
import {
|
|
38
|
+
AWS_REGION_PATTERN,
|
|
39
|
+
KIRO_DEFAULT_REGION,
|
|
40
|
+
KIRO_MANAGEMENT_HOST_TEMPLATE,
|
|
41
|
+
kiroTokenTypeHeader,
|
|
42
|
+
} from "./kiro-catalog";
|
|
38
43
|
|
|
39
44
|
/**
|
|
40
45
|
* The fetcher shape this module needs: a plain callable. `FetchLike` from the
|
|
@@ -82,9 +87,8 @@ function usageHeaders(credential: string, auth: KiroQuotaAuth): Record<string, s
|
|
|
82
87
|
"user-agent": buildKiroRuntimeUserAgent(version, auth.machineId),
|
|
83
88
|
"x-kiro-machineid": auth.machineId,
|
|
84
89
|
};
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
else if (auth.authMethod === "idc") headers["TokenType"] = "SSO_OIDC";
|
|
90
|
+
const tokenType = kiroTokenTypeHeader(auth.authMethod);
|
|
91
|
+
if (tokenType !== undefined) headers["TokenType"] = tokenType;
|
|
88
92
|
return headers;
|
|
89
93
|
}
|
|
90
94
|
|
|
@@ -59,6 +59,7 @@ import {
|
|
|
59
59
|
kiroContextWindow,
|
|
60
60
|
KIRO_GENERATE_PATH,
|
|
61
61
|
KIRO_RUNTIME_HOST_TEMPLATE,
|
|
62
|
+
kiroTokenTypeHeader,
|
|
62
63
|
} from "./kiro-catalog";
|
|
63
64
|
import { resolveInboundSessionId } from "../../operations/session-resolution";
|
|
64
65
|
import { KiroStreamDecoder, isKiroTruncationReason, type KiroUsage } from "./kiro-stream";
|
|
@@ -180,19 +181,6 @@ export function kiroEndpoint(authState: KiroAuthState | undefined): string {
|
|
|
180
181
|
*/
|
|
181
182
|
export const KIRO_RUNTIME_AWS_JSON_TARGET = "KiroRuntimeService.GenerateAssistantResponse" as const;
|
|
182
183
|
|
|
183
|
-
/**
|
|
184
|
-
* Maps an auth method onto the `TokenType` header the 1.4.62 client sends.
|
|
185
|
-
*
|
|
186
|
-
* Observed map (`qje`): `api_key → API_KEY`, `external_idp → EXTERNAL_IDP`,
|
|
187
|
-
* `idc → SSO_OIDC`, `machine_token → KIRO_MACHINE_TOKEN`. Google/GitHub/
|
|
188
|
-
* Builder-ID sessions send no `TokenType` header.
|
|
189
|
-
*/
|
|
190
|
-
const KIRO_TOKEN_TYPE: Readonly<Record<string, string>> = {
|
|
191
|
-
api_key: "API_KEY",
|
|
192
|
-
external_idp: "EXTERNAL_IDP",
|
|
193
|
-
idc: "SSO_OIDC",
|
|
194
|
-
};
|
|
195
|
-
|
|
196
184
|
/**
|
|
197
185
|
* Builds the request headers.
|
|
198
186
|
*
|
|
@@ -230,7 +218,7 @@ export function kiroHeaders(
|
|
|
230
218
|
"x-amz-user-agent": buildKiroAmzUserAgent(version, machineId),
|
|
231
219
|
authorization: `Bearer ${secret}`,
|
|
232
220
|
};
|
|
233
|
-
const tokenType = authMethod
|
|
221
|
+
const tokenType = kiroTokenTypeHeader(authMethod);
|
|
234
222
|
if (tokenType !== undefined) {
|
|
235
223
|
headers["TokenType"] = tokenType;
|
|
236
224
|
}
|
|
@@ -377,9 +365,17 @@ class KiroAdapter implements ProviderAdapter {
|
|
|
377
365
|
effortPath !== undefined
|
|
378
366
|
? undefined
|
|
379
367
|
: (request.reasoning?.budget_tokens ?? kiroThinkingBudgetForEffort(requestedEffort));
|
|
368
|
+
// One resolution per dispatch: the resolver mints a fresh UUID only when
|
|
369
|
+
// the request carries no session, conversation id, or derivable opening
|
|
370
|
+
// turn, so resolving twice here would give `conversationId` and
|
|
371
|
+
// `rootConversationId` two different UUIDs — contradicting the client rule
|
|
372
|
+
// (`rootConversationId ?? conversationId`). The same id feeds the session
|
|
373
|
+
// cache estimator at stream end, so its key matches what the request
|
|
374
|
+
// presented upstream.
|
|
375
|
+
const conversationId = resolveKiroConversationId(request, context);
|
|
380
376
|
const built = buildKiroWireRequest(request, {
|
|
381
|
-
conversationId
|
|
382
|
-
rootConversationId:
|
|
377
|
+
conversationId,
|
|
378
|
+
rootConversationId: conversationId,
|
|
383
379
|
modelId,
|
|
384
380
|
profileArn: resolveProfileArn(context),
|
|
385
381
|
...(effortPath === undefined || effort === undefined ? {} : { effortPath, effort }),
|
|
@@ -414,7 +410,7 @@ class KiroAdapter implements ProviderAdapter {
|
|
|
414
410
|
}, "upstream");
|
|
415
411
|
}
|
|
416
412
|
|
|
417
|
-
yield* this.#stream(response.body, built.value, request,
|
|
413
|
+
yield* this.#stream(response.body, built.value, request, conversationId);
|
|
418
414
|
}
|
|
419
415
|
|
|
420
416
|
/**
|
|
@@ -471,7 +467,7 @@ class KiroAdapter implements ProviderAdapter {
|
|
|
471
467
|
stream: ReadableStream<Uint8Array>,
|
|
472
468
|
built: KiroWireRequest,
|
|
473
469
|
request: CanonicalRequest,
|
|
474
|
-
|
|
470
|
+
conversationId: string,
|
|
475
471
|
): AsyncIterable<CanonicalEvent> {
|
|
476
472
|
const decoder = new KiroStreamDecoder();
|
|
477
473
|
const reader = stream.getReader();
|
|
@@ -605,7 +601,7 @@ class KiroAdapter implements ProviderAdapter {
|
|
|
605
601
|
reader.releaseLock();
|
|
606
602
|
}
|
|
607
603
|
|
|
608
|
-
const finalUsage = kiroUsage(usage, request.model, outputText, request.messages,
|
|
604
|
+
const finalUsage = kiroUsage(usage, request.model, outputText, request.messages, conversationId);
|
|
609
605
|
yield {
|
|
610
606
|
type: "usage",
|
|
611
607
|
sequence_number: sequence++,
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
* All six serve the chat wire (none is a Responses-native id), and all report
|
|
17
17
|
* `supported_in_api: true` on the live roster.
|
|
18
18
|
*/
|
|
19
|
-
import { defineModel } from "
|
|
20
|
-
import type { ModelDefinition } from "
|
|
19
|
+
import { defineModel } from "../../provider-model-definition";
|
|
20
|
+
import type { ModelDefinition } from "../../provider-model-definition";
|
|
21
21
|
|
|
22
22
|
export const OLLAMACLOUD_PROVIDER_ID = "ollamacloud" as const;
|
|
23
23
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { FetchLike, ProviderQuotaResult } from "
|
|
2
|
-
import { getJson, record, text } from "
|
|
3
|
-
import { parseQuotaWindows } from "
|
|
1
|
+
import type { FetchLike, ProviderQuotaResult } from "../../quota/quota-contracts";
|
|
2
|
+
import { getJson, record, text } from "../../quota/quota-contracts";
|
|
3
|
+
import { parseQuotaWindows } from "../../quota/quota-window-parser";
|
|
4
4
|
|
|
5
5
|
async function fetchPlan(fetcher: FetchLike, headers: Record<string, string>): Promise<string> {
|
|
6
6
|
try {
|
|
@@ -9,7 +9,7 @@ import { createHash, randomBytes } from "node:crypto";
|
|
|
9
9
|
* can pin the exact identity sent before discovery resolves. Keep both in
|
|
10
10
|
* lockstep when the CLI releases.
|
|
11
11
|
*/
|
|
12
|
-
export const OPENCODE_CLIENT_VERSION = "2.2.
|
|
12
|
+
export const OPENCODE_CLIENT_VERSION = "2.2.6";
|
|
13
13
|
|
|
14
14
|
let lastTimestamp = 0;
|
|
15
15
|
let sequenceCounter = 0;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getJson,
|
|
3
|
+
isoDate,
|
|
3
4
|
type FetchLike,
|
|
4
5
|
type ProviderQuotaResult,
|
|
5
6
|
type ProviderQuotaWindow,
|
|
@@ -42,13 +43,6 @@ function labelFor(kind: string): string {
|
|
|
42
43
|
return kind.charAt(0).toUpperCase() + kind.slice(1);
|
|
43
44
|
}
|
|
44
45
|
|
|
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
46
|
/**
|
|
53
47
|
* One window, or `undefined` when the upstream omitted what makes it usable.
|
|
54
48
|
*
|
|
@@ -75,7 +69,7 @@ function windowFor(
|
|
|
75
69
|
accounting: "independent",
|
|
76
70
|
usedPercent: percent,
|
|
77
71
|
remainingPercent: 100 - percent,
|
|
78
|
-
resetsAt:
|
|
72
|
+
resetsAt: isoDate(raw.resetsAt),
|
|
79
73
|
};
|
|
80
74
|
}
|
|
81
75
|
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// Perch model roster.
|
|
2
|
+
//
|
|
3
|
+
// Perch's hosted model layer ("Roost") exposes tier labels rather than raw
|
|
4
|
+
// model ids: `standard` and `standard_max` are the tiers included in the free
|
|
5
|
+
// Starter plan. In addition, the plan pins a small "Starter" model pool
|
|
6
|
+
// (`PERCH_STARTER_PINS`) whose pins are verified live 2026-11-08:
|
|
7
|
+
// `glm-5.3-flash-starter`, `deepseek-flash-starter`, and `crouton-alpha`
|
|
8
|
+
// answer 200 and the server reports the pinned backing model; `beam` was not
|
|
9
|
+
// verified (turn rate limit). Paid `pro` tiers are deliberately absent.
|
|
10
|
+
//
|
|
11
|
+
// Model ids here are the gateway-facing ids; the adapter maps them to the
|
|
12
|
+
// upstream wire (Roost tier + backing pin) via `PERCH_STARTER_PINS` /
|
|
13
|
+
// `roostModelChoice` — the upstream itself hides real model names.
|
|
14
|
+
|
|
15
|
+
import { defineModel, type ModelDefinition } from "../../provider-model-definition";
|
|
16
|
+
import {
|
|
17
|
+
PERCH_CONTEXT_STANDARD,
|
|
18
|
+
PERCH_CONTEXT_STANDARD_1M,
|
|
19
|
+
PERCH_PROVIDER_ID,
|
|
20
|
+
PERCH_STARTER_PINS,
|
|
21
|
+
} from "./perch-realm";
|
|
22
|
+
|
|
23
|
+
interface PerchRow {
|
|
24
|
+
readonly id: string;
|
|
25
|
+
readonly displayName: string;
|
|
26
|
+
readonly ctx: number;
|
|
27
|
+
/**
|
|
28
|
+
* Output ceiling. When absent it falls back to the CLI's `sUr` resolution
|
|
29
|
+
* (`perchOutputTokens`); starter-pool rows carry the client card's own
|
|
30
|
+
* `maxOutputTokens` (2.4.125) so a big request is not clamped below what
|
|
31
|
+
* the upstream actually serves.
|
|
32
|
+
*/
|
|
33
|
+
readonly out?: number;
|
|
34
|
+
/** `undefined` = plain Roost tier; else starter-pool pin id. */
|
|
35
|
+
readonly pin?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Roost tier sent for the plain tier rows (CLI canonical tier ids). */
|
|
39
|
+
const TIER_ROOST_TIERS: Readonly<Record<string, string>> = {
|
|
40
|
+
standard: "standard",
|
|
41
|
+
"standard 1m": "standard_max",
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const PERCH_ROWS: readonly PerchRow[] = [
|
|
45
|
+
{ id: "standard", displayName: "Roost Standard", ctx: PERCH_CONTEXT_STANDARD },
|
|
46
|
+
{ id: "standard 1m", displayName: "Roost Standard 1M", ctx: PERCH_CONTEXT_STANDARD_1M },
|
|
47
|
+
// Starter-pool pins — context/output per the client's published cards
|
|
48
|
+
// (2.4.125): glm-5.3-flash 1048576, crouton-alpha 1048576 / 943718,
|
|
49
|
+
// beam-1.0 1048576 / 131072, deepseek-v4.1-flash-1017-starter 1048576 /
|
|
50
|
+
// 131072.
|
|
51
|
+
{ id: "glm-5.3-flash-starter", displayName: "GLM 5.3 Flash (Starter)", ctx: PERCH_CONTEXT_STANDARD_1M, out: 131_072, pin: "glm-5.3-flash-starter" },
|
|
52
|
+
{ id: "deepseek-flash-starter", displayName: "DeepSeek V4.1 Flash 1017 (Starter)", ctx: PERCH_CONTEXT_STANDARD_1M, out: 131_072, pin: "deepseek-flash-starter" },
|
|
53
|
+
{ id: "crouton-alpha", displayName: "Crouton Alpha (Stealth)", ctx: PERCH_CONTEXT_STANDARD_1M, out: 943_718, pin: "crouton-alpha" },
|
|
54
|
+
{ id: "beam-1.0-starter", displayName: "Beam 1.0 (Starter)", ctx: PERCH_CONTEXT_STANDARD_1M, out: 131_072, pin: "beam-1.0-starter" },
|
|
55
|
+
// Pinned 1M tier: the CLI normalizes `standard 1m` → `standard_max`; the
|
|
56
|
+
// adapter keys `roostModelChoice` off the catalog id so the right tier is
|
|
57
|
+
// sent even though the id is a label.
|
|
58
|
+
{ id: "standard 1m", displayName: "Roost Standard 1M", ctx: PERCH_CONTEXT_STANDARD_1M, pin: "standard-max" },
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Output cap per model, mirroring the CLI's own resolution (`sUr` in the
|
|
63
|
+
* bundled `perch.mjs`): up to 8k context → 4096, up to 32k → 8192, above
|
|
64
|
+
* 32k → 32768. Derive per model from its context window, never hardcode.
|
|
65
|
+
*/
|
|
66
|
+
function perchOutputTokens(contextWindow: number): number {
|
|
67
|
+
if (contextWindow <= 8_000) return 4_096;
|
|
68
|
+
if (contextWindow <= 32_000) return 8_192;
|
|
69
|
+
return 32_768;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const PERCH_MODELS: readonly ModelDefinition[] = PERCH_ROWS.map((row) =>
|
|
73
|
+
defineModel({
|
|
74
|
+
id: row.id,
|
|
75
|
+
providerId: PERCH_PROVIDER_ID,
|
|
76
|
+
wireFamily: "chat",
|
|
77
|
+
endpoint: "/api/perch-terminal/model-call",
|
|
78
|
+
ctx: row.ctx,
|
|
79
|
+
out: row.out ?? perchOutputTokens(row.ctx),
|
|
80
|
+
// The tier surfaces are chat-text; no modality claims beyond that. No
|
|
81
|
+
// `free`/`freeTier` flag is set: the upstream does not expose a
|
|
82
|
+
// per-model plan list (cli-plan only reports planRequired), and a free
|
|
83
|
+
// claim would be an unverified assertion rather than upstream truth.
|
|
84
|
+
vision: false,
|
|
85
|
+
reasoning: false,
|
|
86
|
+
toolCall: false,
|
|
87
|
+
}),
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
/** Model-id → starter pin, for the adapter's dispatch-time lookup. */
|
|
91
|
+
export const PERCH_MODEL_PINS: Readonly<Record<string, string | undefined>> = Object.fromEntries(
|
|
92
|
+
PERCH_ROWS.map((row) => [row.id, row.pin]),
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
/** Model-id → Roost tier, for the adapter's dispatch-time lookup. */
|
|
96
|
+
export const PERCH_MODEL_ROOST_TIERS: Readonly<Record<string, string>> = Object.fromEntries(
|
|
97
|
+
PERCH_ROWS.map((row) => [
|
|
98
|
+
row.id,
|
|
99
|
+
row.pin === undefined
|
|
100
|
+
? TIER_ROOST_TIERS[row.id] ?? "standard"
|
|
101
|
+
: row.pin === "standard-max"
|
|
102
|
+
? "standard_max"
|
|
103
|
+
: PERCH_STARTER_PINS[row.pin]?.roostTier ?? "standard",
|
|
104
|
+
]),
|
|
105
|
+
);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Perch credential-envelope parsing.
|
|
2
|
+
//
|
|
3
|
+
// Perch accounts authenticate via Supabase OAuth (PKCE), and the stored secret
|
|
4
|
+
// is the OAuth envelope JSON with `accessToken` (or `access_token`). Both the
|
|
5
|
+
// dispatch adapter and the quota collector need the access token out of that
|
|
6
|
+
// envelope; the parse is shared here and each surface keeps its own fallback
|
|
7
|
+
// for a secret that is not an envelope.
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Reads the access token out of a stored Perch OAuth envelope.
|
|
11
|
+
*
|
|
12
|
+
* Returns the token when the secret parses as JSON and carries `accessToken`
|
|
13
|
+
* (or `access_token`) as a string; `null` when it is not such an envelope
|
|
14
|
+
* (not JSON, or JSON without a token field). The caller decides what a
|
|
15
|
+
* `null` means for its surface.
|
|
16
|
+
*/
|
|
17
|
+
export function parsePerchCredentialToken(secret: string): string | null {
|
|
18
|
+
try {
|
|
19
|
+
const parsed = JSON.parse(secret) as Record<string, unknown>;
|
|
20
|
+
const found = parsed["accessToken"] ?? parsed["access_token"];
|
|
21
|
+
return typeof found === "string" ? found : null;
|
|
22
|
+
} catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|