cartethyia 2.7.3 → 2.7.5
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 +2 -0
- package/README.md +17 -5
- package/dist/dashboard/assets/{BannedPage-2TJD37Hb.js → BannedPage-Cj15GsMp.js} +1 -1
- package/dist/dashboard/assets/BannedPage-Cj15GsMp.js.gz +0 -0
- package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js +1 -0
- package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-xefJNRmJ.js → CliToolDetailPage-DZKmVuJN.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-DZKmVuJN.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-Rj9iHQ3F.js → CliToolsPage-BIccZmeL.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-BIccZmeL.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-DEEKkYD-.js +1 -0
- package/dist/dashboard/assets/CombosPage-DEEKkYD-.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js +1 -0
- package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-BKj_r0rp.js +1 -0
- package/dist/dashboard/assets/CustomizationPage-BKj_r0rp.js.gz +0 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js +656 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-C4w7vea-.js → LoginPage-DkXb6dx-.js} +1 -1
- package/dist/dashboard/assets/LoginPage-DkXb6dx-.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BtPcAfot.js → ModelPicker-DnQPSIA8.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-DnQPSIA8.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js +1 -0
- package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js +5 -0
- package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js +1 -0
- package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-5SnUSy3j.js +9 -0
- package/dist/dashboard/assets/ProxyPage-5SnUSy3j.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js +1 -0
- package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js +1 -0
- package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-BQS0Rx_u.js → SetupPage-WTa0sktC.js} +1 -1
- package/dist/dashboard/assets/SetupPage-WTa0sktC.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-TP7voAQ0.js → StudioPage-BfAb5-o_.js} +3 -3
- package/dist/dashboard/assets/StudioPage-BfAb5-o_.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js +56 -0
- package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-l29JROPv.js +1 -0
- package/dist/dashboard/assets/api-keys-l29JROPv.js.gz +0 -0
- package/dist/dashboard/assets/app--PJWq8_C.css +2 -0
- package/dist/dashboard/assets/app--PJWq8_C.css.gz +0 -0
- package/dist/dashboard/assets/{assert-C0YYuZJ4.js → assert-C0K-c4eo.js} +1 -1
- package/dist/dashboard/assets/assert-C0K-c4eo.js.gz +0 -0
- package/dist/dashboard/assets/{badge-B_DMpMJN.js → badge-DfbhQU4k.js} +1 -1
- package/dist/dashboard/assets/badge-DfbhQU4k.js.gz +0 -0
- package/dist/dashboard/assets/{banner-DMrMPmth.js → banner-BllT4LcF.js} +1 -1
- package/dist/dashboard/assets/banner-BllT4LcF.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-Be5Uzamx.js → card-CtkX66Wd.js} +1 -1
- package/dist/dashboard/assets/card-CtkX66Wd.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/{cli-tools-muFRphDu.js → cli-tools-CQXVMn4P.js} +1 -1
- package/dist/dashboard/assets/cli-tools-CQXVMn4P.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-DOfrVmsi.js → clipboard-button-BQqBQd2n.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-BQqBQd2n.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-C9omdjQt.js → dialog-BEK7KP0H.js} +1 -1
- package/dist/dashboard/assets/dialog-BEK7KP0H.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-Bm8WKaGY.js → drawer-BrTEZ8zu.js} +1 -1
- package/dist/dashboard/assets/drawer-BrTEZ8zu.js.gz +0 -0
- package/dist/dashboard/assets/entry-CHWxbS56.js +1 -0
- package/dist/dashboard/assets/entry-CHWxbS56.js.gz +0 -0
- package/dist/dashboard/assets/{entry-q5HwZ8nN.js → entry-EBHJ3DrE.js} +1 -1
- package/dist/dashboard/assets/entry-EBHJ3DrE.js.gz +0 -0
- package/dist/dashboard/assets/entry-LCS85hiq.js +4 -0
- package/dist/dashboard/assets/entry-LCS85hiq.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-BTScrQpe.js → formatters-BAACA727.js} +1 -1
- package/dist/dashboard/assets/formatters-BAACA727.js.gz +0 -0
- package/dist/dashboard/assets/{github-badge-Orjuzemr.js → github-badge-YSCE4UC2.js} +1 -1
- package/dist/dashboard/assets/github-badge-YSCE4UC2.js.gz +0 -0
- package/dist/dashboard/assets/{index-cPrX5vn6.js → index-FQlj0HUT.js} +2 -2
- package/dist/dashboard/assets/index-FQlj0HUT.js.gz +0 -0
- package/dist/dashboard/assets/{inline-Dvux8w-0.js → inline-C4gU5iOL.js} +1 -1
- package/dist/dashboard/assets/inline-C4gU5iOL.js.gz +0 -0
- package/dist/dashboard/assets/{input-CU1Rgf3p.js → input-BHHX_Tmm.js} +1 -1
- package/dist/dashboard/assets/input-BHHX_Tmm.js.gz +0 -0
- package/dist/dashboard/assets/{layout-C_7A6H55.js → layout-CajrYUnD.js} +1 -1
- package/dist/dashboard/assets/{layout-C_7A6H55.js.gz → layout-CajrYUnD.js.gz} +0 -0
- package/dist/dashboard/assets/{list-row-CzFvogbj.js → list-row-Bx2I7XUe.js} +1 -1
- package/dist/dashboard/assets/list-row-Bx2I7XUe.js.gz +0 -0
- package/dist/dashboard/assets/live-DNNqRbj2.js +1 -0
- package/dist/dashboard/assets/live-DNNqRbj2.js.gz +0 -0
- package/dist/dashboard/assets/minimize-2-BTmMTK4o.js +1 -0
- package/dist/dashboard/assets/minimize-2-BTmMTK4o.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-JJGQm8TD.js → mutation-Rr0TIvcj.js} +1 -1
- package/dist/dashboard/assets/mutation-Rr0TIvcj.js.gz +0 -0
- package/dist/dashboard/assets/network-C5UBACrJ.js +1 -0
- package/dist/dashboard/assets/network-C5UBACrJ.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CUWAZK4J.js +2 -0
- package/dist/dashboard/assets/numbers-CUWAZK4J.js.gz +0 -0
- package/dist/dashboard/assets/pagination-Xsi9Qx04.js +1 -0
- package/dist/dashboard/assets/pagination-Xsi9Qx04.js.gz +0 -0
- package/dist/dashboard/assets/{query-keys-CLaNz8Xz.js → query-keys-BloKtaXJ.js} +1 -1
- package/dist/dashboard/assets/query-keys-BloKtaXJ.js.gz +0 -0
- package/dist/dashboard/assets/quota-DvQbD_sr.js +1 -0
- package/dist/dashboard/assets/quota-DvQbD_sr.js.gz +0 -0
- package/dist/dashboard/assets/{routing-BEH32QOC.js → routing-in0f_IfK.js} +1 -1
- package/dist/dashboard/assets/routing-in0f_IfK.js.gz +0 -0
- package/dist/dashboard/assets/{select-B3iTetHN.js → select-BLULNqTp.js} +2 -2
- package/dist/dashboard/assets/select-BLULNqTp.js.gz +0 -0
- package/dist/dashboard/assets/settings-CcGczj6I.js +1 -0
- package/dist/dashboard/assets/settings-CcGczj6I.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-KrOrm7JZ.js → stack-D2lIR0tg.js} +1 -1
- package/dist/dashboard/assets/stack-D2lIR0tg.js.gz +0 -0
- package/dist/dashboard/assets/{state-DLS7IDMy.js → state-DTARjfiW.js} +1 -1
- package/dist/dashboard/assets/state-DTARjfiW.js.gz +0 -0
- package/dist/dashboard/assets/{switch-42ItvbAs.js → switch-c0oPSnqW.js} +1 -1
- package/dist/dashboard/assets/switch-c0oPSnqW.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-Dmnfh1Ue.js → useMutation-m8WGNPrz.js} +1 -1
- package/dist/dashboard/assets/useMutation-m8WGNPrz.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 +59 -57
- package/migrations/full-postgres/0027_qoder_identity_genuine_seed.sql +9 -10
- package/migrations/full-postgres/0032_add_provider_pool_accounts.sql +53 -0
- package/migrations/full-postgres/0033_add_api_key_ban.sql +9 -0
- package/migrations/full-postgres/0034_add_api_key_ban_until.sql +7 -0
- package/migrations/full-postgres/0035_align_pool_account_status_enum.sql +21 -0
- 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/lite-sqlite3/0027_qoder_identity_genuine_seed.sql +9 -10
- package/migrations/lite-sqlite3/0032_add_provider_pool_accounts.sql +44 -0
- package/migrations/lite-sqlite3/0033_add_api_key_ban.sql +8 -0
- package/migrations/lite-sqlite3/0034_add_api_key_ban_until.sql +5 -0
- package/migrations/lite-sqlite3/0035_align_pool_account_status_enum.sql +6 -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/package.json +4 -5
- package/scripts/cli/update.ts +15 -41
- package/src/boot/app.ts +67 -10
- package/src/boot/dependencies.ts +786 -732
- package/src/boot/lifecycle.ts +11 -12
- package/src/config/cooldowns.ts +34 -55
- package/src/config/network.ts +8 -4
- package/src/config/package-paths.ts +1 -1
- package/src/config/providers.ts +13 -14
- package/src/config/resources.ts +0 -5
- package/src/config/runtime.ts +2 -5
- package/src/config/spec.ts +26 -6
- package/src/console/api-keys/ban-constants.ts +38 -0
- package/src/console/api-keys/contracts.ts +92 -31
- package/src/console/api-keys/routes.ts +131 -6
- package/src/console/audit/routes.ts +3 -3
- package/src/console/auth/access.ts +4 -4
- package/src/console/auth/account-reset.ts +5 -5
- 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 +40 -34
- 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 +11 -9
- package/src/console/backup/export-endpoint.ts +11 -12
- package/src/console/backup/nine-router.ts +1 -7
- package/src/console/backup/routes.ts +32 -36
- 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 +7 -7
- package/src/console/cli-tools/injectors/cline.ts +110 -110
- package/src/console/cli-tools/injectors/codex.ts +181 -181
- package/src/console/cli-tools/injectors/copilot.ts +108 -108
- package/src/console/cli-tools/injectors/driver.ts +247 -247
- package/src/console/cli-tools/injectors/jcode.ts +115 -115
- package/src/console/cli-tools/injectors/openclaw.ts +161 -161
- package/src/console/cli-tools/injectors/opencode.ts +153 -153
- package/src/console/cli-tools/routes.ts +4 -4
- package/src/console/cli-tools/service.ts +1 -1
- package/src/console/cli-tools/store.ts +2 -2
- package/src/console/console-router-guards.ts +2 -2
- package/src/console/console-router.ts +36 -4
- package/src/console/dashboard-assets.ts +9 -9
- package/src/console/data-management/routes.ts +3 -3
- package/src/console/domain-registration.ts +18 -4
- 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 +5 -1
- package/src/console/observability/live.ts +34 -21
- package/src/console/observability/logs.ts +4 -4
- package/src/console/observability/performance.ts +3 -3
- package/src/console/observability/routes.ts +3 -3
- package/src/console/observability/sse.ts +62 -8
- package/src/console/observability/store.ts +36 -20
- package/src/console/providers/catalog/catalog-projections.ts +1 -1
- package/src/console/providers/catalog/contracts.ts +82 -22
- package/src/console/providers/catalog/model-operations.ts +1 -1
- package/src/console/providers/catalog/provider-operations.ts +110 -17
- package/src/console/providers/catalog/public-model-store.ts +0 -0
- package/src/console/providers/catalog/routes.ts +30 -6
- package/src/console/providers/catalog/store-helpers.ts +349 -326
- package/src/console/providers/catalog/store.ts +1662 -1292
- package/src/console/providers/detail/routes.ts +4 -4
- package/src/console/providers/oauth/callback-listener.ts +100 -18
- package/src/console/providers/oauth/routes.ts +95 -16
- 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 +285 -67
- package/src/console/quota/account-test-egress.ts +4 -4
- 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/model/routes.ts +3 -3
- package/src/console/routing/pools/contracts.ts +13 -10
- package/src/console/routing/pools/import-parse.ts +3 -3
- package/src/console/routing/pools/operations.ts +14 -7
- package/src/console/routing/pools/probe-verdict.ts +8 -3
- package/src/console/routing/pools/relay-deploy.ts +12 -12
- package/src/console/routing/pools/routes.ts +3 -3
- package/src/console/routing/pools/store.ts +21 -1
- package/src/console/settings/contracts.ts +29 -2
- package/src/console/settings/routes.ts +3 -3
- package/src/console/settings/store.ts +20 -0
- package/src/console/share/share-router.ts +112 -44
- package/src/console/share/share-stats.ts +109 -39
- 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 +42 -6
- 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 +256 -98
- 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 +76 -5
- package/src/network/pool/agent.ts +7 -6
- package/src/network/pool/byte-accounting.ts +1 -1
- package/src/network/pool/resolver.ts +55 -51
- package/src/network/pool/selector.ts +150 -136
- package/src/network/pool-cooldown-store.ts +71 -16
- package/src/network/pool-health-machine.ts +22 -2
- package/src/network/rate-limit-verdict.ts +68 -0
- package/src/network/retry.ts +1 -1
- package/src/network/ssrf.ts +24 -75
- package/src/observability/event-log.ts +2 -2
- package/src/observability/event-query.ts +286 -214
- 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 +12 -3
- package/src/observability/telemetry-reconciliation.ts +3 -3
- package/src/observability/telemetry-status.ts +1 -1
- 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 +10 -5
- package/src/persistence/dialect.ts +5 -1
- package/src/persistence/readiness.ts +19 -7
- package/src/persistence/redis.ts +1 -1
- package/src/persistence/schema.ts +177 -45
- package/src/persistence/shared-cache.ts +2 -2
- package/src/persistence/sort-order.ts +1 -1
- package/src/persistence/stores/api-key-store.ts +109 -4
- package/src/persistence/stores/share-store.ts +20 -8
- package/src/persistence/stores/telemetry-store.ts +1 -1
- 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 +12 -16
- package/src/protocol/dsml.ts +3 -49
- package/src/protocol/gateway-error.ts +6 -3
- package/src/protocol/image-clamp.ts +2 -2
- package/src/protocol/image-generation.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 +27 -12
- package/src/protocol/response/codex.ts +2 -2
- package/src/protocol/response/gemini.ts +1 -1
- package/src/protocol/response/messages.ts +6 -6
- package/src/protocol/response/omp-tool-call-markup.ts +1 -1
- package/src/protocol/response/responses.ts +3 -3
- package/src/protocol/sse-decoder.ts +64 -4
- 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 +8 -8
- 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/protocol/upstream/send-claude-messages.ts +3 -3
- package/src/providers/adapters/base-adapter.ts +1 -1
- package/src/providers/adapters/compatible-adapter.ts +44 -5
- 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/authentication/oauth-refresh-service.ts +2 -2
- package/src/providers/bundled-discovery-providers.ts +6 -30
- package/src/providers/configured-openai-providers.ts +82 -97
- package/src/providers/configured-provider.ts +1 -1
- package/src/providers/default-registry.ts +23 -35
- 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 +50 -15
- package/src/providers/discovery/probing-service.ts +18 -20
- package/src/providers/integrations/agentrouter/agentrouter.ts +14 -5
- package/src/providers/integrations/alibabacp/alibabacp.ts +2 -2
- package/src/providers/integrations/anthropic.ts +4 -11
- package/src/providers/integrations/antigravity/antigravity-oauth.ts +0 -1
- package/src/providers/integrations/antigravity/antigravity-protocol.ts +0 -14
- package/src/providers/integrations/antigravity/antigravity.ts +15 -26
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +2 -2
- 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-discovery-shared.ts +37 -6
- package/src/providers/integrations/buddy/buddy-identity.ts +108 -1
- package/src/providers/integrations/buddy/buddy-media.ts +16 -16
- 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 +5 -16
- package/src/providers/integrations/buddy/codebuddy/shared.ts +30 -9
- package/src/providers/integrations/buddy/workbuddy/provider.ts +6 -10
- package/src/providers/integrations/buddy/workbuddy/shared.ts +21 -3
- package/src/providers/integrations/claude/claude-betas.ts +1 -1
- package/src/providers/integrations/claude/claude-cch.ts +148 -148
- package/src/providers/integrations/claude/claude-credentials.ts +1 -1
- package/src/providers/integrations/claude/claude-slow-lane-retry.ts +1 -1
- package/src/providers/integrations/claude/claude.ts +3 -10
- package/src/providers/integrations/claude/fallback-credit.ts +3 -7
- package/src/providers/integrations/cline/cline.ts +2 -2
- package/src/providers/integrations/cloudflareai/cloudflareai.ts +4 -7
- package/src/providers/integrations/codex/codex-device-code.ts +101 -101
- package/src/providers/integrations/codex/codex-errors.ts +1 -1
- package/src/providers/integrations/codex/codex-oauth.ts +0 -1
- package/src/providers/integrations/codex/codex.ts +14 -15
- package/src/providers/integrations/commandcode/commandcode.ts +76 -116
- package/src/providers/integrations/commandcode/quota.ts +132 -48
- package/src/providers/integrations/cursor/cursor-http2.ts +11 -14
- 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 +53 -20
- 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 +13 -13
- package/src/providers/integrations/gemini.ts +11 -11
- package/src/providers/integrations/github/github-discovery.ts +55 -10
- package/src/providers/integrations/github/github-oauth.ts +6 -5
- package/src/providers/integrations/github/github.ts +47 -20
- 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 +88 -42
- package/src/providers/integrations/inferhub.ts +4 -11
- package/src/providers/integrations/kilo/kilo-oauth.ts +1 -1
- package/src/providers/integrations/kimi/kimi.ts +4 -11
- 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 +91 -78
- package/src/providers/integrations/muse/muse-oauth.ts +0 -1
- package/src/providers/integrations/muse/muse-quota.ts +0 -4
- package/src/providers/integrations/muse/muse.ts +6 -9
- package/src/providers/integrations/opencode/fingerprint.ts +7 -5
- package/src/providers/integrations/opencode/provider.ts +17 -24
- package/src/providers/integrations/perplexity.ts +2 -2
- package/src/providers/integrations/qoder/qoder-catalog.ts +132 -17
- package/src/providers/integrations/qoder/qoder-checkin.ts +26 -8
- package/src/providers/integrations/qoder/qoder-native-identity-store.ts +9 -8
- 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 +22 -28
- package/src/providers/integrations/qoder/qoder-sse.ts +159 -0
- package/src/providers/integrations/qoder/qoder-umid.ts +33 -38
- package/src/providers/integrations/qoder/qoder-virtual.ts +14 -2
- package/src/providers/integrations/qoder/qoder.ts +521 -63
- 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/tokenharbor.ts +2 -2
- 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 +59 -19
- package/src/providers/integrations/xai/xai-oauth.ts +5 -5
- package/src/providers/integrations/zcode/oauth.ts +1 -1
- 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 +131 -116
- package/src/providers/operations/account-health-service.ts +31 -39
- package/src/providers/operations/account-reset-service.ts +58 -1
- 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 +22 -6
- package/src/providers/operations/provider-credential-service.ts +35 -6
- package/src/providers/operations/upstream-deadline.ts +3 -3
- package/src/providers/provider-contracts.ts +65 -10
- package/src/providers/provider-credential-resolver.ts +1 -1
- 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-registry.ts +4 -4
- package/src/providers/provider-usage.ts +81 -16
- package/src/providers/quota/cache.ts +29 -0
- package/src/providers/quota/quota-contracts.ts +28 -10
- package/src/providers/quota/refresh.ts +29 -6
- package/src/providers/quota/snapshot.ts +94 -0
- package/src/providers/search/search-provider.ts +6 -8
- package/src/providers/search/search-providers.ts +2 -1
- package/src/security/abuse.ts +8 -8
- package/src/security/admission/reasons.ts +17 -17
- package/src/security/admission/service.ts +2 -2
- package/src/security/admission/ttl.ts +61 -61
- package/src/security/api-key-auth.ts +20 -8
- 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/coerce.ts +19 -0
- package/src/shared/invoke-guard.ts +47 -0
- package/src/transport/contracts.ts +13 -4
- package/src/transport/dispatch/attempt-finalize.ts +5 -4
- package/src/transport/dispatch/attempt-loop.ts +10 -7
- package/src/transport/dispatch/capture-policy.ts +34 -37
- package/src/transport/dispatch/empty-stream.ts +28 -25
- package/src/transport/dispatch/generation.ts +33 -53
- package/src/transport/dispatch/leases.ts +8 -8
- package/src/transport/dispatch/native-shared.ts +127 -0
- package/src/transport/dispatch/proxy-request.ts +10 -8
- package/src/transport/dispatch/responses-compact.ts +35 -56
- package/src/transport/dispatch/retry-policy.ts +4 -67
- package/src/transport/dispatch/stream-bridge.ts +1 -1
- package/src/transport/dispatch/streaming/encoder.ts +18 -72
- package/src/transport/dispatch/streaming/finalize.ts +11 -10
- 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 +27 -55
- package/src/transport/dispatch/token-count.ts +49 -46
- package/src/transport/dispatch/websearch.ts +24 -50
- package/src/transport/drain-endpoint.ts +3 -3
- package/src/transport/failure-policy.ts +19 -6
- package/src/transport/guards/auth-guard.ts +6 -11
- package/src/transport/guards/body-policy.ts +7 -7
- package/src/transport/guards/error-lifecycle.ts +18 -3
- package/src/transport/guards/guard-errors.ts +7 -3
- package/src/transport/guards/headroom-guard.ts +2 -2
- package/src/transport/guards/pipeline.ts +7 -7
- package/src/transport/guards/readiness-guard.ts +16 -2
- package/src/transport/guards/request-context.ts +15 -20
- package/src/transport/request/preparer.ts +306 -27
- 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 +5 -20
- 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 +113 -19
- package/src/transport/routing/route-model.ts +131 -38
- package/src/transport/routing/router.ts +154 -39
- package/src/transport/shutdown-notice.ts +21 -9
- 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 +3 -3
- package/src/transport/surface/content-parts.ts +1 -1
- package/src/transport/surface/dialects.ts +2 -2
- package/src/transport/surface/messages/encode.ts +1 -1
- package/src/transport/surface/messages/parse.ts +3 -3
- 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 +376 -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-2TJD37Hb.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-xefJNRmJ.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-Rj9iHQ3F.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-JEbYJFxw.js +0 -1
- package/dist/dashboard/assets/CombosPage-JEbYJFxw.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-C3xx_inM.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-C3xx_inM.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-Dw306gJU.js +0 -1
- package/dist/dashboard/assets/CustomizationPage-Dw306gJU.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-jaBo1TWV.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-jaBo1TWV.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-C4w7vea-.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-BtPcAfot.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-CGC5gNs1.js +0 -1
- package/dist/dashboard/assets/OverviewPage-CGC5gNs1.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-DQcthNGt.js +0 -4
- package/dist/dashboard/assets/ProviderDetailPage-DQcthNGt.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-0OsXRGXe.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-0OsXRGXe.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-DdPc8slb.js +0 -9
- package/dist/dashboard/assets/ProxyPage-DdPc8slb.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-Ci5O4BnH.js +0 -1
- package/dist/dashboard/assets/QuotaPage-Ci5O4BnH.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CDZjTt87.js +0 -1
- package/dist/dashboard/assets/SettingsPage-CDZjTt87.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-BQS0Rx_u.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-BAL5npBC.js +0 -1
- package/dist/dashboard/assets/SortableList-BAL5npBC.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-TP7voAQ0.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-Cj_fEzhg.js +0 -56
- package/dist/dashboard/assets/UsagePage-Cj_fEzhg.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-MbI7e7rt.js +0 -1
- package/dist/dashboard/assets/api-keys-MbI7e7rt.js.gz +0 -0
- package/dist/dashboard/assets/app-B2vyPoII.css +0 -2
- package/dist/dashboard/assets/app-B2vyPoII.css.gz +0 -0
- package/dist/dashboard/assets/assert-C0YYuZJ4.js.gz +0 -0
- package/dist/dashboard/assets/badge-B_DMpMJN.js.gz +0 -0
- package/dist/dashboard/assets/banner-DMrMPmth.js.gz +0 -0
- package/dist/dashboard/assets/card-Be5Uzamx.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-muFRphDu.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-DOfrVmsi.js.gz +0 -0
- package/dist/dashboard/assets/dialog-C9omdjQt.js.gz +0 -0
- package/dist/dashboard/assets/drawer-Bm8WKaGY.js.gz +0 -0
- package/dist/dashboard/assets/entry-DS90gUks.js +0 -1
- package/dist/dashboard/assets/entry-DS90gUks.js.gz +0 -0
- package/dist/dashboard/assets/entry-j40LJotO.js +0 -4
- package/dist/dashboard/assets/entry-j40LJotO.js.gz +0 -0
- package/dist/dashboard/assets/entry-q5HwZ8nN.js.gz +0 -0
- package/dist/dashboard/assets/formatters-BTScrQpe.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-Orjuzemr.js.gz +0 -0
- package/dist/dashboard/assets/index-cPrX5vn6.js.gz +0 -0
- package/dist/dashboard/assets/inline-Dvux8w-0.js.gz +0 -0
- package/dist/dashboard/assets/input-CU1Rgf3p.js.gz +0 -0
- package/dist/dashboard/assets/list-row-CzFvogbj.js.gz +0 -0
- package/dist/dashboard/assets/live-KaG15HLQ.js +0 -1
- package/dist/dashboard/assets/live-KaG15HLQ.js.gz +0 -0
- package/dist/dashboard/assets/minimize-2-D-MN8W8a.js +0 -1
- package/dist/dashboard/assets/minimize-2-D-MN8W8a.js.gz +0 -0
- package/dist/dashboard/assets/mutation-JJGQm8TD.js.gz +0 -0
- package/dist/dashboard/assets/numbers-BNDZnsUE.js +0 -2
- package/dist/dashboard/assets/numbers-BNDZnsUE.js.gz +0 -0
- package/dist/dashboard/assets/query-keys-CLaNz8Xz.js.gz +0 -0
- package/dist/dashboard/assets/quota-DZGyp0N5.js +0 -1
- package/dist/dashboard/assets/quota-DZGyp0N5.js.gz +0 -0
- package/dist/dashboard/assets/routing-BEH32QOC.js.gz +0 -0
- package/dist/dashboard/assets/select-B3iTetHN.js.gz +0 -0
- package/dist/dashboard/assets/settings-Dt3Eqbnq.js +0 -1
- package/dist/dashboard/assets/settings-Dt3Eqbnq.js.gz +0 -0
- package/dist/dashboard/assets/stack-KrOrm7JZ.js.gz +0 -0
- package/dist/dashboard/assets/state-DLS7IDMy.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-42ItvbAs.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-Dmnfh1Ue.js.gz +0 -0
- 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/{app-wvwCi4Eh.js → app-Bgd3zANQ.js} +0 -0
- /package/dist/dashboard/assets/{app-wvwCi4Eh.js.gz → app-Bgd3zANQ.js.gz} +0 -0
- /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,6 +1,8 @@
|
|
|
1
1
|
import type { ProviderDispatchContext } from "../../provider-contracts";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import { decodeJwtPayload } from "../../authentication/oauth-flow-store";
|
|
4
|
+
import { buddyAccountUid } from "./buddy-oauth-shared";
|
|
5
|
+
import type { CanonicalRequest } from "../../../protocol/canonical-model";
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* Which upstream client a buddy provider presents itself as.
|
|
@@ -41,8 +43,17 @@ export function resolveBuddyIdentity(
|
|
|
41
43
|
* The reference CLI sends the literal `anonymous` when it has no uid rather
|
|
42
44
|
* than omitting the header, so an unauthenticated dispatch still looks like a
|
|
43
45
|
* client rather than like a caller that forgot a header.
|
|
46
|
+
*
|
|
47
|
+
* When the credential carries a JWT, the `sub` claim is the upstream uid and
|
|
48
|
+
* wins over the gateway's internal account id — the two can differ after an
|
|
49
|
+
* import, and the channel check keys on the upstream identity. Opaque API keys
|
|
50
|
+
* carry no identity, so the internal account id is the fallback.
|
|
44
51
|
*/
|
|
45
52
|
export function buddyUserId(context?: ProviderDispatchContext): string {
|
|
53
|
+
const secret = context?.credential?.secret;
|
|
54
|
+
const token = secret ? new TextDecoder().decode(secret).trim() : "";
|
|
55
|
+
const uid = buddyAccountUid(token);
|
|
56
|
+
if (uid !== undefined) return uid;
|
|
46
57
|
const accountId = context?.credential.account_id;
|
|
47
58
|
return accountId !== undefined && accountId.length > 0 ? accountId : "anonymous";
|
|
48
59
|
}
|
|
@@ -108,10 +119,17 @@ export function buddyEnterprise(context?: ProviderDispatchContext): string | und
|
|
|
108
119
|
*
|
|
109
120
|
* Resolution order:
|
|
110
121
|
* 1. `auth_state.qimei36` — explicit operator-set binding (imported or edited).
|
|
111
|
-
* 2.
|
|
122
|
+
* 2. Derived deterministically from the internal account id (sha256 → 32 hex).
|
|
112
123
|
* This keeps the binding stable across restarts without a database write,
|
|
113
124
|
* and gives each freshly-added account its own id automatically.
|
|
114
125
|
*
|
|
126
|
+
* IMPORTANT — the derived fallback is **not portable across instances**:
|
|
127
|
+
* export/import mints a NEW account id, so the derived binding changes and the
|
|
128
|
+
* upstream channel check (11128) rejects the re-imported account. The export
|
|
129
|
+
* path therefore materializes the raw result of this resolver into
|
|
130
|
+
* `auth_state.qimei36` whenever an account relies on the derivation, so a
|
|
131
|
+
* re-import carries the exact same device identity.
|
|
132
|
+
*
|
|
115
133
|
* Returns `undefined` only when no account id is available (unauthenticated).
|
|
116
134
|
*/
|
|
117
135
|
export function resolveBuddyDeviceBinding(context?: ProviderDispatchContext): string | undefined {
|
|
@@ -121,3 +139,92 @@ export function resolveBuddyDeviceBinding(context?: ProviderDispatchContext): st
|
|
|
121
139
|
if (accountId === undefined || accountId.length === 0) return undefined;
|
|
122
140
|
return createHash("sha256").update(`wb2a:qimei36:${accountId}`).digest("hex").slice(0, 32);
|
|
123
141
|
}
|
|
142
|
+
|
|
143
|
+
/** Materializes the portable binding for an account into a stored auth-state
|
|
144
|
+
* map, when the account does not already pin one explicitly. Used by the
|
|
145
|
+
* export path so a re-import keeps the exact qimei36 device identity. */
|
|
146
|
+
export function materializeBuddyDeviceBinding(
|
|
147
|
+
accountId: string,
|
|
148
|
+
authState: Readonly<Record<string, unknown>> | undefined,
|
|
149
|
+
): Record<string, unknown> | undefined {
|
|
150
|
+
const existing = authState?.["qimei36"];
|
|
151
|
+
if (typeof existing === "string" && existing.trim().length > 0) return undefined;
|
|
152
|
+
if (accountId.length === 0) return undefined;
|
|
153
|
+
const derived = createHash("sha256").update(`wb2a:qimei36:${accountId}`).digest("hex").slice(0, 32);
|
|
154
|
+
return { ...(authState ?? {}), qimei36: derived };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* The OAuth identity header family the reference ships on every cloud API call
|
|
159
|
+
* (`runIdentityHeaders`): `X-User-Id` plus the base64 `X-Userinfo` envelope and
|
|
160
|
+
* the auth-method / id-source markers.
|
|
161
|
+
*
|
|
162
|
+
* The JWT `sub` is the uid; the base64 envelope mirrors the reference exactly:
|
|
163
|
+
* `{ uin, owner_uin?, id_source?, token_source? }` — one leg per identity
|
|
164
|
+
* field that exists, so a personal account sends `{uin}` while an enterprise
|
|
165
|
+
* account adds `owner_uin`. `X-Auth-Method` / `X-Id-Source` are only sent when
|
|
166
|
+
* the operator pinned them in `auth_state` (there is no reliable source to
|
|
167
|
+
* invent them from). An opaque API key carries no uid and yields nothing.
|
|
168
|
+
*/
|
|
169
|
+
export function buddyOAuthIdentityHeaders(
|
|
170
|
+
context?: ProviderDispatchContext,
|
|
171
|
+
): Record<string, string> {
|
|
172
|
+
const secret = context?.credential?.secret;
|
|
173
|
+
const token = secret ? new TextDecoder().decode(secret).trim() : "";
|
|
174
|
+
const uid = buddyAccountUid(token) ?? context?.credential.account_id ?? "";
|
|
175
|
+
if (uid.length === 0) return {};
|
|
176
|
+
const enterpriseId = buddyEnterprise(context);
|
|
177
|
+
const state = context?.credential.auth_state;
|
|
178
|
+
const idSource =
|
|
179
|
+
typeof state?.["idSource"] === "string" && (state["idSource"] as string).trim().length > 0
|
|
180
|
+
? (state["idSource"] as string).trim()
|
|
181
|
+
: undefined;
|
|
182
|
+
const method =
|
|
183
|
+
typeof state?.["authMethod"] === "string" && (state["authMethod"] as string).trim().length > 0
|
|
184
|
+
? (state["authMethod"] as string).trim()
|
|
185
|
+
: undefined;
|
|
186
|
+
const headers: Record<string, string> = { "X-User-Id": uid };
|
|
187
|
+
if (method !== undefined) headers["X-Auth-Method"] = method;
|
|
188
|
+
if (idSource !== undefined) headers["X-Id-Source"] = idSource;
|
|
189
|
+
if (enterpriseId !== undefined || idSource !== undefined || method !== undefined) {
|
|
190
|
+
const info: Record<string, string> = { uin: uid };
|
|
191
|
+
if (enterpriseId !== undefined) info["owner_uin"] = enterpriseId;
|
|
192
|
+
if (idSource !== undefined) info["id_source"] = idSource;
|
|
193
|
+
if (method !== undefined) info["token_source"] = method;
|
|
194
|
+
headers["X-Userinfo"] = Buffer.from(JSON.stringify(info), "utf-8").toString("base64");
|
|
195
|
+
}
|
|
196
|
+
return headers;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Whether this dispatch is in the reference's private-data mode. The CLI only
|
|
201
|
+
* sends `X-Private-Data: true` while the session is private; otherwise the
|
|
202
|
+
* header is deleted, never sent as `false`. The gateway has no session-level
|
|
203
|
+
* private flag, so the operator pins one per account in `auth_state.privateData`.
|
|
204
|
+
*/
|
|
205
|
+
export function buddyPrivateData(context?: ProviderDispatchContext): boolean {
|
|
206
|
+
return context?.credential.auth_state?.["privateData"] === true;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* The effective agent purpose for one dispatch, matching the reference's
|
|
211
|
+
* `getEffectiveAgentPurpose` behavior as closely as the gateway can:
|
|
212
|
+
*
|
|
213
|
+
* - `PERSONAL_AGENT_ROLE` set → `person_agent` (same env the CLI reads);
|
|
214
|
+
* - otherwise an inbound `x-agent-purpose` header is preserved (the caller
|
|
215
|
+
* already stated a purpose — same shape the reference passes through);
|
|
216
|
+
* - otherwise the header is omitted. The reference does not invent `conversation`.
|
|
217
|
+
*/
|
|
218
|
+
export function buddyAgentPurpose(
|
|
219
|
+
context?: ProviderDispatchContext,
|
|
220
|
+
request?: CanonicalRequest,
|
|
221
|
+
): string | undefined {
|
|
222
|
+
if (process.env.PERSONAL_AGENT_ROLE && process.env.PERSONAL_AGENT_ROLE.trim().length > 0) {
|
|
223
|
+
return "person_agent";
|
|
224
|
+
}
|
|
225
|
+
const inbound = context?.request_headers?.["x-agent-purpose"]?.trim();
|
|
226
|
+
if (inbound !== undefined && inbound.length > 0) return inbound;
|
|
227
|
+
const fromRequest = request?.metadata?.["agent_purpose"];
|
|
228
|
+
if (typeof fromRequest === "string" && fromRequest.trim().length > 0) return fromRequest.trim();
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
@@ -108,7 +108,7 @@ export async function buddyGenerateImage(
|
|
|
108
108
|
context: ProviderDispatchContext,
|
|
109
109
|
): Promise<ImageGenerationOutcome> {
|
|
110
110
|
const model = modelOf(body, candidate);
|
|
111
|
-
if (model.length === 0) throw new GatewayError("invalid_request", 400, "model is required");
|
|
111
|
+
if (model.length === 0) throw new GatewayError("invalid_request", 400, "model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
112
112
|
const prompt = imagePrompt(body);
|
|
113
113
|
if (config.imageGenerationPath !== undefined) {
|
|
114
114
|
const requestBody: Record<string, unknown> = { model, prompt };
|
|
@@ -134,28 +134,28 @@ export async function buddyGenerateImage(
|
|
|
134
134
|
release();
|
|
135
135
|
}
|
|
136
136
|
if (!isRecord(responseBody)) {
|
|
137
|
-
throw new GatewayError("platform_unavailable", 502, "CodeBuddy image generation returned an invalid response", {}, "upstream");
|
|
137
|
+
throw new GatewayError("platform_unavailable", 502, "CodeBuddy image generation returned an invalid response (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
138
138
|
}
|
|
139
139
|
const providerError = buddyErrorOf(responseBody);
|
|
140
140
|
if (providerError !== undefined) {
|
|
141
|
-
throw new GatewayError("platform_unavailable", 502, providerError
|
|
141
|
+
throw new GatewayError("platform_unavailable", 502, `${providerError} (request {requestId}). The upstream came back empty-handed — retry 🌙`, {}, "upstream");
|
|
142
142
|
}
|
|
143
143
|
if (responseBody.code !== undefined && responseBody.code !== 0 && responseBody.code !== "0") {
|
|
144
144
|
const message =
|
|
145
145
|
typeof responseBody.msg === "string" && responseBody.msg.trim().length > 0
|
|
146
146
|
? responseBody.msg.trim()
|
|
147
147
|
: `CodeBuddy image generation failed with code ${String(responseBody.code)}`;
|
|
148
|
-
throw new GatewayError("platform_unavailable", 502, message
|
|
148
|
+
throw new GatewayError("platform_unavailable", 502, `${message} (request {requestId}). The upstream came back empty-handed — retry 🌙`, {}, "upstream");
|
|
149
149
|
}
|
|
150
150
|
if (!isRecord(responseBody.data)) {
|
|
151
|
-
throw new GatewayError("platform_unavailable", 502, "CodeBuddy image generation returned no image data", {}, "upstream");
|
|
151
|
+
throw new GatewayError("platform_unavailable", 502, "CodeBuddy image generation returned no image data (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
152
152
|
}
|
|
153
153
|
const result = responseBody.data;
|
|
154
154
|
if (!Array.isArray(result.data) || result.data.some((image) => !isRecord(image))) {
|
|
155
|
-
throw new GatewayError("platform_unavailable", 502, "CodeBuddy image generation returned malformed image data", {}, "upstream");
|
|
155
|
+
throw new GatewayError("platform_unavailable", 502, "CodeBuddy image generation returned malformed image data (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
156
156
|
}
|
|
157
157
|
if (result.data.length === 0) {
|
|
158
|
-
throw new GatewayError("platform_unavailable", 502, "CodeBuddy image generation returned no images", {}, "upstream");
|
|
158
|
+
throw new GatewayError("platform_unavailable", 502, "CodeBuddy image generation returned no images (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
159
159
|
}
|
|
160
160
|
return {
|
|
161
161
|
...(typeof result.created === "number" ? { created: result.created } : {}),
|
|
@@ -217,7 +217,7 @@ export async function buddyGenerateImage(
|
|
|
217
217
|
if (!contentType.includes("text/event-stream")) {
|
|
218
218
|
const parsed: unknown = await response.json().catch(() => null);
|
|
219
219
|
const message = buddyErrorOf(parsed) ?? "CodeBuddy image generation returned a non-stream body";
|
|
220
|
-
throw new GatewayError("platform_unavailable", 502, message
|
|
220
|
+
throw new GatewayError("platform_unavailable", 502, `${message} (request {requestId}). The upstream came back empty-handed — retry 🌙`, {}, "upstream");
|
|
221
221
|
}
|
|
222
222
|
let content = "";
|
|
223
223
|
for await (const event of decodeSseEvents(response.body, { signal: context.abort_signal })) {
|
|
@@ -232,7 +232,7 @@ export async function buddyGenerateImage(
|
|
|
232
232
|
if (!isRecord(parsed)) continue;
|
|
233
233
|
if (isRecord(parsed.error)) {
|
|
234
234
|
const message = isRecord(parsed.error) && typeof parsed.error.message === "string" ? parsed.error.message : "CodeBuddy image generation failed";
|
|
235
|
-
throw new GatewayError("platform_unavailable", 502, message
|
|
235
|
+
throw new GatewayError("platform_unavailable", 502, `${message} (request {requestId}). The upstream came back empty-handed — retry 🌙`, {}, "upstream");
|
|
236
236
|
}
|
|
237
237
|
const choices = parsed.choices;
|
|
238
238
|
if (!Array.isArray(choices) || !isRecord(choices[0])) continue;
|
|
@@ -244,7 +244,7 @@ export async function buddyGenerateImage(
|
|
|
244
244
|
throw new GatewayError(
|
|
245
245
|
"platform_unavailable",
|
|
246
246
|
502,
|
|
247
|
-
"CodeBuddy image generation returned no image in the chat stream",
|
|
247
|
+
"CodeBuddy image generation returned no image in the chat stream (request {requestId}). The upstream came back empty-handed — retry 🌙",
|
|
248
248
|
{},
|
|
249
249
|
"upstream",
|
|
250
250
|
);
|
|
@@ -318,7 +318,7 @@ export async function buddyGenerateVideo(
|
|
|
318
318
|
context: ProviderDispatchContext,
|
|
319
319
|
): Promise<Record<string, unknown>> {
|
|
320
320
|
const model = modelOf(body, candidate);
|
|
321
|
-
if (model.length === 0) throw new GatewayError("invalid_request", 400, "model is required");
|
|
321
|
+
if (model.length === 0) throw new GatewayError("invalid_request", 400, "model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
322
322
|
const prompt = imagePrompt(body);
|
|
323
323
|
const submitBody: Record<string, unknown> = { model, prompt };
|
|
324
324
|
if (typeof body.n === "number" && Number.isFinite(body.n)) submitBody["n"] = Math.max(1, Math.floor(body.n));
|
|
@@ -354,14 +354,14 @@ export async function buddyGenerateVideo(
|
|
|
354
354
|
if (url !== undefined) return { data: [{ url }] };
|
|
355
355
|
// Otherwise cb refused (HTTP 200 error envelope) — surface its own reason.
|
|
356
356
|
const message = buddyErrorOf(submitted) ?? "CodeBuddy video submit returned no task id";
|
|
357
|
-
throw new GatewayError("platform_unavailable", 502, message
|
|
357
|
+
throw new GatewayError("platform_unavailable", 502, `${message} (request {requestId}). The upstream came back empty-handed — retry 🌙`, {}, "upstream");
|
|
358
358
|
}
|
|
359
359
|
// Poll the sibling task endpoint until the clip is ready.
|
|
360
360
|
const taskPath = `${submitUrl.replace(/\/+$/, "")}/${taskId}`;
|
|
361
361
|
const deadline = Date.now() + VIDEO_POLL_TIMEOUT_MS;
|
|
362
362
|
for (;;) {
|
|
363
363
|
if (context.abort_signal?.aborted) {
|
|
364
|
-
throw new GatewayError("transport_closed", 499, "video generation aborted");
|
|
364
|
+
throw new GatewayError("transport_closed", 499, "video generation aborted (request {requestId}). Send it again whenever ready 🙃");
|
|
365
365
|
}
|
|
366
366
|
const lifecycle = createUpstreamDeadlineLifecycle(context);
|
|
367
367
|
let statusRes: Response;
|
|
@@ -374,7 +374,7 @@ export async function buddyGenerateVideo(
|
|
|
374
374
|
} catch (error: unknown) {
|
|
375
375
|
const abortError = abortGatewayError(lifecycle, error, context.abort_signal);
|
|
376
376
|
if (abortError) throw abortError;
|
|
377
|
-
throw new GatewayError("platform_unavailable", 502, `CodeBuddy video status unreachable: ${error instanceof Error ? error.message : String(error)}
|
|
377
|
+
throw new GatewayError("platform_unavailable", 502, `CodeBuddy video status unreachable (request {requestId}): ${error instanceof Error ? error.message : String(error)}. The connection ghosted us — come back in a moment 👻`, {}, "upstream");
|
|
378
378
|
} finally {
|
|
379
379
|
lifecycle.release();
|
|
380
380
|
}
|
|
@@ -386,10 +386,10 @@ export async function buddyGenerateVideo(
|
|
|
386
386
|
if (url !== undefined) return { data: [{ url }], task_id: taskId };
|
|
387
387
|
const status = videoStatusOf(payload);
|
|
388
388
|
if (status !== undefined && !VIDEO_PENDING.has(status)) {
|
|
389
|
-
throw new GatewayError("platform_unavailable", 502, `CodeBuddy video task ended in state "${status}" with no clip
|
|
389
|
+
throw new GatewayError("platform_unavailable", 502, `CodeBuddy video task ended in state "${status}" with no clip (request {requestId}). The upstream came back empty-handed — retry 🌙`, {}, "upstream");
|
|
390
390
|
}
|
|
391
391
|
if (Date.now() > deadline) {
|
|
392
|
-
throw new GatewayError("platform_unavailable", 504, `CodeBuddy video task ${taskId} did not finish within ${VIDEO_POLL_TIMEOUT_MS}ms
|
|
392
|
+
throw new GatewayError("platform_unavailable", 504, `CodeBuddy video task ${taskId} did not finish within ${VIDEO_POLL_TIMEOUT_MS}ms (request {requestId}). Some things just take longer 🐢`, {}, "upstream");
|
|
393
393
|
}
|
|
394
394
|
await new Promise((resolve) => setTimeout(resolve, VIDEO_POLL_INTERVAL_MS));
|
|
395
395
|
}
|
|
@@ -120,7 +120,7 @@ export function buddyAccountUid(accessToken: string): string | undefined {
|
|
|
120
120
|
* Falls back to `undefined` when the token carries no usable identity, letting
|
|
121
121
|
* the console keep the operator-supplied label.
|
|
122
122
|
*/
|
|
123
|
-
|
|
123
|
+
function buddyAccountLabel(accessToken: string): string | undefined {
|
|
124
124
|
const claims = decodeJwtPayload(accessToken);
|
|
125
125
|
if (!claims) return undefined;
|
|
126
126
|
const email = nonEmptyTrimmedString(claims.email) ?? nonEmptyTrimmedString(claims.preferred_username);
|
|
@@ -48,8 +48,7 @@ function isAgentPromptText(text: string): boolean {
|
|
|
48
48
|
);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
const CODEBUDDY_CN_NEUTRAL_PROMPT =
|
|
52
|
-
"You are a helpful AI assistant that helps with software engineering tasks.";
|
|
51
|
+
const CODEBUDDY_CN_NEUTRAL_PROMPT = "You are a helpful assistant.";
|
|
53
52
|
|
|
54
53
|
function flattenContent(content: unknown): string {
|
|
55
54
|
if (typeof content === "string") return content;
|
|
@@ -51,22 +51,11 @@ export const CODEBUDDY_BASE_URL = providerBaseUrl("cb");
|
|
|
51
51
|
*
|
|
52
52
|
* The wire contract is that the request *opens* with a `system` turn (code
|
|
53
53
|
* `11128`); the gateway replaces any caller `system`/`developer` turn with this
|
|
54
|
-
* fixed prompt.
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* than a neutral stand-in.
|
|
58
|
-
*
|
|
59
|
-
* Keeping the official identity is forward-compatible: the upstream is not
|
|
60
|
-
* observed to validate this text today, but a proxy that claims the real
|
|
61
|
-
* client's identity cannot be caught out if it starts to. A previous neutral
|
|
62
|
-
* persona ("You are a pragmatic and direct software engineering assistant…")
|
|
63
|
-
* worked, but diverged from every request the official CLI emits.
|
|
54
|
+
* fixed prompt. Deliberately neutral: a simple helpful-assistant persona with
|
|
55
|
+
* no client/CLI branding, kept minimal so the text reads naturally to any
|
|
56
|
+
* model and does not advertise a channel identity upstream.
|
|
64
57
|
*/
|
|
65
|
-
export const CODEBUDDY_SYSTEM_PROMPT =
|
|
66
|
-
"You are CodeBuddy Code.\n\n" +
|
|
67
|
-
"You are an interactive CLI tool that helps users with software engineering tasks. " +
|
|
68
|
-
"Use the instructions below and the tools available to you to assist the user. " +
|
|
69
|
-
"Your main goal is to follow the USER's instructions at each message, denoted by the <user_query> tag.";
|
|
58
|
+
export const CODEBUDDY_SYSTEM_PROMPT = "You are a helpful assistant.";
|
|
70
59
|
|
|
71
60
|
function codeBuddyIntlPrePayload(
|
|
72
61
|
payload: Record<string, unknown>,
|
|
@@ -81,7 +70,7 @@ function codeBuddyIntlPrePayload(
|
|
|
81
70
|
typeof rawModel === "string" && rawModel.length > 0
|
|
82
71
|
? rawModel
|
|
83
72
|
: candidate.model_id;
|
|
84
|
-
if (!source) throw new GatewayError("invalid_request", 400, "CodeBuddy model is required");
|
|
73
|
+
if (!source) throw new GatewayError("invalid_request", 400, "CodeBuddy model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
85
74
|
const messages = payload["messages"];
|
|
86
75
|
if (Array.isArray(messages)) {
|
|
87
76
|
applyBuddySystemPrompt(
|
|
@@ -3,7 +3,15 @@ import type { CanonicalRequest } from "../../../../protocol/canonical-model";
|
|
|
3
3
|
import type { ProviderDispatchContext, ProviderDispatchTarget, ProviderId } from "../../../provider-contracts";
|
|
4
4
|
import { resolveInboundSessionId } from "../../../operations/session-resolution";
|
|
5
5
|
import { buddyConversationHeaders } from "../buddy-conversation-headers";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
buddyAgentPurpose,
|
|
8
|
+
buddyEnterprise,
|
|
9
|
+
buddyOAuthIdentityHeaders,
|
|
10
|
+
buddyPrivateData,
|
|
11
|
+
buddyUserId,
|
|
12
|
+
resolveBuddyDeviceBinding,
|
|
13
|
+
resolveBuddyIdentity,
|
|
14
|
+
} from "../buddy-identity";
|
|
7
15
|
import { buildCodeBuddyUserAgent, getCodeBuddyCnVersion, getCodeBuddyVersion } from "../../../operations/client-versions";
|
|
8
16
|
import { buddyDeviceTokenHeaders } from "../workbuddy/shared";
|
|
9
17
|
import { CODEBUDDY_TURING_CONFIG } from "../turing-device-token";
|
|
@@ -40,6 +48,13 @@ export async function codebuddyHeaders(
|
|
|
40
48
|
...(conversationId === undefined ? {} : { conversationId }),
|
|
41
49
|
});
|
|
42
50
|
if (resolveBuddyIdentity(context, cliIdentity) === "cli") {
|
|
51
|
+
const purpose = buddyAgentPurpose(context, request);
|
|
52
|
+
// Root/parent conversation context is forwarded only when the caller
|
|
53
|
+
// actually supplied it — the reference emits these conditionally for
|
|
54
|
+
// subagent/root chains and never invents them.
|
|
55
|
+
const inbound = context?.request_headers;
|
|
56
|
+
const rootRequestId = inbound?.["x-root-request-id"]?.trim();
|
|
57
|
+
const parentConversationId = inbound?.["x-parent-conversation-id"]?.trim();
|
|
43
58
|
return {
|
|
44
59
|
// The CLI sends `Accept: application/json` and no device token. It keeps
|
|
45
60
|
// the request-shape markers (`X-Requested-With`, `X-CodeBuddy-Request`)
|
|
@@ -55,19 +70,24 @@ export async function codebuddyHeaders(
|
|
|
55
70
|
"X-Domain": codebuddyDomain(variant),
|
|
56
71
|
"x-requested-with": "XMLHttpRequest",
|
|
57
72
|
"x-codebuddy-request": "1",
|
|
58
|
-
|
|
59
|
-
// verified against the live API that a request succeeds without it — but
|
|
60
|
-
// it is part of the client's real request, and matching the client is the
|
|
61
|
-
// defence against a channel check tightening later.
|
|
62
|
-
"X-Agent-Purpose": "conversation",
|
|
73
|
+
...(purpose === undefined ? {} : { "X-Agent-Purpose": purpose }),
|
|
63
74
|
...conversation,
|
|
75
|
+
...(rootRequestId === undefined ? {} : { "X-Root-Request-ID": rootRequestId }),
|
|
76
|
+
...(parentConversationId === undefined
|
|
77
|
+
? {}
|
|
78
|
+
: { "X-Parent-Conversation-ID": parentConversationId }),
|
|
64
79
|
...buddyCliTraceHeaders(conversation),
|
|
80
|
+
// The CLI's OAuth identity family: X-User-Id from the JWT sub plus the
|
|
81
|
+
// base64 X-Userinfo envelope when identity fields exist.
|
|
82
|
+
...buddyOAuthIdentityHeaders(context),
|
|
65
83
|
...buddyCliHeaders({
|
|
66
84
|
userId: buddyUserId(context),
|
|
67
85
|
enterpriseId: buddyEnterprise(context),
|
|
86
|
+
privateData: buddyPrivateData(context),
|
|
68
87
|
}),
|
|
69
88
|
};
|
|
70
89
|
}
|
|
90
|
+
const purpose = buddyAgentPurpose(context, request);
|
|
71
91
|
return {
|
|
72
92
|
accept: "text/event-stream",
|
|
73
93
|
"User-Agent": ua,
|
|
@@ -81,9 +101,10 @@ export async function codebuddyHeaders(
|
|
|
81
101
|
"X-Domain": codebuddyDomain(variant),
|
|
82
102
|
"x-requested-with": "XMLHttpRequest",
|
|
83
103
|
"x-codebuddy-request": "1",
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
|
|
104
|
+
// The effective agent purpose, matching the reference's dynamic value.
|
|
105
|
+
// The reference does not invent `conversation`; it sends the purpose only
|
|
106
|
+
// when one exists.
|
|
107
|
+
...(purpose === undefined ? {} : { "X-Agent-Purpose": purpose }),
|
|
87
108
|
// Same family WorkBuddy sends: the upstream's channel check reads the
|
|
88
109
|
// turn-level aggregation key, and a chat request without it is refused for a
|
|
89
110
|
// missing conversation id.
|
|
@@ -56,15 +56,11 @@ export const WORKBUDDY_BASE_URL = providerBaseUrl("workbuddy");
|
|
|
56
56
|
* channel"`. So this prompt is a wire contract, not merely a product choice —
|
|
57
57
|
* see the sibling in `codebuddy.ts`.
|
|
58
58
|
*
|
|
59
|
-
* The text is
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* neutral persona was accepted but diverged from every request the official
|
|
63
|
-
* desktop client emits.
|
|
59
|
+
* The text is deliberately neutral: a simple helpful-assistant persona with no
|
|
60
|
+
* client/CLI branding, kept minimal so it reads naturally to any model and
|
|
61
|
+
* does not advertise a channel identity upstream.
|
|
64
62
|
*/
|
|
65
|
-
export const WORKBUDDY_SYSTEM_PROMPT =
|
|
66
|
-
"You are WorkBuddy, a powerful AI assistant.\n\n" +
|
|
67
|
-
"Your main goal is to follow the USER's instructions at each message, denoted by the <user_query> tag.";
|
|
63
|
+
export const WORKBUDDY_SYSTEM_PROMPT = "You are a helpful assistant.";
|
|
68
64
|
|
|
69
65
|
/**
|
|
70
66
|
* Reconstructs generic function declarations when a later tool-history turn
|
|
@@ -134,7 +130,7 @@ export function workbuddyPrePayload(
|
|
|
134
130
|
const rawModel = payload["model"];
|
|
135
131
|
const source =
|
|
136
132
|
typeof rawModel === "string" && rawModel.length > 0 ? rawModel : candidate.model_id;
|
|
137
|
-
if (!source) throw new GatewayError("invalid_request", 400, "WorkBuddy model is required");
|
|
133
|
+
if (!source) throw new GatewayError("invalid_request", 400, "WorkBuddy model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
138
134
|
const messages = payload["messages"];
|
|
139
135
|
if (Array.isArray(messages)) {
|
|
140
136
|
const normalizedMessages = messages as Array<Record<string, unknown>>;
|
|
@@ -156,7 +152,7 @@ export function workbuddyPrePayload(
|
|
|
156
152
|
// declared reasoning-effort scale.
|
|
157
153
|
const WORKBUDDY_RAW: readonly BuddyRawEntry[] = BUDDY_SHARED_RAW;
|
|
158
154
|
|
|
159
|
-
|
|
155
|
+
function makeWorkBuddyModels(providerId: "workbuddy" | "workbuddycn"): readonly ModelDefinition[] {
|
|
160
156
|
return [
|
|
161
157
|
...WORKBUDDY_RAW.filter(
|
|
162
158
|
(entry) => !BUDDY_IMAGE_MODEL_ID_SET.has(entry[0]) && !BUDDY_VIDEO_MODEL_ID_SET.has(entry[0]),
|
|
@@ -8,7 +8,15 @@ import type { ProviderDispatchContext, ProviderDispatchTarget, ProviderId } from
|
|
|
8
8
|
import { resolveInboundSessionId } from "../../../operations/session-resolution";
|
|
9
9
|
import { buddyConversationHeaders } from "../buddy-conversation-headers";
|
|
10
10
|
import { buddyCliHeaders, buddyCliTraceHeaders } from "../buddy-cli-headers";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
buddyAgentPurpose,
|
|
13
|
+
buddyEnterprise,
|
|
14
|
+
buddyOAuthIdentityHeaders,
|
|
15
|
+
buddyPrivateData,
|
|
16
|
+
buddyUserId,
|
|
17
|
+
resolveBuddyDeviceBinding,
|
|
18
|
+
resolveBuddyIdentity,
|
|
19
|
+
} from "../buddy-identity";
|
|
12
20
|
import {
|
|
13
21
|
buildWorkBuddyUserAgent,
|
|
14
22
|
getWorkBuddyClientVersion,
|
|
@@ -86,7 +94,11 @@ export async function workbuddyHeaders(
|
|
|
86
94
|
messageIdStyle: identity === "desktop" ? "uuid" : "hex",
|
|
87
95
|
});
|
|
88
96
|
const accountId = context?.credential.account_id;
|
|
97
|
+
const purpose = buddyAgentPurpose(context, request);
|
|
89
98
|
if (identity === "cli") {
|
|
99
|
+
const inbound = context?.request_headers;
|
|
100
|
+
const rootRequestId = inbound?.["x-root-request-id"]?.trim();
|
|
101
|
+
const parentConversationId = inbound?.["x-parent-conversation-id"]?.trim();
|
|
90
102
|
// The reference CLI: issued by the OpenAI Node SDK, so no browser
|
|
91
103
|
// *transport* header (origin/referer/accept-language) and no device token,
|
|
92
104
|
// and the machine/session device pair does not exist — only `X-User-Id`,
|
|
@@ -99,17 +111,23 @@ export async function workbuddyHeaders(
|
|
|
99
111
|
"x-requested-with": "XMLHttpRequest",
|
|
100
112
|
"x-codebuddy-request": "1",
|
|
101
113
|
"x-domain": domain,
|
|
102
|
-
"x-agent-purpose":
|
|
114
|
+
...(purpose === undefined ? {} : { "x-agent-purpose": purpose }),
|
|
103
115
|
"x-ide-name": "CLI",
|
|
104
116
|
"x-ide-type": "CLI",
|
|
105
117
|
"x-ide-version": getWorkBuddyCliVersion(),
|
|
106
118
|
"x-product": "SaaS",
|
|
107
119
|
"x-no-enterprise-id": "1",
|
|
108
120
|
...conversation,
|
|
121
|
+
...(rootRequestId === undefined ? {} : { "x-root-request-id": rootRequestId }),
|
|
122
|
+
...(parentConversationId === undefined
|
|
123
|
+
? {}
|
|
124
|
+
: { "x-parent-conversation-id": parentConversationId }),
|
|
109
125
|
...buddyCliTraceHeaders(conversation),
|
|
126
|
+
...buddyOAuthIdentityHeaders(context),
|
|
110
127
|
...buddyCliHeaders({
|
|
111
128
|
userId: buddyUserId(context),
|
|
112
129
|
enterpriseId: buddyEnterprise(context),
|
|
130
|
+
privateData: buddyPrivateData(context),
|
|
113
131
|
}),
|
|
114
132
|
};
|
|
115
133
|
}
|
|
@@ -122,7 +140,7 @@ export async function workbuddyHeaders(
|
|
|
122
140
|
"x-requested-with": "XMLHttpRequest",
|
|
123
141
|
"x-codebuddy-request": "1",
|
|
124
142
|
"x-domain": domain,
|
|
125
|
-
"x-agent-purpose":
|
|
143
|
+
...(purpose === undefined ? {} : { "x-agent-purpose": purpose }),
|
|
126
144
|
"x-ide-name": "WorkBuddy",
|
|
127
145
|
"x-ide-type": "WorkBuddy",
|
|
128
146
|
"x-ide-version": clientVersion,
|
|
@@ -67,7 +67,7 @@ export const ANTHROPIC_BETA_CAPABILITIES: Readonly<Record<string, readonly strin
|
|
|
67
67
|
const BETA_TOKEN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
68
68
|
|
|
69
69
|
function invalidBeta(message: string, value: unknown): GatewayError {
|
|
70
|
-
return new GatewayError("invalid_request", 400, message
|
|
70
|
+
return new GatewayError("invalid_request", 400, `${message} (request {requestId}). Check the shape of what you sent — then resend 🪞`, { field: "anthropic-beta", value });
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
/**
|