feat(webui): persist fork boundary metadata

This commit is contained in:
Xubin Ren
2026-06-10 04:26:06 +08:00
parent 03bca4c0a9
commit 73d4b1cb2f
6 changed files with 182 additions and 8 deletions
+46 -1
View File
@@ -17,6 +17,7 @@ from nanobot.config.paths import get_webui_dir
from nanobot.session.manager import SessionManager
WEBUI_TRANSCRIPT_SCHEMA_VERSION = 3
WEBUI_FORK_MARKER_EVENT = "fork_marker"
_MAX_TRANSCRIPT_FILE_BYTES = 8 * 1024 * 1024
_WEBUI_TURN_ID_RE = re.compile(r"^[A-Za-z0-9._:-]{1,128}$")
WEBUI_TURN_METADATA_KEY = "webui_turn_id"
@@ -306,6 +307,8 @@ def fork_transcript_before_user_index(
user_index = 0
found_target = False
for row in lines:
if row.get("event") == WEBUI_FORK_MARKER_EVENT:
continue
if _is_user_transcript_row(row):
if user_index == before_user_index:
found_target = True
@@ -340,6 +343,17 @@ def fork_transcript_before_user_index(
return True
def append_fork_marker(session_key: str) -> None:
"""Mark the UI-only boundary where a WebUI fork starts accepting new turns."""
append_transcript_object(
session_key,
{
"event": WEBUI_FORK_MARKER_EVENT,
"chat_id": _chat_id_from_session_key(session_key),
},
)
def write_session_messages_as_transcript(
target_key: str,
messages: list[dict[str, Any]],
@@ -1397,6 +1411,28 @@ def replay_transcript_to_ui_messages(
return messages
def fork_boundary_message_count(
lines: list[dict[str, Any]],
*,
augment_user_media: Callable[[list[str]], list[dict[str, Any]]] | None = None,
augment_assistant_media: Callable[[list[str]], list[dict[str, Any]]] | None = None,
augment_assistant_text: Callable[[str], str] | None = None,
) -> int | None:
"""Return the replayed UI message count before the first fork marker, if any."""
for idx, rec in enumerate(lines):
if rec.get("event") != WEBUI_FORK_MARKER_EVENT:
continue
return len(
replay_transcript_to_ui_messages(
lines[:idx],
augment_user_media=augment_user_media,
augment_assistant_media=augment_assistant_media,
augment_assistant_text=augment_assistant_text,
),
)
return None
def build_webui_thread_response(
session_key: str,
*,
@@ -1410,14 +1446,23 @@ def build_webui_thread_response(
if not lines:
return None
lines = inject_missing_user_events_from_session(session_key, lines, session_messages)
fork_boundary = fork_boundary_message_count(
lines,
augment_user_media=augment_user_media,
augment_assistant_media=augment_assistant_media,
augment_assistant_text=augment_assistant_text,
)
msgs = replay_transcript_to_ui_messages(
lines,
augment_user_media=augment_user_media,
augment_assistant_media=augment_assistant_media,
augment_assistant_text=augment_assistant_text,
)
return {
payload = {
"schemaVersion": WEBUI_TRANSCRIPT_SCHEMA_VERSION,
"sessionKey": session_key,
"messages": msgs,
}
if fork_boundary is not None:
payload["fork_boundary_message_count"] = fork_boundary
return payload