refactor: inline base64 image stripping in _save_turn
This commit is contained in:
@@ -463,15 +463,20 @@ class AgentLoop:
|
|||||||
def _save_turn(self, session: Session, messages: list[dict], skip: int) -> None:
|
def _save_turn(self, session: Session, messages: list[dict], skip: int) -> None:
|
||||||
"""Save new-turn messages into session, truncating large tool results."""
|
"""Save new-turn messages into session, truncating large tool results."""
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from nanobot.utils import helpers
|
|
||||||
for m in messages[skip:]:
|
for m in messages[skip:]:
|
||||||
entry = {k: v for k, v in m.items() if k != "reasoning_content"}
|
entry = {k: v for k, v in m.items() if k != "reasoning_content"}
|
||||||
if entry.get("role") == "tool" and isinstance(entry.get("content"), str):
|
if entry.get("role") == "tool" and isinstance(entry.get("content"), str):
|
||||||
content = entry["content"]
|
content = entry["content"]
|
||||||
if len(content) > self._TOOL_RESULT_MAX_CHARS:
|
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":
|
if entry.get("role") == "user" and isinstance(entry.get("content"), list):
|
||||||
entry["content"] = helpers.strip_base64_images(entry["content"])
|
entry["content"] = [
|
||||||
|
{"type": "text", "text": "[image]"} if (
|
||||||
|
c.get("type") == "image_url"
|
||||||
|
and c.get("image_url", {}).get("url", "").startswith("data:image/")
|
||||||
|
) else c
|
||||||
|
for c in entry["content"]
|
||||||
|
]
|
||||||
entry.setdefault("timestamp", datetime.now().isoformat())
|
entry.setdefault("timestamp", datetime.now().isoformat())
|
||||||
session.messages.append(entry)
|
session.messages.append(entry)
|
||||||
session.updated_at = datetime.now()
|
session.updated_at = datetime.now()
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
|
|
||||||
def ensure_dir(path: Path) -> Path:
|
def ensure_dir(path: Path) -> Path:
|
||||||
"""Ensure a directory exists, creating it if necessary."""
|
"""Ensure a directory exists, creating it if necessary."""
|
||||||
@@ -78,29 +76,4 @@ def parse_session_key(key: str) -> tuple[str, str]:
|
|||||||
parts = key.split(":", 1)
|
parts = key.split(":", 1)
|
||||||
if len(parts) != 2:
|
if len(parts) != 2:
|
||||||
raise ValueError(f"Invalid session key: {key}")
|
raise ValueError(f"Invalid session key: {key}")
|
||||||
return parts[0], parts[1]
|
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
|
|
||||||
Reference in New Issue
Block a user