use-computer 0.0.22__tar.gz → 0.0.24__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 (60) hide show
  1. {use_computer-0.0.22 → use_computer-0.0.24}/PKG-INFO +14 -1
  2. {use_computer-0.0.22 → use_computer-0.0.24}/README.md +13 -0
  3. {use_computer-0.0.22 → use_computer-0.0.24}/pyproject.toml +1 -1
  4. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/__init__.py +4 -0
  5. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/client.py +71 -3
  6. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/sandbox.py +111 -3
  7. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/windows/shell.py +11 -7
  8. use_computer-0.0.22/examples/_1_hello_macos.py +0 -8
  9. use_computer-0.0.22/examples/_2_hello_ios.py +0 -11
  10. use_computer-0.0.22/examples/_3_recording.py +0 -10
  11. use_computer-0.0.22/examples/_4_file_transfer.py +0 -7
  12. use_computer-0.0.22/examples/_5_keepalive.py +0 -9
  13. use_computer-0.0.22/examples/_6_hello_tvos.py +0 -11
  14. use_computer-0.0.22/examples/_7_hello_windows.py +0 -11
  15. use_computer-0.0.22/examples/go/hello_windows.go +0 -35
  16. use_computer-0.0.22/examples/javascript/hello_windows.ts +0 -14
  17. use_computer-0.0.22/go/README.md +0 -46
  18. use_computer-0.0.22/go/client.go +0 -192
  19. use_computer-0.0.22/go/go.mod +0 -3
  20. use_computer-0.0.22/go/sandbox.go +0 -156
  21. use_computer-0.0.22/javascript/.gitignore +0 -3
  22. use_computer-0.0.22/javascript/README.md +0 -48
  23. use_computer-0.0.22/javascript/package-lock.json +0 -51
  24. use_computer-0.0.22/javascript/package.json +0 -27
  25. use_computer-0.0.22/javascript/src/client.ts +0 -82
  26. use_computer-0.0.22/javascript/src/http.ts +0 -96
  27. use_computer-0.0.22/javascript/src/index.ts +0 -11
  28. use_computer-0.0.22/javascript/src/sandbox.ts +0 -208
  29. use_computer-0.0.22/javascript/tsconfig.json +0 -16
  30. {use_computer-0.0.22 → use_computer-0.0.24}/.env.example +0 -0
  31. {use_computer-0.0.22 → use_computer-0.0.24}/.gitignore +0 -0
  32. {use_computer-0.0.22 → use_computer-0.0.24}/.pre-commit-config.yaml +0 -0
  33. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/accessibility.py +0 -0
  34. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/ax_transpile.py +0 -0
  35. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/display.py +0 -0
  36. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/errors.py +0 -0
  37. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/ios/__init__.py +0 -0
  38. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/ios/apps.py +0 -0
  39. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/ios/environment.py +0 -0
  40. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/ios/input.py +0 -0
  41. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/macos/__init__.py +0 -0
  42. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/macos/keyboard.py +0 -0
  43. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/macos/mouse.py +0 -0
  44. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/models.py +0 -0
  45. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/parsers.py +0 -0
  46. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/py.typed +0 -0
  47. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/recording.py +0 -0
  48. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/retry.py +0 -0
  49. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/screenshot.py +0 -0
  50. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/simulators.py +0 -0
  51. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/tasks/__init__.py +0 -0
  52. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/tasks/templates/pre_command.sh +0 -0
  53. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/tasks/templates/task.toml +0 -0
  54. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/tasks/templates/test_ios.sh +0 -0
  55. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/tasks/templates/test_ios_nograder.sh +0 -0
  56. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/tasks/templates/test_macos.sh +0 -0
  57. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/tasks/templates/test_macos_check.sh +0 -0
  58. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/tasks/templates/test_macos_nograder.sh +0 -0
  59. {use_computer-0.0.22 → use_computer-0.0.24}/use_computer/windows/__init__.py +0 -0
  60. {use_computer-0.0.22 → use_computer-0.0.24}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: use-computer
3
- Version: 0.0.22
3
+ Version: 0.0.24
4
4
  Summary: Python SDK for the use.computer macOS and iOS Computer Use API
5
5
  Project-URL: Homepage, https://use.computer
6
6
  Project-URL: Documentation, https://api.use.computer/docs
@@ -60,6 +60,19 @@ recording/file surface as macOS; exec runs in-guest via PowerShell/cmd
60
60
  (`win.run` / `win.shell`) instead of SSH. `AsyncWindowsSandbox` mirrors it.
61
61
  See [docs.use.computer/docs/windows](https://docs.use.computer/docs/windows).
62
62
 
63
+ ### Ubuntu (Beta)
64
+
65
+ ```python
66
+ with Computer().create(type="ubuntu", version="ubuntu-24.04") as ubuntu:
67
+ print(ubuntu.run("uname -a").stdout) # bash exec (no SSH)
68
+ ubuntu.keyboard.type("hello")
69
+ ubuntu.screenshot.take_full_screen()
70
+ ```
71
+
72
+ Ubuntu sandboxes are **Beta** (admin-only). They use the same KVM/noVNC backend
73
+ as Windows; pass `version="ubuntu-24.04"` to select a specific image. Exec
74
+ defaults to bash and the macOS accessibility tree is not available yet.
75
+
63
76
  Full DSL reference (macOS + simulator): [docs.use.computer/docs/sdk](https://docs.use.computer/docs/sdk)
64
77
 
65
78
  Simulator sandboxes use `type=SandboxType.IOS` for the SDK route, but
@@ -38,6 +38,19 @@ recording/file surface as macOS; exec runs in-guest via PowerShell/cmd
38
38
  (`win.run` / `win.shell`) instead of SSH. `AsyncWindowsSandbox` mirrors it.
39
39
  See [docs.use.computer/docs/windows](https://docs.use.computer/docs/windows).
40
40
 
41
+ ### Ubuntu (Beta)
42
+
43
+ ```python
44
+ with Computer().create(type="ubuntu", version="ubuntu-24.04") as ubuntu:
45
+ print(ubuntu.run("uname -a").stdout) # bash exec (no SSH)
46
+ ubuntu.keyboard.type("hello")
47
+ ubuntu.screenshot.take_full_screen()
48
+ ```
49
+
50
+ Ubuntu sandboxes are **Beta** (admin-only). They use the same KVM/noVNC backend
51
+ as Windows; pass `version="ubuntu-24.04"` to select a specific image. Exec
52
+ defaults to bash and the macOS accessibility tree is not available yet.
53
+
41
54
  Full DSL reference (macOS + simulator): [docs.use.computer/docs/sdk](https://docs.use.computer/docs/sdk)
42
55
 
43
56
  Simulator sandboxes use `type=SandboxType.IOS` for the SDK route, but
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "use-computer"
7
- version = "0.0.22"
7
+ version = "0.0.24"
8
8
  description = "Python SDK for the use.computer macOS and iOS Computer Use API"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -15,11 +15,13 @@ from use_computer.sandbox import (
15
15
  AsyncIOSSandbox,
16
16
  AsyncMacOSSandbox,
17
17
  AsyncSandbox,
18
+ AsyncUbuntuSandbox,
18
19
  AsyncWindowsSandbox,
19
20
  IOSSandbox,
20
21
  MacOSSandbox,
21
22
  Sandbox,
22
23
  SandboxType,
24
+ UbuntuSandbox,
23
25
  WindowsSandbox,
24
26
  )
25
27
  from use_computer.simulators import (
@@ -42,6 +44,7 @@ __all__ = [
42
44
  "AsyncMacOSSandbox",
43
45
  "AsyncComputer",
44
46
  "AsyncSandbox",
47
+ "AsyncUbuntuSandbox",
45
48
  "AsyncWindowsSandbox",
46
49
  "Button",
47
50
  "Computer",
@@ -63,6 +66,7 @@ __all__ = [
63
66
  "TaskSummary",
64
67
  "TasksClient",
65
68
  "UseComputerError",
69
+ "UbuntuSandbox",
66
70
  "WindowsSandbox",
67
71
  "family_for_device",
68
72
  "is_usable_device_type",
@@ -14,11 +14,13 @@ from use_computer.sandbox import (
14
14
  AsyncIOSSandbox,
15
15
  AsyncMacOSSandbox,
16
16
  AsyncSandbox,
17
+ AsyncUbuntuSandbox,
17
18
  AsyncWindowsSandbox,
18
19
  IOSSandbox,
19
20
  MacOSSandbox,
20
21
  Sandbox,
21
22
  SandboxType,
23
+ UbuntuSandbox,
22
24
  WindowsSandbox,
23
25
  )
24
26
  from use_computer.simulators import SimulatorFamily, select_simulator
@@ -26,7 +28,7 @@ from use_computer.tasks import TasksClient
26
28
 
27
29
  DEFAULT_BASE_URL = "https://api.use.computer"
28
30
 
29
- SandboxTypeInput = SandboxType | Literal["macos", "ios", "windows"]
31
+ SandboxTypeInput = SandboxType | Literal["macos", "ios", "windows", "ubuntu"]
30
32
 
31
33
 
32
34
  def _resolve_api_key(api_key: str | None) -> str | None:
@@ -135,9 +137,19 @@ class Computer:
135
137
  self,
136
138
  *,
137
139
  type: Literal["windows", SandboxType.WINDOWS],
140
+ version: str = ...,
138
141
  host: str = ...,
139
142
  ) -> WindowsSandbox: ...
140
143
 
144
+ @overload
145
+ def create(
146
+ self,
147
+ *,
148
+ type: Literal["ubuntu", SandboxType.UBUNTU],
149
+ version: str = ...,
150
+ host: str = ...,
151
+ ) -> UbuntuSandbox: ...
152
+
141
153
  def create(
142
154
  self,
143
155
  *,
@@ -146,7 +158,8 @@ class Computer:
146
158
  family: SimulatorFamily | str | None = None,
147
159
  device_type: str = "",
148
160
  runtime: str = "",
149
- ) -> MacOSSandbox | IOSSandbox | WindowsSandbox:
161
+ version: str = "",
162
+ ) -> MacOSSandbox | IOSSandbox | WindowsSandbox | UbuntuSandbox:
150
163
  """Create a new sandbox.
151
164
 
152
165
  Args:
@@ -155,11 +168,15 @@ class Computer:
155
168
  family: Simulator family enum/alias, for example SimulatorFamily.TV.
156
169
  device_type: Simulator device type identifier, for exact pinning.
157
170
  runtime: Simulator runtime identifier, for exact pinning.
171
+ version: KVM desktop image version, for example "windows-11",
172
+ "windows-10", or "ubuntu-24.04".
158
173
  """
159
174
  sandbox_type = _normalize_sandbox_type(type)
160
175
  body: dict = {"type": sandbox_type.value}
161
176
  if host:
162
177
  body["host"] = host
178
+ if sandbox_type in (SandboxType.WINDOWS, SandboxType.UBUNTU) and version:
179
+ body["version"] = version
163
180
  if sandbox_type == SandboxType.IOS:
164
181
  if family and (not device_type or not runtime):
165
182
  choice = select_simulator(self.platforms(), family)
@@ -183,6 +200,15 @@ class Computer:
183
200
  http=self._http,
184
201
  vnc_url=f"{self._base_url}{data.get('vnc_url', '')}",
185
202
  host=data.get("host", ""),
203
+ version=data.get("version", ""),
204
+ )
205
+ if sandbox_type == SandboxType.UBUNTU:
206
+ return UbuntuSandbox(
207
+ sandbox_id=sid,
208
+ http=self._http,
209
+ vnc_url=f"{self._base_url}{data.get('vnc_url', '')}",
210
+ host=data.get("host", ""),
211
+ version=data.get("version", ""),
186
212
  )
187
213
  return MacOSSandbox(
188
214
  sandbox_id=sid,
@@ -207,6 +233,15 @@ class Computer:
207
233
  http=self._http,
208
234
  vnc_url=f"{self._base_url}{data.get('vnc_url', '')}",
209
235
  host=data.get("host", ""),
236
+ version=data.get("version", ""),
237
+ )
238
+ if sb_type == SandboxType.UBUNTU:
239
+ return UbuntuSandbox(
240
+ sandbox_id=data["sandbox_id"],
241
+ http=self._http,
242
+ vnc_url=f"{self._base_url}{data.get('vnc_url', '')}",
243
+ host=data.get("host", ""),
244
+ version=data.get("version", ""),
210
245
  )
211
246
  return MacOSSandbox(
212
247
  sandbox_id=data["sandbox_id"],
@@ -321,9 +356,19 @@ class AsyncComputer:
321
356
  self,
322
357
  *,
323
358
  type: Literal["windows", SandboxType.WINDOWS],
359
+ version: str = ...,
324
360
  host: str = ...,
325
361
  ) -> AsyncWindowsSandbox: ...
326
362
 
363
+ @overload
364
+ async def create(
365
+ self,
366
+ *,
367
+ type: Literal["ubuntu", SandboxType.UBUNTU],
368
+ version: str = ...,
369
+ host: str = ...,
370
+ ) -> AsyncUbuntuSandbox: ...
371
+
327
372
  async def create(
328
373
  self,
329
374
  *,
@@ -332,7 +377,8 @@ class AsyncComputer:
332
377
  family: SimulatorFamily | str | None = None,
333
378
  device_type: str = "",
334
379
  runtime: str = "",
335
- ) -> AsyncMacOSSandbox | AsyncIOSSandbox | AsyncWindowsSandbox:
380
+ version: str = "",
381
+ ) -> AsyncMacOSSandbox | AsyncIOSSandbox | AsyncWindowsSandbox | AsyncUbuntuSandbox:
336
382
  """Create a new sandbox.
337
383
 
338
384
  Args:
@@ -341,11 +387,15 @@ class AsyncComputer:
341
387
  family: Simulator family enum/alias, for example SimulatorFamily.TV.
342
388
  device_type: Simulator device type identifier, for exact pinning.
343
389
  runtime: Simulator runtime identifier, for exact pinning.
390
+ version: KVM desktop image version, for example "windows-11",
391
+ "windows-10", or "ubuntu-24.04".
344
392
  """
345
393
  sandbox_type = _normalize_sandbox_type(type)
346
394
  body: dict = {"type": sandbox_type.value}
347
395
  if host:
348
396
  body["host"] = host
397
+ if sandbox_type in (SandboxType.WINDOWS, SandboxType.UBUNTU) and version:
398
+ body["version"] = version
349
399
  if sandbox_type == SandboxType.IOS:
350
400
  if family and (not device_type or not runtime):
351
401
  choice = select_simulator(await self.platforms(), family)
@@ -369,6 +419,15 @@ class AsyncComputer:
369
419
  http=self._http,
370
420
  vnc_url=f"{self._base_url}{data.get('vnc_url', '')}",
371
421
  host=data.get("host", ""),
422
+ version=data.get("version", ""),
423
+ )
424
+ if sandbox_type == SandboxType.UBUNTU:
425
+ return AsyncUbuntuSandbox(
426
+ sandbox_id=sid,
427
+ http=self._http,
428
+ vnc_url=f"{self._base_url}{data.get('vnc_url', '')}",
429
+ host=data.get("host", ""),
430
+ version=data.get("version", ""),
372
431
  )
373
432
  return AsyncMacOSSandbox(
374
433
  sandbox_id=sid,
@@ -393,6 +452,15 @@ class AsyncComputer:
393
452
  http=self._http,
394
453
  vnc_url=f"{self._base_url}{data.get('vnc_url', '')}",
395
454
  host=data.get("host", ""),
455
+ version=data.get("version", ""),
456
+ )
457
+ if sb_type == SandboxType.UBUNTU:
458
+ return AsyncUbuntuSandbox(
459
+ sandbox_id=data["sandbox_id"],
460
+ http=self._http,
461
+ vnc_url=f"{self._base_url}{data.get('vnc_url', '')}",
462
+ host=data.get("host", ""),
463
+ version=data.get("version", ""),
396
464
  )
397
465
  return AsyncMacOSSandbox(
398
466
  sandbox_id=data["sandbox_id"],
@@ -27,6 +27,7 @@ class SandboxType(str, Enum):
27
27
  MACOS = "macos"
28
28
  IOS = "ios"
29
29
  WINDOWS = "windows"
30
+ UBUNTU = "ubuntu"
30
31
 
31
32
 
32
33
  # ---------------------------------------------------------------------------
@@ -256,14 +257,17 @@ class IOSSandbox(Sandbox):
256
257
 
257
258
 
258
259
  class _NoAxeAccessibility:
259
- """Mixin: Windows has no macOS axe-schema tree — `.accessibility` raises, use `.ui_tree()`."""
260
+ """Mixin for desktop guests without the macOS axe-schema tree."""
261
+
262
+ _accessibility_sandbox_type = "desktop"
263
+ _accessibility_hint = "accessibility tree is not supported for this sandbox"
260
264
 
261
265
  @property
262
266
  def accessibility(self):
263
267
  raise PlatformNotSupportedError(
264
268
  action="accessibility (macOS axe schema)",
265
- sandbox_type="windows",
266
- hint="use .ui_tree() for the native Windows UIAutomation tree",
269
+ sandbox_type=self._accessibility_sandbox_type,
270
+ hint=self._accessibility_hint,
267
271
  )
268
272
 
269
273
  @accessibility.setter
@@ -279,6 +283,9 @@ class WindowsSandbox(_NoAxeAccessibility, Sandbox):
279
283
  macOS axe-schema `.accessibility` raises PlatformNotSupportedError here.
280
284
  """
281
285
 
286
+ _accessibility_sandbox_type = "windows"
287
+ _accessibility_hint = "use .ui_tree() for the native Windows UIAutomation tree"
288
+
282
289
  def __init__(
283
290
  self,
284
291
  sandbox_id: str,
@@ -286,9 +293,11 @@ class WindowsSandbox(_NoAxeAccessibility, Sandbox):
286
293
  *,
287
294
  vnc_url: str = "",
288
295
  host: str = "",
296
+ version: str = "",
289
297
  ):
290
298
  super().__init__(sandbox_id, SandboxType.WINDOWS, http, vnc_url=vnc_url)
291
299
  self.host = host
300
+ self.version = version
292
301
  # Mouse/keyboard hit the same gateway command path as macOS.
293
302
  self.mouse = Mouse(http, self._prefix)
294
303
  self.keyboard = Keyboard(http, self._prefix)
@@ -324,6 +333,52 @@ class WindowsSandbox(_NoAxeAccessibility, Sandbox):
324
333
  return resp.json()
325
334
 
326
335
 
336
+ class UbuntuSandbox(_NoAxeAccessibility, Sandbox):
337
+ """Ubuntu desktop VM sandbox — mouse, keyboard, bash exec, VNC."""
338
+
339
+ _accessibility_sandbox_type = "ubuntu"
340
+ _accessibility_hint = "Ubuntu accessibility tree is not supported yet"
341
+
342
+ def __init__(
343
+ self,
344
+ sandbox_id: str,
345
+ http: httpx.Client,
346
+ *,
347
+ vnc_url: str = "",
348
+ host: str = "",
349
+ version: str = "",
350
+ ):
351
+ super().__init__(sandbox_id, SandboxType.UBUNTU, http, vnc_url=vnc_url)
352
+ self.host = host
353
+ self.version = version
354
+ self.mouse = Mouse(http, self._prefix)
355
+ self.keyboard = Keyboard(http, self._prefix)
356
+ self.shell = Shell(http, self._prefix, default_shell="bash")
357
+
358
+ def act(
359
+ self,
360
+ action: dict,
361
+ screenshot_after: bool = True,
362
+ screenshot_delay_ms: int = 100,
363
+ ) -> ActResult:
364
+ resp = self._http.post(
365
+ f"{self._prefix}/act",
366
+ json={
367
+ "action": action,
368
+ "screenshot_after": screenshot_after,
369
+ "screenshot_delay_ms": screenshot_delay_ms,
370
+ },
371
+ )
372
+ resp.raise_for_status()
373
+ if screenshot_after and resp.headers.get("content-type", "").startswith("image/"):
374
+ return ActResult(screenshot=resp.content)
375
+ return ActResult(data=resp.json())
376
+
377
+ def run(self, command: str, shell: ShellKind | None = None, timeout: int = 300) -> ExecResult:
378
+ """Shorthand for self.shell.run()."""
379
+ return self.shell.run(command, shell, timeout)
380
+
381
+
327
382
  # ---------------------------------------------------------------------------
328
383
  # Async
329
384
  # ---------------------------------------------------------------------------
@@ -497,6 +552,9 @@ class AsyncIOSSandbox(AsyncSandbox):
497
552
  class AsyncWindowsSandbox(_NoAxeAccessibility, AsyncSandbox):
498
553
  """Async Windows VM sandbox — see WindowsSandbox."""
499
554
 
555
+ _accessibility_sandbox_type = "windows"
556
+ _accessibility_hint = "use .ui_tree() for the native Windows UIAutomation tree"
557
+
500
558
  def __init__(
501
559
  self,
502
560
  sandbox_id: str,
@@ -504,9 +562,11 @@ class AsyncWindowsSandbox(_NoAxeAccessibility, AsyncSandbox):
504
562
  *,
505
563
  vnc_url: str = "",
506
564
  host: str = "",
565
+ version: str = "",
507
566
  ):
508
567
  super().__init__(sandbox_id, SandboxType.WINDOWS, http, vnc_url=vnc_url)
509
568
  self.host = host
569
+ self.version = version
510
570
  self.mouse = AsyncMouse(http, self._prefix)
511
571
  self.keyboard = AsyncKeyboard(http, self._prefix)
512
572
  self.shell = AsyncShell(http, self._prefix)
@@ -543,3 +603,51 @@ class AsyncWindowsSandbox(_NoAxeAccessibility, AsyncSandbox):
543
603
  )
544
604
  resp.raise_for_status()
545
605
  return resp.json()
606
+
607
+
608
+ class AsyncUbuntuSandbox(_NoAxeAccessibility, AsyncSandbox):
609
+ """Async Ubuntu desktop VM sandbox — see UbuntuSandbox."""
610
+
611
+ _accessibility_sandbox_type = "ubuntu"
612
+ _accessibility_hint = "Ubuntu accessibility tree is not supported yet"
613
+
614
+ def __init__(
615
+ self,
616
+ sandbox_id: str,
617
+ http: httpx.AsyncClient,
618
+ *,
619
+ vnc_url: str = "",
620
+ host: str = "",
621
+ version: str = "",
622
+ ):
623
+ super().__init__(sandbox_id, SandboxType.UBUNTU, http, vnc_url=vnc_url)
624
+ self.host = host
625
+ self.version = version
626
+ self.mouse = AsyncMouse(http, self._prefix)
627
+ self.keyboard = AsyncKeyboard(http, self._prefix)
628
+ self.shell = AsyncShell(http, self._prefix, default_shell="bash")
629
+
630
+ async def act(
631
+ self,
632
+ action: dict,
633
+ screenshot_after: bool = True,
634
+ screenshot_delay_ms: int = 100,
635
+ ) -> ActResult:
636
+ resp = await self._http.post(
637
+ f"{self._prefix}/act",
638
+ json={
639
+ "action": action,
640
+ "screenshot_after": screenshot_after,
641
+ "screenshot_delay_ms": screenshot_delay_ms,
642
+ },
643
+ )
644
+ resp.raise_for_status()
645
+ if screenshot_after and resp.headers.get("content-type", "").startswith("image/"):
646
+ return ActResult(screenshot=resp.content)
647
+ return ActResult(data=resp.json())
648
+
649
+ async def run(
650
+ self, command: str, shell: ShellKind | None = None, timeout: int = 300
651
+ ) -> ExecResult:
652
+ """Shorthand for self.shell.run()."""
653
+ return await self.shell.run(command, shell, timeout)
@@ -6,20 +6,21 @@ import httpx
6
6
 
7
7
  from use_computer.models import ExecResult
8
8
 
9
- ShellKind = Literal["powershell", "cmd"]
9
+ ShellKind = Literal["bash", "sh", "powershell", "cmd"]
10
10
 
11
11
 
12
12
  class Shell:
13
13
  """Run commands inside a Windows sandbox via the in-guest agent (no SSH)."""
14
14
 
15
- def __init__(self, http: httpx.Client, prefix: str):
15
+ def __init__(self, http: httpx.Client, prefix: str, default_shell: ShellKind = "powershell"):
16
16
  self._http = http
17
17
  self._prefix = prefix
18
+ self._default_shell = default_shell
18
19
 
19
- def run(self, command: str, shell: ShellKind = "powershell", timeout: int = 300) -> ExecResult:
20
+ def run(self, command: str, shell: ShellKind | None = None, timeout: int = 300) -> ExecResult:
20
21
  resp = self._http.post(
21
22
  f"{self._prefix}/exec",
22
- json={"command": command, "shell": shell},
23
+ json={"command": command, "shell": shell or self._default_shell},
23
24
  timeout=timeout,
24
25
  )
25
26
  resp.raise_for_status()
@@ -35,16 +36,19 @@ class Shell:
35
36
  class AsyncShell:
36
37
  """Async variant of Shell."""
37
38
 
38
- def __init__(self, http: httpx.AsyncClient, prefix: str):
39
+ def __init__(
40
+ self, http: httpx.AsyncClient, prefix: str, default_shell: ShellKind = "powershell"
41
+ ):
39
42
  self._http = http
40
43
  self._prefix = prefix
44
+ self._default_shell = default_shell
41
45
 
42
46
  async def run(
43
- self, command: str, shell: ShellKind = "powershell", timeout: int = 300
47
+ self, command: str, shell: ShellKind | None = None, timeout: int = 300
44
48
  ) -> ExecResult:
45
49
  resp = await self._http.post(
46
50
  f"{self._prefix}/exec",
47
- json={"command": command, "shell": shell},
51
+ json={"command": command, "shell": shell or self._default_shell},
48
52
  timeout=timeout,
49
53
  )
50
54
  resp.raise_for_status()
@@ -1,8 +0,0 @@
1
- from use_computer import Computer
2
-
3
- with Computer().create() as mac:
4
- mac.exec_ssh("open -a TextEdit")
5
- mac.keyboard.type("hello from use.computer")
6
- png = mac.screenshot.take_full_screen()
7
- open("hello_macos.png", "wb").write(png)
8
- print(f"saved hello_macos.png ({len(png)} bytes)")
@@ -1,11 +0,0 @@
1
- from use_computer import Computer, SandboxType, SimulatorFamily
2
-
3
- # iPhone is the default when family= is omitted. Pass family= to target a
4
- # different simulator family (iPad, Apple Watch, Apple TV, Apple Vision); the
5
- # SDK picks a compatible installed device_type + runtime pair for you. See
6
- # _6_hello_tvos.py for an Apple TV walkthrough.
7
- with Computer().create(type=SandboxType.IOS, family=SimulatorFamily.IPHONE) as ios:
8
- ios.apps.open_url("https://example.com")
9
- png = ios.screenshot.take_full_screen()
10
- open("hello_ios.png", "wb").write(png)
11
- print(f"saved hello_ios.png ({len(png)} bytes)")
@@ -1,10 +0,0 @@
1
- import time
2
-
3
- from use_computer import Computer
4
-
5
- with Computer().create() as mac:
6
- rec = mac.recording.start(name="demo")
7
- time.sleep(5)
8
- mac.recording.stop(rec.id)
9
- mac.recording.download(rec.id, "demo.mp4")
10
- print("saved demo.mp4")
@@ -1,7 +0,0 @@
1
- from use_computer import Computer
2
-
3
- with Computer().create() as mac:
4
- # Seed data files the task needs before handing the sandbox to an agent.
5
- mac.upload_bytes(b"hello from use.computer\n", "/Users/lume/Desktop/hello.txt")
6
- mac.download_file("/Users/lume/Desktop/hello.txt", "hello.txt")
7
- print("saved hello.txt")
@@ -1,9 +0,0 @@
1
- import time
2
-
3
- from use_computer import Computer
4
-
5
- with Computer().create() as mac:
6
- mac.start_keepalive(interval=30)
7
- time.sleep(180)
8
- png = mac.screenshot.take_full_screen()
9
- print(f"still alive: screenshot {len(png)} bytes")
@@ -1,11 +0,0 @@
1
- from use_computer import Computer, RemoteButton, SandboxType, SimulatorFamily
2
-
3
- # tvOS sims have no touch — drive them with the remote (D-pad + select / menu /
4
- # home). `press_remote` accepts the enum or a string.
5
- with Computer().create(type=SandboxType.IOS, family=SimulatorFamily.TV) as tv:
6
- tv.input.press_remote(RemoteButton.DOWN)
7
- tv.input.press_remote(RemoteButton.DOWN)
8
- tv.input.press_remote(RemoteButton.SELECT)
9
- png = tv.screenshot.take_full_screen()
10
- open("hello_tvos.png", "wb").write(png)
11
- print(f"saved hello_tvos.png ({len(png)} bytes)")
@@ -1,11 +0,0 @@
1
- from use_computer import Computer
2
-
3
- # Beta: Windows sandboxes. No SSH — exec runs in-guest via PowerShell/cmd.
4
- with Computer().create(type="windows") as win:
5
- win.run("Start-Process notepad") # PowerShell by default
6
- win.keyboard.type("hello from use.computer")
7
- print(win.run("$env:COMPUTERNAME", shell="powershell").stdout)
8
-
9
- png = win.screenshot.take_full_screen()
10
- open("hello_windows.png", "wb").write(png)
11
- print(f"saved hello_windows.png ({len(png)} bytes)")
@@ -1,35 +0,0 @@
1
- // Windows (Beta). Run:
2
- // export USE_COMPUTER_API_KEY=...
3
- // go run hello_windows.go
4
- package main
5
-
6
- import (
7
- "context"
8
- "fmt"
9
- "os"
10
-
11
- uc "github.com/josancamon19/use-computer-sdk/go"
12
- )
13
-
14
- func main() {
15
- ctx := context.Background()
16
- c := uc.New()
17
-
18
- win, err := c.Create(ctx, uc.CreateOptions{Type: uc.Windows, Version: "windows-11"})
19
- if err != nil {
20
- panic(err)
21
- }
22
- defer win.Close(ctx)
23
-
24
- name, _ := win.RunShell(ctx, "$env:COMPUTERNAME", "powershell")
25
- fmt.Println("computer name:", name.Stdout)
26
- win.RunShell(ctx, "Start-Process notepad", "powershell")
27
- win.TypeText(ctx, "hello from use.computer")
28
-
29
- png, err := win.Screenshot(ctx)
30
- if err != nil {
31
- panic(err)
32
- }
33
- os.WriteFile("hello_windows.png", png, 0o644)
34
- fmt.Printf("saved hello_windows.png (%d bytes)\n", len(png))
35
- }
@@ -1,14 +0,0 @@
1
- // Windows (Beta) — run: USE_COMPUTER_API_KEY=... npx tsx hello_windows.ts
2
- import { Computer } from "use-computer";
3
-
4
- const computer = new Computer();
5
- await using win = await computer.create({ type: "windows", version: "windows-11" });
6
-
7
- console.log("computer name:", (await win.run("$env:COMPUTERNAME")).stdout.trim());
8
- await win.run("Start-Process notepad");
9
- await win.keyboard.type("hello from use.computer");
10
-
11
- const png = await win.screenshot.takeFullScreen();
12
- const { writeFile } = await import("node:fs/promises");
13
- await writeFile("hello_windows.png", png);
14
- console.log(`saved hello_windows.png (${png.length} bytes)`);
@@ -1,46 +0,0 @@
1
- # use-computer — Go SDK
2
-
3
- Go client for [use.computer](https://use.computer) — rent dedicated VMs (macOS, iOS/visionOS/tvOS simulators, **Windows**, **Ubuntu**) built for computer-use agents. Parity with the [Python](../python) and [TypeScript](../javascript) SDKs.
4
-
5
- ```bash
6
- go get github.com/josancamon19/use-computer-sdk/go@latest
7
- export USE_COMPUTER_API_KEY=mk_live_...
8
- ```
9
-
10
- ```go
11
- package main
12
-
13
- import (
14
- "context"
15
- "fmt"
16
-
17
- uc "github.com/josancamon19/use-computer-sdk/go"
18
- )
19
-
20
- func main() {
21
- ctx := context.Background()
22
- c := uc.New() // base URL + key from env, or uc.WithBaseURL/WithAPIKey
23
-
24
- // Windows (Beta) — no SSH; runs in-guest via PowerShell/cmd
25
- win, err := c.Create(ctx, uc.CreateOptions{Type: uc.Windows, Version: "windows-11"})
26
- if err != nil {
27
- panic(err)
28
- }
29
- defer win.Close(ctx)
30
-
31
- r, _ := win.RunShell(ctx, "$env:COMPUTERNAME", "powershell")
32
- fmt.Println(r.Stdout)
33
- win.Click(ctx, 400, 300)
34
- win.TypeText(ctx, "hello from use.computer")
35
- png, _ := win.Screenshot(ctx)
36
- fmt.Printf("screenshot %d bytes\n", len(png))
37
- }
38
- ```
39
-
40
- ## Surface
41
-
42
- - `New(opts...)` → `*Computer`; `WithBaseURL`, `WithAPIKey`, `WithHTTPClient`.
43
- - `Create(ctx, CreateOptions{Type, Version, Host, Family, DeviceType, Runtime})` → `*Sandbox`.
44
- - `Sandbox`: `Exec` (SSH on macOS / in-guest on Ubuntu / PowerShell on Windows), `RunShell(cmd, "powershell"|"cmd")`, `Screenshot`, `Click`, `Move`, `Scroll`, `TypeText`, `PressKey`, `Hotkey`, `UITree`, `Upload`, `Download`, `StartRecording`/`StopRecording`, `Keepalive`, `Close`.
45
-
46
- Every call takes a `context.Context`. Docs: [docs.use.computer](https://docs.use.computer). Windows is **Beta** (admin-only).