pygpt-net 2.7.7__py3-none-any.whl → 2.7.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.
Files changed (98) hide show
  1. pygpt_net/CHANGELOG.txt +12 -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/dialogs/confirm.py +35 -58
  9. pygpt_net/controller/lang/mapping.py +9 -9
  10. pygpt_net/controller/realtime/realtime.py +13 -1
  11. pygpt_net/controller/remote_store/{google/batch.py → batch.py} +209 -252
  12. pygpt_net/controller/remote_store/remote_store.py +982 -13
  13. pygpt_net/core/command/command.py +0 -0
  14. pygpt_net/core/db/viewer.py +1 -1
  15. pygpt_net/core/realtime/worker.py +3 -1
  16. pygpt_net/{controller/remote_store/google → core/remote_store/anthropic}/__init__.py +0 -1
  17. pygpt_net/core/remote_store/anthropic/files.py +211 -0
  18. pygpt_net/core/remote_store/anthropic/store.py +208 -0
  19. pygpt_net/core/remote_store/openai/store.py +5 -4
  20. pygpt_net/core/remote_store/remote_store.py +5 -1
  21. pygpt_net/{controller/remote_store/openai → core/remote_store/xai}/__init__.py +0 -1
  22. pygpt_net/core/remote_store/xai/files.py +225 -0
  23. pygpt_net/core/remote_store/xai/store.py +219 -0
  24. pygpt_net/data/config/config.json +10 -6
  25. pygpt_net/data/config/models.json +38 -22
  26. pygpt_net/data/config/settings.json +54 -1
  27. pygpt_net/data/icons/folder_eye.svg +1 -0
  28. pygpt_net/data/icons/folder_eye_filled.svg +1 -0
  29. pygpt_net/data/icons/folder_open.svg +1 -0
  30. pygpt_net/data/icons/folder_open_filled.svg +1 -0
  31. pygpt_net/data/locale/locale.de.ini +4 -3
  32. pygpt_net/data/locale/locale.en.ini +14 -4
  33. pygpt_net/data/locale/locale.es.ini +4 -3
  34. pygpt_net/data/locale/locale.fr.ini +4 -3
  35. pygpt_net/data/locale/locale.it.ini +4 -3
  36. pygpt_net/data/locale/locale.pl.ini +5 -4
  37. pygpt_net/data/locale/locale.uk.ini +4 -3
  38. pygpt_net/data/locale/locale.zh.ini +4 -3
  39. pygpt_net/icons.qrc +4 -0
  40. pygpt_net/icons_rc.py +282 -138
  41. pygpt_net/provider/api/anthropic/__init__.py +2 -0
  42. pygpt_net/provider/api/anthropic/chat.py +84 -1
  43. pygpt_net/provider/api/anthropic/store.py +307 -0
  44. pygpt_net/provider/api/anthropic/stream.py +75 -0
  45. pygpt_net/provider/api/anthropic/worker/__init__.py +0 -0
  46. pygpt_net/provider/api/anthropic/worker/importer.py +278 -0
  47. pygpt_net/provider/api/google/chat.py +59 -2
  48. pygpt_net/provider/api/google/realtime/client.py +70 -24
  49. pygpt_net/provider/api/google/realtime/realtime.py +48 -12
  50. pygpt_net/provider/api/google/store.py +124 -3
  51. pygpt_net/provider/api/google/stream.py +91 -24
  52. pygpt_net/provider/api/google/worker/importer.py +16 -28
  53. pygpt_net/provider/api/openai/assistants.py +2 -2
  54. pygpt_net/provider/api/openai/realtime/realtime.py +26 -6
  55. pygpt_net/provider/api/openai/store.py +4 -1
  56. pygpt_net/provider/api/openai/worker/importer.py +19 -61
  57. pygpt_net/provider/api/openai/worker/importer_assistants.py +230 -0
  58. pygpt_net/provider/api/x_ai/__init__.py +27 -6
  59. pygpt_net/provider/api/x_ai/audio.py +43 -11
  60. pygpt_net/provider/api/x_ai/chat.py +92 -4
  61. pygpt_net/provider/api/x_ai/realtime/__init__.py +12 -0
  62. pygpt_net/provider/api/x_ai/realtime/client.py +1864 -0
  63. pygpt_net/provider/api/x_ai/realtime/realtime.py +213 -0
  64. pygpt_net/provider/api/x_ai/remote_tools.py +102 -1
  65. pygpt_net/provider/api/x_ai/store.py +610 -0
  66. pygpt_net/provider/api/x_ai/stream.py +30 -9
  67. pygpt_net/provider/api/x_ai/tools.py +51 -0
  68. pygpt_net/provider/api/x_ai/worker/importer.py +308 -0
  69. pygpt_net/provider/audio_input/xai_grok_voice.py +390 -0
  70. pygpt_net/provider/audio_output/xai_tts.py +325 -0
  71. pygpt_net/provider/core/config/patch.py +29 -3
  72. pygpt_net/provider/core/config/patches/patch_before_2_6_42.py +2 -2
  73. pygpt_net/provider/core/model/patch.py +49 -1
  74. pygpt_net/tools/image_viewer/tool.py +334 -34
  75. pygpt_net/tools/image_viewer/ui/dialogs.py +317 -21
  76. pygpt_net/ui/dialog/assistant.py +1 -1
  77. pygpt_net/ui/dialog/plugins.py +13 -5
  78. pygpt_net/ui/dialog/remote_store.py +552 -0
  79. pygpt_net/ui/dialogs.py +3 -5
  80. pygpt_net/ui/layout/ctx/ctx_list.py +58 -7
  81. pygpt_net/ui/menu/tools.py +6 -13
  82. pygpt_net/ui/widget/dialog/{remote_store_google.py → remote_store.py} +10 -10
  83. pygpt_net/ui/widget/element/button.py +4 -4
  84. pygpt_net/ui/widget/image/display.py +2 -2
  85. pygpt_net/ui/widget/lists/context.py +2 -2
  86. {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/METADATA +14 -2
  87. {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/RECORD +87 -75
  88. pygpt_net/controller/remote_store/google/store.py +0 -615
  89. pygpt_net/controller/remote_store/openai/batch.py +0 -524
  90. pygpt_net/controller/remote_store/openai/store.py +0 -699
  91. pygpt_net/ui/dialog/remote_store_google.py +0 -539
  92. pygpt_net/ui/dialog/remote_store_openai.py +0 -539
  93. pygpt_net/ui/widget/dialog/remote_store_openai.py +0 -56
  94. pygpt_net/ui/widget/lists/remote_store_google.py +0 -248
  95. pygpt_net/ui/widget/lists/remote_store_openai.py +0 -317
  96. {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/LICENSE +0 -0
  97. {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/WHEEL +0 -0
  98. {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.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,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 = {}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pygpt-net
3
- Version: 2.7.7
3
+ Version: 2.7.9
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.7** | build: **2026-01-05** | Python: **>=3.10, <3.14**
123
+ Release: **2.7.9** | build: **2026-01-08** | Python: **>=3.10, <3.14**
124
124
 
125
125
  > Official website: https://pygpt.net | Documentation: https://pygpt.readthedocs.io
126
126
  >
@@ -3796,6 +3796,18 @@ may consume additional tokens that are not displayed in the main window.
3796
3796
 
3797
3797
  ## Recent changes:
3798
3798
 
3799
+ **2.7.9 (2026-01-08)**
3800
+
3801
+ - Improved realtime audio mode.
3802
+ - Added xAI provider and Grok support in realtime audio mode.
3803
+
3804
+ **2.7.8 (2026-01-06)**
3805
+
3806
+ - Added the xAI Collections remote tool and integrated collections management into the Remote Vector Stores tool.
3807
+ - Unified the Remote Vector Stores tool into a single tool for all providers.
3808
+ - Added xAI Grok audio input and output provider (realtime audio support for Grok coming soon!).
3809
+ - Enhanced the Image Viewer tool with a toolbox featuring Prev/Next and more options.
3810
+
3799
3811
  **2.7.7 (2026-01-05)**
3800
3812
 
3801
3813
  - Added support for Responses API in xAI.