From 472df045d366217e23d7cf6eddd0b4690930f353 Mon Sep 17 00:00:00 2001 From: Fan Date: Tue, 26 Aug 2025 17:01:09 +0800 Subject: [PATCH] Fix parallel tool use (#400) --- .../core/src/core/openaiContentGenerator.ts | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/packages/core/src/core/openaiContentGenerator.ts b/packages/core/src/core/openaiContentGenerator.ts index 8f05f2e0..be681b0a 100644 --- a/packages/core/src/core/openaiContentGenerator.ts +++ b/packages/core/src/core/openaiContentGenerator.ts @@ -1351,7 +1351,9 @@ export class OpenAIContentGenerator implements ContentGenerator { // Handle text content if (choice.delta?.content) { - parts.push({ text: choice.delta.content }); + if (typeof choice.delta.content === 'string') { + parts.push({ text: choice.delta.content }); + } } // Handle tool calls - only accumulate during streaming, emit when complete @@ -1371,10 +1373,36 @@ export class OpenAIContentGenerator implements ContentGenerator { accumulatedCall.id = toolCall.id; } if (toolCall.function?.name) { + // If this is a new function name, reset the arguments + if (accumulatedCall.name !== toolCall.function.name) { + accumulatedCall.arguments = ''; + } accumulatedCall.name = toolCall.function.name; } if (toolCall.function?.arguments) { - accumulatedCall.arguments += toolCall.function.arguments; + // Check if we already have a complete JSON object + const currentArgs = accumulatedCall.arguments; + const newArgs = toolCall.function.arguments; + + // If current arguments already form a complete JSON and new arguments start a new object, + // this indicates a new tool call with the same name + let shouldReset = false; + if (currentArgs && newArgs.trim().startsWith('{')) { + try { + JSON.parse(currentArgs); + // If we can parse current arguments as complete JSON and new args start with {, + // this is likely a new tool call + shouldReset = true; + } catch { + // Current arguments are not complete JSON, continue accumulating + } + } + + if (shouldReset) { + accumulatedCall.arguments = newArgs; + } else { + accumulatedCall.arguments += newArgs; + } } } } @@ -1562,7 +1590,7 @@ export class OpenAIContentGenerator implements ContentGenerator { } } - messageContent = textParts.join(''); + messageContent = textParts.join('').trimEnd(); } const choice: OpenAIChoice = {