Add Google Gemini platform via OpenAI-compat endpoint (provider 7)

The 10th registry row: id "google", GEMINI_API_KEY > auth.json "google"
scope, https://generativelanguage.googleapis.com/v1beta/openai (Gemini's
OpenAI-compatibility shim) with KIGI_GOOGLE_BASE_URL override, Bearer,
OpenAI listing + ChatCompletions + Passthrough, enrichment-backed
metadata (models_dev_id google), tool-calling listing restriction.

Review caught a ship-blocking defect: Gemini's compat /models returns
-PREFIXED ids (confirmed via Google's own cookbook), but the
models.dev snapshot keys and the chat endpoint use the BARE id. Without
normalization the enrichment lookup misses and restrict_to_enriched
silently empties the Gemini catalog (login works, zero models
selectable). A doc WebFetch had hidden this — the compat docs show bare
INPUT ids to retrieve/chat but never print the list OUTPUT.

Fix: new spec field strip_listing_id_prefix, applied in the fetch before
filter/enrich/keying. Google sets Some("models/") (defensive: a no-op if
an id is already bare, so correct regardless of the live shape); all other
rows None. The e2e now feeds the REAL prefixed listing ids and asserts
they survive as the bare managed key google/gemini-2.5-pro with the bare
id on the wire (chat rejects the prefix); a registry test pins the config.

Note: models.dev models Gemini reasoning as budget_tokens (not
effort-type), so no auto effort-menu — models still fully work; reasoning
is dynamic. Gemini compat applies default safety filters (no BLOCK_NONE).
This commit is contained in:
2026-07-21 11:47:47 -04:00
parent e373ff8b29
commit 7a2cd8a726
4 changed files with 208 additions and 9 deletions
@@ -597,7 +597,8 @@ mod tests {
"deepseek",
"groq",
"mistral",
"fireworks"
"fireworks",
"google"
]
);
assert_eq!(default_id(&built), Some(XAI_API_KEY_METHOD_ID));
@@ -629,7 +630,8 @@ mod tests {
"deepseek",
"groq",
"mistral",
"fireworks"
"fireworks",
"google"
]
);
assert_eq!(default_id(&built), Some(CACHED_TOKEN_AUTH_METHOD_ID));
@@ -654,7 +656,8 @@ mod tests {
"deepseek",
"groq",
"mistral",
"fireworks"
"fireworks",
"google"
]
);
assert_eq!(default_id(&built), Some(CACHED_TOKEN_AUTH_METHOD_ID));
@@ -682,7 +685,8 @@ mod tests {
"deepseek",
"groq",
"mistral",
"fireworks"
"fireworks",
"google"
]
);
assert_eq!(default_id(&built), None);