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.01 03:00:00 #
9
+ # Updated Date: 2025.08.23 15:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import json
@@ -226,75 +226,73 @@ class JsonFileProvider(BaseProvider):
226
226
  :param data: serialized item
227
227
  :param item: item to deserialize
228
228
  """
229
- if MODE_CHAT in data:
230
- item.chat = data[MODE_CHAT]
231
- if MODE_COMPLETION in data:
232
- item.completion = data[MODE_COMPLETION]
233
- if MODE_IMAGE in data:
234
- item.img = data[MODE_IMAGE]
235
- if MODE_VISION in data:
236
- item.vision = data[MODE_VISION]
237
- # if MODE_LANGCHAIN in data:
238
- # item.langchain = data[MODE_LANGCHAIN]
239
- if MODE_ASSISTANT in data:
240
- item.assistant = data[MODE_ASSISTANT]
241
- if MODE_LLAMA_INDEX in data:
242
- item.llama_index = data[MODE_LLAMA_INDEX]
243
229
  if MODE_AGENT in data:
244
230
  item.agent = data[MODE_AGENT]
245
231
  if MODE_AGENT_LLAMA in data:
246
232
  item.agent_llama = data[MODE_AGENT_LLAMA]
247
233
  if MODE_AGENT_OPENAI in data:
248
234
  item.agent_openai = data[MODE_AGENT_OPENAI]
249
- if MODE_EXPERT in data:
250
- item.expert = data[MODE_EXPERT]
235
+ if MODE_ASSISTANT in data:
236
+ item.assistant = data[MODE_ASSISTANT]
251
237
  if MODE_AUDIO in data:
252
238
  item.audio = data[MODE_AUDIO]
253
- if MODE_RESEARCH in data:
254
- item.research = data[MODE_RESEARCH]
239
+ if MODE_CHAT in data:
240
+ item.chat = data[MODE_CHAT]
241
+ if MODE_COMPLETION in data:
242
+ item.completion = data[MODE_COMPLETION]
255
243
  if MODE_COMPUTER in data:
256
244
  item.computer = data[MODE_COMPUTER]
245
+ if MODE_EXPERT in data:
246
+ item.expert = data[MODE_EXPERT]
247
+ if MODE_IMAGE in data:
248
+ item.img = data[MODE_IMAGE]
249
+ if MODE_LLAMA_INDEX in data:
250
+ item.llama_index = data[MODE_LLAMA_INDEX]
251
+ if MODE_RESEARCH in data:
252
+ item.research = data[MODE_RESEARCH]
253
+ if MODE_VISION in data:
254
+ item.vision = data[MODE_VISION]
257
255
 
258
- if 'uuid' in data:
259
- item.uuid = data['uuid']
260
- if 'name' in data:
261
- item.name = data['name']
262
- if 'ai_name' in data:
263
- item.ai_name = data['ai_name']
264
- if 'ai_avatar' in data:
265
- item.ai_avatar = data['ai_avatar']
266
- if 'ai_personalize' in data:
267
- item.ai_personalize = data['ai_personalize']
268
- if 'user_name' in data:
269
- item.user_name = data['user_name']
270
- if 'prompt' in data:
271
- item.prompt = data['prompt']
272
- if 'temperature' in data:
273
- item.temperature = data['temperature']
274
- if 'filename' in data:
275
- item.filename = data['filename']
276
- if 'model' in data:
277
- item.model = data['model']
278
- if 'tools' in data:
279
- item.tools = data['tools']
280
- if 'experts' in data:
281
- item.experts = data['experts']
282
- if 'idx' in data:
283
- item.idx = data['idx']
284
256
  if 'agent_provider' in data:
285
257
  item.agent_provider = data['agent_provider']
286
258
  if 'agent_provider_openai' in data:
287
259
  item.agent_provider_openai = data['agent_provider_openai']
260
+ if 'ai_avatar' in data:
261
+ item.ai_avatar = data['ai_avatar']
262
+ if 'ai_name' in data:
263
+ item.ai_name = data['ai_name']
264
+ if 'ai_personalize' in data:
265
+ item.ai_personalize = data['ai_personalize']
288
266
  if 'assistant_id' in data:
289
267
  item.assistant_id = data['assistant_id']
290
- if 'enabled' in data:
291
- item.enabled = data['enabled']
292
268
  if 'description' in data:
293
269
  item.description = data['description']
294
- if 'remote_tools' in data:
295
- item.remote_tools = data['remote_tools']
270
+ if 'enabled' in data:
271
+ item.enabled = data['enabled']
272
+ if 'experts' in data:
273
+ item.experts = data['experts']
296
274
  if 'extra' in data:
297
275
  item.extra = data['extra']
276
+ if 'filename' in data:
277
+ item.filename = data['filename']
278
+ if 'idx' in data:
279
+ item.idx = data['idx']
280
+ if 'model' in data:
281
+ item.model = data['model']
282
+ if 'name' in data:
283
+ item.name = data['name']
284
+ if 'prompt' in data:
285
+ item.prompt = data['prompt']
286
+ if 'remote_tools' in data:
287
+ item.remote_tools = data['remote_tools']
288
+ if 'temperature' in data:
289
+ item.temperature = data['temperature']
290
+ if 'tools' in data:
291
+ item.tools = data['tools']
292
+ if 'user_name' in data:
293
+ item.user_name = data['user_name']
294
+ if 'uuid' in data:
295
+ item.uuid = data['uuid']
298
296
 
299
297
  # get version
300
298
  if '__meta__' in data and 'version' in data['__meta__']:
@@ -3,7 +3,7 @@
3
3
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
4
4
  # MIT License #
5
5
  # Created By : Marcin Szczygliński #
6
- # Updated Date: 2025.08.11 19:00:00 #
6
+ # Updated Date: 2025.08.24 03:00:00 #
7
7
  # ================================================== #
8
8
 
9
9
  from agents import (
@@ -74,7 +74,7 @@ def get_expert(
74
74
  kwargs = {
75
75
  "name": agent_name,
76
76
  "instructions": prompt,
77
- "model": model.id,
77
+ "model": window.core.agents.provider.get_openai_model(model),
78
78
  }
79
79
  tool_kwargs = append_tools(
80
80
  tools=tools,
@@ -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.03.26 15:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Qt
@@ -20,6 +20,7 @@ from pygpt_net.utils import trans
20
20
 
21
21
 
22
22
  class AudioTranscribe:
23
+
23
24
  def __init__(self, window=None):
24
25
  """
25
26
  Audio Transcribe dialog
@@ -31,30 +32,21 @@ class AudioTranscribe:
31
32
  self.file_menu = None
32
33
  self.actions = {}
33
34
 
34
- def setup_menu(self) -> QMenuBar:
35
+ def setup_menu(self, parent=None) -> QMenuBar:
35
36
  """Setup audio transcriber dialog menu"""
36
- self.menu_bar = QMenuBar()
37
+ self.menu_bar = QMenuBar(parent)
37
38
  self.file_menu = self.menu_bar.addMenu(trans("menu.file"))
39
+ t = self.window.tools.get("transcriber")
40
+
41
+ self.actions["open"] = QAction(QIcon(":/icons/folder.svg"), trans("action.open"), self.menu_bar)
42
+ self.actions["open"].triggered.connect(lambda checked=False, t=t: t.open_file())
43
+
44
+ self.actions["save_as"] = QAction(QIcon(":/icons/save.svg"), trans("action.save_as"), self.menu_bar)
45
+ self.actions["save_as"].triggered.connect(lambda checked=False, t=t: t.save_as_file())
46
+
47
+ self.actions["exit"] = QAction(QIcon(":/icons/logout.svg"), trans("menu.file.exit"), self.menu_bar)
48
+ self.actions["exit"].triggered.connect(lambda checked=False, t=t: t.close())
38
49
 
39
- # open
40
- self.actions["open"] = QAction(QIcon(":/icons/folder.svg"), trans("action.open"))
41
- self.actions["open"].triggered.connect(
42
- lambda: self.window.tools.get("transcriber").open_file()
43
- )
44
-
45
- # save as
46
- self.actions["save_as"] = QAction(QIcon(":/icons/save.svg"), trans("action.save_as"))
47
- self.actions["save_as"].triggered.connect(
48
- lambda: self.window.tools.get("transcriber").save_as_file()
49
- )
50
-
51
- # exit
52
- self.actions["exit"] = QAction(QIcon(":/icons/logout.svg"), trans("menu.file.exit"))
53
- self.actions["exit"].triggered.connect(
54
- lambda: self.window.tools.get("transcriber").close()
55
- )
56
-
57
- # add actions
58
50
  self.file_menu.addAction(self.actions["open"])
59
51
  self.file_menu.addAction(self.actions["save_as"])
60
52
  self.file_menu.addAction(self.actions["exit"])
@@ -63,53 +55,51 @@ class AudioTranscribe:
63
55
  def setup(self):
64
56
  """Setup transcriber dialog"""
65
57
  id = 'audio.transcribe'
58
+ u = self.window.ui
59
+ t = self.window.tools.get("transcriber")
66
60
 
67
- self.window.ui.editor[id] = CodeEditor(self.window)
68
- self.window.ui.editor[id].setReadOnly(False)
69
- self.window.ui.editor[id].setProperty('class', 'code-editor')
61
+ u.dialog['audio.transcribe'] = AudioTranscribeDialog(self.window)
62
+ dlg = u.dialog['audio.transcribe']
70
63
 
71
- self.window.ui.nodes['audio.transcribe.convert_video'] = QCheckBox(trans("audio.transcribe.auto_convert"))
72
- self.window.ui.nodes['audio.transcribe.convert_video'].setChecked(True)
73
- self.window.ui.nodes['audio.transcribe.convert_video'].clicked.connect(
74
- lambda: self.window.tools.get("transcriber").toggle_auto_convert()
75
- )
64
+ u.editor[id] = CodeEditor(self.window)
65
+ u.editor[id].setReadOnly(False)
66
+ u.editor[id].setProperty('class', 'code-editor')
76
67
 
77
- self.window.ui.nodes['audio.transcribe.clear'] = QPushButton(trans("dialog.logger.btn.clear"))
78
- self.window.ui.nodes['audio.transcribe.clear'].clicked.connect(
79
- lambda: self.clear()
80
- )
68
+ u.nodes['audio.transcribe.convert_video'] = QCheckBox(trans("audio.transcribe.auto_convert"))
69
+ u.nodes['audio.transcribe.convert_video'].setChecked(True)
70
+ u.nodes['audio.transcribe.convert_video'].clicked.connect(lambda checked=False, t=t: t.toggle_auto_convert())
81
71
 
82
- self.window.ui.nodes['audio.transcribe.open'] = QPushButton(trans("audio.transcribe.open"))
83
- self.window.ui.nodes['audio.transcribe.open'].clicked.connect(
84
- lambda: self.window.tools.get("transcriber").open_file()
85
- )
72
+ u.nodes['audio.transcribe.clear'] = QPushButton(trans("dialog.logger.btn.clear"))
73
+ u.nodes['audio.transcribe.clear'].clicked.connect(self.clear)
74
+
75
+ u.nodes['audio.transcribe.open'] = QPushButton(trans("audio.transcribe.open"))
76
+ u.nodes['audio.transcribe.open'].clicked.connect(lambda checked=False, t=t: t.open_file())
86
77
 
87
78
  bottom_layout = QHBoxLayout()
88
- bottom_layout.addWidget(self.window.ui.nodes['audio.transcribe.clear'])
89
- bottom_layout.addWidget(self.window.ui.nodes['audio.transcribe.open'])
79
+ bottom_layout.addWidget(u.nodes['audio.transcribe.clear'])
80
+ bottom_layout.addWidget(u.nodes['audio.transcribe.open'])
90
81
 
91
- self.window.ui.nodes['audio.transcribe.title'] = HelpLabel(trans("audio.transcribe.tip"))
92
- self.window.ui.nodes['audio.transcribe.status'] = QLabel("...")
93
- self.window.ui.nodes['audio.transcribe.status'].setAlignment(Qt.AlignCenter)
94
- self.window.ui.nodes['audio.transcribe.status'].setWordWrap(True)
82
+ u.nodes['audio.transcribe.title'] = HelpLabel(trans("audio.transcribe.tip"))
83
+ u.nodes['audio.transcribe.status'] = QLabel("...")
84
+ u.nodes['audio.transcribe.status'].setAlignment(Qt.AlignCenter)
85
+ u.nodes['audio.transcribe.status'].setWordWrap(True)
95
86
 
96
87
  layout = QVBoxLayout()
97
- layout.setMenuBar(self.setup_menu())
98
- layout.addWidget(self.window.ui.editor[id])
99
- layout.addWidget(self.window.ui.nodes['audio.transcribe.title'])
88
+ layout.setMenuBar(self.setup_menu(dlg))
89
+ layout.addWidget(u.editor[id])
90
+ layout.addWidget(u.nodes['audio.transcribe.title'])
100
91
  layout.addLayout(bottom_layout)
101
- layout.addWidget(self.window.ui.nodes['audio.transcribe.convert_video'])
102
- layout.addWidget(self.window.ui.nodes['audio.transcribe.status'])
103
-
104
- self.window.ui.dialog['audio.transcribe'] = AudioTranscribeDialog(self.window)
105
- self.window.ui.dialog['audio.transcribe'].setLayout(layout)
106
- self.window.ui.dialog['audio.transcribe'].setWindowTitle(trans("audio.transcribe.title"))
92
+ layout.addWidget(u.nodes['audio.transcribe.convert_video'])
93
+ layout.addWidget(u.nodes['audio.transcribe.status'])
107
94
 
95
+ dlg.setLayout(layout)
96
+ dlg.setWindowTitle(trans("audio.transcribe.title"))
108
97
 
109
98
  def clear(self):
110
99
  """Clear transcribe dialog"""
111
100
  self.window.tools.get("transcriber").clear()
112
101
 
102
+
113
103
  class AudioTranscribeDialog(BaseDialog):
114
104
  def __init__(self, window=None, id=None):
115
105
  """
@@ -139,7 +129,7 @@ class AudioTranscribeDialog(BaseDialog):
139
129
  """
140
130
  if event.key() == Qt.Key_Escape:
141
131
  self.cleanup()
142
- self.close() # close dialog when the Esc key is pressed.
132
+ self.close()
143
133
  else:
144
134
  super(AudioTranscribeDialog, self).keyPressEvent(event)
145
135
 
@@ -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.19 07:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -140,7 +140,6 @@ class Body:
140
140
  </style>
141
141
  <script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
142
142
  <script type="text/javascript" src="qrc:///js/highlight.min.js"></script>
143
- <script type="text/javascript" src="qrc:///js/auto-render.min.js"></script>
144
143
  <script>
145
144
 
146
145
  let scrollTimeout = null;
@@ -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.05 21:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import json
@@ -26,7 +26,7 @@ from pygpt_net.item.ctx import CtxItem
26
26
  from pygpt_net.utils import trans
27
27
  from .ui.html import HtmlOutput, CodeBlock
28
28
 
29
- from .ui.widgets import PythonInput, PythonOutput, ToolWidget, ToolSignals
29
+ from .ui.widgets import PythonInput, ToolWidget, ToolSignals
30
30
 
31
31
 
32
32
  class CodeInterpreter(BaseTool):
@@ -48,6 +48,7 @@ class CodeInterpreter(BaseTool):
48
48
  self.ipython = True
49
49
  self.auto_opened = False
50
50
  self.signals = ToolSignals()
51
+ self.max_history_size = 1000 # max history lines
51
52
 
52
53
  # interpreter data files in /data directory
53
54
  self.file_current = ".interpreter.current.py"
@@ -366,11 +367,13 @@ class CodeInterpreter(BaseTool):
366
367
 
367
368
  def save_history(self, input: str):
368
369
  """
369
- Save input data
370
+ Save input data (history)
370
371
 
371
372
  :param input: Input data
372
373
  """
373
374
  path = self.get_path_input()
375
+ if self.max_history_size > 0 and isinstance(input, str):
376
+ input = ''.join(input.splitlines(True)[-self.max_history_size:])
374
377
  with open(path , "w", encoding="utf-8") as f:
375
378
  f.write(input)
376
379
 
@@ -431,7 +434,7 @@ class CodeInterpreter(BaseTool):
431
434
  self.window.controller.command.dispatch_only(event)
432
435
  self.signals.focus_input.emit()
433
436
  event = KernelEvent(KernelEvent.STATUS, {
434
- 'status': "[OK] Kernel restarted at " + strftime("%H:%M:%S") + ".",
437
+ 'status': f"[OK] Kernel restarted at {strftime('%H:%M:%S')}.",
435
438
  })
436
439
  self.window.dispatch(event)
437
440
 
@@ -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.08 21:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import json
@@ -25,8 +25,6 @@ from pygpt_net.core.text.web_finder import WebFinder
25
25
  from pygpt_net.tools.code_interpreter.body import Body
26
26
  from pygpt_net.utils import trans
27
27
 
28
- import pygpt_net.icons_rc
29
-
30
28
  class CodeBlock:
31
29
  def __init__(
32
30
  self,
@@ -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.05 21:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6 import QtCore
@@ -17,10 +17,9 @@ from PySide6.QtWidgets import QTextEdit, QApplication, QVBoxLayout, QLabel, QChe
17
17
 
18
18
  from pygpt_net.item.ctx import CtxItem
19
19
  from pygpt_net.ui.widget.textarea.editor import BaseCodeEditor
20
+ from pygpt_net.utils import trans
20
21
 
21
22
  from .html import HtmlOutput, CustomWebEnginePage
22
- from pygpt_net.utils import trans
23
- import pygpt_net.icons_rc
24
23
 
25
24
 
26
25
  class ToolWidget:
@@ -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.05 21:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Qt, Slot, QUrl, QObject, Signal
@@ -15,8 +15,6 @@ from PySide6.QtWidgets import QVBoxLayout, QCheckBox, QHBoxLayout
15
15
  from pygpt_net.ui.widget.element.labels import HelpLabel
16
16
  from pygpt_net.ui.widget.textarea.editor import BaseCodeEditor
17
17
  from pygpt_net.ui.widget.textarea.html import HtmlOutput, CustomWebEnginePage
18
-
19
- import pygpt_net.icons_rc
20
18
  from pygpt_net.utils import trans
21
19
 
22
20
 
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.26 02:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Qt
@@ -17,8 +17,6 @@ from pygpt_net.ui.widget.dialog.base import BaseDialog
17
17
  from pygpt_net.ui.widget.image.display import ImageLabel
18
18
  from pygpt_net.utils import trans
19
19
 
20
- import pygpt_net.icons_rc
21
-
22
20
  class DialogSpawner:
23
21
  def __init__(self, window=None):
24
22
  """
@@ -37,9 +35,13 @@ class DialogSpawner:
37
35
  :param id: dialog id
38
36
  :return: BaseDialog instance
39
37
  """
40
- source = ImageLabel(self.window, self.path)
38
+ dialog = ImageViewerDialog(self.window, self.id)
39
+ dialog.disable_geometry_store = True # disable geometry store
40
+ dialog.id = id
41
+
42
+ source = ImageLabel(dialog, self.path)
41
43
  source.setVisible(False)
42
- pixmap = ImageLabel(self.window, self.path)
44
+ pixmap = ImageLabel(dialog, self.path)
43
45
  pixmap.setSizePolicy(QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored))
44
46
 
45
47
  row = QHBoxLayout()
@@ -48,11 +50,7 @@ class DialogSpawner:
48
50
  layout = QVBoxLayout()
49
51
  layout.addLayout(row)
50
52
 
51
- dialog = ImageViewerDialog(self.window, self.id)
52
- dialog.disable_geometry_store = True # disable geometry store
53
- dialog.id = id
54
53
  dialog.append_layout(layout)
55
- dialog.setLayout(layout)
56
54
  dialog.source = source
57
55
  dialog.pixmap = pixmap
58
56
 
@@ -74,9 +72,14 @@ class ImageViewerDialog(BaseDialog):
74
72
  self.menu_bar = None
75
73
  self.file_menu = None
76
74
  self.actions = {}
77
- self.resizeEvent = self.onResizeEvent # resize event to adjust the pixmap
78
75
  self.source = None
79
76
  self.pixmap = None
77
+ self._last_src_key = 0
78
+ self._last_target_size = None
79
+ self._icon_add = QIcon(":/icons/add.svg")
80
+ self._icon_folder = QIcon(":/icons/folder.svg")
81
+ self._icon_save = QIcon(":/icons/save.svg")
82
+ self._icon_logout = QIcon(":/icons/logout.svg")
80
83
 
81
84
  def append_layout(self, layout):
82
85
  """
@@ -84,23 +87,29 @@ class ImageViewerDialog(BaseDialog):
84
87
 
85
88
  :param layout: layout
86
89
  """
87
- layout.setMenuBar(self.setup_menu()) # attach menu
90
+ layout.setMenuBar(self.setup_menu())
88
91
  self.setLayout(layout)
89
92
 
90
- def onResizeEvent(self, event):
93
+ def resizeEvent(self, event):
91
94
  """
92
95
  Resize event to adjust the pixmap on window resizing
93
96
 
94
97
  :param event: resize event
95
98
  """
96
- if self.source.pixmap() and not self.source.pixmap().isNull():
97
- self.pixmap.setPixmap(
98
- self.source.pixmap().scaled(
99
- self.pixmap.size(),
100
- Qt.KeepAspectRatio,
101
- Qt.SmoothTransformation
99
+ src = self.source.pixmap() if self.source is not None else None
100
+ if src and not src.isNull() and self.pixmap is not None:
101
+ target_size = self.pixmap.size()
102
+ key = src.cacheKey()
103
+ if key != self._last_src_key or target_size != self._last_target_size:
104
+ self.pixmap.setPixmap(
105
+ src.scaled(
106
+ target_size,
107
+ Qt.KeepAspectRatio,
108
+ Qt.SmoothTransformation
109
+ )
102
110
  )
103
- )
111
+ self._last_src_key = key
112
+ self._last_target_size = target_size
104
113
  super(ImageViewerDialog, self).resizeEvent(event)
105
114
 
106
115
  def setup_menu(self) -> QMenuBar:
@@ -109,44 +118,38 @@ class ImageViewerDialog(BaseDialog):
109
118
 
110
119
  :return: QMenuBar
111
120
  """
112
- self.menu_bar = QMenuBar()
121
+ self.menu_bar = QMenuBar(self)
113
122
  self.file_menu = self.menu_bar.addMenu(trans("menu.file"))
114
123
 
115
- # new
116
- self.actions["new"] = QAction(QIcon(":/icons/add.svg"), trans("action.new"))
124
+ self.actions["new"] = QAction(self._icon_add, trans("action.new"), self)
117
125
  self.actions["new"].triggered.connect(
118
- lambda: self.window.tools.get("viewer").new()
126
+ lambda checked=False: self.window.tools.get("viewer").new()
119
127
  )
120
128
 
121
- # open
122
- self.actions["open"] = QAction(QIcon(":/icons/folder.svg"), trans("action.open"))
129
+ self.actions["open"] = QAction(self._icon_folder, trans("action.open"), self)
123
130
  self.actions["open"].triggered.connect(
124
- lambda: self.window.tools.get("viewer").open_file(self.id, auto_close=True)
131
+ lambda checked=False: self.window.tools.get("viewer").open_file(self.id, auto_close=True)
125
132
  )
126
133
 
127
- # open (new window)
128
- self.actions["open_new"] = QAction(QIcon(":/icons/folder.svg"), trans("action.open_new_window"))
134
+ self.actions["open_new"] = QAction(self._icon_folder, trans("action.open_new_window"), self)
129
135
  self.actions["open_new"].triggered.connect(
130
- lambda: self.window.tools.get("viewer").open_file(self.id, auto_close=False)
136
+ lambda checked=False: self.window.tools.get("viewer").open_file(self.id, auto_close=False)
131
137
  )
132
138
 
133
- # save as
134
- self.actions["save_as"] = QAction(QIcon(":/icons/save.svg"), trans("action.save_as"))
139
+ self.actions["save_as"] = QAction(self._icon_save, trans("action.save_as"), self)
135
140
  self.actions["save_as"].triggered.connect(
136
- lambda: self.window.tools.get("viewer").save_by_id(self.id)
141
+ lambda checked=False: self.window.tools.get("viewer").save_by_id(self.id)
137
142
  )
138
143
 
139
- # exit
140
- self.actions["exit"] = QAction(QIcon(":/icons/logout.svg"), trans("menu.file.exit"))
144
+ self.actions["exit"] = QAction(self._icon_logout, trans("menu.file.exit"), self)
141
145
  self.actions["exit"].triggered.connect(
142
- lambda: self.window.tools.get("viewer").close_preview(self.id)
146
+ lambda checked=False: self.window.tools.get("viewer").close_preview(self.id)
143
147
  )
144
148
 
145
- # add actions
146
149
  self.file_menu.addAction(self.actions["new"])
147
150
  self.file_menu.addAction(self.actions["open"])
148
151
  self.file_menu.addAction(self.actions["open_new"])
149
152
  self.file_menu.addAction(self.actions["save_as"])
150
153
  self.file_menu.addAction(self.actions["exit"])
151
154
 
152
- return self.menu_bar
155
+ return self.menu_bar
@@ -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.04.17 01:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Qt
@@ -33,7 +33,6 @@ class IdxBrowseList(DatabaseList):
33
33
 
34
34
  :param parent: Parent
35
35
  """
36
-
37
36
  def copy_to_clipboard():
38
37
  index = parent.currentIndex()
39
38
  if index.isValid():
@@ -64,9 +63,8 @@ class IdxBrowser(DataBrowser):
64
63
  :return: Tables dictionary
65
64
  """
66
65
  data = self.window.tools.get("indexer").get_tables()
67
- tables = {k: v for k, v in data.items() if k in [
66
+ return {k: v for k, v in data.items() if k in [
68
67
  "idx_ctx", "idx_file", "idx_external"]}
69
- return tables
70
68
 
71
69
  @override
72
70
  def get_filters(self):
@@ -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.12 15:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import datetime
@@ -15,15 +15,12 @@ import shutil
15
15
  from typing import Dict
16
16
 
17
17
  from PySide6.QtGui import QAction, QIcon
18
+ from PySide6.QtWidgets import QMessageBox, QFileDialog
18
19
 
19
20
  from pygpt_net.tools.base import BaseTool
20
21
  from pygpt_net.tools.media_player.ui.dialogs import VideoPlayer
21
- from PySide6.QtWidgets import QMessageBox, QFileDialog
22
-
23
22
  from pygpt_net.utils import trans
24
23
 
25
- import pygpt_net.icons_rc
26
-
27
24
 
28
25
  class MediaPlayer(BaseTool):
29
26
  def __init__(self, *args, **kwargs):