mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:40:44 +00:00
feat(models): read provider owners from installed index
This commit is contained in:
@@ -6,12 +6,19 @@ import {
|
||||
} from "./list.provider-catalog.js";
|
||||
|
||||
const providerDiscoveryMocks = vi.hoisted(() => ({
|
||||
loadInstalledPluginIndex: vi.fn(),
|
||||
resolveBundledProviderCompatPluginIds: vi.fn(),
|
||||
resolveInstalledPluginContributions: vi.fn(),
|
||||
resolveOwningPluginIdsForProvider: vi.fn(),
|
||||
resolvePluginDiscoveryProviders: vi.fn(),
|
||||
resolveProviderContractPluginIdsForProviderAlias: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../../plugins/installed-plugin-index.js", () => ({
|
||||
loadInstalledPluginIndex: providerDiscoveryMocks.loadInstalledPluginIndex,
|
||||
resolveInstalledPluginContributions: providerDiscoveryMocks.resolveInstalledPluginContributions,
|
||||
}));
|
||||
|
||||
vi.mock("../../plugins/providers.js", () => ({
|
||||
resolveBundledProviderCompatPluginIds:
|
||||
providerDiscoveryMocks.resolveBundledProviderCompatPluginIds,
|
||||
@@ -102,9 +109,34 @@ const catalogOnlyProvider = {
|
||||
|
||||
const defaultProviders = [chutesProvider, moonshotProvider, openaiProvider];
|
||||
|
||||
function createContributionMaps(params: {
|
||||
providers?: ReadonlyMap<string, readonly string[]>;
|
||||
cliBackends?: ReadonlyMap<string, readonly string[]>;
|
||||
}) {
|
||||
return {
|
||||
providers: params.providers ?? new Map(),
|
||||
channels: new Map(),
|
||||
channelConfigs: new Map(),
|
||||
setupProviders: new Map(),
|
||||
cliBackends: params.cliBackends ?? new Map(),
|
||||
modelCatalogProviders: new Map(),
|
||||
commandAliases: new Map(),
|
||||
contracts: new Map(),
|
||||
};
|
||||
}
|
||||
|
||||
describe("loadProviderCatalogModelsForList", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
providerDiscoveryMocks.loadInstalledPluginIndex.mockReturnValue({
|
||||
plugins: [],
|
||||
diagnostics: [],
|
||||
});
|
||||
providerDiscoveryMocks.resolveInstalledPluginContributions.mockReturnValue(
|
||||
createContributionMaps({
|
||||
providers: new Map(defaultProviders.map((provider) => [provider.id, [provider.pluginId]])),
|
||||
}),
|
||||
);
|
||||
providerDiscoveryMocks.resolveBundledProviderCompatPluginIds.mockReturnValue([
|
||||
"chutes",
|
||||
"moonshot",
|
||||
@@ -167,6 +199,22 @@ describe("loadProviderCatalogModelsForList", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("resolves provider owners from the installed plugin index before manifest fallback", async () => {
|
||||
await expect(
|
||||
resolveProviderCatalogPluginIdsForFilter({
|
||||
cfg: baseParams.cfg,
|
||||
env: baseParams.env,
|
||||
providerFilter: "moonshot",
|
||||
}),
|
||||
).resolves.toEqual(["moonshot"]);
|
||||
|
||||
expect(providerDiscoveryMocks.loadInstalledPluginIndex).toHaveBeenCalledWith({
|
||||
config: baseParams.cfg,
|
||||
env: baseParams.env,
|
||||
});
|
||||
expect(providerDiscoveryMocks.resolveOwningPluginIdsForProvider).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("returns an empty catalog when a static provider catalog throws", async () => {
|
||||
providerDiscoveryMocks.resolvePluginDiscoveryProviders.mockResolvedValueOnce([
|
||||
{
|
||||
@@ -224,6 +272,9 @@ describe("loadProviderCatalogModelsForList", () => {
|
||||
});
|
||||
|
||||
it("does not skip registry for non-bundled static catalog owners", async () => {
|
||||
providerDiscoveryMocks.resolveInstalledPluginContributions.mockReturnValueOnce(
|
||||
createContributionMaps({}),
|
||||
);
|
||||
providerDiscoveryMocks.resolveOwningPluginIdsForProvider.mockReturnValueOnce([
|
||||
"workspace-static-provider",
|
||||
]);
|
||||
@@ -241,6 +292,10 @@ describe("loadProviderCatalogModelsForList", () => {
|
||||
});
|
||||
|
||||
it("recognizes bundled provider hook aliases before the unknown-provider short-circuit", async () => {
|
||||
providerDiscoveryMocks.resolveInstalledPluginContributions.mockReturnValueOnce(
|
||||
createContributionMaps({}),
|
||||
);
|
||||
|
||||
await expect(
|
||||
resolveProviderCatalogPluginIdsForFilter({
|
||||
cfg: baseParams.cfg,
|
||||
@@ -291,6 +346,10 @@ describe("loadProviderCatalogModelsForList", () => {
|
||||
});
|
||||
|
||||
it("keeps unknown provider filters eligible for early empty results", async () => {
|
||||
providerDiscoveryMocks.resolveInstalledPluginContributions.mockReturnValueOnce(
|
||||
createContributionMaps({}),
|
||||
);
|
||||
|
||||
await expect(
|
||||
resolveProviderCatalogPluginIdsForFilter({
|
||||
cfg: baseParams.cfg,
|
||||
|
||||
@@ -4,6 +4,10 @@ import type { ModelProviderConfig } from "../../config/types.models.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import { formatErrorMessage } from "../../infra/errors.js";
|
||||
import { createSubsystemLogger } from "../../logging/subsystem.js";
|
||||
import {
|
||||
loadInstalledPluginIndex,
|
||||
resolveInstalledPluginContributions,
|
||||
} from "../../plugins/installed-plugin-index.js";
|
||||
import {
|
||||
groupPluginDiscoveryProvidersByOrder,
|
||||
normalizePluginDiscoveryResult,
|
||||
@@ -31,6 +35,38 @@ function providerMatchesFilter(params: {
|
||||
].some((providerId) => normalizeProviderId(providerId) === params.providerFilter);
|
||||
}
|
||||
|
||||
function collectMatchingContributionPluginIds(
|
||||
contributions: ReadonlyMap<string, readonly string[]>,
|
||||
providerFilter: string,
|
||||
): string[] {
|
||||
const pluginIds: string[] = [];
|
||||
for (const [contributionId, ownerPluginIds] of contributions) {
|
||||
if (normalizeProviderId(contributionId) === providerFilter) {
|
||||
pluginIds.push(...ownerPluginIds);
|
||||
}
|
||||
}
|
||||
return [...new Set(pluginIds)].toSorted((left, right) => left.localeCompare(right));
|
||||
}
|
||||
|
||||
function resolveInstalledIndexPluginIdsForProviderFilter(params: {
|
||||
cfg: OpenClawConfig;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
providerFilter: string;
|
||||
}): string[] | undefined {
|
||||
const index = loadInstalledPluginIndex({
|
||||
config: params.cfg,
|
||||
env: params.env,
|
||||
});
|
||||
const contributions = resolveInstalledPluginContributions(index);
|
||||
const pluginIds = [
|
||||
...collectMatchingContributionPluginIds(contributions.providers, params.providerFilter),
|
||||
...collectMatchingContributionPluginIds(contributions.cliBackends, params.providerFilter),
|
||||
];
|
||||
return pluginIds.length > 0
|
||||
? [...new Set(pluginIds)].toSorted((left, right) => left.localeCompare(right))
|
||||
: undefined;
|
||||
}
|
||||
|
||||
export async function resolveProviderCatalogPluginIdsForFilter(params: {
|
||||
cfg: OpenClawConfig;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
@@ -40,6 +76,14 @@ export async function resolveProviderCatalogPluginIdsForFilter(params: {
|
||||
if (!providerFilter) {
|
||||
return undefined;
|
||||
}
|
||||
const installedIndexPluginIds = resolveInstalledIndexPluginIdsForProviderFilter({
|
||||
cfg: params.cfg,
|
||||
env: params.env,
|
||||
providerFilter,
|
||||
});
|
||||
if (installedIndexPluginIds) {
|
||||
return installedIndexPluginIds;
|
||||
}
|
||||
const manifestPluginIds = resolveOwningPluginIdsForProvider({
|
||||
provider: providerFilter,
|
||||
config: params.cfg,
|
||||
|
||||
Reference in New Issue
Block a user