openclaw/src/plugins/provider-catalog.test.ts

141 lines
3.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type { OpenClawConfig } from "../config/config.js";
import type { ModelProviderConfig } from "../config/types.models.js";
import {
buildPairedProviderApiKeyCatalog,
buildSingleProviderApiKeyCatalog,
findCatalogTemplate,
} from "./provider-catalog.js";
import type { ProviderCatalogContext } from "./types.js";
function createProviderConfig(overrides: Partial<ModelProviderConfig> = {}): ModelProviderConfig {
return {
api: "openai-completions",
baseUrl: "https://default.example/v1",
models: [],
...overrides,
};
}
function createCatalogContext(params: {
config?: OpenClawConfig;
apiKeys?: Record<string, string | undefined>;
}): ProviderCatalogContext {
return {
config: params.config ?? {},
env: {},
resolveProviderApiKey: (providerId) => ({
apiKey: providerId ? params.apiKeys?.[providerId] : undefined,
}),
resolveProviderAuth: (providerId) => ({
apiKey: providerId ? params.apiKeys?.[providerId] : undefined,
mode: providerId && params.apiKeys?.[providerId] ? "api_key" : "none",
source: providerId && params.apiKeys?.[providerId] ? "env" : "none",
}),
};
}
describe("buildSingleProviderApiKeyCatalog", () => {
it("matches provider templates case-insensitively", () => {
const result = findCatalogTemplate({
entries: [
{ provider: "OpenAI", id: "gpt-5.2" },
{ provider: "other", id: "fallback" },
],
providerId: "openai",
templateIds: ["missing", "GPT-5.2"],
});
expect(result).toEqual({ provider: "OpenAI", id: "gpt-5.2" });
});
it("returns null when api key is missing", async () => {
const result = await buildSingleProviderApiKeyCatalog({
ctx: createCatalogContext({}),
providerId: "test-provider",
buildProvider: () => createProviderConfig(),
});
expect(result).toBeNull();
});
it("adds api key to the built provider", async () => {
const result = await buildSingleProviderApiKeyCatalog({
ctx: createCatalogContext({
apiKeys: { "test-provider": "secret-key" },
}),
providerId: "test-provider",
buildProvider: async () => createProviderConfig(),
});
expect(result).toEqual({
provider: {
api: "openai-completions",
baseUrl: "https://default.example/v1",
models: [],
apiKey: "secret-key",
},
});
});
it("prefers explicit base url when allowed", async () => {
const result = await buildSingleProviderApiKeyCatalog({
ctx: createCatalogContext({
apiKeys: { "test-provider": "secret-key" },
config: {
models: {
providers: {
"test-provider": {
baseUrl: " https://override.example/v1/ ",
models: [],
},
},
},
},
}),
providerId: "test-provider",
buildProvider: () => createProviderConfig(),
allowExplicitBaseUrl: true,
});
expect(result).toEqual({
provider: {
api: "openai-completions",
baseUrl: "https://override.example/v1/",
models: [],
apiKey: "secret-key",
},
});
});
it("adds api key to each paired provider", async () => {
const result = await buildPairedProviderApiKeyCatalog({
ctx: createCatalogContext({
apiKeys: { "test-provider": "secret-key" },
}),
providerId: "test-provider",
buildProviders: async () => ({
alpha: createProviderConfig(),
beta: createProviderConfig(),
}),
});
expect(result).toEqual({
providers: {
alpha: {
api: "openai-completions",
baseUrl: "https://default.example/v1",
models: [],
apiKey: "secret-key",
},
beta: {
api: "openai-completions",
baseUrl: "https://default.example/v1",
models: [],
apiKey: "secret-key",
},
},
});
});
});