sunholo 0.74.8__py3-none-any.whl → 0.74.9__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.
- sunholo/tools/web_browser.py +44 -11
- sunholo/utils/parsers.py +1 -1
- {sunholo-0.74.8.dist-info → sunholo-0.74.9.dist-info}/METADATA +2 -2
- {sunholo-0.74.8.dist-info → sunholo-0.74.9.dist-info}/RECORD +8 -8
- {sunholo-0.74.8.dist-info → sunholo-0.74.9.dist-info}/LICENSE.txt +0 -0
- {sunholo-0.74.8.dist-info → sunholo-0.74.9.dist-info}/WHEEL +0 -0
- {sunholo-0.74.8.dist-info → sunholo-0.74.9.dist-info}/entry_points.txt +0 -0
- {sunholo-0.74.8.dist-info → sunholo-0.74.9.dist-info}/top_level.txt +0 -0
sunholo/tools/web_browser.py
CHANGED
|
@@ -213,6 +213,35 @@ class BrowseWebWithImagePromptsBot:
|
|
|
213
213
|
except Exception as err:
|
|
214
214
|
log.warning(f"navigate failed with {str(err)}")
|
|
215
215
|
self.action_log.append(f"Tried to navigate to {url} but got an error")
|
|
216
|
+
|
|
217
|
+
def get_locator_via_roles_and_placeholder(self, selector: str):
|
|
218
|
+
interactive_roles = ["button", "link", "menuitem", "menuitemcheckbox", "menuitemradio", "tab", "option"]
|
|
219
|
+
|
|
220
|
+
for role in interactive_roles:
|
|
221
|
+
log.info(f'Trying role {role} for selector {selector}')
|
|
222
|
+
elements = self.page.get_by_role(role).get_by_placeholder(selector).locator("visible=true").all()
|
|
223
|
+
if elements:
|
|
224
|
+
log.info(f"Got {len(elements)} elements for selector {selector} with role {role}")
|
|
225
|
+
for element in elements:
|
|
226
|
+
try:
|
|
227
|
+
log.info(f"Trying {selector} with element.hover locator: {element}")
|
|
228
|
+
try:
|
|
229
|
+
element.hover(timeout=10000, trial=True)
|
|
230
|
+
self.action_log.append(f"Successfully found element via selector: {selector}")
|
|
231
|
+
|
|
232
|
+
return element
|
|
233
|
+
|
|
234
|
+
except Exception as err:
|
|
235
|
+
log.warning(f"Could not hover over element: {element} {str(err)} - trying next element")
|
|
236
|
+
except Exception as e:
|
|
237
|
+
log.error(f"Failed to get locator for selector '{selector}' with role {role}: {str(e)}")
|
|
238
|
+
|
|
239
|
+
time.sleep(0.5) # Wait for a bit before retrying
|
|
240
|
+
|
|
241
|
+
log.info(f"No elements for '{selector}' within role '{role}'")
|
|
242
|
+
|
|
243
|
+
self.action_log.append(f"FAILED: Using page.get_by_role('role').get_by_placeholder('{selector}').locator('visible=true') could not find any valid element. Try something else.")
|
|
244
|
+
return None
|
|
216
245
|
|
|
217
246
|
def get_locator_via_roles_and_text(self, selector: str):
|
|
218
247
|
interactive_roles = ["button", "link", "menuitem", "menuitemcheckbox", "menuitemradio", "tab", "option"]
|
|
@@ -240,7 +269,7 @@ class BrowseWebWithImagePromptsBot:
|
|
|
240
269
|
|
|
241
270
|
log.info(f"No elements for '{selector}' within role '{role}'")
|
|
242
271
|
|
|
243
|
-
self.action_log.append(f"FAILED: Using page.get_by_role('role').
|
|
272
|
+
self.action_log.append(f"FAILED: Using page.get_by_role('role').get_by_text('{selector}').locator('visible=true') could not find any valid element. Try something else.")
|
|
244
273
|
return None
|
|
245
274
|
|
|
246
275
|
def get_locator(self, selector, by_text=True):
|
|
@@ -256,10 +285,10 @@ class BrowseWebWithImagePromptsBot:
|
|
|
256
285
|
|
|
257
286
|
return None
|
|
258
287
|
|
|
259
|
-
def click(self, selector
|
|
288
|
+
def click(self, selector):
|
|
260
289
|
(x,y)=(0,0)
|
|
261
290
|
|
|
262
|
-
element = self.
|
|
291
|
+
element = self.get_locator_via_roles_and_text(selector)
|
|
263
292
|
if element is None:
|
|
264
293
|
self.action_log.append(f"Tried to click on text {selector} but it was not a valid location to click")
|
|
265
294
|
return (x,y)
|
|
@@ -303,9 +332,9 @@ class BrowseWebWithImagePromptsBot:
|
|
|
303
332
|
log.warning(f"Scrolled failed with {str(err)}")
|
|
304
333
|
self.action_log.append(f"Tried to scroll {direction} by {amount} pixels but got an error")
|
|
305
334
|
|
|
306
|
-
def type_text(self, selector, text
|
|
335
|
+
def type_text(self, selector, text):
|
|
307
336
|
(x,y)=(0,0)
|
|
308
|
-
element = self.
|
|
337
|
+
element = self.get_locator_via_roles_and_placeholder(selector)
|
|
309
338
|
if element is None:
|
|
310
339
|
self.action_log.append(f"Tried to type {text} via website text: {selector} but it was not a valid element to add text")
|
|
311
340
|
return (x,y)
|
|
@@ -344,6 +373,10 @@ class BrowseWebWithImagePromptsBot:
|
|
|
344
373
|
url_path = "index.html"
|
|
345
374
|
else:
|
|
346
375
|
url_path = url_path.replace("/","_")
|
|
376
|
+
|
|
377
|
+
if get_clean_website_name(url_path) != self.website_name:
|
|
378
|
+
url_path = f"{get_clean_website_name(url_path)}_{url_path}"
|
|
379
|
+
|
|
347
380
|
screenshot_path = os.path.join(self.screenshot_dir, f"{timestamp}_{url_path}.png")
|
|
348
381
|
screenshot_bytes = self.page.screenshot(full_page=full_page, scale='css')
|
|
349
382
|
|
|
@@ -358,7 +391,7 @@ class BrowseWebWithImagePromptsBot:
|
|
|
358
391
|
#self.action_log.append(f"Screenshot {self.page.url} taken and saved to {screenshot_path}")
|
|
359
392
|
self.session_screenshots.append(screenshot_path)
|
|
360
393
|
|
|
361
|
-
return
|
|
394
|
+
return screenshot_bytes
|
|
362
395
|
|
|
363
396
|
def mark_screenshot(self, screenshot_bytes, mark_action):
|
|
364
397
|
"""
|
|
@@ -433,9 +466,9 @@ class BrowseWebWithImagePromptsBot:
|
|
|
433
466
|
|
|
434
467
|
return output
|
|
435
468
|
|
|
436
|
-
def send_screenshot_to_llm(self,
|
|
437
|
-
|
|
438
|
-
|
|
469
|
+
def send_screenshot_to_llm(self, screenshot_bytes, last_message):
|
|
470
|
+
|
|
471
|
+
encoded_image = base64.b64encode(screenshot_bytes).decode('utf-8')
|
|
439
472
|
|
|
440
473
|
prompt_vars = self.create_prompt_vars(last_message)
|
|
441
474
|
response = self.send_prompt_to_llm(prompt_vars, encoded_image) # Sending prompt and image separately
|
|
@@ -495,9 +528,9 @@ This method should be implemented by subclasses: `def send_prompt_to_llm(self, p
|
|
|
495
528
|
log.warning(f"Reached the maximum number of steps: {self.max_steps}")
|
|
496
529
|
return
|
|
497
530
|
time.sleep(2)
|
|
498
|
-
|
|
531
|
+
screenshot_bytes = self.take_screenshot(mark_action=mark_action)
|
|
499
532
|
next_browser_instructions = self.send_screenshot_to_llm(
|
|
500
|
-
|
|
533
|
+
screenshot_bytes,
|
|
501
534
|
last_message=last_message)
|
|
502
535
|
|
|
503
536
|
return next_browser_instructions
|
sunholo/utils/parsers.py
CHANGED
|
@@ -186,6 +186,6 @@ def escape_braces(text):
|
|
|
186
186
|
text = re.sub(r'(?<!})}(?!})', '}}', text) # Replace '}' with '}}' if not already double braced
|
|
187
187
|
return text
|
|
188
188
|
|
|
189
|
-
def get_clean_website_name(url):
|
|
189
|
+
def get_clean_website_name(url: str):
|
|
190
190
|
parsed_url = urllib.parse.urlparse(url)
|
|
191
191
|
return parsed_url.netloc
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.74.
|
|
3
|
+
Version: 0.74.9
|
|
4
4
|
Summary: Large Language Model DevOps - a package to help deploy LLMs to the Cloud.
|
|
5
5
|
Home-page: https://github.com/sunholo-data/sunholo-py
|
|
6
|
-
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.74.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.74.9.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -99,7 +99,7 @@ sunholo/streaming/streaming.py,sha256=9z6pXINEopuL_Z1RnmgXAoZJum9dzyuOxqYtEYnjf8
|
|
|
99
99
|
sunholo/summarise/__init__.py,sha256=MZk3dblUMODcPb1crq4v-Z508NrFIpkSWNf9FIO8BcU,38
|
|
100
100
|
sunholo/summarise/summarise.py,sha256=C3HhjepTjUhUC8FLk4jMQIBvq1BcORniwuTFHjPVhVo,3784
|
|
101
101
|
sunholo/tools/__init__.py,sha256=5NuYpwwTX81qGUWvgwfItoSLXteNnp7KjgD7IPZUFjI,53
|
|
102
|
-
sunholo/tools/web_browser.py,sha256
|
|
102
|
+
sunholo/tools/web_browser.py,sha256=wms9vHndrbD2NaAvNpYG291YiGP8wVHJ6iljsMVZc5w,26292
|
|
103
103
|
sunholo/utils/__init__.py,sha256=Hv02T5L2zYWvCso5hzzwm8FQogwBq0OgtUbN_7Quzqc,89
|
|
104
104
|
sunholo/utils/api_key.py,sha256=Ct4bIAQZxzPEw14hP586LpVxBAVi_W9Serpy0BK-7KI,244
|
|
105
105
|
sunholo/utils/big_context.py,sha256=gJIP7_ZL-YSLhOMq8jmFTMqH1wq8eB1NK7oKPeZAq2s,5578
|
|
@@ -108,7 +108,7 @@ sunholo/utils/config_class.py,sha256=4fm2Bwn_zFhVJBiUnMBzfCA5LKhTcBMU3mzhf5seXrw
|
|
|
108
108
|
sunholo/utils/config_schema.py,sha256=Wv-ncitzljOhgbDaq9qnFqH5LCuxNv59dTGDWgd1qdk,4189
|
|
109
109
|
sunholo/utils/gcp.py,sha256=uueODEpA-P6O15-t0hmcGC9dONLO_hLfzSsSoQnkUss,4854
|
|
110
110
|
sunholo/utils/gcp_project.py,sha256=0ozs6tzI4qEvEeXb8MxLnCdEVoWKxlM6OH05htj7_tc,1325
|
|
111
|
-
sunholo/utils/parsers.py,sha256=
|
|
111
|
+
sunholo/utils/parsers.py,sha256=akLSZLdvHf5T9OKVj5C3bo4g3Y8puATd8rxnbB4tWDs,5419
|
|
112
112
|
sunholo/utils/timedelta.py,sha256=BbLabEx7_rbErj_YbNM0MBcaFN76DC4PTe4zD2ucezg,493
|
|
113
113
|
sunholo/utils/user_ids.py,sha256=SQd5_H7FE7vcTZp9AQuQDWBXd4FEEd7TeVMQe1H4Ny8,292
|
|
114
114
|
sunholo/utils/version.py,sha256=P1QAJQdZfT2cMqdTSmXmcxrD2PssMPEGM-WI6083Fck,237
|
|
@@ -117,9 +117,9 @@ sunholo/vertex/extensions_class.py,sha256=4PsUM9dSYrIPpq9bZ3K2rL9MRb_rlqAgnMsW0o
|
|
|
117
117
|
sunholo/vertex/init.py,sha256=-w7b9GKsyJnAJpYHYz6_zBUtmeJeLXlEkgOfwoe4DEI,2715
|
|
118
118
|
sunholo/vertex/memory_tools.py,sha256=pomHrDKqvY8MZxfUqoEwhdlpCvSGP6KmFJMVKOimXjs,6842
|
|
119
119
|
sunholo/vertex/safety.py,sha256=S9PgQT1O_BQAkcqauWncRJaydiP8Q_Jzmu9gxYfy1VA,2482
|
|
120
|
-
sunholo-0.74.
|
|
121
|
-
sunholo-0.74.
|
|
122
|
-
sunholo-0.74.
|
|
123
|
-
sunholo-0.74.
|
|
124
|
-
sunholo-0.74.
|
|
125
|
-
sunholo-0.74.
|
|
120
|
+
sunholo-0.74.9.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
|
|
121
|
+
sunholo-0.74.9.dist-info/METADATA,sha256=tf6DzIGnmFeb47QUwocgunQWJD2WEmYI3Kv73pcCNy4,7010
|
|
122
|
+
sunholo-0.74.9.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
|
|
123
|
+
sunholo-0.74.9.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
|
|
124
|
+
sunholo-0.74.9.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
|
|
125
|
+
sunholo-0.74.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|