cartethyia 2.7.5 → 2.7.7
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 +8 -3
- package/README.md +26 -2
- package/dist/dashboard/assets/BannedPage-B05aF8Dg.js +1 -0
- package/dist/dashboard/assets/BannedPage-B05aF8Dg.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-CLUhmjUy.js +3 -0
- package/dist/dashboard/assets/CliToolDetailPage-CLUhmjUy.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-CQmrqqrk.js +1 -0
- package/dist/dashboard/assets/CliToolsPage-CQmrqqrk.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-CHG_1Wr3.js +1 -0
- package/dist/dashboard/assets/CombosPage-CHG_1Wr3.js.gz +0 -0
- package/dist/dashboard/assets/{ConsoleLogPage-D5rol2j2.js → ConsoleLogPage-DPgbklad.js} +1 -1
- package/dist/dashboard/assets/ConsoleLogPage-DPgbklad.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-BKj_r0rp.js → CustomizationPage-pnfAqr_-.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-pnfAqr_-.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-DGJuU2A6.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-DGJuU2A6.js.gz +0 -0
- package/dist/dashboard/assets/{InjectSystemPromptPanel-B5nZvmf0.js → InjectSystemPromptPanel-C-e2AMz6.js} +245 -2
- package/dist/dashboard/assets/InjectSystemPromptPanel-C-e2AMz6.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-J8wPbmfT.js +1 -0
- package/dist/dashboard/assets/LoginPage-J8wPbmfT.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-DnQPSIA8.js → ModelPicker-C6WlpU5E.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-C6WlpU5E.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-BSQnF2Lp.js +1 -0
- package/dist/dashboard/assets/OverviewPage-BSQnF2Lp.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-DK_e0FJz.js +7 -0
- package/dist/dashboard/assets/ProviderDetailPage-DK_e0FJz.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js +1 -0
- package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-D_a3r6Gc.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-D_a3r6Gc.js.gz +0 -0
- package/dist/dashboard/assets/{ProxyPage-5SnUSy3j.js → ProxyPage-BBTRBAQ3.js} +1 -1
- package/dist/dashboard/assets/ProxyPage-BBTRBAQ3.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-B2WqMSG1.js +1 -0
- package/dist/dashboard/assets/QuotaPage-B2WqMSG1.js.gz +0 -0
- package/dist/dashboard/assets/{SettingsPage-BJtRZ4qD.js → SettingsPage-D7xp5Ij_.js} +1 -1
- package/dist/dashboard/assets/SettingsPage-D7xp5Ij_.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-LND6_Ss7.js +1 -0
- package/dist/dashboard/assets/SetupPage-LND6_Ss7.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-BfAb5-o_.js → StudioPage-BzNnm6Bi.js} +4 -4
- package/dist/dashboard/assets/StudioPage-BzNnm6Bi.js.gz +0 -0
- package/dist/dashboard/assets/ToolIcon-CfeLA-Z_.js +1 -0
- package/dist/dashboard/assets/ToolIcon-CfeLA-Z_.js.gz +0 -0
- package/dist/dashboard/assets/{UsagePage-BNzeZ2Vk.js → UsagePage-C1TbL24N.js} +13 -13
- package/dist/dashboard/assets/UsagePage-C1TbL24N.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-KvX83mRe.js +1 -0
- package/dist/dashboard/assets/api-keys-KvX83mRe.js.gz +0 -0
- package/dist/dashboard/assets/app-DRnQLhsc.js +9 -0
- package/dist/dashboard/assets/app-DRnQLhsc.js.gz +0 -0
- package/dist/dashboard/assets/app-mweRcsKp.css +2 -0
- package/dist/dashboard/assets/app-mweRcsKp.css.gz +0 -0
- package/dist/dashboard/assets/{assert-C0K-c4eo.js → assert-CidQVoNo.js} +1 -1
- package/dist/dashboard/assets/assert-CidQVoNo.js.gz +0 -0
- package/dist/dashboard/assets/{badge-DfbhQU4k.js → badge-BaX2GTrn.js} +1 -1
- package/dist/dashboard/assets/badge-BaX2GTrn.js.gz +0 -0
- package/dist/dashboard/assets/{banner-BllT4LcF.js → banner-DFH4Bkte.js} +1 -1
- package/dist/dashboard/assets/banner-DFH4Bkte.js.gz +0 -0
- package/dist/dashboard/assets/{card-CtkX66Wd.js → card-CxDw0lK6.js} +1 -1
- package/dist/dashboard/assets/card-CxDw0lK6.js.gz +0 -0
- package/dist/dashboard/assets/circle-question-mark-Cz4un8sH.js +1 -0
- package/dist/dashboard/assets/circle-question-mark-Cz4un8sH.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-CQXVMn4P.js → cli-tools-Bwv5-zGZ.js} +1 -1
- package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-BQqBQd2n.js → clipboard-button-DfS1ntiq.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-DfS1ntiq.js.gz +0 -0
- package/dist/dashboard/assets/dialog-BK-NRr5u.js +1 -0
- package/dist/dashboard/assets/dialog-BK-NRr5u.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-BrTEZ8zu.js → drawer-QqPul6sC.js} +1 -1
- package/dist/dashboard/assets/drawer-QqPul6sC.js.gz +0 -0
- package/dist/dashboard/assets/entry-BMlYJVFj.js +1 -0
- package/dist/dashboard/assets/entry-BMlYJVFj.js.gz +0 -0
- package/dist/dashboard/assets/entry-Dmx7gBiN.js +1 -0
- package/dist/dashboard/assets/entry-Dmx7gBiN.js.gz +0 -0
- package/dist/dashboard/assets/entry-vqGb8yVz.js +4 -0
- package/dist/dashboard/assets/entry-vqGb8yVz.js.gz +0 -0
- package/dist/dashboard/assets/formatters-DP-5E01-.js +1 -0
- package/dist/dashboard/assets/formatters-DP-5E01-.js.gz +0 -0
- package/dist/dashboard/assets/house-h9AZlJuT.js +1 -0
- package/dist/dashboard/assets/house-h9AZlJuT.js.gz +0 -0
- package/dist/dashboard/assets/{index-FQlj0HUT.js → index-D36vCZht.js} +2 -2
- package/dist/dashboard/assets/index-D36vCZht.js.gz +0 -0
- package/dist/dashboard/assets/{inline-C4gU5iOL.js → inline-CHJQwxLa.js} +1 -1
- package/dist/dashboard/assets/inline-CHJQwxLa.js.gz +0 -0
- package/dist/dashboard/assets/{input-BHHX_Tmm.js → input-BlmlizVV.js} +1 -1
- package/dist/dashboard/assets/input-BlmlizVV.js.gz +0 -0
- package/dist/dashboard/assets/{layout-CajrYUnD.js → layout-Bz93I-yE.js} +1 -1
- package/dist/dashboard/assets/layout-Bz93I-yE.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-Bx2I7XUe.js → list-row-Ml16KCfu.js} +1 -1
- package/dist/dashboard/assets/list-row-Ml16KCfu.js.gz +0 -0
- package/dist/dashboard/assets/{live-DNNqRbj2.js → live-7_QpnYGu.js} +1 -1
- package/dist/dashboard/assets/live-7_QpnYGu.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-Rr0TIvcj.js → mutation-GU7XdEjz.js} +1 -1
- package/dist/dashboard/assets/mutation-GU7XdEjz.js.gz +0 -0
- package/dist/dashboard/assets/{network-C5UBACrJ.js → network-CuMDaTzT.js} +1 -1
- package/dist/dashboard/assets/network-CuMDaTzT.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CoqpaDMx.js +2 -0
- package/dist/dashboard/assets/numbers-CoqpaDMx.js.gz +0 -0
- package/dist/dashboard/assets/{pagination-Xsi9Qx04.js → pagination-B5aOoweZ.js} +1 -1
- package/dist/dashboard/assets/pagination-B5aOoweZ.js.gz +0 -0
- package/dist/dashboard/assets/providers/zai.webp +0 -0
- package/dist/dashboard/assets/providers/zcode.webp +0 -0
- package/dist/dashboard/assets/{query-keys-BloKtaXJ.js → query-keys-YSoQOUh6.js} +1 -1
- package/dist/dashboard/assets/{query-keys-BloKtaXJ.js.gz → query-keys-YSoQOUh6.js.gz} +0 -0
- package/dist/dashboard/assets/quota-DJ1QlAOq.js +1 -0
- package/dist/dashboard/assets/quota-DJ1QlAOq.js.gz +0 -0
- package/dist/dashboard/assets/{routing-in0f_IfK.js → routing-fnCsxgNO.js} +1 -1
- package/dist/dashboard/assets/routing-fnCsxgNO.js.gz +0 -0
- package/dist/dashboard/assets/{select-BLULNqTp.js → select-C9Ssle9b.js} +2 -2
- package/dist/dashboard/assets/select-C9Ssle9b.js.gz +0 -0
- package/dist/dashboard/assets/{settings-CcGczj6I.js → settings-BxslsErn.js} +1 -1
- package/dist/dashboard/assets/settings-BxslsErn.js.gz +0 -0
- package/dist/dashboard/assets/{stack-D2lIR0tg.js → stack-j7cXjgYX.js} +1 -1
- package/dist/dashboard/assets/stack-j7cXjgYX.js.gz +0 -0
- package/dist/dashboard/assets/{state-DTARjfiW.js → state-DHmEnLa2.js} +1 -1
- package/dist/dashboard/assets/state-DHmEnLa2.js.gz +0 -0
- package/dist/dashboard/assets/{switch-c0oPSnqW.js → switch-DmZcyTIC.js} +1 -1
- package/dist/dashboard/assets/switch-DmZcyTIC.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-m8WGNPrz.js → useMutation-CbCP4w1o.js} +1 -1
- package/dist/dashboard/assets/useMutation-CbCP4w1o.js.gz +0 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +57 -57
- package/migrations/full-postgres/0042_add_telemetry_degenerate_stop.sql +14 -0
- package/migrations/full-postgres/0043_add_provider_custom_user_agent.sql +14 -0
- package/migrations/lite-sqlite3/0042_add_telemetry_degenerate_stop.sql +12 -0
- package/migrations/lite-sqlite3/0043_add_provider_custom_user_agent.sql +10 -0
- package/package.json +3 -1
- package/src/boot/dependencies.ts +10 -2
- package/src/config/providers.ts +13 -7
- package/src/config/security.ts +1 -1
- package/src/config/spec.ts +31 -17
- package/src/config/usage.ts +27 -0
- package/src/console/api-keys/routes.ts +19 -23
- package/src/console/cli-tools/cartethyia-websearch-plugin.ts +186 -0
- package/src/console/cli-tools/contracts.ts +39 -295
- package/src/console/cli-tools/fs-ops.ts +29 -0
- package/src/console/cli-tools/injectors/claude.ts +3 -3
- package/src/console/cli-tools/injectors/codex.ts +6 -6
- package/src/console/cli-tools/injectors/driver.ts +8 -105
- package/src/console/cli-tools/injectors/kilo.ts +146 -21
- package/src/console/cli-tools/injectors/opencode.ts +68 -17
- package/src/console/cli-tools/routes.ts +6 -0
- package/src/console/cli-tools/service.ts +7 -6
- package/src/console/observability/contracts.ts +6 -0
- package/src/console/observability/store.ts +3 -0
- package/src/console/providers/catalog/contracts.ts +4 -0
- package/src/console/providers/catalog/routes.ts +1 -0
- package/src/console/providers/detail/routes.ts +8 -0
- package/src/console/providers/detail/store.ts +4 -0
- package/src/console/quota/account-quota-tenant.ts +74 -0
- package/src/console/share/share-stats.ts +7 -9
- package/src/observability/event-log.ts +7 -0
- package/src/observability/event-query.ts +2 -0
- package/src/observability/telemetry-buffer.ts +9 -1
- package/src/persistence/boot.ts +13 -4
- package/src/persistence/schema.ts +15 -1
- package/src/persistence/stores/api-key-store.ts +19 -1
- package/src/protocol/canonical-model.ts +7 -0
- package/src/protocol/dsml.ts +5 -76
- package/src/protocol/request/gemini.ts +20 -1
- package/src/protocol/tool-identity.ts +15 -1
- package/src/providers/adapters/compatible-adapter.ts +29 -1
- package/src/providers/default-registry.ts +20 -4
- package/src/providers/discovery/discovery-types.ts +18 -0
- package/src/providers/discovery/probe-phases.ts +45 -0
- package/src/providers/discovery/probing-service.ts +41 -6
- package/src/providers/integrations/antigravity/antigravity-protocol.ts +108 -16
- package/src/providers/integrations/antigravity/antigravity-quota.ts +18 -6
- package/src/providers/integrations/antigravity/antigravity.ts +44 -11
- package/src/providers/integrations/codex/codex.ts +28 -1
- package/src/providers/integrations/cursor/cursor.ts +2 -3
- package/src/providers/integrations/github/github-discovery.ts +15 -2
- package/src/providers/integrations/github/github-oauth.ts +178 -9
- package/src/providers/integrations/github/github.ts +95 -14
- package/src/providers/integrations/kiro/kiro.ts +1 -2
- package/src/providers/integrations/qoder/chat-proto.ts +328 -0
- package/src/providers/integrations/qoder/claim-qoder-credits.ts +258 -0
- package/src/providers/integrations/qoder/qoder-adapter.ts +275 -0
- package/src/providers/integrations/qoder/qoder-auth.ts +201 -0
- package/src/providers/integrations/qoder/qoder-body.ts +78 -0
- package/src/providers/integrations/qoder/qoder-catalog.ts +14 -4
- package/src/providers/integrations/qoder/qoder-chat.ts +514 -0
- package/src/providers/integrations/qoder/qoder-cosy.ts +162 -0
- package/src/providers/integrations/qoder/qoder-grpc.ts +667 -0
- package/src/providers/integrations/qoder/qoder-ide.ts +584 -0
- package/src/providers/integrations/qoder/qoder-oauth.ts +4 -4
- package/src/providers/integrations/qoder/qoder-quota.ts +1 -1
- package/src/providers/integrations/qoder/qoder-realm.ts +40 -4
- package/src/providers/integrations/qoder/qoder-types.ts +51 -0
- package/src/providers/integrations/qoder/qoder-umid.ts +123 -8
- package/src/providers/integrations/qoder/qoder.ts +147 -1830
- package/src/providers/integrations/trae/trae.ts +2 -2
- package/src/providers/operations/account-error-classification.ts +67 -17
- package/src/providers/operations/byok-wire-profile.ts +19 -15
- package/src/providers/provider-contracts.ts +7 -0
- package/src/providers/provider-usage.ts +24 -55
- package/src/security/abuse.ts +5 -5
- package/src/security/admission/service.ts +11 -4
- package/src/security/api-key-auth.ts +5 -3
- package/src/transport/dispatch/attempt-finalize.ts +69 -21
- package/src/transport/dispatch/attempt-loop.ts +22 -0
- package/src/transport/dispatch/upstream.ts +4 -2
- package/src/transport/failure-policy.ts +15 -1
- package/src/transport/guards/error-lifecycle.ts +4 -0
- package/src/transport/request/state.ts +6 -0
- package/src/transport/routing/route-catalog.ts +8 -0
- package/src/transport/routing/route-model.ts +4 -0
- package/src/transport/routing/router.ts +8 -110
- package/src/transport/surface/reasoning-summary.ts +9 -14
- package/src/transport/vision-handoff.ts +83 -28
- package/dist/dashboard/assets/BannedPage-Cj15GsMp.js +0 -1
- package/dist/dashboard/assets/BannedPage-Cj15GsMp.js.gz +0 -0
- package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js +0 -1
- package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-DZKmVuJN.js +0 -1
- package/dist/dashboard/assets/CliToolDetailPage-DZKmVuJN.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-BIccZmeL.js +0 -1
- package/dist/dashboard/assets/CliToolsPage-BIccZmeL.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-DEEKkYD-.js +0 -1
- package/dist/dashboard/assets/CombosPage-DEEKkYD-.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-BKj_r0rp.js.gz +0 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-DkXb6dx-.js +0 -1
- package/dist/dashboard/assets/LoginPage-DkXb6dx-.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-DnQPSIA8.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js +0 -1
- package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js +0 -5
- package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js +0 -1
- package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-5SnUSy3j.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js +0 -1
- package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-WTa0sktC.js +0 -1
- package/dist/dashboard/assets/SetupPage-WTa0sktC.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-BfAb5-o_.js.gz +0 -0
- package/dist/dashboard/assets/ToolIcon-K1ckcDKg.js +0 -1
- package/dist/dashboard/assets/ToolIcon-K1ckcDKg.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-l29JROPv.js +0 -1
- package/dist/dashboard/assets/api-keys-l29JROPv.js.gz +0 -0
- package/dist/dashboard/assets/app--PJWq8_C.css +0 -2
- package/dist/dashboard/assets/app--PJWq8_C.css.gz +0 -0
- package/dist/dashboard/assets/app-Bgd3zANQ.js +0 -9
- package/dist/dashboard/assets/app-Bgd3zANQ.js.gz +0 -0
- package/dist/dashboard/assets/assert-C0K-c4eo.js.gz +0 -0
- package/dist/dashboard/assets/badge-DfbhQU4k.js.gz +0 -0
- package/dist/dashboard/assets/banner-BllT4LcF.js.gz +0 -0
- package/dist/dashboard/assets/card-CtkX66Wd.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-CQXVMn4P.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-BQqBQd2n.js.gz +0 -0
- package/dist/dashboard/assets/dialog-BEK7KP0H.js +0 -1
- package/dist/dashboard/assets/dialog-BEK7KP0H.js.gz +0 -0
- package/dist/dashboard/assets/drawer-BrTEZ8zu.js.gz +0 -0
- package/dist/dashboard/assets/entry-CHWxbS56.js +0 -1
- package/dist/dashboard/assets/entry-CHWxbS56.js.gz +0 -0
- package/dist/dashboard/assets/entry-EBHJ3DrE.js +0 -1
- package/dist/dashboard/assets/entry-EBHJ3DrE.js.gz +0 -0
- package/dist/dashboard/assets/entry-LCS85hiq.js +0 -4
- package/dist/dashboard/assets/entry-LCS85hiq.js.gz +0 -0
- package/dist/dashboard/assets/formatters-BAACA727.js +0 -1
- package/dist/dashboard/assets/formatters-BAACA727.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-YSCE4UC2.js +0 -1
- package/dist/dashboard/assets/github-badge-YSCE4UC2.js.gz +0 -0
- package/dist/dashboard/assets/index-FQlj0HUT.js.gz +0 -0
- package/dist/dashboard/assets/inline-C4gU5iOL.js.gz +0 -0
- package/dist/dashboard/assets/input-BHHX_Tmm.js.gz +0 -0
- package/dist/dashboard/assets/layout-CajrYUnD.js.gz +0 -0
- package/dist/dashboard/assets/list-row-Bx2I7XUe.js.gz +0 -0
- package/dist/dashboard/assets/live-DNNqRbj2.js.gz +0 -0
- package/dist/dashboard/assets/mutation-Rr0TIvcj.js.gz +0 -0
- package/dist/dashboard/assets/network-C5UBACrJ.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CUWAZK4J.js +0 -2
- package/dist/dashboard/assets/numbers-CUWAZK4J.js.gz +0 -0
- package/dist/dashboard/assets/pagination-Xsi9Qx04.js.gz +0 -0
- package/dist/dashboard/assets/providers/zai-coding-plan.svg +0 -6
- package/dist/dashboard/assets/providers/zai-coding-plan.svg.gz +0 -0
- package/dist/dashboard/assets/quota-DvQbD_sr.js +0 -1
- package/dist/dashboard/assets/quota-DvQbD_sr.js.gz +0 -0
- package/dist/dashboard/assets/routing-in0f_IfK.js.gz +0 -0
- package/dist/dashboard/assets/select-BLULNqTp.js.gz +0 -0
- package/dist/dashboard/assets/settings-CcGczj6I.js.gz +0 -0
- package/dist/dashboard/assets/stack-D2lIR0tg.js.gz +0 -0
- package/dist/dashboard/assets/state-DTARjfiW.js.gz +0 -0
- package/dist/dashboard/assets/switch-c0oPSnqW.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-m8WGNPrz.js.gz +0 -0
- package/src/console/cli-tools/injectors/cline.ts +0 -110
- package/src/console/cli-tools/injectors/copilot.ts +0 -108
- package/src/console/cli-tools/injectors/cowork.ts +0 -64
- package/src/console/cli-tools/injectors/deepseek-tui.ts +0 -85
- package/src/console/cli-tools/injectors/droid.ts +0 -96
- package/src/console/cli-tools/injectors/grok-build.ts +0 -70
- package/src/console/cli-tools/injectors/hermes.ts +0 -101
- package/src/console/cli-tools/injectors/jcode.ts +0 -115
- package/src/console/cli-tools/injectors/openclaw.ts +0 -161
- package/src/providers/integrations/qoder/qoder-text-tools.ts +0 -277
|
@@ -1,76 +1,77 @@
|
|
|
1
1
|
{
|
|
2
2
|
"count": 119,
|
|
3
3
|
"assets": [
|
|
4
|
-
"assets/BannedPage-
|
|
5
|
-
"assets/
|
|
6
|
-
"assets/
|
|
7
|
-
"assets/
|
|
8
|
-
"assets/
|
|
9
|
-
"assets/
|
|
10
|
-
"assets/
|
|
11
|
-
"assets/InjectSystemPromptPanel-
|
|
12
|
-
"assets/LoginPage-
|
|
13
|
-
"assets/ModelPicker-
|
|
14
|
-
"assets/OverviewPage-
|
|
15
|
-
"assets/ProviderDetailPage-
|
|
16
|
-
"assets/ProviderIcon-
|
|
17
|
-
"assets/ProvidersPage-
|
|
18
|
-
"assets/ProxyPage-
|
|
19
|
-
"assets/QuotaPage-
|
|
20
|
-
"assets/SettingsPage-
|
|
21
|
-
"assets/SetupPage-
|
|
22
|
-
"assets/StudioPage-
|
|
23
|
-
"assets/ToolIcon-
|
|
24
|
-
"assets/UsagePage-
|
|
25
|
-
"assets/api-keys-
|
|
26
|
-
"assets/app
|
|
27
|
-
"assets/app-
|
|
4
|
+
"assets/BannedPage-B05aF8Dg.js",
|
|
5
|
+
"assets/CliToolDetailPage-CLUhmjUy.js",
|
|
6
|
+
"assets/CliToolsPage-CQmrqqrk.js",
|
|
7
|
+
"assets/CombosPage-CHG_1Wr3.js",
|
|
8
|
+
"assets/ConsoleLogPage-DPgbklad.js",
|
|
9
|
+
"assets/CustomizationPage-pnfAqr_-.js",
|
|
10
|
+
"assets/HealthEventsModal-DGJuU2A6.js",
|
|
11
|
+
"assets/InjectSystemPromptPanel-C-e2AMz6.js",
|
|
12
|
+
"assets/LoginPage-J8wPbmfT.js",
|
|
13
|
+
"assets/ModelPicker-C6WlpU5E.js",
|
|
14
|
+
"assets/OverviewPage-BSQnF2Lp.js",
|
|
15
|
+
"assets/ProviderDetailPage-DK_e0FJz.js",
|
|
16
|
+
"assets/ProviderIcon-jjqXJDA3.js",
|
|
17
|
+
"assets/ProvidersPage-D_a3r6Gc.js",
|
|
18
|
+
"assets/ProxyPage-BBTRBAQ3.js",
|
|
19
|
+
"assets/QuotaPage-B2WqMSG1.js",
|
|
20
|
+
"assets/SettingsPage-D7xp5Ij_.js",
|
|
21
|
+
"assets/SetupPage-LND6_Ss7.js",
|
|
22
|
+
"assets/StudioPage-BzNnm6Bi.js",
|
|
23
|
+
"assets/ToolIcon-CfeLA-Z_.js",
|
|
24
|
+
"assets/UsagePage-C1TbL24N.js",
|
|
25
|
+
"assets/api-keys-KvX83mRe.js",
|
|
26
|
+
"assets/app-DRnQLhsc.js",
|
|
27
|
+
"assets/app-mweRcsKp.css",
|
|
28
28
|
"assets/arrow-left-CpBxkoxI.js",
|
|
29
29
|
"assets/arrow-right-Dl5yKnp8.js",
|
|
30
30
|
"assets/arrow-up-59ms1iiT.js",
|
|
31
|
-
"assets/assert-
|
|
31
|
+
"assets/assert-CidQVoNo.js",
|
|
32
32
|
"assets/backup-file-gdKIlg8U.js",
|
|
33
|
-
"assets/badge-
|
|
34
|
-
"assets/banner-
|
|
33
|
+
"assets/badge-BaX2GTrn.js",
|
|
34
|
+
"assets/banner-DFH4Bkte.js",
|
|
35
35
|
"assets/brain-Cwed_72z.js",
|
|
36
|
-
"assets/card-
|
|
36
|
+
"assets/card-CxDw0lK6.js",
|
|
37
37
|
"assets/chevron-left-Bf6CaTSJ.js",
|
|
38
38
|
"assets/chevron-right-BXIy5l3h.js",
|
|
39
39
|
"assets/circle-alert-CntYHV5v.js",
|
|
40
40
|
"assets/circle-check-BU3v_mFW.js",
|
|
41
|
-
"assets/
|
|
42
|
-
"assets/
|
|
41
|
+
"assets/circle-question-mark-Cz4un8sH.js",
|
|
42
|
+
"assets/cli-tools-Bwv5-zGZ.js",
|
|
43
|
+
"assets/clipboard-button-DfS1ntiq.js",
|
|
43
44
|
"assets/database-Dz9N3zGd.js",
|
|
44
|
-
"assets/dialog-
|
|
45
|
+
"assets/dialog-BK-NRr5u.js",
|
|
45
46
|
"assets/dialog-actions-B1axpEg7.js",
|
|
46
47
|
"assets/download-dRFo5_Wu.js",
|
|
47
|
-
"assets/drawer-
|
|
48
|
-
"assets/entry-
|
|
49
|
-
"assets/entry-
|
|
50
|
-
"assets/entry-
|
|
48
|
+
"assets/drawer-QqPul6sC.js",
|
|
49
|
+
"assets/entry-BMlYJVFj.js",
|
|
50
|
+
"assets/entry-Dmx7gBiN.js",
|
|
51
|
+
"assets/entry-vqGb8yVz.js",
|
|
51
52
|
"assets/eye-C_hawfH4.js",
|
|
52
53
|
"assets/eye-off-Bk5g2luF.js",
|
|
53
54
|
"assets/fingerprint-pattern-BWuHtbW4.js",
|
|
54
|
-
"assets/formatters-
|
|
55
|
+
"assets/formatters-DP-5E01-.js",
|
|
55
56
|
"assets/gauge-BbIMy7MB.js",
|
|
56
|
-
"assets/
|
|
57
|
+
"assets/house-h9AZlJuT.js",
|
|
57
58
|
"assets/image-BPaouViG.js",
|
|
58
|
-
"assets/index-
|
|
59
|
-
"assets/inline-
|
|
60
|
-
"assets/input-
|
|
59
|
+
"assets/index-D36vCZht.js",
|
|
60
|
+
"assets/inline-CHJQwxLa.js",
|
|
61
|
+
"assets/input-BlmlizVV.js",
|
|
61
62
|
"assets/jsx-runtime-CXUMngI_.js",
|
|
62
63
|
"assets/key-round-UkavsGxp.js",
|
|
63
64
|
"assets/layers-2-glBbjl.js",
|
|
64
|
-
"assets/layout-
|
|
65
|
-
"assets/list-row-
|
|
66
|
-
"assets/live-
|
|
65
|
+
"assets/layout-Bz93I-yE.js",
|
|
66
|
+
"assets/list-row-Ml16KCfu.js",
|
|
67
|
+
"assets/live-7_QpnYGu.js",
|
|
67
68
|
"assets/log-in-BmRjy60c.js",
|
|
68
69
|
"assets/message-circle-CCxGwRvv.js",
|
|
69
70
|
"assets/minimize-2-BTmMTK4o.js",
|
|
70
|
-
"assets/mutation-
|
|
71
|
-
"assets/network-
|
|
72
|
-
"assets/numbers-
|
|
73
|
-
"assets/pagination-
|
|
71
|
+
"assets/mutation-GU7XdEjz.js",
|
|
72
|
+
"assets/network-CuMDaTzT.js",
|
|
73
|
+
"assets/numbers-CoqpaDMx.js",
|
|
74
|
+
"assets/pagination-B5aOoweZ.js",
|
|
74
75
|
"assets/pencil-768ysRAr.js",
|
|
75
76
|
"assets/plus-DIdX_g-x.js",
|
|
76
77
|
"assets/power-off-Yjw9GMJh.js",
|
|
@@ -92,23 +93,22 @@
|
|
|
92
93
|
"assets/providers/openai-light.svg",
|
|
93
94
|
"assets/providers/parallel.svg",
|
|
94
95
|
"assets/providers/tokenharbor.svg",
|
|
95
|
-
"assets/
|
|
96
|
-
"assets/
|
|
97
|
-
"assets/quota-DvQbD_sr.js",
|
|
96
|
+
"assets/query-keys-YSoQOUh6.js",
|
|
97
|
+
"assets/quota-DJ1QlAOq.js",
|
|
98
98
|
"assets/refresh-cw-BqJFk4sU.js",
|
|
99
99
|
"assets/rotate-ccw-CufcqITi.js",
|
|
100
100
|
"assets/route-CNSNj9Zm.js",
|
|
101
|
-
"assets/routing-
|
|
101
|
+
"assets/routing-fnCsxgNO.js",
|
|
102
102
|
"assets/scaling-nWE4Cx8f.js",
|
|
103
103
|
"assets/search-JOKus9rb.js",
|
|
104
|
-
"assets/select-
|
|
104
|
+
"assets/select-C9Ssle9b.js",
|
|
105
105
|
"assets/settings-2-Ds9DQp0t.js",
|
|
106
|
-
"assets/settings-
|
|
106
|
+
"assets/settings-BxslsErn.js",
|
|
107
107
|
"assets/shield-BMQNxORh.js",
|
|
108
108
|
"assets/shield-check-DVS0Foqh.js",
|
|
109
|
-
"assets/stack-
|
|
110
|
-
"assets/state-
|
|
111
|
-
"assets/switch-
|
|
109
|
+
"assets/stack-j7cXjgYX.js",
|
|
110
|
+
"assets/state-DHmEnLa2.js",
|
|
111
|
+
"assets/switch-DmZcyTIC.js",
|
|
112
112
|
"assets/terminal-0_IjPWTk.js",
|
|
113
113
|
"assets/tokens-COzario9.js",
|
|
114
114
|
"assets/trash-Cppn5c3R.js",
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
"assets/use-modal-focus-By7oJoGd.js",
|
|
117
117
|
"assets/use-reduced-motion-C4B0R6Sz.js",
|
|
118
118
|
"assets/use-timeout-BwcBBRrT.js",
|
|
119
|
-
"assets/useMutation-
|
|
119
|
+
"assets/useMutation-CbCP4w1o.js",
|
|
120
120
|
"assets/wrench-B6E1oEuY.js",
|
|
121
121
|
"assets/zap-C4EeVW4q.js",
|
|
122
122
|
"index.html"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
-- Adds `telemetry_events.degenerate_stop` (boolean, nullable).
|
|
2
|
+
--
|
|
3
|
+
-- Marked on completed requests whose output is far smaller than the model's
|
|
4
|
+
-- ceiling and which ended with an ordinary `stop`. This is the signature of a
|
|
5
|
+
-- model truncating itself on a cached prefix: a short, cut-off reply that the
|
|
6
|
+
-- upstream reported as a clean stop. The column lets an operator measure how
|
|
7
|
+
-- often that happens instead of having to eyeball request detail.
|
|
8
|
+
--
|
|
9
|
+
-- NULL means the row predates this column (or the request never reached a
|
|
10
|
+
-- completed outcome). Only completed requests can carry a value.
|
|
11
|
+
--
|
|
12
|
+
-- `ADD COLUMN IF NOT EXISTS` keeps the file idempotent: a database built from a
|
|
13
|
+
-- newer baseline that already carries the column must not fail startup.
|
|
14
|
+
ALTER TABLE "telemetry_events" ADD COLUMN IF NOT EXISTS "degenerate_stop" boolean;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
-- Adds `provider_routing_settings.custom_user_agent` (text, nullable) — an
|
|
2
|
+
-- operator-set custom User-Agent that is stored separately from the provider's
|
|
3
|
+
-- native client identity (`user_agent`). This is the column the dashboard's
|
|
4
|
+
-- custom User-Agent control writes to.
|
|
5
|
+
--
|
|
6
|
+
-- NULL (default) means no custom override: dispatch uses the provider's native
|
|
7
|
+
-- identity. A non-NULL value is an explicit override and is applied at the
|
|
8
|
+
-- request edge (it replaces the User-Agent header even when the provider would
|
|
9
|
+
-- otherwise stamp its own).
|
|
10
|
+
--
|
|
11
|
+
-- Idempotency comes from the migration ledger plus `ADD COLUMN IF NOT EXISTS`:
|
|
12
|
+
-- a database built from a newer baseline that already carries the column must
|
|
13
|
+
-- not fail startup.
|
|
14
|
+
ALTER TABLE "provider_routing_settings" ADD COLUMN IF NOT EXISTS "custom_user_agent" text;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
-- Adds `telemetry_events.degenerate_stop` (boolean, nullable) — see the
|
|
2
|
+
-- identically named PostgreSQL migration for why. Both backends must apply the
|
|
3
|
+
-- same behavior; SQLite stores it as integer (0/1).
|
|
4
|
+
--
|
|
5
|
+
-- Idempotency comes from the migration ledger, not from the statement: the
|
|
6
|
+
-- runner records the file inside the same transaction, so a file that has
|
|
7
|
+
-- already run is never re-executed. The baseline is generated from
|
|
8
|
+
-- `0000_baseline.sql` alone and does not carry this column.
|
|
9
|
+
--
|
|
10
|
+
-- NOTE: the runner already wraps each migration in a transaction, so this file
|
|
11
|
+
-- must NOT issue BEGIN/COMMIT.
|
|
12
|
+
ALTER TABLE "telemetry_events" ADD COLUMN "degenerate_stop" integer;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
-- Adds `provider_routing_settings.custom_user_agent` (text, nullable) — an
|
|
2
|
+
-- operator-set custom User-Agent stored separately from the provider's native
|
|
3
|
+
-- client identity (`user_agent`). SQLite stores text as-is; NULL = no custom
|
|
4
|
+
-- override (native identity is used).
|
|
5
|
+
--
|
|
6
|
+
-- Idempotency comes from the migration ledger, not from the statement: the
|
|
7
|
+
-- runner records the file inside the same transaction, so a file that has
|
|
8
|
+
-- already run is never re-executed. The baseline is generated from
|
|
9
|
+
-- `0000_baseline.sql` alone and does not carry this column.
|
|
10
|
+
ALTER TABLE "provider_routing_settings" ADD COLUMN "custom_user_agent" text;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cartethyia",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.7",
|
|
4
4
|
"description": "A powerful, self-hosted reverse proxy for OpenAI- and Anthropic-compatible AI clients, powered by native Bun and Elysia. It serves both protocols from a single server, routes every model across any configured provider, and translates requests and responses in real time — streaming and prompt caching included. Underneath it runs a full delivery engine: per-account health tracking, quota and cooldown enforcement, automatic failover across pools and providers, usage accounting, and telemetry. Point OpenCode, Cline, Claude Code, Codex, or any compatible client at Cartethyia and it keeps its native protocol while the gateway absorbs every provider-specific difference behind it. Runs on embedded SQLite or external PostgreSQL with optional Redis coordination, ships as a global CLI with a system-tray console, and needs only Bun 1.4+ alongside Node.js/npm.",
|
|
5
5
|
"license": "GPL-3.0-only",
|
|
6
6
|
"type": "module",
|
|
@@ -69,6 +69,8 @@
|
|
|
69
69
|
"check:migrations": "bun run scripts/test/check-migrations.ts"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
+
"@grpc/grpc-js": "^1.14.7",
|
|
73
|
+
"@grpc/proto-loader": "^0.8.1",
|
|
72
74
|
"drizzle-orm": "0.45.2",
|
|
73
75
|
"elysia": "2.0.0-beta.16",
|
|
74
76
|
"enquirer": "^2.4.1",
|
package/src/boot/dependencies.ts
CHANGED
|
@@ -28,6 +28,7 @@ import { DrizzleProviderCatalogStore } from "../console/providers/catalog/store"
|
|
|
28
28
|
import { InMemoryRouteSnapshotService } from "../transport/routing/route-model";
|
|
29
29
|
import { RoutingEngine } from "../transport/routing/router";
|
|
30
30
|
import { RedisAdmissionController } from "../transport/routing/admission";
|
|
31
|
+
import { admissionKey } from "../transport/routing/admission";
|
|
31
32
|
import { ApiKeyAdmissionService } from "../security/admission/service";
|
|
32
33
|
import { InMemoryAdmissionCounterStore } from "../security/admission/in-memory-store";
|
|
33
34
|
import { RedisAdmissionCounterStore } from "../security/admission/redis-store";
|
|
@@ -479,10 +480,17 @@ export async function buildProductionDeps(): Promise<ProductionDeps> {
|
|
|
479
480
|
owned.has(candidate.provider_account_id),
|
|
480
481
|
);
|
|
481
482
|
const snapshot = await routingEngine.accountInflightSnapshot(ownedCandidates);
|
|
483
|
+
// Map each bucket back to the account it belongs to using the same
|
|
484
|
+
// `admissionKey` format admission writes with — never string-slicing the
|
|
485
|
+
// bucket (the trailing segment is the owner tenant, not the account id).
|
|
486
|
+
const accountByBucket = new Map<string, string>();
|
|
487
|
+
for (const candidate of ownedCandidates) {
|
|
488
|
+
accountByBucket.set(admissionKey(candidate), candidate.provider_account_id!);
|
|
489
|
+
}
|
|
482
490
|
const totals = new Map<string, number>();
|
|
483
491
|
for (const [bucket, count] of snapshot) {
|
|
484
|
-
const accountId =
|
|
485
|
-
if (!owned.has(accountId)) continue;
|
|
492
|
+
const accountId = accountByBucket.get(bucket);
|
|
493
|
+
if (accountId === undefined || !owned.has(accountId)) continue;
|
|
486
494
|
totals.set(accountId, (totals.get(accountId) ?? 0) + count);
|
|
487
495
|
}
|
|
488
496
|
return [...totals].map(([accountId, inflight]) => ({ accountId, inflight }));
|
package/src/config/providers.ts
CHANGED
|
@@ -91,14 +91,20 @@ export function resolveGithubEnterpriseDomain(): string {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
export type GithubCopilotMode = "opencode-copilot" | "vscode-client-real";
|
|
95
|
+
|
|
94
96
|
/**
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
+
* Which GitHub Copilot wire identity the adapter uses. Defaults to
|
|
98
|
+
* `opencode-copilot` (raw GitHub OAuth token + minimal OpenCode headers),
|
|
99
|
+
* which is the proven-most-stable path (one token, no mint expiry). The
|
|
100
|
+
* `vscode-client-real` mode matches the VS Code reference client exactly but
|
|
101
|
+
* requires a freshly minted Copilot token.
|
|
97
102
|
*/
|
|
98
|
-
export function
|
|
103
|
+
export function resolveGithubCopilotMode(): GithubCopilotMode {
|
|
99
104
|
const raw = readText(
|
|
100
|
-
"
|
|
101
|
-
CONFIG_SPEC.
|
|
102
|
-
).toLowerCase();
|
|
103
|
-
|
|
105
|
+
"CARTETHYIA_GITHUB_COPILOT_MODE",
|
|
106
|
+
CONFIG_SPEC.CARTETHYIA_GITHUB_COPILOT_MODE,
|
|
107
|
+
).trim().toLowerCase();
|
|
108
|
+
if (raw === "vscode-client-real") return "vscode-client-real";
|
|
109
|
+
return "opencode-copilot";
|
|
104
110
|
}
|
package/src/config/security.ts
CHANGED
|
@@ -9,7 +9,7 @@ const ENCRYPTION_KEY_LENGTH = 32;
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Per-IP request ceiling for the unauthenticated abuse-protection layer.
|
|
12
|
-
* Defaults to
|
|
12
|
+
* Defaults to 540 requests per window so an unset env does not mean unlimited;
|
|
13
13
|
* operators tune it via `IP_RATE_MAX_PER_WINDOW`.
|
|
14
14
|
*/
|
|
15
15
|
export function resolveIpRateLimit(): number {
|
package/src/config/spec.ts
CHANGED
|
@@ -89,11 +89,12 @@ export const CONFIG_SPEC = {
|
|
|
89
89
|
CARTETHYIA_API_KEY: { kind: "optional-text" },
|
|
90
90
|
CARTETHYIA_SERVER_MAX_BODY_BYTES: {
|
|
91
91
|
kind: "int",
|
|
92
|
-
// A
|
|
93
|
-
//
|
|
94
|
-
// admission's job, so an
|
|
95
|
-
// sets the ceiling in
|
|
96
|
-
|
|
92
|
+
// A 1M-token context is roughly 4+ MB of text (Qoder gRPC/legacy paths
|
|
93
|
+
// accept it), so 16 MB admits every real request while bounding the
|
|
94
|
+
// worst-case hold. How many may be in flight is admission's job, so an
|
|
95
|
+
// operator with even larger payloads raises this and sets the ceiling in
|
|
96
|
+
// Settings.
|
|
97
|
+
default: 16 * 1024 * 1024,
|
|
97
98
|
min: 1024,
|
|
98
99
|
max: Number.MAX_SAFE_INTEGER,
|
|
99
100
|
},
|
|
@@ -172,6 +173,12 @@ export const CONFIG_SPEC = {
|
|
|
172
173
|
*/
|
|
173
174
|
CARTETHYIA_DISABLED_TASKS: { kind: "list" },
|
|
174
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Force the Qoder UMID bridge to the mini-ELF bundle on Linux
|
|
178
|
+
* (`1` = always mini, `0` = never mini; absent = auto-detect containers).
|
|
179
|
+
*/
|
|
180
|
+
CARTETHYIA_QODER_UMID_MINI: { kind: "int", default: 0, min: 0, max: 1 },
|
|
181
|
+
|
|
175
182
|
/**
|
|
176
183
|
* How long a day's telemetry is kept, in days.
|
|
177
184
|
*
|
|
@@ -188,6 +195,13 @@ export const CONFIG_SPEC = {
|
|
|
188
195
|
min: 1 * 1024 * 1024,
|
|
189
196
|
max: 16 * 1024 * 1024,
|
|
190
197
|
},
|
|
198
|
+
// Input-token accounting for usage display. Providers disagree on whether
|
|
199
|
+
// `input_tokens` already includes cached tokens: OpenAI/DeepSeek report the
|
|
200
|
+
// inclusive total with a cached subset, while Anthropic reports fresh-only
|
|
201
|
+
// with cache reads separate. `inclusive` (default) folds cache into input so
|
|
202
|
+
// every provider reads alike — IN is always the whole prompt and CACHED its
|
|
203
|
+
// subset. `as-is` keeps the raw upstream semantics.
|
|
204
|
+
CARTETHYIA_USAGE_INPUT_MODE: { kind: "text", default: "inclusive" },
|
|
191
205
|
|
|
192
206
|
// Upstream request timeout + retry backoff
|
|
193
207
|
//
|
|
@@ -262,7 +276,7 @@ export const CONFIG_SPEC = {
|
|
|
262
276
|
CARTETHYIA_PROXY_MAX_FREE_SOCKETS: { kind: "int", default: 20, min: 0, max: 100_000 },
|
|
263
277
|
|
|
264
278
|
// Security (encryption key, public origin, abuse ceiling)
|
|
265
|
-
IP_RATE_MAX_PER_WINDOW: { kind: "int", default:
|
|
279
|
+
IP_RATE_MAX_PER_WINDOW: { kind: "int", default: 540, min: 1, max: Number.MAX_SAFE_INTEGER },
|
|
266
280
|
CARTETHYIA_ENCRYPTION_KEY: {
|
|
267
281
|
kind: "required",
|
|
268
282
|
error:
|
|
@@ -297,20 +311,20 @@ export const CONFIG_SPEC = {
|
|
|
297
311
|
* an operator on one has no other way to point the login at it.
|
|
298
312
|
*/
|
|
299
313
|
CARTETHYIA_GITHUB_ENTERPRISE_DOMAIN: { kind: "text", default: "" },
|
|
300
|
-
// Only the literal true opts active ZCode accounts into daily gift claims.
|
|
301
|
-
CARTETHYIA_ZCODE_AUTO_CLAIM: { kind: "text", default: "false" },
|
|
302
314
|
/**
|
|
303
|
-
*
|
|
315
|
+
* Which wire identity the GitHub Copilot Auto/chat path presents to the
|
|
316
|
+
* upstream:
|
|
304
317
|
*
|
|
305
|
-
* - `
|
|
306
|
-
*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
* more than a uniform hit-rate reading.
|
|
318
|
+
* - `opencode-copilot` (default): the long-lived GitHub OAuth token + minimal
|
|
319
|
+
* OpenCode headers. One token, no mint step, no short-lived minted-token
|
|
320
|
+
* expiry. This is the most stable in practice.
|
|
321
|
+
* - `vscode-client-real`: a freshly minted Copilot token + the full VS Code
|
|
322
|
+
* reference headers. Matches the VS Code client exactly, but requires the
|
|
323
|
+
* minted token (expires ~25 min) and the reference identity.
|
|
312
324
|
*/
|
|
313
|
-
|
|
325
|
+
CARTETHYIA_GITHUB_COPILOT_MODE: { kind: "text", default: "opencode-copilot" },
|
|
326
|
+
// Only the literal true opts active ZCode accounts into daily gift claims.
|
|
327
|
+
CARTETHYIA_ZCODE_AUTO_CLAIM: { kind: "text", default: "false" },
|
|
314
328
|
/**
|
|
315
329
|
* Free-tier OpenCode ids the listing still advertises but upstream refuses.
|
|
316
330
|
* Replaces the bundled list outright; the single token `none` trusts the
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Usage input-token accounting mode.
|
|
3
|
+
*
|
|
4
|
+
* Providers disagree on whether `input_tokens` already includes cached tokens.
|
|
5
|
+
* OpenAI/DeepSeek report the inclusive total with a cached subset; Anthropic
|
|
6
|
+
* reports fresh-only with cache reads (and writes) separate. `normalizeUsage`
|
|
7
|
+
* reads this mode to decide whether to fold cache into input so every provider
|
|
8
|
+
* reads alike (`inclusive`, the default) or to keep the raw upstream semantics
|
|
9
|
+
* (`as-is`).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { CONFIG_SPEC, readText } from "./spec";
|
|
13
|
+
|
|
14
|
+
export type UsageInputMode = "inclusive" | "as-is";
|
|
15
|
+
|
|
16
|
+
/** Resolves the operator's chosen accounting mode; defaults to inclusive. */
|
|
17
|
+
export function resolveUsageInputMode(): UsageInputMode {
|
|
18
|
+
const raw = readText(
|
|
19
|
+
"CARTETHYIA_USAGE_INPUT_MODE",
|
|
20
|
+
CONFIG_SPEC.CARTETHYIA_USAGE_INPUT_MODE,
|
|
21
|
+
)
|
|
22
|
+
.trim()
|
|
23
|
+
.toLowerCase();
|
|
24
|
+
if (raw === "inclusive") return "inclusive";
|
|
25
|
+
if (raw === "as-is") return "as-is";
|
|
26
|
+
throw new Error('CARTETHYIA_USAGE_INPUT_MODE must be "inclusive" or "as-is"');
|
|
27
|
+
}
|
|
@@ -41,7 +41,6 @@ import {
|
|
|
41
41
|
} from "./contracts";
|
|
42
42
|
import type { SharedKeyActivityDetail, SharedKeySummary } from "../share/share-usage";
|
|
43
43
|
import { popupImageBytes } from "./share-popup-image";
|
|
44
|
-
import { log } from "../../observability/logger";
|
|
45
44
|
|
|
46
45
|
const SHARED_CHILD_SORT_COLUMNS = new Set<SharedChildSortColumn>([
|
|
47
46
|
"createdAt",
|
|
@@ -87,33 +86,23 @@ export function createApiKeyOperations(config: ApiKeyConfig) {
|
|
|
87
86
|
const topLevel = records.filter(
|
|
88
87
|
(record) => record.revokedAt === undefined && record.parentKeyId === undefined,
|
|
89
88
|
);
|
|
90
|
-
// A share template's own counter
|
|
91
|
-
//
|
|
92
|
-
//
|
|
93
|
-
//
|
|
94
|
-
// telemetry total the family ever recorded — revoked/deleted children
|
|
95
|
-
// included (their spend is already spent), so the number survives
|
|
96
|
-
// cleanup and matches the share page.
|
|
89
|
+
// A share template's own counter is the live family accumulator now:
|
|
90
|
+
// every recipient commit adds to it (see ApiKeyAdmissionService
|
|
91
|
+
// commitUsage), so reporting it raw gives the enforced family total.
|
|
92
|
+
// No telemetry add-on is needed, and adding it here would double-count.
|
|
97
93
|
return Promise.all(
|
|
98
94
|
topLevel.map(async (record) => {
|
|
99
95
|
const response = sanitizeApiKeyResponse(record);
|
|
100
96
|
if (record.keyMode !== "share") return response;
|
|
101
|
-
|
|
102
|
-
.sumFamilyTelemetryConsumed(authorized.tenantId, record.id)
|
|
103
|
-
.catch((error) => {
|
|
104
|
-
// A failed sum must not fail the whole list, but it must not
|
|
105
|
-
// be silent either: reporting the share template's spend as 0
|
|
106
|
-
// under-reports consumed tokens in the console list.
|
|
107
|
-
log.warn(
|
|
108
|
-
`[api-keys] sumFamilyTelemetryConsumed failed for key ${record.id}; reporting 0`,
|
|
109
|
-
error as Error,
|
|
110
|
-
);
|
|
111
|
-
return 0;
|
|
112
|
-
});
|
|
113
|
-
return { ...response, tokensConsumed: response.tokensConsumed + family };
|
|
97
|
+
return response;
|
|
114
98
|
}),
|
|
115
|
-
|
|
116
|
-
|
|
99
|
+
);
|
|
100
|
+
},
|
|
101
|
+
async listActiveBannedKeys(access: AccessDecision | undefined): Promise<ApiKeyResponse[]> {
|
|
102
|
+
const authorized = requireTenantScope(access, "dashboard:read");
|
|
103
|
+
const records = await config.store.listActiveBanned(authorized.tenantId);
|
|
104
|
+
return records.map(sanitizeApiKeyResponse);
|
|
105
|
+
},
|
|
117
106
|
/** Persists a new credential order. `keyIds` must name every top-level key
|
|
118
107
|
the tenant has, so a partial list cannot silently renumber rows. */
|
|
119
108
|
async reorderKeys(access: AccessDecision | undefined, keyIds: readonly string[]): Promise<void> {
|
|
@@ -939,6 +928,13 @@ export function createApiKeyRoutes(config: ApiKeyConfig): AnyElysia {
|
|
|
939
928
|
return errorResponse(error, set, "API-key operation failed");
|
|
940
929
|
}
|
|
941
930
|
})
|
|
931
|
+
.get("/banned", async ({ request, set }) => {
|
|
932
|
+
try {
|
|
933
|
+
return await factory.listActiveBannedKeys(config.accessResolver(request));
|
|
934
|
+
} catch (error) {
|
|
935
|
+
return errorResponse(error, set, "API-key operation failed");
|
|
936
|
+
}
|
|
937
|
+
})
|
|
942
938
|
.post("/reorder", { body: reorderKeysBody }, async ({ request, body, set }) => {
|
|
943
939
|
try {
|
|
944
940
|
await factory.reorderKeys(config.accessResolver(request), body.keyIds);
|