fix: keep Moonshot CN base URL in onboarding (#7180) (thanks @waynelwz)
parent
1c6b25ddbb
commit
4a5d368926
|
|
@ -6,7 +6,7 @@ Docs: https://docs.openclaw.ai
|
|||
|
||||
### Changes
|
||||
|
||||
- TBD.
|
||||
- Onboarding: add Moonshot (.cn) auth choice and keep the China base URL when preserving defaults. (#7180) Thanks @waynelwz.
|
||||
|
||||
### Fixes
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import {
|
|||
applyMoonshotConfig,
|
||||
applyMoonshotConfigCn,
|
||||
applyMoonshotProviderConfig,
|
||||
applyMoonshotProviderConfigCn,
|
||||
applyOpencodeZenConfig,
|
||||
applyOpencodeZenProviderConfig,
|
||||
applyOpenrouterConfig,
|
||||
|
|
@ -314,7 +315,7 @@ export async function applyAuthChoiceApiProviders(
|
|||
setDefaultModel: params.setDefaultModel,
|
||||
defaultModel: MOONSHOT_DEFAULT_MODEL_REF,
|
||||
applyDefaultConfig: applyMoonshotConfigCn,
|
||||
applyProviderConfig: (cfg) => applyMoonshotProviderConfigCnShim(cfg),
|
||||
applyProviderConfig: applyMoonshotProviderConfigCn,
|
||||
noteAgentModel,
|
||||
prompter: params.prompter,
|
||||
});
|
||||
|
|
@ -324,14 +325,6 @@ export async function applyAuthChoiceApiProviders(
|
|||
return { config: nextConfig, agentModelOverride };
|
||||
}
|
||||
|
||||
function applyMoonshotProviderConfigCnShim(
|
||||
cfg: Parameters<typeof applyMoonshotProviderConfig>[0],
|
||||
) {
|
||||
// For now, provider-level CN behavior is fully handled inside applyMoonshotConfigCn.
|
||||
// Keep a thin shim to satisfy the applyDefaultModelChoice signature.
|
||||
return applyMoonshotProviderConfig(cfg);
|
||||
}
|
||||
|
||||
if (authChoice === "kimi-code-api-key") {
|
||||
let hasCredential = false;
|
||||
const tokenProvider = params.opts?.tokenProvider?.trim().toLowerCase();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,154 @@
|
|||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import type { WizardPrompter } from "../wizard/prompts.js";
|
||||
import { applyAuthChoice } from "./auth-choice.js";
|
||||
|
||||
const noopAsync = async () => {};
|
||||
const noop = () => {};
|
||||
const authProfilePathFor = (agentDir: string) => path.join(agentDir, "auth-profiles.json");
|
||||
const requireAgentDir = () => {
|
||||
const agentDir = process.env.OPENCLAW_AGENT_DIR;
|
||||
if (!agentDir) {
|
||||
throw new Error("OPENCLAW_AGENT_DIR not set");
|
||||
}
|
||||
return agentDir;
|
||||
};
|
||||
|
||||
describe("applyAuthChoice (moonshot)", () => {
|
||||
const previousStateDir = process.env.OPENCLAW_STATE_DIR;
|
||||
const previousAgentDir = process.env.OPENCLAW_AGENT_DIR;
|
||||
const previousPiAgentDir = process.env.PI_CODING_AGENT_DIR;
|
||||
const previousMoonshotKey = process.env.MOONSHOT_API_KEY;
|
||||
let tempStateDir: string | null = null;
|
||||
|
||||
afterEach(async () => {
|
||||
if (tempStateDir) {
|
||||
await fs.rm(tempStateDir, { recursive: true, force: true });
|
||||
tempStateDir = null;
|
||||
}
|
||||
if (previousStateDir === undefined) {
|
||||
delete process.env.OPENCLAW_STATE_DIR;
|
||||
} else {
|
||||
process.env.OPENCLAW_STATE_DIR = previousStateDir;
|
||||
}
|
||||
if (previousAgentDir === undefined) {
|
||||
delete process.env.OPENCLAW_AGENT_DIR;
|
||||
} else {
|
||||
process.env.OPENCLAW_AGENT_DIR = previousAgentDir;
|
||||
}
|
||||
if (previousPiAgentDir === undefined) {
|
||||
delete process.env.PI_CODING_AGENT_DIR;
|
||||
} else {
|
||||
process.env.PI_CODING_AGENT_DIR = previousPiAgentDir;
|
||||
}
|
||||
if (previousMoonshotKey === undefined) {
|
||||
delete process.env.MOONSHOT_API_KEY;
|
||||
} else {
|
||||
process.env.MOONSHOT_API_KEY = previousMoonshotKey;
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps the .cn baseUrl when setDefaultModel is false", async () => {
|
||||
tempStateDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-auth-"));
|
||||
process.env.OPENCLAW_STATE_DIR = tempStateDir;
|
||||
process.env.OPENCLAW_AGENT_DIR = path.join(tempStateDir, "agent");
|
||||
process.env.PI_CODING_AGENT_DIR = process.env.OPENCLAW_AGENT_DIR;
|
||||
delete process.env.MOONSHOT_API_KEY;
|
||||
|
||||
const text = vi.fn().mockResolvedValue("sk-moonshot-cn-test");
|
||||
const prompter: WizardPrompter = {
|
||||
intro: vi.fn(noopAsync),
|
||||
outro: vi.fn(noopAsync),
|
||||
note: vi.fn(noopAsync),
|
||||
select: vi.fn(async () => "" as never),
|
||||
multiselect: vi.fn(async () => []),
|
||||
text,
|
||||
confirm: vi.fn(async () => false),
|
||||
progress: vi.fn(() => ({ update: noop, stop: noop })),
|
||||
};
|
||||
const runtime: RuntimeEnv = {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
exit: vi.fn((code: number) => {
|
||||
throw new Error(`exit:${code}`);
|
||||
}),
|
||||
};
|
||||
|
||||
const result = await applyAuthChoice({
|
||||
authChoice: "moonshot-api-key-cn",
|
||||
config: {
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "anthropic/claude-opus-4-5" },
|
||||
},
|
||||
},
|
||||
},
|
||||
prompter,
|
||||
runtime,
|
||||
setDefaultModel: false,
|
||||
});
|
||||
|
||||
expect(text).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ message: "Enter Moonshot API key (.cn)" }),
|
||||
);
|
||||
expect(result.config.agents?.defaults?.model?.primary).toBe("anthropic/claude-opus-4-5");
|
||||
expect(result.config.models?.providers?.moonshot?.baseUrl).toBe("https://api.moonshot.cn/v1");
|
||||
expect(result.agentModelOverride).toBe("moonshot/kimi-k2.5");
|
||||
|
||||
const authProfilePath = authProfilePathFor(requireAgentDir());
|
||||
const raw = await fs.readFile(authProfilePath, "utf8");
|
||||
const parsed = JSON.parse(raw) as {
|
||||
profiles?: Record<string, { key?: string }>;
|
||||
};
|
||||
expect(parsed.profiles?.["moonshot:default"]?.key).toBe("sk-moonshot-cn-test");
|
||||
});
|
||||
|
||||
it("sets the default model when setDefaultModel is true", async () => {
|
||||
tempStateDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-auth-"));
|
||||
process.env.OPENCLAW_STATE_DIR = tempStateDir;
|
||||
process.env.OPENCLAW_AGENT_DIR = path.join(tempStateDir, "agent");
|
||||
process.env.PI_CODING_AGENT_DIR = process.env.OPENCLAW_AGENT_DIR;
|
||||
delete process.env.MOONSHOT_API_KEY;
|
||||
|
||||
const text = vi.fn().mockResolvedValue("sk-moonshot-cn-test");
|
||||
const prompter: WizardPrompter = {
|
||||
intro: vi.fn(noopAsync),
|
||||
outro: vi.fn(noopAsync),
|
||||
note: vi.fn(noopAsync),
|
||||
select: vi.fn(async () => "" as never),
|
||||
multiselect: vi.fn(async () => []),
|
||||
text,
|
||||
confirm: vi.fn(async () => false),
|
||||
progress: vi.fn(() => ({ update: noop, stop: noop })),
|
||||
};
|
||||
const runtime: RuntimeEnv = {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
exit: vi.fn((code: number) => {
|
||||
throw new Error(`exit:${code}`);
|
||||
}),
|
||||
};
|
||||
|
||||
const result = await applyAuthChoice({
|
||||
authChoice: "moonshot-api-key-cn",
|
||||
config: {},
|
||||
prompter,
|
||||
runtime,
|
||||
setDefaultModel: true,
|
||||
});
|
||||
|
||||
expect(result.config.agents?.defaults?.model?.primary).toBe("moonshot/kimi-k2.5");
|
||||
expect(result.config.models?.providers?.moonshot?.baseUrl).toBe("https://api.moonshot.cn/v1");
|
||||
expect(result.agentModelOverride).toBeUndefined();
|
||||
|
||||
const authProfilePath = authProfilePathFor(requireAgentDir());
|
||||
const raw = await fs.readFile(authProfilePath, "utf8");
|
||||
const parsed = JSON.parse(raw) as {
|
||||
profiles?: Record<string, { key?: string }>;
|
||||
};
|
||||
expect(parsed.profiles?.["moonshot:default"]?.key).toBe("sk-moonshot-cn-test");
|
||||
});
|
||||
});
|
||||
|
|
@ -141,6 +141,10 @@ export function applyMoonshotProviderConfig(cfg: OpenClawConfig): OpenClawConfig
|
|||
return applyMoonshotProviderConfigWithBaseUrl(cfg, MOONSHOT_BASE_URL);
|
||||
}
|
||||
|
||||
export function applyMoonshotProviderConfigCn(cfg: OpenClawConfig): OpenClawConfig {
|
||||
return applyMoonshotProviderConfigWithBaseUrl(cfg, MOONSHOT_CN_BASE_URL);
|
||||
}
|
||||
|
||||
function applyMoonshotProviderConfigWithBaseUrl(
|
||||
cfg: OpenClawConfig,
|
||||
baseUrl: string,
|
||||
|
|
@ -210,7 +214,7 @@ export function applyMoonshotConfig(cfg: OpenClawConfig): OpenClawConfig {
|
|||
}
|
||||
|
||||
export function applyMoonshotConfigCn(cfg: OpenClawConfig): OpenClawConfig {
|
||||
const next = applyMoonshotProviderConfigWithBaseUrl(cfg, MOONSHOT_CN_BASE_URL);
|
||||
const next = applyMoonshotProviderConfigCn(cfg);
|
||||
const existingModel = next.agents?.defaults?.model;
|
||||
return {
|
||||
...next,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ export {
|
|||
applyMoonshotConfig,
|
||||
applyMoonshotConfigCn,
|
||||
applyMoonshotProviderConfig,
|
||||
applyMoonshotProviderConfigCn,
|
||||
applyOpenrouterConfig,
|
||||
applyOpenrouterProviderConfig,
|
||||
applySyntheticConfig,
|
||||
|
|
|
|||
Loading…
Reference in New Issue