simplex 1.2.2__py3-none-any.whl → 1.2.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.

Potentially problematic release.


This version of simplex might be problematic. Click here for more details.

simplex/constants.py ADDED
@@ -0,0 +1 @@
1
+ BASE_URL = "https://u3mvtbirxf.us-east-1.awsapprunner.com"
simplex/simplex.py CHANGED
@@ -30,7 +30,7 @@ class Simplex:
30
30
  self.driver.set_default_navigation_timeout(0)
31
31
  self.driver.set_default_timeout(0)
32
32
 
33
- def find_element(self, element_description: str, state: Image.Image | None = None, annotate: bool = True) -> List[int]:
33
+ def extract_bbox(self, element_description: str, state: Image.Image | None = None, annotate: bool = True) -> List[int]:
34
34
  """
35
35
  Find an element in the screenshot using the element description
36
36
 
@@ -41,7 +41,7 @@ class Simplex:
41
41
  Returns:
42
42
  bounding_box (tuple): [x1, y1, x2, y2] bounding box of the found element
43
43
  """
44
- print(f"Finding element \"{element_description}\"...")
44
+ print(f"[SIMPLEX] Finding element \"{element_description}\"...")
45
45
  if state is None:
46
46
  state = self.take_stable_screenshot()
47
47
 
@@ -58,7 +58,7 @@ class Simplex:
58
58
  'element_description': (None, element_description),
59
59
  'api_key': (None, self.api_key)
60
60
  }
61
- print("Sending screenshot to server...")
61
+ print("[SIMPLEX] Sending screenshot to server...")
62
62
  # Make the request
63
63
  response = requests.post(
64
64
  endpoint,
@@ -67,7 +67,6 @@ class Simplex:
67
67
 
68
68
 
69
69
  # Print the results
70
- print(f"Status Code: {response.status_code}")
71
70
  if response.status_code == 200:
72
71
  res = response.json()
73
72
  bbox = [int(res['x1']), int(res['y1']), int(res['x2']), int(res['y2'])]
@@ -87,7 +86,7 @@ class Simplex:
87
86
  const overlay = document.createElement('div');
88
87
  overlay.id = 'simplex-bbox-overlay';
89
88
  overlay.style.position = 'fixed';
90
- overlay.style.border = '2px dashed rgba(74, 144, 226, 1)';
89
+ overlay.style.border = '2px dashed rgba(0, 255, 0, 1)';
91
90
  overlay.style.background = 'rgba(74, 144, 226, 0.1)';
92
91
  overlay.style.animation = 'marching-ants 0.5s linear infinite';
93
92
  overlay.style.left = bbox[0] + 'px';
@@ -122,10 +121,9 @@ class Simplex:
122
121
  }
123
122
  """, bbox)
124
123
  self.driver.wait_for_selector('#simplex-bbox-overlay')
125
- print(f"Found element \"{element_description}\" at pixel coordinates {bbox}.")
126
124
  return bbox
127
125
  else:
128
- print("Error:", response.text)
126
+ print("[SIMPLEX] Error:", response.text)
129
127
 
130
128
  def step_to_action(self, step_description: str, state: Image.Image | None = None) -> List[List[str]]:
131
129
  """
@@ -169,7 +167,7 @@ class Simplex:
169
167
  actions = [[action.strip() for action in action_pair] for action_pair in actions]
170
168
  return actions
171
169
  else:
172
- print(f"Error: {response.status_code}")
170
+ print(f"[SIMPLEX] Error: {response.status_code}")
173
171
  print(response.text)
174
172
  return []
175
173
 
@@ -184,9 +182,39 @@ class Simplex:
184
182
  if new_tab:
185
183
  self.driver = self.browser.new_page()
186
184
  self.driver.wait_for_load_state()
187
- print(f"Navigating to URL {url}...")
185
+ print(f"[SIMPLEX] Navigating to URL {url}...")
188
186
  self.driver.goto(url)
189
187
 
188
+ def click(self, element_description: str, annotate: bool = True) -> None:
189
+ """
190
+ Click on an element
191
+ """
192
+ self.execute_action(["CLICK", element_description], annotate=annotate)
193
+
194
+ def type(self, text: str) -> None:
195
+ """
196
+ Type text into an element
197
+ """
198
+ self.execute_action(["TYPE", text])
199
+
200
+ def press_enter(self, annotate: bool = True) -> None:
201
+ """
202
+ Press enter
203
+ """
204
+ self.execute_action(["ENTER", ""], annotate=annotate)
205
+
206
+ def scroll(self, scroll_amount: int, annotate: bool = True) -> None:
207
+ """
208
+ Scroll the page
209
+ """
210
+ self.execute_action(["SCROLL", scroll_amount], annotate=annotate)
211
+
212
+ def wait(self, wait_time: int, annotate: bool = True) -> None:
213
+ """
214
+ Wait for a given amount of time
215
+ """
216
+ self.execute_action(["WAIT", wait_time], annotate=annotate)
217
+
190
218
  def execute_action(self, action: List[List[str]], state: Image.Image | None = None, annotate: bool = True) -> None:
191
219
  """
192
220
  Execute an action with playwright driver
@@ -194,35 +222,31 @@ class Simplex:
194
222
  Args:
195
223
  action (List[List[str]]): List of actions to perform
196
224
  """
197
- print(f"Executing action {action}...")
198
225
  action_type, description = action
199
226
  try:
200
227
  if action_type == "CLICK":
201
- bbox = self.find_element(description, state, annotate=annotate)
228
+ bbox = self.extract_bbox(description, state, annotate=annotate)
202
229
  center_x, center_y = center_bbox(bbox)
203
230
  self.driver.mouse.click(center_x, center_y)
204
-
205
- elif action_type == "HOVER":
206
- bbox = self.find_element(description, state, annotate=annotate)
207
- center_x, center_y = center_bbox(bbox)
208
- self.driver.mouse.move(center_x, center_y)
209
-
231
+ print(f"[SIMPLEX] Clicked on element \"{description}\"")
210
232
  elif action_type == "TYPE":
211
- print(f"Typing \"{description}\"...")
212
233
  self.driver.keyboard.type(description)
234
+ print(f"[SIMPLEX] Typed \"{description}\"")
213
235
 
214
236
  elif action_type == "ENTER":
215
237
  self.driver.keyboard.press("Enter")
238
+ print(f"[SIMPLEX] Pressed enter")
216
239
 
217
240
  elif action_type == "SCROLL":
218
241
  self.driver.mouse.wheel(0, int(description))
242
+ print(f"[SIMPLEX] Scrolled {description} pixels")
219
243
 
220
244
  elif action_type == "WAIT":
221
245
  self.driver.wait_for_timeout(int(description))
222
-
246
+ print(f"[SIMPLEX] Waited {description} seconds")
223
247
 
224
248
  except Exception as e:
225
- print(f"Error executing action: {e}")
249
+ print(f"[SIMPLEX] Error executing action: {e}")
226
250
  return None
227
251
 
228
252
  def do(self, step_description: str, annotate: bool = True) -> None:
@@ -234,13 +258,56 @@ class Simplex:
234
258
  for action in actions:
235
259
  self.execute_action(action, annotate=annotate)
236
260
 
237
- def extract(self, step_description: str, annotate: bool = True) -> None:
261
+ def extract_text(self, element_description: str, state: Image.Image | None = None) -> List[str] | None:
238
262
  """
239
- Extract an element from the page
263
+ Extract an element text from the page
240
264
  """
241
- state = self.take_stable_screenshot()
265
+ print(f"[SIMPLEX] Finding element \"{element_description}\"...")
266
+ if state is None:
267
+ state = self.take_stable_screenshot()
268
+
269
+ endpoint = f"{BASE_URL}/extract-text"
270
+
271
+ # Convert PIL Image to bytes
272
+ img_byte_arr = io.BytesIO()
273
+ state.save(img_byte_arr, format='PNG')
274
+ img_byte_arr = img_byte_arr.getvalue()
275
+
276
+ # Prepare multipart form data
277
+ files = {
278
+ 'image_data': ('screenshot.png', img_byte_arr, 'image/png'),
279
+ 'element_description': (None, element_description),
280
+ 'api_key': (None, self.api_key)
281
+ }
282
+ print("[SIMPLEX] Sending screenshot to server...")
283
+
284
+ # Make the request
285
+ response = requests.post(
286
+ endpoint,
287
+ files=files
288
+ )
289
+
290
+ # Print the results
291
+ if response.status_code == 200:
292
+ res = response.json()
293
+ text = res['text']
294
+ return text
295
+ else:
296
+ print("[SIMPLEX] Error:", response.text)
297
+ return None
298
+
299
+ def extract_image(self, element_description: str, state: Image.Image | None = None) -> Image.Image | None:
300
+ """
301
+ Extract an element image from the page
302
+ """
303
+ if state is None:
304
+ state = self.take_stable_screenshot()
305
+
306
+ bbox = self.extract_bbox(element_description, state)
307
+ cropped_state = state.crop((bbox[0], bbox[1], bbox[2], bbox[3]))
308
+ return cropped_state
309
+
242
310
 
243
- # self.execute_action(action, annotate=annotate)
244
311
 
245
312
  def take_stable_screenshot(self) -> Image.Image:
246
313
  """
@@ -249,7 +316,7 @@ class Simplex:
249
316
  Returns:
250
317
  PIL.Image.Image: Screenshot of the current page
251
318
  """
252
- print("Taking screenshot of the page...")
319
+ print("[SIMPLEX] Taking screenshot of the page...")
253
320
  self.driver.wait_for_load_state('networkidle')
254
321
  return screenshot_to_image(self.driver.screenshot())
255
322
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: simplex
3
- Version: 1.2.2
3
+ Version: 1.2.3
4
4
  Summary: Official Python SDK for Simplex API
5
5
  Home-page: https://github.com/shreyka/simplex-python
6
6
  Author: Simplex Labs, Inc.
@@ -18,9 +18,18 @@ Requires-Dist: python-dotenv>=0.19.0
18
18
  Requires-Dist: tiktoken>=0.5.0
19
19
  Requires-Dist: click>=8.0.0
20
20
  Requires-Dist: rich>=13.0.0
21
- Requires-Dist: prompt-toolkit>=3.0.0
21
+ Requires-Dist: prompt_toolkit>=3.0.0
22
22
  Requires-Dist: playwright>=1.0.0
23
23
  Requires-Dist: Pillow>=9.0.0
24
+ Dynamic: author
25
+ Dynamic: author-email
26
+ Dynamic: classifier
27
+ Dynamic: description
28
+ Dynamic: description-content-type
29
+ Dynamic: home-page
30
+ Dynamic: requires-dist
31
+ Dynamic: requires-python
32
+ Dynamic: summary
24
33
 
25
34
  # Simplex AI Python SDK
26
35
 
@@ -0,0 +1,10 @@
1
+ simplex/__init__.py,sha256=1mbM4XUk0FNW161WOkM4ayC1s_QSsaBEls6PZ0iBScY,74
2
+ simplex/constants.py,sha256=nIXF2oVNNNknXweXAlmE-KBM9QjJtYw9osXVYjvloN0,59
3
+ simplex/simplex.py,sha256=c1kWt8KvOIu-vhVmQga1BH-sRNFHvmWBrfP9t-93iBE,12101
4
+ simplex/utils.py,sha256=UrD4Ena3yk0POmxxyiqMszzPbTscTCJpMP4xZFDAuOc,339
5
+ simplex-1.2.3.dist-info/LICENSE,sha256=Xh0SJjYZfNI71pCNMB40aKlBLLuOB0blx5xkTtufFNQ,1075
6
+ simplex-1.2.3.dist-info/METADATA,sha256=HM_H6qRoBXMEtKsO6Ish0NU5V62a7JnugRZmSvGYNMs,1114
7
+ simplex-1.2.3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
8
+ simplex-1.2.3.dist-info/entry_points.txt,sha256=3veL2w3c5vxb3dm8I_M8Fs-370n1ZnvD8uu1nSsL7z8,45
9
+ simplex-1.2.3.dist-info/top_level.txt,sha256=cbMH1bYpN0A3gP-ecibPRHasHoqB-01T_2BUFS8p0CE,8
10
+ simplex-1.2.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.1.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,9 +0,0 @@
1
- simplex/__init__.py,sha256=1mbM4XUk0FNW161WOkM4ayC1s_QSsaBEls6PZ0iBScY,74
2
- simplex/simplex.py,sha256=___oQuVrlTYR3BJDxb0INKHQO74aSqeNZyCkj8NzdYQ,9856
3
- simplex/utils.py,sha256=UrD4Ena3yk0POmxxyiqMszzPbTscTCJpMP4xZFDAuOc,339
4
- simplex-1.2.2.dist-info/LICENSE,sha256=Xh0SJjYZfNI71pCNMB40aKlBLLuOB0blx5xkTtufFNQ,1075
5
- simplex-1.2.2.dist-info/METADATA,sha256=cRRdYjOEPq-fkUDokBgx8Sas49liFjB6BLo4Ypv1dG0,917
6
- simplex-1.2.2.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
7
- simplex-1.2.2.dist-info/entry_points.txt,sha256=3veL2w3c5vxb3dm8I_M8Fs-370n1ZnvD8uu1nSsL7z8,45
8
- simplex-1.2.2.dist-info/top_level.txt,sha256=cbMH1bYpN0A3gP-ecibPRHasHoqB-01T_2BUFS8p0CE,8
9
- simplex-1.2.2.dist-info/RECORD,,