pygpt-net 2.4.38__py3-none-any.whl → 2.4.40__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.
Files changed (105) hide show
  1. CHANGELOG.md +19 -0
  2. README.md +25 -2
  3. pygpt_net/CHANGELOG.txt +19 -0
  4. pygpt_net/__init__.py +3 -3
  5. pygpt_net/controller/__init__.py +7 -3
  6. pygpt_net/controller/audio/__init__.py +9 -1
  7. pygpt_net/controller/calendar/__init__.py +3 -1
  8. pygpt_net/controller/chat/input.py +2 -1
  9. pygpt_net/controller/chat/render.py +8 -5
  10. pygpt_net/controller/ctx/__init__.py +33 -25
  11. pygpt_net/controller/ctx/common.py +3 -2
  12. pygpt_net/controller/debug/__init__.py +13 -2
  13. pygpt_net/controller/dialogs/confirm.py +2 -2
  14. pygpt_net/controller/kernel/__init__.py +2 -1
  15. pygpt_net/controller/lang/custom.py +2 -7
  16. pygpt_net/controller/lang/mapping.py +2 -2
  17. pygpt_net/controller/layout.py +2 -2
  18. pygpt_net/controller/notepad.py +14 -10
  19. pygpt_net/controller/theme/nodes.py +2 -5
  20. pygpt_net/controller/tools/__init__.py +37 -1
  21. pygpt_net/controller/ui/__init__.py +1 -5
  22. pygpt_net/controller/ui/tabs.py +295 -60
  23. pygpt_net/core/command.py +3 -1
  24. pygpt_net/core/ctx/__init__.py +16 -2
  25. pygpt_net/core/ctx/container.py +18 -11
  26. pygpt_net/core/ctx/output.py +86 -67
  27. pygpt_net/core/debug/tabs.py +5 -2
  28. pygpt_net/core/filesystem/url.py +7 -3
  29. pygpt_net/core/render/base.py +14 -3
  30. pygpt_net/core/render/markdown/renderer.py +3 -1
  31. pygpt_net/core/render/plain/renderer.py +3 -3
  32. pygpt_net/core/render/web/body.py +10 -4
  33. pygpt_net/core/render/web/renderer.py +213 -41
  34. pygpt_net/core/tabs/__init__.py +268 -98
  35. pygpt_net/core/tabs/tab.py +16 -4
  36. pygpt_net/core/web.py +127 -1
  37. pygpt_net/data/config/config.json +12 -5
  38. pygpt_net/data/config/models.json +3 -3
  39. pygpt_net/data/config/modes.json +3 -3
  40. pygpt_net/data/css/web-blocks.css +18 -0
  41. pygpt_net/data/css/web-blocks.light.css +7 -0
  42. pygpt_net/data/css/web-chatgpt.css +8 -0
  43. pygpt_net/data/css/web-chatgpt_wide.css +8 -0
  44. pygpt_net/data/icons/split_screen.svg +1 -0
  45. pygpt_net/data/locale/locale.de.ini +3 -0
  46. pygpt_net/data/locale/locale.en.ini +6 -1
  47. pygpt_net/data/locale/locale.es.ini +3 -0
  48. pygpt_net/data/locale/locale.fr.ini +3 -0
  49. pygpt_net/data/locale/locale.it.ini +3 -0
  50. pygpt_net/data/locale/locale.pl.ini +4 -1
  51. pygpt_net/data/locale/locale.uk.ini +3 -0
  52. pygpt_net/data/locale/locale.zh.ini +3 -0
  53. pygpt_net/data/locale/plugin.cmd_web.de.ini +2 -0
  54. pygpt_net/data/locale/plugin.cmd_web.en.ini +20 -10
  55. pygpt_net/data/locale/plugin.cmd_web.es.ini +2 -0
  56. pygpt_net/data/locale/plugin.cmd_web.fr.ini +2 -0
  57. pygpt_net/data/locale/plugin.cmd_web.it.ini +2 -0
  58. pygpt_net/data/locale/plugin.cmd_web.pl.ini +2 -0
  59. pygpt_net/data/locale/plugin.cmd_web.uk.ini +2 -0
  60. pygpt_net/data/locale/plugin.cmd_web.zh.ini +2 -0
  61. pygpt_net/icons.qrc +1 -0
  62. pygpt_net/icons_rc.py +165 -136
  63. pygpt_net/item/ctx.py +46 -24
  64. pygpt_net/plugin/audio_input/simple.py +4 -2
  65. pygpt_net/plugin/audio_output/__init__.py +4 -1
  66. pygpt_net/plugin/base/plugin.py +18 -4
  67. pygpt_net/plugin/cmd_code_interpreter/__init__.py +39 -37
  68. pygpt_net/plugin/cmd_code_interpreter/runner.py +25 -12
  69. pygpt_net/plugin/cmd_web/__init__.py +46 -6
  70. pygpt_net/plugin/cmd_web/config.py +74 -48
  71. pygpt_net/plugin/cmd_web/websearch.py +61 -28
  72. pygpt_net/plugin/cmd_web/worker.py +79 -13
  73. pygpt_net/provider/core/config/patch.py +29 -1
  74. pygpt_net/provider/core/ctx/base.py +4 -1
  75. pygpt_net/provider/core/ctx/db_sqlite/__init__.py +10 -1
  76. pygpt_net/provider/core/ctx/db_sqlite/storage.py +22 -1
  77. pygpt_net/tools/__init__.py +9 -1
  78. pygpt_net/tools/base.py +15 -1
  79. pygpt_net/tools/code_interpreter/__init__.py +174 -75
  80. pygpt_net/tools/code_interpreter/ui/dialogs.py +21 -103
  81. pygpt_net/tools/code_interpreter/ui/widgets.py +284 -9
  82. pygpt_net/tools/html_canvas/__init__.py +78 -23
  83. pygpt_net/tools/html_canvas/ui/dialogs.py +46 -62
  84. pygpt_net/tools/html_canvas/ui/widgets.py +96 -3
  85. pygpt_net/ui/base/context_menu.py +2 -2
  86. pygpt_net/ui/layout/chat/input.py +10 -18
  87. pygpt_net/ui/layout/chat/output.py +26 -44
  88. pygpt_net/ui/layout/ctx/ctx_list.py +13 -4
  89. pygpt_net/ui/layout/toolbox/footer.py +18 -2
  90. pygpt_net/ui/main.py +2 -2
  91. pygpt_net/ui/menu/debug.py +11 -1
  92. pygpt_net/ui/widget/filesystem/explorer.py +2 -2
  93. pygpt_net/ui/widget/lists/context.py +26 -5
  94. pygpt_net/ui/widget/tabs/Input.py +2 -2
  95. pygpt_net/ui/widget/tabs/body.py +2 -1
  96. pygpt_net/ui/widget/tabs/layout.py +195 -0
  97. pygpt_net/ui/widget/tabs/output.py +209 -55
  98. pygpt_net/ui/widget/textarea/html.py +11 -1
  99. pygpt_net/ui/widget/textarea/output.py +10 -1
  100. pygpt_net/ui/widget/textarea/web.py +49 -9
  101. {pygpt_net-2.4.38.dist-info → pygpt_net-2.4.40.dist-info}/METADATA +26 -3
  102. {pygpt_net-2.4.38.dist-info → pygpt_net-2.4.40.dist-info}/RECORD +105 -103
  103. {pygpt_net-2.4.38.dist-info → pygpt_net-2.4.40.dist-info}/LICENSE +0 -0
  104. {pygpt_net-2.4.38.dist-info → pygpt_net-2.4.40.dist-info}/WHEEL +0 -0
  105. {pygpt_net-2.4.38.dist-info → pygpt_net-2.4.40.dist-info}/entry_points.txt +0 -0
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.26 19:00:00 #
9
+ # Updated Date: 2024.12.13 08:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Slot
@@ -127,12 +127,15 @@ class Plugin(BasePlugin):
127
127
  elif name == Event.CTX_AFTER:
128
128
  if mode == MODE_AUDIO:
129
129
  return # skip if audio mode
130
+ self.stop_audio()
130
131
  self.on_generate(ctx, event)
131
132
 
132
133
  elif name == Event.AUDIO_READ_TEXT:
134
+ self.stop_audio()
133
135
  self.on_generate(ctx, event)
134
136
 
135
137
  elif name == Event.AUDIO_PLAYBACK:
138
+ self.stop_audio()
136
139
  self.on_playback(ctx, event)
137
140
 
138
141
  elif name == Event.AUDIO_OUTPUT_STOP:
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.21 20:00:00 #
9
+ # Updated Date: 2024.12.12 20:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import copy
@@ -329,7 +329,12 @@ class BasePlugin(QObject):
329
329
  }))
330
330
 
331
331
  @Slot(object, object, dict)
332
- def handle_finished(self, response: dict, ctx: CtxItem = None, extra_data: dict = None):
332
+ def handle_finished(
333
+ self,
334
+ response: dict,
335
+ ctx: CtxItem = None,
336
+ extra_data: dict = None
337
+ ):
333
338
  """
334
339
  Handle finished response signal
335
340
 
@@ -354,7 +359,12 @@ class BasePlugin(QObject):
354
359
  self.window.dispatch(event)
355
360
 
356
361
  @Slot(object, object, dict)
357
- def handle_finished_more(self, responses: list, ctx: CtxItem = None, extra_data: dict = None):
362
+ def handle_finished_more(
363
+ self,
364
+ responses: list,
365
+ ctx: CtxItem = None,
366
+ extra_data: dict = None
367
+ ):
358
368
  """
359
369
  Handle finished response signal
360
370
 
@@ -379,7 +389,11 @@ class BasePlugin(QObject):
379
389
  })
380
390
  self.window.dispatch(event)
381
391
 
382
- def prepare_reply_ctx(self, response: dict, ctx: CtxItem = None) -> dict:
392
+ def prepare_reply_ctx(
393
+ self,
394
+ response: dict,
395
+ ctx: CtxItem = None
396
+ ) -> dict:
383
397
  """
384
398
  Prepare reply context
385
399
 
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.25 02:00:00 #
9
+ # Updated Date: 2024.12.12 01:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -118,42 +118,6 @@ class Plugin(BasePlugin):
118
118
  "directory is mapped as volume in host machine to: {}").format(legacy_data)
119
119
  data['cmd'].append(cmd) # append command
120
120
 
121
- @Slot(object, str)
122
- def handle_interpreter_output(self, data, type):
123
- """
124
- Handle interpreter output
125
-
126
- :param data: output data
127
- :param type: output type
128
- """
129
- if not self.get_option_value("attach_output"):
130
- return
131
- self.window.tools.get("interpreter").append_output(data, type)
132
-
133
- @Slot()
134
- def handle_interpreter_clear(self):
135
- """Handle interpreter clear"""
136
- self.window.tools.get("interpreter").clear_all()
137
-
138
- @Slot(object)
139
- def handle_html_output(self, data):
140
- """
141
- Handle HTML/JS canvas output
142
-
143
- :param data: HTML/JS code
144
- """
145
- self.window.tools.get("html_canvas").set_output(data)
146
- self.window.tools.get("html_canvas").open()
147
- def get_interpreter(self):
148
- """
149
- Get interpreter
150
-
151
- :return: interpreter
152
- """
153
- if self.get_option_value("sandbox_ipython"):
154
- return self.ipython_docker
155
- else:
156
- return self.ipython_local
157
121
 
158
122
  def cmd(self, ctx: CtxItem, cmds: list, silent: bool = False):
159
123
  """
@@ -270,3 +234,41 @@ class Plugin(BasePlugin):
270
234
  self.window.tools.get("interpreter").append_output(cleaned_data)
271
235
  if self.window.tools.get("interpreter").opened:
272
236
  self.window.update_status("")
237
+
238
+ @Slot(object, str)
239
+ def handle_interpreter_output(self, data, type):
240
+ """
241
+ Handle interpreter output
242
+
243
+ :param data: output data
244
+ :param type: output type
245
+ """
246
+ if not self.get_option_value("attach_output"):
247
+ return
248
+ self.window.tools.get("interpreter").append_output(data, type)
249
+
250
+ @Slot()
251
+ def handle_interpreter_clear(self):
252
+ """Handle interpreter clear"""
253
+ self.window.tools.get("interpreter").clear_all()
254
+
255
+ @Slot(object)
256
+ def handle_html_output(self, data):
257
+ """
258
+ Handle HTML/JS canvas output
259
+
260
+ :param data: HTML/JS code
261
+ """
262
+ self.window.tools.get("html_canvas").set_output(data)
263
+ self.window.tools.get("html_canvas").auto_open()
264
+
265
+ def get_interpreter(self):
266
+ """
267
+ Get interpreter
268
+
269
+ :return: interpreter
270
+ """
271
+ if self.get_option_value("sandbox_ipython"):
272
+ return self.ipython_docker
273
+ else:
274
+ return self.ipython_local
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.26 04:00:00 #
9
+ # Updated Date: 2024.12.12 01:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os.path
@@ -164,6 +164,14 @@ class Runner:
164
164
  """
165
165
  return self.plugin.get_option_value('sandbox_docker')
166
166
 
167
+ def is_sandbox_ipython(self) -> bool:
168
+ """
169
+ Check if sandbox is enabled for IPython
170
+
171
+ :return: True if sandbox is enabled
172
+ """
173
+ return self.plugin.get_option_value('sandbox_ipython')
174
+
167
175
  def get_docker(self) -> docker.client.DockerClient:
168
176
  """
169
177
  Get docker client
@@ -392,13 +400,14 @@ class Runner:
392
400
  :param all: execute all
393
401
  :return: response dict
394
402
  """
403
+ sandbox = self.is_sandbox_ipython()
395
404
  data = item["params"]['code']
396
405
  if not all:
397
406
  path = self.plugin.window.tools.get("interpreter").file_current
398
407
  if "path" in item["params"]:
399
408
  path = item["params"]['path']
400
409
  msg = "Saving Python file: {}".format(path)
401
- self.log(msg, sandbox=True)
410
+ self.log(msg, sandbox=sandbox)
402
411
  with open(self.prepare_path(path, on_host=True), 'w', encoding="utf-8") as file:
403
412
  file.write(data)
404
413
  else:
@@ -412,12 +421,13 @@ class Runner:
412
421
 
413
422
  # run code in IPython interpreter
414
423
  msg = "Executing Python code: {}".format(item["params"]['code'])
415
- self.log(msg, sandbox=True)
416
- self.log("Connecting to IPython interpreter...", sandbox=True)
424
+ self.log(msg, sandbox=sandbox)
425
+ self.log("Connecting to IPython interpreter...", sandbox=sandbox)
417
426
  try:
418
- self.log("Please wait...", sandbox=True)
427
+ self.log("Please wait...", sandbox=sandbox)
419
428
  result = self.plugin.get_interpreter().execute(data, current=False)
420
429
  result = self.handle_result_ipython(ctx, result)
430
+ self.log("Python Code Executed.", sandbox=sandbox)
421
431
  except Exception as e:
422
432
  self.error(e)
423
433
  result = str(e)
@@ -437,13 +447,14 @@ class Runner:
437
447
  :param all: execute all
438
448
  :return: response dict
439
449
  """
450
+ sandbox = self.is_sandbox_ipython()
440
451
  data = item["params"]['code']
441
452
  if not all:
442
453
  path = self.plugin.window.tools.get("interpreter").file_current
443
454
  if "path" in item["params"]:
444
455
  path = item["params"]['path']
445
456
  msg = "Saving Python file: {}".format(path)
446
- self.log(msg, sandbox=True)
457
+ self.log(msg, sandbox=sandbox)
447
458
  with open(self.prepare_path(path, on_host=True), 'w', encoding="utf-8") as file:
448
459
  file.write(data)
449
460
  else:
@@ -457,12 +468,13 @@ class Runner:
457
468
 
458
469
  # run code in IPython interpreter
459
470
  msg = "Executing Python code: {}".format(item["params"]['code'])
460
- self.log(msg, sandbox=True)
461
- self.log("Connecting to IPython interpreter...", sandbox=True)
471
+ self.log(msg, sandbox=sandbox)
472
+ self.log("Connecting to IPython interpreter...", sandbox=sandbox)
462
473
  try:
463
- self.log("Please wait...", sandbox=True)
474
+ self.log("Please wait...", sandbox=sandbox)
464
475
  result = self.plugin.get_interpreter().execute(data, current=True)
465
476
  result = self.handle_result_ipython(ctx, result)
477
+ self.log("Python Code Executed.", sandbox=sandbox)
466
478
  except Exception as e:
467
479
  self.error(e)
468
480
  result = str(e)
@@ -482,13 +494,14 @@ class Runner:
482
494
  :param all: execute all
483
495
  :return: response dict
484
496
  """
497
+ sandbox = self.is_sandbox_ipython()
485
498
  self.append_input("")
486
499
  self.send_interpreter_input("") # send input to interpreter tool
487
500
 
488
501
  # restart IPython interpreter
489
- self.log("Connecting to IPython interpreter...", sandbox=True)
502
+ self.log("Connecting to IPython interpreter...", sandbox=sandbox)
490
503
  try:
491
- self.log("Restarting IPython kernel...", sandbox=True)
504
+ self.log("Restarting IPython kernel...", sandbox=sandbox)
492
505
  response = self.plugin.get_interpreter().restart_kernel()
493
506
  except Exception as e:
494
507
  self.error(e)
@@ -497,7 +510,7 @@ class Runner:
497
510
  result = "Kernel restarted"
498
511
  else:
499
512
  result = "Kernel not restarted"
500
- self.log(result)
513
+ self.log(result, sandbox=sandbox)
501
514
  return {
502
515
  "request": request,
503
516
  "result": str(result),
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.20 21:00:00 #
9
+ # Updated Date: 2024.12.13 08:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import ssl
@@ -40,6 +40,8 @@ class Plugin(BasePlugin):
40
40
  "web_url_raw",
41
41
  "web_index",
42
42
  "web_index_query",
43
+ "web_extract_links",
44
+ "web_extract_images",
43
45
  ]
44
46
  self.order = 100
45
47
  self.use_locale = True
@@ -269,26 +271,66 @@ class Plugin(BasePlugin):
269
271
 
270
272
  :param data: event data dict
271
273
  """
274
+ max_urls = self.get_option_value("max_open_urls")
275
+ is_summary = True
276
+ if self.get_option_value("raw"):
277
+ is_summary = False
278
+
272
279
  for option in self.allowed_cmds:
273
280
  if not self.has_cmd(option):
274
281
  continue
275
282
 
276
- # special case for web_index
277
283
  if option == "web_index":
278
284
  data['cmd'].append(self.prepare_idx_syntax()) # prepare params
279
285
  continue
280
286
  elif option == "web_index_query":
281
287
  data['cmd'].append(self.prepare_idx_query_syntax()) # prepare params
282
288
  continue
289
+ elif option == "web_url_open":
290
+ cmd = self.get_cmd(option)
291
+ try:
292
+ cmd["instruction"] = cmd["instruction"].format(
293
+ max_urls=max_urls,
294
+ )
295
+ if not is_summary:
296
+ for param in list(cmd["params"]):
297
+ if param["name"] == "summarize_prompt":
298
+ cmd["params"].remove(param)
299
+ data['cmd'].append(cmd)
300
+ continue
301
+ except Exception as e:
302
+ pass
303
+ elif option == "web_url_raw":
304
+ cmd = self.get_cmd(option)
305
+ try:
306
+ cmd["instruction"] = cmd["instruction"].format(
307
+ max_urls=max_urls,
308
+ )
309
+ if not is_summary:
310
+ for param in list(cmd["params"]):
311
+ if param["name"] == "summarize_prompt":
312
+ cmd["params"].remove(param)
313
+ data['cmd'].append(cmd)
314
+ continue
315
+ except Exception as e:
316
+ pass
283
317
  elif option == "web_search":
284
318
  max_pages = self.get_option_value("num_pages")
285
319
  cmd = self.get_cmd(option)
286
320
  try:
287
- cmd["instruction"] = cmd["instruction"].format(max_pages=max_pages)
321
+ cmd["instruction"] = cmd["instruction"].format(
322
+ max_pages=max_pages,
323
+ max_urls=max_urls,
324
+ )
325
+ if not is_summary:
326
+ for param in list(cmd["params"]):
327
+ if param["name"] == "summarize_prompt":
328
+ cmd["params"].remove(param)
288
329
  data['cmd'].append(cmd)
289
330
  continue
290
331
  except Exception as e:
291
332
  pass
333
+
292
334
  data['cmd'].append(self.get_cmd(option)) # append command
293
335
 
294
336
  def cmd(self, ctx: CtxItem, cmds: list):
@@ -389,8 +431,6 @@ class Plugin(BasePlugin):
389
431
  req,
390
432
  timeout=self.get_option_value('timeout'),
391
433
  ).read()
392
- except HTTPError as e:
393
- data = str(e)
394
434
  except Exception as e:
395
- raise e
435
+ data = str(e)
396
436
  return data
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.18 19:00:00 #
9
+ # Updated Date: 2024.12.13 08:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.plugin.base.config import BaseConfig, BasePlugin
@@ -41,6 +41,15 @@ class Config(BaseConfig):
41
41
  min=1,
42
42
  max=None,
43
43
  )
44
+ plugin.add_option(
45
+ "max_open_urls",
46
+ type="int",
47
+ value=1,
48
+ label="Number of max URLs to open at once",
49
+ description="Number of max URLs to open at once",
50
+ min=1,
51
+ max=None,
52
+ )
44
53
  plugin.add_option(
45
54
  "max_page_content_length",
46
55
  type="int",
@@ -59,6 +68,14 @@ class Config(BaseConfig):
59
68
  min=1,
60
69
  max=None,
61
70
  )
71
+ plugin.add_option(
72
+ "raw",
73
+ type="bool",
74
+ value=True,
75
+ label="Use raw content (without summarization)",
76
+ description="Return raw content from web search instead of summarized content",
77
+ tooltip="Use raw content for search",
78
+ )
62
79
  plugin.add_option(
63
80
  "disable_ssl",
64
81
  type="bool",
@@ -67,6 +84,14 @@ class Config(BaseConfig):
67
84
  description="Disables SSL verification when crawling web pages",
68
85
  tooltip="Disable SSL verify",
69
86
  )
87
+ plugin.add_option(
88
+ "img_thumbnail",
89
+ type="bool",
90
+ value=True,
91
+ label="Show thumbnail images",
92
+ description="Enable fetching thumbnails from opened websites",
93
+ tooltip="Enable fetching thumbnails from opened websites",
94
+ )
70
95
  plugin.add_option(
71
96
  "timeout",
72
97
  type="int",
@@ -86,7 +111,7 @@ class Config(BaseConfig):
86
111
  plugin.add_option(
87
112
  "max_result_length",
88
113
  type="int",
89
- value=1500,
114
+ value=50000,
90
115
  label="Max result length",
91
116
  description="Max length of summarized result (characters)",
92
117
  min=0,
@@ -104,10 +129,10 @@ class Config(BaseConfig):
104
129
  plugin.add_option(
105
130
  "model_tmp_query",
106
131
  type="combo",
107
- value="gpt-3.5-turbo",
132
+ value="gpt-4o-mini",
108
133
  label="Model for query in-memory index",
109
134
  description="Model used for query in-memory index for `web_index_query` command, "
110
- "default: gpt-3.5-turbo",
135
+ "default: gpt-4o-mini",
111
136
  tooltip="Query model",
112
137
  use="models",
113
138
  tab="indexing",
@@ -134,10 +159,11 @@ class Config(BaseConfig):
134
159
  )
135
160
  plugin.add_option(
136
161
  "summary_model",
137
- type="text",
138
- value="gpt-3.5-turbo-1106",
162
+ type="combo",
163
+ value="gpt-4o-mini",
139
164
  label="Model used for web page summarize",
140
165
  description="Model used for web page summarize, default: gpt-3.5-turbo-1106",
166
+ use="models",
141
167
  advanced=True,
142
168
  )
143
169
  plugin.add_option(
@@ -163,39 +189,9 @@ class Config(BaseConfig):
163
189
  )
164
190
 
165
191
  # commands
166
- plugin.add_cmd(
167
- "web_search",
168
- instruction="search the Web for more info, prepare a query for the search engine itself, start from page 1. "
169
- "If no results, then try the next page. "
170
- "Use a custom summary prompt if necessary, otherwise, a default summary will be used. "
171
- "Max pages: {max_pages}",
172
- params=[
173
- {
174
- "name": "query",
175
- "type": "str",
176
- "description": "search query",
177
- "required": True,
178
- },
179
- {
180
- "name": "page",
181
- "type": "int",
182
- "description": "page number",
183
- "required": False,
184
- },
185
- {
186
- "name": "summarize_prompt",
187
- "type": "str",
188
- "description": "summary prompt",
189
- "required": False,
190
- },
191
- ],
192
- enabled=True,
193
- description="If enabled, model will be able to search the Web",
194
- )
195
192
  plugin.add_cmd(
196
193
  "web_url_open",
197
- instruction="read and get summarized content from ANY website URL. Use a custom summary prompt if necessary, "
198
- "otherwise default summary will be used",
194
+ instruction="read and get text content from ANY website URL. Always open a max of {max_urls} URLs at a time.",
199
195
  params=[
200
196
  {
201
197
  "name": "url",
@@ -203,19 +199,13 @@ class Config(BaseConfig):
203
199
  "description": "URL to website",
204
200
  "required": True,
205
201
  },
206
- {
207
- "name": "summarize_prompt",
208
- "type": "str",
209
- "description": "summary prompt",
210
- "required": False,
211
- },
212
202
  ],
213
203
  enabled=True,
214
- description="If enabled, model will be able to open URL and summarize content",
204
+ description="If enabled, model will be able to open URL and read text content from it",
215
205
  )
216
206
  plugin.add_cmd(
217
207
  "web_url_raw",
218
- instruction="read and get raw HTML/txt content (not summarized) from ANY website URL",
208
+ instruction="read and get raw HTML body from ANY website URL. Always open a max of {max_urls} URLs at a time.",
219
209
  params=[
220
210
  {
221
211
  "name": "url",
@@ -225,12 +215,14 @@ class Config(BaseConfig):
225
215
  },
226
216
  ],
227
217
  enabled=True,
228
- description="If enabled, model will be able to open specified URL and get raw content",
218
+ description="If enabled, model will be able to open specified URL and get raw HTML body from it",
229
219
  )
230
220
  plugin.add_cmd(
231
- "web_urls",
221
+ "web_search",
232
222
  instruction="search the Web for list of URLs, prepare search query itself, list of "
233
- "URLs will be returned, 10 links per page max.",
223
+ "URLs will be returned, 10 links per page max. After receiving the list of URLs, "
224
+ "choose the best matched URLs and use the `web_url_open` command to read the content. "
225
+ "Always open a max of {max_urls} URLs at a time.",
234
226
  params=[
235
227
  {
236
228
  "name": "query",
@@ -254,6 +246,40 @@ class Config(BaseConfig):
254
246
  enabled=True,
255
247
  description="If enabled, model will be able to search the Web and get founded URLs list",
256
248
  )
249
+ plugin.add_cmd(
250
+ "web_extract_links",
251
+ instruction="open webpage and get list of all links from it",
252
+ params=[
253
+ {
254
+ "name": "url",
255
+ "type": "str",
256
+ "description": "URL to website",
257
+ "required": True,
258
+ },
259
+ ],
260
+ enabled=True,
261
+ description="If enabled, model will be able to open URL and get list of all links from it",
262
+ )
263
+ plugin.add_cmd(
264
+ "web_extract_images",
265
+ instruction="open webpage and get list of all images from it",
266
+ params=[
267
+ {
268
+ "name": "url",
269
+ "type": "str",
270
+ "description": "URL to website",
271
+ "required": True,
272
+ },
273
+ {
274
+ "name": "download",
275
+ "type": "bool",
276
+ "description": "Download images to disk if user wants to, default: False",
277
+ "required": False,
278
+ },
279
+ ],
280
+ enabled=True,
281
+ description="If enabled, model will be able to open URL and get list of all images from it",
282
+ )
257
283
  plugin.add_cmd(
258
284
  "web_index",
259
285
  instruction="",