orgo 0.0.11__tar.gz → 0.0.12__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {orgo-0.0.11 → orgo-0.0.12}/PKG-INFO +1 -1
- {orgo-0.0.11 → orgo-0.0.12}/pyproject.toml +1 -1
- {orgo-0.0.11 → orgo-0.0.12}/src/orgo/prompt.py +56 -27
- {orgo-0.0.11 → orgo-0.0.12}/src/orgo.egg-info/PKG-INFO +1 -1
- {orgo-0.0.11 → orgo-0.0.12}/README.md +0 -0
- {orgo-0.0.11 → orgo-0.0.12}/setup.cfg +0 -0
- {orgo-0.0.11 → orgo-0.0.12}/src/orgo/__init__.py +0 -0
- {orgo-0.0.11 → orgo-0.0.12}/src/orgo/adapters/__init__.py +0 -0
- {orgo-0.0.11 → orgo-0.0.12}/src/orgo/adapters/anthropic.py +0 -0
- {orgo-0.0.11 → orgo-0.0.12}/src/orgo/adapters/base.py +0 -0
- {orgo-0.0.11 → orgo-0.0.12}/src/orgo/adapters/openai.py +0 -0
- {orgo-0.0.11 → orgo-0.0.12}/src/orgo/api/__init__.py +0 -0
- {orgo-0.0.11 → orgo-0.0.12}/src/orgo/api/client.py +0 -0
- {orgo-0.0.11 → orgo-0.0.12}/src/orgo/computer.py +0 -0
- {orgo-0.0.11 → orgo-0.0.12}/src/orgo/utils/__init__.py +0 -0
- {orgo-0.0.11 → orgo-0.0.12}/src/orgo/utils/auth.py +0 -0
- {orgo-0.0.11 → orgo-0.0.12}/src/orgo.egg-info/SOURCES.txt +0 -0
- {orgo-0.0.11 → orgo-0.0.12}/src/orgo.egg-info/dependency_links.txt +0 -0
- {orgo-0.0.11 → orgo-0.0.12}/src/orgo.egg-info/requires.txt +0 -0
- {orgo-0.0.11 → orgo-0.0.12}/src/orgo.egg-info/top_level.txt +0 -0
|
@@ -3,6 +3,7 @@ Prompt module for interacting with virtual computers using AI models.
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
|
+
import base64
|
|
6
7
|
from typing import Dict, List, Any, Optional, Callable, Union, Protocol
|
|
7
8
|
|
|
8
9
|
|
|
@@ -105,7 +106,14 @@ class AnthropicProvider:
|
|
|
105
106
|
- File browser items: DOUBLE-CLICK to open folders and files
|
|
106
107
|
- When submitting, use the 'Enter' key, not the 'Return' key.
|
|
107
108
|
* If you see an icon on the desktop that you need to open, ALWAYS use the double_click action, never use left_click.
|
|
108
|
-
</UBUNTU_DESKTOP_GUIDELINES>
|
|
109
|
+
</UBUNTU_DESKTOP_GUIDELINES>
|
|
110
|
+
|
|
111
|
+
<SCREENSHOT_GUIDELINES>
|
|
112
|
+
* Be mindful of how many screenshots you take - they consume significant memory.
|
|
113
|
+
* Only take screenshots when you need to see the current state of the screen.
|
|
114
|
+
* Try to batch multiple actions before taking another screenshot.
|
|
115
|
+
* For better performance, limit the number of screenshots you take.
|
|
116
|
+
</SCREENSHOT_GUIDELINES>"""
|
|
109
117
|
|
|
110
118
|
try:
|
|
111
119
|
# Define the computer tool per Anthropic's documentation
|
|
@@ -138,9 +146,9 @@ class AnthropicProvider:
|
|
|
138
146
|
while iteration < max_iterations:
|
|
139
147
|
iteration += 1
|
|
140
148
|
|
|
141
|
-
#
|
|
149
|
+
# Filter to keep only the N most recent screenshots
|
|
142
150
|
if screenshot_count > max_saved_screenshots:
|
|
143
|
-
self.
|
|
151
|
+
self._filter_to_n_most_recent_images(messages, max_saved_screenshots)
|
|
144
152
|
screenshot_count = max_saved_screenshots
|
|
145
153
|
|
|
146
154
|
# Create the request parameters
|
|
@@ -161,7 +169,20 @@ class AnthropicProvider:
|
|
|
161
169
|
}
|
|
162
170
|
|
|
163
171
|
# Create message request to Claude
|
|
164
|
-
|
|
172
|
+
try:
|
|
173
|
+
response = client.beta.messages.create(**request_params)
|
|
174
|
+
except Exception as e:
|
|
175
|
+
if "base64" in str(e).lower():
|
|
176
|
+
# If we get a base64 error, try again after more aggressively filtering images
|
|
177
|
+
if callback:
|
|
178
|
+
callback("error", f"Base64 error detected. Attempting recovery...")
|
|
179
|
+
|
|
180
|
+
# Remove all but the most recent image and try again
|
|
181
|
+
self._filter_to_n_most_recent_images(messages, 1)
|
|
182
|
+
response = client.beta.messages.create(**request_params)
|
|
183
|
+
else:
|
|
184
|
+
# Not a base64 error, re-raise
|
|
185
|
+
raise
|
|
165
186
|
|
|
166
187
|
# Extract the content from the response
|
|
167
188
|
response_content = response.content
|
|
@@ -226,49 +247,57 @@ class AnthropicProvider:
|
|
|
226
247
|
if callback:
|
|
227
248
|
callback("error", str(e))
|
|
228
249
|
raise
|
|
229
|
-
|
|
230
|
-
def
|
|
250
|
+
|
|
251
|
+
def _filter_to_n_most_recent_images(self, messages: List[Dict[str, Any]], max_images: int):
|
|
231
252
|
"""
|
|
232
|
-
|
|
253
|
+
Keep only the N most recent images in the conversation history.
|
|
233
254
|
|
|
234
255
|
Args:
|
|
235
256
|
messages: The conversation history
|
|
236
|
-
|
|
257
|
+
max_images: Maximum number of images to keep
|
|
237
258
|
"""
|
|
238
|
-
|
|
259
|
+
# Find all the image blocks in the conversation history
|
|
260
|
+
image_blocks = []
|
|
239
261
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if messages[i]["role"] != "user":
|
|
262
|
+
for msg_idx, msg in enumerate(messages):
|
|
263
|
+
if msg["role"] != "user":
|
|
243
264
|
continue
|
|
244
265
|
|
|
245
|
-
content =
|
|
266
|
+
content = msg.get("content", [])
|
|
246
267
|
if not isinstance(content, list):
|
|
247
268
|
continue
|
|
248
269
|
|
|
249
|
-
|
|
250
|
-
for j, block in enumerate(content):
|
|
270
|
+
for content_idx, block in enumerate(content):
|
|
251
271
|
if not isinstance(block, dict):
|
|
252
272
|
continue
|
|
253
273
|
|
|
254
274
|
if block.get("type") != "tool_result":
|
|
255
275
|
continue
|
|
256
|
-
|
|
257
|
-
# Check if this tool_result contains an image
|
|
276
|
+
|
|
258
277
|
block_content = block.get("content", [])
|
|
259
|
-
for
|
|
278
|
+
for content_item_idx, content_item in enumerate(block_content):
|
|
260
279
|
if not isinstance(content_item, dict):
|
|
261
280
|
continue
|
|
262
281
|
|
|
263
|
-
if content_item.get("type") == "image":
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
282
|
+
if content_item.get("type") == "image" and "source" in content_item:
|
|
283
|
+
image_blocks.append({
|
|
284
|
+
"msg_idx": msg_idx,
|
|
285
|
+
"content_idx": content_idx,
|
|
286
|
+
"block": block,
|
|
287
|
+
"content_item_idx": content_item_idx,
|
|
288
|
+
"content_item": content_item
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
# If we have more images than our limit, remove the oldest ones
|
|
292
|
+
if len(image_blocks) > max_images:
|
|
293
|
+
# Keep only the most recent ones (which are at the end of the list)
|
|
294
|
+
images_to_remove = image_blocks[:-max_images]
|
|
295
|
+
|
|
296
|
+
for img_block in images_to_remove:
|
|
297
|
+
content_item = img_block["content_item"]
|
|
298
|
+
if "source" in content_item and "data" in content_item["source"]:
|
|
299
|
+
# Replace the base64 data with a placeholder
|
|
300
|
+
content_item["source"]["data"] = "[IMAGE DATA REMOVED]"
|
|
272
301
|
|
|
273
302
|
def _execute_tool(self,
|
|
274
303
|
computer_id: str,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|