Files
openclaw/src/agents/models-config.providers.stepfun.test.ts
2026-04-05 17:33:01 +01:00

245 lines
7.6 KiB
TypeScript

import { mkdtempSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import type { ModelDefinitionConfig, ModelProviderConfig } from "../config/types.models.js";
import { upsertAuthProfile } from "./auth-profiles.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 createStepFunModel(id: string): ModelDefinitionConfig {
return {
id,
name: id,
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 8192,
maxTokens: 4096,
};
}
function buildStepFunCatalog(params: {
surface: StepFunSurface;
apiKey?: string;
explicitBaseUrl?: string;
profileId?: string;
env?: NodeJS.ProcessEnv;
}): ModelProviderConfig | null {
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(createStepFunModel)
: EXPECTED_STANDARD_MODELS.map(createStepFunModel),
};
}
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", () => {
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,
});
if (!standardProvider || !planProvider) {
throw new Error("expected StepFun providers");
}
expect(standardProvider).toMatchObject({
baseUrl: "https://api.stepfun.ai/v1",
api: "openai-completions",
apiKey: "STEPFUN_API_KEY",
});
expect(planProvider).toMatchObject({
baseUrl: "https://api.stepfun.ai/step_plan/v1",
api: "openai-completions",
apiKey: "STEPFUN_API_KEY",
});
expect(standardProvider.models?.map((model) => model.id)).toEqual(EXPECTED_STANDARD_MODELS);
expect(planProvider.models?.map((model) => model.id)).toEqual(EXPECTED_PLAN_MODELS);
});
it("falls back to global endpoints for untagged StepFun auth profiles", () => {
const agentDir = mkdtempSync(join(tmpdir(), "openclaw-test-"));
upsertAuthProfile({
profileId: "stepfun:default",
credential: {
type: "api_key",
provider: "stepfun",
key: "sk-stepfun-default", // pragma: allowlist secret
},
agentDir,
});
upsertAuthProfile({
profileId: "stepfun-plan:default",
credential: {
type: "api_key",
provider: "stepfun-plan",
key: "sk-stepfun-default", // pragma: allowlist secret
},
agentDir,
});
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");
expect(providers?.stepfun?.models?.map((model) => model.id)).toEqual(EXPECTED_STANDARD_MODELS);
expect(providers?.["stepfun-plan"]?.models?.map((model) => model.id)).toEqual(
EXPECTED_PLAN_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(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", () => {
const agentDir = mkdtempSync(join(tmpdir(), "openclaw-test-"));
upsertAuthProfile({
profileId: "stepfun:cn",
credential: {
type: "api_key",
provider: "stepfun",
key: "sk-stepfun-cn", // pragma: allowlist secret
},
agentDir,
});
upsertAuthProfile({
profileId: "stepfun-plan:cn",
credential: {
type: "api_key",
provider: "stepfun-plan",
key: "sk-stepfun-cn", // pragma: allowlist secret
},
agentDir,
});
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");
expect(providers?.stepfun?.models?.map((model) => model.id)).toEqual(EXPECTED_STANDARD_MODELS);
expect(providers?.["stepfun-plan"]?.models?.map((model) => model.id)).toEqual(
EXPECTED_PLAN_MODELS,
);
});
});