pygpt-net 2.6.10__py3-none-any.whl → 2.6.12__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 +10 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/app.py +7 -1
- pygpt_net/config.py +11 -11
- pygpt_net/controller/access/access.py +49 -2
- pygpt_net/controller/chat/attachment.py +13 -13
- pygpt_net/controller/chat/command.py +4 -4
- pygpt_net/controller/chat/common.py +9 -14
- pygpt_net/controller/chat/files.py +2 -2
- pygpt_net/controller/chat/input.py +4 -4
- pygpt_net/controller/chat/output.py +4 -4
- pygpt_net/controller/chat/render.py +11 -6
- pygpt_net/controller/chat/response.py +7 -7
- pygpt_net/controller/chat/stream.py +11 -6
- pygpt_net/controller/chat/text.py +15 -10
- pygpt_net/controller/command/command.py +7 -7
- pygpt_net/controller/ctx/ctx.py +9 -5
- pygpt_net/controller/debug/debug.py +2 -2
- pygpt_net/core/ctx/bag.py +2 -1
- pygpt_net/core/debug/debug.py +17 -3
- pygpt_net/core/dispatcher/dispatcher.py +5 -3
- pygpt_net/core/events/render.py +3 -0
- pygpt_net/core/render/base.py +4 -4
- pygpt_net/core/render/web/body.py +83 -88
- pygpt_net/core/render/web/parser.py +11 -6
- pygpt_net/core/render/web/pid.py +19 -4
- pygpt_net/core/render/web/renderer.py +217 -74
- pygpt_net/data/config/config.json +3 -3
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/config/presets/agent_openai.json +1 -1
- pygpt_net/data/config/presets/agent_openai_assistant.json +1 -1
- pygpt_net/data/config/presets/agent_planner.json +1 -1
- pygpt_net/data/config/presets/agent_react.json +1 -1
- pygpt_net/item/ctx.py +3 -3
- pygpt_net/launcher.py +2 -9
- pygpt_net/provider/gpt/__init__.py +13 -4
- pygpt_net/tools/code_interpreter/body.py +2 -3
- pygpt_net/ui/main.py +8 -3
- pygpt_net/ui/widget/textarea/html.py +2 -7
- pygpt_net/ui/widget/textarea/web.py +52 -28
- pygpt_net/utils.py +15 -8
- {pygpt_net-2.6.10.dist-info → pygpt_net-2.6.12.dist-info}/METADATA +12 -2
- {pygpt_net-2.6.10.dist-info → pygpt_net-2.6.12.dist-info}/RECORD +46 -46
- {pygpt_net-2.6.10.dist-info → pygpt_net-2.6.12.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.10.dist-info → pygpt_net-2.6.12.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.10.dist-info → pygpt_net-2.6.12.dist-info}/entry_points.txt +0 -0
pygpt_net/item/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.08.
|
|
9
|
+
# Updated Date: 2025.08.19 07:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import copy
|
|
@@ -103,7 +103,7 @@ class CtxItem:
|
|
|
103
103
|
if self.input is None:
|
|
104
104
|
return None
|
|
105
105
|
if self.hidden_input:
|
|
106
|
-
return
|
|
106
|
+
return "\n\n".join(self.input, self.hidden_input)
|
|
107
107
|
return self.input
|
|
108
108
|
|
|
109
109
|
@property
|
|
@@ -116,7 +116,7 @@ class CtxItem:
|
|
|
116
116
|
if self.output is None:
|
|
117
117
|
return None
|
|
118
118
|
if self.hidden_output:
|
|
119
|
-
return
|
|
119
|
+
return "\n\n".join(self.output, self.hidden_output)
|
|
120
120
|
return self.output
|
|
121
121
|
|
|
122
122
|
def clear_reply(self):
|
pygpt_net/launcher.py
CHANGED
|
@@ -6,12 +6,9 @@
|
|
|
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.
|
|
9
|
+
# Updated Date: 2025.08.19 07:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
|
-
import asyncio
|
|
13
|
-
from qasync import QEventLoop
|
|
14
|
-
|
|
15
12
|
import os
|
|
16
13
|
import sys
|
|
17
14
|
import argparse
|
|
@@ -123,8 +120,6 @@ class Launcher:
|
|
|
123
120
|
QCoreApplication.setAttribute(Qt.AA_ShareOpenGLContexts)
|
|
124
121
|
self.app = QApplication(sys.argv)
|
|
125
122
|
self.app.setAttribute(QtCore.Qt.AA_DontUseNativeMenuBar)
|
|
126
|
-
self.loop = QEventLoop(self.app)
|
|
127
|
-
asyncio.set_event_loop(self.loop)
|
|
128
123
|
self.window = MainWindow(self.app, args=args)
|
|
129
124
|
self.shortcut_filter = GlobalShortcutFilter(self.window)
|
|
130
125
|
|
|
@@ -295,6 +290,4 @@ class Launcher:
|
|
|
295
290
|
# self.window.core.debug.mem("INIT") # debug memory usage
|
|
296
291
|
signal.signal(signal.SIGTERM, self.handle_signal)
|
|
297
292
|
signal.signal(signal.SIGINT, self.handle_signal)
|
|
298
|
-
|
|
299
|
-
self.loop.run_forever()
|
|
300
|
-
# sys.exit(self.app.exec())
|
|
293
|
+
sys.exit(self.app.exec())
|
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.08.19 07:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from openai import OpenAI
|
|
@@ -63,6 +63,7 @@ class Gpt:
|
|
|
63
63
|
self.vision = Vision(window)
|
|
64
64
|
self.client = None
|
|
65
65
|
self.locked = False
|
|
66
|
+
self.last_client_args = None # last client args used, for debug purposes
|
|
66
67
|
|
|
67
68
|
def get_client(
|
|
68
69
|
self,
|
|
@@ -78,7 +79,15 @@ class Gpt:
|
|
|
78
79
|
"""
|
|
79
80
|
# update client args by mode and model
|
|
80
81
|
args = self.window.core.models.prepare_client_args(mode, model)
|
|
81
|
-
self.client
|
|
82
|
+
if self.client is None or self.last_client_args != args:
|
|
83
|
+
if self.client is not None:
|
|
84
|
+
try:
|
|
85
|
+
self.client.close() # close previous client if exists
|
|
86
|
+
except Exception as e:
|
|
87
|
+
self.window.core.debug.log(e)
|
|
88
|
+
print("Error closing previous GPT client:", e)
|
|
89
|
+
self.client = OpenAI(**args)
|
|
90
|
+
self.last_client_args = args
|
|
82
91
|
return self.client
|
|
83
92
|
|
|
84
93
|
def call(self, context: BridgeContext, extra: dict = None) -> bool:
|
|
@@ -308,8 +317,8 @@ class Gpt:
|
|
|
308
317
|
return
|
|
309
318
|
if self.client is not None:
|
|
310
319
|
try:
|
|
311
|
-
|
|
312
|
-
self.client
|
|
320
|
+
pass
|
|
321
|
+
# self.client.close()
|
|
313
322
|
except Exception as e:
|
|
314
323
|
self.window.core.debug.log(e)
|
|
315
324
|
print("Error closing GPT client:", e)
|
|
@@ -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.08.19 07:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -185,8 +185,7 @@ class Body:
|
|
|
185
185
|
function highlightCode() {
|
|
186
186
|
document.querySelectorAll('pre code').forEach(el => {
|
|
187
187
|
if (!el.classList.contains('hljs')) hljs.highlightElement(el);
|
|
188
|
-
});
|
|
189
|
-
restoreCollapsedCode();
|
|
188
|
+
});
|
|
190
189
|
}
|
|
191
190
|
function scrollToBottom() {
|
|
192
191
|
getScrollPosition(); // store using bridge
|
pygpt_net/ui/main.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.08.
|
|
9
|
+
# Updated Date: 2025.08.19 07:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -115,7 +115,10 @@ class MainWindow(QMainWindow, QtStyleTools):
|
|
|
115
115
|
if not render_debug:
|
|
116
116
|
QLoggingCategory.setFilterRules("*.info=false")
|
|
117
117
|
else:
|
|
118
|
-
|
|
118
|
+
if "QTWEBENGINE_CHROMIUM_FLAGS" in os.environ:
|
|
119
|
+
os.environ["QTWEBENGINE_CHROMIUM_FLAGS"] += " --enable-logging --log-level=0"
|
|
120
|
+
else:
|
|
121
|
+
os.environ["QTWEBENGINE_CHROMIUM_FLAGS"] = "--enable-logging --log-level=0"
|
|
119
122
|
|
|
120
123
|
# OpenGL disable
|
|
121
124
|
if self.core.config.get("render.open_gl") is False:
|
|
@@ -247,7 +250,9 @@ class MainWindow(QMainWindow, QtStyleTools):
|
|
|
247
250
|
|
|
248
251
|
:param message: status message
|
|
249
252
|
"""
|
|
250
|
-
|
|
253
|
+
message = message if isinstance(message, str) else str(message)
|
|
254
|
+
self.dispatch(KernelEvent(KernelEvent.STATUS, {"status": message}))
|
|
255
|
+
del message # free memory
|
|
251
256
|
|
|
252
257
|
@Slot(str)
|
|
253
258
|
def update_state(self, state: str):
|
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.08.19 07:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import re
|
|
@@ -207,12 +207,7 @@ class HtmlOutput(QWebEngineView):
|
|
|
207
207
|
|
|
208
208
|
:param success: True if loaded successfully
|
|
209
209
|
"""
|
|
210
|
-
|
|
211
|
-
event = RenderEvent(RenderEvent.ON_PAGE_LOAD, {
|
|
212
|
-
"meta": self.meta,
|
|
213
|
-
"tab": self.tab,
|
|
214
|
-
})
|
|
215
|
-
self.window.dispatch(event)
|
|
210
|
+
pass
|
|
216
211
|
|
|
217
212
|
def get_selected_text(self) -> str:
|
|
218
213
|
"""
|
|
@@ -6,9 +6,10 @@
|
|
|
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.
|
|
9
|
+
# Updated Date: 2025.08.19 07:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
|
+
from PySide6 import QtCore
|
|
12
13
|
from PySide6.QtCore import Qt, QObject, Signal, Slot, QEvent, QTimer
|
|
13
14
|
from PySide6.QtWebChannel import QWebChannel
|
|
14
15
|
from PySide6.QtWebEngineCore import QWebEngineSettings, QWebEnginePage, QWebEngineProfile
|
|
@@ -22,6 +23,16 @@ from pygpt_net.core.text.web_finder import WebFinder
|
|
|
22
23
|
from pygpt_net.ui.widget.tabs.layout import FocusEventFilter
|
|
23
24
|
from pygpt_net.utils import trans, mem_clean
|
|
24
25
|
|
|
26
|
+
def make_shared_profile():
|
|
27
|
+
prof = QWebEngineProfile("app", None)
|
|
28
|
+
prof.setHttpCacheType(QWebEngineProfile.MemoryHttpCache)
|
|
29
|
+
prof.setHttpCacheMaximumSize(32 * 1024 * 1024) # 32MB
|
|
30
|
+
prof.setPersistentCookiesPolicy(QWebEngineProfile.NoPersistentCookies)
|
|
31
|
+
prof.setSpellCheckEnabled(False)
|
|
32
|
+
return prof
|
|
33
|
+
|
|
34
|
+
SHARED_PROFILE = None
|
|
35
|
+
|
|
25
36
|
import pygpt_net.icons_rc
|
|
26
37
|
|
|
27
38
|
class ChatWebOutput(QWebEngineView):
|
|
@@ -41,17 +52,20 @@ class ChatWebOutput(QWebEngineView):
|
|
|
41
52
|
self.filter = FocusEventFilter(self, self.on_focus)
|
|
42
53
|
self.installEventFilter(self)
|
|
43
54
|
|
|
44
|
-
|
|
45
|
-
|
|
55
|
+
global SHARED_PROFILE
|
|
56
|
+
if not SHARED_PROFILE:
|
|
57
|
+
SHARED_PROFILE = make_shared_profile()
|
|
58
|
+
|
|
59
|
+
self.plain = None
|
|
60
|
+
self.html_content = None
|
|
46
61
|
self.meta = None
|
|
47
62
|
self.tab = None
|
|
48
63
|
self.setProperty('class', 'layout-output-web')
|
|
49
64
|
|
|
50
65
|
self._glwidget = None
|
|
51
66
|
self._glwidget_filter_installed = False
|
|
52
|
-
self._profile = self._create_profile(parent=self)
|
|
53
67
|
|
|
54
|
-
self.setPage(CustomWebEnginePage(self.window, self, profile=
|
|
68
|
+
self.setPage(CustomWebEnginePage(self.window, self, profile=SHARED_PROFILE))
|
|
55
69
|
|
|
56
70
|
def _detach_gl_event_filter(self):
|
|
57
71
|
"""Detach OpenGL widget event filter if installed"""
|
|
@@ -113,6 +127,7 @@ class ChatWebOutput(QWebEngineView):
|
|
|
113
127
|
p.setHttpCacheType(QWebEngineProfile.NoCache)
|
|
114
128
|
p.setHttpCacheMaximumSize(0)
|
|
115
129
|
p.setPersistentCookiesPolicy(QWebEngineProfile.NoPersistentCookies)
|
|
130
|
+
p.setSpellCheckEnabled(False)
|
|
116
131
|
except Exception:
|
|
117
132
|
pass
|
|
118
133
|
return p
|
|
@@ -167,26 +182,22 @@ class ChatWebOutput(QWebEngineView):
|
|
|
167
182
|
return new_view
|
|
168
183
|
|
|
169
184
|
def resetPage(self):
|
|
170
|
-
"""Reset current page
|
|
171
|
-
self.
|
|
172
|
-
self.
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
self.setUpdatesEnabled(False)
|
|
179
|
-
new_profile = self._create_profile(parent=self)
|
|
180
|
-
new_page = CustomWebEnginePage(self.window, self, profile=new_profile)
|
|
181
|
-
self.setPage(new_page)
|
|
182
|
-
|
|
183
|
-
if old_page:
|
|
184
|
-
self._teardown_page(old_page)
|
|
185
|
-
|
|
186
|
-
self._release_profile_after_page(old_page, old_profile)
|
|
187
|
-
self._profile = new_profile
|
|
185
|
+
"""Reset current page without creating a new one"""
|
|
186
|
+
self.plain = None
|
|
187
|
+
self.html_content = None
|
|
188
|
+
p = self.page()
|
|
189
|
+
if not p:
|
|
190
|
+
self.setPage(CustomWebEnginePage(self.window, self, profile=SHARED_PROFILE))
|
|
191
|
+
p = self.page()
|
|
188
192
|
|
|
189
|
-
|
|
193
|
+
p.runJavaScript(
|
|
194
|
+
f"""clean();"""
|
|
195
|
+
)
|
|
196
|
+
p.profile().clearHttpCache()
|
|
197
|
+
try:
|
|
198
|
+
p.history().clear()
|
|
199
|
+
except Exception:
|
|
200
|
+
pass
|
|
190
201
|
mem_clean()
|
|
191
202
|
|
|
192
203
|
def on_delete(self):
|
|
@@ -208,8 +219,6 @@ class ChatWebOutput(QWebEngineView):
|
|
|
208
219
|
if page:
|
|
209
220
|
self._teardown_page(page)
|
|
210
221
|
|
|
211
|
-
self._release_profile_after_page(page, prof)
|
|
212
|
-
|
|
213
222
|
# safely unhook signals (may not have been hooked)
|
|
214
223
|
for sig, slot in (
|
|
215
224
|
(self.loadFinished, self.on_page_loaded),
|
|
@@ -311,7 +320,7 @@ class ChatWebOutput(QWebEngineView):
|
|
|
311
320
|
|
|
312
321
|
# audio read (get text only on click, don't copy immediately)
|
|
313
322
|
action = QAction(QIcon(":/icons/volume.svg"), trans('text.context_menu.audio.read'), self)
|
|
314
|
-
action.triggered.connect(
|
|
323
|
+
action.triggered.connect(self._read_selected_text)
|
|
315
324
|
menu.addAction(action)
|
|
316
325
|
|
|
317
326
|
# copy to
|
|
@@ -320,7 +329,7 @@ class ChatWebOutput(QWebEngineView):
|
|
|
320
329
|
|
|
321
330
|
# save as (selected) - get selection at the moment of click
|
|
322
331
|
action = QAction(QIcon(":/icons/save.svg"), trans('action.save_selection_as'), self)
|
|
323
|
-
action.triggered.connect(
|
|
332
|
+
action.triggered.connect(self._save_selected_txt)
|
|
324
333
|
menu.addAction(action)
|
|
325
334
|
else:
|
|
326
335
|
# select all
|
|
@@ -344,6 +353,20 @@ class ChatWebOutput(QWebEngineView):
|
|
|
344
353
|
|
|
345
354
|
menu.exec_(self.mapToGlobal(position))
|
|
346
355
|
|
|
356
|
+
@Slot()
|
|
357
|
+
def _save_selected_txt(self):
|
|
358
|
+
"""Save selected content as text file"""
|
|
359
|
+
self.signals.save_as.emit(self.get_selected_text(), 'txt')
|
|
360
|
+
|
|
361
|
+
@Slot()
|
|
362
|
+
def _read_selected_text(self):
|
|
363
|
+
"""
|
|
364
|
+
Read selected text using text-to-speech
|
|
365
|
+
"""
|
|
366
|
+
selected_text = self.get_selected_text()
|
|
367
|
+
if selected_text:
|
|
368
|
+
self.signals.audio_read.emit(selected_text)
|
|
369
|
+
|
|
347
370
|
@Slot()
|
|
348
371
|
def _save_as_text(self):
|
|
349
372
|
"""
|
|
@@ -497,6 +520,7 @@ class CustomWebEnginePage(QWebEnginePage):
|
|
|
497
520
|
return super().acceptNavigationRequest(url, _type, isMainFrame)
|
|
498
521
|
|
|
499
522
|
def javaScriptConsoleMessage(self, level, message, line_number, source_id):
|
|
523
|
+
# print("[JS CONSOLE] Line", line_number, ":", message)
|
|
500
524
|
self.signals.js_message.emit(line_number, message, source_id) # handled in debug controller
|
|
501
525
|
|
|
502
526
|
def cleanup(self):
|
pygpt_net/utils.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.08.
|
|
9
|
+
# Updated Date: 2025.08.19 07:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import json
|
|
@@ -14,7 +14,8 @@ import os
|
|
|
14
14
|
import re
|
|
15
15
|
from datetime import datetime
|
|
16
16
|
|
|
17
|
-
from PySide6
|
|
17
|
+
from PySide6 import QtCore, QtGui
|
|
18
|
+
from PySide6.QtWidgets import QApplication
|
|
18
19
|
|
|
19
20
|
from pygpt_net.core.locale import Locale
|
|
20
21
|
|
|
@@ -268,19 +269,25 @@ def mem_clean():
|
|
|
268
269
|
gc.collect()
|
|
269
270
|
except Exception:
|
|
270
271
|
pass
|
|
272
|
+
|
|
271
273
|
try:
|
|
272
|
-
|
|
274
|
+
QApplication.sendPostedEvents(None, QtCore.QEvent.DeferredDelete)
|
|
275
|
+
QApplication.processEvents(QtCore.QEventLoop.AllEvents, 50)
|
|
273
276
|
except Exception:
|
|
274
277
|
pass
|
|
278
|
+
|
|
279
|
+
try:
|
|
280
|
+
QtGui.QPixmapCache.clear()
|
|
281
|
+
except Exception:
|
|
282
|
+
pass
|
|
283
|
+
|
|
275
284
|
try:
|
|
276
285
|
if sys.platform.startswith("linux"):
|
|
277
286
|
import ctypes, ctypes.util
|
|
278
|
-
|
|
279
|
-
libc = ctypes.CDLL(libc_path, use_errno=True)
|
|
287
|
+
libc = ctypes.CDLL(ctypes.util.find_library("c") or "libc.so.6")
|
|
280
288
|
if hasattr(libc, "malloc_trim"):
|
|
281
|
-
libc.malloc_trim
|
|
282
|
-
|
|
283
|
-
ok = bool(libc.malloc_trim(0))
|
|
289
|
+
libc.malloc_trim(0)
|
|
290
|
+
ok = True
|
|
284
291
|
elif sys.platform == "win32":
|
|
285
292
|
import ctypes, ctypes.wintypes
|
|
286
293
|
kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: pygpt-net
|
|
3
|
-
Version: 2.6.
|
|
3
|
+
Version: 2.6.12
|
|
4
4
|
Summary: Desktop AI Assistant powered by: OpenAI GPT-5, o1, o3, GPT-4, 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: py_gpt,py-gpt,pygpt,desktop,app,o1,o3,gpt-5,gpt,gpt4,gpt-4o,gpt-4v,gpt3.5,gpt-4,gpt-4-vision,gpt-3.5,llama3,mistral,gemini,grok,deepseek,bielik,claude,tts,whisper,vision,chatgpt,dall-e,chat,chatbot,assistant,text completion,image generation,ai,api,openai,api key,langchain,llama-index,ollama,presets,ui,qt,pyside
|
|
@@ -108,7 +108,7 @@ Description-Content-Type: text/markdown
|
|
|
108
108
|
|
|
109
109
|
[](https://snapcraft.io/pygpt)
|
|
110
110
|
|
|
111
|
-
Release: **2.6.
|
|
111
|
+
Release: **2.6.12** | build: **2025-08-19** | Python: **>=3.10, <3.14**
|
|
112
112
|
|
|
113
113
|
> Official website: https://pygpt.net | Documentation: https://pygpt.readthedocs.io
|
|
114
114
|
>
|
|
@@ -4566,6 +4566,16 @@ may consume additional tokens that are not displayed in the main window.
|
|
|
4566
4566
|
|
|
4567
4567
|
## Recent changes:
|
|
4568
4568
|
|
|
4569
|
+
**2.6.12 (2025-08-19)**
|
|
4570
|
+
|
|
4571
|
+
- Optimized web renderer memory cleanup.
|
|
4572
|
+
|
|
4573
|
+
**2.6.11 (2025-08-18)**
|
|
4574
|
+
|
|
4575
|
+
- Added the ability to close the dialog window with the Esc key.
|
|
4576
|
+
- Made context item deletion without output refresh.
|
|
4577
|
+
- Optimizations.
|
|
4578
|
+
|
|
4569
4579
|
**2.6.10 (2025-08-17)**
|
|
4570
4580
|
|
|
4571
4581
|
- Enhanced the handling of the context list.
|