Skip to content

Add gemini_api_chat flavor, parts passthrough, and tests - #12

Merged
mlennie merged 5 commits into
mainfrom
monty/gemini-api-chat-flavor
Feb 13, 2026
Merged

Add gemini_api_chat flavor, parts passthrough, and tests #12
mlennie merged 5 commits into
mainfrom
monty/gemini-api-chat-flavor

Conversation

@mlennie

@mlennie mlennie commented Feb 10, 2026

Copy link
Copy Markdown
Contributor

Main PR: https://github.com/freeplayai/freeplay-app/pull/1434

Summary by CodeRabbit

Release Notes

  • New Features

    • Added new Gemini API flavor (gemini_api_chat) returning plain-dict tool schemas compatible with google.generativeai library.
    • Added passthrough support for pre-formatted Gemini messages; history messages with existing Gemini format are preserved without re-wrapping, and assistant roles are automatically translated to model roles.
  • Chores

    • Version bumped to 0.5.7.

@macroscopeapp

macroscopeapp Bot commented Feb 10, 2026

Copy link
Copy Markdown

Add gemini_api_chat flavor and pass through Gemini parts messages in GeminiAdapter.to_llm_syntax with assistant role mapped to model

Introduce a new gemini_api_chat flavor, route it to GeminiAdapter, pass through pre-formatted Gemini parts without mutation or rewrap, and format tool schemas as Gemini functionDeclarations for this flavor. Version is bumped to 0.5.7 and tests cover adapter passthrough, role translation, and tool schema formatting.

📍Where to Start

Start with GeminiAdapter.to_llm_syntax in adapters.py, then review BoundPrompt.__format_tool_schema in prompts.py.


Macroscope summarized 73490a1.

- test_prompt_format__history_gemini: full bind→format flow with
  Gemini-format history containing function call/response cycle
- test_prompt_format__history_gemini_with_media: full bind→format
  flow with history containing inlineData parts
- test_gemini_media_in_history_parts: adapter-level test for
  inlineData parts passthrough mixed with standard content messages
- test_prompt_format__history_gemini: full bind→format flow with
  Gemini-format history containing function call/response cycle
- test_prompt_format__history_gemini_with_media: full bind→format
  flow with history containing inlineData parts
- test_gemini_media_in_history_parts: adapter-level test for
  inlineData parts passthrough mixed with standard content messages
- Include type annotation fix for GeminiAdapter.gemini_messages
@mlennie
mlennie marked this pull request as ready for review February 13, 2026 19:04
@macroscopeapp

macroscopeapp Bot commented Feb 13, 2026

Copy link
Copy Markdown

Add gemini_api_chat flavor and pass through Gemini parts messages in GeminiAdapter.to_llm_syntax with assistant role mapped to model

Introduce a new gemini_api_chat flavor, route it to GeminiAdapter, pass through pre-formatted Gemini parts without mutation or rewrap, and format tool schemas as Gemini functionDeclarations for this flavor. Version is bumped to 0.5.7 and tests cover adapter passthrough, role translation, and tool schema formatting.

📍Where to Start

Start with GeminiAdapter.to_llm_syntax in adapters.py, then review BoundPrompt.__format_tool_schema in prompts.py.

Changes since #12 opened

  • Fixed type errors in freeplay.resources.adapters.GeminiAdapter.to_llm_syntax by adding type annotations and introducing typed local variables for deep-copied messages, enabling passthrough of 'parts' fields and supporting fallback message handling without changing transformation logic [4c5c4e1]
  • Consolidated non-supported content handling in freeplay.resources.adapters.GeminiAdapter.__map_content to raise a single ValueError for any content type that is not TextContent or MediaContentBase64, specifically indicating that image URLs are not supported by Gemini [4c5c4e1]
  • Added test test_gemini_media_in_history_parts in tests.test_adapters module to verify passthrough of inlineData parts and conversion of standard content to Gemini format in history [4c5c4e1]
  • Added tests test_prompt_format__history_gemini and test_prompt_format__history_gemini_with_media in tests.test_freeplay module to cover full bind-to-format flow for Gemini history with function calls, responses, and inline media [4c5c4e1]
  • Renamed local variable from 'formatted' to 'result' across multiple tests in tests.test_adapters module and added explicit type assertions using assert isinstance(result, list) to improve test clarity [4c5c4e1]

Macroscope summarized 73490a1.

@coderabbitai

coderabbitai Bot commented Feb 13, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR adds a new gemini_api_chat flavor alongside the existing gemini_chat flavor, enabling integration with the google.generativeai SDK. It introduces passthrough handling for pre-formatted Gemini messages containing parts fields, with automatic role translation from "assistant" to "model". Tool schema generation is extended to support both flavors with appropriate formatting.

Changes

Cohort / File(s) Summary
Version & Type Baseline
pyproject.toml, scripts/type-baseline/pyright-baseline.json
Version bump from 0.5.6 to 0.5.7 and removal of outdated Pyright diagnostics related to adapters.py.
Gemini Adapter & Prompts
src/freeplay/resources/adapters.py, src/freeplay/resources/prompts.py
Added gemini_api_chat flavor support. GeminiAdapter now detects and passes through pre-formatted messages with parts field while translating assistant roles to model. Simplified content mapping branching for MediaContentUrl. Tool schema formatting extended to build plain-dict declarations for gemini_api_chat.
Tests
tests/test_adapters.py, tests/test_freeplay.py
Comprehensive test coverage for message passthrough behavior, parts preservation, role translation, and gemini_api_chat tool schema formatting. New public exports: MissingFlavorError and adaptor_for_flavor.
Documentation
CHANGELOG.md
Updated changelog documenting new Gemini API flavor and message passthrough capabilities.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A new Gemini flavor hops into view,
Parts passthrough dancing in rabbit-y hue,
Assistant roles transform to model with grace,
Tool schemas shift—plain dicts take their place,
API compatibility finds its true home!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: introducing a new gemini_api_chat flavor, implementing parts passthrough functionality, and adding comprehensive tests.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch monty/gemini-api-chat-flavor

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
src/freeplay/resources/adapters.py (2)

212-212: Consider simplifying the key check (Ruff RUF019).

Static analysis flags the "has_media" in message and message["has_media"] pattern as a redundant key check before dict access. This could be simplified to message.get("has_media").

Note: the same pattern exists in the other adapters (AnthropicAdapter, OpenAIAdapter), so this could be deferred to a follow-up cleanup.

♻️ Proposed fix
-            elif "has_media" in message and message["has_media"]:
+            elif message.get("has_media"):

248-252: Collapsing MediaContentUrl into the else branch is fine, but the error message is narrow.

The error says "image URL" specifically, but MediaContentUrl could also carry file/audio/video URLs. This is a pre-existing issue with the message text and not a regression from this PR.

tests/test_freeplay.py (1)

1272-1282: Consider extracting the repeated gemini_api_prompt_info to setUp().

The same PromptInfo with flavor_name="gemini_api_chat" is constructed identically in three tests. Other flavors (OpenAI, Anthropic, etc.) are already defined once in setUp().

♻️ Example: add to setUp()
# In setUp(), alongside other prompt_info definitions:
self.gemini_api_prompt_info = PromptInfo(
    prompt_template_id=str(uuid.uuid4()),
    prompt_template_version_id=str(uuid.uuid4()),
    template_name="template-name",
    environment="environment",
    model_parameters=LLMParameters({}),
    provider_info=None,
    provider="gemini",
    model="gemini-2.0-flash",
    flavor_name="gemini_api_chat",
)

Also applies to: 1361-1371, 1638-1648


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

- Type-annotate msg_copy from copy.deepcopy() in GeminiAdapter
- Remove unnecessary isinstance check in __map_content
- Regenerate baseline (49 → 44 errors)
@mlennie
mlennie merged commit 009308c into main Feb 13, 2026
5 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