feat(webui): persist fork boundary metadata
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user