pygpt-net 2.4.41__py3-none-any.whl → 2.4.44__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 (183) hide show
  1. CHANGELOG.md +19 -0
  2. README.md +151 -71
  3. pygpt_net/CHANGELOG.txt +19 -0
  4. pygpt_net/__init__.py +3 -3
  5. pygpt_net/app.py +3 -1
  6. pygpt_net/controller/attachment.py +31 -3
  7. pygpt_net/controller/audio/__init__.py +2 -2
  8. pygpt_net/controller/camera.py +1 -10
  9. pygpt_net/controller/chat/attachment.py +37 -36
  10. pygpt_net/controller/chat/audio.py +2 -2
  11. pygpt_net/controller/config/placeholder.py +20 -4
  12. pygpt_net/controller/idx/common.py +7 -3
  13. pygpt_net/controller/ui/mode.py +16 -21
  14. pygpt_net/core/attachments/__init__.py +7 -2
  15. pygpt_net/core/attachments/context.py +52 -34
  16. pygpt_net/core/audio/__init__.py +4 -1
  17. pygpt_net/core/audio/whisper.py +37 -0
  18. pygpt_net/core/bridge/worker.py +2 -2
  19. pygpt_net/core/db/__init__.py +2 -1
  20. pygpt_net/core/debug/attachments.py +1 -0
  21. pygpt_net/core/debug/events.py +22 -10
  22. pygpt_net/core/debug/tabs.py +6 -3
  23. pygpt_net/core/history.py +3 -2
  24. pygpt_net/core/idx/__init__.py +23 -6
  25. pygpt_net/core/idx/chat.py +15 -5
  26. pygpt_net/core/idx/indexing.py +47 -14
  27. pygpt_net/core/idx/ui/__init__.py +22 -0
  28. pygpt_net/core/idx/ui/loaders.py +217 -0
  29. pygpt_net/core/installer.py +2 -4
  30. pygpt_net/core/models.py +62 -17
  31. pygpt_net/core/modes.py +11 -13
  32. pygpt_net/core/notepad.py +4 -4
  33. pygpt_net/core/plugins.py +27 -16
  34. pygpt_net/core/presets.py +20 -9
  35. pygpt_net/core/profile.py +11 -3
  36. pygpt_net/core/render/web/parser.py +3 -1
  37. pygpt_net/core/settings.py +5 -5
  38. pygpt_net/core/tabs/tab.py +10 -2
  39. pygpt_net/core/tokens.py +8 -6
  40. pygpt_net/core/web/__init__.py +105 -0
  41. pygpt_net/core/{web.py → web/helpers.py} +93 -67
  42. pygpt_net/data/config/config.json +4 -4
  43. pygpt_net/data/config/models.json +3 -3
  44. pygpt_net/data/config/modes.json +3 -3
  45. pygpt_net/data/config/settings.json +5 -5
  46. pygpt_net/data/locale/locale.de.ini +3 -3
  47. pygpt_net/data/locale/locale.en.ini +12 -9
  48. pygpt_net/data/locale/locale.es.ini +3 -3
  49. pygpt_net/data/locale/locale.fr.ini +3 -3
  50. pygpt_net/data/locale/locale.it.ini +3 -3
  51. pygpt_net/data/locale/locale.pl.ini +3 -3
  52. pygpt_net/data/locale/locale.uk.ini +3 -3
  53. pygpt_net/data/locale/locale.zh.ini +3 -3
  54. pygpt_net/data/locale/plugin.cmd_web.en.ini +2 -0
  55. pygpt_net/data/locale/plugin.mailer.en.ini +21 -0
  56. pygpt_net/item/attachment.py +5 -1
  57. pygpt_net/item/ctx.py +111 -3
  58. pygpt_net/migrations/Version20241215110000.py +25 -0
  59. pygpt_net/migrations/__init__.py +3 -1
  60. pygpt_net/plugin/agent/__init__.py +7 -2
  61. pygpt_net/plugin/audio_output/__init__.py +6 -1
  62. pygpt_net/plugin/base/plugin.py +58 -26
  63. pygpt_net/plugin/base/worker.py +20 -17
  64. pygpt_net/plugin/cmd_files/__init__.py +3 -2
  65. pygpt_net/plugin/cmd_history/config.py +2 -2
  66. pygpt_net/plugin/cmd_web/__init__.py +3 -4
  67. pygpt_net/plugin/cmd_web/config.py +71 -3
  68. pygpt_net/plugin/cmd_web/websearch.py +20 -12
  69. pygpt_net/plugin/cmd_web/worker.py +67 -4
  70. pygpt_net/plugin/idx_llama_index/config.py +3 -3
  71. pygpt_net/plugin/mailer/__init__.py +123 -0
  72. pygpt_net/plugin/mailer/config.py +149 -0
  73. pygpt_net/plugin/mailer/runner.py +285 -0
  74. pygpt_net/plugin/mailer/worker.py +123 -0
  75. pygpt_net/provider/agents/base.py +5 -2
  76. pygpt_net/provider/agents/openai.py +4 -2
  77. pygpt_net/provider/agents/openai_assistant.py +4 -2
  78. pygpt_net/provider/agents/planner.py +4 -2
  79. pygpt_net/provider/agents/react.py +4 -2
  80. pygpt_net/provider/audio_output/openai_tts.py +5 -11
  81. pygpt_net/provider/core/assistant/base.py +5 -3
  82. pygpt_net/provider/core/assistant/json_file.py +8 -5
  83. pygpt_net/provider/core/assistant_file/base.py +4 -3
  84. pygpt_net/provider/core/assistant_file/db_sqlite/__init__.py +4 -3
  85. pygpt_net/provider/core/assistant_file/db_sqlite/storage.py +3 -2
  86. pygpt_net/provider/core/assistant_store/base.py +6 -4
  87. pygpt_net/provider/core/assistant_store/db_sqlite/__init__.py +5 -4
  88. pygpt_net/provider/core/assistant_store/db_sqlite/storage.py +5 -3
  89. pygpt_net/provider/core/attachment/base.py +5 -3
  90. pygpt_net/provider/core/attachment/json_file.py +7 -3
  91. pygpt_net/provider/core/calendar/base.py +5 -3
  92. pygpt_net/provider/core/calendar/db_sqlite/__init__.py +6 -5
  93. pygpt_net/provider/core/calendar/db_sqlite/storage.py +5 -4
  94. pygpt_net/provider/core/config/base.py +8 -6
  95. pygpt_net/provider/core/config/json_file.py +9 -7
  96. pygpt_net/provider/core/config/patch.py +6 -0
  97. pygpt_net/provider/core/ctx/base.py +27 -25
  98. pygpt_net/provider/core/ctx/db_sqlite/__init__.py +51 -35
  99. pygpt_net/provider/core/ctx/db_sqlite/storage.py +92 -38
  100. pygpt_net/provider/core/ctx/db_sqlite/utils.py +37 -11
  101. pygpt_net/provider/core/index/base.py +129 -23
  102. pygpt_net/provider/core/index/db_sqlite/__init__.py +130 -23
  103. pygpt_net/provider/core/index/db_sqlite/storage.py +130 -23
  104. pygpt_net/provider/core/index/db_sqlite/utils.py +4 -2
  105. pygpt_net/provider/core/mode/base.py +5 -3
  106. pygpt_net/provider/core/mode/json_file.py +7 -6
  107. pygpt_net/provider/core/model/base.py +6 -4
  108. pygpt_net/provider/core/model/json_file.py +9 -7
  109. pygpt_net/provider/core/notepad/base.py +5 -3
  110. pygpt_net/provider/core/notepad/db_sqlite/__init__.py +5 -4
  111. pygpt_net/provider/core/notepad/db_sqlite/storage.py +4 -3
  112. pygpt_net/provider/core/plugin_preset/base.py +4 -2
  113. pygpt_net/provider/core/plugin_preset/json_file.py +5 -3
  114. pygpt_net/provider/core/preset/base.py +6 -4
  115. pygpt_net/provider/core/preset/json_file.py +9 -9
  116. pygpt_net/provider/core/prompt/base.py +6 -3
  117. pygpt_net/provider/core/prompt/json_file.py +11 -6
  118. pygpt_net/provider/gpt/assistants.py +15 -6
  119. pygpt_net/provider/gpt/audio.py +5 -5
  120. pygpt_net/provider/gpt/chat.py +7 -5
  121. pygpt_net/provider/gpt/completion.py +8 -4
  122. pygpt_net/provider/gpt/image.py +3 -3
  123. pygpt_net/provider/gpt/store.py +46 -12
  124. pygpt_net/provider/gpt/vision.py +16 -11
  125. pygpt_net/provider/llms/anthropic.py +7 -2
  126. pygpt_net/provider/llms/azure_openai.py +26 -5
  127. pygpt_net/provider/llms/base.py +47 -9
  128. pygpt_net/provider/llms/google.py +7 -2
  129. pygpt_net/provider/llms/hugging_face.py +13 -3
  130. pygpt_net/provider/llms/hugging_face_api.py +18 -4
  131. pygpt_net/provider/llms/local.py +7 -2
  132. pygpt_net/provider/llms/ollama.py +30 -6
  133. pygpt_net/provider/llms/openai.py +32 -6
  134. pygpt_net/provider/loaders/base.py +14 -0
  135. pygpt_net/provider/loaders/hub/yt/base.py +5 -0
  136. pygpt_net/provider/loaders/web_database.py +13 -5
  137. pygpt_net/provider/loaders/web_github_issues.py +5 -1
  138. pygpt_net/provider/loaders/web_google_calendar.py +9 -1
  139. pygpt_net/provider/loaders/web_google_docs.py +6 -1
  140. pygpt_net/provider/loaders/web_google_drive.py +10 -1
  141. pygpt_net/provider/loaders/web_google_gmail.py +2 -1
  142. pygpt_net/provider/loaders/web_google_keep.py +5 -1
  143. pygpt_net/provider/loaders/web_google_sheets.py +5 -1
  144. pygpt_net/provider/loaders/web_microsoft_onedrive.py +15 -1
  145. pygpt_net/provider/loaders/web_page.py +4 -2
  146. pygpt_net/provider/loaders/web_rss.py +2 -1
  147. pygpt_net/provider/loaders/web_sitemap.py +2 -1
  148. pygpt_net/provider/loaders/web_twitter.py +4 -2
  149. pygpt_net/provider/loaders/web_yt.py +17 -2
  150. pygpt_net/provider/vector_stores/__init__.py +45 -14
  151. pygpt_net/provider/vector_stores/base.py +35 -8
  152. pygpt_net/provider/vector_stores/chroma.py +13 -3
  153. pygpt_net/provider/vector_stores/ctx_attachment.py +32 -13
  154. pygpt_net/provider/vector_stores/elasticsearch.py +12 -3
  155. pygpt_net/provider/vector_stores/pinecode.py +12 -3
  156. pygpt_net/provider/vector_stores/redis.py +12 -3
  157. pygpt_net/provider/vector_stores/simple.py +12 -3
  158. pygpt_net/provider/vector_stores/temp.py +16 -4
  159. pygpt_net/provider/web/base.py +10 -3
  160. pygpt_net/provider/web/google_custom_search.py +9 -3
  161. pygpt_net/provider/web/microsoft_bing.py +9 -3
  162. pygpt_net/tools/__init__.py +13 -5
  163. pygpt_net/tools/audio_transcriber/__init__.py +4 -3
  164. pygpt_net/tools/base.py +15 -8
  165. pygpt_net/tools/code_interpreter/__init__.py +4 -3
  166. pygpt_net/tools/html_canvas/__init__.py +4 -3
  167. pygpt_net/tools/image_viewer/__init__.py +10 -4
  168. pygpt_net/tools/indexer/__init__.py +15 -46
  169. pygpt_net/tools/indexer/ui/web.py +20 -78
  170. pygpt_net/tools/media_player/__init__.py +4 -3
  171. pygpt_net/tools/text_editor/__init__.py +36 -10
  172. pygpt_net/ui/layout/chat/output.py +2 -2
  173. pygpt_net/ui/layout/ctx/ctx_list.py +86 -18
  174. pygpt_net/ui/menu/audio.py +12 -1
  175. pygpt_net/ui/widget/dialog/url.py +151 -14
  176. pygpt_net/ui/widget/element/group.py +15 -2
  177. pygpt_net/ui/widget/lists/context.py +23 -9
  178. pygpt_net/utils.py +1 -1
  179. {pygpt_net-2.4.41.dist-info → pygpt_net-2.4.44.dist-info}/METADATA +152 -72
  180. {pygpt_net-2.4.41.dist-info → pygpt_net-2.4.44.dist-info}/RECORD +183 -173
  181. {pygpt_net-2.4.41.dist-info → pygpt_net-2.4.44.dist-info}/LICENSE +0 -0
  182. {pygpt_net-2.4.41.dist-info → pygpt_net-2.4.44.dist-info}/WHEEL +0 -0
  183. {pygpt_net-2.4.41.dist-info → pygpt_net-2.4.44.dist-info}/entry_points.txt +0 -0
@@ -19,9 +19,6 @@ import cv2
19
19
  from PySide6.QtCore import Slot, QObject
20
20
  from PySide6.QtGui import QImage, QPixmap, Qt
21
21
 
22
- from pygpt_net.core.types import (
23
- MODE_VISION,
24
- )
25
22
  from pygpt_net.core.events import AppEvent, KernelEvent
26
23
  from pygpt_net.core.camera import CaptureWorker
27
24
  from pygpt_net.utils import trans
@@ -508,15 +505,9 @@ class Camera(QObject):
508
505
 
509
506
  :return: True if capture is allowed
510
507
  """
511
- mode = self.window.core.config.get('mode')
512
508
  if self.window.controller.painter.is_active():
513
509
  return True
514
- if (mode != MODE_VISION
515
- and mode not in self.window.controller.chat.vision.allowed_modes):
516
- return False
517
- if self.window.controller.plugins.is_type_enabled('vision'):
518
- return True
519
- if self.window.controller.ui.vision.is_vision_model():
510
+ if self.window.controller.ui.vision.has_vision():
520
511
  return True
521
512
  return False
522
513
 
@@ -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.12.14 08:00:00 #
9
+ # Updated Date: 2024.12.16 01:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -180,7 +180,7 @@ class Attachment(QObject):
180
180
  if tmp_path:
181
181
  for root, dirs, files in os.walk(tmp_path):
182
182
  for file in files:
183
- path = os.path.join(root, file)
183
+ path = str(os.path.join(root, file))
184
184
  sub_attachment = AttachmentItem()
185
185
  sub_attachment.path = path
186
186
  sub_attachment.name = os.path.basename(path)
@@ -197,11 +197,9 @@ class Attachment(QObject):
197
197
  auto_index=auto_index,
198
198
  )
199
199
  if item:
200
- item["path"] = os.path.basename(attachment.path) + "/" + path_relative
200
+ item["path"] = os.path.basename(attachment.path) + "/" + str(path_relative)
201
201
  item["size"] = os.path.getsize(path)
202
- if meta.additional_ctx is None:
203
- meta.additional_ctx = []
204
- meta.additional_ctx.append(item)
202
+ self.append_to_meta(meta, item)
205
203
  uploaded = True
206
204
  sub_attachment.consumed = True
207
205
  attachment.consumed = True
@@ -215,14 +213,27 @@ class Attachment(QObject):
215
213
  auto_index=auto_index,
216
214
  )
217
215
  if item:
218
- if meta.additional_ctx is None:
219
- meta.additional_ctx = []
220
- meta.additional_ctx.append(item)
216
+ self.append_to_meta(meta, item)
221
217
  attachment.consumed = True # allow for deletion
222
218
  uploaded = True
223
-
224
219
  return uploaded
225
220
 
221
+ def append_to_meta(self, meta: CtxMeta, item: Dict[str, Any]):
222
+ """
223
+ Append item to meta
224
+
225
+ :param meta: CtxMeta instance
226
+ :param item: Attachment item
227
+ """
228
+ if meta.group:
229
+ if meta.group.additional_ctx is None:
230
+ meta.group.additional_ctx = []
231
+ meta.group.additional_ctx.append(item)
232
+ return
233
+ if meta.additional_ctx is None:
234
+ meta.additional_ctx = []
235
+ meta.additional_ctx.append(item)
236
+
226
237
  def upload_web(
227
238
  self,
228
239
  attachment: AttachmentItem,
@@ -248,9 +259,9 @@ class Attachment(QObject):
248
259
  :param meta: CtxMeta
249
260
  :return: True if has context
250
261
  """
251
- if meta is None or meta.additional_ctx is None:
262
+ if meta is None:
252
263
  return False
253
- return len(meta.additional_ctx) > 0
264
+ return meta.has_additional_ctx()
254
265
 
255
266
  def current_has_context(self) -> bool:
256
267
  """
@@ -306,18 +317,6 @@ class Attachment(QObject):
306
317
  return "====================================\nADDITIONAL CONTEXT FROM ATTACHMENT(s): {}".format(content)
307
318
  return ""
308
319
 
309
- def get_uploaded_attachments(
310
- self,
311
- meta: CtxMeta
312
- ) -> List[Dict[str, Any]]:
313
- """
314
- Get uploaded attachments for meta
315
-
316
- :param meta: CtxMeta instance
317
- :return: List of attachments
318
- """
319
- return meta.additional_ctx
320
-
321
320
  def update(self):
322
321
  """Update attachments list"""
323
322
  mode = self.window.core.config.get("mode")
@@ -334,7 +333,7 @@ class Attachment(QObject):
334
333
  :param meta: CtxMeta instance
335
334
  """
336
335
  # update list of attachments
337
- if meta is None or meta.additional_ctx is None:
336
+ if meta is None or not meta.has_additional_ctx():
338
337
  items = []
339
338
  else:
340
339
  items = self.window.core.attachments.context.get_all(meta)
@@ -347,7 +346,7 @@ class Attachment(QObject):
347
346
 
348
347
  :param meta: CtxMeta instance
349
348
  """
350
- if meta is None or meta.additional_ctx is None:
349
+ if meta is None or not meta.has_additional_ctx():
351
350
  num_files = 0
352
351
  else:
353
352
  num_files = self.window.core.attachments.context.count(meta)
@@ -402,13 +401,14 @@ class Attachment(QObject):
402
401
  )
403
402
  return
404
403
  meta = self.window.core.ctx.get_current_meta()
405
- if meta is None or meta.additional_ctx is None:
404
+ if meta is None or not meta.has_additional_ctx():
406
405
  return
407
406
  items = self.window.core.attachments.context.get_all(meta)
408
407
  if idx < len(items):
409
408
  item = items[idx]
410
409
  self.window.core.attachments.context.delete(meta, item, delete_files=remove_local)
411
410
  self.update_list(meta)
411
+ self.window.controller.ctx.update()
412
412
 
413
413
  def clear(
414
414
  self,
@@ -432,10 +432,11 @@ class Attachment(QObject):
432
432
  return
433
433
 
434
434
  meta = self.window.core.ctx.get_current_meta()
435
- if meta is None or meta.additional_ctx is None:
435
+ if meta is None or not meta.has_additional_ctx():
436
436
  return
437
437
  self.window.core.attachments.context.clear(meta, delete_files=remove_local)
438
438
  self.update_list(meta)
439
+ self.window.controller.ctx.update()
439
440
 
440
441
  def select(self, idx: int):
441
442
  """
@@ -452,7 +453,7 @@ class Attachment(QObject):
452
453
  :param idx: Index on list
453
454
  """
454
455
  meta = self.window.core.ctx.get_current_meta()
455
- if meta is None or meta.additional_ctx is None:
456
+ if meta is None or not meta.has_additional_ctx():
456
457
  return
457
458
  items = self.window.core.attachments.context.get_all(meta)
458
459
  if idx < len(items):
@@ -471,7 +472,7 @@ class Attachment(QObject):
471
472
  :param idx: Index on list
472
473
  """
473
474
  meta = self.window.core.ctx.get_current_meta()
474
- if meta is None or meta.additional_ctx is None:
475
+ if meta is None or not meta.has_additional_ctx():
475
476
  return
476
477
  items = self.window.core.attachments.context.get_all(meta)
477
478
  if idx < len(items):
@@ -491,7 +492,7 @@ class Attachment(QObject):
491
492
  :param idx: Index on list
492
493
  """
493
494
  meta = self.window.core.ctx.get_current_meta()
494
- if meta is None or meta.additional_ctx is None:
495
+ if meta is None or not meta.has_additional_ctx():
495
496
  return
496
497
  items = self.window.core.attachments.context.get_all(meta)
497
498
  if idx < len(items):
@@ -510,7 +511,7 @@ class Attachment(QObject):
510
511
  :return: True if has file
511
512
  """
512
513
  meta = self.window.core.ctx.get_current_meta()
513
- if meta is None or meta.additional_ctx is None:
514
+ if meta is None or not meta.has_additional_ctx():
514
515
  return False
515
516
  items = self.window.core.attachments.context.get_all(meta)
516
517
  if idx < len(items):
@@ -529,7 +530,7 @@ class Attachment(QObject):
529
530
  :return: True if has source directory
530
531
  """
531
532
  meta = self.window.core.ctx.get_current_meta()
532
- if meta is None or meta.additional_ctx is None:
533
+ if meta is None or not meta.has_additional_ctx():
533
534
  return False
534
535
  items = self.window.core.attachments.context.get_all(meta)
535
536
  if idx < len(items):
@@ -549,7 +550,7 @@ class Attachment(QObject):
549
550
  :return: True if has destination directory
550
551
  """
551
552
  meta = self.window.core.ctx.get_current_meta()
552
- if meta is None or meta.additional_ctx is None:
553
+ if meta is None or not meta.has_additional_ctx():
553
554
  return False
554
555
  items = self.window.core.attachments.context.get_all(meta)
555
556
  if idx < len(items):
@@ -570,10 +571,10 @@ class Attachment(QObject):
570
571
  meta = self.window.core.ctx.get_current_meta()
571
572
  if meta is None:
572
573
  return 0
573
- if meta.additional_ctx is None:
574
+ if not meta.has_additional_ctx():
574
575
  return 0
575
576
  tokens = 0
576
- for item in meta.additional_ctx:
577
+ for item in meta.get_additional_ctx():
577
578
  if "tokens" in item:
578
579
  try:
579
580
  tokens += int(item["tokens"])
@@ -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.14 18:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import base64
@@ -63,7 +63,7 @@ class Audio:
63
63
  :param ctx: Context item
64
64
  """
65
65
  wav_path = os.path.join(self.window.core.config.get_user_path(), self.audio_file)
66
- if ctx.is_audio and ctx.audio_output:
66
+ if ctx.is_audio and ctx.audio_output and ctx.audio_read_allowed():
67
67
  wav_bytes = base64.b64decode(ctx.audio_output)
68
68
  with open(wav_path, "wb") as f:
69
69
  f.write(wav_bytes)
@@ -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.12.14 08:00:00 #
9
+ # Updated Date: 2024.12.16 01:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Dict, Any, List
@@ -104,9 +104,23 @@ class Placeholder:
104
104
  return self.get_voice_control_actions()
105
105
  elif id == "audio_input_devices":
106
106
  return self.get_audio_input_devices()
107
+ elif id == "audio_tts_whisper_voices":
108
+ return self.get_audio_tts_whisper_voices()
107
109
  else:
108
110
  return []
109
111
 
112
+ def get_audio_tts_whisper_voices(self) -> List[Dict[str, str]]:
113
+ """
114
+ Get audio TTS whisper voices list
115
+
116
+ :return: placeholders list
117
+ """
118
+ voices = self.window.core.audio.whisper.get_voices()
119
+ data = []
120
+ for voice in voices:
121
+ data.append({voice: voice})
122
+ return data
123
+
110
124
  def get_audio_input_devices(self) -> List[Dict[str, str]]:
111
125
  """
112
126
  Get audio input devices list
@@ -265,7 +279,8 @@ class Placeholder:
265
279
  modes = self.window.core.agents.legacy.get_allowed_modes()
266
280
  data = []
267
281
  for id in modes:
268
- data.append({id: id}) # TODO: name
282
+ name = trans(f"mode.{id}")
283
+ data.append({id: name})
269
284
  return data
270
285
 
271
286
  def get_idx(self) -> List[Dict[str, str]]:
@@ -277,8 +292,9 @@ class Placeholder:
277
292
  indexes = self.window.core.idx.get_idx_ids()
278
293
  data = []
279
294
  data.append({'_': '---'})
280
- for id in indexes:
281
- data.append({id: id})
295
+ for item in indexes:
296
+ for k, v in item.items():
297
+ data.append({k: v})
282
298
  return data
283
299
 
284
300
  def get_syntax_styles(self) -> List[Dict[str, str]]:
@@ -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.12.14 08:00:00 #
9
+ # Updated Date: 2024.12.16 01:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import List, Dict
@@ -50,13 +50,17 @@ class Common:
50
50
  ext_str = " (" + ", ".join(loader.extensions) + ")"
51
51
  # name = "(File) " + loader.name + ext_str # TODO: implement option names
52
52
  data.append({
53
- id: id
53
+ id: loader.name
54
54
  })
55
+ # sort by name
56
+ data = sorted(data, key=lambda x: list(x.values())[0])
55
57
  # web
56
58
  if "web" in loader.type:
57
59
  id = "web_" + id
58
60
  # name = "(Web) " + loader.name # TODO: implement option names
59
61
  data.append({
60
- id: id
62
+ id: loader.name
61
63
  })
64
+ # sort by name
65
+ data = sorted(data, key=lambda x: list(x.values())[0])
62
66
  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.23 00:00:00 #
9
+ # Updated Date: 2024.12.14 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.core.types import (
@@ -189,8 +189,12 @@ class Mode:
189
189
  self.window.ui.tabs['input'].setTabVisible(2, False)
190
190
  self.window.ui.tabs['input'].setTabVisible(3, False)
191
191
 
192
- # toggle chat footer
193
- if not self.is_chat_tab():
192
+ # chat footer
193
+ self.toggle_chat_footer()
194
+
195
+ def toggle_chat_footer(self):
196
+ """Toggle chat footer"""
197
+ if self.window.controller.ui.tabs.get_current_type() != Tab.TAB_CHAT:
194
198
  self.hide_chat_footer()
195
199
  else:
196
200
  self.show_chat_footer()
@@ -200,18 +204,12 @@ class Mode:
200
204
  Check if vision is allowed
201
205
 
202
206
  :param mode: current mode
207
+ :return: True if vision is allowed
203
208
  """
204
- if mode == MODE_VISION:
205
- return True
206
-
207
- allowed = self.window.controller.painter.is_active()
208
- if allowed:
209
+ if self.window.controller.ui.vision.has_vision():
209
210
  return True
210
211
 
211
- if mode in [MODE_IMAGE, MODE_ASSISTANT]:
212
- return False
213
-
214
- if self.window.controller.ui.vision.is_vision_model():
212
+ if self.window.controller.painter.is_active():
215
213
  return True
216
214
 
217
215
  # event: UI: vision
@@ -224,7 +222,12 @@ class Mode:
224
222
  return event.data['value']
225
223
 
226
224
  def are_attachments(self, mode: str) -> bool:
227
- """Check if attachments are allowed"""
225
+ """
226
+ Check if attachments are allowed
227
+
228
+ :param mode: current mode
229
+ :return: True if attachments are allowed
230
+ """
228
231
  if mode in [MODE_VISION, MODE_ASSISTANT]:
229
232
  return True
230
233
 
@@ -243,14 +246,6 @@ class Mode:
243
246
  self.window.dispatch(event)
244
247
  return event.data['value']
245
248
 
246
- def is_chat_tab(self) -> bool:
247
- """
248
- Check if current tab is chat
249
-
250
- :return: True if chat tab
251
- """
252
- return self.window.controller.ui.tabs.get_current_type() == Tab.TAB_CHAT
253
-
254
249
  def show_chat_footer(self):
255
250
  """Show chat footer"""
256
251
  self.window.ui.nodes['chat.footer'].setVisible(True)
@@ -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.12.14 08:00:00 #
9
+ # Updated Date: 2024.12.16 01:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import copy
@@ -161,7 +161,7 @@ class Attachments:
161
161
  if meta is None:
162
162
  return []
163
163
  attachments = []
164
- for attachment in meta.additional_ctx:
164
+ for attachment in meta.get_additional_ctx():
165
165
  item = AttachmentItem()
166
166
  if 'uuid' not in attachment:
167
167
  continue
@@ -187,6 +187,7 @@ class Attachments:
187
187
  path: Optional[str] = None,
188
188
  auto_save: bool = True,
189
189
  type: str = AttachmentItem.TYPE_FILE,
190
+ extra: Optional[dict] = None
190
191
  ) -> AttachmentItem:
191
192
  """
192
193
  Create new attachment
@@ -196,6 +197,7 @@ class Attachments:
196
197
  :param path: path
197
198
  :param auto_save: auto_save
198
199
  :param type: type
200
+ :param extra: extra data
199
201
  :return: AttachmentItem
200
202
  """
201
203
  # make local copy of external attachment if enabled
@@ -209,6 +211,9 @@ class Attachments:
209
211
  attachment.path = path
210
212
  attachment.type = type
211
213
 
214
+ if extra is not None:
215
+ attachment.extra = extra
216
+
212
217
  if mode not in self.items:
213
218
  self.items[mode] = {}
214
219