cartethyia 2.7.7 → 2.7.9
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 +0 -1
- package/README.md +29 -59
- package/dist/dashboard/assets/BannedPage-BxoG1MrL.js +1 -0
- package/dist/dashboard/assets/BannedPage-BxoG1MrL.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-CLUhmjUy.js → CliToolDetailPage-ixwgKk53.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-ixwgKk53.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-CQmrqqrk.js → CliToolsPage-BmttNV3U.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-BmttNV3U.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-BE3qwwfC.js +1 -0
- package/dist/dashboard/assets/CombosPage-BE3qwwfC.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-CRZdmMIX.js +1 -0
- package/dist/dashboard/assets/ConsoleLogPage-CRZdmMIX.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-Dv_FJ6Er.js +1 -0
- package/dist/dashboard/assets/CustomizationPage-Dv_FJ6Er.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-CoVrw2sM.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-CoVrw2sM.js.gz +0 -0
- package/dist/dashboard/assets/{InjectSystemPromptPanel-C-e2AMz6.js → InjectSystemPromptPanel-BOoO8rpz.js} +2 -2
- package/dist/dashboard/assets/InjectSystemPromptPanel-BOoO8rpz.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-J8wPbmfT.js → LoginPage-ChJuNNVN.js} +1 -1
- package/dist/dashboard/assets/LoginPage-ChJuNNVN.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-C6WlpU5E.js → ModelPicker-BZAJtPg1.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-BZAJtPg1.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-BE40s3u5.js +1 -0
- package/dist/dashboard/assets/OverviewPage-BE40s3u5.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-sfLoQtPV.js +8 -0
- package/dist/dashboard/assets/ProviderDetailPage-sfLoQtPV.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-CQ6bPUf_.js +1 -0
- package/dist/dashboard/assets/ProviderIcon-CQ6bPUf_.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-DcepmPWo.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-DcepmPWo.js.gz +0 -0
- package/dist/dashboard/assets/{ProxyPage-BBTRBAQ3.js → ProxyPage-BJ87Pp0U.js} +1 -1
- package/dist/dashboard/assets/ProxyPage-BJ87Pp0U.js.gz +0 -0
- package/dist/dashboard/assets/{QuotaPage-B2WqMSG1.js → QuotaPage-gkSyRAKa.js} +1 -1
- package/dist/dashboard/assets/QuotaPage-gkSyRAKa.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-C5HPWqEv.js +1 -0
- package/dist/dashboard/assets/SettingsPage-C5HPWqEv.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-LND6_Ss7.js → SetupPage-CFNcATJJ.js} +1 -1
- package/dist/dashboard/assets/SetupPage-CFNcATJJ.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-BzNnm6Bi.js → StudioPage-YoD4tY5l.js} +1 -1
- package/dist/dashboard/assets/StudioPage-YoD4tY5l.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-DxjaAhb_.js +56 -0
- package/dist/dashboard/assets/UsagePage-DxjaAhb_.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-BTlkq_Uk.js +1 -0
- package/dist/dashboard/assets/api-keys-BTlkq_Uk.js.gz +0 -0
- package/dist/dashboard/assets/app-BX2nnKqs.css +2 -0
- package/dist/dashboard/assets/app-BX2nnKqs.css.gz +0 -0
- package/dist/dashboard/assets/assert-CndthXFQ.js +1 -0
- package/dist/dashboard/assets/assert-CndthXFQ.js.gz +0 -0
- package/dist/dashboard/assets/{badge-BaX2GTrn.js → badge-DdbT_7Am.js} +1 -1
- package/dist/dashboard/assets/badge-DdbT_7Am.js.gz +0 -0
- package/dist/dashboard/assets/ban-durations-B58FyRxC.js +1 -0
- package/dist/dashboard/assets/ban-durations-B58FyRxC.js.gz +0 -0
- package/dist/dashboard/assets/{banner-DFH4Bkte.js → banner-CsGN-nbm.js} +1 -1
- package/dist/dashboard/assets/banner-CsGN-nbm.js.gz +0 -0
- package/dist/dashboard/assets/brand/bansos_page.webp +0 -0
- package/dist/dashboard/assets/brand/denia_bansos.webp +0 -0
- package/dist/dashboard/assets/brand/favicon.webp +0 -0
- package/dist/dashboard/assets/brand/login_register.webp +0 -0
- package/dist/dashboard/assets/brand/login_register_initial.webp +0 -0
- package/dist/dashboard/assets/brand/og_bansos.webp +0 -0
- package/dist/dashboard/assets/brand/og_image.webp +0 -0
- package/dist/dashboard/assets/brand/sidebar_ico.webp +0 -0
- package/dist/dashboard/assets/{card-CxDw0lK6.js → card-mgZ_TLLZ.js} +1 -1
- package/dist/dashboard/assets/card-mgZ_TLLZ.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-A1-v8-03.js +1 -0
- package/dist/dashboard/assets/cli-tools-A1-v8-03.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-DfS1ntiq.js → clipboard-button-CJ4Zty89.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-CJ4Zty89.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-BK-NRr5u.js → dialog-B5L2jPQ_.js} +1 -1
- package/dist/dashboard/assets/dialog-B5L2jPQ_.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-QqPul6sC.js → drawer-DkjUouAj.js} +1 -1
- package/dist/dashboard/assets/drawer-DkjUouAj.js.gz +0 -0
- package/dist/dashboard/assets/{entry-BMlYJVFj.js → entry-B-LVLV6o.js} +1 -1
- package/dist/dashboard/assets/entry-B-LVLV6o.js.gz +0 -0
- package/dist/dashboard/assets/entry-CAhdYl3B.js +1 -0
- package/dist/dashboard/assets/entry-CAhdYl3B.js.gz +0 -0
- package/dist/dashboard/assets/entry-D2xD0Tmd.js +4 -0
- package/dist/dashboard/assets/entry-D2xD0Tmd.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-DP-5E01-.js → formatters-CrsdLVsn.js} +1 -1
- package/dist/dashboard/assets/formatters-CrsdLVsn.js.gz +0 -0
- package/dist/dashboard/assets/{index-D36vCZht.js → index-BU64Lqvp.js} +2 -2
- package/dist/dashboard/assets/index-BU64Lqvp.js.gz +0 -0
- package/dist/dashboard/assets/{inline-CHJQwxLa.js → inline-B2aDLyyg.js} +1 -1
- package/dist/dashboard/assets/inline-B2aDLyyg.js.gz +0 -0
- package/dist/dashboard/assets/{input-BlmlizVV.js → input-BCVkdR9d.js} +1 -1
- package/dist/dashboard/assets/input-BCVkdR9d.js.gz +0 -0
- package/dist/dashboard/assets/{layout-Bz93I-yE.js → layout-DNcAdMK-.js} +1 -1
- package/dist/dashboard/assets/layout-DNcAdMK-.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-Ml16KCfu.js → list-row-DgrIH0hw.js} +1 -1
- package/dist/dashboard/assets/list-row-DgrIH0hw.js.gz +0 -0
- package/dist/dashboard/assets/{live-7_QpnYGu.js → live-Cae01iu8.js} +1 -1
- package/dist/dashboard/assets/live-Cae01iu8.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-GU7XdEjz.js → mutation-BQ0ccH_A.js} +1 -1
- package/dist/dashboard/assets/mutation-BQ0ccH_A.js.gz +0 -0
- package/dist/dashboard/assets/{network-CuMDaTzT.js → network-CRib7H_2.js} +1 -1
- package/dist/dashboard/assets/network-CRib7H_2.js.gz +0 -0
- package/dist/dashboard/assets/{numbers-CoqpaDMx.js → numbers-BKQE8Xpz.js} +1 -1
- package/dist/dashboard/assets/numbers-BKQE8Xpz.js.gz +0 -0
- package/dist/dashboard/assets/{pagination-B5aOoweZ.js → pagination-ecPvG_8g.js} +1 -1
- package/dist/dashboard/assets/pagination-ecPvG_8g.js.gz +0 -0
- package/dist/dashboard/assets/providers/devin.svg +9 -0
- package/dist/dashboard/assets/providers/devin.svg.gz +0 -0
- package/dist/dashboard/assets/providers/windsurf.svg +10 -0
- package/dist/dashboard/assets/providers/windsurf.svg.gz +0 -0
- package/dist/dashboard/assets/{query-keys-YSoQOUh6.js → query-keys-IKLh0YFd.js} +1 -1
- package/dist/dashboard/assets/query-keys-IKLh0YFd.js.gz +0 -0
- package/dist/dashboard/assets/routing-Ckm1UXuC.js +1 -0
- package/dist/dashboard/assets/routing-Ckm1UXuC.js.gz +0 -0
- package/dist/dashboard/assets/{select-C9Ssle9b.js → select-ChoFWyKz.js} +1 -1
- package/dist/dashboard/assets/select-ChoFWyKz.js.gz +0 -0
- package/dist/dashboard/assets/settings-CKjFPlKW.js +1 -0
- package/dist/dashboard/assets/settings-CKjFPlKW.js.gz +0 -0
- package/dist/dashboard/assets/{stack-j7cXjgYX.js → stack-DWCwU3fh.js} +1 -1
- package/dist/dashboard/assets/stack-DWCwU3fh.js.gz +0 -0
- package/dist/dashboard/assets/{state-DHmEnLa2.js → state-Cg3VL5J_.js} +1 -1
- package/dist/dashboard/assets/state-Cg3VL5J_.js.gz +0 -0
- package/dist/dashboard/assets/story/25817331.webp +0 -0
- package/dist/dashboard/assets/story/Shorekeeper.webp +0 -0
- package/dist/dashboard/assets/story/cartethyia-god.webp +0 -0
- package/dist/dashboard/assets/story/fleurdelys_plus.webp +0 -0
- package/dist/dashboard/assets/story/jinhsi-blossom.webp +0 -0
- package/dist/dashboard/assets/story/phrolova-a.webp +0 -0
- package/dist/dashboard/assets/story/requestdeniawokkjpg.webp +0 -0
- package/dist/dashboard/assets/story/wuthering-waves-hiyuki-aemeath-hiyuki-rover.webp +0 -0
- package/dist/dashboard/assets/{switch-DmZcyTIC.js → switch-Db70BMix.js} +1 -1
- package/dist/dashboard/assets/switch-Db70BMix.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-CbCP4w1o.js → useMutation-BqdE0LuM.js} +1 -1
- package/dist/dashboard/assets/useMutation-BqdE0LuM.js.gz +0 -0
- package/dist/dashboard/console-backgrounds.webp +0 -0
- package/dist/dashboard/console-backgrounds_initial.webp +0 -0
- package/dist/dashboard/donation/qris-risun-marke.webp +0 -0
- package/dist/dashboard/index.html +3 -3
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +57 -55
- package/migrations/full-postgres/0044_add_models_warning_metadata.sql +10 -0
- package/migrations/full-postgres/0045_migrate_workbuddy_to_codebuddy.sql +156 -0
- package/migrations/lite-sqlite3/0044_add_models_warning_metadata.sql +11 -0
- package/migrations/lite-sqlite3/0045_migrate_workbuddy_to_codebuddy.sql +156 -0
- package/package.json +1 -1
- package/src/boot/dependencies.ts +11 -3
- package/src/config/cooldowns.ts +1 -1
- package/src/config/spec.ts +0 -6
- package/src/console/api-keys/routes.ts +11 -4
- package/src/console/console-router.ts +7 -0
- package/src/console/dashboard-assets.ts +5 -5
- package/src/console/domain-registration.ts +27 -0
- package/src/console/ip-bans/routes.ts +99 -0
- package/src/console/providers/catalog/catalog-projections.ts +5 -2
- package/src/console/providers/catalog/contracts.ts +123 -0
- package/src/console/providers/catalog/model-operations.ts +122 -10
- package/src/console/providers/catalog/provider-operations.ts +116 -8
- package/src/console/providers/catalog/public-model-store.ts +0 -0
- package/src/console/providers/catalog/routes.ts +64 -4
- package/src/console/providers/catalog/store-helpers.ts +30 -1
- package/src/console/providers/catalog/store.ts +243 -3
- package/src/console/quota/account-quota-global.ts +89 -1
- package/src/console/quota/native-identity.ts +2 -0
- package/src/console/settings/contracts.ts +18 -0
- package/src/console/settings/store.ts +32 -0
- package/src/console/system-prompt/contracts.ts +0 -1
- package/src/main.ts +1 -0
- package/src/observability/event-query.ts +18 -4
- package/src/persistence/dialect.ts +12 -0
- package/src/persistence/schema.ts +20 -2
- package/src/protocol/dsml.ts +1 -1
- package/src/protocol/gateway-error.ts +1 -0
- package/src/protocol/reasoning.ts +1 -1
- package/src/protocol/request/chat.ts +4 -4
- package/src/protocol/request/messages.ts +1 -1
- package/src/protocol/response/gemini.ts +6 -1
- package/src/protocol/sse-decoder.ts +25 -8
- package/src/protocol/stream-error-frames.ts +13 -3
- package/src/protocol/translation/quirks.ts +1 -1
- package/src/protocol/translation/tool-repair.ts +2 -2
- package/src/protocol/upstream/send-claude-messages.ts +15 -4
- package/src/protocol/upstream-parsing.ts +1 -1
- package/src/providers/adapters/compatible-adapter.ts +7 -5
- package/src/providers/authentication/oauth-refresh-service.ts +149 -36
- package/src/providers/default-registry.ts +68 -3
- package/src/providers/discovery/discovery-types.ts +12 -0
- package/src/providers/discovery/probe-phases.ts +61 -30
- package/src/providers/discovery/probing-service.ts +279 -164
- package/src/providers/integrations/antigravity/antigravity-protocol.ts +117 -2
- package/src/providers/integrations/antigravity/antigravity.ts +13 -2
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +72 -34
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +18 -18
- package/src/providers/integrations/buddy/buddy-checkin.ts +17 -39
- package/src/providers/integrations/buddy/buddy-conversation-headers.ts +2 -2
- package/src/providers/integrations/buddy/buddy-discovery-shared.ts +5 -5
- package/src/providers/integrations/buddy/buddy-identity.ts +70 -0
- package/src/providers/integrations/buddy/buddy-media.ts +4 -5
- package/src/providers/integrations/buddy/buddy-oauth-shared.ts +2 -2
- package/src/providers/integrations/buddy/buddy-quota-shared.ts +1 -1
- package/src/providers/integrations/buddy/buddy-usage-shared.ts +1 -3
- package/src/providers/integrations/buddy/capabilities.ts +4 -41
- package/src/providers/integrations/buddy/codebuddy/cn-catalog.ts +2 -1
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +20 -1
- package/src/providers/integrations/buddy/codebuddy/provider.ts +2 -2
- package/src/providers/integrations/buddy/codebuddy/shared.ts +6 -10
- package/src/providers/integrations/cursor/cursor-catalog.ts +2 -0
- package/src/providers/integrations/cursor/cursor-exec.ts +738 -0
- package/src/providers/integrations/cursor/cursor-http2.ts +2 -0
- package/src/providers/integrations/cursor/cursor-request.ts +9 -8
- package/src/providers/integrations/cursor/cursor-shared.ts +19 -1
- package/src/providers/integrations/cursor/cursor.ts +50 -30
- package/src/providers/integrations/cursor/protocol/tool-canonical.ts +26 -100
- package/src/providers/integrations/devin/devin-auth.ts +353 -0
- package/src/providers/integrations/devin/devin-catalog.ts +207 -0
- package/src/providers/integrations/devin/devin-http.ts +91 -0
- package/src/providers/integrations/devin/devin-quota.ts +214 -0
- package/src/providers/integrations/devin/devin-shared.ts +111 -0
- package/src/providers/integrations/devin/devin.ts +539 -0
- package/src/providers/integrations/devin/protocol/devin-proto.ts +584 -0
- package/src/providers/integrations/devin/protocol/framing.ts +124 -0
- package/src/providers/integrations/factory/factory.ts +2 -2
- package/src/providers/integrations/freepi/freepi-catalog.ts +60 -0
- package/src/providers/integrations/freepi/freepi-discovery.ts +82 -0
- package/src/providers/integrations/freepi/freepi-headers.ts +21 -0
- package/src/providers/integrations/freepi/freepi-oauth.ts +142 -0
- package/src/providers/integrations/freepi/freepi-protocol.ts +242 -0
- package/src/providers/integrations/freepi/freepi-quota.ts +126 -0
- package/src/providers/integrations/freepi/freepi-realm.ts +35 -0
- package/src/providers/integrations/freepi/freepi.ts +292 -0
- package/src/providers/integrations/gemini.ts +2 -2
- package/src/providers/integrations/hermes/hermes-oauth.ts +94 -0
- package/src/providers/integrations/hermes.ts +4 -12
- package/src/providers/integrations/opencode/fingerprint.ts +1 -1
- package/src/providers/integrations/perch/perch-catalog.ts +105 -0
- package/src/providers/integrations/perch/perch-oauth.ts +170 -0
- package/src/providers/integrations/perch/perch-protocol.ts +211 -0
- package/src/providers/integrations/perch/perch-quota.ts +137 -0
- package/src/providers/integrations/perch/perch-realm.ts +82 -0
- package/src/providers/integrations/perch/perch-system-prompt.ts +13 -0
- package/src/providers/integrations/perch/perch.ts +315 -0
- package/src/providers/integrations/perch/saffron-system-prompt.txt +8 -0
- package/src/providers/integrations/qoder/chat-proto.ts +328 -328
- package/src/providers/integrations/qoder/claim-qoder-credits.ts +1 -1
- package/src/providers/integrations/qoder/qoder-adapter.ts +89 -28
- package/src/providers/integrations/qoder/qoder-cache.ts +32 -0
- package/src/providers/integrations/qoder/qoder-catalog.ts +6 -1
- package/src/providers/integrations/qoder/qoder-checkin.ts +2 -2
- package/src/providers/integrations/qoder/qoder-grpc.ts +209 -5
- package/src/providers/integrations/qoder/qoder-ide.ts +5 -1
- package/src/providers/integrations/qoder/qoder-identity-cache.ts +184 -0
- package/src/providers/integrations/qoder/qoder-native-identity-store.ts +83 -18
- package/src/providers/integrations/qoder/qoder-realm.ts +9 -6
- package/src/providers/integrations/qoder/qoder-umid.ts +109 -342
- package/src/providers/integrations/qoder/qoder-virtual.ts +33 -1
- package/src/providers/integrations/qoder/qoder.ts +3 -6
- package/src/providers/integrations/trae/trae-catalog.ts +9 -14
- package/src/providers/integrations/trae/trae-headers.ts +36 -11
- package/src/providers/integrations/trae/trae-oauth.ts +14 -17
- package/src/providers/integrations/trae/trae-protocol.ts +3 -6
- package/src/providers/integrations/trae/trae-quota.ts +103 -21
- package/src/providers/integrations/trae/trae-realm.ts +36 -15
- package/src/providers/integrations/trae/trae.ts +97 -7
- package/src/providers/operations/account-error-classification.ts +66 -1
- package/src/providers/operations/account-health-service.ts +192 -26
- package/src/providers/operations/account-refresh-status.ts +284 -0
- package/src/providers/operations/account-tier.ts +67 -0
- package/src/providers/operations/byok-wire-profile.ts +9 -12
- package/src/providers/operations/client-versions.ts +37 -99
- package/src/providers/operations/cooldown-rules.ts +61 -0
- package/src/providers/operations/provider-catalog-seeder.ts +4 -0
- package/src/providers/provider-contracts.ts +29 -0
- package/src/providers/provider-metadata.ts +59 -4
- package/src/providers/provider-model-definition.ts +36 -0
- package/src/providers/quota/refresh.ts +21 -0
- package/src/security/abuse.ts +71 -0
- package/src/transport/dispatch/proxy-request.ts +1 -0
- package/src/transport/dispatch/streaming/stream.ts +1 -0
- package/src/transport/dispatch/upstream.ts +4 -1
- package/src/transport/failure-policy.ts +113 -7
- package/src/transport/routing/router.ts +25 -1
- package/src/transport/surface/messages/adapter.ts +2 -1
- package/src/transport/surface/responses/encode.ts +12 -1
- package/src/workers/daily-checkin.ts +1 -1
- package/src/workers/quota-refresh-sweep.ts +1 -1
- package/src/workers/scheduler.ts +22 -4
- package/dist/dashboard/assets/BannedPage-B05aF8Dg.js +0 -1
- package/dist/dashboard/assets/BannedPage-B05aF8Dg.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-CLUhmjUy.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-CQmrqqrk.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-CHG_1Wr3.js +0 -1
- package/dist/dashboard/assets/CombosPage-CHG_1Wr3.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-DPgbklad.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-DPgbklad.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-pnfAqr_-.js +0 -1
- package/dist/dashboard/assets/CustomizationPage-pnfAqr_-.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-DGJuU2A6.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-DGJuU2A6.js.gz +0 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-C-e2AMz6.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-J8wPbmfT.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-C6WlpU5E.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-BSQnF2Lp.js +0 -1
- package/dist/dashboard/assets/OverviewPage-BSQnF2Lp.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-DK_e0FJz.js +0 -7
- package/dist/dashboard/assets/ProviderDetailPage-DK_e0FJz.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js +0 -1
- package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-D_a3r6Gc.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-D_a3r6Gc.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-BBTRBAQ3.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-B2WqMSG1.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-D7xp5Ij_.js +0 -1
- package/dist/dashboard/assets/SettingsPage-D7xp5Ij_.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-LND6_Ss7.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-BzNnm6Bi.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-C1TbL24N.js +0 -56
- package/dist/dashboard/assets/UsagePage-C1TbL24N.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-KvX83mRe.js +0 -1
- package/dist/dashboard/assets/api-keys-KvX83mRe.js.gz +0 -0
- package/dist/dashboard/assets/app-mweRcsKp.css +0 -2
- package/dist/dashboard/assets/app-mweRcsKp.css.gz +0 -0
- package/dist/dashboard/assets/assert-CidQVoNo.js +0 -1
- package/dist/dashboard/assets/assert-CidQVoNo.js.gz +0 -0
- package/dist/dashboard/assets/badge-BaX2GTrn.js.gz +0 -0
- package/dist/dashboard/assets/banner-DFH4Bkte.js.gz +0 -0
- package/dist/dashboard/assets/brand/bansos_page.png +0 -0
- package/dist/dashboard/assets/brand/denia_bansos.jpg +0 -0
- package/dist/dashboard/assets/brand/favicon.jpg +0 -0
- package/dist/dashboard/assets/brand/login_register.jpg +0 -0
- package/dist/dashboard/assets/brand/login_register_initial.jpg +0 -0
- package/dist/dashboard/assets/brand/og_bansos.jpg +0 -0
- package/dist/dashboard/assets/brand/og_image.jpg +0 -0
- package/dist/dashboard/assets/brand/sidebar_ico.jpg +0 -0
- package/dist/dashboard/assets/card-CxDw0lK6.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js +0 -1
- package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-DfS1ntiq.js.gz +0 -0
- package/dist/dashboard/assets/dialog-BK-NRr5u.js.gz +0 -0
- package/dist/dashboard/assets/drawer-QqPul6sC.js.gz +0 -0
- package/dist/dashboard/assets/entry-BMlYJVFj.js.gz +0 -0
- package/dist/dashboard/assets/entry-Dmx7gBiN.js +0 -1
- package/dist/dashboard/assets/entry-Dmx7gBiN.js.gz +0 -0
- package/dist/dashboard/assets/entry-vqGb8yVz.js +0 -4
- package/dist/dashboard/assets/entry-vqGb8yVz.js.gz +0 -0
- package/dist/dashboard/assets/formatters-DP-5E01-.js.gz +0 -0
- package/dist/dashboard/assets/index-D36vCZht.js.gz +0 -0
- package/dist/dashboard/assets/inline-CHJQwxLa.js.gz +0 -0
- package/dist/dashboard/assets/input-BlmlizVV.js.gz +0 -0
- package/dist/dashboard/assets/layout-Bz93I-yE.js.gz +0 -0
- package/dist/dashboard/assets/list-row-Ml16KCfu.js.gz +0 -0
- package/dist/dashboard/assets/live-7_QpnYGu.js.gz +0 -0
- package/dist/dashboard/assets/minimize-2-BTmMTK4o.js +0 -1
- package/dist/dashboard/assets/minimize-2-BTmMTK4o.js.gz +0 -0
- package/dist/dashboard/assets/mutation-GU7XdEjz.js.gz +0 -0
- package/dist/dashboard/assets/network-CuMDaTzT.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CoqpaDMx.js.gz +0 -0
- package/dist/dashboard/assets/pagination-B5aOoweZ.js.gz +0 -0
- package/dist/dashboard/assets/query-keys-YSoQOUh6.js.gz +0 -0
- package/dist/dashboard/assets/routing-fnCsxgNO.js +0 -1
- package/dist/dashboard/assets/routing-fnCsxgNO.js.gz +0 -0
- package/dist/dashboard/assets/select-C9Ssle9b.js.gz +0 -0
- package/dist/dashboard/assets/settings-BxslsErn.js +0 -1
- package/dist/dashboard/assets/settings-BxslsErn.js.gz +0 -0
- package/dist/dashboard/assets/stack-j7cXjgYX.js.gz +0 -0
- package/dist/dashboard/assets/state-DHmEnLa2.js.gz +0 -0
- package/dist/dashboard/assets/switch-DmZcyTIC.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-CbCP4w1o.js.gz +0 -0
- package/dist/dashboard/console-backgrounds.jpg +0 -0
- package/dist/dashboard/console-backgrounds_initial.jpg +0 -0
- package/dist/dashboard/donation/qris-risun-marke.png +0 -0
- package/src/providers/integrations/buddy/turing-device-token.ts +0 -262
- package/src/providers/integrations/buddy/workbuddy/cn-oauth.ts +0 -30
- package/src/providers/integrations/buddy/workbuddy/cn-provider.ts +0 -58
- package/src/providers/integrations/buddy/workbuddy/oauth.ts +0 -31
- package/src/providers/integrations/buddy/workbuddy/provider.ts +0 -209
- package/src/providers/integrations/buddy/workbuddy/quota.ts +0 -161
- package/src/providers/integrations/buddy/workbuddy/shared.ts +0 -285
- /package/dist/dashboard/assets/{app-DRnQLhsc.js → app-B7kIWFm5.js} +0 -0
- /package/dist/dashboard/assets/{app-DRnQLhsc.js.gz → app-B7kIWFm5.js.gz} +0 -0
|
@@ -1,398 +1,165 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Qoder
|
|
2
|
+
* Qoder OS-derived machine identity — donor-style deterministic derivation.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* a deterministic generated fallback when no bridge is available.
|
|
4
|
+
* The vendor bridge (runtime-info / umidpack) is no longer vendored or
|
|
5
|
+
* executed. This module derives the machine identity with the same *shape*
|
|
6
|
+
* and *derivation pattern* as the donor hub's fingerprint module:
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* mint = wipe → run → capture seed+token; replay = write stored seed → run.
|
|
15
|
-
* Verified cycle (umidpack ELF under WSL): mint A, mint B (distinct),
|
|
16
|
-
* replay A ✓, replay B ✓, replay A again ✓.
|
|
8
|
+
* - `derive_id(uid, salt)` → a UUIDv4-shaped id (version nibble `4`,
|
|
9
|
+
* variant nibble `a`), stable per (uid, salt).
|
|
10
|
+
* - `derive_machine_token(uid)` → a base64url-looking 43-char token
|
|
11
|
+
* (sha512-derived).
|
|
12
|
+
* - `derive_machine_type(uid)` → 18 hex chars.
|
|
17
13
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* flock serialization; the bridge binary is staged into /tmp once.
|
|
14
|
+
* The donor salted with the account uid alone. We salt with the **OS
|
|
15
|
+
* fingerprint + account uid** instead: the fingerprint keeps the identity
|
|
16
|
+
* host-stable (one machine = one base), and the uid keeps accounts
|
|
17
|
+
* isolated on the same host — the same collision-avoidance property the
|
|
18
|
+
* native bridge had (per-machine hardware identity, but per-account seeds).
|
|
24
19
|
*
|
|
25
|
-
* The
|
|
26
|
-
*
|
|
27
|
-
* controls showed that machine identity does not gate daily CREDITS grants.
|
|
28
|
-
*
|
|
29
|
-
* Bridge CLI (donor-verified):
|
|
30
|
-
* linux : runtime-info <env>
|
|
31
|
-
* darwin: printf '{"account":"<uid>"}\n' | runtime-info <env> --account-stdin
|
|
32
|
-
* win32 : runtime-info.exe <env> [--account-stdin]
|
|
20
|
+
* The result is deterministic, offline, and never touches the network. It is
|
|
21
|
+
* not an Alibaba SG-signed token — it is a spoofed native-shaped identity.
|
|
33
22
|
*/
|
|
34
|
-
import { spawnSync } from "node:child_process";
|
|
35
23
|
import { createHash } from "node:crypto";
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
|
|
39
|
-
|
|
24
|
+
import { readFileSync } from "node:fs";
|
|
25
|
+
import {
|
|
26
|
+
arch as osArch,
|
|
27
|
+
cpus,
|
|
28
|
+
hostname,
|
|
29
|
+
platform as osPlatform,
|
|
30
|
+
release as osRelease,
|
|
31
|
+
totalmem,
|
|
32
|
+
userInfo,
|
|
33
|
+
} from "node:os";
|
|
40
34
|
import { qoderMachineHostname, qoderMachineOs } from "../../operations/cli-platform";
|
|
41
35
|
|
|
42
|
-
/**
|
|
43
|
-
const ENV_CODE = "3";
|
|
44
|
-
|
|
45
|
-
/** One native identity sample (same shape the bridge prints). */
|
|
36
|
+
/** One machine identity sample (same shape the bridge printed). */
|
|
46
37
|
export interface QoderNativeIdentity {
|
|
47
38
|
readonly machineToken: string;
|
|
48
39
|
readonly machineType: string;
|
|
49
40
|
readonly machineCode: string;
|
|
50
41
|
readonly isVm: boolean;
|
|
51
|
-
readonly source: "runtime-info" | "generated";
|
|
42
|
+
readonly source: "runtime-info" | "generated" | "os";
|
|
52
43
|
}
|
|
53
44
|
|
|
54
|
-
/**
|
|
55
|
-
const TOKEN_PAYLOAD_LENGTH = 84;
|
|
56
|
-
/** Hex length of machineType / machineCode in the bridge's output. */
|
|
45
|
+
/** Hex length of machineType / machineCode (donor `derive_id` output, dashes stripped). */
|
|
57
46
|
const MACHINE_TYPE_LENGTH = 18;
|
|
58
47
|
const MACHINE_CODE_LENGTH = 18;
|
|
48
|
+
/** base64url token length after the sha512 digest (donor `derive_machine_token`). */
|
|
49
|
+
const MACHINE_TOKEN_LENGTH = 43;
|
|
59
50
|
|
|
60
|
-
/**
|
|
61
|
-
|
|
62
|
-
return join(process.cwd(), "vendor", "qoder-umid", "umidpack");
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** The vendored mini-ELF tarball (static glibc bundle for containers). */
|
|
66
|
-
export function umidMiniTarball(): string {
|
|
67
|
-
return join(process.cwd(), "vendor", "qoder-umid", "qoder-umid-mini.tar.gz");
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Staging directory for the extracted mini-ELF bundle. Uses a per-user cache
|
|
72
|
-
* dir (respecting `XDG_CACHE_HOME` on Linux) so a container does not need to
|
|
73
|
-
* carry the extracted tree, and the repo stays clean.
|
|
74
|
-
*/
|
|
75
|
-
export function umidMiniDir(): string {
|
|
76
|
-
const base = process.env.XDG_CACHE_HOME?.trim() || join(process.env.HOME ?? tmpdir(), ".cache");
|
|
77
|
-
return join(base, "cartethyia", "umid-mini");
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
let miniExtracted = false;
|
|
81
|
-
|
|
82
|
-
/** Extracts `qoder-umid-mini.tar.gz` once into {@link umidMiniDir}. */
|
|
83
|
-
export function ensureUmidMiniExtracted(): boolean {
|
|
84
|
-
const tar = umidMiniTarball();
|
|
85
|
-
const out = umidMiniDir();
|
|
86
|
-
if (!existsSync(tar)) return false;
|
|
87
|
-
if (existsSync(join(out, "opt", "umid", "runtime-info")) && miniExtracted) return true;
|
|
51
|
+
/** Reads a file if it exists, trimming whitespace; empty string otherwise. */
|
|
52
|
+
function readTrimmed(path: string): string {
|
|
88
53
|
try {
|
|
89
|
-
|
|
90
|
-
// Re-extract on empty/missing target only; leave existing tree in place.
|
|
91
|
-
if (!existsSync(join(out, "opt", "umid", "runtime-info"))) {
|
|
92
|
-
const r = spawnSync("tar", ["-xzf", tar, "-C", out], { encoding: "utf8", timeout: 30_000 });
|
|
93
|
-
if (r.status !== 0) {
|
|
94
|
-
log.warn(`[qoder] umid mini extract failed: ${String(r.stderr ?? "").slice(0, 300)}`);
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
const bin = join(out, "opt", "umid", "runtime-info");
|
|
99
|
-
if (existsSync(bin)) chmodSync(bin, 0o755);
|
|
100
|
-
miniExtracted = true;
|
|
101
|
-
return true;
|
|
102
|
-
} catch (error) {
|
|
103
|
-
log.warn("[qoder] umid mini extract error", error as Error);
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/** WSL-side staging/seed paths for the Linux bridge on a Windows host. */
|
|
109
|
-
const WSL_BIN = "/tmp/umidpack/runtime-info";
|
|
110
|
-
const WSL_SEED = "/home/risun/.config/.locale_cfg";
|
|
111
|
-
const WSL_LOCK = "/tmp/umidpack/bridge.lock";
|
|
112
|
-
|
|
113
|
-
type Bridge = { kind: "elf" | "macho" | "pe" | "wsl-elf" | "mini-elf" };
|
|
114
|
-
|
|
115
|
-
/** True when this process runs inside a container (Docker/Podman). */
|
|
116
|
-
function isContainerized(): boolean {
|
|
117
|
-
if (existsSync(join("/", ".dockerenv")) || existsSync(join("/", ".containerenv"))) return true;
|
|
118
|
-
try {
|
|
119
|
-
const cgroup = readFileSync("/proc/1/cgroup", "utf8");
|
|
120
|
-
return /(?:docker|containerd|podman|kubepods)/i.test(cgroup);
|
|
54
|
+
return readFileSync(path, "utf8").trim();
|
|
121
55
|
} catch {
|
|
122
|
-
return
|
|
56
|
+
return "";
|
|
123
57
|
}
|
|
124
58
|
}
|
|
125
59
|
|
|
126
|
-
/**
|
|
127
|
-
function
|
|
128
|
-
if (process.platform === "
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const dll = join(umidpackDir(), "sgsdk.dll");
|
|
135
|
-
if (existsSync(exe) && existsSync(dll)) return { kind: "pe" };
|
|
136
|
-
// Windows has no native mini-ELF runner; WSL may still be present.
|
|
137
|
-
return ensureUmidMiniExtracted() ? { kind: "wsl-elf" } : null;
|
|
138
|
-
}
|
|
139
|
-
if (process.platform === "darwin") {
|
|
140
|
-
const arch = process.arch === "arm64" ? "macho-arm64" : "macho-x86_64";
|
|
141
|
-
// Prefer the re-signed adhoc `.clean` binary (DYLD-spoofable); the stock
|
|
142
|
-
// vendored binary is Hardened Runtime and ignores DYLD_INSERT_LIBRARIES.
|
|
143
|
-
const clean = join(umidpackDir(), arch, "runtime-info.clean");
|
|
144
|
-
if (existsSync(clean)) return { kind: "macho" };
|
|
145
|
-
return existsSync(join(umidpackDir(), arch, "runtime-info")) ? { kind: "macho" } : null;
|
|
146
|
-
}
|
|
147
|
-
// Linux. Containers (Docker/K8s/Podman) prefer the mini-ELF bundle: it ships
|
|
148
|
-
// a static glibc tree and mints tokens with `isVm:false`, so a containerized
|
|
149
|
-
// deployment is not flagged as a VM. Set CARTETHYIA_QODER_UMID_MINI=1 to
|
|
150
|
-
// force it on any Linux host, or =0 to disable container detection.
|
|
151
|
-
const miniForced = process.env.CARTETHYIA_QODER_UMID_MINI;
|
|
152
|
-
const wantMini =
|
|
153
|
-
miniForced === "1" || (miniForced !== "0" && isContainerized());
|
|
154
|
-
if (wantMini && process.arch === "x64" && ensureUmidMiniExtracted()) {
|
|
155
|
-
return { kind: "mini-elf" };
|
|
60
|
+
/** Best-effort machine id per platform (empty when unavailable without a spawn). */
|
|
61
|
+
function machineId(): string {
|
|
62
|
+
if (process.platform === "linux") {
|
|
63
|
+
return (
|
|
64
|
+
readTrimmed("/etc/machine-id") ||
|
|
65
|
+
readTrimmed("/var/lib/dbus/machine-id") ||
|
|
66
|
+
readTrimmed("/sys/class/dmi/id/product_uuid")
|
|
67
|
+
);
|
|
156
68
|
}
|
|
157
|
-
|
|
158
|
-
if (existsSync(join(umidpackDir(), arch, "runtime-info"))) return { kind: "elf" };
|
|
159
|
-
if (existsSync(join(umidpackDir(), "elf-x86_64", "runtime-info"))) return { kind: "elf" };
|
|
160
|
-
// Linux without a native vendored ELF (e.g. a slim container with no mini):
|
|
161
|
-
// fall back to the mini-ELF bundle when it extracts.
|
|
162
|
-
if (ensureUmidMiniExtracted() && process.arch === "x64") return { kind: "mini-elf" };
|
|
163
|
-
return null;
|
|
69
|
+
return "";
|
|
164
70
|
}
|
|
165
71
|
|
|
166
|
-
/**
|
|
167
|
-
export function
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
72
|
+
/** Collects a stable, host-unique fingerprint string (the salt base). */
|
|
73
|
+
export function collectOsFingerprint(): string {
|
|
74
|
+
const parts: string[] = [
|
|
75
|
+
hostname(),
|
|
76
|
+
osPlatform(),
|
|
77
|
+
osArch(),
|
|
78
|
+
osRelease(),
|
|
79
|
+
String(cpus().length),
|
|
80
|
+
String(Math.floor(totalmem() / (1024 * 1024))),
|
|
81
|
+
qoderMachineOs(),
|
|
82
|
+
qoderMachineHostname(),
|
|
83
|
+
];
|
|
84
|
+
const mid = machineId();
|
|
85
|
+
if (mid) parts.push(mid);
|
|
86
|
+
const user = userInfo().username;
|
|
87
|
+
if (user) parts.push(user);
|
|
88
|
+
return parts.join("\n");
|
|
178
89
|
}
|
|
179
90
|
|
|
180
|
-
/**
|
|
181
|
-
function
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const machineType = String(rec.machineType ?? "").trim();
|
|
188
|
-
const machineCode = String(rec.machineCode ?? "").trim();
|
|
189
|
-
if (!machineToken || !machineType || !machineCode) return null;
|
|
190
|
-
const vmInfo = rec.vmInfo;
|
|
191
|
-
const isVm = typeof vmInfo === "object" && vmInfo !== null && (vmInfo as Record<string, unknown>).isVm === true;
|
|
192
|
-
return { machineToken, machineType, machineCode, isVm, source: "runtime-info" };
|
|
193
|
-
} catch {
|
|
194
|
-
return null;
|
|
195
|
-
}
|
|
91
|
+
/** Donor `derive_id`: md5(salt:uid) → UUIDv4-shaped id (version 4, variant a). */
|
|
92
|
+
function deriveId(uid: string, salt: string): string {
|
|
93
|
+
const seed = `${salt}:${uid || "anonymous"}`;
|
|
94
|
+
let h = createHash("md5").update(seed).digest("hex");
|
|
95
|
+
// Force the UUIDv4 version (13th nibble) and variant (17th nibble).
|
|
96
|
+
h = h.slice(0, 12) + "4" + h.slice(13, 16) + "a" + h.slice(17);
|
|
97
|
+
return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20, 32)}`;
|
|
196
98
|
}
|
|
197
99
|
|
|
198
|
-
/**
|
|
199
|
-
function
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
const wslSrc = drive ? `/mnt/${drive[1]!.toLowerCase()}${src.slice(2)}` : src;
|
|
203
|
-
wsl(
|
|
204
|
-
`mkdir -p /tmp/umidpack && cp "${wslSrc}" ${WSL_BIN} && chmod +x ${WSL_BIN} && ` +
|
|
205
|
-
`mkdir -p $(dirname ${WSL_SEED})`,
|
|
206
|
-
);
|
|
100
|
+
/** Donor `derive_machine_token`: sha512 → base64url, 43 chars. */
|
|
101
|
+
function deriveMachineToken(uid: string, salt: string): string {
|
|
102
|
+
const raw = createHash("sha512").update(`machinetoken:${salt}:${uid}`).digest();
|
|
103
|
+
return raw.toString("base64url").slice(0, MACHINE_TOKEN_LENGTH);
|
|
207
104
|
}
|
|
208
105
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
return
|
|
106
|
+
/** Donor `derive_machine_type`: derive_id without dashes, 18 chars. */
|
|
107
|
+
function deriveMachineType(uid: string, salt: string): string {
|
|
108
|
+
return deriveId(uid, `machinetype:${salt}`).replaceAll("-", "").slice(0, MACHINE_TYPE_LENGTH);
|
|
212
109
|
}
|
|
213
110
|
|
|
214
111
|
/**
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
* nothing else in the delivery path sets it — a Docker image or a fresh clone
|
|
218
|
-
* on Linux/macOS would otherwise fail to spawn them (EACCES -> "[qoder] elf
|
|
219
|
-
* mint failed"). Idempotent; if it cannot set the bit, `spawnSync` reports
|
|
220
|
-
* the real failure as before.
|
|
112
|
+
* Derives a machine identity for one account from the host OS fingerprint +
|
|
113
|
+
* account uid. Deterministic: same host + same account → same identity.
|
|
221
114
|
*/
|
|
222
|
-
export function
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
115
|
+
export function mintQoderOsIdentity(accountId: string): QoderNativeIdentity {
|
|
116
|
+
const salt = collectOsFingerprint();
|
|
117
|
+
const uid = accountId || "anonymous";
|
|
118
|
+
return {
|
|
119
|
+
machineToken: deriveMachineToken(uid, salt),
|
|
120
|
+
machineType: deriveMachineType(uid, salt),
|
|
121
|
+
machineCode: deriveId(uid, `machinecode:${salt}`).replaceAll("-", "").slice(0, MACHINE_CODE_LENGTH),
|
|
122
|
+
isVm: false,
|
|
123
|
+
source: "os",
|
|
124
|
+
};
|
|
228
125
|
}
|
|
229
126
|
|
|
230
|
-
/**
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
if (process.platform === "win32") return WSL_SEED;
|
|
234
|
-
const home = process.env.HOME ?? "";
|
|
235
|
-
return join(home, ".config", ".locale_cfg");
|
|
127
|
+
/** Legacy alias retained for callers that still import the generated mint. */
|
|
128
|
+
export function mintQoderGeneratedIdentity(accountId: string): QoderNativeIdentity {
|
|
129
|
+
return mintQoderOsIdentity(accountId);
|
|
236
130
|
}
|
|
237
131
|
|
|
238
|
-
/**
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
* for later replay of this same native identity. Returns `null` when the
|
|
242
|
-
* bridge fails; falls back to the generated identity only when no bridge
|
|
243
|
-
* exists.
|
|
244
|
-
*/
|
|
245
|
-
export function mintQoderNativeIdentity(accountId: string): { identity: QoderNativeIdentity; seed: string } | null {
|
|
246
|
-
const bridge = pickBridge();
|
|
247
|
-
if (!bridge) {
|
|
248
|
-
log.warn("[qoder] no native bridge for this host — using generated identity fallback");
|
|
249
|
-
return { identity: mintQoderGeneratedIdentity(accountId), seed: "" };
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
if (bridge.kind === "wsl-elf") {
|
|
253
|
-
ensureWslStaged();
|
|
254
|
-
const out = wsl(
|
|
255
|
-
`exec 9>${WSL_LOCK}; flock 9; rm -f ${WSL_SEED}; ${WSL_BIN} ${ENV_CODE}`,
|
|
256
|
-
);
|
|
257
|
-
const identity = parseBridgeLine(out);
|
|
258
|
-
if (!identity) { log.warn("[qoder] wsl mint failed"); return null; }
|
|
259
|
-
const seed = wsl(`cat ${WSL_SEED}`);
|
|
260
|
-
return { identity, seed };
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
if (bridge.kind === "elf") {
|
|
264
|
-
const exe = join(umidpackDir(), process.arch === "arm64" ? "elf-aarch64" : "elf-x86_64", "runtime-info");
|
|
265
|
-
ensurePosixExecutable(exe);
|
|
266
|
-
const seed = seedPath();
|
|
267
|
-
const dir = seed.slice(0, seed.lastIndexOf("/"));
|
|
268
|
-
mkdirSync(dir, { recursive: true });
|
|
269
|
-
try { spawnSync("rm", ["-f", seed]); } catch { /* ignore */ }
|
|
270
|
-
const r = spawnSync(exe, [ENV_CODE], { encoding: "utf8", timeout: 25_000 });
|
|
271
|
-
const identity = parseBridgeLine(String(r.stdout ?? ""));
|
|
272
|
-
if (!identity) { log.warn("[qoder] elf mint failed"); return null; }
|
|
273
|
-
return { identity, seed: existsSync(seed) ? readFileSync(seed, "utf8") : "" };
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
if (bridge.kind === "macho") {
|
|
277
|
-
const arch = process.arch === "arm64" ? "macho-arm64" : "macho-x86_64";
|
|
278
|
-
const exe = join(umidpackDir(), arch, "runtime-info");
|
|
279
|
-
ensurePosixExecutable(exe);
|
|
280
|
-
const seed = seedPath();
|
|
281
|
-
const dir = seed.slice(0, seed.lastIndexOf("/"));
|
|
282
|
-
mkdirSync(dir, { recursive: true });
|
|
283
|
-
try { spawnSync("rm", ["-f", seed]); } catch { /* ignore */ }
|
|
284
|
-
const r = spawnSync(exe, [ENV_CODE, "--account-stdin"], {
|
|
285
|
-
input: `${JSON.stringify({ account: accountId })}\n`,
|
|
286
|
-
encoding: "utf8",
|
|
287
|
-
timeout: 25_000,
|
|
288
|
-
});
|
|
289
|
-
const identity = parseBridgeLine(String(r.stdout ?? ""));
|
|
290
|
-
if (!identity) { log.warn("[qoder] macho mint failed"); return null; }
|
|
291
|
-
return { identity, seed: existsSync(seed) ? readFileSync(seed, "utf8") : "" };
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
if (bridge.kind === "mini-elf") {
|
|
295
|
-
const exe = join(umidMiniDir(), "opt", "umid", "runtime-info");
|
|
296
|
-
ensurePosixExecutable(exe);
|
|
297
|
-
const seed = seedPath();
|
|
298
|
-
const dir = seed.slice(0, seed.lastIndexOf("/"));
|
|
299
|
-
mkdirSync(dir, { recursive: true });
|
|
300
|
-
try { spawnSync("rm", ["-f", seed]); } catch { /* ignore */ }
|
|
301
|
-
const r = spawnSync(exe, [ENV_CODE], {
|
|
302
|
-
encoding: "utf8",
|
|
303
|
-
timeout: 25_000,
|
|
304
|
-
env: { ...process.env, LD_LIBRARY_PATH: join(umidMiniDir(), "lib", "x86_64-linux-gnu") },
|
|
305
|
-
});
|
|
306
|
-
const identity = parseBridgeLine(String(r.stdout ?? ""));
|
|
307
|
-
if (!identity) { log.warn("[qoder] mini-elf mint failed"); return null; }
|
|
308
|
-
return { identity, seed: existsSync(seed) ? readFileSync(seed, "utf8") : "" };
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
// pe — hardware-bound; no seed concept on Windows.
|
|
312
|
-
const exe = join(umidpackDir(), "runtime-info.exe");
|
|
313
|
-
const r = spawnSync(exe, [ENV_CODE], { encoding: "utf8", timeout: 30_000, windowsHide: true, cwd: umidpackDir() });
|
|
314
|
-
const identity = parseBridgeLine(String(r.stdout ?? ""));
|
|
315
|
-
if (!identity) { log.warn("[qoder] pe mint failed"); return null; }
|
|
316
|
-
return { identity, seed: "" };
|
|
132
|
+
/** No bridge exists anymore; the OS mint is the only path. */
|
|
133
|
+
export function mintQoderNativeIdentity(accountId = ""): QoderNativeIdentity {
|
|
134
|
+
return mintQoderOsIdentity(accountId);
|
|
317
135
|
}
|
|
318
136
|
|
|
319
|
-
/**
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
* matches the stored record. Returns `null` when no seed is available, the
|
|
323
|
-
* host cannot replay (Windows exe), or the bridge failed.
|
|
324
|
-
*/
|
|
325
|
-
export function replayQoderNativeIdentity(seed: string, accountId: string): QoderNativeIdentity | null {
|
|
326
|
-
if (!seed) return null;
|
|
327
|
-
const bridge = pickBridge();
|
|
328
|
-
if (!bridge) return null;
|
|
329
|
-
|
|
330
|
-
if (bridge.kind === "wsl-elf") {
|
|
331
|
-
ensureWslStaged();
|
|
332
|
-
const quoted = seed.replace(/'/g, `'\\''`);
|
|
333
|
-
const out = wsl(
|
|
334
|
-
`exec 9>${WSL_LOCK}; flock 9; printf '%s' '${quoted}' > ${WSL_SEED}; ${WSL_BIN} ${ENV_CODE}`,
|
|
335
|
-
);
|
|
336
|
-
return parseBridgeLine(out);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
if (bridge.kind === "elf") {
|
|
340
|
-
const exe = join(umidpackDir(), process.arch === "arm64" ? "elf-aarch64" : "elf-x86_64", "runtime-info");
|
|
341
|
-
ensurePosixExecutable(exe);
|
|
342
|
-
const seed = seedPath();
|
|
343
|
-
writeFileSync(seed, seed, "utf8");
|
|
344
|
-
const r = spawnSync(exe, [ENV_CODE], { encoding: "utf8", timeout: 25_000 });
|
|
345
|
-
return parseBridgeLine(String(r.stdout ?? ""));
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
if (bridge.kind === "macho") {
|
|
349
|
-
const arch = process.arch === "arm64" ? "macho-arm64" : "macho-x86_64";
|
|
350
|
-
const exe = join(umidpackDir(), arch, "runtime-info");
|
|
351
|
-
ensurePosixExecutable(exe);
|
|
352
|
-
const seedPathStr = seedPath();
|
|
353
|
-
writeFileSync(seedPathStr, seed, "utf8");
|
|
354
|
-
const r = spawnSync(exe, [ENV_CODE, "--account-stdin"], {
|
|
355
|
-
input: `${JSON.stringify({ account: accountId })}\n`,
|
|
356
|
-
encoding: "utf8",
|
|
357
|
-
timeout: 25_000,
|
|
358
|
-
});
|
|
359
|
-
return parseBridgeLine(String(r.stdout ?? ""));
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
if (bridge.kind === "mini-elf") {
|
|
363
|
-
const exe = join(umidMiniDir(), "opt", "umid", "runtime-info");
|
|
364
|
-
ensurePosixExecutable(exe);
|
|
365
|
-
const seedPathStr = seedPath();
|
|
366
|
-
writeFileSync(seedPathStr, seed, "utf8");
|
|
367
|
-
const r = spawnSync(exe, [ENV_CODE], {
|
|
368
|
-
encoding: "utf8",
|
|
369
|
-
timeout: 25_000,
|
|
370
|
-
env: { ...process.env, LD_LIBRARY_PATH: join(umidMiniDir(), "lib", "x86_64-linux-gnu") },
|
|
371
|
-
});
|
|
372
|
-
return parseBridgeLine(String(r.stdout ?? ""));
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
return null; // pe: cannot replay a seed on a hardware-bound identity
|
|
137
|
+
/** Replay is a no-op: the OS identity is deterministic and host-bound. */
|
|
138
|
+
export function replayQoderNativeIdentity(_seed: string, accountId = ""): QoderNativeIdentity | null {
|
|
139
|
+
return mintQoderOsIdentity(accountId);
|
|
376
140
|
}
|
|
377
141
|
|
|
378
142
|
/**
|
|
379
143
|
* The six native machine headers for one identity.
|
|
380
144
|
*
|
|
381
|
-
* The upstream treats `cosy-machineid` as a stable UUID-shaped machine id
|
|
382
|
-
*
|
|
383
|
-
* account
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
*
|
|
145
|
+
* The upstream treats `cosy-machineid` as a stable UUID-shaped machine id.
|
|
146
|
+
* OS-derived identities (source "os") keep the full header set — they are
|
|
147
|
+
* host-stable, per-account isolated, and shaped like the bridge output.
|
|
148
|
+
* Generated identities (source "generated") do NOT send the full set: the
|
|
149
|
+
* upstream filters the daily CREDITS campaign when a full set of derived
|
|
150
|
+
* headers appears (donor issue #10).
|
|
387
151
|
*/
|
|
388
152
|
export function qoderMachineHeaders(identity: QoderNativeIdentity, machineId?: string): Record<string, string> {
|
|
389
153
|
const mid = machineId && machineId.length > 0 ? machineId : identity.machineToken;
|
|
390
|
-
|
|
154
|
+
const headers: Record<string, string> = {
|
|
391
155
|
"cosy-machineid": mid,
|
|
392
|
-
"cosy-machinetoken": identity.machineToken,
|
|
393
|
-
"cosy-machinetype": identity.machineType,
|
|
394
|
-
"cosy-machinecode": identity.machineCode,
|
|
395
156
|
"cosy-machineos": qoderMachineOs(),
|
|
396
157
|
"cosy-machinehostname": qoderMachineHostname(),
|
|
397
158
|
};
|
|
159
|
+
if (identity.source !== "generated") {
|
|
160
|
+
headers["cosy-machinetoken"] = identity.machineToken;
|
|
161
|
+
headers["cosy-machinetype"] = identity.machineType;
|
|
162
|
+
headers["cosy-machinecode"] = identity.machineCode;
|
|
163
|
+
}
|
|
164
|
+
return headers;
|
|
398
165
|
}
|
|
@@ -10,6 +10,34 @@
|
|
|
10
10
|
// is deliberately static — Qoder publishes no endpoint that resolves a name to
|
|
11
11
|
// a slot the way Copilot's `/auto` does, so there is nothing to ask at runtime.
|
|
12
12
|
|
|
13
|
+
import type { ModelWarning } from "../../provider-model-definition";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Three provider-level caveats (D37), attached to every `qoder`/`qodercn` row —
|
|
17
|
+
* static, virtual, and discovered alike. These are deliberately statements of
|
|
18
|
+
* possibility, not per-model claims: the provider may route a slot to a
|
|
19
|
+
* different model, its cache may be unreliable, and a plan/transport decision
|
|
20
|
+
* may refuse a request. No roster row is asserted to have any of these
|
|
21
|
+
* behaviours individually.
|
|
22
|
+
*/
|
|
23
|
+
export const QODER_PROVIDER_WARNINGS: readonly ModelWarning[] = [
|
|
24
|
+
{
|
|
25
|
+
kind: "fallback_model",
|
|
26
|
+
message: "Provider may fall back to another model for this slot.",
|
|
27
|
+
severity: "warn",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
kind: "cache_reliability",
|
|
31
|
+
message: "Cache reliability may be degraded for this provider.",
|
|
32
|
+
severity: "warn",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
kind: "model_refusal",
|
|
36
|
+
message: "This provider may refuse certain model requests (plan/transport).",
|
|
37
|
+
severity: "warn",
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
|
|
13
41
|
/** A virtual id and the roster key it stands for. */
|
|
14
42
|
export interface QoderVirtualModel {
|
|
15
43
|
/** The id a caller sends and the catalog publishes. */
|
|
@@ -43,7 +71,11 @@ export const QODER_VIRTUAL_MODELS: readonly QoderVirtualModel[] = [
|
|
|
43
71
|
{ id: "cantus", target: "cmodel", displayName: "Cantus" },
|
|
44
72
|
{ id: "sonus", target: "smodel", displayName: "Sonus" },
|
|
45
73
|
{ id: "qwen3.8-max", target: "qmodel_38max", displayName: "Qwen3.8-Max" },
|
|
46
|
-
|
|
74
|
+
// `qwen3.8-flash` is the free-tier entry point over the `qfmodel` slot.
|
|
75
|
+
// Upstream's live `is_free` on this slot is a plan-tier flag rather than a
|
|
76
|
+
// zero-cost tier, so the static roster deliberately does not state it; the
|
|
77
|
+
// free badge is applied here, the same way `lite` overrides `qmodel`.
|
|
78
|
+
{ id: "qwen3.8-flash", target: "qfmodel", displayName: "Qwen3.8-Flash", free: true },
|
|
47
79
|
{ id: "qwen3.7-max", target: "qmodel_latest", displayName: "Qwen3.7-Max" },
|
|
48
80
|
{ id: "qwen3.7-plus", target: "qmodel", displayName: "Qwen3.7-Plus" },
|
|
49
81
|
{ id: "kimi-k3", target: "kmodel_latest", displayName: "Kimi-K3.1-Pro" },
|
|
@@ -115,17 +115,14 @@ export type { QoderUserInfo, QoderOAuthState } from "./qoder-oauth";
|
|
|
115
115
|
// Quota
|
|
116
116
|
export { fetchQoderQuota, fetchQoderCnQuota } from "./qoder-quota";
|
|
117
117
|
|
|
118
|
-
// UMID /
|
|
118
|
+
// UMID / OS-derived machine identity
|
|
119
119
|
export {
|
|
120
|
+
mintQoderOsIdentity,
|
|
121
|
+
collectOsFingerprint,
|
|
120
122
|
mintQoderNativeIdentity,
|
|
121
123
|
replayQoderNativeIdentity,
|
|
122
124
|
mintQoderGeneratedIdentity,
|
|
123
125
|
qoderMachineHeaders,
|
|
124
|
-
ensurePosixExecutable,
|
|
125
|
-
umidpackDir,
|
|
126
|
-
umidMiniTarball,
|
|
127
|
-
umidMiniDir,
|
|
128
|
-
ensureUmidMiniExtracted,
|
|
129
126
|
} from "./qoder-umid";
|
|
130
127
|
export type { QoderNativeIdentity } from "./qoder-umid";
|
|
131
128
|
export {
|
|
@@ -37,7 +37,7 @@ export interface TraeModelRow {
|
|
|
37
37
|
/** Which upstream endpoint serves a row. */
|
|
38
38
|
export type TraeSurface = "chat" | "agent";
|
|
39
39
|
|
|
40
|
-
/** CN roster: 20 chat-face models from the
|
|
40
|
+
/** CN roster: 20 chat-face models from the client-state snapshot. */
|
|
41
41
|
const TRAE_CN_ROWS: readonly TraeModelRow[] = [
|
|
42
42
|
{ id: "Doubao-Seed-Code", displayName: "Seed-Code", ctx: 256000, out: 224000, vision: true, reasoning: true },
|
|
43
43
|
{ id: "DeepSeek-V4-Flash-Official", displayName: "DeepSeek-V4-Flash", ctx: 1000000, out: 936000, vision: false, reasoning: true },
|
|
@@ -100,21 +100,16 @@ const TRAE_CN_ROWS: readonly TraeModelRow[] = [
|
|
|
100
100
|
*/
|
|
101
101
|
const TRAE_INTL_ROWS: readonly TraeModelRow[] = [
|
|
102
102
|
{ id: "gpt-5.4", displayName: "GPT-5.4", ctx: 1_000_000, out: 128_000, vision: true, reasoning: true, surface: "agent" },
|
|
103
|
-
{ id: "gpt-5.2", displayName: "GPT-5.2", ctx: 272000, out: 128_000, vision: true, reasoning: true, surface: "agent" },
|
|
104
103
|
{ id: "gpt-5.2-codex-paygo", displayName: "GPT-5.2-Codex", ctx: 272000, out: 128_000, vision: true, reasoning: true, surface: "agent" },
|
|
105
|
-
{ id: "gpt-5.1-paygo", displayName: "GPT-5.1", ctx: 272000, out: 128_000, vision: true, reasoning: true, surface: "agent" },
|
|
106
|
-
{ id: "gpt-5-paygo", displayName: "GPT-5", ctx: 272000, out: 128_000, vision: true, reasoning: true, surface: "agent" },
|
|
107
104
|
{ id: "Dola-Seed-2.0-Code", displayName: "Seed-2.1-Turbo", ctx: 1000000, out: 131_072, vision: true, reasoning: true, surface: "agent" },
|
|
108
|
-
{ id: "
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
{ id: "
|
|
114
|
-
{ id: "
|
|
115
|
-
{ id: "
|
|
116
|
-
{ id: "minimax-m3", displayName: "MiniMax-M3", ctx: 1000000, out: 512_000, vision: true, reasoning: true, surface: "agent" },
|
|
117
|
-
{ id: "minimax-m2.7", displayName: "MiniMax-M2.7", ctx: 200000, out: 131_072, vision: false, reasoning: true, surface: "agent" },
|
|
105
|
+
{ id: "gemini-3.1-pro-paygo", displayName: "Gemini-3.1-Pro-PayGo", ctx: 1000000, out: 65_536, vision: true, reasoning: true, surface: "agent" },
|
|
106
|
+
// Search-agent configs from the live picker (batch_get_detail_param). They
|
|
107
|
+
// resolve to real chat models — gpt-5.4 / gpt-5.3-codex / gemini-3-flash —
|
|
108
|
+
// and accept the same tool-calling wire as any agent row, so their specs
|
|
109
|
+
// mirror the model they resolve to (verified live 2026-11-06).
|
|
110
|
+
{ id: "search_agent_gpt-5.4", displayName: "Search Agent (GPT-5.4)", ctx: 1_000_000, out: 128_000, vision: true, reasoning: true, surface: "agent" },
|
|
111
|
+
{ id: "search_agent_gpt-5.3-codex", displayName: "Search Agent (GPT-5.3-Codex)", ctx: 272000, out: 128_000, vision: true, reasoning: true, surface: "agent" },
|
|
112
|
+
{ id: "search_agent_gemini_3_pro_with_g3f", displayName: "Search Agent (Gemini-3-Flash)", ctx: 1000000, out: 65_536, vision: true, reasoning: true, surface: "agent" },
|
|
118
113
|
];
|
|
119
114
|
|
|
120
115
|
function traeModels(rows: readonly TraeModelRow[], providerId: string): readonly ModelDefinition[] {
|