e2b-desktop 0.0.1__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.
@@ -0,0 +1,147 @@
1
+ Metadata-Version: 2.1
2
+ Name: e2b-desktop
3
+ Version: 0.0.1
4
+ Summary: E2B Desktop Sandbox - Deskstop sandbox in cloud powered by E2B
5
+ Home-page: https://e2b.dev/
6
+ License: Apache-2.0
7
+ Author: e2b
8
+ Author-email: hello@e2b.dev
9
+ Requires-Python: >=3.9,<4.0
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Requires-Dist: e2b (>=1.0.1,<2.0.0)
17
+ Requires-Dist: easyocr (>=1.7.2,<2.0.0)
18
+ Requires-Dist: numpy (==1.24)
19
+ Requires-Dist: opencv-python (==4.8.1.78)
20
+ Project-URL: Bug Tracker, https://github.com/e2b-dev/desktop/issues
21
+ Project-URL: Repository, https://github.com/e2b-dev/desktop/tree/main/python
22
+ Description-Content-Type: text/markdown
23
+
24
+ # E2B Desktop Sandbox (beta)
25
+
26
+ E2B Desktop Sandbox is an isolated cloud environment with a desktop-like interface powered by [E2B](https://e2b.dev).
27
+
28
+ Launching E2B Sandbox takes about 300-500ms. You can customize the desktop environment and preinstall any dependencies you want using our [custom sandbox templates](https://e2b.dev/docs/sandbox-template).
29
+
30
+ ![Desktop Sandbox](screenshot.png)
31
+
32
+ **Work in progress**
33
+ This repository is a work in progress. We welcome feedback and contributions. Here's the list of features we're working on:
34
+ - [ ] JavaScript SDK
35
+ - [ ] Streaming live desktop
36
+ - [ ] Tests
37
+ - [ ] Docstrings
38
+
39
+ ## Getting started
40
+ The E2B Desktop Sandbox is built on top of [E2B Sandbox](https://e2b.dev/docs).
41
+
42
+ ### 1. Get E2B API key
43
+ Sign up at [E2B](https://e2b.dev) and get your API key.
44
+ Set environment variable `E2B_API_KEY` with your API key.
45
+
46
+ ### 2. Install SDK
47
+ **Python**
48
+ ```bash
49
+ pip install e2b-desktop
50
+ ```
51
+
52
+ **JavaScript**
53
+ ```bash
54
+ Coming soon
55
+ ```
56
+
57
+ ### 3. Create Desktop Sandbox
58
+ ```python
59
+ from e2b_desktop import Sandbox
60
+
61
+ desktop = Sandbox()
62
+ ```
63
+
64
+ ## Features
65
+
66
+ ### Mouse control
67
+ ```python
68
+ from e2b_desktop import Sandbox
69
+ desktop = Sandbox()
70
+
71
+ desktop.double_click()
72
+ desktop.left_click()
73
+ desktop.right_click()
74
+ desktop.middle_click()
75
+ desktop.scroll(10) # Scroll by the amount. Positive for up, negative for down.
76
+ desktop.mouse_move(100, 200) # Move to x, y coordinates
77
+ ```
78
+
79
+ ### Locate on screen
80
+ ```python
81
+ from e2b_desktop import Sandbox
82
+ desktop = Sandbox()
83
+
84
+ # Find "Home" text on the screen and return the coordinates
85
+ x, y = desktop.locate_on_screen("Home")
86
+ # Move the mouse to the coordinates
87
+ desktop.mouse_move(x, y)
88
+ ```
89
+
90
+ ### Keyboard control
91
+ ```python
92
+ from e2b_desktop import Sandbox
93
+ desktop = Sandbox()
94
+
95
+ desktop.write("Hello, world!") # Write text at the current cursor position
96
+ desktop.hotkey("ctrl", "c") # Press ctrl+c
97
+ ```
98
+
99
+ ### Screenshot
100
+ ```python
101
+ from e2b_desktop import Sandbox
102
+ desktop = Sandbox()
103
+
104
+ # Take a screenshot and save it as "screenshot.png" locally
105
+ desktop.screenshot("screenshot.png")
106
+ ```
107
+
108
+ ### Open file
109
+ ```python
110
+ from e2b_desktop import Sandbox
111
+ desktop = Sandbox()
112
+
113
+ # Open file with default application
114
+ desktop.files.write("/home/user/index.js", "console.log('hello')") # First create the file
115
+ desktop.open("/home/user/index.js") # Then open it
116
+ ```
117
+
118
+ ### Run any bash commands
119
+ ```python
120
+ from e2b_desktop import Sandbox
121
+ desktop = Sandbox()
122
+
123
+ # Run any bash command
124
+ desktop.commands.run("ls -la /home/user")
125
+ ```
126
+
127
+ ### Run PyAutoGUI commands
128
+ ```python
129
+ from e2b_desktop import Sandbox
130
+ desktop = Sandbox()
131
+
132
+ # Run any PyAutoGUI command
133
+ desktop.pyautogui("pyautogui.click()")
134
+ ```
135
+
136
+ <!-- ### Customization
137
+ ```python
138
+ from e2b_desktop import Sandbox
139
+ desktop = Sandbox()
140
+ ``` -->
141
+
142
+ ## Under the hood
143
+ You can use [PyAutoGUI](https://pyautogui.readthedocs.io/en/latest/) to control the whole environment programmatically.
144
+
145
+ The desktop-like environment is based on Linux and [Xfce](https://www.xfce.org/) at the moment. We chose Xfce because it's a fast and lightweight environment that's also popular and actively supported. However, this Sandbox template is fully customizable and you can create your own desktop environment.
146
+ Check out the code [here](./template/)
147
+
@@ -0,0 +1,123 @@
1
+ # E2B Desktop Sandbox (beta)
2
+
3
+ E2B Desktop Sandbox is an isolated cloud environment with a desktop-like interface powered by [E2B](https://e2b.dev).
4
+
5
+ Launching E2B Sandbox takes about 300-500ms. You can customize the desktop environment and preinstall any dependencies you want using our [custom sandbox templates](https://e2b.dev/docs/sandbox-template).
6
+
7
+ ![Desktop Sandbox](screenshot.png)
8
+
9
+ **Work in progress**
10
+ This repository is a work in progress. We welcome feedback and contributions. Here's the list of features we're working on:
11
+ - [ ] JavaScript SDK
12
+ - [ ] Streaming live desktop
13
+ - [ ] Tests
14
+ - [ ] Docstrings
15
+
16
+ ## Getting started
17
+ The E2B Desktop Sandbox is built on top of [E2B Sandbox](https://e2b.dev/docs).
18
+
19
+ ### 1. Get E2B API key
20
+ Sign up at [E2B](https://e2b.dev) and get your API key.
21
+ Set environment variable `E2B_API_KEY` with your API key.
22
+
23
+ ### 2. Install SDK
24
+ **Python**
25
+ ```bash
26
+ pip install e2b-desktop
27
+ ```
28
+
29
+ **JavaScript**
30
+ ```bash
31
+ Coming soon
32
+ ```
33
+
34
+ ### 3. Create Desktop Sandbox
35
+ ```python
36
+ from e2b_desktop import Sandbox
37
+
38
+ desktop = Sandbox()
39
+ ```
40
+
41
+ ## Features
42
+
43
+ ### Mouse control
44
+ ```python
45
+ from e2b_desktop import Sandbox
46
+ desktop = Sandbox()
47
+
48
+ desktop.double_click()
49
+ desktop.left_click()
50
+ desktop.right_click()
51
+ desktop.middle_click()
52
+ desktop.scroll(10) # Scroll by the amount. Positive for up, negative for down.
53
+ desktop.mouse_move(100, 200) # Move to x, y coordinates
54
+ ```
55
+
56
+ ### Locate on screen
57
+ ```python
58
+ from e2b_desktop import Sandbox
59
+ desktop = Sandbox()
60
+
61
+ # Find "Home" text on the screen and return the coordinates
62
+ x, y = desktop.locate_on_screen("Home")
63
+ # Move the mouse to the coordinates
64
+ desktop.mouse_move(x, y)
65
+ ```
66
+
67
+ ### Keyboard control
68
+ ```python
69
+ from e2b_desktop import Sandbox
70
+ desktop = Sandbox()
71
+
72
+ desktop.write("Hello, world!") # Write text at the current cursor position
73
+ desktop.hotkey("ctrl", "c") # Press ctrl+c
74
+ ```
75
+
76
+ ### Screenshot
77
+ ```python
78
+ from e2b_desktop import Sandbox
79
+ desktop = Sandbox()
80
+
81
+ # Take a screenshot and save it as "screenshot.png" locally
82
+ desktop.screenshot("screenshot.png")
83
+ ```
84
+
85
+ ### Open file
86
+ ```python
87
+ from e2b_desktop import Sandbox
88
+ desktop = Sandbox()
89
+
90
+ # Open file with default application
91
+ desktop.files.write("/home/user/index.js", "console.log('hello')") # First create the file
92
+ desktop.open("/home/user/index.js") # Then open it
93
+ ```
94
+
95
+ ### Run any bash commands
96
+ ```python
97
+ from e2b_desktop import Sandbox
98
+ desktop = Sandbox()
99
+
100
+ # Run any bash command
101
+ desktop.commands.run("ls -la /home/user")
102
+ ```
103
+
104
+ ### Run PyAutoGUI commands
105
+ ```python
106
+ from e2b_desktop import Sandbox
107
+ desktop = Sandbox()
108
+
109
+ # Run any PyAutoGUI command
110
+ desktop.pyautogui("pyautogui.click()")
111
+ ```
112
+
113
+ <!-- ### Customization
114
+ ```python
115
+ from e2b_desktop import Sandbox
116
+ desktop = Sandbox()
117
+ ``` -->
118
+
119
+ ## Under the hood
120
+ You can use [PyAutoGUI](https://pyautogui.readthedocs.io/en/latest/) to control the whole environment programmatically.
121
+
122
+ The desktop-like environment is based on Linux and [Xfce](https://www.xfce.org/) at the moment. We chose Xfce because it's a fast and lightweight environment that's also popular and actively supported. However, this Sandbox template is fully customizable and you can create your own desktop environment.
123
+ Check out the code [here](./template/)
@@ -0,0 +1,3 @@
1
+ from e2b import *
2
+
3
+ from .main import Sandbox
@@ -0,0 +1,198 @@
1
+ import uuid
2
+ import easyocr
3
+ import numpy as np
4
+ import cv2
5
+
6
+ from typing import Callable, Optional, Union
7
+ from e2b import Sandbox as SandboxBase
8
+
9
+
10
+ class Sandbox(SandboxBase):
11
+ default_template = "desktop"
12
+
13
+ def screenshot(
14
+ self,
15
+ name: str,
16
+ on_stdout: Optional[Callable[[str], None]] = None,
17
+ on_stderr: Optional[Callable[[str], None]] = None,
18
+ ):
19
+ """
20
+ Take a screenshot and save it to the given name.
21
+ :param name: The name of the screenshot file to save locally.
22
+ """
23
+ screenshot_path = f"/home/user/screenshot-{uuid.uuid4()}.png"
24
+
25
+ self.commands.run(
26
+ f"scrot --pointer {screenshot_path}",
27
+ on_stderr=on_stderr,
28
+ on_stdout=on_stdout,
29
+ cwd="/home/user",
30
+ )
31
+
32
+ with open(name, "wb") as f:
33
+ file = self.files.read(screenshot_path, format="bytes")
34
+ f.write(file)
35
+
36
+ def left_click(self):
37
+ """
38
+ Left click on the current mouse position.
39
+ """
40
+ return self.pyautogui("pyautogui.click()")
41
+
42
+ def double_click(self):
43
+ """
44
+ Double left click on the current mouse position.
45
+ """
46
+ return self.pyautogui("pyautogui.doubleClick()")
47
+
48
+ def right_click(self):
49
+ """
50
+ Right click on the current mouse position.
51
+ """
52
+ return self.pyautogui("pyautogui.rightClick()")
53
+
54
+ def middle_click(self):
55
+ return self.pyautogui("pyautogui.middleClick()")
56
+
57
+ def scroll(self, amount: int):
58
+ return self.pyautogui(f"pyautogui.scroll({amount})")
59
+
60
+ def mouse_move(
61
+ self,
62
+ x_or_coords: Union[int, tuple[int, int]],
63
+ y: Optional[int] = None,
64
+ ):
65
+ """
66
+ Move the mouse to the given coordinates.
67
+ :param x_or_coords: The x coordinate or a tuple of (x, y).
68
+ :param y: The y coordinate, if x_or_coords is not a tuple.
69
+ """
70
+ if isinstance(x_or_coords, tuple):
71
+ x, y = x_or_coords
72
+ return self.pyautogui(f"pyautogui.moveTo({x}, {y})")
73
+
74
+ def locate_on_screen(self, text: str) -> tuple[int, int] | None:
75
+ """
76
+ Locate the text on the screen and return the position.
77
+ :param text: The text to locate.
78
+ """
79
+
80
+ # Take a screenshot
81
+ screenshot_path = f"/home/user/screenshot-{uuid.uuid4()}.png"
82
+ self.commands.run(f"scrot --pointer {screenshot_path}")
83
+ image_bytes = self.files.read(screenshot_path, format="bytes")
84
+
85
+ # Convert bytes to numpy array
86
+ nparr = np.frombuffer(image_bytes, np.uint8)
87
+ image = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
88
+
89
+ # Initialize EasyOCR reader
90
+ reader = easyocr.Reader(["en"])
91
+
92
+ # Perform OCR
93
+ results = reader.readtext(image)
94
+
95
+ # Find the text in the results
96
+ for bbox, detected_text, prob in results:
97
+ if text.lower() in detected_text.lower():
98
+ # Calculate center of bounding box
99
+ (top_left, top_right, bottom_right, bottom_left) = bbox
100
+ center_x = (top_left[0] + bottom_right[0]) / 2
101
+ center_y = (top_left[1] + bottom_right[1]) / 2
102
+ return center_x, center_y
103
+ return None
104
+
105
+ def get_cursor_position(self):
106
+ """
107
+ Get the current cursor position.
108
+ :return: A tuple with the x and y coordinates.
109
+ """
110
+ # We save the value to a file because stdout contains warnings about Xauthority.
111
+ self.pyautogui(
112
+ """
113
+ x, y = pyautogui.position()
114
+ with open("/tmp/cursor_position.txt", "w") as f:
115
+ f.write(str(x) + " " + str(y))
116
+ """
117
+ )
118
+ # pos is like this: 100 200
119
+ pos = self.files.read("/tmp/cursor_position.txt")
120
+ return tuple(map(int, pos.split(" ")))
121
+
122
+ def get_screen_size(self):
123
+ """
124
+ Get the current screen size.
125
+ :return: A tuple with the width and height.
126
+ """
127
+ # We save the value to a file because stdout contains warnings about Xauthority.
128
+ self.pyautogui(
129
+ """
130
+ width, height = pyautogui.size()
131
+ with open("/tmp/size.txt", "w") as f:
132
+ f.write(str(width) + " " + str(height))
133
+ """
134
+ )
135
+ # size is like this: 100 200
136
+ size = self.files.read("/tmp/size.txt")
137
+ return tuple(map(int, size.split(" ")))
138
+
139
+ def write(self, text: str):
140
+ """
141
+ Write the given text at the current cursor position.
142
+ :param text: The text to write.
143
+ """
144
+ return self.pyautogui(f"pyautogui.write({text!r})")
145
+
146
+ def hotkey(self, *keys):
147
+ """
148
+ Press a hotkey.
149
+ :param keys: The keys to press.
150
+ """
151
+ return self.pyautogui(f"pyautogui.hotkey({keys!r})")
152
+
153
+ def open(self, file_or_url: str):
154
+ """
155
+ Open a file or a URL in the default application.
156
+ :param file_or_url: The file or URL to open.
157
+ """
158
+ return self.commands.run(f"xdg-open {file_or_url}", background=True)
159
+
160
+ def install_package(self, package: str):
161
+ """
162
+ Install a package with apt.
163
+ :param package: The package to install.
164
+ """
165
+ return self.commands.run(f"apt-get install -y {package}")
166
+
167
+ @staticmethod
168
+ def _wrap_pyautogui_code(code: str):
169
+ return f"""
170
+ import pyautogui
171
+ import os
172
+ import Xlib.display
173
+
174
+ display = Xlib.display.Display(os.environ["DISPLAY"])
175
+ pyautogui._pyautogui_x11._display = display
176
+
177
+ {code}
178
+ exit(0)
179
+ """
180
+
181
+ def pyautogui(
182
+ self,
183
+ pyautogui_code: str,
184
+ on_stdout: Optional[Callable[[str], None]] = None,
185
+ on_stderr: Optional[Callable[[str], None]] = None,
186
+ ):
187
+ code_path = f"/home/user/code-{uuid.uuid4()}.py"
188
+
189
+ code = self._wrap_pyautogui_code(pyautogui_code)
190
+
191
+ self.files.write(code_path, code)
192
+
193
+ out = self.commands.run(
194
+ f"python {code_path}",
195
+ on_stdout=on_stdout,
196
+ on_stderr=on_stderr,
197
+ )
198
+ return out
@@ -0,0 +1,32 @@
1
+ [tool.poetry]
2
+ name = "e2b-desktop"
3
+ version = "0.0.1"
4
+ description = "E2B Desktop Sandbox - Deskstop sandbox in cloud powered by E2B"
5
+ authors = ["e2b <hello@e2b.dev>"]
6
+ license = "Apache-2.0"
7
+ readme = "README.md"
8
+ homepage = "https://e2b.dev/"
9
+ repository = "https://github.com/e2b-dev/desktop/tree/main/python"
10
+ packages = [{ include = "e2b_desktop" }]
11
+
12
+ [tool.poetry.dependencies]
13
+ python = "^3.9"
14
+
15
+ e2b = "^1.0.1"
16
+ easyocr = "^1.7.2"
17
+ numpy = "1.24"
18
+ opencv-python = "4.8.1.78"
19
+
20
+ [tool.poetry.group.dev.dependencies]
21
+ black = "^24.3.0"
22
+ pytest = "^7.4.0"
23
+ python-dotenv = "^1.0.0"
24
+ pytest-dotenv = "^0.5.2"
25
+ pytest-xdist = "^3.6.1"
26
+
27
+ [build-system]
28
+ requires = ["poetry-core"]
29
+ build-backend = "poetry.core.masonry.api"
30
+
31
+ [tool.poetry.urls]
32
+ "Bug Tracker" = "https://github.com/e2b-dev/desktop/issues"