fix(pdf): keep gemini keys out of request urls

This commit is contained in:
Peter Steinberger
2026-05-02 05:16:29 +01:00
parent 7934a2390c
commit d56374b93a
3 changed files with 5 additions and 2 deletions

View File

@@ -55,6 +55,7 @@ Docs: https://docs.openclaw.ai
- Slack/delivery: retry Slack Web API writes only when the SDK wraps a DNS request failure such as `EAI_AGAIN`, so transient resolver hiccups can recover without retrying platform errors that may duplicate messages. Fixes #68789. Thanks @sonnyb9.
- Slack/mentions: resolve `<!subteam^...>` user-group mentions through Slack `usergroups.users.list` and treat them as explicit mentions only when the bot user is a member, so mention-gated agent channels wake for real user-group mentions without config-only allowlists. Fixes #73827. Thanks @CG-Intelligence-Agent-Jack.
- Slack/message tool: let `read` fetch an exact Slack message timestamp, including a specific thread reply when paired with `threadId`, instead of returning only the parent thread or recent channel history. Fixes #53943. Thanks @zomars.
- PDF/Gemini: send native PDF analysis API keys in the `x-goog-api-key` header instead of the request URL, keeping secrets out of proxy and access logs. Supersedes #60600. Thanks @garagon.
- Web search: point missing-key errors to `web_fetch` for known URLs and the browser tool for interactive pages. Thanks @zhaoyang97.
- Web search: late-bind managed agent `web_search` calls to the current runtime config snapshot, so existing sessions do not keep stale unresolved SecretRefs after secrets reload. Fixes #75420. Thanks @richardmqq.
- Web search/Gemini: reuse `models.providers.google.apiKey` and `models.providers.google.baseUrl` as lower-priority fallbacks for Gemini web search after dedicated search config and `GEMINI_API_KEY`. Supersedes #57496. Thanks @Aoiujz.

View File

@@ -134,6 +134,8 @@ describe("native PDF provider API calls", () => {
const [url, opts] = fetchMock.mock.calls[0];
expect(url).toContain("generateContent");
expect(url).toContain("gemini-2.5-pro");
expect(url).not.toContain("?key=");
expect(opts.headers["x-goog-api-key"]).toBe("test-key");
expect(opts.signal).toBeInstanceOf(AbortSignal);
expect(opts.signal.aborted).toBe(false);
const body = JSON.parse(opts.body);

View File

@@ -153,11 +153,11 @@ export async function geminiAnalyzePdf(params: {
/\/v1beta$/i,
"",
);
const url = `${baseUrl}/v1beta/models/${encodeURIComponent(params.modelId)}:generateContent?key=${encodeURIComponent(apiKey)}`;
const url = `${baseUrl}/v1beta/models/${encodeURIComponent(params.modelId)}:generateContent`;
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
headers: { "Content-Type": "application/json", "x-goog-api-key": apiKey },
body: JSON.stringify({
contents: [{ role: "user", parts }],
}),