diff --git a/packages/coding-agent/src/web/search/providers/duckduckgo.ts b/packages/coding-agent/src/web/search/providers/duckduckgo.ts index aeb411cbe..72756fe68 100644 --- a/packages/coding-agent/src/web/search/providers/duckduckgo.ts +++ b/packages/coding-agent/src/web/search/providers/duckduckgo.ts @@ -2,7 +2,7 @@ import type { AuthStorage } from "@oh-my-pi/pi-ai"; import type { SearchResponse, SearchSource } from "../../../web/search/types"; import { SearchProviderError } from "../../../web/search/types"; import type { QuerySyntax } from "../query"; -import { formatScraperQuery } from "../query"; +import { formatScraperQuery, parseSearchQuery } from "../query"; import { clampNumResults } from "../utils"; import type { SearchParams } from "./base"; import { SearchProvider } from "./base"; @@ -246,9 +246,10 @@ export function localeToKl(lang: string | undefined): string | undefined { } async function callDuckDuckGoHtml(params: SearchParams): Promise { + const parsed = params.parsedQuery ?? parseSearchQuery(params.query); const form = new URLSearchParams({ - q: formatScraperQuery(params.query, params.parsedQuery, DDG_QUERY_SYNTAX), - kl: localeToKl(params.parsedQuery?.lang) ?? "us-en", + q: formatScraperQuery(params.query, parsed, DDG_QUERY_SYNTAX), + kl: localeToKl(parsed.lang) ?? "us-en", }); const df = params.recency ? RECENCY_TO_DDG_DF[params.recency] : undefined; if (df) form.set("df", df); diff --git a/packages/coding-agent/test/web/search/duckduckgo.test.ts b/packages/coding-agent/test/web/search/duckduckgo.test.ts index 071c46632..6ab1ad4ec 100644 --- a/packages/coding-agent/test/web/search/duckduckgo.test.ts +++ b/packages/coding-agent/test/web/search/duckduckgo.test.ts @@ -39,7 +39,8 @@ describe("localeToKl", () => { describe("searchDuckDuckGo kl parameter (integration)", () => { const fakeAuthStorage = {} as unknown as AuthStorage; - async function effectiveForm(query: string): Promise { + async function effectiveForm(query: string, opts: { withParsedQuery?: boolean } = {}): Promise { + const withParsedQuery = opts.withParsedQuery ?? true; let body: string | undefined; const fetchMock: FetchImpl = async (_input, init) => { body = init?.body as string; @@ -50,7 +51,7 @@ describe("searchDuckDuckGo kl parameter (integration)", () => { }; await searchDuckDuckGo({ query, - parsedQuery: parseSearchQuery(query), + parsedQuery: withParsedQuery ? parseSearchQuery(query) : undefined, systemPrompt: "", authStorage: fakeAuthStorage, fetch: fetchMock, @@ -84,4 +85,10 @@ describe("searchDuckDuckGo kl parameter (integration)", () => { const form = await effectiveForm("weather lang:de"); expect(form.get("kl")).toBe("us-en"); }); + + it("parses lang: from the raw query when parsedQuery is omitted (direct call)", async () => { + const form = await effectiveForm("weather lang:de-de", { withParsedQuery: false }); + expect(form.get("q")).toBe("weather"); + expect(form.get("kl")).toBe("de-de"); + }); });