Skip to content

Commit c45f6d3

Browse files
committed
fix Gemini 3 function call
1 parent 537511c commit c45f6d3

File tree

3 files changed

+9
-12
lines changed

3 files changed

+9
-12
lines changed

src/Providers/Gemini/Gemini.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ protected function createToolCallMessage(array $message): Message
9696
return null;
9797
}
9898

99+
// https://ai.google.dev/gemini-api/docs/thought-signatures
99100
if ($item['thoughtSignature'] ?? false) {
100101
$signature = $item['thoughtSignature'];
101102
}
@@ -106,7 +107,7 @@ protected function createToolCallMessage(array $message): Message
106107
->setCallId($item['functionCall']['name']);
107108
}, $message['parts']);
108109

109-
// array_values() reindexes so tools are always a 0-based sequential array,
110+
// array_values() reindex so tools are always a 0-based sequential array,
110111
// even when text/thought parts precede functionCall parts.
111112
$result = new ToolCallMessage(
112113
$message['content'] ?? null,

src/Providers/Gemini/HandleChat.php

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
use function json_encode;
2222
use function trim;
2323
use function str_starts_with;
24+
use function array_filter;
25+
use function count;
2426

2527
trait HandleChat
2628
{
@@ -93,16 +95,9 @@ public function chatAsync(array $messages): PromiseInterface
9395

9496
$parts = $content['parts'];
9597

96-
// Scan ALL parts for functionCall, not just parts[0].
97-
// Gemini 3 models may return text or thought parts before functionCall parts.
98-
// See https://ai.google.dev/gemini-api/docs/thought-signatures
99-
$hasFunctionCall = false;
100-
foreach ($parts as $part) {
101-
if (array_key_exists('functionCall', $part) && !empty($part['functionCall'])) {
102-
$hasFunctionCall = true;
103-
break;
104-
}
105-
}
98+
$hasFunctionCall = count(
99+
array_filter($parts, fn (array $part): bool => !empty($part['functionCall'] ?? null))
100+
) > 0;
106101

107102
if ($hasFunctionCall) {
108103
$response = $this->createToolCallMessage($content);

tests/Providers/GeminiTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use NeuronAI\Providers\Gemini\Gemini;
1919
use NeuronAI\Tools\PropertyType;
2020
use NeuronAI\Tools\Tool;
21+
use NeuronAI\Tools\ToolInterface;
2122
use NeuronAI\Tools\ToolProperty;
2223
use PHPUnit\Framework\TestCase;
2324

@@ -538,7 +539,7 @@ public function test_function_call_with_thought_signature(): void
538539
$this->assertSame('sig-abc123', $response->getMetadata('thoughtSignature'));
539540
}
540541

541-
private function makeSimpleTool(string $name): Tool
542+
private function makeSimpleTool(string $name): ToolInterface
542543
{
543544
return Tool::make($name, "A test tool called {$name}.")
544545
->addProperty(new ToolProperty('prop', PropertyType::STRING, 'A test property', true))

0 commit comments

Comments
 (0)