From 24142a8e91fbdd81a3eb693e31f9dcec50eb48bf Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza Date: Sat, 25 Jul 2026 04:56:46 -0300 Subject: [PATCH] fix(providers): expose base-URL override for Kimi/Moonshot CN-region keys (#7447) (#8500) CN-region Moonshot/Kimi API keys (issued on the domestic platform.kimi.com/moonshot.cn account) belong to a completely separate keyspace than the international platform.kimi.ai/api.moonshot.ai account, so OmniRoute's hard-coded international base URL rejects them with a generic "Invalid API key" 401. Neither "kimi" (legacy id) nor "moonshot" (current user-facing id) was in CONFIGURABLE_BASE_URL_PROVIDERS, so the Add-connection modal never rendered a base-URL field for them and there was no supported way to point a new connection at api.moonshot.cn. The underlying resolveBaseUrl()/buildUrl() primitives already honor a providerSpecificData.baseUrl override generically (same mechanism used by siliconflow, xiaomi-mimo, etc.) -- this only exposes that existing affordance for kimi/moonshot, defaulting to the unchanged international host so existing users see no behavior change. Co-authored-by: ikelvingo --- changelog.d/fixes/7447-kimi-cn-key-format.md | 1 + .../providers/[id]/providerPageHelpers.ts | 20 ++++++++ tests/unit/kimi-cn-region-baseurl.test.ts | 50 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 changelog.d/fixes/7447-kimi-cn-key-format.md create mode 100644 tests/unit/kimi-cn-region-baseurl.test.ts diff --git a/changelog.d/fixes/7447-kimi-cn-key-format.md b/changelog.d/fixes/7447-kimi-cn-key-format.md new file mode 100644 index 0000000000..9bd45b2eb2 --- /dev/null +++ b/changelog.d/fixes/7447-kimi-cn-key-format.md @@ -0,0 +1 @@ +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) diff --git a/src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts b/src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts index c06fcecda2..77f8e315fb 100644 --- a/src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts +++ b/src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts @@ -223,6 +223,16 @@ export const CONFIGURABLE_BASE_URL_PROVIDERS = new Set([ "searxng-search", "petals", "comfyui", + // #7447 — Moonshot/Kimi's international host (api.moonshot.ai) rejects + // CN-region keys (issued on platform.kimi.com/moonshot.cn — a separate + // account/keyspace). Neither "kimi" (legacy id) nor "moonshot" (current + // user-facing id) previously exposed a base-URL field at Add-connection + // time, so a CN-region user had no way to point a new connection at + // api.moonshot.cn. resolveBaseUrl()/buildUrl() already honor a + // providerSpecificData.baseUrl override generically — this only exposes + // the existing override affordance for these two ids. + "kimi", + "moonshot", ]); export const DEFAULT_PROVIDER_BASE_URLS: Record = { @@ -234,6 +244,11 @@ export const DEFAULT_PROVIDER_BASE_URLS: Record = { "searxng-search": "http://localhost:8888/search", petals: "https://chat.petals.dev/api/v1/generate", comfyui: "http://localhost:8188", + // #7447 — default stays the international host so existing/new + // international Kimi/Moonshot users see the same prefilled value as + // before; a CN-region user overrides it (see placeholder hint below). + kimi: "https://api.moonshot.ai/v1", + moonshot: "https://api.moonshot.ai/v1", }; export function getLocalProviderMetadata(providerId?: string | null) { @@ -327,6 +342,11 @@ export function getProviderBaseUrlPlaceholder(providerId?: string | null) { return "https://example-account.snowflakecomputing.com"; case "searxng-search": return "http://localhost:8888/search"; + case "kimi": + case "moonshot": + // #7447 — surfaces the CN-region alternative host as the placeholder + // example (mirrors the siliconflow.com/siliconflow.cn pattern above). + return "https://api.moonshot.cn/v1"; default: return ""; } diff --git a/tests/unit/kimi-cn-region-baseurl.test.ts b/tests/unit/kimi-cn-region-baseurl.test.ts new file mode 100644 index 0000000000..89650105f9 --- /dev/null +++ b/tests/unit/kimi-cn-region-baseurl.test.ts @@ -0,0 +1,50 @@ +// #7447 — Kimi/Moonshot CN-region API keys were rejected because the built-in +// "kimi"/"moonshot" registry entries are hard-coded to the international host +// (api.moonshot.ai) and neither provider exposed a base-URL field at +// Add-connection time, so a CN-region key (issued on platform.kimi.com / +// moonshot.cn — a separate account/keyspace) had no supported way to point a +// new connection at api.moonshot.cn. Fix: expose the existing generic +// providerSpecificData.baseUrl override affordance for "kimi" and "moonshot" +// via CONFIGURABLE_BASE_URL_PROVIDERS, defaulting to the unchanged +// international host so existing users see no behavior change. +import test from "node:test"; +import assert from "node:assert/strict"; + +import { getRegistryEntry } from "../../open-sse/config/providerRegistry.ts"; +import { + isBaseUrlConfigurableProvider, + getProviderBaseUrlDefault, + getProviderBaseUrlPlaceholder, +} from "../../src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts"; + +test("kimi/moonshot registry entries still default to the international api.moonshot.ai host", () => { + const kimi = getRegistryEntry("kimi"); + const moonshot = getRegistryEntry("moonshot"); + assert.ok(kimi, "expected a registered 'kimi' provider entry"); + assert.ok(moonshot, "expected a registered 'moonshot' provider entry"); + assert.equal(kimi!.baseUrl, "https://api.moonshot.ai/v1/chat/completions"); + assert.equal(moonshot!.baseUrl, "https://api.moonshot.ai/v1/chat/completions"); +}); + +test("kimi and moonshot are base-URL configurable at Add-connection time (regression guard for #7447)", () => { + assert.equal( + isBaseUrlConfigurableProvider("kimi"), + true, + "expected 'kimi' to be base-URL configurable so a CN-region key can be pointed at api.moonshot.cn" + ); + assert.equal( + isBaseUrlConfigurableProvider("moonshot"), + true, + "expected 'moonshot' to be base-URL configurable so a CN-region key can be pointed at api.moonshot.cn" + ); +}); + +test("default base URL for kimi/moonshot stays international (no behavior change for existing users)", () => { + assert.equal(getProviderBaseUrlDefault("kimi"), "https://api.moonshot.ai/v1"); + assert.equal(getProviderBaseUrlDefault("moonshot"), "https://api.moonshot.ai/v1"); +}); + +test("placeholder surfaces the CN-region alternative host for kimi/moonshot", () => { + assert.equal(getProviderBaseUrlPlaceholder("kimi"), "https://api.moonshot.cn/v1"); + assert.equal(getProviderBaseUrlPlaceholder("moonshot"), "https://api.moonshot.cn/v1"); +});