fix(web-search): derived duckduckgo lang from raw query

callDuckDuckGoHtml now parses params.query once when parsedQuery is absent and uses that structured view for both q and kl. Direct searchDuckDuckGo/DuckDuckGoProvider.search calls no longer strip lang: from q while defaulting kl to us-en.

Fixes #7110
This commit is contained in:
roboomp
2026-07-30 21:55:47 +00:00
parent 8cf4e30a61
commit 942f856b29
2 changed files with 13 additions and 5 deletions
@@ -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<string> {
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);
@@ -39,7 +39,8 @@ describe("localeToKl", () => {
describe("searchDuckDuckGo kl parameter (integration)", () => {
const fakeAuthStorage = {} as unknown as AuthStorage;
async function effectiveForm(query: string): Promise<URLSearchParams> {
async function effectiveForm(query: string, opts: { withParsedQuery?: boolean } = {}): Promise<URLSearchParams> {
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");
});
});