cua-computer 0.2.4__tar.gz → 0.2.6__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.
Files changed (28) hide show
  1. {cua_computer-0.2.4 → cua_computer-0.2.6}/PKG-INFO +1 -1
  2. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/interface/linux.py +31 -34
  3. {cua_computer-0.2.4 → cua_computer-0.2.6}/pyproject.toml +3 -3
  4. {cua_computer-0.2.4 → cua_computer-0.2.6}/README.md +0 -0
  5. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/__init__.py +0 -0
  6. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/computer.py +0 -0
  7. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/interface/__init__.py +0 -0
  8. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/interface/base.py +0 -0
  9. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/interface/factory.py +0 -0
  10. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/interface/macos.py +0 -0
  11. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/interface/models.py +0 -0
  12. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/logger.py +0 -0
  13. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/models.py +0 -0
  14. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/providers/__init__.py +0 -0
  15. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/providers/base.py +0 -0
  16. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/providers/cloud/__init__.py +0 -0
  17. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/providers/cloud/provider.py +0 -0
  18. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/providers/factory.py +0 -0
  19. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/providers/lume/__init__.py +0 -0
  20. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/providers/lume/provider.py +0 -0
  21. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/providers/lume_api.py +0 -0
  22. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/providers/lumier/__init__.py +0 -0
  23. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/providers/lumier/provider.py +0 -0
  24. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/telemetry.py +0 -0
  25. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/ui/__init__.py +0 -0
  26. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/ui/gradio/__init__.py +0 -0
  27. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/ui/gradio/app.py +0 -0
  28. {cua_computer-0.2.4 → cua_computer-0.2.6}/computer/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cua-computer
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: Computer-Use Interface (CUI) framework powering Cua
5
5
  Author-Email: TryCua <gh@trycua.com>
6
6
  Requires-Python: >=3.10
@@ -26,6 +26,7 @@ class LinuxComputerInterface(BaseComputerInterface):
26
26
  self._reconnect_delay = 1 # Start with 1 second delay
27
27
  self._max_reconnect_delay = 30 # Maximum delay between reconnection attempts
28
28
  self._log_connection_attempts = True # Flag to control connection attempt logging
29
+ self._authenticated = False # Track authentication status
29
30
 
30
31
  # Set logger name for Linux interface
31
32
  self.logger = Logger("cua.interface.linux", LogLevel.NORMAL)
@@ -89,34 +90,14 @@ class LinuxComputerInterface(BaseComputerInterface):
89
90
  )
90
91
  self.logger.info("WebSocket connection established")
91
92
 
92
- # If api_key and vm_name are provided, perform authentication handshake
93
- if self.api_key and self.vm_name:
94
- self.logger.info("Performing authentication handshake...")
95
- auth_message = {
96
- "command": "authenticate",
97
- "params": {
98
- "api_key": self.api_key,
99
- "container_name": self.vm_name
100
- }
101
- }
102
- await self._ws.send(json.dumps(auth_message))
103
-
104
- # Wait for authentication response
105
- auth_response = await asyncio.wait_for(self._ws.recv(), timeout=10)
106
- auth_result = json.loads(auth_response)
107
-
108
- if not auth_result.get("success"):
109
- error_msg = auth_result.get("error", "Authentication failed")
110
- self.logger.error(f"Authentication failed: {error_msg}")
111
- await self._ws.close()
112
- self._ws = None
113
- raise ConnectionError(f"Authentication failed: {error_msg}")
114
-
115
- self.logger.info("Authentication successful")
93
+ # Authentication will be handled by the first command that needs it
94
+ # Don't do authentication here to avoid recv conflicts
116
95
 
117
96
  self._reconnect_delay = 1 # Reset reconnect delay on successful connection
118
97
  self._last_ping = time.time()
119
98
  retry_count = 0 # Reset retry count on successful connection
99
+ self._authenticated = False # Reset auth status on new connection
100
+
120
101
  except (asyncio.TimeoutError, websockets.exceptions.WebSocketException) as e:
121
102
  next_retry = self._reconnect_delay
122
103
 
@@ -140,13 +121,6 @@ class LinuxComputerInterface(BaseComputerInterface):
140
121
  pass
141
122
  self._ws = None
142
123
 
143
- # Use exponential backoff for connection retries
144
- await asyncio.sleep(self._reconnect_delay)
145
- self._reconnect_delay = min(
146
- self._reconnect_delay * 2, self._max_reconnect_delay
147
- )
148
- continue
149
-
150
124
  # Regular ping to check connection
151
125
  if self._ws and self._ws.state == websockets.protocol.State.OPEN:
152
126
  try:
@@ -225,6 +199,31 @@ class LinuxComputerInterface(BaseComputerInterface):
225
199
  if not self._ws:
226
200
  raise ConnectionError("WebSocket connection is not established")
227
201
 
202
+ # Handle authentication if needed
203
+ if self.api_key and self.vm_name and not self._authenticated:
204
+ self.logger.info("Performing authentication handshake...")
205
+ auth_message = {
206
+ "command": "authenticate",
207
+ "params": {
208
+ "api_key": self.api_key,
209
+ "container_name": self.vm_name
210
+ }
211
+ }
212
+ await self._ws.send(json.dumps(auth_message))
213
+
214
+ # Wait for authentication response
215
+ auth_response = await asyncio.wait_for(self._ws.recv(), timeout=10)
216
+ auth_result = json.loads(auth_response)
217
+
218
+ if not auth_result.get("success"):
219
+ error_msg = auth_result.get("error", "Authentication failed")
220
+ self.logger.error(f"Authentication failed: {error_msg}")
221
+ self._authenticated = False
222
+ raise ConnectionError(f"Authentication failed: {error_msg}")
223
+
224
+ self.logger.info("Authentication successful")
225
+ self._authenticated = True
226
+
228
227
  message = {"command": command, "params": params or {}}
229
228
  await self._ws.send(json.dumps(message))
230
229
  response = await asyncio.wait_for(self._ws.recv(), timeout=30)
@@ -245,9 +244,7 @@ class LinuxComputerInterface(BaseComputerInterface):
245
244
  f"Failed to send command '{command}' after {max_retries} retries"
246
245
  )
247
246
  self.logger.debug(f"Command failure details: {e}")
248
- raise
249
-
250
- raise last_error if last_error else RuntimeError("Failed to send command")
247
+ raise last_error if last_error else RuntimeError("Failed to send command")
251
248
 
252
249
  async def wait_for_ready(self, timeout: int = 60, interval: float = 1.0):
253
250
  """Wait for WebSocket connection to become available."""
@@ -6,7 +6,7 @@ build-backend = "pdm.backend"
6
6
 
7
7
  [project]
8
8
  name = "cua-computer"
9
- version = "0.2.4"
9
+ version = "0.2.6"
10
10
  description = "Computer-Use Interface (CUI) framework powering Cua"
11
11
  readme = "README.md"
12
12
  authors = [
@@ -57,7 +57,7 @@ target-version = [
57
57
 
58
58
  [tool.ruff]
59
59
  line-length = 100
60
- target-version = "0.2.4"
60
+ target-version = "0.2.6"
61
61
  select = [
62
62
  "E",
63
63
  "F",
@@ -71,7 +71,7 @@ docstring-code-format = true
71
71
 
72
72
  [tool.mypy]
73
73
  strict = true
74
- python_version = "0.2.4"
74
+ python_version = "0.2.6"
75
75
  ignore_missing_imports = true
76
76
  disallow_untyped_defs = true
77
77
  check_untyped_defs = true
File without changes