simplex 1.2.2__py3-none-any.whl → 1.2.4__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,7 @@ class Simplex:
67
67
 
68
68
 
69
69
  # Print the results
70
- print(f"Status Code: {response.status_code}")
70
+ print(response.status_code)
71
71
  if response.status_code == 200:
72
72
  res = response.json()
73
73
  bbox = [int(res['x1']), int(res['y1']), int(res['x2']), int(res['y2'])]
@@ -87,7 +87,7 @@ class Simplex:
87
87
  const overlay = document.createElement('div');
88
88
  overlay.id = 'simplex-bbox-overlay';
89
89
  overlay.style.position = 'fixed';
90
- overlay.style.border = '2px dashed rgba(74, 144, 226, 1)';
90
+ overlay.style.border = '2px dashed rgba(0, 255, 0, 1)';
91
91
  overlay.style.background = 'rgba(74, 144, 226, 0.1)';
92
92
  overlay.style.animation = 'marching-ants 0.5s linear infinite';
93
93
  overlay.style.left = bbox[0] + 'px';
@@ -122,10 +122,9 @@ class Simplex:
122
122
  }
123
123
  """, bbox)
124
124
  self.driver.wait_for_selector('#simplex-bbox-overlay')
125
- print(f"Found element \"{element_description}\" at pixel coordinates {bbox}.")
126
125
  return bbox
127
126
  else:
128
- print("Error:", response.text)
127
+ print("[SIMPLEX] Error:", response.text)
129
128
 
130
129
  def step_to_action(self, step_description: str, state: Image.Image | None = None) -> List[List[str]]:
131
130
  """
@@ -169,7 +168,7 @@ class Simplex:
169
168
  actions = [[action.strip() for action in action_pair] for action_pair in actions]
170
169
  return actions
171
170
  else:
172
- print(f"Error: {response.status_code}")
171
+ print(f"[SIMPLEX] Error: {response.status_code}")
173
172
  print(response.text)
174
173
  return []
175
174
 
@@ -184,9 +183,39 @@ class Simplex:
184
183
  if new_tab:
185
184
  self.driver = self.browser.new_page()
186
185
  self.driver.wait_for_load_state()
187
- print(f"Navigating to URL {url}...")
186
+ print(f"[SIMPLEX] Navigating to URL {url}...")
188
187
  self.driver.goto(url)
189
188
 
189
+ def click(self, element_description: str, annotate: bool = True) -> None:
190
+ """
191
+ Click on an element
192
+ """
193
+ self.execute_action(["CLICK", element_description], annotate=annotate)
194
+
195
+ def type(self, text: str) -> None:
196
+ """
197
+ Type text into an element
198
+ """
199
+ self.execute_action(["TYPE", text])
200
+
201
+ def press_enter(self, annotate: bool = True) -> None:
202
+ """
203
+ Press enter
204
+ """
205
+ self.execute_action(["ENTER", ""], annotate=annotate)
206
+
207
+ def scroll(self, scroll_amount: int, annotate: bool = True) -> None:
208
+ """
209
+ Scroll the page
210
+ """
211
+ self.execute_action(["SCROLL", scroll_amount], annotate=annotate)
212
+
213
+ def wait(self, wait_time: int, annotate: bool = True) -> None:
214
+ """
215
+ Wait for a given amount of time
216
+ """
217
+ self.execute_action(["WAIT", wait_time], annotate=annotate)
218
+
190
219
  def execute_action(self, action: List[List[str]], state: Image.Image | None = None, annotate: bool = True) -> None:
191
220
  """
192
221
  Execute an action with playwright driver
@@ -194,35 +223,31 @@ class Simplex:
194
223
  Args:
195
224
  action (List[List[str]]): List of actions to perform
196
225
  """
197
- print(f"Executing action {action}...")
198
226
  action_type, description = action
199
227
  try:
200
228
  if action_type == "CLICK":
201
- bbox = self.find_element(description, state, annotate=annotate)
229
+ bbox = self.extract_bbox(description, state, annotate=annotate)
202
230
  center_x, center_y = center_bbox(bbox)
203
231
  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
-
232
+ print(f"[SIMPLEX] Clicked on element \"{description}\"")
210
233
  elif action_type == "TYPE":
211
- print(f"Typing \"{description}\"...")
212
234
  self.driver.keyboard.type(description)
235
+ print(f"[SIMPLEX] Typed \"{description}\"")
213
236
 
214
237
  elif action_type == "ENTER":
215
238
  self.driver.keyboard.press("Enter")
239
+ print(f"[SIMPLEX] Pressed enter")
216
240
 
217
241
  elif action_type == "SCROLL":
218
242
  self.driver.mouse.wheel(0, int(description))
243
+ print(f"[SIMPLEX] Scrolled {description} pixels")
219
244
 
220
245
  elif action_type == "WAIT":
221
246
  self.driver.wait_for_timeout(int(description))
222
-
247
+ print(f"[SIMPLEX] Waited {description} seconds")
223
248
 
224
249
  except Exception as e:
225
- print(f"Error executing action: {e}")
250
+ print(f"[SIMPLEX] Error executing action: {e}")
226
251
  return None
227
252
 
228
253
  def do(self, step_description: str, annotate: bool = True) -> None:
@@ -234,13 +259,56 @@ class Simplex:
234
259
  for action in actions:
235
260
  self.execute_action(action, annotate=annotate)
236
261
 
237
- def extract(self, step_description: str, annotate: bool = True) -> None:
262
+ def extract_text(self, element_description: str, state: Image.Image | None = None) -> List[str] | None:
238
263
  """
239
- Extract an element from the page
264
+ Extract an element text from the page
240
265
  """
241
- state = self.take_stable_screenshot()
266
+ print(f"[SIMPLEX] Finding element \"{element_description}\"...")
267
+ if state is None:
268
+ state = self.take_stable_screenshot()
269
+
270
+ endpoint = f"{BASE_URL}/extract-text"
271
+
272
+ # Convert PIL Image to bytes
273
+ img_byte_arr = io.BytesIO()
274
+ state.save(img_byte_arr, format='PNG')
275
+ img_byte_arr = img_byte_arr.getvalue()
276
+
277
+ # Prepare multipart form data
278
+ files = {
279
+ 'image_data': ('screenshot.png', img_byte_arr, 'image/png'),
280
+ 'element_description': (None, element_description),
281
+ 'api_key': (None, self.api_key)
282
+ }
283
+ print("[SIMPLEX] Sending screenshot to server...")
284
+
285
+ # Make the request
286
+ response = requests.post(
287
+ endpoint,
288
+ files=files
289
+ )
290
+
291
+ # Print the results
292
+ if response.status_code == 200:
293
+ res = response.json()
294
+ text = res['text']
295
+ return text
296
+ else:
297
+ print("[SIMPLEX] Error:", response.text)
298
+ return None
299
+
300
+ def extract_image(self, element_description: str, state: Image.Image | None = None) -> Image.Image | None:
301
+ """
302
+ Extract an element image from the page
303
+ """
304
+ if state is None:
305
+ state = self.take_stable_screenshot()
306
+
307
+ bbox = self.extract_bbox(element_description, state)
308
+ cropped_state = state.crop((bbox[0], bbox[1], bbox[2], bbox[3]))
309
+ return cropped_state
310
+
242
311
 
243
- # self.execute_action(action, annotate=annotate)
244
312
 
245
313
  def take_stable_screenshot(self) -> Image.Image:
246
314
  """
@@ -249,7 +317,7 @@ class Simplex:
249
317
  Returns:
250
318
  PIL.Image.Image: Screenshot of the current page
251
319
  """
252
- print("Taking screenshot of the page...")
320
+ print("[SIMPLEX] Taking screenshot of the page...")
253
321
  self.driver.wait_for_load_state('networkidle')
254
322
  return screenshot_to_image(self.driver.screenshot())
255
323
 
@@ -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.4
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=m5vQxhVCyeU-h-cOVmpaAMoTATPJKdecfp1Fv51uaL0,12137
4
+ simplex/utils.py,sha256=UrD4Ena3yk0POmxxyiqMszzPbTscTCJpMP4xZFDAuOc,339
5
+ simplex-1.2.4.dist-info/LICENSE,sha256=Xh0SJjYZfNI71pCNMB40aKlBLLuOB0blx5xkTtufFNQ,1075
6
+ simplex-1.2.4.dist-info/METADATA,sha256=YyDn-TaMU_3JQO9ZWFbRA214_Lak1zKmA8beIHl0zPI,1114
7
+ simplex-1.2.4.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
8
+ simplex-1.2.4.dist-info/entry_points.txt,sha256=3veL2w3c5vxb3dm8I_M8Fs-370n1ZnvD8uu1nSsL7z8,45
9
+ simplex-1.2.4.dist-info/top_level.txt,sha256=cbMH1bYpN0A3gP-ecibPRHasHoqB-01T_2BUFS8p0CE,8
10
+ simplex-1.2.4.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,,