mirror of https://github.com/openclaw/openclaw.git
157 lines
4.3 KiB
TypeScript
157 lines
4.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { normalizeRegisteredProvider } from "./provider-validation.js";
|
|
import type { PluginDiagnostic, ProviderPlugin } from "./types.js";
|
|
|
|
function collectDiagnostics() {
|
|
const diagnostics: PluginDiagnostic[] = [];
|
|
return {
|
|
diagnostics,
|
|
pushDiagnostic: (diag: PluginDiagnostic) => {
|
|
diagnostics.push(diag);
|
|
},
|
|
};
|
|
}
|
|
|
|
function makeProvider(overrides: Partial<ProviderPlugin>): ProviderPlugin {
|
|
return {
|
|
id: "demo",
|
|
label: "Demo",
|
|
auth: [],
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe("normalizeRegisteredProvider", () => {
|
|
it("drops invalid and duplicate auth methods, and clears bad wizard method bindings", () => {
|
|
const { diagnostics, pushDiagnostic } = collectDiagnostics();
|
|
|
|
const provider = normalizeRegisteredProvider({
|
|
pluginId: "demo-plugin",
|
|
source: "/tmp/demo/index.ts",
|
|
provider: makeProvider({
|
|
id: " demo ",
|
|
label: " Demo Provider ",
|
|
aliases: [" alias-one ", "alias-one", ""],
|
|
envVars: [" DEMO_API_KEY ", "DEMO_API_KEY"],
|
|
auth: [
|
|
{
|
|
id: " primary ",
|
|
label: " Primary ",
|
|
kind: "custom",
|
|
run: async () => ({ profiles: [] }),
|
|
},
|
|
{
|
|
id: "primary",
|
|
label: "Duplicate",
|
|
kind: "custom",
|
|
run: async () => ({ profiles: [] }),
|
|
},
|
|
{ id: " ", label: "Missing", kind: "custom", run: async () => ({ profiles: [] }) },
|
|
],
|
|
wizard: {
|
|
setup: {
|
|
choiceId: " demo-choice ",
|
|
methodId: " missing ",
|
|
},
|
|
modelPicker: {
|
|
label: " Demo models ",
|
|
methodId: " missing ",
|
|
},
|
|
},
|
|
}),
|
|
pushDiagnostic,
|
|
});
|
|
|
|
expect(provider).toMatchObject({
|
|
id: "demo",
|
|
label: "Demo Provider",
|
|
aliases: ["alias-one"],
|
|
envVars: ["DEMO_API_KEY"],
|
|
auth: [{ id: "primary", label: "Primary" }],
|
|
wizard: {
|
|
setup: {
|
|
choiceId: "demo-choice",
|
|
},
|
|
modelPicker: {
|
|
label: "Demo models",
|
|
},
|
|
},
|
|
});
|
|
expect(diagnostics.map((diag) => ({ level: diag.level, message: diag.message }))).toEqual([
|
|
{
|
|
level: "error",
|
|
message: 'provider "demo" auth method duplicated id "primary"',
|
|
},
|
|
{
|
|
level: "error",
|
|
message: 'provider "demo" auth method missing id',
|
|
},
|
|
{
|
|
level: "warn",
|
|
message:
|
|
'provider "demo" setup method "missing" not found; falling back to available methods',
|
|
},
|
|
{
|
|
level: "warn",
|
|
message:
|
|
'provider "demo" model-picker method "missing" not found; falling back to available methods',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it("drops wizard metadata when a provider has no auth methods", () => {
|
|
const { diagnostics, pushDiagnostic } = collectDiagnostics();
|
|
|
|
const provider = normalizeRegisteredProvider({
|
|
pluginId: "demo-plugin",
|
|
source: "/tmp/demo/index.ts",
|
|
provider: makeProvider({
|
|
wizard: {
|
|
setup: {
|
|
choiceId: "demo",
|
|
},
|
|
modelPicker: {
|
|
label: "Demo",
|
|
},
|
|
},
|
|
}),
|
|
pushDiagnostic,
|
|
});
|
|
|
|
expect(provider?.wizard).toBeUndefined();
|
|
expect(diagnostics.map((diag) => diag.message)).toEqual([
|
|
'provider "demo" setup metadata ignored because it has no auth methods',
|
|
'provider "demo" model-picker metadata ignored because it has no auth methods',
|
|
]);
|
|
});
|
|
|
|
it("prefers catalog when a provider registers both catalog and discovery", () => {
|
|
const { diagnostics, pushDiagnostic } = collectDiagnostics();
|
|
|
|
const provider = normalizeRegisteredProvider({
|
|
pluginId: "demo-plugin",
|
|
source: "/tmp/demo/index.ts",
|
|
provider: makeProvider({
|
|
catalog: {
|
|
run: async () => null,
|
|
},
|
|
discovery: {
|
|
run: async () => ({
|
|
provider: {
|
|
baseUrl: "http://127.0.0.1:8000/v1",
|
|
models: [],
|
|
},
|
|
}),
|
|
},
|
|
}),
|
|
pushDiagnostic,
|
|
});
|
|
|
|
expect(provider?.catalog).toBeDefined();
|
|
expect(provider?.discovery).toBeUndefined();
|
|
expect(diagnostics.map((diag) => diag.message)).toEqual([
|
|
'provider "demo" registered both catalog and discovery; using catalog',
|
|
]);
|
|
});
|
|
});
|