2026-03-15 23:54:37 -07:00
|
|
|
import { describe, expect, it } from "vitest";
|
2026-03-16 00:13:52 -07:00
|
|
|
import {
|
2026-03-16 20:42:00 -07:00
|
|
|
mediaUnderstandingProviderContractRegistry,
|
2026-03-16 00:13:52 -07:00
|
|
|
pluginRegistrationContractRegistry,
|
|
|
|
|
providerContractRegistry,
|
2026-03-16 20:01:08 -07:00
|
|
|
speechProviderContractRegistry,
|
2026-03-16 00:13:52 -07:00
|
|
|
webSearchProviderContractRegistry,
|
|
|
|
|
} from "./registry.js";
|
2026-03-15 23:54:37 -07:00
|
|
|
|
|
|
|
|
function findProviderIdsForPlugin(pluginId: string) {
|
|
|
|
|
return providerContractRegistry
|
|
|
|
|
.filter((entry) => entry.pluginId === pluginId)
|
|
|
|
|
.map((entry) => entry.provider.id)
|
|
|
|
|
.toSorted((left, right) => left.localeCompare(right));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function findWebSearchIdsForPlugin(pluginId: string) {
|
|
|
|
|
return webSearchProviderContractRegistry
|
|
|
|
|
.filter((entry) => entry.pluginId === pluginId)
|
|
|
|
|
.map((entry) => entry.provider.id)
|
|
|
|
|
.toSorted((left, right) => left.localeCompare(right));
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 20:01:08 -07:00
|
|
|
function findSpeechProviderIdsForPlugin(pluginId: string) {
|
|
|
|
|
return speechProviderContractRegistry
|
|
|
|
|
.filter((entry) => entry.pluginId === pluginId)
|
|
|
|
|
.map((entry) => entry.provider.id)
|
|
|
|
|
.toSorted((left, right) => left.localeCompare(right));
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 20:27:25 -07:00
|
|
|
function findSpeechProviderForPlugin(pluginId: string) {
|
|
|
|
|
const entry = speechProviderContractRegistry.find((candidate) => candidate.pluginId === pluginId);
|
|
|
|
|
if (!entry) {
|
|
|
|
|
throw new Error(`speech provider contract missing for ${pluginId}`);
|
|
|
|
|
}
|
|
|
|
|
return entry.provider;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 20:42:00 -07:00
|
|
|
function findMediaUnderstandingProviderIdsForPlugin(pluginId: string) {
|
|
|
|
|
return mediaUnderstandingProviderContractRegistry
|
|
|
|
|
.filter((entry) => entry.pluginId === pluginId)
|
|
|
|
|
.map((entry) => entry.provider.id)
|
|
|
|
|
.toSorted((left, right) => left.localeCompare(right));
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 21:59:39 -07:00
|
|
|
function findMediaUnderstandingProviderForPlugin(pluginId: string) {
|
|
|
|
|
const entry = mediaUnderstandingProviderContractRegistry.find(
|
|
|
|
|
(candidate) => candidate.pluginId === pluginId,
|
|
|
|
|
);
|
|
|
|
|
if (!entry) {
|
|
|
|
|
throw new Error(`media-understanding provider contract missing for ${pluginId}`);
|
|
|
|
|
}
|
|
|
|
|
return entry.provider;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 00:13:52 -07:00
|
|
|
function findRegistrationForPlugin(pluginId: string) {
|
|
|
|
|
const entry = pluginRegistrationContractRegistry.find(
|
|
|
|
|
(candidate) => candidate.pluginId === pluginId,
|
|
|
|
|
);
|
|
|
|
|
if (!entry) {
|
|
|
|
|
throw new Error(`plugin registration contract missing for ${pluginId}`);
|
|
|
|
|
}
|
|
|
|
|
return entry;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-15 23:54:37 -07:00
|
|
|
describe("plugin contract registry", () => {
|
|
|
|
|
it("does not duplicate bundled provider ids", () => {
|
|
|
|
|
const ids = providerContractRegistry.map((entry) => entry.provider.id);
|
|
|
|
|
expect(ids).toEqual([...new Set(ids)]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("does not duplicate bundled web search provider ids", () => {
|
|
|
|
|
const ids = webSearchProviderContractRegistry.map((entry) => entry.provider.id);
|
|
|
|
|
expect(ids).toEqual([...new Set(ids)]);
|
|
|
|
|
});
|
|
|
|
|
|
2026-03-16 20:01:08 -07:00
|
|
|
it("does not duplicate bundled speech provider ids", () => {
|
|
|
|
|
const ids = speechProviderContractRegistry.map((entry) => entry.provider.id);
|
|
|
|
|
expect(ids).toEqual([...new Set(ids)]);
|
|
|
|
|
});
|
|
|
|
|
|
2026-03-16 20:42:00 -07:00
|
|
|
it("does not duplicate bundled media provider ids", () => {
|
|
|
|
|
const ids = mediaUnderstandingProviderContractRegistry.map((entry) => entry.provider.id);
|
|
|
|
|
expect(ids).toEqual([...new Set(ids)]);
|
|
|
|
|
});
|
|
|
|
|
|
2026-03-15 23:54:37 -07:00
|
|
|
it("keeps multi-provider plugin ownership explicit", () => {
|
|
|
|
|
expect(findProviderIdsForPlugin("google")).toEqual(["google", "google-gemini-cli"]);
|
|
|
|
|
expect(findProviderIdsForPlugin("minimax")).toEqual(["minimax", "minimax-portal"]);
|
|
|
|
|
expect(findProviderIdsForPlugin("openai")).toEqual(["openai", "openai-codex"]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("keeps bundled web search ownership explicit", () => {
|
|
|
|
|
expect(findWebSearchIdsForPlugin("brave")).toEqual(["brave"]);
|
|
|
|
|
expect(findWebSearchIdsForPlugin("firecrawl")).toEqual(["firecrawl"]);
|
|
|
|
|
expect(findWebSearchIdsForPlugin("google")).toEqual(["gemini"]);
|
|
|
|
|
expect(findWebSearchIdsForPlugin("moonshot")).toEqual(["kimi"]);
|
|
|
|
|
expect(findWebSearchIdsForPlugin("perplexity")).toEqual(["perplexity"]);
|
|
|
|
|
expect(findWebSearchIdsForPlugin("xai")).toEqual(["grok"]);
|
|
|
|
|
});
|
2026-03-16 00:13:52 -07:00
|
|
|
|
2026-03-16 20:01:08 -07:00
|
|
|
it("keeps bundled speech ownership explicit", () => {
|
|
|
|
|
expect(findSpeechProviderIdsForPlugin("elevenlabs")).toEqual(["elevenlabs"]);
|
|
|
|
|
expect(findSpeechProviderIdsForPlugin("microsoft")).toEqual(["microsoft"]);
|
|
|
|
|
expect(findSpeechProviderIdsForPlugin("openai")).toEqual(["openai"]);
|
|
|
|
|
});
|
|
|
|
|
|
2026-03-16 20:42:00 -07:00
|
|
|
it("keeps bundled media-understanding ownership explicit", () => {
|
|
|
|
|
expect(findMediaUnderstandingProviderIdsForPlugin("anthropic")).toEqual(["anthropic"]);
|
|
|
|
|
expect(findMediaUnderstandingProviderIdsForPlugin("google")).toEqual(["google"]);
|
|
|
|
|
expect(findMediaUnderstandingProviderIdsForPlugin("minimax")).toEqual([
|
|
|
|
|
"minimax",
|
|
|
|
|
"minimax-portal",
|
|
|
|
|
]);
|
|
|
|
|
expect(findMediaUnderstandingProviderIdsForPlugin("mistral")).toEqual(["mistral"]);
|
|
|
|
|
expect(findMediaUnderstandingProviderIdsForPlugin("moonshot")).toEqual(["moonshot"]);
|
|
|
|
|
expect(findMediaUnderstandingProviderIdsForPlugin("openai")).toEqual(["openai"]);
|
|
|
|
|
expect(findMediaUnderstandingProviderIdsForPlugin("zai")).toEqual(["zai"]);
|
|
|
|
|
});
|
|
|
|
|
|
2026-03-16 00:13:52 -07:00
|
|
|
it("keeps bundled provider and web search tool ownership explicit", () => {
|
|
|
|
|
expect(findRegistrationForPlugin("firecrawl")).toMatchObject({
|
|
|
|
|
providerIds: [],
|
2026-03-16 20:01:08 -07:00
|
|
|
speechProviderIds: [],
|
2026-03-16 20:42:00 -07:00
|
|
|
mediaUnderstandingProviderIds: [],
|
2026-03-16 00:13:52 -07:00
|
|
|
webSearchProviderIds: ["firecrawl"],
|
|
|
|
|
toolNames: ["firecrawl_search", "firecrawl_scrape"],
|
|
|
|
|
});
|
|
|
|
|
});
|
2026-03-16 20:01:08 -07:00
|
|
|
|
|
|
|
|
it("tracks speech registrations on bundled provider plugins", () => {
|
|
|
|
|
expect(findRegistrationForPlugin("openai")).toMatchObject({
|
|
|
|
|
providerIds: ["openai", "openai-codex"],
|
|
|
|
|
speechProviderIds: ["openai"],
|
2026-03-16 20:42:00 -07:00
|
|
|
mediaUnderstandingProviderIds: ["openai"],
|
2026-03-16 20:01:08 -07:00
|
|
|
});
|
|
|
|
|
expect(findRegistrationForPlugin("elevenlabs")).toMatchObject({
|
|
|
|
|
providerIds: [],
|
|
|
|
|
speechProviderIds: ["elevenlabs"],
|
2026-03-16 20:42:00 -07:00
|
|
|
mediaUnderstandingProviderIds: [],
|
2026-03-16 20:01:08 -07:00
|
|
|
});
|
|
|
|
|
expect(findRegistrationForPlugin("microsoft")).toMatchObject({
|
|
|
|
|
providerIds: [],
|
|
|
|
|
speechProviderIds: ["microsoft"],
|
2026-03-16 20:42:00 -07:00
|
|
|
mediaUnderstandingProviderIds: [],
|
2026-03-16 20:01:08 -07:00
|
|
|
});
|
|
|
|
|
});
|
2026-03-16 20:27:25 -07:00
|
|
|
|
|
|
|
|
it("keeps bundled speech voice-list support explicit", () => {
|
|
|
|
|
expect(findSpeechProviderForPlugin("openai").listVoices).toEqual(expect.any(Function));
|
|
|
|
|
expect(findSpeechProviderForPlugin("elevenlabs").listVoices).toEqual(expect.any(Function));
|
|
|
|
|
expect(findSpeechProviderForPlugin("microsoft").listVoices).toEqual(expect.any(Function));
|
|
|
|
|
});
|
2026-03-16 21:59:39 -07:00
|
|
|
|
|
|
|
|
it("keeps bundled multi-image support explicit", () => {
|
|
|
|
|
expect(findMediaUnderstandingProviderForPlugin("anthropic").describeImages).toEqual(
|
|
|
|
|
expect.any(Function),
|
|
|
|
|
);
|
|
|
|
|
expect(findMediaUnderstandingProviderForPlugin("google").describeImages).toEqual(
|
|
|
|
|
expect.any(Function),
|
|
|
|
|
);
|
|
|
|
|
expect(findMediaUnderstandingProviderForPlugin("minimax").describeImages).toEqual(
|
|
|
|
|
expect.any(Function),
|
|
|
|
|
);
|
|
|
|
|
expect(findMediaUnderstandingProviderForPlugin("moonshot").describeImages).toEqual(
|
|
|
|
|
expect.any(Function),
|
|
|
|
|
);
|
|
|
|
|
expect(findMediaUnderstandingProviderForPlugin("openai").describeImages).toEqual(
|
|
|
|
|
expect.any(Function),
|
|
|
|
|
);
|
|
|
|
|
expect(findMediaUnderstandingProviderForPlugin("zai").describeImages).toEqual(
|
|
|
|
|
expect.any(Function),
|
|
|
|
|
);
|
|
|
|
|
});
|
2026-03-15 23:54:37 -07:00
|
|
|
});
|