fix(providers): use non-descriptive placeholder when stripping images

The image-strip fallback (triggered when a model errors on image input)
replaced image_url blocks with [image: <path>] or [image omitted]. Both
read like a live, available image to the LLM, causing it to:

1. hallucinate about image contents it never received
2. attempt read_file on the leaked server path
3. expose internal file paths to the model

Replace with an explicit '[Image not delivered to model — do not describe
or reference it]' placeholder that tells the LLM the image was stripped.

Fixes #4345
This commit is contained in:
michaelxer
2026-06-19 14:59:52 +08:00
committed by Xubin Ren
parent bbd7bbd7f5
commit 9ed3905a23
2 changed files with 181 additions and 6 deletions
+8 -6
View File
@@ -15,8 +15,6 @@ from typing import Any
import json_repair
from loguru import logger
from nanobot.utils.helpers import image_placeholder_text
STREAM_IDLE_TIMEOUT_ENV = "NANOBOT_STREAM_IDLE_TIMEOUT_S"
DEFAULT_STREAM_IDLE_TIMEOUT_S = 90.0
MAX_STREAM_IDLE_TIMEOUT_S = 3600.0
@@ -564,8 +562,10 @@ class LLMProvider(ABC):
new_content = []
for b in content:
if isinstance(b, dict) and b.get("type") == "image_url":
path = (b.get("_meta") or {}).get("path", "")
placeholder = image_placeholder_text(path, empty="[image omitted]")
placeholder = (
"[Image not delivered to model — "
"do not describe or reference it]"
)
new_content.append({"type": "text", "text": placeholder})
found = True
else:
@@ -589,8 +589,10 @@ class LLMProvider(ABC):
if isinstance(content, list):
for i, b in enumerate(content):
if isinstance(b, dict) and b.get("type") == "image_url":
path = (b.get("_meta") or {}).get("path", "")
placeholder = image_placeholder_text(path, empty="[image omitted]")
placeholder = (
"[Image not delivered to model — "
"do not describe or reference it]"
)
content[i] = {"type": "text", "text": placeholder}
found = True
return found