sunholo 0.74.1__py3-none-any.whl → 0.74.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.
@@ -3,6 +3,7 @@ import base64
3
3
  import json
4
4
  from datetime import datetime
5
5
  import urllib.parse
6
+ import time
6
7
 
7
8
  from ..logging import log
8
9
 
@@ -354,12 +355,18 @@ class BrowseWebWithImagePromptsBot:
354
355
  output = response
355
356
  elif isinstance(response, str):
356
357
  output = json.loads(response)
357
-
358
- #TODO: more validation
359
- log.info(f'Response: {output=}')
358
+ elif isinstance(response, list):
359
+ log.warning(f'Response was a list, assuming its only new_instructions: {response=}')
360
+ output['new_instructions'] = response
361
+ output['status'] = 'in-progress'
362
+ output['message'] = 'No message was received, which is a mistake by the assistant'
363
+ else:
364
+ log.warning(f'Unknown response: {response=} {type(response)}')
365
+ output = None
360
366
 
361
367
  if 'status' not in output:
362
368
  log.error(f'Response did not contain status')
369
+
363
370
 
364
371
  if 'new_instructions' not in output:
365
372
  log.warning(f'Response did not include new_instructions')
@@ -391,6 +398,8 @@ This method should be implemented by subclasses: `def send_prompt_to_llm(self, p
391
398
  self.save_cookies()
392
399
  self.browser.close()
393
400
  self.playwright.stop()
401
+ self.save_action_log()
402
+ self.create_gif_from_pngs()
394
403
 
395
404
  def execute_instructions(self, instructions: list, last_message: str=None):
396
405
  if not instructions:
@@ -426,13 +435,50 @@ This method should be implemented by subclasses: `def send_prompt_to_llm(self, p
426
435
  if self.steps >= self.max_steps:
427
436
  log.warning(f"Reached the maximum number of steps: {self.max_steps}")
428
437
  return
429
-
438
+ time.sleep(2)
430
439
  screenshot_path = self.take_screenshot(mark_action=mark_action)
431
440
  next_browser_instructions = self.send_screenshot_to_llm(
432
441
  screenshot_path,
433
442
  last_message=last_message)
434
443
 
435
444
  return next_browser_instructions
445
+
446
+ def create_gif_from_pngs(self, frame_duration=500):
447
+ """
448
+ Creates a GIF from a folder of PNG images.
449
+
450
+ Args:
451
+ folder_path (str): The path to the folder containing PNG images.
452
+ output_gif_path (str): The path where the output GIF will be saved.
453
+ duration (int): Duration between frames in milliseconds.
454
+
455
+ Example:
456
+ create_gif_from_pngs('/path/to/png_folder', '/path/to/output.gif', duration=500)
457
+ """
458
+ from PIL import Image
459
+
460
+ folder_path=self.screenshot_dir
461
+ output_gif_path = os.path.join(self.screenshot_dir, "session.gif")
462
+
463
+ # List all PNG files in the folder
464
+ png_files = [f for f in sorted(os.listdir(folder_path)) if f.endswith('.png')]
465
+
466
+ # Open images and store them in a list
467
+ images = [Image.open(os.path.join(folder_path, file)) for file in png_files]
468
+
469
+ duration = len(images) * frame_duration
470
+ # Save images as a GIF
471
+ if images:
472
+ images[0].save(
473
+ output_gif_path,
474
+ save_all=True,
475
+ append_images=images[1:],
476
+ duration=duration,
477
+ loop=0
478
+ )
479
+ print(f"GIF saved at {output_gif_path}")
480
+ else:
481
+ print("No PNG images found in the folder.")
436
482
 
437
483
  def start_session(self, instructions, session_goal):
438
484
  self.session_goal = session_goal
@@ -442,6 +488,9 @@ This method should be implemented by subclasses: `def send_prompt_to_llm(self, p
442
488
 
443
489
  next_instructions = self.execute_instructions(instructions)
444
490
 
491
+ # load previous actions from same session
492
+ self.load_action_log()
493
+
445
494
  in_session = True
446
495
  while in_session:
447
496
  if next_instructions and 'status' in next_instructions:
@@ -464,16 +513,16 @@ This method should be implemented by subclasses: `def send_prompt_to_llm(self, p
464
513
  break
465
514
 
466
515
  log.info("Session finished")
467
- final_path = self.take_screenshot(final=True)
516
+ final_screenshot = self.take_screenshot()
517
+
468
518
  self.close()
469
- self.save_action_log()
470
519
 
471
520
  return {
472
521
  "website": self.website_name,
473
522
  "log": self.action_log,
474
523
  "next_instructions": next_instructions,
475
524
  "session_screenshots": self.session_screenshots,
476
- "final_page": final_path,
525
+ "final_screenshot": final_screenshot,
477
526
  "session_goal": self.session_goal
478
527
  }
479
528
 
@@ -90,6 +90,9 @@ class ConfigManager:
90
90
  config = self._reload_config_file(config_file, filename, folder == self.local_config_folder)
91
91
  else:
92
92
  config = self._reload_config_file(config_file, filename, folder == self.local_config_folder)
93
+ if config is None:
94
+ log.error(f"No config found within {filename}")
95
+ continue
93
96
  kind = config.get('kind')
94
97
  if kind:
95
98
  configs_by_kind[kind] = config
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.74.1
3
+ Version: 0.74.3
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.1.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.74.3.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -99,12 +99,12 @@ 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=ElwIBtVptyYcPd0wo7WXLNYCC02FJL_Lv3cfTzOJpnQ,19663
102
+ sunholo/tools/web_browser.py,sha256=FqFD9uI1VQ9ui10evIqxTgor_xqM9LhGt16Fz3EmP-w,21533
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
106
106
  sunholo/utils/config.py,sha256=Ute6SORPtkMnZy-BVVv0rtN28qSQ77GAzb7XtZGIAT0,8901
107
- sunholo/utils/config_class.py,sha256=uyAsPXdxOY47CbQ8RifhUDL2BlxWP2QI-DIWBNlv6yk,8421
107
+ sunholo/utils/config_class.py,sha256=4fm2Bwn_zFhVJBiUnMBzfCA5LKhTcBMU3mzhf5seXrw,8553
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
@@ -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.1.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
121
- sunholo-0.74.1.dist-info/METADATA,sha256=6QFlkGilosGyFUklfh5uzkTD4ghMdfCNuzwyLmiSyCE,7010
122
- sunholo-0.74.1.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
123
- sunholo-0.74.1.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
124
- sunholo-0.74.1.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
125
- sunholo-0.74.1.dist-info/RECORD,,
120
+ sunholo-0.74.3.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
121
+ sunholo-0.74.3.dist-info/METADATA,sha256=7N8nhIaNV1kRBuvAcAUnEMfK4apKMeG9eF7BDTZqZ1c,7010
122
+ sunholo-0.74.3.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
123
+ sunholo-0.74.3.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
124
+ sunholo-0.74.3.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
125
+ sunholo-0.74.3.dist-info/RECORD,,