diff --git a/CHANGELOG.md b/CHANGELOG.md index 8feaadb4e7f..8673c4a21d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Docs: https://docs.openclaw.ai - CLI/migrate: drop trailing periods from Codex migrate item messages and `REASON_CODE_MESSAGES` strings so plan/result rows read as labels instead of sentence fragments. (#81705) Thanks @sjf. - Slack: treat malformed private-file redirect `Location` headers as unfollowable redirects instead of failing Slack media downloads. - Matrix: ignore malformed percent-encoding in optional location URI parameters instead of letting a bad `geo:` event abort inbound message handling. +- Web search: auto-detect Brave from the documented `tools.web.search.apiKey` config path, keeping allowlisted isolated cron runs from reporting `web_search` unavailable when the key is stored outside plugin-scoped config. Fixes #81538. Thanks @atomicmonk. - Plugins: discover provider plugins from `setup.providers[].envVars` credentials during provider discovery while keeping the deprecated `providerAuthEnvVars` fallback. (#81542) Thanks @JARVIS-Glasses. - Docs/Codex harness: clarify that per-agent `CODEX_HOME` isolates `~/.codex` while inherited `HOME` intentionally keeps `.agents` discovery and subprocess user-home state available. - CLI/plugins: keep bare plugin and parent-command help on the lightweight path, avoiding plugin registry discovery before rendering help. diff --git a/src/secrets/runtime-web-tools.test.ts b/src/secrets/runtime-web-tools.test.ts index c02eab28ca1..bcdc2c99a40 100644 --- a/src/secrets/runtime-web-tools.test.ts +++ b/src/secrets/runtime-web-tools.test.ts @@ -1094,8 +1094,8 @@ describe("runtime web tools resolution", () => { expect(resolvePluginWebSearchProvidersMock).not.toHaveBeenCalled(); }); - it("does not auto-detect from legacy top-level web search apiKey", async () => { - const { metadata } = await runRuntimeWebTools({ + it("auto-detects Brave from legacy top-level web search apiKey", async () => { + const { metadata, resolvedConfig } = await runRuntimeWebTools({ config: asConfig({ tools: { web: { @@ -1110,7 +1110,10 @@ describe("runtime web tools resolution", () => { }, }); - expect(metadata.search.selectedProvider).toBe("duckduckgo"); + expect(metadata.search.providerSource).toBe("auto-detect"); + expect(metadata.search.selectedProvider).toBe("brave"); + expect(metadata.search.selectedProviderKeySource).toBe("secretRef"); + expect(readProviderKey(resolvedConfig, "brave")).toBe("legacy-web-search-key"); expect(resolveManifestContractPluginIdsByCompatibilityRuntimePathMock).not.toHaveBeenCalled(); expect(resolveBundledExplicitWebSearchProvidersFromPublicArtifactsMock).not.toHaveBeenCalled(); expect(resolvePluginWebSearchProvidersMock).not.toHaveBeenCalled(); diff --git a/src/secrets/runtime-web-tools.ts b/src/secrets/runtime-web-tools.ts index 43509849a0a..70ea130d9cb 100644 --- a/src/secrets/runtime-web-tools.ts +++ b/src/secrets/runtime-web-tools.ts @@ -479,7 +479,10 @@ function readConfiguredProviderCredential(params: { config: OpenClawConfig; search: Record | undefined; }): unknown { - return params.provider.getConfiguredCredentialValue?.(params.config); + return ( + params.provider.getConfiguredCredentialValue?.(params.config) ?? + params.provider.getCredentialValue(params.search) + ); } function readConfiguredProviderCredentialFallback(params: {