Skip to content

Commit 9be1699

Browse files
authored
fix(wizard): report keyless web search providers as ready
Onboarding finalize now treats configured web search providers with requiresCredential: false as ready instead of warning that an API key is missing. This covers keyless providers such as Parallel Search (Free), DuckDuckGo, and Ollama while preserving credential-required warnings for providers that need keys.\n\nProof: focused wizard/search tests; oxlint on changed files; git diff --check; autoreview clean; Azure Crabbox check:changed cbx_b92ef084c21c passed; GitHub checks green.
1 parent 777f740 commit 9be1699

5 files changed

Lines changed: 60 additions & 1 deletion

File tree

src/wizard/i18n/locales/en.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,7 @@ export const en = {
998998
webSearchGetKey: "Get your key at: {url}",
999999
webSearchAuthProfile: "Credential: existing {provider} auth profile.",
10001000
webSearchKeyEnv: "API key: provided via {env} env var.",
1001+
webSearchKeyFree: "Web search is ready — this provider works with no API key.",
10011002
webSearchKeyRef: "API key: configured via secret reference.",
10021003
webSearchKeyStored: "API key: stored in config.",
10031004
webSearchNeedsKey: "web_search will not work until a key is added.",

src/wizard/i18n/locales/zh-CN.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,7 @@ export const zh_CN = {
962962
webSearchGetKey: "获取 key:{url}",
963963
webSearchAuthProfile: "凭据:使用已有 {provider} auth profile。",
964964
webSearchKeyEnv: "API key:通过 {env} 环境变量提供。",
965+
webSearchKeyFree: "Web search 已就绪 —— 此 provider 无需 API key。",
965966
webSearchKeyRef: "API key:通过 secret reference 配置。",
966967
webSearchKeyStored: "API key:已存入配置。",
967968
webSearchNeedsKey: "添加 key 前 web_search 无法工作。",

src/wizard/i18n/locales/zh-TW.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,7 @@ export const zh_TW = {
963963
webSearchGetKey: "取得 key:{url}",
964964
webSearchAuthProfile: "憑證:使用已有 {provider} auth profile。",
965965
webSearchKeyEnv: "API key:透過 {env} 環境變數提供。",
966+
webSearchKeyFree: "Web search 已就緒 —— 此 provider 無需 API key。",
966967
webSearchKeyRef: "API key:透過 secret reference 設定。",
967968
webSearchKeyStored: "API key:已存入設定。",
968969
webSearchNeedsKey: "新增 key 前 web_search 無法運作。",

src/wizard/setup.finalize.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ function createWebSearchProviderEntry(
188188
| "placeholder"
189189
| "signupUrl"
190190
| "credentialPath"
191+
| "requiresCredential"
191192
>,
192193
): PluginWebSearchProviderEntry {
193194
return {
@@ -839,6 +840,49 @@ describe("finalizeSetupWizard", () => {
839840
);
840841
});
841842

843+
it("reports a keyless provider as ready without prompting for an API key", async () => {
844+
listConfiguredWebSearchProviders.mockReturnValue([
845+
createWebSearchProviderEntry({
846+
id: "parallel-free",
847+
label: "Parallel Search (Free)",
848+
hint: "Free web search via Parallel's hosted Search MCP",
849+
envVars: [],
850+
placeholder: "",
851+
signupUrl: "https://parallel.ai",
852+
credentialPath: "",
853+
requiresCredential: false,
854+
}),
855+
]);
856+
857+
const prompter = createLaterPrompter();
858+
859+
await finalizeSetupWizard(
860+
createAdvancedFinalizeArgs({
861+
nextConfig: {
862+
tools: { web: { search: { provider: "parallel-free", enabled: true } } },
863+
},
864+
prompter,
865+
}),
866+
);
867+
868+
expectNoteContains(
869+
prompter,
870+
"Web search is ready — this provider works with no API key.",
871+
"Web search",
872+
);
873+
// The credential-required warning must NOT appear for a keyless provider.
874+
expect(
875+
vi
876+
.mocked(prompter.note)
877+
.mock.calls.some(
878+
([message, title]) =>
879+
title === "Web search" &&
880+
(message.includes("no API key was found") ||
881+
message.includes("will not work until a key is added")),
882+
),
883+
).toBe(false);
884+
});
885+
842886
it("uses the setup token for health checks to avoid local env token drift", async () => {
843887
vi.stubEnv("OPENCLAW_GATEWAY_TOKEN", "env-token");
844888
const prompter = createLaterPrompter();

src/wizard/setup.finalize.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,18 @@ export async function finalizeSetupWizard(
644644
].join("\n"),
645645
t("wizard.finalize.webSearchTitle"),
646646
);
647+
} else if (webSearchEnabled !== false && entry.requiresCredential === false) {
648+
// Keyless providers (e.g. Parallel Search (Free), DuckDuckGo, Ollama) need
649+
// no API key — report ready rather than the credential-required warning.
650+
await prompter.note(
651+
[
652+
t("wizard.finalize.webSearchKeyFree"),
653+
"",
654+
t("wizard.finalize.webSearchProvider", { provider: label }),
655+
t("wizard.finalize.webDocs"),
656+
].join("\n"),
657+
t("wizard.finalize.webSearchTitle"),
658+
);
647659
} else if (webSearchEnabled !== false && hasCredential) {
648660
await prompter.note(
649661
[
@@ -655,7 +667,7 @@ export async function finalizeSetupWizard(
655667
].join("\n"),
656668
t("wizard.finalize.webSearchTitle"),
657669
);
658-
} else if (!hasCredential) {
670+
} else if (entry.requiresCredential !== false && !hasCredential) {
659671
await prompter.note(
660672
[
661673
t("wizard.finalize.webSearchNoKey", { provider: label }),

0 commit comments

Comments
 (0)