diff --git a/src/api/providers/openai-codex.ts b/src/api/providers/openai-codex.ts index 7ca49eb5a9..bdb06c5ef5 100644 --- a/src/api/providers/openai-codex.ts +++ b/src/api/providers/openai-codex.ts @@ -925,22 +925,12 @@ export class OpenAiCodexHandler extends BaseProvider implements SingleCompletion } } - // Only handle tool/function calls from done events (to ensure arguments are complete) - if ( - (item.type === "function_call" || item.type === "tool_call") && - event.type === "response.output_item.done" - ) { - const callId = item.call_id || item.tool_call_id || item.id - if (callId) { - const args = item.arguments || item.function?.arguments || item.function_arguments - yield { - type: "tool_call", - id: callId, - name: item.name || item.function?.name || item.function_name || "", - arguments: typeof args === "string" ? args : "{}", - } - } - } + // Note: We intentionally do NOT emit tool_call from response.output_item.done + // for function_call/tool_call items. The streaming path handles tool calls via: + // 1. tool_call_partial events during argument deltas + // 2. NativeToolCallParser.finalizeRawChunks() at stream end emitting tool_call_end + // 3. NativeToolCallParser.finalizeStreamingToolCall() creating the final ToolUse + // Emitting tool_call here would cause duplicate tool rendering. } return } diff --git a/src/api/providers/openai-native.ts b/src/api/providers/openai-native.ts index 5719995dd6..82f55c02d8 100644 --- a/src/api/providers/openai-native.ts +++ b/src/api/providers/openai-native.ts @@ -1241,24 +1241,12 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio } } - // Only handle tool/function calls from done events (to ensure arguments are complete) - if ( - (item.type === "function_call" || item.type === "tool_call") && - event.type === "response.output_item.done" - ) { - // Handle complete tool/function call item - // Emit as tool_call for backward compatibility with non-streaming tool handling - const callId = item.call_id || item.tool_call_id || item.id - if (callId) { - const args = item.arguments || item.function?.arguments || item.function_arguments - yield { - type: "tool_call", - id: callId, - name: item.name || item.function?.name || item.function_name || "", - arguments: typeof args === "string" ? args : "{}", - } - } - } + // Note: We intentionally do NOT emit tool_call from response.output_item.done + // for function_call/tool_call items. The streaming path handles tool calls via: + // 1. tool_call_partial events during argument deltas + // 2. NativeToolCallParser.finalizeRawChunks() at stream end emitting tool_call_end + // 3. NativeToolCallParser.finalizeStreamingToolCall() creating the final ToolUse + // Emitting tool_call here would cause duplicate tool rendering. } return }