diff --git a/backend/agent/run.py b/backend/agent/run.py index 820e0447..404c8428 100644 --- a/backend/agent/run.py +++ b/backend/agent/run.py @@ -114,81 +114,7 @@ async def test_agent(): if not user_message.strip(): print("\nšŸ”„ Running agent...\n") - - chunk_counter = 0 - current_response = "" - tool_call_counter = 0 # Track number of tool calls - - async for chunk in run_agent(thread_id=thread_id, stream=True, thread_manager=thread_manager, native_max_auto_continues=25): - chunk_counter += 1 - - if chunk.get('type') == 'content' and 'content' in chunk: - current_response += chunk.get('content', '') - # Print the response as it comes in - print(chunk.get('content', ''), end='', flush=True) - elif chunk.get('type') == 'tool_result': - # Add timestamp and format tool result nicely - tool_name = chunk.get('function_name', 'Tool') - result = chunk.get('result', '') - print(f"\n\nšŸ› ļø TOOL RESULT [{tool_name}] → {result}") - elif chunk.get('type') == 'tool_call': - # Display native tool call chunks as they arrive - tool_call = chunk.get('tool_call', {}) - - # Check if it's a meaningful part of the tool call to display - args = tool_call.get('function', {}).get('arguments', '') - - # Only show when we have substantial arguments or a function name - should_display = ( - len(args) > 3 or # More than just '{}' - tool_call.get('function', {}).get('name') # Or we have a name - ) - - if should_display: - tool_call_counter += 1 - tool_name = tool_call.get('function', {}).get('name', 'Building...') - - # Print tool call header with counter and tool name - print(f"\nšŸ”§ TOOL CALL #{tool_call_counter} [{tool_name}]") - - # Try to parse and pretty print the arguments if they're JSON - try: - # Check if it's complete JSON or just a fragment - if args.strip().startswith('{') and args.strip().endswith('}'): - args_obj = json.loads(args) - # Only print non-empty args to reduce clutter - if args_obj and args_obj != {}: - # Format JSON with nice indentation and color indicators for readability - print(f" ARGS: {json.dumps(args_obj, indent=2)}") - else: - # Only print if there's actual content to show - if args.strip(): - print(f" ARGS: {args}") - except json.JSONDecodeError: - if args.strip(): - print(f" ARGS: {args}") - - # Add a separator for visual clarity - print(" " + "-" * 40) - - # Return to the current content display - if current_response: - print("\nContinuing response:", flush=True) - print(current_response, end='', flush=True) - elif chunk.get('type') == 'tool_status': - # Log tool status changes - status = chunk.get('status', '') - function_name = chunk.get('function_name', '') - if status and function_name: - status_emoji = "āœ…" if status == "completed" else "ā³" if status == "started" else "āŒ" - print(f"\n{status_emoji} TOOL {status.upper()}: {function_name}") - elif chunk.get('type') == 'finish': - # Just log finish reason to console but don't show to user - finish_reason = chunk.get('finish_reason', '') - if finish_reason: - print(f"\nšŸ“Œ Finished: {finish_reason}") - - print(f"\n\nāœ… Agent run completed with {tool_call_counter} tool calls") + await process_agent_response(thread_id, thread_manager) continue # Add the user message to the thread @@ -203,84 +129,87 @@ async def test_agent(): ) print("\nšŸ”„ Running agent...\n") - - chunk_counter = 0 - current_response = "" - tool_call_counter = 0 # Track number of tool calls - - async for chunk in run_agent(thread_id=thread_id, stream=True, thread_manager=thread_manager, native_max_auto_continues=25): - chunk_counter += 1 - - if chunk.get('type') == 'content' and 'content' in chunk: - current_response += chunk.get('content', '') - # Print the response as it comes in - print(chunk.get('content', ''), end='', flush=True) - elif chunk.get('type') == 'tool_result': - # Add timestamp and format tool result nicely - tool_name = chunk.get('function_name', 'Tool') - result = chunk.get('result', '') - print(f"\n\nšŸ› ļø TOOL RESULT [{tool_name}] → {result}") - elif chunk.get('type') == 'tool_call': - # Display native tool call chunks as they arrive - tool_call = chunk.get('tool_call', {}) - - # Check if it's a meaningful part of the tool call to display - args = tool_call.get('function', {}).get('arguments', '') - - # Only show when we have substantial arguments or a function name - should_display = ( - len(args) > 3 or # More than just '{}' - tool_call.get('function', {}).get('name') # Or we have a name - ) - - if should_display: - tool_call_counter += 1 - tool_name = tool_call.get('function', {}).get('name', 'Building...') - - # Print tool call header with counter and tool name - print(f"\nšŸ”§ TOOL CALL #{tool_call_counter} [{tool_name}]") - - # Try to parse and pretty print the arguments if they're JSON - try: - # Check if it's complete JSON or just a fragment - if args.strip().startswith('{') and args.strip().endswith('}'): - args_obj = json.loads(args) - # Only print non-empty args to reduce clutter - if args_obj and args_obj != {}: - # Format JSON with nice indentation and color indicators for readability - print(f" ARGS: {json.dumps(args_obj, indent=2)}") - else: - # Only print if there's actual content to show - if args.strip(): - print(f" ARGS: {args}") - except json.JSONDecodeError: - if args.strip(): - print(f" ARGS: {args}") - - # Add a separator for visual clarity - print(" " + "-" * 40) - - # Return to the current content display - if current_response: - print("\nContinuing response:", flush=True) - print(current_response, end='', flush=True) - elif chunk.get('type') == 'tool_status': - # Log tool status changes - status = chunk.get('status', '') - function_name = chunk.get('function_name', '') - if status and function_name: - status_emoji = "āœ…" if status == "completed" else "ā³" if status == "started" else "āŒ" - print(f"\n{status_emoji} TOOL {status.upper()}: {function_name}") - elif chunk.get('type') == 'finish': - # Just log finish reason to console but don't show to user - finish_reason = chunk.get('finish_reason', '') - if finish_reason: - print(f"\nšŸ“Œ Finished: {finish_reason}") - - print(f"\n\nāœ… Agent run completed with {tool_call_counter} tool calls") + await process_agent_response(thread_id, thread_manager) print("\nšŸ‘‹ Test completed. Goodbye!") +async def process_agent_response(thread_id: str, thread_manager: ThreadManager): + """Process the streaming response from the agent.""" + chunk_counter = 0 + current_response = "" + tool_call_counter = 0 # Track number of tool calls + + async for chunk in run_agent(thread_id=thread_id, stream=True, thread_manager=thread_manager, native_max_auto_continues=25): + chunk_counter += 1 + + if chunk.get('type') == 'content' and 'content' in chunk: + current_response += chunk.get('content', '') + # Print the response as it comes in + print(chunk.get('content', ''), end='', flush=True) + elif chunk.get('type') == 'tool_result': + # Add timestamp and format tool result nicely + tool_name = chunk.get('function_name', 'Tool') + result = chunk.get('result', '') + print(f"\n\nšŸ› ļø TOOL RESULT [{tool_name}] → {result}") + elif chunk.get('type') == 'tool_call': + # Display native tool call chunks as they arrive + tool_call = chunk.get('tool_call', {}) + + # Check if it's a meaningful part of the tool call to display + args = tool_call.get('function', {}).get('arguments', '') + + # Only show when we have substantial arguments or a function name + should_display = ( + len(args) > 3 or # More than just '{}' + tool_call.get('function', {}).get('name') # Or we have a name + ) + + if should_display: + tool_call_counter += 1 + tool_name = tool_call.get('function', {}).get('name', 'Building...') + + # Print tool call header with counter and tool name + print(f"\nšŸ”§ TOOL CALL #{tool_call_counter} [{tool_name}]") + + # Try to parse and pretty print the arguments if they're JSON + try: + # Check if it's complete JSON or just a fragment + if args.strip().startswith('{') and args.strip().endswith('}'): + args_obj = json.loads(args) + # Only print non-empty args to reduce clutter + if args_obj and args_obj != {}: + # Format JSON with nice indentation and color indicators for readability + print(f" ARGS: {json.dumps(args_obj, indent=2)}") + else: + # Only print if there's actual content to show + if args.strip(): + print(f" ARGS: {args}") + except json.JSONDecodeError: + if args.strip(): + print(f" ARGS: {args}") + + # Add a separator for visual clarity + print(" " + "-" * 40) + + # Return to the current content display + if current_response: + print("\nContinuing response:", flush=True) + print(current_response, end='', flush=True) + elif chunk.get('type') == 'tool_status': + # Log tool status changes + status = chunk.get('status', '') + function_name = chunk.get('function_name', '') + if status and function_name: + status_emoji = "āœ…" if status == "completed" else "ā³" if status == "started" else "āŒ" + print(f"\n{status_emoji} TOOL {status.upper()}: {function_name}") + elif chunk.get('type') == 'finish': + # Just log finish reason to console but don't show to user + finish_reason = chunk.get('finish_reason', '') + if finish_reason: + print(f"\nšŸ“Œ Finished: {finish_reason}") + + print(f"\n\nāœ… Agent run completed with {tool_call_counter} tool calls") + if __name__ == "__main__": import asyncio