xueyiming 3 дней назад
Родитель
Сommit
64bd06c4a0
1 измененных файлов с 141 добавлено и 19 удалено
  1. 141 19
      examples/create/run.py

+ 141 - 19
examples/create/run.py

@@ -17,7 +17,9 @@ import os
 import sys
 import select
 import asyncio
+import json
 from pathlib import Path
+from typing import Any
 
 # Clash Verge TUN 模式兼容:禁止 httpx/urllib 自动检测系统 HTTP 代理
 # TUN 虚拟网卡已在网络层接管所有流量,不需要应用层再走 HTTP 代理,
@@ -80,6 +82,141 @@ def check_stdin() -> str | None:
         return None
 
 
+# ===== 格式化打印 =====
+
+def _format_json(obj: Any, indent: int = 2) -> str:
+    """格式化 JSON 对象为字符串"""
+    try:
+        return json.dumps(obj, indent=indent, ensure_ascii=False)
+    except (TypeError, ValueError):
+        # 如果无法序列化为 JSON,返回字符串表示
+        return str(obj)
+
+
+def _print_message_details(message: Message):
+    """完整打印消息的详细信息"""
+    print("\n" + "=" * 80)
+    print(f"[Message #{message.sequence}] {message.role.upper()}")
+    print("=" * 80)
+    
+    # 基本信息
+    if message.goal_id:
+        print(f"Goal ID: {message.goal_id}")
+    if message.parent_sequence is not None:
+        print(f"Parent Sequence: {message.parent_sequence}")
+    if message.tool_call_id:
+        print(f"Tool Call ID: {message.tool_call_id}")
+    
+    # 内容打印
+    if message.role == "user":
+        print("\n[输入内容]")
+        print("-" * 80)
+        if isinstance(message.content, str):
+            print(message.content)
+        else:
+            print(_format_json(message.content))
+    
+    elif message.role == "assistant":
+        content = message.content
+        if isinstance(content, dict):
+            text = content.get("text", "")
+            tool_calls = content.get("tool_calls")
+            
+            if text:
+                print("\n[LLM 文本回复]")
+                print("-" * 80)
+                print(text)
+            
+            if tool_calls:
+                print(f"\n[工具调用] (共 {len(tool_calls)} 个)")
+                print("-" * 80)
+                for idx, tc in enumerate(tool_calls, 1):
+                    func = tc.get("function", {})
+                    tool_name = func.get("name", "unknown")
+                    tool_id = tc.get("id", "unknown")
+                    arguments = func.get("arguments", {})
+                    
+                    print(f"\n工具 #{idx}: {tool_name}")
+                    print(f"  Call ID: {tool_id}")
+                    print(f"  参数:")
+                    # 尝试解析 arguments(可能是字符串或字典)
+                    if isinstance(arguments, str):
+                        try:
+                            parsed_args = json.loads(arguments)
+                            print(_format_json(parsed_args, indent=4))
+                        except json.JSONDecodeError:
+                            print(f"    {arguments}")
+                    else:
+                        print(_format_json(arguments, indent=4))
+        elif isinstance(content, str):
+            print("\n[LLM 文本回复]")
+            print("-" * 80)
+            print(content)
+        else:
+            print("\n[内容]")
+            print("-" * 80)
+            print(_format_json(content))
+        
+        if message.finish_reason:
+            print(f"\n完成原因: {message.finish_reason}")
+    
+    elif message.role == "tool":
+        content = message.content
+        print("\n[工具执行结果]")
+        print("-" * 80)
+        if isinstance(content, dict):
+            tool_name = content.get("tool_name", "unknown")
+            result = content.get("result", content)
+            print(f"工具名称: {tool_name}")
+            print(f"\n返回结果:")
+            if isinstance(result, str):
+                print(result)
+            elif isinstance(result, list):
+                # 可能是多模态内容(包含图片)
+                for idx, item in enumerate(result, 1):
+                    if isinstance(item, dict) and item.get("type") == "image_url":
+                        print(f"  [{idx}] 图片 (base64, 已省略显示)")
+                    else:
+                        print(f"  [{idx}] {item}")
+            else:
+                print(_format_json(result))
+        else:
+            print(str(content) if content is not None else "(无内容)")
+    
+    elif message.role == "system":
+        print("\n[系统提示]")
+        print("-" * 80)
+        if isinstance(message.content, str):
+            print(message.content)
+        else:
+            print(_format_json(message.content))
+    
+    # Token 和成本信息
+    if message.prompt_tokens is not None or message.completion_tokens is not None:
+        print("\n[Token 使用]")
+        print("-" * 80)
+        if message.prompt_tokens is not None:
+            print(f"  输入 Tokens: {message.prompt_tokens:,}")
+        if message.completion_tokens is not None:
+            print(f"  输出 Tokens: {message.completion_tokens:,}")
+        if message.reasoning_tokens is not None:
+            print(f"  推理 Tokens: {message.reasoning_tokens:,}")
+        if message.cache_creation_tokens is not None:
+            print(f"  缓存创建 Tokens: {message.cache_creation_tokens:,}")
+        if message.cache_read_tokens is not None:
+            print(f"  缓存读取 Tokens: {message.cache_read_tokens:,}")
+        if message.tokens:
+            print(f"  总计 Tokens: {message.tokens:,}")
+    
+    if message.cost is not None:
+        print(f"\n[成本] ${message.cost:.6f}")
+    
+    if message.duration_ms is not None:
+        print(f"[执行时间] {message.duration_ms}ms")
+    
+    print("=" * 80 + "\n")
+
+
 # ===== 交互菜单 =====
 
 def _read_multiline() -> str:
@@ -512,7 +649,11 @@ async def main():
                     # 处理 Message 对象(执行过程)
                     elif isinstance(item, Message):
                         current_sequence = item.sequence
+                        
+                        # 完整打印所有消息详情
+                        _print_message_details(item)
 
+                        # 保留原有的简化输出逻辑(用于最终响应)
                         if item.role == "assistant":
                             content = item.content
                             if isinstance(content, dict):
@@ -522,25 +663,6 @@ async def main():
                                 if text and not tool_calls:
                                     # 纯文本回复(最终响应)
                                     final_response = text
-                                    print(f"\n[Response] Agent 回复:")
-                                    print(text)
-                                elif text:
-                                    preview = text[:150] + "..." if len(text) > 150 else text
-                                    print(f"[Assistant] {preview}")
-
-                                if tool_calls:
-                                    for tc in tool_calls:
-                                        tool_name = tc.get("function", {}).get("name", "unknown")
-                                        print(f"[Tool Call] 🛠️  {tool_name}")
-
-                        elif item.role == "tool":
-                            content = item.content
-                            if isinstance(content, dict):
-                                tool_name = content.get("tool_name", "unknown")
-                                print(f"[Tool Result] ✅ {tool_name}")
-                            if item.description:
-                                desc = item.description[:80] if len(item.description) > 80 else item.description
-                                print(f"  {desc}...")
 
             except Exception as e:
                 print(f"\n执行出错: {e}")