




















@@ -300,24 +300,6 @@ function readProviderKey(config: OpenClawConfig, provider: ProviderUnderTest): u
300300return pluginConfig?.webSearch?.apiKey;
301301}
302302303-function expectInactiveWebFetchProviderSecretRef(params: {
304-resolveSpy: ReturnType<typeof vi.spyOn>;
305-metadata: Awaited<ReturnType<typeof runRuntimeWebTools>>["metadata"];
306-context: Awaited<ReturnType<typeof runRuntimeWebTools>>["context"];
307-}) {
308-expect(params.resolveSpy).not.toHaveBeenCalled();
309-expect(params.metadata.fetch.selectedProvider).toBeUndefined();
310-expect(params.metadata.fetch.selectedProviderKeySource).toBeUndefined();
311-expect(params.context.warnings).toEqual(
312-expect.arrayContaining([
313-expect.objectContaining({
314-code: "SECRETS_REF_IGNORED_INACTIVE_SURFACE",
315-path: "plugins.entries.firecrawl.config.webFetch.apiKey",
316-}),
317-]),
318-);
319-}
320-321303describe("runtime web tools resolution", () => {
322304beforeAll(async () => {
323305secretResolve = await import("./resolve.js");
@@ -416,6 +398,105 @@ describe("runtime web tools resolution", () => {
416398expect(resolvePluginWebFetchProvidersMock).not.toHaveBeenCalled();
417399});
418400401+it("skips fetch provider discovery when web fetch only configures runtime limits", async () => {
402+const { metadata } = await runRuntimeWebTools({
403+config: asConfig({
404+tools: {
405+web: {
406+fetch: {
407+enabled: true,
408+maxChars: 200_000,
409+maxCharsCap: 2_000_000,
410+},
411+},
412+},
413+plugins: {
414+enabled: true,
415+allow: [],
416+entries: {},
417+},
418+}),
419+env: {
420+FIRECRAWL_API_KEY: "firecrawl-key-should-not-resolve", // pragma: allowlist secret
421+},
422+});
423+424+expect(metadata.fetch.providerSource).toBe("none");
425+expect(metadata.fetch.selectedProvider).toBeUndefined();
426+expect(resolveBundledExplicitWebFetchProvidersFromPublicArtifactsMock).not.toHaveBeenCalled();
427+expect(resolveBundledWebFetchProvidersFromPublicArtifactsMock).not.toHaveBeenCalled();
428+expect(resolvePluginWebFetchProvidersMock).not.toHaveBeenCalled();
429+});
430+431+it("skips fetch provider discovery when web fetch is explicitly disabled", async () => {
432+const { metadata } = await runRuntimeWebTools({
433+config: asConfig({
434+tools: {
435+web: {
436+fetch: {
437+enabled: false,
438+provider: "firecrawl",
439+},
440+},
441+},
442+plugins: {
443+entries: {
444+firecrawl: {
445+config: {
446+webFetch: {
447+apiKey: { source: "env", provider: "default", id: "FIRECRAWL_API_KEY" },
448+},
449+},
450+},
451+},
452+},
453+}),
454+env: {
455+FIRECRAWL_API_KEY: "firecrawl-key-should-not-resolve", // pragma: allowlist secret
456+},
457+});
458+459+expect(metadata.fetch.providerSource).toBe("none");
460+expect(metadata.fetch.selectedProvider).toBeUndefined();
461+expect(resolveBundledExplicitWebFetchProvidersFromPublicArtifactsMock).not.toHaveBeenCalled();
462+expect(resolveBundledWebFetchProvidersFromPublicArtifactsMock).not.toHaveBeenCalled();
463+expect(resolvePluginWebFetchProvidersMock).not.toHaveBeenCalled();
464+});
465+466+it("keeps active fetch provider SecretRefs on the discovery path", async () => {
467+const { metadata } = await runRuntimeWebTools({
468+config: asConfig({
469+tools: {
470+web: {
471+fetch: {
472+provider: "firecrawl",
473+},
474+},
475+},
476+plugins: {
477+entries: {
478+firecrawl: {
479+config: {
480+webFetch: {
481+apiKey: { source: "env", provider: "default", id: "FIRECRAWL_API_KEY" },
482+},
483+},
484+},
485+},
486+},
487+}),
488+env: {
489+FIRECRAWL_API_KEY: "firecrawl-key", // pragma: allowlist secret
490+},
491+});
492+493+expect(metadata.fetch.providerSource).toBe("configured");
494+expect(metadata.fetch.selectedProvider).toBe("firecrawl");
495+expect(resolveBundledExplicitWebFetchProvidersFromPublicArtifactsMock).toHaveBeenCalledWith({
496+onlyPluginIds: ["firecrawl"],
497+});
498+});
499+419500it("auto-selects a keyless provider when no credentials are configured", async () => {
420501const { metadata } = await runRuntimeWebTools({
421502config: asConfig({
@@ -969,7 +1050,13 @@ describe("runtime web tools resolution", () => {
9691050}),
9701051});
9711052972-expectInactiveWebFetchProviderSecretRef({ resolveSpy, metadata, context });
1053+expect(resolveSpy).not.toHaveBeenCalled();
1054+expect(metadata.fetch.selectedProvider).toBeUndefined();
1055+expect(metadata.fetch.selectedProviderKeySource).toBeUndefined();
1056+expect(context.warnings).toEqual([]);
1057+expect(resolveBundledExplicitWebFetchProvidersFromPublicArtifactsMock).not.toHaveBeenCalled();
1058+expect(resolveBundledWebFetchProvidersFromPublicArtifactsMock).not.toHaveBeenCalled();
1059+expect(resolvePluginWebFetchProvidersMock).not.toHaveBeenCalled();
9731060});
97410619751062it("keeps configured provider metadata and inactive warnings when search is disabled", async () => {
@@ -1151,17 +1238,18 @@ describe("runtime web tools resolution", () => {
1151123811521239const { metadata } = await runRuntimeWebTools({
11531240config: asConfig({
1154-tools: {
1155-web: {
1156-fetch: {
1157-enabled: true,
1241+plugins: {
1242+entries: {
1243+firecrawl: {
1244+config: {
1245+webFetch: {
1246+apiKey: "firecrawl-config-key",
1247+},
1248+},
11581249},
11591250},
11601251},
11611252}),
1162-env: {
1163-FIRECRAWL_API_KEY: "firecrawl-key", // pragma: allowlist secret
1164-},
11651253});
1166125411671255expect(metadata.fetch.selectedProvider).toBe("firecrawl");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。