cua-agent 0.2.7__tar.gz → 0.2.9__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.

Potentially problematic release.


This version of cua-agent might be problematic. Click here for more details.

Files changed (85) hide show
  1. {cua_agent-0.2.7 → cua_agent-0.2.9}/PKG-INFO +1 -1
  2. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/__init__.py +2 -2
  3. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/messages.py +1 -100
  4. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/loop.py +5 -1
  5. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/openai/loop.py +2 -2
  6. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/uitars/clients/oaicompat.py +4 -2
  7. {cua_agent-0.2.7 → cua_agent-0.2.9}/pyproject.toml +3 -3
  8. {cua_agent-0.2.7 → cua_agent-0.2.9}/README.md +0 -0
  9. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/__init__.py +0 -0
  10. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/agent.py +0 -0
  11. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/base.py +0 -0
  12. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/callbacks.py +0 -0
  13. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/experiment.py +0 -0
  14. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/factory.py +0 -0
  15. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/provider_config.py +0 -0
  16. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/telemetry.py +0 -0
  17. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/tools/__init__.py +0 -0
  18. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/tools/base.py +0 -0
  19. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/tools/bash.py +0 -0
  20. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/tools/collection.py +0 -0
  21. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/tools/computer.py +0 -0
  22. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/tools/edit.py +0 -0
  23. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/tools/manager.py +0 -0
  24. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/tools.py +0 -0
  25. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/types.py +0 -0
  26. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/core/visualization.py +0 -0
  27. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/__init__.py +0 -0
  28. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/__init__.py +0 -0
  29. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/api/client.py +0 -0
  30. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/api/logging.py +0 -0
  31. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/api_handler.py +0 -0
  32. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/callbacks/__init__.py +0 -0
  33. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/callbacks/manager.py +0 -0
  34. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/prompts.py +0 -0
  35. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/response_handler.py +0 -0
  36. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/tools/__init__.py +0 -0
  37. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/tools/base.py +0 -0
  38. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/tools/bash.py +0 -0
  39. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/tools/collection.py +0 -0
  40. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/tools/computer.py +0 -0
  41. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/tools/edit.py +0 -0
  42. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/tools/manager.py +0 -0
  43. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/tools/run.py +0 -0
  44. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/types.py +0 -0
  45. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/anthropic/utils.py +0 -0
  46. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/__init__.py +0 -0
  47. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/api_handler.py +0 -0
  48. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/clients/anthropic.py +0 -0
  49. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/clients/base.py +0 -0
  50. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/clients/oaicompat.py +0 -0
  51. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/clients/ollama.py +0 -0
  52. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/clients/openai.py +0 -0
  53. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/clients/utils.py +0 -0
  54. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/image_utils.py +0 -0
  55. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/loop.py +0 -0
  56. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/parser.py +0 -0
  57. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/prompts.py +0 -0
  58. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/tools/__init__.py +0 -0
  59. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/tools/base.py +0 -0
  60. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/tools/bash.py +0 -0
  61. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/tools/computer.py +0 -0
  62. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/tools/manager.py +0 -0
  63. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/omni/utils.py +0 -0
  64. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/openai/__init__.py +0 -0
  65. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/openai/api_handler.py +0 -0
  66. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/openai/response_handler.py +0 -0
  67. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/openai/tools/__init__.py +0 -0
  68. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/openai/tools/base.py +0 -0
  69. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/openai/tools/computer.py +0 -0
  70. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/openai/tools/manager.py +0 -0
  71. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/openai/types.py +0 -0
  72. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/openai/utils.py +0 -0
  73. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/uitars/__init__.py +0 -0
  74. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/uitars/clients/base.py +0 -0
  75. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/uitars/clients/mlxvlm.py +0 -0
  76. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/uitars/loop.py +0 -0
  77. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/uitars/prompts.py +0 -0
  78. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/uitars/tools/__init__.py +0 -0
  79. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/uitars/tools/computer.py +0 -0
  80. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/uitars/tools/manager.py +0 -0
  81. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/providers/uitars/utils.py +0 -0
  82. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/telemetry.py +0 -0
  83. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/ui/__init__.py +0 -0
  84. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/ui/gradio/__init__.py +0 -0
  85. {cua_agent-0.2.7 → cua_agent-0.2.9}/agent/ui/gradio/app.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cua-agent
3
- Version: 0.2.7
3
+ Version: 0.2.9
4
4
  Summary: CUA (Computer Use) Agent for AI-driven computer interaction
5
5
  Author-Email: TryCua <gh@trycua.com>
6
6
  Requires-Python: >=3.11
@@ -2,7 +2,7 @@
2
2
 
3
3
  from .factory import BaseLoop
4
4
  from .messages import (
5
- BaseMessageManager,
5
+ StandardMessageManager,
6
6
  ImageRetentionConfig,
7
7
  )
8
8
  from .callbacks import (
@@ -18,7 +18,7 @@ __all__ = [
18
18
  "BaseLoop",
19
19
  "CallbackManager",
20
20
  "CallbackHandler",
21
- "BaseMessageManager",
21
+ "StandardMessageManager",
22
22
  "ImageRetentionConfig",
23
23
  "BaseCallbackManager",
24
24
  "ContentCallback",
@@ -22,106 +22,6 @@ class ImageRetentionConfig:
22
22
  """Check if image retention is enabled."""
23
23
  return self.num_images_to_keep is not None and self.num_images_to_keep > 0
24
24
 
25
-
26
- class BaseMessageManager:
27
- """Base class for message preparation and management."""
28
-
29
- def __init__(self, image_retention_config: Optional[ImageRetentionConfig] = None):
30
- """Initialize the message manager.
31
-
32
- Args:
33
- image_retention_config: Configuration for image retention
34
- """
35
- self.image_retention_config = image_retention_config or ImageRetentionConfig()
36
- if self.image_retention_config.min_removal_threshold < 1:
37
- raise ValueError("min_removal_threshold must be at least 1")
38
-
39
- # Track provider for message formatting
40
- self.provider = "openai" # Default provider
41
-
42
- def set_provider(self, provider: str) -> None:
43
- """Set the current provider to format messages for.
44
-
45
- Args:
46
- provider: Provider name (e.g., 'openai', 'anthropic')
47
- """
48
- self.provider = provider.lower()
49
-
50
- def prepare_messages(self, messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
51
- """Prepare messages by applying image retention and caching as configured.
52
-
53
- Args:
54
- messages: List of messages to prepare
55
-
56
- Returns:
57
- Prepared messages
58
- """
59
- if self.image_retention_config.should_retain_images():
60
- self._filter_images(messages)
61
- if self.image_retention_config.enable_caching:
62
- self._inject_caching(messages)
63
- return messages
64
-
65
- def _filter_images(self, messages: List[Dict[str, Any]]) -> None:
66
- """Filter messages to retain only the specified number of most recent images.
67
-
68
- Args:
69
- messages: Messages to filter
70
- """
71
- # Find all tool result blocks that contain images
72
- tool_results = [
73
- item
74
- for message in messages
75
- for item in (message["content"] if isinstance(message["content"], list) else [])
76
- if isinstance(item, dict) and item.get("type") == "tool_result"
77
- ]
78
-
79
- # Count total images
80
- total_images = sum(
81
- 1
82
- for result in tool_results
83
- for content in result.get("content", [])
84
- if isinstance(content, dict) and content.get("type") == "image"
85
- )
86
-
87
- # Calculate how many images to remove
88
- images_to_remove = total_images - (self.image_retention_config.num_images_to_keep or 0)
89
- images_to_remove -= images_to_remove % self.image_retention_config.min_removal_threshold
90
-
91
- # Remove oldest images first
92
- for result in tool_results:
93
- if isinstance(result.get("content"), list):
94
- new_content = []
95
- for content in result["content"]:
96
- if isinstance(content, dict) and content.get("type") == "image":
97
- if images_to_remove > 0:
98
- images_to_remove -= 1
99
- continue
100
- new_content.append(content)
101
- result["content"] = new_content
102
-
103
- def _inject_caching(self, messages: List[Dict[str, Any]]) -> None:
104
- """Inject caching control for recent message turns.
105
-
106
- Args:
107
- messages: Messages to inject caching into
108
- """
109
- # Only apply cache_control for Anthropic API, not OpenAI
110
- if self.provider != "anthropic":
111
- return
112
-
113
- # Default to caching last 3 turns
114
- turns_to_cache = 3
115
- for message in reversed(messages):
116
- if message["role"] == "user" and isinstance(content := message["content"], list):
117
- if turns_to_cache:
118
- turns_to_cache -= 1
119
- content[-1]["cache_control"] = {"type": "ephemeral"}
120
- else:
121
- content[-1].pop("cache_control", None)
122
- break
123
-
124
-
125
25
  class StandardMessageManager:
126
26
  """Manages messages in a standardized OpenAI format across different providers."""
127
27
 
@@ -160,6 +60,7 @@ class StandardMessageManager:
160
60
 
161
61
  def get_messages(self) -> List[Dict[str, Any]]:
162
62
  """Get all messages in standard format.
63
+ This method applies image retention policy if configured.
163
64
 
164
65
  Returns:
165
66
  List of messages
@@ -283,8 +283,12 @@ class AnthropicLoop(BaseLoop):
283
283
  # Create new turn directory for this API call
284
284
  self._create_turn_dir()
285
285
 
286
+
287
+ # Apply image retention policy
288
+ self.message_manager.messages = messages.copy()
289
+ prepared_messages = self.message_manager.get_messages()
286
290
  # Convert standard messages to Anthropic format using utility function
287
- anthropic_messages, system_content = to_anthropic_format(messages.copy())
291
+ anthropic_messages, system_content = to_anthropic_format(prepared_messages)
288
292
 
289
293
  # Use API handler to make API call with Anthropic format
290
294
  response = await self.api_handler.make_api_call(
@@ -276,7 +276,7 @@ class OpenAILoop(BaseLoop):
276
276
  # Call API
277
277
  screen_size = await self.computer.interface.get_screen_size()
278
278
  response = await self.api_handler.send_initial_request(
279
- messages=messages,
279
+ messages=self.message_manager.get_messages(), # Apply image retention policy
280
280
  display_width=str(screen_size["width"]),
281
281
  display_height=str(screen_size["height"]),
282
282
  previous_response_id=self.last_response_id,
@@ -397,7 +397,7 @@ class OpenAILoop(BaseLoop):
397
397
  # The API handler will extract this from the message history
398
398
  if isinstance(self.last_response_id, str):
399
399
  response = await self.api_handler.send_computer_call_request(
400
- messages=self.message_manager.messages,
400
+ messages=self.message_manager.get_messages(), # Apply image retention policy
401
401
  display_width=str(screen_size["width"]),
402
402
  display_height=str(screen_size["height"]),
403
403
  previous_response_id=self.last_response_id, # Use instance variable
@@ -6,6 +6,7 @@ from typing import Dict, List, Optional, Any
6
6
  import aiohttp
7
7
  import re
8
8
  from .base import BaseUITarsClient
9
+ import asyncio
9
10
 
10
11
  logger = logging.getLogger(__name__)
11
12
 
@@ -144,7 +145,7 @@ class OAICompatClient(BaseUITarsClient):
144
145
  else:
145
146
  message = {"role": "user", "content": [{"type": "text", "text": item}]}
146
147
  final_messages.append(message)
147
-
148
+
148
149
  payload = {
149
150
  "model": self.model,
150
151
  "messages": final_messages,
@@ -192,7 +193,8 @@ class OAICompatClient(BaseUITarsClient):
192
193
 
193
194
  # if 503, then the endpoint is still warming up
194
195
  if response.status == 503:
195
- logger.error(f"Endpoint is still warming up, please try again later")
196
+ logger.error(f"Endpoint is still warming up, trying again in 30 seconds...")
197
+ await asyncio.sleep(30)
196
198
  raise Exception(f"Endpoint is still warming up: {response_text}")
197
199
 
198
200
  # Try to parse as JSON if the content type is appropriate
@@ -6,7 +6,7 @@ build-backend = "pdm.backend"
6
6
 
7
7
  [project]
8
8
  name = "cua-agent"
9
- version = "0.2.7"
9
+ version = "0.2.9"
10
10
  description = "CUA (Computer Use) Agent for AI-driven computer interaction"
11
11
  readme = "README.md"
12
12
  authors = [
@@ -109,7 +109,7 @@ target-version = [
109
109
 
110
110
  [tool.ruff]
111
111
  line-length = 100
112
- target-version = "0.2.7"
112
+ target-version = "0.2.9"
113
113
  select = [
114
114
  "E",
115
115
  "F",
@@ -123,7 +123,7 @@ docstring-code-format = true
123
123
 
124
124
  [tool.mypy]
125
125
  strict = true
126
- python_version = "0.2.7"
126
+ python_version = "0.2.9"
127
127
  ignore_missing_imports = true
128
128
  disallow_untyped_defs = true
129
129
  check_untyped_defs = true
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes