Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
"""Send-path eviction of stale vision_analyze / screenshot tool payloads.
|
||||
|
||||
Issue #89296: compression only retires older image-bearing tool results when
|
||||
prune/compress fires, so OpenAI-style screenshots are re-serialized on every
|
||||
later turn until a 413. ``evict_stale_outbound_tool_images`` is the
|
||||
unconditional per-call chokepoint.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from agent.agent_runtime_helpers import sanitize_api_messages
|
||||
from agent.context_compressor import (
|
||||
_MAX_KEEP_TOOL_IMAGES,
|
||||
_tool_content_has_images,
|
||||
evict_stale_outbound_tool_images,
|
||||
)
|
||||
|
||||
|
||||
def _image_tool(i: int, *, blob: str = "A" * 80) -> list[dict]:
|
||||
return [
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": None,
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": f"call_{i}",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "vision_analyze",
|
||||
"arguments": f'{{"image_url":"shot{i}.png"}}',
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"role": "tool",
|
||||
"tool_call_id": f"call_{i}",
|
||||
"content": [
|
||||
{"type": "text", "text": f"Image attached natively shot {i}"},
|
||||
{
|
||||
"type": "image_url",
|
||||
"image_url": {"url": f"data:image/png;base64,{blob}{i}"},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def _history_with_screenshots(n: int) -> list[dict]:
|
||||
msgs: list[dict] = [{"role": "user", "content": "look at these"}]
|
||||
for i in range(n):
|
||||
msgs.extend(_image_tool(i))
|
||||
msgs.append({"role": "user", "content": "compare them"})
|
||||
return msgs
|
||||
|
||||
|
||||
def _image_bearing_tool_ids(messages: list[dict]) -> list[str]:
|
||||
return [
|
||||
m["tool_call_id"]
|
||||
for m in messages
|
||||
if m.get("role") == "tool" and _tool_content_has_images(m.get("content"))
|
||||
]
|
||||
|
||||
|
||||
class TestOutboundStaleVisionEviction:
|
||||
def test_sanitize_alone_keeps_every_screenshot(self):
|
||||
"""The previous send chokepoint does not close #89296 by itself."""
|
||||
history = _history_with_screenshots(5)
|
||||
sanitized = sanitize_api_messages(history)
|
||||
assert _image_bearing_tool_ids(sanitized) == [f"call_{i}" for i in range(5)]
|
||||
|
||||
def test_eviction_keeps_only_newest_window(self):
|
||||
history = _history_with_screenshots(5)
|
||||
outbound = sanitize_api_messages(history)
|
||||
pruned = evict_stale_outbound_tool_images(outbound)
|
||||
assert pruned == 5 - _MAX_KEEP_TOOL_IMAGES
|
||||
kept = _image_bearing_tool_ids(outbound)
|
||||
assert kept == [f"call_{i}" for i in range(5 - _MAX_KEEP_TOOL_IMAGES, 5)]
|
||||
|
||||
oldest = next(m for m in outbound if m.get("tool_call_id") == "call_0")
|
||||
assert isinstance(oldest["content"], list)
|
||||
assert not _tool_content_has_images(oldest["content"])
|
||||
assert any(
|
||||
isinstance(part, dict)
|
||||
and part.get("type") == "text"
|
||||
and "screenshot removed" in str(part.get("text", ""))
|
||||
for part in oldest["content"]
|
||||
)
|
||||
|
||||
def test_does_not_rewrite_persisted_history(self):
|
||||
from agent.conversation_loop import _clone_message_for_send
|
||||
|
||||
history = _history_with_screenshots(5)
|
||||
outbound = [_clone_message_for_send(m) for m in history]
|
||||
evict_stale_outbound_tool_images(outbound)
|
||||
assert _image_bearing_tool_ids(history) == [f"call_{i}" for i in range(5)]
|
||||
assert _image_bearing_tool_ids(outbound) == [
|
||||
f"call_{i}" for i in range(5 - _MAX_KEEP_TOOL_IMAGES, 5)
|
||||
]
|
||||
|
||||
def test_user_uploads_are_not_evicted(self):
|
||||
history = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "text", "text": "look"},
|
||||
{
|
||||
"type": "image_url",
|
||||
"image_url": {"url": "data:image/png;base64,USERUPLOAD"},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
for i in range(_MAX_KEEP_TOOL_IMAGES + 2):
|
||||
history.extend(_image_tool(i))
|
||||
outbound = sanitize_api_messages(history)
|
||||
evict_stale_outbound_tool_images(outbound)
|
||||
user = next(m for m in outbound if m.get("role") == "user")
|
||||
assert user["content"][1]["image_url"]["url"].endswith("USERUPLOAD")
|
||||
Reference in New Issue
Block a user