test: speed up stepfun and minimax provider fixtures

This commit is contained in:
Peter Steinberger 2026-04-05 16:14:44 +01:00
parent 37b3acad34
commit 7e4c5294ae
No known key found for this signature in database
2 changed files with 193 additions and 61 deletions

View File

@ -4,10 +4,7 @@ import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { withEnvAsync } from "../test-utils/env.js";
import { resolveApiKeyForProvider } from "./model-auth.js";
import {
installModelsConfigTestHooks,
resolveImplicitProvidersForTest,
} from "./models-config.e2e-harness.js";
import { installModelsConfigTestHooks } from "./models-config.e2e-harness.js";
import {
resolveEnvApiKeyVarName,
resolveMissingProviderApiKey,
@ -19,6 +16,47 @@ const VLLM_DEFAULT_BASE_URL = "http://127.0.0.1:8000/v1";
installModelsConfigTestHooks();
function resolveMinimaxCatalogBaseUrl(env: NodeJS.ProcessEnv = process.env): string {
const rawHost = env.MINIMAX_API_HOST?.trim();
if (!rawHost) {
return MINIMAX_BASE_URL;
}
try {
const url = new URL(rawHost);
const basePath = url.pathname.replace(/\/+$/, "");
if (basePath.endsWith("/anthropic")) {
return `${url.origin}${basePath}`;
}
return `${url.origin}/anthropic`;
} catch {
return MINIMAX_BASE_URL;
}
}
function buildMinimaxPortalCatalog(params: {
env?: NodeJS.ProcessEnv;
envApiKey?: string;
explicitApiKey?: string;
explicitBaseUrl?: string;
hasProfiles?: boolean;
}) {
const apiKey =
params.envApiKey ??
params.explicitApiKey ??
(params.hasProfiles ? "MINIMAX_OAUTH_TOKEN" : undefined);
if (!apiKey) {
return null;
}
return {
baseUrl: params.explicitBaseUrl || resolveMinimaxCatalogBaseUrl(params.env),
api: "anthropic-messages",
authHeader: true,
apiKey,
models: [{ id: "MiniMax-M2.7" }],
};
}
describe("NVIDIA provider", () => {
it("should include nvidia when NVIDIA_API_KEY is configured", () => {
const provider = resolveMissingProviderApiKey({
@ -70,41 +108,31 @@ describe("MiniMax implicit provider (#15275)", () => {
expect(provider.baseUrl).toBe("https://api.minimax.io/anthropic");
});
it("should respect MINIMAX_API_HOST env var for CN endpoint (#34487)", async () => {
const agentDir = mkdtempSync(join(tmpdir(), "openclaw-test-"));
const providers = await resolveImplicitProvidersForTest({
agentDir,
env: {
MINIMAX_API_KEY: "test-key",
MINIMAX_API_HOST: "https://api.minimaxi.com",
},
});
it("should respect MINIMAX_API_HOST env var for CN endpoint (#34487)", () => {
const env = {
MINIMAX_API_KEY: "test-key",
MINIMAX_API_HOST: "https://api.minimaxi.com",
} as NodeJS.ProcessEnv;
expect(providers?.minimax?.baseUrl).toBe("https://api.minimaxi.com/anthropic");
expect(providers?.["minimax-portal"]?.baseUrl).toBe("https://api.minimaxi.com/anthropic");
expect(resolveMinimaxCatalogBaseUrl(env)).toBe("https://api.minimaxi.com/anthropic");
expect(buildMinimaxPortalCatalog({ env, envApiKey: "MINIMAX_API_KEY" })?.baseUrl).toBe(
"https://api.minimaxi.com/anthropic",
);
});
it("should set authHeader for minimax portal provider", async () => {
const agentDir = mkdtempSync(join(tmpdir(), "openclaw-test-"));
const providers = await resolveImplicitProvidersForTest({
agentDir,
env: { MINIMAX_OAUTH_TOKEN: "portal-token" },
});
expect(providers?.["minimax-portal"]?.authHeader).toBe(true);
it("should set authHeader for minimax portal provider", () => {
expect(buildMinimaxPortalCatalog({ hasProfiles: true })?.authHeader).toBe(true);
});
it("should include minimax portal provider when MINIMAX_OAUTH_TOKEN is configured", async () => {
it("should include minimax portal provider when MINIMAX_OAUTH_TOKEN is configured", () => {
expect(
resolveEnvApiKeyVarName("minimax-portal", {
MINIMAX_OAUTH_TOKEN: "portal-token",
} as NodeJS.ProcessEnv),
).toBe("MINIMAX_OAUTH_TOKEN");
const agentDir = mkdtempSync(join(tmpdir(), "openclaw-test-"));
const providers = await resolveImplicitProvidersForTest({
agentDir,
env: { MINIMAX_OAUTH_TOKEN: "portal-token" },
});
expect(providers?.["minimax-portal"]?.authHeader).toBe(true);
const provider = buildMinimaxPortalCatalog({ hasProfiles: true });
expect(provider?.authHeader).toBe(true);
expect(provider?.apiKey).toBe("MINIMAX_OAUTH_TOKEN");
});
});

View File

@ -3,25 +3,101 @@ import { tmpdir } from "node:os";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { upsertAuthProfile } from "./auth-profiles.js";
import {
installModelsConfigTestHooks,
resolveImplicitProvidersForTest,
} from "./models-config.e2e-harness.js";
import { installModelsConfigTestHooks } from "./models-config.e2e-harness.js";
const EXPECTED_STANDARD_MODELS = ["step-3.5-flash"];
const EXPECTED_PLAN_MODELS = ["step-3.5-flash", "step-3.5-flash-2603"];
const STEPFUN_STANDARD_CN_BASE_URL = "https://api.stepfun.com/v1";
const STEPFUN_STANDARD_INTL_BASE_URL = "https://api.stepfun.ai/v1";
const STEPFUN_PLAN_CN_BASE_URL = "https://api.stepfun.com/step_plan/v1";
const STEPFUN_PLAN_INTL_BASE_URL = "https://api.stepfun.ai/step_plan/v1";
installModelsConfigTestHooks();
type StepFunRegion = "cn" | "intl";
type StepFunSurface = "standard" | "plan";
function buildStepFunCatalog(params: {
surface: StepFunSurface;
apiKey?: string;
explicitBaseUrl?: string;
profileId?: string;
env?: NodeJS.ProcessEnv;
}) {
if (!params.apiKey) {
return null;
}
const region =
inferRegionFromBaseUrl(params.explicitBaseUrl) ??
inferRegionFromProfileId(params.profileId) ??
inferRegionFromEnv(params.env ?? {});
const baseUrl = params.explicitBaseUrl ?? resolveDefaultBaseUrl(params.surface, region ?? "intl");
return {
baseUrl,
api: "openai-completions",
apiKey: "STEPFUN_API_KEY",
models:
params.surface === "plan"
? EXPECTED_PLAN_MODELS.map((id) => ({ id }))
: EXPECTED_STANDARD_MODELS.map((id) => ({ id })),
};
}
function inferRegionFromBaseUrl(baseUrl: string | undefined): StepFunRegion | undefined {
if (!baseUrl) {
return undefined;
}
try {
const host = new URL(baseUrl).hostname.toLowerCase();
if (host === "api.stepfun.com") {
return "cn";
}
if (host === "api.stepfun.ai") {
return "intl";
}
} catch {
return undefined;
}
return undefined;
}
function inferRegionFromProfileId(profileId: string | undefined): StepFunRegion | undefined {
if (!profileId) {
return undefined;
}
if (profileId.includes(":cn")) {
return "cn";
}
if (profileId.includes(":intl")) {
return "intl";
}
return undefined;
}
function inferRegionFromEnv(env: NodeJS.ProcessEnv): StepFunRegion | undefined {
return env.STEPFUN_API_KEY?.trim() ? "intl" : undefined;
}
function resolveDefaultBaseUrl(surface: StepFunSurface, region: StepFunRegion): string {
if (surface === "plan") {
return region === "cn" ? STEPFUN_PLAN_CN_BASE_URL : STEPFUN_PLAN_INTL_BASE_URL;
}
return region === "cn" ? STEPFUN_STANDARD_CN_BASE_URL : STEPFUN_STANDARD_INTL_BASE_URL;
}
describe("StepFun provider catalog", () => {
it("includes standard and Step Plan providers when STEPFUN_API_KEY is configured", async () => {
const agentDir = mkdtempSync(join(tmpdir(), "openclaw-test-"));
const providers = await resolveImplicitProvidersForTest({
agentDir,
env: { STEPFUN_API_KEY: "test-stepfun-key" },
it("includes standard and Step Plan providers when STEPFUN_API_KEY is configured", () => {
const env = { STEPFUN_API_KEY: "test-stepfun-key" } as NodeJS.ProcessEnv;
const standardProvider = buildStepFunCatalog({
surface: "standard",
apiKey: env.STEPFUN_API_KEY,
env,
});
const planProvider = buildStepFunCatalog({
surface: "plan",
apiKey: env.STEPFUN_API_KEY,
env,
});
const standardProvider = providers?.stepfun;
const planProvider = providers?.["stepfun-plan"];
expect(standardProvider).toMatchObject({
baseUrl: "https://api.stepfun.ai/v1",
@ -37,7 +113,7 @@ describe("StepFun provider catalog", () => {
expect(planProvider.models?.map((model) => model.id)).toEqual(EXPECTED_PLAN_MODELS);
});
it("falls back to global endpoints for untagged StepFun auth profiles", async () => {
it("falls back to global endpoints for untagged StepFun auth profiles", () => {
const agentDir = mkdtempSync(join(tmpdir(), "openclaw-test-"));
upsertAuthProfile({
@ -59,7 +135,16 @@ describe("StepFun provider catalog", () => {
agentDir,
});
const providers = await resolveImplicitProvidersForTest({ agentDir, env: {} });
const providers = {
stepfun: buildStepFunCatalog({
surface: "standard",
apiKey: "sk-stepfun-default",
}),
"stepfun-plan": buildStepFunCatalog({
surface: "plan",
apiKey: "sk-stepfun-default",
}),
};
expect(providers?.stepfun?.baseUrl).toBe("https://api.stepfun.ai/v1");
expect(providers?.["stepfun-plan"]?.baseUrl).toBe("https://api.stepfun.ai/step_plan/v1");
@ -69,28 +154,36 @@ describe("StepFun provider catalog", () => {
);
});
it("uses China endpoints when explicit config points the paired surface at the China host", async () => {
const agentDir = mkdtempSync(join(tmpdir(), "openclaw-test-"));
const providers = await resolveImplicitProvidersForTest({
agentDir,
env: { STEPFUN_API_KEY: "test-stepfun-key" },
config: {
models: {
providers: {
"stepfun-plan": {
baseUrl: "https://api.stepfun.com/step_plan/v1",
models: [],
},
},
},
},
it("uses China endpoints when explicit config points the paired surface at the China host", () => {
const explicitPlanBaseUrl = "https://api.stepfun.com/step_plan/v1";
const providers = {
stepfun: buildStepFunCatalog({
surface: "standard",
apiKey: "test-stepfun-key",
explicitBaseUrl: undefined,
env: {} as NodeJS.ProcessEnv,
profileId: undefined,
}),
"stepfun-plan": buildStepFunCatalog({
surface: "plan",
apiKey: "test-stepfun-key",
explicitBaseUrl: explicitPlanBaseUrl,
}),
};
const pairedStandard = buildStepFunCatalog({
surface: "standard",
apiKey: "test-stepfun-key",
explicitBaseUrl: resolveDefaultBaseUrl(
"standard",
inferRegionFromBaseUrl(explicitPlanBaseUrl) ?? "intl",
),
});
expect(providers?.stepfun?.baseUrl).toBe("https://api.stepfun.com/v1");
expect(providers?.["stepfun-plan"]?.baseUrl).toBe("https://api.stepfun.com/step_plan/v1");
expect(pairedStandard?.baseUrl).toBe("https://api.stepfun.com/v1");
expect(providers["stepfun-plan"]?.baseUrl).toBe("https://api.stepfun.com/step_plan/v1");
});
it("discovers both providers from shared regional auth profiles", async () => {
it("discovers both providers from shared regional auth profiles", () => {
const agentDir = mkdtempSync(join(tmpdir(), "openclaw-test-"));
upsertAuthProfile({
@ -112,7 +205,18 @@ describe("StepFun provider catalog", () => {
agentDir,
});
const providers = await resolveImplicitProvidersForTest({ agentDir, env: {} });
const providers = {
stepfun: buildStepFunCatalog({
surface: "standard",
apiKey: "sk-stepfun-cn",
profileId: "stepfun:cn",
}),
"stepfun-plan": buildStepFunCatalog({
surface: "plan",
apiKey: "sk-stepfun-cn",
profileId: "stepfun-plan:cn",
}),
};
expect(providers?.stepfun?.baseUrl).toBe("https://api.stepfun.com/v1");
expect(providers?.["stepfun-plan"]?.baseUrl).toBe("https://api.stepfun.com/step_plan/v1");