Files
openclaw/src/plugins/provider-discovery.test.ts
Peter Steinberger a724bbce1a feat: add bundled Chutes extension (#49136)
* refactor: generalize bundled provider discovery seams

* feat: land chutes extension via plugin-owned auth (#41416) (thanks @Veightor)
2026-03-17 09:35:21 -07:00

139 lines
4.1 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type { ModelProviderConfig } from "../config/types.js";
import {
groupPluginDiscoveryProvidersByOrder,
normalizePluginDiscoveryResult,
runProviderCatalog,
} from "./provider-discovery.js";
import type { ProviderDiscoveryOrder, ProviderPlugin } from "./types.js";
function makeProvider(params: {
id: string;
label?: string;
order?: ProviderDiscoveryOrder;
mode?: "catalog" | "discovery";
}): ProviderPlugin {
const hook = {
...(params.order ? { order: params.order } : {}),
run: async () => null,
};
return {
id: params.id,
label: params.label ?? params.id,
auth: [],
...(params.mode === "discovery" ? { discovery: hook } : { catalog: hook }),
};
}
function makeModelProviderConfig(overrides?: Partial<ModelProviderConfig>): ModelProviderConfig {
return {
baseUrl: "http://127.0.0.1:8000/v1",
models: [],
...overrides,
};
}
describe("groupPluginDiscoveryProvidersByOrder", () => {
it("groups providers by declared order and sorts labels within each group", () => {
const grouped = groupPluginDiscoveryProvidersByOrder([
makeProvider({ id: "late-b", label: "Zulu" }),
makeProvider({ id: "late-a", label: "Alpha" }),
makeProvider({ id: "paired", label: "Paired", order: "paired" }),
makeProvider({ id: "profile", label: "Profile", order: "profile" }),
makeProvider({ id: "simple", label: "Simple", order: "simple" }),
]);
expect(grouped.simple.map((provider) => provider.id)).toEqual(["simple"]);
expect(grouped.profile.map((provider) => provider.id)).toEqual(["profile"]);
expect(grouped.paired.map((provider) => provider.id)).toEqual(["paired"]);
expect(grouped.late.map((provider) => provider.id)).toEqual(["late-a", "late-b"]);
});
it("uses the legacy discovery hook when catalog is absent", () => {
const grouped = groupPluginDiscoveryProvidersByOrder([
makeProvider({ id: "legacy", label: "Legacy", order: "profile", mode: "discovery" }),
]);
expect(grouped.profile.map((provider) => provider.id)).toEqual(["legacy"]);
});
});
describe("normalizePluginDiscoveryResult", () => {
it("maps a single provider result to the plugin id", () => {
const provider = makeProvider({ id: "Ollama" });
const normalized = normalizePluginDiscoveryResult({
provider,
result: {
provider: makeModelProviderConfig({
baseUrl: "http://127.0.0.1:11434",
api: "ollama",
}),
},
});
expect(normalized).toEqual({
ollama: {
baseUrl: "http://127.0.0.1:11434",
api: "ollama",
models: [],
},
});
});
it("normalizes keys for multi-provider discovery results", () => {
const normalized = normalizePluginDiscoveryResult({
provider: makeProvider({ id: "ignored" }),
result: {
providers: {
" VLLM ": makeModelProviderConfig(),
"": makeModelProviderConfig({ baseUrl: "http://ignored" }),
},
},
});
expect(normalized).toEqual({
vllm: {
baseUrl: "http://127.0.0.1:8000/v1",
models: [],
},
});
});
});
describe("runProviderCatalog", () => {
it("prefers catalog over discovery when both exist", async () => {
const catalogRun = async () => ({
provider: makeModelProviderConfig({ baseUrl: "http://catalog.example/v1" }),
});
const discoveryRun = async () => ({
provider: makeModelProviderConfig({ baseUrl: "http://discovery.example/v1" }),
});
const result = await runProviderCatalog({
provider: {
id: "demo",
label: "Demo",
auth: [],
catalog: { run: catalogRun },
discovery: { run: discoveryRun },
},
config: {},
env: {},
resolveProviderApiKey: () => ({ apiKey: undefined }),
resolveProviderAuth: () => ({
apiKey: undefined,
discoveryApiKey: undefined,
mode: "none",
source: "none",
}),
});
expect(result).toEqual({
provider: {
baseUrl: "http://catalog.example/v1",
models: [],
},
});
});
});