Fix: The base64 images are stored in the session history, causing context overflow.

This commit is contained in:
dxtime
2026-02-25 20:58:59 +08:00
parent 9e806d7159
commit 6aed4265b7
2 changed files with 30 additions and 1 deletions

View File

@@ -427,12 +427,15 @@ class AgentLoop:
def _save_turn(self, session: Session, messages: list[dict], skip: int) -> None:
"""Save new-turn messages into session, truncating large tool results."""
from datetime import datetime
from nanobot.utils import helpers
for m in messages[skip:]:
entry = {k: v for k, v in m.items() if k != "reasoning_content"}
if entry.get("role") == "tool" and isinstance(entry.get("content"), str):
content = entry["content"]
if len(content) > self._TOOL_RESULT_MAX_CHARS:
entry["content"] = content[:self._TOOL_RESULT_MAX_CHARS] + "\n... (truncated)"
entry["content"] = content[: self._TOOL_RESULT_MAX_CHARS] + "\n... (truncated)"
if entry.get("role") == "user":
entry["content"] = helpers.strip_base64_images(entry["content"])
entry.setdefault("timestamp", datetime.now().isoformat())
session.messages.append(entry)
session.updated_at = datetime.now()

View File

@@ -2,6 +2,7 @@
from pathlib import Path
from datetime import datetime
from typing import Any
def ensure_dir(path: Path) -> Path:
@@ -78,3 +79,28 @@ def parse_session_key(key: str) -> tuple[str, str]:
if len(parts) != 2:
raise ValueError(f"Invalid session key: {key}")
return parts[0], parts[1]
def strip_base64_images(content: str | list[dict[str, Any]]) -> str | list[dict[str, Any]]:
"""Strip base64 image data from message content, replacing with text placeholder."""
if not isinstance(content, list):
return content
new_content = []
for item in content:
if not isinstance(item, dict):
new_content.append(item)
continue
if item.get("type") == "image_url":
url = item.get("image_url", {}).get("url", "")
if url.startswith("data:image/") and ";base64," in url:
new_content.append({"type": "text", "text": "[image]"})
continue
new_content.append(item)
text_parts = [c["text"] for c in new_content if isinstance(c, dict) and c.get("type") == "text"]
if len(new_content) == 1 and not text_parts:
return new_content[0] if new_content else ""
if text_parts and len(new_content) == len(text_parts):
return "\n".join(text_parts)
return new_content