cartethyia 2.7.9 → 2.8.1
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 +6 -5
- package/dist/dashboard/assets/{BannedPage-BxoG1MrL.js → BannedPage-Dq530awD.js} +1 -1
- package/dist/dashboard/assets/BannedPage-Dq530awD.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-ixwgKk53.js → CliToolDetailPage-DZzaS-7S.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-DZzaS-7S.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-BmttNV3U.js → CliToolsPage-DaZZ3cqP.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-DaZZ3cqP.js.gz +0 -0
- package/dist/dashboard/assets/{CombosPage-BE3qwwfC.js → CombosPage-BlC_xdkX.js} +1 -1
- package/dist/dashboard/assets/CombosPage-BlC_xdkX.js.gz +0 -0
- package/dist/dashboard/assets/{ConsoleLogPage-CRZdmMIX.js → ConsoleLogPage-D-rqeVtG.js} +1 -1
- package/dist/dashboard/assets/ConsoleLogPage-D-rqeVtG.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-Dv_FJ6Er.js → CustomizationPage-7xT5yg2E.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-7xT5yg2E.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-Clq8E9cW.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-Clq8E9cW.js.gz +0 -0
- package/dist/dashboard/assets/{InjectSystemPromptPanel-BOoO8rpz.js → InjectSystemPromptPanel-6Teoq9Se.js} +2 -2
- package/dist/dashboard/assets/InjectSystemPromptPanel-6Teoq9Se.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-ChJuNNVN.js → LoginPage-CZuI0MAR.js} +1 -1
- package/dist/dashboard/assets/LoginPage-CZuI0MAR.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BZAJtPg1.js → ModelPicker-C1hNTlkr.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-C1hNTlkr.js.gz +0 -0
- package/dist/dashboard/assets/{OverviewPage-BE40s3u5.js → OverviewPage-0yfhSI1C.js} +1 -1
- package/dist/dashboard/assets/OverviewPage-0yfhSI1C.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-xqTxdQ4c.js +8 -0
- package/dist/dashboard/assets/ProviderDetailPage-xqTxdQ4c.js.gz +0 -0
- package/dist/dashboard/assets/{ProviderIcon-CQ6bPUf_.js → ProviderIcon-Ddhm1InL.js} +1 -1
- package/dist/dashboard/assets/ProviderIcon-Ddhm1InL.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-C3fYuu6i.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-C3fYuu6i.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-CHtJtZ3u.js +9 -0
- package/dist/dashboard/assets/ProxyPage-CHtJtZ3u.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-D1RV_2BX.js +1 -0
- package/dist/dashboard/assets/QuotaPage-D1RV_2BX.js.gz +0 -0
- package/dist/dashboard/assets/{SettingsPage-C5HPWqEv.js → SettingsPage-BzZAvYSX.js} +1 -1
- package/dist/dashboard/assets/SettingsPage-BzZAvYSX.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-CFNcATJJ.js → SetupPage--s-EfEIL.js} +1 -1
- package/dist/dashboard/assets/SetupPage--s-EfEIL.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-YoD4tY5l.js → StudioPage-BjXFGSK4.js} +1 -1
- package/dist/dashboard/assets/StudioPage-BjXFGSK4.js.gz +0 -0
- package/dist/dashboard/assets/{UsagePage-DxjaAhb_.js → UsagePage-CP8F8BN7.js} +1 -1
- package/dist/dashboard/assets/UsagePage-CP8F8BN7.js.gz +0 -0
- package/dist/dashboard/assets/{api-keys-BTlkq_Uk.js → api-keys-2hc12Uz2.js} +1 -1
- package/dist/dashboard/assets/api-keys-2hc12Uz2.js.gz +0 -0
- package/dist/dashboard/assets/app-DGXbNfAR.css +2 -0
- package/dist/dashboard/assets/app-DGXbNfAR.css.gz +0 -0
- package/dist/dashboard/assets/assert-BMcj1xZE.js +1 -0
- package/dist/dashboard/assets/assert-BMcj1xZE.js.gz +0 -0
- package/dist/dashboard/assets/{badge-DdbT_7Am.js → badge-DkRUuVfz.js} +1 -1
- package/dist/dashboard/assets/badge-DkRUuVfz.js.gz +0 -0
- package/dist/dashboard/assets/{banner-CsGN-nbm.js → banner-CDjW841Q.js} +1 -1
- package/dist/dashboard/assets/banner-CDjW841Q.js.gz +0 -0
- package/dist/dashboard/assets/{card-mgZ_TLLZ.js → card-Bto5UlL9.js} +1 -1
- package/dist/dashboard/assets/card-Bto5UlL9.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-A1-v8-03.js → cli-tools-DaH6g9hL.js} +1 -1
- package/dist/dashboard/assets/cli-tools-DaH6g9hL.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-CJ4Zty89.js → clipboard-button-BYKBCzjk.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-BYKBCzjk.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-B5L2jPQ_.js → dialog-DL0Zftwv.js} +1 -1
- package/dist/dashboard/assets/dialog-DL0Zftwv.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-DkjUouAj.js → drawer-Dpx_UXaS.js} +1 -1
- package/dist/dashboard/assets/drawer-Dpx_UXaS.js.gz +0 -0
- package/dist/dashboard/assets/{entry-B-LVLV6o.js → entry-BV7-1NoM.js} +1 -1
- package/dist/dashboard/assets/entry-BV7-1NoM.js.gz +0 -0
- package/dist/dashboard/assets/{entry-CAhdYl3B.js → entry-CGvdNU6r.js} +1 -1
- package/dist/dashboard/assets/entry-CGvdNU6r.js.gz +0 -0
- package/dist/dashboard/assets/entry-DScKYvZj.js +4 -0
- package/dist/dashboard/assets/entry-DScKYvZj.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-CrsdLVsn.js → formatters-BS3DZlZj.js} +1 -1
- package/dist/dashboard/assets/formatters-BS3DZlZj.js.gz +0 -0
- package/dist/dashboard/assets/{index-BU64Lqvp.js → index-SQnvvTWX.js} +2 -2
- package/dist/dashboard/assets/index-SQnvvTWX.js.gz +0 -0
- package/dist/dashboard/assets/{inline-B2aDLyyg.js → inline-Dl-cuLK0.js} +1 -1
- package/dist/dashboard/assets/inline-Dl-cuLK0.js.gz +0 -0
- package/dist/dashboard/assets/{input-BCVkdR9d.js → input-Bfx0EzRc.js} +1 -1
- package/dist/dashboard/assets/input-Bfx0EzRc.js.gz +0 -0
- package/dist/dashboard/assets/{layout-DNcAdMK-.js → layout-BxhbQ_JS.js} +1 -1
- package/dist/dashboard/assets/layout-BxhbQ_JS.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-DgrIH0hw.js → list-row-D49Y4ptn.js} +1 -1
- package/dist/dashboard/assets/list-row-D49Y4ptn.js.gz +0 -0
- package/dist/dashboard/assets/{live-Cae01iu8.js → live-CbVTdX9V.js} +1 -1
- package/dist/dashboard/assets/live-CbVTdX9V.js.gz +0 -0
- package/dist/dashboard/assets/{network-CRib7H_2.js → network-JGvDveof.js} +1 -1
- package/dist/dashboard/assets/network-JGvDveof.js.gz +0 -0
- package/dist/dashboard/assets/{numbers-BKQE8Xpz.js → numbers-Dw6kiew-.js} +1 -1
- package/dist/dashboard/assets/numbers-Dw6kiew-.js.gz +0 -0
- package/dist/dashboard/assets/{pagination-ecPvG_8g.js → pagination-iUoI8GeE.js} +1 -1
- package/dist/dashboard/assets/pagination-iUoI8GeE.js.gz +0 -0
- package/dist/dashboard/assets/providers/sensenova-intl.png +0 -0
- package/dist/dashboard/assets/providers/sensenova.png +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/quota-DiPD6UKH.js +1 -0
- package/dist/dashboard/assets/quota-DiPD6UKH.js.gz +0 -0
- package/dist/dashboard/assets/{routing-Ckm1UXuC.js → routing-8jZr-3WE.js} +1 -1
- package/dist/dashboard/assets/routing-8jZr-3WE.js.gz +0 -0
- package/dist/dashboard/assets/{select-ChoFWyKz.js → select-oO1FxMVb.js} +2 -2
- package/dist/dashboard/assets/select-oO1FxMVb.js.gz +0 -0
- package/dist/dashboard/assets/{settings-CKjFPlKW.js → settings-CLr3kdIx.js} +1 -1
- package/dist/dashboard/assets/settings-CLr3kdIx.js.gz +0 -0
- package/dist/dashboard/assets/{stack-DWCwU3fh.js → stack-Y3pDteZr.js} +1 -1
- package/dist/dashboard/assets/stack-Y3pDteZr.js.gz +0 -0
- package/dist/dashboard/assets/{state-Cg3VL5J_.js → state-CArX_Iak.js} +1 -1
- package/dist/dashboard/assets/state-CArX_Iak.js.gz +0 -0
- package/dist/dashboard/assets/{switch-Db70BMix.js → switch-DwlwmDO-.js} +1 -1
- package/dist/dashboard/assets/switch-DwlwmDO-.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-BqdE0LuM.js → useMutation-DJ9GYEgf.js} +1 -1
- package/dist/dashboard/assets/useMutation-DJ9GYEgf.js.gz +0 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +54 -53
- package/migrations/full-postgres/0046_add_accounts_quota_plan_fetched_at.sql +7 -0
- package/migrations/full-postgres/0047_add_provider_device_flow_proxy.sql +17 -0
- package/migrations/lite-sqlite3/0046_add_accounts_quota_plan_fetched_at.sql +4 -0
- package/migrations/lite-sqlite3/0047_add_provider_device_flow_proxy.sql +19 -0
- package/package.json +1 -1
- package/src/boot/app.ts +11 -14
- package/src/boot/dependencies.ts +5 -7
- package/src/boot/flush.ts +20 -0
- package/src/boot/lifecycle.ts +7 -5
- package/src/config/providers.ts +6 -5
- package/src/config/routing.ts +26 -0
- package/src/config/spec-metadata.ts +72 -0
- package/src/config/spec.ts +28 -8
- package/src/console/api-keys/contracts.ts +12 -1
- package/src/console/api-keys/routes.ts +40 -28
- 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/backup/nine-router.ts +71 -10
- package/src/console/backup/service.ts +8 -1
- package/src/console/cli-tools/service.ts +6 -12
- package/src/console/console-router-guards.ts +23 -16
- package/src/console/console-router.ts +1 -1
- package/src/console/domain-registration.ts +7 -4
- package/src/console/inferhub/client.ts +1 -1
- package/src/console/inferhub/normalize.ts +24 -28
- package/src/console/inferhub/types.ts +3 -0
- package/src/console/ip-bans/routes.ts +7 -13
- package/src/console/observability/live.ts +2 -2
- package/src/console/observability/store.ts +0 -53
- package/src/console/providers/catalog/contracts.ts +9 -3
- package/src/console/providers/catalog/model-operations.ts +2 -3
- package/src/console/providers/catalog/provider-operations.ts +1 -1
- package/src/console/providers/catalog/routes.ts +3 -2
- package/src/console/providers/catalog/store.ts +1914 -1902
- package/src/console/providers/detail/routes.ts +1 -0
- package/src/console/providers/detail/store.ts +4 -0
- package/src/console/providers/oauth/callback-listener.ts +30 -11
- package/src/console/providers/oauth/device-egress.ts +123 -0
- package/src/console/providers/oauth/routes.ts +123 -16
- package/src/console/quota/account-quota-global.ts +14 -24
- package/src/console/quota/account-quota-shared.ts +49 -0
- package/src/console/quota/account-quota-tenant.ts +11 -23
- package/src/console/quota/account-test-egress.ts +2 -2
- package/src/console/quota/daily-growth-job.ts +1 -1
- package/src/console/quota/quota-view.ts +19 -3
- package/src/console/routing/pools/contracts.ts +1 -1
- package/src/console/routing/pools/operations.ts +32 -47
- package/src/console/routing/pools/probe-verdict.ts +2 -2
- package/src/console/routing/pools/relay-deploy.ts +1 -1
- package/src/console/routing/pools/store.ts +4 -4
- package/src/console/shared/errors.ts +33 -6
- package/src/main.ts +2 -3
- package/src/network/client.ts +67 -0
- package/src/network/egress/bidi-session.ts +322 -0
- package/src/network/egress/dial.ts +201 -0
- package/src/network/egress/factory.ts +191 -0
- package/src/network/{outbound-fetch.ts → egress/fetch.ts} +195 -29
- package/src/network/egress/tls-profile.ts +123 -0
- package/src/network/egress/ws.ts +175 -0
- package/src/network/pool/{byte-accounting.ts → accounting.ts} +3 -2
- package/src/network/{types.ts → pool/agent-config.ts} +1 -1
- package/src/network/pool/agent.ts +2 -2
- package/src/network/{pool-cooldown-store.ts → pool/cooldown-store.ts} +95 -20
- package/src/network/{pool-health-machine.ts → pool/health.ts} +205 -6
- package/src/network/pool/resolver.ts +10 -849
- package/src/network/pool/selector.ts +184 -41
- package/src/network/ssrf.ts +7 -7
- package/src/network/{retry.ts → util/retry.ts} +1 -1
- package/src/network/{rate-limit-verdict.ts → verdict.ts} +1 -1
- package/src/observability/event-log.ts +7 -361
- package/src/observability/performance-metrics.ts +9 -0
- package/src/observability/runtime-metrics.ts +14 -9
- package/src/observability/telemetry-buffer.ts +16 -26
- 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 +18 -0
- package/src/persistence/migrate.ts +6 -3
- package/src/persistence/schema.ts +17 -0
- package/src/persistence/ttl-cache.ts +21 -3
- package/src/protocol/codecs.ts +59 -2
- package/src/protocol/dsml.ts +34 -86
- package/src/protocol/markup-stream-parser.ts +195 -0
- package/src/protocol/reasoning-text.ts +19 -0
- package/src/protocol/request/chat.ts +10 -10
- package/src/protocol/request/gemini.ts +8 -2
- package/src/protocol/request/messages.ts +34 -22
- package/src/protocol/response/chat.ts +12 -20
- package/src/protocol/response/messages.ts +34 -7
- package/src/protocol/response/omp-tool-call-markup.ts +43 -86
- package/src/protocol/response/responses.ts +18 -2
- package/src/protocol/stop-reason.ts +23 -1
- package/src/protocol/think-split.ts +112 -0
- package/src/protocol/translation/dialect/qwen.ts +26 -58
- package/src/protocol/translation/quirks.ts +15 -0
- package/src/protocol/upstream/send-claude-messages.ts +2 -2
- package/src/providers/adapters/compatible-adapter.ts +76 -12
- package/src/providers/authentication/oauth-client.ts +40 -6
- package/src/providers/authentication/oauth-device-flow.ts +105 -11
- package/src/providers/authentication/oauth-flow-store.ts +82 -1
- package/src/providers/authentication/oauth-refresh-service.ts +766 -758
- package/src/providers/configured-provider.ts +148 -0
- package/src/providers/default-registry.ts +137 -36
- package/src/providers/discovery/discovery-types.ts +7 -0
- package/src/providers/discovery/probe-phases.ts +20 -6
- package/src/providers/discovery/probing-service.ts +22 -2
- 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 +16 -1
- package/src/providers/integrations/buddy/account.ts +969 -0
- package/src/providers/integrations/buddy/capabilities.ts +12 -12
- package/src/providers/integrations/buddy/{buddy-catalog-shared.ts → catalog.ts} +198 -136
- package/src/providers/integrations/buddy/{buddy-chat-shared.ts → chat.ts} +176 -20
- package/src/providers/integrations/buddy/codebuddy/index.ts +429 -0
- package/src/providers/integrations/buddy/codebuddy/shared.ts +41 -26
- package/src/providers/integrations/buddy/headers.ts +311 -0
- package/src/providers/integrations/buddy/lifecycle.ts +1018 -0
- package/src/providers/integrations/buddy/{buddy-media.ts → media.ts} +1 -1
- package/src/providers/integrations/claude/claude-quota.ts +14 -17
- package/src/providers/integrations/cline/cline-oauth.ts +10 -5
- package/src/providers/integrations/cline/cline.ts +5 -6
- package/src/providers/integrations/clixad/clixad-oauth.ts +98 -0
- package/src/providers/integrations/clixad/clixad-quota.ts +132 -0
- package/src/providers/integrations/clixad/provider.ts +145 -0
- package/src/providers/integrations/codex/codex-oauth.ts +8 -5
- package/src/providers/integrations/commandcode/quota.ts +22 -28
- package/src/providers/integrations/cursor/cursor-auth.ts +1 -9
- package/src/providers/integrations/cursor/cursor-exec.ts +9 -2
- package/src/providers/integrations/cursor/cursor-hardening.ts +279 -0
- package/src/providers/integrations/cursor/cursor-http2.ts +605 -6
- package/src/providers/integrations/cursor/cursor-request.ts +26 -12
- package/src/providers/integrations/cursor/cursor-shared.ts +8 -5
- package/src/providers/integrations/cursor/cursor.ts +574 -110
- 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/deepai/deepai-catalog.ts +149 -0
- package/src/providers/integrations/deepai/deepai-common.ts +145 -0
- package/src/providers/integrations/deepai/deepai-oauth.ts +129 -0
- package/src/providers/integrations/deepai/deepai-quota.ts +97 -0
- package/src/providers/integrations/deepai/provider.ts +42 -0
- package/src/providers/integrations/devin/devin-auth.ts +7 -0
- package/src/providers/integrations/devin/protocol/devin-proto.ts +1 -27
- package/src/providers/integrations/factory/factory-oauth.ts +33 -51
- 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 +5 -0
- package/src/providers/integrations/freepi/freepi-discovery.ts +2 -2
- package/src/providers/integrations/freepi/freepi-headers.ts +2 -2
- package/src/providers/integrations/freepi/freepi-protocol.ts +11 -2
- package/src/providers/integrations/freepi/freepi-realm.ts +0 -3
- package/src/providers/integrations/freepi/freepi-session.ts +158 -0
- package/src/providers/integrations/freepi/freepi.ts +80 -54
- package/src/providers/integrations/github/github-discovery.ts +30 -13
- package/src/providers/integrations/github/github-oauth.ts +217 -44
- package/src/providers/integrations/github/github-quota.ts +22 -5
- package/src/providers/integrations/github/github.ts +40 -32
- package/src/providers/integrations/grok/grok-oauth.ts +52 -49
- 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 +3 -3
- package/src/providers/integrations/{hermes.ts → hermes/hermes.ts} +42 -13
- package/src/providers/integrations/hermes/index.ts +2 -0
- package/src/providers/integrations/kilo/kilo-oauth.ts +4 -4
- package/src/providers/integrations/kilo/kilo.ts +1 -1
- package/src/providers/integrations/kimi/kimi-oauth.ts +3 -3
- 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-oauth.ts +2 -2
- package/src/providers/integrations/kiro/kiro-quota.ts +8 -4
- package/src/providers/integrations/kiro/kiro.ts +15 -19
- package/src/providers/integrations/muse/muse-oauth.ts +5 -5
- 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/openrouter/provider.ts +1 -1
- package/src/providers/integrations/perch/perch-credential.ts +25 -0
- package/src/providers/integrations/perch/perch-protocol.ts +0 -6
- package/src/providers/integrations/perch/perch-quota.ts +2 -16
- package/src/providers/integrations/perch/perch.ts +6 -16
- package/src/providers/integrations/qoder/claim-qoder-credits.ts +19 -60
- package/src/providers/integrations/qoder/qoder-adapter.ts +20 -125
- package/src/providers/integrations/qoder/qoder-auth.ts +109 -30
- package/src/providers/integrations/qoder/qoder-catalog.ts +21 -6
- package/src/providers/integrations/qoder/qoder-chat.ts +32 -29
- package/src/providers/integrations/qoder/qoder-checkin.ts +5 -5
- package/src/providers/integrations/qoder/qoder-cosy.ts +37 -9
- package/src/providers/integrations/qoder/qoder-oauth.ts +9 -2
- package/src/providers/integrations/qoder/qoder-realm.ts +13 -36
- package/src/providers/integrations/qoder/qoder-sse.ts +447 -68
- package/src/providers/integrations/qoder/qoder-types.ts +9 -0
- package/src/providers/integrations/qoder/qoder.ts +3 -26
- package/src/providers/integrations/sensenova/provider.ts +144 -0
- package/src/providers/integrations/trae/trae-protocol.ts +9 -5
- package/src/providers/integrations/trae/trae-quota.ts +21 -29
- package/src/providers/integrations/trae/trae-realm.ts +38 -0
- package/src/providers/integrations/trae/trae.ts +7 -24
- package/src/providers/integrations/vercel/provider.ts +117 -0
- package/src/providers/integrations/vercel/vercel-quota.ts +96 -0
- package/src/providers/integrations/xai/xai-oauth.ts +5 -5
- package/src/providers/integrations/zcode-start-plan/gifts.ts +1 -1
- package/src/providers/integrations/zcode-start-plan/oauth.ts +3 -3
- 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 +205 -0
- package/src/providers/operations/account-error-classification.ts +199 -307
- package/src/providers/operations/account-health-service.ts +82 -1
- package/src/providers/operations/account-refresh-status.ts +36 -37
- package/src/providers/operations/account-tier.ts +15 -16
- package/src/providers/operations/client-version-resolver.ts +1 -1
- package/src/providers/operations/client-versions.ts +100 -81
- package/src/providers/operations/cooldown-rules.ts +11 -16
- package/src/providers/operations/oauth-refresh-lead.ts +46 -22
- package/src/providers/operations/{model-catalog-cache.ts → provider-caches.ts} +68 -16
- package/src/providers/operations/provider-catalog-service.ts +1 -1
- package/src/providers/operations/provider-credential-service.ts +118 -51
- 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/operations/session-resolution.ts +17 -1
- package/src/providers/provider-contracts.ts +6 -4
- package/src/providers/{provider-credential-resolver.ts → provider-credentials.ts} +40 -3
- package/src/providers/provider-metadata.ts +70 -10
- package/src/providers/provider-probe.ts +15 -1
- package/src/providers/provider-registry.ts +42 -33
- package/src/providers/quota/quota-contracts.ts +2 -0
- 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 +100 -21
- package/src/security/api-key-auth-cache.ts +1 -1
- package/src/security/api-key-auth.ts +6 -2
- package/src/security/ip-boundary.ts +1 -1
- package/src/transport/dispatch/attempt-finalize.ts +15 -14
- package/src/transport/dispatch/attempt-loop.ts +73 -19
- package/src/transport/dispatch/generation.ts +2 -8
- package/src/transport/dispatch/handler-deps.ts +1 -1
- package/src/transport/dispatch/leases.ts +1 -1
- package/src/transport/dispatch/native-shared.ts +25 -0
- package/src/transport/dispatch/proxy-request.ts +8 -46
- package/src/transport/dispatch/responses-compact.ts +2 -8
- package/src/transport/dispatch/retry-policy.ts +1 -1
- package/src/transport/dispatch/streaming/finalize.ts +10 -7
- package/src/transport/dispatch/streaming/stream.ts +9 -37
- package/src/transport/dispatch/systemone.ts +2 -8
- package/src/transport/dispatch/token-count.ts +2 -6
- package/src/transport/dispatch/upstream.ts +63 -0
- package/src/transport/drain-endpoint.ts +31 -4
- package/src/transport/failure-policy.ts +16 -30
- 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 +393 -32
- package/src/transport/shutdown-notice.ts +1 -1
- 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 +7 -1
- 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 +22 -5
- package/src/transport/surface/responses/parse.ts +3 -11
- package/src/workers/buddy-growth-tasks.ts +8 -8
- package/src/workers/daily-checkin.ts +4 -4
- package/src/workers/quota-refresh-sweep.ts +1 -1
- package/src/workers/zcode-gift-claim.ts +1 -1
- package/dist/dashboard/assets/BannedPage-BxoG1MrL.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-ixwgKk53.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-BmttNV3U.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-BE3qwwfC.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-CRZdmMIX.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-Dv_FJ6Er.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-CoVrw2sM.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-CoVrw2sM.js.gz +0 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-BOoO8rpz.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-ChJuNNVN.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-BZAJtPg1.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-BE40s3u5.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-sfLoQtPV.js +0 -8
- package/dist/dashboard/assets/ProviderDetailPage-sfLoQtPV.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-CQ6bPUf_.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-DcepmPWo.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-DcepmPWo.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-BJ87Pp0U.js +0 -9
- package/dist/dashboard/assets/ProxyPage-BJ87Pp0U.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-gkSyRAKa.js +0 -1
- package/dist/dashboard/assets/QuotaPage-gkSyRAKa.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-C5HPWqEv.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-CFNcATJJ.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-YoD4tY5l.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-DxjaAhb_.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-BTlkq_Uk.js.gz +0 -0
- package/dist/dashboard/assets/app-BX2nnKqs.css +0 -2
- package/dist/dashboard/assets/app-BX2nnKqs.css.gz +0 -0
- package/dist/dashboard/assets/assert-CndthXFQ.js +0 -1
- package/dist/dashboard/assets/assert-CndthXFQ.js.gz +0 -0
- package/dist/dashboard/assets/badge-DdbT_7Am.js.gz +0 -0
- package/dist/dashboard/assets/banner-CsGN-nbm.js.gz +0 -0
- package/dist/dashboard/assets/card-mgZ_TLLZ.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-A1-v8-03.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-CJ4Zty89.js.gz +0 -0
- package/dist/dashboard/assets/dialog-B5L2jPQ_.js.gz +0 -0
- package/dist/dashboard/assets/drawer-DkjUouAj.js.gz +0 -0
- package/dist/dashboard/assets/entry-B-LVLV6o.js.gz +0 -0
- package/dist/dashboard/assets/entry-CAhdYl3B.js.gz +0 -0
- package/dist/dashboard/assets/entry-D2xD0Tmd.js +0 -4
- package/dist/dashboard/assets/entry-D2xD0Tmd.js.gz +0 -0
- package/dist/dashboard/assets/formatters-CrsdLVsn.js.gz +0 -0
- package/dist/dashboard/assets/index-BU64Lqvp.js.gz +0 -0
- package/dist/dashboard/assets/inline-B2aDLyyg.js.gz +0 -0
- package/dist/dashboard/assets/input-BCVkdR9d.js.gz +0 -0
- package/dist/dashboard/assets/layout-DNcAdMK-.js.gz +0 -0
- package/dist/dashboard/assets/list-row-DgrIH0hw.js.gz +0 -0
- package/dist/dashboard/assets/live-Cae01iu8.js.gz +0 -0
- package/dist/dashboard/assets/network-CRib7H_2.js.gz +0 -0
- package/dist/dashboard/assets/numbers-BKQE8Xpz.js.gz +0 -0
- package/dist/dashboard/assets/pagination-ecPvG_8g.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-Ckm1UXuC.js.gz +0 -0
- package/dist/dashboard/assets/select-ChoFWyKz.js.gz +0 -0
- package/dist/dashboard/assets/settings-CKjFPlKW.js.gz +0 -0
- package/dist/dashboard/assets/stack-DWCwU3fh.js.gz +0 -0
- package/dist/dashboard/assets/state-Cg3VL5J_.js.gz +0 -0
- package/dist/dashboard/assets/switch-Db70BMix.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-BqdE0LuM.js.gz +0 -0
- package/src/network/pool-health.ts +0 -210
- package/src/providers/bundled-discovery-providers.ts +0 -98
- package/src/providers/configured-openai-providers.ts +0 -120
- package/src/providers/integrations/buddy/buddy-checkin.ts +0 -521
- package/src/providers/integrations/buddy/buddy-cli-headers.ts +0 -76
- package/src/providers/integrations/buddy/buddy-conversation-headers.ts +0 -130
- package/src/providers/integrations/buddy/buddy-discovery-shared.ts +0 -234
- package/src/providers/integrations/buddy/buddy-growth-shared.ts +0 -496
- package/src/providers/integrations/buddy/buddy-identity.ts +0 -300
- package/src/providers/integrations/buddy/buddy-oauth-shared.ts +0 -341
- package/src/providers/integrations/buddy/buddy-quota-shared.ts +0 -417
- package/src/providers/integrations/buddy/buddy-server-tools.ts +0 -240
- package/src/providers/integrations/buddy/buddy-usage-shared.ts +0 -221
- package/src/providers/integrations/buddy/buddy-usage-store.ts +0 -181
- package/src/providers/integrations/buddy/codebuddy/cn-catalog.ts +0 -37
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +0 -185
- package/src/providers/integrations/buddy/codebuddy/oauth.ts +0 -47
- package/src/providers/integrations/buddy/codebuddy/provider.ts +0 -175
- package/src/providers/integrations/buddy/codebuddy/quota.ts +0 -154
- package/src/providers/integrations/qoder/chat-proto.ts +0 -328
- package/src/providers/integrations/qoder/qoder-grpc.ts +0 -871
- package/src/providers/integrations/qoder/qoder-ide.ts +0 -588
- 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-B7kIWFm5.js → app-C0gTXEoN.js} +0 -0
- /package/dist/dashboard/assets/{app-B7kIWFm5.js.gz → app-C0gTXEoN.js.gz} +0 -0
- /package/src/network/{http2-bidi.ts → bidi.ts} +0 -0
- /package/src/network/pool/{pool-scripts.ts → scripts.ts} +0 -0
- /package/src/network/pool/{pool-state.ts → state.ts} +0 -0
- /package/src/network/{backoff.ts → util/backoff.ts} +0 -0
- /package/src/network/{deduplication.ts → util/dedupe.ts} +0 -0
- /package/src/network/{ip-utils.ts → util/ip.ts} +0 -0
|
@@ -1,521 +0,0 @@
|
|
|
1
|
-
import { asCoercedNumber as sharedAsNumber, asRecord as sharedAsRecord } from "../../../shared/coerce";
|
|
2
|
-
|
|
3
|
-
// Buddy-family daily check-in (daily login credit claim), shared by both
|
|
4
|
-
// variants (`cb`, `cbcn`): same Tencent billing facade, same
|
|
5
|
-
// status/claim contract — only the endpoint base and identity headers differ
|
|
6
|
-
// per variant, and those already live in each provider's own modules.
|
|
7
|
-
//
|
|
8
|
-
// The desktop client claims a free daily credit grant once per calendar day.
|
|
9
|
-
// The gateway mirrors that for every stored account so an operator can see,
|
|
10
|
-
// per account, whether today's grant was claimed — without opening the app.
|
|
11
|
-
//
|
|
12
|
-
// Contract (from the reverse-engineered desktop bundle, vendor/research):
|
|
13
|
-
// Status : POST {base}/v2/billing/meter/checkin-activity-status body {}
|
|
14
|
-
// Claim : POST {base}/v2/billing/meter/daily-checkin body {}
|
|
15
|
-
// Envelope: { code: 0, data: { today_checked_in, streak_days, ... } }
|
|
16
|
-
// "already claimed" business code is 1001 (NOT 10001 — that belongs to the
|
|
17
|
-
// artifact-release API).
|
|
18
|
-
//
|
|
19
|
-
// One request per account per day: the sweep asks the status endpoint first and
|
|
20
|
-
// only POSTs the claim when the account has not claimed today. A successful
|
|
21
|
-
// claim short-circuits the day, so a restart cannot double-post.
|
|
22
|
-
|
|
23
|
-
import { providerBaseUrl } from "../../provider-metadata";
|
|
24
|
-
import { sleep } from "../../../shared/sleep";
|
|
25
|
-
import { BUDDY_PROVIDER_IDS } from "../../provider-metadata";
|
|
26
|
-
import { QODER_CHECKIN_PROVIDER_IDS } from "../qoder/qoder-checkin";
|
|
27
|
-
import { buildCodeBuddyUserAgent } from "../../operations/client-versions";
|
|
28
|
-
import { codebuddyDomain, type CodeBuddyVariant } from "./codebuddy/shared";
|
|
29
|
-
/** Providers whose billing facade exposes the daily check-in routes. */
|
|
30
|
-
/**
|
|
31
|
-
* The Buddy providers the daily check-in claims a credit for. Derived from the
|
|
32
|
-
* shared family set so this list cannot drift from the health recorder's or the
|
|
33
|
-
* request preparer's.
|
|
34
|
-
*/
|
|
35
|
-
export const DAILY_CHECKIN_PROVIDER_IDS: readonly string[] = [
|
|
36
|
-
...BUDDY_PROVIDER_IDS,
|
|
37
|
-
...QODER_CHECKIN_PROVIDER_IDS,
|
|
38
|
-
];
|
|
39
|
-
|
|
40
|
-
/** Abort budget for one upstream check-in request. */
|
|
41
|
-
const TIMEOUT_MS = 15_000;
|
|
42
|
-
|
|
43
|
-
export const CHECKIN_STATUS_PATH = "/billing/meter/checkin-activity-status";
|
|
44
|
-
export const CHECKIN_CLAIM_PATH = "/billing/meter/daily-checkin";
|
|
45
|
-
|
|
46
|
-
export type DailyCheckinState =
|
|
47
|
-
| "claimed"
|
|
48
|
-
| "already_claimed"
|
|
49
|
-
| "not_eligible"
|
|
50
|
-
| "event_ended"
|
|
51
|
-
| "unavailable"
|
|
52
|
-
| "error";
|
|
53
|
-
|
|
54
|
-
export interface DailyCheckinResult {
|
|
55
|
-
readonly providerId: string;
|
|
56
|
-
readonly accountId: string;
|
|
57
|
-
readonly state: DailyCheckinState;
|
|
58
|
-
/** Credits granted by this claim; `null` when nothing was granted. */
|
|
59
|
-
readonly credit: number | null;
|
|
60
|
-
readonly streakDays: number | null;
|
|
61
|
-
/** Provider-facing detail for the audit log; `null` on success. */
|
|
62
|
-
readonly error: string | null;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* One `chat_request_send` growth event for `POST {base}/v2/report`.
|
|
67
|
-
*
|
|
68
|
-
* The growth backend scores conversation activity, not credit grants: one
|
|
69
|
-
* report lights the login streak and unlocks the `first_buddy` task. The full
|
|
70
|
-
* client shape is sent (not a minimal subset) because the upstream may tighten
|
|
71
|
-
* validation later. `userId` is mandatory — the server answers 200 but silently
|
|
72
|
-
* drops events without it.
|
|
73
|
-
*/
|
|
74
|
-
export interface BuddyActivityReportEvent {
|
|
75
|
-
readonly eventCode: "chat_request_send";
|
|
76
|
-
readonly timestamp: number;
|
|
77
|
-
readonly reportDelay: number;
|
|
78
|
-
readonly mode: string;
|
|
79
|
-
readonly conversationId: string;
|
|
80
|
-
readonly requestId: string;
|
|
81
|
-
readonly inputLength: number;
|
|
82
|
-
readonly requestModelId: string;
|
|
83
|
-
readonly requestModelName: string;
|
|
84
|
-
readonly isPlan: boolean;
|
|
85
|
-
readonly isAutoExecuteTerminal: boolean;
|
|
86
|
-
readonly isAutoModify: boolean;
|
|
87
|
-
readonly codebaseEnable: boolean;
|
|
88
|
-
readonly maxToken: number;
|
|
89
|
-
readonly maxSteps: number;
|
|
90
|
-
readonly temperature: number;
|
|
91
|
-
readonly maxRetries: number;
|
|
92
|
-
readonly mentionContexts: readonly unknown[];
|
|
93
|
-
readonly knowledgeId: readonly unknown[];
|
|
94
|
-
readonly knowledgeName: readonly unknown[];
|
|
95
|
-
readonly codebaseId: string;
|
|
96
|
-
readonly mentionContextCount: number;
|
|
97
|
-
readonly command: string;
|
|
98
|
-
readonly recommendId: string;
|
|
99
|
-
readonly skillId: string;
|
|
100
|
-
readonly skillCount: number;
|
|
101
|
-
readonly totalCount: number;
|
|
102
|
-
readonly presentAt: number;
|
|
103
|
-
readonly rootRequestId: string;
|
|
104
|
-
readonly parentConversationId: string;
|
|
105
|
-
readonly agentName: string;
|
|
106
|
-
readonly agentType: string;
|
|
107
|
-
readonly product: string;
|
|
108
|
-
readonly userId: string;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export const ACTIVITY_REPORT_PATH = "/report";
|
|
112
|
-
export type BuddyActivityReportState = "reported" | "unavailable" | "error";
|
|
113
|
-
|
|
114
|
-
export interface BuddyActivityReportResult {
|
|
115
|
-
readonly providerId: string;
|
|
116
|
-
readonly accountId: string;
|
|
117
|
-
readonly state: BuddyActivityReportState;
|
|
118
|
-
/** Provider-facing detail for the audit log; `null` on success. */
|
|
119
|
-
readonly error: string | null;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Builds one growth-activity event. `conversationId` is caller-generated (a
|
|
124
|
-
* synthetic `activity-<millis>` id is fine — the server does not validate it
|
|
125
|
-
* against a real conversation); `requestId` defaults to it. The model fields
|
|
126
|
-
* mirror the desktop client's own report so the event reads as a normal chat
|
|
127
|
-
* send, and `userId` carries the account uid the streak is scored against.
|
|
128
|
-
*/
|
|
129
|
-
export function buildActivityReportEvent(args: {
|
|
130
|
-
readonly conversationId: string;
|
|
131
|
-
readonly userId: string;
|
|
132
|
-
readonly requestId?: string;
|
|
133
|
-
readonly now?: number;
|
|
134
|
-
}): BuddyActivityReportEvent {
|
|
135
|
-
const now = args.now ?? Date.now();
|
|
136
|
-
const requestId = args.requestId ?? args.conversationId;
|
|
137
|
-
return {
|
|
138
|
-
eventCode: "chat_request_send",
|
|
139
|
-
timestamp: now,
|
|
140
|
-
reportDelay: 0,
|
|
141
|
-
mode: "unknown",
|
|
142
|
-
conversationId: args.conversationId,
|
|
143
|
-
requestId,
|
|
144
|
-
inputLength: 0,
|
|
145
|
-
requestModelId: "auto",
|
|
146
|
-
requestModelName: "Auto",
|
|
147
|
-
isPlan: false,
|
|
148
|
-
isAutoExecuteTerminal: false,
|
|
149
|
-
isAutoModify: false,
|
|
150
|
-
codebaseEnable: false,
|
|
151
|
-
maxToken: 0,
|
|
152
|
-
maxSteps: 0,
|
|
153
|
-
temperature: 0,
|
|
154
|
-
maxRetries: 0,
|
|
155
|
-
mentionContexts: [],
|
|
156
|
-
knowledgeId: [],
|
|
157
|
-
knowledgeName: [],
|
|
158
|
-
codebaseId: "",
|
|
159
|
-
mentionContextCount: 0,
|
|
160
|
-
command: "",
|
|
161
|
-
recommendId: "",
|
|
162
|
-
skillId: "",
|
|
163
|
-
skillCount: 0,
|
|
164
|
-
totalCount: 0,
|
|
165
|
-
presentAt: now,
|
|
166
|
-
rootRequestId: args.conversationId,
|
|
167
|
-
parentConversationId: args.conversationId,
|
|
168
|
-
agentName: "default",
|
|
169
|
-
agentType: "main",
|
|
170
|
-
product: "SaaS",
|
|
171
|
-
userId: args.userId,
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* How the growth report is sent.
|
|
177
|
-
*
|
|
178
|
-
* The billing facade scores conversation activity, and one event reads as one
|
|
179
|
-
* chat send. A single event did not move the growth tasks; four events per
|
|
180
|
-
* batch, sent twice with a pause between the rounds, is what does. The pause
|
|
181
|
-
* is what keeps the two rounds from landing as one burst. Both numbers apply
|
|
182
|
-
* to every buddy variant — the request is built the same way for `cb` and
|
|
183
|
-
* `cbcn`, so neither can drift back to a single shot.
|
|
184
|
-
*/
|
|
185
|
-
export const ACTIVITY_REPORT_EVENTS_PER_BATCH = 4;
|
|
186
|
-
export const ACTIVITY_REPORT_ROUNDS = 2;
|
|
187
|
-
export const ACTIVITY_REPORT_ROUND_DELAY_MS = 1_500;
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Sends the growth-activity report (`POST {base}/v2/report`, the versioned
|
|
191
|
-
* billing-meter path joined the same way as the status/claim routes:
|
|
192
|
-
* `VERSION_SEGMENT` supplies nothing for `cb`/`cbcn`, which already end in
|
|
193
|
-
* `/v2`).
|
|
194
|
-
*
|
|
195
|
-
* Two rounds of four events, paused between rounds. Each event carries its
|
|
196
|
-
* own conversation and request id: the facade drops a repeated id as a
|
|
197
|
-
* duplicate, so a batch of identical events would score as one. The first
|
|
198
|
-
* round that fails stops the sequence — a credential or transport failure
|
|
199
|
-
* will not be fixed by the second round, and sending it only adds load.
|
|
200
|
-
*/
|
|
201
|
-
export async function fetchBuddyActivityReport(args: {
|
|
202
|
-
readonly providerId: string;
|
|
203
|
-
readonly accountId: string;
|
|
204
|
-
readonly credential: string;
|
|
205
|
-
readonly userId: string;
|
|
206
|
-
readonly fetcher: typeof fetch;
|
|
207
|
-
readonly conversationId?: string;
|
|
208
|
-
/** Pause between rounds. Injectable so a test does not wait on the real delay. */
|
|
209
|
-
readonly roundDelayMs?: number;
|
|
210
|
-
readonly sleep?: (ms: number) => Promise<void>;
|
|
211
|
-
}): Promise<BuddyActivityReportResult> {
|
|
212
|
-
const { providerId, accountId, credential, userId, fetcher } = args;
|
|
213
|
-
const base = { providerId, accountId, error: null };
|
|
214
|
-
if (!credential) {
|
|
215
|
-
return { ...base, state: "error", error: "Account has no stored credential." };
|
|
216
|
-
}
|
|
217
|
-
if (!userId) {
|
|
218
|
-
return { ...base, state: "error", error: "Account uid is unavailable; cannot report activity." };
|
|
219
|
-
}
|
|
220
|
-
const headers = {
|
|
221
|
-
...(await checkinHeaders(providerId)),
|
|
222
|
-
Authorization: `Bearer ${credential}`,
|
|
223
|
-
"X-User-Id": userId,
|
|
224
|
-
};
|
|
225
|
-
const url = `${providerBaseUrl(providerId)}${VERSION_SEGMENT[providerId] ?? ""}${ACTIVITY_REPORT_PATH}`;
|
|
226
|
-
const delayMs = args.roundDelayMs ?? ACTIVITY_REPORT_ROUND_DELAY_MS;
|
|
227
|
-
const sleep = args.sleep ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
228
|
-
const conversationId = args.conversationId ?? `activity-${Date.now()}`;
|
|
229
|
-
|
|
230
|
-
for (let round = 0; round < ACTIVITY_REPORT_ROUNDS; round += 1) {
|
|
231
|
-
if (round > 0 && delayMs > 0) await sleep(delayMs);
|
|
232
|
-
const events = Array.from({ length: ACTIVITY_REPORT_EVENTS_PER_BATCH }, (_, index) => {
|
|
233
|
-
const sequence = round * ACTIVITY_REPORT_EVENTS_PER_BATCH + index;
|
|
234
|
-
return buildActivityReportEvent({
|
|
235
|
-
conversationId: `${conversationId}-${sequence}`,
|
|
236
|
-
requestId: `${conversationId}-req-${sequence}`,
|
|
237
|
-
userId,
|
|
238
|
-
});
|
|
239
|
-
});
|
|
240
|
-
let payload: unknown;
|
|
241
|
-
try {
|
|
242
|
-
const response = await fetcher(url, {
|
|
243
|
-
method: "POST",
|
|
244
|
-
headers,
|
|
245
|
-
body: JSON.stringify(events),
|
|
246
|
-
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
247
|
-
});
|
|
248
|
-
if (response.status === 401 || response.status === 403) {
|
|
249
|
-
return { ...base, state: "error", error: "Credential invalid or expired." };
|
|
250
|
-
}
|
|
251
|
-
if (!response.ok) {
|
|
252
|
-
return { ...base, state: "error", error: `Activity report API error (${response.status}).` };
|
|
253
|
-
}
|
|
254
|
-
payload = await response.text().then((text) => (text ? JSON.parse(text) : null));
|
|
255
|
-
} catch (error) {
|
|
256
|
-
if (error instanceof SyntaxError) {
|
|
257
|
-
return { ...base, state: "error", error: "Activity report response returned invalid JSON." };
|
|
258
|
-
}
|
|
259
|
-
return {
|
|
260
|
-
...base,
|
|
261
|
-
state: "error",
|
|
262
|
-
error: error instanceof Error ? error.message : "Activity report request failed.",
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
const code = envelopeCode(payload);
|
|
266
|
-
if (code !== null && code !== 0) {
|
|
267
|
-
return { ...base, state: "error", error: `Activity report error (code ${code}).` };
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
return { ...base, state: "reported" };
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Check-in business codes, per the desktop bundle's `mapCheckinStatus()`.
|
|
275
|
-
* `1001` is "already claimed" — NOT `10001`, which belongs to the
|
|
276
|
-
* artifact-release API and never appears in this path.
|
|
277
|
-
*/
|
|
278
|
-
const ALREADY_CLAIMED_CODE = 1001;
|
|
279
|
-
const NOT_ELIGIBLE_CODE = 1002;
|
|
280
|
-
const EVENT_ENDED_CODE = 1003;
|
|
281
|
-
/** Delays between 5xx/network retries on the claim POST, mirroring the buddy gateway's own backoff. */
|
|
282
|
-
const CLAIM_RETRY_DELAYS_MS = [1_000, 2_000] as const;
|
|
283
|
-
/**
|
|
284
|
-
* Check-in paths are joined onto the provider's manifest base URL, which does
|
|
285
|
-
* NOT carry a consistent version segment: `cb`/`cbcn` already end in `/v2`,
|
|
286
|
-
* so no segment is prepended. This map keeps the join aligned with each
|
|
287
|
-
* provider's own quota collector, so the gateways cannot drift apart.
|
|
288
|
-
*/
|
|
289
|
-
const VERSION_SEGMENT: Readonly<Record<string, string>> = {
|
|
290
|
-
cb: "",
|
|
291
|
-
cbcn: "",
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
function statusUrl(providerId: string): string {
|
|
295
|
-
return `${providerBaseUrl(providerId)}${VERSION_SEGMENT[providerId] ?? ""}${CHECKIN_STATUS_PATH}`;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
function claimUrl(providerId: string): string {
|
|
299
|
-
return `${providerBaseUrl(providerId)}${VERSION_SEGMENT[providerId] ?? ""}${CHECKIN_CLAIM_PATH}`;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Per-provider billing headers. The Buddy gateways share the Tencent billing
|
|
304
|
-
* facade but each risk-gates on its own client identity: CodeBuddy intl
|
|
305
|
-
* wants the `IDE` identity, and CN wants `CLI` (plus its own `X-Domain`).
|
|
306
|
-
* Sending the wrong one trips a 403 the same way the chat surface does.
|
|
307
|
-
*/
|
|
308
|
-
async function checkinHeaders(providerId: string): Promise<Record<string, string>> {
|
|
309
|
-
const common = {
|
|
310
|
-
"X-Product": "SaaS",
|
|
311
|
-
"X-Requested-With": "XMLHttpRequest",
|
|
312
|
-
"X-CodeBuddy-Request": "1",
|
|
313
|
-
"Content-Type": "application/json",
|
|
314
|
-
Accept: "application/json",
|
|
315
|
-
};
|
|
316
|
-
const variant: CodeBuddyVariant = providerId === "cb" ? "IDE" : "CLI";
|
|
317
|
-
return {
|
|
318
|
-
...common,
|
|
319
|
-
"User-Agent": buildCodeBuddyUserAgent(variant),
|
|
320
|
-
"X-IDE-Type": variant,
|
|
321
|
-
"X-IDE-Name": variant,
|
|
322
|
-
"X-Domain": codebuddyDomain(variant),
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* Textual "already checked in" fingerprints. The claim POST answers `1001`
|
|
328
|
-
* when the envelope is well-formed, but a locale or gateway variant can answer
|
|
329
|
-
* the same state as prose (the reference gateway matches `已签到` and
|
|
330
|
-
* `already…check…` case-insensitively across the message or raw body), so both
|
|
331
|
-
* shapes resolve to `already_claimed` instead of a spurious error.
|
|
332
|
-
*/
|
|
333
|
-
function alreadyClaimedMessage(payload: unknown, rawBody: string): string | null {
|
|
334
|
-
const message = asTextField(payload) || rawBody.trim();
|
|
335
|
-
if (!message) return null;
|
|
336
|
-
if (message.includes("已签到")) return message;
|
|
337
|
-
const lower = message.toLowerCase();
|
|
338
|
-
if (lower.includes("already") && lower.includes("check")) return message;
|
|
339
|
-
return null;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
function asTextField(payload: unknown): string | null {
|
|
343
|
-
const data = asRecord(payload);
|
|
344
|
-
if (!data) return null;
|
|
345
|
-
const direct = data["msg"] ?? data["message"];
|
|
346
|
-
if (typeof direct === "string" && direct.trim()) return direct.trim();
|
|
347
|
-
return null;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
/** True when the claim attempt is worth retrying: 5xx or a network throw, never a business code. */
|
|
351
|
-
function isRetryableClaim(error: unknown, status: number | null): boolean {
|
|
352
|
-
if (status !== null) return status >= 500;
|
|
353
|
-
return !(error instanceof DOMException && error.name === "AbortError");
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
function asRecord(value: unknown): Record<string, unknown> | null {
|
|
357
|
-
return sharedAsRecord(value) ?? null;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
function asNumber(value: unknown): number | null {
|
|
361
|
-
return sharedAsNumber(value) ?? null;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
/** Reads the envelope's business code; `0` means success. */
|
|
366
|
-
function envelopeCode(payload: unknown): number | null {
|
|
367
|
-
const envelope = asRecord(payload);
|
|
368
|
-
if (!envelope || !("code" in envelope)) return null;
|
|
369
|
-
return asNumber(envelope["code"]);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
/**
|
|
373
|
-
* Unwraps the check-in payload. The gateway returns a flat `{ code, data }`,
|
|
374
|
-
* while the CodeBuddy billing facade nests Tencent's `data.Response.Data`
|
|
375
|
-
* (the same double wrap its quota endpoint uses), so both shapes resolve.
|
|
376
|
-
*/
|
|
377
|
-
function envelopeData(payload: unknown): Record<string, unknown> | null {
|
|
378
|
-
const data = asRecord(asRecord(payload)?.["data"]);
|
|
379
|
-
if (!data) return null;
|
|
380
|
-
if ("today_checked_in" in data || "active" in data || "streak_days" in data) return data;
|
|
381
|
-
return asRecord(asRecord(data["Response"])?.["Data"]);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
/**
|
|
385
|
-
* Performs one account's daily check-in.
|
|
386
|
-
*
|
|
387
|
-
* Status first, claim only when `today_checked_in` is false — so the daily
|
|
388
|
-
* budget is one request for an already-claimed account and two on claim day.
|
|
389
|
-
*/
|
|
390
|
-
export async function fetchDailyCheckin(args: {
|
|
391
|
-
readonly providerId: string;
|
|
392
|
-
readonly accountId: string;
|
|
393
|
-
readonly credential: string;
|
|
394
|
-
readonly fetcher: typeof fetch;
|
|
395
|
-
/** Overrides the status probe when the caller already knows the state. */
|
|
396
|
-
readonly forceClaim?: boolean;
|
|
397
|
-
}): Promise<DailyCheckinResult> {
|
|
398
|
-
const { providerId, accountId, credential, fetcher } = args;
|
|
399
|
-
const base = { providerId, accountId, credit: null, streakDays: null, error: null };
|
|
400
|
-
|
|
401
|
-
if (!credential) {
|
|
402
|
-
return { ...base, state: "error", error: "Account has no stored credential." };
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// `checkinHeaders()` already carries Content-Type/Accept; only auth is
|
|
406
|
-
// layered on here so the per-provider identity stays in one place.
|
|
407
|
-
const headers = {
|
|
408
|
-
...(await checkinHeaders(providerId)),
|
|
409
|
-
Authorization: `Bearer ${credential}`,
|
|
410
|
-
};
|
|
411
|
-
|
|
412
|
-
let status: unknown;
|
|
413
|
-
try {
|
|
414
|
-
const response = await fetcher(statusUrl(providerId), {
|
|
415
|
-
method: "POST",
|
|
416
|
-
headers,
|
|
417
|
-
body: "{}",
|
|
418
|
-
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
419
|
-
});
|
|
420
|
-
if (response.status === 401 || response.status === 403) {
|
|
421
|
-
return { ...base, state: "error", error: "Credential invalid or expired." };
|
|
422
|
-
}
|
|
423
|
-
if (!response.ok) {
|
|
424
|
-
return { ...base, state: "error", error: `Check-in status API error (${response.status}).` };
|
|
425
|
-
}
|
|
426
|
-
status = await response.json().catch(() => null);
|
|
427
|
-
} catch (error) {
|
|
428
|
-
return {
|
|
429
|
-
...base,
|
|
430
|
-
state: "error",
|
|
431
|
-
error: error instanceof Error ? error.message : "Check-in status request failed.",
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
const statusCode = envelopeCode(status);
|
|
436
|
-
if (statusCode !== null && statusCode !== 0) {
|
|
437
|
-
return { ...base, state: "error", error: `Check-in status error (code ${statusCode}).` };
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
const data = envelopeData(status);
|
|
441
|
-
if (!data) return { ...base, state: "unavailable", error: "Check-in activity unavailable." };
|
|
442
|
-
if (data["active"] === false) {
|
|
443
|
-
return { ...base, state: "unavailable", error: "No check-in activity running." };
|
|
444
|
-
}
|
|
445
|
-
const streak = asNumber(data["streak_days"]);
|
|
446
|
-
if (!args.forceClaim && data["today_checked_in"] === true) {
|
|
447
|
-
return { ...base, state: "already_claimed", streakDays: streak };
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
let claim: unknown;
|
|
451
|
-
let claimRaw = "";
|
|
452
|
-
let attempt = 0;
|
|
453
|
-
for (;;) {
|
|
454
|
-
try {
|
|
455
|
-
const response = await fetcher(claimUrl(providerId), {
|
|
456
|
-
method: "POST",
|
|
457
|
-
headers,
|
|
458
|
-
body: "{}",
|
|
459
|
-
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
460
|
-
});
|
|
461
|
-
if (response.status === 401 || response.status === 403) {
|
|
462
|
-
return { ...base, state: "error", error: "Credential invalid or expired." };
|
|
463
|
-
}
|
|
464
|
-
if (response.status >= 500 && attempt < CLAIM_RETRY_DELAYS_MS.length) {
|
|
465
|
-
await sleep(CLAIM_RETRY_DELAYS_MS[attempt] as number);
|
|
466
|
-
attempt += 1;
|
|
467
|
-
continue;
|
|
468
|
-
}
|
|
469
|
-
if (!response.ok) {
|
|
470
|
-
return { ...base, state: "error", error: `Daily check-in API error (${response.status}).` };
|
|
471
|
-
}
|
|
472
|
-
claimRaw = await response.text().catch(() => "");
|
|
473
|
-
claim = claimRaw ? JSON.parse(claimRaw) : null;
|
|
474
|
-
break;
|
|
475
|
-
} catch (error) {
|
|
476
|
-
if (error instanceof SyntaxError) {
|
|
477
|
-
return { ...base, state: "error", error: "Daily check-in response returned invalid JSON." };
|
|
478
|
-
}
|
|
479
|
-
if (isRetryableClaim(error, null) && attempt < CLAIM_RETRY_DELAYS_MS.length) {
|
|
480
|
-
await sleep(CLAIM_RETRY_DELAYS_MS[attempt] as number);
|
|
481
|
-
attempt += 1;
|
|
482
|
-
continue;
|
|
483
|
-
}
|
|
484
|
-
return {
|
|
485
|
-
...base,
|
|
486
|
-
state: "error",
|
|
487
|
-
error: error instanceof Error ? error.message : "Daily check-in request failed.",
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
const claimCode = envelopeCode(claim);
|
|
493
|
-
if (claimCode !== null && claimCode !== 0) {
|
|
494
|
-
const alreadyText = alreadyClaimedMessage(claim, claimRaw);
|
|
495
|
-
if (claimCode === ALREADY_CLAIMED_CODE || alreadyText) {
|
|
496
|
-
return { ...base, state: "already_claimed", streakDays: streak };
|
|
497
|
-
}
|
|
498
|
-
if (claimCode === NOT_ELIGIBLE_CODE) return { ...base, state: "not_eligible" };
|
|
499
|
-
if (claimCode === EVENT_ENDED_CODE) return { ...base, state: "event_ended" };
|
|
500
|
-
return { ...base, state: "error", error: `Daily check-in error (code ${claimCode}).` };
|
|
501
|
-
}
|
|
502
|
-
// Some gateway variants answer the duplicate-claim state as prose with a
|
|
503
|
-
// success envelope; catch that before reporting a fresh claim.
|
|
504
|
-
if (claimCode === 0) {
|
|
505
|
-
const alreadyText = alreadyClaimedMessage(claim, claimRaw);
|
|
506
|
-
if (alreadyText) return { ...base, state: "already_claimed", streakDays: streak };
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
const claimData = envelopeData(claim);
|
|
510
|
-
return {
|
|
511
|
-
...base,
|
|
512
|
-
state: "claimed",
|
|
513
|
-
credit: asNumber(claimData?.["credit"]) ?? asNumber(claimData?.["today_credit"]) ?? null,
|
|
514
|
-
streakDays: asNumber(claimData?.["streak_days"]) ?? streak,
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
/** Calendar-day key in UTC, matching the provider's own day boundary. */
|
|
519
|
-
export function checkinDayKey(now: Date = new Date()): string {
|
|
520
|
-
return now.toISOString().slice(0, 10);
|
|
521
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The header family only the CLI identity sends.
|
|
3
|
-
*
|
|
4
|
-
* Everything here comes from the two reference gateways, which agree: the
|
|
5
|
-
* desktop product sends conversation/tracing headers and a device token, while
|
|
6
|
-
* the CLI sends the agent envelope. The CLI still drops the browser *transport*
|
|
7
|
-
* headers (`origin`, `referer`, `accept-language`) and the device token, but
|
|
8
|
-
* keeps the request-shape markers (`x-requested-with`, `x-codebuddy-request`)
|
|
9
|
-
* the reference sends on every call regardless of transport — see the CLI
|
|
10
|
-
* branches in each provider's `*-shared.ts`.
|
|
11
|
-
*
|
|
12
|
-
* The CLI's cloud chat transport is axios (`RestOperations`), not the OpenAI
|
|
13
|
-
* Node SDK, so it sends **no** `x-stainless-*` fingerprint. The reference's
|
|
14
|
-
* chat request helper sets only `Content-Type`, `Accept`, and `Authorization`
|
|
15
|
-
* before the conversation/agent/identity headers are injected; the stainless
|
|
16
|
-
* set belongs to the SDK-backed secondary clients, not to CodeBuddy chat.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* The trace family the CLI carries as a child span.
|
|
21
|
-
*
|
|
22
|
-
* The desktop product omits the parent (`with_parent=False` in the reference);
|
|
23
|
-
* the CLI conversation request is a child span, so it also sends `b3`'s fourth
|
|
24
|
-
* field and `X-B3-ParentSpanId`. `buddyConversationHeaders` already produces
|
|
25
|
-
* `traceparent`, `b3`, and the `X-B3-*` set, so only the parent is added here.
|
|
26
|
-
*/
|
|
27
|
-
export function buddyCliTraceHeaders(
|
|
28
|
-
conversation: Readonly<Record<string, string>>,
|
|
29
|
-
): Record<string, string> {
|
|
30
|
-
const traceId = conversation["x-trace-id"] ?? conversation["x-b3-traceid"];
|
|
31
|
-
const spanId = conversation["x-b3-spanid"];
|
|
32
|
-
if (traceId === undefined) return {};
|
|
33
|
-
const b3 = `${traceId}-${spanId ?? traceId.slice(0, 16)}-1-${traceId.slice(0, 16)}`;
|
|
34
|
-
return { ...(spanId === undefined ? {} : { "X-B3-ParentSpanId": spanId }), b3 };
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* The full CLI identity envelope, minus what each caller already supplies.
|
|
39
|
-
*
|
|
40
|
-
* The caller keeps ownership of `User-Agent`, `X-IDE-*`, `X-Domain`, the
|
|
41
|
-
* conversation family, and the OAuth identity headers; only the headers that
|
|
42
|
-
* are the same for every CLI dispatch are built here.
|
|
43
|
-
*
|
|
44
|
-
* No `x-stainless-*` fingerprint: the CLI's chat transport is axios, not the
|
|
45
|
-
* OpenAI Node SDK. `X-Private-Data` is added by the caller only when the
|
|
46
|
-
* dispatch is actually private — the reference never sends it as `false`.
|
|
47
|
-
*/
|
|
48
|
-
export function buddyCliHeaders(args: {
|
|
49
|
-
readonly userId: string;
|
|
50
|
-
readonly enterpriseId?: string | undefined;
|
|
51
|
-
readonly privateData?: boolean;
|
|
52
|
-
}): Record<string, string> {
|
|
53
|
-
const enterpriseId =
|
|
54
|
-
args.enterpriseId !== undefined && args.enterpriseId.trim().length > 0
|
|
55
|
-
? args.enterpriseId.trim()
|
|
56
|
-
: undefined;
|
|
57
|
-
return {
|
|
58
|
-
"X-Agent-Intent": "craft",
|
|
59
|
-
"X-Agent-Type": "main",
|
|
60
|
-
// The reference enum is local-agent / cloud-agent / agent-agent, and its
|
|
61
|
-
// parser returns "other" for anything unknown or absent. A gateway is none
|
|
62
|
-
// of the three, so "other" is the honest value rather than a guess.
|
|
63
|
-
"X-Agent-Runtime": "other",
|
|
64
|
-
"X-User-Id": args.userId,
|
|
65
|
-
...(args.privateData === true ? { "X-Private-Data": "true" } : {}),
|
|
66
|
-
...(enterpriseId === undefined
|
|
67
|
-
? {}
|
|
68
|
-
: {
|
|
69
|
-
"X-Enterprise-Id": enterpriseId,
|
|
70
|
-
// The tenant falls back to the enterprise: the two are the same value
|
|
71
|
-
// for an account that belongs to one enterprise, and the upstream
|
|
72
|
-
// reads both.
|
|
73
|
-
"X-Tenant-Id": enterpriseId,
|
|
74
|
-
}),
|
|
75
|
-
};
|
|
76
|
-
}
|