pygpt-net 2.7.9__py3-none-any.whl → 2.7.10__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 (102) hide show
  1. pygpt_net/CHANGELOG.txt +9 -0
  2. pygpt_net/LICENSE +1 -1
  3. pygpt_net/__init__.py +3 -3
  4. pygpt_net/config.py +15 -1
  5. pygpt_net/controller/chat/common.py +5 -4
  6. pygpt_net/controller/chat/image.py +3 -3
  7. pygpt_net/controller/chat/stream.py +76 -41
  8. pygpt_net/controller/chat/stream_worker.py +3 -3
  9. pygpt_net/controller/ctx/extra.py +3 -1
  10. pygpt_net/controller/dialogs/debug.py +37 -8
  11. pygpt_net/controller/kernel/kernel.py +3 -7
  12. pygpt_net/controller/lang/custom.py +25 -12
  13. pygpt_net/controller/lang/lang.py +45 -3
  14. pygpt_net/controller/lang/mapping.py +15 -2
  15. pygpt_net/controller/notepad/notepad.py +68 -25
  16. pygpt_net/controller/presets/editor.py +5 -1
  17. pygpt_net/controller/presets/presets.py +17 -5
  18. pygpt_net/controller/theme/theme.py +11 -2
  19. pygpt_net/controller/ui/tabs.py +1 -1
  20. pygpt_net/core/ctx/output.py +38 -12
  21. pygpt_net/core/db/database.py +4 -2
  22. pygpt_net/core/debug/console/console.py +30 -2
  23. pygpt_net/core/debug/context.py +2 -1
  24. pygpt_net/core/debug/ui.py +26 -4
  25. pygpt_net/core/filesystem/filesystem.py +6 -2
  26. pygpt_net/core/notepad/notepad.py +2 -2
  27. pygpt_net/core/tabs/tabs.py +79 -19
  28. pygpt_net/data/config/config.json +3 -3
  29. pygpt_net/data/config/models.json +3 -3
  30. pygpt_net/data/config/settings.json +12 -0
  31. pygpt_net/data/locale/locale.ar.ini +1833 -0
  32. pygpt_net/data/locale/locale.bg.ini +1833 -0
  33. pygpt_net/data/locale/locale.cs.ini +1833 -0
  34. pygpt_net/data/locale/locale.da.ini +1833 -0
  35. pygpt_net/data/locale/locale.de.ini +4 -1
  36. pygpt_net/data/locale/locale.en.ini +70 -67
  37. pygpt_net/data/locale/locale.es.ini +4 -1
  38. pygpt_net/data/locale/locale.fi.ini +1833 -0
  39. pygpt_net/data/locale/locale.fr.ini +4 -1
  40. pygpt_net/data/locale/locale.he.ini +1833 -0
  41. pygpt_net/data/locale/locale.hi.ini +1833 -0
  42. pygpt_net/data/locale/locale.hu.ini +1833 -0
  43. pygpt_net/data/locale/locale.it.ini +4 -1
  44. pygpt_net/data/locale/locale.ja.ini +1833 -0
  45. pygpt_net/data/locale/locale.ko.ini +1833 -0
  46. pygpt_net/data/locale/locale.nl.ini +1833 -0
  47. pygpt_net/data/locale/locale.no.ini +1833 -0
  48. pygpt_net/data/locale/locale.pl.ini +5 -2
  49. pygpt_net/data/locale/locale.pt.ini +1833 -0
  50. pygpt_net/data/locale/locale.ro.ini +1833 -0
  51. pygpt_net/data/locale/locale.ru.ini +1833 -0
  52. pygpt_net/data/locale/locale.sk.ini +1833 -0
  53. pygpt_net/data/locale/locale.sv.ini +1833 -0
  54. pygpt_net/data/locale/locale.tr.ini +1833 -0
  55. pygpt_net/data/locale/locale.uk.ini +4 -1
  56. pygpt_net/data/locale/locale.zh.ini +4 -1
  57. pygpt_net/item/notepad.py +8 -2
  58. pygpt_net/migrations/Version20260121190000.py +25 -0
  59. pygpt_net/migrations/Version20260122140000.py +25 -0
  60. pygpt_net/migrations/__init__.py +5 -1
  61. pygpt_net/preload.py +246 -3
  62. pygpt_net/provider/api/__init__.py +16 -2
  63. pygpt_net/provider/api/anthropic/__init__.py +21 -7
  64. pygpt_net/provider/api/google/__init__.py +21 -7
  65. pygpt_net/provider/api/google/image.py +89 -2
  66. pygpt_net/provider/api/google/video.py +2 -2
  67. pygpt_net/provider/api/openai/__init__.py +26 -11
  68. pygpt_net/provider/api/openai/image.py +79 -3
  69. pygpt_net/provider/api/openai/responses.py +11 -31
  70. pygpt_net/provider/api/openai/video.py +2 -2
  71. pygpt_net/provider/api/x_ai/__init__.py +21 -7
  72. pygpt_net/provider/core/notepad/db_sqlite/storage.py +53 -10
  73. pygpt_net/tools/agent_builder/ui/dialogs.py +2 -1
  74. pygpt_net/tools/audio_transcriber/ui/dialogs.py +2 -1
  75. pygpt_net/tools/code_interpreter/ui/dialogs.py +2 -1
  76. pygpt_net/tools/html_canvas/ui/dialogs.py +2 -1
  77. pygpt_net/tools/image_viewer/ui/dialogs.py +3 -5
  78. pygpt_net/tools/indexer/ui/dialogs.py +2 -1
  79. pygpt_net/tools/media_player/ui/dialogs.py +2 -1
  80. pygpt_net/tools/translator/ui/dialogs.py +2 -1
  81. pygpt_net/tools/translator/ui/widgets.py +6 -2
  82. pygpt_net/ui/dialog/about.py +2 -2
  83. pygpt_net/ui/dialog/db.py +2 -1
  84. pygpt_net/ui/dialog/debug.py +169 -6
  85. pygpt_net/ui/dialog/logger.py +6 -2
  86. pygpt_net/ui/dialog/models.py +36 -3
  87. pygpt_net/ui/dialog/preset.py +5 -1
  88. pygpt_net/ui/dialog/remote_store.py +2 -1
  89. pygpt_net/ui/main.py +3 -2
  90. pygpt_net/ui/widget/dialog/editor_file.py +2 -1
  91. pygpt_net/ui/widget/lists/debug.py +12 -7
  92. pygpt_net/ui/widget/option/checkbox.py +2 -8
  93. pygpt_net/ui/widget/option/combo.py +10 -2
  94. pygpt_net/ui/widget/textarea/console.py +156 -7
  95. pygpt_net/ui/widget/textarea/highlight.py +66 -0
  96. pygpt_net/ui/widget/textarea/input.py +624 -57
  97. pygpt_net/ui/widget/textarea/notepad.py +294 -27
  98. {pygpt_net-2.7.9.dist-info → pygpt_net-2.7.10.dist-info}/LICENSE +1 -1
  99. {pygpt_net-2.7.9.dist-info → pygpt_net-2.7.10.dist-info}/METADATA +11 -64
  100. {pygpt_net-2.7.9.dist-info → pygpt_net-2.7.10.dist-info}/RECORD +102 -81
  101. {pygpt_net-2.7.9.dist-info → pygpt_net-2.7.10.dist-info}/WHEEL +0 -0
  102. {pygpt_net-2.7.9.dist-info → pygpt_net-2.7.10.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.09.16 22:00:00 #
9
+ # Updated Date: 2026.01.21 12:30:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import uuid
@@ -59,16 +59,49 @@ class Tabs:
59
59
  column_idx: int = 0
60
60
  ) -> Optional[Tab]:
61
61
  """
62
- Get tab by index
62
+ Get tab by index (robust, with late owner binding fallback)
63
63
 
64
64
  :param idx: Tab index
65
65
  :param column_idx: Column index
66
66
  :return: Tab
67
67
  """
68
- tab = self.window.ui.layout.get_tabs_by_idx(column_idx).widget(idx)
69
- if tab is None:
68
+ tabs_widget = self.window.ui.layout.get_tabs_by_idx(column_idx)
69
+ if tabs_widget is None:
70
+ return None
71
+
72
+ child = tabs_widget.widget(idx)
73
+ if child is not None:
74
+ # try direct owner first
75
+ try:
76
+ tab = child.getOwner()
77
+ except Exception:
78
+ tab = None
79
+
80
+ if tab is not None:
81
+ return tab
82
+
83
+ # late owner binding: match by object identity
84
+ for t in self.pids.values():
85
+ if t.child is child:
86
+ if hasattr(child, "setOwner"):
87
+ child.setOwner(t)
88
+ return t
89
+
90
+ # fallback: match by (column_idx, idx) if child reference is not yet available
91
+ for t in self.pids.values():
92
+ if t.column_idx == column_idx and getattr(t, "idx", -1) == idx:
93
+ if hasattr(child, "setOwner"):
94
+ child.setOwner(t)
95
+ return t
96
+
70
97
  return None
71
- return tab.getOwner()
98
+
99
+ # child is None -> fallback by (column_idx, idx)
100
+ for t in self.pids.values():
101
+ if t.column_idx == column_idx and getattr(t, "idx", -1) == idx:
102
+ return t
103
+
104
+ return None
72
105
 
73
106
  def get_tab_by_pid(self, pid: int) -> Optional[Tab]:
74
107
  """
@@ -139,6 +172,8 @@ class Tabs:
139
172
  tab.data_id = data_id
140
173
  tab.tool_id = tool_id
141
174
 
175
+ self.pids[tab.pid] = tab
176
+
142
177
  if type == Tab.TAB_CHAT:
143
178
  self.add_chat(tab)
144
179
  elif type == Tab.TAB_NOTEPAD:
@@ -152,7 +187,6 @@ class Tabs:
152
187
  elif type == Tab.TAB_TOOL:
153
188
  self.add_tool(tab)
154
189
 
155
- self.pids[tab.pid] = tab
156
190
  return tab
157
191
 
158
192
  def append(
@@ -185,10 +219,21 @@ class Tabs:
185
219
  tab.type = type
186
220
  tab.title = title
187
221
  tab.icon = icon
188
- tab.new_idx = idx + 1 # place on right side
222
+
223
+ # compute a safe insertion index within the target column
224
+ tabs_widget = self.window.ui.layout.get_tabs_by_idx(column_idx)
225
+ count = tabs_widget.count() if tabs_widget is not None else 0
226
+ if count == 0:
227
+ safe_new_idx = 0
228
+ else:
229
+ safe_new_idx = min(idx + 1, count)
230
+
231
+ tab.new_idx = safe_new_idx # final insertion index
189
232
  tab.column_idx = column_idx
190
233
  tab.tool_id = tool_id
191
234
 
235
+ self.pids[tab.pid] = tab
236
+
192
237
  if type == Tab.TAB_CHAT:
193
238
  self.add_chat(tab)
194
239
  elif type == Tab.TAB_NOTEPAD:
@@ -196,7 +241,6 @@ class Tabs:
196
241
  elif type == Tab.TAB_TOOL:
197
242
  self.add_tool(tab)
198
243
 
199
- self.pids[tab.pid] = tab
200
244
  self.update()
201
245
 
202
246
  # load data from db
@@ -233,6 +277,8 @@ class Tabs:
233
277
  if tab.type in self.icons:
234
278
  tab.icon = self.icons[tab.type]
235
279
 
280
+ self.pids[tab.pid] = tab
281
+
236
282
  if tab.type == Tab.TAB_CHAT: # chat
237
283
  try:
238
284
  self.add_chat(tab)
@@ -243,7 +289,7 @@ class Tabs:
243
289
  print("Error restoring chat tab:", e)
244
290
  elif tab.type == Tab.TAB_NOTEPAD: # notepad
245
291
  try:
246
- self.add_notepad(tab)
292
+ self.add_notepad(tab, restore=True) # without creating new
247
293
  except Exception as e:
248
294
  print("Error restoring notepad tab:", e)
249
295
  elif tab.type == Tab.TAB_FILES: # files
@@ -267,7 +313,6 @@ class Tabs:
267
313
  except Exception as e:
268
314
  print("Error restoring tool tab:", e)
269
315
 
270
- self.pids[tab.pid] = tab
271
316
  self.last_pid = self.get_max_pid()
272
317
 
273
318
  def remove_tab_by_idx(
@@ -619,18 +664,28 @@ class Tabs:
619
664
  column = self.window.ui.layout.get_column_by_idx(tab.column_idx)
620
665
  tabs = column.get_tabs()
621
666
  tab.parent = column
622
- tab.child = self.window.core.ctx.container.get(tab) # tab is already appended here
667
+ tab.child = self.window.core.ctx.container.get(tab)
668
+
669
+ # ensure owner is set on the page widget even before insertion
670
+ if hasattr(tab.child, "setOwner"):
671
+ tab.child.setOwner(tab)
672
+
623
673
  tab.idx = self.insert_tab(tabs, tab)
624
- tab.child.setOwner(tab)
674
+
675
+ # set again after insertion to be 100% sure the widget in the stack has owner set
676
+ if hasattr(tab.child, "setOwner"):
677
+ tab.child.setOwner(tab)
678
+
625
679
  tabs.setTabIcon(tab.idx, QIcon(tab.icon))
626
680
  if tab.tooltip is not None:
627
681
  tabs.setTabToolTip(tab.idx, tab.tooltip)
628
682
 
629
- def add_notepad(self, tab: Tab):
683
+ def add_notepad(self, tab: Tab, restore: bool = False):
630
684
  """
631
685
  Add notepad tab
632
686
 
633
687
  :param tab: Tab instance
688
+ :param restore: Restore only (do not try to create new)
634
689
  """
635
690
  idx = None
636
691
  column = self.window.ui.layout.get_column_by_idx(tab.column_idx)
@@ -639,10 +694,11 @@ class Tabs:
639
694
  tab.parent = tabs.get_column()
640
695
  if tab.data_id is not None:
641
696
  idx = tab.data_id # restore prev idx
642
- tab.child, idx, data_id = self.window.controller.notepad.create(idx, tab)
697
+ tab.child, idx, data_id = self.window.controller.notepad.create(idx, tab, restore=restore)
643
698
  tab.data_id = data_id # notepad idx in db, enumerated from 1
644
699
  tab.idx = self.insert_tab(tabs, tab)
645
- tab.child.setOwner(tab)
700
+ if hasattr(tab.child, "setOwner"):
701
+ tab.child.setOwner(tab)
646
702
  tabs.setTabIcon(tab.idx, QIcon(tab.icon))
647
703
  if tab.tooltip is not None:
648
704
  tabs.setTabToolTip(tab.idx, tab.tooltip)
@@ -658,7 +714,8 @@ class Tabs:
658
714
  tab.parent = column
659
715
  tab.child = self.window.ui.chat.output.explorer.setup()
660
716
  tab.idx = self.insert_tab(tabs, tab)
661
- tab.child.setOwner(tab)
717
+ if hasattr(tab.child, "setOwner"):
718
+ tab.child.setOwner(tab)
662
719
  tabs.setTabIcon(tab.idx, QIcon(tab.icon))
663
720
  if tab.tooltip is not None:
664
721
  tabs.setTabToolTip(tab.idx, tab.tooltip)
@@ -675,7 +732,8 @@ class Tabs:
675
732
  tab.child = self.window.ui.chat.output.painter.setup()
676
733
  tab.child.append(self.window.ui.painter)
677
734
  tab.idx = self.insert_tab(tabs, tab)
678
- tab.child.setOwner(tab)
735
+ if hasattr(tab.child, "setOwner"):
736
+ tab.child.setOwner(tab)
679
737
  tabs.setTabIcon(tab.idx, QIcon(tab.icon))
680
738
  if tab.tooltip is not None:
681
739
  tabs.setTabToolTip(tab.idx, tab.tooltip)
@@ -691,7 +749,8 @@ class Tabs:
691
749
  tab.parent = column
692
750
  tab.child = self.window.ui.chat.output.calendar.setup()
693
751
  tab.idx = self.insert_tab(tabs, tab)
694
- tab.child.setOwner(tab)
752
+ if hasattr(tab.child, "setOwner"):
753
+ tab.child.setOwner(tab)
695
754
  tabs.setTabIcon(tab.idx, QIcon(tab.icon))
696
755
  if tab.tooltip is not None:
697
756
  tabs.setTabToolTip(tab.idx, tab.tooltip)
@@ -715,7 +774,8 @@ class Tabs:
715
774
  tab.parent = column
716
775
  tab.child = self.from_widget(widget)
717
776
  tab.idx = self.insert_tab(tabs, tab)
718
- tab.child.setOwner(tab)
777
+ if hasattr(tab.child, "setOwner"):
778
+ tab.child.setOwner(tab)
719
779
  tabs.setTabIcon(tab.idx, QIcon(tab.icon))
720
780
  if tab.tooltip is not None:
721
781
  tabs.setTabToolTip(tab.idx, tab.tooltip)
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.7.9",
4
- "app.version": "2.7.9",
5
- "updated_at": "2026-01-08T00:00:00"
3
+ "version": "2.7.10",
4
+ "app.version": "2.7.10",
5
+ "updated_at": "2026-01-22T00:00:00"
6
6
  },
7
7
  "access.audio.event.speech": false,
8
8
  "access.audio.event.speech.disabled": [],
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.7.9",
4
- "app.version": "2.7.9",
5
- "updated_at": "2026-01-08T00:00:00"
3
+ "version": "2.7.10",
4
+ "app.version": "2.7.10",
5
+ "updated_at": "2026-01-22T00:00:00"
6
6
  },
7
7
  "items": {
8
8
  "SpeakLeash/bielik-11b-v2.3-instruct:Q4_K_M": {
@@ -915,6 +915,9 @@
915
915
  "section": "files",
916
916
  "type": "combo",
917
917
  "use": "models",
918
+ "use_params": {
919
+ "mode": ["chat"]
920
+ },
918
921
  "slider": false,
919
922
  "label": "settings.ctx.attachment.summary.model",
920
923
  "description": "settings.ctx.attachment.summary.model.desc",
@@ -929,6 +932,9 @@
929
932
  "section": "files",
930
933
  "type": "combo",
931
934
  "use": "models",
935
+ "use_params": {
936
+ "mode": ["chat"]
937
+ },
932
938
  "slider": false,
933
939
  "label": "settings.ctx.attachment.query.model",
934
940
  "description": "settings.ctx.attachment.query.model.desc",
@@ -994,6 +1000,9 @@
994
1000
  "section": "ctx",
995
1001
  "type": "combo",
996
1002
  "use": "models",
1003
+ "use_params": {
1004
+ "mode": ["chat"]
1005
+ },
997
1006
  "slider": false,
998
1007
  "label": "settings.ctx.auto_summary.model",
999
1008
  "description": "settings.ctx.auto_summary.model.desc",
@@ -1538,6 +1547,9 @@
1538
1547
  "section": "images",
1539
1548
  "type": "combo",
1540
1549
  "use": "models",
1550
+ "use_params": {
1551
+ "mode": ["chat"]
1552
+ },
1541
1553
  "slider": false,
1542
1554
  "label": "settings.img_prompt_model",
1543
1555
  "description": "settings.img_prompt_model.desc",