pygpt-net 2.6.21__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 (144) hide show
  1. pygpt_net/CHANGELOG.txt +4 -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/assistant/batch.py +2 -3
  7. pygpt_net/controller/assistant/editor.py +2 -2
  8. pygpt_net/controller/assistant/files.py +2 -3
  9. pygpt_net/controller/assistant/store.py +2 -2
  10. pygpt_net/controller/audio/audio.py +2 -2
  11. pygpt_net/controller/ctx/ctx.py +2 -1
  12. pygpt_net/controller/idx/indexer.py +85 -76
  13. pygpt_net/controller/lang/lang.py +52 -34
  14. pygpt_net/controller/model/importer.py +2 -2
  15. pygpt_net/controller/notepad/notepad.py +86 -84
  16. pygpt_net/controller/plugins/settings.py +3 -4
  17. pygpt_net/controller/settings/profile.py +105 -124
  18. pygpt_net/controller/theme/menu.py +154 -57
  19. pygpt_net/controller/theme/nodes.py +51 -44
  20. pygpt_net/controller/theme/theme.py +33 -9
  21. pygpt_net/controller/tools/tools.py +2 -2
  22. pygpt_net/controller/ui/tabs.py +2 -3
  23. pygpt_net/core/ctx/container.py +13 -12
  24. pygpt_net/core/ctx/output.py +7 -4
  25. pygpt_net/core/debug/console/console.py +2 -2
  26. pygpt_net/core/filesystem/actions.py +1 -2
  27. pygpt_net/core/render/plain/helpers.py +2 -5
  28. pygpt_net/core/render/plain/renderer.py +26 -30
  29. pygpt_net/core/render/web/body.py +1 -1
  30. pygpt_net/core/settings/settings.py +43 -13
  31. pygpt_net/core/tabs/tabs.py +20 -13
  32. pygpt_net/data/config/config.json +4 -4
  33. pygpt_net/data/config/models.json +3 -3
  34. pygpt_net/data/locale/locale.de.ini +4 -1
  35. pygpt_net/data/locale/locale.en.ini +4 -1
  36. pygpt_net/data/locale/locale.es.ini +4 -1
  37. pygpt_net/data/locale/locale.fr.ini +4 -1
  38. pygpt_net/data/locale/locale.it.ini +4 -1
  39. pygpt_net/data/locale/locale.pl.ini +5 -4
  40. pygpt_net/data/locale/locale.uk.ini +4 -1
  41. pygpt_net/data/locale/locale.zh.ini +4 -1
  42. pygpt_net/plugin/twitter/plugin.py +2 -2
  43. pygpt_net/tools/audio_transcriber/ui/dialogs.py +44 -54
  44. pygpt_net/tools/code_interpreter/body.py +1 -2
  45. pygpt_net/tools/code_interpreter/tool.py +7 -4
  46. pygpt_net/tools/code_interpreter/ui/html.py +1 -3
  47. pygpt_net/tools/code_interpreter/ui/widgets.py +2 -3
  48. pygpt_net/tools/html_canvas/ui/widgets.py +1 -3
  49. pygpt_net/tools/image_viewer/ui/dialogs.py +40 -37
  50. pygpt_net/tools/indexer/ui/widgets.py +2 -4
  51. pygpt_net/tools/media_player/tool.py +2 -5
  52. pygpt_net/tools/media_player/ui/widgets.py +60 -36
  53. pygpt_net/tools/text_editor/ui/widgets.py +18 -19
  54. pygpt_net/tools/translator/ui/widgets.py +39 -35
  55. pygpt_net/ui/base/context_menu.py +9 -4
  56. pygpt_net/ui/dialog/db.py +1 -3
  57. pygpt_net/ui/dialog/models.py +1 -3
  58. pygpt_net/ui/dialog/models_importer.py +2 -4
  59. pygpt_net/ui/dialogs.py +34 -30
  60. pygpt_net/ui/layout/chat/attachments.py +72 -84
  61. pygpt_net/ui/layout/chat/attachments_ctx.py +40 -44
  62. pygpt_net/ui/layout/chat/attachments_uploaded.py +36 -39
  63. pygpt_net/ui/layout/chat/calendar.py +100 -70
  64. pygpt_net/ui/layout/chat/chat.py +23 -17
  65. pygpt_net/ui/layout/chat/input.py +95 -118
  66. pygpt_net/ui/layout/chat/output.py +100 -162
  67. pygpt_net/ui/layout/chat/painter.py +89 -61
  68. pygpt_net/ui/layout/ctx/ctx_list.py +43 -52
  69. pygpt_net/ui/layout/status.py +23 -14
  70. pygpt_net/ui/layout/toolbox/agent.py +27 -38
  71. pygpt_net/ui/layout/toolbox/agent_llama.py +42 -45
  72. pygpt_net/ui/layout/toolbox/assistants.py +42 -38
  73. pygpt_net/ui/layout/toolbox/computer_env.py +32 -23
  74. pygpt_net/ui/layout/toolbox/footer.py +13 -16
  75. pygpt_net/ui/layout/toolbox/image.py +18 -21
  76. pygpt_net/ui/layout/toolbox/indexes.py +46 -89
  77. pygpt_net/ui/layout/toolbox/mode.py +20 -7
  78. pygpt_net/ui/layout/toolbox/model.py +12 -10
  79. pygpt_net/ui/layout/toolbox/presets.py +68 -52
  80. pygpt_net/ui/layout/toolbox/prompt.py +31 -58
  81. pygpt_net/ui/layout/toolbox/toolbox.py +25 -21
  82. pygpt_net/ui/layout/toolbox/vision.py +20 -22
  83. pygpt_net/ui/main.py +2 -4
  84. pygpt_net/ui/menu/about.py +64 -84
  85. pygpt_net/ui/menu/audio.py +87 -63
  86. pygpt_net/ui/menu/config.py +121 -127
  87. pygpt_net/ui/menu/debug.py +69 -76
  88. pygpt_net/ui/menu/file.py +32 -35
  89. pygpt_net/ui/menu/menu.py +2 -3
  90. pygpt_net/ui/menu/plugins.py +69 -33
  91. pygpt_net/ui/menu/theme.py +45 -46
  92. pygpt_net/ui/menu/tools.py +56 -60
  93. pygpt_net/ui/menu/video.py +20 -25
  94. pygpt_net/ui/tray.py +1 -2
  95. pygpt_net/ui/widget/audio/bar.py +1 -3
  96. pygpt_net/ui/widget/audio/input_button.py +3 -4
  97. pygpt_net/ui/widget/calendar/select.py +1 -2
  98. pygpt_net/ui/widget/dialog/base.py +12 -9
  99. pygpt_net/ui/widget/dialog/editor_file.py +20 -23
  100. pygpt_net/ui/widget/dialog/find.py +25 -24
  101. pygpt_net/ui/widget/dialog/profile.py +57 -53
  102. pygpt_net/ui/widget/draw/painter.py +62 -93
  103. pygpt_net/ui/widget/element/button.py +42 -30
  104. pygpt_net/ui/widget/element/checkbox.py +23 -15
  105. pygpt_net/ui/widget/element/group.py +6 -5
  106. pygpt_net/ui/widget/element/labels.py +1 -2
  107. pygpt_net/ui/widget/filesystem/explorer.py +93 -102
  108. pygpt_net/ui/widget/image/display.py +1 -2
  109. pygpt_net/ui/widget/lists/assistant.py +1 -2
  110. pygpt_net/ui/widget/lists/attachment.py +1 -2
  111. pygpt_net/ui/widget/lists/attachment_ctx.py +1 -2
  112. pygpt_net/ui/widget/lists/context.py +2 -4
  113. pygpt_net/ui/widget/lists/index.py +1 -2
  114. pygpt_net/ui/widget/lists/model.py +1 -2
  115. pygpt_net/ui/widget/lists/model_editor.py +1 -2
  116. pygpt_net/ui/widget/lists/model_importer.py +1 -2
  117. pygpt_net/ui/widget/lists/preset.py +1 -2
  118. pygpt_net/ui/widget/lists/preset_plugins.py +1 -2
  119. pygpt_net/ui/widget/lists/profile.py +1 -2
  120. pygpt_net/ui/widget/lists/uploaded.py +1 -2
  121. pygpt_net/ui/widget/option/checkbox.py +2 -4
  122. pygpt_net/ui/widget/option/checkbox_list.py +1 -4
  123. pygpt_net/ui/widget/option/cmd.py +1 -4
  124. pygpt_net/ui/widget/option/dictionary.py +25 -28
  125. pygpt_net/ui/widget/option/input.py +1 -3
  126. pygpt_net/ui/widget/tabs/Input.py +16 -12
  127. pygpt_net/ui/widget/tabs/body.py +5 -3
  128. pygpt_net/ui/widget/tabs/layout.py +36 -25
  129. pygpt_net/ui/widget/tabs/output.py +96 -74
  130. pygpt_net/ui/widget/textarea/calendar_note.py +1 -2
  131. pygpt_net/ui/widget/textarea/editor.py +41 -73
  132. pygpt_net/ui/widget/textarea/find.py +11 -10
  133. pygpt_net/ui/widget/textarea/html.py +3 -6
  134. pygpt_net/ui/widget/textarea/input.py +63 -64
  135. pygpt_net/ui/widget/textarea/notepad.py +54 -38
  136. pygpt_net/ui/widget/textarea/output.py +65 -54
  137. pygpt_net/ui/widget/textarea/search_input.py +5 -4
  138. pygpt_net/ui/widget/textarea/web.py +2 -4
  139. pygpt_net/ui/widget/vision/camera.py +2 -31
  140. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.22.dist-info}/METADATA +15 -151
  141. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.22.dist-info}/RECORD +144 -144
  142. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.22.dist-info}/LICENSE +0 -0
  143. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.22.dist-info}/WHEEL +0 -0
  144. {pygpt_net-2.6.21.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: 2024.12.14 22:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import copy
@@ -15,7 +15,10 @@ import os
15
15
  import shutil
16
16
  from typing import Optional, Dict, Any, List
17
17
 
18
+ from PySide6.QtWidgets import QApplication
19
+
18
20
  from pygpt_net.core.events import RenderEvent
21
+ from pygpt_net.utils import trans
19
22
 
20
23
 
21
24
  class Settings:
@@ -116,7 +119,7 @@ class Settings:
116
119
  """Load defaults from file"""
117
120
  file = self.window.ui.dialog['config.editor'].file
118
121
  self.load_editor(file)
119
- self.window.update_status("Restored from user file: {}".format(file))
122
+ self.window.update_status(f"Restored from user file: {file}")
120
123
 
121
124
  def load_default_editor_app(self):
122
125
  """Load defaults from file (app)"""
@@ -125,11 +128,11 @@ class Settings:
125
128
  if basename.endswith(".css"):
126
129
  path = str(os.path.join(self.window.core.config.get_app_path(), "data", "css", basename))
127
130
  self.load_editor(file, path)
128
- self.window.update_status("Restored from app defaults: {}".format(basename))
131
+ self.window.update_status(f"Restored from app defaults: {basename}")
129
132
  elif basename.endswith(".json"):
130
133
  path = str(os.path.join(self.window.core.config.get_app_path(), "data", "config", basename))
131
134
  self.load_editor(file, path)
132
- self.window.update_status("Restored from app defaults: {}".format(basename))
135
+ self.window.update_status(f"Restored from app defaults: {basename}")
133
136
 
134
137
  def load_editor(
135
138
  self,
@@ -151,13 +154,14 @@ class Settings:
151
154
  self.window.ui.paths['config'].setText(path)
152
155
 
153
156
  self.window.ui.dialog['config.editor'].file = file
157
+
154
158
  try:
155
159
  with open(path, 'r', encoding="utf-8") as f:
156
160
  txt = f.read()
157
161
  self.window.ui.editor['config'].setPlainText(txt)
158
162
  except Exception as e:
159
163
  self.window.core.debug.log(e)
160
- self.window.update_status("Error loading file: {}".format(e))
164
+ self.window.update_status(f"Error loading file: {e}")
161
165
 
162
166
  def save_editor(self):
163
167
  """Save file to disk"""
@@ -170,8 +174,8 @@ class Settings:
170
174
  try:
171
175
  json.loads(data)
172
176
  except Exception as e:
173
- self.window.update_status("This is not a valid JSON: {}".format(e))
174
- self.window.ui.dialogs.alert("This is not a valid JSON: {}".format(e))
177
+ self.window.update_status(f"This is not a valid JSON: {e}")
178
+ self.window.ui.dialogs.alert(f"This is not a valid JSON: {e}")
175
179
  return
176
180
  path = os.path.join(self.window.core.config.get_user_path(), file)
177
181
  elif file.endswith('.css'):
@@ -189,22 +193,48 @@ class Settings:
189
193
  backup_path = os.path.join(self.window.core.config.get_user_path(), backup_file)
190
194
  if os.path.isfile(path):
191
195
  shutil.copyfile(path, backup_path)
192
- self.window.update_status("Created backup file: {}".format(backup_file))
196
+ self.window.update_status(f"Created backup file: {backup_file}")
197
+
198
+ prev_content = None
199
+ if os.path.isfile(path):
200
+ try:
201
+ with open(path, 'r', encoding="utf-8") as f:
202
+ prev_content = f.read()
203
+ except Exception as e:
204
+ pass
193
205
 
194
206
  # save changes to current file
195
207
  try:
196
208
  with open(path, 'w', encoding="utf-8") as f:
197
209
  f.write(data)
198
- self.window.update_status("Saved file: {}".format(path))
199
- self.window.ui.dialogs.alert("Saved file: {}".format(path))
210
+ self.window.update_status(f"Saved file: {path}")
211
+ except Exception as e:
212
+ self.window.core.debug.log(e)
213
+ self.window.update_status(f"Error saving file: {path}")
214
+ return # abort if error
215
+
216
+ if prev_content == data:
217
+ self.window.update_status(f"Saved file: {path}")
218
+ self.window.ui.dialogs.alert(f"Saved file: {path}")
219
+ return # no changes made, no need to reload
220
+
221
+ if file in ("config.json", "models.json") or file.endswith('.css'):
222
+ self.window.update_status(trans("status.reloading"))
223
+
224
+ QApplication.processEvents() # process events to update UI
225
+
226
+ try:
200
227
  if file == "config.json":
201
228
  self.window.core.config.load_config() # reload config
202
229
  elif file == "models.json":
203
230
  self.window.core.models.load() # reload models
204
231
  elif file.endswith('.css'):
205
- event = RenderEvent(RenderEvent.ON_THEME_CHANGE)
206
- self.window.dispatch(event)
232
+ self.window.dispatch(RenderEvent(RenderEvent.ON_THEME_CHANGE))
207
233
  self.window.controller.theme.reload(force=True) # reload theme
234
+ self.window.update_status(f"Saved file: {path}")
235
+ self.window.ui.dialogs.alert(f"Saved file: {path}")
208
236
  except Exception as e:
209
237
  self.window.core.debug.log(e)
210
- self.window.update_status("Error saving file: {}".format(path))
238
+ self.window.update_status(f"Error reloading saved file: {path}")
239
+
240
+
@@ -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 18:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import uuid
@@ -559,6 +559,19 @@ class Tabs:
559
559
  tab.tooltip = tabs.tabToolTip(tab.idx)
560
560
  tab.updated_at = datetime.now()
561
561
 
562
+ def insert_tab(self, tabs, tab: Tab) -> int:
563
+ """
564
+ Insert tab into the specified tab widget
565
+
566
+ :param tabs: Tabs instance
567
+ :param tab: Tab instance
568
+ :return: new index of the tab
569
+ """
570
+ if tab.new_idx is not None:
571
+ return tabs.insertTab(tab.new_idx, tab.child, tab.title)
572
+ else:
573
+ return tabs.addTab(tab.child, tab.title)
574
+
562
575
  def add_chat(self, tab: Tab):
563
576
  """
564
577
  Add chat tab
@@ -569,10 +582,7 @@ class Tabs:
569
582
  tabs = column.get_tabs()
570
583
  tab.parent = column
571
584
  tab.child = self.window.core.ctx.container.get(tab) # tab is already appended here
572
- if tab.new_idx is not None:
573
- tab.idx = tabs.insertTab(tab.new_idx, tab.child, tab.title)
574
- else:
575
- tab.idx = tabs.addTab(tab.child, tab.title)
585
+ tab.idx = self.insert_tab(tabs, tab)
576
586
  tab.child.setOwner(tab)
577
587
  tabs.setTabIcon(tab.idx, QIcon(tab.icon))
578
588
  if tab.tooltip is not None:
@@ -593,10 +603,7 @@ class Tabs:
593
603
  idx = tab.data_id # restore prev idx
594
604
  tab.child, idx, data_id = self.window.controller.notepad.create(idx, tab)
595
605
  tab.data_id = data_id # notepad idx in db, enumerated from 1
596
- if tab.new_idx is not None:
597
- tab.idx = tabs.insertTab(tab.new_idx, tab.child, tab.title)
598
- else:
599
- tab.idx = tabs.addTab(tab.child, tab.title)
606
+ tab.idx = self.insert_tab(tabs, tab)
600
607
  tab.child.setOwner(tab)
601
608
  tabs.setTabIcon(tab.idx, QIcon(tab.icon))
602
609
  if tab.tooltip is not None:
@@ -612,7 +619,7 @@ class Tabs:
612
619
  tabs = column.get_tabs()
613
620
  tab.parent = column
614
621
  tab.child = self.window.ui.chat.output.explorer.setup()
615
- tab.idx = tabs.addTab(tab.child, tab.title)
622
+ tab.idx = self.insert_tab(tabs, tab)
616
623
  tab.child.setOwner(tab)
617
624
  tabs.setTabIcon(tab.idx, QIcon(tab.icon))
618
625
  if tab.tooltip is not None:
@@ -629,7 +636,7 @@ class Tabs:
629
636
  tab.parent = column
630
637
  tab.child = self.window.ui.chat.output.painter.setup()
631
638
  tab.child.append(self.window.ui.painter)
632
- tab.idx = tabs.addTab(tab.child, tab.title)
639
+ tab.idx = self.insert_tab(tabs, tab)
633
640
  tab.child.setOwner(tab)
634
641
  tabs.setTabIcon(tab.idx, QIcon(tab.icon))
635
642
  if tab.tooltip is not None:
@@ -645,7 +652,7 @@ class Tabs:
645
652
  tabs = column.get_tabs()
646
653
  tab.parent = column
647
654
  tab.child = self.window.ui.chat.output.calendar.setup()
648
- tab.idx = tabs.addTab(tab.child, tab.title)
655
+ tab.idx = self.insert_tab(tabs, tab)
649
656
  tab.child.setOwner(tab)
650
657
  tabs.setTabIcon(tab.idx, QIcon(tab.icon))
651
658
  if tab.tooltip is not None:
@@ -669,7 +676,7 @@ class Tabs:
669
676
  tab.title = trans(tool.tab_title)
670
677
  tab.parent = column
671
678
  tab.child = self.from_widget(widget)
672
- tab.idx = tabs.addTab(tab.child, tab.title)
679
+ tab.idx = self.insert_tab(tabs, tab)
673
680
  tab.child.setOwner(tab)
674
681
  tabs.setTabIcon(tab.idx, QIcon(tab.icon))
675
682
  if tab.tooltip is not None:
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.6.21",
4
- "app.version": "2.6.21",
5
- "updated_at": "2025-08-24T00:00:00"
3
+ "version": "2.6.22",
4
+ "app.version": "2.6.22",
5
+ "updated_at": "2025-08-25T00:00:00"
6
6
  },
7
7
  "access.audio.event.speech": false,
8
8
  "access.audio.event.speech.disabled": [],
@@ -422,7 +422,7 @@
422
422
  }
423
423
  },
424
424
  "temperature": 1.0,
425
- "theme": "dark",
425
+ "theme": "dark_darker",
426
426
  "theme.markdown": true,
427
427
  "theme.style": "chatgpt",
428
428
  "top_p": 1.0,
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.6.21",
4
- "app.version": "2.6.21",
5
- "updated_at": "2025-08-24T23:07:35"
3
+ "version": "2.6.22",
4
+ "app.version": "2.6.22",
5
+ "updated_at": "2025-08-25T23:07:35"
6
6
  },
7
7
  "items": {
8
8
  "SpeakLeash/bielik-11b-v2.3-instruct:Q4_K_M": {
@@ -1347,6 +1347,9 @@ status.preset.deleted = Voreinstellung gelöscht
1347
1347
  status.preset.duplicated = Voreinstellung dupliziert
1348
1348
  status.preset.empty_id = WARNUNG: Voreinstellungs-ID (Dateiname) ist leer! Abbruch...
1349
1349
  status.preset.saved = Voreinstellung gespeichert
1350
+ status.reloading = Aktualisieren... Bitte warten
1351
+ status.reloading.profile.begin = Aktualisieren der Komponenten... bitte warten...
1352
+ status.reloading.profile.end = [OK] Komponenten erfolgreich aktualisiert.
1350
1353
  status.saved = Gespeichert
1351
1354
  status.sending = Bitte warten...
1352
1355
  status.started = Bereit
@@ -1356,7 +1359,7 @@ status.tokens = Token
1356
1359
  status.uploaded = Dateien hochgeladen
1357
1360
  status.uploading = Dateien hochladen...
1358
1361
  tab.close_all.confirm = Bist du sicher, dass du alle Tabs schließen möchtest?
1359
- text.context_menu.audio.read = Ausgewählten Text vorlesen (Sprachsynthese)...
1362
+ text.context_menu.audio.read = Lesen (Sprachsynthese)
1360
1363
  text.context_menu.copy_to = Kopieren zu...
1361
1364
  text.context_menu.copy_to.calendar = Kalender
1362
1365
  text.context_menu.copy_to.input = Eingabe
@@ -1359,6 +1359,9 @@ status.preset.deleted = Preset has been deleted.
1359
1359
  status.preset.duplicated = Preset has been duplicated.
1360
1360
  status.preset.empty_id = WARNING: Preset ID (filename) is empty! Aborting...
1361
1361
  status.preset.saved = Preset has been saved.
1362
+ status.reloading = Reloading... Please wait
1363
+ status.reloading.profile.begin = Reloading components... please wait...
1364
+ status.reloading.profile.end = [OK] Components reloaded successfully.
1362
1365
  status.saved = Saved
1363
1366
  status.sending = Please wait...
1364
1367
  status.started = Ready
@@ -1368,7 +1371,7 @@ status.tokens = Tokens
1368
1371
  status.uploaded = Files have been uploaded
1369
1372
  status.uploading = Uploading files...
1370
1373
  tab.close_all.confirm = Are you sure you want to close all tabs?
1371
- text.context_menu.audio.read = Read selected text (speech synthesis)...
1374
+ text.context_menu.audio.read = Read (speech synthesis)
1372
1375
  text.context_menu.copy_to = Copy to...
1373
1376
  text.context_menu.copy_to.calendar = Calendar
1374
1377
  text.context_menu.copy_to.input = Input
@@ -1348,6 +1348,9 @@ status.preset.deleted = Ajuste preestablecido eliminado
1348
1348
  status.preset.duplicated = Ajuste preestablecido duplicado
1349
1349
  status.preset.empty_id = ADVERTENCIA: ¡El ID del ajuste preestablecido (nombre de archivo) está vacío! Abortando...
1350
1350
  status.preset.saved = Ajuste preestablecido guardado
1351
+ status.reloading = Actualizando... Por favor, espere
1352
+ status.reloading.profile.begin = Actualizando componentes... por favor, espere...
1353
+ status.reloading.profile.end = [OK] Componentes actualizados con éxito.
1351
1354
  status.saved = Guardado
1352
1355
  status.sending = Por favor, espere...
1353
1356
  status.started = Listo
@@ -1357,7 +1360,7 @@ status.tokens = Tokens
1357
1360
  status.uploaded = Archivos subidos
1358
1361
  status.uploading = Subiendo archivos...
1359
1362
  tab.close_all.confirm = ¿Estás seguro de cerrar todas las pestañas?
1360
- text.context_menu.audio.read = Leer texto seleccionado (síntesis de voz)...
1363
+ text.context_menu.audio.read = Leer (síntesis de voz)
1361
1364
  text.context_menu.copy_to = Copiar a...
1362
1365
  text.context_menu.copy_to.calendar = Calendario
1363
1366
  text.context_menu.copy_to.input = Entrada
@@ -1347,6 +1347,9 @@ status.preset.deleted = Préréglage supprimé
1347
1347
  status.preset.duplicated = Préréglage dupliqué
1348
1348
  status.preset.empty_id = ATTENTION : L'ID du préréglage (nom de fichier) est vide ! Annulation...
1349
1349
  status.preset.saved = Préréglage sauvegardé
1350
+ status.reloading = Actualisation... Veuillez patienter
1351
+ status.reloading.profile.begin = Actualisation des composants... veuillez patienter...
1352
+ status.reloading.profile.end = [OK] Composants actualisés avec succès.
1350
1353
  status.saved = Sauvegardé
1351
1354
  status.sending = Veuillez patienter...
1352
1355
  status.started = Prêt
@@ -1356,7 +1359,7 @@ status.tokens = Jetons
1356
1359
  status.uploaded = Les fichiers sont téléversés
1357
1360
  status.uploading = Téléversement des fichiers...
1358
1361
  tab.close_all.confirm = Êtes-vous sûr de vouloir fermer tous les onglets ?
1359
- text.context_menu.audio.read = Lire le texte sélectionné (synthèse vocale)...
1362
+ text.context_menu.audio.read = Lire (synthèse vocale)
1360
1363
  text.context_menu.copy_to = Copier vers...
1361
1364
  text.context_menu.copy_to.calendar = Calendrier
1362
1365
  text.context_menu.copy_to.input = Entrée
@@ -1347,6 +1347,9 @@ status.preset.deleted = Preset cancellato.
1347
1347
  status.preset.duplicated = Preset duplicato.
1348
1348
  status.preset.empty_id = ATTENZIONE: ID del preset (nome del file) vuoto! Annullamento...
1349
1349
  status.preset.saved = Preset salvato.
1350
+ status.reloading = Aggiornamento in corso... Attendere
1351
+ status.reloading.profile.begin = Aggiornamento dei componenti... attendere...
1352
+ status.reloading.profile.end = [OK] Componenti aggiornati con successo.
1350
1353
  status.saved = Salvato.
1351
1354
  status.sending = Attendere...
1352
1355
  status.started = Pronto.
@@ -1356,7 +1359,7 @@ status.tokens = Token.
1356
1359
  status.uploaded = I file sono stati caricati.
1357
1360
  status.uploading = Caricamento dei file...
1358
1361
  tab.close_all.confirm = Sei sicuro di voler chiudere tutte le schede?
1359
- text.context_menu.audio.read = Leggi il testo selezionato (sintesi vocale)...
1362
+ text.context_menu.audio.read = Leggi (sintesi vocale)
1360
1363
  text.context_menu.copy_to = Copia a...
1361
1364
  text.context_menu.copy_to.calendar = Calendario
1362
1365
  text.context_menu.copy_to.input = Input
@@ -1,6 +1,4 @@
1
1
  [LOCALE]
2
-
3
-
4
2
  about.btn.github = GitHub
5
3
  about.btn.support = Wsparcie
6
4
  about.btn.website = WWW
@@ -1344,12 +1342,15 @@ status.evaluating = Proszę czekać... ocena w toku...
1344
1342
  status.finished = Zakończono.
1345
1343
  status.img.generated = Obraz został wygenerowany.
1346
1344
  status.img.saved = Obraz został zapisany
1347
- status.loading = Ładowanie... Proszę czekać
1345
+ status.loading = Ładowanie... Proszę czekać
1348
1346
  status.preset.cleared = Preset wyczyszczony
1349
1347
  status.preset.deleted = Preset usunięty
1350
1348
  status.preset.duplicated = Preset skopiowany
1351
1349
  status.preset.empty_id = Uwaga: nie podano ID dla presetu!
1352
1350
  status.preset.saved = Preset zapisany
1351
+ status.reloading = Odświeżanie... Proszę czekać
1352
+ status.reloading.profile.begin = Odświeżanie komponentów... proszę czekać...
1353
+ status.reloading.profile.end = [OK] Komponenty zostały pomyślnie odświeżone.
1353
1354
  status.saved = Zapisano
1354
1355
  status.sending = Czekaj...
1355
1356
  status.started = Gotowy
@@ -1359,7 +1360,7 @@ status.tokens = Tokenów
1359
1360
  status.uploaded = Pliki wgrane na serwer
1360
1361
  status.uploading = Upload plików...
1361
1362
  tab.close_all.confirm = Czy na pewno chcesz zamknąć wszystkie karty?
1362
- text.context_menu.audio.read = Przeczytaj (synteza mowy)...
1363
+ text.context_menu.audio.read = Czytaj (synteza mowy)
1363
1364
  text.context_menu.copy_to = Kopiuj do...
1364
1365
  text.context_menu.copy_to.calendar = Kalendarz
1365
1366
  text.context_menu.copy_to.input = Wejście (input)
@@ -1347,6 +1347,9 @@ status.preset.deleted = Пресет видалено
1347
1347
  status.preset.duplicated = Пресет дубльовано
1348
1348
  status.preset.empty_id = УВАГА: ID пресету (ім'я файлу) порожній! Скасовано...
1349
1349
  status.preset.saved = Пресет збережено
1350
+ status.reloading = Оновлення... Будь ласка, зачекайте
1351
+ status.reloading.profile.begin = Оновлення компонентів... будь ласка, зачекайте...
1352
+ status.reloading.profile.end = [OK] Компоненти успішно оновлено.
1350
1353
  status.saved = Збережено
1351
1354
  status.sending = Будь ласка, зачекайте...
1352
1355
  status.started = Готово
@@ -1356,7 +1359,7 @@ status.tokens = Токени
1356
1359
  status.uploaded = Файли завантажено
1357
1360
  status.uploading = Вивантаження файлів...
1358
1361
  tab.close_all.confirm = Ви впевнені, що хочете закрити всі вкладки?
1359
- text.context_menu.audio.read = Читати вибраний текст (синтез мовлення)...
1362
+ text.context_menu.audio.read = Читати (синтез мови)
1360
1363
  text.context_menu.copy_to = Копіювати до...
1361
1364
  text.context_menu.copy_to.calendar = Календар
1362
1365
  text.context_menu.copy_to.input = Введення
@@ -1347,6 +1347,9 @@ status.preset.deleted = 预设已删除。
1347
1347
  status.preset.duplicated = 预设已复制。
1348
1348
  status.preset.empty_id = 警告:预设 ID(文件名)为空!正在中止...
1349
1349
  status.preset.saved = 预设已保存。
1350
+ status.reloading = 正在刷新... 请稍候
1351
+ status.reloading.profile.begin = 正在刷新组件... 请稍候...
1352
+ status.reloading.profile.end = [OK] 组件刷新成功。
1350
1353
  status.saved = 已保存
1351
1354
  status.sending = 请稍候...
1352
1355
  status.started = 准备好
@@ -1356,7 +1359,7 @@ status.tokens = 令牌
1356
1359
  status.uploaded = 文件已上傳
1357
1360
  status.uploading = 正在上傳文件...
1358
1361
  tab.close_all.confirm = 确定要关闭所有标签页吗?
1359
- text.context_menu.audio.read = 閱讀選定文本(語音合成)...
1362
+ text.context_menu.audio.read = 阅读(语音合成)
1360
1363
  text.context_menu.copy_to = 複製到...
1361
1364
  text.context_menu.copy_to.calendar = 日曆
1362
1365
  text.context_menu.copy_to.input = 輸入
@@ -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.15 23:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.plugin.base.plugin import BasePlugin
@@ -20,7 +20,7 @@ class Plugin(BasePlugin):
20
20
  def __init__(self, *args, **kwargs):
21
21
  super(Plugin, self).__init__(*args, **kwargs)
22
22
  self.id = "twitter"
23
- self.name = "Twitter/X"
23
+ self.name = "X/Twitter"
24
24
  self.description = "Interact with tweets and users, manage bookmarks and media, perform likes, retweets, and more."
25
25
  self.prefix = "API"
26
26
  self.order = 100
@@ -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