pygpt-net 2.6.48__py3-none-any.whl → 2.6.49__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 +4 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/controller/ctx/ctx.py +5 -3
- pygpt_net/controller/ui/tabs.py +4 -6
- pygpt_net/core/render/web/renderer.py +4 -10
- pygpt_net/core/tabs/tabs.py +7 -15
- pygpt_net/data/config/config.json +3 -3
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/tools/code_interpreter/ui/html.py +176 -31
- pygpt_net/tools/code_interpreter/ui/widgets.py +1 -4
- pygpt_net/tools/html_canvas/ui/widgets.py +2 -5
- pygpt_net/ui/widget/tabs/body.py +23 -1
- pygpt_net/ui/widget/textarea/web.py +85 -45
- {pygpt_net-2.6.48.dist-info → pygpt_net-2.6.49.dist-info}/METADATA +6 -2
- {pygpt_net-2.6.48.dist-info → pygpt_net-2.6.49.dist-info}/RECORD +18 -18
- {pygpt_net-2.6.48.dist-info → pygpt_net-2.6.49.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.48.dist-info → pygpt_net-2.6.49.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.48.dist-info → pygpt_net-2.6.49.dist-info}/entry_points.txt +0 -0
pygpt_net/CHANGELOG.txt
CHANGED
pygpt_net/__init__.py
CHANGED
|
@@ -6,15 +6,15 @@
|
|
|
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.
|
|
9
|
+
# Updated Date: 2025.09.16 00:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
__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.
|
|
17
|
-
__build__ = "2025-09-
|
|
16
|
+
__version__ = "2.6.49"
|
|
17
|
+
__build__ = "2025-09-16"
|
|
18
18
|
__maintainer__ = "Marcin Szczygliński"
|
|
19
19
|
__github__ = "https://github.com/szczyglis-dev/py-gpt"
|
|
20
20
|
__report__ = "https://github.com/szczyglis-dev/py-gpt/issues"
|
pygpt_net/controller/ctx/ctx.py
CHANGED
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.09.16 02:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import Optional, List
|
|
@@ -479,7 +479,8 @@ class Ctx:
|
|
|
479
479
|
id: int,
|
|
480
480
|
restore_model: bool = True,
|
|
481
481
|
select_idx: Optional[int] = None,
|
|
482
|
-
new_tab: Optional[bool] = False
|
|
482
|
+
new_tab: Optional[bool] = False,
|
|
483
|
+
no_fresh: bool = False
|
|
483
484
|
):
|
|
484
485
|
"""
|
|
485
486
|
Load ctx data
|
|
@@ -488,6 +489,7 @@ class Ctx:
|
|
|
488
489
|
:param restore_model: restore model if defined in ctx
|
|
489
490
|
:param select_idx: select index on list after loading
|
|
490
491
|
:param new_tab: open in new tab
|
|
492
|
+
:param no_fresh: do not fresh output
|
|
491
493
|
"""
|
|
492
494
|
if new_tab:
|
|
493
495
|
col_idx = self.window.controller.ui.tabs.column_idx
|
|
@@ -500,7 +502,7 @@ class Ctx:
|
|
|
500
502
|
if meta is not None:
|
|
501
503
|
self.set_group(meta.group_id)
|
|
502
504
|
|
|
503
|
-
if meta is not None:
|
|
505
|
+
if meta is not None and not no_fresh:
|
|
504
506
|
self.fresh_output(meta)
|
|
505
507
|
|
|
506
508
|
self.reload_config()
|
pygpt_net/controller/ui/tabs.py
CHANGED
|
@@ -6,14 +6,12 @@
|
|
|
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.
|
|
9
|
+
# Updated Date: 2025.09.16 02:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
|
-
import gc
|
|
12
|
-
from typing import Any, Optional, Tuple
|
|
13
11
|
|
|
14
|
-
from
|
|
15
|
-
from PySide6.QtWebEngineCore import QWebEnginePage
|
|
12
|
+
from typing import Any, Optional, Tuple
|
|
16
13
|
|
|
14
|
+
from PySide6.QtCore import QTimer
|
|
17
15
|
from pygpt_net.core.events import AppEvent, RenderEvent
|
|
18
16
|
from pygpt_net.core.tabs.tab import Tab
|
|
19
17
|
from pygpt_net.item.ctx import CtxMeta
|
|
@@ -363,7 +361,7 @@ class Tabs:
|
|
|
363
361
|
if tab.type == Tab.TAB_CHAT and self.column_idx == 1 and not getattr(tab, "loaded", False):
|
|
364
362
|
meta = self.window.core.ctx.get_meta_by_id(tab.data_id)
|
|
365
363
|
if meta is not None:
|
|
366
|
-
self.window.controller.ctx.load(meta.id)
|
|
364
|
+
self.window.controller.ctx.load(meta.id, no_fresh=True)
|
|
367
365
|
tab.loaded = True
|
|
368
366
|
|
|
369
367
|
current_ctx = self.window.core.ctx.get_current()
|
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.09.16 02:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import gc
|
|
@@ -1274,12 +1274,7 @@ class Renderer(BaseRenderer):
|
|
|
1274
1274
|
pass
|
|
1275
1275
|
self._bridge_ready[pid] = False
|
|
1276
1276
|
self._pending_nodes[pid] = []
|
|
1277
|
-
node.
|
|
1278
|
-
p = node.page()
|
|
1279
|
-
p.triggerAction(QWebEnginePage.Stop)
|
|
1280
|
-
p.setUrl(QUrl("about:blank"))
|
|
1281
|
-
p.history().clear()
|
|
1282
|
-
p.setLifecycleState(QWebEnginePage.LifecycleState.Discarded)
|
|
1277
|
+
node.unload() # unload web page
|
|
1283
1278
|
self._stream_reset(pid)
|
|
1284
1279
|
self.pids[pid].clear(all=True)
|
|
1285
1280
|
self.pids[pid].loaded = False
|
|
@@ -1294,9 +1289,8 @@ class Renderer(BaseRenderer):
|
|
|
1294
1289
|
:param meta: context meta
|
|
1295
1290
|
"""
|
|
1296
1291
|
tab = node.get_tab()
|
|
1297
|
-
tab.delete_ref(node)
|
|
1298
1292
|
layout = tab.child.layout()
|
|
1299
|
-
|
|
1293
|
+
tab.child.remove_widget(node)
|
|
1300
1294
|
self.window.ui.nodes['output'].pop(tab.pid, None)
|
|
1301
1295
|
|
|
1302
1296
|
node.on_delete()
|
|
@@ -1307,7 +1301,7 @@ class Renderer(BaseRenderer):
|
|
|
1307
1301
|
view.signals.save_as.connect(self.window.controller.chat.render.handle_save_as)
|
|
1308
1302
|
view.signals.audio_read.connect(self.window.controller.chat.render.handle_audio_read)
|
|
1309
1303
|
|
|
1310
|
-
layout.addWidget(view)
|
|
1304
|
+
layout.addWidget(view) # tab body layout
|
|
1311
1305
|
view.setVisible(True)
|
|
1312
1306
|
self.window.ui.nodes['output'][tab.pid] = view
|
|
1313
1307
|
try:
|
pygpt_net/core/tabs/tabs.py
CHANGED
|
@@ -6,16 +6,14 @@
|
|
|
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.
|
|
9
|
+
# Updated Date: 2025.09.16 02:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import uuid
|
|
13
13
|
from datetime import datetime
|
|
14
14
|
from typing import Optional, Any, Dict, Tuple, Union
|
|
15
15
|
|
|
16
|
-
from PySide6.QtCore import QUrl
|
|
17
16
|
from PySide6.QtGui import QIcon
|
|
18
|
-
from PySide6.QtWebEngineCore import QWebEnginePage
|
|
19
17
|
from PySide6.QtWidgets import QVBoxLayout, QWidget, QLayout
|
|
20
18
|
|
|
21
19
|
from pygpt_net.ui.widget.tabs.body import TabBody
|
|
@@ -301,30 +299,24 @@ class Tabs:
|
|
|
301
299
|
if tab.type == Tab.TAB_CHAT:
|
|
302
300
|
node = self.window.ui.nodes['output'].get(tab.pid)
|
|
303
301
|
if node:
|
|
304
|
-
node.
|
|
305
|
-
|
|
306
|
-
p.triggerAction(QWebEnginePage.Stop)
|
|
307
|
-
p.setUrl(QUrl("about:blank"))
|
|
308
|
-
p.history().clear()
|
|
309
|
-
p.setLifecycleState(QWebEnginePage.LifecycleState.Discarded)
|
|
310
|
-
tab.delete_ref(node)
|
|
311
|
-
layout = tab.child.layout()
|
|
312
|
-
layout.removeWidget(node)
|
|
302
|
+
node.unload() # unload web page
|
|
303
|
+
tab.child.remove_widget(node)
|
|
313
304
|
self.window.ui.nodes['output'].pop(pid, None)
|
|
314
305
|
node.on_delete()
|
|
315
306
|
node_plain = self.window.ui.nodes['output_plain'].get(tab.pid)
|
|
316
307
|
if node_plain:
|
|
317
|
-
tab.
|
|
318
|
-
layout = tab.child.layout()
|
|
319
|
-
layout.removeWidget(node_plain)
|
|
308
|
+
tab.child.remove_widget(node_plain)
|
|
320
309
|
self.window.ui.nodes['output_plain'].pop(pid, None)
|
|
321
310
|
node_plain.on_delete()
|
|
322
311
|
|
|
323
312
|
if tab.type in (Tab.TAB_CHAT, Tab.TAB_NOTEPAD, Tab.TAB_TOOL):
|
|
324
313
|
tab.cleanup() # unload assigned data from memory
|
|
325
314
|
|
|
315
|
+
# tab.delete_refs()
|
|
316
|
+
|
|
326
317
|
except Exception as e:
|
|
327
318
|
print(f"Error unloading tab {pid}: {e}")
|
|
319
|
+
self.window.core.debug.log(e)
|
|
328
320
|
|
|
329
321
|
column_idx = tab.column_idx
|
|
330
322
|
self.window.ui.layout.get_tabs_by_idx(column_idx).removeTab(tab.idx)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"__meta__": {
|
|
3
|
-
"version": "2.6.
|
|
4
|
-
"app.version": "2.6.
|
|
5
|
-
"updated_at": "2025-09-
|
|
3
|
+
"version": "2.6.49",
|
|
4
|
+
"app.version": "2.6.49",
|
|
5
|
+
"updated_at": "2025-09-16T00: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.6.
|
|
4
|
-
"app.version": "2.6.
|
|
5
|
-
"updated_at": "2025-09-
|
|
3
|
+
"version": "2.6.49",
|
|
4
|
+
"app.version": "2.6.49",
|
|
5
|
+
"updated_at": "2025-09-16T08:03:34"
|
|
6
6
|
},
|
|
7
7
|
"items": {
|
|
8
8
|
"SpeakLeash/bielik-11b-v2.3-instruct:Q4_K_M": {
|
|
@@ -6,16 +6,16 @@
|
|
|
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.
|
|
9
|
+
# Updated Date: 2025.09.16 02:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import json
|
|
13
13
|
import re
|
|
14
14
|
from typing import Optional
|
|
15
15
|
|
|
16
|
-
from PySide6.QtCore import Qt, QObject, Signal, Slot, QEvent, QTimer
|
|
16
|
+
from PySide6.QtCore import Qt, QObject, Signal, Slot, QEvent, QTimer, QUrl, QCoreApplication, QEventLoop
|
|
17
17
|
from PySide6.QtWebChannel import QWebChannel
|
|
18
|
-
from PySide6.QtWebEngineCore import QWebEngineSettings, QWebEnginePage
|
|
18
|
+
from PySide6.QtWebEngineCore import QWebEngineSettings, QWebEnginePage, QWebEngineProfile
|
|
19
19
|
from PySide6.QtWebEngineWidgets import QWebEngineView
|
|
20
20
|
from PySide6.QtGui import QAction, QIcon, QKeySequence
|
|
21
21
|
from PySide6.QtWidgets import QMenu
|
|
@@ -25,6 +25,7 @@ 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
|
+
|
|
28
29
|
class CodeBlock:
|
|
29
30
|
def __init__(
|
|
30
31
|
self,
|
|
@@ -109,32 +110,119 @@ class HtmlOutput(QWebEngineView):
|
|
|
109
110
|
self.is_dialog = False
|
|
110
111
|
self.nodes = [] # code blocks
|
|
111
112
|
|
|
113
|
+
# OpenGL widgets
|
|
114
|
+
self._glwidget = None
|
|
115
|
+
self._glwidget_filter_installed = False
|
|
116
|
+
self._unloaded = False # flag to check if unloaded
|
|
117
|
+
self._destroyed = False
|
|
118
|
+
|
|
119
|
+
# self._profile = self._make_profile(self)
|
|
120
|
+
self.setPage(CustomWebEnginePage(self.window, self, profile=None))
|
|
121
|
+
|
|
122
|
+
def _make_profile(self, parent=None) -> QWebEngineProfile:
|
|
123
|
+
"""Make profile"""
|
|
124
|
+
profile = QWebEngineProfile()
|
|
125
|
+
profile.setPersistentCookiesPolicy(QWebEngineProfile.NoPersistentCookies)
|
|
126
|
+
profile.setSpellCheckEnabled(False)
|
|
127
|
+
return profile
|
|
128
|
+
|
|
129
|
+
def _detach_gl_event_filter(self):
|
|
130
|
+
"""Detach OpenGL widget event filter if installed"""
|
|
131
|
+
if self._glwidget and self._glwidget_filter_installed:
|
|
132
|
+
try:
|
|
133
|
+
self._glwidget.removeEventFilter(self)
|
|
134
|
+
except Exception as e:
|
|
135
|
+
self._on_delete_failed(e)
|
|
136
|
+
self._glwidget = None
|
|
137
|
+
self._glwidget_filter_installed = False
|
|
138
|
+
|
|
139
|
+
def _on_delete_failed(self, e):
|
|
140
|
+
"""
|
|
141
|
+
Handle delete failure
|
|
142
|
+
|
|
143
|
+
:param e: Exception instance
|
|
144
|
+
"""
|
|
145
|
+
pass
|
|
146
|
+
# self.window.core.debug.log(e)
|
|
147
|
+
|
|
148
|
+
def unload(self):
|
|
149
|
+
"""Unload the current page and free resources"""
|
|
150
|
+
try:
|
|
151
|
+
self.hide()
|
|
152
|
+
p = self.page()
|
|
153
|
+
p.triggerAction(QWebEnginePage.Stop)
|
|
154
|
+
p.setUrl(QUrl("about:blank"))
|
|
155
|
+
p.history().clear()
|
|
156
|
+
p.setLifecycleState(QWebEnginePage.LifecycleState.Discarded)
|
|
157
|
+
except Exception as e:
|
|
158
|
+
self._on_delete_failed(e)
|
|
159
|
+
finally:
|
|
160
|
+
self._unloaded = True
|
|
161
|
+
|
|
112
162
|
def on_delete(self):
|
|
113
163
|
"""Clean up on delete"""
|
|
164
|
+
if self._destroyed:
|
|
165
|
+
return
|
|
166
|
+
if not self._unloaded:
|
|
167
|
+
self.unload()
|
|
168
|
+
|
|
169
|
+
self.hide()
|
|
170
|
+
self._detach_gl_event_filter()
|
|
171
|
+
|
|
114
172
|
if self.finder:
|
|
115
|
-
|
|
116
|
-
|
|
173
|
+
try:
|
|
174
|
+
self.finder.disconnect()
|
|
175
|
+
except Exception as e:
|
|
176
|
+
self._on_delete_failed(e)
|
|
177
|
+
finally:
|
|
178
|
+
self.finder = None
|
|
117
179
|
|
|
118
|
-
self.tab = None
|
|
180
|
+
self.tab = None
|
|
181
|
+
self.meta = None
|
|
119
182
|
|
|
120
|
-
# delete page
|
|
121
183
|
page = self.page()
|
|
122
|
-
|
|
123
|
-
if hasattr(page, 'bridge'):
|
|
124
|
-
page.bridge.deleteLater()
|
|
125
|
-
if hasattr(page, 'channel'):
|
|
126
|
-
page.channel.deleteLater()
|
|
127
|
-
if hasattr(page, 'signals') and page.signals:
|
|
128
|
-
page.signals.deleteLater()
|
|
129
|
-
page.deleteLater() # delete page
|
|
184
|
+
prof = page.profile()
|
|
130
185
|
|
|
131
186
|
# disconnect signals
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
187
|
+
try:
|
|
188
|
+
self.loadFinished.disconnect()
|
|
189
|
+
self.customContextMenuRequested.disconnect()
|
|
190
|
+
self.signals.save_as.disconnect()
|
|
191
|
+
self.signals.audio_read.disconnect()
|
|
192
|
+
except Exception as e:
|
|
193
|
+
self._on_delete_failed(e)
|
|
194
|
+
|
|
195
|
+
try:
|
|
196
|
+
if hasattr(page, "setWebChannel"):
|
|
197
|
+
page.setWebChannel(None)
|
|
198
|
+
except Exception as e:
|
|
199
|
+
self._on_delete_failed(e)
|
|
200
|
+
|
|
201
|
+
try:
|
|
202
|
+
page.cleanup()
|
|
203
|
+
except Exception as e:
|
|
204
|
+
self._on_delete_failed(e)
|
|
205
|
+
|
|
206
|
+
"""
|
|
207
|
+
if prof is not None:
|
|
208
|
+
try:
|
|
209
|
+
prof.deleteLater()
|
|
210
|
+
except Exception as e:
|
|
211
|
+
self._on_delete_failed(e)
|
|
212
|
+
"""
|
|
213
|
+
|
|
214
|
+
try:
|
|
215
|
+
self.deleteLater()
|
|
216
|
+
except Exception as e:
|
|
217
|
+
self._on_delete_failed(e)
|
|
218
|
+
|
|
219
|
+
try:
|
|
220
|
+
QCoreApplication.sendPostedEvents(None, QEvent.DeferredDelete)
|
|
221
|
+
QCoreApplication.processEvents(QEventLoop.AllEvents, 50)
|
|
222
|
+
except Exception as e:
|
|
223
|
+
self._on_delete_failed(e)
|
|
136
224
|
|
|
137
|
-
self.
|
|
225
|
+
self._destroyed = True
|
|
138
226
|
|
|
139
227
|
def init(self, force: bool = False):
|
|
140
228
|
"""
|
|
@@ -164,7 +252,7 @@ class HtmlOutput(QWebEngineView):
|
|
|
164
252
|
|
|
165
253
|
def reload(self):
|
|
166
254
|
"""Reload HTML output"""
|
|
167
|
-
#return
|
|
255
|
+
# return
|
|
168
256
|
self.reload_css()
|
|
169
257
|
|
|
170
258
|
def get_nodes(self) -> list:
|
|
@@ -203,7 +291,7 @@ class HtmlOutput(QWebEngineView):
|
|
|
203
291
|
|
|
204
292
|
:param text: text
|
|
205
293
|
"""
|
|
206
|
-
self.plain+= str(text)
|
|
294
|
+
self.plain += str(text)
|
|
207
295
|
|
|
208
296
|
def set_plaintext(self, text: str):
|
|
209
297
|
"""
|
|
@@ -267,7 +355,7 @@ class HtmlOutput(QWebEngineView):
|
|
|
267
355
|
if node.content != "":
|
|
268
356
|
self.nodes.append(node)
|
|
269
357
|
if self.loaded:
|
|
270
|
-
|
|
358
|
+
self.insert_output(node)
|
|
271
359
|
self.update_current_content()
|
|
272
360
|
QTimer.singleShot(100, self.scroll_to_bottom) # wait for rendering to complete
|
|
273
361
|
|
|
@@ -508,7 +596,7 @@ class HtmlOutput(QWebEngineView):
|
|
|
508
596
|
menu.addSeparator()
|
|
509
597
|
action = QAction(QIcon(":/icons/search.svg"), trans('text.context_menu.find'), self)
|
|
510
598
|
action.triggered.connect(self.find_open)
|
|
511
|
-
#action.setShortcut(QKeySequence("Ctrl+F"))
|
|
599
|
+
# action.setShortcut(QKeySequence("Ctrl+F"))
|
|
512
600
|
menu.addAction(action)
|
|
513
601
|
|
|
514
602
|
menu.exec_(self.mapToGlobal(position))
|
|
@@ -615,14 +703,20 @@ class HtmlOutput(QWebEngineView):
|
|
|
615
703
|
if (event.type() == QEvent.ChildAdded and
|
|
616
704
|
source is self and
|
|
617
705
|
event.child().isWidgetType()):
|
|
706
|
+
self._detach_gl_event_filter()
|
|
618
707
|
self._glwidget = event.child()
|
|
619
|
-
|
|
708
|
+
try:
|
|
709
|
+
self._glwidget.installEventFilter(self)
|
|
710
|
+
self._glwidget_filter_installed = True
|
|
711
|
+
except Exception:
|
|
712
|
+
self._glwidget = None
|
|
713
|
+
self._glwidget_filter_installed = False
|
|
620
714
|
elif event.type() == event.Type.MouseButtonPress:
|
|
621
715
|
if self.tab:
|
|
622
716
|
col_idx = self.tab.column_idx
|
|
623
717
|
self.window.controller.ui.tabs.on_column_focus(col_idx)
|
|
624
718
|
elif event.type() == event.Type.FocusIn:
|
|
625
|
-
if self.tab
|
|
719
|
+
if self.tab:
|
|
626
720
|
col_idx = self.tab.column_idx
|
|
627
721
|
self.window.controller.ui.tabs.on_column_focus(col_idx)
|
|
628
722
|
elif event.type() == QEvent.KeyPress:
|
|
@@ -633,10 +727,17 @@ class HtmlOutput(QWebEngineView):
|
|
|
633
727
|
|
|
634
728
|
class CustomWebEnginePage(QWebEnginePage):
|
|
635
729
|
"""Custom WebEnginePage to handle web events"""
|
|
636
|
-
|
|
637
|
-
|
|
730
|
+
|
|
731
|
+
def __init__(self, window, view, profile: QWebEngineProfile = None):
|
|
732
|
+
|
|
733
|
+
# use the profile if provided, otherwise the default
|
|
734
|
+
if profile is not None:
|
|
735
|
+
super(CustomWebEnginePage, self).__init__(profile, view)
|
|
736
|
+
else:
|
|
737
|
+
super(CustomWebEnginePage, self).__init__(view)
|
|
738
|
+
|
|
638
739
|
self.window = window
|
|
639
|
-
self.parent =
|
|
740
|
+
self.parent = view
|
|
640
741
|
self.signals = WebEnginePageSignals()
|
|
641
742
|
self.findTextFinished.connect(self.on_find_finished)
|
|
642
743
|
self.zoomFactorChanged.connect(self.on_view_changed)
|
|
@@ -687,7 +788,7 @@ class CustomWebEnginePage(QWebEnginePage):
|
|
|
687
788
|
"""On selection changed"""
|
|
688
789
|
pass
|
|
689
790
|
|
|
690
|
-
def acceptNavigationRequest(self, url,
|
|
791
|
+
def acceptNavigationRequest(self, url, _type, isMainFrame):
|
|
691
792
|
"""
|
|
692
793
|
On navigation (link click) event
|
|
693
794
|
|
|
@@ -698,7 +799,7 @@ class CustomWebEnginePage(QWebEnginePage):
|
|
|
698
799
|
if _type == QWebEnginePage.NavigationTypeLinkClicked:
|
|
699
800
|
self.window.core.filesystem.url.handle(url)
|
|
700
801
|
return False
|
|
701
|
-
return super().acceptNavigationRequest(url,
|
|
802
|
+
return super().acceptNavigationRequest(url, _type, isMainFrame)
|
|
702
803
|
|
|
703
804
|
def javaScriptConsoleMessage(self, level, message, line_number, source_id):
|
|
704
805
|
"""
|
|
@@ -711,9 +812,40 @@ class CustomWebEnginePage(QWebEnginePage):
|
|
|
711
812
|
"""
|
|
712
813
|
self.signals.js_message.emit(line_number, message, source_id) # handled in debug controller
|
|
713
814
|
|
|
815
|
+
def cleanup(self):
|
|
816
|
+
"""Cleanup method to release resources"""
|
|
817
|
+
try:
|
|
818
|
+
self.findTextFinished.disconnect()
|
|
819
|
+
self.zoomFactorChanged.disconnect()
|
|
820
|
+
self.selectionChanged.disconnect()
|
|
821
|
+
except Exception:
|
|
822
|
+
pass
|
|
823
|
+
|
|
824
|
+
if self.bridge:
|
|
825
|
+
try:
|
|
826
|
+
self.bridge.cleanup()
|
|
827
|
+
except Exception:
|
|
828
|
+
pass
|
|
829
|
+
self.bridge = None
|
|
830
|
+
|
|
831
|
+
if self.channel:
|
|
832
|
+
try:
|
|
833
|
+
self.channel.unregisterObject("bridge")
|
|
834
|
+
except Exception:
|
|
835
|
+
pass
|
|
836
|
+
self.channel = None
|
|
837
|
+
|
|
838
|
+
if self.signals:
|
|
839
|
+
try:
|
|
840
|
+
self.signals.deleteLater()
|
|
841
|
+
except Exception:
|
|
842
|
+
pass
|
|
843
|
+
self.signals = None
|
|
844
|
+
|
|
714
845
|
|
|
715
846
|
class Bridge(QObject):
|
|
716
847
|
"""Bridge between Python and JavaScript"""
|
|
848
|
+
|
|
717
849
|
def __init__(self, window):
|
|
718
850
|
super(Bridge, self).__init__(window)
|
|
719
851
|
self.window = window
|
|
@@ -754,10 +886,23 @@ class Bridge(QObject):
|
|
|
754
886
|
"""
|
|
755
887
|
self.window.controller.chat.render.scroll = pos
|
|
756
888
|
|
|
889
|
+
def cleanup(self):
|
|
890
|
+
"""Cleanup method to release resources"""
|
|
891
|
+
if self.window:
|
|
892
|
+
try:
|
|
893
|
+
self.window = None
|
|
894
|
+
except Exception:
|
|
895
|
+
pass
|
|
896
|
+
|
|
897
|
+
# delete the bridge object
|
|
898
|
+
self.deleteLater()
|
|
899
|
+
|
|
900
|
+
|
|
757
901
|
class WebEngineSignals(QObject):
|
|
758
902
|
save_as = Signal(str, str)
|
|
759
903
|
audio_read = Signal(str)
|
|
760
904
|
|
|
905
|
+
|
|
761
906
|
class WebEnginePageSignals(QObject):
|
|
762
907
|
js_message = Signal(int, str, str) # on Javascript message
|
|
763
908
|
|
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.09.16 02:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6 import QtCore
|
|
@@ -100,9 +100,6 @@ class ToolWidget:
|
|
|
100
100
|
:return: QVBoxLayout
|
|
101
101
|
"""
|
|
102
102
|
self.output = HtmlOutput(self.window, self.tool)
|
|
103
|
-
self.output.setPage(
|
|
104
|
-
CustomWebEnginePage(self.window, self.output)
|
|
105
|
-
)
|
|
106
103
|
self.output.signals.save_as.connect(self.window.controller.chat.render.handle_save_as)
|
|
107
104
|
self.output.signals.audio_read.connect(self.window.controller.chat.render.handle_audio_read)
|
|
108
105
|
|
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.09.16 02:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6.QtCore import Qt, Slot, QUrl, QObject, Signal
|
|
@@ -14,7 +14,7 @@ from PySide6.QtWidgets import QVBoxLayout, QCheckBox, QHBoxLayout
|
|
|
14
14
|
|
|
15
15
|
from pygpt_net.ui.widget.element.labels import HelpLabel
|
|
16
16
|
from pygpt_net.ui.widget.textarea.editor import BaseCodeEditor
|
|
17
|
-
from pygpt_net.ui.widget.textarea.html import HtmlOutput
|
|
17
|
+
from pygpt_net.ui.widget.textarea.html import HtmlOutput
|
|
18
18
|
from pygpt_net.utils import trans
|
|
19
19
|
|
|
20
20
|
|
|
@@ -61,9 +61,6 @@ class ToolWidget:
|
|
|
61
61
|
:return: QVBoxLayout
|
|
62
62
|
"""
|
|
63
63
|
self.output = CanvasOutput(self.window)
|
|
64
|
-
self.output.setPage(
|
|
65
|
-
CustomWebEnginePage(self.window, self.output)
|
|
66
|
-
)
|
|
67
64
|
self.edit = CanvasEdit(self.window)
|
|
68
65
|
self.edit.setVisible(False)
|
|
69
66
|
self.edit.textChanged.connect(
|
pygpt_net/ui/widget/tabs/body.py
CHANGED
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.09.16 02:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import Any
|
|
@@ -35,6 +35,28 @@ class TabBody(QTabWidget):
|
|
|
35
35
|
self.on_delete(self)
|
|
36
36
|
self.delete_refs()
|
|
37
37
|
|
|
38
|
+
def remove_widget(self, widget: QWidget) -> None:
|
|
39
|
+
"""
|
|
40
|
+
Remove widget from tab body
|
|
41
|
+
|
|
42
|
+
:param widget: widget to remove
|
|
43
|
+
"""
|
|
44
|
+
layout = self.layout()
|
|
45
|
+
if layout is not None:
|
|
46
|
+
layout.removeWidget(widget)
|
|
47
|
+
self.delete_ref(widget)
|
|
48
|
+
|
|
49
|
+
def remove_all_widgets(self) -> None:
|
|
50
|
+
"""
|
|
51
|
+
Remove all widgets from tab body
|
|
52
|
+
"""
|
|
53
|
+
layout = self.layout()
|
|
54
|
+
if layout is not None:
|
|
55
|
+
while layout.count():
|
|
56
|
+
item = layout.takeAt(0)
|
|
57
|
+
widget = item.widget()
|
|
58
|
+
layout.removeWidget(widget)
|
|
59
|
+
|
|
38
60
|
def add_ref(self, ref: Any) -> None:
|
|
39
61
|
"""
|
|
40
62
|
Add reference to widget in this tab
|
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.09.16 02:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6.QtCore import Qt, QObject, Signal, Slot, QEvent, QUrl, QCoreApplication, QEventLoop
|
|
@@ -22,6 +22,7 @@ from pygpt_net.core.text.web_finder import WebFinder
|
|
|
22
22
|
from pygpt_net.ui.widget.tabs.layout import FocusEventFilter
|
|
23
23
|
from pygpt_net.utils import trans
|
|
24
24
|
|
|
25
|
+
|
|
25
26
|
class ChatWebOutput(QWebEngineView):
|
|
26
27
|
def __init__(self, window=None):
|
|
27
28
|
"""
|
|
@@ -47,113 +48,153 @@ class ChatWebOutput(QWebEngineView):
|
|
|
47
48
|
# OpenGL widgets
|
|
48
49
|
self._glwidget = None
|
|
49
50
|
self._glwidget_filter_installed = False
|
|
51
|
+
self._unloaded = False
|
|
52
|
+
self._destroyed = False
|
|
50
53
|
|
|
51
54
|
# set the page with a shared profile
|
|
52
55
|
self.setUpdatesEnabled(False) # disable updates until the page is set, re-enable in `on_page_loaded`
|
|
53
56
|
|
|
54
|
-
self._profile =
|
|
57
|
+
# self._profile = self._make_profile(self)
|
|
58
|
+
self.setPage(CustomWebEnginePage(self.window, self, profile=None))
|
|
59
|
+
|
|
60
|
+
def _make_profile(self, parent=None) -> QWebEngineProfile:
|
|
61
|
+
"""Make profile"""
|
|
62
|
+
profile = QWebEngineProfile(parent)
|
|
55
63
|
# self._profile.setHttpCacheType(QWebEngineProfile.MemoryHttpCache)
|
|
56
64
|
# self._profile.setHttpCacheMaximumSize(32 * 1024 * 1024) # 32MB
|
|
57
|
-
|
|
65
|
+
profile.setPersistentCookiesPolicy(QWebEngineProfile.NoPersistentCookies)
|
|
58
66
|
# self._profile.setHttpCacheType(QWebEngineProfile.NoCache)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
67
|
+
profile.setSpellCheckEnabled(False)
|
|
68
|
+
return profile
|
|
69
|
+
|
|
62
70
|
|
|
63
71
|
def _detach_gl_event_filter(self):
|
|
64
72
|
"""Detach OpenGL widget event filter if installed"""
|
|
65
73
|
if self._glwidget and self._glwidget_filter_installed:
|
|
66
74
|
try:
|
|
67
75
|
self._glwidget.removeEventFilter(self)
|
|
68
|
-
except Exception:
|
|
69
|
-
|
|
76
|
+
except Exception as e:
|
|
77
|
+
self._on_delete_failed(e)
|
|
70
78
|
self._glwidget = None
|
|
71
79
|
self._glwidget_filter_installed = False
|
|
72
80
|
|
|
81
|
+
def _on_delete_failed(self, e):
|
|
82
|
+
"""
|
|
83
|
+
Handle delete failure
|
|
84
|
+
|
|
85
|
+
:param e: Exception instance
|
|
86
|
+
"""
|
|
87
|
+
pass
|
|
88
|
+
# self.window.core.debug.log(e)
|
|
89
|
+
|
|
90
|
+
def unload(self):
|
|
91
|
+
"""Unload the current page and free resources"""
|
|
92
|
+
try:
|
|
93
|
+
self.hide()
|
|
94
|
+
p = self.page()
|
|
95
|
+
p.triggerAction(QWebEnginePage.Stop)
|
|
96
|
+
p.setUrl(QUrl("about:blank"))
|
|
97
|
+
p.history().clear()
|
|
98
|
+
p.setLifecycleState(QWebEnginePage.LifecycleState.Discarded)
|
|
99
|
+
except Exception as e:
|
|
100
|
+
self._on_delete_failed(e)
|
|
101
|
+
finally:
|
|
102
|
+
self._unloaded = True
|
|
103
|
+
|
|
73
104
|
def on_delete(self):
|
|
74
105
|
"""Clean up on delete"""
|
|
106
|
+
if self._destroyed:
|
|
107
|
+
return
|
|
108
|
+
if not self._unloaded:
|
|
109
|
+
self.unload()
|
|
110
|
+
|
|
75
111
|
self.hide()
|
|
76
112
|
self._detach_gl_event_filter()
|
|
77
|
-
|
|
113
|
+
|
|
78
114
|
if self.finder:
|
|
79
115
|
try:
|
|
80
116
|
self.finder.disconnect()
|
|
81
|
-
except Exception:
|
|
82
|
-
|
|
83
|
-
|
|
117
|
+
except Exception as e:
|
|
118
|
+
self._on_delete_failed(e)
|
|
119
|
+
finally:
|
|
120
|
+
self.finder = None
|
|
84
121
|
|
|
85
122
|
self.tab = None
|
|
86
123
|
self.meta = None
|
|
87
124
|
|
|
88
125
|
# safely unhook signals (may not have been hooked)
|
|
89
126
|
for sig, slot in (
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
127
|
+
(self.loadFinished, self.on_page_loaded),
|
|
128
|
+
(self.customContextMenuRequested, self.on_context_menu),
|
|
129
|
+
(self.signals.save_as, getattr(self.window.controller.chat.render, "handle_save_as", None)),
|
|
130
|
+
(self.signals.audio_read, getattr(self.window.controller.chat.render, "handle_audio_read", None)),
|
|
94
131
|
):
|
|
95
132
|
if slot:
|
|
96
133
|
try:
|
|
97
134
|
sig.disconnect(slot)
|
|
98
|
-
except Exception:
|
|
99
|
-
|
|
135
|
+
except Exception as e:
|
|
136
|
+
self._on_delete_failed(e)
|
|
100
137
|
|
|
101
138
|
page = self.page()
|
|
102
139
|
page.set_loaded(False)
|
|
103
140
|
|
|
104
141
|
try:
|
|
105
142
|
page.triggerAction(QWebEnginePage.Stop)
|
|
106
|
-
except Exception:
|
|
107
|
-
|
|
143
|
+
except Exception as e:
|
|
144
|
+
self._on_delete_failed(e)
|
|
145
|
+
|
|
108
146
|
try:
|
|
109
147
|
page.setUrl(QUrl("about:blank"))
|
|
110
|
-
except Exception:
|
|
111
|
-
|
|
148
|
+
except Exception as e:
|
|
149
|
+
self._on_delete_failed(e)
|
|
150
|
+
|
|
112
151
|
try:
|
|
113
152
|
page.history().clear()
|
|
114
|
-
except Exception:
|
|
115
|
-
|
|
153
|
+
except Exception as e:
|
|
154
|
+
self._on_delete_failed(e)
|
|
155
|
+
|
|
116
156
|
try:
|
|
117
157
|
page.setLifecycleState(QWebEnginePage.LifecycleState.Discarded)
|
|
118
|
-
except Exception:
|
|
119
|
-
|
|
158
|
+
except Exception as e:
|
|
159
|
+
self._on_delete_failed(e)
|
|
160
|
+
|
|
120
161
|
try:
|
|
121
162
|
if hasattr(page, "setWebChannel"):
|
|
122
163
|
page.setWebChannel(None)
|
|
123
|
-
except Exception:
|
|
124
|
-
|
|
125
|
-
try:
|
|
126
|
-
self.disconnect()
|
|
127
|
-
except Exception:
|
|
128
|
-
pass
|
|
164
|
+
except Exception as e:
|
|
165
|
+
self._on_delete_failed(e)
|
|
129
166
|
|
|
130
167
|
prof = None
|
|
131
168
|
try:
|
|
132
169
|
prof = page.profile()
|
|
133
|
-
except Exception:
|
|
134
|
-
|
|
170
|
+
except Exception as e:
|
|
171
|
+
self._on_delete_failed(e)
|
|
135
172
|
|
|
136
173
|
try:
|
|
137
174
|
page.cleanup()
|
|
138
|
-
except Exception:
|
|
139
|
-
|
|
175
|
+
except Exception as e:
|
|
176
|
+
self._on_delete_failed(e)
|
|
140
177
|
|
|
178
|
+
"""
|
|
141
179
|
if prof is not None:
|
|
142
180
|
try:
|
|
143
181
|
prof.deleteLater()
|
|
144
|
-
except Exception:
|
|
145
|
-
|
|
182
|
+
except Exception as e:
|
|
183
|
+
self._on_delete_failed(e)
|
|
184
|
+
"""
|
|
146
185
|
|
|
147
186
|
try:
|
|
148
187
|
self.deleteLater()
|
|
149
|
-
except Exception:
|
|
150
|
-
|
|
188
|
+
except Exception as e:
|
|
189
|
+
self._on_delete_failed(e)
|
|
151
190
|
|
|
152
191
|
try:
|
|
153
192
|
QCoreApplication.sendPostedEvents(None, QEvent.DeferredDelete)
|
|
154
193
|
QCoreApplication.processEvents(QEventLoop.AllEvents, 50)
|
|
155
|
-
except Exception:
|
|
156
|
-
|
|
194
|
+
except Exception as e:
|
|
195
|
+
self._on_delete_failed(e)
|
|
196
|
+
|
|
197
|
+
self._destroyed = True
|
|
157
198
|
|
|
158
199
|
def eventFilter(self, source, event):
|
|
159
200
|
"""
|
|
@@ -390,6 +431,7 @@ class ChatWebOutput(QWebEngineView):
|
|
|
390
431
|
|
|
391
432
|
class CustomWebEnginePage(QWebEnginePage):
|
|
392
433
|
"""Custom WebEnginePage to handle web events"""
|
|
434
|
+
|
|
393
435
|
def __init__(self, window, view, profile: QWebEngineProfile = None):
|
|
394
436
|
|
|
395
437
|
# use the profile if provided, otherwise the default
|
|
@@ -495,12 +537,10 @@ class CustomWebEnginePage(QWebEnginePage):
|
|
|
495
537
|
pass
|
|
496
538
|
self.signals = None
|
|
497
539
|
|
|
498
|
-
# delete the page object
|
|
499
|
-
self.deleteLater()
|
|
500
|
-
|
|
501
540
|
|
|
502
541
|
class Bridge(QObject):
|
|
503
542
|
"""Bridge between Python and JavaScript"""
|
|
543
|
+
|
|
504
544
|
def __init__(self, window, parent=None):
|
|
505
545
|
super(Bridge, self).__init__(parent)
|
|
506
546
|
self.window = window
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: pygpt-net
|
|
3
|
-
Version: 2.6.
|
|
3
|
+
Version: 2.6.49
|
|
4
4
|
Summary: Desktop AI Assistant powered by: OpenAI GPT-5, GPT-4, o1, o3, Gemini, Claude, Grok, DeepSeek, and other models supported by Llama Index, and Ollama. Chatbot, agents, completion, image generation, vision analysis, speech-to-text, plugins, internet access, file handling, command execution and more.
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: ai,api,api key,app,assistant,bielik,chat,chatbot,chatgpt,claude,dall-e,deepseek,desktop,gemini,gpt,gpt-3.5,gpt-4,gpt-4-vision,gpt-4o,gpt-5,gpt-oss,gpt3.5,gpt4,grok,langchain,llama-index,llama3,mistral,o1,o3,ollama,openai,presets,py-gpt,py_gpt,pygpt,pyside,qt,text completion,tts,ui,vision,whisper
|
|
@@ -118,7 +118,7 @@ Description-Content-Type: text/markdown
|
|
|
118
118
|
|
|
119
119
|
[](https://snapcraft.io/pygpt)
|
|
120
120
|
|
|
121
|
-
Release: **2.6.
|
|
121
|
+
Release: **2.6.49** | build: **2025-09-16** | Python: **>=3.10, <3.14**
|
|
122
122
|
|
|
123
123
|
> Official website: https://pygpt.net | Documentation: https://pygpt.readthedocs.io
|
|
124
124
|
>
|
|
@@ -3612,6 +3612,10 @@ may consume additional tokens that are not displayed in the main window.
|
|
|
3612
3612
|
|
|
3613
3613
|
## Recent changes:
|
|
3614
3614
|
|
|
3615
|
+
**2.6.49 (2025-09-16)**
|
|
3616
|
+
|
|
3617
|
+
- Fixed: Occasional crashes when focusing on an output container unloaded from memory in the second column.
|
|
3618
|
+
|
|
3615
3619
|
**2.6.48 (2025-09-15)**
|
|
3616
3620
|
|
|
3617
3621
|
- Added: auto-loading of next items to the list of contexts when scrolling to the end of the list.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
pygpt_net/CHANGELOG.txt,sha256=
|
|
1
|
+
pygpt_net/CHANGELOG.txt,sha256=p65ExEC2HTbdlw2RFL75_4I2T5TAc2R0j4Pi4uNh2vc,106378
|
|
2
2
|
pygpt_net/LICENSE,sha256=dz9sfFgYahvu2NZbx4C1xCsVn9GVer2wXcMkFRBvqzY,1146
|
|
3
|
-
pygpt_net/__init__.py,sha256=
|
|
3
|
+
pygpt_net/__init__.py,sha256=vxaKvvX5rLWJ_cLCuVaUaVEvyJon-6Ja6Ga0CG4wb4k,1373
|
|
4
4
|
pygpt_net/app.py,sha256=prS80WfKSu8U_Ox9oUdxgzgHgRB1nvQQAMFTNltiECY,21954
|
|
5
5
|
pygpt_net/app_core.py,sha256=PwBOV9wZLtr-O6SxBiazABhYXMHH8kZ6OgbvSv2OiZA,3827
|
|
6
6
|
pygpt_net/config.py,sha256=SCps_FfwdrynVAgpn37Ci1qTN8BFC05IGl9sYIi9e0w,16720
|
|
@@ -72,7 +72,7 @@ pygpt_net/controller/config/field/textarea.py,sha256=Ln545IHzXBeFIjnfMIpmlUr-V3w
|
|
|
72
72
|
pygpt_net/controller/config/placeholder.py,sha256=-PWPNILPVkxMsY64aYnKTWvgUIvx7KA2Nwfd2LW_K30,16711
|
|
73
73
|
pygpt_net/controller/ctx/__init__.py,sha256=0wH7ziC75WscBW8cxpeGBwEz5tolo_kCxGPoz2udI_E,507
|
|
74
74
|
pygpt_net/controller/ctx/common.py,sha256=1oR7cUgVzO_asqiRln4L4vZaxXsssAPtGyAp-B0FUE4,6409
|
|
75
|
-
pygpt_net/controller/ctx/ctx.py,sha256=
|
|
75
|
+
pygpt_net/controller/ctx/ctx.py,sha256=bjz0qCFRAoFpAR3EglV-Lo3yX-sRIo9I85i1sgzfaCs,46250
|
|
76
76
|
pygpt_net/controller/ctx/extra.py,sha256=0r-G6Tlm9WPDkLRmgPDlgyRr_XLfCJntnUGlYPJiXVw,8598
|
|
77
77
|
pygpt_net/controller/ctx/summarizer.py,sha256=UNsq-JTARblGNT97uSMpZEVzdUuDJ8YA2j2dw9R2X3o,3079
|
|
78
78
|
pygpt_net/controller/debug/__init__.py,sha256=dOJGTICjvTtrPIEDOsxCzcOHsfu8AFPLpSKbdN0q0KI,509
|
|
@@ -146,7 +146,7 @@ pygpt_net/controller/tools/__init__.py,sha256=ds63rOuwLEIe-SlY_sQkhWSdXS0lfVwseU
|
|
|
146
146
|
pygpt_net/controller/tools/tools.py,sha256=bWxdwL3J2-WHBS3MBiKsS3kTW_rQI_nS9z8-8iKifKg,2920
|
|
147
147
|
pygpt_net/controller/ui/__init__.py,sha256=cxfh2SYeEDATGAZpcYDqCxYfp4KReQ1CYehevSf89EU,507
|
|
148
148
|
pygpt_net/controller/ui/mode.py,sha256=35J5TRCg33D-RP9epFsWD-ZO-jQ2O0Q41iuqrePC1zM,9107
|
|
149
|
-
pygpt_net/controller/ui/tabs.py,sha256=
|
|
149
|
+
pygpt_net/controller/ui/tabs.py,sha256=Pih53K5G6hD3dWeCF_EWaG5VIF6-x1z1Vs1enmpA6q0,29190
|
|
150
150
|
pygpt_net/controller/ui/ui.py,sha256=w6rxJ0bNk_43Hd0vZB0roxZo7h-AmISEhr8ZiqcBTgA,8496
|
|
151
151
|
pygpt_net/controller/ui/vision.py,sha256=tnzllFV2-sYDHfrP12ATY6ZKi6FcGtQofrsoKF6UcCU,2407
|
|
152
152
|
pygpt_net/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -354,13 +354,13 @@ pygpt_net/core/render/web/debug.py,sha256=784RYXF6inn_bkRtYD1_FllQSyk67JmxKGWPiA
|
|
|
354
354
|
pygpt_net/core/render/web/helpers.py,sha256=8-JkbEOOLoCEAkylJWr8yk3aIliQBMyqcatsyW99VWY,7340
|
|
355
355
|
pygpt_net/core/render/web/parser.py,sha256=pDFc9Tf8P-jvrDilXyT1fukcQHbixHRJ9Dn9hF10Gko,12892
|
|
356
356
|
pygpt_net/core/render/web/pid.py,sha256=F33x_OtrHL9BDMXx_JUbfo8-DOiN4vo1Tv4rrRVADTo,4343
|
|
357
|
-
pygpt_net/core/render/web/renderer.py,sha256=
|
|
357
|
+
pygpt_net/core/render/web/renderer.py,sha256=baP3vaZHk21k_M6aIiMIaj7p-Bi3CtgmkR3L7EQ_MOE,68859
|
|
358
358
|
pygpt_net/core/render/web/syntax_highlight.py,sha256=QSLGF5cJL_Xeqej7_TYwY_5C2w9enXV_cMEuaJ3C43U,2005
|
|
359
359
|
pygpt_net/core/settings/__init__.py,sha256=GQ6_gJ2jf_Chm7ZuZLvkcvEh_sfMDVMBieeoJi2iPI4,512
|
|
360
360
|
pygpt_net/core/settings/settings.py,sha256=Ix06y-gJ3q7NJDf55XAWBBYulBLpinBqzYqsytH_9mo,8686
|
|
361
361
|
pygpt_net/core/tabs/__init__.py,sha256=reDufOWWDQsZwfvtnXrFQROEdl9nqoKI7S3bFA3D9As,508
|
|
362
362
|
pygpt_net/core/tabs/tab.py,sha256=oUQEBWLmVEAp8ck7ur6BI9Ax98csQEHgKiAf1BnWjQk,6138
|
|
363
|
-
pygpt_net/core/tabs/tabs.py,sha256=
|
|
363
|
+
pygpt_net/core/tabs/tabs.py,sha256=D18xA9dkQw2AhkA6Mbqmcc3-x9GHLA3mo1k2pSciwng,32359
|
|
364
364
|
pygpt_net/core/text/__init__.py,sha256=6aEjrckL5kWVfyxpi5mVpSPB6XWV83e_30g_V5meL1M,19
|
|
365
365
|
pygpt_net/core/text/finder.py,sha256=NBzYUE_Av3oZH8RlCrSe6EeLcHpfz79WJV_vSK0P1jI,6656
|
|
366
366
|
pygpt_net/core/text/text.py,sha256=WyQdXx4TpBGgr3XU6AhPILvhaipB57S2XtIs8FYif84,3217
|
|
@@ -395,8 +395,8 @@ pygpt_net/css_rc.py,sha256=PX6g9z5BsD-DXISuR2oq3jHcjiKfcJ4HsgcHez6wGMc,27762
|
|
|
395
395
|
pygpt_net/data/audio/click_off.mp3,sha256=aNiRDP1pt-Jy7ija4YKCNFBwvGWbzU460F4pZWZDS90,65201
|
|
396
396
|
pygpt_net/data/audio/click_on.mp3,sha256=qfdsSnthAEHVXzeyN4LlC0OvXuyW8p7stb7VXtlvZ1k,65201
|
|
397
397
|
pygpt_net/data/audio/ok.mp3,sha256=LTiV32pEBkpUGBkKkcOdOFB7Eyt_QoP2Nv6c5AaXftk,32256
|
|
398
|
-
pygpt_net/data/config/config.json,sha256=
|
|
399
|
-
pygpt_net/data/config/models.json,sha256=
|
|
398
|
+
pygpt_net/data/config/config.json,sha256=H-h9zQr_rSrCy5MsXResKny8XtUDaUE3S98q4477h0Y,30845
|
|
399
|
+
pygpt_net/data/config/models.json,sha256=Jrqq-Jgyx730ZlXrdDASa5MN57BQYRkmEieBKrl_x_k,118192
|
|
400
400
|
pygpt_net/data/config/modes.json,sha256=IpjLOm428_vs6Ma9U-YQTNKJNtZw-qyM1lwhh73xl1w,2111
|
|
401
401
|
pygpt_net/data/config/presets/agent_code_act.json,sha256=GYHqhxtKFLUCvRI3IJAJ7Qe1k8yD9wGGNwManldWzlI,754
|
|
402
402
|
pygpt_net/data/config/presets/agent_openai.json,sha256=bpDJgLRey_effQkzFRoOEGd4aHUrmzeODSDdNzrf62I,730
|
|
@@ -2340,13 +2340,13 @@ pygpt_net/tools/code_interpreter/body.py,sha256=jDEHJuAI8U1RjV0Dhm5CcL4Y8b09UNDw
|
|
|
2340
2340
|
pygpt_net/tools/code_interpreter/tool.py,sha256=XH3_ZUWp1tp21rGlj6-ULI723DXfY1xs7dN9Ye03Pm8,24185
|
|
2341
2341
|
pygpt_net/tools/code_interpreter/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2342
2342
|
pygpt_net/tools/code_interpreter/ui/dialogs.py,sha256=iYCtmn_gPMKhvy8Ygga_oYPVg80zP3-10SZgv0O6xYQ,5429
|
|
2343
|
-
pygpt_net/tools/code_interpreter/ui/html.py,sha256=
|
|
2344
|
-
pygpt_net/tools/code_interpreter/ui/widgets.py,sha256=
|
|
2343
|
+
pygpt_net/tools/code_interpreter/ui/html.py,sha256=8XI_RVZsOm6x95LTp3Lol4xmuTb_Mnb08lnNHxp6QpM,27414
|
|
2344
|
+
pygpt_net/tools/code_interpreter/ui/widgets.py,sha256=noOvecQNHcZKDfyfmgnupNr8KtY8WPvfbds63z6vOV0,18020
|
|
2345
2345
|
pygpt_net/tools/html_canvas/__init__.py,sha256=7FScUoJWFBsF6Rbmt14zb2YEERcywW_xAeX0GTAHhX4,508
|
|
2346
2346
|
pygpt_net/tools/html_canvas/tool.py,sha256=F0rozMO1rva7ABr1hXhOBCW9XWq9hL8RjTWsI6cp-wc,9875
|
|
2347
2347
|
pygpt_net/tools/html_canvas/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2348
2348
|
pygpt_net/tools/html_canvas/ui/dialogs.py,sha256=zw4XusCoZ-52ks8ogcasEVAxDHQwSHh88FtW2rk4HP0,4825
|
|
2349
|
-
pygpt_net/tools/html_canvas/ui/widgets.py,sha256=
|
|
2349
|
+
pygpt_net/tools/html_canvas/ui/widgets.py,sha256=Yp_IP1VhAF5zRymdQ2ADG_wObKOf44rNgI58Vn2c3_4,5050
|
|
2350
2350
|
pygpt_net/tools/image_viewer/__init__.py,sha256=BQLr8Kg670xPAyv_qoRA_EjWq5WZclqoc4OpTk5V11k,508
|
|
2351
2351
|
pygpt_net/tools/image_viewer/tool.py,sha256=8cIcEG9R0HGUXwikD8XOxQHqt0QZkgB4LzpiQ4GAWwU,9269
|
|
2352
2352
|
pygpt_net/tools/image_viewer/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -2549,7 +2549,7 @@ pygpt_net/ui/widget/option/toggle.py,sha256=ainYgH-1UKeHf_BP0yZ48luD0k4zAvZ5jMLd
|
|
|
2549
2549
|
pygpt_net/ui/widget/option/toggle_label.py,sha256=JZwI_mpqLX6Ml9ovijXMWBHTT0t_nf3aYTqRqTYFtpY,2271
|
|
2550
2550
|
pygpt_net/ui/widget/tabs/Input.py,sha256=ELHpaWjhHJdKRhtTjDIByaMF_BqaHCyKwEWDofm0Gls,1875
|
|
2551
2551
|
pygpt_net/ui/widget/tabs/__init__.py,sha256=8HT4tQFqQogEEpGYTv2RplKBthlsFKcl5egnv4lzzEw,488
|
|
2552
|
-
pygpt_net/ui/widget/tabs/body.py,sha256=
|
|
2552
|
+
pygpt_net/ui/widget/tabs/body.py,sha256=dNHfsQ1c6qVylg44I3PvDN21zyJKOkUz2KdH93St5l8,4373
|
|
2553
2553
|
pygpt_net/ui/widget/tabs/layout.py,sha256=6b6bN04IFS0I0cYvq-nUxN2eWwHVUBiNwPXoNgLokM4,6628
|
|
2554
2554
|
pygpt_net/ui/widget/tabs/output.py,sha256=OwlRYcAwb12kMp5RT-DjsEOkXHG9FNQfJuVQBL7XnKA,25082
|
|
2555
2555
|
pygpt_net/ui/widget/textarea/__init__.py,sha256=8HT4tQFqQogEEpGYTv2RplKBthlsFKcl5egnv4lzzEw,488
|
|
@@ -2566,12 +2566,12 @@ pygpt_net/ui/widget/textarea/output.py,sha256=krWta3GHwdlPOqcxLln150bo7iUOtbFL_y
|
|
|
2566
2566
|
pygpt_net/ui/widget/textarea/rename.py,sha256=NwuGRIeWMo7WfsMguAFpTqdOz1eTiXbxrDXGsbWF_TY,1358
|
|
2567
2567
|
pygpt_net/ui/widget/textarea/search_input.py,sha256=aoOlunBwxn-z3gIMNKfnghHX00sC36wQHl87dRlDJlM,5227
|
|
2568
2568
|
pygpt_net/ui/widget/textarea/url.py,sha256=xbNQxoM5fYI1ZWbvybQkPmNPrIq3yhtNPBOSOWftZCg,1337
|
|
2569
|
-
pygpt_net/ui/widget/textarea/web.py,sha256=
|
|
2569
|
+
pygpt_net/ui/widget/textarea/web.py,sha256=FGS0NGSpzKgtP8AzMwnC-LHDXEOY7baHImmnxsbIyGY,19279
|
|
2570
2570
|
pygpt_net/ui/widget/vision/__init__.py,sha256=8HT4tQFqQogEEpGYTv2RplKBthlsFKcl5egnv4lzzEw,488
|
|
2571
2571
|
pygpt_net/ui/widget/vision/camera.py,sha256=v1qEncaZr5pXocO5Cpk_lsgfCMvfFigdJmzsYfzvCl0,1877
|
|
2572
2572
|
pygpt_net/utils.py,sha256=7lZj_YSzx7ZfvqFtjYThEvRJNSBZzrJyK7ZxDAtYPAQ,9708
|
|
2573
|
-
pygpt_net-2.6.
|
|
2574
|
-
pygpt_net-2.6.
|
|
2575
|
-
pygpt_net-2.6.
|
|
2576
|
-
pygpt_net-2.6.
|
|
2577
|
-
pygpt_net-2.6.
|
|
2573
|
+
pygpt_net-2.6.49.dist-info/LICENSE,sha256=rbPqNB_xxANH8hKayJyIcTwD4bj4Y2G-Mcm85r1OImM,1126
|
|
2574
|
+
pygpt_net-2.6.49.dist-info/METADATA,sha256=AykZ3KQvjl_5RGn7sLhu76V2NsPRRCFZDPg9aKAB7Uo,163340
|
|
2575
|
+
pygpt_net-2.6.49.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
2576
|
+
pygpt_net-2.6.49.dist-info/entry_points.txt,sha256=qvpII6UHIt8XfokmQWnCYQrTgty8FeJ9hJvOuUFCN-8,43
|
|
2577
|
+
pygpt_net-2.6.49.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|