cartethyia 2.7.4 → 2.7.6
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 +5 -0
- package/README.md +18 -6
- package/dist/dashboard/assets/BannedPage-B1N603cM.js +1 -0
- package/dist/dashboard/assets/BannedPage-B1N603cM.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-9q4_4NoK.js +3 -0
- package/dist/dashboard/assets/CliToolDetailPage-9q4_4NoK.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-DwshGtK-.js +1 -0
- package/dist/dashboard/assets/CliToolsPage-DwshGtK-.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-D762MIkp.js +1 -0
- package/dist/dashboard/assets/CombosPage-D762MIkp.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-KRYjHZsX.js +1 -0
- package/dist/dashboard/assets/ConsoleLogPage-KRYjHZsX.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-DXsxk5uM.js +1 -0
- package/dist/dashboard/assets/CustomizationPage-DXsxk5uM.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-BEjAjD4F.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-BEjAjD4F.js.gz +0 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-d5v3K_Yc.js +899 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-d5v3K_Yc.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-Ccv4tjNS.js +1 -0
- package/dist/dashboard/assets/LoginPage-Ccv4tjNS.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BMS2t8BA.js → ModelPicker-C6WlpU5E.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-C6WlpU5E.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-DN9fYNWA.js +1 -0
- package/dist/dashboard/assets/OverviewPage-DN9fYNWA.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-BY0ieUgz.js +5 -0
- package/dist/dashboard/assets/ProviderDetailPage-BY0ieUgz.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-DNsbfea2.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-DNsbfea2.js.gz +0 -0
- package/dist/dashboard/assets/{ProxyPage-lsrx7NYg.js → ProxyPage-DxjvUzSD.js} +1 -1
- package/dist/dashboard/assets/ProxyPage-DxjvUzSD.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-OaHScjpX.js +1 -0
- package/dist/dashboard/assets/QuotaPage-OaHScjpX.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-BW4AKj2H.js +1 -0
- package/dist/dashboard/assets/SettingsPage-BW4AKj2H.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-44BZrxFC.js +1 -0
- package/dist/dashboard/assets/SetupPage-44BZrxFC.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-Cq5tW7hW.js → StudioPage-DRPavCdU.js} +4 -4
- package/dist/dashboard/assets/StudioPage-DRPavCdU.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-B7M7LvMM.js +56 -0
- package/dist/dashboard/assets/UsagePage-B7M7LvMM.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-CidQVoNo.js +1 -0
- package/dist/dashboard/assets/assert-CidQVoNo.js.gz +0 -0
- package/dist/dashboard/assets/{badge-D9CS6dZk.js → badge-BaX2GTrn.js} +1 -1
- package/dist/dashboard/assets/badge-BaX2GTrn.js.gz +0 -0
- package/dist/dashboard/assets/{banner-DympBNq4.js → banner-DFH4Bkte.js} +1 -1
- package/dist/dashboard/assets/banner-DFH4Bkte.js.gz +0 -0
- package/dist/dashboard/assets/brand/login_register.jpg +0 -0
- package/dist/dashboard/assets/brand/login_register_initial.jpg +0 -0
- package/dist/dashboard/assets/brand/og_bansos.jpg +0 -0
- package/dist/dashboard/assets/brand/og_image.jpg +0 -0
- package/dist/dashboard/assets/{card-ibRWU_uT.js → card-CxDw0lK6.js} +1 -1
- package/dist/dashboard/assets/card-CxDw0lK6.js.gz +0 -0
- package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js +1 -0
- package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js.gz +0 -0
- package/dist/dashboard/assets/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-Bwv5-zGZ.js +1 -0
- package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-DJm-9pz7.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-CqGYeOrd.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-D6WvojeD.js +4 -0
- package/dist/dashboard/assets/entry-D6WvojeD.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/{formatters-D-MTJxMr.js → formatters-u7JPB5BX.js} +1 -1
- package/dist/dashboard/assets/formatters-u7JPB5BX.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-DBNPOfhV.js → index-Ko4dLRnV.js} +2 -2
- package/dist/dashboard/assets/index-Ko4dLRnV.js.gz +0 -0
- package/dist/dashboard/assets/{inline-BT0zntEr.js → inline-CHJQwxLa.js} +1 -1
- package/dist/dashboard/assets/inline-CHJQwxLa.js.gz +0 -0
- package/dist/dashboard/assets/{input-Da2ZViWg.js → input-BlmlizVV.js} +1 -1
- package/dist/dashboard/assets/input-BlmlizVV.js.gz +0 -0
- package/dist/dashboard/assets/{layout-BXNeLw6M.js → layout-Bz93I-yE.js} +1 -1
- package/dist/dashboard/assets/layout-Bz93I-yE.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-BycOrrIV.js → list-row-Ml16KCfu.js} +1 -1
- package/dist/dashboard/assets/list-row-Ml16KCfu.js.gz +0 -0
- package/dist/dashboard/assets/live-7_QpnYGu.js +1 -0
- 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-CuMDaTzT.js +1 -0
- 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-B5aOoweZ.js +1 -0
- 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-fnCsxgNO.js +1 -0
- package/dist/dashboard/assets/routing-fnCsxgNO.js.gz +0 -0
- package/dist/dashboard/assets/{select-BIYIBkMU.js → select-BHqpd-bg.js} +2 -2
- package/dist/dashboard/assets/select-BHqpd-bg.js.gz +0 -0
- package/dist/dashboard/assets/settings-BxslsErn.js +1 -0
- package/dist/dashboard/assets/settings-BxslsErn.js.gz +0 -0
- package/dist/dashboard/assets/shield-BMQNxORh.js +1 -0
- package/dist/dashboard/assets/shield-BMQNxORh.js.gz +0 -0
- package/dist/dashboard/assets/{stack-DfgnFDWY.js → stack-j7cXjgYX.js} +1 -1
- package/dist/dashboard/assets/stack-j7cXjgYX.js.gz +0 -0
- package/dist/dashboard/assets/{state-CkfdYWel.js → state-DHmEnLa2.js} +1 -1
- package/dist/dashboard/assets/state-DHmEnLa2.js.gz +0 -0
- package/dist/dashboard/assets/{switch-SYm237HG.js → switch-DmZcyTIC.js} +1 -1
- package/dist/dashboard/assets/switch-DmZcyTIC.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-BQqCRNIi.js → useMutation-CbCP4w1o.js} +1 -1
- 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/index.html +2 -2
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +60 -59
- package/migrations/full-postgres/0036_system_prompt_presets_refs.sql +10 -0
- package/migrations/full-postgres/0037_share_concurrency_scope.sql +3 -0
- package/migrations/full-postgres/0038_add_accounts_quota_snapshot.sql +7 -0
- package/migrations/full-postgres/0039_add_telemetry_provider_model_indexes.sql +13 -0
- package/migrations/full-postgres/0040_add_models_dialect.sql +3 -0
- package/migrations/full-postgres/0041_add_daily_checkin_ledger_account_fk.sql +7 -0
- package/migrations/full-postgres/0042_add_telemetry_degenerate_stop.sql +14 -0
- package/migrations/lite-sqlite3/0036_system_prompt_presets_refs.sql +14 -0
- package/migrations/lite-sqlite3/0037_share_concurrency_scope.sql +3 -0
- package/migrations/lite-sqlite3/0038_add_accounts_quota_snapshot.sql +4 -0
- package/migrations/lite-sqlite3/0039_add_telemetry_provider_model_indexes.sql +6 -0
- package/migrations/lite-sqlite3/0040_add_models_dialect.sql +3 -0
- package/migrations/lite-sqlite3/0041_add_daily_checkin_ledger_account_fk.sql +26 -0
- package/migrations/lite-sqlite3/0042_add_telemetry_degenerate_stop.sql +12 -0
- package/package.json +4 -6
- package/scripts/cli/update.ts +15 -41
- package/src/boot/app.ts +58 -2
- package/src/boot/dependencies.ts +794 -732
- package/src/boot/lifecycle.ts +11 -12
- package/src/config/cooldowns.ts +34 -55
- package/src/config/network.ts +1 -1
- package/src/config/package-paths.ts +1 -1
- package/src/config/providers.ts +19 -14
- package/src/config/resources.ts +0 -5
- package/src/config/runtime.ts +2 -5
- package/src/config/spec.ts +33 -6
- package/src/config/usage.ts +27 -0
- package/src/console/api-keys/ban-constants.ts +38 -0
- package/src/console/api-keys/contracts.ts +71 -62
- package/src/console/api-keys/routes.ts +56 -24
- package/src/console/auth/access.ts +4 -4
- package/src/console/auth/account-reset.ts +1 -1
- package/src/console/auth/audit-recorder.ts +1 -1
- package/src/console/auth/lockout.ts +7 -3
- package/src/console/auth/row-coercion.ts +57 -12
- package/src/console/auth/session-resolver.ts +1 -1
- package/src/console/auth/session-service.ts +8 -2
- package/src/console/auth/session.ts +37 -31
- package/src/console/auth/setup-service.ts +4 -3
- package/src/console/auth/user-store.ts +1 -1
- package/src/console/backup/9router-map.ts +0 -3
- package/src/console/backup/contracts.ts +9 -9
- package/src/console/backup/export-endpoint.ts +5 -6
- package/src/console/backup/nine-router.ts +1 -7
- package/src/console/backup/routes.ts +29 -33
- package/src/console/backup/service.ts +468 -468
- package/src/console/backup/store.ts +47 -29
- package/src/console/backup/validate.ts +11 -1
- package/src/console/cli-tools/contracts.ts +43 -299
- 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 +181 -181
- package/src/console/cli-tools/injectors/driver.ts +150 -247
- package/src/console/cli-tools/injectors/kilo.ts +146 -21
- package/src/console/cli-tools/injectors/opencode.ts +176 -153
- package/src/console/cli-tools/routes.ts +7 -1
- package/src/console/cli-tools/service.ts +8 -7
- package/src/console/cli-tools/store.ts +2 -2
- package/src/console/console-router.ts +32 -0
- package/src/console/dashboard-assets.ts +9 -9
- package/src/console/domain-registration.ts +16 -2
- package/src/console/inferhub/client.ts +0 -7
- package/src/console/inferhub/key-store.ts +1 -1
- package/src/console/inferhub/normalize.ts +2 -2
- package/src/console/inferhub/routes.ts +1 -1
- package/src/console/inferhub/types.ts +1 -1
- package/src/console/observability/contracts.ts +7 -1
- package/src/console/observability/live.ts +31 -18
- package/src/console/observability/logs.ts +1 -1
- package/src/console/observability/sse.ts +62 -8
- package/src/console/observability/store.ts +23 -4
- package/src/console/providers/catalog/catalog-projections.ts +1 -1
- package/src/console/providers/catalog/contracts.ts +39 -0
- package/src/console/providers/catalog/model-operations.ts +1 -1
- package/src/console/providers/catalog/provider-operations.ts +95 -17
- package/src/console/providers/catalog/public-model-store.ts +0 -0
- package/src/console/providers/catalog/routes.ts +27 -3
- package/src/console/providers/catalog/store.ts +147 -8
- package/src/console/providers/detail/routes.ts +1 -1
- package/src/console/providers/oauth/callback-listener.ts +100 -18
- package/src/console/providers/oauth/routes.ts +92 -13
- package/src/console/quota/account-quota-global.ts +41 -3
- package/src/console/quota/account-quota-shared.ts +10 -3
- package/src/console/quota/account-quota-tenant.ts +259 -66
- package/src/console/quota/daily-growth-job.ts +308 -0
- package/src/console/quota/native-identity.ts +2 -2
- package/src/console/quota/quota-view.ts +1 -1
- package/src/console/remote-support/routes.ts +1 -1
- package/src/console/remote-support/service.ts +2 -2
- package/src/console/routing/model/contracts.ts +1 -1
- package/src/console/routing/pools/contracts.ts +2 -2
- package/src/console/routing/pools/import-parse.ts +3 -3
- package/src/console/routing/pools/relay-deploy.ts +3 -3
- package/src/console/settings/contracts.ts +29 -2
- package/src/console/settings/store.ts +20 -0
- package/src/console/share/share-router.ts +100 -32
- package/src/console/share/share-stats.ts +11 -13
- package/src/console/share/share-usage.ts +1 -1
- package/src/console/shared/errors.ts +2 -2
- package/src/console/shared/object.ts +18 -0
- package/src/console/shared/read-through-cache.ts +4 -4
- package/src/console/shared/transaction.ts +14 -0
- package/src/console/system-prompt/contracts.ts +89 -12
- package/src/console/system-prompt/routes.ts +98 -45
- package/src/console/updates/apply-update.ts +244 -0
- package/src/console/updates/routes.ts +252 -97
- package/src/main.ts +11 -5
- package/src/network/http2-bidi.ts +1 -1
- package/src/network/ip-utils.ts +298 -0
- package/src/network/outbound-fetch.ts +1 -1
- package/src/network/pool/agent.ts +7 -6
- package/src/network/pool/byte-accounting.ts +1 -1
- package/src/network/pool/resolver.ts +16 -12
- package/src/network/pool/selector.ts +150 -136
- package/src/network/pool-health-machine.ts +1 -1
- package/src/network/rate-limit-verdict.ts +1 -1
- package/src/network/retry.ts +1 -1
- package/src/network/ssrf.ts +20 -71
- package/src/observability/event-log.ts +9 -2
- package/src/observability/event-query.ts +61 -291
- package/src/observability/log-sanitize.ts +1 -1
- package/src/observability/metrics.ts +4 -4
- package/src/observability/payload-capture.ts +6 -5
- package/src/observability/payload-store.ts +1 -1
- package/src/observability/runtime-metrics.ts +1 -1
- package/src/observability/telemetry-buffer.ts +19 -3
- package/src/observability/telemetry-reconciliation.ts +3 -3
- package/src/observability/token-speed.ts +1 -1
- package/src/persistence/connection-url.ts +1 -1
- package/src/persistence/db-handle.ts +1 -1
- package/src/persistence/db-pg.ts +2 -2
- package/src/persistence/db-sqlite.ts +3 -3
- package/src/persistence/dialect.ts +5 -1
- package/src/persistence/readiness.ts +1 -1
- package/src/persistence/redis.ts +1 -1
- package/src/persistence/schema.ts +121 -40
- package/src/persistence/shared-cache.ts +2 -2
- package/src/persistence/sort-order.ts +1 -1
- package/src/persistence/stores/api-key-store.ts +29 -2
- package/src/persistence/stores/share-store.ts +20 -8
- package/src/persistence/system-prompt-store.ts +63 -18
- package/src/persistence/tenant-preferences.ts +1 -1
- package/src/persistence/ttl-cache.ts +3 -3
- package/src/persistence/usage-flush.ts +7 -2
- package/src/protocol/canonical-model.ts +1 -1
- package/src/protocol/codecs.ts +6 -10
- package/src/protocol/dsml.ts +8 -125
- package/src/protocol/image-clamp.ts +2 -2
- package/src/protocol/reasoning-text.ts +1 -1
- package/src/protocol/reasoning.ts +7 -52
- package/src/protocol/registry.ts +50 -15
- package/src/protocol/request/chat.ts +46 -19
- package/src/protocol/request/codex.ts +1 -1
- package/src/protocol/request/messages.ts +46 -14
- package/src/protocol/request/responses.ts +19 -10
- package/src/protocol/response/chat.ts +25 -10
- package/src/protocol/response/codex.ts +1 -1
- package/src/protocol/response/messages.ts +1 -1
- package/src/protocol/response/omp-tool-call-markup.ts +1 -1
- package/src/protocol/response/responses.ts +1 -1
- package/src/protocol/sse-decoder.ts +50 -1
- package/src/protocol/stop-reason.ts +2 -2
- package/src/protocol/think-split.ts +347 -0
- package/src/protocol/translation/attachment-integrity.ts +3 -3
- package/src/protocol/translation/cache-controls.ts +8 -20
- package/src/protocol/translation/capabilities.ts +6 -6
- package/src/protocol/translation/dialect/deepseek.ts +10 -0
- package/src/protocol/translation/dialect/inband.ts +39 -0
- package/src/protocol/translation/dialect/model-thinking.ts +89 -0
- package/src/protocol/translation/dialect/qwen.ts +114 -0
- package/src/protocol/translation/dialect/resolver.ts +83 -0
- package/src/protocol/translation/dialect/rules.ts +93 -0
- package/src/protocol/translation/dialect/thinking-ladder.ts +245 -0
- package/src/protocol/translation/dialect/types.ts +58 -0
- package/src/protocol/translation/quirks.ts +18 -4
- package/src/protocol/translation/thinking.ts +12 -252
- package/src/protocol/translation/tool-id.ts +3 -3
- package/src/protocol/translation/tool-repair.ts +1 -1
- package/src/protocol/upstream/post-json.ts +6 -1
- package/src/providers/adapters/compatible-adapter.ts +71 -4
- package/src/providers/authentication/jwt-validator.ts +0 -5
- package/src/providers/authentication/oauth-client.ts +254 -253
- package/src/providers/authentication/oauth-flow-store.ts +42 -7
- package/src/providers/bundled-discovery-providers.ts +6 -30
- package/src/providers/configured-openai-providers.ts +82 -97
- package/src/providers/default-registry.ts +35 -37
- package/src/providers/discovery/catalog/catalog-format.ts +13 -2
- package/src/providers/discovery/discovery-types.ts +0 -1
- package/src/providers/discovery/openai-model-discovery.ts +2 -2
- package/src/providers/discovery/probe-phases.ts +48 -13
- package/src/providers/discovery/probing-service.ts +6 -8
- package/src/providers/integrations/agentrouter/agentrouter.ts +12 -2
- package/src/providers/integrations/antigravity/antigravity-oauth.ts +0 -1
- package/src/providers/integrations/antigravity/antigravity-protocol.ts +88 -28
- package/src/providers/integrations/antigravity/antigravity-quota.ts +18 -6
- package/src/providers/integrations/antigravity/antigravity.ts +22 -13
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +1 -1
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +20 -4
- package/src/providers/integrations/buddy/buddy-cli-headers.ts +19 -52
- package/src/providers/integrations/buddy/buddy-identity.ts +86 -0
- package/src/providers/integrations/buddy/buddy-oauth-shared.ts +1 -1
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +1 -2
- package/src/providers/integrations/buddy/codebuddy/provider.ts +4 -15
- package/src/providers/integrations/buddy/codebuddy/shared.ts +30 -9
- package/src/providers/integrations/buddy/workbuddy/provider.ts +5 -9
- package/src/providers/integrations/buddy/workbuddy/shared.ts +21 -3
- package/src/providers/integrations/claude/claude-cch.ts +148 -148
- package/src/providers/integrations/claude/fallback-credit.ts +3 -7
- package/src/providers/integrations/cline/cline.ts +1 -1
- package/src/providers/integrations/codex/codex-device-code.ts +101 -101
- package/src/providers/integrations/codex/codex-oauth.ts +0 -1
- package/src/providers/integrations/commandcode/commandcode.ts +75 -115
- package/src/providers/integrations/commandcode/quota.ts +131 -51
- package/src/providers/integrations/cursor/cursor-http2.ts +0 -3
- package/src/providers/integrations/cursor/cursor-quota.ts +2 -6
- package/src/providers/integrations/cursor/cursor-request.ts +0 -87
- package/src/providers/integrations/cursor/cursor-shared.ts +0 -4
- package/src/providers/integrations/cursor/cursor.ts +35 -3
- package/src/providers/integrations/cursor/protocol/framing.ts +0 -56
- package/src/providers/integrations/cursor/protocol/messages.ts +0 -96
- package/src/providers/integrations/factory/factory.ts +9 -9
- package/src/providers/integrations/github/github-discovery.ts +70 -12
- package/src/providers/integrations/github/github-oauth.ts +184 -14
- package/src/providers/integrations/github/github.ts +134 -26
- package/src/providers/integrations/grok/grok-oauth.ts +261 -261
- package/src/providers/integrations/grok/grok-quota-frame.ts +1 -1
- package/src/providers/integrations/grok/grok-quota.ts +16 -7
- package/src/providers/integrations/grok/grok-ratelimit-store.ts +0 -5
- package/src/providers/integrations/grok/grok-ratelimit.ts +3 -0
- package/src/providers/integrations/grok/grok.ts +86 -36
- package/src/providers/integrations/kilo/kilo-oauth.ts +1 -1
- package/src/providers/integrations/kiro/kiro-cache.ts +31 -0
- package/src/providers/integrations/kiro/kiro-catalog.ts +31 -5
- package/src/providers/integrations/kiro/kiro-discovery.ts +47 -43
- package/src/providers/integrations/kiro/kiro-machine-id.ts +6 -3
- package/src/providers/integrations/kiro/kiro-oauth.ts +523 -255
- package/src/providers/integrations/kiro/kiro-quota.ts +35 -47
- package/src/providers/integrations/kiro/kiro-request.ts +8 -11
- package/src/providers/integrations/kiro/kiro-stream.ts +13 -0
- package/src/providers/integrations/kiro/kiro.ts +80 -68
- package/src/providers/integrations/muse/muse-oauth.ts +0 -1
- package/src/providers/integrations/muse/muse-quota.ts +0 -4
- package/src/providers/integrations/opencode/fingerprint.ts +7 -5
- package/src/providers/integrations/opencode/provider.ts +17 -24
- package/src/providers/integrations/qoder/qoder-catalog.ts +94 -11
- package/src/providers/integrations/qoder/qoder-oauth.ts +165 -25
- package/src/providers/integrations/qoder/qoder-quota.ts +48 -6
- package/src/providers/integrations/qoder/qoder-realm.ts +10 -31
- package/src/providers/integrations/qoder/qoder-sse.ts +159 -0
- package/src/providers/integrations/qoder/qoder-umid.ts +21 -25
- package/src/providers/integrations/qoder/qoder-virtual.ts +12 -0
- package/src/providers/integrations/qoder/qoder.ts +422 -71
- package/src/providers/integrations/shared/connect.ts +0 -54
- package/src/providers/integrations/shared/hash.ts +15 -0
- package/src/providers/integrations/shared/session-cache.ts +136 -0
- package/src/providers/integrations/trae/trae-cache.ts +7 -87
- package/src/providers/integrations/trae/trae-catalog.ts +1 -6
- package/src/providers/integrations/trae/trae-protocol.ts +17 -8
- package/src/providers/integrations/trae/trae-realm.ts +0 -7
- package/src/providers/integrations/trae/trae.ts +51 -8
- package/src/providers/integrations/xai/xai-oauth.ts +5 -5
- package/src/providers/integrations/zcode-start-plan/gifts.ts +265 -0
- package/src/providers/integrations/zcode-start-plan/oauth.ts +154 -0
- package/src/providers/integrations/zcode-start-plan/provider.ts +131 -0
- package/src/providers/integrations/zcode-start-plan/quota.ts +152 -0
- package/src/providers/integrations/zcode-start-plan/zcode_prompt.json +10 -0
- package/src/providers/operations/account-error-classification.ts +198 -133
- package/src/providers/operations/account-health-service.ts +31 -39
- package/src/providers/operations/account-reset-service.ts +58 -1
- package/src/providers/operations/byok-wire-profile.ts +19 -15
- package/src/providers/operations/cli-platform.ts +31 -5
- package/src/providers/operations/client-version-resolver.ts +4 -6
- package/src/providers/operations/client-versions.ts +10 -7
- package/src/providers/operations/provider-catalog-seeder.ts +2 -0
- package/src/providers/operations/provider-catalog-service.ts +18 -2
- package/src/providers/operations/provider-credential-service.ts +19 -2
- package/src/providers/provider-contracts.ts +18 -7
- package/src/providers/provider-metadata.ts +17 -2
- package/src/providers/provider-model-definition.ts +22 -1
- package/src/providers/provider-probe.ts +4 -2
- package/src/providers/provider-usage.ts +50 -19
- package/src/providers/quota/cache.ts +29 -0
- package/src/providers/quota/quota-contracts.ts +4 -0
- package/src/providers/quota/refresh.ts +27 -4
- package/src/providers/quota/snapshot.ts +94 -0
- package/src/providers/search/search-provider.ts +1 -3
- package/src/providers/search/search-providers.ts +2 -1
- package/src/security/abuse.ts +4 -4
- package/src/security/admission/service.ts +13 -6
- package/src/security/admission/ttl.ts +61 -61
- package/src/security/api-key-auth.ts +17 -3
- package/src/security/client-router-fingerprint.ts +4 -4
- package/src/security/credential-codec.ts +3 -3
- package/src/security/csrf.ts +2 -2
- package/src/security/ip-boundary.ts +16 -189
- package/src/security/model-access-rule.ts +1 -1
- package/src/security/outbound-headers.ts +18 -0
- package/src/shared/invoke-guard.ts +47 -0
- package/src/transport/contracts.ts +13 -4
- package/src/transport/dispatch/attempt-finalize.ts +70 -22
- package/src/transport/dispatch/attempt-loop.ts +22 -0
- package/src/transport/dispatch/capture-policy.ts +34 -37
- package/src/transport/dispatch/empty-stream.ts +23 -20
- package/src/transport/dispatch/generation.ts +25 -45
- package/src/transport/dispatch/native-shared.ts +127 -0
- package/src/transport/dispatch/proxy-request.ts +3 -1
- package/src/transport/dispatch/responses-compact.ts +25 -46
- package/src/transport/dispatch/streaming/encoder.ts +18 -72
- package/src/transport/dispatch/streaming/finalize.ts +2 -2
- package/src/transport/dispatch/streaming/stream.ts +7 -3
- package/src/transport/dispatch/streaming/thinking-loop.ts +1 -1
- package/src/transport/dispatch/systemone.ts +20 -48
- package/src/transport/dispatch/token-count.ts +41 -38
- package/src/transport/dispatch/websearch.ts +19 -45
- package/src/transport/drain-endpoint.ts +1 -1
- package/src/transport/failure-policy.ts +21 -1
- package/src/transport/guards/auth-guard.ts +0 -6
- package/src/transport/guards/body-policy.ts +3 -3
- package/src/transport/guards/error-lifecycle.ts +4 -0
- package/src/transport/guards/headroom-guard.ts +1 -1
- package/src/transport/guards/pipeline.ts +1 -1
- package/src/transport/guards/request-context.ts +12 -17
- package/src/transport/request/preparer.ts +286 -7
- package/src/transport/request/rtk/compress-request.ts +3 -3
- package/src/transport/request/rtk/rtk-constants.ts +2 -2
- package/src/transport/request/rtk/rtk-filters.ts +8 -8
- package/src/transport/request/state.ts +7 -13
- package/src/transport/request/system-prompt-injection.ts +74 -11
- package/src/transport/request/tenant-preferences.ts +22 -0
- package/src/transport/routing/candidate-index.ts +2 -2
- package/src/transport/routing/round-robin.ts +1 -1
- package/src/transport/routing/route-catalog.ts +17 -18
- package/src/transport/routing/route-model.ts +126 -33
- package/src/transport/routing/router.ts +159 -37
- package/src/transport/shutdown-notice.ts +2 -2
- package/src/transport/surface/adapters.ts +3 -3
- package/src/transport/surface/chat/encode.ts +7 -7
- package/src/transport/surface/chat/parse.ts +7 -7
- package/src/transport/surface/completion.ts +2 -2
- package/src/transport/surface/content-parts.ts +1 -1
- package/src/transport/surface/dialects.ts +2 -2
- package/src/transport/surface/messages/parse.ts +3 -3
- package/src/transport/surface/reasoning-summary.ts +9 -14
- package/src/transport/surface/responses/adapter.ts +1 -1
- package/src/transport/surface/responses/errors.ts +0 -9
- package/src/transport/vision-handoff-cache.ts +58 -0
- package/src/transport/vision-handoff.ts +431 -0
- package/src/workers/account-identity-sweep.ts +2 -2
- package/src/workers/buddy-growth-tasks.ts +392 -346
- package/src/workers/daily-checkin.ts +102 -49
- package/src/workers/maintenance-lease.ts +2 -35
- package/src/workers/oauth-refresh-sweep.ts +8 -1
- package/src/workers/quota-refresh-sweep.ts +120 -82
- package/src/workers/scheduler.ts +67 -4
- package/src/workers/sweep-runner.ts +24 -5
- package/src/workers/zcode-gift-claim.ts +108 -0
- package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js +0 -1
- package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js.gz +0 -0
- package/dist/dashboard/assets/BannedPage-ChG5svFb.js +0 -1
- package/dist/dashboard/assets/BannedPage-ChG5svFb.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js +0 -1
- package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js +0 -1
- package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-DCgm5g6g.js +0 -1
- package/dist/dashboard/assets/CombosPage-DCgm5g6g.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js +0 -1
- package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-U6AKaJcF.js +0 -1
- package/dist/dashboard/assets/LoginPage-U6AKaJcF.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-BMS2t8BA.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js +0 -1
- package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js +0 -5
- package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js +0 -1
- package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-lsrx7NYg.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-L0skzML8.js +0 -1
- package/dist/dashboard/assets/QuotaPage-L0skzML8.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js +0 -1
- package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-f0DE1h0-.js +0 -1
- package/dist/dashboard/assets/SetupPage-f0DE1h0-.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-ClzpwyET.js +0 -1
- package/dist/dashboard/assets/SortableList-ClzpwyET.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-Cq5tW7hW.js.gz +0 -0
- package/dist/dashboard/assets/ToolIcon-K1ckcDKg.js +0 -1
- package/dist/dashboard/assets/ToolIcon-K1ckcDKg.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js +0 -56
- package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-C38iXoO4.js +0 -1
- package/dist/dashboard/assets/api-keys-C38iXoO4.js.gz +0 -0
- package/dist/dashboard/assets/app-BayTTy01.js +0 -9
- package/dist/dashboard/assets/app-BayTTy01.js.gz +0 -0
- package/dist/dashboard/assets/app-a159k0ub.css +0 -2
- package/dist/dashboard/assets/app-a159k0ub.css.gz +0 -0
- package/dist/dashboard/assets/assert-DbRA8EG2.js +0 -15
- package/dist/dashboard/assets/assert-DbRA8EG2.js.gz +0 -0
- package/dist/dashboard/assets/badge-D9CS6dZk.js.gz +0 -0
- package/dist/dashboard/assets/banner-DympBNq4.js.gz +0 -0
- package/dist/dashboard/assets/card-ibRWU_uT.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-63qBGaRw.js +0 -1
- package/dist/dashboard/assets/cli-tools-63qBGaRw.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-DJm-9pz7.js.gz +0 -0
- package/dist/dashboard/assets/dialog-8fiE6tec.js +0 -1
- package/dist/dashboard/assets/dialog-8fiE6tec.js.gz +0 -0
- package/dist/dashboard/assets/drawer-CqGYeOrd.js.gz +0 -0
- package/dist/dashboard/assets/entry-BSAsYsmV.js +0 -1
- package/dist/dashboard/assets/entry-BSAsYsmV.js.gz +0 -0
- package/dist/dashboard/assets/entry-CiIQULZD.js +0 -4
- package/dist/dashboard/assets/entry-CiIQULZD.js.gz +0 -0
- package/dist/dashboard/assets/entry-Daz0lJ-W.js +0 -1
- package/dist/dashboard/assets/entry-Daz0lJ-W.js.gz +0 -0
- package/dist/dashboard/assets/formatters-D-MTJxMr.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-CPK47xQx.js +0 -1
- package/dist/dashboard/assets/github-badge-CPK47xQx.js.gz +0 -0
- package/dist/dashboard/assets/index-DBNPOfhV.js.gz +0 -0
- package/dist/dashboard/assets/inline-BT0zntEr.js.gz +0 -0
- package/dist/dashboard/assets/input-Da2ZViWg.js.gz +0 -0
- package/dist/dashboard/assets/layout-BXNeLw6M.js.gz +0 -0
- package/dist/dashboard/assets/list-row-BycOrrIV.js.gz +0 -0
- package/dist/dashboard/assets/live-DCQNZpF7.js +0 -1
- package/dist/dashboard/assets/live-DCQNZpF7.js.gz +0 -0
- package/dist/dashboard/assets/mutation-Rr0TIvcj.js.gz +0 -0
- package/dist/dashboard/assets/network-9Yj2ZyLo.js +0 -1
- package/dist/dashboard/assets/network-9Yj2ZyLo.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CEagj6ZZ.js +0 -2
- package/dist/dashboard/assets/numbers-CEagj6ZZ.js.gz +0 -0
- package/dist/dashboard/assets/providers/zai-coding-plan.svg +0 -6
- package/dist/dashboard/assets/providers/zai-coding-plan.svg.gz +0 -0
- package/dist/dashboard/assets/quota-Caw7wqci.js +0 -1
- package/dist/dashboard/assets/quota-Caw7wqci.js.gz +0 -0
- package/dist/dashboard/assets/routing-CO9zCUus.js +0 -1
- package/dist/dashboard/assets/routing-CO9zCUus.js.gz +0 -0
- package/dist/dashboard/assets/select-BIYIBkMU.js.gz +0 -0
- package/dist/dashboard/assets/settings-jS3-PNSA.js +0 -1
- package/dist/dashboard/assets/settings-jS3-PNSA.js.gz +0 -0
- package/dist/dashboard/assets/stack-DfgnFDWY.js.gz +0 -0
- package/dist/dashboard/assets/state-CkfdYWel.js.gz +0 -0
- package/dist/dashboard/assets/stream-retry-5QnVuSSo.js +0 -1
- package/dist/dashboard/assets/stream-retry-5QnVuSSo.js.gz +0 -0
- package/dist/dashboard/assets/switch-SYm237HG.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-BQqCRNIi.js.gz +0 -0
- package/src/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/network/response-headers.ts +0 -39
- package/src/protocol/response/dsml.ts +0 -38
- package/src/providers/integrations/xiaomi-mimo/think-stream.ts +0 -229
- /package/dist/dashboard/assets/brand/{og_bansos.webp → og_bansos_initial.webp} +0 -0
- /package/dist/dashboard/assets/brand/{og_image.webp → og_image_initial.webp} +0 -0
|
@@ -21,18 +21,25 @@ import {
|
|
|
21
21
|
import {
|
|
22
22
|
EMPTY_TENANT_SYSTEM_PROMPTS,
|
|
23
23
|
PROMPT_MODES,
|
|
24
|
+
SYSTEM_PROMPT_ALIAS_LIMIT,
|
|
25
|
+
SYSTEM_PROMPT_COMBO_LIMIT,
|
|
24
26
|
SYSTEM_PROMPT_MODEL_LIMIT,
|
|
27
|
+
SYSTEM_PROMPT_PRESET_LIMIT,
|
|
28
|
+
SYSTEM_PROMPT_PRESET_NAME_CAP,
|
|
25
29
|
SYSTEM_PROMPT_PROVIDER_LIMIT,
|
|
26
30
|
SYSTEM_PROMPT_TEXT_CAP_BYTES,
|
|
27
31
|
isPromptSetting,
|
|
32
|
+
isScopePromptRef,
|
|
33
|
+
isSystemPromptPreset,
|
|
28
34
|
parseSystemPromptModelKey,
|
|
29
35
|
type PromptSetting,
|
|
30
|
-
type
|
|
36
|
+
type ScopePromptRef,
|
|
37
|
+
type SystemPromptPreset,
|
|
31
38
|
type TenantSystemPrompts,
|
|
32
39
|
} from "./contracts";
|
|
33
40
|
|
|
34
41
|
/** Route-group context injected by the composition root. */
|
|
35
|
-
|
|
42
|
+
interface SystemPromptRoutesConfig {
|
|
36
43
|
readonly db: CartethyiaDatabase;
|
|
37
44
|
readonly accessResolver: ConsoleAccessResolver;
|
|
38
45
|
readonly auditSink?: AuditSink;
|
|
@@ -53,6 +60,46 @@ function validateSetting(value: unknown, scopeLabel: string): PromptSetting {
|
|
|
53
60
|
return value;
|
|
54
61
|
}
|
|
55
62
|
|
|
63
|
+
/** Validates one preset. */
|
|
64
|
+
function validatePreset(value: unknown, scopeLabel: string): SystemPromptPreset {
|
|
65
|
+
if (!isSystemPromptPreset(value)) {
|
|
66
|
+
throw new ConsoleDomainError("invalid_request", 400, `${scopeLabel} is not a valid preset`);
|
|
67
|
+
}
|
|
68
|
+
if (value.name.length > SYSTEM_PROMPT_PRESET_NAME_CAP) {
|
|
69
|
+
throw new ConsoleDomainError(
|
|
70
|
+
"invalid_request",
|
|
71
|
+
400,
|
|
72
|
+
`${scopeLabel} name exceeds the ${SYSTEM_PROMPT_PRESET_NAME_CAP} character limit`,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
validateSetting(value, scopeLabel);
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Validates one scope reference; a preset id that does not exist is
|
|
80
|
+
* neutralized to `off` rather than rejected, so deleting a preset does not
|
|
81
|
+
* block saving a configuration that still references it. */
|
|
82
|
+
function validateScopeRef(
|
|
83
|
+
value: unknown,
|
|
84
|
+
scopeLabel: string,
|
|
85
|
+
presetIds: ReadonlySet<string>,
|
|
86
|
+
): ScopePromptRef {
|
|
87
|
+
if (!isScopePromptRef(value)) {
|
|
88
|
+
throw new ConsoleDomainError("invalid_request", 400, `${scopeLabel} is not a valid scope reference`);
|
|
89
|
+
}
|
|
90
|
+
if (value.kind === "preset") {
|
|
91
|
+
if (!presetIds.has(value.presetId)) {
|
|
92
|
+
return { kind: "off" };
|
|
93
|
+
}
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
if (value.kind === "custom") {
|
|
97
|
+
validateSetting(value.setting, scopeLabel);
|
|
98
|
+
return value;
|
|
99
|
+
}
|
|
100
|
+
return value;
|
|
101
|
+
}
|
|
102
|
+
|
|
56
103
|
/** Validates the full PUT body into the stored shape. */
|
|
57
104
|
function validateBody(value: unknown): TenantSystemPrompts {
|
|
58
105
|
if (typeof value !== "object" || value === null) {
|
|
@@ -60,68 +107,71 @@ function validateBody(value: unknown): TenantSystemPrompts {
|
|
|
60
107
|
}
|
|
61
108
|
const body = value as {
|
|
62
109
|
global?: unknown;
|
|
110
|
+
presets?: unknown;
|
|
63
111
|
providers?: unknown;
|
|
64
112
|
models?: unknown;
|
|
113
|
+
combos?: unknown;
|
|
114
|
+
aliases?: unknown;
|
|
65
115
|
};
|
|
66
116
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
? null
|
|
70
|
-
: validateSetting(body.global, "global");
|
|
71
|
-
|
|
72
|
-
if (body.providers !== undefined && typeof body.providers !== "object") {
|
|
73
|
-
throw new ConsoleDomainError("invalid_request", 400, "providers must be an object");
|
|
117
|
+
if (body.presets !== undefined && typeof body.presets !== "object") {
|
|
118
|
+
throw new ConsoleDomainError("invalid_request", 400, "presets must be an object");
|
|
74
119
|
}
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
if (
|
|
120
|
+
const rawPresets = (body.presets ?? {}) as Record<string, unknown>;
|
|
121
|
+
const presetIds = Object.keys(rawPresets);
|
|
122
|
+
if (presetIds.length > SYSTEM_PROMPT_PRESET_LIMIT) {
|
|
78
123
|
throw new ConsoleDomainError(
|
|
79
124
|
"invalid_request",
|
|
80
125
|
400,
|
|
81
|
-
`
|
|
126
|
+
`presets exceeds the ${SYSTEM_PROMPT_PRESET_LIMIT} entry limit`,
|
|
82
127
|
);
|
|
83
128
|
}
|
|
84
|
-
const
|
|
85
|
-
for (const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
129
|
+
const presets: Record<string, SystemPromptPreset> = {};
|
|
130
|
+
for (const id of presetIds) {
|
|
131
|
+
presets[id] = validatePreset(rawPresets[id], `preset ${id}`);
|
|
132
|
+
}
|
|
133
|
+
const presetIdSet = new Set(presetIds);
|
|
134
|
+
|
|
135
|
+
const global =
|
|
136
|
+
body.global === null || body.global === undefined
|
|
137
|
+
? null
|
|
138
|
+
: validateScopeRef(body.global, "global", presetIdSet);
|
|
139
|
+
|
|
140
|
+
const readRefMap = (
|
|
141
|
+
raw: unknown,
|
|
142
|
+
label: string,
|
|
143
|
+
limit: number,
|
|
144
|
+
): Record<string, ScopePromptRef> => {
|
|
145
|
+
if (raw !== undefined && typeof raw !== "object") {
|
|
146
|
+
throw new ConsoleDomainError("invalid_request", 400, `${label} must be an object`);
|
|
89
147
|
}
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
148
|
+
const entries = (raw ?? {}) as Record<string, unknown>;
|
|
149
|
+
const keys = Object.keys(entries);
|
|
150
|
+
if (keys.length > limit) {
|
|
151
|
+
throw new ConsoleDomainError(
|
|
152
|
+
"invalid_request",
|
|
153
|
+
400,
|
|
154
|
+
`${label} exceeds the ${limit} entry limit`,
|
|
155
|
+
);
|
|
93
156
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
providers[providerId] = {
|
|
98
|
-
followGlobal: false,
|
|
99
|
-
setting: validateSetting(candidate.setting, `provider ${providerId}`),
|
|
100
|
-
};
|
|
157
|
+
const out: Record<string, ScopePromptRef> = {};
|
|
158
|
+
for (const key of keys) {
|
|
159
|
+
out[key] = validateScopeRef(entries[key], `${label} ${key}`, presetIdSet);
|
|
101
160
|
}
|
|
102
|
-
|
|
161
|
+
return out;
|
|
162
|
+
};
|
|
103
163
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const rawModels = (body.models ?? {}) as Record<string, unknown>;
|
|
108
|
-
const modelKeys = Object.keys(rawModels);
|
|
109
|
-
if (modelKeys.length > SYSTEM_PROMPT_MODEL_LIMIT) {
|
|
110
|
-
throw new ConsoleDomainError(
|
|
111
|
-
"invalid_request",
|
|
112
|
-
400,
|
|
113
|
-
`models exceeds the ${SYSTEM_PROMPT_MODEL_LIMIT} entry limit`,
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
const models: Record<string, PromptSetting> = {};
|
|
117
|
-
for (const key of modelKeys) {
|
|
164
|
+
const providers = readRefMap(body.providers, "providers", SYSTEM_PROMPT_PROVIDER_LIMIT);
|
|
165
|
+
const models = readRefMap(body.models, "models", SYSTEM_PROMPT_MODEL_LIMIT);
|
|
166
|
+
for (const key of Object.keys(models)) {
|
|
118
167
|
if (parseSystemPromptModelKey(key) === null) {
|
|
119
168
|
throw new ConsoleDomainError("invalid_request", 400, `model key ${key} is malformed`);
|
|
120
169
|
}
|
|
121
|
-
models[key] = validateSetting(rawModels[key], `model ${key}`);
|
|
122
170
|
}
|
|
171
|
+
const combos = readRefMap(body.combos, "combos", SYSTEM_PROMPT_COMBO_LIMIT);
|
|
172
|
+
const aliases = readRefMap(body.aliases, "aliases", SYSTEM_PROMPT_ALIAS_LIMIT);
|
|
123
173
|
|
|
124
|
-
return { global, providers, models };
|
|
174
|
+
return { global, presets, providers, models, combos, aliases };
|
|
125
175
|
}
|
|
126
176
|
|
|
127
177
|
/**
|
|
@@ -150,8 +200,11 @@ export function createSystemPromptRoutes(config: SystemPromptRoutesConfig) {
|
|
|
150
200
|
target: "tenant_system_prompts",
|
|
151
201
|
detail: {
|
|
152
202
|
global: next.global !== null,
|
|
203
|
+
presets: Object.keys(next.presets).length,
|
|
153
204
|
providers: Object.keys(next.providers).length,
|
|
154
205
|
models: Object.keys(next.models).length,
|
|
206
|
+
combos: Object.keys(next.combos).length,
|
|
207
|
+
aliases: Object.keys(next.aliases).length,
|
|
155
208
|
},
|
|
156
209
|
});
|
|
157
210
|
return next;
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The detached update flow — the one implementation the console route and the
|
|
3
|
+
* CLI (`carte update`, console menu) share.
|
|
4
|
+
*
|
|
5
|
+
* npm cannot replace this package's directory while a process is executing out
|
|
6
|
+
* of it (EBUSY on Windows), and the deployment model has no process supervisor
|
|
7
|
+
* that could restart after an in-process install. So the installer MUST be a
|
|
8
|
+
* detached process that outlives the gateway that asked for it: the caller
|
|
9
|
+
* writes an intent file, spawns the installer, and then exits (gracefully, via
|
|
10
|
+
* the ShutdownCoordinator, on the console route).
|
|
11
|
+
*
|
|
12
|
+
* The status file is the contract between the two processes: the gateway writes
|
|
13
|
+
* `{status:"installing"}` before spawning, and the detached installer
|
|
14
|
+
* (spawnDetachedInstaller's wrapper) overwrites it with
|
|
15
|
+
* `{status:"success"|"failed", exitCode, stderrTail}` when npm finishes.
|
|
16
|
+
* `GET /updates/status` reads it back, so the dashboard knows whether the
|
|
17
|
+
* install landed or died — instead of polling a release tag forever with no
|
|
18
|
+
* answer when npm failed.
|
|
19
|
+
*/
|
|
20
|
+
import { spawn } from "node:child_process";
|
|
21
|
+
import { closeSync, mkdirSync, openSync, readFileSync, writeFileSync } from "node:fs";
|
|
22
|
+
import { join } from "node:path";
|
|
23
|
+
import { resolveUserConfigDir } from "../../config/package-paths";
|
|
24
|
+
|
|
25
|
+
/** Shape written before the installer spawns and overwritten by its wrapper. */
|
|
26
|
+
export interface UpdateStatus {
|
|
27
|
+
readonly status: "installing" | "success" | "failed";
|
|
28
|
+
readonly targetTag?: string;
|
|
29
|
+
readonly startedAt: string;
|
|
30
|
+
readonly exitCode?: number;
|
|
31
|
+
/** Last bytes of the installer's stderr, so a failed install is diagnosable. */
|
|
32
|
+
readonly stderrTail?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Age under which a fresh `installing` status means "already running". */
|
|
36
|
+
export const INSTALLING_FRESH_MS = 10 * 60_000;
|
|
37
|
+
|
|
38
|
+
const UPDATE_STATUS_FILE = "update-status.json";
|
|
39
|
+
const UPDATE_LOG_FILE = "update.log";
|
|
40
|
+
|
|
41
|
+
/** How much of the installer's stderr is preserved in a failed status. */
|
|
42
|
+
const STDERR_TAIL_BYTES = 4_096;
|
|
43
|
+
|
|
44
|
+
export function updateStatusPath(configDir: string = resolveUserConfigDir()): string {
|
|
45
|
+
return join(configDir, UPDATE_STATUS_FILE);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function updateLogPath(configDir: string = resolveUserConfigDir()): string {
|
|
49
|
+
return join(configDir, UPDATE_LOG_FILE);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Reads and parses the status file; any absence or corruption answers null. */
|
|
53
|
+
export function readUpdateStatus(configDir: string = resolveUserConfigDir()): UpdateStatus | null {
|
|
54
|
+
try {
|
|
55
|
+
const raw = readFileSync(updateStatusPath(configDir), "utf8");
|
|
56
|
+
const parsed = JSON.parse(raw) as Partial<UpdateStatus> | null;
|
|
57
|
+
if (
|
|
58
|
+
parsed === null ||
|
|
59
|
+
typeof parsed !== "object" ||
|
|
60
|
+
(parsed.status !== "installing" && parsed.status !== "success" && parsed.status !== "failed") ||
|
|
61
|
+
typeof parsed.startedAt !== "string"
|
|
62
|
+
) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
return parsed as UpdateStatus;
|
|
66
|
+
} catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Writes a status atomically enough for this purpose: one rename via write. */
|
|
72
|
+
export function writeUpdateStatus(status: UpdateStatus, configDir: string = resolveUserConfigDir()): void {
|
|
73
|
+
mkdirSync(configDir, { recursive: true });
|
|
74
|
+
writeFileSync(updateStatusPath(configDir), JSON.stringify(status));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** True when a still-`installing` status was written recently enough to trust. */
|
|
78
|
+
export function isFreshlyInstalling(status: UpdateStatus | null, now: number = Date.now()): boolean {
|
|
79
|
+
if (status === null || status.status !== "installing") return false;
|
|
80
|
+
const startedAt = Date.parse(status.startedAt);
|
|
81
|
+
if (!Number.isFinite(startedAt)) return false;
|
|
82
|
+
return now - startedAt < INSTALLING_FRESH_MS;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Processes still running out of the package directory, so npm can rename it.
|
|
87
|
+
*
|
|
88
|
+
* The rename is the whole install on Windows, and it fails with EBUSY while
|
|
89
|
+
* anything holds the directory — including a hold that outlives the process
|
|
90
|
+
* that took it. `carte` itself runs from that directory, so the install has to
|
|
91
|
+
* wait until this process is gone; these are the others.
|
|
92
|
+
*/
|
|
93
|
+
export function stopHoldingProcesses(): void {
|
|
94
|
+
if (process.platform !== "win32") return;
|
|
95
|
+
// `taskkill` filters on the window title and image name only, so it is asked
|
|
96
|
+
// for the two processes this CLI can leave behind. /T takes the tree, so a
|
|
97
|
+
// detached gateway started by a tray goes with it.
|
|
98
|
+
for (const image of ["cartethyia.exe", "carte.exe"]) {
|
|
99
|
+
try {
|
|
100
|
+
spawn("taskkill", ["/F", "/T", "/IM", image], { stdio: "ignore" }).unref();
|
|
101
|
+
} catch {
|
|
102
|
+
// A missing taskkill is not the install's problem; npm will report the
|
|
103
|
+
// hold if one is left.
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export const UPDATE_INSTALL_COMMAND = "npm install -g cartethyia@latest --prefer-online";
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Spawns the detached installer and returns immediately.
|
|
112
|
+
*
|
|
113
|
+
* `stdio` is redirected to `update.log` (append) rather than ignored, so a
|
|
114
|
+
* failed npm run leaves its output behind for the operator. The spawned
|
|
115
|
+
* wrapper re-execs this module's finish step as a `bun -e` script that runs
|
|
116
|
+
* `npm` to completion and then overwrites the status file — see
|
|
117
|
+
* {@link finishDetachedUpdate}, the function the wrapper string mirrors. If the
|
|
118
|
+
* wrapper itself cannot be spawned, the status is flipped to `failed` here so
|
|
119
|
+
* the dashboard's poll loop is not left spinning on a silent `installing`.
|
|
120
|
+
*/
|
|
121
|
+
export function spawnDetachedUpdate(options: {
|
|
122
|
+
readonly targetTag?: string;
|
|
123
|
+
readonly configDir?: string;
|
|
124
|
+
}): { started: boolean; error?: string } {
|
|
125
|
+
const configDir = options.configDir ?? resolveUserConfigDir();
|
|
126
|
+
const isWin = process.platform === "win32";
|
|
127
|
+
const restart = isWin
|
|
128
|
+
? "cartethyia start"
|
|
129
|
+
: "systemctl restart cartethyia 2>/dev/null || cartethyia start";
|
|
130
|
+
const script = `${UPDATE_INSTALL_COMMAND} && ${restart}`;
|
|
131
|
+
const wrapper = buildInstallerWrapperScript(script);
|
|
132
|
+
try {
|
|
133
|
+
stopHoldingProcesses();
|
|
134
|
+
let logFd: number | undefined;
|
|
135
|
+
try {
|
|
136
|
+
mkdirSync(configDir, { recursive: true });
|
|
137
|
+
logFd = openSync(updateLogPath(configDir), "a");
|
|
138
|
+
} catch {
|
|
139
|
+
// A log file that cannot be opened must not block the install; the
|
|
140
|
+
// installer then runs with stdio ignored as before.
|
|
141
|
+
}
|
|
142
|
+
const child = spawn(
|
|
143
|
+
process.execPath,
|
|
144
|
+
["-e", wrapper],
|
|
145
|
+
{ detached: true, stdio: logFd === undefined ? "ignore" : ["ignore", logFd, logFd] },
|
|
146
|
+
);
|
|
147
|
+
child.unref();
|
|
148
|
+
if (logFd !== undefined) {
|
|
149
|
+
try {
|
|
150
|
+
// The parent's copy of the fd is not needed once the child inherits it.
|
|
151
|
+
closeSync(logFd);
|
|
152
|
+
} catch {
|
|
153
|
+
// An unclosed fd in a process that is about to drain and exit is
|
|
154
|
+
// harmless.
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return { started: true };
|
|
158
|
+
} catch (error) {
|
|
159
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
160
|
+
try {
|
|
161
|
+
writeUpdateStatus(
|
|
162
|
+
{ status: "failed", ...(options.targetTag === undefined ? {} : { targetTag: options.targetTag }), startedAt: new Date().toISOString(), stderrTail: message },
|
|
163
|
+
configDir,
|
|
164
|
+
);
|
|
165
|
+
} catch {
|
|
166
|
+
// Nothing more can be reported if even the status write fails.
|
|
167
|
+
}
|
|
168
|
+
return { started: false, error: message };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* The script string handed to `bun -e` (or `node -e`, whatever `process.execPath`
|
|
174
|
+
* is). It mirrors {@link finishDetachedUpdate} because a detached process cannot
|
|
175
|
+
* import this module: it must be one self-contained expression that survives the
|
|
176
|
+
* parent exiting. Kept in this file, next to the function, so the two are
|
|
177
|
+
* reviewed together.
|
|
178
|
+
*/
|
|
179
|
+
function buildInstallerWrapperScript(script: string): string {
|
|
180
|
+
const installer = JSON.stringify(script);
|
|
181
|
+
const shell = JSON.stringify(process.platform === "win32" ? "cmd.exe" : "/bin/sh");
|
|
182
|
+
const argsPrefix = process.platform === "win32" ? '"/c",' : '"-c",';
|
|
183
|
+
const statusPath = JSON.stringify(updateStatusPath());
|
|
184
|
+
return `
|
|
185
|
+
const { spawn } = require("node:child_process");
|
|
186
|
+
const { readFileSync, writeFileSync, openSync } = require("node:fs");
|
|
187
|
+
const startedAt = new Date().toISOString();
|
|
188
|
+
let logFd;
|
|
189
|
+
try { logFd = openSync(${JSON.stringify(updateLogPath())}, "a"); } catch {}
|
|
190
|
+
const child = spawn(${shell}, [${argsPrefix} ${installer}], { stdio: logFd === undefined ? "ignore" : ["ignore", logFd, logFd] });
|
|
191
|
+
let stderrTail = "";
|
|
192
|
+
child.on("exit", (exitCode) => {
|
|
193
|
+
writeFileSync(${statusPath}, JSON.stringify({
|
|
194
|
+
status: exitCode === 0 ? "success" : "failed",
|
|
195
|
+
startedAt,
|
|
196
|
+
exitCode: exitCode ?? -1,
|
|
197
|
+
...(stderrTail ? { stderrTail } : {}),
|
|
198
|
+
}));
|
|
199
|
+
process.exit(exitCode ?? -1);
|
|
200
|
+
});
|
|
201
|
+
child.on("error", (error) => {
|
|
202
|
+
try {
|
|
203
|
+
writeFileSync(${statusPath}, JSON.stringify({ status: "failed", startedAt, exitCode: -1, stderrTail: String(error) }));
|
|
204
|
+
} catch {}
|
|
205
|
+
process.exit(-1);
|
|
206
|
+
});
|
|
207
|
+
`.trim();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Runs the install to completion and records the terminal status. Exported for
|
|
212
|
+
* the test suite, which exercises the same code shape the wrapper string
|
|
213
|
+
* executes; production reaches it only through the detached wrapper.
|
|
214
|
+
*/
|
|
215
|
+
export async function finishDetachedUpdate(
|
|
216
|
+
runInstall: (onStderr: (chunk: string) => void) => Promise<number>,
|
|
217
|
+
configDir: string = resolveUserConfigDir(),
|
|
218
|
+
): Promise<UpdateStatus> {
|
|
219
|
+
const startedAt = new Date().toISOString();
|
|
220
|
+
let stderrTail = "";
|
|
221
|
+
let exitCode: number;
|
|
222
|
+
try {
|
|
223
|
+
exitCode = await runInstall((chunk) => {
|
|
224
|
+
stderrTail = (stderrTail + chunk).slice(-STDERR_TAIL_BYTES);
|
|
225
|
+
});
|
|
226
|
+
} catch (error) {
|
|
227
|
+
const status: UpdateStatus = {
|
|
228
|
+
status: "failed",
|
|
229
|
+
startedAt,
|
|
230
|
+
exitCode: -1,
|
|
231
|
+
stderrTail: (error instanceof Error ? error.message : String(error)).slice(-STDERR_TAIL_BYTES),
|
|
232
|
+
};
|
|
233
|
+
writeUpdateStatus(status, configDir);
|
|
234
|
+
return status;
|
|
235
|
+
}
|
|
236
|
+
const status: UpdateStatus = {
|
|
237
|
+
status: exitCode === 0 ? "success" : "failed",
|
|
238
|
+
startedAt,
|
|
239
|
+
exitCode,
|
|
240
|
+
...(stderrTail ? { stderrTail } : {}),
|
|
241
|
+
};
|
|
242
|
+
writeUpdateStatus(status, configDir);
|
|
243
|
+
return status;
|
|
244
|
+
}
|