pygpt-net 2.6.10__py3-none-any.whl → 2.6.11__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 +6 -0
- pygpt_net/__init__.py +3 -3
- 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 +5 -5
- pygpt_net/controller/chat/stream.py +2 -3
- 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/debug/debug.py +6 -1
- 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 +35 -82
- pygpt_net/core/render/web/parser.py +11 -6
- pygpt_net/core/render/web/renderer.py +71 -37
- 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/ui/main.py +4 -2
- pygpt_net/ui/widget/textarea/web.py +17 -3
- {pygpt_net-2.6.10.dist-info → pygpt_net-2.6.11.dist-info}/METADATA +8 -2
- {pygpt_net-2.6.10.dist-info → pygpt_net-2.6.11.dist-info}/RECORD +37 -37
- {pygpt_net-2.6.10.dist-info → pygpt_net-2.6.11.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.10.dist-info → pygpt_net-2.6.11.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.10.dist-info → pygpt_net-2.6.11.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.08.
|
|
9
|
+
# Updated Date: 2025.08.18 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-08-
|
|
16
|
+
__version__ = "2.6.11"
|
|
17
|
+
__build__ = "2025-08-18"
|
|
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/config.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.18 01:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import copy
|
|
@@ -112,14 +112,14 @@ class Config:
|
|
|
112
112
|
"""
|
|
113
113
|
path = os.path.join(Path.home(), '.config', Config.CONFIG_DIR)
|
|
114
114
|
if "PYGPT_WORKDIR" in os.environ and os.environ["PYGPT_WORKDIR"] != "":
|
|
115
|
-
print("FORCE using workdir: {
|
|
115
|
+
print(f"FORCE using workdir: {os.environ['PYGPT_WORKDIR']}")
|
|
116
116
|
if not os.path.isabs(os.environ["PYGPT_WORKDIR"]):
|
|
117
117
|
path = os.path.join(os.getcwd(), os.environ["PYGPT_WORKDIR"])
|
|
118
118
|
else:
|
|
119
119
|
path = os.environ["PYGPT_WORKDIR"]
|
|
120
120
|
if not os.path.exists(path):
|
|
121
|
-
print("Workdir path not exists: {}"
|
|
122
|
-
print("Creating workdir path: {}"
|
|
121
|
+
print(f"Workdir path not exists: {path}")
|
|
122
|
+
print(f"Creating workdir path: {path}")
|
|
123
123
|
os.makedirs(path, exist_ok=True)
|
|
124
124
|
return path
|
|
125
125
|
|
|
@@ -147,7 +147,7 @@ class Config:
|
|
|
147
147
|
if os.path.exists(tmp_path):
|
|
148
148
|
path = Path(tmp_path)
|
|
149
149
|
else:
|
|
150
|
-
print("CRITICAL: Workdir path not exists: {}"
|
|
150
|
+
print(f"CRITICAL: Workdir path not exists: {tmp_path}")
|
|
151
151
|
return str(path)
|
|
152
152
|
|
|
153
153
|
def set_workdir(self, path: str, reload: bool = False):
|
|
@@ -181,7 +181,7 @@ class Config:
|
|
|
181
181
|
:return: user dir
|
|
182
182
|
"""
|
|
183
183
|
if dir not in self.dirs:
|
|
184
|
-
raise Exception('Unknown dir: {}'
|
|
184
|
+
raise Exception(f'Unknown dir: {dir}')
|
|
185
185
|
|
|
186
186
|
dir_data_allowed = ("img", "capture", "upload")
|
|
187
187
|
|
|
@@ -244,7 +244,7 @@ class Config:
|
|
|
244
244
|
|
|
245
245
|
print("===================================================")
|
|
246
246
|
print(f" {Color.BOLD}PyGPT {v}{Color.ENDC} build {build} ({os_name}, {architecture})")
|
|
247
|
-
print(" Author: Marcin
|
|
247
|
+
print(" Author: Marcin Szczygliński")
|
|
248
248
|
print(" GitHub: https://github.com/szczyglis-dev/py-gpt")
|
|
249
249
|
print(" Website: https://pygpt.net")
|
|
250
250
|
print(" Email: info@pygpt.net")
|
|
@@ -276,7 +276,7 @@ class Config:
|
|
|
276
276
|
if self.window is not None:
|
|
277
277
|
self.window.core.debug.log(e)
|
|
278
278
|
else:
|
|
279
|
-
print("Error loading version file: {}"
|
|
279
|
+
print(f"Error loading version file: {e}")
|
|
280
280
|
|
|
281
281
|
def get_build(self) -> str:
|
|
282
282
|
"""
|
|
@@ -297,7 +297,7 @@ class Config:
|
|
|
297
297
|
if self.window is not None:
|
|
298
298
|
self.window.core.debug.log(e)
|
|
299
299
|
else:
|
|
300
|
-
print("Error loading version file: {}"
|
|
300
|
+
print(f"Error loading version file: {e}")
|
|
301
301
|
|
|
302
302
|
def get_options(self) -> dict:
|
|
303
303
|
"""
|
|
@@ -541,9 +541,9 @@ class Config:
|
|
|
541
541
|
os.environ[item['name']] = value
|
|
542
542
|
list_loaded.append(item['name'])
|
|
543
543
|
except Exception as e:
|
|
544
|
-
print("Error setting env var: {}"
|
|
544
|
+
print(f"Error setting env var: {e}")
|
|
545
545
|
if list_loaded:
|
|
546
|
-
print("Setting environment vars: {
|
|
546
|
+
print(f"Setting environment vars: {', '.join(list_loaded)}")
|
|
547
547
|
|
|
548
548
|
def save(self, filename: str = "config.json"):
|
|
549
549
|
"""
|
|
@@ -6,9 +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.08.18 01:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
|
+
from PySide6.QtCore import Qt
|
|
13
|
+
from PySide6.QtWidgets import QApplication, QDialog, QMainWindow
|
|
14
|
+
|
|
12
15
|
from pygpt_net.core.events import BaseEvent, ControlEvent, AppEvent
|
|
13
16
|
|
|
14
17
|
from .control import Control
|
|
@@ -76,4 +79,48 @@ class Access:
|
|
|
76
79
|
self.window.controller.audio.stop_output()
|
|
77
80
|
|
|
78
81
|
# stop generating if active
|
|
79
|
-
self.window.controller.kernel.stop()
|
|
82
|
+
self.window.controller.kernel.stop()
|
|
83
|
+
|
|
84
|
+
# close top dialog if any
|
|
85
|
+
self.close_top_dialog_if_any()
|
|
86
|
+
|
|
87
|
+
def close_top_dialog_if_any(self) -> bool:
|
|
88
|
+
"""Close top dialog if any"""
|
|
89
|
+
app = QApplication.instance()
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
w = app.activeModalWidget()
|
|
93
|
+
if w:
|
|
94
|
+
top = w.window()
|
|
95
|
+
if top and (top.windowFlags() & (Qt.Dialog | Qt.Sheet | Qt.Tool | Qt.Popup)):
|
|
96
|
+
top.close()
|
|
97
|
+
return True
|
|
98
|
+
except Exception:
|
|
99
|
+
pass
|
|
100
|
+
|
|
101
|
+
try:
|
|
102
|
+
w = app.activeWindow()
|
|
103
|
+
if w:
|
|
104
|
+
top = w.window()
|
|
105
|
+
if isinstance(top, QMainWindow):
|
|
106
|
+
pass
|
|
107
|
+
else:
|
|
108
|
+
if top and (top.windowFlags() & (Qt.Dialog | Qt.Sheet | Qt.Tool | Qt.Popup)):
|
|
109
|
+
top.close()
|
|
110
|
+
return True
|
|
111
|
+
except Exception:
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
try:
|
|
115
|
+
for top in reversed(QApplication.topLevelWidgets()):
|
|
116
|
+
if not top.isVisible():
|
|
117
|
+
continue
|
|
118
|
+
if isinstance(top, QMainWindow):
|
|
119
|
+
continue
|
|
120
|
+
if top.windowFlags() & (Qt.Dialog | Qt.Sheet | Qt.Tool | Qt.Popup):
|
|
121
|
+
top.close()
|
|
122
|
+
return True
|
|
123
|
+
except Exception:
|
|
124
|
+
pass
|
|
125
|
+
|
|
126
|
+
return False
|
|
@@ -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:
|
|
9
|
+
# Updated Date: 2025.08.18 01:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -128,7 +128,7 @@ class Attachment(QObject):
|
|
|
128
128
|
attachments = self.window.core.attachments.get_all(mode, only_files=True)
|
|
129
129
|
|
|
130
130
|
if self.is_verbose() and len(attachments) > 0:
|
|
131
|
-
print("\nUploading attachments...\nWork Mode: {}"
|
|
131
|
+
print(f"\nUploading attachments...\nWork Mode: {mode}")
|
|
132
132
|
|
|
133
133
|
for uuid in attachments:
|
|
134
134
|
attachment = attachments[uuid]
|
|
@@ -175,7 +175,7 @@ class Attachment(QObject):
|
|
|
175
175
|
return False
|
|
176
176
|
if self.window.core.filesystem.packer.is_archive(attachment.path):
|
|
177
177
|
if self.is_verbose():
|
|
178
|
-
print("Unpacking archive: {
|
|
178
|
+
print(f"Unpacking archive: {attachment.path}")
|
|
179
179
|
tmp_path = self.window.core.filesystem.packer.unpack(attachment.path)
|
|
180
180
|
if tmp_path:
|
|
181
181
|
for root, dirs, files in os.walk(tmp_path):
|
|
@@ -188,7 +188,7 @@ class Attachment(QObject):
|
|
|
188
188
|
path_relative = os.path.relpath(path, tmp_path)
|
|
189
189
|
if self.is_allowed(str(path)):
|
|
190
190
|
if self.is_verbose():
|
|
191
|
-
print("Uploading unpacked from archive: {}"
|
|
191
|
+
print(f"Uploading unpacked from archive: {path_relative}")
|
|
192
192
|
item = self.window.core.attachments.context.upload(
|
|
193
193
|
meta=meta,
|
|
194
194
|
attachment=sub_attachment,
|
|
@@ -197,7 +197,7 @@ class Attachment(QObject):
|
|
|
197
197
|
auto_index=auto_index,
|
|
198
198
|
)
|
|
199
199
|
if item:
|
|
200
|
-
item["path"] = os.path.basename(attachment.path)
|
|
200
|
+
item["path"] = f"{os.path.basename(attachment.path)}/{str(path_relative)}"
|
|
201
201
|
item["size"] = os.path.getsize(path)
|
|
202
202
|
self.append_to_meta(meta, item)
|
|
203
203
|
uploaded = True
|
|
@@ -296,7 +296,7 @@ class Attachment(QObject):
|
|
|
296
296
|
"""
|
|
297
297
|
if self.mode != self.MODE_DISABLED:
|
|
298
298
|
if self.is_verbose():
|
|
299
|
-
print("\nPreparing additional context...\nContext Mode: {
|
|
299
|
+
print(f"\nPreparing additional context...\nContext Mode: {self.mode}")
|
|
300
300
|
|
|
301
301
|
self.window.core.attachments.context.reset() # reset used files and urls
|
|
302
302
|
|
|
@@ -313,8 +313,8 @@ class Attachment(QObject):
|
|
|
313
313
|
|
|
314
314
|
if content:
|
|
315
315
|
if self.is_verbose():
|
|
316
|
-
print("\n--- Using additional context ---\n\n{}"
|
|
317
|
-
return "====================================\nADDITIONAL CONTEXT FROM ATTACHMENT(s): {}"
|
|
316
|
+
print(f"\n--- Using additional context ---\n\n{content}")
|
|
317
|
+
return f"====================================\nADDITIONAL CONTEXT FROM ATTACHMENT(s): {content}"
|
|
318
318
|
return ""
|
|
319
319
|
|
|
320
320
|
def update(self):
|
|
@@ -355,7 +355,7 @@ class Attachment(QObject):
|
|
|
355
355
|
suffix = f' ({num_files})'
|
|
356
356
|
self.window.ui.tabs['input'].setTabText(
|
|
357
357
|
3,
|
|
358
|
-
trans('attachments_uploaded.tab')
|
|
358
|
+
f"{trans('attachments_uploaded.tab')}{suffix}",
|
|
359
359
|
)
|
|
360
360
|
"""
|
|
361
361
|
if num_files > 0:
|
|
@@ -462,7 +462,7 @@ class Attachment(QObject):
|
|
|
462
462
|
if "real_path" in item:
|
|
463
463
|
path = item["real_path"]
|
|
464
464
|
if os.path.exists(path) and os.path.isfile(path):
|
|
465
|
-
print("Opening attachment: {}"
|
|
465
|
+
print(f"Opening attachment: {path}")
|
|
466
466
|
self.window.controller.files.open(path)
|
|
467
467
|
|
|
468
468
|
def open_dir_src_by_idx(self, idx: int):
|
|
@@ -482,7 +482,7 @@ class Attachment(QObject):
|
|
|
482
482
|
path = item["real_path"]
|
|
483
483
|
dir = os.path.dirname(path)
|
|
484
484
|
if os.path.exists(dir) and os.path.isdir(dir):
|
|
485
|
-
print("Opening source directory: {}"
|
|
485
|
+
print(f"Opening source directory: {dir}")
|
|
486
486
|
self.window.controller.files.open(dir)
|
|
487
487
|
|
|
488
488
|
def open_dir_dest_by_idx(self, idx: int):
|
|
@@ -501,7 +501,7 @@ class Attachment(QObject):
|
|
|
501
501
|
dir = os.path.join(root_dir, item["uuid"])
|
|
502
502
|
if os.path.exists(dir) and os.path.isdir(dir):
|
|
503
503
|
self.window.controller.files.open(dir)
|
|
504
|
-
print("Opening destination directory: {}"
|
|
504
|
+
print(f"Opening destination directory: {dir}")
|
|
505
505
|
|
|
506
506
|
def has_file_by_idx(self, idx: int) -> bool:
|
|
507
507
|
"""
|
|
@@ -591,7 +591,7 @@ class Attachment(QObject):
|
|
|
591
591
|
"""
|
|
592
592
|
self.window.dispatch(KernelEvent(KernelEvent.STATE_ERROR, {
|
|
593
593
|
"id": "chat",
|
|
594
|
-
"msg": "Error reading attachments: {
|
|
594
|
+
"msg": f"Error reading attachments: {str(error)}"
|
|
595
595
|
}))
|
|
596
596
|
|
|
597
597
|
@Slot(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.
|
|
9
|
+
# Updated Date: 2025.08.18 01:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import copy
|
|
@@ -52,12 +52,12 @@ class Command:
|
|
|
52
52
|
# check if commands are enabled, leave only enabled commands
|
|
53
53
|
for cmd in list(cmds):
|
|
54
54
|
if "cmd" not in cmd:
|
|
55
|
-
self.log("[cmd] Command without 'cmd' key: "
|
|
55
|
+
self.log(f"[cmd] Command without 'cmd' key: {cmd}")
|
|
56
56
|
cmds.remove(cmd)
|
|
57
57
|
continue
|
|
58
58
|
cmd_id = str(cmd["cmd"])
|
|
59
59
|
if not self.window.core.command.is_enabled(cmd_id) and not ctx.force_call:
|
|
60
|
-
self.log("[cmd] Command not allowed: "
|
|
60
|
+
self.log(f"[cmd] Command not allowed: {cmd_id}")
|
|
61
61
|
cmds.remove(cmd) # remove command from execution list
|
|
62
62
|
|
|
63
63
|
# agent mode
|
|
@@ -134,4 +134,4 @@ class Command:
|
|
|
134
134
|
|
|
135
135
|
:param data: Data to log
|
|
136
136
|
"""
|
|
137
|
-
self.window.core.debug.info(data)
|
|
137
|
+
self.window.core.debug.info(data)
|
|
@@ -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.18 01:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -15,6 +15,7 @@ from PySide6.QtGui import QTextCursor
|
|
|
15
15
|
from PySide6.QtWidgets import QFileDialog, QApplication
|
|
16
16
|
|
|
17
17
|
from pygpt_net.core.events import Event, AppEvent, RenderEvent
|
|
18
|
+
from pygpt_net.core.types import MODE_ASSISTANT
|
|
18
19
|
from pygpt_net.item.ctx import CtxItem
|
|
19
20
|
from pygpt_net.item.model import ModelItem
|
|
20
21
|
from pygpt_net.utils import trans
|
|
@@ -138,7 +139,7 @@ class Common:
|
|
|
138
139
|
cur.movePosition(QTextCursor.End)
|
|
139
140
|
text = str(text).strip()
|
|
140
141
|
if prev_text.strip() != "":
|
|
141
|
-
text = separator
|
|
142
|
+
text = f"{separator}{text}"
|
|
142
143
|
s = text
|
|
143
144
|
while s:
|
|
144
145
|
head, sep, s = s.partition("\n") # Split line at LF
|
|
@@ -283,7 +284,7 @@ class Common:
|
|
|
283
284
|
self.window.stateChanged.emit(self.window.STATE_IDLE)
|
|
284
285
|
|
|
285
286
|
# remotely stop assistant
|
|
286
|
-
if mode ==
|
|
287
|
+
if mode == MODE_ASSISTANT and not exit:
|
|
287
288
|
try:
|
|
288
289
|
self.window.controller.assistant.run_stop()
|
|
289
290
|
except Exception as e:
|
|
@@ -329,14 +330,14 @@ class Common:
|
|
|
329
330
|
if monit:
|
|
330
331
|
self.window.ui.nodes['start.api_key.provider'].setText(name)
|
|
331
332
|
self.window.controller.launcher.show_api_monit()
|
|
332
|
-
self.window.update_status("Missing API KEY for provider: {}"
|
|
333
|
+
self.window.update_status(f"Missing API KEY for provider: {name}")
|
|
333
334
|
return False
|
|
334
335
|
else:
|
|
335
336
|
if api_key is None or api_key == '':
|
|
336
337
|
if monit:
|
|
337
338
|
self.window.ui.nodes['start.api_key.provider'].setText(name)
|
|
338
339
|
self.window.controller.launcher.show_api_monit()
|
|
339
|
-
self.window.update_status("Missing API KEY for provider: {}"
|
|
340
|
+
self.window.update_status(f"Missing API KEY for provider: {name}")
|
|
340
341
|
return False
|
|
341
342
|
return True
|
|
342
343
|
|
|
@@ -450,7 +451,7 @@ class Common:
|
|
|
450
451
|
)
|
|
451
452
|
with open(file_name, 'w', encoding="utf-8") as f:
|
|
452
453
|
f.write(str(text).strip())
|
|
453
|
-
self.window.update_status(trans('status.saved')
|
|
454
|
+
self.window.update_status(f"{trans('status.saved')}: {os.path.basename(file_name)}")
|
|
454
455
|
|
|
455
456
|
def show_response_tokens(self, ctx: CtxItem):
|
|
456
457
|
"""
|
|
@@ -462,11 +463,5 @@ class Common:
|
|
|
462
463
|
if ctx.is_vision:
|
|
463
464
|
extra_data = " (VISION)"
|
|
464
465
|
self.window.update_status(
|
|
465
|
-
trans('status.tokens')
|
|
466
|
-
|
|
467
|
-
ctx.input_tokens,
|
|
468
|
-
ctx.output_tokens,
|
|
469
|
-
ctx.total_tokens,
|
|
470
|
-
extra_data,
|
|
471
|
-
))
|
|
472
|
-
|
|
466
|
+
f"{trans('status.tokens')}: {ctx.input_tokens} + {ctx.output_tokens} = {ctx.total_tokens}{extra_data}"
|
|
467
|
+
)
|
|
@@ -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:
|
|
9
|
+
# Updated Date: 2025.08.18 01:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import Dict
|
|
@@ -41,7 +41,7 @@ class Files:
|
|
|
41
41
|
if len(attachments) > 0:
|
|
42
42
|
ctx.attachments = attachments
|
|
43
43
|
self.window.update_status(trans('status.sending'))
|
|
44
|
-
self.window.controller.chat.log("Uploaded attachments (Assistant): {
|
|
44
|
+
self.window.controller.chat.log(f"Uploaded attachments (Assistant): {len(attachments)}")
|
|
45
45
|
return attachments
|
|
46
46
|
|
|
47
47
|
def upload(self, mode: str) -> Dict[str, AttachmentItem]:
|
|
@@ -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.18 01:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -148,7 +148,7 @@ class Input:
|
|
|
148
148
|
except Exception as e:
|
|
149
149
|
self.window.dispatch(KernelEvent(KernelEvent.STATE_ERROR, {
|
|
150
150
|
"id": "chat",
|
|
151
|
-
"msg": "Error reading attachments: {
|
|
151
|
+
"msg": f"Error reading attachments: {str(e)}"
|
|
152
152
|
}))
|
|
153
153
|
return
|
|
154
154
|
|
|
@@ -237,11 +237,11 @@ class Input:
|
|
|
237
237
|
self.window.controller.assistant.threads.stop = False
|
|
238
238
|
self.window.controller.kernel.resume()
|
|
239
239
|
|
|
240
|
-
self.log("Input prompt: {}"
|
|
240
|
+
self.log(f"Input prompt: {text}") # log
|
|
241
241
|
|
|
242
242
|
# agent mode
|
|
243
243
|
if mode == MODE_AGENT:
|
|
244
|
-
self.log("Agent: input before: {}"
|
|
244
|
+
self.log(f"Agent: input before: {text}")
|
|
245
245
|
text = self.window.controller.agent.legacy.on_input_before(text)
|
|
246
246
|
|
|
247
247
|
# event: before input
|
|
@@ -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.18 01:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import Any, Optional
|
|
@@ -257,14 +257,14 @@ class Output:
|
|
|
257
257
|
self.log("Attachments cleared.") # log
|
|
258
258
|
|
|
259
259
|
if self.window.core.config.get("log.ctx"):
|
|
260
|
-
self.log("Context: END: {}"
|
|
260
|
+
self.log(f"Context: END: {ctx}")
|
|
261
261
|
else:
|
|
262
262
|
self.log("Context: END.")
|
|
263
263
|
|
|
264
264
|
# agent mode
|
|
265
265
|
if mode == MODE_AGENT:
|
|
266
266
|
agent_iterations = int(self.window.core.config.get("agent.iterations"))
|
|
267
|
-
self.log("Agent: ctx end, iterations: {}"
|
|
267
|
+
self.log(f"Agent: ctx end, iterations: {agent_iterations}")
|
|
268
268
|
self.window.controller.agent.legacy.on_ctx_end(
|
|
269
269
|
ctx,
|
|
270
270
|
iterations=agent_iterations,
|
|
@@ -304,4 +304,4 @@ class Output:
|
|
|
304
304
|
|
|
305
305
|
:param data: Data to log
|
|
306
306
|
"""
|
|
307
|
-
self.window.controller.chat.log(data)
|
|
307
|
+
self.window.controller.chat.log(data)
|
|
@@ -166,6 +166,11 @@ class Render:
|
|
|
166
166
|
meta = data.get("meta") or self.window.core.ctx.get_current_meta()
|
|
167
167
|
self.on_state_changed(name, meta)
|
|
168
168
|
|
|
169
|
+
elif name == RenderEvent.ITEM_DELETE_ID:
|
|
170
|
+
self.remove_item(data.get("ctx"))
|
|
171
|
+
elif name == RenderEvent.ITEM_DELETE_FROM_ID:
|
|
172
|
+
self.remove_items_from(data.get("ctx"))
|
|
173
|
+
|
|
169
174
|
def on_state_changed(self, state: str, meta: Optional[CtxMeta] = None) -> None:
|
|
170
175
|
"""
|
|
171
176
|
Handle state change event
|
|
@@ -404,22 +409,22 @@ class Render:
|
|
|
404
409
|
self.instance().on_disable_timestamp(live)
|
|
405
410
|
self.update()
|
|
406
411
|
|
|
407
|
-
def remove_item(self,
|
|
412
|
+
def remove_item(self, ctx: CtxItem) -> None:
|
|
408
413
|
"""
|
|
409
414
|
Remove item from output
|
|
410
415
|
|
|
411
|
-
:param
|
|
416
|
+
:param ctx: context item
|
|
412
417
|
"""
|
|
413
|
-
self.instance().remove_item(
|
|
418
|
+
self.instance().remove_item(ctx)
|
|
414
419
|
self.update()
|
|
415
420
|
|
|
416
|
-
def remove_items_from(self,
|
|
421
|
+
def remove_items_from(self, ctx: CtxItem) -> None:
|
|
417
422
|
"""
|
|
418
423
|
Remove item from output
|
|
419
424
|
|
|
420
|
-
:param
|
|
425
|
+
:param ctx: context item
|
|
421
426
|
"""
|
|
422
|
-
self.instance().remove_items_from(
|
|
427
|
+
self.instance().remove_items_from(ctx)
|
|
423
428
|
self.update()
|
|
424
429
|
|
|
425
430
|
def on_edit_submit(self, ctx: CtxItem) -> None:
|
|
@@ -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.18 01:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import Dict, Any
|
|
@@ -251,9 +251,9 @@ class Response:
|
|
|
251
251
|
try:
|
|
252
252
|
self.window.controller.chat.output.handle(ctx, mode, stream)
|
|
253
253
|
except Exception as e:
|
|
254
|
-
self.window.controller.chat.log("Output ERROR: {}"
|
|
254
|
+
self.window.controller.chat.log(f"Output ERROR: {e}") # log
|
|
255
255
|
self.window.controller.chat.handle_error(e)
|
|
256
|
-
print("Error in append text: "
|
|
256
|
+
print(f"Error in append text: {e}")
|
|
257
257
|
|
|
258
258
|
# post-handle, execute cmd, etc.
|
|
259
259
|
self.window.controller.chat.output.post_handle(ctx, mode, stream, reply, internal)
|
|
@@ -314,10 +314,10 @@ class Response:
|
|
|
314
314
|
:param extra: Extra data
|
|
315
315
|
"""
|
|
316
316
|
err = extra.get("error") if "error" in extra else None
|
|
317
|
-
self.window.controller.chat.log("Output ERROR: {}"
|
|
317
|
+
self.window.controller.chat.log(f"Output ERROR: {err}") # log
|
|
318
318
|
self.window.controller.chat.handle_error(err)
|
|
319
319
|
self.window.controller.chat.common.unlock_input() # unlock input
|
|
320
|
-
print("Error in sending text: "
|
|
320
|
+
print(f"Error in sending text: {err}")
|
|
321
321
|
# set state to: error
|
|
322
322
|
self.window.dispatch(KernelEvent(KernelEvent.STATE_ERROR, {
|
|
323
323
|
"id": "chat",
|
|
@@ -6,11 +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.18 01:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import base64
|
|
13
|
-
import gc
|
|
14
13
|
import io
|
|
15
14
|
from typing import Optional, Literal
|
|
16
15
|
|
|
@@ -327,7 +326,7 @@ class StreamWorker(QRunnable):
|
|
|
327
326
|
|
|
328
327
|
else:
|
|
329
328
|
if chunk is not None:
|
|
330
|
-
response = str(chunk)
|
|
329
|
+
response = chunk if isinstance(chunk, str) else str(chunk)
|
|
331
330
|
|
|
332
331
|
if response is not None and response != "" and not stopped:
|
|
333
332
|
if begin and response == "":
|
|
@@ -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.18 01:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import Optional
|
|
@@ -73,6 +73,7 @@ class Text:
|
|
|
73
73
|
ai_name = event.data['value']
|
|
74
74
|
|
|
75
75
|
# prepare mode, model, etc.
|
|
76
|
+
agent_provider = None # agent provider (llama or openai)
|
|
76
77
|
mode = self.window.core.config.get('mode')
|
|
77
78
|
model = self.window.core.config.get('model')
|
|
78
79
|
model_data = self.window.core.models.get(model)
|
|
@@ -93,11 +94,11 @@ class Text:
|
|
|
93
94
|
agent_provider = self.window.core.config.get('agent.openai.provider')
|
|
94
95
|
|
|
95
96
|
# o1 models: disable stream mode
|
|
96
|
-
if mode in
|
|
97
|
+
if mode in (MODE_AGENT_LLAMA, MODE_AUDIO):
|
|
97
98
|
stream_mode = False
|
|
98
|
-
if mode
|
|
99
|
+
if mode == MODE_LLAMA_INDEX and idx_mode == "retrieval":
|
|
99
100
|
stream_mode = False
|
|
100
|
-
if mode
|
|
101
|
+
if mode == MODE_LLAMA_INDEX:
|
|
101
102
|
if not self.window.core.idx.chat.is_stream_allowed():
|
|
102
103
|
stream_mode = False
|
|
103
104
|
|
|
@@ -156,7 +157,11 @@ class Text:
|
|
|
156
157
|
self.window.dispatch(event)
|
|
157
158
|
|
|
158
159
|
# agent or expert mode
|
|
159
|
-
sys_prompt = self.window.controller.agent.experts.append_prompts(
|
|
160
|
+
sys_prompt = self.window.controller.agent.experts.append_prompts(
|
|
161
|
+
mode,
|
|
162
|
+
sys_prompt,
|
|
163
|
+
parent_id
|
|
164
|
+
)
|
|
160
165
|
|
|
161
166
|
# on pre prompt event
|
|
162
167
|
event = Event(Event.PRE_PROMPT, {
|
|
@@ -221,7 +226,7 @@ class Text:
|
|
|
221
226
|
files = self.window.core.attachments.get_all(mode)
|
|
222
227
|
num_files = len(files)
|
|
223
228
|
if num_files > 0:
|
|
224
|
-
self.window.controller.chat.log("Attachments ({}): {}"
|
|
229
|
+
self.window.controller.chat.log(f"Attachments ({mode}): {num_files}")
|
|
225
230
|
|
|
226
231
|
# assistant
|
|
227
232
|
assistant_id = self.window.core.config.get('assistant')
|
|
@@ -257,7 +262,7 @@ class Text:
|
|
|
257
262
|
'reply': reply,
|
|
258
263
|
'internal': internal,
|
|
259
264
|
}
|
|
260
|
-
if mode in
|
|
265
|
+
if mode in (MODE_AGENT_LLAMA, MODE_AGENT_OPENAI):
|
|
261
266
|
extra['agent_idx'] = agent_idx
|
|
262
267
|
extra['agent_provider'] = agent_provider
|
|
263
268
|
|
|
@@ -269,8 +274,8 @@ class Text:
|
|
|
269
274
|
self.window.dispatch(event)
|
|
270
275
|
|
|
271
276
|
except Exception as e:
|
|
272
|
-
self.window.controller.chat.log("Bridge call ERROR: {}"
|
|
277
|
+
self.window.controller.chat.log(f"Bridge call ERROR: {e}") # log
|
|
273
278
|
self.window.controller.chat.handle_error(e)
|
|
274
|
-
print("Error when calling bridge: "
|
|
279
|
+
print(f"Error when calling bridge: {e}")
|
|
275
280
|
|
|
276
|
-
return ctx
|
|
281
|
+
return ctx
|