feat(agent): GeminiProvider over reqwest with function calling (#9) - #57
Merged
Conversation
Implements LlmProvider for Gemini against :generateContent (no SDK,
same posture as chat/anthropic.rs):
- Pure, unit-tested conversions to_wire_request / from_wire_response;
complete() is the thin HTTP shell around them.
- System turns lifted to systemInstruction; user/assistant -> user/model;
assistant tool_calls -> functionCall parts; tool results -> functionResponse
parts (role user), routed by name.
- API key sent via x-goog-api-key header (never in URL/query/logs).
- Token usage reported; finish_reason forced to ToolCalls when the model
emits function calls.
- HTTP errors classified (400 InvalidRequest, 401/403 Auth, else Provider).
- with_base_url() for mock-server tests.
Adds ChatMessage.name (Option) so tool results carry the tool name for
name-routed providers; tool_result() now takes (id, name, content).
Tests: 7 non-live (wire mapping + parsing + error classification) plus an
#[ignore] live smoke test. Verified live against gemini-2.5-flash with a
real key: text completion returned usage, tool calling returned
apply_seed{kind,n} with finish=ToolCalls.
Closes #9.
ammar-s847
force-pushed
the
agent/gemini-provider
branch
from
May 27, 2026 22:17
c6fe269 to
459a1e9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements #9 — the first concrete
LlmProvider. Stacked on #8 (PR #49); base isagent/loop-provider, so review/merge #49 first.What
core/src/agent/provider/gemini.rs:GeminiProvideragainst:generateContent, no SDK (mirrorschat/anthropic.rs).to_wire_request/from_wire_response(unit-tested without a network);complete()is the thin HTTP shell.systemInstruction; user/assistant →user/model; assistanttool_calls→functionCall; tool results →functionResponse(roleuser), routed by name.x-goog-api-keyheader (never in URL/query/logs).ChatMessage.nameso tool results carry the tool name (Gemini routes by name; OpenAI uses it too).tool_result(id, name, content).MVP / Acceptance (#9)
functionCall/functionResponse↔ neutral typesgemini-2.5-flash)Live verification (real key)
Ran the
#[ignore]smoke test against gemini-2.5-flash:Note:
gemini-2.0-flashreturned HTTP 429limit: 0(no free-tier quota on this key) — our error classification handled it correctly; default test model is now2.5-flash.Tests
cargo test -p core agent::provider→ 13 passed, 1 ignored (live).Live:
GOOGLE_API_KEY=... cargo test -p core gemini_live -- --ignored --nocapture.Closes #9.