fix(webui): hide subagent backfill payloads

This commit is contained in:
chengyongru
2026-07-02 14:36:23 +08:00
committed by Xubin Ren
parent 5abe06f808
commit 34535b4e7c
11 changed files with 232 additions and 12 deletions
+15 -1
View File
@@ -62,6 +62,7 @@ from nanobot.session.goal_state import (
runner_wall_llm_timeout_s,
sustained_goal_active,
)
from nanobot.session.history_visibility import HIDDEN_HISTORY_META
from nanobot.session.keys import UNIFIED_SESSION_KEY, session_key_for_channel
from nanobot.session.manager import (
Session,
@@ -795,7 +796,20 @@ class AgentLoop:
content, media = self._prepare_message_media(content, media)
media = media or None
user_content = self.context._build_user_content(content, media)
return {"role": "user", "content": user_content}
row: dict[str, Any] = {"role": "user", "content": user_content}
metadata = pending_msg.metadata if isinstance(pending_msg.metadata, dict) else {}
if (
pending_msg.sender_id == "subagent"
and metadata.get("injected_event") == "subagent_result"
):
marker: dict[str, Any] = {"kind": "subagent_result"}
task_id = metadata.get("subagent_task_id")
if isinstance(task_id, str) and task_id:
marker["subagent_task_id"] = task_id
row["subagent_task_id"] = task_id
row[HIDDEN_HISTORY_META] = marker
row["injected_event"] = "subagent_result"
return row
items: list[dict[str, Any]] = []
while len(items) < limit:
+3
View File
@@ -20,6 +20,7 @@ from nanobot.agent.context_governance import (
from nanobot.agent.hook import AgentHook, AgentHookContext, AgentRunHookContext
from nanobot.agent.tools.registry import ToolRegistry, is_tool_error_result
from nanobot.providers.base import LLMProvider, LLMResponse, ToolCallRequest
from nanobot.session.history_visibility import is_hidden_history_message
from nanobot.utils.file_edit_events import (
StreamingFileEditTracker,
build_file_edit_end_event,
@@ -155,6 +156,8 @@ class AgentRunner:
messages
and injection.get("role") == "user"
and messages[-1].get("role") == "user"
and not is_hidden_history_message(injection)
and not is_hidden_history_message(messages[-1])
):
merged = dict(messages[-1])
merged["content"] = cls._merge_message_content(
+22
View File
@@ -0,0 +1,22 @@
"""Visibility helpers for persisted session history messages."""
from __future__ import annotations
from collections.abc import Mapping
from typing import Any
from nanobot.session.automation_turns import is_automation_history_message
HIDDEN_HISTORY_META = "_hidden_history"
def _has_hidden_history_marker(message: Mapping[str, Any] | None) -> bool:
if not message:
return False
marker = message.get(HIDDEN_HISTORY_META)
return marker is True or isinstance(marker, Mapping)
def is_hidden_history_message(message: Mapping[str, Any] | None) -> bool:
"""True for persisted messages that should not be shown as chat turns."""
return _has_hidden_history_marker(message) or is_automation_history_message(message)
+2 -2
View File
@@ -31,8 +31,8 @@ from nanobot.bus.runtime_events import (
TurnRunStatusChanged,
)
from nanobot.providers.base import LLMProvider
from nanobot.session.automation_turns import is_automation_history_message
from nanobot.session.goal_state import goal_state_ws_blob
from nanobot.session.history_visibility import is_hidden_history_message
from nanobot.session.manager import Session, SessionManager
from nanobot.utils.helpers import strip_think, truncate_text
from nanobot.utils.llm_runtime import LLMRuntime
@@ -77,7 +77,7 @@ def _title_inputs(session: Session) -> tuple[str, str]:
for message in session.messages:
if message.get("_command") is True:
continue
if is_automation_history_message(message):
if is_hidden_history_message(message):
continue
role = message.get("role")
content = message.get("content")
+2 -2
View File
@@ -6,7 +6,7 @@ from collections.abc import Collection
from typing import Any, Protocol
from nanobot.cron.types import CronJob
from nanobot.session.automation_turns import is_automation_history_message
from nanobot.session.history_visibility import is_hidden_history_message
from nanobot.session.manager import _message_preview_text
from nanobot.triggers.local_types import LocalTrigger
@@ -328,7 +328,7 @@ def _session_preview(messages: Any) -> str:
for message in messages:
if not isinstance(message, dict):
continue
if is_automation_history_message(message):
if is_hidden_history_message(message):
continue
text = _message_preview_text(message)
if not text:
+4 -4
View File
@@ -16,7 +16,7 @@ from typing import Any
from loguru import logger
from nanobot.config.paths import get_webui_dir
from nanobot.session.automation_turns import is_automation_history_message
from nanobot.session.history_visibility import is_hidden_history_message
from nanobot.session.manager import (
_SESSION_LIST_PREVIEW_MAX_CHARS,
_SESSION_LIST_PREVIEW_MAX_RECORDS,
@@ -154,7 +154,7 @@ def _preview_from_messages(messages: list[dict[str, Any]]) -> str:
or scanned_chars > _SESSION_LIST_PREVIEW_MAX_CHARS
):
break
if is_automation_history_message(item):
if is_hidden_history_message(item):
continue
text = _message_preview_text(item)
if not text:
@@ -216,7 +216,7 @@ def _latest_updated_at(stored: str | None, activity: str | None) -> str | None:
def _visible_message_timestamp(item: dict[str, Any]) -> str | None:
if is_automation_history_message(item):
if is_hidden_history_message(item):
return None
if item.get("role") not in _VISIBLE_TRANSCRIPT_ROLES:
return None
@@ -298,7 +298,7 @@ def _scan_session_row(session_manager: SessionManager, path: Path) -> dict[str,
continue
if item.get("_type") == "metadata":
continue
if is_automation_history_message(item):
if is_hidden_history_message(item):
continue
text = _message_preview_text(item)
if not text:
+19 -3
View File
@@ -17,7 +17,8 @@ from urllib.parse import unquote, urlparse
from loguru import logger
from nanobot.config.paths import get_webui_dir
from nanobot.session.automation_turns import is_automation_history_message, is_automation_kind
from nanobot.session.automation_turns import is_automation_kind
from nanobot.session.history_visibility import is_hidden_history_message
from nanobot.session.manager import SessionManager
from nanobot.webui.metadata import WEBUI_MESSAGE_SOURCE_METADATA_KEY, WEBUI_TURN_METADATA_KEY
@@ -782,7 +783,7 @@ def write_session_messages_as_transcript(
target_chat_id = _chat_id_from_session_key(target_key)
rows: list[dict[str, Any]] = []
for msg in messages:
if is_automation_history_message(msg):
if is_hidden_history_message(msg):
continue
role = msg.get("role")
content = msg.get("content")
@@ -854,13 +855,28 @@ def build_user_transcript_event(
return event
def _is_legacy_raw_subagent_result(message: dict[str, Any]) -> bool:
content = message.get("content")
if not isinstance(content, str):
return False
text = content.replace("\r\n", "\n").strip()
return (
text.startswith("[Subagent '")
and "\n\nTask:" in text
and "\n\nResult:" in text
and "Summarize this naturally" in text
)
def _session_user_event(
session_key: str,
message: dict[str, Any],
) -> dict[str, Any] | None:
if message.get("role") != "user":
return None
if is_automation_history_message(message):
if is_hidden_history_message(message):
return None
if _is_legacy_raw_subagent_result(message):
return None
content = message.get("content")
text = content if isinstance(content, str) else ""