fix(memory): expose media references to session consolidation (#5157)

Co-authored-by: shakewingo <yaoyingshakewin@gmail.com>
Co-authored-by: bingqilinweimaotai <111987281+bingqilinweimaotai@users.noreply.github.com>
This commit is contained in:
chengyongru
2026-07-29 15:18:44 +08:00
committed by GitHub
co-authored by shakewingo bingqilinweimaotai
parent 393d429e0a
commit e703481755
5 changed files with 96 additions and 9 deletions
+9 -2
View File
@@ -19,6 +19,7 @@ from nanobot.runtime_context import public_history_messages
from nanobot.session.manager import Session, SessionManager
from nanobot.utils.gitstore import GitStore
from nanobot.utils.helpers import (
content_with_media_breadcrumbs,
ensure_dir,
estimate_message_tokens,
estimate_prompt_tokens_chain,
@@ -695,11 +696,17 @@ class MemoryStore:
def _format_messages(messages: list[dict]) -> str:
lines = []
for message in messages:
if not message.get("content"):
content = content_with_media_breadcrumbs(
message.get("role"),
message.get("content", ""),
message.get("media"),
)
if not content:
continue
tools = f" [tools: {', '.join(message['tools_used'])}]" if message.get("tools_used") else ""
lines.append(
f"[{message.get('timestamp', '?')[:16]}] {message['role'].upper()}{tools}: {message['content']}"
f"[{message.get('timestamp', '?')[:16]}] "
f"{message['role'].upper()}{tools}: {content}"
)
return "\n".join(lines)
+6 -7
View File
@@ -22,10 +22,10 @@ from nanobot.runtime_context import (
public_history_message,
)
from nanobot.utils.helpers import (
content_with_media_breadcrumbs,
ensure_dir,
estimate_message_tokens,
find_legal_message_start,
image_placeholder_text,
recent_message_start_index,
safe_filename,
strip_think,
@@ -214,12 +214,11 @@ class Session:
# image used to be. Without this, an image-only user turn
# replays as an empty user message — the assistant's reply then
# looks like it's responding to nothing.
media = message.get("media")
if role == "user" and isinstance(media, list) and media and isinstance(content, str):
breadcrumbs = "\n".join(
image_placeholder_text(p) for p in media if isinstance(p, str) and p
)
content = f"{content}\n{breadcrumbs}" if content else breadcrumbs
content = content_with_media_breadcrumbs(
role,
content,
message.get("media"),
)
cli_apps = message.get("cli_apps")
if (
include_runtime_context
+18
View File
@@ -367,6 +367,24 @@ def image_placeholder_text(path: str | None, *, empty: str = "[image]") -> str:
return f"[image: {path}]" if path else empty
def content_with_media_breadcrumbs(
role: str | None,
content: Any,
media: Any,
) -> Any:
"""Append persisted user-media breadcrumbs to plain-text content."""
if role != "user" or not isinstance(content, str) or not isinstance(media, list):
return content
breadcrumbs = "\n".join(
image_placeholder_text(path)
for path in media
if isinstance(path, str) and path
)
if not breadcrumbs:
return content
return f"{content}\n{breadcrumbs}" if content else breadcrumbs
def truncate_text(text: str, max_chars: int) -> str:
"""Truncate text with a stable suffix."""
if max_chars <= 0 or len(text) <= max_chars: