From bfeea5d23fc6516cdc376c6b5be442d39b0ae70b Mon Sep 17 00:00:00 2001 From: sline Date: Wed, 11 Mar 2026 00:52:49 +0800 Subject: [PATCH] fix(agents): prevent /v1beta duplication in Gemini PDF URL (#34369) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Strip trailing /v1beta from baseUrl before appending the version segment, so callers that already include /v1beta in their base URL (e.g. subagent-registry) no longer produce /v1beta/v1beta/models/… which results in a 404 from the Gemini API. Closes #34312 Co-authored-by: Claude Opus 4.6 --- src/agents/tools/pdf-native-providers.ts | 7 +++---- src/agents/tools/pdf-tool.test.ts | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/agents/tools/pdf-native-providers.ts b/src/agents/tools/pdf-native-providers.ts index 36d43ffb9f7..70a1e2e0e94 100644 --- a/src/agents/tools/pdf-native-providers.ts +++ b/src/agents/tools/pdf-native-providers.ts @@ -137,10 +137,9 @@ export async function geminiAnalyzePdf(params: { } parts.push({ text: params.prompt }); - const baseUrl = (params.baseUrl ?? "https://generativelanguage.googleapis.com").replace( - /\/+$/, - "", - ); + const baseUrl = (params.baseUrl ?? "https://generativelanguage.googleapis.com") + .replace(/\/+$/, "") + .replace(/\/v1beta$/, ""); const url = `${baseUrl}/v1beta/models/${encodeURIComponent(params.modelId)}:generateContent?key=${encodeURIComponent(apiKey)}`; const res = await fetch(url, { diff --git a/src/agents/tools/pdf-tool.test.ts b/src/agents/tools/pdf-tool.test.ts index 6cbc6ca54d1..381fc53c4b9 100644 --- a/src/agents/tools/pdf-tool.test.ts +++ b/src/agents/tools/pdf-tool.test.ts @@ -711,6 +711,26 @@ describe("native PDF provider API calls", () => { "apiKey required", ); }); + + it("geminiAnalyzePdf does not duplicate /v1beta when baseUrl already includes it", async () => { + const { geminiAnalyzePdf } = await import("./pdf-native-providers.js"); + const fetchMock = mockFetchResponse({ + ok: true, + json: async () => ({ + candidates: [{ content: { parts: [{ text: "ok" }] } }], + }), + }); + + await geminiAnalyzePdf( + makeGeminiAnalyzeParams({ + baseUrl: "https://generativelanguage.googleapis.com/v1beta", + }), + ); + + const [url] = fetchMock.mock.calls[0]; + expect(url).toContain("/v1beta/models/"); + expect(url).not.toContain("/v1beta/v1beta"); + }); }); // ---------------------------------------------------------------------------