pygpt-net 2.7.6__py3-none-any.whl → 2.7.8__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 (120) hide show
  1. pygpt_net/CHANGELOG.txt +13 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +5 -1
  4. pygpt_net/controller/assistant/batch.py +2 -2
  5. pygpt_net/controller/assistant/files.py +7 -6
  6. pygpt_net/controller/assistant/threads.py +0 -0
  7. pygpt_net/controller/chat/command.py +0 -0
  8. pygpt_net/controller/chat/remote_tools.py +3 -9
  9. pygpt_net/controller/chat/stream.py +2 -2
  10. pygpt_net/controller/chat/{handler/worker.py → stream_worker.py} +13 -35
  11. pygpt_net/controller/dialogs/confirm.py +35 -58
  12. pygpt_net/controller/lang/mapping.py +9 -9
  13. pygpt_net/controller/remote_store/{google/batch.py → batch.py} +209 -252
  14. pygpt_net/controller/remote_store/remote_store.py +982 -13
  15. pygpt_net/core/command/command.py +0 -0
  16. pygpt_net/core/db/viewer.py +1 -1
  17. pygpt_net/core/debug/models.py +2 -2
  18. pygpt_net/core/realtime/worker.py +3 -1
  19. pygpt_net/{controller/remote_store/google → core/remote_store/anthropic}/__init__.py +0 -1
  20. pygpt_net/core/remote_store/anthropic/files.py +211 -0
  21. pygpt_net/core/remote_store/anthropic/store.py +208 -0
  22. pygpt_net/core/remote_store/openai/store.py +5 -4
  23. pygpt_net/core/remote_store/remote_store.py +5 -1
  24. pygpt_net/{controller/remote_store/openai → core/remote_store/xai}/__init__.py +0 -1
  25. pygpt_net/core/remote_store/xai/files.py +225 -0
  26. pygpt_net/core/remote_store/xai/store.py +219 -0
  27. pygpt_net/data/config/config.json +18 -5
  28. pygpt_net/data/config/models.json +193 -4
  29. pygpt_net/data/config/settings.json +179 -36
  30. pygpt_net/data/icons/folder_eye.svg +1 -0
  31. pygpt_net/data/icons/folder_eye_filled.svg +1 -0
  32. pygpt_net/data/icons/folder_open.svg +1 -0
  33. pygpt_net/data/icons/folder_open_filled.svg +1 -0
  34. pygpt_net/data/locale/locale.de.ini +6 -3
  35. pygpt_net/data/locale/locale.en.ini +46 -12
  36. pygpt_net/data/locale/locale.es.ini +6 -3
  37. pygpt_net/data/locale/locale.fr.ini +6 -3
  38. pygpt_net/data/locale/locale.it.ini +6 -3
  39. pygpt_net/data/locale/locale.pl.ini +7 -4
  40. pygpt_net/data/locale/locale.uk.ini +6 -3
  41. pygpt_net/data/locale/locale.zh.ini +6 -3
  42. pygpt_net/icons.qrc +4 -0
  43. pygpt_net/icons_rc.py +282 -138
  44. pygpt_net/plugin/cmd_mouse_control/worker.py +2 -1
  45. pygpt_net/plugin/cmd_mouse_control/worker_sandbox.py +2 -1
  46. pygpt_net/provider/api/anthropic/__init__.py +10 -3
  47. pygpt_net/provider/api/anthropic/chat.py +342 -11
  48. pygpt_net/provider/api/anthropic/computer.py +844 -0
  49. pygpt_net/provider/api/anthropic/remote_tools.py +172 -0
  50. pygpt_net/provider/api/anthropic/store.py +307 -0
  51. pygpt_net/{controller/chat/handler/anthropic_stream.py → provider/api/anthropic/stream.py} +99 -10
  52. pygpt_net/provider/api/anthropic/tools.py +32 -77
  53. pygpt_net/provider/api/anthropic/utils.py +30 -0
  54. pygpt_net/{controller/chat/handler → provider/api/anthropic/worker}/__init__.py +0 -0
  55. pygpt_net/provider/api/anthropic/worker/importer.py +278 -0
  56. pygpt_net/provider/api/google/chat.py +62 -9
  57. pygpt_net/provider/api/google/store.py +124 -3
  58. pygpt_net/{controller/chat/handler/google_stream.py → provider/api/google/stream.py} +92 -25
  59. pygpt_net/provider/api/google/utils.py +185 -0
  60. pygpt_net/provider/api/google/worker/importer.py +16 -28
  61. pygpt_net/provider/api/langchain/__init__.py +0 -0
  62. pygpt_net/{controller/chat/handler/langchain_stream.py → provider/api/langchain/stream.py} +1 -1
  63. pygpt_net/provider/api/llama_index/__init__.py +0 -0
  64. pygpt_net/{controller/chat/handler/llamaindex_stream.py → provider/api/llama_index/stream.py} +1 -1
  65. pygpt_net/provider/api/openai/assistants.py +2 -2
  66. pygpt_net/provider/api/openai/image.py +2 -2
  67. pygpt_net/provider/api/openai/store.py +4 -1
  68. pygpt_net/{controller/chat/handler/openai_stream.py → provider/api/openai/stream.py} +1 -1
  69. pygpt_net/provider/api/openai/utils.py +69 -3
  70. pygpt_net/provider/api/openai/worker/importer.py +19 -61
  71. pygpt_net/provider/api/openai/worker/importer_assistants.py +230 -0
  72. pygpt_net/provider/api/x_ai/__init__.py +138 -15
  73. pygpt_net/provider/api/x_ai/audio.py +43 -11
  74. pygpt_net/provider/api/x_ai/chat.py +92 -4
  75. pygpt_net/provider/api/x_ai/image.py +149 -47
  76. pygpt_net/provider/api/x_ai/realtime/__init__.py +12 -0
  77. pygpt_net/provider/api/x_ai/realtime/client.py +1825 -0
  78. pygpt_net/provider/api/x_ai/realtime/realtime.py +198 -0
  79. pygpt_net/provider/api/x_ai/{remote.py → remote_tools.py} +183 -70
  80. pygpt_net/provider/api/x_ai/responses.py +507 -0
  81. pygpt_net/provider/api/x_ai/store.py +610 -0
  82. pygpt_net/{controller/chat/handler/xai_stream.py → provider/api/x_ai/stream.py} +42 -10
  83. pygpt_net/provider/api/x_ai/tools.py +59 -8
  84. pygpt_net/{controller/chat/handler → provider/api/x_ai}/utils.py +1 -2
  85. pygpt_net/provider/api/x_ai/vision.py +1 -4
  86. pygpt_net/provider/api/x_ai/worker/importer.py +308 -0
  87. pygpt_net/provider/audio_input/xai_grok_voice.py +390 -0
  88. pygpt_net/provider/audio_output/xai_tts.py +325 -0
  89. pygpt_net/provider/core/config/patch.py +39 -3
  90. pygpt_net/provider/core/config/patches/patch_before_2_6_42.py +2 -2
  91. pygpt_net/provider/core/model/patch.py +39 -1
  92. pygpt_net/tools/image_viewer/tool.py +334 -34
  93. pygpt_net/tools/image_viewer/ui/dialogs.py +319 -22
  94. pygpt_net/tools/text_editor/ui/dialogs.py +3 -2
  95. pygpt_net/tools/text_editor/ui/widgets.py +0 -0
  96. pygpt_net/ui/dialog/assistant.py +1 -1
  97. pygpt_net/ui/dialog/plugins.py +13 -5
  98. pygpt_net/ui/dialog/remote_store.py +552 -0
  99. pygpt_net/ui/dialogs.py +3 -5
  100. pygpt_net/ui/layout/ctx/ctx_list.py +58 -7
  101. pygpt_net/ui/menu/tools.py +6 -13
  102. pygpt_net/ui/widget/dialog/base.py +16 -5
  103. pygpt_net/ui/widget/dialog/{remote_store_google.py → remote_store.py} +10 -10
  104. pygpt_net/ui/widget/element/button.py +4 -4
  105. pygpt_net/ui/widget/image/display.py +2 -2
  106. pygpt_net/ui/widget/lists/context.py +2 -2
  107. pygpt_net/ui/widget/textarea/editor.py +0 -0
  108. {pygpt_net-2.7.6.dist-info → pygpt_net-2.7.8.dist-info}/METADATA +15 -2
  109. {pygpt_net-2.7.6.dist-info → pygpt_net-2.7.8.dist-info}/RECORD +107 -89
  110. pygpt_net/controller/remote_store/google/store.py +0 -615
  111. pygpt_net/controller/remote_store/openai/batch.py +0 -524
  112. pygpt_net/controller/remote_store/openai/store.py +0 -699
  113. pygpt_net/ui/dialog/remote_store_google.py +0 -539
  114. pygpt_net/ui/dialog/remote_store_openai.py +0 -539
  115. pygpt_net/ui/widget/dialog/remote_store_openai.py +0 -56
  116. pygpt_net/ui/widget/lists/remote_store_google.py +0 -248
  117. pygpt_net/ui/widget/lists/remote_store_openai.py +0 -317
  118. {pygpt_net-2.7.6.dist-info → pygpt_net-2.7.8.dist-info}/LICENSE +0 -0
  119. {pygpt_net-2.7.6.dist-info → pygpt_net-2.7.8.dist-info}/WHEEL +0 -0
  120. {pygpt_net-2.7.6.dist-info → pygpt_net-2.7.8.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: 2025.12.28 12:00:00 #
9
+ # Updated Date: 2026.01.03 17:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6 import QtCore
@@ -34,6 +34,10 @@ class CtxList:
34
34
  self._group_separators = False
35
35
  self._pinned_separators = False
36
36
 
37
+ # Cached icons for closed/open folder states
38
+ self._folder_icon = None
39
+ self._folder_open_icon = None
40
+
37
41
  def setup(self) -> QWidget:
38
42
  """
39
43
  Setup list
@@ -80,6 +84,14 @@ class CtxList:
80
84
  ctx = self.window.controller.ctx
81
85
  ctx_list.selectionModel().selectionChanged.connect(lambda *_: ctx.selection_change())
82
86
 
87
+ # Switch group folder icon on expand/collapse
88
+ try:
89
+ ctx_list.expanded.connect(self.on_group_expanded)
90
+ ctx_list.collapsed.connect(self.on_group_collapsed)
91
+ except Exception:
92
+ # View might not expose expanded/collapsed; ignore if not supported
93
+ pass
94
+
83
95
  self._group_separators = self.window.core.config.get("ctx.records.groups.separators")
84
96
  self._pinned_separators = self.window.core.config.get("ctx.records.pinned.separators")
85
97
 
@@ -258,10 +270,11 @@ class CtxList:
258
270
  if gid is not None and gid != 0:
259
271
  grouped.setdefault(gid, []).append((meta_id, meta))
260
272
 
261
- folder_icon = getattr(self, "_folder_icon", None)
262
- if folder_icon is None:
263
- from PySide6.QtGui import QIcon
264
- folder_icon = self._folder_icon = QIcon(":/icons/folder_filled.svg")
273
+ # Ensure icons for closed/open folder states are loaded once
274
+ if getattr(self, "_folder_icon", None) is None:
275
+ self._folder_icon = QIcon(":/icons/folder.svg")
276
+ if getattr(self, "_folder_open_icon", None) is None:
277
+ self._folder_open_icon = QIcon(":/icons/folder_open.svg")
265
278
 
266
279
  node = self.window.ui.nodes[id]
267
280
 
@@ -276,7 +289,7 @@ class CtxList:
276
289
  # Display only the group name; the counter is drawn by delegate on the right
277
290
  is_attachment = group.has_additional_ctx()
278
291
  group_name = group.name
279
- group_item = GroupItem(folder_icon, group_name, group.id)
292
+ group_item = GroupItem(self._folder_icon, group_name, group.id)
280
293
  group_item.hasAttachments = is_attachment
281
294
 
282
295
  # Provide all metadata required by the delegate
@@ -315,6 +328,7 @@ class CtxList:
315
328
  idx = group_item.index()
316
329
  if node.isExpanded(idx) != desired:
317
330
  node.setExpanded(idx, desired)
331
+ self._set_group_icon_for_index(idx, desired)
318
332
 
319
333
  def count_in_group(self, group_id: int, data: dict) -> int:
320
334
  """
@@ -417,4 +431,41 @@ class CtxList:
417
431
  elif 30 <= days_ago < 32:
418
432
  return trans('dt.month')
419
433
  else:
420
- return date.strftime("%Y-%m-%d")
434
+ return date.strftime("%Y-%m-%d")
435
+
436
+ # ===========================
437
+ # Helpers for group icons
438
+ # ===========================
439
+
440
+ def _set_group_icon_for_index(self, index: QtCore.QModelIndex, expanded: bool):
441
+ """
442
+ Set folder icon for a group index based on expansion state.
443
+ """
444
+ try:
445
+ if not index.isValid():
446
+ return
447
+ model = index.model()
448
+ if not hasattr(model, "itemFromIndex"):
449
+ return
450
+ item = model.itemFromIndex(index)
451
+ if not isinstance(item, GroupItem):
452
+ return
453
+ if getattr(self, "_folder_icon", None) is None:
454
+ self._folder_icon = QIcon(":/icons/folder.svg")
455
+ if getattr(self, "_folder_open_icon", None) is None:
456
+ self._folder_open_icon = QIcon(":/icons/folder_open.svg")
457
+ item.setIcon(self._folder_open_icon if expanded else self._folder_icon)
458
+ except Exception:
459
+ pass
460
+
461
+ def on_group_expanded(self, index: QtCore.QModelIndex):
462
+ """
463
+ Slot: update icon when a group is expanded.
464
+ """
465
+ self._set_group_icon_for_index(index, True)
466
+
467
+ def on_group_collapsed(self, index: QtCore.QModelIndex):
468
+ """
469
+ Slot: update icon when a group is collapsed.
470
+ """
471
+ self._set_group_icon_for_index(index, False)
@@ -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: 2026.01.02 19:00:00 #
9
+ # Updated Date: 2026.01.05 17:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtGui import QAction, QIcon
@@ -26,11 +26,8 @@ class Tools:
26
26
  action = self.window.sender()
27
27
  self.window.controller.tools.open_tab(action.data())
28
28
 
29
- def _toggle_remote_store_openai(self, checked=False):
30
- self.window.controller.remote_store.openai.toggle_editor()
31
-
32
- def _toggle_remote_store_google(self, checked=False):
33
- self.window.controller.remote_store.google.toggle_editor()
29
+ def _toggle_remote_store(self, checked=False):
30
+ self.window.controller.remote_store.toggle_editor()
34
31
 
35
32
  def _rebuild_ipython(self, checked=False):
36
33
  self.window.core.plugins.get("cmd_code_interpreter").builder.build_and_restart()
@@ -72,13 +69,9 @@ class Tools:
72
69
 
73
70
  menu_tools.addSeparator()
74
71
  db_icon = QIcon(":/icons/db.svg")
75
- ui_menu['menu.tools.openai.stores'] = QAction(db_icon, trans("dialog.remote_store.openai"), window)
76
- menu_tools.addAction(ui_menu['menu.tools.openai.stores'])
77
- ui_menu['menu.tools.openai.stores'].triggered.connect(self._toggle_remote_store_openai)
78
-
79
- ui_menu['menu.tools.google.stores'] = QAction(db_icon, trans("dialog.remote_store.google"), window)
80
- menu_tools.addAction(ui_menu['menu.tools.google.stores'])
81
- ui_menu['menu.tools.google.stores'].triggered.connect(self._toggle_remote_store_google)
72
+ ui_menu['menu.tools.remote_store'] = QAction(db_icon, trans("dialog.remote_store"), window)
73
+ menu_tools.addAction(ui_menu['menu.tools.remote_store'])
74
+ ui_menu['menu.tools.remote_store'].triggered.connect(self._toggle_remote_store)
82
75
  # ------------------------------------------------- #
83
76
 
84
77
  menu_tools.addSeparator()
@@ -6,11 +6,11 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.12.31 14:00:00 #
9
+ # Updated Date: 2026.01.05 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtWidgets import QApplication
13
- from PySide6.QtCore import QRect, QSize, QPoint, QEvent, Qt
13
+ from PySide6.QtCore import QSize, QPoint, QEvent, Qt
14
14
  from PySide6.QtWidgets import QDialog
15
15
 
16
16
 
@@ -25,11 +25,20 @@ class BaseDialog(QDialog):
25
25
  super(BaseDialog, self).__init__(window)
26
26
  self.window = window
27
27
  self.id = id
28
+ self.shared_id = None
28
29
  self.disable_geometry_store = False
29
30
  self.setWindowFlags(
30
31
  self.windowFlags() | Qt.WindowMaximizeButtonHint
31
32
  )
32
33
 
34
+ def _get_id(self):
35
+ """
36
+ Get dialog id
37
+
38
+ :return: dialog id
39
+ """
40
+ return self.shared_id if self.shared_id is not None else self.id
41
+
33
42
  def showEvent(self, event):
34
43
  """
35
44
  Event called when the dialog is shown
@@ -58,7 +67,7 @@ class BaseDialog(QDialog):
58
67
  if self.disable_geometry_store:
59
68
  return False
60
69
 
61
- if self.window is None or self.id is None:
70
+ if self.window is None or self._get_id() is None:
62
71
  return False
63
72
 
64
73
  config = self.window.core.config
@@ -71,6 +80,7 @@ class BaseDialog(QDialog):
71
80
  def save_geometry(self):
72
81
  """Save dialog geometry"""
73
82
  config = self.window.core.config
83
+ id = self._get_id()
74
84
  item = {
75
85
  "size": [self.size().width(), self.size().height()],
76
86
  "pos": [self.pos().x(), self.pos().y()]
@@ -81,7 +91,7 @@ class BaseDialog(QDialog):
81
91
 
82
92
  if not isinstance(data, dict):
83
93
  data = {}
84
- data[self.id] = item
94
+ data[id] = item
85
95
 
86
96
  if self.store_geometry_enabled():
87
97
  config.set_session("layout.dialog.geometry", data)
@@ -89,6 +99,7 @@ class BaseDialog(QDialog):
89
99
  def restore_geometry(self):
90
100
  """Restore dialog geometry"""
91
101
  # get available screen geometry
102
+ id = self._get_id()
92
103
  screen = QApplication.primaryScreen()
93
104
  available_geometry = screen.availableGeometry()
94
105
  config = self.window.core.config
@@ -97,7 +108,7 @@ class BaseDialog(QDialog):
97
108
  if self.store_geometry_enabled():
98
109
  data = config.get_session("layout.dialog.geometry", {})
99
110
 
100
- item = data.get(self.id, {})
111
+ item = data.get(id, {})
101
112
  if isinstance(item, dict) and "size" in item and "pos" in item:
102
113
  width, height = item["size"]
103
114
  x, y = item["pos"]
@@ -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: 2026.01.02 20:00:00 #
9
+ # Updated Date: 2026.01.05 17:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Qt
@@ -14,15 +14,15 @@ from PySide6.QtCore import Qt
14
14
  from .base import BaseDialog
15
15
 
16
16
 
17
- class RemoteStoreGoogleDialog(BaseDialog):
17
+ class RemoteStoreDialog(BaseDialog):
18
18
  def __init__(self, window=None, id=None):
19
19
  """
20
- Models dialog (Google File Search)
20
+ Remote stores dialog
21
21
 
22
22
  :param window: main window
23
23
  :param id: settings id
24
24
  """
25
- super(RemoteStoreGoogleDialog, self).__init__(window, id)
25
+ super(RemoteStoreDialog, self).__init__(window, id)
26
26
  self.window = window
27
27
  self.id = id
28
28
 
@@ -32,9 +32,9 @@ class RemoteStoreGoogleDialog(BaseDialog):
32
32
 
33
33
  :param event: close event
34
34
  """
35
- self.window.controller.remote_store.google.dialog = False
36
- self.window.controller.remote_store.google.update()
37
- super(RemoteStoreGoogleDialog, self).closeEvent(event)
35
+ self.window.controller.remote_store.dialog = False
36
+ self.window.controller.remote_store.update()
37
+ super(RemoteStoreDialog, self).closeEvent(event)
38
38
 
39
39
  def keyPressEvent(self, event):
40
40
  """
@@ -46,11 +46,11 @@ class RemoteStoreGoogleDialog(BaseDialog):
46
46
  self.cleanup()
47
47
  self.close()
48
48
  else:
49
- super(RemoteStoreGoogleDialog, self).keyPressEvent(event)
49
+ super(RemoteStoreDialog, self).keyPressEvent(event)
50
50
 
51
51
  def cleanup(self):
52
52
  """
53
53
  Cleanup on close
54
54
  """
55
- self.window.controller.remote_store.google.dialog = False
56
- self.window.controller.remote_store.google.update()
55
+ self.window.controller.remote_store.dialog = False
56
+ self.window.controller.remote_store.update()
@@ -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: 2026.01.02 19:00:00 #
9
+ # Updated Date: 2026.01.05 17:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Qt
@@ -87,7 +87,7 @@ class SyncButton(QPushButton):
87
87
  super().__init__(title)
88
88
  self.window = window
89
89
  self.clicked.connect(
90
- lambda: self.window.controller.remote_store.openai.batch.import_files_current()
90
+ lambda: self.window.controller.remote_store.batch.import_files_assistant_current()
91
91
  )
92
92
 
93
93
  @classmethod
@@ -112,11 +112,11 @@ class SyncButton(QPushButton):
112
112
  menu = QMenu(parent)
113
113
  act_current = menu.addAction(type(self)._icon_download, trans('attachments_uploaded.btn.sync.current'))
114
114
  act_current.triggered.connect(
115
- lambda checked=False: self.window.controller.remote_store.openai.batch.import_files_current()
115
+ lambda checked=False: self.window.controller.remote_store.batch.import_files_assistant_current()
116
116
  )
117
117
  act_all = menu.addAction(type(self)._icon_download, trans('attachments_uploaded.btn.sync.all'))
118
118
  act_all.triggered.connect(
119
- lambda checked=False: self.window.controller.remote_store.openai.batch.import_files()
119
+ lambda checked=False: self.window.controller.remote_store.batch.import_files_assistant_all()
120
120
  )
121
121
  menu.exec_(parent.mapToGlobal(pos))
122
122
  menu.deleteLater()
@@ -51,12 +51,12 @@ class ImageLabel(QLabel):
51
51
 
52
52
  actions = {}
53
53
  use_actions = []
54
- actions['open'] = QAction(QIcon(":/icons/fullscreen.svg"), trans('img.action.open'), self)
54
+ actions['open'] = QAction(QIcon(":/icons/fit.svg"), trans('img.action.open'), self)
55
55
  actions['open'].triggered.connect(
56
56
  lambda: self.action_open(event)
57
57
  )
58
58
 
59
- actions['open_dir'] = QAction(QIcon(":/icons/folder_filled.svg"), trans('action.open_dir'), self)
59
+ actions['open_dir'] = QAction(QIcon(":/icons/folder.svg"), trans('action.open_dir'), self)
60
60
  actions['open_dir'].triggered.connect(
61
61
  lambda: self.action_open_dir(event)
62
62
  )
@@ -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: 2025.12.28 00:00:00 #
9
+ # Updated Date: 2026.01.03 17:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import datetime
@@ -44,7 +44,7 @@ class ContextList(BaseList):
44
44
  'pin': QIcon(":/icons/pin3.svg"),
45
45
  'clock': QIcon(":/icons/clock.svg"),
46
46
  'db': QIcon(":/icons/db.svg"),
47
- 'folder': QIcon(":/icons/folder_filled.svg"),
47
+ 'folder': QIcon(":/icons/folder.svg"),
48
48
  'attachment': QIcon(":/icons/attachment.svg"),
49
49
  }
50
50
  self._color_icon_cache = {}
File without changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pygpt-net
3
- Version: 2.7.6
3
+ Version: 2.7.8
4
4
  Summary: Desktop AI Assistant powered by: OpenAI GPT-5, GPT-4, o1, o3, Gemini, Claude, Grok, DeepSeek, and other models supported by Llama Index, and Ollama. Chatbot, agents, completion, image generation, vision analysis, speech-to-text, plugins, MCP, internet access, file handling, command execution and more.
5
5
  License: MIT
6
6
  Keywords: ai,api,api key,app,assistant,bielik,chat,chatbot,chatgpt,claude,dall-e,deepseek,desktop,gemini,gpt,gpt-3.5,gpt-4,gpt-4-vision,gpt-4o,gpt-5,gpt-oss,gpt3.5,gpt4,grok,langchain,llama-index,llama3,mistral,o1,o3,ollama,openai,presets,py-gpt,py_gpt,pygpt,pyside,qt,text completion,tts,ui,vision,whisper
@@ -120,7 +120,7 @@ Description-Content-Type: text/markdown
120
120
 
121
121
  [![pygpt](https://snapcraft.io/pygpt/badge.svg)](https://snapcraft.io/pygpt)
122
122
 
123
- Release: **2.7.6** | build: **2026-01-03** | Python: **>=3.10, <3.14**
123
+ Release: **2.7.8** | build: **2026-01-06** | Python: **>=3.10, <3.14**
124
124
 
125
125
  > Official website: https://pygpt.net | Documentation: https://pygpt.readthedocs.io
126
126
  >
@@ -3796,6 +3796,19 @@ may consume additional tokens that are not displayed in the main window.
3796
3796
 
3797
3797
  ## Recent changes:
3798
3798
 
3799
+ **2.7.8 (2026-01-06)**
3800
+
3801
+ - Added the xAI Collections remote tool and integrated collections management into the Remote Vector Stores tool.
3802
+ - Unified the Remote Vector Stores tool into a single tool for all providers.
3803
+ - Added xAI Grok audio input and output provider (realtime audio support for Grok coming soon!).
3804
+ - Enhanced the Image Viewer tool with a toolbox featuring Prev/Next and more options.
3805
+
3806
+ **2.7.7 (2026-01-05)**
3807
+
3808
+ - Added support for Responses API in xAI.
3809
+ - Added xAI remote tools: Remote MCP, Code Execution.
3810
+ - Added Anthropic remote tools: Remote MCP, Web Fetch, Code Execution.
3811
+
3799
3812
  **2.7.6 (2026-01-03)**
3800
3813
 
3801
3814
  - Fixed compatibility with xAI SDK and resolved empty responses from Grok models.