pygpt-net 2.6.46__py3-none-any.whl → 2.6.47__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.
pygpt_net/CHANGELOG.txt CHANGED
@@ -1,3 +1,8 @@
1
+ 2.6.47 (2025-09-15)
2
+
3
+ - Improved: Parsing of custom markup tags.
4
+ - Optimized: Switching profiles.
5
+
1
6
  2.6.46 (2025-09-15)
2
7
 
3
8
  - Added: Global proxy settings for all API SDKs.
pygpt_net/__init__.py CHANGED
@@ -13,7 +13,7 @@ __author__ = "Marcin Szczygliński"
13
13
  __copyright__ = "Copyright 2025, Marcin Szczygliński"
14
14
  __credits__ = ["Marcin Szczygliński"]
15
15
  __license__ = "MIT"
16
- __version__ = "2.6.46"
16
+ __version__ = "2.6.47"
17
17
  __build__ = "2025-09-15"
18
18
  __maintainer__ = "Marcin Szczygliński"
19
19
  __github__ = "https://github.com/szczyglis-dev/py-gpt"
pygpt_net/app.py CHANGED
@@ -35,6 +35,11 @@ os.environ["QTWEBENGINE_CHROMIUM_FLAGS"] = (
35
35
  "--js-flags=--expose-gc"
36
36
  )
37
37
  """
38
+ # by default, optimize for low-end devices
39
+ os.environ.setdefault(
40
+ "QTWEBENGINE_CHROMIUM_FLAGS",
41
+ "--enable-low-end-device-mode"
42
+ )
38
43
 
39
44
  _original_open = builtins.open
40
45
 
@@ -154,8 +154,6 @@ class Controller:
154
154
 
155
155
  print(trans("status.reloading.profile.begin"))
156
156
 
157
- prev_theme = self.window.core.config.get("theme")
158
-
159
157
  self.window.core.reload() # db, config, patch, etc.
160
158
  self.ui.tabs.reload()
161
159
  self.ctx.reload()
@@ -183,7 +181,7 @@ class Controller:
183
181
  self.ctx.reload_after()
184
182
  self.ui.tabs.restore_data() # restore opened tabs data
185
183
  self.kernel.restart()
186
- self.theme.reload_all(prev_theme=prev_theme) # do not reload theme if no change
184
+ self.theme.reload_all() # do not reload theme if no change
187
185
 
188
186
  self.reloading = False # unlock
189
187
  self.presets.unlock()
@@ -449,6 +449,8 @@ class Audio:
449
449
  if is_enabled:
450
450
  # show/hide extra options
451
451
  tab = self.window.controller.ui.tabs.get_current_tab()
452
+ if not tab:
453
+ return
452
454
  if tab.type == Tab.TAB_NOTEPAD:
453
455
  self.window.controller.audio.ui.on_input_continuous_enable("input")
454
456
  else:
@@ -92,7 +92,8 @@ class Text:
92
92
 
93
93
  # create ctx item
94
94
  meta = core.ctx.get_current_meta()
95
- meta.preset = config.get("preset") # current preset
95
+ if meta:
96
+ meta.preset = config.get("preset") # current preset
96
97
 
97
98
  ctx = CtxItem()
98
99
  ctx.meta = meta # CtxMeta (owner object)
@@ -105,8 +105,6 @@ class Notepad:
105
105
  :param body: TabBody instance
106
106
  """
107
107
  tab = body.owner
108
- if not tab.owner:
109
- return
110
108
  if tab.type != Tab.TAB_NOTEPAD:
111
109
  return
112
110
  idx = tab.data_id
@@ -34,6 +34,7 @@ class Theme:
34
34
  self.markdown = Markdown(window)
35
35
  self.menu = Menu(window)
36
36
  self.nodes = Nodes(window)
37
+ self.current_theme = None
37
38
 
38
39
  def setup(self):
39
40
  """Setup theme"""
@@ -192,7 +193,8 @@ class Theme:
192
193
 
193
194
  :param force: force theme change (manual trigger)
194
195
  """
195
- self.toggle(self.window.core.config.get('theme'), force=force)
196
+ self.current_theme = self.window.core.config.get('theme')
197
+ self.toggle(self.current_theme, force=force)
196
198
 
197
199
  def update_syntax(self):
198
200
  """Update syntax menu"""
@@ -280,13 +282,11 @@ class Theme:
280
282
  """
281
283
  return self.common.get_style(element)
282
284
 
283
- def reload_all(self, prev_theme: Optional[str] = None):
285
+ def reload_all(self):
284
286
  """
285
287
  Reload all
286
-
287
- :param prev_theme: previous theme name
288
288
  """
289
- if not prev_theme or prev_theme != self.window.core.config.get('theme'):
289
+ if self.current_theme != self.window.core.config.get('theme'):
290
290
  self.setup()
291
291
  self.update_style()
292
292
  self.update_syntax()
@@ -8,10 +8,11 @@
8
8
  # Created By : Marcin Szczygliński #
9
9
  # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
-
11
+ import gc
12
12
  from typing import Any, Optional, Tuple
13
13
 
14
- from PySide6.QtCore import QTimer
14
+ from PySide6.QtCore import QTimer, QUrl
15
+ from PySide6.QtWebEngineCore import QWebEnginePage
15
16
 
16
17
  from pygpt_net.core.events import AppEvent, RenderEvent
17
18
  from pygpt_net.core.tabs.tab import Tab
@@ -133,10 +134,47 @@ class Tabs:
133
134
 
134
135
  def reload(self):
135
136
  """Reload tabs"""
137
+ self.unload_current()
136
138
  self.window.core.tabs.reload()
137
139
  self.window.dispatch(RenderEvent(RenderEvent.PREPARE))
138
140
  self.debug()
139
141
 
142
+ def unload_current(self):
143
+ """Unload current tabs from memory"""
144
+ tabs = self.window.core.tabs.pids
145
+ for pid in tabs:
146
+ tab = self.window.core.tabs.get_tab_by_pid(pid)
147
+ if tab is not None:
148
+ try:
149
+ if tab.type == Tab.TAB_CHAT:
150
+ node = self.window.ui.nodes['output'].get(tab.pid)
151
+ if node:
152
+ node.hide()
153
+ p = node.page()
154
+ p.triggerAction(QWebEnginePage.Stop)
155
+ p.setUrl(QUrl("about:blank"))
156
+ p.history().clear()
157
+ p.setLifecycleState(QWebEnginePage.LifecycleState.Discarded)
158
+ tab.delete_ref(node)
159
+ layout = tab.child.layout()
160
+ layout.removeWidget(node)
161
+ self.window.ui.nodes['output'].pop(pid, None)
162
+ node.on_delete()
163
+ node_plain = self.window.ui.nodes['output_plain'].get(tab.pid)
164
+ if node_plain:
165
+ tab.delete_ref(node_plain)
166
+ layout = tab.child.layout()
167
+ layout.removeWidget(node_plain)
168
+ self.window.ui.nodes['output_plain'].pop(pid, None)
169
+ node_plain.on_delete()
170
+ tab.cleanup()
171
+ except Exception as e:
172
+ print(f"Error unloading tab {pid}: {e}")
173
+ try:
174
+ gc.collect()
175
+ except Exception:
176
+ pass
177
+
140
178
  def reload_after(self):
141
179
  """Reload tabs after"""
142
180
  w = self.window
@@ -210,6 +210,8 @@ class Renderer(BaseRenderer):
210
210
  :param meta: context meta
211
211
  """
212
212
  node = self.get_output_node(meta)
213
+ if not node:
214
+ return
213
215
  node.set_meta(meta)
214
216
  self.reset(meta)
215
217
  try:
@@ -109,7 +109,7 @@ class Tab:
109
109
  def cleanup(self):
110
110
  """Clean up on delete"""
111
111
  try:
112
- if self.on_delete:
112
+ if self.on_delete and callable(self.on_delete):
113
113
  self.on_delete(self)
114
114
  self.delete_refs()
115
115
  except Exception as e:
@@ -131,7 +131,7 @@ class Tab:
131
131
  Delete all references to widgets in this tab
132
132
  """
133
133
  # cleanup children
134
- if self.child:
134
+ if self.child and hasattr(self.child, 'cleanup'):
135
135
  self.child.cleanup()
136
136
 
137
137
  # cleanup parent
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.6.46",
4
- "app.version": "2.6.46",
3
+ "version": "2.6.47",
4
+ "app.version": "2.6.47",
5
5
  "updated_at": "2025-09-15T00:00:00"
6
6
  },
7
7
  "access.audio.event.speech": false,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.6.46",
4
- "app.version": "2.6.46",
3
+ "version": "2.6.47",
4
+ "app.version": "2.6.47",
5
5
  "updated_at": "2025-09-15T08:03:34"
6
6
  },
7
7
  "items": {