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
@@ -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.16 00:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6 import QtCore
@@ -20,7 +20,6 @@ from pygpt_net.ui.widget.element.button import NewCtxButton
20
20
  from pygpt_net.ui.widget.element.labels import TitleLabel
21
21
  from pygpt_net.ui.widget.lists.context import ContextList, Item, GroupItem, SectionItem
22
22
  from pygpt_net.utils import trans
23
- import pygpt_net.icons_rc
24
23
 
25
24
 
26
25
  class CtxList:
@@ -32,6 +31,8 @@ class CtxList:
32
31
  """
33
32
  self.window = window
34
33
  self.search_input = SearchInput(window)
34
+ self._group_separators = False
35
+ self._pinned_separators = False
35
36
 
36
37
  def setup(self) -> QWidget:
37
38
  """
@@ -39,28 +40,40 @@ class CtxList:
39
40
 
40
41
  :return: QWidget
41
42
  """
42
- id = 'ctx.list'
43
- self.window.ui.nodes['ctx.new'] = NewCtxButton(trans('ctx.new'), self.window)
44
- self.window.ui.nodes[id] = ContextList(self.window, id)
45
- self.window.ui.nodes[id].selection_locked = self.window.controller.ctx.context_change_locked
46
- self.window.ui.nodes['ctx.label'] = TitleLabel(trans("ctx.list.label"))
47
- self.window.ui.nodes['ctx.new'].setContentsMargins(0,0,0,0)
43
+ ctx_id = 'ctx.list'
44
+ ui = self.window.ui
45
+ nodes = ui.nodes
46
+ models = ui.models
47
+
48
+ widget = QWidget()
49
+ widget.setContentsMargins(0, 0, 0, 0)
50
+
51
+ new_btn = NewCtxButton(trans('ctx.new'), self.window)
52
+ new_btn.setContentsMargins(0, 0, 0, 0)
53
+ nodes['ctx.new'] = new_btn
54
+
55
+ ctx_list = ContextList(self.window, ctx_id)
56
+ ctx_list.selection_locked = self.window.controller.ctx.context_change_locked
57
+ nodes[ctx_id] = ctx_list
58
+
59
+ nodes['ctx.label'] = TitleLabel(trans("ctx.list.label"))
48
60
  search_input = self.search_input.setup()
49
61
 
50
- layout = QVBoxLayout()
51
- layout.addWidget(self.window.ui.nodes['ctx.new'])
52
- layout.addWidget(search_input)
53
- layout.addWidget(self.window.ui.nodes[id])
62
+ layout = QVBoxLayout(widget)
54
63
  layout.setContentsMargins(0, 0, 0, 0)
64
+ layout.addWidget(new_btn)
65
+ layout.addWidget(search_input)
66
+ layout.addWidget(ctx_list)
55
67
 
56
- self.window.ui.models[id] = self.create_model(self.window)
57
- self.window.ui.nodes[id].setModel(self.window.ui.models[id])
58
- self.window.ui.nodes[id].selectionModel().selectionChanged.connect(
59
- lambda: self.window.controller.ctx.selection_change()
60
- )
61
- widget = QWidget()
62
- widget.setLayout(layout)
63
- widget.setContentsMargins(0, 0, 0, 0)
68
+ model = self.create_model(self.window)
69
+ models[ctx_id] = model
70
+ ctx_list.setModel(model)
71
+
72
+ ctx = self.window.controller.ctx
73
+ ctx_list.selectionModel().selectionChanged.connect(lambda *_: ctx.selection_change())
74
+
75
+ self._group_separators = self.window.core.config.get("ctx.records.groups.separators")
76
+ self._pinned_separators = self.window.core.config.get("ctx.records.pinned.separators")
64
77
 
65
78
  return widget
66
79
 
@@ -84,6 +97,9 @@ class CtxList:
84
97
  node = self.window.ui.nodes[id]
85
98
  node.backup_selection()
86
99
 
100
+ self._group_separators = self.window.core.config.get("ctx.records.groups.separators")
101
+ self._pinned_separators = self.window.core.config.get("ctx.records.pinned.separators")
102
+
87
103
  model = self.window.ui.models.get(id)
88
104
  if model is not None:
89
105
  node.setUpdatesEnabled(False)
@@ -109,16 +125,12 @@ class CtxList:
109
125
  """
110
126
  i = 0
111
127
  last_dt_str = None
112
- config = self.window.core.config
113
- separators = config.get("ctx.records.separators")
114
- pinned_separators = config.get("ctx.records.pinned.separators")
115
128
  model = self.window.ui.models[id]
116
-
117
129
  for meta_id, meta in data.items():
118
130
  gid = meta.group_id
119
131
  if (gid is None or gid == 0) and not meta.important:
120
132
  item = self.build_item(meta_id, meta, is_group=False)
121
- if separators and (not item.isPinned or pinned_separators):
133
+ if self._group_separators and (not item.isPinned or self._pinned_separators):
122
134
  if i == 0 or last_dt_str != item.dt:
123
135
  section = self.build_date_section(item.dt, group=False)
124
136
  if section:
@@ -137,15 +149,12 @@ class CtxList:
137
149
  i = 0
138
150
  last_dt_str = None
139
151
  model = self.window.ui.models[id]
140
- config = self.window.core.config
141
- separators = config.get("ctx.records.separators")
142
- pinned_separators = config.get("ctx.records.pinned.separators")
143
152
 
144
153
  for meta_id, meta in data.items():
145
154
  gid = meta.group_id
146
155
  if (gid is None or gid == 0) and meta.important:
147
156
  item = self.build_item(meta_id, meta, is_group=False)
148
- if separators and pinned_separators:
157
+ if self._group_separators and self._pinned_separators:
149
158
  if i == 0 or last_dt_str != item.dt:
150
159
  section = self.build_date_section(item.dt, group=False)
151
160
  if section:
@@ -165,10 +174,6 @@ class CtxList:
165
174
  model = self.window.ui.models[id]
166
175
  groups = self.window.core.ctx.get_groups()
167
176
  search_string = self.window.core.ctx.get_search_string()
168
- config = self.window.core.config
169
- is_group_separators = config.get("ctx.records.groups.separators")
170
- is_pinned_separators = config.get("ctx.records.pinned.separators")
171
-
172
177
  grouped = {}
173
178
  for meta_id, meta in data.items():
174
179
  gid = meta.group_id
@@ -213,7 +218,7 @@ class CtxList:
213
218
  i = 0
214
219
  for meta_id, meta in items_in_group:
215
220
  item = self.build_item(meta_id, meta, is_group=True)
216
- if is_group_separators and (not item.isPinned or is_pinned_separators):
221
+ if self._group_separators and (not item.isPinned or self._pinned_separators):
217
222
  if i == 0 or last_dt_str != item.dt:
218
223
  section = self.build_date_section(item.dt, group=True)
219
224
  if section:
@@ -259,13 +264,7 @@ class CtxList:
259
264
  is_important = data.important
260
265
  is_attachment = data.has_additional_ctx()
261
266
  in_group = bool(data.group)
262
-
263
- if is_group:
264
- if self.window.core.config.get("ctx.records.groups.separators"):
265
- append_dt = False
266
- else:
267
- if self.window.core.config.get("ctx.records.separators"):
268
- append_dt = False
267
+ append_dt = False if (is_group and self._pinned_separators) or ((not is_group) and self._group_separators) else append_dt
269
268
 
270
269
  dt = self.convert_date(data.updated)
271
270
  date_time_str = datetime.fromtimestamp(data.updated).strftime("%Y-%m-%d %H:%M")
@@ -274,15 +273,8 @@ class CtxList:
274
273
  title = title[:80] + '...'
275
274
  clean_title = title.replace("\n", "")
276
275
 
277
- if append_dt:
278
- name = f"{clean_title} ({dt})"
279
- else:
280
- name = clean_title
281
-
282
- mode_str = ''
283
- if data.last_mode is not None:
284
- mode_str = f" ({trans('mode.' + data.last_mode)})"
285
-
276
+ name = f"{clean_title} ({dt})" if append_dt else clean_title
277
+ mode_str = f" ({trans('mode.' + data.last_mode)})" if data.last_mode is not None else ""
286
278
  tooltip_text = f"{date_time_str}: {data.name}{mode_str} #{id}"
287
279
 
288
280
  if is_attachment:
@@ -317,8 +309,7 @@ class CtxList:
317
309
  :param group: is group
318
310
  :return: SectionItem
319
311
  """
320
- item = SectionItem(dt, group=group)
321
- return item
312
+ return SectionItem(dt, group=group)
322
313
 
323
314
  def convert_date(self, timestamp: int) -> str:
324
315
  """
@@ -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: 2023.12.25 21:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Qt
@@ -32,20 +32,29 @@ class Status:
32
32
 
33
33
  :return: QHBoxLayout
34
34
  """
35
- self.window.ui.nodes['status'] = QLabel(trans('status.started'))
36
- self.window.ui.nodes['status.agent'] = HelpLabel("")
37
- self.window.ui.nodes['status.agent'].setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
38
- self.window.ui.nodes['global.stop'] = QPushButton("STOP")
39
- self.window.ui.nodes['global.stop'].setVisible(False)
40
- self.window.ui.nodes['global.stop'].clicked.connect(self.window.controller.ui.on_global_stop)
41
- self.window.ui.nodes['anim.loading.status'] = Loader()
42
- self.window.ui.nodes['anim.loading.status'].hide()
35
+ nodes = self.window.ui.nodes
36
+
37
+ nodes['status'] = QLabel(trans('status.started'))
38
+ nodes['status'].setParent(self.window)
39
+
40
+ nodes['status.agent'] = HelpLabel("")
41
+ nodes['status.agent'].setParent(self.window)
42
+ nodes['status.agent'].setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
43
+
44
+ nodes['global.stop'] = QPushButton("STOP")
45
+ nodes['global.stop'].setParent(self.window)
46
+ nodes['global.stop'].hide()
47
+ nodes['global.stop'].clicked.connect(self.window.controller.ui.on_global_stop)
48
+
49
+ nodes['anim.loading.status'] = Loader()
50
+ nodes['anim.loading.status'].setParent(self.window)
51
+ nodes['anim.loading.status'].hide()
43
52
 
44
53
  layout = QHBoxLayout()
45
- layout.addWidget(self.window.ui.nodes['anim.loading.status'])
46
- layout.addWidget(self.window.ui.nodes['status.agent'])
47
- layout.addWidget(self.window.ui.nodes['status'])
48
- layout.addWidget(self.window.ui.nodes['global.stop'])
54
+ layout.addWidget(nodes['anim.loading.status'])
55
+ layout.addWidget(nodes['status.agent'])
56
+ layout.addWidget(nodes['status'])
57
+ layout.addWidget(nodes['global.stop'])
49
58
  layout.setAlignment(Qt.AlignLeft)
50
59
 
51
- return layout
60
+ return layout
@@ -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.24 22:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtWidgets import QVBoxLayout, QLabel, QHBoxLayout, QWidget, QCheckBox
@@ -31,49 +31,38 @@ class Agent:
31
31
 
32
32
  :return: QWidget
33
33
  """
34
- # iterations
35
- option = self.window.controller.agent.legacy.options["agent.iterations"]
36
- self.window.ui.nodes['agent.iterations.label'] = QLabel(trans("toolbox.agent.iterations.label"))
37
- self.window.ui.nodes['agent.iterations'] = \
38
- OptionSlider(
39
- self.window,
40
- 'global',
41
- 'agent.iterations',
42
- option,
43
- )
44
- self.window.ui.config['global']['agent.iterations'] = self.window.ui.nodes['agent.iterations']
34
+ window = self.window
35
+ ui = window.ui
36
+ nodes = ui.nodes
37
+ cfg = ui.config['global']
38
+ common = window.controller.agent.common
45
39
 
46
- # auto stop
47
- self.window.ui.nodes['agent.auto_stop'] = ToggleLabel(trans("toolbox.agent.auto_stop.label"), parent=self.window)
48
- self.window.ui.nodes['agent.auto_stop'].box.stateChanged.connect(
49
- lambda:
50
- self.window.controller.agent.common.toggle_auto_stop(
51
- self.window.ui.config['global']['agent.auto_stop'].box.isChecked())
52
- )
53
- self.window.ui.config['global']['agent.auto_stop'] = self.window.ui.nodes['agent.auto_stop']
40
+ container = QWidget(window)
54
41
 
55
- # continue more
56
- self.window.ui.nodes['agent.continue'] = ToggleLabel(trans("toolbox.agent.continue.label"), parent=self.window)
57
- self.window.ui.nodes['agent.continue'].box.stateChanged.connect(
58
- lambda:
59
- self.window.controller.agent.common.toggle_continue(
60
- self.window.ui.config['global']['agent.continue'].box.isChecked())
61
- )
62
- self.window.ui.config['global']['agent.continue'] = self.window.ui.nodes['agent.continue']
42
+ option = window.controller.agent.legacy.options["agent.iterations"]
43
+ nodes['agent.iterations.label'] = QLabel(trans("toolbox.agent.iterations.label"), parent=container)
44
+ nodes['agent.iterations'] = OptionSlider(window, 'global', 'agent.iterations', option)
45
+ cfg['agent.iterations'] = nodes['agent.iterations']
46
+
47
+ nodes['agent.auto_stop'] = ToggleLabel(trans("toolbox.agent.auto_stop.label"), parent=window)
48
+ nodes['agent.auto_stop'].box.toggled.connect(common.toggle_auto_stop)
49
+ cfg['agent.auto_stop'] = nodes['agent.auto_stop']
50
+
51
+ nodes['agent.continue'] = ToggleLabel(trans("toolbox.agent.continue.label"), parent=window)
52
+ nodes['agent.continue'].box.toggled.connect(common.toggle_continue)
53
+ cfg['agent.continue'] = nodes['agent.continue']
63
54
 
64
- # options
65
55
  cols = QHBoxLayout()
66
- cols.addWidget(self.window.ui.config['global']['agent.auto_stop'])
67
- cols.addWidget(self.window.ui.config['global']['agent.continue'])
56
+ cols.addWidget(cfg['agent.auto_stop'])
57
+ cols.addWidget(cfg['agent.continue'])
68
58
 
69
- # rows
70
59
  rows = QVBoxLayout()
71
- rows.addWidget(self.window.ui.nodes['agent.iterations.label'])
72
- rows.addWidget(self.window.ui.config['global']['agent.iterations'])
60
+ rows.addWidget(nodes['agent.iterations.label'])
61
+ rows.addWidget(cfg['agent.iterations'])
73
62
  rows.addLayout(cols)
74
63
 
75
- self.window.ui.nodes['agent.options'] = QWidget()
76
- self.window.ui.nodes['agent.options'].setLayout(rows)
77
- self.window.ui.nodes['agent.options'].setContentsMargins(0, 0, 0, 0)
64
+ nodes['agent.options'] = container
65
+ nodes['agent.options'].setLayout(rows)
66
+ nodes['agent.options'].setContentsMargins(0, 0, 0, 0)
78
67
 
79
- return self.window.ui.nodes['agent.options']
68
+ return nodes['agent.options']
@@ -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.07.22 15:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtWidgets import QVBoxLayout, QLabel, QHBoxLayout, QWidget, QCheckBox
@@ -32,56 +32,53 @@ class AgentLlama:
32
32
 
33
33
  :return: QWidget
34
34
  """
35
- # loop score
36
- option = self.window.controller.agent.llama.options["agent.llama.loop.score"]
37
- self.window.ui.nodes['agent.llama.loop.score.label'] = QLabel(trans("toolbox.agent.llama.loop.score.label"))
38
- self.window.ui.nodes['agent.llama.loop.score'] = \
39
- OptionSlider(
40
- self.window,
41
- 'global',
42
- 'agent.llama.loop.score',
43
- option,
44
- )
45
- self.window.ui.nodes['agent.llama.loop.score'].setToolTip(trans("toolbox.agent.llama.loop.score.tooltip"))
46
- self.window.ui.config['global']['agent.llama.loop.score'] = self.window.ui.nodes['agent.llama.loop.score']
47
-
48
- option_mode = self.window.controller.agent.llama.options["agent.llama.loop.mode"]
49
- self.window.ui.nodes['agent.llama.loop.mode.label'] = QLabel(trans("toolbox.agent.llama.loop.mode.label"))
50
- self.window.ui.nodes['agent.llama.loop.mode'] = \
51
- OptionCombo(
52
- self.window,
53
- 'global',
54
- 'agent.llama.loop.mode',
55
- option_mode,
56
- )
57
- self.window.ui.nodes['agent.llama.loop.mode'].setToolTip(trans("toolbox.agent.llama.loop.mode.tooltip"))
58
- self.window.ui.config['global']['agent.llama.loop.mode'] = self.window.ui.nodes['agent.llama.loop.mode']
59
-
60
- # loop enabled
61
- self.window.ui.nodes['agent.llama.loop.enabled'] = ToggleLabel(trans("toolbox.agent.llama.loop.enabled.label"), parent=self.window)
62
- self.window.ui.nodes['agent.llama.loop.enabled'].box.stateChanged.connect(
63
- lambda:
64
- self.window.controller.agent.common.toggle_loop(
65
- self.window.ui.config['global']['agent.llama.loop.enabled'].box.isChecked())
35
+ win = self.window
36
+ ui = win.ui
37
+ nodes = ui.nodes
38
+ config_global = ui.config.setdefault('global', {})
39
+ llama_opts = win.controller.agent.llama.options
40
+
41
+ container = QWidget(win)
42
+
43
+ nodes['agent.llama.loop.score.label'] = QLabel(trans("toolbox.agent.llama.loop.score.label"), parent=container)
44
+ nodes['agent.llama.loop.score'] = OptionSlider(
45
+ win,
46
+ 'global',
47
+ 'agent.llama.loop.score',
48
+ llama_opts["agent.llama.loop.score"],
49
+ )
50
+ nodes['agent.llama.loop.score'].setToolTip(trans("toolbox.agent.llama.loop.score.tooltip"))
51
+ config_global['agent.llama.loop.score'] = nodes['agent.llama.loop.score']
52
+
53
+ nodes['agent.llama.loop.mode.label'] = QLabel(trans("toolbox.agent.llama.loop.mode.label"), parent=container)
54
+ nodes['agent.llama.loop.mode'] = OptionCombo(
55
+ win,
56
+ 'global',
57
+ 'agent.llama.loop.mode',
58
+ llama_opts["agent.llama.loop.mode"],
59
+ )
60
+ nodes['agent.llama.loop.mode'].setToolTip(trans("toolbox.agent.llama.loop.mode.tooltip"))
61
+ config_global['agent.llama.loop.mode'] = nodes['agent.llama.loop.mode']
62
+
63
+ nodes['agent.llama.loop.enabled'] = ToggleLabel(trans("toolbox.agent.llama.loop.enabled.label"), parent=win)
64
+ nodes['agent.llama.loop.enabled'].box.toggled.connect(
65
+ win.controller.agent.common.toggle_loop
66
66
  )
67
- self.window.ui.config['global']['agent.llama.loop.enabled'] = self.window.ui.nodes['agent.llama.loop.enabled']
67
+ config_global['agent.llama.loop.enabled'] = nodes['agent.llama.loop.enabled']
68
68
 
69
- # label
70
- self.window.ui.nodes['agent.llama.loop.label'] = QLabel(trans("toolbox.agent.llama.loop.label"))
69
+ nodes['agent.llama.loop.label'] = QLabel(trans("toolbox.agent.llama.loop.label"), parent=container)
71
70
 
72
- # options
73
71
  cols = QHBoxLayout()
74
- cols.addWidget(self.window.ui.config['global']['agent.llama.loop.enabled'])
75
- cols.addWidget(self.window.ui.config['global']['agent.llama.loop.score'])
72
+ cols.addWidget(config_global['agent.llama.loop.enabled'])
73
+ cols.addWidget(config_global['agent.llama.loop.score'])
76
74
 
77
- # rows
78
75
  rows = QVBoxLayout()
79
- rows.addWidget(self.window.ui.nodes['agent.llama.loop.label'])
76
+ rows.addWidget(nodes['agent.llama.loop.label'])
80
77
  rows.addLayout(cols)
81
- rows.addWidget(self.window.ui.nodes['agent.llama.loop.mode'])
78
+ rows.addWidget(nodes['agent.llama.loop.mode'])
82
79
 
83
- self.window.ui.nodes['agent_llama.options'] = QWidget()
84
- self.window.ui.nodes['agent_llama.options'].setLayout(rows)
85
- self.window.ui.nodes['agent_llama.options'].setContentsMargins(0, 0, 0, 0)
80
+ container.setLayout(rows)
81
+ container.setContentsMargins(0, 0, 0, 0)
86
82
 
87
- return self.window.ui.nodes['agent_llama.options']
83
+ nodes['agent_llama.options'] = container
84
+ return nodes['agent_llama.options']
@@ -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.17 03:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6 import QtCore
@@ -16,7 +16,6 @@ from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QPushButton, QWidget
16
16
  from pygpt_net.ui.widget.element.labels import HelpLabel, TitleLabel
17
17
  from pygpt_net.ui.widget.lists.assistant import AssistantList
18
18
  from pygpt_net.utils import trans
19
- import pygpt_net.icons_rc
20
19
 
21
20
  class Assistants:
22
21
  def __init__(self, window=None):
@@ -48,49 +47,50 @@ class Assistants:
48
47
 
49
48
  :return: QVBoxLayout
50
49
  """
50
+ nodes = self.window.ui.nodes
51
+ ctrl = self.window.controller
52
+
51
53
  # new
52
- self.window.ui.nodes['assistants.new'] = QPushButton(QIcon(":/icons/add.svg"), "")
53
- self.window.ui.nodes['assistants.new'].clicked.connect(
54
- lambda: self.window.controller.assistant.editor.edit())
54
+ nodes['assistants.new'] = QPushButton(QIcon(":/icons/add.svg"), "")
55
+ _cb_new = ctrl.assistant.editor.edit
56
+ nodes['assistants.new'].clicked.connect(lambda checked=False, cb=_cb_new: cb())
55
57
 
56
58
  # import
57
- self.window.ui.nodes['assistants.import'] = QPushButton(trans('assistant.import'))
58
- self.window.ui.nodes['assistants.import'].clicked.connect(
59
- lambda: self.window.controller.assistant.batch.import_assistants()
60
- )
59
+ nodes['assistants.import'] = QPushButton(trans('assistant.import'))
60
+ _cb_import = ctrl.assistant.batch.import_assistants
61
+ nodes['assistants.import'].clicked.connect(lambda checked=False, cb=_cb_import: cb())
61
62
 
62
63
  # label
63
- self.window.ui.nodes['assistants.label'] = TitleLabel(trans("toolbox.assistants.label"))
64
+ nodes['assistants.label'] = TitleLabel(trans("toolbox.assistants.label"))
64
65
 
65
66
  # header
66
67
  header = QHBoxLayout()
67
- header.addWidget(self.window.ui.nodes['assistants.label'])
68
+ header.addWidget(nodes['assistants.label'])
68
69
  header.addStretch(1)
69
-
70
- header.addWidget(self.window.ui.nodes['assistants.new'], alignment=Qt.AlignRight)
71
- header.addWidget(self.window.ui.nodes['assistants.import'], alignment=Qt.AlignRight)
70
+ header.addWidget(nodes['assistants.new'], alignment=Qt.AlignRight)
71
+ header.addWidget(nodes['assistants.import'], alignment=Qt.AlignRight)
72
72
  header.setContentsMargins(5, 0, 0, 0)
73
73
  header_widget = QWidget()
74
74
  header_widget.setLayout(header)
75
75
 
76
76
  # list
77
- self.window.ui.nodes[self.id] = AssistantList(self.window, self.id)
78
- self.window.ui.nodes[self.id].selection_locked = self.window.controller.assistant.change_locked
79
- self.window.ui.nodes[self.id].setMinimumWidth(40)
77
+ nodes[self.id] = AssistantList(self.window, self.id)
78
+ nodes[self.id].selection_locked = ctrl.assistant.change_locked
79
+ nodes[self.id].setMinimumWidth(40)
80
80
 
81
- self.window.ui.nodes['tip.toolbox.assistants'] = HelpLabel(trans('tip.toolbox.assistants'), self.window)
82
- self.window.ui.nodes['tip.toolbox.assistants'].setAlignment(Qt.AlignCenter)
81
+ nodes['tip.toolbox.assistants'] = HelpLabel(trans('tip.toolbox.assistants'), self.window)
82
+ nodes['tip.toolbox.assistants'].setAlignment(Qt.AlignCenter)
83
83
 
84
84
  # rows
85
85
  layout = QVBoxLayout()
86
86
  layout.addWidget(header_widget)
87
- layout.addWidget(self.window.ui.nodes[self.id])
88
- layout.addWidget(self.window.ui.nodes['tip.toolbox.assistants'])
87
+ layout.addWidget(nodes[self.id])
88
+ layout.addWidget(nodes['tip.toolbox.assistants'])
89
89
  layout.setContentsMargins(2, 5, 5, 5)
90
90
 
91
91
  # model
92
- self.window.ui.models[self.id] = self.create_model(self.window)
93
- self.window.ui.nodes[self.id].setModel(self.window.ui.models[self.id])
92
+ self.window.ui.models[self.id] = self.create_model(nodes[self.id])
93
+ nodes[self.id].setModel(self.window.ui.models[self.id])
94
94
 
95
95
  return layout
96
96
 
@@ -109,18 +109,22 @@ class Assistants:
109
109
 
110
110
  :param data: Data to update
111
111
  """
112
- # store previous selection
113
- self.window.ui.nodes[self.id].backup_selection()
114
-
115
- self.window.ui.models[self.id].removeRows(0, self.window.ui.models[self.id].rowCount())
116
- i = 0
117
- for n in data:
118
- self.window.ui.models[self.id].insertRow(i)
119
- name = data[n].name
120
- index = self.window.ui.models[self.id].index(i, 0)
121
- self.window.ui.models[self.id].setData(index, "ID: " + data[n].id, QtCore.Qt.ToolTipRole)
122
- self.window.ui.models[self.id].setData(self.window.ui.models[self.id].index(i, 0), name)
123
- i += 1
124
-
125
- # restore previous selection
126
- self.window.ui.nodes[self.id].restore_selection()
112
+ view = self.window.ui.nodes[self.id]
113
+ model = self.window.ui.models[self.id]
114
+
115
+ view.backup_selection()
116
+ view.setUpdatesEnabled(False)
117
+ try:
118
+ with QtCore.QSignalBlocker(model):
119
+ model.setRowCount(0)
120
+ count = len(data)
121
+ if count:
122
+ model.setRowCount(count)
123
+ for i, item in enumerate(data.values()):
124
+ index = model.index(i, 0)
125
+ model.setData(index, "ID: " + item.id, QtCore.Qt.ToolTipRole)
126
+ model.setData(index, item.name)
127
+ finally:
128
+ view.setUpdatesEnabled(True)
129
+
130
+ view.restore_selection()
@@ -6,14 +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.07.26 18:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
- from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QWidget, QComboBox
12
+ from PySide6.QtWidgets import QHBoxLayout, QWidget, QComboBox
13
13
 
14
14
  from pygpt_net.ui.widget.element.labels import TitleLabel
15
15
  from pygpt_net.utils import trans
16
- import pygpt_net.icons_rc
17
16
 
18
17
 
19
18
  class ComputerEnv:
@@ -33,36 +32,46 @@ class ComputerEnv:
33
32
  :return: QWidget
34
33
  """
35
34
  layout = self.setup_env()
36
- self.window.ui.nodes['env.widget'] = QWidget()
37
- self.window.ui.nodes['env.widget'].setLayout(layout)
38
- return self.window.ui.nodes['env.widget']
35
+ nodes = self.window.ui.nodes
36
+ widget = QWidget()
37
+ widget.setLayout(layout)
38
+ nodes['env.widget'] = widget
39
+ return widget
39
40
 
40
- def setup_env(self) -> QVBoxLayout:
41
+ def _on_env_index_changed(self, index: int) -> None:
42
+ nodes = self.window.ui.nodes
43
+ cbox = nodes.get(self.id)
44
+ if cbox is None:
45
+ return
46
+ data = cbox.itemData(index)
47
+ self.window.controller.ui.on_computer_env_changed(data)
48
+
49
+ def setup_env(self) -> QHBoxLayout:
41
50
  """
42
51
  Setup list of environments
43
52
 
44
53
  :return: QVBoxLayout
45
54
  """
46
55
 
47
- # label
48
- self.window.ui.nodes['env.label'] = TitleLabel(trans("toolbox.env.label"))
56
+ nodes = self.window.ui.nodes
57
+ label = TitleLabel(trans("toolbox.env.label"))
58
+ nodes['env.label'] = label
49
59
 
50
- # list
51
- self.window.ui.nodes[self.id] = QComboBox()
52
- self.window.ui.nodes[self.id].addItem("Browser", "browser")
53
- self.window.ui.nodes[self.id].addItem("Windows", "windows")
54
- self.window.ui.nodes[self.id].addItem("Linux", "linux")
55
- self.window.ui.nodes[self.id].addItem("Mac", "mac")
56
- self.window.ui.nodes[self.id].setMinimumWidth(40)
60
+ cbox = QComboBox()
61
+ for text, data in (
62
+ ("Browser", "browser"),
63
+ ("Windows", "windows"),
64
+ ("Linux", "linux"),
65
+ ("Mac", "mac"),
66
+ ):
67
+ cbox.addItem(text, data)
68
+ cbox.setMinimumWidth(40)
57
69
 
58
- # on change signal
59
- self.window.ui.nodes[self.id].currentIndexChanged.connect(
60
- lambda index: self.window.controller.ui.on_computer_env_changed(
61
- self.window.ui.nodes[self.id].itemData(index)))
70
+ cbox.currentIndexChanged.connect(self._on_env_index_changed)
71
+ nodes[self.id] = cbox
62
72
 
63
- # rows
64
73
  layout = QHBoxLayout()
65
- layout.addWidget(self.window.ui.nodes['env.label'], 0) # label
66
- layout.addWidget(self.window.ui.nodes[self.id], 1) # combobox
74
+ layout.addWidget(label, 0)
75
+ layout.addWidget(cbox, 1)
67
76
  layout.setContentsMargins(2, 5, 5, 5)
68
77
  return layout