From 56326c7551f608b9d3a7c09ff085245fa50e1a76 Mon Sep 17 00:00:00 2001 From: Fiber <48828021+leafliber@users.noreply.github.com> Date: Mon, 6 Jul 2026 21:12:29 +0800 Subject: [PATCH] fix: serialize webchat history timestamps as UTC-aware ISO strings (#9159) ChatService serialized PlatformMessageHistory records via bare model_dump(), causing created_at/updated_at to be emitted as naive ISO strings without a timezone suffix. The frontend new Date() parses such strings as local time per ES2015+, so UTC values were displayed as-is instead of converted. Add serialize_history_entry helper and apply it to get_session, get_thread, and update_message. This matches the SSE real-time path and session list path, ensuring the frontend consistently receives ISO strings with the +00:00 suffix across all code paths. --- astrbot/dashboard/services/chat_service.py | 23 +++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/astrbot/dashboard/services/chat_service.py b/astrbot/dashboard/services/chat_service.py index afbe4bd4c..ed2a581ad 100644 --- a/astrbot/dashboard/services/chat_service.py +++ b/astrbot/dashboard/services/chat_service.py @@ -345,6 +345,23 @@ def serialize_thread(thread) -> dict: } +def serialize_history_entry(history) -> dict: + """Serialize a PlatformMessageHistory record with UTC-aware timestamps. + + Args: + history: A PlatformMessageHistory instance. Must not be None. + + Returns: + Dict with all model fields plus created_at/updated_at serialized as + UTC-aware ISO strings (e.g. ``2026-07-06T04:00:00+00:00``). + """ + return { + **history.model_dump(), + "created_at": to_utc_isoformat(history.created_at), + "updated_at": to_utc_isoformat(history.updated_at), + } + + def find_checkpoint_index(history: list[dict], checkpoint_id: str) -> int | None: for index, message in enumerate(history): if get_checkpoint_id(message) == checkpoint_id: @@ -1217,7 +1234,7 @@ class ChatService: ) response_data = { - "history": [history.model_dump() for history in history_ls], + "history": [serialize_history_entry(history) for history in history_ls], "threads": [serialize_thread(thread) for thread in threads], "is_running": self.running_convs.get(session_id, False), } @@ -1333,7 +1350,7 @@ class ChatService: ) return { "thread": serialize_thread(thread), - "history": [history.model_dump() for history in history_ls], + "history": [serialize_history_entry(history) for history in history_ls], "is_running": self.running_convs.get(thread_id, False), } @@ -1487,7 +1504,7 @@ class ChatService: await self.db.update_platform_session(session_id=session_id) updated = await self.db.get_platform_message_history_by_id(message_id) return { - "message": updated.model_dump() if updated else None, + "message": serialize_history_entry(updated) if updated else None, "needs_regenerate": True, "truncated_after_message": True, }