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
package/.env.example
CHANGED
|
@@ -61,8 +61,13 @@ CARTETHYIA_PUBLIC_ORIGIN=http://localhost:12800
|
|
|
61
61
|
# CARTETHYIA_ALLOWED_NETWORKS= # Private CIDRs allowed for upstream connections.
|
|
62
62
|
# CARTETHYIA_TELEMETRY_PAYLOAD_DIR=./data/telemetry-payloads # Payload capture directory.
|
|
63
63
|
# CARTETHYIA_CONFIG_DIR= # npm CLI only: directory holding .env. OS default otherwise.
|
|
64
|
+
# CARTETHYIA_USAGE_INPUT_MODE=inclusive # input accounting: inclusive (fold cache into IN) or as-is (raw upstream semantics).
|
|
64
65
|
# DASHBOARD_PORT= # Dashboard dev port override (default 5173, fallback 1931 if occupied).
|
|
65
66
|
# VITE_BACKEND_URL= # Gateway URL for dashboard dev proxy (defaults to http://127.0.0.1:<PORT>).
|
|
67
|
+
# CARTETHYIA_ZCODE_AUTO_CLAIM=false # Set true to claim ZCode gifts daily for active accounts. Manual claim stays available.
|
|
68
|
+
# CARTETHYIA_GITHUB_COPILOT_MODE=opencode-copilot # GitHub Copilot wire identity:
|
|
69
|
+
# opencode-copilot (default, raw GitHub token + minimal headers) or
|
|
70
|
+
# vscode-client-real (minted Copilot token + full VS Code reference headers).
|
|
66
71
|
|
|
67
72
|
# Defaults and overrides. Uncomment only when the built-in default is not
|
|
68
73
|
# suitable. The full list lives in `documentation/reference/configuration.md`;
|
package/README.md
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# Cartethyia
|
|
2
2
|
|
|
3
|
-
<img width="1760" height="576" alt="
|
|
3
|
+
<img width="1760" height="576" alt="og_image" src="https://github.com/user-attachments/assets/1f5f609f-42a3-4556-bfcb-82510f787a50" />
|
|
4
4
|
|
|
5
5
|
**A self-hosted multi-provider AI gateway.**
|
|
6
6
|
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
[](CODE_OF_CONDUCT.md)
|
|
9
|
+
|
|
7
10
|
Cartethyia gives AI clients one stable, OpenAI and Anthropic-compatible endpoint. Behind it, the gateway handles the operational work: provider-aware translation, account selection, health-aware failover, quota and cooldown enforcement, usage accounting, telemetry, and optional proxy pools.
|
|
8
11
|
|
|
9
|
-
Configure provider accounts once, issue an API key, and point OpenCode, Droid, Cline, Claude Code, Codex, or any compatible client at Cartethyia. The client keeps its native protocol; Cartethyia normalizes the request, selects a viable route, dispatches upstream, and returns the response in the contract the client expects.
|
|
12
|
+
Configure provider accounts once, issue an API key, and point OpenCode, Kilo, Droid, Cline, Claude Code, Codex, ZCode, or any compatible client at Cartethyia. The client keeps its native protocol; Cartethyia normalizes the request, selects a viable route, dispatches upstream, and returns the response in the contract the client expects.
|
|
10
13
|
|
|
11
14
|
Built with Bun, TypeScript, Elysia, embedded SQLite or external PostgreSQL, and optional Redis coordination.
|
|
12
15
|
|
|
@@ -77,16 +80,19 @@ and change routing without restarting anything.
|
|
|
77
80
|
|
|
78
81
|
<table>
|
|
79
82
|
<tr>
|
|
80
|
-
<td align="center"><img src="documentation/assets/screenshots/overview.png" width="100%" alt="Overview" /><br /><b>Overview</b><br /><sub>
|
|
83
|
+
<td align="center"><img src="documentation/assets/screenshots/overview.png" width="100%" alt="Overview" /><br /><b>Overview</b><br /><sub>Gateway endpoint, remote support, and compression</sub></td>
|
|
81
84
|
<td align="center"><img src="documentation/assets/screenshots/usage.png" width="100%" alt="Usage" /><br /><b>Usage</b><br /><sub>Volume, latency, cached tokens, spend per model</sub></td>
|
|
82
85
|
</tr>
|
|
83
86
|
<tr>
|
|
84
|
-
<td align="center"><img src="documentation/assets/screenshots/
|
|
87
|
+
<td align="center"><img src="documentation/assets/screenshots/quota-management.png" width="100%" alt="Quota Management" /><br /><b>Quota Management</b><br /><sub>Per-account quota windows, resets, and availability</sub></td>
|
|
88
|
+
<td align="center"><img src="documentation/assets/screenshots/proxy-pool.png" width="100%" alt="Proxy & Requests" /><br /><b>Proxy & Requests</b><br /><sub>Outbound proxy pools: capacity, latency, and health</sub></td>
|
|
89
|
+
</tr>
|
|
90
|
+
<tr>
|
|
85
91
|
<td align="center"><img src="documentation/assets/screenshots/model-lab.png" width="100%" alt="Model Lab" /><br /><b>Model Lab</b><br /><sub>Chat a routed model through the real gateway path</sub></td>
|
|
92
|
+
<td align="center"><img src="documentation/assets/screenshots/cli-tools.png" width="100%" alt="CLI Tools" /><br /><b>CLI Tools</b><br /><sub>Per-CLI model mappings and downloadable config</sub></td>
|
|
86
93
|
</tr>
|
|
87
94
|
<tr>
|
|
88
95
|
<td align="center"><img src="documentation/assets/screenshots/customization.png" width="100%" alt="Customization" /><br /><b>Customization</b><br /><sub>Background, transparency, and per-surface blur</sub></td>
|
|
89
|
-
<td align="center"><img src="documentation/assets/screenshots/settings.png" width="100%" alt="Settings" /><br /><b>Settings</b><br /><sub>Backup, retention, payload capture, update checks</sub></td>
|
|
90
96
|
</tr>
|
|
91
97
|
</table>
|
|
92
98
|
|
|
@@ -176,4 +182,10 @@ suite never touches the runtime `DATABASE_URL`.
|
|
|
176
182
|
## <img src="https://api.iconify.design/lucide/scale.svg?color=%238b949e" width="20" height="20" alt=""> License
|
|
177
183
|
|
|
178
184
|
[GNU GPL v3.0 only](LICENSE). You can use, change, and share it. If you ship a
|
|
179
|
-
build or a fork, ship the source with it, under the same license. No warranty.
|
|
185
|
+
build or a fork, ship the source with it, under the same license. No warranty.
|
|
186
|
+
|
|
187
|
+
## <img src="https://api.iconify.design/lucide/heart.svg?color=%238b949e" width="20" height="20" alt=""> Community
|
|
188
|
+
|
|
189
|
+
- [Contributing](CONTRIBUTING.md) — workflow, code conventions, and pull requests.
|
|
190
|
+
- [Code of Conduct](CODE_OF_CONDUCT.md) — expectations for everyone in the community.
|
|
191
|
+
- [Security Policy](SECURITY.md) — how to report a vulnerability safely.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as e}from"./jsx-runtime-CXUMngI_.js";import{ot as t,t as n}from"./entry-D6WvojeD.js";var r=e();function i(){return(0,r.jsx)(n,{title:`Access Restricted`,description:`Security policy lockout or untrusted origin address`,icon:(0,r.jsx)(t,{size:24}),logoClassName:`bg-red bg-none`,children:(0,r.jsxs)(`div`,{className:`rounded-panel border border-inner-border bg-surface-2 p-7 text-caption leading-relaxed text-text-secondary`,children:[(0,r.jsx)(`strong`,{className:`block text-text-primary mb-2`,children:`HTTP 403 Forbidden`}),`This client IP has been temporarily locked out due to repeated invalid credential attempts or untrusted proxy headers.`]})})}export{i as default};
|
|
Binary file
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{n as e,o as t,r as n,t as r}from"./jsx-runtime-CXUMngI_.js";import{t as i}from"./arrow-left-CpBxkoxI.js";import{E as a,c as o,g as s}from"./numbers-CoqpaDMx.js";import{t as c}from"./circle-check-BU3v_mFW.js";import{t as l}from"./eye-C_hawfH4.js";import{n as u,r as d}from"./state-DHmEnLa2.js";import{t as ee}from"./dialog-BK-NRr5u.js";import{t as te}from"./plus-DIdX_g-x.js";import{t as f}from"./search-JOKus9rb.js";import{t as ne}from"./settings-2-Ds9DQp0t.js";import{l as p}from"./query-keys-YSoQOUh6.js";import{rt as re,tt as ie}from"./entry-D6WvojeD.js";import{n as ae,r as oe,t as se}from"./card-CxDw0lK6.js";import{n as ce}from"./download-dRFo5_Wu.js";import{t as m}from"./switch-DmZcyTIC.js";import{t as h}from"./badge-BaX2GTrn.js";import{n as le}from"./input-BlmlizVV.js";import{t as g}from"./select-BHqpd-bg.js";import{n as ue,t as de}from"./ModelPicker-C6WlpU5E.js";import{t as _}from"./stack-j7cXjgYX.js";import{n as fe}from"./inline-CHJQwxLa.js";import{g as pe,t as v}from"./api-keys-KvX83mRe.js";import{a as me,i as he,n as ge,o as y,r as _e,s as b,t as ve}from"./cli-tools-Bwv5-zGZ.js";import{t as ye}from"./ToolIcon-CfeLA-Z_.js";var be=e(`circle-x`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`m15 9-6 6`,key:`1uzhvr`}],[`path`,{d:`m9 9 6 6`,key:`z0biqf`}]]),x=t(n(),1),S=r();function C({ok:e,label:t,missingLabel:n,title:r}){return e?(0,S.jsxs)(h,{tone:`ok`,dot:!0,title:r,children:[t,` set`]}):(0,S.jsxs)(h,{tone:`warn`,dot:!0,title:r,children:[n??t,` not set`]})}var w=[{id:`@opencode/ai/providers/openai-compatible`,label:`OpenAI Compatible`,protocol:`openai-compatible`,description:`OpenAI chat-completions wire — the default for a gateway like Cartethyia.`},{id:`@opencode/ai/providers/openai/responses`,label:`OpenAI Responses`,protocol:`openai-responses`,description:`OpenAI Responses wire (Responses API).`},{id:`@opencode/ai/providers/anthropic`,label:`Anthropic Messages (official)`,protocol:`anthropic-messages`,description:`Anthropic Messages wire — for Anthropic-compatible endpoints.`},{id:`@opencode/ai/providers/google`,label:`Gemini`,protocol:`gemini`,description:`Google GenerateContent wire — when your gateway exposes Gemini.`}],T=[{id:`@ai-sdk/openai-compatible`,label:`OpenAI Compatible`,protocol:`openai-compatible`,native:`@opencode/ai/providers/openai-compatible`,description:`Kilo's bundled OpenAI-compatible runtime (OpenAI chat format).`},{id:`@ai-sdk/openai`,label:`OpenAI / Responses`,protocol:`openai-responses`,native:`@opencode/ai/providers/openai/responses`,description:`Kilo's bundled OpenAI runtime (Responses API).`},{id:`@ai-sdk/anthropic`,label:`Anthropic Messages`,protocol:`anthropic-messages`,native:`@opencode/ai/providers/anthropic`,description:`Kilo's bundled Anthropic runtime (Messages API).`},{id:`@ai-sdk/google`,label:`Google Gemini`,protocol:`gemini`,native:`@opencode/ai/providers/google`,description:`Kilo's bundled Google runtime (GenerateContent).`}],E=`@opencode/ai/providers/openai-compatible`,D=`@ai-sdk/openai-compatible`;function xe(e){return e===`kilo`?{choices:T,defaultSdk:D}:{choices:w,defaultSdk:E}}function Se(e){return`${e.label} · ${e.id}`}function Ce(e){return e.native?`AI SDK ${e.id} ↔ native ${e.native}`:null}function O(e,t){return e==null?!1:e instanceof Set?e.has(t):e.includes(t)}function k(e){return e==null?0:e instanceof Set?e.size:e.length}function A(e){let t=e.lastIndexOf(`/`);return t<0?e:e.slice(t+1)}function j(e,t,n,r){let i=n?`${n}/${A(t)}`:void 0,a=[t,A(t),...i?[i]:[]];r&&r!==t&&a.push(r);let o=e.model_list;return e.model_access_mode===`blacklist`?a.some(e=>O(o,e))?`model-denied`:null:o==null||k(o)===0||a.some(e=>O(o,e))?null:`model-not-allowed`}function we(e,t,n,r){return j(e,t,n,r)===null}function M(){let{toolId:e}=re(),t=y(),n=b(),r=v(),i=(0,x.useMemo)(()=>t.data?.find(t=>t.id===e)??null,[t.data,e]),a=(0,x.useMemo)(()=>{let t=n.data;if(t)return Array.isArray(t)?t.find(t=>t.toolId===e):t[e]},[n.data,e]);return t.isLoading?(0,S.jsx)(d,{label:`Loading tool details…`}):t.isError?(0,S.jsx)(u,{title:`Unable to load tool`,message:t.error?.message??`Could not load the CLI tool registry.`,onRetry:()=>void t.refetch()}):i?(0,S.jsx)(F,{tool:i,status:a,apiKeys:r.data??[]}):(0,S.jsxs)(_,{gap:`12px`,children:[(0,S.jsx)(ie,{to:`/cli-tools`,className:`text-caption text-accent`,children:`← Back to CLI Tools`}),(0,S.jsx)(u,{title:`Tool not found`,message:`Unknown CLI tool id.`})]})}function N(e){let t=new Set([`settings`,`options`,`headers`,`body`]),n=e=>typeof e==`object`&&!!e&&!Array.isArray(e),r=e=>n(e)?Object.entries(e).some(([e,i])=>t.has(e)&&n(i)?!0:r(i)):!1,i=e=>{if(e===null)return`null`;if(Array.isArray(e))return e.length===0?`[]`:`[${e.map(i).join(`, `)}]`;if(n(e)){let t=Object.entries(e);return t.length===0?`{}`:`{ ${t.map(([e,t])=>`${JSON.stringify(e)}: ${i(t)}`).join(`, `)} }`}return JSON.stringify(e)},a=(e,o,s=!1)=>{let c=` `.repeat(o);if(Array.isArray(e))return e.length===0?`[]`:e.every(e=>!n(e))?i(e):`[\n${e.map(e=>{let t=n(e)&&i(e).length<=85?i(e):a(e,o+1);return`${c} ${t},`}).join(`
|
|
2
|
+
`)}\n${c}]`;if(n(e)){let l=Object.entries(e);if(l.length===0)return`{}`;let u=r(e);return o>0&&!u&&!s&&i(e).length<=85?i(e):`{\n${l.map(([e,r])=>{let s=t.has(e)&&n(r),l=s||!u&&n(r)&&i(r).length<=85?s?a(r,o+1,!0):i(r):a(r,o+1);return`${c} ${JSON.stringify(e)}: ${l}`}).join(`,
|
|
3
|
+
`)}\n${c}}`}return i(e)};return a(e,0)}function P({ok:e,label:t}){return(0,S.jsx)(C,{ok:e,label:t})}function F({tool:e,status:t,apiKeys:n}){let[r,u]=(0,x.useState)(``),[d,re]=(0,x.useState)(()=>typeof window>`u`?`http://localhost:12800`:window.location.origin),[v,y]=(0,x.useState)({}),[b,C]=(0,x.useState)(!1),[w,T]=(0,x.useState)({}),[E,D]=(0,x.useState)(null),[O,k]=(0,x.useState)(`slot`),A=(0,x.useMemo)(()=>xe(e.id),[e.id]),[j,M]=(0,x.useState)(A.defaultSdk),[F,Te]=(0,x.useState)(`carte`),[I,Ee]=(0,x.useState)(!0),[L,R]=(0,x.useState)([]),[De,Oe]=(0,x.useState)(!1),[ke,Ae]=(0,x.useState)(!1),{items:je}=ue(!0),z=(0,x.useRef)(null),Me=(0,x.useMemo)(()=>n.filter(e=>e.keyMode===`personal`||e.keyMode===`share`&&e.parentKeyId===void 0),[n]),B=me(e.id,r),V=he(),H=_e(),U=pe(),W=ge(),G=ve(),K=Me.find(e=>e.id===r),Ne=K?.scopes?.includes(`routing:cli_mapping`)===!0,q=K?.keyMode===`personal`,J=K?.modelAccessMode??`whitelist`,Pe=K?.modelList,Fe=e=>we({model_access_mode:J,model_list:Pe},e),Ie=(0,x.useMemo)(()=>{let t=new Set;if(!e.mappingSupported)return t;for(let n of e.defaultModels){let e=w[n.alias]??``;if(e.length===0)continue;let r=v[n.alias]??n.defaultValue??n.id;!Fe(e)&&!Fe(r)&&t.add(n.alias)}return t},[e.defaultModels,e.mappingSupported,w,v,K]),Le=e=>{if(!K)return;let t=Pe??[],n=J===`blacklist`?t.filter(t=>t!==e):[...new Set([...t,e])];U.mutate({keyId:K.id,request:{modelAccessMode:J,modelList:n}},{onSuccess:()=>s.success(J===`blacklist`?`Model unblocked for this key`:`Model allowed for this key`),onError:e=>s.error(p(e,`Could not update the API key.`))})};(0,x.useEffect)(()=>{let t=Object.fromEntries(e.defaultModels.map(e=>[e.alias,e.defaultValue??e.id]));y(t),T({}),z.current=null},[e,r]),(0,x.useEffect)(()=>{let t=B.data;if(t&&t.apiKeyId===r){if(C(t.enabled),t.mappings.length>0)y(e=>({...e,...Object.fromEntries(t.mappings.map(e=>[e.slotKey,e.sourceModel]))})),T(e=>({...e,...Object.fromEntries(t.mappings.map(e=>[e.slotKey,e.targetModel]))}));else{let t=Object.fromEntries(e.defaultModels.map(e=>[e.alias,e.defaultValue??e.id]));y(t),T({})}z.current=JSON.stringify({enabled:t.enabled,mappings:t.mappings})}},[r,B.data,e.defaultModels]);let Re=t?.installed??!1,Y=t?.configured??!1,X=(0,x.useMemo)(()=>e.defaultModels.map(e=>v[e.alias]??e.defaultValue??e.id),[v,e.defaultModels]),ze=(0,x.useMemo)(()=>[...X,...L.filter(e=>e.trim().length>0)],[X,L]),Z=[r.length>0,d.trim().length>0,ze.length>0].filter(Boolean).length,Q=(0,x.useCallback)(()=>{if(e.mappingSupported)return{enabled:b,mappings:e.defaultModels.filter(e=>(w[e.alias]??``).length>0).map(e=>({slotKey:e.alias,sourceModel:v[e.alias]??e.defaultValue??e.id,targetModel:w[e.alias]??``,enabled:!0})).filter(e=>e.targetModel.length>0)}},[b,w,v,e.defaultModels,e.mappingSupported]);(0,x.useEffect)(()=>{if(!e.mappingSupported||r.length===0)return;let t=B.data;if(!t||t.apiKeyId!==r)return;let n=Q();if(!n)return;let i=JSON.stringify({enabled:n.enabled,mappings:n.mappings});if(i===z.current)return;let a=setTimeout(()=>{V.mutate({toolId:e.id,keyId:r,input:n},{onSuccess:()=>{z.current=i},onError:e=>s.error(p(e,`Could not save mappings.`))})},600);return()=>clearTimeout(a)},[Q,r,B.data,V,e.id,e.mappingSupported]);let $=(0,x.useCallback)(()=>{let t=Object.fromEntries(e.defaultModels.map(e=>[e.alias,v[e.alias]??e.defaultValue??e.id])),n=e.defaultModels.find(e=>e.roleKind===`subagent`),i=[...X,...L.filter(e=>e.trim().length>0)];return{endpoint:d,apiKey:``,modelIds:e.id===`claude`?[]:i,modelSlots:t,...i[0]?{activeModel:i[0]}:{},...n?{subagentModel:v[n.alias]??n.defaultValue??n.id}:{},mappingOwnerId:r,...e.mappingSupported?{mapping:Q()}:{},...e.id===`opencode`||e.id===`kilo`?{sdk:j}:{},...e.id===`opencode`?{websearch:F}:{},...e.id===`opencode`||e.id===`kilo`?{bypassPermissions:I}:{}}},[X,Q,r,d,v,e,j,L,F,I]),Be=(0,x.useMemo)(()=>{let t=$(),n=[...X,...L.filter(e=>e.trim().length>0)],r=`cartethyia`,i=t.endpoint.replace(/\/+$/,``)+`/v1`,a=new Map;for(let e of je)a.set(e.qualified,e);let o=e=>{let t=a.get(e);if(!t)return{name:e};let n=t.entry,r={name:n.modelId};n.contextLimit!==null&&n.outputLimit!==null&&(r.limit={context:n.contextLimit,...n.outputLimit===null?{}:{output:n.outputLimit}});let i=[`text`];return n.vision&&i.push(`image`),n.audio&&i.push(`audio`),n.document&&i.push(`pdf`),r.capabilities={tools:n.toolCall,input:i,output:[`text`],...n.mediaGeneration?{image:!0}:{},...n.reasoning?{reasoning:{supported:!0}}:{}},r},s={};return s=e.id===`opencode`?{$schema:`https://opencode.ai/config.json`,...I?{permissions:[{action:`shell`,resource:`*`,effect:`allow`},{action:`external_directory`,resource:`*`,effect:`allow`},{action:`question`,resource:`*`,effect:`deny`}]}:{},provider:{[r]:{package:j,settings:{baseURL:i,apiKey:`•••••••• (selected key)`},models:Object.fromEntries(n.map(e=>[e,o(e)]))}},model:n[0]?`${r}/${n[0]}`:``,...F?{websearch:{provider:F}}:{}}:e.id===`kilo`?{provider:{[r]:{npm:j,options:{baseURL:t.endpoint,apiKey:`•••••••• (selected key)`},models:Object.fromEntries(n.map(e=>[e,o(e)]))}},model:n[0]?`${r}/${n[0]}`:``}:{note:`No config preview for this tool.`},N(s)},[e.id,j,X,L,F,I,$,je]);return(0,S.jsxs)(_,{gap:`16px`,children:[(0,S.jsxs)(ie,{to:`/cli-tools`,className:`inline-flex items-center gap-3 text-caption text-accent`,children:[(0,S.jsx)(i,{size:14}),`Back to CLI Tools`]}),(0,S.jsx)(se,{children:(0,S.jsxs)(ae,{className:`flex flex-col gap-5`,children:[(0,S.jsxs)(fe,{gap:`14px`,align:`flex-start`,className:`flex-wrap`,children:[(0,S.jsx)(ye,{toolId:e.id,name:e.name,color:e.color,size:46}),(0,S.jsxs)(fe,{gap:`8px`,className:`flex-wrap`,children:[(0,S.jsx)(`h1`,{className:`text-title font-bold m-0`,children:e.name}),Re?(0,S.jsx)(h,{tone:`ok`,children:`Installed`}):(0,S.jsx)(h,{tone:`disabled`,children:`Not installed`}),Y?(0,S.jsx)(h,{tone:`accent`,children:`Configured`}):null]})]}),(0,S.jsx)(`p`,{className:`m-0 text-caption text-text-secondary`,children:e.description}),e.docsUrl?(0,S.jsx)(`a`,{href:e.docsUrl,target:`_blank`,rel:`noreferrer`,className:`inline-block text-caption text-accent`,children:`Official documentation →`}):null,t?.settingsPath?(0,S.jsxs)(`div`,{className:`font-mono tabular-nums px-6 py-4 rounded-inset bg-surface-2 border border-inner-border text-badge text-text-secondary break-all`,children:[`Config file: `,t.settingsPath]}):null,t?.message?(0,S.jsxs)(`div`,{className:`flex items-center gap-3 text-badge ${Y?`text-green`:`text-orange`}`,children:[Y?(0,S.jsx)(c,{size:13}):(0,S.jsx)(be,{size:13}),t.message]}):null]})}),(0,S.jsxs)(se,{children:[(0,S.jsx)(oe,{title:`CLI tool configuration`,subtitle:`Pick the API key, endpoint and models, then apply or download. The key's secret is read server-side — you never paste it.`,subtitleAddon:(0,S.jsxs)(`span`,{className:Z===3?`text-green`:`text-orange`,children:[Z,`/`,3,` set ·`,` `,Z===3?`ready to apply`:`complete the missing fields`]}),icon:(0,S.jsx)(ne,{size:16})}),(0,S.jsx)(ae,{children:(0,S.jsxs)(_,{gap:`20px`,children:[(0,S.jsxs)(`section`,{className:`flex flex-col gap-3`,children:[(0,S.jsxs)(`div`,{className:`flex items-center justify-between gap-4 flex-wrap`,children:[(0,S.jsx)(`h3`,{className:`text-body font-semibold m-0`,children:`Account`}),(0,S.jsxs)(`div`,{className:`flex items-center gap-3 flex-wrap`,children:[(0,S.jsx)(P,{ok:r.length>0,label:`API key`}),(0,S.jsx)(P,{ok:d.trim().length>0,label:`Endpoint`})]})]}),(0,S.jsxs)(`div`,{className:`grid grid-cols-2 gap-4 items-start min-w-0 max-medium:grid-cols-1`,children:[(0,S.jsxs)(`div`,{className:`flex flex-col gap-3 min-w-0`,children:[(0,S.jsx)(g,{label:`Apikey Name`,id:`api-key-select`,value:r,onValueChange:u,options:[{value:``,label:`Select…`},...Me.map(e=>({value:e.id,label:`${e.label} — ${e.keyMode===`personal`?`Personal`:`Share template`}`}))]}),(0,S.jsx)(`div`,{className:`flex items-center gap-3 flex-wrap`,children:K===void 0?(0,S.jsx)(`span`,{className:`mt-1 text-badge text-text-tertiary`,children:`Choose the Apikey Name whose routes this CLI session should use.`}):Ne?(0,S.jsxs)(S.Fragment,{children:[(0,S.jsx)(h,{tone:`ok`,children:`routing:cli_mapping`}),(0,S.jsx)(`span`,{className:`mt-1 text-badge text-text-tertiary`,children:`Remote routes work with this key.`})]}):(0,S.jsxs)(S.Fragment,{children:[(0,S.jsx)(h,{tone:`warn`,title:`This key cannot resolve persisted CLI mappings on /v1/*. Turn on Remote Routing below to enable it.`,children:`no CLI scope`}),(0,S.jsx)(`span`,{className:`mt-1 text-badge text-text-tertiary`,children:`Remote routes stay inert on this key — turning on Remote Routing below will activate it.`})]})}),K?.keyMode===`share`?(0,S.jsx)(`span`,{className:`mt-1 text-badge text-text-tertiary`,children:`Share template: its child keys inherit these routes automatically.`}):null]}),(0,S.jsx)(`div`,{className:`min-w-0`,children:(0,S.jsx)(le,{label:`Endpoint`,value:d,onChange:e=>re(e.target.value)})})]})]}),e.id===`opencode`||e.id===`kilo`?(0,S.jsxs)(`section`,{className:`flex flex-col gap-3 border-t border-inner-border pt-5`,children:[(0,S.jsx)(`h3`,{className:`text-body font-semibold m-0`,children:`Runtime & web search`}),(0,S.jsxs)(`div`,{className:`grid grid-cols-2 gap-4 items-start min-w-0 max-medium:grid-cols-1`,children:[(0,S.jsxs)(`div`,{className:`flex flex-col gap-2 min-w-0`,children:[(0,S.jsx)(g,{label:`Runtime package (SDK)`,id:`sdk-select`,value:j,onValueChange:M,options:A.choices.map(e=>({value:e.id,label:Se(e)}))}),(0,S.jsx)(`p`,{className:`text-micro text-text-tertiary m-0`,children:A.choices.find(e=>e.id===j)?.description??`Runtime package used in the provider config.`}),(0,S.jsx)(`p`,{className:`text-micro font-mono text-text-tertiary m-0 break-all`,children:Ce(A.choices.find(e=>e.id===j))??(e.id===`opencode`?`Native package — bundled with OpenCode`:``)})]}),e.id===`opencode`?(0,S.jsxs)(`div`,{className:`flex flex-col gap-2 min-w-0`,children:[(0,S.jsx)(g,{label:`Web search provider`,id:`websearch-select`,value:F,onValueChange:Te,options:[{value:`carte`,label:`Via Cartethyia (default)`},{value:`random`,label:`Native OpenCode Console`}]}),(0,S.jsx)(`p`,{className:`text-micro text-text-tertiary m-0`,children:F===`carte`?`Search routes through the Cartethyia gateway — no extra key needed.`:`OpenCode's own provider selection (may require an API key or Console billing).`})]}):null,e.id===`opencode`||e.id===`kilo`?(0,S.jsxs)(`div`,{className:`flex flex-col gap-2 min-w-0`,children:[(0,S.jsx)(m,{checked:I,onChange:Ee,label:I?`YOLO mode on`:`YOLO mode off`}),(0,S.jsx)(`p`,{className:`text-micro text-text-tertiary m-0`,children:I?`Auto-approve shell/read/write — permission prompts are skipped (dangerous but convenient).`:`Keep OpenCode's built-in permission prompts (default ask/deny).`})]}):null]})]}):null,(0,S.jsxs)(`section`,{className:`flex flex-col gap-3 border-t border-inner-border pt-5`,children:[(0,S.jsxs)(`div`,{className:`flex items-center justify-between gap-4 flex-wrap`,children:[(0,S.jsx)(`h3`,{className:`text-body font-semibold m-0`,children:`Model routing`}),(0,S.jsx)(P,{ok:ze.length>0,label:`Models`}),e.mappingSupported?(0,S.jsxs)(`div`,{className:`flex items-center gap-4`,children:[(0,S.jsx)(m,{checked:b,disabled:!r,onChange:t=>{if(C(t),!r){s.error(`Select an API key first to configure its Remote Routing.`);return}if(t&&K&&!Ne){let e=[...new Set([...K.scopes??[],`routing:cli_mapping`])];U.mutate({keyId:K.id,request:{scopes:e}},{onSuccess:()=>{s.success(`Activated routing:cli_mapping on "${K.label}".`)},onError:e=>{s.error(p(e,`Could not update key scope.`))}})}let n=Q();n&&V.mutate({toolId:e.id,keyId:r,input:{...n,enabled:t}},{onError:e=>s.error(p(e,`Could not save mappings.`))})},label:b?`Remote Routing on`:`Remote Routing off`}),(0,S.jsx)(o,{variant:`secondary`,size:`sm`,disabled:!r||H.isPending,onClick:()=>{if(!r){s.error(`Select an API key first.`);return}H.mutate({toolId:e.id,keyId:r},{onSuccess:()=>{C(!1),T({}),s.success(`Remote routes cleared and Remote Routing turned off.`)},onError:e=>s.error(p(e,`Could not reset remote routes.`))})},children:H.isPending?`Resetting…`:`Reset`})]}):null]}),(0,S.jsx)(`p`,{className:`text-badge text-text-tertiary m-0`,children:e.mappingSupported?`Left is the model name the CLI asks for. Right is the route Cartethyia sends it to. Leave a target empty to send that slot straight to the provider.`:`The model names written into this tool's config.`}),r?null:(0,S.jsx)(`p`,{className:`text-badge text-text-tertiary`,children:`Select an API key above to load and save remote routes for that key. You can still set models below to apply or download a config file.`}),e.mappingSupported?(0,S.jsxs)(`div`,{className:`mb-5 flex items-center gap-4 rounded-inset border border-inner-border bg-surface-2 px-5 py-3 text-micro text-text-tertiary`,children:[(0,S.jsx)(`span`,{className:`flex-1`,children:`CLI asks for`}),(0,S.jsx)(`span`,{className:`w-9 text-center`,children:`→`}),(0,S.jsx)(`span`,{className:`flex-1`,children:`Cartethyia routes to`})]}):null,(0,S.jsxs)(_,{gap:`6px`,children:[e.defaultModels.map(t=>{let n=v[t.alias]??t.defaultValue??t.id,r=w[t.alias]??``,i=r===n;return(0,S.jsxs)(`div`,{className:`grid items-center gap-4 ${e.mappingSupported?`grid-cols-2`:`grid-cols-1`}`,children:[(0,S.jsxs)(`div`,{className:`flex flex-col gap-1 min-w-0`,children:[(0,S.jsxs)(`button`,{type:`button`,onClick:()=>{D(t.alias),k(`slot`)},className:`font-mono tabular-nums flex w-full min-w-0 cursor-pointer items-center justify-between gap-4 rounded-inset border border-inner-border bg-surface-2 px-5 py-3.5 text-left text-badge text-text-primary`,children:[(0,S.jsx)(`span`,{className:`overflow-hidden truncate whitespace-nowrap`,children:n}),(0,S.jsx)(f,{size:12,className:`text-text-tertiary shrink-0`})]}),(0,S.jsx)(`span`,{className:`text-micro text-text-tertiary pl-1`,children:t.roleLabel??t.name})]}),e.mappingSupported?(0,S.jsxs)(`div`,{className:`flex flex-col gap-1 min-w-0`,children:[(0,S.jsxs)(`button`,{type:`button`,onClick:()=>{D(t.alias),k(`target`)},className:`font-mono tabular-nums flex w-full min-w-0 cursor-pointer items-center justify-between gap-4 rounded-inset border px-5 py-3.5 text-left text-badge ${i?`border-inner-border bg-surface-2 text-text-tertiary`:`border-accent bg-accent-soft text-text-primary`}`,children:[(0,S.jsx)(`span`,{className:`overflow-hidden truncate whitespace-nowrap`,children:r.length>0?r:`Not routed`}),(0,S.jsx)(f,{size:12,className:`text-text-tertiary shrink-0`})]}),(0,S.jsxs)(`span`,{className:`pl-1 text-micro ${r.length===0?`text-text-tertiary`:`text-accent`}`,children:[r.length===0?`not routed`:`rerouted`,r.length>0?(0,S.jsx)(`button`,{type:`button`,onClick:()=>T(e=>({...e,[t.alias]:``})),className:`ml-3 border-none bg-none p-0 text-micro text-text-tertiary cursor-pointer underline`,children:`clear`}):null]}),Ie.has(t.alias)?(0,S.jsxs)(`span`,{className:`mt-1 flex items-center gap-3 text-micro text-orange`,children:[(0,S.jsx)(`span`,{children:J===`blacklist`?`This key blocks the target model.`:`This key does not allow the target model.`}),(0,S.jsx)(`button`,{type:`button`,disabled:U.isPending,onClick:()=>Le(r),className:`border-none bg-none p-0 text-micro font-semibold text-accent underline ${U.isPending?`cursor-not-allowed`:`cursor-pointer`}`,children:J===`blacklist`?`Unblock`:`Allow this model`})]}):null]}):null]},t.alias)}),e.id===`opencode`||e.id===`kilo`?(0,S.jsxs)(S.Fragment,{children:[(0,S.jsx)(`div`,{className:`flex flex-col gap-2`,children:L.map((e,t)=>(0,S.jsxs)(`div`,{className:`flex items-center gap-3 rounded-inset border border-inner-border bg-surface-2 px-4 py-2.5`,children:[(0,S.jsx)(`span`,{className:`font-mono tabular-nums text-badge text-text-primary flex-1 truncate`,children:e||`\xA0`}),(0,S.jsx)(o,{variant:`ghost`,size:`sm`,onClick:()=>R(e=>e.filter((e,n)=>n!==t)),children:`Remove`})]},`extra-${t}`))}),(0,S.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,S.jsx)(o,{variant:`secondary`,size:`sm`,icon:(0,S.jsx)(te,{size:14}),onClick:()=>Oe(!0),children:`Add models…`})})]}):null]})]}),(0,S.jsxs)(`section`,{className:`flex flex-col gap-3 border-t border-inner-border pt-5`,children:[(0,S.jsx)(`h3`,{className:`text-body font-semibold m-0`,children:`Write config`}),(0,S.jsx)(`p`,{className:`text-badge text-text-tertiary m-0`,children:`Write the config on this machine (with a .bak backup), or download it for manual placement. The selected API key secret is decrypted automatically.`}),(0,S.jsxs)(`div`,{className:`flex gap-4 flex-wrap justify-end`,children:[(0,S.jsx)(o,{variant:`ghost`,icon:(0,S.jsx)(l,{size:14}),onClick:()=>Ae(!0),disabled:!r,children:`Preview config`}),(0,S.jsx)(o,{variant:`secondary`,icon:(0,S.jsx)(c,{size:14}),onClick:()=>{if(!r){s.error(`Select an API key first.`);return}G.mutate({toolId:e.id,keyId:r,input:{...$(),mode:`both`}},{onSuccess:e=>{s.success(e.wroteFile?`Config written${e.settingsPath?` to ${e.settingsPath}`:``} (backup .bak created).`:e.message)},onError:e=>s.error(p(e,`Could not apply config.`))})},disabled:G.isPending||!q,children:G.isPending?`Applying…`:`Apply & cek`}),(0,S.jsx)(o,{variant:`primary`,icon:(0,S.jsx)(a,{size:14}),onClick:()=>{if(!r){s.error(`Select an API key first.`);return}W.mutate({toolId:e.id,keyId:r,input:$()},{onSuccess:e=>{ce(e.filename,e.content,e.mimeType),s.success(`Downloaded ${e.filename}.`)},onError:e=>s.error(p(e,`Could not download config.`))})},disabled:W.isPending||!q,children:W.isPending?`Downloading…`:`Download config`})]}),q?null:(0,S.jsx)(`p`,{className:`text-badge text-text-tertiary text-right`,children:K?.keyMode===`share`?`A share template has no secret to write into a config. Select a personal key to write or download the config file.`:`Select an Apikey Name above to enable applying or downloading the config file.`})]})]})})]}),(0,S.jsx)(de,{open:E!==null,onClose:()=>D(null),selected:E?[O===`target`?w[E]??v[E]??``:v[E]??``]:[],onToggle:()=>{},onSelectOne:e=>{if(E){if(O===`target`)T(t=>({...t,[E]:e}));else if(E.startsWith(`extra-`)){let t=Number(E.slice(6));Number.isFinite(t)&&R(n=>{let r=[...n];return r[t]=e,r})}else y(t=>({...t,[E]:e}))}D(null)},title:E?`Select ${E} model`:`Select model`,multi:!1}),(0,S.jsx)(de,{open:De,onClose:()=>Oe(!1),selected:L,onToggle:e=>{R(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e])},title:`Select models`,multi:!0}),(0,S.jsx)(ee,{open:ke,onClose:()=>Ae(!1),title:`Config preview`,size:`lg`,children:(0,S.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,S.jsxs)(`p`,{className:`text-micro text-text-tertiary m-0`,children:[`This is the JSON that will be written (or downloaded) for `,e.name,`. Existing providers in your config are kept as-is — only`,` `,(0,S.jsx)(`span`,{className:`font-mono`,children:`cartethyia`}),` is added/updated.`]}),(0,S.jsx)(`pre`,{className:`m-0 max-h-[60vh] overflow-auto rounded-inset border border-inner-border bg-surface-2 p-5 font-mono text-badge text-text-primary whitespace-pre-wrap break-all`,children:Be})]})})]})}export{M as default,N as stringifyFlat};
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{o as e,r as t,t as n}from"./jsx-runtime-CXUMngI_.js";import{t as r}from"./terminal-0_IjPWTk.js";import{n as i,r as a,t as o}from"./state-DHmEnLa2.js";import{tt as s}from"./entry-D6WvojeD.js";import{n as c,r as l,t as u}from"./card-CxDw0lK6.js";import{t as d}from"./badge-BaX2GTrn.js";import{t as f}from"./stack-j7cXjgYX.js";import{n as p}from"./inline-CHJQwxLa.js";import{o as m,s as h}from"./cli-tools-Bwv5-zGZ.js";import{t as g}from"./ToolIcon-CfeLA-Z_.js";import{n as _}from"./layout-Bz93I-yE.js";var v=e(t(),1),y=n();function b(){let e=m(),t=h(),n=(0,v.useMemo)(()=>{let e=new Map,n=t.data;if(!n)return e;if(Array.isArray(n))for(let t of n)t?.toolId&&e.set(t.toolId,t);else if(typeof n==`object`)for(let[t,r]of Object.entries(n))r&&e.set(r.toolId||t,r);return e},[t.data]);if(e.isLoading)return(0,y.jsx)(a,{label:`Loading CLI tools…`});if(e.isError||!e.data)return(0,y.jsx)(i,{title:`Unable to load CLI tools`,message:e.error?.message??`Could not load the CLI tools registry.`,onRetry:()=>void e.refetch()});let b=e.data,x=b.filter(e=>n.get(e.id)?.configured).length;return b.length===0?(0,y.jsx)(`div`,{className:`flex-1 flex items-center justify-center p-12 border border-dashed border-transparent rounded-card bg-transparent text-center`,children:(0,y.jsx)(o,{title:`No CLI tools registered`,message:`The registry is empty, so there is nothing to configure yet.`})}):(0,y.jsx)(f,{gap:`16px`,children:(0,y.jsxs)(u,{children:[(0,y.jsx)(l,{title:`CLI Tools`,subtitle:`${x}/${b.length} tools configured`,icon:(0,y.jsx)(r,{size:16}),action:(0,y.jsx)(d,{tone:`accent`,children:`${b.length} tools`})}),(0,y.jsx)(c,{className:`flex flex-col gap-8`,children:(0,y.jsxs)(`section`,{className:`flex flex-col gap-6`,children:[(0,y.jsx)(_,{title:`Supported tools (${b.length})`,description:`Direct config file writing and preset model mappings`}),(0,y.jsx)(`div`,{className:`provider-grid grid gap-6 w-full min-w-0`,children:b.map(e=>{let t=n.get(e.id);return(0,y.jsx)(u,{interactive:!0,className:`relative overflow-hidden rounded-panel`,children:(0,y.jsx)(s,{to:`/cli-tools/${e.id}`,className:`no-underline text-inherit block p-6`,children:(0,y.jsxs)(p,{gap:`10px`,children:[(0,y.jsx)(g,{toolId:e.id,name:e.name,color:e.color,size:32}),(0,y.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,y.jsx)(`div`,{className:`text-body font-semibold overflow-hidden truncate whitespace-nowrap`,children:e.name}),(0,y.jsx)(`div`,{className:`mt-1.5`,children:t?.configured?(0,y.jsx)(d,{tone:`ok`,dot:!0,children:`Configured`}):t?.installed?(0,y.jsx)(d,{tone:`warn`,dot:!0,children:`Installed`}):(0,y.jsx)(d,{children:`Not installed`})})]}),(0,y.jsxs)(`div`,{className:`flex flex-col items-end gap-1.5 shrink-0`,children:[(0,y.jsx)(`span`,{className:`font-mono tabular-nums text-micro font-semibold bg-kbd-bg py-0.5 px-2.5 rounded-tiny text-text-secondary`,children:e.id}),e.surface?(0,y.jsx)(d,{tone:`default`,children:e.surface}):null]})]})})},e.id)})})]})})]})})}export{b as default};
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e,o as t,r as n,t as r}from"./jsx-runtime-CXUMngI_.js";import{t as i}from"./arrow-right-Dl5yKnp8.js";import{D as a,c as o,g as s}from"./numbers-CoqpaDMx.js";import{a as c,i as l,o as u,r as d,s as f,t as p}from"./InjectSystemPromptPanel-d5v3K_Yc.js";import{t as m}from"./circle-question-mark-Cz4un8sH.js";import{t as h}from"./image-BPaouViG.js";import{n as ee,r as g,t as _}from"./state-DHmEnLa2.js";import{t as v}from"./layers-2-glBbjl.js";import{r as y}from"./use-modal-focus-By7oJoGd.js";import{t as b}from"./dialog-BK-NRr5u.js";import{t as te}from"./pencil-768ysRAr.js";import{t as ne}from"./plus-DIdX_g-x.js";import{t as x}from"./route-CNSNj9Zm.js";import{t as re}from"./search-JOKus9rb.js";import{t as ie}from"./trash-Cppn5c3R.js";import{l as S}from"./query-keys-YSoQOUh6.js";import{t as ae}from"./dialog-actions-B1axpEg7.js";import{B as C}from"./entry-D6WvojeD.js";import{n as w,r as T,t as E}from"./card-CxDw0lK6.js";import{t as oe}from"./use-clipboard-B0Sy03fE.js";import{t as D}from"./badge-BaX2GTrn.js";import{n as se,r as O}from"./input-BlmlizVV.js";import{t as k}from"./select-BHqpd-bg.js";import{t as A}from"./ModelPicker-C6WlpU5E.js";import{t as j}from"./stack-j7cXjgYX.js";import{n as M,t as ce}from"./inline-CHJQwxLa.js";import{n as N,t as P}from"./settings-BxslsErn.js";import{a as le,d as F,f as I,i as L,n as R,o as ue,p as z,r as de,s as B,t as fe,u as V}from"./routing-fnCsxgNO.js";import{t as H}from"./list-row-Ml16KCfu.js";import{t as pe}from"./use-timeout-BwcBBRrT.js";var me=e(`copy-plus`,[[`line`,{x1:`15`,x2:`15`,y1:`12`,y2:`18`,key:`1p7wdc`}],[`line`,{x1:`12`,x2:`18`,y1:`15`,y2:`15`,key:`1nscbv`}],[`rect`,{width:`14`,height:`14`,x:`8`,y:`8`,rx:`2`,ry:`2`,key:`17jyea`}],[`path`,{d:`M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2`,key:`zix9uf`}]]),U=t(n(),1),W=r(),G=[{value:`append`,label:`Append`},{value:`override`,label:`Override`}];function K(e,t){if(e.kind===`off`)return{label:`Off`,active:!1};if(e.kind===`global`)return{label:`Following global`,active:!1};if(e.kind===`preset`){let n=t[e.presetId];return{label:`Preset · ${n?.name??e.presetId}`,active:n?.enabled===!0}}return{label:e.setting.enabled?`Custom`:`Custom off`,active:e.setting.enabled}}function he({kind:e,name:t,value:n,onChange:r,presets:i}){let a=n,{label:o,active:s}=K(a,i),c=a.kind,l=Object.values(i);return(0,W.jsxs)(`div`,{className:`rounded-control border border-inner-border bg-surface-2 p-4`,children:[(0,W.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,W.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2.5`,children:[(0,W.jsx)(f,{size:14,className:`shrink-0 text-text-tertiary`,"aria-hidden":`true`}),(0,W.jsx)(`p`,{className:`text-caption font-semibold text-text-primary`,children:`System prompt`})]}),(0,W.jsx)(D,{tone:s?`ok`:`default`,dot:!0,className:`shrink-0`,children:o})]}),(0,W.jsxs)(`div`,{className:`mt-3 grid grid-cols-4 gap-2 max-small:grid-cols-2`,role:`radiogroup`,"aria-label":`System prompt source`,children:[(0,W.jsxs)(`label`,{className:`flex cursor-pointer items-center justify-center gap-2 rounded-control border border-inner-border bg-surface-2 px-2 py-2 text-badge font-medium text-text-primary select-none has-checked:border-accent has-checked:bg-accent-soft`,children:[(0,W.jsx)(`input`,{type:`radio`,name:`scp-${e}-${t}`,checked:c===`off`,onChange:()=>r({kind:`off`}),className:`accent-accent`}),`Off`]}),(0,W.jsxs)(`label`,{className:`flex cursor-pointer items-center justify-center gap-2 rounded-control border border-inner-border bg-surface-2 px-2 py-2 text-badge font-medium text-text-primary select-none has-checked:border-accent has-checked:bg-accent-soft`,children:[(0,W.jsx)(`input`,{type:`radio`,name:`scp-${e}-${t}`,checked:c===`global`,onChange:()=>r({kind:`global`}),className:`accent-accent`}),`Global`]}),(0,W.jsxs)(`label`,{className:`flex cursor-pointer items-center justify-center gap-2 rounded-control border border-inner-border bg-surface-2 px-2 py-2 text-badge font-medium text-text-primary select-none has-checked:border-accent has-checked:bg-accent-soft`,children:[(0,W.jsx)(`input`,{type:`radio`,name:`scp-${e}-${t}`,checked:c===`preset`,onChange:()=>{let e=l.find(e=>e.enabled)??l[0];r(e?{kind:`preset`,presetId:e.id}:{kind:`global`})},className:`accent-accent`}),`Preset`]}),(0,W.jsxs)(`label`,{className:`flex cursor-pointer items-center justify-center gap-2 rounded-control border border-inner-border bg-surface-2 px-2 py-2 text-badge font-medium text-text-primary select-none has-checked:border-accent has-checked:bg-accent-soft`,children:[(0,W.jsx)(`input`,{type:`radio`,name:`scp-${e}-${t}`,checked:c===`custom`,onChange:()=>r({kind:`custom`,setting:{enabled:!0,mode:`append`,text:``}}),className:`accent-accent`}),`Custom`]})]}),c===`preset`?(0,W.jsxs)(`div`,{className:`mt-3`,children:[(0,W.jsx)(k,{"aria-label":`Preset`,value:a.kind===`preset`?a.presetId:``,onValueChange:e=>r({kind:`preset`,presetId:e}),options:l.map(e=>({value:e.id,label:`${e.name}${e.enabled?``:` (off)`}`})),size:`sm`,className:`w-full`}),l.length===0?(0,W.jsx)(`p`,{className:`mt-2 text-badge text-text-tertiary`,children:`No presets yet — create one in Inject System Prompt first.`}):null]}):null,c===`custom`?(0,W.jsxs)(`div`,{className:`mt-3`,children:[(0,W.jsxs)(`div`,{className:`mb-2 flex items-center gap-3`,children:[(0,W.jsx)(k,{"aria-label":`Injection mode`,value:a.kind===`custom`?a.setting.mode:`append`,onValueChange:e=>r({kind:`custom`,setting:{enabled:!0,mode:e,text:a.kind===`custom`?a.setting.text:``}}),options:G,size:`sm`,className:`w-40`}),a.kind===`custom`?(0,W.jsxs)(`span`,{className:`text-badge tabular-nums text-text-tertiary`,children:[a.setting.text.length.toLocaleString(),` chars`]}):null]}),(0,W.jsx)(O,{id:`scp-${e}-${t}-text`,rows:4,value:a.kind===`custom`?a.setting.text:``,onChange:e=>r({kind:`custom`,setting:{enabled:!0,mode:a.kind===`custom`?a.setting.mode:`append`,text:e.target.value}}),placeholder:`Injected system prompt…`})]}):null]})}var q=[{value:`fallback`,label:`Fallback (try in order)`},{value:`round_robin`,label:`Round Robin (rotate)`}],J=()=>`m${Date.now().toString(36)}${Math.random().toString(36).slice(2,8)}`;function Y(){let e=ue(),t=R(),n=I(),r=L(),f=V(),[m,h]=(0,U.useState)(!1),[v,y]=(0,U.useState)(null),[D,O]=(0,U.useState)(``),[k,N]=(0,U.useState)(``),[P,le]=(0,U.useState)(!1),[F,z]=(0,U.useState)(null),[de,B]=(0,U.useState)(null),{copy:fe}=oe(),me=pe(),G=l(),K=c(),q=d(G.data??p),[J,Y]=(0,U.useState)({kind:`global`}),X=(0,U.useMemo)(()=>e.data??[],[e.data]),Z=()=>{y(null),O(``),N(``),h(!0)},ge=e=>{y(e),O(e.alias),N(e.targetModel),Y(q.aliases[e.alias]??{kind:`global`}),h(!0)},_e=e=>{if(e.preventDefault(),D.trim()&&k.trim()){if(v){let e=D.trim();n.mutate({id:v.id,request:{alias:e,targetModel:k.trim()}},{onSuccess:()=>{let t={...q,aliases:{...q.aliases,[e]:J}};v.alias!==e&&delete t.aliases[v.alias],K.mutate(t,{onError:e=>s.error(S(e,`Could not update system prompt.`))}),h(!1),y(null),s.success(`Alias updated`)},onError:e=>s.error(S(e,`Could not save the alias.`))})}else t.mutate({alias:D.trim(),targetModel:k.trim()},{onSuccess:()=>{h(!1),O(``),N(``),s.success(`Alias created`)},onError:e=>s.error(S(e,`Could not create the alias.`))})}},ve=(e,t)=>{fe(e).then(e=>{if(!e){s.error(`Copy failed`);return}B(t),me(()=>B(null),1500)})};return(0,W.jsxs)(E,{children:[(0,W.jsx)(T,{title:`Model Aliases`,subtitle:`Map readable names to real models (e.g. claude-mythos-5 → claude-opus-5)`,icon:(0,W.jsx)(x,{size:16}),action:(0,W.jsx)(ce,{children:(0,W.jsx)(o,{variant:`primary`,size:`sm`,icon:(0,W.jsx)(ne,{size:13}),onClick:Z,children:`New Alias`})})}),(0,W.jsx)(w,{children:e.isPending?(0,W.jsx)(g,{label:`Loading aliases...`}):e.isError?(0,W.jsx)(ee,{message:`Failed to load aliases`,onRetry:()=>e.refetch()}):X.length===0?(0,W.jsx)(_,{title:`No aliases defined`,message:`Create an alias to route short or friendly names to real provider model IDs.`}):(0,W.jsx)(u,{items:X,label:`Model aliases`,gap:`8px`,disabled:f.isPending,onReorder:e=>f.mutate(e,{onError:e=>s.error(S(e,`Could not save the new order.`))}),renderItem:e=>(0,W.jsx)(H,{className:`items-start flex-col sm:flex-row`,actions:(0,W.jsxs)(M,{gap:`4px`,className:`w-full justify-start sm:w-auto sm:justify-end`,children:[(0,W.jsx)(o,{variant:`ghost`,size:`sm`,icon:(0,W.jsx)(a,{size:13}),onClick:()=>ve(e.alias,e.id),title:de===e.id?`Copied!`:`Copy alias`}),(0,W.jsx)(o,{variant:`ghost`,size:`sm`,icon:(0,W.jsx)(te,{size:13}),onClick:()=>ge(e),title:`Edit target model`}),(0,W.jsx)(o,{variant:`ghost`,size:`sm`,icon:(0,W.jsx)(ie,{size:13}),onClick:()=>z(e),title:`Delete alias`,className:`text-red`})]}),children:(0,W.jsxs)(`div`,{className:`flex items-center gap-4 flex-wrap min-w-0`,children:[(0,W.jsx)(C,{value:e.alias,tone:`accent`}),(0,W.jsx)(i,{size:13,className:`text-text-tertiary shrink-0`}),(0,W.jsx)(C,{value:e.targetModel,tone:`plain`})]})})})}),(0,W.jsx)(b,{open:m,onClose:()=>h(!1),title:v?`Edit Model Alias`:`New Model Alias`,footer:(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(o,{variant:`secondary`,type:`button`,onClick:()=>h(!1),children:`Cancel`}),(0,W.jsx)(o,{variant:`primary`,type:`submit`,form:`alias-form`,disabled:t.isPending||n.isPending||!D.trim()||!k.trim(),children:v?`Save Changes`:`Create Alias`})]}),children:(0,W.jsxs)(`form`,{id:`alias-form`,onSubmit:_e,className:`flex flex-col gap-6`,children:[(0,W.jsx)(se,{label:`Alias name`,id:`alias-name-input`,value:D,onChange:e=>O(e.target.value),placeholder:`e.g. fast, sonnet, smart`,required:!0}),(0,W.jsxs)(M,{gap:`8px`,align:`flex-end`,children:[(0,W.jsx)(`div`,{className:`flex-1`,children:(0,W.jsx)(se,{label:`Target model`,id:`target-model-input`,value:k,onChange:e=>N(e.target.value),placeholder:`e.g. codex/gpt-5.5, claude/claude-sonnet-5`,required:!0})}),(0,W.jsx)(o,{variant:`secondary`,size:`sm`,type:`button`,onClick:()=>le(!0),icon:(0,W.jsx)(re,{size:13}),children:`Browse`})]}),(0,W.jsx)(A,{open:P,onClose:()=>le(!1),selected:k?[k]:[],onToggle:()=>{},onSelectOne:e=>N(e),title:`Select target model`,multi:!1}),v?(0,W.jsx)(he,{kind:`alias`,name:v.alias,value:J,onChange:Y,presets:q.presets}):null]})}),(0,W.jsx)(b,{open:!!F,onClose:()=>z(null),title:`Delete Model Alias`,children:(0,W.jsxs)(j,{gap:`12px`,children:[(0,W.jsxs)(`p`,{className:`text-body text-text-secondary`,children:[`Are you sure you want to delete alias `,(0,W.jsx)(`strong`,{children:F?.alias}),`? Clients requesting this name will need their full model path.`]}),(0,W.jsxs)(ae,{children:[(0,W.jsx)(o,{variant:`secondary`,onClick:()=>z(null),children:`Cancel`}),(0,W.jsx)(o,{variant:`danger`,onClick:()=>{F&&r.mutate(F.id,{onSuccess:()=>z(null)})},disabled:r.isPending,children:r.isPending?`Deleting...`:`Delete Alias`})]})]})})]})}function X(e){return e.kind===`model`&&e.entry.vision===!0}function Z(){let e=P(),t=N(),[n,r]=(0,U.useState)(!1),[i,a]=(0,U.useState)(!1),c=e.data,l=c?.visionHandoffModels??[],[d,f]=(0,U.useState)([]);(0,U.useEffect)(()=>{f(l.map(e=>({id:`v${e}`,value:e})))},[c]);let p=(e,n)=>{t.mutate(e,{onSuccess:()=>s.success(n),onError:e=>s.error(S(e,`Could not update vision handoff.`))})},v=e=>{let t=d.some(t=>t.value===e)?d.filter(t=>t.value!==e):[...d,{id:`v${e}-${d.length}`,value:e}];f(t),p({visionHandoffModels:t.map(e=>e.value)},`Vision handoff models updated.`)};return e.isPending?(0,W.jsx)(g,{label:`Loading vision handoff settings…`}):e.isError||!c?(0,W.jsx)(ee,{message:S(e.error,`Failed to load runtime settings`),onRetry:()=>void e.refetch()}):(0,W.jsxs)(E,{children:[(0,W.jsx)(T,{title:(0,W.jsxs)(`span`,{className:`inline-flex items-center gap-2.5`,children:[`Vision Handoff`,(0,W.jsx)(`span`,{className:`badge border border-warning-line bg-surface-2 text-micro tracking-label text-status-warning`,children:`BETA`})]}),subtitle:`When the selected model cannot see images, describe them with a vision model first`,icon:(0,W.jsx)(h,{size:16}),action:(0,W.jsxs)(ce,{children:[(0,W.jsx)(o,{variant:`ghost`,size:`sm`,icon:(0,W.jsx)(m,{size:14}),"aria-label":`How vision handoff works`,onClick:()=>a(!0),children:`How it works`}),(0,W.jsx)(o,{variant:`secondary`,size:`sm`,icon:(0,W.jsx)(ne,{size:13}),onClick:()=>r(!0),children:`Pick models`})]})}),(0,W.jsx)(w,{children:d.length===0?(0,W.jsx)(_,{title:`No vision handoff models`,message:`Add an ordered list of image-capable models. When a request carries an image but the chosen model cannot see it, the gateway will ask the first healthy model on this list to describe it and pass that description to the chosen model as text.`}):(0,W.jsx)(u,{items:d,label:`Vision handoff models`,gap:`6px`,onReorder:e=>{let t=new Map(d.map(e=>[e.id,e])),n=e.map(e=>t.get(e)).filter(e=>!!e);f(n),p({visionHandoffModels:n.map(e=>e.value)},`Vision handoff order updated.`)},renderItem:e=>(0,W.jsx)(H,{density:`compact`,actions:(0,W.jsx)(`button`,{type:`button`,"aria-label":`Remove ${e.value}`,onClick:()=>v(e.value),className:`grid size-7 cursor-pointer place-items-center rounded-control text-text-tertiary hover:bg-hover`,children:(0,W.jsx)(y,{size:12})}),children:(0,W.jsxs)(`div`,{className:`flex items-center gap-3 min-w-0`,children:[(0,W.jsx)(h,{size:14,className:`shrink-0 text-text-tertiary`}),(0,W.jsx)(C,{value:e.value,tone:`accent`})]})})})}),(0,W.jsx)(A,{open:n,onClose:()=>r(!1),selected:d.map(e=>e.value),onToggle:v,title:`Select vision models`,multi:!0,filter:X}),(0,W.jsx)(b,{open:i,onClose:()=>a(!1),title:`How vision handoff works`,size:`md`,children:(0,W.jsxs)(`div`,{className:`flex flex-col gap-4 text-badge leading-relaxed text-text-secondary`,children:[(0,W.jsxs)(`p`,{children:[(0,W.jsx)(`strong`,{children:`Vision handoff`}),` lets a text-only model still answer when a request carries images. The gateway sends the image to the first healthy model on your list and injects its description as text back into the conversation — the chosen model never sees the raw image, only the description.`]}),(0,W.jsx)(`p`,{children:`The list is ordered: drag models to set priority. The first healthy model wins; if it fails (cooldown, quota, upstream error), the handoff falls to the next entry.`}),(0,W.jsxs)(`p`,{children:[(0,W.jsx)(`strong`,{children:`Empty list`}),` keeps the legacy`,` `,(0,W.jsx)(`code`,{children:`[image]`}),` placeholder behavior — the raw image marker is passed through instead of a description.`]}),(0,W.jsx)(`p`,{className:`text-micro text-text-tertiary`,children:`Only image-capable chat models are offered in the picker.`})]})})]})}function ge(){let e=B(),t=de(),n=fe(),r=z(),i=le(),f=F(),[m,h]=(0,U.useState)(!1),[x,D]=(0,U.useState)(null),[O,N]=(0,U.useState)(``),[P,I]=(0,U.useState)([]),[L,R]=(0,U.useState)(`fallback`),[ue,V]=(0,U.useState)(!1),[G,K]=(0,U.useState)(null),[Y,X]=(0,U.useState)(null),{copy:Z}=oe(),ge=pe(),_e=l(),ve=c(),Q=d(_e.data??p),[ye,be]=(0,U.useState)({kind:`global`}),$=(0,U.useMemo)(()=>P.map(e=>e.value),[P]),xe=e=>{$.includes(e)?I(P.filter(t=>t.value!==e)):I([...P,{id:J(),value:e.trim()}])},Se=e.data??[],Ce=()=>{D(null),N(``),I([]),R(`fallback`),h(!0)},we=e=>{D(e),N(e.name),be(Q.combos[e.name]??{kind:`global`}),I(e.members.map(e=>({id:J(),value:e}))),h(!0)},Te=e=>{n.mutate(e.id,{onSuccess:e=>{let t=e.skippedMembers;t.length>0?s.success(`Combo cloned`,`${e.combo.name} — skipped unresolvable member${t.length>1?`s`:``}: ${t.join(`, `)}`):s.success(`Combo cloned`,e.combo.name)},onError:e=>s.error(S(e,`Could not clone the combo.`))})},Ee=e=>{if(e.preventDefault(),O.trim()&&$.length!==0){if(x){let e=O.trim();r.mutate({id:x.id,request:{name:e,members:$,strategy:L}},{onSuccess:()=>{let t={...Q,combos:{...Q.combos,[e]:ye}};x.name!==e&&delete t.combos[x.name],ve.mutate(t,{onError:e=>s.error(S(e,`Could not update system prompt.`))}),h(!1),D(null),s.success(`Combo saved`)},onError:e=>s.error(S(e,`Could not save the combo.`))})}else t.mutate({name:O.trim(),members:$,strategy:L},{onSuccess:()=>{h(!1),N(``),I([]),s.success(`Combo created`)},onError:e=>s.error(S(e,`Could not create the combo.`))})}},De=(e,t)=>{r.mutate({id:e.id,request:{strategy:t}},{onSuccess:()=>s.success(`Combo strategy updated`),onError:e=>s.error(S(e,`Could not update the combo strategy.`))})},Oe=(e,t)=>{Z(e).then(e=>{if(!e){s.error(`Copy failed`);return}X(t),ge(()=>X(null),1500)})};return(0,W.jsxs)(E,{children:[(0,W.jsx)(T,{title:`Combos`,subtitle:`Combine multiple models with fallback or round-robin rotation`,icon:(0,W.jsx)(v,{size:16}),action:(0,W.jsx)(ce,{children:(0,W.jsx)(o,{variant:`primary`,size:`sm`,icon:(0,W.jsx)(ne,{size:13}),onClick:Ce,children:`New Combo`})})}),(0,W.jsx)(w,{children:e.isPending?(0,W.jsx)(g,{label:`Loading combos...`}):e.isError?(0,W.jsx)(ee,{message:`Failed to load combos`,onRetry:()=>e.refetch()}):Se.length===0?(0,W.jsx)(_,{title:`No combos defined`,message:`Create a model combo to distribute requests across multiple models.`}):(0,W.jsx)(u,{items:Se,label:`Model combos`,disabled:f.isPending,onReorder:e=>f.mutate(e,{onError:e=>s.error(S(e,`Could not save the new order.`))}),renderItem:e=>(0,W.jsxs)(H,{className:`items-start flex-col sm:flex-row`,actions:(0,W.jsxs)(M,{gap:`8px`,className:`w-full justify-between sm:w-auto sm:justify-start`,children:[(0,W.jsx)(k,{value:e.strategy,onValueChange:t=>De(e,t),options:q}),(0,W.jsxs)(M,{gap:`4px`,className:`flex-wrap`,children:[(0,W.jsx)(o,{variant:`ghost`,size:`sm`,icon:(0,W.jsx)(a,{size:13}),onClick:()=>Oe(e.name,e.id),title:Y===e.id?`Copied!`:`Copy combo name`}),(0,W.jsx)(o,{variant:`ghost`,size:`sm`,icon:(0,W.jsx)(me,{size:13}),onClick:()=>Te(e),disabled:n.isPending,title:`Clone combo (same members and strategy)`}),(0,W.jsx)(o,{variant:`ghost`,size:`sm`,icon:(0,W.jsx)(te,{size:13}),onClick:()=>we(e),title:`Edit combo`}),(0,W.jsx)(o,{variant:`ghost`,size:`sm`,icon:(0,W.jsx)(ie,{size:13}),onClick:()=>K(e),title:`Delete combo`,className:`text-red`})]})]}),children:[(0,W.jsx)(`div`,{className:`flex items-center justify-between gap-6 flex-wrap`,children:(0,W.jsx)(`strong`,{className:`text-body`,children:e.name})}),(0,W.jsx)(M,{gap:`6px`,className:`w-full flex-wrap`,children:e.members.map(e=>(0,W.jsx)(C,{value:e},e))})]})})}),(0,W.jsx)(b,{open:m,onClose:()=>h(!1),title:x?`Edit Model Combo`:`New Model Combo`,footer:(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(o,{variant:`secondary`,type:`button`,onClick:()=>h(!1),children:`Cancel`}),(0,W.jsx)(o,{variant:`primary`,type:`submit`,form:`combo-form`,disabled:t.isPending||r.isPending||!O.trim()||$.length===0,children:x?`Save Changes`:`Create Combo`})]}),children:(0,W.jsxs)(`form`,{id:`combo-form`,onSubmit:Ee,className:`flex flex-col gap-6`,children:[(0,W.jsx)(se,{label:`Combo name`,id:`combo-name-input`,value:O,onChange:e=>N(e.target.value),placeholder:`e.g. smart-combo, fast-pool`,required:!0}),(0,W.jsx)(k,{label:`Strategy`,id:`combo-strategy-select`,value:L,onValueChange:e=>R(e),options:q}),x?(0,W.jsx)(he,{kind:`combo`,name:x.name,value:ye,onChange:be,presets:Q.presets}):null,(0,W.jsxs)(j,{gap:`6px`,children:[(0,W.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,W.jsx)(`label`,{className:`text-caption font-semibold text-text-secondary`,children:`Member models — use arrows or drag to reorder`}),(0,W.jsx)(o,{variant:`secondary`,size:`sm`,type:`button`,icon:(0,W.jsx)(re,{size:12}),onClick:()=>V(!0),children:`Browse models`})]}),(0,W.jsx)(`div`,{role:`list`,"aria-label":`Combo members`,"data-testid":`combo-members-list`,className:`flex min-h-22 flex-col gap-2 rounded-control border border-dashed border-inner-border ${P.length===0?`p-0`:`p-3`}`,children:P.length===0?(0,W.jsx)(`button`,{type:`button`,onClick:()=>V(!0),className:`flex-1 cursor-pointer font-inherit text-caption text-text-tertiary`,children:`Pick models to add`}):(0,W.jsx)(u,{items:P,label:`Combo members`,gap:`4px`,onReorder:e=>{let t=new Map(P.map(e=>[e.id,e]));I(e.map(e=>t.get(e)).filter(Boolean))},renderItem:e=>(0,W.jsx)(H,{density:`compact`,actions:(0,W.jsx)(`button`,{type:`button`,onClick:()=>xe(e.value),"aria-label":`Remove ${e.value}`,className:`flex shrink-0 cursor-pointer text-text-tertiary`,children:(0,W.jsx)(y,{size:12})}),children:(0,W.jsx)(C,{value:e.value,tone:`accent`})})})})]}),(0,W.jsx)(A,{open:ue,onClose:()=>V(!1),selected:$,onToggle:xe,title:`Select combo members`,multi:!0})]})}),(0,W.jsx)(b,{open:!!G,onClose:()=>K(null),title:`Delete Model Combo`,children:(0,W.jsxs)(j,{gap:`12px`,children:[(0,W.jsxs)(`p`,{className:`text-body text-text-secondary`,children:[`Are you sure you want to delete combo `,(0,W.jsx)(`strong`,{children:G?.name}),`? Any aliases pointing to it will fail to resolve.`]}),(0,W.jsxs)(ae,{children:[(0,W.jsx)(o,{variant:`secondary`,onClick:()=>K(null),children:`Cancel`}),(0,W.jsx)(o,{variant:`danger`,onClick:()=>{G&&i.mutate(G.id,{onSuccess:()=>K(null)})},disabled:i.isPending,children:i.isPending?`Deleting...`:`Delete Combo`})]})]})})]})}function _e(){return(0,W.jsxs)(j,{gap:`16px`,children:[(0,W.jsx)(ge,{}),(0,W.jsx)(Y,{}),(0,W.jsx)(Z,{})]})}export{Z as VisionHandoffSection,_e as default};
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{o as e,r as t,t as n}from"./jsx-runtime-CXUMngI_.js";import{c as r,g as i,r as a,s as o}from"./numbers-CoqpaDMx.js";import{n as s,r as c,t as l}from"./state-DHmEnLa2.js";import{t as u}from"./refresh-cw-BqJFk4sU.js";import{t as d}from"./search-JOKus9rb.js";import{t as f}from"./shield-check-DVS0Foqh.js";import{t as p}from"./trash-Cppn5c3R.js";import{l as m,o as h,u as g}from"./query-keys-YSoQOUh6.js";import{M as _,N as v,V as y,ct as b}from"./entry-D6WvojeD.js";import{n as x,r as S,t as C}from"./card-CxDw0lK6.js";import{t as w}from"./badge-BaX2GTrn.js";import{n as T}from"./input-BlmlizVV.js";import{t as E}from"./layout-Bz93I-yE.js";var D=e(t(),1),O=500,k=1500;function A(e){return g(e)&&typeof e.ts==`string`&&(e.level===`debug`||e.level===`info`||e.level===`warn`||e.level===`error`)&&typeof e.msg==`string`}function j(e){return!g(e)||!Array.isArray(e.lines)?[]:e.lines.filter(A)}function M(){let[e,t]=(0,D.useState)([]),[n,r]=(0,D.useState)(new Set),[i,a]=(0,D.useState)(`idle`),s=(0,D.useRef)(0),c=(0,D.useRef)(new Set),l=e=>({...e,id:`l${s.current+=1}`}),u=(e,t)=>{let n=window.setTimeout(()=>{c.current.delete(n),e()},t);c.current.add(n)};return o({url:`/console/api/logs/stream`,preflight:async()=>{let e=await h(`/logs?limit=200`);t(j(e).slice(-500).map(l)),r(new Set)},events:[`init`,`line`,`clear`],onEvent:(e,n)=>{if(e===`init`){try{let e=JSON.parse(n);g(e)&&(t(j(e).slice(-500).map(l)),r(new Set)),a(`live`)}catch{}return}if(e===`clear`){t([]),r(new Set);return}if(e===`line`){let e;try{e=JSON.parse(n)}catch{return}if(!A(e))return;let i=l(e);r(e=>{let t=new Set(e);return t.add(i.id),t}),u(()=>{r(e=>{if(!e.has(i.id))return e;let t=new Set(e);return t.delete(i.id),t})},k),t(e=>{let t=[...e,i];return t.length>O?t.slice(t.length-O):t}),a(`live`)}},onClose:()=>a(`reconnecting`)}),{lines:e,newLineIds:n,status:i,clear:(0,D.useCallback)(async()=>{await h(`/logs`,{method:`DELETE`}),t([]),r(new Set)},[])}}var N={"api_key.created":`API key created`,"api_key.updated":`API key updated`,"api_key.revoked":`API key revoked`,"api_key.regenerated":`API key regenerated`,"api_key.shared":`API key shared`,"api_key.share_regenerated":`API key share link regenerated`,"api_key.share_revoked":`API key unshared`,"provider.created":`Provider created`,"provider.updated":`Provider updated`,"provider.deleted":`Provider deleted`,"provider.global.updated":`Global provider updated`,"provider.global.deleted":`Global provider deleted`,"provider.routing.updated":`Provider routing updated`,"provider.models.registered":`Provider models registered`,"provider.models.bulk_deleted":`Provider models bulk-deleted`,"provider.model.deleted":`Provider model deleted`,"provider.model.enabled":`Provider model enabled`,"provider.model.disabled":`Provider model disabled`,"provider_account.created":`Provider account connected`,"provider_account.updated":`Provider account updated`,"provider_account.recovered":`Provider account recovered`,"provider_account.revoked":`Provider account revoked`,"provider_account.circuit_force_closed":`Provider account circuit force-closed`,"provider_account.deleted":`Provider account deleted`,"provider_account.exported":`Provider accounts exported (plaintext)`,"provider_account.global.updated":`Global provider account updated`,"provider_account.global.refreshed":`Global provider account refreshed`,"provider_account.global.deleted":`Global provider account deleted`,"model_alias.created":`Model alias created`,"model_alias.updated":`Model alias updated`,"model_alias.deleted":`Model alias deleted`,"model_combo.created":`Model combo created`,"model_combo.updated":`Model combo updated`,"model_combo.cloned":`Model combo cloned`,"model_combo.deleted":`Model combo deleted`,"network_pool.created":`Network pool created`,"network_pool.updated":`Network pool updated`,"network_pool.deleted":`Network pool deleted`,"network_pool.recovered":`Network pool recovered`,"network_pool.strategy_updated":`Network pool strategy updated`,"network_pool.relay_deployed":`Network pool relay deployed`,"filter_rule.created":`Filter rule created`,"filter_rule.updated":`Filter rule updated`,"filter_rule.deleted":`Filter rule deleted`,"filter_rule.reordered":`Filter rules reordered`,"filter_rule.master_toggle":`Filter master switch toggled`,"settings.runtime.updated":`Runtime settings updated`,"cli_tool.mappings_saved":`CLI tool mappings saved`,"cli_tool.mappings_reset":`CLI tool mappings reset`,"cli_tool.applied":`CLI tool applied`,"console.password_changed":`Console password changed`,"console_logs.cleared":`Console logs cleared`,"security.ip_banned":`IP banned`,"backup.reset":`Backup reset`,"backup.delete_all":`Delete all configuration`},P={api:`API`,ip:`IP`,cli:`CLI`,oauth:`OAuth`};function F(e){return e.split(`.`).map(e=>e.split(/[_-]+/).filter(Boolean).map(e=>P[e.toLowerCase()]??e.charAt(0).toUpperCase()+e.slice(1)).join(` `)).join(` · `)}function I(e){return N[e]??F(e)}var L=n(),R=50,z=[{id:`all`,label:`All`},{id:`debug`,label:`Debug`},{id:`info`,label:`Info`},{id:`warn`,label:`Warn`},{id:`error`,label:`Error`}],B={debug:`var(--text-tertiary)`,info:`var(--accent)`,warn:`var(--orange)`,error:`var(--red)`},V={debug:`DBG`,info:`INF`,warn:`WRN`,error:`ERR`};function H(e){return e>=500?`err`:e>=400?`warn`:`ok`}function U(e,t,n){let r=n.trim().toLowerCase();return e.filter(e=>t!==`all`&&e.level!==t?!1:!r||`${e.msg} ${e.endpoint??``} ${e.model??``} ${e.routedModel??``} ${e.providerId??``} ${e.errorCode??``} ${e.userAgent??``} ${e.clientIp??``} ${e.accountLabel??``} ${e.networkPoolId??``}`.toLowerCase().includes(r))}function W(){let[e,t]=(0,D.useState)(`logs`),n=v().data?.isPlatformAdmin??!1,i=e===`audit`&&!n?`logs`:e,a=(0,L.jsxs)(`div`,{className:`flex gap-4`,children:[(0,L.jsx)(r,{variant:i===`logs`?`primary`:`secondary`,size:`sm`,onClick:()=>t(`logs`),icon:(0,L.jsx)(b,{size:13}),"aria-pressed":i===`logs`,children:`Console Log`}),n?(0,L.jsx)(r,{variant:i===`audit`?`primary`:`secondary`,size:`sm`,onClick:()=>t(`audit`),icon:(0,L.jsx)(f,{size:13}),"aria-pressed":i===`audit`,children:`Admin Audit`}):null]});return(0,L.jsx)(`div`,{className:`flex flex-col flex-1 min-h-0`,children:i===`logs`?(0,L.jsx)(Q,{tabAction:a}):(0,L.jsx)($,{tabAction:a})})}function G(e){let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleTimeString([],{hour12:!1})}function K(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}function q(e){let t=e.details;if(!t)return null;let n=typeof t.inputTokens==`number`?t.inputTokens:void 0,r=typeof t.outputTokens==`number`?t.outputTokens:void 0,i=typeof t.cachedInputTokens==`number`?t.cachedInputTokens:void 0,a=typeof t.reasoningTokens==`number`?t.reasoningTokens:void 0;if(n===void 0&&r===void 0&&i===void 0&&a===void 0)return null;let o=[];return n!==void 0&&o.push(`${K(n)} in`),r!==void 0&&o.push(`${K(r)} out`),i!==void 0&&o.push(`${K(i)} cached`),a!==void 0&&a>0&&o.push(`${K(a)} reason`),o.join(` / `)}function J(e){let t=e.model,n=e.routedModel,r=e.providerId,i=n??t;if(!i&&!r)return null;let a=r&&i?`${r}/${i}`:i??r??``;return n&&t&&n!==t?`${a} ← ${t}`:a}var Y=(0,D.memo)(function({line:e,isNew:t}){let n=e.event!==void 0,r=e.level;return(0,L.jsxs)(`div`,{className:`flex flex-wrap items-baseline gap-4 px-8 py-1.5 font-mono text-caption leading-normal max-medium:gap-3 max-medium:px-5 max-medium:text-badge${r===`warn`?` bg-orange-soft`:r===`error`?` bg-red-soft`:``}${t?` bg-surface-muted`:``} hover:bg-surface-hover`,"data-log-tone":r,children:[(0,L.jsx)(`span`,{className:`max-medium:flex-none flex-none tabular-nums text-text-tertiary`,children:G(e.ts)}),(0,L.jsx)(`span`,{className:`flex-none w-13 text-left text-micro font-bold tracking-label`,style:{color:B[e.level]},title:e.level.toUpperCase(),children:V[e.level]}),n?(0,L.jsx)(X,{line:e}):(0,L.jsx)(`span`,{className:`min-w-0 flex-1 whitespace-pre-wrap wrap-anywhere break-words text-text-secondary`,children:e.msg})]})});function X({line:e}){let t=J(e),n=q(e),r=Z(e);return(0,L.jsxs)(`span`,{className:`min-w-0 flex-1 whitespace-pre-wrap wrap-anywhere`,children:[(0,L.jsxs)(`span`,{className:`font-bold tracking-label ${r.tone}`,"data-log-field":`badge`,children:[`[`,r.label,`]`]}),` `,(0,L.jsx)(`span`,{className:`text-text-tertiary`,children:e.method??`POST`}),` `,(0,L.jsx)(`span`,{className:`text-text-primary`,children:e.endpoint??``}),e.status===void 0?null:(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`tabular-nums ${H(e.status)===`ok`?`text-text-tertiary`:H(e.status)===`warn`?`text-orange font-semibold`:`text-red font-semibold`}`,children:e.status})]}),e.durationMs===void 0?null:(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`tabular-nums text-text-secondary`,children:a(e.durationMs)})]}),t?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`text-status-info`,"data-log-field":`route`,children:t})]}):null,e.accountLabel?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`text-purple`,"data-log-field":`account`,title:e.accountId??void 0,children:e.accountLabel})]}):null,e.networkPoolId?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`text-text-tertiary`,"data-log-field":`pool`,title:`pool ${e.networkPoolId}`,children:e.networkPoolId.slice(0,8)})]}):null,e.clientIp?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`tabular-nums text-text-secondary`,"data-log-field":`ip`,children:e.clientIp})]}):null,n?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`tabular-nums text-orange`,"data-log-field":`tokens`,children:n})]}):null,e.errorCode?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsxs)(`span`,{className:`text-red`,title:e.msg,children:[e.msg,` (`,e.errorCode,`)`]})]}):null,e.requestId?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`text-micro text-text-tertiary`,"data-log-field":`id`,children:e.requestId.slice(0,8)})]}):null]})}function Z(e){return e.event===`request_start`||e.status===void 0?{label:`REQUEST`,tone:`text-text-tertiary`}:e.event===`request_error`||e.status>=400?{label:`FAILED`,tone:`text-red`}:{label:`SUCCESS`,tone:`text-status-info`}}function Q({tabAction:e}){let{lines:t,newLineIds:n,clear:r}=M(),[a,o]=(0,D.useState)(`all`),[s,c]=(0,D.useState)(``),[u,f]=(0,D.useState)(!1),[m,h]=(0,D.useState)(null),g=s.trim().toLowerCase(),_=(0,D.useMemo)(()=>U(t,a,g).slice().reverse(),[t,a,g]),v=(0,D.useMemo)(()=>{let e=new Map([[`all`,t.length]]);for(let n of t)e.set(n.level,(e.get(n.level)??0)+1);return e},[t]);return(0,L.jsxs)(C,{className:`flex-1 min-h-0 flex flex-col`,children:[(0,L.jsx)(S,{title:`Console Log`,subtitle:`${_.length} of ${t.length} lines`,icon:(0,L.jsx)(b,{size:16}),action:e}),(0,L.jsxs)(x,{className:`flex flex-row items-center justify-between gap-8 flex-none min-h-0 px-7 py-4 border-b border-inner-border max-medium:flex-col max-medium:items-start max-medium:gap-4`,children:[(0,L.jsx)(`div`,{className:`inline-flex items-center gap-1.5 flex-none max-medium:w-full max-medium:overflow-x-auto`,role:`group`,"aria-label":`Log level`,children:z.map(e=>{let t=v.get(e.id)??0;return(0,L.jsxs)(`button`,{className:`inline-flex items-center appearance-none border-0 rounded-tiny px-5 py-3.5 bg-transparent font-sans text-badge font-semibold leading-none cursor-pointer ${a===e.id?`bg-surface-muted text-text-primary`:`text-text-tertiary hover:bg-surface-muted hover:text-text-primary`}`,type:`button`,onClick:()=>o(e.id),"aria-pressed":a===e.id,children:[(0,L.jsx)(`span`,{children:e.label}),(0,L.jsx)(`span`,{className:`ml-2.5 text-inherit opacity-65 tabular-nums`,children:t})]},e.id)})}),(0,L.jsxs)(`div`,{className:`flex items-center gap-4 ml-auto max-medium:w-full max-medium:ml-0 max-medium:min-w-0`,children:[(0,L.jsxs)(`div`,{className:`relative w-140 min-w-0 max-w-full max-medium:flex-auto max-medium:w-auto`,children:[(0,L.jsx)(d,{size:13,"aria-hidden":`true`,className:`absolute left-5 top-1/2 -translate-y-1/2 text-text-tertiary pointer-events-none`}),(0,L.jsx)(T,{"aria-label":`Search console logs`,value:s,onChange:e=>c(e.target.value),placeholder:`Search logs...`,className:`pl-15 w-full min-w-0`})]}),(0,L.jsx)(`button`,{className:`inline-grid place-items-center w-16 h-16 border border-border-subtle rounded-control bg-transparent text-text-secondary cursor-pointer hover:border-red hover:text-red hover:bg-red-soft`,type:`button`,onClick:()=>f(!0),"aria-label":`Clear console logs`,title:`Clear logs`,children:(0,L.jsx)(p,{size:15,"aria-hidden":`true`})})]})]}),(0,L.jsxs)(x,{className:`p-0 flex-1 min-h-0 flex flex-col`,children:[(0,L.jsx)(`div`,{className:`scroll-region flex-1 min-h-0 flex flex-col p-0 bg-code-surface text-text-primary`,children:_.length===0?(0,L.jsx)(l,{title:t.length===0?`No log lines yet`:g?`No lines match your search`:`No lines match this level`,message:t.length===0?`Server log output will stream here as the gateway runs.`:`Adjust the search or pick another level to widen the view.`,icon:(0,L.jsx)(b,{size:20})}):_.map(e=>(0,L.jsx)(Y,{line:e,isNew:n.has(e.id)},e.id))}),(0,L.jsx)(`div`,{className:`flex items-center justify-between gap-5 shrink-0 px-8 py-4 border-t border-inner-border bg-surface-2 text-micro text-text-tertiary`,"aria-live":`polite`,children:(0,L.jsxs)(`span`,{className:`min-w-0 overflow-hidden text-ellipsis whitespace-nowrap`,children:[_.length,` of `,t.length,` lines`,a===`all`?``:` · ${a}`,g?` · search: "${s.trim()}"`:``]})})]}),(0,L.jsx)(y,{open:u,onClose:()=>f(!1),onConfirm:async()=>{h(null);try{await r(),f(!1),i.success(`Console logs cleared`)}catch{h(`Failed to clear server logs.`)}},title:`Clear console logs`,message:`Clear the in-memory server log tail? New lines keep streaming afterwards.`,confirmLabel:`Clear`,danger:!0}),m?(0,L.jsx)(`span`,{className:`text-badge text-red pt-0 px-8 pb-4`,children:m}):null]})}function $({tabAction:e}){let[t,n]=(0,D.useState)(``),[i,a]=(0,D.useState)(``),[o,d]=(0,D.useState)(``),[p,h]=(0,D.useState)(``),[g,v]=(0,D.useState)(void 0),[y,b]=(0,D.useState)([]);(0,D.useEffect)(()=>{let e=setTimeout(()=>d(t),300);return()=>clearTimeout(e)},[t]),(0,D.useEffect)(()=>{let e=setTimeout(()=>h(i),300);return()=>clearTimeout(e)},[i]);let w=_({limit:R,...o?{action:o}:{},...p?{actor:p}:{},...g?{cursor:g}:{}}),O=w.data,k=O?.entries??[],A=O?.nextCursor,j=()=>{A&&(b(e=>[...e,g??``]),v(A))},M=()=>{b(e=>{let t=e[e.length-1];return v(t||void 0),e.slice(0,-1)})},N=()=>{v(void 0),b([])};return(0,L.jsxs)(C,{className:`flex-1 min-h-0 flex flex-col`,children:[(0,L.jsx)(S,{title:`Admin Audit Trail`,subtitle:`Every privileged console mutation, retained on its own lifecycle`,icon:(0,L.jsx)(f,{size:16}),action:(0,L.jsxs)(`div`,{className:`flex gap-4 items-center`,children:[e,(0,L.jsx)(r,{variant:`secondary`,size:`sm`,onClick:()=>void w.refetch(),disabled:w.isFetching,icon:(0,L.jsx)(u,{size:13,className:w.isFetching?`animate-spin`:``}),children:`Refresh`})]})}),(0,L.jsxs)(x,{className:`flex flex-row items-center justify-between gap-6 flex-none min-h-0 px-8 py-5 border-b border-inner-border items-end`,children:[(0,L.jsx)(T,{label:`Action`,placeholder:`e.g. provider updated`,value:t,onChange:e=>{n(e.target.value),N()}}),(0,L.jsx)(T,{label:`Actor`,placeholder:`e.g. alice or a user id`,value:i,onChange:e=>{a(e.target.value),N()}}),(0,L.jsxs)(`div`,{className:`ml-auto flex gap-4`,children:[(0,L.jsx)(r,{size:`sm`,variant:`secondary`,onClick:M,disabled:y.length===0,children:`← Newer`}),(0,L.jsx)(r,{size:`sm`,variant:`secondary`,onClick:j,disabled:!A,children:`Older →`})]})]}),(0,L.jsx)(x,{className:`p-0 flex-1 min-h-0 flex flex-col`,children:(0,L.jsx)(`div`,{className:`flex-1 min-h-0 flex flex-col overflow-y-auto p-0 bg-transparent text-inherit`,children:w.isPending&&k.length===0?(0,L.jsx)(c,{compact:!0,label:`Loading audit trail…`}):w.isError&&k.length===0?(0,L.jsx)(s,{compact:!0,message:m(w.error,`Unable to load audit trail.`),onRetry:()=>void w.refetch()}):k.length===0?(0,L.jsx)(l,{compact:!0,title:`No audit entries yet`,message:`Privileged mutations (provider changes, key rotations, backups, bans) will appear here.`,icon:(0,L.jsx)(f,{size:20})}):(0,L.jsx)(E,{headers:[`Timestamp`,`Actor`,`Action`,`Target`,`Detail`],children:k.map(e=>(0,L.jsx)(ee,{entry:e},e.id))})})})]})}function ee({entry:e}){return(0,L.jsxs)(`tr`,{children:[(0,L.jsx)(`td`,{className:`text-badge text-text-tertiary whitespace-nowrap`,children:new Date(e.createdAt).toLocaleString()}),(0,L.jsxs)(`td`,{className:`max-w-100`,children:[(0,L.jsx)(`div`,{className:`text-caption font-semibold`,children:e.actorName??e.actor}),e.actorName?(0,L.jsx)(`div`,{title:e.actor,className:`truncate font-mono tabular-nums text-micro text-text-tertiary`,children:e.actor}):null]}),(0,L.jsx)(`td`,{children:(0,L.jsx)(w,{tone:e.action.includes(`delete`)||e.action.includes(`revoked`)?`err`:`ok`,title:e.action,children:I(e.action)})}),(0,L.jsx)(`td`,{title:e.target,className:`truncate font-mono tabular-nums text-badge max-w-110`,children:e.target}),(0,L.jsx)(`td`,{className:`font-mono tabular-nums text-badge max-w-160 overflow-hidden truncate`,children:e.detail?JSON.stringify(e.detail):`—`})]})}export{W as default,U as filterLogLines,H as statusTone};
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e,o as t,r as n,t as r}from"./jsx-runtime-CXUMngI_.js";import{c as i,v as a}from"./numbers-CoqpaDMx.js";import{t as o}from"./image-BPaouViG.js";import{t as s}from"./layers-2-glBbjl.js";import{t as c}from"./rotate-ccw-CufcqITi.js";import{$ as l,G as u,H as d,J as f,K as p,Q as m,U as h,W as g,X as _,Y as v,Z as y,et as b}from"./entry-D6WvojeD.js";import{n as x,r as S,t as C}from"./card-CxDw0lK6.js";import{t as w}from"./switch-DmZcyTIC.js";import{t as T}from"./select-BHqpd-bg.js";import{t as E}from"./stack-j7cXjgYX.js";import{t as D}from"./inline-CHJQwxLa.js";var O=e(`frame`,[[`line`,{x1:`22`,x2:`2`,y1:`6`,y2:`6`,key:`15w7dq`}],[`line`,{x1:`22`,x2:`2`,y1:`18`,y2:`18`,key:`1ip48p`}],[`line`,{x1:`6`,x2:`6`,y1:`2`,y2:`22`,key:`a2lnyx`}],[`line`,{x1:`18`,x2:`18`,y1:`2`,y2:`22`,key:`8vb6jd`}]]),k=e(`panel-top`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M3 9h18`,key:`1pudct`}]]),A=e(`rectangle-horizontal`,[[`rect`,{width:`20`,height:`12`,x:`2`,y:`6`,rx:`2`,key:`9lu3g6`}]]),j=t(n(),1),M=r(),N={cards:{label:`Cards`,description:`The card body on every page`,icon:(0,M.jsx)(A,{size:15})},chrome:{label:`Sidebar & topbar`,description:`The shell around the page`,icon:(0,M.jsx)(k,{size:15})}};function P(e){return e<1048576?`${Math.max(1,Math.round(e/1024))} KB`:`${(e/1048576).toFixed(1)} MB`}function F(){let[e,t]=p(),[n,r]=(0,j.useState)(!1),[m,v]=(0,j.useState)(null),w=async n=>{let i=n.target.files?.[0];if(n.target.value=``,!i)return;let o=y(i);if(!o){a.error(`Choose an image or a video.`);return}if(i.size>4294967296){a.error(`File too big. 4 GB is the limit.`);return}let s=i.size>f;r(!0);try{let n=o===`image`?await l(i):i;await b(n,o),v(n.size),t({backgroundSet:!0,backgroundEnabled:!0,backgroundRevision:e.backgroundRevision+1}),a.success(o===`video`?`Video background saved in this browser.`:`Background saved in this browser.`),s&&a.warning(`File too big. Your web performance and experience may be degraded.`)}catch{a.error(`Could not store that file. The browser may be out of space.`)}finally{r(!1)}},k=async()=>{r(!0);try{await _(),v(null),t({backgroundSet:!1,backgroundEnabled:!1})}catch{a.error(`Could not remove the background.`)}finally{r(!1)}};return(0,M.jsxs)(E,{gap:`16px`,children:[(0,M.jsxs)(C,{children:[(0,M.jsx)(S,{title:`Background`,subtitle:`Stored in this browser only. It never leaves the machine.`,icon:(0,M.jsx)(o,{size:16}),action:(0,M.jsx)(D,{children:(0,M.jsx)(i,{variant:`ghost`,size:`sm`,icon:(0,M.jsx)(c,{size:13}),onClick:()=>{u({backgroundOpacity:h.backgroundOpacity,backgroundScale:h.backgroundScale,backgroundX:h.backgroundX,backgroundY:h.backgroundY,backgroundBlur:h.backgroundBlur,backgroundEnabled:e.backgroundSet}),a.success(`Background reset to defaults.`)},children:`Reset`})})}),(0,M.jsx)(x,{children:(0,M.jsxs)(E,{gap:`14px`,children:[(0,M.jsx)(I,{settings:e,onBytes:v,bytes:m}),(0,M.jsxs)(`div`,{className:`flex flex-wrap items-center gap-4`,children:[(0,M.jsxs)(`label`,{className:`btn btn-primary inline-flex items-center justify-center gap-3.5 rounded-control font-semibold text-caption px-7 py-2 cursor-pointer bg-accent text-accent-foreground`,children:[n?`Working…`:e.backgroundSet?`Replace`:`Upload image or video`,(0,M.jsx)(`input`,{type:`file`,accept:`image/*,video/*`,className:`sr-only`,onChange:e=>void w(e),disabled:n})]}),e.backgroundSet?(0,M.jsx)(i,{variant:`danger`,size:`sm`,onClick:()=>void k(),disabled:n,children:`Remove`}):null,(0,M.jsx)(`span`,{className:`text-badge text-text-tertiary`,children:`Images are resized to 2560px. Videos play on desktop and show their first frame on mobile.`})]}),(0,M.jsx)(L,{settings:e,setSettings:t})]})})]}),(0,M.jsxs)(C,{children:[(0,M.jsx)(S,{title:`Blur`,subtitle:`Each surface keeps its own style. Dialogs are never blurred, so they stay readable.`,icon:(0,M.jsx)(s,{size:16}),action:(0,M.jsx)(D,{children:(0,M.jsx)(i,{variant:`ghost`,size:`sm`,icon:(0,M.jsx)(c,{size:13}),onClick:()=>{u({blurCardsAmount:h.blurCardsAmount,blurChromeAmount:h.blurChromeAmount,blurCardsEnabled:h.blurCardsEnabled,blurChromeEnabled:h.blurChromeEnabled,blurCardsDepth:h.blurCardsDepth,blurChromeDepth:h.blurChromeDepth,renderMode:h.renderMode}),a.success(`Blur reset to defaults.`)},children:`Reset`})})}),(0,M.jsxs)(x,{children:[(0,M.jsxs)(`div`,{className:`mb-10 flex items-center justify-between gap-6 rounded-card border border-inner-border bg-surface-2 px-7 py-6 max-small:flex-col max-small:items-stretch`,children:[(0,M.jsxs)(`span`,{className:`flex min-w-0 flex-col`,children:[(0,M.jsx)(`span`,{className:`text-caption font-semibold text-text-primary`,children:`Render preset`}),(0,M.jsx)(`span`,{className:`text-badge text-text-tertiary`,children:`Pretty keeps surfaces near-solid with no card blur; Extreme removes the backdrop read everywhere. Either one overrides the toggles below while active — the background image stays.`})]}),(0,M.jsx)(T,{value:e.renderMode,onValueChange:e=>{t({renderMode:e}),a.success(e===`off`?`Render preset off`:`Render preset: ${e===`pretty`?`Pretty`:`Extreme`}`)},options:[{value:`off`,label:`Off (default)`},{value:`pretty`,label:`Pretty`},{value:`extreme`,label:`Extreme`}],size:`sm`,"aria-label":`Render preset`,className:`max-small:self-end`})]}),(0,M.jsx)(`div`,{className:`grid gap-10 lg:grid-cols-2`,children:d.map(n=>{let r=n===`chrome`,i=e.renderMode===`off`?void 0:g[e.renderMode][r?`chrome`:`cards`];return(0,M.jsx)(z,{target:n,enabled:r?e.blurChromeEnabled:e.blurCardsEnabled,held:e.renderMode===`off`?void 0:e.renderMode,onToggle:()=>t(r?{blurChromeEnabled:!e.blurChromeEnabled}:{blurCardsEnabled:!e.blurCardsEnabled}),clarity:i?i.amount:r?e.blurChromeAmount:e.blurCardsAmount,onClarity:e=>t(r?{blurChromeAmount:e}:{blurCardsAmount:e}),depth:i?i.depth:r?e.blurChromeDepth:e.blurCardsDepth,onDepth:e=>t(r?{blurChromeDepth:e}:{blurCardsDepth:e})},n)})})]})]}),(0,M.jsxs)(C,{children:[(0,M.jsx)(S,{title:`Empty panels`,subtitle:`A dashed frame around a page that has nothing to show yet.`,icon:(0,M.jsx)(O,{size:16})}),(0,M.jsx)(x,{children:(0,M.jsxs)(`button`,{type:`button`,role:`switch`,"aria-checked":e.emptyOutline,onClick:()=>t({emptyOutline:!e.emptyOutline}),className:`flex w-full items-center justify-between gap-6 rounded-card border border-inner-border bg-surface-2 px-7 py-6 text-left`,children:[(0,M.jsxs)(`span`,{className:`flex min-w-0 flex-col`,children:[(0,M.jsx)(`span`,{className:`text-caption font-semibold text-text-primary`,children:`Dashed border`}),(0,M.jsx)(`span`,{className:`text-badge text-text-tertiary`,children:`Off leaves the empty state sitting on the card.`})]}),(0,M.jsx)(`span`,{"aria-hidden":`true`,className:e.emptyOutline?`h-10 w-18 shrink-0 rounded-pill bg-accent p-1`:`h-10 w-18 shrink-0 rounded-pill bg-surface-active p-1`,children:(0,M.jsx)(`span`,{className:e.emptyOutline?`block size-8 translate-x-8 rounded-full bg-accent-foreground transition-transform`:`block size-8 rounded-full bg-text-secondary transition-transform`})})]})})]})]})}function I({settings:e,bytes:t,onBytes:n}){let[r,i]=(0,j.useState)(null),[a,o]=(0,j.useState)(null);if((0,j.useEffect)(()=>{if(!e.backgroundSet){i(v),o(`image`);return}let t=!0,r=null;return m().then(e=>{if(e){if(!t){URL.revokeObjectURL(e.url);return}r=e.url,i(e.url),o(e.kind),n(e.blob.size)}}).catch(()=>{}),()=>{t=!1,r&&URL.revokeObjectURL(r)}},[e.backgroundSet,n]),!r)return(0,M.jsx)(`div`,{className:`flex h-60 items-center justify-center rounded-card border border-dashed border-inner-border bg-surface-2 text-caption text-text-tertiary`,children:`No background yet. The console uses its plain surface.`});let s={objectFit:`cover`,objectPosition:`${50+e.backgroundX/2}% ${50+e.backgroundY/2}%`,transform:`scale(${e.backgroundScale/100})`,opacity:e.backgroundOpacity/100};return(0,M.jsxs)(`div`,{className:`relative h-75 overflow-hidden rounded-card border border-inner-border bg-surface-2`,children:[a===`video`?(0,M.jsx)(`video`,{src:r,muted:!0,playsInline:!0,preload:`metadata`,className:`size-full`,style:s}):(0,M.jsx)(`img`,{src:r,alt:``,className:`size-full`,style:s}),(0,M.jsxs)(`span`,{className:`absolute bottom-4 left-5 rounded-control bg-surface-1 px-4 py-1 text-micro text-text-secondary`,children:[a===`video`?`Video`:`Image`,t===null?``:` · ${P(t)}`,e.backgroundEnabled?``:` · hidden`]})]})}function L({settings:e,setSettings:t}){return(0,M.jsxs)(`div`,{className:`flex flex-col gap-7`,children:[(0,M.jsxs)(`label`,{className:`flex min-h-18 items-center justify-between gap-6 text-body font-semibold text-text-primary`,children:[(0,M.jsx)(`span`,{children:`Show background`}),(0,M.jsx)(w,{checked:e.backgroundEnabled,onChange:e=>t({backgroundEnabled:e}),"aria-label":`Show background`})]}),(0,M.jsxs)(`div`,{className:`grid gap-7 sm:grid-cols-2`,children:[(0,M.jsx)(R,{label:`Visibility`,value:e.backgroundOpacity,defaultValue:h.backgroundOpacity,min:0,max:100,unit:`%`,onChange:e=>t({backgroundOpacity:e})}),(0,M.jsx)(R,{label:`Blur`,value:e.backgroundBlur,defaultValue:h.backgroundBlur,min:0,max:100,unit:`%`,onChange:e=>t({backgroundBlur:e})}),(0,M.jsx)(R,{label:`Zoom`,value:e.backgroundScale,defaultValue:h.backgroundScale,min:100,max:180,unit:`%`,onChange:e=>t({backgroundScale:e})}),(0,M.jsx)(R,{label:`Shift horizontal`,value:e.backgroundX,defaultValue:h.backgroundX,min:-100,max:100,onChange:e=>t({backgroundX:e})}),(0,M.jsx)(R,{label:`Shift vertical`,value:e.backgroundY,defaultValue:h.backgroundY,min:-100,max:100,onChange:e=>t({backgroundY:e})})]})]})}function R({label:e,value:t,defaultValue:n,min:r,max:i,unit:a,onChange:o}){return(0,M.jsxs)(`label`,{className:`flex flex-col gap-2 text-caption text-text-secondary`,children:[(0,M.jsxs)(`span`,{className:`flex items-center justify-between`,children:[e,(0,M.jsxs)(`span`,{className:`flex items-center gap-3`,children:[(0,M.jsxs)(`span`,{className:`font-mono tabular-nums text-badge text-text-tertiary`,children:[t,a??``]}),(0,M.jsx)(`button`,{type:`button`,onClick:()=>o(n),disabled:t===n,"aria-label":`Reset ${e}`,title:`Reset ${e} to ${n}${a??``}`,className:`flex size-9 items-center justify-center rounded-control text-text-tertiary hover:bg-hover hover:text-text-primary disabled:pointer-events-none disabled:opacity-30`,children:(0,M.jsx)(c,{size:11})})]})]}),(0,M.jsx)(`input`,{type:`range`,min:r,max:i,value:t,onChange:e=>o(Number(e.target.value)),"aria-label":e,className:`blur-slider w-full h-11 m-0 border-0 rounded-pill cursor-pointer`,style:{"--fill":`${(t-r)/(i-r)*100}%`}})]})}function z({target:e,enabled:t,held:n,onToggle:r,clarity:i,onClarity:a,depth:o,onDepth:s}){let c=N[e]??N.cards,l=n===`pretty`?`Held by Pretty`:n===`extreme`?`Held by Extreme`:void 0,u=t&&n===void 0;return(0,M.jsxs)(`div`,{className:`flex flex-col gap-8 rounded-card border border-inner-border bg-surface-2 p-8`,children:[(0,M.jsxs)(`div`,{className:`flex items-center gap-5`,children:[(0,M.jsx)(`span`,{className:`flex size-16 shrink-0 items-center justify-center rounded-control bg-surface-1 text-text-secondary`,children:c.icon}),(0,M.jsxs)(`span`,{className:`flex min-w-0 flex-1 flex-col`,children:[(0,M.jsx)(`span`,{className:`text-body font-semibold text-text-primary`,children:c.label}),(0,M.jsx)(`span`,{className:`text-micro text-text-tertiary`,children:l??c.description})]}),(0,M.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":n===void 0&&t,"aria-label":`Toggle ${c.label} blur`,disabled:n!==void 0,onClick:n===void 0?r:void 0,className:`${n===void 0?t?`h-10 w-18 shrink-0 rounded-pill bg-accent p-1`:`h-10 w-18 shrink-0 rounded-pill bg-surface-active p-1`:`h-10 w-18 shrink-0 rounded-pill bg-surface-active p-1 cursor-default`}`,children:(0,M.jsx)(`span`,{className:n!==void 0||!t?`block size-8 rounded-full bg-text-secondary`:`block size-8 translate-x-8 rounded-full bg-accent-foreground`})})]}),(0,M.jsxs)(`div`,{className:u?`flex flex-col gap-6`:`flex flex-col gap-6 opacity-40`,children:[(0,M.jsxs)(`label`,{className:`flex flex-col gap-3 text-caption text-text-secondary`,children:[(0,M.jsxs)(`span`,{className:`flex items-center justify-between`,children:[`Clarity`,(0,M.jsxs)(`span`,{className:`font-mono text-badge tabular-nums text-text-tertiary`,children:[i,`%`]})]}),(0,M.jsx)(`input`,{type:`range`,min:0,max:100,value:i,disabled:!t,onChange:e=>a(Number(e.target.value)),"aria-label":`${c.label} clarity. How see-through the surface is.`,className:`blur-slider w-full h-11 m-0 border-0 rounded-pill cursor-pointer`,style:{"--fill":`${i}%`}}),(0,M.jsxs)(`span`,{className:`flex justify-between text-badge text-text-tertiary`,children:[(0,M.jsx)(`span`,{children:`See-through`}),(0,M.jsx)(`span`,{children:`Solid`})]})]}),(0,M.jsxs)(`label`,{className:`flex flex-col gap-3 text-caption text-text-secondary`,children:[(0,M.jsxs)(`span`,{className:`flex items-center justify-between`,children:[`Blur`,(0,M.jsxs)(`span`,{className:`font-mono text-badge tabular-nums text-text-tertiary`,children:[o,`%`]})]}),(0,M.jsx)(`input`,{type:`range`,min:0,max:100,value:o,disabled:!t,onChange:e=>s(Number(e.target.value)),"aria-label":`${c.label} blur. How blurred whatever is behind it looks.`,className:`blur-slider w-full h-11 m-0 border-0 rounded-pill cursor-pointer`,style:{"--fill":`${o}%`}}),(0,M.jsxs)(`span`,{className:`flex justify-between text-badge text-text-tertiary`,children:[(0,M.jsx)(`span`,{children:`Sharp`}),(0,M.jsx)(`span`,{children:`Blurred`})]})]})]})]})}export{F as default};
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{o as e,r as t,t as n}from"./jsx-runtime-CXUMngI_.js";import{i as r}from"./terminal-0_IjPWTk.js";import{c as i,g as a}from"./numbers-CoqpaDMx.js";import{n as o,r as s,t as c}from"./state-DHmEnLa2.js";import{t as l}from"./dialog-BK-NRr5u.js";import{t as u}from"./rotate-ccw-CufcqITi.js";import{t as d}from"./trash-Cppn5c3R.js";import{C as f,T as p,v as m}from"./assert-CidQVoNo.js";import{o as h,t as g}from"./query-keys-YSoQOUh6.js";import{t as _}from"./useMutation-CbCP4w1o.js";import{V as v,b as y,j as b,r as x,x as S}from"./entry-D6WvojeD.js";import{t as C}from"./badge-BaX2GTrn.js";import{n as w}from"./inline-CHJQwxLa.js";import{t as T}from"./layout-Bz93I-yE.js";async function E(e){return h(`/quota/overview`,e?{signal:e}:void 0)}function D(){return f({queryKey:g.quota.all,queryFn:e=>E(m(e)),staleTime:1/0,refetchInterval:!1,refetchIntervalInBackground:!1,refetchOnMount:!1,refetchOnWindowFocus:!1,placeholderData:e=>e})}function O(e){let t=p(),n=g.quota.account(e);return _({mutationFn:async()=>h(`/accounts/${encodeURIComponent(e)}/quota/refresh`,{method:`POST`}),onSuccess:async()=>{await Promise.all([t.invalidateQueries({queryKey:n,exact:!0}),t.invalidateQueries({queryKey:g.quota.all}),t.invalidateQueries({queryKey:g.providers.all})])}})}function k(e){let t=p();return _({mutationFn:async()=>(await h(`/accounts/${encodeURIComponent(e)}/claim-gifts`,{method:`POST`})).data,onSuccess:async n=>{n.claimed.length!==0&&await Promise.all([t.invalidateQueries({queryKey:g.quota.account(e),exact:!0}),t.invalidateQueries({queryKey:g.quota.all}),t.invalidateQueries({queryKey:g.providers.all})])}})}function A(){let e=p();return _({mutationFn:async({accountIds:e,onProgress:t})=>{let n=e.length,r=0,i=await h(`/quota/refresh`,{method:`POST`,body:JSON.stringify({accountIds:e})});return r=i.queued,t?.(r,n),i},onSuccess:async(t,n)=>{let r=n.accountIds,i=new Set(t.failures.map(e=>e.accountId)),a=r.filter(e=>!i.has(e));await Promise.all([...a.map(t=>e.invalidateQueries({queryKey:g.quota.account(t),exact:!0})),e.invalidateQueries({queryKey:g.quota.all})])}})}function j(){let e=p();return _({mutationFn:({id:e,active:t})=>h(`/accounts/${encodeURIComponent(e)}`,{method:`PATCH`,body:JSON.stringify({active:t})}),onSuccess:async()=>{await Promise.all([e.invalidateQueries({queryKey:g.quota.all}),e.invalidateQueries({queryKey:g.providers.all})])}})}function M(){let e=p();return _({mutationFn:async({ids:e,active:t})=>{e.length!==0&&await h(`/accounts/batch`,{method:`PATCH`,body:JSON.stringify({ids:e,active:t})})},onSuccess:async()=>{await Promise.all([e.invalidateQueries({queryKey:g.quota.all}),e.invalidateQueries({queryKey:g.providers.all})])}})}function N(){let e=p();return _({mutationFn:async e=>{await h(`/accounts/${encodeURIComponent(e)}`,{method:`DELETE`})},onSuccess:async(t,n)=>{e.removeQueries({queryKey:g.quota.account(n),exact:!0}),await Promise.all([e.invalidateQueries({queryKey:g.quota.all}),e.invalidateQueries({queryKey:g.providers.all})])}})}var P=new Set([`workbuddy`,`workbuddycn`,`cb`,`cbcn`]);function F(e){return P.has(e.trim().toLowerCase())}function I(e){let t=p();return _({mutationFn:async()=>{if(e.length===0)throw Error(`Select a provider first`);return h(`/quota/daily-growth`,{method:`POST`,body:JSON.stringify({providerId:e})})},onSuccess:async()=>{await Promise.all([t.invalidateQueries({queryKey:g.quota.all}),t.invalidateQueries({queryKey:g.providers.all})])}})}function L(e){let t=p();return _({mutationFn:async()=>{let t=await h(`/accounts/${encodeURIComponent(e)}/activity-report`,{method:`POST`}),n=t.message??`Activity reported`,r=await h(`/accounts/${encodeURIComponent(e)}/checkin`,{method:`POST`}),i=r.message??`Daily check-in done`;return{ok:t.ok,message:t.ok?`Report success · Check-in ${i}`:`Report failed: ${n} · Check-in ${i}`,checkin:r,report:t}},onSuccess:async()=>{await Promise.all([t.invalidateQueries({queryKey:g.quota.all}),t.invalidateQueries({queryKey:g.providers.all})])}})}var R=new Set([`codex`,`claude`,`anthropic`]);function z(e){return R.has(e.trim().toLowerCase())}function B(e,t){return f({queryKey:g.quota.resets(e),queryFn:({signal:t})=>h(`/accounts/${encodeURIComponent(e)}/resets`,t?{signal:t}:void 0),enabled:t,staleTime:3e4})}function V(e){let t=p();return _({mutationFn:async t=>h(`/accounts/${encodeURIComponent(e)}/reset`,{method:`POST`,body:JSON.stringify(t??{})}),onSettled:async()=>{await Promise.all([t.invalidateQueries({queryKey:g.quota.all}),t.invalidateQueries({queryKey:g.providers.all})])}})}var H=e(t(),1),U=n();function W(e){return e===`cooldown`}function G(e){return e===`active`?`ok`:e===`disabled`?`disabled`:`warn`}function K(e,t){return e?{title:`Enable static-token mode?`,message:`${t} will be used exactly as issued and will not be refreshed. Re-enable refresh before this token expires.`,confirmLabel:`Enable static mode`}:{title:`Re-enable credential refresh?`,message:`${t} will return to the OAuth refresh sweep. Use this only when a refresh token is available.`,confirmLabel:`Re-enable refresh`}}function q({summary:e,onClose:t}){let{providerId:n,accountId:f,title:p,status:m,errorCategory:h,errorMessage:g,jwtIssuer:_}=e,E=x(n,f),D=S(),O=E.data??[],k=b(),A=e.credentialKind===`oauth`||e.credentialMode===`jwt`||e.staticToken===!0,[j,M]=(0,H.useState)(e.staticToken===!0),[N,P]=(0,H.useState)(null),[F,I]=(0,H.useState)(!1);(0,H.useEffect)(()=>M(e.staticToken===!0),[e.staticToken]);let L=y();return(0,U.jsx)(l,{open:!0,onClose:t,title:`Health & Error Log — ${p}`,size:`lg`,children:(0,U.jsxs)(`div`,{className:`flex flex-col gap-7 min-w-0`,children:[(0,U.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-5 rounded-control border border-inner-border bg-surface-2 py-5 px-7`,children:[(0,U.jsxs)(`div`,{className:`min-w-0`,children:[(0,U.jsxs)(w,{gap:`8px`,className:`flex-wrap`,children:[(0,U.jsx)(`span`,{className:`text-body font-semibold`,children:`Account status:`}),(0,U.jsx)(C,{tone:G(m),dot:!0,children:m.toUpperCase()}),h?(0,U.jsx)(C,{tone:`warn`,title:g??void 0,children:h}):null]}),g?(0,U.jsx)(`p`,{className:`text-badge text-red mt-2 wrap-anywhere`,children:g}):null]}),W(m)?(0,U.jsx)(i,{size:`sm`,variant:`secondary`,icon:(0,U.jsx)(u,{size:12,className:D.isPending?`animate-spin`:``}),disabled:D.isPending,onClick:()=>D.mutate({providerId:n,accountId:f},{onSuccess:()=>void E.refetch()}),children:D.isPending?`Recovering...`:`Recover Now`}):null]}),A?(0,U.jsxs)(`div`,{className:`flex items-center justify-between gap-6 rounded-control border border-inner-border bg-surface-2 py-5 px-7`,children:[(0,U.jsxs)(`div`,{children:[(0,U.jsx)(`div`,{className:`text-caption font-semibold`,children:`Credential management`}),(0,U.jsx)(`div`,{className:`text-badge text-text-tertiary`,children:j?`Static mode: no refresh request will be sent.`:`OAuth refresh is enabled for this account.`}),_?(0,U.jsxs)(`div`,{className:`text-badge text-text-tertiary mt-1 wrap-anywhere`,children:[`Static · no refresh · issuer`,` `,(0,U.jsx)(`span`,{className:`font-mono text-text-secondary`,children:_})]}):null]}),(0,U.jsx)(i,{size:`sm`,variant:j?`primary`:`secondary`,disabled:k.isPending,onClick:()=>P(!j),children:j?`Static · no refresh`:`Enable static mode`})]}):null,(0,U.jsxs)(`div`,{className:`min-w-0`,children:[(0,U.jsxs)(`div`,{className:`flex items-center justify-between gap-5 mb-4`,children:[(0,U.jsxs)(`h4`,{className:`text-caption font-semibold text-text-secondary`,children:[`Transition Events & Audit (`,O.length,`)`]}),(0,U.jsx)(i,{size:`sm`,variant:`secondary`,icon:(0,U.jsx)(d,{size:12}),disabled:O.length===0||L.isPending,onClick:()=>I(!0),title:`Deletes this account's recorded transitions and audit entries.`,children:`Purge log`})]}),E.isPending?(0,U.jsx)(s,{compact:!0,label:`Loading health events...`}):E.isError?(0,U.jsx)(o,{compact:!0,message:`Failed to load health events`,onRetry:()=>void E.refetch()}):O.length===0?(0,U.jsx)(c,{compact:!0,title:`No health events recorded`,message:e.emptyMessage,icon:(0,U.jsx)(r,{size:20})}):(0,U.jsx)(`div`,{className:`rounded-inset border border-inner-border`,children:(0,U.jsx)(T,{maxHeight:480,scrollRegion:!0,headers:[`Timestamp`,`From → To`,`Model`,`Category`,`Reason / Details`],children:O.map(e=>(0,U.jsxs)(`tr`,{children:[(0,U.jsx)(`td`,{className:`text-badge text-text-tertiary whitespace-nowrap`,children:new Date(e.createdAt).toLocaleString()}),(0,U.jsxs)(`td`,{className:`whitespace-nowrap`,children:[e.fromStatus!==null&&e.fromStatus!==e.toStatus?(0,U.jsxs)(`span`,{className:`text-badge text-text-secondary`,children:[e.fromStatus,` →`,` `]}):(0,U.jsx)(`span`,{className:`text-badge text-text-tertiary`,children:`logged · `}),(0,U.jsx)(C,{tone:G(e.toStatus),children:e.toStatus})]}),(0,U.jsx)(`td`,{className:`font-mono tabular-nums text-badge text-text-secondary wrap-anywhere`,children:e.modelId??`—`}),(0,U.jsx)(`td`,{className:`font-mono tabular-nums text-badge text-text-secondary`,children:e.errorCategory??`—`}),(0,U.jsx)(`td`,{className:`text-badge text-text-primary min-w-110 max-w-260 wrap-anywhere`,children:e.reason??`—`})]},e.id))})})]}),(0,U.jsx)(v,{open:N!==null,onClose:()=>P(null),onConfirm:()=>{let e=N===!0;k.mutate({providerId:n,accountId:f,request:{staticToken:e}},{onSuccess:()=>{M(e),P(null),a.success(e?`Static mode enabled`:`Credential refresh re-enabled`,p),E.refetch()},onError:e=>a.error(`Credential update failed`,e instanceof Error?e.message:`Unable to update credential mode`)})},title:K(N===!0,p).title,message:K(N===!0,p).message,confirmLabel:K(N===!0,p).confirmLabel,cancelLabel:`Cancel`}),(0,U.jsx)(v,{open:F,onClose:()=>I(!1),onConfirm:()=>{L.mutate({providerId:n,accountId:f,title:p},{onSuccess:()=>I(!1)})},title:`Purge the health & error log for ${p}?`,message:`Deletes every transition and audit entry recorded for this account. Its status, credentials, and counters are untouched. This cannot be undone.`,confirmLabel:`Purge log`,cancelLabel:`Cancel`}),(0,U.jsx)(w,{justify:`flex-end`,gap:`0px`,children:(0,U.jsx)(i,{variant:`secondary`,size:`sm`,onClick:t,children:`Close`})})]})})}export{k as a,O as c,V as d,L as f,B as i,A as l,j as m,F as n,N as o,I as p,z as r,D as s,q as t,M as u};
|
|
Binary file
|