Skip to content

Add tool/function calling support for Google Gemini adapter#147

Merged
wachterjohannes merged 1 commit into
0.4from
feature/google-gemini-tool-support
Jun 1, 2026
Merged

Add tool/function calling support for Google Gemini adapter#147
wachterjohannes merged 1 commit into
0.4from
feature/google-gemini-tool-support

Conversation

@wachterjohannes

@wachterjohannes wachterjohannes commented Feb 11, 2026

Copy link
Copy Markdown
Member

This commit implements tool support for the Google Gemini adapter, preparing it for function calling capabilities once the SDK adds support.

Changes:

  • Add ToolFormatter class to convert ToolInfo to Google Gemini's function declaration format with UPPERCASE types
  • Update GoogleGeminiChatAdapter to handle ToolCallsPart and ToolCallPart message types
  • Add extractToolCalls method for parsing function calls from responses
  • Add comprehensive test suite with 11 test cases covering all parameter types and edge cases
  • Update PHPStan baseline for test-related type issues
  • Update composer dependencies to include latest chat package

Note: The current Google Gemini PHP SDK (v1.0.15) does not yet support function calling. User warnings are triggered when tools are used until SDK support is available. The implementation is ready and will work immediately once the SDK is updated.

Summary by CodeRabbit

  • New Features

    • Google Gemini adapter now supports tool-call messages and returns tool-call data alongside assistant text.
    • Added tool formatting so tool definitions and parameters are translated for Gemini requests.
  • Tests

    • Added comprehensive tests for tool formatting and adapter tool-call handling, including nested structures, arrays, enums, and error cases.
  • Chores

    • Updated static analysis baseline to account for new test cases and suppressions.

@coderabbitai

coderabbitai Bot commented Feb 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b5050784-a1b0-47b2-b2ab-193e8009712b

📥 Commits

Reviewing files that changed from the base of the PR and between 5bfc317 and 587c9e1.

📒 Files selected for processing (5)
  • packages/google-gemini-adapter/phpstan-baseline.neon
  • packages/google-gemini-adapter/src/Chat/GoogleGeminiChatAdapter.php
  • packages/google-gemini-adapter/src/Chat/ToolFormatter.php
  • packages/google-gemini-adapter/tests/Unit/Chat/GoogleGeminiChatAdapterTest.php
  • packages/google-gemini-adapter/tests/Unit/Chat/ToolFormatterTest.php
✅ Files skipped from review due to trivial changes (1)
  • packages/google-gemini-adapter/phpstan-baseline.neon
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/google-gemini-adapter/tests/Unit/Chat/ToolFormatterTest.php

Walkthrough

Adds ToolFormatter, integrates tool-call serialization and extraction into GoogleGeminiChatAdapter (request and streaming paths), expands EXPECTED_ROLES to include TOOL, updates PHPStan baseline, and adds unit tests covering formatting and adapter tool-call behavior.

Changes

Gemini tool-call support

Layer / File(s) Summary
PHPStan baseline updates
packages/google-gemini-adapter/phpstan-baseline.neon
Extended ignore rules and increased suppression counts for method/offset/property warnings in GoogleGeminiChatAdapterTest.php.
ToolFormatter implementation
packages/google-gemini-adapter/src/Chat/ToolFormatter.php
Added ToolFormatter with formatTools()/formatTool() and parameter→Gemini Schema mapping plus helpers convertType, convertFormat, convertEnum.
ToolFormatter unit tests
packages/google-gemini-adapter/tests/Unit/Chat/ToolFormatterTest.php
Added comprehensive PHPUnit tests for tool formatting: single/multiple tools, nested objects, arrays (primitives/objects), nullable, enums, formats, and invalid-parameter exceptions.
Chat adapter: imports and request serialization
packages/google-gemini-adapter/src/Chat/GoogleGeminiChatAdapter.php
Expanded imports, added AIChatMessageRoleEnum::TOOL support, serialize ToolCallsPartfunctionCall and ToolCallPartfunctionResponse, and configure Gemini ToolConfig when tools are present.
Chat adapter: response parsing and streaming
packages/google-gemini-adapter/src/Chat/GoogleGeminiChatAdapter.php
Added extractToolCalls() and extractText() helpers, include $toolCalls in AIChatResponseMessage for both create() and streaming createStreamedMessages().
Adapter unit tests for tool calls
packages/google-gemini-adapter/tests/Unit/Chat/GoogleGeminiChatAdapterTest.php
Added tests for parsing functionCall parts into AIChatToolCall and for serializing request parts into FunctionCall/FunctionResponse with correct role mappings and ids.

Sequence Diagram

sequenceDiagram
  participant Client
  participant GoogleGeminiChatAdapter
  participant ToolFormatter
  participant GoogleGeminiAPI
  participant ResponseBuilder

  Client->>GoogleGeminiChatAdapter: create(request with tools)
  GoogleGeminiChatAdapter->>ToolFormatter: formatTools(tools)
  ToolFormatter-->>GoogleGeminiChatAdapter: formatted functionDeclarations
  GoogleGeminiChatAdapter->>GoogleGeminiAPI: generateContent(request with tools)
  GoogleGeminiAPI-->>GoogleGeminiChatAdapter: GenerateContentResponse (parts)
  GoogleGeminiChatAdapter->>GoogleGeminiChatAdapter: extractToolCalls(response)
  GoogleGeminiChatAdapter->>ResponseBuilder: build AIChatResponseMessage(text, toolCalls)
  ResponseBuilder-->>Client: AIChatResponseMessage (including tool calls)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • modelflow-ai/.github#145: Overlapping modifications to tool-parameter formatting and parameter schema handling for nested, nullable, and required fields.

Poem

🐰 I hop with joy, a carrot in hand,

Tools mapped to Gemini across the land,
Functions and schemas now neatly arrayed,
Tests to confirm each parameter's parade,
Hop, hop — the adapter and formatter played.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately describes the main change: adding tool/function calling support for the Google Gemini adapter, which is the primary objective across all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/google-gemini-tool-support

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@packages/google-gemini-adapter/src/Chat/ToolFormatter.php`:
- Around line 158-164: The checks for $parameter->enum and $parameter->format
use loose truthy checks; update them to strict comparisons (e.g., !== null and
!== [] as appropriate) so that in the ToolFormatter logic you only set
$param['enum'] and $param['format'] when the parameter properties are explicitly
present—locate the code in ToolFormatter.php where $parameter->enum and
$parameter->format are inspected and replace the if ($parameter->enum) / if
($parameter->format) conditions with strict non-null/empty checks (referencing
the $parameter variable and $param array in that block).
🧹 Nitpick comments (4)
packages/google-gemini-adapter/src/Chat/GoogleGeminiChatAdapter.php (2)

80-87: TODO comments have misleading indentation.

Lines 82-83 and 86-87 are logically inside their respective elseif branches but are flush-left, which makes them look like they sit between the branches rather than inside them. This could confuse future contributors trying to understand the control flow.

🔧 Indent the TODO comments to match their enclosing block
             } elseif ($part instanceof ToolCallsPart) {
                 @\trigger_error('Tool calls are not yet supported by the Google Gemini PHP SDK. Tool calls will be ignored.', \E_USER_WARNING);
-            // TODO: Implement when SDK supports function calls
-            // Format: ['functionCall' => ['name' => $tool->name, 'args' => $tool->arguments]]
+                // TODO: Implement when SDK supports function calls
+                // Format: ['functionCall' => ['name' => $tool->name, 'args' => $tool->arguments]]
             } elseif ($part instanceof ToolCallPart) {
                 @\trigger_error('Tool call results are not yet supported by the Google Gemini PHP SDK. Tool results will be ignored.', \E_USER_WARNING);
-            // TODO: Implement when SDK supports function responses
-            // Format: ['functionResponse' => ['name' => $part->toolName, 'response' => ['content' => $part->content]]]
+                // TODO: Implement when SDK supports function responses
+                // Format: ['functionResponse' => ['name' => $part->toolName, 'response' => ['content' => $part->content]]]

162-177: Suppress PHPMD warning for the intentionally unused $result parameter.

PHPMD flags $result as unused (static analysis hint confirms). Since this is a deliberate placeholder for future SDK support, consider suppressing the warning to keep the baseline clean.

🔧 Add SuppressWarnings annotation
     /**
      * Extract tool calls from the response.
      *
      * `@return` AIChatToolCall[]
+     *
+     * `@SuppressWarnings`(PHPMD.UnusedFormalParameter)
      */
     private function extractToolCalls(GenerateContentResponse $result): array
packages/google-gemini-adapter/src/Chat/ToolFormatter.php (2)

111-143: Use specific exception classes instead of generic \Exception.

The coding guidelines require exception hierarchies with specific exception classes. Lines 113 and 142 throw generic \Exception. Consider creating an InvalidParameterException or using \InvalidArgumentException which better describes the error condition (invalid input configuration).

Proposed fix
-                throw new \Exception('Array type parameter must have items description. Define a type or use the Parameter class for object.');
+                throw new \InvalidArgumentException('Array type parameter must have items description. Define a type or use the Parameter class for object.');
-                throw new \Exception('Object type parameter must have properties description. You need to pass an array of Parameter.');
+                throw new \InvalidArgumentException('Object type parameter must have properties description. You need to pass an array of Parameter.');

Note: The test expectations in ToolFormatterTest.php (lines 287 and 305) would also need updating to expect \InvalidArgumentException. As per coding guidelines: "Use exception hierarchies with specific exception classes for error handling."


174-181: Silent fallback to STRING for unknown types may mask bugs.

The default => 'STRING' branch silently converts any unrecognized type (e.g., number, float) to STRING. Consider throwing an exception for unmapped types to surface configuration errors early, or at minimum add 'number' => 'NUMBER' since it's a common JSON Schema type.

Comment thread packages/google-gemini-adapter/src/Chat/ToolFormatter.php Outdated
Implement function calling against the Google Gemini PHP SDK on top of the
structured-output support from #148:

- ToolFormatter converts ToolInfo into typed Gemini\Data\Tool /
  FunctionDeclaration / Schema objects (correct nullable handling via the
  Schema nullable flag, NUMBER type, and dropping formats Gemini rejects).
- GoogleGeminiChatAdapter sends tools via withTool/withToolConfig, maps
  ToolCallsPart/ToolCallPart to functionCall/functionResponse parts,
  accepts the TOOL role (mapped to the Gemini user role), and parses
  functionCall parts from responses into AIChatToolCall.
- Tool calls are extracted before reading text, so function-call responses
  no longer trip the single-part text() accessor and get misreported as
  blocked by safety settings.
- Add unit tests for the typed formatter output and the tool round-trip.
@wachterjohannes wachterjohannes force-pushed the feature/google-gemini-tool-support branch from 5bfc317 to 587c9e1 Compare June 1, 2026 16:08
@wachterjohannes wachterjohannes merged commit 43fdedb into 0.4 Jun 1, 2026
86 checks passed
@wachterjohannes wachterjohannes deleted the feature/google-gemini-tool-support branch June 1, 2026 16:53
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.

1 participant