diff --git a/src/converters/strategies/GeminiConverter.js b/src/converters/strategies/GeminiConverter.js index 0ae394a..41a9d06 100644 --- a/src/converters/strategies/GeminiConverter.js +++ b/src/converters/strategies/GeminiConverter.js @@ -232,6 +232,11 @@ export class GeminiConverter extends BaseConverter { candidate.finishReason.toLowerCase(); } + // 如果包含工具调用,且完成原因为 stop,则将完成原因修改为 tool_calls + if (toolCalls.length > 0 && finishReason === 'stop') { + finishReason = 'tool_calls'; + } + // 构建delta对象 const delta = {}; if (content) delta.content = content; diff --git a/tests/gemini-converter.test.js b/tests/gemini-converter.test.js index 466b562..aac0168 100644 --- a/tests/gemini-converter.test.js +++ b/tests/gemini-converter.test.js @@ -66,4 +66,25 @@ describe('GeminiConverter', () => { expect(result.choices[0].delta.tool_calls[1].index).toBe(1); expect(result.choices[0].delta.tool_calls[1].function.name).toBe('tool_two'); }); + + test('toOpenAIStreamChunk sets finish_reason to tool_calls when tool calls are present and finishReason is STOP', () => { + const geminiChunk = { + candidates: [{ + finishReason: 'STOP', + content: { + parts: [{ + functionCall: { + name: 'test_tool', + args: {} + } + }] + } + }] + }; + + const result = converter.toOpenAIStreamChunk(geminiChunk, 'gemini-pro'); + + expect(result).not.toBeNull(); + expect(result.choices[0].finish_reason).toBe('tool_calls'); + }); });