diff --git a/src/cai/cli.py b/src/cai/cli.py index 1258b77d..a90c6c33 100644 --- a/src/cai/cli.py +++ b/src/cai/cli.py @@ -744,80 +744,28 @@ def run_cai_cli(starting_agent, context_variables=None, max_turns=float('inf'), # Use non-streamed response response = asyncio.run(Runner.run(agent, conversation_input)) - # Process the response items + # En modo no-streaming, procesamos SOLO los tool outputs de response.new_items + # Los tool calls (assistant messages) ya se añaden correctamente en openai_chatcompletions.py for item in response.new_items: - # Handle tool call output items (tool results) + # Handle ONLY tool call output items (tool results) if isinstance(item, ToolCallOutputItem): - # First, ensure there's a corresponding assistant message with tool_calls - # before adding the tool response to prevent the OpenAI error - assistant_with_tool_call_exists = False tool_call_id = item.raw_item["call_id"] - for msg in message_history: - if (msg.get("role") == "assistant" and - msg.get("tool_calls") and - any(tc.get("id") == tool_call_id for tc in msg.get("tool_calls", []))): - assistant_with_tool_call_exists = True - break + # Verificar si ya existe este tool output en message_history para evitar duplicación + tool_msg_exists = any( + msg.get("role") == "tool" and msg.get("tool_call_id") == tool_call_id + for msg in message_history + ) - # If no matching assistant message exists, create one first - if not assistant_with_tool_call_exists: - tool_call_msg = { - "role": "assistant", - "content": None, - "tool_calls": [{ - "id": tool_call_id, - "type": "function", - "function": { - "name": "unknown_function", - "arguments": "{}" - } - }] + if not tool_msg_exists: + # Añadir solo el tool output al message_history + tool_msg = { + "role": "tool", + "tool_call_id": tool_call_id, + "content": item.output, } - add_to_message_history(tool_call_msg) - - # Now add the tool response - tool_msg = { - "role": "tool", - "tool_call_id": tool_call_id, - "content": item.output, - } - add_to_message_history(tool_msg) + add_to_message_history(tool_msg) - # Make sure that assistant messages with tool calls are also added to message_history - # This is especially important for non-streaming mode - if hasattr(agent, 'model'): - # Access the _Converter directly from the OpenAIChatCompletionsModel implementation - from cai.sdk.agents.models.openai_chatcompletions import _Converter - - # Check if recent_tool_calls exists and process them - if hasattr(_Converter, 'recent_tool_calls'): - for call_id, call_info in _Converter.recent_tool_calls.items(): - # Only process new tool calls that haven't been added to message history yet - tool_call_found = False - for msg in message_history: - if (msg.get("role") == "assistant" and - msg.get("tool_calls") and - any(tc.get("id") == call_id for tc in msg.get("tool_calls", []))): - tool_call_found = True - break - - if not tool_call_found: - # Add the assistant message with the tool call - tool_call_msg = { - "role": "assistant", - "content": None, - "tool_calls": [{ - "id": call_id, - "type": "function", - "function": { - "name": call_info.get('name', ''), - "arguments": call_info.get('arguments', '{}') - } - }] - } - add_to_message_history(tool_call_msg) - # Final validation to ensure message history follows OpenAI's requirements # Ensure every tool message has a preceding assistant message with matching tool_call_id from cai.util import fix_message_list diff --git a/src/cai/sdk/agents/models/openai_chatcompletions.py b/src/cai/sdk/agents/models/openai_chatcompletions.py index 2d7cdca4..777d590b 100644 --- a/src/cai/sdk/agents/models/openai_chatcompletions.py +++ b/src/cai/sdk/agents/models/openai_chatcompletions.py @@ -656,6 +656,29 @@ class OpenAIChatCompletionsModel(Model): # Log the assistant message self.logger.log_assistant_message(assistant_msg.content) + # En no-streaming, también necesitamos añadir cualquier tool output al message_history + # Esto se hace procesando los items de output del ModelResponse + items = _Converter.message_to_output_items(response.choices[0].message) + + # Además, necesitamos añadir los tool outputs que se hayan generado + # durante la ejecución de las herramientas + if hasattr(_Converter, 'tool_outputs'): + for call_id, output_content in _Converter.tool_outputs.items(): + # Verificar si ya existe un mensaje tool con este call_id en message_history + tool_msg_exists = any( + msg.get("role") == "tool" and msg.get("tool_call_id") == call_id + for msg in message_history + ) + + if not tool_msg_exists: + # Añadir el mensaje tool al message_history + tool_msg = { + "role": "tool", + "tool_call_id": call_id, + "content": output_content + } + add_to_message_history(tool_msg) + # Log the complete response for the session self.logger.rec_training_data( {