pygpt-net 2.6.20__py3-none-any.whl → 2.6.22__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 (221) hide show
  1. pygpt_net/CHANGELOG.txt +13 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +3 -1
  4. pygpt_net/controller/__init__.py +4 -8
  5. pygpt_net/controller/access/voice.py +2 -2
  6. pygpt_net/controller/agent/agent.py +130 -2
  7. pygpt_net/controller/agent/experts.py +93 -96
  8. pygpt_net/controller/agent/llama.py +2 -1
  9. pygpt_net/controller/assistant/assistant.py +18 -1
  10. pygpt_net/controller/assistant/batch.py +2 -3
  11. pygpt_net/controller/assistant/editor.py +2 -2
  12. pygpt_net/controller/assistant/files.py +2 -3
  13. pygpt_net/controller/assistant/store.py +2 -2
  14. pygpt_net/controller/attachment/attachment.py +17 -1
  15. pygpt_net/controller/audio/audio.py +2 -2
  16. pygpt_net/controller/camera/camera.py +15 -7
  17. pygpt_net/controller/chat/chat.py +2 -2
  18. pygpt_net/controller/chat/common.py +50 -33
  19. pygpt_net/controller/chat/image.py +67 -77
  20. pygpt_net/controller/chat/input.py +94 -166
  21. pygpt_net/controller/chat/output.py +83 -140
  22. pygpt_net/controller/chat/response.py +83 -102
  23. pygpt_net/controller/chat/text.py +116 -149
  24. pygpt_net/controller/ctx/common.py +2 -1
  25. pygpt_net/controller/ctx/ctx.py +87 -6
  26. pygpt_net/controller/files/files.py +13 -1
  27. pygpt_net/controller/idx/idx.py +26 -2
  28. pygpt_net/controller/idx/indexer.py +85 -76
  29. pygpt_net/controller/kernel/reply.py +53 -66
  30. pygpt_net/controller/kernel/stack.py +16 -16
  31. pygpt_net/controller/lang/lang.py +52 -34
  32. pygpt_net/controller/model/importer.py +3 -2
  33. pygpt_net/controller/model/model.py +62 -3
  34. pygpt_net/controller/notepad/notepad.py +86 -84
  35. pygpt_net/controller/plugins/settings.py +3 -4
  36. pygpt_net/controller/settings/editor.py +4 -4
  37. pygpt_net/controller/settings/profile.py +105 -124
  38. pygpt_net/controller/theme/menu.py +154 -57
  39. pygpt_net/controller/theme/nodes.py +51 -44
  40. pygpt_net/controller/theme/theme.py +33 -9
  41. pygpt_net/controller/tools/tools.py +2 -2
  42. pygpt_net/controller/ui/tabs.py +2 -3
  43. pygpt_net/controller/ui/ui.py +16 -2
  44. pygpt_net/core/agents/observer/evaluation.py +3 -3
  45. pygpt_net/core/agents/provider.py +25 -3
  46. pygpt_net/core/agents/runner.py +4 -1
  47. pygpt_net/core/agents/runners/llama_workflow.py +19 -7
  48. pygpt_net/core/agents/runners/loop.py +3 -1
  49. pygpt_net/core/agents/runners/openai_workflow.py +17 -3
  50. pygpt_net/core/agents/tools.py +4 -1
  51. pygpt_net/core/bridge/context.py +34 -37
  52. pygpt_net/core/ctx/container.py +13 -12
  53. pygpt_net/core/ctx/ctx.py +1 -1
  54. pygpt_net/core/ctx/output.py +7 -4
  55. pygpt_net/core/db/database.py +2 -2
  56. pygpt_net/core/debug/console/console.py +2 -2
  57. pygpt_net/core/debug/debug.py +12 -1
  58. pygpt_net/core/dispatcher/dispatcher.py +24 -1
  59. pygpt_net/core/events/app.py +7 -7
  60. pygpt_net/core/events/control.py +26 -26
  61. pygpt_net/core/events/event.py +6 -3
  62. pygpt_net/core/events/kernel.py +2 -2
  63. pygpt_net/core/events/render.py +13 -13
  64. pygpt_net/core/experts/experts.py +76 -82
  65. pygpt_net/core/experts/worker.py +12 -12
  66. pygpt_net/core/filesystem/actions.py +1 -2
  67. pygpt_net/core/models/models.py +5 -1
  68. pygpt_net/core/models/ollama.py +14 -5
  69. pygpt_net/core/render/plain/helpers.py +2 -5
  70. pygpt_net/core/render/plain/renderer.py +26 -30
  71. pygpt_net/core/render/web/body.py +1 -1
  72. pygpt_net/core/render/web/helpers.py +2 -2
  73. pygpt_net/core/render/web/renderer.py +4 -4
  74. pygpt_net/core/settings/settings.py +43 -13
  75. pygpt_net/core/tabs/tabs.py +20 -13
  76. pygpt_net/core/types/__init__.py +2 -1
  77. pygpt_net/core/types/agent.py +4 -4
  78. pygpt_net/core/types/base.py +19 -0
  79. pygpt_net/core/types/console.py +6 -6
  80. pygpt_net/core/types/mode.py +8 -8
  81. pygpt_net/core/types/multimodal.py +3 -3
  82. pygpt_net/core/types/openai.py +2 -1
  83. pygpt_net/data/config/config.json +5 -5
  84. pygpt_net/data/config/models.json +19 -3
  85. pygpt_net/data/config/settings.json +14 -14
  86. pygpt_net/data/locale/locale.de.ini +4 -1
  87. pygpt_net/data/locale/locale.en.ini +6 -3
  88. pygpt_net/data/locale/locale.es.ini +4 -1
  89. pygpt_net/data/locale/locale.fr.ini +4 -1
  90. pygpt_net/data/locale/locale.it.ini +4 -1
  91. pygpt_net/data/locale/locale.pl.ini +5 -4
  92. pygpt_net/data/locale/locale.uk.ini +4 -1
  93. pygpt_net/data/locale/locale.zh.ini +4 -1
  94. pygpt_net/item/ctx.py +256 -240
  95. pygpt_net/item/model.py +59 -116
  96. pygpt_net/item/preset.py +122 -105
  97. pygpt_net/plugin/twitter/plugin.py +2 -2
  98. pygpt_net/provider/agents/llama_index/workflow/planner.py +3 -3
  99. pygpt_net/provider/agents/openai/agent.py +4 -12
  100. pygpt_net/provider/agents/openai/agent_b2b.py +10 -15
  101. pygpt_net/provider/agents/openai/agent_planner.py +4 -4
  102. pygpt_net/provider/agents/openai/agent_with_experts.py +3 -7
  103. pygpt_net/provider/agents/openai/agent_with_experts_feedback.py +4 -8
  104. pygpt_net/provider/agents/openai/agent_with_feedback.py +4 -8
  105. pygpt_net/provider/agents/openai/bot_researcher.py +2 -18
  106. pygpt_net/provider/agents/openai/bots/__init__.py +0 -0
  107. pygpt_net/provider/agents/openai/bots/research_bot/__init__.py +0 -0
  108. pygpt_net/provider/agents/openai/bots/research_bot/agents/__init__.py +0 -0
  109. pygpt_net/provider/agents/openai/bots/research_bot/agents/planner_agent.py +1 -1
  110. pygpt_net/provider/agents/openai/bots/research_bot/agents/search_agent.py +1 -0
  111. pygpt_net/provider/agents/openai/bots/research_bot/agents/writer_agent.py +1 -1
  112. pygpt_net/provider/agents/openai/bots/research_bot/manager.py +1 -10
  113. pygpt_net/provider/agents/openai/evolve.py +5 -9
  114. pygpt_net/provider/agents/openai/supervisor.py +4 -8
  115. pygpt_net/provider/core/config/patch.py +10 -3
  116. pygpt_net/provider/core/ctx/db_sqlite/utils.py +43 -43
  117. pygpt_net/provider/core/model/patch.py +11 -1
  118. pygpt_net/provider/core/preset/json_file.py +47 -49
  119. pygpt_net/provider/gpt/agents/experts.py +2 -2
  120. pygpt_net/tools/audio_transcriber/ui/dialogs.py +44 -54
  121. pygpt_net/tools/code_interpreter/body.py +1 -2
  122. pygpt_net/tools/code_interpreter/tool.py +7 -4
  123. pygpt_net/tools/code_interpreter/ui/html.py +1 -3
  124. pygpt_net/tools/code_interpreter/ui/widgets.py +2 -3
  125. pygpt_net/tools/html_canvas/ui/widgets.py +1 -3
  126. pygpt_net/tools/image_viewer/ui/dialogs.py +40 -37
  127. pygpt_net/tools/indexer/ui/widgets.py +2 -4
  128. pygpt_net/tools/media_player/tool.py +2 -5
  129. pygpt_net/tools/media_player/ui/widgets.py +60 -36
  130. pygpt_net/tools/text_editor/ui/widgets.py +18 -19
  131. pygpt_net/tools/translator/ui/widgets.py +39 -35
  132. pygpt_net/ui/base/context_menu.py +9 -4
  133. pygpt_net/ui/dialog/db.py +1 -3
  134. pygpt_net/ui/dialog/models.py +1 -3
  135. pygpt_net/ui/dialog/models_importer.py +2 -4
  136. pygpt_net/ui/dialogs.py +34 -30
  137. pygpt_net/ui/layout/chat/attachments.py +72 -84
  138. pygpt_net/ui/layout/chat/attachments_ctx.py +40 -44
  139. pygpt_net/ui/layout/chat/attachments_uploaded.py +36 -39
  140. pygpt_net/ui/layout/chat/calendar.py +100 -70
  141. pygpt_net/ui/layout/chat/chat.py +23 -17
  142. pygpt_net/ui/layout/chat/input.py +95 -118
  143. pygpt_net/ui/layout/chat/output.py +100 -162
  144. pygpt_net/ui/layout/chat/painter.py +89 -61
  145. pygpt_net/ui/layout/ctx/ctx_list.py +43 -52
  146. pygpt_net/ui/layout/status.py +23 -14
  147. pygpt_net/ui/layout/toolbox/agent.py +27 -38
  148. pygpt_net/ui/layout/toolbox/agent_llama.py +42 -45
  149. pygpt_net/ui/layout/toolbox/assistants.py +42 -38
  150. pygpt_net/ui/layout/toolbox/computer_env.py +32 -23
  151. pygpt_net/ui/layout/toolbox/footer.py +13 -16
  152. pygpt_net/ui/layout/toolbox/image.py +18 -21
  153. pygpt_net/ui/layout/toolbox/indexes.py +46 -89
  154. pygpt_net/ui/layout/toolbox/mode.py +20 -7
  155. pygpt_net/ui/layout/toolbox/model.py +12 -10
  156. pygpt_net/ui/layout/toolbox/presets.py +68 -52
  157. pygpt_net/ui/layout/toolbox/prompt.py +31 -58
  158. pygpt_net/ui/layout/toolbox/toolbox.py +25 -21
  159. pygpt_net/ui/layout/toolbox/vision.py +20 -22
  160. pygpt_net/ui/main.py +2 -4
  161. pygpt_net/ui/menu/about.py +64 -84
  162. pygpt_net/ui/menu/audio.py +87 -63
  163. pygpt_net/ui/menu/config.py +121 -127
  164. pygpt_net/ui/menu/debug.py +69 -76
  165. pygpt_net/ui/menu/file.py +32 -35
  166. pygpt_net/ui/menu/menu.py +2 -3
  167. pygpt_net/ui/menu/plugins.py +69 -33
  168. pygpt_net/ui/menu/theme.py +45 -46
  169. pygpt_net/ui/menu/tools.py +56 -60
  170. pygpt_net/ui/menu/video.py +20 -25
  171. pygpt_net/ui/tray.py +1 -2
  172. pygpt_net/ui/widget/audio/bar.py +1 -3
  173. pygpt_net/ui/widget/audio/input_button.py +3 -4
  174. pygpt_net/ui/widget/calendar/select.py +1 -2
  175. pygpt_net/ui/widget/dialog/base.py +12 -9
  176. pygpt_net/ui/widget/dialog/editor_file.py +20 -23
  177. pygpt_net/ui/widget/dialog/find.py +25 -24
  178. pygpt_net/ui/widget/dialog/profile.py +57 -53
  179. pygpt_net/ui/widget/draw/painter.py +62 -93
  180. pygpt_net/ui/widget/element/button.py +42 -30
  181. pygpt_net/ui/widget/element/checkbox.py +23 -15
  182. pygpt_net/ui/widget/element/group.py +6 -5
  183. pygpt_net/ui/widget/element/labels.py +1 -2
  184. pygpt_net/ui/widget/filesystem/explorer.py +93 -102
  185. pygpt_net/ui/widget/image/display.py +1 -2
  186. pygpt_net/ui/widget/lists/assistant.py +1 -2
  187. pygpt_net/ui/widget/lists/attachment.py +1 -2
  188. pygpt_net/ui/widget/lists/attachment_ctx.py +1 -2
  189. pygpt_net/ui/widget/lists/context.py +2 -4
  190. pygpt_net/ui/widget/lists/index.py +1 -2
  191. pygpt_net/ui/widget/lists/model.py +1 -2
  192. pygpt_net/ui/widget/lists/model_editor.py +1 -2
  193. pygpt_net/ui/widget/lists/model_importer.py +1 -2
  194. pygpt_net/ui/widget/lists/preset.py +1 -2
  195. pygpt_net/ui/widget/lists/preset_plugins.py +1 -2
  196. pygpt_net/ui/widget/lists/profile.py +1 -2
  197. pygpt_net/ui/widget/lists/uploaded.py +1 -2
  198. pygpt_net/ui/widget/option/checkbox.py +2 -4
  199. pygpt_net/ui/widget/option/checkbox_list.py +1 -4
  200. pygpt_net/ui/widget/option/cmd.py +1 -4
  201. pygpt_net/ui/widget/option/dictionary.py +25 -28
  202. pygpt_net/ui/widget/option/input.py +1 -3
  203. pygpt_net/ui/widget/tabs/Input.py +16 -12
  204. pygpt_net/ui/widget/tabs/body.py +5 -3
  205. pygpt_net/ui/widget/tabs/layout.py +36 -25
  206. pygpt_net/ui/widget/tabs/output.py +96 -74
  207. pygpt_net/ui/widget/textarea/calendar_note.py +1 -2
  208. pygpt_net/ui/widget/textarea/editor.py +41 -73
  209. pygpt_net/ui/widget/textarea/find.py +11 -10
  210. pygpt_net/ui/widget/textarea/html.py +3 -6
  211. pygpt_net/ui/widget/textarea/input.py +63 -64
  212. pygpt_net/ui/widget/textarea/notepad.py +54 -38
  213. pygpt_net/ui/widget/textarea/output.py +65 -54
  214. pygpt_net/ui/widget/textarea/search_input.py +5 -4
  215. pygpt_net/ui/widget/textarea/web.py +2 -4
  216. pygpt_net/ui/widget/vision/camera.py +2 -31
  217. {pygpt_net-2.6.20.dist-info → pygpt_net-2.6.22.dist-info}/METADATA +25 -154
  218. {pygpt_net-2.6.20.dist-info → pygpt_net-2.6.22.dist-info}/RECORD +218 -217
  219. {pygpt_net-2.6.20.dist-info → pygpt_net-2.6.22.dist-info}/LICENSE +0 -0
  220. {pygpt_net-2.6.20.dist-info → pygpt_net-2.6.22.dist-info}/WHEEL +0 -0
  221. {pygpt_net-2.6.20.dist-info → pygpt_net-2.6.22.dist-info}/entry_points.txt +0 -0
pygpt_net/CHANGELOG.txt CHANGED
@@ -1,3 +1,16 @@
1
+ 2.6.22 (2025-08-25)
2
+
3
+ - UI refactor and optimizations.
4
+
5
+ 2.6.21 (2025-08-24)
6
+
7
+ - Ollama models are now available in OpenAI Agents mode.
8
+ - Improved parsing of responses from Agents.
9
+ - Fix: do not initialize index in Agents mode if not provided.
10
+ - Fix: agent response evaluation steps limit.
11
+ - Fix: do not execute code in agents if Tools are disabled.
12
+ - Refactoring.
13
+
1
14
  2.6.20 (2025-08-22)
2
15
 
3
16
  - Added a new plugin: Server (FTP/SSH) - connect to remote servers using FTP, SFTP, and SSH. Execute remote commands, upload, download, and more (beta).
pygpt_net/__init__.py CHANGED
@@ -6,15 +6,15 @@
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.08.22 00:00:00 #
9
+ # Updated Date: 2025.08.25 00:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  __author__ = "Marcin Szczygliński"
13
13
  __copyright__ = "Copyright 2025, Marcin Szczygliński"
14
14
  __credits__ = ["Marcin Szczygliński"]
15
15
  __license__ = "MIT"
16
- __version__ = "2.6.20"
17
- __build__ = "2025-08-22"
16
+ __version__ = "2.6.22"
17
+ __build__ = "2025-08-25"
18
18
  __maintainer__ = "Marcin Szczygliński"
19
19
  __github__ = "https://github.com/szczyglis-dev/py-gpt"
20
20
  __report__ = "https://github.com/szczyglis-dev/py-gpt/issues"
pygpt_net/app.py CHANGED
@@ -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.08.22 10:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -14,6 +14,8 @@ import builtins
14
14
  import io
15
15
  import platform
16
16
 
17
+ import pygpt_net.icons_rc
18
+
17
19
  # disable warnings
18
20
  os.environ["TRANSFORMERS_NO_ADVISORY_WARNINGS"] = "1"
19
21
  os.environ["QT_LOGGING_RULES"] = "qt.multimedia.ffmpeg=false;qt.qpa.fonts=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: 2025.08.20 23:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.controller.access import Access
@@ -39,7 +39,7 @@ from pygpt_net.controller.settings import Settings
39
39
  from pygpt_net.controller.theme import Theme
40
40
  from pygpt_net.controller.tools import Tools
41
41
  from pygpt_net.controller.ui import UI
42
- from pygpt_net.utils import mem_clean
42
+ from pygpt_net.utils import trans
43
43
 
44
44
 
45
45
  class Controller:
@@ -109,8 +109,6 @@ class Controller:
109
109
  self.camera.setup_ui()
110
110
  self.access.setup()
111
111
 
112
-
113
-
114
112
  def post_setup(self):
115
113
  """Post-setup, after plugins are loaded"""
116
114
  self.settings.setup()
@@ -147,9 +145,7 @@ class Controller:
147
145
  """Reload components"""
148
146
  self.reloading = True # lock
149
147
 
150
- print("Reloading components... please wait...")
151
-
152
- mem_clean() # try to clean memory
148
+ print(trans("status.reloading.profile.begin"))
153
149
 
154
150
  prev_theme = self.window.core.config.get("theme")
155
151
 
@@ -183,4 +179,4 @@ class Controller:
183
179
 
184
180
  self.reloading = False # unlock
185
181
 
186
- print("[OK] Components reloaded successfully.")
182
+ print(trans("status.reloading.profile.end"))
@@ -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.08.07 22:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Optional, List, Dict, Any
@@ -14,7 +14,7 @@ from typing import Optional, List, Dict, Any
14
14
  import os
15
15
 
16
16
  from PySide6.QtCore import QTimer, Slot, QObject
17
- from qasync import QApplication
17
+ from PySide6.QtWidgets import QApplication
18
18
 
19
19
  from pygpt_net.item.ctx import CtxItem
20
20
  from pygpt_net.plugin.audio_input.worker import ControlWorker
@@ -6,9 +6,18 @@
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.08.03 14:00:00 #
9
+ # Updated Date: 2025.08.23 15:00:00 #
10
10
  # ================================================== #
11
11
 
12
+ from pygpt_net.core.events import BaseEvent, Event
13
+ from pygpt_net.core.types import (
14
+ MODE_AGENT,
15
+ MODE_AGENT_LLAMA,
16
+ MODE_AGENT_OPENAI,
17
+ )
18
+ from pygpt_net.item.ctx import CtxItem
19
+ from pygpt_net.utils import trans
20
+
12
21
  from .common import Common
13
22
  from .experts import Experts
14
23
  from .legacy import Legacy
@@ -28,7 +37,7 @@ class Agent:
28
37
  self.legacy = Legacy(window)
29
38
 
30
39
  def setup(self):
31
- """Setup agent controller"""
40
+ """Setup agents"""
32
41
  self.legacy.setup()
33
42
  self.llama.setup()
34
43
 
@@ -41,3 +50,122 @@ class Agent:
41
50
  """Force stop all agents"""
42
51
  self.legacy.on_stop()
43
52
  self.llama.on_stop()
53
+
54
+ def handle(self, event: BaseEvent):
55
+ """
56
+ Handle events
57
+
58
+ :param event: BaseEvent: Event to handle
59
+ """
60
+ name = event.name
61
+
62
+ # on input begin, unlock experts and reset evaluation steps
63
+ if name == Event.INPUT_BEGIN:
64
+ mode = event.data.get("mode", "")
65
+ force = event.data.get("force", False)
66
+ self.experts.unlock() # unlock experts
67
+ self.llama.reset_eval_step() # reset evaluation steps
68
+
69
+ if not force:
70
+ # if agent mode: iterations check, show alert confirm if infinity loop
71
+ if self.common.is_infinity_loop(mode):
72
+ event.data["stop"] = True # stop flow
73
+ self.common.display_infinity_loop_confirm()
74
+ return
75
+
76
+ # check if agent is selected
77
+ if mode in (MODE_AGENT_OPENAI, MODE_AGENT_LLAMA):
78
+ preset = self.window.controller.presets.get_current()
79
+ if not preset or preset.name == "*":
80
+ event.data["stop"] = True # stop flow
81
+ self.window.ui.dialogs.alert(
82
+ trans("dialog.agent.not_selected"))
83
+ return
84
+
85
+ # on user send, start agent flow
86
+ elif name == Event.USER_SEND:
87
+ mode = event.data.get("mode", "")
88
+ text = event.data.get("value", "")
89
+ if mode == MODE_AGENT:
90
+ self.legacy.on_user_send(text) # begin Legacy (autonomous) agent flow
91
+ elif mode in (
92
+ MODE_AGENT_LLAMA,
93
+ MODE_AGENT_OPENAI,
94
+ ):
95
+ self.llama.on_user_send(text) # begin LlamaIndex adn OpenAI agent flow
96
+
97
+ # on input before, process text before sending input
98
+ elif name == Event.INPUT_BEFORE:
99
+ mode = event.data.get("mode", "")
100
+ if mode == MODE_AGENT:
101
+ text = event.data.get("value", "")
102
+ self.window.controller.chat.log(f"Agent: input before: {text}")
103
+ event.data["value"] = self.legacy.on_input_before(text)
104
+
105
+ # on pre-prompt
106
+ elif name == Event.PRE_PROMPT:
107
+ mode = event.data.get("mode", "")
108
+ sys_prompt = event.data.get("value", "")
109
+ is_expert = event.data.get("is_expert", False)
110
+ if is_expert:
111
+ return # abort if expert call
112
+ event.data["value"] = self.experts.append_prompts(
113
+ mode,
114
+ sys_prompt,
115
+ )
116
+ # on ctx after
117
+ elif name == Event.CTX_BEFORE:
118
+ mode = event.data.get("mode", "")
119
+ if mode == MODE_AGENT:
120
+ self.legacy.on_ctx_before(event.ctx)
121
+
122
+ # on bridge before, prepare bridge context
123
+ elif name == Event.BRIDGE_BEFORE:
124
+ mode = event.data.get("mode", "")
125
+ bridge_context = event.data.get("context", None)
126
+ extra = event.data.get("extra", {})
127
+ if mode in (MODE_AGENT_LLAMA, MODE_AGENT_OPENAI):
128
+
129
+ # agent provider
130
+ agent_provider = None # agent provider (llama or openai)
131
+ if mode == MODE_AGENT_LLAMA:
132
+ agent_provider = self.window.core.config.get("agent.llama.provider")
133
+ elif mode == MODE_AGENT_OPENAI:
134
+ agent_provider =self.window.core.config.get("agent.openai.provider")
135
+ agent_idx = self.window.core.config.get("agent.llama.idx")
136
+
137
+ extra["agent_idx"] = agent_idx
138
+ extra["agent_provider"] = agent_provider
139
+
140
+ # update assistant ID if assistant agent
141
+ if mode == MODE_AGENT_LLAMA:
142
+ preset = self.window.controller.presets.get_current()
143
+ if preset is not None:
144
+ bridge_context.assistant_id = preset.assistant_id
145
+
146
+ # on ctx after
147
+ elif name == Event.CTX_AFTER:
148
+ mode = event.data.get("mode", "")
149
+ if mode == MODE_AGENT:
150
+ self.legacy.on_ctx_after(event.ctx)
151
+
152
+ # on ctx end
153
+ elif name == Event.CTX_END:
154
+ mode = event.data.get("mode", "")
155
+ if mode == MODE_AGENT:
156
+ iterations = int(self.window.core.config.get("agent.iterations"))
157
+ self.window.controller.chat.log(f"Agent: ctx end, iterations: {iterations}")
158
+ self.legacy.on_ctx_end(
159
+ event.ctx,
160
+ iterations=iterations,
161
+ )
162
+
163
+ def on_reply(self, ctx: CtxItem):
164
+ """
165
+ On reply event
166
+
167
+ :param ctx: CtxItem: Context item to handle reply for
168
+ """
169
+ if ctx.internal and self.legacy.enabled():
170
+ self.legacy.add_run()
171
+ self.legacy.update()
@@ -6,10 +6,10 @@
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.07.25 22:00:00 #
9
+ # Updated Date: 2025.08.23 15:00:00 #
10
10
  # ================================================== #
11
11
 
12
- from typing import Optional, Any
12
+ from typing import Any
13
13
 
14
14
  from pygpt_net.core.types import (
15
15
  MODE_AGENT,
@@ -31,79 +31,42 @@ class Experts:
31
31
  self.window = window
32
32
  self.is_stop = False
33
33
 
34
- def stop(self):
35
- """
36
- Stop experts
37
- """
38
- self.is_stop = True
39
-
40
- def stopped(self) -> bool:
41
- """
42
- Check if experts are stopped
43
-
44
- :return: True if experts are stopped
45
- """
46
- return self.is_stop
47
-
48
- def unlock(self):
49
- """Unlock experts"""
50
- self.is_stop = False
51
-
52
- def enabled(self, check_inline = True) -> bool:
53
- """
54
- Check if experts are enabled
55
-
56
- :param check_inline: check inline mode
57
- :return: True if experts are enabled
58
- """
59
- modes = [MODE_EXPERT]
60
- mode = self.window.core.config.get('mode')
61
- if not check_inline:
62
- if mode in modes:
63
- return True
64
- else:
65
- return False
66
- else:
67
- if mode in modes or self.window.controller.plugins.is_type_enabled("expert"):
68
- return True
69
- else:
70
- return False
71
-
72
34
  def append_prompts(
73
35
  self,
74
36
  mode: str,
75
37
  sys_prompt: str,
76
- parent_id: Optional[str] = None
77
- ):
38
+ ) -> str:
78
39
  """
79
40
  Append prompt to the window
80
41
 
81
42
  :param mode: Mode
82
43
  :param sys_prompt: Prompt text
83
- :param parent_id: Parent ID
44
+ :return: Updated system prompt
84
45
  """
46
+ core = self.window.core
47
+ controller = self.window.controller
48
+
85
49
  # if agent enabled
86
- if self.window.controller.agent.legacy.enabled():
50
+ if controller.agent.legacy.enabled():
87
51
  prev_prompt = sys_prompt
88
- sys_prompt = self.window.core.prompt.get("agent.instruction")
52
+ sys_prompt = core.prompt.get("agent.instruction")
89
53
  if prev_prompt is not None and prev_prompt.strip() != "":
90
54
  sys_prompt = sys_prompt + "\n\n" + prev_prompt # append previous prompt
91
55
 
92
- # expert or agent mode
93
- if ((self.enabled() or self.window.controller.agent.legacy.enabled(check_inline=False))
94
- and parent_id is None): # master expert has special prompt
95
- if self.window.controller.agent.legacy.enabled(): # if agent then leave agent prompt
96
- sys_prompt += "\n\n" + self.window.core.experts.get_prompt() # both, agent + experts
56
+ # if expert or agent mode
57
+ if self.enabled() or controller.agent.legacy.enabled(check_inline=False): # master expert has special prompt
58
+ if controller.agent.legacy.enabled(): # if agent then leave agent prompt
59
+ sys_prompt += "\n\n" + core.experts.get_prompt() # both, agent + experts
97
60
  else:
98
- sys_prompt = self.window.core.experts.get_prompt()
61
+ sys_prompt = core.experts.get_prompt()
99
62
  # mode = "chat" # change mode to chat for expert
100
63
 
101
64
  # if global mode is agent
102
65
  if mode == MODE_AGENT:
103
- sys_prompt = self.window.controller.agent.legacy.on_system_prompt(
66
+ sys_prompt = controller.agent.legacy.on_system_prompt(
104
67
  sys_prompt,
105
68
  append_prompt=None, # sys prompt from preset is used here
106
- auto_stop=self.window.core.config.get('agent.auto_stop'),
69
+ auto_stop=core.config.get('agent.auto_stop'),
107
70
  )
108
71
 
109
72
  return sys_prompt
@@ -113,60 +76,94 @@ class Experts:
113
76
  Handle mentions (calls) to experts
114
77
 
115
78
  :param ctx: CtxItem
79
+ :return: Number of calls made to experts
116
80
  """
117
- stream_mode = self.window.core.config.get('stream')
81
+ core = self.window.core
82
+ controller = self.window.controller
83
+ dispatch = self.window.dispatch
84
+ log = self.log
85
+ stream = core.config.get('stream')
118
86
  num_calls = 0
119
87
 
120
88
  # extract expert mentions
121
- if self.enabled() or self.window.controller.agent.legacy.enabled(check_inline=False):
89
+ if self.enabled() or controller.agent.legacy.enabled(check_inline=False):
122
90
  # re-send to master
123
91
  if ctx.sub_reply:
124
- self.window.core.ctx.update_item(ctx)
125
- self.window.core.experts.reply(ctx)
92
+ core.ctx.update_item(ctx)
93
+ core.experts.reply(ctx)
126
94
  else:
95
+ # abort if reply
96
+ if ctx.reply:
97
+ return num_calls
98
+
127
99
  # call experts
128
- if not ctx.reply:
129
- mentions = self.window.core.experts.extract_calls(ctx)
130
- if mentions:
131
- num_calls = 0
132
- self.log("Calling experts...")
133
- data = {
134
- "meta": ctx.meta,
135
- "ctx": ctx,
136
- "stream": stream_mode,
137
- }
138
- event = RenderEvent(RenderEvent.END, data)
139
- self.window.dispatch(event) # close previous render
140
- for expert_id in mentions:
141
- if not self.window.core.experts.exists(expert_id):
142
- self.log("Expert not found: " + expert_id)
143
- continue
144
- self.log("Calling: " + expert_id)
145
- ctx.sub_calls += 1
146
-
147
- # add to reply stack
148
- reply = ReplyContext()
149
- reply.type = ReplyContext.EXPERT_CALL
150
- reply.ctx = ctx
151
- reply.parent_id = expert_id
152
- reply.input = mentions[expert_id]
153
-
154
- # send to kernel
155
- context = BridgeContext()
156
- context.ctx = ctx
157
- context.reply_context = reply
158
- event = KernelEvent(KernelEvent.AGENT_CALL, {
159
- 'context': context,
160
- 'extra': {},
161
- })
162
- self.window.dispatch(event)
163
-
164
- num_calls += 1
165
- if num_calls > 0:
166
- return num_calls # abort continue if expert call detected
100
+ mentions = core.experts.extract_calls(ctx)
101
+
102
+ if mentions:
103
+ log("Calling experts...")
104
+ dispatch(RenderEvent(RenderEvent.END, {
105
+ "meta": ctx.meta,
106
+ "ctx": ctx,
107
+ "stream": stream,
108
+ })) # close previous render
109
+
110
+ for expert_id in mentions:
111
+ if not core.experts.exists(expert_id):
112
+ log(f"Expert not found: {expert_id}")
113
+ continue
114
+
115
+ log(f"Calling: {expert_id}")
116
+ ctx.sub_calls += 1
117
+
118
+ # add to reply stack
119
+ reply = ReplyContext()
120
+ reply.type = ReplyContext.EXPERT_CALL
121
+ reply.ctx = ctx
122
+ reply.parent_id = expert_id
123
+ reply.input = mentions[expert_id]
124
+
125
+ # send to kernel
126
+ context = BridgeContext()
127
+ context.ctx = ctx
128
+ context.reply_context = reply
129
+ dispatch(KernelEvent(KernelEvent.AGENT_CALL, {
130
+ 'context': context,
131
+ 'extra': {},
132
+ }))
133
+ num_calls += 1
167
134
 
168
135
  return num_calls
169
136
 
137
+ def enabled(self, check_inline: bool = True) -> bool:
138
+ """
139
+ Check if experts are enabled
140
+
141
+ :param check_inline: check inline mode
142
+ :return: True if experts are enabled
143
+ """
144
+ modes = [MODE_EXPERT]
145
+ mode = self.window.core.config.get('mode')
146
+ if not check_inline:
147
+ return mode in modes
148
+ else:
149
+ return mode in modes or self.window.controller.plugins.is_type_enabled("expert")
150
+
151
+ def stopped(self) -> bool:
152
+ """
153
+ Check if experts are stopped
154
+
155
+ :return: True if experts are stopped
156
+ """
157
+ return self.is_stop
158
+
159
+ def stop(self):
160
+ """Stop experts"""
161
+ self.is_stop = True
162
+
163
+ def unlock(self):
164
+ """Unlock experts"""
165
+ self.is_stop = False
166
+
170
167
  def log(self, data: Any):
171
168
  """
172
169
  Log data to debug
@@ -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.08.01 03:00:00 #
9
+ # Updated Date: 2025.08.24 02:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Any
@@ -136,6 +136,7 @@ class Llama:
136
136
  # check max steps
137
137
  max_steps = int(self.window.core.config.get("agent.llama.max_eval"))
138
138
  if max_steps != 0 and self.get_eval_step() >= max_steps:
139
+ self.window.update_status(f"Stopped. Limit of max steps: {max_steps}") # show info
139
140
  self.on_end()
140
141
  return # abort if max steps reached
141
142
 
@@ -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.08.03 14:00:00 #
9
+ # Updated Date: 2025.08.23 15:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Optional
@@ -56,6 +56,23 @@ class Assistant:
56
56
  self.files.update_list()
57
57
  self.select_current()
58
58
 
59
+ def check(self) -> bool:
60
+ """
61
+ Check if assistants are loaded
62
+
63
+ :return: True if assistants are loaded
64
+ """
65
+ # check if assistant is selected
66
+ if self.window.core.config.get('assistant') is None \
67
+ or self.window.core.config.get('assistant') == "":
68
+ self.window.ui.dialogs.alert(trans('error.assistant_not_selected'))
69
+ return False
70
+ return True
71
+
72
+ def resume(self):
73
+ """Reset assistants state"""
74
+ self.threads.stop = False
75
+
59
76
  def update_list(self):
60
77
  """Update assistants list"""
61
78
  items = self.window.core.assistants.get_all()
@@ -6,13 +6,12 @@
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.08.03 14:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Optional, Any
13
13
 
14
- from qasync import QApplication
15
- from PySide6.QtWidgets import QFileDialog
14
+ from PySide6.QtWidgets import QFileDialog, QApplication
16
15
 
17
16
  from pygpt_net.utils import trans
18
17
 
@@ -6,13 +6,13 @@
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.08.03 14:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import copy
13
13
  from typing import Optional
14
14
 
15
- from qasync import QApplication
15
+ from PySide6.QtWidgets import QApplication
16
16
 
17
17
  from pygpt_net.core.types import MODEL_DEFAULT
18
18
  from pygpt_net.item.assistant import AssistantItem
@@ -6,17 +6,16 @@
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.08.03 14:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
13
13
  from typing import Optional, Dict, List
14
14
 
15
- from qasync import QApplication
15
+ from PySide6.QtWidgets import QApplication
16
16
 
17
17
  from pygpt_net.item.assistant import AssistantItem
18
18
  from pygpt_net.item.attachment import AttachmentItem
19
- from pygpt_net.item.ctx import CtxItem
20
19
  from pygpt_net.utils import trans
21
20
 
22
21
 
@@ -6,14 +6,14 @@
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.08.03 14:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import copy
13
13
  import json
14
14
  from typing import Optional
15
15
 
16
- from qasync import QApplication
16
+ from PySide6.QtWidgets import QApplication
17
17
 
18
18
  from pygpt_net.item.assistant import AssistantStoreItem
19
19
  from pygpt_net.utils import trans
@@ -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.16 01:00:00 #
9
+ # Updated Date: 2025.08.23 15:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -79,6 +79,22 @@ class Attachment:
79
79
  # update tokens counter (vision plugin, etc.)
80
80
  self.window.controller.ui.update_tokens()
81
81
 
82
+ def cleanup(self, ctx: CtxItem) -> bool:
83
+ """
84
+ Clear attachments list on ctx end
85
+
86
+ :param ctx: CtxItem
87
+ :return: True if cleared
88
+ """
89
+ auto_clear = self.window.core.config.get('attachments_send_clear')
90
+ if self.clear_allowed(ctx):
91
+ if auto_clear and not self.is_locked():
92
+ self.clear(force=True, auto=True)
93
+ self.update()
94
+ self.window.controller.chat.log("Attachments cleared.") # log
95
+ return True
96
+ return False
97
+
82
98
  def update_tab(self, mode: str):
83
99
  """
84
100
  Update tab label