From 9fa698b3ea767ffaf15fbd37b2d1e9199fdd26a6 Mon Sep 17 00:00:00 2001 From: weishen Date: Sun, 5 Apr 2026 14:57:17 +0800 Subject: [PATCH] feat: admin daily conversation view with date filtering Co-Authored-By: Claude Opus 4.6 --- src/openclaw/admin.py | 80 +++++++++++++++++++ .../templates/admin/openclaw/daily_view.html | 43 ++++++++++ 2 files changed, 123 insertions(+) create mode 100644 src/openclaw/templates/admin/openclaw/daily_view.html diff --git a/src/openclaw/admin.py b/src/openclaw/admin.py index 5b24f69..0328896 100644 --- a/src/openclaw/admin.py +++ b/src/openclaw/admin.py @@ -1,4 +1,9 @@ +from datetime import date + from django.contrib import admin +from django.db.models import Prefetch +from django.template.response import TemplateResponse + from openclaw.models import Session, Message, ToolCall @@ -28,6 +33,73 @@ class ToolCallInline(admin.TabularInline): return False +def daily_conversation_view(request): + """Admin standalone view for date-range conversation browsing.""" + start_str = request.GET.get("start") + end_str = request.GET.get("end") + agent_filter = request.GET.get("agent", "") + + start_date = start_str if start_str else date.today().isoformat() + end_date = end_str if end_str else date.today().isoformat() + + agents = list( + Session.objects.values_list("agent_name", flat=True) + .distinct() + .order_by("agent_name") + ) + + sessions_qs = Session.objects.filter( + start_time__date__gte=start_date, + start_time__date__lte=end_date, + ).order_by("start_time") + + if agent_filter: + sessions_qs = sessions_qs.filter(agent_name=agent_filter) + + messages_prefetch = Prefetch( + "messages", + queryset=Message.objects.order_by("seq"), + ) + sessions_qs = sessions_qs.prefetch_related(messages_prefetch) + + role_labels = { + "user": "User", + "assistant": "Assistant", + "toolResult": "Tool Result", + } + + session_list = [] + for session in sessions_qs: + messages = [] + for msg in session.messages.all(): + messages.append({ + "timestamp": msg.timestamp, + "role": msg.role, + "content_text": msg.content_text, + "tool_name": msg.tool_name, + "get_role_label": role_labels.get(msg.role, msg.role), + }) + session_list.append({ + "session_id": session.session_id, + "agent_name": session.agent_name, + "model_id": session.model_id, + "total_tokens": session.total_tokens, + "start_time": session.start_time, + "messages": messages, + }) + + context = { + **admin.site.each_context(request), + "start_date": start_date, + "end_date": end_date, + "selected_agent": agent_filter, + "agents": agents, + "sessions": session_list, + "title": "Daily Conversation View", + } + return TemplateResponse(request, "admin/openclaw/daily_view.html", context) + + @admin.register(Session) class SessionAdmin(admin.ModelAdmin): list_display = ( @@ -51,6 +123,14 @@ class SessionAdmin(admin.ModelAdmin): "pushed_at", ) + def get_urls(self): + from django.urls import path + urls = super().get_urls() + custom_urls = [ + path("daily/", admin.site.admin_view(daily_conversation_view), name="openclaw_daily"), + ] + return custom_urls + urls + @admin.register(Message) class MessageAdmin(admin.ModelAdmin): diff --git a/src/openclaw/templates/admin/openclaw/daily_view.html b/src/openclaw/templates/admin/openclaw/daily_view.html new file mode 100644 index 0000000..c4d60f9 --- /dev/null +++ b/src/openclaw/templates/admin/openclaw/daily_view.html @@ -0,0 +1,43 @@ +{% extends "admin/base_site.html" %} +{% block content %} +

Daily Conversation View

+ +
+ + + + +
+ +{% if sessions %} +{% for session in sessions %} +
+

Session: {{ session.session_id }} ({{ session.agent_name }})

+

Model: {{ session.model_id or 'N/A' }} | Tokens: {{ session.total_tokens }} | + Start: {{ session.start_time|default:"N/A" }}

+ + {% for msg in session.messages %} +
+ {{ msg.timestamp|date:"H:i" }} {{ msg.get_role_label }} + {% if msg.role == 'toolResult' %} + {% if msg.tool_name %}[Tool: {{ msg.tool_name }}]{% endif %} + {% endif %} +
+ Content +
{{ msg.content_text|default:"(empty)" }}
+
+
+ {% empty %} +

No messages.

+ {% endfor %} +
+{% endfor %} +{% endif %} +{% endblock %}