simplex 1.2.55__py3-none-any.whl → 1.2.58__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/simplex.py +76 -26
- {simplex-1.2.55.dist-info → simplex-1.2.58.dist-info}/METADATA +1 -1
- simplex-1.2.58.dist-info/RECORD +11 -0
- simplex-1.2.55.dist-info/RECORD +0 -11
- {simplex-1.2.55.dist-info → simplex-1.2.58.dist-info}/LICENSE +0 -0
- {simplex-1.2.55.dist-info → simplex-1.2.58.dist-info}/WHEEL +0 -0
- {simplex-1.2.55.dist-info → simplex-1.2.58.dist-info}/entry_points.txt +0 -0
- {simplex-1.2.55.dist-info → simplex-1.2.58.dist-info}/top_level.txt +0 -0
simplex/simplex.py
CHANGED
|
@@ -4,7 +4,7 @@ from typing import Optional, Union
|
|
|
4
4
|
import os
|
|
5
5
|
import json
|
|
6
6
|
import warnings
|
|
7
|
-
|
|
7
|
+
import time
|
|
8
8
|
# Try to import playwright, but don't fail if it's not available (lite version)
|
|
9
9
|
try:
|
|
10
10
|
from playwright.sync_api import sync_playwright
|
|
@@ -17,8 +17,8 @@ except ImportError:
|
|
|
17
17
|
ImportWarning
|
|
18
18
|
)
|
|
19
19
|
|
|
20
|
+
# BASE_URL = "https://simplex-dev--api-server-fastapi-app.modal.run"
|
|
20
21
|
BASE_URL = "https://api.simplex.sh"
|
|
21
|
-
|
|
22
22
|
class Playwright:
|
|
23
23
|
def __init__(self, simplex_instance):
|
|
24
24
|
self.simplex = simplex_instance
|
|
@@ -61,7 +61,7 @@ class Playwright:
|
|
|
61
61
|
print(response.json())
|
|
62
62
|
raise ValueError(f"It looks like the click action with playwright failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
63
63
|
|
|
64
|
-
if response.json()
|
|
64
|
+
if "succeeded" in response.json():
|
|
65
65
|
return
|
|
66
66
|
else:
|
|
67
67
|
raise ValueError(f"Failed to click element: {response.json()['error']}")
|
|
@@ -81,6 +81,7 @@ class Simplex:
|
|
|
81
81
|
self.pw = None
|
|
82
82
|
|
|
83
83
|
def close_session(self):
|
|
84
|
+
time.sleep(30)
|
|
84
85
|
if PLAYWRIGHT_AVAILABLE and self.pw_browser:
|
|
85
86
|
try:
|
|
86
87
|
self.pw_browser.close()
|
|
@@ -105,12 +106,15 @@ class Simplex:
|
|
|
105
106
|
self.session_id = None
|
|
106
107
|
if 'succeeded' not in response.json():
|
|
107
108
|
raise ValueError(f"It looks like the close_session action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
108
|
-
if response.json()
|
|
109
|
+
if "succeeded" in response.json():
|
|
109
110
|
return
|
|
110
111
|
else:
|
|
111
112
|
raise ValueError(f"Failed to close session: {response.json()['error']}")
|
|
112
113
|
|
|
113
|
-
def create_session(self, show_in_console: Optional[bool] = True, proxies: Optional[bool] = True, session_data: Optional[dict | str] = None):
|
|
114
|
+
def create_session(self, show_in_console: Optional[bool] = True, proxies: Optional[bool] = True, workflow_name: Optional[str] = None, session_data: Optional[dict | str] = None):
|
|
115
|
+
if self.session_id:
|
|
116
|
+
raise ValueError("A session is already active. Please close the current session before creating a new one.")
|
|
117
|
+
|
|
114
118
|
if session_data:
|
|
115
119
|
if isinstance(session_data, dict):
|
|
116
120
|
session_data_dict = session_data
|
|
@@ -130,7 +134,7 @@ class Simplex:
|
|
|
130
134
|
headers={
|
|
131
135
|
'x-api-key': self.api_key
|
|
132
136
|
},
|
|
133
|
-
data={'proxies': proxies, 'session_data': json.dumps(session_data_dict)}
|
|
137
|
+
data={'proxies': proxies, 'session_data': json.dumps(session_data_dict), 'workflow_name': workflow_name}
|
|
134
138
|
)
|
|
135
139
|
else:
|
|
136
140
|
response = requests.post(
|
|
@@ -138,7 +142,7 @@ class Simplex:
|
|
|
138
142
|
headers={
|
|
139
143
|
'x-api-key': self.api_key
|
|
140
144
|
},
|
|
141
|
-
data={'proxies': proxies}
|
|
145
|
+
data={'proxies': proxies, "workflow_name": workflow_name}
|
|
142
146
|
)
|
|
143
147
|
# Check for non-200 status code
|
|
144
148
|
if response.status_code != 200:
|
|
@@ -155,7 +159,9 @@ class Simplex:
|
|
|
155
159
|
self.pw = sync_playwright().start()
|
|
156
160
|
self.connect_url = response_json['connect_url']
|
|
157
161
|
# self.pw_browser = self.pw.chromium.connect_over_cdp(response_json['connect_url'])
|
|
158
|
-
|
|
162
|
+
if not "api.simplex.sh" in BASE_URL:
|
|
163
|
+
livestream_url = f"http://localhost:3000/session/{self.session_id}"
|
|
164
|
+
|
|
159
165
|
if show_in_console:
|
|
160
166
|
print(f"Livestream URL: {livestream_url}")
|
|
161
167
|
|
|
@@ -185,12 +191,14 @@ class Simplex:
|
|
|
185
191
|
if 'succeeded' not in response.json():
|
|
186
192
|
raise ValueError(f"It looks like the goto action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
187
193
|
|
|
188
|
-
if response.json()
|
|
194
|
+
if "succeeded" in response.json():
|
|
189
195
|
return
|
|
190
196
|
else:
|
|
191
197
|
raise ValueError(f"Failed to goto url: {response.json()['error']}")
|
|
192
198
|
|
|
193
199
|
def click(self, element_description: str, cdp_url: str = None):
|
|
200
|
+
if not element_description or not element_description.strip():
|
|
201
|
+
raise ValueError("element_description cannot be empty")
|
|
194
202
|
if not cdp_url and not self.session_id:
|
|
195
203
|
raise ValueError(f"Must call create_session before calling action click with element_description='{element_description}'")
|
|
196
204
|
|
|
@@ -210,12 +218,14 @@ class Simplex:
|
|
|
210
218
|
)
|
|
211
219
|
if 'succeeded' not in response.json():
|
|
212
220
|
raise ValueError(f"It looks like the click action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
213
|
-
if response.json()
|
|
221
|
+
if "succeeded" in response.json():
|
|
214
222
|
return response.json()["element_clicked"]
|
|
215
223
|
else:
|
|
216
224
|
raise ValueError(f"Failed to click element: {response.json()['error']}")
|
|
217
225
|
|
|
218
226
|
def type(self, text: str, cdp_url: str = None):
|
|
227
|
+
if not text or not text.strip():
|
|
228
|
+
raise ValueError("text cannot be empty")
|
|
219
229
|
if not cdp_url and not self.session_id:
|
|
220
230
|
raise ValueError(f"Must call create_session before calling action type with text='{text}'")
|
|
221
231
|
|
|
@@ -233,11 +243,38 @@ class Simplex:
|
|
|
233
243
|
},
|
|
234
244
|
data=data
|
|
235
245
|
)
|
|
236
|
-
if response.json()
|
|
246
|
+
if "succeeded" in response.json():
|
|
237
247
|
return
|
|
238
248
|
else:
|
|
249
|
+
print(response.json())
|
|
239
250
|
raise ValueError(f"Failed to type text: {response.json()['error']}")
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def reload(self, cdp_url: str = None):
|
|
254
|
+
if not cdp_url and not self.session_id:
|
|
255
|
+
raise ValueError("Must call create_session before calling action reload")
|
|
256
|
+
|
|
257
|
+
data = {}
|
|
258
|
+
|
|
259
|
+
if cdp_url:
|
|
260
|
+
data['cdp_url'] = cdp_url
|
|
261
|
+
else:
|
|
262
|
+
data['session_id'] = self.session_id
|
|
240
263
|
|
|
264
|
+
response = requests.post(
|
|
265
|
+
f"{BASE_URL}/reload",
|
|
266
|
+
headers={
|
|
267
|
+
'x-api-key': self.api_key
|
|
268
|
+
},
|
|
269
|
+
data=data
|
|
270
|
+
)
|
|
271
|
+
if 'succeeded' not in response.json():
|
|
272
|
+
raise ValueError(f"It looks like the reload action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
273
|
+
if "succeeded" in response.json():
|
|
274
|
+
return
|
|
275
|
+
else:
|
|
276
|
+
raise ValueError(f"Failed to reload: {response.json()['error']}")
|
|
277
|
+
|
|
241
278
|
def press_enter(self, cdp_url: str = None):
|
|
242
279
|
if not cdp_url and not self.session_id:
|
|
243
280
|
raise ValueError("Must call create_session before calling action press_enter")
|
|
@@ -258,7 +295,7 @@ class Simplex:
|
|
|
258
295
|
)
|
|
259
296
|
if 'succeeded' not in response.json():
|
|
260
297
|
raise ValueError(f"It looks like the press_enter action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
261
|
-
if response.json()
|
|
298
|
+
if "succeeded" in response.json():
|
|
262
299
|
return
|
|
263
300
|
else:
|
|
264
301
|
raise ValueError(f"Failed to press enter: {response.json()['error']}")
|
|
@@ -283,7 +320,7 @@ class Simplex:
|
|
|
283
320
|
)
|
|
284
321
|
if 'succeeded' not in response.json():
|
|
285
322
|
raise ValueError(f"It looks like the press_tab action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
286
|
-
if response.json()
|
|
323
|
+
if "succeeded" in response.json():
|
|
287
324
|
return
|
|
288
325
|
else:
|
|
289
326
|
raise ValueError(f"Failed to press tab: {response.json()['error']}")
|
|
@@ -308,12 +345,14 @@ class Simplex:
|
|
|
308
345
|
)
|
|
309
346
|
if 'succeeded' not in response.json():
|
|
310
347
|
raise ValueError(f"It looks like the delete_text action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
311
|
-
if response.json()
|
|
348
|
+
if "succeeded" in response.json():
|
|
312
349
|
return
|
|
313
350
|
else:
|
|
314
351
|
raise ValueError(f"Failed to delete text: {response.json()['error']}")
|
|
315
352
|
|
|
316
353
|
def extract_bbox(self, element_description: str, cdp_url: str = None):
|
|
354
|
+
if not element_description or not element_description.strip():
|
|
355
|
+
raise ValueError("element_description cannot be empty")
|
|
317
356
|
if not cdp_url and not self.session_id:
|
|
318
357
|
raise ValueError(f"Must call create_session before calling action extract_bbox with element_description='{element_description}'")
|
|
319
358
|
|
|
@@ -333,12 +372,14 @@ class Simplex:
|
|
|
333
372
|
)
|
|
334
373
|
if 'succeeded' not in response.json():
|
|
335
374
|
raise ValueError(f"It looks like the extract_bbox action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
336
|
-
if response.json()
|
|
375
|
+
if "succeeded" in response.json():
|
|
337
376
|
return response.json()["bbox"]
|
|
338
377
|
else:
|
|
339
378
|
raise ValueError(f"Failed to extract bbox: {response.json()['error']}")
|
|
340
379
|
|
|
341
380
|
def extract_text(self, element_description: str, cdp_url: str = None):
|
|
381
|
+
if not element_description or not element_description.strip():
|
|
382
|
+
raise ValueError("element_description cannot be empty")
|
|
342
383
|
if not cdp_url and not self.session_id:
|
|
343
384
|
raise ValueError(f"Must call create_session before calling action extract_text with element_description='{element_description}'")
|
|
344
385
|
|
|
@@ -356,14 +397,17 @@ class Simplex:
|
|
|
356
397
|
},
|
|
357
398
|
data=data
|
|
358
399
|
)
|
|
359
|
-
|
|
400
|
+
response_json = response.json()
|
|
401
|
+
if 'succeeded' not in response_json:
|
|
360
402
|
raise ValueError(f"It looks like the extract_text action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
361
|
-
if
|
|
362
|
-
return
|
|
403
|
+
if "succeeded" in response_json:
|
|
404
|
+
return response_json["text"]
|
|
363
405
|
else:
|
|
364
|
-
raise ValueError(f"Failed to extract text: {
|
|
406
|
+
raise ValueError(f"Failed to extract text: {response_json['error']}")
|
|
365
407
|
|
|
366
408
|
def extract_image(self, element_description: str, cdp_url: str = None):
|
|
409
|
+
if not element_description or not element_description.strip():
|
|
410
|
+
raise ValueError("element_description cannot be empty")
|
|
367
411
|
if not cdp_url and not self.session_id:
|
|
368
412
|
raise ValueError(f"Must call create_session before calling action extract_image with element_description='{element_description}'")
|
|
369
413
|
|
|
@@ -383,7 +427,7 @@ class Simplex:
|
|
|
383
427
|
)
|
|
384
428
|
if 'succeeded' not in response.json():
|
|
385
429
|
raise ValueError(f"It looks like the extract_image action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
386
|
-
if response.json()
|
|
430
|
+
if "succeeded" in response.json():
|
|
387
431
|
return response.json()["image"]
|
|
388
432
|
else:
|
|
389
433
|
raise ValueError(f"Failed to extract image: {response.json()['error']}")
|
|
@@ -408,7 +452,7 @@ class Simplex:
|
|
|
408
452
|
)
|
|
409
453
|
if 'succeeded' not in response.json():
|
|
410
454
|
raise ValueError(f"It looks like the scroll action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
411
|
-
if response.json()
|
|
455
|
+
if "succeeded" in response.json():
|
|
412
456
|
return
|
|
413
457
|
else:
|
|
414
458
|
raise ValueError(f"Failed to scroll: {response.json()['error']}")
|
|
@@ -433,7 +477,7 @@ class Simplex:
|
|
|
433
477
|
)
|
|
434
478
|
if 'succeeded' not in response.json():
|
|
435
479
|
raise ValueError(f"It looks like the wait action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
436
|
-
if response.json()
|
|
480
|
+
if "succeeded" in response.json():
|
|
437
481
|
return
|
|
438
482
|
else:
|
|
439
483
|
raise ValueError(f"Failed to wait: {response.json()['error']}")
|
|
@@ -550,7 +594,7 @@ class Simplex:
|
|
|
550
594
|
)
|
|
551
595
|
if 'succeeded' not in response.json():
|
|
552
596
|
raise ValueError(f"It looks like the restore_login_session action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
553
|
-
if response.json()
|
|
597
|
+
if "succeeded" in response.json():
|
|
554
598
|
return
|
|
555
599
|
else:
|
|
556
600
|
raise ValueError(f"Failed to restore login session: {response.json()['error']}")
|
|
@@ -561,6 +605,8 @@ class Simplex:
|
|
|
561
605
|
element_description: Description of the element to click and upload to
|
|
562
606
|
file_path_or_callable: Either a path to the file to be uploaded or a callable that returns a file-like object in 'rb' mode
|
|
563
607
|
"""
|
|
608
|
+
if not element_description or not element_description.strip():
|
|
609
|
+
raise ValueError("element_description cannot be empty")
|
|
564
610
|
if not self.session_id:
|
|
565
611
|
raise ValueError(f"Must call create_session before calling action click_and_upload with element_description='{element_description}'")
|
|
566
612
|
|
|
@@ -592,12 +638,14 @@ class Simplex:
|
|
|
592
638
|
)
|
|
593
639
|
if 'succeeded' not in response.json():
|
|
594
640
|
raise ValueError(f"It looks like the click_and_upload action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
595
|
-
if response.json()
|
|
641
|
+
if "succeeded" in response.json():
|
|
596
642
|
return
|
|
597
643
|
else:
|
|
598
644
|
raise ValueError(f"Failed to click and upload: {response.json()['error']}")
|
|
599
645
|
|
|
600
646
|
def click_and_download(self, element_description: str):
|
|
647
|
+
if not element_description or not element_description.strip():
|
|
648
|
+
raise ValueError("element_description cannot be empty")
|
|
601
649
|
if not self.session_id:
|
|
602
650
|
raise ValueError(f"Must call create_session before calling action click_and_download with element_description='{element_description}'")
|
|
603
651
|
|
|
@@ -616,12 +664,14 @@ class Simplex:
|
|
|
616
664
|
)
|
|
617
665
|
if 'succeeded' not in response.json():
|
|
618
666
|
raise ValueError(f"It looks like the click_and_download action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
619
|
-
if response.json()
|
|
667
|
+
if "succeeded" in response.json():
|
|
620
668
|
return response.json()["b64"], response.json()["filename"]
|
|
621
669
|
else:
|
|
622
670
|
raise ValueError(f"Failed to click and download: {response.json()['error']}")
|
|
623
671
|
|
|
624
672
|
def exists(self, element_description: str, cdp_url: str = None):
|
|
673
|
+
if not element_description or not element_description.strip():
|
|
674
|
+
raise ValueError("element_description cannot be empty")
|
|
625
675
|
if not cdp_url and not self.session_id:
|
|
626
676
|
raise ValueError(f"Must call create_session before calling action exists with element_description='{element_description}'")
|
|
627
677
|
|
|
@@ -642,7 +692,7 @@ class Simplex:
|
|
|
642
692
|
if 'succeeded' not in response.json():
|
|
643
693
|
raise ValueError(f"It looks like the exists action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
644
694
|
response_json = response.json()
|
|
645
|
-
if response_json
|
|
695
|
+
if "succeeded" in response_json:
|
|
646
696
|
return response_json['exists'], response_json['reasoning']
|
|
647
697
|
else:
|
|
648
698
|
raise ValueError(f"Failed to check if element exists: {response_json['error']}")
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
simplex/__init__.py,sha256=L_5i__xt_ZDkr6e-Wx9cr84t9sXpioOT7j01NJYJCTE,75
|
|
2
|
+
simplex/cli.py,sha256=0K_pzoVdF7vfTJPUONhFzzTvjZk2M7FZPpEONjZWJC8,2268
|
|
3
|
+
simplex/simplex.py,sha256=1rHcnBxP9KGXAARMg0R-sHpvWHha3oqvVUQIv4qvzIY,27649
|
|
4
|
+
simplex/deploy/__init__.py,sha256=_JQ81F_Nu7hSAfMA691gzs6a4-8oZ-buJ9h3Au12BKw,96
|
|
5
|
+
simplex/deploy/push.py,sha256=hRAbtFZaECKnBljaOLQ5nzJ6hk7tZgc1c7QdgxKQFoY,6123
|
|
6
|
+
simplex-1.2.58.dist-info/LICENSE,sha256=Xh0SJjYZfNI71pCNMB40aKlBLLuOB0blx5xkTtufFNQ,1075
|
|
7
|
+
simplex-1.2.58.dist-info/METADATA,sha256=XLJEsvkYBQZpZPYobkRrGbhECHqsC7VW2bXlU64dUuI,1045
|
|
8
|
+
simplex-1.2.58.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
9
|
+
simplex-1.2.58.dist-info/entry_points.txt,sha256=3veL2w3c5vxb3dm8I_M8Fs-370n1ZnvD8uu1nSsL7z8,45
|
|
10
|
+
simplex-1.2.58.dist-info/top_level.txt,sha256=cbMH1bYpN0A3gP-ecibPRHasHoqB-01T_2BUFS8p0CE,8
|
|
11
|
+
simplex-1.2.58.dist-info/RECORD,,
|
simplex-1.2.55.dist-info/RECORD
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
simplex/__init__.py,sha256=L_5i__xt_ZDkr6e-Wx9cr84t9sXpioOT7j01NJYJCTE,75
|
|
2
|
-
simplex/cli.py,sha256=0K_pzoVdF7vfTJPUONhFzzTvjZk2M7FZPpEONjZWJC8,2268
|
|
3
|
-
simplex/simplex.py,sha256=sjUFTbg496nAX43u8vTbIZUzByPaHXHuGbg_jG_nUfM,25122
|
|
4
|
-
simplex/deploy/__init__.py,sha256=_JQ81F_Nu7hSAfMA691gzs6a4-8oZ-buJ9h3Au12BKw,96
|
|
5
|
-
simplex/deploy/push.py,sha256=hRAbtFZaECKnBljaOLQ5nzJ6hk7tZgc1c7QdgxKQFoY,6123
|
|
6
|
-
simplex-1.2.55.dist-info/LICENSE,sha256=Xh0SJjYZfNI71pCNMB40aKlBLLuOB0blx5xkTtufFNQ,1075
|
|
7
|
-
simplex-1.2.55.dist-info/METADATA,sha256=QNmTq-K2vBPIschX-M_H_NUnOvGLQkZe3fmCjLt7h6E,1045
|
|
8
|
-
simplex-1.2.55.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
9
|
-
simplex-1.2.55.dist-info/entry_points.txt,sha256=3veL2w3c5vxb3dm8I_M8Fs-370n1ZnvD8uu1nSsL7z8,45
|
|
10
|
-
simplex-1.2.55.dist-info/top_level.txt,sha256=cbMH1bYpN0A3gP-ecibPRHasHoqB-01T_2BUFS8p0CE,8
|
|
11
|
-
simplex-1.2.55.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|