pygpt-net 2.6.55__py3-none-any.whl → 2.6.57__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 +12 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/app.py +26 -22
- pygpt_net/config.py +44 -0
- pygpt_net/controller/audio/audio.py +0 -0
- pygpt_net/controller/calendar/calendar.py +0 -0
- pygpt_net/controller/calendar/note.py +0 -0
- pygpt_net/controller/chat/chat.py +0 -0
- pygpt_net/controller/chat/handler/openai_stream.py +2 -1
- pygpt_net/controller/chat/handler/worker.py +0 -0
- pygpt_net/controller/chat/remote_tools.py +5 -3
- pygpt_net/controller/chat/render.py +0 -0
- pygpt_net/controller/chat/text.py +0 -0
- pygpt_net/controller/ctx/common.py +0 -0
- pygpt_net/controller/debug/debug.py +26 -2
- pygpt_net/controller/debug/fixtures.py +1 -1
- pygpt_net/controller/dialogs/confirm.py +15 -1
- pygpt_net/controller/dialogs/debug.py +2 -0
- pygpt_net/controller/lang/mapping.py +0 -0
- pygpt_net/controller/launcher/launcher.py +0 -0
- pygpt_net/controller/mode/mode.py +0 -0
- pygpt_net/controller/presets/presets.py +0 -0
- pygpt_net/controller/realtime/realtime.py +0 -0
- pygpt_net/controller/theme/theme.py +0 -0
- pygpt_net/controller/ui/mode.py +5 -3
- pygpt_net/controller/ui/tabs.py +0 -0
- pygpt_net/core/agents/agents.py +3 -1
- pygpt_net/core/agents/custom.py +150 -0
- pygpt_net/core/agents/provider.py +0 -0
- pygpt_net/core/builder/__init__.py +12 -0
- pygpt_net/core/builder/graph.py +478 -0
- pygpt_net/core/calendar/calendar.py +0 -0
- pygpt_net/core/ctx/ctx.py +0 -0
- pygpt_net/core/ctx/output.py +0 -0
- pygpt_net/core/debug/agent.py +0 -0
- pygpt_net/core/debug/agent_builder.py +29 -0
- pygpt_net/core/debug/console/console.py +0 -0
- pygpt_net/core/debug/db.py +0 -0
- pygpt_net/core/debug/debug.py +0 -0
- pygpt_net/core/debug/events.py +0 -0
- pygpt_net/core/debug/indexes.py +0 -0
- pygpt_net/core/debug/kernel.py +0 -0
- pygpt_net/core/debug/tabs.py +0 -0
- pygpt_net/core/filesystem/filesystem.py +0 -0
- pygpt_net/core/fixtures/__init__ +0 -0
- pygpt_net/core/fixtures/stream/__init__.py +0 -0
- pygpt_net/core/fixtures/stream/generator.py +0 -0
- pygpt_net/core/models/models.py +2 -1
- pygpt_net/core/plugins/plugins.py +60 -0
- pygpt_net/core/render/plain/pid.py +0 -0
- pygpt_net/core/render/plain/renderer.py +26 -4
- pygpt_net/core/render/web/body.py +46 -4
- pygpt_net/core/render/web/debug.py +0 -0
- pygpt_net/core/render/web/helpers.py +0 -0
- pygpt_net/core/render/web/pid.py +0 -0
- pygpt_net/core/render/web/renderer.py +15 -20
- pygpt_net/core/tabs/tab.py +0 -0
- pygpt_net/core/tabs/tabs.py +0 -0
- pygpt_net/core/text/utils.py +0 -0
- pygpt_net/css.qrc +0 -0
- pygpt_net/css_rc.py +0 -0
- pygpt_net/data/config/config.json +8 -7
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/config/settings.json +14 -0
- pygpt_net/data/css/web-blocks.css +9 -0
- pygpt_net/data/css/web-blocks.dark.css +6 -0
- pygpt_net/data/css/web-blocks.darkest.css +6 -0
- pygpt_net/data/css/web-chatgpt.css +14 -6
- pygpt_net/data/css/web-chatgpt.dark.css +6 -0
- pygpt_net/data/css/web-chatgpt.darkest.css +6 -0
- pygpt_net/data/css/web-chatgpt.light.css +6 -0
- pygpt_net/data/css/web-chatgpt_wide.css +14 -6
- pygpt_net/data/css/web-chatgpt_wide.dark.css +6 -0
- pygpt_net/data/css/web-chatgpt_wide.darkest.css +6 -0
- pygpt_net/data/css/web-chatgpt_wide.light.css +6 -0
- pygpt_net/data/fixtures/fake_stream.txt +14 -1
- pygpt_net/data/icons/case.svg +0 -0
- pygpt_net/data/icons/chat1.svg +0 -0
- pygpt_net/data/icons/chat2.svg +0 -0
- pygpt_net/data/icons/chat3.svg +0 -0
- pygpt_net/data/icons/chat4.svg +0 -0
- pygpt_net/data/icons/fit.svg +0 -0
- pygpt_net/data/icons/note1.svg +0 -0
- pygpt_net/data/icons/note2.svg +0 -0
- pygpt_net/data/icons/note3.svg +0 -0
- pygpt_net/data/icons/stt.svg +0 -0
- pygpt_net/data/icons/translate.svg +0 -0
- pygpt_net/data/icons/tts.svg +0 -0
- pygpt_net/data/icons/url.svg +0 -0
- pygpt_net/data/icons/vision.svg +0 -0
- pygpt_net/data/icons/web_off.svg +0 -0
- pygpt_net/data/icons/web_on.svg +0 -0
- pygpt_net/data/js/app/async.js +166 -0
- pygpt_net/data/js/app/bridge.js +88 -0
- pygpt_net/data/js/app/common.js +212 -0
- pygpt_net/data/js/app/config.js +223 -0
- pygpt_net/data/js/app/custom.js +961 -0
- pygpt_net/data/js/app/data.js +84 -0
- pygpt_net/data/js/app/dom.js +322 -0
- pygpt_net/data/js/app/events.js +400 -0
- pygpt_net/data/js/app/highlight.js +542 -0
- pygpt_net/data/js/app/logger.js +305 -0
- pygpt_net/data/js/app/markdown.js +1137 -0
- pygpt_net/data/js/app/math.js +167 -0
- pygpt_net/data/js/app/nodes.js +395 -0
- pygpt_net/data/js/app/queue.js +260 -0
- pygpt_net/data/js/app/raf.js +250 -0
- pygpt_net/data/js/app/runtime.js +582 -0
- pygpt_net/data/js/app/scroll.js +433 -0
- pygpt_net/data/js/app/stream.js +2708 -0
- pygpt_net/data/js/app/template.js +287 -0
- pygpt_net/data/js/app/tool.js +87 -0
- pygpt_net/data/js/app/ui.js +86 -0
- pygpt_net/data/js/app/user.js +380 -0
- pygpt_net/data/js/app/utils.js +64 -0
- pygpt_net/data/js/app.min.js +880 -0
- pygpt_net/data/js/markdown-it/markdown-it-katex.min.js +1 -1
- pygpt_net/data/js/markdown-it/markdown-it.min.js +0 -0
- pygpt_net/data/locale/locale.de.ini +3 -1
- pygpt_net/data/locale/locale.en.ini +8 -0
- pygpt_net/data/locale/locale.es.ini +2 -0
- pygpt_net/data/locale/locale.fr.ini +2 -0
- pygpt_net/data/locale/locale.it.ini +2 -0
- pygpt_net/data/locale/locale.pl.ini +3 -1
- pygpt_net/data/locale/locale.uk.ini +3 -1
- pygpt_net/data/locale/locale.zh.ini +2 -0
- pygpt_net/data/locale/plugin.osm.en.ini +24 -24
- pygpt_net/data/locale/plugin.wolfram.en.ini +9 -9
- pygpt_net/fonts.qrc +0 -0
- pygpt_net/fonts_rc.py +0 -0
- pygpt_net/icons.qrc +0 -0
- pygpt_net/icons_rc.py +0 -0
- pygpt_net/item/agent.py +62 -0
- pygpt_net/item/builder_layout.py +62 -0
- pygpt_net/js.qrc +24 -1
- pygpt_net/js_rc.py +51394 -33687
- pygpt_net/plugin/base/worker.py +0 -0
- pygpt_net/plugin/cmd_web/config.py +17 -17
- pygpt_net/plugin/cmd_web/worker.py +325 -171
- pygpt_net/plugin/mcp/__init__.py +0 -0
- pygpt_net/plugin/mcp/config.py +0 -0
- pygpt_net/plugin/mcp/plugin.py +0 -0
- pygpt_net/plugin/mcp/worker.py +0 -0
- pygpt_net/plugin/osm/__init__.py +0 -0
- pygpt_net/plugin/osm/config.py +0 -0
- pygpt_net/plugin/osm/plugin.py +0 -0
- pygpt_net/plugin/osm/worker.py +0 -0
- pygpt_net/plugin/wolfram/__init__.py +0 -0
- pygpt_net/plugin/wolfram/config.py +0 -0
- pygpt_net/plugin/wolfram/plugin.py +0 -0
- pygpt_net/plugin/wolfram/worker.py +0 -0
- pygpt_net/provider/api/anthropic/tools.py +0 -0
- pygpt_net/provider/api/google/__init__.py +0 -0
- pygpt_net/provider/api/google/video.py +0 -0
- pygpt_net/provider/api/openai/agents/experts.py +0 -0
- pygpt_net/provider/api/openai/agents/remote_tools.py +0 -0
- pygpt_net/provider/api/openai/remote_tools.py +0 -0
- pygpt_net/provider/api/openai/responses.py +0 -0
- pygpt_net/provider/api/x_ai/__init__.py +2 -0
- pygpt_net/provider/api/x_ai/remote.py +0 -0
- pygpt_net/provider/core/agent/__init__.py +10 -0
- pygpt_net/provider/core/agent/base.py +51 -0
- pygpt_net/provider/core/agent/json_file.py +200 -0
- pygpt_net/provider/core/config/patch.py +33 -0
- pygpt_net/provider/core/config/patches/__init__.py +0 -0
- pygpt_net/provider/core/config/patches/patch_before_2_6_42.py +1 -0
- pygpt_net/provider/core/ctx/db_sqlite/storage.py +0 -0
- pygpt_net/provider/core/model/patches/__init__.py +0 -0
- pygpt_net/provider/core/model/patches/patch_before_2_6_42.py +0 -0
- pygpt_net/provider/core/preset/patch.py +0 -0
- pygpt_net/provider/core/preset/patches/__init__.py +0 -0
- pygpt_net/provider/core/preset/patches/patch_before_2_6_42.py +0 -0
- pygpt_net/provider/llms/anthropic.py +4 -0
- pygpt_net/provider/llms/base.py +2 -0
- pygpt_net/provider/llms/deepseek_api.py +2 -0
- pygpt_net/provider/llms/google.py +2 -0
- pygpt_net/provider/llms/hugging_face_api.py +4 -0
- pygpt_net/provider/llms/hugging_face_embedding.py +0 -0
- pygpt_net/provider/llms/hugging_face_router.py +2 -0
- pygpt_net/provider/llms/local.py +0 -0
- pygpt_net/provider/llms/mistral.py +4 -0
- pygpt_net/provider/llms/open_router.py +0 -0
- pygpt_net/provider/llms/perplexity.py +2 -0
- pygpt_net/provider/llms/utils.py +0 -0
- pygpt_net/provider/llms/voyage.py +0 -0
- pygpt_net/provider/llms/x_ai.py +2 -0
- pygpt_net/tools/agent_builder/__init__.py +12 -0
- pygpt_net/tools/agent_builder/tool.py +292 -0
- pygpt_net/tools/agent_builder/ui/__init__.py +0 -0
- pygpt_net/tools/agent_builder/ui/dialogs.py +152 -0
- pygpt_net/tools/agent_builder/ui/list.py +228 -0
- pygpt_net/tools/code_interpreter/ui/html.py +0 -0
- pygpt_net/tools/code_interpreter/ui/widgets.py +0 -0
- pygpt_net/tools/html_canvas/tool.py +23 -6
- pygpt_net/tools/html_canvas/ui/widgets.py +224 -2
- pygpt_net/ui/layout/chat/chat.py +0 -0
- pygpt_net/ui/layout/chat/output.py +5 -5
- pygpt_net/ui/main.py +10 -9
- pygpt_net/ui/menu/debug.py +39 -1
- pygpt_net/ui/widget/builder/__init__.py +12 -0
- pygpt_net/ui/widget/builder/editor.py +2001 -0
- pygpt_net/ui/widget/dialog/base.py +4 -1
- pygpt_net/ui/widget/draw/painter.py +0 -0
- pygpt_net/ui/widget/element/labels.py +9 -4
- pygpt_net/ui/widget/lists/db.py +0 -0
- pygpt_net/ui/widget/lists/debug.py +0 -0
- pygpt_net/ui/widget/tabs/body.py +0 -0
- pygpt_net/ui/widget/textarea/html.py +1 -0
- pygpt_net/ui/widget/textarea/input.py +28 -10
- pygpt_net/ui/widget/textarea/output.py +21 -1
- pygpt_net/ui/widget/textarea/web.py +31 -3
- pygpt_net/utils.py +40 -0
- {pygpt_net-2.6.55.dist-info → pygpt_net-2.6.57.dist-info}/METADATA +16 -2
- {pygpt_net-2.6.55.dist-info → pygpt_net-2.6.57.dist-info}/RECORD +116 -77
- pygpt_net/data/js/app.js +0 -5869
- {pygpt_net-2.6.55.dist-info → pygpt_net-2.6.57.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.55.dist-info → pygpt_net-2.6.57.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.55.dist-info → pygpt_net-2.6.57.dist-info}/entry_points.txt +0 -0
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6.QtWidgets import QApplication
|
|
13
|
-
from PySide6.QtCore import QRect, QSize, QPoint, QEvent
|
|
13
|
+
from PySide6.QtCore import QRect, QSize, QPoint, QEvent, Qt
|
|
14
14
|
from PySide6.QtWidgets import QDialog
|
|
15
15
|
|
|
16
16
|
|
|
@@ -26,6 +26,9 @@ class BaseDialog(QDialog):
|
|
|
26
26
|
self.window = window
|
|
27
27
|
self.id = id
|
|
28
28
|
self.disable_geometry_store = False
|
|
29
|
+
self.setWindowFlags(
|
|
30
|
+
self.windowFlags() | Qt.WindowMaximizeButtonHint
|
|
31
|
+
)
|
|
29
32
|
|
|
30
33
|
def showEvent(self, event):
|
|
31
34
|
"""
|
|
File without changes
|
|
@@ -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.19 00:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6.QtCore import Qt, QTimer, QRect, Signal, QUrl, QEvent
|
|
@@ -124,15 +124,16 @@ class CmdLabel(QLineEdit):
|
|
|
124
124
|
class IconLabel(QLabel):
|
|
125
125
|
clicked = Signal()
|
|
126
126
|
|
|
127
|
-
def __init__(self, icon: str, window=None):
|
|
127
|
+
def __init__(self, icon: str, window=None, hover=True):
|
|
128
128
|
super().__init__("", window)
|
|
129
129
|
self.window = window
|
|
130
130
|
self.setWordWrap(True)
|
|
131
131
|
self.setAlignment(Qt.AlignRight)
|
|
132
132
|
self.setProperty('class', 'label-chat-status')
|
|
133
133
|
self.setContentsMargins(0, 0, 0, 0)
|
|
134
|
-
self.
|
|
135
|
-
|
|
134
|
+
self.hover = hover
|
|
135
|
+
if hover:
|
|
136
|
+
self.setMouseTracking(True)
|
|
136
137
|
self.original_pixmap = None
|
|
137
138
|
self.hover_pixmap = None
|
|
138
139
|
self.set_icon(icon)
|
|
@@ -181,6 +182,8 @@ class IconLabel(QLabel):
|
|
|
181
182
|
return recolored
|
|
182
183
|
|
|
183
184
|
def enterEvent(self, event: QEvent):
|
|
185
|
+
if not self.hover:
|
|
186
|
+
return
|
|
184
187
|
self.setCursor(Qt.PointingHandCursor)
|
|
185
188
|
self.hover_pixmap = self.create_hover_icon(self.original_pixmap)
|
|
186
189
|
if self.hover_pixmap is not None and not self.hover_pixmap.isNull():
|
|
@@ -190,6 +193,8 @@ class IconLabel(QLabel):
|
|
|
190
193
|
super().enterEvent(event)
|
|
191
194
|
|
|
192
195
|
def leaveEvent(self, event: QEvent):
|
|
196
|
+
if not self.hover:
|
|
197
|
+
return
|
|
193
198
|
self.unsetCursor()
|
|
194
199
|
self.setPixmap(self.original_pixmap)
|
|
195
200
|
super().leaveEvent(event)
|
pygpt_net/ui/widget/lists/db.py
CHANGED
|
File without changes
|
|
File without changes
|
pygpt_net/ui/widget/tabs/body.py
CHANGED
|
File without changes
|
|
@@ -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.22 12:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import Optional
|
|
@@ -30,10 +30,12 @@ class ChatInput(QTextEdit):
|
|
|
30
30
|
ICON_PASTE = QIcon(":/icons/paste.svg")
|
|
31
31
|
ICON_VOLUME = QIcon(":/icons/volume.svg")
|
|
32
32
|
ICON_SAVE = QIcon(":/icons/save.svg")
|
|
33
|
-
ICON_ATTACHMENT = QIcon(":/icons/add.svg")
|
|
34
|
-
|
|
33
|
+
# ICON_ATTACHMENT = QIcon(":/icons/add.svg")
|
|
34
|
+
ICON_ATTACHMENT = QIcon(":/icons/attachment.svg")
|
|
35
35
|
ICON_MIC_ON = QIcon(":/icons/mic.svg")
|
|
36
36
|
ICON_MIC_OFF = QIcon(":/icons/mic_off.svg")
|
|
37
|
+
ICON_WEB_ON = QIcon(":/icons/web_on.svg")
|
|
38
|
+
ICON_WEB_OFF = QIcon(":/icons/web_off.svg")
|
|
37
39
|
|
|
38
40
|
def __init__(self, window=None):
|
|
39
41
|
"""
|
|
@@ -87,6 +89,16 @@ class ChatInput(QTextEdit):
|
|
|
87
89
|
callback=self.action_toggle_mic,
|
|
88
90
|
visible=False,
|
|
89
91
|
)
|
|
92
|
+
# Add a web search toggle button
|
|
93
|
+
self.add_icon(
|
|
94
|
+
key="web",
|
|
95
|
+
icon=self.ICON_WEB_OFF,
|
|
96
|
+
alt_icon=self.ICON_WEB_ON,
|
|
97
|
+
tooltip=trans('icon.remote_tool.web'),
|
|
98
|
+
alt_tooltip=trans('icon.remote_tool.web'),
|
|
99
|
+
callback=self.action_toggle_web,
|
|
100
|
+
visible=True,
|
|
101
|
+
)
|
|
90
102
|
|
|
91
103
|
# Apply initial margins (top padding + left space for icons)
|
|
92
104
|
self._apply_margins()
|
|
@@ -108,7 +120,7 @@ class ChatInput(QTextEdit):
|
|
|
108
120
|
|
|
109
121
|
self._tokens_timer = QTimer(self)
|
|
110
122
|
self._tokens_timer.setSingleShot(True)
|
|
111
|
-
self._tokens_timer.setInterval(
|
|
123
|
+
self._tokens_timer.setInterval(1500)
|
|
112
124
|
self._tokens_timer.timeout.connect(self.window.controller.ui.update_tokens)
|
|
113
125
|
self.textChanged.connect(self._on_text_changed_tokens)
|
|
114
126
|
|
|
@@ -221,27 +233,29 @@ class ChatInput(QTextEdit):
|
|
|
221
233
|
def keyPressEvent(self, event):
|
|
222
234
|
"""
|
|
223
235
|
Key press event
|
|
224
|
-
|
|
225
|
-
:param event: key event
|
|
226
236
|
"""
|
|
227
237
|
handled = False
|
|
228
238
|
key = event.key()
|
|
239
|
+
|
|
229
240
|
if key in (Qt.Key_Return, Qt.Key_Enter):
|
|
230
241
|
mode = self.window.core.config.get('send_mode')
|
|
231
242
|
if mode > 0:
|
|
232
|
-
|
|
243
|
+
mods = event.modifiers()
|
|
244
|
+
has_shift_or_ctrl = bool(mods & (Qt.ShiftModifier | Qt.ControlModifier))
|
|
245
|
+
|
|
233
246
|
if mode == 2:
|
|
234
|
-
if
|
|
247
|
+
if has_shift_or_ctrl:
|
|
235
248
|
self.window.controller.chat.input.send_input()
|
|
236
249
|
handled = True
|
|
237
250
|
else:
|
|
238
|
-
if
|
|
251
|
+
if not has_shift_or_ctrl:
|
|
239
252
|
self.window.controller.chat.input.send_input()
|
|
240
253
|
handled = True
|
|
254
|
+
|
|
241
255
|
self.setFocus()
|
|
242
|
-
# Collapse to minimum after sending
|
|
243
256
|
if handled:
|
|
244
257
|
QTimer.singleShot(0, self.collapse_to_min)
|
|
258
|
+
|
|
245
259
|
elif key == Qt.Key_Escape and self.window.controller.ctx.extra.is_editing():
|
|
246
260
|
self.window.controller.ctx.extra.edit_cancel()
|
|
247
261
|
handled = True
|
|
@@ -288,6 +302,10 @@ class ChatInput(QTextEdit):
|
|
|
288
302
|
"""Toggle microphone (button click)."""
|
|
289
303
|
self.window.dispatch(Event(Event.AUDIO_INPUT_RECORD_TOGGLE))
|
|
290
304
|
|
|
305
|
+
def action_toggle_web(self):
|
|
306
|
+
"""Toggle web search (button click)."""
|
|
307
|
+
self.window.controller.chat.remote_tools.toggle('web_search')
|
|
308
|
+
|
|
291
309
|
# -------------------- Left icon bar --------------------
|
|
292
310
|
# - Add icons: add_icon(...) or add_icons([...])
|
|
293
311
|
# - Show/hide: set_icon_visible(key, bool)
|
|
@@ -45,6 +45,9 @@ class ChatOutput(QTextBrowser):
|
|
|
45
45
|
self.tab = None
|
|
46
46
|
self.installEventFilter(self)
|
|
47
47
|
self.setProperty('class', 'layout-output-plain')
|
|
48
|
+
self._auto_scroll = True
|
|
49
|
+
self._auto_scroll_margin = None
|
|
50
|
+
self.verticalScrollBar().valueChanged.connect(self._on_vsb_value_changed)
|
|
48
51
|
|
|
49
52
|
def on_delete(self):
|
|
50
53
|
"""Clean up on delete"""
|
|
@@ -197,4 +200,21 @@ class ChatOutput(QTextBrowser):
|
|
|
197
200
|
:param e: focus event
|
|
198
201
|
"""
|
|
199
202
|
super().focusInEvent(e)
|
|
200
|
-
self.window.controller.finder.focus_in(self.finder)
|
|
203
|
+
self.window.controller.finder.focus_in(self.finder)
|
|
204
|
+
|
|
205
|
+
def _calc_auto_scroll_margin(self) -> int:
|
|
206
|
+
vsb = self.verticalScrollBar()
|
|
207
|
+
ps = vsb.pageStep()
|
|
208
|
+
if ps <= 0:
|
|
209
|
+
return 2
|
|
210
|
+
return max(2, min(64, ps // 10))
|
|
211
|
+
|
|
212
|
+
def _on_vsb_value_changed(self, value: int):
|
|
213
|
+
self._auto_scroll = self.was_at_bottom()
|
|
214
|
+
|
|
215
|
+
def was_at_bottom(self) -> bool:
|
|
216
|
+
vsb = self.verticalScrollBar()
|
|
217
|
+
return (vsb.maximum() - vsb.value()) <= self._calc_auto_scroll_margin()
|
|
218
|
+
|
|
219
|
+
def is_auto_scroll_enabled(self) -> bool:
|
|
220
|
+
return self._auto_scroll
|
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
# Created By : Marcin Szczygliński #
|
|
9
9
|
# Updated Date: 2025.09.16 02:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
|
-
|
|
11
|
+
from PySide6 import QtCore
|
|
12
12
|
from PySide6.QtCore import Qt, QObject, Signal, Slot, QEvent, QUrl, QCoreApplication, QEventLoop
|
|
13
13
|
from PySide6.QtWebChannel import QWebChannel
|
|
14
14
|
from PySide6.QtWebEngineCore import QWebEngineSettings, QWebEnginePage, QWebEngineProfile
|
|
15
15
|
from PySide6.QtWebEngineWidgets import QWebEngineView
|
|
16
16
|
from PySide6.QtGui import QAction, QIcon
|
|
17
|
-
from PySide6.QtWidgets import QMenu
|
|
17
|
+
from PySide6.QtWidgets import QMenu, QDialog, QVBoxLayout
|
|
18
18
|
|
|
19
19
|
from pygpt_net.core.events import RenderEvent
|
|
20
20
|
from pygpt_net.item.ctx import CtxMeta
|
|
@@ -44,6 +44,7 @@ class ChatWebOutput(QWebEngineView):
|
|
|
44
44
|
self.meta = None
|
|
45
45
|
self.tab = None
|
|
46
46
|
self.setProperty('class', 'layout-output-web')
|
|
47
|
+
self.setMouseTracking(True)
|
|
47
48
|
|
|
48
49
|
# OpenGL widgets
|
|
49
50
|
self._glwidget = None
|
|
@@ -87,6 +88,33 @@ class ChatWebOutput(QWebEngineView):
|
|
|
87
88
|
pass
|
|
88
89
|
# self.window.core.debug.log(e)
|
|
89
90
|
|
|
91
|
+
def show_devtools(self, modal: bool = False, title: str = "DevTools"):
|
|
92
|
+
"""Show DevTools window"""
|
|
93
|
+
if getattr(self, "_devtools_dlg", None) is None:
|
|
94
|
+
dlg = QDialog(self.window)
|
|
95
|
+
dlg.setWindowTitle(title)
|
|
96
|
+
dlg.setModal(modal)
|
|
97
|
+
dlg.setAttribute(Qt.WA_DeleteOnClose, True)
|
|
98
|
+
dlg.resize(1100, 750)
|
|
99
|
+
|
|
100
|
+
layout = QVBoxLayout(dlg)
|
|
101
|
+
view = QWebEngineView(dlg)
|
|
102
|
+
layout.addWidget(view)
|
|
103
|
+
|
|
104
|
+
profile = self.page().profile()
|
|
105
|
+
view.setPage(QWebEnginePage(profile, view))
|
|
106
|
+
|
|
107
|
+
self.page().setDevToolsPage(view.page())
|
|
108
|
+
|
|
109
|
+
dlg.destroyed.connect(lambda: setattr(self, "_devtools_dlg", None))
|
|
110
|
+
|
|
111
|
+
self._devtools_dlg = dlg
|
|
112
|
+
self._devtools_view = view
|
|
113
|
+
|
|
114
|
+
self._devtools_dlg.show()
|
|
115
|
+
self._devtools_dlg.raise_()
|
|
116
|
+
self._devtools_dlg.activateWindow()
|
|
117
|
+
|
|
90
118
|
def unload(self):
|
|
91
119
|
"""Unload the current page and free resources"""
|
|
92
120
|
try:
|
|
@@ -503,7 +531,7 @@ class CustomWebEnginePage(QWebEnginePage):
|
|
|
503
531
|
return super().acceptNavigationRequest(url, _type, isMainFrame)
|
|
504
532
|
|
|
505
533
|
def javaScriptConsoleMessage(self, level, message, line_number, source_id):
|
|
506
|
-
|
|
534
|
+
print("[JS CONSOLE] Line", line_number, ":", message)
|
|
507
535
|
self.signals.js_message.emit(line_number, message, source_id) # handled in debug controller
|
|
508
536
|
|
|
509
537
|
def cleanup(self):
|
pygpt_net/utils.py
CHANGED
|
@@ -78,6 +78,46 @@ def sizeof_fmt(num: Any, suffix: str = 'B'):
|
|
|
78
78
|
num /= 1024.0
|
|
79
79
|
return f"{num:.1f} Yi{suffix}".replace('.', ',')
|
|
80
80
|
|
|
81
|
+
def set_env(key: str, value: Any, append: bool = False, allow_overwrite: bool = False):
|
|
82
|
+
"""
|
|
83
|
+
Setup environment flag / variable
|
|
84
|
+
|
|
85
|
+
:param key: env key
|
|
86
|
+
:param value: env value
|
|
87
|
+
:param append: append to existing value
|
|
88
|
+
:param allow_overwrite: allow overwrite value before setting
|
|
89
|
+
"""
|
|
90
|
+
if allow_overwrite and key in os.environ:
|
|
91
|
+
return
|
|
92
|
+
if append:
|
|
93
|
+
if key in os.environ and os.environ[key]:
|
|
94
|
+
os.environ[key] = f"{os.environ[key]} {value}"
|
|
95
|
+
else:
|
|
96
|
+
os.environ[key] = str(value)
|
|
97
|
+
else:
|
|
98
|
+
os.environ[key] = str(value)
|
|
99
|
+
|
|
100
|
+
def has_env(key: str) -> bool:
|
|
101
|
+
"""
|
|
102
|
+
Check if environment variable is set
|
|
103
|
+
|
|
104
|
+
:param key: env key
|
|
105
|
+
:return: True if env variable is set
|
|
106
|
+
"""
|
|
107
|
+
return key in os.environ and os.environ[key] != ""
|
|
108
|
+
|
|
109
|
+
def get_env(key: str, default: Any = None) -> Any:
|
|
110
|
+
"""
|
|
111
|
+
Get environment variable
|
|
112
|
+
|
|
113
|
+
:param key: env key
|
|
114
|
+
:param default: default value if env variable is not set
|
|
115
|
+
:return: env variable value or default
|
|
116
|
+
"""
|
|
117
|
+
if key in os.environ and os.environ[key]:
|
|
118
|
+
return os.environ[key]
|
|
119
|
+
return default
|
|
120
|
+
|
|
81
121
|
|
|
82
122
|
@contextmanager
|
|
83
123
|
def freeze_updates(widget):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: pygpt-net
|
|
3
|
-
Version: 2.6.
|
|
3
|
+
Version: 2.6.57
|
|
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, MCP, 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
|
|
@@ -119,7 +119,7 @@ Description-Content-Type: text/markdown
|
|
|
119
119
|
|
|
120
120
|
[](https://snapcraft.io/pygpt)
|
|
121
121
|
|
|
122
|
-
Release: **2.6.
|
|
122
|
+
Release: **2.6.57** | build: **2025-09-22** | Python: **>=3.10, <3.14**
|
|
123
123
|
|
|
124
124
|
> Official website: https://pygpt.net | Documentation: https://pygpt.readthedocs.io
|
|
125
125
|
>
|
|
@@ -2321,6 +2321,8 @@ Config -> Settings...
|
|
|
2321
2321
|
|
|
2322
2322
|
- `OpenGL hardware acceleration`: enables hardware acceleration in `WebEngine / Chromium` renderer. Default: False.
|
|
2323
2323
|
|
|
2324
|
+
- `Use proxy`: Enable this option to use a proxy for connections to APIs. Default: False.
|
|
2325
|
+
|
|
2324
2326
|
- `Proxy address`: Proxy address to be used for connection in API SDKs; supports HTTP/SOCKS, e.g. http://proxy.example.com or socks5://user:pass@host:port
|
|
2325
2327
|
|
|
2326
2328
|
- `Application environment (os.environ)`: Additional environment vars to set on application start.
|
|
@@ -3646,6 +3648,18 @@ may consume additional tokens that are not displayed in the main window.
|
|
|
3646
3648
|
|
|
3647
3649
|
## Recent changes:
|
|
3648
3650
|
|
|
3651
|
+
**2.6.57 (2025-09-22)**
|
|
3652
|
+
|
|
3653
|
+
- Changed: The web search icon has been moved to the input area.
|
|
3654
|
+
- Improved: The local web search plugin has been enhanced to retrieve multiple URLs at once.
|
|
3655
|
+
- Added: Use proxy switch in Settings.
|
|
3656
|
+
|
|
3657
|
+
**2.6.56 (2025-09-22)**
|
|
3658
|
+
|
|
3659
|
+
- Optimized: Memory usage and performance in streaming and rendering large contexts.
|
|
3660
|
+
- Added: Copy to clipboard functionality in user messages.
|
|
3661
|
+
- Added: Manual scroll in plain-text mode.
|
|
3662
|
+
|
|
3649
3663
|
**2.6.55 (2025-09-18)**
|
|
3650
3664
|
|
|
3651
3665
|
- Fixed: Unnecessary context loading from the database.
|