Skip to content

feat(gemini): Gemini provider Phase 1 — basic generateContent chat#1605

Merged
bug-ops merged 1 commit intomainfrom
gemini-provider
Mar 13, 2026
Merged

feat(gemini): Gemini provider Phase 1 — basic generateContent chat#1605
bug-ops merged 1 commit intomainfrom
gemini-provider

Conversation

@bug-ops
Copy link
Owner

@bug-ops bug-ops commented Mar 13, 2026

Closes #1593. Part of epic #1592.

Summary

  • New GeminiProvider in crates/zeph-llm/src/gemini.rs — basic generateContent chat via Google Gemini API
  • Authentication via x-goog-api-key header (not ?key= URL query param — avoids key leakage in DEBUG logs)
  • System prompt extracted to systemInstruction top-level field; Role::Assistant"model" role
  • Consecutive same-role message merging (Gemini requires strict user/model alternation)
  • First-message guard: if contents[0].role == "model", a synthetic empty user turn is prepended
  • Configurable base_url, model (default gemini-2.0-flash), max_tokens
  • JSON serialized once before retry loop; HTTP 429 and 503 retried via shared send_with_retry()
  • ProviderKind::Gemini, [llm.gemini] config section, ZEPH_GEMINI_API_KEY vault key
  • --init wizard updated with Gemini provider option
  • Also fixes send_with_retry() to retry HTTP 503 alongside 429 (benefits all providers)

Test plan

  • 128 new tests (5032 → 5160 total), including 3 wiremock end-to-end HTTP tests:
    • HTTP 4xx + error body → LlmError::Other
    • HTTP 429 + RESOURCE_EXHAUSTEDLlmError::RateLimited
    • Success + usageMetadatalast_usage() populated
  • cargo +nightly fmt --check: pass
  • cargo clippy --workspace --features full -- -D warnings: 0 warnings
  • cargo nextest run --config-file .github/nextest.toml --workspace --features full --lib --bins: 5160 passed

@github-actions github-actions bot added documentation Improvements or additions to documentation llm zeph-llm crate (Ollama, Claude) rust Rust code changes core zeph-core crate enhancement New feature or request size/XL Extra large PR (500+ lines) labels Mar 13, 2026
@bug-ops bug-ops enabled auto-merge (squash) March 13, 2026 13:21
#1593)

New GeminiProvider in crates/zeph-llm/src/gemini.rs:
- POST to generateContent with x-goog-api-key header (not ?key= query param)
- System prompt extracted to systemInstruction top-level field
- Role::Assistant mapped to "model" role
- Consecutive same-role message merging (Gemini requires strict alternation)
- First-message guard: prepend empty user turn if contents[0] is "model"
- JSON serialized once before retry loop (not per-attempt)
- HTTP 429 and 503 retried via shared send_with_retry()
- context_window() per model family (gemini-2.0-flash/2.5-pro/1.5-pro → 1M/2M tokens)
- last_usage() populated from usageMetadata in response
- debug_request_json() serializes actual request payload

Integration:
- ProviderKind::Gemini, GeminiConfig (api_key, model, max_tokens, base_url)
- [llm.gemini] TOML config section with commented defaults in config/default.toml
- ZEPH_GEMINI_API_KEY vault key resolution
- AnyProvider::Gemini and SubProvider::Gemini variants wired in all match blocks
- Bootstrap provider.rs: all 4 creation functions + build_orchestrator
- --init wizard: Gemini option in provider selection with api_key prompt
- instructions.rs: Gemini → AGENTS.md detection path

Also fix send_with_retry() to retry HTTP 503 (SERVICE_UNAVAILABLE) alongside 429,
benefiting all providers.

128 new tests (5032 → 5160), including 3 wiremock end-to-end HTTP tests.

Closes #1593. Part of epic #1592.
@bug-ops bug-ops merged commit c03f203 into main Mar 13, 2026
15 checks passed
@bug-ops bug-ops deleted the gemini-provider branch March 13, 2026 13:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core zeph-core crate documentation Improvements or additions to documentation enhancement New feature or request llm zeph-llm crate (Ollama, Claude) rust Rust code changes size/XL Extra large PR (500+ lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(gemini): Phase 1 -- basic chat (generateContent)

1 participant