pygpt-net 2.6.15__py3-none-any.whl → 2.6.17__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/controller/__init__.py +8 -2
- pygpt_net/controller/chat/command.py +18 -6
- pygpt_net/controller/ctx/ctx.py +2 -2
- pygpt_net/controller/mode/mode.py +3 -2
- pygpt_net/controller/plugins/plugins.py +31 -15
- pygpt_net/controller/presets/editor.py +11 -32
- pygpt_net/controller/settings/profile.py +16 -3
- pygpt_net/controller/settings/workdir.py +184 -124
- pygpt_net/controller/theme/theme.py +11 -5
- pygpt_net/core/agents/observer/evaluation.py +3 -14
- pygpt_net/core/agents/runners/llama_workflow.py +7 -6
- pygpt_net/core/command/command.py +5 -3
- pygpt_net/core/experts/experts.py +58 -13
- pygpt_net/core/plugins/plugins.py +12 -1
- pygpt_net/core/render/plain/body.py +10 -19
- pygpt_net/core/render/plain/renderer.py +27 -27
- pygpt_net/data/config/config.json +6 -6
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/locale/locale.en.ini +2 -2
- pygpt_net/data/locale/plugin.openai_dalle.de.ini +1 -1
- pygpt_net/data/locale/plugin.openai_dalle.en.ini +1 -1
- pygpt_net/data/locale/plugin.openai_dalle.es.ini +1 -1
- pygpt_net/data/locale/plugin.openai_dalle.fr.ini +1 -1
- pygpt_net/data/locale/plugin.openai_dalle.it.ini +1 -1
- pygpt_net/data/locale/plugin.openai_dalle.pl.ini +1 -1
- pygpt_net/data/locale/plugin.openai_dalle.uk.ini +1 -1
- pygpt_net/data/locale/plugin.openai_dalle.zh.ini +1 -1
- pygpt_net/data/locale/plugin.openai_vision.de.ini +1 -1
- pygpt_net/data/locale/plugin.openai_vision.en.ini +1 -1
- pygpt_net/data/locale/plugin.openai_vision.es.ini +1 -1
- pygpt_net/data/locale/plugin.openai_vision.fr.ini +1 -1
- pygpt_net/data/locale/plugin.openai_vision.it.ini +1 -1
- pygpt_net/data/locale/plugin.openai_vision.pl.ini +1 -1
- pygpt_net/data/locale/plugin.openai_vision.uk.ini +1 -1
- pygpt_net/data/locale/plugin.openai_vision.zh.ini +1 -1
- pygpt_net/item/ctx.py +5 -4
- pygpt_net/plugin/idx_llama_index/plugin.py +9 -5
- pygpt_net/plugin/idx_llama_index/worker.py +5 -2
- pygpt_net/plugin/openai_dalle/plugin.py +1 -1
- pygpt_net/tools/translator/ui/dialogs.py +1 -0
- pygpt_net/tools/translator/ui/widgets.py +1 -2
- pygpt_net/ui/__init__.py +12 -10
- pygpt_net/ui/base/config_dialog.py +15 -10
- pygpt_net/ui/dialog/about.py +26 -18
- pygpt_net/ui/dialog/plugins.py +6 -4
- pygpt_net/ui/dialog/settings.py +75 -87
- pygpt_net/ui/dialog/workdir.py +7 -2
- pygpt_net/ui/main.py +5 -1
- pygpt_net/ui/widget/textarea/editor.py +1 -2
- pygpt_net/ui/widget/textarea/web.py +22 -16
- {pygpt_net-2.6.15.dist-info → pygpt_net-2.6.17.dist-info}/METADATA +26 -14
- {pygpt_net-2.6.15.dist-info → pygpt_net-2.6.17.dist-info}/RECORD +57 -57
- {pygpt_net-2.6.15.dist-info → pygpt_net-2.6.17.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.15.dist-info → pygpt_net-2.6.17.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.15.dist-info → pygpt_net-2.6.17.dist-info}/entry_points.txt +0 -0
|
@@ -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.20 23:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import copy
|
|
@@ -16,6 +16,7 @@ from typing import Optional
|
|
|
16
16
|
from uuid import uuid4
|
|
17
17
|
|
|
18
18
|
from PySide6.QtCore import QObject, QRunnable, Signal, Slot
|
|
19
|
+
from PySide6.QtWidgets import QApplication
|
|
19
20
|
|
|
20
21
|
from pygpt_net.utils import trans
|
|
21
22
|
|
|
@@ -32,7 +33,7 @@ class WorkerSignals(QObject):
|
|
|
32
33
|
updateStatus = Signal(str) # update status in dialog
|
|
33
34
|
updateGlobalStatus = Signal(str) # update global status
|
|
34
35
|
alert = Signal(object) # dialog alert
|
|
35
|
-
|
|
36
|
+
after_migrate = Signal(bool, str, str, str) # result, profile_name, current_path, new_path
|
|
36
37
|
confirm = Signal(str, str, str) # confirm dialog (action, path, message)
|
|
37
38
|
restored = Signal(str) # after restoring workdir
|
|
38
39
|
updated = Signal(str) # after updating workdir
|
|
@@ -68,12 +69,8 @@ class WorkdirWorker(QRunnable):
|
|
|
68
69
|
@Slot()
|
|
69
70
|
def run(self):
|
|
70
71
|
try:
|
|
71
|
-
if self.action == "
|
|
72
|
-
self.worker_update()
|
|
73
|
-
elif self.action == "migrate":
|
|
72
|
+
if self.action == "migrate":
|
|
74
73
|
self.worker_migrate()
|
|
75
|
-
elif self.action == "restore":
|
|
76
|
-
self.worker_restore()
|
|
77
74
|
elif self.action == "delete":
|
|
78
75
|
self.worker_delete_files()
|
|
79
76
|
elif self.action == "duplicate":
|
|
@@ -116,7 +113,7 @@ class WorkdirWorker(QRunnable):
|
|
|
116
113
|
if not os.path.exists(path) or not os.path.isdir(path):
|
|
117
114
|
self.signals.alert.emit(trans("dialog.profile.alert.path.not_exists"))
|
|
118
115
|
return
|
|
119
|
-
print("Clearing workdir: "
|
|
116
|
+
print(f"Clearing workdir: {path}")
|
|
120
117
|
self.window.core.filesystem.clear_workdir(
|
|
121
118
|
path,
|
|
122
119
|
remove_db=remove_db,
|
|
@@ -149,7 +146,7 @@ class WorkdirWorker(QRunnable):
|
|
|
149
146
|
# copy files from workdir
|
|
150
147
|
path_from = profile['workdir'].replace("%HOME%", str(Path.home()))
|
|
151
148
|
path_to = new_path
|
|
152
|
-
print("Copying all files from {} to: {}"
|
|
149
|
+
print(f"Copying all files from {path_from} to: {path_to}")
|
|
153
150
|
self.signals.updateGlobalStatus.emit("Copying files...")
|
|
154
151
|
result = self.window.core.filesystem.copy_workdir(
|
|
155
152
|
path_from,
|
|
@@ -175,7 +172,7 @@ class WorkdirWorker(QRunnable):
|
|
|
175
172
|
profile = profiles[uuid]
|
|
176
173
|
path = profile['workdir'].replace("%HOME%", str(Path.home()))
|
|
177
174
|
if not os.path.exists(path) or not os.path.isdir(path):
|
|
178
|
-
self.signals.alert.emit("Directory not exists
|
|
175
|
+
self.signals.alert.emit(f"Directory not exists: {path}")
|
|
179
176
|
return
|
|
180
177
|
print("Clearing workdir: ", path)
|
|
181
178
|
self.window.core.db.close()
|
|
@@ -186,53 +183,7 @@ class WorkdirWorker(QRunnable):
|
|
|
186
183
|
)
|
|
187
184
|
if uuid == current:
|
|
188
185
|
self.signals.switch.emit(uuid) # switch to profile
|
|
189
|
-
self.signals.updateGlobalStatus.emit("Profile cleared:
|
|
190
|
-
|
|
191
|
-
def worker_update(self):
|
|
192
|
-
"""Switch working directory to the existing one"""
|
|
193
|
-
print("\n====================")
|
|
194
|
-
print("Changing workdir to: ", self.path)
|
|
195
|
-
print("====================\n")
|
|
196
|
-
current_path = self.window.core.config.get_user_path()
|
|
197
|
-
default_path = self.window.core.config.get_base_workdir()
|
|
198
|
-
|
|
199
|
-
if self.force:
|
|
200
|
-
self.signals.updateStatus.emit(trans("dialog.workdir.result.wait"))
|
|
201
|
-
|
|
202
|
-
lock_file = os.path.join(default_path, 'path.cfg') # put "path.cfg"
|
|
203
|
-
lock_path = self.path.replace(str(Path.home()), "%HOME%")
|
|
204
|
-
if self.path == default_path:
|
|
205
|
-
lock_path = "" # set empty if default dir
|
|
206
|
-
with open(lock_file, 'w', encoding='utf-8') as f:
|
|
207
|
-
f.write(lock_path)
|
|
208
|
-
|
|
209
|
-
# update path in current profile
|
|
210
|
-
self.window.core.config.profile.update_current_workdir(self.path)
|
|
211
|
-
|
|
212
|
-
# reload config
|
|
213
|
-
self.window.core.config.set_workdir(self.path, reload=True)
|
|
214
|
-
self.window.core.config.set('license.accepted', True) # accept license to prevent show dialog again
|
|
215
|
-
|
|
216
|
-
# reload components
|
|
217
|
-
if self.force:
|
|
218
|
-
try:
|
|
219
|
-
self.signals.reload.emit()
|
|
220
|
-
success_msg = trans("dialog.workdir.result.success").format(path=self.path)
|
|
221
|
-
self.signals.updateStatus.emit(success_msg)
|
|
222
|
-
self.signals.alert.emit(success_msg)
|
|
223
|
-
except Exception as e:
|
|
224
|
-
self.window.core.debug.log(e)
|
|
225
|
-
self.signals.alert.emit(str(e))
|
|
226
|
-
print("Error reloading components: ", e)
|
|
227
|
-
self.worker_restore(custom_current=current_path)
|
|
228
|
-
self.window.controller.reloading = False # unlock
|
|
229
|
-
else:
|
|
230
|
-
# always reload
|
|
231
|
-
self.signals.reload.emit()
|
|
232
|
-
|
|
233
|
-
# update profile after workdir change
|
|
234
|
-
if self.profile_name:
|
|
235
|
-
self.signals.updated.emit(self.profile_name)
|
|
186
|
+
self.signals.updateGlobalStatus.emit(f"Profile cleared: {profile['name']}")
|
|
236
187
|
|
|
237
188
|
def worker_migrate(self):
|
|
238
189
|
"""Migrate working directory"""
|
|
@@ -267,7 +218,7 @@ class WorkdirWorker(QRunnable):
|
|
|
267
218
|
|
|
268
219
|
self.signals.hideStatus.emit()
|
|
269
220
|
self.window.controller.settings.workdir.busy = True
|
|
270
|
-
print("Migrating workdir from:
|
|
221
|
+
print(f"Migrating workdir from: {current} to: {self.path}...")
|
|
271
222
|
|
|
272
223
|
# check if path exists
|
|
273
224
|
if not os.path.exists(self.path) or not os.path.isdir(self.path):
|
|
@@ -289,6 +240,8 @@ class WorkdirWorker(QRunnable):
|
|
|
289
240
|
return
|
|
290
241
|
|
|
291
242
|
# copy workdir
|
|
243
|
+
self.signals.updateGlobalStatus.emit(trans("dialog.workdir.result.wait"))
|
|
244
|
+
QApplication.processEvents() # process events to update UI
|
|
292
245
|
try:
|
|
293
246
|
result = self.window.core.filesystem.copy_workdir(current, self.path)
|
|
294
247
|
except Exception as e:
|
|
@@ -297,46 +250,28 @@ class WorkdirWorker(QRunnable):
|
|
|
297
250
|
print("Error migrating workdir: ", e)
|
|
298
251
|
result = False
|
|
299
252
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
# remove old workdir
|
|
303
|
-
self.window.core.debug.info("Clearing old workdir: {}".format(current))
|
|
304
|
-
try:
|
|
305
|
-
# allow errors here
|
|
306
|
-
self.window.core.filesystem.clear_workdir(current)
|
|
307
|
-
except Exception as e:
|
|
308
|
-
self.window.core.debug.log(e)
|
|
309
|
-
print("Error clearing old workdir: ", e)
|
|
253
|
+
# reload UI, config, etc.
|
|
254
|
+
self.signals.after_migrate.emit(result, self.profile_name, current, self.path)
|
|
310
255
|
|
|
311
|
-
# update workdir to new path
|
|
312
|
-
self.worker_update()
|
|
313
|
-
success_msg = trans("dialog.workdir.result.success").format(path=self.path)
|
|
314
|
-
print(success_msg)
|
|
315
|
-
self.signals.updateStatus.emit(success_msg)
|
|
316
|
-
self.signals.alert.emit(success_msg)
|
|
317
|
-
except Exception as e:
|
|
318
|
-
self.window.core.debug.log(e)
|
|
319
|
-
self.signals.alert.emit(str(e))
|
|
320
|
-
print("Error migrating workdir: ", e)
|
|
321
|
-
self.worker_restore(custom_current=current)
|
|
322
|
-
self.window.controller.reloading = False
|
|
323
|
-
else:
|
|
324
|
-
self.signals.updateStatus.emit(trans("dialog.workdir.result.failed"))
|
|
325
|
-
self.signals.alert.emit(trans("dialog.workdir.result.failed"))
|
|
326
|
-
self.worker_restore(custom_current=current)
|
|
327
|
-
self.window.controller.reloading = False
|
|
328
256
|
|
|
329
|
-
|
|
330
|
-
|
|
257
|
+
class Workdir:
|
|
258
|
+
def __init__(self, window=None):
|
|
259
|
+
"""
|
|
260
|
+
Workdir controller
|
|
331
261
|
|
|
332
|
-
|
|
262
|
+
:param window: window instance
|
|
333
263
|
"""
|
|
334
|
-
|
|
264
|
+
self.window = window
|
|
265
|
+
self.is_dialog = False
|
|
266
|
+
self.busy = False
|
|
267
|
+
|
|
268
|
+
def rollback(self, current: str = None):
|
|
269
|
+
"""
|
|
270
|
+
Rollback to the previous working directory
|
|
335
271
|
|
|
336
|
-
:param
|
|
272
|
+
:param current: current working directory (optional)
|
|
337
273
|
"""
|
|
338
|
-
|
|
339
|
-
print("Reverting workdir to: ", current)
|
|
274
|
+
print(f"Reverting workdir to: {current}...")
|
|
340
275
|
self.window.core.config.set_workdir(current, reload=True)
|
|
341
276
|
default_path = self.window.core.config.get_base_workdir()
|
|
342
277
|
lock_file = os.path.join(default_path, 'path.cfg')
|
|
@@ -345,23 +280,151 @@ class WorkdirWorker(QRunnable):
|
|
|
345
280
|
lock_path = ""
|
|
346
281
|
with open(lock_file, 'w', encoding='utf-8') as f:
|
|
347
282
|
f.write(lock_path)
|
|
348
|
-
self.
|
|
349
|
-
self.
|
|
350
|
-
self.
|
|
283
|
+
self.window.ui.dialogs.workdir.set_path(current)
|
|
284
|
+
self.window.ui.dialogs.workdir.show_status(f"Failed. Reverted to previous workdir: {current}.")
|
|
285
|
+
self.window.controller.reload()
|
|
351
286
|
self.window.core.config.profile.update_current_workdir(current)
|
|
352
287
|
|
|
288
|
+
def update_workdir(
|
|
289
|
+
self,
|
|
290
|
+
force: bool = False,
|
|
291
|
+
path: str = None
|
|
292
|
+
):
|
|
293
|
+
"""
|
|
294
|
+
Update working directory
|
|
353
295
|
|
|
354
|
-
|
|
355
|
-
|
|
296
|
+
:param force: boolean indicating if update should be forced (confirm)
|
|
297
|
+
:param path: new working directory to set
|
|
356
298
|
"""
|
|
357
|
-
|
|
299
|
+
print("\n====================")
|
|
300
|
+
print(f"Changing workdir to: {path}")
|
|
301
|
+
print("====================\n")
|
|
302
|
+
default_path = self.window.core.config.get_base_workdir()
|
|
303
|
+
if force:
|
|
304
|
+
self.window.ui.dialogs.workdir.show_status(trans("dialog.workdir.result.wait"))
|
|
358
305
|
|
|
359
|
-
|
|
306
|
+
lock_file = os.path.join(default_path, 'path.cfg') # put "path.cfg"
|
|
307
|
+
lock_path = path.replace(str(Path.home()), "%HOME%")
|
|
308
|
+
if path == default_path:
|
|
309
|
+
lock_path = "" # set empty if default dir
|
|
310
|
+
with open(lock_file, 'w', encoding='utf-8') as f:
|
|
311
|
+
f.write(lock_path)
|
|
312
|
+
|
|
313
|
+
# update path in current profile
|
|
314
|
+
self.window.core.config.profile.update_current_workdir(path)
|
|
315
|
+
|
|
316
|
+
# reload config
|
|
317
|
+
self.window.core.config.set_workdir(path, reload=True)
|
|
318
|
+
self.window.core.config.set('license.accepted', True) # accept license to prevent show dialog again
|
|
319
|
+
|
|
320
|
+
@Slot(bool, str, str, str)
|
|
321
|
+
def do_update(
|
|
322
|
+
self,
|
|
323
|
+
force: bool,
|
|
324
|
+
profile_name: str,
|
|
325
|
+
current_path: str,
|
|
326
|
+
new_path: str
|
|
327
|
+
) -> bool:
|
|
360
328
|
"""
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
329
|
+
Update working directory
|
|
330
|
+
|
|
331
|
+
:param force: boolean indicating if update should be forced (confirm)
|
|
332
|
+
:param profile_name: profile name to update after workdir change
|
|
333
|
+
:param current_path: current working directory before update
|
|
334
|
+
:param new_path: new working directory to set
|
|
335
|
+
:return: boolean indicating if update was successful
|
|
336
|
+
"""
|
|
337
|
+
self.update_workdir(
|
|
338
|
+
force=force,
|
|
339
|
+
path=new_path,
|
|
340
|
+
)
|
|
341
|
+
rollback = False
|
|
342
|
+
success = False
|
|
343
|
+
if force:
|
|
344
|
+
try:
|
|
345
|
+
self.window.ui.dialogs.workdir.show_status(trans("dialog.workdir.result.wait"))
|
|
346
|
+
self.window.controller.reload()
|
|
347
|
+
self.window.ui.dialogs.workdir.show_status(trans("dialog.workdir.result.wait"))
|
|
348
|
+
msg = trans("dialog.workdir.result.success").format(path=new_path)
|
|
349
|
+
self.window.ui.dialogs.workdir.show_status(msg)
|
|
350
|
+
self.window.ui.dialogs.alert(msg)
|
|
351
|
+
success = True
|
|
352
|
+
except Exception as e:
|
|
353
|
+
rollback = True
|
|
354
|
+
self.window.core.debug.log(e)
|
|
355
|
+
self.window.ui.dialogs.alert(str(e))
|
|
356
|
+
print("Error reloading components: ", e)
|
|
357
|
+
self.window.controller.reloading = False # unlock
|
|
358
|
+
else:
|
|
359
|
+
self.window.controller.reload() # reload only
|
|
360
|
+
|
|
361
|
+
if rollback: # if failed
|
|
362
|
+
self.rollback(current=current_path) # revert to previous workdir
|
|
363
|
+
else:
|
|
364
|
+
# update profile after workdir change
|
|
365
|
+
if profile_name:
|
|
366
|
+
self.window.controller.settings.profile.after_update(profile_name)
|
|
367
|
+
return success
|
|
368
|
+
|
|
369
|
+
@Slot(bool, str, str, str)
|
|
370
|
+
def do_migrate(
|
|
371
|
+
self,
|
|
372
|
+
result: bool,
|
|
373
|
+
profile_name: str,
|
|
374
|
+
current_path: str,
|
|
375
|
+
new_path: str
|
|
376
|
+
) -> bool:
|
|
377
|
+
"""
|
|
378
|
+
Handle migration result
|
|
379
|
+
|
|
380
|
+
:param result: boolean indicating if migration was successful
|
|
381
|
+
:param profile_name: profile name to update after migration
|
|
382
|
+
:param current_path: current working directory before migration
|
|
383
|
+
:param new_path: new working directory after migration
|
|
384
|
+
:return: boolean indicating if migration was successful
|
|
385
|
+
"""
|
|
386
|
+
success = False
|
|
387
|
+
if result:
|
|
388
|
+
try:
|
|
389
|
+
# update workdir to new path
|
|
390
|
+
success = self.do_update(
|
|
391
|
+
force=True,
|
|
392
|
+
profile_name=profile_name,
|
|
393
|
+
current_path=current_path,
|
|
394
|
+
new_path=new_path,
|
|
395
|
+
) # with rollback if failed
|
|
396
|
+
|
|
397
|
+
if not success:
|
|
398
|
+
raise Exception("Migration failed, workdir not updated.")
|
|
399
|
+
|
|
400
|
+
msg = trans("dialog.workdir.result.success").format(path=new_path)
|
|
401
|
+
self.window.ui.dialogs.workdir.show_status(msg)
|
|
402
|
+
self.window.ui.dialogs.alert(msg)
|
|
403
|
+
|
|
404
|
+
# remove old workdir only if success
|
|
405
|
+
self.window.core.debug.info(f"Clearing old workdir: {current_path}...")
|
|
406
|
+
try:
|
|
407
|
+
self.window.core.filesystem.clear_workdir(current_path) # allow errors here
|
|
408
|
+
self.window.core.debug.info(f"Old workdir cleared: {current_path}.")
|
|
409
|
+
except Exception as e:
|
|
410
|
+
self.window.core.debug.log(e)
|
|
411
|
+
print("Error clearing old workdir: ", e)
|
|
412
|
+
|
|
413
|
+
except Exception as e:
|
|
414
|
+
self.window.core.debug.log(e)
|
|
415
|
+
self.window.ui.dialogs.alert(str(e))
|
|
416
|
+
print("Error migrating workdir: ", e)
|
|
417
|
+
self.window.controller.reloading = False
|
|
418
|
+
else:
|
|
419
|
+
# if migration failed
|
|
420
|
+
self.window.ui.dialogs.workdir.show_status(trans("dialog.workdir.result.failed"))
|
|
421
|
+
self.window.ui.dialogs.alert(trans("dialog.workdir.result.failed"))
|
|
422
|
+
self.window.controller.reloading = False
|
|
423
|
+
|
|
424
|
+
self.window.controller.settings.workdir.busy = False
|
|
425
|
+
if success:
|
|
426
|
+
self.window.core.debug.info(f"Finished migrating workdir from: {current_path} to: {new_path}.")
|
|
427
|
+
return success
|
|
365
428
|
|
|
366
429
|
def change(self):
|
|
367
430
|
"""Change working directory (open dialog)"""
|
|
@@ -402,7 +465,7 @@ class Workdir:
|
|
|
402
465
|
:param profile_new_name: new profile name (optional, for duplicate action)
|
|
403
466
|
:param profile_new_path: new profile path (optional, for duplicate action)
|
|
404
467
|
"""
|
|
405
|
-
|
|
468
|
+
worker = WorkdirWorker(
|
|
406
469
|
window=self.window,
|
|
407
470
|
action=action,
|
|
408
471
|
path=path,
|
|
@@ -415,21 +478,21 @@ class Workdir:
|
|
|
415
478
|
)
|
|
416
479
|
|
|
417
480
|
# connect signals
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
481
|
+
worker.signals.updateGlobalStatus.connect(self.window.update_status)
|
|
482
|
+
worker.signals.updateStatus.connect(self.window.ui.dialogs.workdir.show_status)
|
|
483
|
+
worker.signals.hideStatus.connect(self.window.ui.dialogs.workdir.hide_status)
|
|
484
|
+
worker.signals.alert.connect(self.window.ui.dialogs.alert)
|
|
485
|
+
worker.signals.error.connect(lambda err: self.window.core.debug.log(f"Worker error: {err}"))
|
|
486
|
+
worker.signals.confirm.connect(self.window.ui.dialogs.confirm)
|
|
487
|
+
worker.signals.restored.connect(lambda current: self.window.ui.dialogs.workdir.set_path(current))
|
|
488
|
+
worker.signals.updated.connect(self.window.controller.settings.profile.after_update)
|
|
489
|
+
worker.signals.deleted.connect(self.window.controller.settings.profile.after_delete)
|
|
490
|
+
worker.signals.duplicated.connect(self.window.controller.settings.profile.after_duplicate)
|
|
491
|
+
worker.signals.switch.connect(self.window.controller.settings.profile.switch_current)
|
|
492
|
+
worker.signals.after_migrate.connect(self.do_migrate)
|
|
430
493
|
|
|
431
494
|
# start worker in thread pool
|
|
432
|
-
self.window.threadpool.start(
|
|
495
|
+
self.window.threadpool.start(worker)
|
|
433
496
|
|
|
434
497
|
def update(
|
|
435
498
|
self,
|
|
@@ -444,11 +507,11 @@ class Workdir:
|
|
|
444
507
|
:param force: force update (confirm)
|
|
445
508
|
:param profile_name: profile name (optional, for future use)
|
|
446
509
|
"""
|
|
447
|
-
self.
|
|
448
|
-
action="update",
|
|
449
|
-
path=path,
|
|
510
|
+
self.do_update(
|
|
450
511
|
force=force,
|
|
451
512
|
profile_name=profile_name,
|
|
513
|
+
current_path=self.window.core.config.get_user_path(),
|
|
514
|
+
new_path=path,
|
|
452
515
|
)
|
|
453
516
|
|
|
454
517
|
def migrate(
|
|
@@ -477,10 +540,7 @@ class Workdir:
|
|
|
477
540
|
|
|
478
541
|
:param current: current working directory
|
|
479
542
|
"""
|
|
480
|
-
self.
|
|
481
|
-
action="restore",
|
|
482
|
-
current=current,
|
|
483
|
-
)
|
|
543
|
+
self.rollback(current=current)
|
|
484
544
|
|
|
485
545
|
def delete_files(
|
|
486
546
|
self,
|
|
@@ -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.20 23:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -248,8 +248,14 @@ class Theme:
|
|
|
248
248
|
"""
|
|
249
249
|
return self.common.get_style(element)
|
|
250
250
|
|
|
251
|
-
def reload_all(self):
|
|
252
|
-
"""
|
|
253
|
-
|
|
254
|
-
|
|
251
|
+
def reload_all(self, prev_theme: Optional[str] = None):
|
|
252
|
+
"""
|
|
253
|
+
Reload all
|
|
254
|
+
|
|
255
|
+
:param prev_theme: previous theme name
|
|
256
|
+
"""
|
|
257
|
+
current_theme = self.window.core.config.get('theme')
|
|
258
|
+
if not prev_theme or prev_theme != current_theme:
|
|
259
|
+
self.setup()
|
|
260
|
+
self.update_style()
|
|
255
261
|
self.update_syntax()
|
|
@@ -188,24 +188,13 @@ class Evaluation:
|
|
|
188
188
|
"""
|
|
189
189
|
outputs = []
|
|
190
190
|
for ctx in history:
|
|
191
|
-
if self.is_output(ctx):
|
|
192
|
-
if ctx.output:
|
|
193
|
-
outputs.append(ctx.output)
|
|
194
|
-
|
|
195
191
|
# if next input then clear outputs - use only output after last user input
|
|
196
192
|
if self.is_input(ctx):
|
|
197
193
|
outputs.clear()
|
|
198
194
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if self.is_output(ctx):
|
|
203
|
-
if ctx.output:
|
|
204
|
-
outputs.append(ctx.output)
|
|
205
|
-
|
|
206
|
-
# if next input then clear outputs - use only output after last user input
|
|
207
|
-
if self.is_input(ctx):
|
|
208
|
-
outputs.clear()
|
|
195
|
+
if self.is_output(ctx):
|
|
196
|
+
if ctx.output:
|
|
197
|
+
outputs.append(ctx.output)
|
|
209
198
|
|
|
210
199
|
return "\n\n".join(outputs) if outputs else ""
|
|
211
200
|
|
|
@@ -275,12 +275,13 @@ class LlamaWorkflow(BaseRunner):
|
|
|
275
275
|
if verbose:
|
|
276
276
|
print("\n\n-----STEP-----\n\n")
|
|
277
277
|
print(f"[{event.name}] {event.index}/{event.total} meta={event.meta}")
|
|
278
|
-
|
|
279
|
-
item_ctx
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
278
|
+
if flush:
|
|
279
|
+
item_ctx = self.on_next_ctx(
|
|
280
|
+
item_ctx,
|
|
281
|
+
signals=signals,
|
|
282
|
+
begin=begin,
|
|
283
|
+
stream=True,
|
|
284
|
+
)
|
|
284
285
|
elif isinstance(event, AgentStream):
|
|
285
286
|
if verbose:
|
|
286
287
|
print(f"{event.delta}", end="", flush=True)
|
|
@@ -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.20 09:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import copy
|
|
@@ -574,11 +574,12 @@ class Command:
|
|
|
574
574
|
pass
|
|
575
575
|
return params
|
|
576
576
|
|
|
577
|
-
def is_native_enabled(self, force: bool = False) -> bool:
|
|
577
|
+
def is_native_enabled(self, force: bool = False, model: str = None) -> bool:
|
|
578
578
|
"""
|
|
579
579
|
Check if native tool calls are enabled
|
|
580
580
|
|
|
581
581
|
:param force: force check, ignore config
|
|
582
|
+
:param model: model name (optional)
|
|
582
583
|
:return: True if enabled
|
|
583
584
|
"""
|
|
584
585
|
disabled_modes = [
|
|
@@ -592,7 +593,8 @@ class Command:
|
|
|
592
593
|
return False
|
|
593
594
|
|
|
594
595
|
if not force:
|
|
595
|
-
model
|
|
596
|
+
if model is None:
|
|
597
|
+
model = self.window.core.config.get('model') # get from globals
|
|
596
598
|
if model:
|
|
597
599
|
model_data = self.window.core.models.get(model)
|
|
598
600
|
if model_data:
|