diff --git a/docs/i18n/pl/docs/providers/ALIBABA-QWEN-PROVIDER-FAMILIES.md b/docs/i18n/pl/docs/providers/ALIBABA-QWEN-PROVIDER-FAMILIES.md index a08c63839f..5a633a0656 100644 --- a/docs/i18n/pl/docs/providers/ALIBABA-QWEN-PROVIDER-FAMILIES.md +++ b/docs/i18n/pl/docs/providers/ALIBABA-QWEN-PROVIDER-FAMILIES.md @@ -32,7 +32,7 @@ innych rodzin endpointów, więc wszystkie cztery produkty pozostają osobnymi I | Rodzina providera | `global-sg` | `china-beijing` | Format wire | | ----------------------- | ------------------------------------------------------------------------ | -------------------------------------------------------------------- | ----------- | | `alibaba` | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | `https://dashscope.aliyuncs.com/compatible-mode/v1` | OpenAI | -| `bailian-coding-plan` | `https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1` | `https://coding.dashscope.aliyuncs.com/apps/anthropic/v1` | Anthropic | +| `bailian-coding-plan` | `https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1` | `https://token-plan.cn-beijing.maas.aliyuncs.com/apps/anthropic/v1` | Anthropic | | `qwen-cloud` | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | `https://dashscope.aliyuncs.com/compatible-mode/v1` | OpenAI | | `qwen-cloud-token-plan` | `https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1` | `https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1` | OpenAI | diff --git a/src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts b/src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts index bce408d4f9..fc52c914ad 100644 --- a/src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts +++ b/src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts @@ -248,7 +248,7 @@ export const CONFIGURABLE_BASE_URL_PROVIDERS = new Set([ export const DEFAULT_PROVIDER_BASE_URLS: Record = { "azure-openai": "https://example-resource.openai.azure.com", "azure-ai": "https://example-resource.services.ai.azure.com/openai/v1", - "bailian-coding-plan": "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1", + "bailian-coding-plan": "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1", "xiaomi-mimo": "https://token-plan-sgp.xiaomimimo.com/v1", siliconflow: "https://api.siliconflow.com/v1", "searxng-search": "http://localhost:8888/search", diff --git a/src/lib/providers/validation/audioMiscProviders.ts b/src/lib/providers/validation/audioMiscProviders.ts index e6df87dc80..c00ac829ef 100644 --- a/src/lib/providers/validation/audioMiscProviders.ts +++ b/src/lib/providers/validation/audioMiscProviders.ts @@ -294,7 +294,9 @@ export async function validateBailianCodingPlanProvider({ providerSpecificData ), body: JSON.stringify({ - model: "qwen3-coder-plus", + // qwen3-coder-plus belonged to the retired Coding Plan host and is absent from + // BAILIAN_CODING_PLAN_MODELS; probe with a model this plan actually serves. + model: providerSpecificData.validationModelId || "qwen3.7-max", max_tokens: 1, messages: [{ role: "user", content: "test" }], }), diff --git a/src/shared/constants/alibabaProviderRegions.ts b/src/shared/constants/alibabaProviderRegions.ts index cd8b61a464..478e150de5 100644 --- a/src/shared/constants/alibabaProviderRegions.ts +++ b/src/shared/constants/alibabaProviderRegions.ts @@ -11,9 +11,14 @@ export const ALIBABA_PROVIDER_ENDPOINTS: Readonly< "global-sg": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1", "china-beijing": "https://dashscope.aliyuncs.com/compatible-mode/v1", }, + // The catalog entry is the personal TOKEN Plan (see providers/apikey/regional.ts: + // name "Alibaba Token Plan"). The legacy coding-intl/coding hosts serve the separate + // Coding Plan product and reject Token Plan keys with 401 invalid_api_key — verified + // live 2026-08-18 against the same key that returns 429 (quota) on the host below. + // Keeps /apps/anthropic/v1 because the registry entry is format "claude". "bailian-coding-plan": { - "global-sg": "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1", - "china-beijing": "https://coding.dashscope.aliyuncs.com/apps/anthropic/v1", + "global-sg": "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1", + "china-beijing": "https://token-plan.cn-beijing.maas.aliyuncs.com/apps/anthropic/v1", }, "qwen-cloud": { "global-sg": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1", @@ -74,11 +79,48 @@ function normalizeEndpoint(value: string): string { .toLowerCase(); } +/** + * Preset hosts this family used to ship. They must keep counting as presets: a connection + * saved while a preset was current carries that URL in providerSpecificData.baseUrl, and if + * a retired preset were mistaken for a deliberate custom URL the connection would stay + * pinned to a host that no longer accepts its key, deaf to the region selector. + */ +const LEGACY_FAMILY_PRESETS: Readonly> = { + alibaba: [], + // Retired 2026-08-18 — Coding Plan hosts, wrong product for this Token Plan entry. + "bailian-coding-plan": [ + "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1", + "https://coding.dashscope.aliyuncs.com/apps/anthropic/v1", + ], + "qwen-cloud": [], + "qwen-cloud-token-plan": [], +}; + +/** + * Media (AIGC) roots, when they differ from the chat root. + * + * Only bailian-coding-plan diverges: its CHAT traffic moved to the Token Plan host + * (2026-08), but image/video generation keeps running on the DashScope AIGC service + * (`/api/v1/services/aigc/…`) — see imageRegistry.ts / videoRegistry.ts, which pin those + * hosts literally. Deriving media from the chat root would have silently repointed every + * Bailian image/video call at a host that does not serve AIGC. + */ +const ALIBABA_PROVIDER_MEDIA_OVERRIDES: Partial< + Record>> +> = { + "bailian-coding-plan": { + "global-sg": "https://coding-intl.dashscope.aliyuncs.com/api/v1", + "china-beijing": "https://coding.dashscope.aliyuncs.com/api/v1", + }, +}; + function isFamilyPresetUrl(family: AlibabaProviderFamily, value: string): boolean { const normalized = normalizeEndpoint(value); - return ALIBABA_PROVIDER_REGION_VALUES.some( + const isCurrentPreset = ALIBABA_PROVIDER_REGION_VALUES.some( (region) => normalizeEndpoint(ALIBABA_PROVIDER_ENDPOINTS[family][region]) === normalized ); + if (isCurrentPreset) return true; + return LEGACY_FAMILY_PRESETS[family].some((preset) => normalizeEndpoint(preset) === normalized); } export function isAlibabaRegionalProvider(providerId: string | null | undefined): boolean { @@ -167,6 +209,22 @@ export function resolveAlibabaProviderMediaBaseUrl( providerSpecificData?: unknown, fallback = "" ): string { + const family = canonicalProviderFamily(providerId); + const data = asRecord(providerSpecificData); + const configuredBaseUrl = + typeof data.baseUrl === "string" && data.baseUrl.trim() ? data.baseUrl.trim() : ""; + const mediaOverride = family ? ALIBABA_PROVIDER_MEDIA_OVERRIDES[family] : undefined; + + // A custom base URL still drives media, as before — the override only replaces the + // preset-derived host. + if ( + family && + mediaOverride && + (!configuredBaseUrl || isFamilyPresetUrl(family, configuredBaseUrl)) + ) { + return mediaOverride[resolveAlibabaProviderRegion(providerId, data)]; + } + return stripTrailingSlashes( resolveAlibabaProviderBaseUrl(providerId, providerSpecificData, fallback).trim() ) diff --git a/src/shared/constants/config.ts b/src/shared/constants/config.ts index 0ec376305a..eacf73db7e 100644 --- a/src/shared/constants/config.ts +++ b/src/shared/constants/config.ts @@ -38,7 +38,8 @@ export const PROVIDER_ENDPOINTS = { helixmind: "https://helixmind.online/v1/chat/completions", glm: "https://api.z.ai/api/anthropic/v1/messages", glmt: "https://api.z.ai/api/anthropic/v1/messages", - "bailian-coding-plan": "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1/messages", + "bailian-coding-plan": + "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1/messages", "qwen-cloud": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions", "qwen-cloud-token-plan": "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1/chat/completions", diff --git a/tests/e2e/providers-bailian-coding-plan.spec.ts b/tests/e2e/providers-bailian-coding-plan.spec.ts index 4194d6bf34..01e143b826 100644 --- a/tests/e2e/providers-bailian-coding-plan.spec.ts +++ b/tests/e2e/providers-bailian-coding-plan.spec.ts @@ -3,7 +3,8 @@ import { gotoDashboardRoute } from "./helpers/dashboardAuth"; // #7882 replaced this provider's free-text Base URL field with a region step: // the endpoint is now derived from the choice ("global-sg" -> -// coding-intl.dashscope.aliyuncs.com, "china-beijing" -> coding.dashscope.aliyuncs.com, +// token-plan.ap-southeast-1.maas.aliyuncs.com, "china-beijing" -> +// token-plan.cn-beijing.maas.aliyuncs.com, // see src/shared/constants/alibabaProviderRegions.ts), so the modal persists // providerSpecificData.region instead of a baseUrl. A per-connection base-URL // override still exists, but it moved to Advanced in the edit-connection modal. @@ -120,7 +121,7 @@ test.describe("Bailian Coding Plan Provider", () => { // free-text Base URL field, which #7882 removed for this provider — an invalid // URL is no longer reachable from this modal. Replaced with the other half of // the region contract: the China-mainland choice must persist as typed, since - // that is what selects the coding.dashscope.aliyuncs.com endpoint. + // that is what selects the token-plan.cn-beijing.maas.aliyuncs.com endpoint. test("region step persists the China-mainland (Beijing) choice", async ({ page }) => { const capturedPayloads: { createProvider?: Record } = {}; @@ -222,6 +223,8 @@ test.describe("Bailian Coding Plan Provider", () => { expect(capturedPayloads.createProvider).toBeDefined(); const payload = capturedPayloads.createProvider; expect(payload?.providerSpecificData).toBeDefined(); - expect((payload?.providerSpecificData as Record)?.region).toBe("china-beijing"); + expect((payload?.providerSpecificData as Record)?.region).toBe( + "china-beijing" + ); }); }); diff --git a/tests/unit/alibaba-provider-regions.test.ts b/tests/unit/alibaba-provider-regions.test.ts index a9e8a65094..07f879ff5e 100644 --- a/tests/unit/alibaba-provider-regions.test.ts +++ b/tests/unit/alibaba-provider-regions.test.ts @@ -24,8 +24,8 @@ test("Alibaba-family endpoint matrix keeps product and region boundaries distinc "china-beijing": "https://dashscope.aliyuncs.com/compatible-mode/v1", }, "bailian-coding-plan": { - "global-sg": "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1", - "china-beijing": "https://coding.dashscope.aliyuncs.com/apps/anthropic/v1", + "global-sg": "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1", + "china-beijing": "https://token-plan.cn-beijing.maas.aliyuncs.com/apps/anthropic/v1", }, "qwen-cloud": { "global-sg": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1", @@ -92,7 +92,7 @@ test("DefaultExecutor applies the regional endpoint to normal requests", () => { codingPlan.buildUrl("qwen3.7-plus", true, 0, { providerSpecificData: { region: "china-beijing" }, }), - "https://coding.dashscope.aliyuncs.com/apps/anthropic/v1/messages" + "https://token-plan.cn-beijing.maas.aliyuncs.com/apps/anthropic/v1/messages" ); const qwenCloud = new DefaultExecutor("qwen-cloud"); @@ -133,7 +133,11 @@ test("provider validation probes the selected Coding Plan region", async () => { }, }); assert.equal(result.valid, true); - assert.deepEqual(urls, ["https://coding.dashscope.aliyuncs.com/apps/anthropic/v1/messages"]); + // The stored URL is a RETIRED preset, so it must not pin the connection: the + // china-beijing selector still wins and routes to the Token Plan CN host. + assert.deepEqual(urls, [ + "https://token-plan.cn-beijing.maas.aliyuncs.com/apps/anthropic/v1/messages", + ]); } finally { globalThis.fetch = originalFetch; } diff --git a/tests/unit/bailian-coding-plan-provider.test.ts b/tests/unit/bailian-coding-plan-provider.test.ts index a74fd53099..757578f214 100644 --- a/tests/unit/bailian-coding-plan-provider.test.ts +++ b/tests/unit/bailian-coding-plan-provider.test.ts @@ -34,7 +34,7 @@ test("bailian-coding-plan not in OAUTH_PROVIDERS", () => { }); // Schema validation tests for providerSpecificData.baseUrl -const VALID_BAILIAN_URL = "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1"; +const VALID_BAILIAN_URL = "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1"; test("createProviderSchema accepts valid baseUrl in providerSpecificData", () => { const validation = validateBody(createProviderSchema, { @@ -427,7 +427,7 @@ test("validateProviderApiKey returns invalid for 401 response (bailian-coding-pl provider: "bailian-coding-plan", apiKey: "invalid-key", providerSpecificData: { - baseUrl: "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1", + baseUrl: "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1", }, }); @@ -452,7 +452,7 @@ test("validateProviderApiKey returns invalid for 403 response (bailian-coding-pl provider: "bailian-coding-plan", apiKey: "forbidden-key", providerSpecificData: { - baseUrl: "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1", + baseUrl: "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1", }, }); @@ -479,7 +479,7 @@ test("validateProviderApiKey returns valid for 400 response (bailian-coding-plan provider: "bailian-coding-plan", apiKey: "valid-key", providerSpecificData: { - baseUrl: "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1", + baseUrl: "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1", }, }); @@ -508,7 +508,7 @@ test("validateProviderApiKey returns valid for 200 response (bailian-coding-plan provider: "bailian-coding-plan", apiKey: "valid-key", providerSpecificData: { - baseUrl: "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1", + baseUrl: "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1", }, }); @@ -533,7 +533,7 @@ test("validateProviderApiKey returns invalid for 500 response (bailian-coding-pl provider: "bailian-coding-plan", apiKey: "bad-key", providerSpecificData: { - baseUrl: "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1", + baseUrl: "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1", }, }); @@ -561,7 +561,7 @@ test("validateProviderApiKey avoids double /messages suffix for bailian-coding-p provider: "bailian-coding-plan", apiKey: "valid-key", providerSpecificData: { - baseUrl: "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1/messages", + baseUrl: "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1/messages", }, }); @@ -569,7 +569,7 @@ test("validateProviderApiKey avoids double /messages suffix for bailian-coding-p assert.equal(urls.length, 1); assert.equal( urls[0], - "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1/messages", + "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1/messages", "Should probe exactly one /messages suffix" ); } finally { @@ -588,7 +588,7 @@ test("POST /api/providers validation: bailian-coding-plan with baseUrl passes sc apiKey: "sk-placeholder-key", name: "Test Bailian Provider", providerSpecificData: { - baseUrl: "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1", + baseUrl: "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1", }, }); @@ -597,7 +597,7 @@ test("POST /api/providers validation: bailian-coding-plan with baseUrl passes sc assert.equal(validation.data.provider, "bailian-coding-plan"); assert.equal( validation.data.providerSpecificData?.baseUrl, - "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1" + "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1" ); } }); diff --git a/tests/unit/bailian-token-plan-endpoint-parity.test.ts b/tests/unit/bailian-token-plan-endpoint-parity.test.ts new file mode 100644 index 0000000000..49ccee3bf9 --- /dev/null +++ b/tests/unit/bailian-token-plan-endpoint-parity.test.ts @@ -0,0 +1,102 @@ +/** + * bailian-coding-plan ("Alibaba Token Plan") pointed inference and validation at two + * DIFFERENT hosts. + * + * #10290 moved the open-sse registry to the Token Plan host, but the dashboard's key + * validation resolves its URL through ALIBABA_PROVIDER_REGION_ENDPOINTS, which still held + * the legacy Coding Plan host. Verified live 2026-08-18 with a valid Token Plan key: + * + * coding-intl.dashscope.aliyuncs.com → 401 invalid_api_key + * token-plan.ap-southeast-1.maas... → 429 Throttling.AllocationQuota (auth OK) + * + * validateBailianCodingPlanProvider maps 401/403 to "Invalid API key", so a perfectly + * good key was rejected at add-connection time while the very same key worked for + * inference. These tests pin the two paths together. + */ + +import test from "node:test"; +import assert from "node:assert/strict"; + +import { REGISTRY } from "../../open-sse/config/providers/index.ts"; +import { PROVIDER_ENDPOINTS } from "../../src/shared/constants/config.ts"; +import { DEFAULT_PROVIDER_BASE_URLS } from "../../src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts"; +import { + ALIBABA_PROVIDER_ENDPOINTS, + resolveAlibabaProviderBaseUrl, +} from "../../src/shared/constants/alibabaProviderRegions.ts"; + +const LEGACY_CODING_PLAN_HOST = "coding-intl.dashscope.aliyuncs.com"; + +test("validation resolves the same host the inference registry dispatches to", () => { + const registryBaseUrl = REGISTRY["bailian-coding-plan"].baseUrl; + const resolved = resolveAlibabaProviderBaseUrl("bailian-coding-plan", { + region: "global-sg", + }); + + assert.equal( + resolved, + registryBaseUrl, + "the dashboard would validate the key against a different host than inference uses" + ); +}); + +test("no default endpoint still points at the Coding Plan host", () => { + // The catalog entry is a TOKEN Plan; Coding Plan keys are a different product and the + // legacy host rejects Token Plan keys outright. Compare parsed hostnames, not URL + // substrings (CodeQL js/incomplete-url-substring-sanitization). + assert.notEqual( + new URL(PROVIDER_ENDPOINTS["bailian-coding-plan"]).hostname, + LEGACY_CODING_PLAN_HOST, + "PROVIDER_ENDPOINTS still defaults to the legacy Coding Plan host" + ); + assert.notEqual( + new URL(DEFAULT_PROVIDER_BASE_URLS["bailian-coding-plan"]).hostname, + LEGACY_CODING_PLAN_HOST, + "the dashboard base-URL placeholder still shows the legacy Coding Plan host" + ); + for (const region of ["global-sg", "china-beijing"] as const) { + assert.notEqual( + new URL(ALIBABA_PROVIDER_ENDPOINTS["bailian-coding-plan"][region]).hostname, + LEGACY_CODING_PLAN_HOST, + `region ${region} still maps to the legacy Coding Plan host` + ); + } +}); + +test("both regions keep the Anthropic-compatible path the claude format requires", () => { + // format: "claude" + chatPath "/messages" — a compatible-mode URL here would 404. + for (const region of ["global-sg", "china-beijing"] as const) { + assert.ok( + ALIBABA_PROVIDER_ENDPOINTS["bailian-coding-plan"][region].endsWith("/apps/anthropic/v1"), + `region ${region} must keep the /apps/anthropic/v1 root` + ); + } +}); + +test("a saved legacy preset URL still follows the region selector", () => { + // Migration guard: connections created before the fix carry the legacy host in + // providerSpecificData.baseUrl. isFamilyPresetUrl must keep recognizing it as a + // preset — otherwise it is treated as a deliberate custom URL and the connection + // stays pinned to the host that rejects its key, with no way out but manual editing. + const legacyPreset = "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1"; + + assert.equal( + resolveAlibabaProviderBaseUrl("bailian-coding-plan", { + region: "global-sg", + baseUrl: legacyPreset, + }), + ALIBABA_PROVIDER_ENDPOINTS["bailian-coding-plan"]["global-sg"], + "a stored legacy preset must not pin the connection to the dead host" + ); +}); + +test("a genuinely custom base URL still wins over the region preset", () => { + const custom = "https://my-gateway.internal/apps/anthropic/v1"; + assert.equal( + resolveAlibabaProviderBaseUrl("bailian-coding-plan", { + region: "global-sg", + baseUrl: custom, + }), + custom + ); +}); diff --git a/tests/unit/executor-default-base.test.ts b/tests/unit/executor-default-base.test.ts index d8a5d1a046..f144d7f224 100644 --- a/tests/unit/executor-default-base.test.ts +++ b/tests/unit/executor-default-base.test.ts @@ -220,10 +220,10 @@ test("DefaultExecutor.buildUrl normalizes configurable chat-openai-compat base U assert.equal( bailian.buildUrl("qwen3-coder-plus", true, 0, { providerSpecificData: { - baseUrl: "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1", + baseUrl: "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1", }, }), - "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1/messages" + "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1/messages" ); assert.equal( heroku.buildUrl("claude-4-sonnet", true, 0, { diff --git a/tests/unit/provider-validation-specialty.test.ts b/tests/unit/provider-validation-specialty.test.ts index 7b638a79cc..c798cdf034 100644 --- a/tests/unit/provider-validation-specialty.test.ts +++ b/tests/unit/provider-validation-specialty.test.ts @@ -1451,7 +1451,9 @@ test("specialty validators cover remaining status branches for Deepgram, Assembl if (target.match(/inworld/i)) { throw new Error("inworld offline"); } - if (target.match(/dashscope\.aliyuncs\.com/i)) { + // Alibaba-family hosts: dashscope.aliyuncs.com (pay-as-you-go / AIGC) and + // *.maas.aliyuncs.com (Token Plan). + if (target.match(/(?:dashscope|maas)\.aliyuncs\.com/i)) { return new Response(JSON.stringify({ error: "server" }), { status: 500 }); } if (target.match(/longcat/i)) { @@ -1468,7 +1470,7 @@ test("specialty validators cover remaining status branches for Deepgram, Assembl provider: "bailian-coding-plan", apiKey: "bailian-key", providerSpecificData: { - baseUrl: "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1/messages", + baseUrl: "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1/messages", }, }); const longcatInvalid = await validateProviderApiKey({ provider: "longcat", apiKey: "lc-key" });