mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-07-25 07:28:07 +00:00
feat(tools): support GIF images in view_image (#4438)
Add GIF to the view_image allowlist: map the .gif extension to image/gif and detect the GIF87a/GIF89a magic bytes so the existing extension/content cross-check accepts GIFs instead of rejecting them as an unsupported format. Covered by a new success test.
This commit is contained in:
parent
80c06414f8
commit
cd9432bcc1
@ -22,6 +22,7 @@ _EXTENSION_TO_MIME = {
|
||||
".jpeg": "image/jpeg",
|
||||
".png": "image/png",
|
||||
".webp": "image/webp",
|
||||
".gif": "image/gif",
|
||||
}
|
||||
|
||||
|
||||
@ -36,6 +37,8 @@ def _detect_image_mime(image_data: bytes) -> str | None:
|
||||
return "image/png"
|
||||
if len(image_data) >= 12 and image_data.startswith(b"RIFF") and image_data[8:12] == b"WEBP":
|
||||
return "image/webp"
|
||||
if image_data.startswith((b"GIF87a", b"GIF89a")):
|
||||
return "image/gif"
|
||||
return None
|
||||
|
||||
|
||||
@ -63,7 +66,7 @@ def view_image_tool(
|
||||
- For multiple files at once (use present_files instead)
|
||||
|
||||
Args:
|
||||
image_path: Absolute /mnt/user-data virtual path to the image file. Common formats supported: jpg, jpeg, png, webp.
|
||||
image_path: Absolute /mnt/user-data virtual path to the image file. Common formats supported: jpg, jpeg, png, webp, gif.
|
||||
"""
|
||||
from deerflow.sandbox.exceptions import SandboxRuntimeError
|
||||
from deerflow.sandbox.tools import (
|
||||
|
||||
@ -12,6 +12,9 @@ view_image_module = importlib.import_module("deerflow.tools.builtins.view_image_
|
||||
|
||||
PNG_BYTES = base64.b64decode("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==")
|
||||
|
||||
# Minimal 1x1 transparent GIF (starts with the "GIF89a" magic bytes).
|
||||
GIF_BYTES = base64.b64decode("R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")
|
||||
|
||||
|
||||
def _make_thread_data(tmp_path: Path) -> dict[str, str]:
|
||||
user_data = tmp_path / "threads" / "thread-1" / "user-data"
|
||||
@ -73,6 +76,23 @@ def test_view_image_reads_virtual_uploads_path(tmp_path: Path) -> None:
|
||||
assert viewed_image["actual_path"] == str(image_path)
|
||||
|
||||
|
||||
def test_view_image_reads_gif(tmp_path: Path) -> None:
|
||||
thread_data = _make_thread_data(tmp_path)
|
||||
image_path = Path(thread_data["uploads_path"]) / "animation.gif"
|
||||
image_path.write_bytes(GIF_BYTES)
|
||||
|
||||
result = view_image_tool.func(
|
||||
runtime=_make_runtime(thread_data),
|
||||
image_path="/mnt/user-data/uploads/animation.gif",
|
||||
tool_call_id="tc-gif",
|
||||
)
|
||||
|
||||
assert _message_content(result) == "Successfully read image"
|
||||
viewed_image = result.update["viewed_images"]["/mnt/user-data/uploads/animation.gif"]
|
||||
assert viewed_image["mime_type"] == "image/gif"
|
||||
assert viewed_image["size"] == len(GIF_BYTES)
|
||||
|
||||
|
||||
def test_view_image_rejects_spoofed_extension(tmp_path: Path) -> None:
|
||||
thread_data = _make_thread_data(tmp_path)
|
||||
image_path = Path(thread_data["uploads_path"]) / "not-really.png"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user