cartethyia 2.7.3 → 2.7.5
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 +2 -0
- package/README.md +17 -5
- package/dist/dashboard/assets/{BannedPage-2TJD37Hb.js → BannedPage-Cj15GsMp.js} +1 -1
- package/dist/dashboard/assets/BannedPage-Cj15GsMp.js.gz +0 -0
- package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js +1 -0
- package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-xefJNRmJ.js → CliToolDetailPage-DZKmVuJN.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-DZKmVuJN.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-Rj9iHQ3F.js → CliToolsPage-BIccZmeL.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-BIccZmeL.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-DEEKkYD-.js +1 -0
- package/dist/dashboard/assets/CombosPage-DEEKkYD-.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js +1 -0
- package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-BKj_r0rp.js +1 -0
- package/dist/dashboard/assets/CustomizationPage-BKj_r0rp.js.gz +0 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js +656 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-C4w7vea-.js → LoginPage-DkXb6dx-.js} +1 -1
- package/dist/dashboard/assets/LoginPage-DkXb6dx-.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BtPcAfot.js → ModelPicker-DnQPSIA8.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-DnQPSIA8.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js +1 -0
- package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js +5 -0
- package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js +1 -0
- package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-5SnUSy3j.js +9 -0
- package/dist/dashboard/assets/ProxyPage-5SnUSy3j.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js +1 -0
- package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js +1 -0
- package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-BQS0Rx_u.js → SetupPage-WTa0sktC.js} +1 -1
- package/dist/dashboard/assets/SetupPage-WTa0sktC.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-TP7voAQ0.js → StudioPage-BfAb5-o_.js} +3 -3
- package/dist/dashboard/assets/StudioPage-BfAb5-o_.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js +56 -0
- package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-l29JROPv.js +1 -0
- package/dist/dashboard/assets/api-keys-l29JROPv.js.gz +0 -0
- package/dist/dashboard/assets/app--PJWq8_C.css +2 -0
- package/dist/dashboard/assets/app--PJWq8_C.css.gz +0 -0
- package/dist/dashboard/assets/{assert-C0YYuZJ4.js → assert-C0K-c4eo.js} +1 -1
- package/dist/dashboard/assets/assert-C0K-c4eo.js.gz +0 -0
- package/dist/dashboard/assets/{badge-B_DMpMJN.js → badge-DfbhQU4k.js} +1 -1
- package/dist/dashboard/assets/badge-DfbhQU4k.js.gz +0 -0
- package/dist/dashboard/assets/{banner-DMrMPmth.js → banner-BllT4LcF.js} +1 -1
- package/dist/dashboard/assets/banner-BllT4LcF.js.gz +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/{card-Be5Uzamx.js → card-CtkX66Wd.js} +1 -1
- package/dist/dashboard/assets/card-CtkX66Wd.js.gz +0 -0
- package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js +1 -0
- package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-muFRphDu.js → cli-tools-CQXVMn4P.js} +1 -1
- package/dist/dashboard/assets/cli-tools-CQXVMn4P.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-DOfrVmsi.js → clipboard-button-BQqBQd2n.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-BQqBQd2n.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-C9omdjQt.js → dialog-BEK7KP0H.js} +1 -1
- package/dist/dashboard/assets/dialog-BEK7KP0H.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-Bm8WKaGY.js → drawer-BrTEZ8zu.js} +1 -1
- package/dist/dashboard/assets/drawer-BrTEZ8zu.js.gz +0 -0
- package/dist/dashboard/assets/entry-CHWxbS56.js +1 -0
- package/dist/dashboard/assets/entry-CHWxbS56.js.gz +0 -0
- package/dist/dashboard/assets/{entry-q5HwZ8nN.js → entry-EBHJ3DrE.js} +1 -1
- package/dist/dashboard/assets/entry-EBHJ3DrE.js.gz +0 -0
- package/dist/dashboard/assets/entry-LCS85hiq.js +4 -0
- package/dist/dashboard/assets/entry-LCS85hiq.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-BTScrQpe.js → formatters-BAACA727.js} +1 -1
- package/dist/dashboard/assets/formatters-BAACA727.js.gz +0 -0
- package/dist/dashboard/assets/{github-badge-Orjuzemr.js → github-badge-YSCE4UC2.js} +1 -1
- package/dist/dashboard/assets/github-badge-YSCE4UC2.js.gz +0 -0
- package/dist/dashboard/assets/{index-cPrX5vn6.js → index-FQlj0HUT.js} +2 -2
- package/dist/dashboard/assets/index-FQlj0HUT.js.gz +0 -0
- package/dist/dashboard/assets/{inline-Dvux8w-0.js → inline-C4gU5iOL.js} +1 -1
- package/dist/dashboard/assets/inline-C4gU5iOL.js.gz +0 -0
- package/dist/dashboard/assets/{input-CU1Rgf3p.js → input-BHHX_Tmm.js} +1 -1
- package/dist/dashboard/assets/input-BHHX_Tmm.js.gz +0 -0
- package/dist/dashboard/assets/{layout-C_7A6H55.js → layout-CajrYUnD.js} +1 -1
- package/dist/dashboard/assets/{layout-C_7A6H55.js.gz → layout-CajrYUnD.js.gz} +0 -0
- package/dist/dashboard/assets/{list-row-CzFvogbj.js → list-row-Bx2I7XUe.js} +1 -1
- package/dist/dashboard/assets/list-row-Bx2I7XUe.js.gz +0 -0
- package/dist/dashboard/assets/live-DNNqRbj2.js +1 -0
- package/dist/dashboard/assets/live-DNNqRbj2.js.gz +0 -0
- package/dist/dashboard/assets/minimize-2-BTmMTK4o.js +1 -0
- package/dist/dashboard/assets/minimize-2-BTmMTK4o.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-JJGQm8TD.js → mutation-Rr0TIvcj.js} +1 -1
- package/dist/dashboard/assets/mutation-Rr0TIvcj.js.gz +0 -0
- package/dist/dashboard/assets/network-C5UBACrJ.js +1 -0
- package/dist/dashboard/assets/network-C5UBACrJ.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CUWAZK4J.js +2 -0
- package/dist/dashboard/assets/numbers-CUWAZK4J.js.gz +0 -0
- package/dist/dashboard/assets/pagination-Xsi9Qx04.js +1 -0
- package/dist/dashboard/assets/pagination-Xsi9Qx04.js.gz +0 -0
- package/dist/dashboard/assets/{query-keys-CLaNz8Xz.js → query-keys-BloKtaXJ.js} +1 -1
- package/dist/dashboard/assets/query-keys-BloKtaXJ.js.gz +0 -0
- package/dist/dashboard/assets/quota-DvQbD_sr.js +1 -0
- package/dist/dashboard/assets/quota-DvQbD_sr.js.gz +0 -0
- package/dist/dashboard/assets/{routing-BEH32QOC.js → routing-in0f_IfK.js} +1 -1
- package/dist/dashboard/assets/routing-in0f_IfK.js.gz +0 -0
- package/dist/dashboard/assets/{select-B3iTetHN.js → select-BLULNqTp.js} +2 -2
- package/dist/dashboard/assets/select-BLULNqTp.js.gz +0 -0
- package/dist/dashboard/assets/settings-CcGczj6I.js +1 -0
- package/dist/dashboard/assets/settings-CcGczj6I.js.gz +0 -0
- package/dist/dashboard/assets/shield-BMQNxORh.js +1 -0
- package/dist/dashboard/assets/shield-BMQNxORh.js.gz +0 -0
- package/dist/dashboard/assets/{stack-KrOrm7JZ.js → stack-D2lIR0tg.js} +1 -1
- package/dist/dashboard/assets/stack-D2lIR0tg.js.gz +0 -0
- package/dist/dashboard/assets/{state-DLS7IDMy.js → state-DTARjfiW.js} +1 -1
- package/dist/dashboard/assets/state-DTARjfiW.js.gz +0 -0
- package/dist/dashboard/assets/{switch-42ItvbAs.js → switch-c0oPSnqW.js} +1 -1
- package/dist/dashboard/assets/switch-c0oPSnqW.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-Dmnfh1Ue.js → useMutation-m8WGNPrz.js} +1 -1
- package/dist/dashboard/assets/useMutation-m8WGNPrz.js.gz +0 -0
- package/dist/dashboard/console-backgrounds.jpg +0 -0
- package/dist/dashboard/console-backgrounds_initial.jpg +0 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +59 -57
- package/migrations/full-postgres/0027_qoder_identity_genuine_seed.sql +9 -10
- package/migrations/full-postgres/0032_add_provider_pool_accounts.sql +53 -0
- package/migrations/full-postgres/0033_add_api_key_ban.sql +9 -0
- package/migrations/full-postgres/0034_add_api_key_ban_until.sql +7 -0
- package/migrations/full-postgres/0035_align_pool_account_status_enum.sql +21 -0
- package/migrations/full-postgres/0036_system_prompt_presets_refs.sql +10 -0
- package/migrations/full-postgres/0037_share_concurrency_scope.sql +3 -0
- package/migrations/full-postgres/0038_add_accounts_quota_snapshot.sql +7 -0
- package/migrations/full-postgres/0039_add_telemetry_provider_model_indexes.sql +13 -0
- package/migrations/full-postgres/0040_add_models_dialect.sql +3 -0
- package/migrations/full-postgres/0041_add_daily_checkin_ledger_account_fk.sql +7 -0
- package/migrations/lite-sqlite3/0027_qoder_identity_genuine_seed.sql +9 -10
- package/migrations/lite-sqlite3/0032_add_provider_pool_accounts.sql +44 -0
- package/migrations/lite-sqlite3/0033_add_api_key_ban.sql +8 -0
- package/migrations/lite-sqlite3/0034_add_api_key_ban_until.sql +5 -0
- package/migrations/lite-sqlite3/0035_align_pool_account_status_enum.sql +6 -0
- package/migrations/lite-sqlite3/0036_system_prompt_presets_refs.sql +14 -0
- package/migrations/lite-sqlite3/0037_share_concurrency_scope.sql +3 -0
- package/migrations/lite-sqlite3/0038_add_accounts_quota_snapshot.sql +4 -0
- package/migrations/lite-sqlite3/0039_add_telemetry_provider_model_indexes.sql +6 -0
- package/migrations/lite-sqlite3/0040_add_models_dialect.sql +3 -0
- package/migrations/lite-sqlite3/0041_add_daily_checkin_ledger_account_fk.sql +26 -0
- package/package.json +4 -5
- package/scripts/cli/update.ts +15 -41
- package/src/boot/app.ts +67 -10
- package/src/boot/dependencies.ts +786 -732
- package/src/boot/lifecycle.ts +11 -12
- package/src/config/cooldowns.ts +34 -55
- package/src/config/network.ts +8 -4
- package/src/config/package-paths.ts +1 -1
- package/src/config/providers.ts +13 -14
- package/src/config/resources.ts +0 -5
- package/src/config/runtime.ts +2 -5
- package/src/config/spec.ts +26 -6
- package/src/console/api-keys/ban-constants.ts +38 -0
- package/src/console/api-keys/contracts.ts +92 -31
- package/src/console/api-keys/routes.ts +131 -6
- package/src/console/audit/routes.ts +3 -3
- package/src/console/auth/access.ts +4 -4
- package/src/console/auth/account-reset.ts +5 -5
- package/src/console/auth/audit-recorder.ts +1 -1
- package/src/console/auth/lockout.ts +7 -3
- package/src/console/auth/row-coercion.ts +57 -12
- package/src/console/auth/session-resolver.ts +1 -1
- package/src/console/auth/session-service.ts +8 -2
- package/src/console/auth/session.ts +40 -34
- package/src/console/auth/setup-service.ts +4 -3
- package/src/console/auth/user-store.ts +1 -1
- package/src/console/backup/9router-map.ts +0 -3
- package/src/console/backup/contracts.ts +11 -9
- package/src/console/backup/export-endpoint.ts +11 -12
- package/src/console/backup/nine-router.ts +1 -7
- package/src/console/backup/routes.ts +32 -36
- package/src/console/backup/service.ts +468 -468
- package/src/console/backup/store.ts +47 -29
- package/src/console/backup/validate.ts +11 -1
- package/src/console/cli-tools/contracts.ts +7 -7
- package/src/console/cli-tools/injectors/cline.ts +110 -110
- package/src/console/cli-tools/injectors/codex.ts +181 -181
- package/src/console/cli-tools/injectors/copilot.ts +108 -108
- package/src/console/cli-tools/injectors/driver.ts +247 -247
- package/src/console/cli-tools/injectors/jcode.ts +115 -115
- package/src/console/cli-tools/injectors/openclaw.ts +161 -161
- package/src/console/cli-tools/injectors/opencode.ts +153 -153
- package/src/console/cli-tools/routes.ts +4 -4
- package/src/console/cli-tools/service.ts +1 -1
- package/src/console/cli-tools/store.ts +2 -2
- package/src/console/console-router-guards.ts +2 -2
- package/src/console/console-router.ts +36 -4
- package/src/console/dashboard-assets.ts +9 -9
- package/src/console/data-management/routes.ts +3 -3
- package/src/console/domain-registration.ts +18 -4
- package/src/console/inferhub/client.ts +0 -7
- package/src/console/inferhub/key-store.ts +1 -1
- package/src/console/inferhub/normalize.ts +2 -2
- package/src/console/inferhub/routes.ts +1 -1
- package/src/console/inferhub/types.ts +1 -1
- package/src/console/observability/contracts.ts +5 -1
- package/src/console/observability/live.ts +34 -21
- package/src/console/observability/logs.ts +4 -4
- package/src/console/observability/performance.ts +3 -3
- package/src/console/observability/routes.ts +3 -3
- package/src/console/observability/sse.ts +62 -8
- package/src/console/observability/store.ts +36 -20
- package/src/console/providers/catalog/catalog-projections.ts +1 -1
- package/src/console/providers/catalog/contracts.ts +82 -22
- package/src/console/providers/catalog/model-operations.ts +1 -1
- package/src/console/providers/catalog/provider-operations.ts +110 -17
- package/src/console/providers/catalog/public-model-store.ts +0 -0
- package/src/console/providers/catalog/routes.ts +30 -6
- package/src/console/providers/catalog/store-helpers.ts +349 -326
- package/src/console/providers/catalog/store.ts +1662 -1292
- package/src/console/providers/detail/routes.ts +4 -4
- package/src/console/providers/oauth/callback-listener.ts +100 -18
- package/src/console/providers/oauth/routes.ts +95 -16
- package/src/console/quota/account-quota-global.ts +41 -3
- package/src/console/quota/account-quota-shared.ts +10 -3
- package/src/console/quota/account-quota-tenant.ts +285 -67
- package/src/console/quota/account-test-egress.ts +4 -4
- package/src/console/quota/daily-growth-job.ts +308 -0
- package/src/console/quota/native-identity.ts +2 -2
- package/src/console/quota/quota-view.ts +1 -1
- package/src/console/remote-support/routes.ts +1 -1
- package/src/console/remote-support/service.ts +2 -2
- package/src/console/routing/model/contracts.ts +1 -1
- package/src/console/routing/model/routes.ts +3 -3
- package/src/console/routing/pools/contracts.ts +13 -10
- package/src/console/routing/pools/import-parse.ts +3 -3
- package/src/console/routing/pools/operations.ts +14 -7
- package/src/console/routing/pools/probe-verdict.ts +8 -3
- package/src/console/routing/pools/relay-deploy.ts +12 -12
- package/src/console/routing/pools/routes.ts +3 -3
- package/src/console/routing/pools/store.ts +21 -1
- package/src/console/settings/contracts.ts +29 -2
- package/src/console/settings/routes.ts +3 -3
- package/src/console/settings/store.ts +20 -0
- package/src/console/share/share-router.ts +112 -44
- package/src/console/share/share-stats.ts +109 -39
- package/src/console/share/share-usage.ts +1 -1
- package/src/console/shared/errors.ts +2 -2
- package/src/console/shared/object.ts +18 -0
- package/src/console/shared/read-through-cache.ts +42 -6
- package/src/console/shared/transaction.ts +14 -0
- package/src/console/system-prompt/contracts.ts +89 -12
- package/src/console/system-prompt/routes.ts +98 -45
- package/src/console/updates/apply-update.ts +244 -0
- package/src/console/updates/routes.ts +256 -98
- package/src/main.ts +11 -5
- package/src/network/http2-bidi.ts +1 -1
- package/src/network/ip-utils.ts +298 -0
- package/src/network/outbound-fetch.ts +76 -5
- package/src/network/pool/agent.ts +7 -6
- package/src/network/pool/byte-accounting.ts +1 -1
- package/src/network/pool/resolver.ts +55 -51
- package/src/network/pool/selector.ts +150 -136
- package/src/network/pool-cooldown-store.ts +71 -16
- package/src/network/pool-health-machine.ts +22 -2
- package/src/network/rate-limit-verdict.ts +68 -0
- package/src/network/retry.ts +1 -1
- package/src/network/ssrf.ts +24 -75
- package/src/observability/event-log.ts +2 -2
- package/src/observability/event-query.ts +286 -214
- package/src/observability/log-sanitize.ts +1 -1
- package/src/observability/metrics.ts +4 -4
- package/src/observability/payload-capture.ts +6 -5
- package/src/observability/payload-store.ts +1 -1
- package/src/observability/runtime-metrics.ts +1 -1
- package/src/observability/telemetry-buffer.ts +12 -3
- package/src/observability/telemetry-reconciliation.ts +3 -3
- package/src/observability/telemetry-status.ts +1 -1
- package/src/observability/token-speed.ts +1 -1
- package/src/persistence/connection-url.ts +1 -1
- package/src/persistence/db-handle.ts +1 -1
- package/src/persistence/db-pg.ts +2 -2
- package/src/persistence/db-sqlite.ts +10 -5
- package/src/persistence/dialect.ts +5 -1
- package/src/persistence/readiness.ts +19 -7
- package/src/persistence/redis.ts +1 -1
- package/src/persistence/schema.ts +177 -45
- package/src/persistence/shared-cache.ts +2 -2
- package/src/persistence/sort-order.ts +1 -1
- package/src/persistence/stores/api-key-store.ts +109 -4
- package/src/persistence/stores/share-store.ts +20 -8
- package/src/persistence/stores/telemetry-store.ts +1 -1
- package/src/persistence/system-prompt-store.ts +63 -18
- package/src/persistence/tenant-preferences.ts +1 -1
- package/src/persistence/ttl-cache.ts +3 -3
- package/src/persistence/usage-flush.ts +7 -2
- package/src/protocol/canonical-model.ts +1 -1
- package/src/protocol/codecs.ts +12 -16
- package/src/protocol/dsml.ts +3 -49
- package/src/protocol/gateway-error.ts +6 -3
- package/src/protocol/image-clamp.ts +2 -2
- package/src/protocol/image-generation.ts +2 -2
- package/src/protocol/reasoning-text.ts +1 -1
- package/src/protocol/reasoning.ts +7 -52
- package/src/protocol/registry.ts +50 -15
- package/src/protocol/request/chat.ts +46 -19
- package/src/protocol/request/codex.ts +1 -1
- package/src/protocol/request/messages.ts +46 -14
- package/src/protocol/request/responses.ts +19 -10
- package/src/protocol/response/chat.ts +27 -12
- package/src/protocol/response/codex.ts +2 -2
- package/src/protocol/response/gemini.ts +1 -1
- package/src/protocol/response/messages.ts +6 -6
- package/src/protocol/response/omp-tool-call-markup.ts +1 -1
- package/src/protocol/response/responses.ts +3 -3
- package/src/protocol/sse-decoder.ts +64 -4
- package/src/protocol/stop-reason.ts +2 -2
- package/src/protocol/think-split.ts +347 -0
- package/src/protocol/translation/attachment-integrity.ts +3 -3
- package/src/protocol/translation/cache-controls.ts +8 -20
- package/src/protocol/translation/capabilities.ts +8 -8
- package/src/protocol/translation/dialect/deepseek.ts +10 -0
- package/src/protocol/translation/dialect/inband.ts +39 -0
- package/src/protocol/translation/dialect/model-thinking.ts +89 -0
- package/src/protocol/translation/dialect/qwen.ts +114 -0
- package/src/protocol/translation/dialect/resolver.ts +83 -0
- package/src/protocol/translation/dialect/rules.ts +93 -0
- package/src/protocol/translation/dialect/thinking-ladder.ts +245 -0
- package/src/protocol/translation/dialect/types.ts +58 -0
- package/src/protocol/translation/quirks.ts +18 -4
- package/src/protocol/translation/thinking.ts +12 -252
- package/src/protocol/translation/tool-id.ts +3 -3
- package/src/protocol/translation/tool-repair.ts +1 -1
- package/src/protocol/upstream/post-json.ts +6 -1
- package/src/protocol/upstream/send-claude-messages.ts +3 -3
- package/src/providers/adapters/base-adapter.ts +1 -1
- package/src/providers/adapters/compatible-adapter.ts +44 -5
- package/src/providers/authentication/jwt-validator.ts +0 -5
- package/src/providers/authentication/oauth-client.ts +254 -253
- package/src/providers/authentication/oauth-flow-store.ts +42 -7
- package/src/providers/authentication/oauth-refresh-service.ts +2 -2
- package/src/providers/bundled-discovery-providers.ts +6 -30
- package/src/providers/configured-openai-providers.ts +82 -97
- package/src/providers/configured-provider.ts +1 -1
- package/src/providers/default-registry.ts +23 -35
- package/src/providers/discovery/catalog/catalog-format.ts +13 -2
- package/src/providers/discovery/discovery-types.ts +0 -1
- package/src/providers/discovery/openai-model-discovery.ts +2 -2
- package/src/providers/discovery/probe-phases.ts +50 -15
- package/src/providers/discovery/probing-service.ts +18 -20
- package/src/providers/integrations/agentrouter/agentrouter.ts +14 -5
- package/src/providers/integrations/alibabacp/alibabacp.ts +2 -2
- package/src/providers/integrations/anthropic.ts +4 -11
- package/src/providers/integrations/antigravity/antigravity-oauth.ts +0 -1
- package/src/providers/integrations/antigravity/antigravity-protocol.ts +0 -14
- package/src/providers/integrations/antigravity/antigravity.ts +15 -26
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +2 -2
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +20 -4
- package/src/providers/integrations/buddy/buddy-cli-headers.ts +19 -52
- package/src/providers/integrations/buddy/buddy-discovery-shared.ts +37 -6
- package/src/providers/integrations/buddy/buddy-identity.ts +108 -1
- package/src/providers/integrations/buddy/buddy-media.ts +16 -16
- package/src/providers/integrations/buddy/buddy-oauth-shared.ts +1 -1
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +1 -2
- package/src/providers/integrations/buddy/codebuddy/provider.ts +5 -16
- package/src/providers/integrations/buddy/codebuddy/shared.ts +30 -9
- package/src/providers/integrations/buddy/workbuddy/provider.ts +6 -10
- package/src/providers/integrations/buddy/workbuddy/shared.ts +21 -3
- package/src/providers/integrations/claude/claude-betas.ts +1 -1
- package/src/providers/integrations/claude/claude-cch.ts +148 -148
- package/src/providers/integrations/claude/claude-credentials.ts +1 -1
- package/src/providers/integrations/claude/claude-slow-lane-retry.ts +1 -1
- package/src/providers/integrations/claude/claude.ts +3 -10
- package/src/providers/integrations/claude/fallback-credit.ts +3 -7
- package/src/providers/integrations/cline/cline.ts +2 -2
- package/src/providers/integrations/cloudflareai/cloudflareai.ts +4 -7
- package/src/providers/integrations/codex/codex-device-code.ts +101 -101
- package/src/providers/integrations/codex/codex-errors.ts +1 -1
- package/src/providers/integrations/codex/codex-oauth.ts +0 -1
- package/src/providers/integrations/codex/codex.ts +14 -15
- package/src/providers/integrations/commandcode/commandcode.ts +76 -116
- package/src/providers/integrations/commandcode/quota.ts +132 -48
- package/src/providers/integrations/cursor/cursor-http2.ts +11 -14
- package/src/providers/integrations/cursor/cursor-quota.ts +2 -6
- package/src/providers/integrations/cursor/cursor-request.ts +0 -87
- package/src/providers/integrations/cursor/cursor-shared.ts +0 -4
- package/src/providers/integrations/cursor/cursor.ts +53 -20
- package/src/providers/integrations/cursor/protocol/framing.ts +0 -56
- package/src/providers/integrations/cursor/protocol/messages.ts +0 -96
- package/src/providers/integrations/factory/factory.ts +13 -13
- package/src/providers/integrations/gemini.ts +11 -11
- package/src/providers/integrations/github/github-discovery.ts +55 -10
- package/src/providers/integrations/github/github-oauth.ts +6 -5
- package/src/providers/integrations/github/github.ts +47 -20
- package/src/providers/integrations/grok/grok-oauth.ts +261 -261
- package/src/providers/integrations/grok/grok-quota-frame.ts +1 -1
- package/src/providers/integrations/grok/grok-quota.ts +16 -7
- package/src/providers/integrations/grok/grok-ratelimit-store.ts +0 -5
- package/src/providers/integrations/grok/grok-ratelimit.ts +3 -0
- package/src/providers/integrations/grok/grok.ts +88 -42
- package/src/providers/integrations/inferhub.ts +4 -11
- package/src/providers/integrations/kilo/kilo-oauth.ts +1 -1
- package/src/providers/integrations/kimi/kimi.ts +4 -11
- package/src/providers/integrations/kiro/kiro-cache.ts +31 -0
- package/src/providers/integrations/kiro/kiro-catalog.ts +31 -5
- package/src/providers/integrations/kiro/kiro-discovery.ts +47 -43
- package/src/providers/integrations/kiro/kiro-machine-id.ts +6 -3
- package/src/providers/integrations/kiro/kiro-oauth.ts +523 -255
- package/src/providers/integrations/kiro/kiro-quota.ts +35 -47
- package/src/providers/integrations/kiro/kiro-request.ts +8 -11
- package/src/providers/integrations/kiro/kiro-stream.ts +13 -0
- package/src/providers/integrations/kiro/kiro.ts +91 -78
- package/src/providers/integrations/muse/muse-oauth.ts +0 -1
- package/src/providers/integrations/muse/muse-quota.ts +0 -4
- package/src/providers/integrations/muse/muse.ts +6 -9
- package/src/providers/integrations/opencode/fingerprint.ts +7 -5
- package/src/providers/integrations/opencode/provider.ts +17 -24
- package/src/providers/integrations/perplexity.ts +2 -2
- package/src/providers/integrations/qoder/qoder-catalog.ts +132 -17
- package/src/providers/integrations/qoder/qoder-checkin.ts +26 -8
- package/src/providers/integrations/qoder/qoder-native-identity-store.ts +9 -8
- package/src/providers/integrations/qoder/qoder-oauth.ts +165 -25
- package/src/providers/integrations/qoder/qoder-quota.ts +48 -6
- package/src/providers/integrations/qoder/qoder-realm.ts +22 -28
- package/src/providers/integrations/qoder/qoder-sse.ts +159 -0
- package/src/providers/integrations/qoder/qoder-umid.ts +33 -38
- package/src/providers/integrations/qoder/qoder-virtual.ts +14 -2
- package/src/providers/integrations/qoder/qoder.ts +521 -63
- package/src/providers/integrations/shared/connect.ts +0 -54
- package/src/providers/integrations/shared/hash.ts +15 -0
- package/src/providers/integrations/shared/session-cache.ts +136 -0
- package/src/providers/integrations/tokenharbor.ts +2 -2
- package/src/providers/integrations/trae/trae-cache.ts +7 -87
- package/src/providers/integrations/trae/trae-catalog.ts +1 -6
- package/src/providers/integrations/trae/trae-protocol.ts +17 -8
- package/src/providers/integrations/trae/trae-realm.ts +0 -7
- package/src/providers/integrations/trae/trae.ts +59 -19
- package/src/providers/integrations/xai/xai-oauth.ts +5 -5
- package/src/providers/integrations/zcode/oauth.ts +1 -1
- package/src/providers/integrations/zcode-start-plan/gifts.ts +265 -0
- package/src/providers/integrations/zcode-start-plan/oauth.ts +154 -0
- package/src/providers/integrations/zcode-start-plan/provider.ts +131 -0
- package/src/providers/integrations/zcode-start-plan/quota.ts +152 -0
- package/src/providers/integrations/zcode-start-plan/zcode_prompt.json +10 -0
- package/src/providers/operations/account-error-classification.ts +131 -116
- package/src/providers/operations/account-health-service.ts +31 -39
- package/src/providers/operations/account-reset-service.ts +58 -1
- package/src/providers/operations/cli-platform.ts +31 -5
- package/src/providers/operations/client-version-resolver.ts +4 -6
- package/src/providers/operations/client-versions.ts +10 -7
- package/src/providers/operations/provider-catalog-seeder.ts +2 -0
- package/src/providers/operations/provider-catalog-service.ts +22 -6
- package/src/providers/operations/provider-credential-service.ts +35 -6
- package/src/providers/operations/upstream-deadline.ts +3 -3
- package/src/providers/provider-contracts.ts +65 -10
- package/src/providers/provider-credential-resolver.ts +1 -1
- package/src/providers/provider-metadata.ts +17 -2
- package/src/providers/provider-model-definition.ts +22 -1
- package/src/providers/provider-probe.ts +4 -2
- package/src/providers/provider-registry.ts +4 -4
- package/src/providers/provider-usage.ts +81 -16
- package/src/providers/quota/cache.ts +29 -0
- package/src/providers/quota/quota-contracts.ts +28 -10
- package/src/providers/quota/refresh.ts +29 -6
- package/src/providers/quota/snapshot.ts +94 -0
- package/src/providers/search/search-provider.ts +6 -8
- package/src/providers/search/search-providers.ts +2 -1
- package/src/security/abuse.ts +8 -8
- package/src/security/admission/reasons.ts +17 -17
- package/src/security/admission/service.ts +2 -2
- package/src/security/admission/ttl.ts +61 -61
- package/src/security/api-key-auth.ts +20 -8
- package/src/security/client-router-fingerprint.ts +4 -4
- package/src/security/credential-codec.ts +3 -3
- package/src/security/csrf.ts +2 -2
- package/src/security/ip-boundary.ts +16 -189
- package/src/security/model-access-rule.ts +1 -1
- package/src/security/outbound-headers.ts +18 -0
- package/src/shared/coerce.ts +19 -0
- package/src/shared/invoke-guard.ts +47 -0
- package/src/transport/contracts.ts +13 -4
- package/src/transport/dispatch/attempt-finalize.ts +5 -4
- package/src/transport/dispatch/attempt-loop.ts +10 -7
- package/src/transport/dispatch/capture-policy.ts +34 -37
- package/src/transport/dispatch/empty-stream.ts +28 -25
- package/src/transport/dispatch/generation.ts +33 -53
- package/src/transport/dispatch/leases.ts +8 -8
- package/src/transport/dispatch/native-shared.ts +127 -0
- package/src/transport/dispatch/proxy-request.ts +10 -8
- package/src/transport/dispatch/responses-compact.ts +35 -56
- package/src/transport/dispatch/retry-policy.ts +4 -67
- package/src/transport/dispatch/stream-bridge.ts +1 -1
- package/src/transport/dispatch/streaming/encoder.ts +18 -72
- package/src/transport/dispatch/streaming/finalize.ts +11 -10
- package/src/transport/dispatch/streaming/stream.ts +7 -3
- package/src/transport/dispatch/streaming/thinking-loop.ts +1 -1
- package/src/transport/dispatch/systemone.ts +27 -55
- package/src/transport/dispatch/token-count.ts +49 -46
- package/src/transport/dispatch/websearch.ts +24 -50
- package/src/transport/drain-endpoint.ts +3 -3
- package/src/transport/failure-policy.ts +19 -6
- package/src/transport/guards/auth-guard.ts +6 -11
- package/src/transport/guards/body-policy.ts +7 -7
- package/src/transport/guards/error-lifecycle.ts +18 -3
- package/src/transport/guards/guard-errors.ts +7 -3
- package/src/transport/guards/headroom-guard.ts +2 -2
- package/src/transport/guards/pipeline.ts +7 -7
- package/src/transport/guards/readiness-guard.ts +16 -2
- package/src/transport/guards/request-context.ts +15 -20
- package/src/transport/request/preparer.ts +306 -27
- package/src/transport/request/rtk/compress-request.ts +3 -3
- package/src/transport/request/rtk/rtk-constants.ts +2 -2
- package/src/transport/request/rtk/rtk-filters.ts +8 -8
- package/src/transport/request/state.ts +5 -20
- package/src/transport/request/system-prompt-injection.ts +74 -11
- package/src/transport/request/tenant-preferences.ts +22 -0
- package/src/transport/routing/candidate-index.ts +2 -2
- package/src/transport/routing/round-robin.ts +1 -1
- package/src/transport/routing/route-catalog.ts +113 -19
- package/src/transport/routing/route-model.ts +131 -38
- package/src/transport/routing/router.ts +154 -39
- package/src/transport/shutdown-notice.ts +21 -9
- package/src/transport/surface/adapters.ts +3 -3
- package/src/transport/surface/chat/encode.ts +7 -7
- package/src/transport/surface/chat/parse.ts +7 -7
- package/src/transport/surface/completion.ts +3 -3
- package/src/transport/surface/content-parts.ts +1 -1
- package/src/transport/surface/dialects.ts +2 -2
- package/src/transport/surface/messages/encode.ts +1 -1
- package/src/transport/surface/messages/parse.ts +3 -3
- package/src/transport/surface/responses/adapter.ts +1 -1
- package/src/transport/surface/responses/errors.ts +0 -9
- package/src/transport/vision-handoff-cache.ts +58 -0
- package/src/transport/vision-handoff.ts +376 -0
- package/src/workers/account-identity-sweep.ts +2 -2
- package/src/workers/buddy-growth-tasks.ts +392 -346
- package/src/workers/daily-checkin.ts +102 -49
- package/src/workers/maintenance-lease.ts +2 -35
- package/src/workers/oauth-refresh-sweep.ts +8 -1
- package/src/workers/quota-refresh-sweep.ts +120 -82
- package/src/workers/scheduler.ts +67 -4
- package/src/workers/sweep-runner.ts +24 -5
- package/src/workers/zcode-gift-claim.ts +108 -0
- package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js +0 -1
- package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js.gz +0 -0
- package/dist/dashboard/assets/BannedPage-2TJD37Hb.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-xefJNRmJ.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-Rj9iHQ3F.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-JEbYJFxw.js +0 -1
- package/dist/dashboard/assets/CombosPage-JEbYJFxw.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-C3xx_inM.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-C3xx_inM.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-Dw306gJU.js +0 -1
- package/dist/dashboard/assets/CustomizationPage-Dw306gJU.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-jaBo1TWV.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-jaBo1TWV.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-C4w7vea-.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-BtPcAfot.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-CGC5gNs1.js +0 -1
- package/dist/dashboard/assets/OverviewPage-CGC5gNs1.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-DQcthNGt.js +0 -4
- package/dist/dashboard/assets/ProviderDetailPage-DQcthNGt.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js +0 -1
- package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-0OsXRGXe.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-0OsXRGXe.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-DdPc8slb.js +0 -9
- package/dist/dashboard/assets/ProxyPage-DdPc8slb.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-Ci5O4BnH.js +0 -1
- package/dist/dashboard/assets/QuotaPage-Ci5O4BnH.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CDZjTt87.js +0 -1
- package/dist/dashboard/assets/SettingsPage-CDZjTt87.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-BQS0Rx_u.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-BAL5npBC.js +0 -1
- package/dist/dashboard/assets/SortableList-BAL5npBC.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-TP7voAQ0.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-Cj_fEzhg.js +0 -56
- package/dist/dashboard/assets/UsagePage-Cj_fEzhg.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-MbI7e7rt.js +0 -1
- package/dist/dashboard/assets/api-keys-MbI7e7rt.js.gz +0 -0
- package/dist/dashboard/assets/app-B2vyPoII.css +0 -2
- package/dist/dashboard/assets/app-B2vyPoII.css.gz +0 -0
- package/dist/dashboard/assets/assert-C0YYuZJ4.js.gz +0 -0
- package/dist/dashboard/assets/badge-B_DMpMJN.js.gz +0 -0
- package/dist/dashboard/assets/banner-DMrMPmth.js.gz +0 -0
- package/dist/dashboard/assets/card-Be5Uzamx.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-muFRphDu.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-DOfrVmsi.js.gz +0 -0
- package/dist/dashboard/assets/dialog-C9omdjQt.js.gz +0 -0
- package/dist/dashboard/assets/drawer-Bm8WKaGY.js.gz +0 -0
- package/dist/dashboard/assets/entry-DS90gUks.js +0 -1
- package/dist/dashboard/assets/entry-DS90gUks.js.gz +0 -0
- package/dist/dashboard/assets/entry-j40LJotO.js +0 -4
- package/dist/dashboard/assets/entry-j40LJotO.js.gz +0 -0
- package/dist/dashboard/assets/entry-q5HwZ8nN.js.gz +0 -0
- package/dist/dashboard/assets/formatters-BTScrQpe.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-Orjuzemr.js.gz +0 -0
- package/dist/dashboard/assets/index-cPrX5vn6.js.gz +0 -0
- package/dist/dashboard/assets/inline-Dvux8w-0.js.gz +0 -0
- package/dist/dashboard/assets/input-CU1Rgf3p.js.gz +0 -0
- package/dist/dashboard/assets/list-row-CzFvogbj.js.gz +0 -0
- package/dist/dashboard/assets/live-KaG15HLQ.js +0 -1
- package/dist/dashboard/assets/live-KaG15HLQ.js.gz +0 -0
- package/dist/dashboard/assets/minimize-2-D-MN8W8a.js +0 -1
- package/dist/dashboard/assets/minimize-2-D-MN8W8a.js.gz +0 -0
- package/dist/dashboard/assets/mutation-JJGQm8TD.js.gz +0 -0
- package/dist/dashboard/assets/numbers-BNDZnsUE.js +0 -2
- package/dist/dashboard/assets/numbers-BNDZnsUE.js.gz +0 -0
- package/dist/dashboard/assets/query-keys-CLaNz8Xz.js.gz +0 -0
- package/dist/dashboard/assets/quota-DZGyp0N5.js +0 -1
- package/dist/dashboard/assets/quota-DZGyp0N5.js.gz +0 -0
- package/dist/dashboard/assets/routing-BEH32QOC.js.gz +0 -0
- package/dist/dashboard/assets/select-B3iTetHN.js.gz +0 -0
- package/dist/dashboard/assets/settings-Dt3Eqbnq.js +0 -1
- package/dist/dashboard/assets/settings-Dt3Eqbnq.js.gz +0 -0
- package/dist/dashboard/assets/stack-KrOrm7JZ.js.gz +0 -0
- package/dist/dashboard/assets/state-DLS7IDMy.js.gz +0 -0
- package/dist/dashboard/assets/stream-retry-5QnVuSSo.js +0 -1
- package/dist/dashboard/assets/stream-retry-5QnVuSSo.js.gz +0 -0
- package/dist/dashboard/assets/switch-42ItvbAs.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-Dmnfh1Ue.js.gz +0 -0
- package/src/network/response-headers.ts +0 -39
- package/src/protocol/response/dsml.ts +0 -38
- package/src/providers/integrations/xiaomi-mimo/think-stream.ts +0 -229
- /package/dist/dashboard/assets/{app-wvwCi4Eh.js → app-Bgd3zANQ.js} +0 -0
- /package/dist/dashboard/assets/{app-wvwCi4Eh.js.gz → app-Bgd3zANQ.js.gz} +0 -0
- /package/dist/dashboard/assets/brand/{og_bansos.webp → og_bansos_initial.webp} +0 -0
- /package/dist/dashboard/assets/brand/{og_image.webp → og_image_initial.webp} +0 -0
|
@@ -4,17 +4,22 @@ import type { Elysia } from "elysia";
|
|
|
4
4
|
import { and, eq, inArray } from "drizzle-orm";
|
|
5
5
|
import { providerAccounts, providers } from "../../persistence/schema";
|
|
6
6
|
import { providerDisplayName } from "../../providers/provider-metadata";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
invalidateCredentialCache,
|
|
9
|
+
invalidateCredentialCaches,
|
|
10
|
+
} from "../../providers/operations/provider-credential-service";
|
|
8
11
|
import { requireTenantScope } from "../shared/errors";
|
|
9
12
|
import { BUDDY_PROVIDER_IDS } from "../../providers/provider-metadata";
|
|
10
|
-
import { readBuddyUsageSnapshots } from "../../providers/integrations/buddy/buddy-usage-store";
|
|
11
13
|
import { GatewayError } from "../../protocol/gateway-error";
|
|
12
14
|
import {
|
|
13
15
|
GLOBAL_QUOTA_LENS,
|
|
14
16
|
getCachedQuotaEntries,
|
|
15
17
|
getCachedQuotaEntry,
|
|
16
18
|
invalidateQuotaCache,
|
|
19
|
+
invalidateQuotaCaches,
|
|
20
|
+
invalidateQuotaCacheForAccount,
|
|
17
21
|
} from "../../providers/quota/cache";
|
|
22
|
+
import { readQuotaSnapshot, readQuotaSnapshots } from "../../providers/quota/snapshot";
|
|
18
23
|
import {
|
|
19
24
|
QUOTA_REFRESH_TIMEOUT_MS,
|
|
20
25
|
refreshAccountQuota,
|
|
@@ -47,13 +52,16 @@ import {
|
|
|
47
52
|
DrizzleQoderNativeIdentityStore,
|
|
48
53
|
type QoderNativeIdentityStore,
|
|
49
54
|
} from "../../providers/integrations/qoder/qoder-native-identity-store";
|
|
50
|
-
import {
|
|
55
|
+
import { claimZcodeGifts, type ZcodeGiftResult } from "../../providers/integrations/zcode-start-plan/gifts";
|
|
56
|
+
import { ZCODE_START_PLAN_PROVIDER_ID } from "../../providers/integrations/zcode-start-plan/provider";
|
|
51
57
|
import {
|
|
52
58
|
supportsAccountReset,
|
|
53
59
|
consumeAccountResetCredit,
|
|
60
|
+
getCachedResetCredits,
|
|
54
61
|
listAccountResetCredits,
|
|
55
62
|
} from "../../providers/operations/account-reset-service";
|
|
56
63
|
import {
|
|
64
|
+
enqueueBackgroundQuotaRefresh,
|
|
57
65
|
pendingQuotaRefreshes,
|
|
58
66
|
toQuotaAccountHealth,
|
|
59
67
|
toQuotaView,
|
|
@@ -63,6 +71,14 @@ import {
|
|
|
63
71
|
type AccountQuotaRoutesDeps,
|
|
64
72
|
type AccountStatus,
|
|
65
73
|
} from "./account-quota-shared";
|
|
74
|
+
import {
|
|
75
|
+
DAILY_GROWTH_LEG_TIMEOUT_MS,
|
|
76
|
+
enqueueDailyGrowthJob,
|
|
77
|
+
getDailyGrowthJob,
|
|
78
|
+
withLegBudget,
|
|
79
|
+
type DailyGrowthJobAccount,
|
|
80
|
+
type DailyGrowthJobDeps,
|
|
81
|
+
} from "./daily-growth-job";
|
|
66
82
|
|
|
67
83
|
/** Daily check-in only exists on the buddy billing facade; everything else 400s with intent. */
|
|
68
84
|
function supportsAccountCheckin(providerId: string): boolean {
|
|
@@ -132,10 +148,6 @@ async function runAccountCheckin(
|
|
|
132
148
|
});
|
|
133
149
|
}
|
|
134
150
|
|
|
135
|
-
/** Bound on accounts one manual daily-growth batch may cover. */
|
|
136
|
-
/** Concurrent accounts inside one manual daily-growth batch. */
|
|
137
|
-
const DAILY_GROWTH_CONCURRENCY = 3;
|
|
138
|
-
|
|
139
151
|
/**
|
|
140
152
|
* One account's daily growth pass, report first then claim.
|
|
141
153
|
*
|
|
@@ -174,6 +186,12 @@ async function runDailyGrowthForAccount(
|
|
|
174
186
|
// fails closed instead of reporting under another account's identity. Qoder
|
|
175
187
|
// has no activity-report leg — its daily grant is purely the check-in.
|
|
176
188
|
const qoderAccount = isQoderCheckinProvider(String(providerId));
|
|
189
|
+
// dynamic-import: B-02 lazy graph — buddy uid decoder, only for buddy report legs.
|
|
190
|
+
// The buddy-oauth-shared graph is lazy-loaded: the uid decoder is only
|
|
191
|
+
// needed for buddy accounts' report leg (B-02).
|
|
192
|
+
const { buddyAccountUid } = await import(
|
|
193
|
+
"../../providers/integrations/buddy/buddy-oauth-shared"
|
|
194
|
+
);
|
|
177
195
|
const userId = buddyAccountUid(credential);
|
|
178
196
|
let report: { ok: boolean; message: string };
|
|
179
197
|
if (qoderAccount) {
|
|
@@ -352,6 +370,13 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
352
370
|
getCachedQuotaEntries(access.tenantId, ownedIds, redis),
|
|
353
371
|
getCachedQuotaEntries(GLOBAL_QUOTA_LENS, globalIds, redis),
|
|
354
372
|
]);
|
|
373
|
+
// A page open right after a restart finds the in-process cache empty.
|
|
374
|
+
// Fall back to the persisted snapshots (which survive a restart) so the
|
|
375
|
+
// page still renders the last known balance; the sweep refreshes it.
|
|
376
|
+
const snapshots = await readQuotaSnapshots(
|
|
377
|
+
db,
|
|
378
|
+
rows.filter((row) => !globalCache.has(row.id) && !ownedCache.has(row.id)).map((row) => row.id),
|
|
379
|
+
);
|
|
355
380
|
|
|
356
381
|
const pending = pendingQuotaRefreshes();
|
|
357
382
|
const providerIds = [...new Set(rows.map((row) => row.providerId))];
|
|
@@ -369,6 +394,15 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
369
394
|
icon: providerId,
|
|
370
395
|
}));
|
|
371
396
|
let refreshing = 0;
|
|
397
|
+
// Cold-cache backfill: the overview renders whatever is cached, and the
|
|
398
|
+
// periodic sweep owns freshness — but with many accounts (e.g. a large
|
|
399
|
+
// Qoder roster) the sweep's per-pass cap cannot keep every cache warm,
|
|
400
|
+
// so a page open would show accounts with no badge for minutes. Enqueue
|
|
401
|
+
// a bounded background refresh for accounts whose cache entry is missing
|
|
402
|
+
// (not merely stale), so the badge fills in without waiting for the next
|
|
403
|
+
// sweep pass and without fanning out to the whole roster at once.
|
|
404
|
+
const coldCacheCap = 20;
|
|
405
|
+
let coldCacheEnqueued = 0;
|
|
372
406
|
// The sweep's day markers answer "attempted today" without an upstream
|
|
373
407
|
// request; only check-in-capable accounts can carry one, so only they
|
|
374
408
|
// are read.
|
|
@@ -385,6 +419,12 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
385
419
|
// the upstream: the page renders every account at once, and re-hitting the
|
|
386
420
|
// billing endpoint per account would make opening it scale with the
|
|
387
421
|
// account count. One batch read for every buddy row.
|
|
422
|
+
// dynamic-import: B-02 lazy graph — buddy usage snapshots, only when the page renders buddy accounts.
|
|
423
|
+
// The buddy-usage-store graph is lazy-loaded: it is only needed when the
|
|
424
|
+
// page actually renders buddy accounts (B-02).
|
|
425
|
+
const { readBuddyUsageSnapshots } = await import(
|
|
426
|
+
"../../providers/integrations/buddy/buddy-usage-store"
|
|
427
|
+
);
|
|
388
428
|
const usageByAccount = await readBuddyUsageSnapshots(
|
|
389
429
|
db,
|
|
390
430
|
rows.filter((row) => isBuddyProvider(row.providerId)).map((row) => row.id),
|
|
@@ -392,6 +432,9 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
392
432
|
const accounts = rows.map((row) => {
|
|
393
433
|
const entry =
|
|
394
434
|
row.tenantId === null ? globalCache.get(row.id) : ownedCache.get(row.id);
|
|
435
|
+
const snapshot = entry ?? snapshots.get(row.id);
|
|
436
|
+
const entryQuota = snapshot ? snapshot.quota : null;
|
|
437
|
+
const entryFetchedAt = snapshot ? snapshot.fetchedAt : null;
|
|
395
438
|
// No background refresh is enqueued here: enqueuing one for every
|
|
396
439
|
// account whose cached value had aged out means a single page open hits
|
|
397
440
|
// every provider's quota endpoint at once — and because the page also
|
|
@@ -404,19 +447,34 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
404
447
|
const canRefresh = providerRegistry.hasQuotaCollector(row.providerId);
|
|
405
448
|
const isRefreshing = canRefresh && (pending.has(row.id) || entry === undefined);
|
|
406
449
|
if (isRefreshing) refreshing += 1;
|
|
450
|
+
// Backfill a missing cache entry on page open (bounded, see above).
|
|
451
|
+
if (
|
|
452
|
+
canRefresh &&
|
|
453
|
+
entry === undefined &&
|
|
454
|
+
!pending.has(row.id) &&
|
|
455
|
+
coldCacheEnqueued < coldCacheCap
|
|
456
|
+
) {
|
|
457
|
+
coldCacheEnqueued += 1;
|
|
458
|
+
enqueueBackgroundQuotaRefresh(refreshDeps, {
|
|
459
|
+
accountId: row.id,
|
|
460
|
+
providerId: row.providerId,
|
|
461
|
+
tenantId: row.tenantId,
|
|
462
|
+
credentialKind: row.credentialKind,
|
|
463
|
+
});
|
|
464
|
+
}
|
|
407
465
|
return {
|
|
408
466
|
id: row.id,
|
|
409
467
|
provider: row.providerId,
|
|
410
468
|
name: row.label || row.id,
|
|
411
469
|
credentialHint: row.credentialKind,
|
|
412
470
|
active: row.status === "active",
|
|
413
|
-
quota:
|
|
414
|
-
? toQuotaView(
|
|
415
|
-
fetchedAt:
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
471
|
+
quota: entryQuota
|
|
472
|
+
? toQuotaView(entryQuota, row, {
|
|
473
|
+
fetchedAt: entryFetchedAt,
|
|
474
|
+
lastAttemptAt: entry?.lastAttemptAt ?? null,
|
|
475
|
+
refreshError: entry?.refreshError ?? null,
|
|
476
|
+
...(isRefreshing ? { status: "refreshing" as const } : {}),
|
|
477
|
+
})
|
|
420
478
|
: null,
|
|
421
479
|
pending: isRefreshing,
|
|
422
480
|
health: toQuotaAccountHealth(row),
|
|
@@ -478,13 +536,33 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
478
536
|
health: toQuotaAccountHealth(account),
|
|
479
537
|
};
|
|
480
538
|
}
|
|
539
|
+
// Cache is cold (e.g. right after a restart): render the last persisted
|
|
540
|
+
// snapshot instead of hitting upstream on every page open. The sweep
|
|
541
|
+
// refreshes it; a page open does not need to pay the upstream cost.
|
|
542
|
+
const snapshot = await readQuotaSnapshot(db, accountId);
|
|
543
|
+
if (snapshot) {
|
|
544
|
+
return {
|
|
545
|
+
accountId,
|
|
546
|
+
quota: toQuotaView(snapshot.quota, account, {
|
|
547
|
+
fetchedAt: snapshot.fetchedAt,
|
|
548
|
+
lastAttemptAt: snapshot.fetchedAt,
|
|
549
|
+
}),
|
|
550
|
+
health: toQuotaAccountHealth(account),
|
|
551
|
+
};
|
|
552
|
+
}
|
|
481
553
|
|
|
482
554
|
// Cold read: this is the one path that legitimately waits on upstream, and
|
|
483
555
|
// it shares the in-flight fetch with any queued background fill so a cold
|
|
484
556
|
// page open never issues two requests for the same account.
|
|
485
557
|
const outcome = await refreshAccountQuota(
|
|
486
558
|
refreshDeps,
|
|
487
|
-
{
|
|
559
|
+
{
|
|
560
|
+
accountId,
|
|
561
|
+
providerId: account.providerId,
|
|
562
|
+
tenantId: account.tenantId,
|
|
563
|
+
credentialKind: account.credentialKind,
|
|
564
|
+
authState: account.authState,
|
|
565
|
+
},
|
|
488
566
|
signalFetch(timeoutSignal(request.signal, QUOTA_REFRESH_TIMEOUT_MS)),
|
|
489
567
|
);
|
|
490
568
|
const fresh = await getCachedQuotaEntry(access.tenantId, accountId, redis);
|
|
@@ -525,7 +603,7 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
525
603
|
throw new GatewayError(
|
|
526
604
|
"proxy_pool_unavailable",
|
|
527
605
|
503,
|
|
528
|
-
"Account test cannot select a proxy because proxy routing is not configured.",
|
|
606
|
+
"Account test cannot select a proxy because proxy routing is not configured (request {requestId}). No bridge to cross — configure a pool first 🏗️",
|
|
529
607
|
{ reason: "proxy_routing_unconfigured" },
|
|
530
608
|
"network",
|
|
531
609
|
);
|
|
@@ -546,7 +624,16 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
546
624
|
try {
|
|
547
625
|
outcome = await refreshAccountQuota(
|
|
548
626
|
refreshDeps,
|
|
549
|
-
{
|
|
627
|
+
{
|
|
628
|
+
accountId,
|
|
629
|
+
providerId: account.providerId,
|
|
630
|
+
tenantId: account.tenantId,
|
|
631
|
+
credentialKind: account.credentialKind,
|
|
632
|
+
// Kiro's usage surface is profile-scoped: without the account's auth
|
|
633
|
+
// state the collector cannot resolve a `profileArn`, and the GET is
|
|
634
|
+
// refused with `400 Invalid profileArn.`.
|
|
635
|
+
authState: account.authState,
|
|
636
|
+
},
|
|
550
637
|
egress.fetch,
|
|
551
638
|
);
|
|
552
639
|
} finally {
|
|
@@ -591,6 +678,7 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
591
678
|
providerId: providerAccounts.providerId,
|
|
592
679
|
tenantId: providerAccounts.tenantId,
|
|
593
680
|
credentialKind: providerAccounts.credentialKind,
|
|
681
|
+
authState: providerAccounts.authState,
|
|
594
682
|
})
|
|
595
683
|
.from(providerAccounts)
|
|
596
684
|
.where(
|
|
@@ -751,17 +839,60 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
751
839
|
});
|
|
752
840
|
return { success: true };
|
|
753
841
|
})
|
|
842
|
+
.post(
|
|
843
|
+
"/accounts/batch-delete",
|
|
844
|
+
{
|
|
845
|
+
body: t.Object({
|
|
846
|
+
accountIds: t.Array(t.String()),
|
|
847
|
+
}),
|
|
848
|
+
},
|
|
849
|
+
async ({ request, body }) => {
|
|
850
|
+
const access = requireTenantScope(accessResolver(request), "dashboard:write");
|
|
851
|
+
const accountIds = [...new Set(body.accountIds)];
|
|
852
|
+
if (accountIds.length === 0) {
|
|
853
|
+
return { ok: true, deleted: [], missing: [] };
|
|
854
|
+
}
|
|
855
|
+
// One DELETE statement for the whole batch, scoped to the tenant: a
|
|
856
|
+
// global/shared account (`tenant_id IS NULL`) is never matchable, so
|
|
857
|
+
// it lands in `missing` rather than being deleted by a tenant.
|
|
858
|
+
const deleted = await db
|
|
859
|
+
.delete(providerAccounts)
|
|
860
|
+
.where(
|
|
861
|
+
and(
|
|
862
|
+
inArray(providerAccounts.id, accountIds),
|
|
863
|
+
eq(providerAccounts.tenantId, access.tenantId),
|
|
864
|
+
),
|
|
865
|
+
)
|
|
866
|
+
.returning({ id: providerAccounts.id });
|
|
867
|
+
const deletedIds = deleted.map((row) => row.id);
|
|
868
|
+
const deletedSet = new Set(deletedIds);
|
|
869
|
+
const missing = accountIds.filter((id) => !deletedSet.has(id));
|
|
870
|
+
// One credential-cache pass, one quota-cache pass, one snapshot
|
|
871
|
+
// invalidation, one audit row — never one per deleted account.
|
|
872
|
+
invalidateCredentialCaches(deletedIds);
|
|
873
|
+
await invalidateQuotaCaches(access.tenantId, deletedIds, redis);
|
|
874
|
+
await snapshotInvalidator?.invalidate();
|
|
875
|
+
await auditRecorder?.record({
|
|
876
|
+
access,
|
|
877
|
+
action: "provider_account.batch_deleted",
|
|
878
|
+
target: access.tenantId,
|
|
879
|
+
detail: { deleted: deletedIds, missing },
|
|
880
|
+
});
|
|
881
|
+
return { ok: true, deleted: deletedIds, missing };
|
|
882
|
+
},
|
|
883
|
+
)
|
|
754
884
|
/**
|
|
755
|
-
*
|
|
756
|
-
*
|
|
885
|
+
* Enqueues a background daily-growth job over a provider's accounts: the
|
|
886
|
+
* growth-activity report first, then the check-in claim — the order the
|
|
757
887
|
* sweep uses — with egress rotated per account the same way the worker
|
|
758
888
|
* does, so a batch leaves from more than one address.
|
|
759
889
|
*
|
|
760
|
-
*
|
|
761
|
-
*
|
|
762
|
-
*
|
|
763
|
-
*
|
|
764
|
-
*
|
|
890
|
+
* Running the whole batch in the request held it open for every account's
|
|
891
|
+
* upstream calls; the route now returns `{ jobId }` immediately and the
|
|
892
|
+
* work drains through a bounded background worker (see the job status
|
|
893
|
+
* route below). A manual trigger is the operator asserting "try now", so
|
|
894
|
+
* it bypasses the sweep's once-per-day ledger; the upstream stays
|
|
895
|
+
* idempotent either way.
|
|
765
896
|
*/
|
|
766
897
|
.post(
|
|
767
898
|
"/quota/daily-growth",
|
|
@@ -807,59 +938,66 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
807
938
|
};
|
|
808
939
|
}
|
|
809
940
|
// No size cap, for the same reason as the quota refresh: the work is
|
|
810
|
-
// already drained through a bounded worker pool
|
|
811
|
-
// protected nothing and just forced the operator
|
|
812
|
-
//
|
|
813
|
-
//
|
|
941
|
+
// already drained through a bounded worker pool behind the job, so
|
|
942
|
+
// refusing the request protected nothing and just forced the operator
|
|
943
|
+
// to batch by hand.
|
|
944
|
+
//
|
|
945
|
+
// One egress rotator for the whole job, exactly as the sweep builds it,
|
|
946
|
+
// so consecutive accounts leave from consecutive pools. The job carries
|
|
947
|
+
// the per-account run (report then claim) through the injected runner.
|
|
814
948
|
const rotator =
|
|
815
949
|
networkBindingFactory !== undefined
|
|
816
950
|
? dailyCheckinEgressForPass({ db, networkBindingFactory })
|
|
817
951
|
: undefined;
|
|
952
|
+
// One leg budget for the whole job: every upstream fetch the per-account
|
|
953
|
+
// run issues carries it on top of the helpers' own per-request timeouts.
|
|
954
|
+
const legSignal = AbortSignal.timeout(DAILY_GROWTH_LEG_TIMEOUT_MS);
|
|
955
|
+
const rotatorWithBudget =
|
|
956
|
+
rotator === undefined
|
|
957
|
+
? undefined
|
|
958
|
+
: async (accountId: string, tenantId?: string | null) => {
|
|
959
|
+
const base = await rotator(accountId, tenantId);
|
|
960
|
+
return withLegBudget(base, legSignal) as unknown as ValidatedFetch;
|
|
961
|
+
};
|
|
818
962
|
|
|
819
|
-
const
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
for (let offset = 0; offset < accounts.length; offset += DAILY_GROWTH_CONCURRENCY) {
|
|
827
|
-
const batch = accounts.slice(offset, offset + DAILY_GROWTH_CONCURRENCY);
|
|
828
|
-
const settled = await Promise.all(
|
|
829
|
-
batch.map(async (account) => {
|
|
830
|
-
const outcome = await runDailyGrowthForAccount(
|
|
831
|
-
providerId as ProviderId,
|
|
832
|
-
account,
|
|
833
|
-
refreshDeps,
|
|
834
|
-
rotator,
|
|
835
|
-
);
|
|
836
|
-
return { account, outcome };
|
|
837
|
-
}),
|
|
963
|
+
const runAccount = async (account: DailyGrowthJobAccount) => {
|
|
964
|
+
const outcome = await runDailyGrowthForAccount(
|
|
965
|
+
providerId as ProviderId,
|
|
966
|
+
account,
|
|
967
|
+
refreshDeps,
|
|
968
|
+
rotatorWithBudget,
|
|
838
969
|
);
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
accountId: account.id,
|
|
842
|
-
label: account.label || account.id,
|
|
843
|
-
report: outcome.report,
|
|
844
|
-
checkin: outcome.checkin,
|
|
845
|
-
});
|
|
970
|
+
if (!outcome.checkin.ok) {
|
|
971
|
+
return { ok: false, error: outcome.checkin.message };
|
|
846
972
|
}
|
|
847
|
-
|
|
973
|
+
return { ok: true };
|
|
974
|
+
};
|
|
848
975
|
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
return {
|
|
855
|
-
ok: true,
|
|
856
|
-
status: 200,
|
|
857
|
-
providerId,
|
|
858
|
-
data: results,
|
|
859
|
-
message: `${results.length} account${results.length === 1 ? "" : "s"} · report ${reportsOk}/${results.length} · check-in ${claimed}/${results.length}`,
|
|
976
|
+
const jobDeps: DailyGrowthJobDeps = {
|
|
977
|
+
db,
|
|
978
|
+
redis,
|
|
979
|
+
runAccount,
|
|
980
|
+
...(snapshotInvalidator ? { snapshotInvalidator } : {}),
|
|
860
981
|
};
|
|
982
|
+
const jobId = enqueueDailyGrowthJob({
|
|
983
|
+
deps: jobDeps,
|
|
984
|
+
tenantId: access.tenantId,
|
|
985
|
+
providerId,
|
|
986
|
+
accounts,
|
|
987
|
+
});
|
|
988
|
+
set.status = 202;
|
|
989
|
+
return { jobId, status: 202 };
|
|
861
990
|
},
|
|
862
991
|
)
|
|
992
|
+
.get("/quota/daily-growth/status/:jobId", async ({ request, params, set }) => {
|
|
993
|
+
const access = requireTenantScope(accessResolver(request), "dashboard:read");
|
|
994
|
+
const job = getDailyGrowthJob(params.jobId, access.tenantId);
|
|
995
|
+
if (job === null) {
|
|
996
|
+
set.status = 404;
|
|
997
|
+
return { error: `Job ${params.jobId} not found`, code: "not_found" };
|
|
998
|
+
}
|
|
999
|
+
return job;
|
|
1000
|
+
})
|
|
863
1001
|
.post("/accounts/:id/checkin", async ({ request, params, set }) => {
|
|
864
1002
|
const access = requireTenantScope(accessResolver(request), "dashboard:write");
|
|
865
1003
|
const rows = await db
|
|
@@ -929,6 +1067,75 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
929
1067
|
message: checkinStateMessage(result),
|
|
930
1068
|
};
|
|
931
1069
|
})
|
|
1070
|
+
// Gift grants are an explicit action, not a side effect of a quota read.
|
|
1071
|
+
.post("/accounts/:id/claim-gifts", async ({ request, params, set }) => {
|
|
1072
|
+
const access = requireTenantScope(accessResolver(request), "dashboard:write");
|
|
1073
|
+
const rows = await db
|
|
1074
|
+
.select()
|
|
1075
|
+
.from(providerAccounts)
|
|
1076
|
+
.where(
|
|
1077
|
+
and(eq(providerAccounts.id, params.id), eq(providerAccounts.tenantId, access.tenantId)),
|
|
1078
|
+
)
|
|
1079
|
+
.limit(1);
|
|
1080
|
+
const account = rows[0];
|
|
1081
|
+
if (!account) {
|
|
1082
|
+
set.status = 404;
|
|
1083
|
+
return { error: `Account ${params.id} not found`, code: "not_found" };
|
|
1084
|
+
}
|
|
1085
|
+
if (account.providerId !== ZCODE_START_PLAN_PROVIDER_ID) {
|
|
1086
|
+
set.status = 400;
|
|
1087
|
+
return {
|
|
1088
|
+
error: `Gift plans are only claimable for ${ZCODE_START_PLAN_PROVIDER_ID}`,
|
|
1089
|
+
code: "gifts_unsupported",
|
|
1090
|
+
};
|
|
1091
|
+
}
|
|
1092
|
+
let result: ZcodeGiftResult;
|
|
1093
|
+
try {
|
|
1094
|
+
const credential = await refreshDeps.resolveCredential(account.providerId as ProviderId, account.id);
|
|
1095
|
+
const fetcher = networkBindingFactory
|
|
1096
|
+
? await dailyCheckinEgressForPass({ db, networkBindingFactory })(account.id, access.tenantId)
|
|
1097
|
+
: globalThis.fetch;
|
|
1098
|
+
result = await claimZcodeGifts({ accountId: account.id, credential, fetcher });
|
|
1099
|
+
} catch {
|
|
1100
|
+
set.status = 502;
|
|
1101
|
+
return {
|
|
1102
|
+
ok: false, status: 502,
|
|
1103
|
+
data: { id: account.id, state: "error", claimed: [], detail: "Gift claim request failed" },
|
|
1104
|
+
message: "Gift claim request failed", code: "gift_claim_failed",
|
|
1105
|
+
};
|
|
1106
|
+
}
|
|
1107
|
+
if (result.claimed.length > 0) {
|
|
1108
|
+
// Cold readers must not resurrect the balance from before the grant.
|
|
1109
|
+
await db.update(providerAccounts).set({ quotaSnapshot: null }).where(
|
|
1110
|
+
and(eq(providerAccounts.id, account.id), eq(providerAccounts.tenantId, access.tenantId)),
|
|
1111
|
+
);
|
|
1112
|
+
await invalidateQuotaCacheForAccount(account.id, redis);
|
|
1113
|
+
await snapshotInvalidator?.invalidate();
|
|
1114
|
+
}
|
|
1115
|
+
if (result.state === "error") {
|
|
1116
|
+
set.status = 502;
|
|
1117
|
+
return {
|
|
1118
|
+
ok: false,
|
|
1119
|
+
status: 502,
|
|
1120
|
+
data: { id: account.id, ...result },
|
|
1121
|
+
message: result.detail ?? "Gift claim failed",
|
|
1122
|
+
code: "gift_claim_failed",
|
|
1123
|
+
};
|
|
1124
|
+
}
|
|
1125
|
+
return {
|
|
1126
|
+
ok: true,
|
|
1127
|
+
status: 200,
|
|
1128
|
+
data: { id: account.id, ...result },
|
|
1129
|
+
message:
|
|
1130
|
+
result.state === "nothing"
|
|
1131
|
+
? "No gift plan to claim"
|
|
1132
|
+
: result.state === "claimed"
|
|
1133
|
+
? `Claimed ${result.claimed.join(", ")}`
|
|
1134
|
+
: result.state === "already_claimed"
|
|
1135
|
+
? "Every gift plan was claimed before"
|
|
1136
|
+
: (result.detail ?? "Claim it in the ZCode app"),
|
|
1137
|
+
};
|
|
1138
|
+
})
|
|
932
1139
|
.post("/accounts/:id/activity-report", async ({ request, params, set }) => {
|
|
933
1140
|
const access = requireTenantScope(accessResolver(request), "dashboard:write");
|
|
934
1141
|
const rows = await db
|
|
@@ -977,6 +1184,12 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
977
1184
|
// The growth event scores by uid, and only a JWT carries one. An
|
|
978
1185
|
// opaque API key must fail closed here — reporting it under another
|
|
979
1186
|
// account's uid would poison someone else's streak.
|
|
1187
|
+
// dynamic-import: B-02 lazy graph — buddy uid decoder on this buddy-only surface.
|
|
1188
|
+
// The buddy-oauth-shared graph is lazy-loaded: the uid decoder is only
|
|
1189
|
+
// needed on this buddy-only surface (B-02).
|
|
1190
|
+
const { buddyAccountUid } = await import(
|
|
1191
|
+
"../../providers/integrations/buddy/buddy-oauth-shared"
|
|
1192
|
+
);
|
|
980
1193
|
const userId = buddyAccountUid(credential);
|
|
981
1194
|
if (!userId) {
|
|
982
1195
|
set.status = 400;
|
|
@@ -1043,7 +1256,12 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
1043
1256
|
account.providerId as ProviderId,
|
|
1044
1257
|
account.id,
|
|
1045
1258
|
);
|
|
1046
|
-
|
|
1259
|
+
// Cached per account for a short TTL: every dialog open was hitting the
|
|
1260
|
+
// upstream live. The cache is cleared on a successful redemption, so a
|
|
1261
|
+
// consumed credit is not shown again for the rest of the TTL.
|
|
1262
|
+
const list = await getCachedResetCredits(account.providerId, account.id, () =>
|
|
1263
|
+
listAccountResetCredits(account.providerId, credential),
|
|
1264
|
+
);
|
|
1047
1265
|
return list ?? { availableCount: 0, credits: [] };
|
|
1048
1266
|
} catch (err) {
|
|
1049
1267
|
return { availableCount: 0, credits: [] };
|
|
@@ -138,7 +138,7 @@ export async function selectAccountTestEgress(
|
|
|
138
138
|
throw new GatewayError(
|
|
139
139
|
"proxy_pool_unavailable",
|
|
140
140
|
503,
|
|
141
|
-
"No active proxy pool is available because coordination is unavailable.",
|
|
141
|
+
"No active proxy pool is available because coordination is unavailable (request {requestId}). The bouncer stepped out — come back shortly 🚪",
|
|
142
142
|
{ reason: "coordination_unavailable" },
|
|
143
143
|
"network",
|
|
144
144
|
);
|
|
@@ -159,10 +159,10 @@ export async function selectAccountTestEgress(
|
|
|
159
159
|
const status = failure.reason === "at_capacity" ? 429 : 503;
|
|
160
160
|
const message =
|
|
161
161
|
failure.reason === "at_capacity"
|
|
162
|
-
? "Every proxy pool for this provider is at its concurrency limit. Retry shortly, or add a pool or raise its capacity."
|
|
162
|
+
? "Every proxy pool for this provider is at its concurrency limit (request {requestId}). Retry shortly, or add a pool or raise its capacity. The pools are full right now — chill 🌊"
|
|
163
163
|
: failure.reason === "cooldown"
|
|
164
|
-
? "Every proxy pool for this provider is cooling down after upstream failures. Retry once the cooldown resets."
|
|
165
|
-
: "No active proxy pool is configured for this tenant and provider. Add one, or route this provider through direct egress.";
|
|
164
|
+
? "Every proxy pool for this provider is cooling down after upstream failures (request {requestId}). Retry once the cooldown resets. The proxies are catching their breath — zzz 💤"
|
|
165
|
+
: "No active proxy pool is configured for this tenant and provider (request {requestId}). Add one, or route this provider through direct egress. No bridge to cross — configure a pool first 🏗️";
|
|
166
166
|
throw new GatewayError(
|
|
167
167
|
code,
|
|
168
168
|
status,
|