mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
fix(plugins): guard provider discovery credential metadata
This commit is contained in:
@@ -170,6 +170,19 @@ function createManifestPluginWithoutDiscovery(params: {
|
||||
};
|
||||
}
|
||||
|
||||
function createPoisonedCredentialMetadataPlugin(params: {
|
||||
id: string;
|
||||
poison: "setup" | "providerAuthEnvVars";
|
||||
}): PluginManifestRecord {
|
||||
const plugin = createManifestPluginWithoutDiscovery({ id: params.id });
|
||||
return Object.defineProperty(plugin, params.poison, {
|
||||
configurable: true,
|
||||
get() {
|
||||
throw new Error(`provider discovery ${params.poison} metadata exploded`);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function createProvider(params: { id: string; mode: "static" | "catalog" }): ProviderPlugin {
|
||||
const hook = {
|
||||
run: async () => ({
|
||||
@@ -548,6 +561,45 @@ describe("resolvePluginDiscoveryProvidersRuntime", () => {
|
||||
expect(params.onlyPluginIds).toEqual(["kilocode"]);
|
||||
});
|
||||
|
||||
it("skips unreadable credential metadata while selecting full-load fallbacks", () => {
|
||||
const codexEntryProvider = createProvider({ id: "codex", mode: "catalog" });
|
||||
const fullProviders = [createProvider({ id: "kilocode", mode: "catalog" })];
|
||||
mocks.resolveDiscoveredProviderPluginIds.mockReturnValue([
|
||||
"codex",
|
||||
"broken-setup",
|
||||
"broken-auth-vars",
|
||||
"kilocode",
|
||||
]);
|
||||
mocks.loadPluginMetadataSnapshot.mockReturnValue({
|
||||
index: { plugins: [] },
|
||||
manifestRegistry: {
|
||||
plugins: [
|
||||
createManifestPlugin("codex"),
|
||||
createPoisonedCredentialMetadataPlugin({ id: "broken-setup", poison: "setup" }),
|
||||
createPoisonedCredentialMetadataPlugin({
|
||||
id: "broken-auth-vars",
|
||||
poison: "providerAuthEnvVars",
|
||||
}),
|
||||
createManifestPluginWithoutDiscovery({
|
||||
id: "kilocode",
|
||||
setupProviders: [{ id: "kilocode", envVars: ["KILOCODE_API_KEY"] }],
|
||||
}),
|
||||
],
|
||||
diagnostics: [],
|
||||
},
|
||||
});
|
||||
mocks.loadSource.mockReturnValue(codexEntryProvider);
|
||||
mocks.resolvePluginProviders.mockReturnValue(fullProviders);
|
||||
|
||||
expect(
|
||||
resolvePluginDiscoveryProvidersRuntime({
|
||||
env: { KILOCODE_API_KEY: "sk-test" } as NodeJS.ProcessEnv,
|
||||
}),
|
||||
).toEqual([{ ...codexEntryProvider, pluginId: "codex" }, ...fullProviders]);
|
||||
expect(mocks.resolvePluginProviders).toHaveBeenCalledTimes(1);
|
||||
expect(requireResolvePluginProvidersParams().onlyPluginIds).toEqual(["kilocode"]);
|
||||
});
|
||||
|
||||
it("enables bundled provider Vitest compat when falling back from discovery entries", () => {
|
||||
const fullProviders = [createProvider({ id: "deepseek", mode: "catalog" })];
|
||||
mocks.resolveDiscoveredProviderPluginIds.mockReturnValue([]);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import path from "node:path";
|
||||
import type { NormalizedModelCatalogRow } from "@openclaw/model-catalog-core/model-catalog-types";
|
||||
import { normalizeProviderId } from "@openclaw/model-catalog-core/provider-id";
|
||||
import { sortUniqueStrings } from "../../packages/normalization-core/src/string-normalization.js";
|
||||
import type { ModelDefinitionConfig, ModelProviderConfig } from "../config/types.models.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { planManifestModelCatalogRows } from "../model-catalog/manifest-planner.js";
|
||||
import { sortUniqueStrings } from "../../packages/normalization-core/src/string-normalization.js";
|
||||
import { loadManifestMetadataSnapshot } from "./manifest-contract-eligibility.js";
|
||||
import type { PluginManifestRecord } from "./manifest-registry.js";
|
||||
import { clearNativeRequireJavaScriptModuleCache } from "./native-module-require.js";
|
||||
@@ -123,14 +123,18 @@ function hasProviderAuthEnvCredential(
|
||||
plugin: PluginManifestRecord,
|
||||
env: NodeJS.ProcessEnv,
|
||||
): boolean {
|
||||
const envVars = [
|
||||
...(plugin.setup?.providers ?? []).flatMap((provider) => provider.envVars ?? []),
|
||||
...Object.values(plugin.providerAuthEnvVars ?? {}).flat(),
|
||||
];
|
||||
return envVars.some((name) => {
|
||||
const value = env[name]?.trim();
|
||||
return value !== undefined && value !== "";
|
||||
});
|
||||
try {
|
||||
const envVars = [
|
||||
...(plugin.setup?.providers ?? []).flatMap((provider) => provider.envVars ?? []),
|
||||
...Object.values(plugin.providerAuthEnvVars ?? {}).flat(),
|
||||
];
|
||||
return envVars.some((name) => {
|
||||
const value = env[name]?.trim();
|
||||
return value !== undefined && value !== "";
|
||||
});
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function modelDefinitionCostFromManifestRow(
|
||||
|
||||
Reference in New Issue
Block a user