Amir Mahla commited on
Commit
7803f5c
·
1 Parent(s): c083612

FIX Max Payload request error

Browse files
cua2-core/src/cua2_core/services/agent_service.py CHANGED
@@ -21,6 +21,7 @@ from cua2_core.services.agent_utils.function_parser import parse_function_call
21
  from cua2_core.services.agent_utils.get_model import get_model
22
  from cua2_core.services.archival_service import ArchivalService
23
  from cua2_core.services.sandbox_service import SandboxService
 
24
  from cua2_core.websocket.websocket_manager import WebSocketException, WebSocketManager
25
  from e2b_desktop import Sandbox, TimeoutException
26
  from fastapi import WebSocket
@@ -413,6 +414,7 @@ class AgentService:
413
  step_filename = f"{message_id}-{memory_step.step_number + 1}"
414
  screenshot_bytes = agent.desktop.screenshot()
415
  image = Image.open(BytesIO(screenshot_bytes))
 
416
 
417
  for previous_memory_step in (
418
  agent.memory.steps
 
21
  from cua2_core.services.agent_utils.get_model import get_model
22
  from cua2_core.services.archival_service import ArchivalService
23
  from cua2_core.services.sandbox_service import SandboxService
24
+ from cua2_core.services.utils import compress_image_to_max_size
25
  from cua2_core.websocket.websocket_manager import WebSocketException, WebSocketManager
26
  from e2b_desktop import Sandbox, TimeoutException
27
  from fastapi import WebSocket
 
414
  step_filename = f"{message_id}-{memory_step.step_number + 1}"
415
  screenshot_bytes = agent.desktop.screenshot()
416
  image = Image.open(BytesIO(screenshot_bytes))
417
+ image = compress_image_to_max_size(image, max_size_kb=500)
418
 
419
  for previous_memory_step in (
420
  agent.memory.steps
cua2-core/src/cua2_core/services/utils.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Utility functions for services."""
2
+
3
+ from io import BytesIO
4
+
5
+ from PIL import Image
6
+
7
+
8
+ def compress_image_to_max_size(
9
+ image: Image.Image, max_size_kb: int = 800
10
+ ) -> Image.Image:
11
+ """
12
+ Compress an image to ensure it doesn't exceed max_size_kb.
13
+ Always returns a PIL Image in PNG format.
14
+ Resizes the image if necessary to meet the size requirement.
15
+
16
+ Args:
17
+ image: PIL Image to compress
18
+ max_size_kb: Maximum size in KB (default: 800KB)
19
+
20
+ Returns:
21
+ PIL Image in PNG format that meets the size requirement
22
+ """
23
+ max_size_bytes = max_size_kb * 1024
24
+ current_image = image.copy()
25
+
26
+ # Try PNG compression first with different compression levels
27
+ for compress_level in [3, 6, 9]:
28
+ buffered = BytesIO()
29
+ current_image.save(buffered, format="PNG", compress_level=compress_level)
30
+ png_size = buffered.tell()
31
+ if png_size <= max_size_bytes:
32
+ # Size is acceptable, return the image as-is (it's already in PNG format when saved)
33
+ return current_image
34
+
35
+ # PNG is too large even with maximum compression, need to resize
36
+ # Binary search for the right size
37
+ scale_factor = 1.0
38
+ min_scale = 0.1
39
+ max_scale = 1.0
40
+ iterations = 0
41
+ max_iterations = 10
42
+ best_image = None
43
+
44
+ while iterations < max_iterations:
45
+ # Resize image
46
+ new_size = (
47
+ int(image.size[0] * scale_factor),
48
+ int(image.size[1] * scale_factor),
49
+ )
50
+ resized_image = image.resize(new_size, Image.Resampling.LANCZOS)
51
+
52
+ # Check PNG size with best compression
53
+ buffered = BytesIO()
54
+ resized_image.save(buffered, format="PNG", compress_level=9)
55
+ png_size = buffered.tell()
56
+
57
+ if png_size <= max_size_bytes:
58
+ # Found acceptable size
59
+ best_image = resized_image
60
+ # Try slightly larger for better quality
61
+ if scale_factor >= max_scale - 0.01: # Close enough to max
62
+ return resized_image
63
+ # Try larger scale
64
+ min_scale = scale_factor
65
+ scale_factor = (scale_factor + max_scale) / 2
66
+ else:
67
+ # Too large, need smaller scale
68
+ max_scale = scale_factor
69
+ scale_factor = (min_scale + scale_factor) / 2
70
+
71
+ iterations += 1
72
+
73
+ # Return the best image found, or resize to minimum scale if none worked
74
+ if best_image is not None:
75
+ return best_image
76
+
77
+ # Final fallback: resize to minimum scale
78
+ final_size = (
79
+ int(image.size[0] * min_scale),
80
+ int(image.size[1] * min_scale),
81
+ )
82
+ final_image = image.resize(final_size, Image.Resampling.LANCZOS)
83
+ return final_image