cua-computer 0.2.5__tar.gz → 0.2.7__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.
- {cua_computer-0.2.5 → cua_computer-0.2.7}/PKG-INFO +2 -2
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/interface/linux.py +31 -34
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/providers/base.py +2 -2
- {cua_computer-0.2.5 → cua_computer-0.2.7}/pyproject.toml +5 -5
- {cua_computer-0.2.5 → cua_computer-0.2.7}/README.md +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/__init__.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/computer.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/interface/__init__.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/interface/base.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/interface/factory.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/interface/macos.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/interface/models.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/logger.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/models.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/providers/__init__.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/providers/cloud/__init__.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/providers/cloud/provider.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/providers/factory.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/providers/lume/__init__.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/providers/lume/provider.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/providers/lume_api.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/providers/lumier/__init__.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/providers/lumier/provider.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/telemetry.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/ui/__init__.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/ui/gradio/__init__.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/ui/gradio/app.py +0 -0
- {cua_computer-0.2.5 → cua_computer-0.2.7}/computer/utils.py +0 -0
@@ -1,9 +1,9 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: cua-computer
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.7
|
4
4
|
Summary: Computer-Use Interface (CUI) framework powering Cua
|
5
5
|
Author-Email: TryCua <gh@trycua.com>
|
6
|
-
Requires-Python: >=3.
|
6
|
+
Requires-Python: >=3.11
|
7
7
|
Requires-Dist: pillow>=10.0.0
|
8
8
|
Requires-Dist: websocket-client>=1.8.0
|
9
9
|
Requires-Dist: websockets>=12.0
|
@@ -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
|
-
#
|
93
|
-
|
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
|
-
|
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."""
|
@@ -1,11 +1,11 @@
|
|
1
1
|
"""Base provider interface for VM backends."""
|
2
2
|
|
3
3
|
import abc
|
4
|
-
from enum import
|
4
|
+
from enum import StrEnum
|
5
5
|
from typing import Dict, List, Optional, Any, AsyncContextManager
|
6
6
|
|
7
7
|
|
8
|
-
class VMProviderType(
|
8
|
+
class VMProviderType(StrEnum):
|
9
9
|
"""Enum of supported VM provider types."""
|
10
10
|
LUME = "lume"
|
11
11
|
LUMIER = "lumier"
|
@@ -6,7 +6,7 @@ build-backend = "pdm.backend"
|
|
6
6
|
|
7
7
|
[project]
|
8
8
|
name = "cua-computer"
|
9
|
-
version = "0.2.
|
9
|
+
version = "0.2.7"
|
10
10
|
description = "Computer-Use Interface (CUI) framework powering Cua"
|
11
11
|
readme = "README.md"
|
12
12
|
authors = [
|
@@ -20,7 +20,7 @@ dependencies = [
|
|
20
20
|
"cua-core>=0.1.0,<0.2.0",
|
21
21
|
"pydantic>=2.11.1",
|
22
22
|
]
|
23
|
-
requires-python = ">=3.
|
23
|
+
requires-python = ">=3.11"
|
24
24
|
|
25
25
|
[project.optional-dependencies]
|
26
26
|
lume = []
|
@@ -52,12 +52,12 @@ source-includes = [
|
|
52
52
|
[tool.black]
|
53
53
|
line-length = 100
|
54
54
|
target-version = [
|
55
|
-
"
|
55
|
+
"py311",
|
56
56
|
]
|
57
57
|
|
58
58
|
[tool.ruff]
|
59
59
|
line-length = 100
|
60
|
-
target-version = "0.2.
|
60
|
+
target-version = "0.2.7"
|
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.
|
74
|
+
python_version = "0.2.7"
|
75
75
|
ignore_missing_imports = true
|
76
76
|
disallow_untyped_defs = true
|
77
77
|
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
|
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
|
File without changes
|