mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
test(commands): collapse provider and endpoint matrices
This commit is contained in:
@@ -16,41 +16,32 @@ function getOptions(includeSkip = false) {
|
||||
}
|
||||
|
||||
describe("buildAuthChoiceOptions", () => {
|
||||
it("includes GitHub Copilot", () => {
|
||||
it("includes core and provider-specific auth choices", () => {
|
||||
const options = getOptions();
|
||||
|
||||
expect(options.find((opt) => opt.value === "github-copilot")).toBeDefined();
|
||||
});
|
||||
|
||||
it("includes setup-token option for Anthropic", () => {
|
||||
const options = getOptions();
|
||||
|
||||
expect(options.some((opt) => opt.value === "token")).toBe(true);
|
||||
});
|
||||
|
||||
it.each([
|
||||
["Z.AI (GLM) auth choice", ["zai-api-key"]],
|
||||
["Xiaomi auth choice", ["xiaomi-api-key"]],
|
||||
["MiniMax auth choice", ["minimax-api", "minimax-api-key-cn", "minimax-api-lightning"]],
|
||||
[
|
||||
"Moonshot auth choice",
|
||||
["moonshot-api-key", "moonshot-api-key-cn", "kimi-code-api-key", "together-api-key"],
|
||||
],
|
||||
["Vercel AI Gateway auth choice", ["ai-gateway-api-key"]],
|
||||
["Cloudflare AI Gateway auth choice", ["cloudflare-ai-gateway-api-key"]],
|
||||
["Together AI auth choice", ["together-api-key"]],
|
||||
["Synthetic auth choice", ["synthetic-api-key"]],
|
||||
["Chutes OAuth auth choice", ["chutes"]],
|
||||
["Qwen auth choice", ["qwen-portal"]],
|
||||
["xAI auth choice", ["xai-api-key"]],
|
||||
["Mistral auth choice", ["mistral-api-key"]],
|
||||
["Volcano Engine auth choice", ["volcengine-api-key"]],
|
||||
["BytePlus auth choice", ["byteplus-api-key"]],
|
||||
["vLLM auth choice", ["vllm"]],
|
||||
])("includes %s", (_label, expectedValues) => {
|
||||
const options = getOptions();
|
||||
|
||||
for (const value of expectedValues) {
|
||||
for (const value of [
|
||||
"github-copilot",
|
||||
"token",
|
||||
"zai-api-key",
|
||||
"xiaomi-api-key",
|
||||
"minimax-api",
|
||||
"minimax-api-key-cn",
|
||||
"minimax-api-lightning",
|
||||
"moonshot-api-key",
|
||||
"moonshot-api-key-cn",
|
||||
"kimi-code-api-key",
|
||||
"together-api-key",
|
||||
"ai-gateway-api-key",
|
||||
"cloudflare-ai-gateway-api-key",
|
||||
"synthetic-api-key",
|
||||
"chutes",
|
||||
"qwen-portal",
|
||||
"xai-api-key",
|
||||
"mistral-api-key",
|
||||
"volcengine-api-key",
|
||||
"byteplus-api-key",
|
||||
"vllm",
|
||||
]) {
|
||||
expect(options.some((opt) => opt.value === value)).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -12,35 +12,31 @@ function makeProvider(params: { id: string; label?: string; aliases?: string[] }
|
||||
}
|
||||
|
||||
describe("resolveRequestedLoginProviderOrThrow", () => {
|
||||
it("returns null when no provider was requested", () => {
|
||||
const providers = [makeProvider({ id: "google-gemini-cli" })];
|
||||
const result = resolveRequestedLoginProviderOrThrow(providers, undefined);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it("resolves requested provider by id", () => {
|
||||
it("returns null and resolves provider by id/alias", () => {
|
||||
const providers = [
|
||||
makeProvider({ id: "google-gemini-cli" }),
|
||||
makeProvider({ id: "google-gemini-cli", aliases: ["gemini-cli"] }),
|
||||
makeProvider({ id: "qwen-portal" }),
|
||||
];
|
||||
const result = resolveRequestedLoginProviderOrThrow(providers, "google-gemini-cli");
|
||||
expect(result?.id).toBe("google-gemini-cli");
|
||||
});
|
||||
const scenarios = [
|
||||
{ requested: undefined, expectedId: null },
|
||||
{ requested: "google-gemini-cli", expectedId: "google-gemini-cli" },
|
||||
{ requested: "gemini-cli", expectedId: "google-gemini-cli" },
|
||||
] as const;
|
||||
|
||||
it("resolves requested provider by alias", () => {
|
||||
const providers = [makeProvider({ id: "google-gemini-cli", aliases: ["gemini-cli"] })];
|
||||
const result = resolveRequestedLoginProviderOrThrow(providers, "gemini-cli");
|
||||
expect(result?.id).toBe("google-gemini-cli");
|
||||
for (const scenario of scenarios) {
|
||||
const result = resolveRequestedLoginProviderOrThrow(providers, scenario.requested);
|
||||
expect(result?.id ?? null).toBe(scenario.expectedId);
|
||||
}
|
||||
});
|
||||
|
||||
it("throws when requested provider is not loaded", () => {
|
||||
const providers = [
|
||||
const loadedProviders = [
|
||||
makeProvider({ id: "google-gemini-cli" }),
|
||||
makeProvider({ id: "qwen-portal" }),
|
||||
];
|
||||
|
||||
expect(() =>
|
||||
resolveRequestedLoginProviderOrThrow(providers, "google-antigravity"),
|
||||
resolveRequestedLoginProviderOrThrow(loadedProviders, "google-antigravity"),
|
||||
).toThrowError(
|
||||
'Unknown provider "google-antigravity". Loaded providers: google-gemini-cli, qwen-portal. Verify plugins via `openclaw plugins list --json`.',
|
||||
);
|
||||
|
||||
@@ -16,51 +16,58 @@ function makeFetch(map: Record<string, { status: number; body?: unknown }>) {
|
||||
}
|
||||
|
||||
describe("detectZaiEndpoint", () => {
|
||||
it("prefers global glm-5 when it works", async () => {
|
||||
const fetchFn = makeFetch({
|
||||
"https://api.z.ai/api/paas/v4/chat/completions": { status: 200 },
|
||||
});
|
||||
|
||||
const detected = await detectZaiEndpoint({ apiKey: "sk-test", fetchFn });
|
||||
expect(detected?.endpoint).toBe("global");
|
||||
expect(detected?.modelId).toBe("glm-5");
|
||||
});
|
||||
|
||||
it("falls back to cn glm-5 when global fails", async () => {
|
||||
const fetchFn = makeFetch({
|
||||
"https://api.z.ai/api/paas/v4/chat/completions": {
|
||||
status: 404,
|
||||
body: { error: { message: "not found" } },
|
||||
it("resolves preferred/fallback endpoints and null when probes fail", async () => {
|
||||
const scenarios: Array<{
|
||||
responses: Record<string, { status: number; body?: unknown }>;
|
||||
expected: { endpoint: string; modelId: string } | null;
|
||||
}> = [
|
||||
{
|
||||
responses: {
|
||||
"https://api.z.ai/api/paas/v4/chat/completions": { status: 200 },
|
||||
},
|
||||
expected: { endpoint: "global", modelId: "glm-5" },
|
||||
},
|
||||
"https://open.bigmodel.cn/api/paas/v4/chat/completions": { status: 200 },
|
||||
});
|
||||
{
|
||||
responses: {
|
||||
"https://api.z.ai/api/paas/v4/chat/completions": {
|
||||
status: 404,
|
||||
body: { error: { message: "not found" } },
|
||||
},
|
||||
"https://open.bigmodel.cn/api/paas/v4/chat/completions": { status: 200 },
|
||||
},
|
||||
expected: { endpoint: "cn", modelId: "glm-5" },
|
||||
},
|
||||
{
|
||||
responses: {
|
||||
"https://api.z.ai/api/paas/v4/chat/completions": { status: 404 },
|
||||
"https://open.bigmodel.cn/api/paas/v4/chat/completions": { status: 404 },
|
||||
"https://api.z.ai/api/coding/paas/v4/chat/completions": { status: 200 },
|
||||
},
|
||||
expected: { endpoint: "coding-global", modelId: "glm-4.7" },
|
||||
},
|
||||
{
|
||||
responses: {
|
||||
"https://api.z.ai/api/paas/v4/chat/completions": { status: 401 },
|
||||
"https://open.bigmodel.cn/api/paas/v4/chat/completions": { status: 401 },
|
||||
"https://api.z.ai/api/coding/paas/v4/chat/completions": { status: 401 },
|
||||
"https://open.bigmodel.cn/api/coding/paas/v4/chat/completions": { status: 401 },
|
||||
},
|
||||
expected: null,
|
||||
},
|
||||
];
|
||||
|
||||
const detected = await detectZaiEndpoint({ apiKey: "sk-test", fetchFn });
|
||||
expect(detected?.endpoint).toBe("cn");
|
||||
expect(detected?.modelId).toBe("glm-5");
|
||||
});
|
||||
for (const scenario of scenarios) {
|
||||
const detected = await detectZaiEndpoint({
|
||||
apiKey: "sk-test",
|
||||
fetchFn: makeFetch(scenario.responses),
|
||||
});
|
||||
|
||||
it("falls back to coding endpoint with glm-4.7", async () => {
|
||||
const fetchFn = makeFetch({
|
||||
"https://api.z.ai/api/paas/v4/chat/completions": { status: 404 },
|
||||
"https://open.bigmodel.cn/api/paas/v4/chat/completions": { status: 404 },
|
||||
"https://api.z.ai/api/coding/paas/v4/chat/completions": { status: 200 },
|
||||
});
|
||||
|
||||
const detected = await detectZaiEndpoint({ apiKey: "sk-test", fetchFn });
|
||||
expect(detected?.endpoint).toBe("coding-global");
|
||||
expect(detected?.modelId).toBe("glm-4.7");
|
||||
});
|
||||
|
||||
it("returns null when nothing works", async () => {
|
||||
const fetchFn = makeFetch({
|
||||
"https://api.z.ai/api/paas/v4/chat/completions": { status: 401 },
|
||||
"https://open.bigmodel.cn/api/paas/v4/chat/completions": { status: 401 },
|
||||
"https://api.z.ai/api/coding/paas/v4/chat/completions": { status: 401 },
|
||||
"https://open.bigmodel.cn/api/coding/paas/v4/chat/completions": { status: 401 },
|
||||
});
|
||||
|
||||
const detected = await detectZaiEndpoint({ apiKey: "sk-test", fetchFn });
|
||||
expect(detected).toBe(null);
|
||||
if (scenario.expected === null) {
|
||||
expect(detected).toBeNull();
|
||||
} else {
|
||||
expect(detected?.endpoint).toBe(scenario.expected.endpoint);
|
||||
expect(detected?.modelId).toBe(scenario.expected.modelId);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user