mirror of https://github.com/openclaw/openclaw.git
test: share model selection config helpers
This commit is contained in:
parent
0e6f150c3b
commit
e474ac882e
|
|
@ -50,6 +50,60 @@ function resolveAnthropicOpusThinking(cfg: OpenClawConfig) {
|
|||
});
|
||||
}
|
||||
|
||||
function createAgentFallbackConfig(params: {
|
||||
primary?: string;
|
||||
fallbacks?: string[];
|
||||
agentFallbacks?: string[];
|
||||
}) {
|
||||
return {
|
||||
agents: {
|
||||
defaults: {
|
||||
models: {
|
||||
"openai/gpt-4o": {},
|
||||
},
|
||||
model: {
|
||||
primary: params.primary ?? "openai/gpt-4o",
|
||||
fallbacks: params.fallbacks ?? [],
|
||||
},
|
||||
},
|
||||
...(params.agentFallbacks
|
||||
? {
|
||||
list: [
|
||||
{
|
||||
id: "coder",
|
||||
model: {
|
||||
primary: params.primary ?? "openai/gpt-4o",
|
||||
fallbacks: params.agentFallbacks,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
}
|
||||
|
||||
function createProviderWithModelsConfig(provider: string, models: Array<Record<string, unknown>>) {
|
||||
return {
|
||||
models: {
|
||||
providers: {
|
||||
[provider]: {
|
||||
baseUrl: `https://${provider}.example.com`,
|
||||
models,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as Partial<OpenClawConfig>;
|
||||
}
|
||||
|
||||
function resolveConfiguredRefForTest(cfg: Partial<OpenClawConfig>) {
|
||||
return resolveConfiguredModelRef({
|
||||
cfg: cfg as OpenClawConfig,
|
||||
defaultProvider: "anthropic",
|
||||
defaultModel: "claude-opus-4-6",
|
||||
});
|
||||
}
|
||||
|
||||
describe("model-selection", () => {
|
||||
describe("normalizeProviderId", () => {
|
||||
it("should normalize provider names", () => {
|
||||
|
|
@ -326,19 +380,9 @@ describe("model-selection", () => {
|
|||
});
|
||||
|
||||
it("includes fallback models in allowed set", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
agents: {
|
||||
defaults: {
|
||||
models: {
|
||||
"openai/gpt-4o": {},
|
||||
},
|
||||
model: {
|
||||
primary: "openai/gpt-4o",
|
||||
fallbacks: ["anthropic/claude-sonnet-4-6", "google/gemini-3-pro"],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
const cfg = createAgentFallbackConfig({
|
||||
fallbacks: ["anthropic/claude-sonnet-4-6", "google/gemini-3-pro"],
|
||||
});
|
||||
|
||||
const result = buildAllowedModelSet({
|
||||
cfg,
|
||||
|
|
@ -354,19 +398,7 @@ describe("model-selection", () => {
|
|||
});
|
||||
|
||||
it("handles empty fallbacks gracefully", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
agents: {
|
||||
defaults: {
|
||||
models: {
|
||||
"openai/gpt-4o": {},
|
||||
},
|
||||
model: {
|
||||
primary: "openai/gpt-4o",
|
||||
fallbacks: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
const cfg = createAgentFallbackConfig({});
|
||||
|
||||
const result = buildAllowedModelSet({
|
||||
cfg,
|
||||
|
|
@ -380,28 +412,10 @@ describe("model-selection", () => {
|
|||
});
|
||||
|
||||
it("prefers per-agent fallback overrides when agentId is provided", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
agents: {
|
||||
defaults: {
|
||||
models: {
|
||||
"openai/gpt-4o": {},
|
||||
},
|
||||
model: {
|
||||
primary: "openai/gpt-4o",
|
||||
fallbacks: ["google/gemini-3-pro"],
|
||||
},
|
||||
},
|
||||
list: [
|
||||
{
|
||||
id: "coder",
|
||||
model: {
|
||||
primary: "openai/gpt-4o",
|
||||
fallbacks: ["anthropic/claude-sonnet-4-6"],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
const cfg = createAgentFallbackConfig({
|
||||
fallbacks: ["google/gemini-3-pro"],
|
||||
agentFallbacks: ["anthropic/claude-sonnet-4-6"],
|
||||
});
|
||||
|
||||
const result = buildAllowedModelSet({
|
||||
cfg,
|
||||
|
|
@ -632,79 +646,40 @@ describe("model-selection", () => {
|
|||
});
|
||||
|
||||
it("should prefer configured custom provider when default provider is not in models.providers", () => {
|
||||
const cfg: Partial<OpenClawConfig> = {
|
||||
models: {
|
||||
providers: {
|
||||
n1n: {
|
||||
baseUrl: "https://n1n.example.com",
|
||||
models: [
|
||||
{
|
||||
id: "gpt-5.4",
|
||||
name: "GPT 5.4",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 128000,
|
||||
maxTokens: 4096,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
const cfg = createProviderWithModelsConfig("n1n", [
|
||||
{
|
||||
id: "gpt-5.4",
|
||||
name: "GPT 5.4",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 128000,
|
||||
maxTokens: 4096,
|
||||
},
|
||||
};
|
||||
const result = resolveConfiguredModelRef({
|
||||
cfg: cfg as OpenClawConfig,
|
||||
defaultProvider: "anthropic",
|
||||
defaultModel: "claude-opus-4-6",
|
||||
});
|
||||
]);
|
||||
const result = resolveConfiguredRefForTest(cfg);
|
||||
expect(result).toEqual({ provider: "n1n", model: "gpt-5.4" });
|
||||
});
|
||||
|
||||
it("should keep default provider when it is in models.providers", () => {
|
||||
const cfg: Partial<OpenClawConfig> = {
|
||||
models: {
|
||||
providers: {
|
||||
anthropic: {
|
||||
baseUrl: "https://api.anthropic.com",
|
||||
models: [
|
||||
{
|
||||
id: "claude-opus-4-6",
|
||||
name: "Claude Opus 4.6",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 200000,
|
||||
maxTokens: 4096,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
const cfg = createProviderWithModelsConfig("anthropic", [
|
||||
{
|
||||
id: "claude-opus-4-6",
|
||||
name: "Claude Opus 4.6",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 200000,
|
||||
maxTokens: 4096,
|
||||
},
|
||||
};
|
||||
const result = resolveConfiguredModelRef({
|
||||
cfg: cfg as OpenClawConfig,
|
||||
defaultProvider: "anthropic",
|
||||
defaultModel: "claude-opus-4-6",
|
||||
});
|
||||
]);
|
||||
const result = resolveConfiguredRefForTest(cfg);
|
||||
expect(result).toEqual({ provider: "anthropic", model: "claude-opus-4-6" });
|
||||
});
|
||||
|
||||
it("should fall back to hardcoded default when no custom providers have models", () => {
|
||||
const cfg: Partial<OpenClawConfig> = {
|
||||
models: {
|
||||
providers: {
|
||||
"empty-provider": {
|
||||
baseUrl: "https://example.com",
|
||||
models: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = resolveConfiguredModelRef({
|
||||
cfg: cfg as OpenClawConfig,
|
||||
defaultProvider: "anthropic",
|
||||
defaultModel: "claude-opus-4-6",
|
||||
});
|
||||
const cfg = createProviderWithModelsConfig("empty-provider", []);
|
||||
const result = resolveConfiguredRefForTest(cfg);
|
||||
expect(result).toEqual({ provider: "anthropic", model: "claude-opus-4-6" });
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue