cartethyia 2.7.4 → 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-ChG5svFb.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-BIcWQun7.js → CliToolDetailPage-DZKmVuJN.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-DZKmVuJN.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-Bf2VelDe.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-ggeMSjte.js → CustomizationPage-BKj_r0rp.js} +1 -1
- 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-U6AKaJcF.js → LoginPage-DkXb6dx-.js} +1 -1
- package/dist/dashboard/assets/LoginPage-DkXb6dx-.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BMS2t8BA.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-lsrx7NYg.js → ProxyPage-5SnUSy3j.js} +1 -1
- 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-f0DE1h0-.js → SetupPage-WTa0sktC.js} +1 -1
- package/dist/dashboard/assets/SetupPage-WTa0sktC.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-Cq5tW7hW.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-C0K-c4eo.js +1 -0
- package/dist/dashboard/assets/assert-C0K-c4eo.js.gz +0 -0
- package/dist/dashboard/assets/{badge-D9CS6dZk.js → badge-DfbhQU4k.js} +1 -1
- package/dist/dashboard/assets/badge-DfbhQU4k.js.gz +0 -0
- package/dist/dashboard/assets/{banner-DympBNq4.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-ibRWU_uT.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-CQXVMn4P.js +1 -0
- package/dist/dashboard/assets/cli-tools-CQXVMn4P.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-DJm-9pz7.js → clipboard-button-BQqBQd2n.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-BQqBQd2n.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-8fiE6tec.js → dialog-BEK7KP0H.js} +1 -1
- package/dist/dashboard/assets/dialog-BEK7KP0H.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-CqGYeOrd.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-BSAsYsmV.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-D-MTJxMr.js → formatters-BAACA727.js} +1 -1
- package/dist/dashboard/assets/formatters-BAACA727.js.gz +0 -0
- package/dist/dashboard/assets/{github-badge-CPK47xQx.js → github-badge-YSCE4UC2.js} +1 -1
- package/dist/dashboard/assets/github-badge-YSCE4UC2.js.gz +0 -0
- package/dist/dashboard/assets/{index-DBNPOfhV.js → index-FQlj0HUT.js} +2 -2
- package/dist/dashboard/assets/index-FQlj0HUT.js.gz +0 -0
- package/dist/dashboard/assets/{inline-BT0zntEr.js → inline-C4gU5iOL.js} +1 -1
- package/dist/dashboard/assets/inline-C4gU5iOL.js.gz +0 -0
- package/dist/dashboard/assets/{input-Da2ZViWg.js → input-BHHX_Tmm.js} +1 -1
- package/dist/dashboard/assets/input-BHHX_Tmm.js.gz +0 -0
- package/dist/dashboard/assets/{layout-BXNeLw6M.js → layout-CajrYUnD.js} +1 -1
- package/dist/dashboard/assets/layout-CajrYUnD.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-BycOrrIV.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/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/quota-DvQbD_sr.js +1 -0
- package/dist/dashboard/assets/quota-DvQbD_sr.js.gz +0 -0
- package/dist/dashboard/assets/routing-in0f_IfK.js +1 -0
- package/dist/dashboard/assets/routing-in0f_IfK.js.gz +0 -0
- package/dist/dashboard/assets/{select-BIYIBkMU.js → select-BLULNqTp.js} +1 -1
- 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-DfgnFDWY.js → stack-D2lIR0tg.js} +1 -1
- package/dist/dashboard/assets/stack-D2lIR0tg.js.gz +0 -0
- package/dist/dashboard/assets/{state-CkfdYWel.js → state-DTARjfiW.js} +1 -1
- package/dist/dashboard/assets/state-DTARjfiW.js.gz +0 -0
- package/dist/dashboard/assets/{switch-SYm237HG.js → switch-c0oPSnqW.js} +1 -1
- package/dist/dashboard/assets/switch-c0oPSnqW.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-BQqCRNIi.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 +56 -55
- 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/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 -6
- package/scripts/cli/update.ts +15 -41
- package/src/boot/app.ts +58 -2
- 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 +1 -1
- 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 +71 -62
- package/src/console/api-keys/routes.ts +48 -12
- package/src/console/auth/access.ts +4 -4
- package/src/console/auth/account-reset.ts +1 -1
- 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 +37 -31
- 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 +9 -9
- package/src/console/backup/export-endpoint.ts +5 -6
- package/src/console/backup/nine-router.ts +1 -7
- package/src/console/backup/routes.ts +29 -33
- 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 +1 -1
- package/src/console/cli-tools/service.ts +1 -1
- package/src/console/cli-tools/store.ts +2 -2
- package/src/console/console-router.ts +32 -0
- package/src/console/dashboard-assets.ts +9 -9
- package/src/console/domain-registration.ts +16 -2
- 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 +1 -1
- package/src/console/observability/live.ts +31 -18
- package/src/console/observability/logs.ts +1 -1
- package/src/console/observability/sse.ts +62 -8
- package/src/console/observability/store.ts +20 -4
- package/src/console/providers/catalog/catalog-projections.ts +1 -1
- package/src/console/providers/catalog/contracts.ts +39 -0
- package/src/console/providers/catalog/model-operations.ts +1 -1
- package/src/console/providers/catalog/provider-operations.ts +95 -17
- package/src/console/providers/catalog/public-model-store.ts +0 -0
- package/src/console/providers/catalog/routes.ts +27 -3
- package/src/console/providers/catalog/store.ts +147 -8
- package/src/console/providers/detail/routes.ts +1 -1
- package/src/console/providers/oauth/callback-listener.ts +100 -18
- package/src/console/providers/oauth/routes.ts +92 -13
- 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 +259 -66
- 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/pools/contracts.ts +2 -2
- package/src/console/routing/pools/import-parse.ts +3 -3
- package/src/console/routing/pools/relay-deploy.ts +3 -3
- package/src/console/settings/contracts.ts +29 -2
- package/src/console/settings/store.ts +20 -0
- package/src/console/share/share-router.ts +100 -32
- package/src/console/share/share-stats.ts +4 -4
- 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 +4 -4
- 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 +252 -97
- 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 +1 -1
- package/src/network/pool/agent.ts +7 -6
- package/src/network/pool/byte-accounting.ts +1 -1
- package/src/network/pool/resolver.ts +16 -12
- package/src/network/pool/selector.ts +150 -136
- package/src/network/pool-health-machine.ts +1 -1
- package/src/network/rate-limit-verdict.ts +1 -1
- package/src/network/retry.ts +1 -1
- package/src/network/ssrf.ts +20 -71
- package/src/observability/event-log.ts +2 -2
- package/src/observability/event-query.ts +59 -291
- 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/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 +3 -3
- package/src/persistence/dialect.ts +5 -1
- package/src/persistence/readiness.ts +1 -1
- package/src/persistence/redis.ts +1 -1
- package/src/persistence/schema.ts +113 -40
- package/src/persistence/shared-cache.ts +2 -2
- package/src/persistence/sort-order.ts +1 -1
- package/src/persistence/stores/api-key-store.ts +10 -1
- package/src/persistence/stores/share-store.ts +20 -8
- 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 +6 -10
- package/src/protocol/dsml.ts +3 -49
- package/src/protocol/image-clamp.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 +25 -10
- package/src/protocol/response/codex.ts +1 -1
- package/src/protocol/response/messages.ts +1 -1
- package/src/protocol/response/omp-tool-call-markup.ts +1 -1
- package/src/protocol/response/responses.ts +1 -1
- package/src/protocol/sse-decoder.ts +50 -1
- 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 +6 -6
- 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/providers/adapters/compatible-adapter.ts +42 -3
- 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/bundled-discovery-providers.ts +6 -30
- package/src/providers/configured-openai-providers.ts +82 -97
- 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 +48 -13
- package/src/providers/discovery/probing-service.ts +6 -8
- package/src/providers/integrations/agentrouter/agentrouter.ts +12 -2
- 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 +2 -2
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +1 -1
- 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-identity.ts +86 -0
- 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 +4 -15
- package/src/providers/integrations/buddy/codebuddy/shared.ts +30 -9
- package/src/providers/integrations/buddy/workbuddy/provider.ts +5 -9
- package/src/providers/integrations/buddy/workbuddy/shared.ts +21 -3
- package/src/providers/integrations/claude/claude-cch.ts +148 -148
- package/src/providers/integrations/claude/fallback-credit.ts +3 -7
- package/src/providers/integrations/cline/cline.ts +1 -1
- package/src/providers/integrations/codex/codex-device-code.ts +101 -101
- package/src/providers/integrations/codex/codex-oauth.ts +0 -1
- package/src/providers/integrations/commandcode/commandcode.ts +75 -115
- package/src/providers/integrations/commandcode/quota.ts +131 -51
- package/src/providers/integrations/cursor/cursor-http2.ts +0 -3
- 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 +38 -5
- 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 +9 -9
- 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 +41 -14
- 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 +86 -36
- package/src/providers/integrations/kilo/kilo-oauth.ts +1 -1
- 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 +81 -68
- package/src/providers/integrations/muse/muse-oauth.ts +0 -1
- package/src/providers/integrations/muse/muse-quota.ts +0 -4
- package/src/providers/integrations/opencode/fingerprint.ts +7 -5
- package/src/providers/integrations/opencode/provider.ts +17 -24
- package/src/providers/integrations/qoder/qoder-catalog.ts +85 -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 +10 -31
- package/src/providers/integrations/qoder/qoder-sse.ts +159 -0
- package/src/providers/integrations/qoder/qoder-umid.ts +21 -25
- package/src/providers/integrations/qoder/qoder-virtual.ts +12 -0
- package/src/providers/integrations/qoder/qoder.ts +354 -62
- 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/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 +53 -10
- package/src/providers/integrations/xai/xai-oauth.ts +5 -5
- 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 +18 -2
- package/src/providers/operations/provider-credential-service.ts +19 -2
- package/src/providers/provider-contracts.ts +18 -7
- 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-usage.ts +81 -16
- package/src/providers/quota/cache.ts +29 -0
- package/src/providers/quota/quota-contracts.ts +4 -0
- package/src/providers/quota/refresh.ts +27 -4
- package/src/providers/quota/snapshot.ts +94 -0
- package/src/providers/search/search-provider.ts +1 -3
- package/src/providers/search/search-providers.ts +2 -1
- package/src/security/abuse.ts +4 -4
- package/src/security/admission/service.ts +2 -2
- package/src/security/admission/ttl.ts +61 -61
- package/src/security/api-key-auth.ts +16 -4
- 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/invoke-guard.ts +47 -0
- package/src/transport/contracts.ts +13 -4
- package/src/transport/dispatch/attempt-finalize.ts +1 -1
- package/src/transport/dispatch/capture-policy.ts +34 -37
- package/src/transport/dispatch/empty-stream.ts +23 -20
- package/src/transport/dispatch/generation.ts +25 -45
- package/src/transport/dispatch/native-shared.ts +127 -0
- package/src/transport/dispatch/proxy-request.ts +3 -1
- package/src/transport/dispatch/responses-compact.ts +25 -46
- package/src/transport/dispatch/streaming/encoder.ts +18 -72
- package/src/transport/dispatch/streaming/finalize.ts +2 -2
- 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 +20 -48
- package/src/transport/dispatch/token-count.ts +41 -38
- package/src/transport/dispatch/websearch.ts +19 -45
- package/src/transport/drain-endpoint.ts +1 -1
- package/src/transport/failure-policy.ts +6 -0
- package/src/transport/guards/auth-guard.ts +0 -6
- package/src/transport/guards/body-policy.ts +3 -3
- package/src/transport/guards/headroom-guard.ts +1 -1
- package/src/transport/guards/pipeline.ts +1 -1
- package/src/transport/guards/request-context.ts +12 -17
- package/src/transport/request/preparer.ts +286 -7
- 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 +1 -13
- 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 +17 -18
- package/src/transport/routing/route-model.ts +126 -33
- package/src/transport/routing/router.ts +152 -37
- package/src/transport/shutdown-notice.ts +2 -2
- 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 +2 -2
- package/src/transport/surface/content-parts.ts +1 -1
- package/src/transport/surface/dialects.ts +2 -2
- 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-ChG5svFb.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-DCgm5g6g.js +0 -1
- package/dist/dashboard/assets/CombosPage-DCgm5g6g.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-U6AKaJcF.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-BMS2t8BA.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js +0 -1
- package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js +0 -5
- package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.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-BSDbquc1.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-lsrx7NYg.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-L0skzML8.js +0 -1
- package/dist/dashboard/assets/QuotaPage-L0skzML8.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js +0 -1
- package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-f0DE1h0-.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-ClzpwyET.js +0 -1
- package/dist/dashboard/assets/SortableList-ClzpwyET.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-Cq5tW7hW.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js +0 -56
- package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-C38iXoO4.js +0 -1
- package/dist/dashboard/assets/api-keys-C38iXoO4.js.gz +0 -0
- package/dist/dashboard/assets/app-a159k0ub.css +0 -2
- package/dist/dashboard/assets/app-a159k0ub.css.gz +0 -0
- package/dist/dashboard/assets/assert-DbRA8EG2.js +0 -15
- package/dist/dashboard/assets/assert-DbRA8EG2.js.gz +0 -0
- package/dist/dashboard/assets/badge-D9CS6dZk.js.gz +0 -0
- package/dist/dashboard/assets/banner-DympBNq4.js.gz +0 -0
- package/dist/dashboard/assets/card-ibRWU_uT.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-63qBGaRw.js +0 -1
- package/dist/dashboard/assets/cli-tools-63qBGaRw.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-DJm-9pz7.js.gz +0 -0
- package/dist/dashboard/assets/dialog-8fiE6tec.js.gz +0 -0
- package/dist/dashboard/assets/drawer-CqGYeOrd.js.gz +0 -0
- package/dist/dashboard/assets/entry-BSAsYsmV.js.gz +0 -0
- package/dist/dashboard/assets/entry-CiIQULZD.js +0 -4
- package/dist/dashboard/assets/entry-CiIQULZD.js.gz +0 -0
- package/dist/dashboard/assets/entry-Daz0lJ-W.js +0 -1
- package/dist/dashboard/assets/entry-Daz0lJ-W.js.gz +0 -0
- package/dist/dashboard/assets/formatters-D-MTJxMr.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-CPK47xQx.js.gz +0 -0
- package/dist/dashboard/assets/index-DBNPOfhV.js.gz +0 -0
- package/dist/dashboard/assets/inline-BT0zntEr.js.gz +0 -0
- package/dist/dashboard/assets/input-Da2ZViWg.js.gz +0 -0
- package/dist/dashboard/assets/layout-BXNeLw6M.js.gz +0 -0
- package/dist/dashboard/assets/list-row-BycOrrIV.js.gz +0 -0
- package/dist/dashboard/assets/live-DCQNZpF7.js +0 -1
- package/dist/dashboard/assets/live-DCQNZpF7.js.gz +0 -0
- package/dist/dashboard/assets/network-9Yj2ZyLo.js +0 -1
- package/dist/dashboard/assets/network-9Yj2ZyLo.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CEagj6ZZ.js +0 -2
- package/dist/dashboard/assets/numbers-CEagj6ZZ.js.gz +0 -0
- package/dist/dashboard/assets/quota-Caw7wqci.js +0 -1
- package/dist/dashboard/assets/quota-Caw7wqci.js.gz +0 -0
- package/dist/dashboard/assets/routing-CO9zCUus.js +0 -1
- package/dist/dashboard/assets/routing-CO9zCUus.js.gz +0 -0
- package/dist/dashboard/assets/select-BIYIBkMU.js.gz +0 -0
- package/dist/dashboard/assets/settings-jS3-PNSA.js +0 -1
- package/dist/dashboard/assets/settings-jS3-PNSA.js.gz +0 -0
- package/dist/dashboard/assets/stack-DfgnFDWY.js.gz +0 -0
- package/dist/dashboard/assets/state-CkfdYWel.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-SYm237HG.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-BQqCRNIi.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-BayTTy01.js → app-Bgd3zANQ.js} +0 -0
- /package/dist/dashboard/assets/{app-BayTTy01.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
|
@@ -1,153 +1,153 @@
|
|
|
1
|
-
import type {} from "../contracts";
|
|
2
|
-
import { ensureV1Suffix, homeDir, join, readJsonFile, writeJsonFile } from "../fs-ops";
|
|
3
|
-
import type { InjectorSpec } from "../contracts";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
// OpenCode injector spec.
|
|
7
|
-
interface OpencodeModel {
|
|
8
|
-
name: string;
|
|
9
|
-
modalities: { input: string[]; output: string[] };
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
interface OpencodeProvider {
|
|
13
|
-
npm: string;
|
|
14
|
-
options: { baseURL?: string; apiKey?: string };
|
|
15
|
-
models: Record<string, OpencodeModel>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface OpencodeConfig {
|
|
19
|
-
provider?: Record<string, OpencodeProvider>;
|
|
20
|
-
model?: string;
|
|
21
|
-
agent?: {
|
|
22
|
-
explorer?: {
|
|
23
|
-
description?: string;
|
|
24
|
-
mode?: string;
|
|
25
|
-
model?: string;
|
|
26
|
-
};
|
|
27
|
-
[k: string]: unknown;
|
|
28
|
-
};
|
|
29
|
-
[k: string]: unknown;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function buildOpencodeModels(models: readonly string[]): Record<string, OpencodeModel> {
|
|
33
|
-
const map: Record<string, OpencodeModel> = {};
|
|
34
|
-
for (const m of models) {
|
|
35
|
-
if (!m) continue;
|
|
36
|
-
map[m] = { name: m, modalities: { input: ["text", "image"], output: ["text"] } };
|
|
37
|
-
}
|
|
38
|
-
return map;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export const opencodeSpec: InjectorSpec = {
|
|
42
|
-
toolId: "opencode",
|
|
43
|
-
displayName: "OpenCode",
|
|
44
|
-
binary: "opencode",
|
|
45
|
-
resolvePath: () => join(homeDir(), ".config", "opencode", "opencode.json"),
|
|
46
|
-
resolveDir: () => join(homeDir(), ".config", "opencode"),
|
|
47
|
-
|
|
48
|
-
async readStatus(path) {
|
|
49
|
-
const config = (await readJsonFile(path)) as OpencodeConfig | null;
|
|
50
|
-
if (!config) {
|
|
51
|
-
return { configured: false, currentEndpoint: null, rawApiKey: null, currentModels: null };
|
|
52
|
-
}
|
|
53
|
-
const provider = config.provider?.cartethyia;
|
|
54
|
-
const endpoint = provider?.options?.baseURL ?? null;
|
|
55
|
-
const models = provider?.models ? Object.keys(provider.models) : null;
|
|
56
|
-
const active =
|
|
57
|
-
typeof config.model === "string" && config.model.startsWith("cartethyia/")
|
|
58
|
-
? config.model.split("/").slice(1).join("/")
|
|
59
|
-
: null;
|
|
60
|
-
return {
|
|
61
|
-
configured: !!provider,
|
|
62
|
-
currentEndpoint: endpoint,
|
|
63
|
-
rawApiKey: provider?.options?.apiKey ?? null,
|
|
64
|
-
currentModels: active && models ? [active, ...models.filter((m) => m !== active)] : models,
|
|
65
|
-
};
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
async apply(input, path) {
|
|
69
|
-
const existing = (await readJsonFile(path)) as OpencodeConfig | null;
|
|
70
|
-
const config: OpencodeConfig = (existing ?? {}) as OpencodeConfig;
|
|
71
|
-
|
|
72
|
-
if (!config.provider) config.provider = {};
|
|
73
|
-
const prior = config.provider.cartethyia;
|
|
74
|
-
config.provider.cartethyia = {
|
|
75
|
-
npm: "@ai-sdk/openai-compatible",
|
|
76
|
-
options: {
|
|
77
|
-
...(prior?.options ?? {}),
|
|
78
|
-
baseURL: ensureV1Suffix(input.endpoint),
|
|
79
|
-
apiKey: input.apiKey,
|
|
80
|
-
},
|
|
81
|
-
models: { ...(prior?.models ?? {}), ...buildOpencodeModels(input.modelIds) },
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const activeModel = input.activeModel ?? input.modelIds[0] ?? "";
|
|
85
|
-
config.model = activeModel === "" ? "" : `cartethyia/${activeModel}`;
|
|
86
|
-
|
|
87
|
-
if (!config.agent) config.agent = {};
|
|
88
|
-
const subagentModel = input.subagentModel ?? input.modelIds[0] ?? activeModel;
|
|
89
|
-
config.agent.explorer = {
|
|
90
|
-
description: "Fast explorer subagent",
|
|
91
|
-
mode: "subagent",
|
|
92
|
-
model: `cartethyia/${subagentModel}`,
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
await writeJsonFile(path, config);
|
|
96
|
-
},
|
|
97
|
-
|
|
98
|
-
async reset(path) {
|
|
99
|
-
const config = (await readJsonFile(path)) as OpencodeConfig | null;
|
|
100
|
-
if (!config) return false;
|
|
101
|
-
|
|
102
|
-
if (config.provider) {
|
|
103
|
-
delete config.provider.cartethyia;
|
|
104
|
-
if (Object.keys(config.provider).length === 0) delete config.provider;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (typeof config.model === "string" && config.model.startsWith("cartethyia/")) {
|
|
108
|
-
delete config.model;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (config.agent?.explorer?.model?.startsWith("cartethyia/")) {
|
|
112
|
-
delete config.agent.explorer;
|
|
113
|
-
if (Object.keys(config.agent).length === 0) delete config.agent;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
await writeJsonFile(path, config);
|
|
117
|
-
},
|
|
118
|
-
|
|
119
|
-
download(input) {
|
|
120
|
-
const activeModel = input.activeModel ?? input.modelIds[0] ?? "";
|
|
121
|
-
const subagentModel = input.subagentModel ?? input.modelIds[0] ?? activeModel;
|
|
122
|
-
const config: OpencodeConfig = {
|
|
123
|
-
provider: {
|
|
124
|
-
cartethyia: {
|
|
125
|
-
npm: "@ai-sdk/openai-compatible",
|
|
126
|
-
options: {
|
|
127
|
-
baseURL: ensureV1Suffix(input.endpoint),
|
|
128
|
-
apiKey: input.apiKey,
|
|
129
|
-
},
|
|
130
|
-
models: buildOpencodeModels(input.modelIds),
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
model: activeModel === "" ? "" : `cartethyia/${activeModel}`,
|
|
134
|
-
agent: {
|
|
135
|
-
explorer: {
|
|
136
|
-
description: "Fast explorer subagent",
|
|
137
|
-
mode: "subagent",
|
|
138
|
-
model: `cartethyia/${subagentModel}`,
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
|
-
};
|
|
142
|
-
return {
|
|
143
|
-
content: JSON.stringify(config, null, 2),
|
|
144
|
-
filename: "opencode.json",
|
|
145
|
-
mimeType: "application/json",
|
|
146
|
-
};
|
|
147
|
-
},
|
|
148
|
-
|
|
149
|
-
messages: {
|
|
150
|
-
applied: "OpenCode settings applied",
|
|
151
|
-
reset: "Cartethyia settings removed from OpenCode",
|
|
152
|
-
},
|
|
153
|
-
};
|
|
1
|
+
import type {} from "../contracts";
|
|
2
|
+
import { ensureV1Suffix, homeDir, join, readJsonFile, writeJsonFile } from "../fs-ops";
|
|
3
|
+
import type { InjectorSpec } from "../contracts";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
// OpenCode injector spec.
|
|
7
|
+
interface OpencodeModel {
|
|
8
|
+
name: string;
|
|
9
|
+
modalities: { input: string[]; output: string[] };
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface OpencodeProvider {
|
|
13
|
+
npm: string;
|
|
14
|
+
options: { baseURL?: string; apiKey?: string };
|
|
15
|
+
models: Record<string, OpencodeModel>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface OpencodeConfig {
|
|
19
|
+
provider?: Record<string, OpencodeProvider>;
|
|
20
|
+
model?: string;
|
|
21
|
+
agent?: {
|
|
22
|
+
explorer?: {
|
|
23
|
+
description?: string;
|
|
24
|
+
mode?: string;
|
|
25
|
+
model?: string;
|
|
26
|
+
};
|
|
27
|
+
[k: string]: unknown;
|
|
28
|
+
};
|
|
29
|
+
[k: string]: unknown;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function buildOpencodeModels(models: readonly string[]): Record<string, OpencodeModel> {
|
|
33
|
+
const map: Record<string, OpencodeModel> = {};
|
|
34
|
+
for (const m of models) {
|
|
35
|
+
if (!m) continue;
|
|
36
|
+
map[m] = { name: m, modalities: { input: ["text", "image"], output: ["text"] } };
|
|
37
|
+
}
|
|
38
|
+
return map;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const opencodeSpec: InjectorSpec = {
|
|
42
|
+
toolId: "opencode",
|
|
43
|
+
displayName: "OpenCode",
|
|
44
|
+
binary: "opencode",
|
|
45
|
+
resolvePath: () => join(homeDir(), ".config", "opencode", "opencode.json"),
|
|
46
|
+
resolveDir: () => join(homeDir(), ".config", "opencode"),
|
|
47
|
+
|
|
48
|
+
async readStatus(path) {
|
|
49
|
+
const config = (await readJsonFile(path)) as OpencodeConfig | null;
|
|
50
|
+
if (!config) {
|
|
51
|
+
return { configured: false, currentEndpoint: null, rawApiKey: null, currentModels: null };
|
|
52
|
+
}
|
|
53
|
+
const provider = config.provider?.cartethyia;
|
|
54
|
+
const endpoint = provider?.options?.baseURL ?? null;
|
|
55
|
+
const models = provider?.models ? Object.keys(provider.models) : null;
|
|
56
|
+
const active =
|
|
57
|
+
typeof config.model === "string" && config.model.startsWith("cartethyia/")
|
|
58
|
+
? config.model.split("/").slice(1).join("/")
|
|
59
|
+
: null;
|
|
60
|
+
return {
|
|
61
|
+
configured: !!provider,
|
|
62
|
+
currentEndpoint: endpoint,
|
|
63
|
+
rawApiKey: provider?.options?.apiKey ?? null,
|
|
64
|
+
currentModels: active && models ? [active, ...models.filter((m) => m !== active)] : models,
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
async apply(input, path) {
|
|
69
|
+
const existing = (await readJsonFile(path)) as OpencodeConfig | null;
|
|
70
|
+
const config: OpencodeConfig = (existing ?? {}) as OpencodeConfig;
|
|
71
|
+
|
|
72
|
+
if (!config.provider) config.provider = {};
|
|
73
|
+
const prior = config.provider.cartethyia;
|
|
74
|
+
config.provider.cartethyia = {
|
|
75
|
+
npm: "@ai-sdk/openai-compatible",
|
|
76
|
+
options: {
|
|
77
|
+
...(prior?.options ?? {}),
|
|
78
|
+
baseURL: ensureV1Suffix(input.endpoint),
|
|
79
|
+
apiKey: input.apiKey,
|
|
80
|
+
},
|
|
81
|
+
models: { ...(prior?.models ?? {}), ...buildOpencodeModels(input.modelIds) },
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const activeModel = input.activeModel ?? input.modelIds[0] ?? "";
|
|
85
|
+
config.model = activeModel === "" ? "" : `cartethyia/${activeModel}`;
|
|
86
|
+
|
|
87
|
+
if (!config.agent) config.agent = {};
|
|
88
|
+
const subagentModel = input.subagentModel ?? input.modelIds[0] ?? activeModel;
|
|
89
|
+
config.agent.explorer = {
|
|
90
|
+
description: "Fast explorer subagent",
|
|
91
|
+
mode: "subagent",
|
|
92
|
+
model: `cartethyia/${subagentModel}`,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
await writeJsonFile(path, config);
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
async reset(path) {
|
|
99
|
+
const config = (await readJsonFile(path)) as OpencodeConfig | null;
|
|
100
|
+
if (!config) return false;
|
|
101
|
+
|
|
102
|
+
if (config.provider) {
|
|
103
|
+
delete config.provider.cartethyia;
|
|
104
|
+
if (Object.keys(config.provider).length === 0) delete config.provider;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (typeof config.model === "string" && config.model.startsWith("cartethyia/")) {
|
|
108
|
+
delete config.model;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (config.agent?.explorer?.model?.startsWith("cartethyia/")) {
|
|
112
|
+
delete config.agent.explorer;
|
|
113
|
+
if (Object.keys(config.agent).length === 0) delete config.agent;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
await writeJsonFile(path, config);
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
download(input) {
|
|
120
|
+
const activeModel = input.activeModel ?? input.modelIds[0] ?? "";
|
|
121
|
+
const subagentModel = input.subagentModel ?? input.modelIds[0] ?? activeModel;
|
|
122
|
+
const config: OpencodeConfig = {
|
|
123
|
+
provider: {
|
|
124
|
+
cartethyia: {
|
|
125
|
+
npm: "@ai-sdk/openai-compatible",
|
|
126
|
+
options: {
|
|
127
|
+
baseURL: ensureV1Suffix(input.endpoint),
|
|
128
|
+
apiKey: input.apiKey,
|
|
129
|
+
},
|
|
130
|
+
models: buildOpencodeModels(input.modelIds),
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
model: activeModel === "" ? "" : `cartethyia/${activeModel}`,
|
|
134
|
+
agent: {
|
|
135
|
+
explorer: {
|
|
136
|
+
description: "Fast explorer subagent",
|
|
137
|
+
mode: "subagent",
|
|
138
|
+
model: `cartethyia/${subagentModel}`,
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
return {
|
|
143
|
+
content: JSON.stringify(config, null, 2),
|
|
144
|
+
filename: "opencode.json",
|
|
145
|
+
mimeType: "application/json",
|
|
146
|
+
};
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
messages: {
|
|
150
|
+
applied: "OpenCode settings applied",
|
|
151
|
+
reset: "Cartethyia settings removed from OpenCode",
|
|
152
|
+
},
|
|
153
|
+
};
|
|
@@ -23,7 +23,7 @@ import type { ApplyInput, CliMappingInput, CliModelMapping } from "./contracts";
|
|
|
23
23
|
* `download` and `apply` require `keyId`; the server resolves the recoverable
|
|
24
24
|
* AES-256-GCM copy so the operator never pastes a raw secret.
|
|
25
25
|
*/
|
|
26
|
-
|
|
26
|
+
interface CliToolsRoutesConfig {
|
|
27
27
|
readonly service: CliToolService;
|
|
28
28
|
readonly accessResolver: ConsoleAccessResolver;
|
|
29
29
|
readonly auditSink?: AuditSink;
|
|
@@ -27,7 +27,7 @@ import { ConsoleDomainError } from "../shared/errors";
|
|
|
27
27
|
* and share one process's home directory (they are not tenant-scoped).
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
function toToolRegistryEntry(def: ToolDef): ToolRegistryEntry {
|
|
31
31
|
return {
|
|
32
32
|
id: def.id,
|
|
33
33
|
name: def.name,
|
|
@@ -14,13 +14,13 @@ import type {
|
|
|
14
14
|
* The API-layer service owns validation against the registry; this store
|
|
15
15
|
* only serializes rows in and out of Postgres.
|
|
16
16
|
*/
|
|
17
|
-
|
|
17
|
+
interface StoredMappingRow extends CliModelMapping {
|
|
18
18
|
readonly toolId: string;
|
|
19
19
|
readonly tenantId: string;
|
|
20
20
|
readonly apiKeyId: string;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
interface StoredSettings {
|
|
24
24
|
readonly tenantId: string;
|
|
25
25
|
readonly toolId: string;
|
|
26
26
|
readonly apiKeyId: string;
|
|
@@ -36,6 +36,7 @@ import type { BundledProviderCatalog } from "../providers/operations/provider-ca
|
|
|
36
36
|
import type { ValidatedNetworkBindingFactory } from "../network/pool/resolver";
|
|
37
37
|
import type { TrustedProxyBoundary } from "../config/network";
|
|
38
38
|
import { gzipResponse } from "./response-compression";
|
|
39
|
+
import { beginConsoleActivity } from "../shared/invoke-guard";
|
|
39
40
|
|
|
40
41
|
export interface ConsoleApiCompositionDeps {
|
|
41
42
|
readonly db: CartethyiaDatabase;
|
|
@@ -80,6 +81,15 @@ export interface ConsoleApiCompositionDeps {
|
|
|
80
81
|
| undefined;
|
|
81
82
|
readonly resolvePeerAddress?: (request: Request) => string | null;
|
|
82
83
|
readonly trustedProxyBoundary?: TrustedProxyBoundary;
|
|
84
|
+
/**
|
|
85
|
+
* The process shutdown coordinator, narrowed to the surface the update apply
|
|
86
|
+
* route needs. Declared structural (not the class) so the console composition
|
|
87
|
+
* root does not import the boot layer; `ShutdownCoordinator` satisfies it.
|
|
88
|
+
*/
|
|
89
|
+
readonly shutdownCoordinator?: {
|
|
90
|
+
readonly begin: (reason: "update") => Promise<void>;
|
|
91
|
+
readonly totalShutdownBudgetMs: () => number;
|
|
92
|
+
};
|
|
83
93
|
}
|
|
84
94
|
/**
|
|
85
95
|
* Extracts a bearer API key from a console request, or `undefined`.
|
|
@@ -109,6 +119,12 @@ export function createConsoleRouter(deps: ConsoleApiCompositionDeps): AnyElysia
|
|
|
109
119
|
* process (tests, or a second app instance) never share decisions.
|
|
110
120
|
*/
|
|
111
121
|
const sessionAccessCache = new WeakMap<Request, AccessDecision | null>();
|
|
122
|
+
/**
|
|
123
|
+
* G-03 InvokeGuard: the console control plane's foreground-activity count.
|
|
124
|
+
* `beforeHandle` bumps it for the request; `afterResponse` releases it. The
|
|
125
|
+
* end callback is keyed by request so parallel requests pair correctly.
|
|
126
|
+
*/
|
|
127
|
+
const consoleActivityEnds = new WeakMap<Request, () => void>();
|
|
112
128
|
const cookiePolicy = defaultSessionCookiePolicy;
|
|
113
129
|
const credentialService = new ConsoleCredentialService();
|
|
114
130
|
const sessionService = new ConsoleSessionService(db, cookiePolicy);
|
|
@@ -137,6 +153,12 @@ export function createConsoleRouter(deps: ConsoleApiCompositionDeps): AnyElysia
|
|
|
137
153
|
.use(createConsoleCsrfMiddleware())
|
|
138
154
|
.use(createConsoleMutationLimiterMiddleware())
|
|
139
155
|
.beforeHandle(async ({ request }: { request: Request }) => {
|
|
156
|
+
// G-03: count this console request as foreground activity for the
|
|
157
|
+
// duration of its handling. Released in `afterResponse` below (or by
|
|
158
|
+
// the catch-all in the error path, which also runs before the response
|
|
159
|
+
// leaves). The scheduled worker registry uses this to defer sweeps
|
|
160
|
+
// while the operator is actively using the console.
|
|
161
|
+
consoleActivityEnds.set(request, beginConsoleActivity());
|
|
140
162
|
// The auth routes (`/console/api/auth/*`) resolve the session themselves
|
|
141
163
|
// and never read `accessResolver`, so resolving here too would repeat the
|
|
142
164
|
// session lookup plus its user query on every login/session/logout call
|
|
@@ -167,6 +189,15 @@ export function createConsoleRouter(deps: ConsoleApiCompositionDeps): AnyElysia
|
|
|
167
189
|
}),
|
|
168
190
|
);
|
|
169
191
|
})
|
|
192
|
+
.afterResponse(({ request }: { request: Request }) => {
|
|
193
|
+
// G-03: release the foreground-activity count for this request.
|
|
194
|
+
// Elysia runs `afterResponse` for every completed request, errored ones
|
|
195
|
+
// included (the error is converted to a response first), so this is the
|
|
196
|
+
// single reliable release point — a failing route can never leak an
|
|
197
|
+
// elevated foreground count (which would defer sweeps forever).
|
|
198
|
+
consoleActivityEnds.get(request)?.();
|
|
199
|
+
consoleActivityEnds.delete(request);
|
|
200
|
+
})
|
|
170
201
|
.use(
|
|
171
202
|
createConsoleAuthRoutes(
|
|
172
203
|
db,
|
|
@@ -197,6 +228,7 @@ export function createConsoleRouter(deps: ConsoleApiCompositionDeps): AnyElysia
|
|
|
197
228
|
admissionService: deps.admissionService,
|
|
198
229
|
readRoutingAccountInflight: deps.readRoutingAccountInflight,
|
|
199
230
|
...(deps.flushBuffers ? { flushBuffers: deps.flushBuffers } : {}),
|
|
231
|
+
...(deps.shutdownCoordinator ? { shutdownCoordinator: deps.shutdownCoordinator } : {}),
|
|
200
232
|
credentialService,
|
|
201
233
|
// The backup surface re-authenticates the operator, so it needs the current
|
|
202
234
|
// user's hash. Read from the session on the request that asks for it, never
|
|
@@ -9,7 +9,7 @@ import { acceptsGzip } from "./response-compression";
|
|
|
9
9
|
/**
|
|
10
10
|
* Represents the result of serving a static file.
|
|
11
11
|
*/
|
|
12
|
-
|
|
12
|
+
interface StaticServeResult {
|
|
13
13
|
status: number;
|
|
14
14
|
body: Uint8Array | undefined;
|
|
15
15
|
headers: Record<string, string>;
|
|
@@ -18,7 +18,7 @@ export interface StaticServeResult {
|
|
|
18
18
|
/**
|
|
19
19
|
* Configuration for the static file handler.
|
|
20
20
|
*/
|
|
21
|
-
|
|
21
|
+
interface StaticHandlerConfig {
|
|
22
22
|
/** Absolute path to the dashboard build directory */
|
|
23
23
|
buildDir: string;
|
|
24
24
|
/**
|
|
@@ -30,7 +30,7 @@ export interface StaticHandlerConfig {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/** Shared landing, console, and public share entry document produced by Vite. */
|
|
33
|
-
|
|
33
|
+
const DEFAULT_ENTRY_DOCUMENTS: Readonly<Record<string, string>> = {
|
|
34
34
|
"/": "index.html",
|
|
35
35
|
"/share": "index.html",
|
|
36
36
|
"/console": "index.html",
|
|
@@ -47,7 +47,7 @@ function dashboardBuildHeader(html: string): Record<string, string> {
|
|
|
47
47
|
* their own card here — crawlers do not run the client bundle, so a
|
|
48
48
|
* `document.title` set at runtime cannot reach them.
|
|
49
49
|
*/
|
|
50
|
-
|
|
50
|
+
interface SocialMeta {
|
|
51
51
|
title: string;
|
|
52
52
|
description: string;
|
|
53
53
|
image: string;
|
|
@@ -62,11 +62,11 @@ export const SHARE_SOCIAL_META: SocialMeta = {
|
|
|
62
62
|
title: "Cartethyia — Bansos Token",
|
|
63
63
|
description:
|
|
64
64
|
"Come and save your tokens 💖 Shared Cartethyia API key — Bansos Token with live quota, usage and model allowlist.",
|
|
65
|
-
image: "/assets/brand/og_bansos.
|
|
66
|
-
imageType: "image/
|
|
67
|
-
// Read from the file's own
|
|
68
|
-
//
|
|
69
|
-
//
|
|
65
|
+
image: "/assets/brand/og_bansos.jpg",
|
|
66
|
+
imageType: "image/jpeg",
|
|
67
|
+
// Read from the file's own header, not carried over from a previous image:
|
|
68
|
+
// og:image:width/height are what a crawler uses to allocate the card before
|
|
69
|
+
// the bytes arrive, so a copied size makes every preview crop.
|
|
70
70
|
imageWidth: 1760,
|
|
71
71
|
imageHeight: 576,
|
|
72
72
|
imageAlt: "Cartethyia Bansos Token — Come and save your tokens",
|
|
@@ -124,6 +124,16 @@ export interface ConsoleDomainContext {
|
|
|
124
124
|
readonly loadConsoleUser: (request: Request) => Promise<{ readonly passwordHash: string } | null>;
|
|
125
125
|
/** Password verification against the console user's stored hash. */
|
|
126
126
|
readonly credentialService: Pick<ConsoleCredentialService, "verifyPassword">;
|
|
127
|
+
/**
|
|
128
|
+
* The process shutdown coordinator, narrowed to the update apply route's
|
|
129
|
+
* drain surface. Optional because reduced compositions (tests) legitimately
|
|
130
|
+
* build a console that cannot apply updates; the apply route answers 503
|
|
131
|
+
* rather than exiting undrained when it is absent.
|
|
132
|
+
*/
|
|
133
|
+
readonly shutdownCoordinator?: {
|
|
134
|
+
readonly begin: (reason: "update") => Promise<void>;
|
|
135
|
+
readonly totalShutdownBudgetMs: () => number;
|
|
136
|
+
};
|
|
127
137
|
}
|
|
128
138
|
import { and, eq, isNull, or } from "drizzle-orm";
|
|
129
139
|
import { networkPools, providerRoutingSettings } from "../persistence/schema";
|
|
@@ -252,6 +262,9 @@ export function registerConsoleDomains(
|
|
|
252
262
|
console.use(createUpdateRoutes({
|
|
253
263
|
accessResolver: ctx.accessResolver,
|
|
254
264
|
observabilityStore,
|
|
265
|
+
...(ctx.shutdownCoordinator === undefined
|
|
266
|
+
? {}
|
|
267
|
+
: { shutdownCoordinator: ctx.shutdownCoordinator }),
|
|
255
268
|
}));
|
|
256
269
|
console.use(createRemoteSupportRoutes({
|
|
257
270
|
accessResolver: ctx.accessResolver,
|
|
@@ -271,6 +284,7 @@ export function registerConsoleDomains(
|
|
|
271
284
|
accessResolver: ctx.accessResolver,
|
|
272
285
|
auditSink: ctx.auditRecorder,
|
|
273
286
|
providerRegistry: ctx.providerRegistry,
|
|
287
|
+
redis: ctx.redis,
|
|
274
288
|
snapshotInvalidator: ctx.routeSnapshotService,
|
|
275
289
|
resolveExportCredentials,
|
|
276
290
|
// Without this, a custom provider only becomes dispatchable after a
|
|
@@ -384,8 +398,8 @@ export function registerConsoleDomains(
|
|
|
384
398
|
// it is released when the last of those flows settles.
|
|
385
399
|
const oauthCallbackListener = new OAuthCallbackListener({
|
|
386
400
|
completer: {
|
|
387
|
-
complete: (providerId, code, state) =>
|
|
388
|
-
completeLogin(oauthConfig, providerId, code, state),
|
|
401
|
+
complete: (providerId, code, state, callbackParams) =>
|
|
402
|
+
completeLogin(oauthConfig, providerId, code, state, callbackParams),
|
|
389
403
|
},
|
|
390
404
|
});
|
|
391
405
|
const oauthConfig: OAuthLoginConfig = {
|
|
@@ -54,13 +54,6 @@ export interface InferhubClientOptions {
|
|
|
54
54
|
readonly now?: () => number;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
export class InferhubRateLimited extends Error {
|
|
58
|
-
constructor() {
|
|
59
|
-
super("inferhub management rate limit reached");
|
|
60
|
-
this.name = "InferhubRateLimited";
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
57
|
/**
|
|
65
58
|
* One management GET.
|
|
66
59
|
*
|
|
@@ -20,7 +20,7 @@ import { decryptCredentialToString, encryptCredential, hashSecret } from "../../
|
|
|
20
20
|
import type { CartethyiaDatabase } from "../../persistence/db-handle";
|
|
21
21
|
|
|
22
22
|
/** Shape returned to the console: whether a key is set, and never the key. */
|
|
23
|
-
|
|
23
|
+
interface InferhubKeyStatus {
|
|
24
24
|
readonly configured: boolean;
|
|
25
25
|
/** Last four characters, so an operator can tell two keys apart. */
|
|
26
26
|
readonly last4: string | null;
|
|
@@ -26,7 +26,7 @@ import type {
|
|
|
26
26
|
/** Ask buckets are keyed to this many decimals so float noise cannot split one price into two tiers. */
|
|
27
27
|
const PRICE_PRECISION = 6;
|
|
28
28
|
/** Default number of live providers a capacity-weighted price must have behind it. */
|
|
29
|
-
|
|
29
|
+
const DEFAULT_MIN_CAPACITY = 2;
|
|
30
30
|
|
|
31
31
|
const FAMILY_STATES: readonly FamilyState[] = [
|
|
32
32
|
"operational",
|
|
@@ -114,7 +114,7 @@ export function groupTiers(
|
|
|
114
114
|
* provider count would make `providersLive` wrong, and a wrong availability
|
|
115
115
|
* number is worse than an absent one.
|
|
116
116
|
*/
|
|
117
|
-
|
|
117
|
+
function pricePointsToTiers(
|
|
118
118
|
points: unknown,
|
|
119
119
|
official: number | null,
|
|
120
120
|
): readonly Tier[] {
|
|
@@ -57,7 +57,7 @@ import type {
|
|
|
57
57
|
/** Success rate below which a model is not routed to, when one is reported. */
|
|
58
58
|
const MIN_SUCCESS_RATE_PCT = 80;
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
interface InferhubRoutesConfig {
|
|
61
61
|
readonly accessResolver: (request: Request) => AccessDecision | undefined;
|
|
62
62
|
/** Resolves the `config_read` key. Absent means the catalog cannot be read. */
|
|
63
63
|
readonly resolveConfigKey?: () => Promise<string | undefined> | string | undefined;
|
|
@@ -34,7 +34,7 @@ export interface ModelHealth {
|
|
|
34
34
|
readonly familyState: FamilyState | null;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
interface ModelCapabilities {
|
|
38
38
|
readonly contextWindow: number | null;
|
|
39
39
|
readonly maxOutputTokens: number | null;
|
|
40
40
|
readonly modalities: readonly string[];
|
|
@@ -173,7 +173,7 @@ export interface UsageCacheResponse {
|
|
|
173
173
|
cacheWriteTokens: number;
|
|
174
174
|
hitRate: number;
|
|
175
175
|
}
|
|
176
|
-
|
|
176
|
+
type UsageRequestMode = "stream" | "non_stream";
|
|
177
177
|
export interface UsageRequestItem {
|
|
178
178
|
requestId: string;
|
|
179
179
|
surface?: string;
|
|
@@ -34,7 +34,7 @@ import { poolByteSnapshot } from "../../network/pool/byte-accounting";
|
|
|
34
34
|
import { consoleSseResponse, createConsoleSseStream } from "./sse";
|
|
35
35
|
import { subscribeRequestCompleted } from "../../observability/request-notify";
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
interface LiveConfig {
|
|
38
38
|
readonly accessResolver: ConsoleAccessResolver;
|
|
39
39
|
readonly poolSelector?: NetworkPoolSelector;
|
|
40
40
|
readonly db?: CartethyiaDatabase;
|
|
@@ -94,10 +94,9 @@ export function createLiveRoutes(config: LiveConfig): AnyElysia {
|
|
|
94
94
|
requireScope(access, "dashboard:read");
|
|
95
95
|
const tenantId = access?.tenantId;
|
|
96
96
|
if (!tenantId) return errorResponse(new Error("Tenant required"), set, "Live operation failed");
|
|
97
|
-
set.headers
|
|
98
|
-
set
|
|
99
|
-
|
|
100
|
-
set.headers["x-accel-buffering"] = "no";
|
|
97
|
+
// No `set.headers` writes here: this handler returns a `Response`, so
|
|
98
|
+
// Elysia discards `set` and `consoleSseResponse` below owns the SSE
|
|
99
|
+
// headers (content-type, cache-control, connection, buffering).
|
|
101
100
|
return consoleSseResponse(
|
|
102
101
|
createConsoleSseStream(request.signal, ({ send }) => {
|
|
103
102
|
return subscribeRequestCompleted((notice) => {
|
|
@@ -119,22 +118,36 @@ export function createLiveRoutes(config: LiveConfig): AnyElysia {
|
|
|
119
118
|
})
|
|
120
119
|
.get("/live/in-flight/stream", ({ request, set }) => {
|
|
121
120
|
try {
|
|
122
|
-
requireScope(config.accessResolver(request), "dashboard:read");
|
|
121
|
+
const access = requireScope(config.accessResolver(request), "dashboard:read");
|
|
122
|
+
const tenantId = access?.tenantId;
|
|
123
|
+
return consoleSseResponse(
|
|
124
|
+
createConsoleSseStream(request.signal, ({ send }) => {
|
|
125
|
+
const store = config.stateStore;
|
|
126
|
+
if (!store) {
|
|
127
|
+
send("count", EMPTY_IN_FLIGHT);
|
|
128
|
+
return () => {};
|
|
129
|
+
}
|
|
130
|
+
// The Usage page keeps one stream open for both the in-flight gauge
|
|
131
|
+
// and request-table invalidation, so this route also fans out
|
|
132
|
+
// `request_completed` events (tagged by kind) for the tenant,
|
|
133
|
+
// mirroring `/live/requests/stream`.
|
|
134
|
+
const unsubscribe = store.subscribeInFlight((snapshot) => send("count", snapshot));
|
|
135
|
+
let unsubscribeCompleted: (() => void) | undefined;
|
|
136
|
+
if (tenantId) {
|
|
137
|
+
unsubscribeCompleted = subscribeRequestCompleted((notice) => {
|
|
138
|
+
if (notice.tenantId === tenantId) send("request_completed", notice);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
send("count", store.inFlightSnapshot());
|
|
142
|
+
return () => {
|
|
143
|
+
unsubscribe();
|
|
144
|
+
unsubscribeCompleted?.();
|
|
145
|
+
};
|
|
146
|
+
}),
|
|
147
|
+
);
|
|
123
148
|
} catch (e) {
|
|
124
149
|
return errorResponse(e, set, "Live operation failed");
|
|
125
150
|
}
|
|
126
|
-
return consoleSseResponse(
|
|
127
|
-
createConsoleSseStream(request.signal, ({ send }) => {
|
|
128
|
-
const store = config.stateStore;
|
|
129
|
-
if (!store) {
|
|
130
|
-
send("count", EMPTY_IN_FLIGHT);
|
|
131
|
-
return () => {};
|
|
132
|
-
}
|
|
133
|
-
const unsubscribe = store.subscribeInFlight((snapshot) => send("count", snapshot));
|
|
134
|
-
send("count", store.inFlightSnapshot());
|
|
135
|
-
return unsubscribe;
|
|
136
|
-
}),
|
|
137
|
-
);
|
|
138
151
|
})
|
|
139
152
|
.get("/live/pools", async ({ request, set }) => {
|
|
140
153
|
try {
|