Compress computer-use captures before embedding in history
Reduce the size of computer-use capture attachments stored by the _a0_connector plugin so Windows screenshots remain usable. - optimize capture images before embedding them in history - convert large captures to JPEG data URLs instead of keeping full PNG payloads - keep the existing capture-path fallback when inline payloads are missing - preserve the current user-facing computer_use_remote flow while shrinking the history payload
Alessandro committed
Apr 20, 2026 at 03:56 UTC
20107ff92154742221cd7daf468182339da07a57
1 file changed
+37
-7
plugins/_a0_connector/tools/computer_use_remote.py
+37
-7
@@ -3,10 +3,14 @@ from __future__ import annotations
3
4
import asyncio
5
import base64
6
+import io
7
+import math
8
from pathlib import Path
9
import uuid
10
from typing import Any
11
12
+from PIL import Image
13
+
14
from helpers import history
15
from helpers.tool import Response, Tool
16
from helpers.ws import NAMESPACE
@@ -22,6 +26,8 @@ from plugins._a0_connector.helpers.ws_runtime import (
26
COMPUTER_USE_OP_TIMEOUT = 180.0
27
COMPUTER_USE_OP_EVENT = "connector_computer_use_op"
28
CAPTURE_TOKENS_ESTIMATE = 1500
29
+CAPTURE_MAX_PIXELS = 768_000
30
+CAPTURE_JPEG_QUALITY = 75
31
_AUTO_CAPTURE_ACTIONS = {
32
"start_session",
33
"move",
@@ -307,13 +313,13 @@ class ComputerUseRemote(Tool):
313
return f"Computer use status={status}, trust_mode={trust_mode or 'unknown'}, active_contexts={active_text}."
314
315
def _record_capture(self, data: dict[str, Any]) -> str:
310
- image_b64 = self._capture_image_base64(data)
316
+ mime_type, image_b64 = self._capture_image_data(data)
317
width = data.get("width", "?")
318
height = data.get("height", "?")
319
summary = f"Computer-use capture {width}x{height}."
320
content = [
321
{"type": "text", "text": summary},
316
- {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{image_b64}"}},
322
+ {"type": "image_url", "image_url": {"url": f"data:{mime_type};base64,{image_b64}"}},
323
]
324
raw_message = history.RawMessage(raw_content=content, preview=summary)
325
self.agent.hist_add_message(False, content=raw_message, tokens=CAPTURE_TOKENS_ESTIMATE)
@@ -393,18 +399,42 @@ class ComputerUseRemote(Tool):
399
return preview
400
return ""
401
396
- def _capture_image_base64(self, data: dict[str, Any]) -> str:
402
+ def _capture_image_data(self, data: dict[str, Any]) -> tuple[str, str]:
403
+ image_bytes = self._capture_image_bytes(data)
404
+ optimized_bytes = self._optimize_capture_image(image_bytes)
405
+ if optimized_bytes is not None:
406
+ return "image/jpeg", base64.b64encode(optimized_bytes).decode("utf-8")
407
+ return "image/png", base64.b64encode(image_bytes).decode("utf-8")
408
+
409
+ def _capture_image_bytes(self, data: dict[str, Any]) -> bytes:
410
inline_payload = str(data.get("png_base64", "") or "").strip()
411
if inline_payload:
412
try:
400
- base64.b64decode(inline_payload, validate=True)
413
+ return base64.b64decode(inline_payload, validate=True)
414
except Exception:
415
pass
403
- else:
404
- return inline_payload
416
417
image_path, _display_path = self._resolve_capture_path(data)
407
- return base64.b64encode(image_path.read_bytes()).decode("utf-8")
418
+ return image_path.read_bytes()
419
+
420
+ def _optimize_capture_image(self, image_bytes: bytes) -> bytes | None:
421
+ try:
422
+ image = Image.open(io.BytesIO(image_bytes))
423
+ current_pixels = image.width * image.height
424
+ if current_pixels > CAPTURE_MAX_PIXELS:
425
+ scale = math.sqrt(CAPTURE_MAX_PIXELS / current_pixels)
426
+ resized = (
427
+ max(1, int(image.width * scale)),
428
+ max(1, int(image.height * scale)),
429
+ )
430
+ image = image.resize(resized, Image.Resampling.LANCZOS)
431
+ if image.mode not in {"RGB", "L"}:
432
+ image = image.convert("RGB")
433
+ output = io.BytesIO()
434
+ image.save(output, format="JPEG", quality=CAPTURE_JPEG_QUALITY, optimize=True)
435
+ return output.getvalue()
436
+ except Exception:
437
+ return None
438
439
def _resolve_capture_path(self, data: dict[str, Any]) -> tuple[Path, str]:
440
candidates = [