diff --git a/src/platform/src/Bridge/Gemini/Gemini/ResultConverter.php b/src/platform/src/Bridge/Gemini/Gemini/ResultConverter.php index d69999378..89574d16d 100644 --- a/src/platform/src/Bridge/Gemini/Gemini/ResultConverter.php +++ b/src/platform/src/Bridge/Gemini/Gemini/ResultConverter.php @@ -146,11 +146,20 @@ private function convertChoice(array $choice): ToolCallResult|TextResult|BinaryR } } + // Fallback for multi-part text responses (e.g., thinking + response) + if ('' === $content) { + foreach ($contentParts as $contentPart) { + if (isset($contentPart['text'])) { + $content .= $contentPart['text']; + } + } + } + if ('' !== $content) { return new TextResult($content); } - throw new RuntimeException('Code execution failed.'); + throw new RuntimeException('Response does not contain any text content.'); } /** diff --git a/src/platform/tests/Bridge/Gemini/Gemini/ResultConverterTest.php b/src/platform/tests/Bridge/Gemini/Gemini/ResultConverterTest.php index 846d115c9..d8ff47d18 100644 --- a/src/platform/tests/Bridge/Gemini/Gemini/ResultConverterTest.php +++ b/src/platform/tests/Bridge/Gemini/Gemini/ResultConverterTest.php @@ -16,6 +16,7 @@ use Symfony\AI\Platform\Exception\RuntimeException; use Symfony\AI\Platform\Result\BinaryResult; use Symfony\AI\Platform\Result\RawHttpResult; +use Symfony\AI\Platform\Result\TextResult; use Symfony\AI\Platform\Result\ToolCall; use Symfony\AI\Platform\Result\ToolCallResult; use Symfony\Contracts\HttpClient\ResponseInterface; @@ -132,4 +133,36 @@ public function testConvertsInlineDataWithoutMimeTypeToBinaryResult() $this->assertSame('base64EncodedData', $result->getContent()); $this->assertNull($result->getMimeType()); } + + public function testConvertsMultiPartThinkingResponseToTextResult() + { + $converter = new ResultConverter(); + $httpResponse = self::createMock(ResponseInterface::class); + $httpResponse->method('getStatusCode')->willReturn(200); + $httpResponse->method('toArray')->willReturn([ + 'candidates' => [ + [ + 'content' => [ + 'parts' => [ + [ + 'text' => 'This is the thinking process...', + 'thoughtSignature' => 'base64-encoded-signature...', + ], + [ + 'text' => '```json\n{"result": "actual response"}\n```', + ], + ], + ], + 'finishReason' => 'STOP', + ], + ], + ]); + + $result = $converter->convert(new RawHttpResult($httpResponse)); + $this->assertInstanceOf(TextResult::class, $result); + $this->assertSame( + 'This is the thinking process...```json\n{"result": "actual response"}\n```', + $result->getContent() + ); + } }