cua-computer 0.3.2__py3-none-any.whl → 0.3.3__py3-none-any.whl
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.
- computer/interface/base.py +201 -44
- computer/interface/generic.py +50 -19
- {cua_computer-0.3.2.dist-info → cua_computer-0.3.3.dist-info}/METADATA +1 -1
- {cua_computer-0.3.2.dist-info → cua_computer-0.3.3.dist-info}/RECORD +6 -6
- {cua_computer-0.3.2.dist-info → cua_computer-0.3.3.dist-info}/WHEEL +0 -0
- {cua_computer-0.3.2.dist-info → cua_computer-0.3.3.dist-info}/entry_points.txt +0 -0
computer/interface/base.py
CHANGED
@@ -24,6 +24,9 @@ class BaseComputerInterface(ABC):
|
|
24
24
|
self.api_key = api_key
|
25
25
|
self.vm_name = vm_name
|
26
26
|
self.logger = Logger("cua.interface", LogLevel.NORMAL)
|
27
|
+
|
28
|
+
# Optional default delay time between commands (in seconds)
|
29
|
+
self.delay: float = 0.0
|
27
30
|
|
28
31
|
@abstractmethod
|
29
32
|
async def wait_for_ready(self, timeout: int = 60) -> None:
|
@@ -52,37 +55,75 @@ class BaseComputerInterface(ABC):
|
|
52
55
|
|
53
56
|
# Mouse Actions
|
54
57
|
@abstractmethod
|
55
|
-
async def mouse_down(self, x: Optional[int] = None, y: Optional[int] = None, button: "MouseButton" = "left") -> None:
|
56
|
-
"""Press and hold a mouse button.
|
58
|
+
async def mouse_down(self, x: Optional[int] = None, y: Optional[int] = None, button: "MouseButton" = "left", delay: Optional[float] = None) -> None:
|
59
|
+
"""Press and hold a mouse button.
|
60
|
+
|
61
|
+
Args:
|
62
|
+
x: X coordinate to press at. If None, uses current cursor position.
|
63
|
+
y: Y coordinate to press at. If None, uses current cursor position.
|
64
|
+
button: Mouse button to press ('left', 'middle', 'right').
|
65
|
+
delay: Optional delay in seconds after the action
|
66
|
+
"""
|
57
67
|
pass
|
58
68
|
|
59
69
|
@abstractmethod
|
60
|
-
async def mouse_up(self, x: Optional[int] = None, y: Optional[int] = None, button: "MouseButton" = "left") -> None:
|
61
|
-
"""Release a mouse button.
|
70
|
+
async def mouse_up(self, x: Optional[int] = None, y: Optional[int] = None, button: "MouseButton" = "left", delay: Optional[float] = None) -> None:
|
71
|
+
"""Release a mouse button.
|
72
|
+
|
73
|
+
Args:
|
74
|
+
x: X coordinate to release at. If None, uses current cursor position.
|
75
|
+
y: Y coordinate to release at. If None, uses current cursor position.
|
76
|
+
button: Mouse button to release ('left', 'middle', 'right').
|
77
|
+
delay: Optional delay in seconds after the action
|
78
|
+
"""
|
62
79
|
pass
|
63
80
|
|
64
81
|
@abstractmethod
|
65
|
-
async def left_click(self, x: Optional[int] = None, y: Optional[int] = None) -> None:
|
66
|
-
"""Perform a left click.
|
82
|
+
async def left_click(self, x: Optional[int] = None, y: Optional[int] = None, delay: Optional[float] = None) -> None:
|
83
|
+
"""Perform a left mouse button click.
|
84
|
+
|
85
|
+
Args:
|
86
|
+
x: X coordinate to click at. If None, uses current cursor position.
|
87
|
+
y: Y coordinate to click at. If None, uses current cursor position.
|
88
|
+
delay: Optional delay in seconds after the action
|
89
|
+
"""
|
67
90
|
pass
|
68
91
|
|
69
92
|
@abstractmethod
|
70
|
-
async def right_click(self, x: Optional[int] = None, y: Optional[int] = None) -> None:
|
71
|
-
"""Perform a right click.
|
93
|
+
async def right_click(self, x: Optional[int] = None, y: Optional[int] = None, delay: Optional[float] = None) -> None:
|
94
|
+
"""Perform a right mouse button click.
|
95
|
+
|
96
|
+
Args:
|
97
|
+
x: X coordinate to click at. If None, uses current cursor position.
|
98
|
+
y: Y coordinate to click at. If None, uses current cursor position.
|
99
|
+
delay: Optional delay in seconds after the action
|
100
|
+
"""
|
72
101
|
pass
|
73
102
|
|
74
103
|
@abstractmethod
|
75
|
-
async def double_click(self, x: Optional[int] = None, y: Optional[int] = None) -> None:
|
76
|
-
"""Perform a double click.
|
104
|
+
async def double_click(self, x: Optional[int] = None, y: Optional[int] = None, delay: Optional[float] = None) -> None:
|
105
|
+
"""Perform a double left mouse button click.
|
106
|
+
|
107
|
+
Args:
|
108
|
+
x: X coordinate to double-click at. If None, uses current cursor position.
|
109
|
+
y: Y coordinate to double-click at. If None, uses current cursor position.
|
110
|
+
delay: Optional delay in seconds after the action
|
111
|
+
"""
|
77
112
|
pass
|
78
113
|
|
79
114
|
@abstractmethod
|
80
|
-
async def move_cursor(self, x: int, y: int) -> None:
|
81
|
-
"""Move the cursor to specified
|
115
|
+
async def move_cursor(self, x: int, y: int, delay: Optional[float] = None) -> None:
|
116
|
+
"""Move the cursor to the specified screen coordinates.
|
117
|
+
|
118
|
+
Args:
|
119
|
+
x: X coordinate to move cursor to.
|
120
|
+
y: Y coordinate to move cursor to.
|
121
|
+
delay: Optional delay in seconds after the action
|
122
|
+
"""
|
82
123
|
pass
|
83
124
|
|
84
125
|
@abstractmethod
|
85
|
-
async def drag_to(self, x: int, y: int, button: str = "left", duration: float = 0.5) -> None:
|
126
|
+
async def drag_to(self, x: int, y: int, button: str = "left", duration: float = 0.5, delay: Optional[float] = None) -> None:
|
86
127
|
"""Drag from current position to specified coordinates.
|
87
128
|
|
88
129
|
Args:
|
@@ -90,60 +131,103 @@ class BaseComputerInterface(ABC):
|
|
90
131
|
y: The y coordinate to drag to
|
91
132
|
button: The mouse button to use ('left', 'middle', 'right')
|
92
133
|
duration: How long the drag should take in seconds
|
134
|
+
delay: Optional delay in seconds after the action
|
93
135
|
"""
|
94
136
|
pass
|
95
137
|
|
96
138
|
@abstractmethod
|
97
|
-
async def drag(self, path: List[Tuple[int, int]], button: str = "left", duration: float = 0.5) -> None:
|
139
|
+
async def drag(self, path: List[Tuple[int, int]], button: str = "left", duration: float = 0.5, delay: Optional[float] = None) -> None:
|
98
140
|
"""Drag the cursor along a path of coordinates.
|
99
141
|
|
100
142
|
Args:
|
101
143
|
path: List of (x, y) coordinate tuples defining the drag path
|
102
144
|
button: The mouse button to use ('left', 'middle', 'right')
|
103
145
|
duration: Total time in seconds that the drag operation should take
|
146
|
+
delay: Optional delay in seconds after the action
|
104
147
|
"""
|
105
148
|
pass
|
106
149
|
|
107
150
|
# Keyboard Actions
|
108
151
|
@abstractmethod
|
109
|
-
async def key_down(self, key: str) -> None:
|
110
|
-
"""Press and hold a key.
|
152
|
+
async def key_down(self, key: str, delay: Optional[float] = None) -> None:
|
153
|
+
"""Press and hold a key.
|
154
|
+
|
155
|
+
Args:
|
156
|
+
key: The key to press and hold (e.g., 'a', 'shift', 'ctrl').
|
157
|
+
delay: Optional delay in seconds after the action.
|
158
|
+
"""
|
111
159
|
pass
|
112
160
|
|
113
161
|
@abstractmethod
|
114
|
-
async def key_up(self, key: str) -> None:
|
115
|
-
"""Release a key.
|
162
|
+
async def key_up(self, key: str, delay: Optional[float] = None) -> None:
|
163
|
+
"""Release a previously pressed key.
|
164
|
+
|
165
|
+
Args:
|
166
|
+
key: The key to release (e.g., 'a', 'shift', 'ctrl').
|
167
|
+
delay: Optional delay in seconds after the action.
|
168
|
+
"""
|
116
169
|
pass
|
117
170
|
|
118
171
|
@abstractmethod
|
119
|
-
async def type_text(self, text: str) -> None:
|
120
|
-
"""Type the specified text.
|
172
|
+
async def type_text(self, text: str, delay: Optional[float] = None) -> None:
|
173
|
+
"""Type the specified text string.
|
174
|
+
|
175
|
+
Args:
|
176
|
+
text: The text string to type.
|
177
|
+
delay: Optional delay in seconds after the action.
|
178
|
+
"""
|
121
179
|
pass
|
122
180
|
|
123
181
|
@abstractmethod
|
124
|
-
async def press_key(self, key: str) -> None:
|
125
|
-
"""Press a single key.
|
182
|
+
async def press_key(self, key: str, delay: Optional[float] = None) -> None:
|
183
|
+
"""Press and release a single key.
|
184
|
+
|
185
|
+
Args:
|
186
|
+
key: The key to press (e.g., 'a', 'enter', 'escape').
|
187
|
+
delay: Optional delay in seconds after the action.
|
188
|
+
"""
|
126
189
|
pass
|
127
190
|
|
128
191
|
@abstractmethod
|
129
|
-
async def hotkey(self, *keys: str) -> None:
|
130
|
-
"""Press multiple keys simultaneously.
|
192
|
+
async def hotkey(self, *keys: str, delay: Optional[float] = None) -> None:
|
193
|
+
"""Press multiple keys simultaneously (keyboard shortcut).
|
194
|
+
|
195
|
+
Args:
|
196
|
+
*keys: Variable number of keys to press together (e.g., 'ctrl', 'c').
|
197
|
+
delay: Optional delay in seconds after the action.
|
198
|
+
"""
|
131
199
|
pass
|
132
200
|
|
133
201
|
# Scrolling Actions
|
134
202
|
@abstractmethod
|
135
|
-
async def scroll(self, x: int, y: int) -> None:
|
136
|
-
"""Scroll the mouse wheel.
|
203
|
+
async def scroll(self, x: int, y: int, delay: Optional[float] = None) -> None:
|
204
|
+
"""Scroll the mouse wheel by specified amounts.
|
205
|
+
|
206
|
+
Args:
|
207
|
+
x: Horizontal scroll amount (positive = right, negative = left).
|
208
|
+
y: Vertical scroll amount (positive = up, negative = down).
|
209
|
+
delay: Optional delay in seconds after the action.
|
210
|
+
"""
|
137
211
|
pass
|
138
212
|
|
139
213
|
@abstractmethod
|
140
|
-
async def scroll_down(self, clicks: int = 1) -> None:
|
141
|
-
"""Scroll down.
|
214
|
+
async def scroll_down(self, clicks: int = 1, delay: Optional[float] = None) -> None:
|
215
|
+
"""Scroll down by the specified number of clicks.
|
216
|
+
|
217
|
+
Args:
|
218
|
+
clicks: Number of scroll clicks to perform downward.
|
219
|
+
delay: Optional delay in seconds after the action.
|
220
|
+
"""
|
142
221
|
pass
|
143
222
|
|
144
223
|
@abstractmethod
|
145
|
-
async def scroll_up(self, clicks: int = 1) -> None:
|
146
|
-
"""Scroll up.
|
224
|
+
async def scroll_up(self, clicks: int = 1, delay: Optional[float] = None) -> None:
|
225
|
+
"""Scroll up by the specified number of clicks.
|
226
|
+
|
227
|
+
Args:
|
228
|
+
clicks: Number of scroll clicks to perform upward.
|
229
|
+
delay: Optional delay in seconds after the action.
|
230
|
+
"""
|
147
231
|
pass
|
148
232
|
|
149
233
|
# Screen Actions
|
@@ -167,44 +251,89 @@ class BaseComputerInterface(ABC):
|
|
167
251
|
|
168
252
|
@abstractmethod
|
169
253
|
async def get_cursor_position(self) -> Dict[str, int]:
|
170
|
-
"""Get current cursor position.
|
254
|
+
"""Get the current cursor position on screen.
|
255
|
+
|
256
|
+
Returns:
|
257
|
+
Dict with 'x' and 'y' keys containing cursor coordinates.
|
258
|
+
"""
|
171
259
|
pass
|
172
260
|
|
173
261
|
# Clipboard Actions
|
174
262
|
@abstractmethod
|
175
263
|
async def copy_to_clipboard(self) -> str:
|
176
|
-
"""Get clipboard content.
|
264
|
+
"""Get the current clipboard content.
|
265
|
+
|
266
|
+
Returns:
|
267
|
+
The text content currently stored in the clipboard.
|
268
|
+
"""
|
177
269
|
pass
|
178
270
|
|
179
271
|
@abstractmethod
|
180
272
|
async def set_clipboard(self, text: str) -> None:
|
181
|
-
"""Set clipboard content.
|
273
|
+
"""Set the clipboard content to the specified text.
|
274
|
+
|
275
|
+
Args:
|
276
|
+
text: The text to store in the clipboard.
|
277
|
+
"""
|
182
278
|
pass
|
183
279
|
|
184
280
|
# File System Actions
|
185
281
|
@abstractmethod
|
186
282
|
async def file_exists(self, path: str) -> bool:
|
187
|
-
"""Check if file exists.
|
283
|
+
"""Check if a file exists at the specified path.
|
284
|
+
|
285
|
+
Args:
|
286
|
+
path: The file path to check.
|
287
|
+
|
288
|
+
Returns:
|
289
|
+
True if the file exists, False otherwise.
|
290
|
+
"""
|
188
291
|
pass
|
189
292
|
|
190
293
|
@abstractmethod
|
191
294
|
async def directory_exists(self, path: str) -> bool:
|
192
|
-
"""Check if directory exists.
|
295
|
+
"""Check if a directory exists at the specified path.
|
296
|
+
|
297
|
+
Args:
|
298
|
+
path: The directory path to check.
|
299
|
+
|
300
|
+
Returns:
|
301
|
+
True if the directory exists, False otherwise.
|
302
|
+
"""
|
193
303
|
pass
|
194
304
|
|
195
305
|
@abstractmethod
|
196
306
|
async def list_dir(self, path: str) -> List[str]:
|
197
|
-
"""List
|
307
|
+
"""List the contents of a directory.
|
308
|
+
|
309
|
+
Args:
|
310
|
+
path: The directory path to list.
|
311
|
+
|
312
|
+
Returns:
|
313
|
+
List of file and directory names in the specified directory.
|
314
|
+
"""
|
198
315
|
pass
|
199
316
|
|
200
317
|
@abstractmethod
|
201
318
|
async def read_text(self, path: str) -> str:
|
202
|
-
"""Read
|
319
|
+
"""Read the text contents of a file.
|
320
|
+
|
321
|
+
Args:
|
322
|
+
path: The file path to read from.
|
323
|
+
|
324
|
+
Returns:
|
325
|
+
The text content of the file.
|
326
|
+
"""
|
203
327
|
pass
|
204
328
|
|
205
329
|
@abstractmethod
|
206
330
|
async def write_text(self, path: str, content: str) -> None:
|
207
|
-
"""Write
|
331
|
+
"""Write text content to a file.
|
332
|
+
|
333
|
+
Args:
|
334
|
+
path: The file path to write to.
|
335
|
+
content: The text content to write.
|
336
|
+
"""
|
208
337
|
pass
|
209
338
|
|
210
339
|
@abstractmethod
|
@@ -220,27 +349,51 @@ class BaseComputerInterface(ABC):
|
|
220
349
|
|
221
350
|
@abstractmethod
|
222
351
|
async def write_bytes(self, path: str, content: bytes) -> None:
|
223
|
-
"""Write
|
352
|
+
"""Write binary content to a file.
|
353
|
+
|
354
|
+
Args:
|
355
|
+
path: The file path to write to.
|
356
|
+
content: The binary content to write.
|
357
|
+
"""
|
224
358
|
pass
|
225
359
|
|
226
360
|
@abstractmethod
|
227
361
|
async def delete_file(self, path: str) -> None:
|
228
|
-
"""Delete file.
|
362
|
+
"""Delete a file at the specified path.
|
363
|
+
|
364
|
+
Args:
|
365
|
+
path: The file path to delete.
|
366
|
+
"""
|
229
367
|
pass
|
230
368
|
|
231
369
|
@abstractmethod
|
232
370
|
async def create_dir(self, path: str) -> None:
|
233
|
-
"""Create directory.
|
371
|
+
"""Create a directory at the specified path.
|
372
|
+
|
373
|
+
Args:
|
374
|
+
path: The directory path to create.
|
375
|
+
"""
|
234
376
|
pass
|
235
377
|
|
236
378
|
@abstractmethod
|
237
379
|
async def delete_dir(self, path: str) -> None:
|
238
|
-
"""Delete directory.
|
380
|
+
"""Delete a directory at the specified path.
|
381
|
+
|
382
|
+
Args:
|
383
|
+
path: The directory path to delete.
|
384
|
+
"""
|
239
385
|
pass
|
240
386
|
|
241
387
|
@abstractmethod
|
242
388
|
async def get_file_size(self, path: str) -> int:
|
243
|
-
"""Get the size of a file in bytes.
|
389
|
+
"""Get the size of a file in bytes.
|
390
|
+
|
391
|
+
Args:
|
392
|
+
path: The file path to get the size of.
|
393
|
+
|
394
|
+
Returns:
|
395
|
+
The size of the file in bytes.
|
396
|
+
"""
|
244
397
|
pass
|
245
398
|
|
246
399
|
@abstractmethod
|
@@ -274,7 +427,11 @@ class BaseComputerInterface(ABC):
|
|
274
427
|
# Accessibility Actions
|
275
428
|
@abstractmethod
|
276
429
|
async def get_accessibility_tree(self) -> Dict:
|
277
|
-
"""Get the accessibility tree of the current screen.
|
430
|
+
"""Get the accessibility tree of the current screen.
|
431
|
+
|
432
|
+
Returns:
|
433
|
+
Dict containing the hierarchical accessibility information of screen elements.
|
434
|
+
"""
|
278
435
|
pass
|
279
436
|
|
280
437
|
@abstractmethod
|
computer/interface/generic.py
CHANGED
@@ -32,6 +32,21 @@ class GenericComputerInterface(BaseComputerInterface):
|
|
32
32
|
# Set logger name for the interface
|
33
33
|
self.logger = Logger(logger_name, LogLevel.NORMAL)
|
34
34
|
|
35
|
+
# Optional default delay time between commands (in seconds)
|
36
|
+
self.delay = 0.0
|
37
|
+
|
38
|
+
async def _handle_delay(self, delay: Optional[float] = None):
|
39
|
+
"""Handle delay between commands using async sleep.
|
40
|
+
|
41
|
+
Args:
|
42
|
+
delay: Optional delay in seconds. If None, uses self.delay.
|
43
|
+
"""
|
44
|
+
if delay is not None:
|
45
|
+
if isinstance(delay, float) and delay > 0:
|
46
|
+
await asyncio.sleep(delay)
|
47
|
+
elif isinstance(self.delay, float) and self.delay > 0:
|
48
|
+
await asyncio.sleep(self.delay)
|
49
|
+
|
35
50
|
@property
|
36
51
|
def ws_uri(self) -> str:
|
37
52
|
"""Get the WebSocket URI using the current IP address.
|
@@ -44,42 +59,52 @@ class GenericComputerInterface(BaseComputerInterface):
|
|
44
59
|
return f"{protocol}://{self.ip_address}:{port}/ws"
|
45
60
|
|
46
61
|
# Mouse actions
|
47
|
-
async def mouse_down(self, x: Optional[int] = None, y: Optional[int] = None, button: str = "left") -> None:
|
62
|
+
async def mouse_down(self, x: Optional[int] = None, y: Optional[int] = None, button: str = "left", delay: Optional[float] = None) -> None:
|
48
63
|
await self._send_command("mouse_down", {"x": x, "y": y, "button": button})
|
64
|
+
await self._handle_delay(delay)
|
49
65
|
|
50
|
-
async def mouse_up(self, x: Optional[int] = None, y: Optional[int] = None, button: str = "left") -> None:
|
66
|
+
async def mouse_up(self, x: Optional[int] = None, y: Optional[int] = None, button: str = "left", delay: Optional[float] = None) -> None:
|
51
67
|
await self._send_command("mouse_up", {"x": x, "y": y, "button": button})
|
68
|
+
await self._handle_delay(delay)
|
52
69
|
|
53
|
-
async def left_click(self, x: Optional[int] = None, y: Optional[int] = None) -> None:
|
70
|
+
async def left_click(self, x: Optional[int] = None, y: Optional[int] = None, delay: Optional[float] = None) -> None:
|
54
71
|
await self._send_command("left_click", {"x": x, "y": y})
|
72
|
+
await self._handle_delay(delay)
|
55
73
|
|
56
|
-
async def right_click(self, x: Optional[int] = None, y: Optional[int] = None) -> None:
|
74
|
+
async def right_click(self, x: Optional[int] = None, y: Optional[int] = None, delay: Optional[float] = None) -> None:
|
57
75
|
await self._send_command("right_click", {"x": x, "y": y})
|
76
|
+
await self._handle_delay(delay)
|
58
77
|
|
59
|
-
async def double_click(self, x: Optional[int] = None, y: Optional[int] = None) -> None:
|
78
|
+
async def double_click(self, x: Optional[int] = None, y: Optional[int] = None, delay: Optional[float] = None) -> None:
|
60
79
|
await self._send_command("double_click", {"x": x, "y": y})
|
80
|
+
await self._handle_delay(delay)
|
61
81
|
|
62
|
-
async def move_cursor(self, x: int, y: int) -> None:
|
82
|
+
async def move_cursor(self, x: int, y: int, delay: Optional[float] = None) -> None:
|
63
83
|
await self._send_command("move_cursor", {"x": x, "y": y})
|
84
|
+
await self._handle_delay(delay)
|
64
85
|
|
65
|
-
async def drag_to(self, x: int, y: int, button: "MouseButton" = "left", duration: float = 0.5) -> None:
|
86
|
+
async def drag_to(self, x: int, y: int, button: "MouseButton" = "left", duration: float = 0.5, delay: Optional[float] = None) -> None:
|
66
87
|
await self._send_command(
|
67
88
|
"drag_to", {"x": x, "y": y, "button": button, "duration": duration}
|
68
89
|
)
|
90
|
+
await self._handle_delay(delay)
|
69
91
|
|
70
|
-
async def drag(self, path: List[Tuple[int, int]], button: "MouseButton" = "left", duration: float = 0.5) -> None:
|
92
|
+
async def drag(self, path: List[Tuple[int, int]], button: "MouseButton" = "left", duration: float = 0.5, delay: Optional[float] = None) -> None:
|
71
93
|
await self._send_command(
|
72
94
|
"drag", {"path": path, "button": button, "duration": duration}
|
73
95
|
)
|
96
|
+
await self._handle_delay(delay)
|
74
97
|
|
75
98
|
# Keyboard Actions
|
76
|
-
async def key_down(self, key: "KeyType") -> None:
|
99
|
+
async def key_down(self, key: "KeyType", delay: Optional[float] = None) -> None:
|
77
100
|
await self._send_command("key_down", {"key": key})
|
101
|
+
await self._handle_delay(delay)
|
78
102
|
|
79
|
-
async def key_up(self, key: "KeyType") -> None:
|
103
|
+
async def key_up(self, key: "KeyType", delay: Optional[float] = None) -> None:
|
80
104
|
await self._send_command("key_up", {"key": key})
|
105
|
+
await self._handle_delay(delay)
|
81
106
|
|
82
|
-
async def type_text(self, text: str) -> None:
|
107
|
+
async def type_text(self, text: str, delay: Optional[float] = None) -> None:
|
83
108
|
# Temporary fix for https://github.com/trycua/cua/issues/165
|
84
109
|
# Check if text contains Unicode characters
|
85
110
|
if any(ord(char) > 127 for char in text):
|
@@ -89,8 +114,9 @@ class GenericComputerInterface(BaseComputerInterface):
|
|
89
114
|
else:
|
90
115
|
# For ASCII text, use the regular typing method
|
91
116
|
await self._send_command("type_text", {"text": text})
|
117
|
+
await self._handle_delay(delay)
|
92
118
|
|
93
|
-
async def press(self, key: "KeyType") -> None:
|
119
|
+
async def press(self, key: "KeyType", delay: Optional[float] = None) -> None:
|
94
120
|
"""Press a single key.
|
95
121
|
|
96
122
|
Args:
|
@@ -126,16 +152,17 @@ class GenericComputerInterface(BaseComputerInterface):
|
|
126
152
|
raise ValueError(f"Invalid key type: {type(key)}. Must be Key enum or string.")
|
127
153
|
|
128
154
|
await self._send_command("press_key", {"key": actual_key})
|
155
|
+
await self._handle_delay(delay)
|
129
156
|
|
130
|
-
async def press_key(self, key: "KeyType") -> None:
|
157
|
+
async def press_key(self, key: "KeyType", delay: Optional[float] = None) -> None:
|
131
158
|
"""DEPRECATED: Use press() instead.
|
132
159
|
|
133
160
|
This method is kept for backward compatibility but will be removed in a future version.
|
134
161
|
Please use the press() method instead.
|
135
162
|
"""
|
136
|
-
await self.press(key)
|
163
|
+
await self.press(key, delay)
|
137
164
|
|
138
|
-
async def hotkey(self, *keys: "KeyType") -> None:
|
165
|
+
async def hotkey(self, *keys: "KeyType", delay: Optional[float] = None) -> None:
|
139
166
|
"""Press multiple keys simultaneously.
|
140
167
|
|
141
168
|
Args:
|
@@ -169,16 +196,20 @@ class GenericComputerInterface(BaseComputerInterface):
|
|
169
196
|
raise ValueError(f"Invalid key type: {type(key)}. Must be Key enum or string.")
|
170
197
|
|
171
198
|
await self._send_command("hotkey", {"keys": actual_keys})
|
199
|
+
await self._handle_delay(delay)
|
172
200
|
|
173
201
|
# Scrolling Actions
|
174
|
-
async def scroll(self, x: int, y: int) -> None:
|
202
|
+
async def scroll(self, x: int, y: int, delay: Optional[float] = None) -> None:
|
175
203
|
await self._send_command("scroll", {"x": x, "y": y})
|
204
|
+
await self._handle_delay(delay)
|
176
205
|
|
177
|
-
async def scroll_down(self, clicks: int = 1) -> None:
|
206
|
+
async def scroll_down(self, clicks: int = 1, delay: Optional[float] = None) -> None:
|
178
207
|
await self._send_command("scroll_down", {"clicks": clicks})
|
179
|
-
|
180
|
-
|
208
|
+
await self._handle_delay(delay)
|
209
|
+
|
210
|
+
async def scroll_up(self, clicks: int = 1, delay: Optional[float] = None) -> None:
|
181
211
|
await self._send_command("scroll_up", {"clicks": clicks})
|
212
|
+
await self._handle_delay(delay)
|
182
213
|
|
183
214
|
# Screen actions
|
184
215
|
async def screenshot(
|
@@ -3,9 +3,9 @@ computer/computer.py,sha256=bHo7pdJoz8p3YSERYvdY7aLYdqYdiXbPVQydirlhwkM,41390
|
|
3
3
|
computer/diorama_computer.py,sha256=jOP7_eXxxU6SMIoE25ni0YXPK0E7p5sZeLKmkYLh6G8,3871
|
4
4
|
computer/helpers.py,sha256=iHkO2WhuCLc15g67kfMnpQWxfNRlz2YeJNEvYaL9jlM,1826
|
5
5
|
computer/interface/__init__.py,sha256=xQvYjq5PMn9ZJOmRR5mWtONTl_0HVd8ACvW6AQnzDdw,262
|
6
|
-
computer/interface/base.py,sha256
|
6
|
+
computer/interface/base.py,sha256=1beR4T0z5anb9NaNgKJrMJTF0BFIKyiHlokMLesOV5Q,15131
|
7
7
|
computer/interface/factory.py,sha256=Eas5u9sOZ8FegwX51dP9M37oZBjy2EiVcmhTPc98L3Y,1639
|
8
|
-
computer/interface/generic.py,sha256=
|
8
|
+
computer/interface/generic.py,sha256=a0S_AkBEc_miqZNXGjYoBBYBtPc46NLQCDX4Isvm-zw,36239
|
9
9
|
computer/interface/linux.py,sha256=fDm2OwqfeeO72HwctboPEE5AwPTo2XBRDyYkwQxMyt0,417
|
10
10
|
computer/interface/macos.py,sha256=m1aRn3BCbA95gPoO-WSP9NPwruT4BT5DZzxY10UuBI0,675
|
11
11
|
computer/interface/models.py,sha256=kPpmoO-TSxSr95f5ELuTpobY-SckG1Sn9pE8zz1t008,3605
|
@@ -31,7 +31,7 @@ computer/ui/__main__.py,sha256=Jwy2oC_mGZLN0fX7WLqpjaQkbXMeM3ISrUc8WSRUG0c,284
|
|
31
31
|
computer/ui/gradio/__init__.py,sha256=5_KimixM48-X74FCsLw7LbSt39MQfUMEL8-M9amK3Cw,117
|
32
32
|
computer/ui/gradio/app.py,sha256=5_AG2dQR9RtFrGQNonScAw64rlswclKW26tYlFBdXtM,70396
|
33
33
|
computer/utils.py,sha256=zY50NXB7r51GNLQ6l7lhG_qv0_ufpQ8n0-SDhCei8m4,2838
|
34
|
-
cua_computer-0.3.
|
35
|
-
cua_computer-0.3.
|
36
|
-
cua_computer-0.3.
|
37
|
-
cua_computer-0.3.
|
34
|
+
cua_computer-0.3.3.dist-info/METADATA,sha256=nL5u-3vmnA485vJoENftRShbgE89kbxxb8d-Rz3i3Lk,5802
|
35
|
+
cua_computer-0.3.3.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
|
36
|
+
cua_computer-0.3.3.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
|
37
|
+
cua_computer-0.3.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|