import json import re from typing import AsyncGenerator, Optional, Any def try_parse_json(json_str: str) -> Optional[Any]: """Utility function to safely parse JSON strings.""" try: return json.loads(json_str) except (json.JSONDecodeError, TypeError): return None async def print_stream(stream: AsyncGenerator[str, None]): """ Simple stream printer that processes async string generator. Follows the same output format as stream_test.py. """ stream_started = False chunks = [] # Store chunks to sort by sequence parsing_state = "text" # "text", "in_function_call", "function_call_ended" current_function_name = None invoke_name_regex = re.compile(r'" in full_text: parsing_state = "in_function_call" print("\n[TOOL USE DETECTED]") elif parsing_state == "in_function_call": if current_function_name is None: match = invoke_name_regex.search(full_text) if match: current_function_name = match.group(1) print( f'[TOOL UPDATE] Calling function: "{current_function_name}"' ) if "" in full_text: parsing_state = "function_call_ended" print("[TOOL USE WAITING]") current_function_name = None # Complete assistant messages (message_id is not null) - print final message elif message_id is not None: if content: parsed_content = try_parse_json(content) if parsed_content: role = parsed_content.get("role", "unknown") message_content = parsed_content.get("content", "") preview = ( message_content[:100] + "..." if len(message_content) > 100 else message_content ) print() # New line print(f"[MESSAGE] {role}: {preview}") else: print() # New line print(f"[MESSAGE] Failed to parse message content") # Reset state for next message chunks = [] parsing_state = "text" current_function_name = None elif event_type == "tool": # Handle tool results message_id = data.get("message_id") content = data.get("content", "") if not content: print(f"[TOOL RESULT] No content in message") continue parsed_content = try_parse_json(content) if not parsed_content: print(f"[TOOL RESULT] Failed to parse message content") continue execution_result = parsed_content if not execution_result: print(f"[TOOL RESULT] Failed to parse execution result") continue tool_execution = execution_result.get("tool_execution", {}) tool_name = tool_execution.get("function_name") result = tool_execution.get("result", {}) was_success = result.get("success", False) output = json.dumps(result.get("output", {})) error = json.dumps(result.get("error", {})) msg = f'[TOOL RESULT] Message ID: {message_id} | Tool: "{tool_name}" | ' if was_success: output_preview = output[:80] + "..." if len(output) > 80 else output if output_preview == "{}": output_preview = "No answer found." msg += f"Success! Output: {output_preview}" else: msg += f"Failure! Error: {error}" print(msg)