fix: support OAuth for Gemini media understanding

Extract parseGeminiAuth() to shared infra module and use it in both
embeddings-gemini.ts and inline-data.ts.

Previously, inline-data.ts directly set x-goog-api-key header without
handling OAuth JSON format. Now it properly supports both traditional
API keys and OAuth tokens.
This commit is contained in:
康熙
2026-02-16 14:19:01 +08:00
committed by Peter Steinberger
parent 3379b9d341
commit 153794080e
3 changed files with 47 additions and 38 deletions

View File

@@ -1,6 +1,7 @@
import type { EmbeddingProvider, EmbeddingProviderOptions } from "./embeddings.js";
import { requireApiKey, resolveApiKeyForProvider } from "../agents/model-auth.js";
import { isTruthyEnvValue } from "../infra/env.js";
import { parseGeminiAuth } from "../infra/gemini-auth.js";
import { createSubsystemLogger } from "../logging/subsystem.js";
export type GeminiEmbeddingClient = {
@@ -37,39 +38,6 @@ function resolveRemoteApiKey(remoteApiKey?: string): string | undefined {
return trimmed;
}
/**
* Parse Gemini API key and return appropriate auth headers.
* Supports both traditional API keys and OAuth JSON format.
*
* OAuth format: `{"token": "...", "projectId": "..."}`
*/
function parseGeminiAuth(apiKey: string): { headers: Record<string, string> } {
// Try parsing as OAuth JSON format
if (apiKey.startsWith("{")) {
try {
const parsed = JSON.parse(apiKey) as { token?: string; projectId?: string };
if (typeof parsed.token === "string" && parsed.token) {
return {
headers: {
Authorization: `Bearer ${parsed.token}`,
"Content-Type": "application/json",
},
};
}
} catch {
// Parse failed, fallback to API key mode
}
}
// Default: traditional API key
return {
headers: {
"x-goog-api-key": apiKey,
"Content-Type": "application/json",
},
};
}
function normalizeGeminiModel(model: string): string {
const trimmed = model.trim();
if (!trimmed) {