#!/usr/bin/env python3 """ Export agent daily messages to Markdown. Usage: python scripts/export_agent_daily.py --agent xingjiang --date 2026-04-07 python scripts/export_agent_daily.py --agent xingjiang --date 2026-04-07 --output /tmp/report.md """ import argparse import json import os import sys from datetime import date # Add src to path for Django settings sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src")) os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production") import django django.setup() from openclaw.models import Session, Message, ToolCall def format_tool_args(args: dict) -> str: """Format tool arguments as pretty JSON.""" if not args: return "" return json.dumps(args, indent=2, ensure_ascii=False) def export_agent_daily(agent_name: str, target_date: str, output_file=None): """ Export all messages for a specific agent on a specific date. Sessions may span multiple days, but we focus on messages within the target date. """ target_date_obj = date.fromisoformat(target_date) # Get sessions for this agent that have messages on the target date sessions = Session.objects.filter( agent_name=agent_name ).prefetch_related("messages", "messages__tool_calls").order_by("start_time") daily_sessions = [] for session in sessions: # Filter messages to only those on target date day_messages = session.messages.filter( timestamp__date=target_date_obj ).order_by("seq") if day_messages.exists(): daily_sessions.append({ "session": session, "messages": list(day_messages), }) if not daily_sessions: print(f"No messages found for agent {agent_name} on {target_date}", file=sys.stderr) return # Build Markdown output lines = [] lines.append(f"# Agent Daily Report: {agent_name} - {target_date}") lines.append("") total_messages = sum(len(s["messages"]) for s in daily_sessions) lines.append(f"**Total Sessions:** {len(daily_sessions)} ") lines.append(f"**Total Messages:** {total_messages} ") lines.append("") role_label_map = { "user": "User", "assistant": "Assistant", "tool": "Tool", "toolResult": "Tool Result", "system": "System", } for session_data in daily_sessions: session = session_data["session"] messages = session_data["messages"] start_str = session.start_time.strftime("%Y-%m-%d %H:%M") if session.start_time else "N/A" end_str = session.end_time.strftime("%H:%M") if session.end_time else " Ongoing" lines.append(f"## Session: {session.session_id}") lines.append(f"**Time:** {start_str} ~ {end_str} ") lines.append(f"**Model:** {session.model_id or 'N/A'} ") lines.append(f"**Tokens:** {session.total_tokens:,} | **Cost:** ${session.total_cost:.4f} ") lines.append(f"**Messages:** {session.message_count} | **Tool Calls:** {session.tool_call_count} ") lines.append("") for msg in messages: role_disp = role_label_map.get(msg.role, msg.role) ts_str = msg.timestamp.strftime("%H:%M:%S") lines.append(f"### [{msg.seq}] [{role_disp}] [{ts_str}]") lines.append("") # Content content = msg.content_text.strip() if msg.content_text else "" if content: # Truncate very long content if len(content) > 2000: content = content[:2000] + "\n\n_[content truncated]_" lines.append(f"**Content:**\n{content}") else: lines.append("**Content:** _(empty)_") lines.append("") # Tool call info if msg.tool_name: lines.append(f"**Tool:** `{msg.tool_name}` | **Exit:** {msg.exit_code} | **Duration:** {msg.duration_ms}ms") lines.append("") # Get tool calls for this message tool_calls = msg.tool_calls.all() if tool_calls.exists(): for tc in tool_calls: args_str = format_tool_args(tc.arguments) if args_str: lines.append(f"**Arguments:**\n```json\n{args_str}\n```") lines.append("") if tc.result_text: result = tc.result_text.strip() if len(result) > 1000: result = result[:1000] + "\n\n_[result truncated]_" lines.append(f"**Result:**\n{result}") lines.append("") # Token info if msg.tokens_total > 0: lines.append(f"**Tokens:** {msg.tokens_total:,} (in: {msg.tokens_input}, out: {msg.tokens_output})") if msg.is_error: lines.append("⚠️ **Error**") lines.append("") lines.append("---") lines.append("") md_content = "\n".join(lines) if output_file: with open(output_file, "w", encoding="utf-8") as f: f.write(md_content) print(f"Report written to: {output_file}", file=sys.stderr) else: print(md_content) def main(): parser = argparse.ArgumentParser( description="Export agent daily messages to Markdown" ) parser.add_argument("--agent", required=True, help="Agent name (e.g. xingjiang)") parser.add_argument("--date", required=True, help="Target date (YYYY-MM-DD)") parser.add_argument("--output", help="Output file path (default: stdout)") args = parser.parse_args() # Validate date format try: date.fromisoformat(args.date) except ValueError: print(f"Error: Invalid date format {args.date}. Use YYYY-MM-DD.", file=sys.stderr) sys.exit(1) export_agent_daily(args.agent, args.date, args.output) if __name__ == "__main__": main()