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
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
import type { FetchLike } from "../../authentication/oauth-client";
|
|
2
|
-
|
|
3
|
-
export const CODEX_DEVICE_USERCODE_URL = "https://auth.openai.com/api/accounts/deviceauth/usercode";
|
|
4
|
-
export const CODEX_DEVICE_TOKEN_URL = "https://auth.openai.com/api/accounts/deviceauth/token";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Lifetime of one device authorization, in seconds.
|
|
8
|
-
*
|
|
9
|
-
* The Codex device endpoint states no expiry, so the flow bounds itself: this
|
|
10
|
-
* is both what `startDeviceAuth` reports to the dashboard (its own countdown)
|
|
11
|
-
* and what the poll checks before spending a request on a dead authorization.
|
|
12
|
-
*/
|
|
13
|
-
export const CODEX_DEVICE_TTL_SECONDS = 900;
|
|
14
|
-
|
|
15
|
-
interface CodexDeviceStart {
|
|
16
|
-
readonly deviceAuthId: string;
|
|
17
|
-
readonly userCode: string;
|
|
18
|
-
readonly intervalSeconds: number;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
interface CodexDeviceAuthorization {
|
|
22
|
-
readonly authorizationCode: string;
|
|
23
|
-
readonly codeVerifier: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** Validates persisted provider-private device state read back from the flow store. */
|
|
27
|
-
export function parseCodexDeviceStart(value: Record<string, unknown>): CodexDeviceStart | undefined {
|
|
28
|
-
const { deviceAuthId, userCode, intervalSeconds } = value;
|
|
29
|
-
if (typeof deviceAuthId !== "string" || typeof userCode !== "string") return undefined;
|
|
30
|
-
if (typeof intervalSeconds !== "number" || !Number.isFinite(intervalSeconds)) return undefined;
|
|
31
|
-
return { deviceAuthId, userCode, intervalSeconds: Math.max(0, intervalSeconds) };
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
interface DeviceUserCodeResponse {
|
|
35
|
-
device_auth_id?: unknown;
|
|
36
|
-
user_code?: unknown;
|
|
37
|
-
interval?: unknown;
|
|
38
|
-
}
|
|
39
|
-
interface DeviceTokenResponse {
|
|
40
|
-
authorization_code?: unknown;
|
|
41
|
-
code_verifier?: unknown;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function jsonHeaders(): HeadersInit {
|
|
45
|
-
return { "content-type": "application/json", accept: "application/json" };
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export async function startCodexDeviceAuth(
|
|
49
|
-
clientId: string,
|
|
50
|
-
fetchFn: FetchLike = globalThis.fetch,
|
|
51
|
-
): Promise<CodexDeviceStart> {
|
|
52
|
-
const response = await fetchFn(CODEX_DEVICE_USERCODE_URL, {
|
|
53
|
-
method: "POST",
|
|
54
|
-
headers: jsonHeaders(),
|
|
55
|
-
body: JSON.stringify({ client_id: clientId }),
|
|
56
|
-
});
|
|
57
|
-
if (!response.ok) throw new Error(`Codex device authorization failed (${response.status})`);
|
|
58
|
-
const body = (await response.json()) as DeviceUserCodeResponse;
|
|
59
|
-
if (typeof body.device_auth_id !== "string" || typeof body.user_code !== "string")
|
|
60
|
-
throw new Error("Codex device authorization returned an invalid response");
|
|
61
|
-
const interval =
|
|
62
|
-
typeof body.interval === "number" && Number.isFinite(body.interval)
|
|
63
|
-
? Math.max(0, body.interval)
|
|
64
|
-
: 5;
|
|
65
|
-
return { deviceAuthId: body.device_auth_id, userCode: body.user_code, intervalSeconds: interval };
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* One device-token poll attempt.
|
|
70
|
-
*
|
|
71
|
-
* Returns `undefined` while the user has not approved yet (the endpoint answers
|
|
72
|
-
* 403/404) and the parsed PKCE pair once it has. Deliberately a single request:
|
|
73
|
-
* the dashboard owns the polling cadence, so the console route returns
|
|
74
|
-
* `pending` between attempts instead of holding one HTTP request open for the
|
|
75
|
-
* whole authorization window. A blocking loop here occupied a console worker
|
|
76
|
-
* for up to the full TTL and made the dialog's own interval meaningless.
|
|
77
|
-
*/
|
|
78
|
-
export async function pollCodexDeviceAuth(
|
|
79
|
-
device: CodexDeviceStart,
|
|
80
|
-
fetchFn: FetchLike = globalThis.fetch,
|
|
81
|
-
): Promise<CodexDeviceAuthorization | undefined> {
|
|
82
|
-
let response: Response;
|
|
83
|
-
try {
|
|
84
|
-
response = await fetchFn(CODEX_DEVICE_TOKEN_URL, {
|
|
85
|
-
method: "POST",
|
|
86
|
-
headers: jsonHeaders(),
|
|
87
|
-
body: JSON.stringify({ device_auth_id: device.deviceAuthId, user_code: device.userCode }),
|
|
88
|
-
});
|
|
89
|
-
} catch (error) {
|
|
90
|
-
// A network failure is not "not approved yet": surface it so the caller
|
|
91
|
-
// can return a failed verdict instead of polling to expiry.
|
|
92
|
-
throw new Error(`Codex device polling failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
93
|
-
}
|
|
94
|
-
// 403/404 are the endpoint's "not approved yet" answers, not failures.
|
|
95
|
-
if (response.status === 403 || response.status === 404) return undefined;
|
|
96
|
-
if (!response.ok) throw new Error(`Codex device polling failed (${response.status})`);
|
|
97
|
-
const body = (await response.json()) as DeviceTokenResponse;
|
|
98
|
-
if (typeof body.authorization_code === "string" && typeof body.code_verifier === "string")
|
|
99
|
-
return { authorizationCode: body.authorization_code, codeVerifier: body.code_verifier };
|
|
100
|
-
return undefined;
|
|
101
|
-
}
|
|
1
|
+
import type { FetchLike } from "../../authentication/oauth-client";
|
|
2
|
+
|
|
3
|
+
export const CODEX_DEVICE_USERCODE_URL = "https://auth.openai.com/api/accounts/deviceauth/usercode";
|
|
4
|
+
export const CODEX_DEVICE_TOKEN_URL = "https://auth.openai.com/api/accounts/deviceauth/token";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lifetime of one device authorization, in seconds.
|
|
8
|
+
*
|
|
9
|
+
* The Codex device endpoint states no expiry, so the flow bounds itself: this
|
|
10
|
+
* is both what `startDeviceAuth` reports to the dashboard (its own countdown)
|
|
11
|
+
* and what the poll checks before spending a request on a dead authorization.
|
|
12
|
+
*/
|
|
13
|
+
export const CODEX_DEVICE_TTL_SECONDS = 900;
|
|
14
|
+
|
|
15
|
+
interface CodexDeviceStart {
|
|
16
|
+
readonly deviceAuthId: string;
|
|
17
|
+
readonly userCode: string;
|
|
18
|
+
readonly intervalSeconds: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface CodexDeviceAuthorization {
|
|
22
|
+
readonly authorizationCode: string;
|
|
23
|
+
readonly codeVerifier: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Validates persisted provider-private device state read back from the flow store. */
|
|
27
|
+
export function parseCodexDeviceStart(value: Record<string, unknown>): CodexDeviceStart | undefined {
|
|
28
|
+
const { deviceAuthId, userCode, intervalSeconds } = value;
|
|
29
|
+
if (typeof deviceAuthId !== "string" || typeof userCode !== "string") return undefined;
|
|
30
|
+
if (typeof intervalSeconds !== "number" || !Number.isFinite(intervalSeconds)) return undefined;
|
|
31
|
+
return { deviceAuthId, userCode, intervalSeconds: Math.max(0, intervalSeconds) };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface DeviceUserCodeResponse {
|
|
35
|
+
device_auth_id?: unknown;
|
|
36
|
+
user_code?: unknown;
|
|
37
|
+
interval?: unknown;
|
|
38
|
+
}
|
|
39
|
+
interface DeviceTokenResponse {
|
|
40
|
+
authorization_code?: unknown;
|
|
41
|
+
code_verifier?: unknown;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function jsonHeaders(): HeadersInit {
|
|
45
|
+
return { "content-type": "application/json", accept: "application/json" };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function startCodexDeviceAuth(
|
|
49
|
+
clientId: string,
|
|
50
|
+
fetchFn: FetchLike = globalThis.fetch,
|
|
51
|
+
): Promise<CodexDeviceStart> {
|
|
52
|
+
const response = await fetchFn(CODEX_DEVICE_USERCODE_URL, {
|
|
53
|
+
method: "POST",
|
|
54
|
+
headers: jsonHeaders(),
|
|
55
|
+
body: JSON.stringify({ client_id: clientId }),
|
|
56
|
+
});
|
|
57
|
+
if (!response.ok) throw new Error(`Codex device authorization failed (${response.status})`);
|
|
58
|
+
const body = (await response.json()) as DeviceUserCodeResponse;
|
|
59
|
+
if (typeof body.device_auth_id !== "string" || typeof body.user_code !== "string")
|
|
60
|
+
throw new Error("Codex device authorization returned an invalid response");
|
|
61
|
+
const interval =
|
|
62
|
+
typeof body.interval === "number" && Number.isFinite(body.interval)
|
|
63
|
+
? Math.max(0, body.interval)
|
|
64
|
+
: 5;
|
|
65
|
+
return { deviceAuthId: body.device_auth_id, userCode: body.user_code, intervalSeconds: interval };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* One device-token poll attempt.
|
|
70
|
+
*
|
|
71
|
+
* Returns `undefined` while the user has not approved yet (the endpoint answers
|
|
72
|
+
* 403/404) and the parsed PKCE pair once it has. Deliberately a single request:
|
|
73
|
+
* the dashboard owns the polling cadence, so the console route returns
|
|
74
|
+
* `pending` between attempts instead of holding one HTTP request open for the
|
|
75
|
+
* whole authorization window. A blocking loop here occupied a console worker
|
|
76
|
+
* for up to the full TTL and made the dialog's own interval meaningless.
|
|
77
|
+
*/
|
|
78
|
+
export async function pollCodexDeviceAuth(
|
|
79
|
+
device: CodexDeviceStart,
|
|
80
|
+
fetchFn: FetchLike = globalThis.fetch,
|
|
81
|
+
): Promise<CodexDeviceAuthorization | undefined> {
|
|
82
|
+
let response: Response;
|
|
83
|
+
try {
|
|
84
|
+
response = await fetchFn(CODEX_DEVICE_TOKEN_URL, {
|
|
85
|
+
method: "POST",
|
|
86
|
+
headers: jsonHeaders(),
|
|
87
|
+
body: JSON.stringify({ device_auth_id: device.deviceAuthId, user_code: device.userCode }),
|
|
88
|
+
});
|
|
89
|
+
} catch (error) {
|
|
90
|
+
// A network failure is not "not approved yet": surface it so the caller
|
|
91
|
+
// can return a failed verdict instead of polling to expiry.
|
|
92
|
+
throw new Error(`Codex device polling failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
93
|
+
}
|
|
94
|
+
// 403/404 are the endpoint's "not approved yet" answers, not failures.
|
|
95
|
+
if (response.status === 403 || response.status === 404) return undefined;
|
|
96
|
+
if (!response.ok) throw new Error(`Codex device polling failed (${response.status})`);
|
|
97
|
+
const body = (await response.json()) as DeviceTokenResponse;
|
|
98
|
+
if (typeof body.authorization_code === "string" && typeof body.code_verifier === "string")
|
|
99
|
+
return { authorizationCode: body.authorization_code, codeVerifier: body.code_verifier };
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
@@ -6,20 +6,22 @@ import { canContainToolResult, joinTextParts, toolCallParts, toolResultParts } f
|
|
|
6
6
|
import {
|
|
7
7
|
classifyUpstreamError,
|
|
8
8
|
extractUpstreamMessage,
|
|
9
|
+
mapUpstreamHttpError,
|
|
9
10
|
upstreamErrorIdentifier,
|
|
10
11
|
} from "../../../transport/failure-policy";
|
|
11
|
-
import {
|
|
12
|
-
import type { CanonicalEvent, CanonicalRequest, CanonicalStopReason, ContentPart } from "../../../protocol/canonical-model";
|
|
12
|
+
import { postUpstreamJson } from "../../../protocol/upstream/post-json";
|
|
13
|
+
import type { CanonicalEvent, CanonicalRequest, CanonicalStopReason, ContentPart, UsageRecord } from "../../../protocol/canonical-model";
|
|
13
14
|
import { isRecord, readNumber, readString, resolveImageSource, splitDataUrl } from "../../../protocol/codecs";
|
|
14
15
|
import { usageFromProvider } from "../../provider-usage";
|
|
15
16
|
import { readCredentialSecret, type ProviderDispatchTarget, type ProviderAdapter, type ProviderDispatchContext } from "../../provider-contracts";
|
|
17
|
+
import { abortGatewayError } from "../../operations/upstream-deadline";
|
|
16
18
|
import { providerBaseUrl } from "../../provider-metadata";
|
|
17
19
|
import { defineModel } from "../../provider-model-definition";
|
|
18
20
|
import type { ModelDefinition } from "../../provider-model-definition";
|
|
19
21
|
import {
|
|
20
22
|
getCommandCodeVersion,
|
|
21
23
|
} from "../../operations/client-versions";
|
|
22
|
-
import {
|
|
24
|
+
import { ThinkSplitter } from "../../../protocol/think-split";
|
|
23
25
|
export const COMMANDCODE_PROVIDER_ID = "commandcode" as const;
|
|
24
26
|
export const COMMANDCODE_BASE_URL = providerBaseUrl("commandcode");
|
|
25
27
|
/**
|
|
@@ -37,10 +39,6 @@ export const COMMANDCODE_HOST = "https://api.commandcode.ai" as const;
|
|
|
37
39
|
* generate.
|
|
38
40
|
*/
|
|
39
41
|
export const COMMANDCODE_GENERATE_PATH = "/alpha/generate" as const;
|
|
40
|
-
/** The three routes the Provider API serves, one per wire family. */
|
|
41
|
-
export const COMMANDCODE_CHAT_PATH = "/chat/completions" as const;
|
|
42
|
-
export const COMMANDCODE_RESPONSES_PATH = "/responses" as const;
|
|
43
|
-
export const COMMANDCODE_MESSAGES_PATH = "/messages" as const;
|
|
44
42
|
|
|
45
43
|
/**
|
|
46
44
|
* Command Code's roster, as the Provider API publishes it.
|
|
@@ -426,7 +424,7 @@ export async function headers(sessionId: string, token: string): Promise<Record<
|
|
|
426
424
|
}
|
|
427
425
|
|
|
428
426
|
|
|
429
|
-
type StreamState = { toolIndexById: Map<string, number>; nextToolIndex: number; finishReason: string | undefined; usage: Record<string, unknown> | undefined; think:
|
|
427
|
+
type StreamState = { toolIndexById: Map<string, number>; nextToolIndex: number; finishReason: string | undefined; usage: Record<string, unknown> | undefined; think: ThinkSplitter };
|
|
430
428
|
|
|
431
429
|
export function ccMapFinishReason(reason: string): CanonicalStopReason {
|
|
432
430
|
return reason === "length" ? "length" : reason === "tool_calls" ? "tool_use" : reason === "content_filter" ? "content_filter" : "stop";
|
|
@@ -450,7 +448,7 @@ export function transformLine(line: string, state: StreamState, seqBase: number)
|
|
|
450
448
|
if (!text) return [];
|
|
451
449
|
const split = state.think.push(text);
|
|
452
450
|
const events: CanonicalEvent[] = [];
|
|
453
|
-
if (split.reasoning) events.push({ type: "content_delta", sequence_number: seqBase
|
|
451
|
+
if (split.reasoning) events.push({ type: "content_delta", sequence_number: seqBase++, content: { kind: "reasoning", payload: null, summary: split.reasoning } } as CanonicalEvent);
|
|
454
452
|
if (split.text) events.push({ type: "content_delta", sequence_number: seqBase, content: { kind: "text", text: split.text } } as CanonicalEvent);
|
|
455
453
|
return events;
|
|
456
454
|
}
|
|
@@ -485,9 +483,11 @@ export function transformLine(line: string, state: StreamState, seqBase: number)
|
|
|
485
483
|
if (type === "finish") {
|
|
486
484
|
const reason = state.finishReason ?? readString(event, "finishReason") ?? "stop";
|
|
487
485
|
const canonicalReason = ccMapFinishReason(reason);
|
|
488
|
-
const
|
|
489
|
-
|
|
490
|
-
|
|
486
|
+
const rest = state.think.flush();
|
|
487
|
+
const events: CanonicalEvent[] = [];
|
|
488
|
+
if (rest.reasoning) events.push({ type: "content_delta", sequence_number: seqBase++, content: { kind: "reasoning", payload: null, summary: rest.reasoning } });
|
|
489
|
+
if (rest.text) events.push({ type: "content_delta", sequence_number: seqBase++, content: { kind: "text", text: rest.text } });
|
|
490
|
+
let usage: UsageRecord | undefined;
|
|
491
491
|
if (state.usage) {
|
|
492
492
|
const prompt = readNumber(state.usage, "promptTokens") ?? readNumber(state.usage, "inputTokens") ?? 0;
|
|
493
493
|
const completion = readNumber(state.usage, "completionTokens") ?? readNumber(state.usage, "outputTokens") ?? 0;
|
|
@@ -500,9 +500,9 @@ export function transformLine(line: string, state: StreamState, seqBase: number)
|
|
|
500
500
|
cached_tokens: cached,
|
|
501
501
|
cache_creation_input_tokens: readNumber(state.usage, "cacheWriteTokens") ?? undefined,
|
|
502
502
|
} as unknown as Record<string, unknown>);
|
|
503
|
-
|
|
504
|
-
(events[0] as unknown as Record<string, unknown>)["usage"] = usageRecord;
|
|
503
|
+
usage = usageRecord;
|
|
505
504
|
}
|
|
505
|
+
events.push({ type: "terminal", sequence_number: seqBase, state: "complete", stop_reason: canonicalReason, provider_stop_reason: reason, ...(usage === undefined ? {} : { usage }) });
|
|
506
506
|
return events;
|
|
507
507
|
}
|
|
508
508
|
if (type === "error") {
|
|
@@ -546,30 +546,29 @@ export function transformLine(line: string, state: StreamState, seqBase: number)
|
|
|
546
546
|
return [];
|
|
547
547
|
}
|
|
548
548
|
|
|
549
|
-
/** NDJSON
|
|
550
|
-
export async function* transformNdjson(body: ReadableStream<Uint8Array>, signal: AbortSignal): AsyncIterable<CanonicalEvent> {
|
|
549
|
+
/** NDJSON decoding uses the request signal after the opening deadline is released. */
|
|
550
|
+
export async function* transformNdjson(body: ReadableStream<Uint8Array>, signal: AbortSignal, model: string): AsyncIterable<CanonicalEvent> {
|
|
551
551
|
const reader = body.getReader();
|
|
552
552
|
const decoder = new TextDecoder();
|
|
553
|
-
const state: StreamState = { toolIndexById: new Map(), nextToolIndex: 0, finishReason: undefined, usage: undefined, think: new
|
|
553
|
+
const state: StreamState = { toolIndexById: new Map(), nextToolIndex: 0, finishReason: undefined, usage: undefined, think: new ThinkSplitter() };
|
|
554
554
|
let buffer = "";
|
|
555
|
-
let hasTerminal = false;
|
|
556
555
|
let seq = 1;
|
|
557
|
-
// initial response_start
|
|
558
|
-
yield { type: "response_start", sequence_number: seq++, model: "commandcode" } as CanonicalEvent;
|
|
559
556
|
|
|
560
|
-
const readWithAbort = (): Promise<{ done: boolean; value?: Uint8Array }> => {
|
|
561
|
-
if (signal.aborted) throw
|
|
562
|
-
const { promise, resolve, reject } = Promise.withResolvers<{ done: boolean; value?: Uint8Array
|
|
563
|
-
const onAbort = (): void =>
|
|
564
|
-
if (signal.aborted) reject(new GatewayError("transport_closed", 499, "Command Code stream aborted (request {requestId}). Send it again whenever ready 🙃"));
|
|
565
|
-
else reject(new GatewayError("platform_unavailable", 502, "Command Code stream error (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream"));
|
|
566
|
-
};
|
|
557
|
+
const readWithAbort = async (): Promise<{ readonly done: boolean; readonly value?: Uint8Array | undefined }> => {
|
|
558
|
+
if (signal.aborted) throw signal.reason;
|
|
559
|
+
const { promise, resolve, reject } = Promise.withResolvers<{ readonly done: boolean; readonly value?: Uint8Array | undefined }>();
|
|
560
|
+
const onAbort = (): void => reject(signal.reason);
|
|
567
561
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
568
|
-
void reader.read().then(resolve, reject)
|
|
569
|
-
|
|
562
|
+
void reader.read().then(resolve, reject);
|
|
563
|
+
try {
|
|
564
|
+
return await promise;
|
|
565
|
+
} finally {
|
|
566
|
+
signal.removeEventListener("abort", onAbort);
|
|
567
|
+
}
|
|
570
568
|
};
|
|
571
569
|
|
|
572
570
|
try {
|
|
571
|
+
yield { type: "response_start", sequence_number: seq++, model };
|
|
573
572
|
while (true) {
|
|
574
573
|
const { done, value } = await readWithAbort();
|
|
575
574
|
if (done) break;
|
|
@@ -579,20 +578,11 @@ export async function* transformNdjson(body: ReadableStream<Uint8Array>, signal:
|
|
|
579
578
|
const line = buffer.slice(0, nl).trim();
|
|
580
579
|
buffer = buffer.slice(nl + 1);
|
|
581
580
|
if (line) {
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
}
|
|
588
|
-
for (const ev of evs) {
|
|
589
|
-
// Strictly increasing per line, in emission order: the Responses
|
|
590
|
-
// surface throws on any non-monotonic sequence mid-stream, after
|
|
591
|
-
// partial bytes are already flushed. No special-casing for
|
|
592
|
-
// dual-event lines — order is order.
|
|
593
|
-
(ev as unknown as Record<string, unknown>)["sequence_number"] = seq++;
|
|
594
|
-
if (ev.type === "terminal") hasTerminal = true;
|
|
595
|
-
yield ev;
|
|
581
|
+
const events = transformLine(line, state, seq);
|
|
582
|
+
seq += events.length;
|
|
583
|
+
for (const event of events) {
|
|
584
|
+
yield event;
|
|
585
|
+
if (event.type === "terminal") return;
|
|
596
586
|
}
|
|
597
587
|
}
|
|
598
588
|
nl = buffer.indexOf("\n");
|
|
@@ -601,101 +591,71 @@ export async function* transformNdjson(body: ReadableStream<Uint8Array>, signal:
|
|
|
601
591
|
buffer += decoder.decode();
|
|
602
592
|
const tail = buffer.trim();
|
|
603
593
|
if (tail) {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
yield
|
|
594
|
+
const events = transformLine(tail, state, seq);
|
|
595
|
+
seq += events.length;
|
|
596
|
+
for (const event of events) {
|
|
597
|
+
yield event;
|
|
598
|
+
if (event.type === "terminal") return;
|
|
608
599
|
}
|
|
609
600
|
}
|
|
610
601
|
const rest = state.think.flush();
|
|
611
|
-
if (rest.reasoning) yield { type: "content_delta", sequence_number: seq++, content: { kind: "reasoning", payload: null, summary: rest.reasoning } }
|
|
612
|
-
if (rest.text) yield { type: "content_delta", sequence_number: seq++, content: { kind: "text", text: rest.text } }
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
yield { type: "terminal", sequence_number: seq++, state: "failed", stop_reason: ccMapFinishReason(state.finishReason ?? "stop"), provider_stop_reason: state.finishReason ?? "stop" } as CanonicalEvent;
|
|
616
|
-
}
|
|
602
|
+
if (rest.reasoning) yield { type: "content_delta", sequence_number: seq++, content: { kind: "reasoning", payload: null, summary: rest.reasoning } };
|
|
603
|
+
if (rest.text) yield { type: "content_delta", sequence_number: seq++, content: { kind: "text", text: rest.text } };
|
|
604
|
+
// NDJSON ended with no terminal envelope: truncated, never complete.
|
|
605
|
+
yield { type: "terminal", sequence_number: seq++, state: "failed", stop_reason: ccMapFinishReason(state.finishReason ?? "stop"), provider_stop_reason: state.finishReason ?? "stop" };
|
|
617
606
|
} finally {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
} catch {
|
|
621
|
-
// Best-effort reader unlock during stream cleanup.
|
|
622
|
-
}
|
|
623
|
-
void reader.cancel().catch(() => {});
|
|
607
|
+
void reader.cancel(signal.reason).catch(() => {});
|
|
608
|
+
reader.releaseLock();
|
|
624
609
|
}
|
|
625
610
|
}
|
|
626
611
|
|
|
627
|
-
//
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
// ProviderAdapter — the Provider API serves three wires, so dispatch is the
|
|
632
|
-
// shared OpenAI-compatible adapter rather than one bespoke NDJSON reader.
|
|
633
|
-
//
|
|
634
|
-
// Generation goes to `/alpha/generate` for every model: that is the CLI's own
|
|
635
|
-
// surface and the one the reference client calls, and it does not vary the path
|
|
636
|
-
// by the wire a model row declares. `/provider/v1` is the catalog surface — it
|
|
637
|
-
// answers `GET /models`, which discovery still uses — so a completion posted to
|
|
638
|
-
// `/provider/v1/<wire>` was reaching a surface the CLI never calls to
|
|
639
|
-
// generate. The wire family still decides how the body is shaped; only the
|
|
640
|
-
// endpoint is shared.
|
|
612
|
+
// The CLI generation surface takes a proprietary envelope and returns NDJSON
|
|
613
|
+
// regardless of the catalog row's wire family.
|
|
641
614
|
|
|
642
615
|
interface CommandCodeAdapterOptions {
|
|
643
616
|
readonly fetch?: typeof fetch;
|
|
644
617
|
}
|
|
645
618
|
|
|
646
|
-
function commandCodeIdentityHeaders(_token: string): Record<string, string> {
|
|
647
|
-
return {
|
|
648
|
-
"x-command-code-version": getCommandCodeVersion(),
|
|
649
|
-
"x-cli-environment": "production",
|
|
650
|
-
"x-taste-learning": "true",
|
|
651
|
-
"x-project-slug": "cartethyia",
|
|
652
|
-
"user-agent": "cli",
|
|
653
|
-
// Per-request, as the CLI client sends it. The upstream expects a session
|
|
654
|
-
// id on every generate call and the reference client mints a fresh UUID
|
|
655
|
-
// for each one; sending a constant correlated requests that had nothing
|
|
656
|
-
// to do with each other.
|
|
657
|
-
"x-session-id": randomUUID(),
|
|
658
|
-
};
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
function providerApiAdapter(options: CommandCodeAdapterOptions): ProviderAdapter {
|
|
662
|
-
return createApiKeyAdapter(
|
|
663
|
-
{
|
|
664
|
-
provider_id: COMMANDCODE_PROVIDER_ID,
|
|
665
|
-
// The host, not the `/provider/v1` base: generation is a sibling
|
|
666
|
-
// surface, so every wire resolves under the host and the path below
|
|
667
|
-
// supplies the CLI endpoint. Nesting it under `/provider/v1` produced a
|
|
668
|
-
// URL that is neither surface.
|
|
669
|
-
base_url: COMMANDCODE_HOST,
|
|
670
|
-
endpoint_paths_by_wire_family: {
|
|
671
|
-
// Every wire, not one per family: the reference client sends all
|
|
672
|
-
// generation to `/alpha/generate` regardless of the row's declared
|
|
673
|
-
// wire, so dispatch must not fan out across three paths.
|
|
674
|
-
chat: COMMANDCODE_GENERATE_PATH,
|
|
675
|
-
responses: COMMANDCODE_GENERATE_PATH,
|
|
676
|
-
messages: COMMANDCODE_GENERATE_PATH,
|
|
677
|
-
},
|
|
678
|
-
buildExtraHeaders: async (context: ProviderDispatchContext) =>
|
|
679
|
-
commandCodeIdentityHeaders(await readCredentialSecret(context.credential, "Command Code bearer token is required")),
|
|
680
|
-
},
|
|
681
|
-
options.fetch,
|
|
682
|
-
);
|
|
683
|
-
}
|
|
684
619
|
|
|
685
620
|
class CommandCodeAdapter implements ProviderAdapter {
|
|
686
621
|
readonly provider_id = COMMANDCODE_PROVIDER_ID;
|
|
687
|
-
private readonly
|
|
622
|
+
private readonly fetchFn: typeof fetch;
|
|
688
623
|
|
|
689
624
|
constructor(options: CommandCodeAdapterOptions = {}) {
|
|
690
|
-
this.
|
|
625
|
+
this.fetchFn = options.fetch ?? globalThis.fetch;
|
|
691
626
|
}
|
|
692
627
|
|
|
693
|
-
dispatch(
|
|
628
|
+
async *dispatch(
|
|
694
629
|
request: CanonicalRequest,
|
|
695
630
|
candidate: ProviderDispatchTarget,
|
|
696
631
|
context: ProviderDispatchContext,
|
|
697
632
|
): AsyncIterable<CanonicalEvent> {
|
|
698
|
-
|
|
633
|
+
const token = readCredentialSecret(context.credential, "Command Code bearer token is required");
|
|
634
|
+
const sessionId = randomUUID();
|
|
635
|
+
const payload = buildRequest(candidate.model_id, {
|
|
636
|
+
messages: request.messages,
|
|
637
|
+
tools: (request.tools ?? []).map(({ name, description, jsonSchema }) => ({ name, description, jsonSchema })),
|
|
638
|
+
maxOutputTokens: request.generation_controls.max_output_tokens ?? request.generation_controls.max_tokens ?? request.generation_controls.max_completion_tokens ?? null,
|
|
639
|
+
temperature: request.generation_controls.temperature ?? null,
|
|
640
|
+
topP: request.generation_controls.top_p ?? null,
|
|
641
|
+
reasoningEffort: request.reasoning?.effort ?? null,
|
|
642
|
+
}, sessionId, [request.system, request.instructions].map((parts) => joinTextParts(parts ?? [])).filter(Boolean).join("\n"));
|
|
643
|
+
const { res, release } = await postUpstreamJson(
|
|
644
|
+
`${COMMANDCODE_HOST}${COMMANDCODE_GENERATE_PATH}`,
|
|
645
|
+
await headers(sessionId, token),
|
|
646
|
+
payload,
|
|
647
|
+
context,
|
|
648
|
+
context.outbound_fetch ?? this.fetchFn,
|
|
649
|
+
);
|
|
650
|
+
release();
|
|
651
|
+
try {
|
|
652
|
+
if (!res.ok) throw await mapUpstreamHttpError(res, COMMANDCODE_PROVIDER_ID);
|
|
653
|
+
if (!res.body) throw new GatewayError("platform_unavailable", 502, "Command Code returned an empty stream (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
654
|
+
// NDJSON carries no model identity; use the selected model, not the provider id.
|
|
655
|
+
yield* transformNdjson(res.body, context.abort_signal, candidate.model_id);
|
|
656
|
+
} catch (error: unknown) {
|
|
657
|
+
throw abortGatewayError({ signal: context.abort_signal, release }, error) ?? error;
|
|
658
|
+
}
|
|
699
659
|
}
|
|
700
660
|
}
|
|
701
661
|
|