Skip to content

Let Gemini clients use any provider - #27

Merged
playgrndlabs-bot merged 3 commits into
mainfrom
claude/project-thread-y9ekd4
Oct 28, 2026
Merged

playgrndlabs-bot merged 3 commits into
mainfrom
claude/project-thread-y9ekd4

Conversation

@playgrndlabs-bot

Copy link
Copy Markdown
Contributor

What

Gemini clients (/v1beta/models/{model}:generateContent, :streamGenerateContent, :countTokens) could only reach Gemini and Vertex. Now they reach every provider through Anthropic Messages, which completes the client-format work started in #23. Every client format now reaches every provider.

  • free/src/gemini-claude.ts (new), ported from CPA's translator/claude/gemini:
    • Request: systemInstruction, contents with text, inlineData/inline_data (images and documents) and https fileData. Gemini's own thought parts are dropped, since their signatures can't be replayed to Claude. functionCall becomes tool_use, with ids synthesized when the client sent none. functionResponse pairs with its call by id or by name in order; unanswered calls get an "interrupted" error result and orphaned results become text. Also handled: functionDeclarations (parameters or parametersJsonSchema, with Gemini's upper-case types lowered), toolConfig modes (NONE, ANY, one allowed name), maxOutputTokens, topP, stopSequences, thinkingConfig (level or budget mapped to Claude thinking), and responseMimeType: application/json as a system instruction.
    • Response: GeminiStream emits Gemini chunks (text, thought: true parts, functionCall with id, a final finishReason and usageMetadata). It writes SSE with ?alt=sse and one streamed JSON array without it, as Google's API does. geminiResponse covers generateContent. countTokens returns an estimate.
  • free/src/app.ts:
    • viaClaudeMessages now serves Gemini clients too.
    • servable() is gone, since every combination is served.
    • Providers whose native format is Anthropic (Claude keys, Kimi logins) get the Claude body directly.
    • Vertex service accounts and Kimi logins are now offered to every client format.
  • free/src/proxy.ts: a Gemini-shaped 403 is now PERMISSION_DENIED.

Security and safety

  • No new upstream hosts. fileData URLs are passed on only when https, and the Worker never fetches them; Anthropic does.
  • Client headers are not forwarded on translated requests, which use a bare request as before. The gateway key sent as ?key= is never forwarded.
  • Claude logins are still not offered to non-Claude-Code clients (no cloaking).
  • The body size cap and single parse are unchanged. Nothing new is logged or stored.

Tests

npm run verify: typecheck, lint and 205 tests pass.

  • New free/test/gemini-claude.test.ts covers request translation, call/result pairing, thinking mapping, SSE and JSON-array streaming, cut-off streams and whole responses.
  • app.test.ts adds:
    • Gemini clients on a Claude key (SSE, array, whole, countTokens);
    • Gemini clients on an OpenAI-compatible key;
    • errors in Gemini's shape;
    • a Chat client on a Vertex service account;
    • a Gemini client on a Kimi login.

Generated by Claude Code

Gemini generateContent requests are translated to Anthropic Messages (ported
from CPA's Gemini-to-Claude translator) and sent to a Claude key or on to the
provider's own format. Answers stream back as Gemini chunks, over SSE with
?alt=sse or as one JSON array without, or come back whole. countTokens gets
an estimate. With every client format now reaching every provider, the
servable() check goes away.
…-y9ekd4

# Conflicts:
#	free/README.md
#	free/src/app.ts
@playgrndlabs-bot
playgrndlabs-bot merged commit cd9991a into main Oct 28, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants