Moonshot: respect explicit baseUrl for CN endpoint so platform.moonshot.cn keys authenticate (#33637) (#33696)

* Moonshot: respect explicit baseUrl for CN endpoint so platform.moonshot.cn keys authenticate (#33637)

* Moonshot: address review - remove dead constant, import canonical URLs (#33696)
This commit is contained in:
chengzhichao-xydt
2026-03-13 00:10:38 +08:00
committed by GitHub
parent 3fa91cd69d
commit 0a8fa0e001
3 changed files with 77 additions and 2 deletions

View File

@@ -28,6 +28,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Moonshot CN API: respect explicit `baseUrl` (api.moonshot.cn) in implicit provider resolution so platform.moonshot.cn API keys authenticate correctly instead of returning HTTP 401. (#33637) Thanks @chengzhichao-xydt.
- Cron/proactive delivery: keep isolated direct cron sends out of the write-ahead resend queue so transient-send retries do not replay duplicate proactive messages after restart. (#40646) Thanks @openperf and @vincentkoc.
- TUI/chat log: reuse the active assistant message component for the same streaming run so `openclaw tui` no longer renders duplicate assistant replies. (#35364) Thanks @lisitan.
- macOS/Reminders: add the missing `NSRemindersUsageDescription` to the bundled app so `apple-reminders` can trigger the system permission prompt from OpenClaw.app. (#8559) Thanks @dinakars777.

View File

@@ -0,0 +1,60 @@
import { mkdtempSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import {
MOONSHOT_BASE_URL as MOONSHOT_AI_BASE_URL,
MOONSHOT_CN_BASE_URL,
} from "../commands/onboard-auth.models.js";
import { captureEnv } from "../test-utils/env.js";
import { resolveImplicitProviders } from "./models-config.providers.js";
describe("moonshot implicit provider (#33637)", () => {
it("uses explicit CN baseUrl when provided", async () => {
const agentDir = mkdtempSync(join(tmpdir(), "openclaw-test-"));
const envSnapshot = captureEnv(["MOONSHOT_API_KEY"]);
process.env.MOONSHOT_API_KEY = "sk-test-cn";
try {
const providers = await resolveImplicitProviders({
agentDir,
explicitProviders: {
moonshot: {
baseUrl: MOONSHOT_CN_BASE_URL,
api: "openai-completions",
models: [
{
id: "kimi-k2.5",
name: "Kimi K2.5",
reasoning: false,
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 256000,
maxTokens: 8192,
},
],
},
},
});
expect(providers?.moonshot).toBeDefined();
expect(providers?.moonshot?.baseUrl).toBe(MOONSHOT_CN_BASE_URL);
expect(providers?.moonshot?.apiKey).toBeDefined();
} finally {
envSnapshot.restore();
}
});
it("defaults to .ai baseUrl when no explicit provider", async () => {
const agentDir = mkdtempSync(join(tmpdir(), "openclaw-test-"));
const envSnapshot = captureEnv(["MOONSHOT_API_KEY"]);
process.env.MOONSHOT_API_KEY = "sk-test";
try {
const providers = await resolveImplicitProviders({ agentDir });
expect(providers?.moonshot).toBeDefined();
expect(providers?.moonshot?.baseUrl).toBe(MOONSHOT_AI_BASE_URL);
} finally {
envSnapshot.restore();
}
});
});

View File

@@ -610,6 +610,7 @@ function withApiKey(
build: (params: {
apiKey: string;
discoveryApiKey?: string;
explicitProvider?: ProviderConfig;
}) => ProviderConfig | Promise<ProviderConfig>,
): ImplicitProviderLoader {
return async (ctx) => {
@@ -618,7 +619,11 @@ function withApiKey(
return undefined;
}
return {
[providerKey]: await build({ apiKey, discoveryApiKey }),
[providerKey]: await build({
apiKey,
discoveryApiKey,
explicitProvider: ctx.explicitProviders?.[providerKey],
}),
};
};
}
@@ -651,7 +656,16 @@ function mergeImplicitProviderSet(
const SIMPLE_IMPLICIT_PROVIDER_LOADERS: ImplicitProviderLoader[] = [
withApiKey("minimax", async ({ apiKey }) => ({ ...buildMinimaxProvider(), apiKey })),
withApiKey("moonshot", async ({ apiKey }) => ({ ...buildMoonshotProvider(), apiKey })),
withApiKey("moonshot", async ({ apiKey, explicitProvider }) => {
const explicitBaseUrl = explicitProvider?.baseUrl;
return {
...buildMoonshotProvider(),
...(typeof explicitBaseUrl === "string" && explicitBaseUrl.trim()
? { baseUrl: explicitBaseUrl.trim() }
: {}),
apiKey,
};
}),
withApiKey("kimi-coding", async ({ apiKey }) => ({ ...buildKimiCodingProvider(), apiKey })),
withApiKey("synthetic", async ({ apiKey }) => ({ ...buildSyntheticProvider(), apiKey })),
withApiKey("venice", async ({ apiKey }) => ({ ...(await buildVeniceProvider()), apiKey })),