mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 15:20:44 +00:00
fix(secrets): honor plugin install ledger for web fetch discovery
This commit is contained in:
@@ -1141,6 +1141,38 @@ describe("runtime web tools resolution", () => {
|
||||
expect(resolvePluginWebFetchProvidersMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("uses runtime web fetch discovery when the managed plugin install ledger is populated", async () => {
|
||||
loadPluginInstallRecordsSyncMock.mockReturnValue({
|
||||
"external-fetch": {
|
||||
source: "npm",
|
||||
spec: "@openclaw/external-fetch",
|
||||
},
|
||||
});
|
||||
|
||||
const { metadata } = await runRuntimeWebTools({
|
||||
config: asConfig({
|
||||
tools: {
|
||||
web: {
|
||||
fetch: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
env: {
|
||||
FIRECRAWL_API_KEY: "firecrawl-key", // pragma: allowlist secret
|
||||
},
|
||||
});
|
||||
|
||||
expect(metadata.fetch.selectedProvider).toBe("firecrawl");
|
||||
expect(resolveBundledWebFetchProvidersFromPublicArtifactsMock).not.toHaveBeenCalled();
|
||||
expect(resolvePluginWebFetchProvidersMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
bundledAllowlistCompat: true,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("uses env fallback for unresolved web fetch provider SecretRef when active", async () => {
|
||||
const { metadata, resolvedConfig, context } = await runRuntimeWebTools({
|
||||
config: asConfig({
|
||||
|
||||
@@ -121,7 +121,10 @@ function inferExactBundledPluginScopedWebToolConfigOwner(params: {
|
||||
return isRecord(pluginConfig?.[params.key]) ? params.pluginId : undefined;
|
||||
}
|
||||
|
||||
async function hasCustomWebSearchPluginRisk(params: {
|
||||
type WebProviderContract = "webSearchProviders" | "webFetchProviders";
|
||||
|
||||
async function hasCustomWebProviderPluginRisk(params: {
|
||||
contract: WebProviderContract;
|
||||
config: OpenClawConfig;
|
||||
env: NodeJS.ProcessEnv;
|
||||
}): Promise<boolean> {
|
||||
@@ -143,7 +146,7 @@ async function hasCustomWebSearchPluginRisk(params: {
|
||||
const { resolveManifestContractPluginIds } = await loadRuntimeWebToolsManifest();
|
||||
const bundledPluginIds = new Set<string>(
|
||||
resolveManifestContractPluginIds({
|
||||
contract: "webSearchProviders",
|
||||
contract: params.contract,
|
||||
origin: "bundled",
|
||||
config: params.config,
|
||||
env: params.env,
|
||||
@@ -377,6 +380,7 @@ async function resolveBundledWebFetchProviders(params: {
|
||||
sourceConfig: OpenClawConfig;
|
||||
context: ResolverContext;
|
||||
configuredBundledPluginId?: string;
|
||||
hasCustomWebFetchPluginRisk: boolean;
|
||||
}): Promise<PluginWebFetchProviderEntry[]> {
|
||||
const env = { ...process.env, ...params.context.env };
|
||||
if (params.configuredBundledPluginId) {
|
||||
@@ -395,15 +399,24 @@ async function resolveBundledWebFetchProviders(params: {
|
||||
origin: "bundled",
|
||||
});
|
||||
}
|
||||
const { resolveBundledWebFetchProvidersFromPublicArtifacts } =
|
||||
await loadRuntimeWebToolsPublicArtifacts();
|
||||
const bundled = resolveBundledWebFetchProvidersFromPublicArtifacts({
|
||||
config: params.sourceConfig,
|
||||
env,
|
||||
bundledAllowlistCompat: true,
|
||||
});
|
||||
if (bundled && bundled.length > 0) {
|
||||
return bundled;
|
||||
if (!params.hasCustomWebFetchPluginRisk) {
|
||||
const { resolveBundledWebFetchProvidersFromPublicArtifacts } =
|
||||
await loadRuntimeWebToolsPublicArtifacts();
|
||||
const bundled = resolveBundledWebFetchProvidersFromPublicArtifacts({
|
||||
config: params.sourceConfig,
|
||||
env,
|
||||
bundledAllowlistCompat: true,
|
||||
});
|
||||
if (bundled && bundled.length > 0) {
|
||||
return bundled;
|
||||
}
|
||||
const { resolvePluginWebFetchProviders } = await loadRuntimeWebToolsFallbackProviders();
|
||||
return resolvePluginWebFetchProviders({
|
||||
config: params.sourceConfig,
|
||||
env,
|
||||
bundledAllowlistCompat: true,
|
||||
origin: "bundled",
|
||||
});
|
||||
}
|
||||
const { resolvePluginWebFetchProviders } = await loadRuntimeWebToolsFallbackProviders();
|
||||
return resolvePluginWebFetchProviders({
|
||||
@@ -481,12 +494,22 @@ export async function resolveRuntimeWebTools(params: {
|
||||
const resolvedWeb = isRecord(resolvedTools?.web) ? resolvedTools.web : undefined;
|
||||
let hasCustomWebSearchRisk: Promise<boolean> | undefined;
|
||||
const getHasCustomWebSearchRisk = (): Promise<boolean> => {
|
||||
hasCustomWebSearchRisk ??= hasCustomWebSearchPluginRisk({
|
||||
hasCustomWebSearchRisk ??= hasCustomWebProviderPluginRisk({
|
||||
contract: "webSearchProviders",
|
||||
config: params.sourceConfig,
|
||||
env,
|
||||
});
|
||||
return hasCustomWebSearchRisk;
|
||||
};
|
||||
let hasCustomWebFetchRisk: Promise<boolean> | undefined;
|
||||
const getHasCustomWebFetchRisk = (): Promise<boolean> => {
|
||||
hasCustomWebFetchRisk ??= hasCustomWebProviderPluginRisk({
|
||||
contract: "webFetchProviders",
|
||||
config: params.sourceConfig,
|
||||
env,
|
||||
});
|
||||
return hasCustomWebFetchRisk;
|
||||
};
|
||||
const legacyXSearchSource = isRecord(sourceWeb?.x_search) ? sourceWeb.x_search : undefined;
|
||||
const legacyXSearchResolved = isRecord(resolvedWeb?.x_search) ? resolvedWeb.x_search : undefined;
|
||||
|
||||
@@ -670,11 +693,12 @@ export async function resolveRuntimeWebTools(params: {
|
||||
invalidAutoDetectCode: "WEB_FETCH_PROVIDER_INVALID_AUTODETECT",
|
||||
sourceConfig: params.sourceConfig,
|
||||
context: params.context,
|
||||
resolveProviders: ({ configuredBundledPluginId }) =>
|
||||
resolveProviders: async ({ configuredBundledPluginId }) =>
|
||||
resolveBundledWebFetchProviders({
|
||||
sourceConfig: params.sourceConfig,
|
||||
context: params.context,
|
||||
configuredBundledPluginId,
|
||||
hasCustomWebFetchPluginRisk: await getHasCustomWebFetchRisk(),
|
||||
}),
|
||||
sortProviders: sortWebFetchProvidersForAutoDetect,
|
||||
readConfiguredCredential: ({ provider, config, toolConfig }) =>
|
||||
|
||||
Reference in New Issue
Block a user