pygpt-net 2.6.67__py3-none-any.whl → 2.7.0__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/assistant/assistant.py +13 -8
- pygpt_net/controller/assistant/batch.py +29 -15
- pygpt_net/controller/assistant/files.py +19 -14
- pygpt_net/controller/assistant/store.py +63 -41
- pygpt_net/controller/attachment/attachment.py +45 -35
- pygpt_net/controller/chat/attachment.py +50 -39
- pygpt_net/controller/config/field/dictionary.py +26 -14
- pygpt_net/controller/ctx/common.py +27 -17
- pygpt_net/controller/ctx/ctx.py +182 -101
- pygpt_net/controller/files/files.py +101 -41
- pygpt_net/controller/idx/indexer.py +87 -31
- pygpt_net/controller/kernel/kernel.py +13 -2
- pygpt_net/controller/mode/mode.py +3 -3
- pygpt_net/controller/model/editor.py +70 -15
- pygpt_net/controller/model/importer.py +153 -54
- pygpt_net/controller/painter/painter.py +2 -2
- pygpt_net/controller/presets/experts.py +68 -15
- pygpt_net/controller/presets/presets.py +72 -36
- pygpt_net/controller/settings/profile.py +76 -35
- pygpt_net/controller/settings/workdir.py +70 -39
- pygpt_net/core/assistants/files.py +20 -18
- pygpt_net/core/filesystem/actions.py +111 -10
- pygpt_net/core/filesystem/filesystem.py +2 -1
- pygpt_net/core/idx/idx.py +12 -11
- pygpt_net/core/idx/worker.py +13 -1
- pygpt_net/core/models/models.py +4 -4
- pygpt_net/core/profile/profile.py +13 -3
- pygpt_net/data/config/config.json +3 -3
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/css/style.dark.css +39 -1
- pygpt_net/data/css/style.light.css +39 -1
- pygpt_net/data/locale/locale.de.ini +3 -1
- pygpt_net/data/locale/locale.en.ini +3 -1
- pygpt_net/data/locale/locale.es.ini +3 -1
- pygpt_net/data/locale/locale.fr.ini +3 -1
- pygpt_net/data/locale/locale.it.ini +3 -1
- pygpt_net/data/locale/locale.pl.ini +4 -2
- pygpt_net/data/locale/locale.uk.ini +3 -1
- pygpt_net/data/locale/locale.zh.ini +3 -1
- pygpt_net/provider/api/openai/__init__.py +4 -2
- pygpt_net/provider/core/config/patch.py +9 -1
- pygpt_net/tools/image_viewer/tool.py +17 -0
- pygpt_net/tools/text_editor/tool.py +9 -0
- pygpt_net/ui/__init__.py +2 -2
- pygpt_net/ui/layout/ctx/ctx_list.py +16 -6
- pygpt_net/ui/main.py +3 -1
- pygpt_net/ui/widget/calendar/select.py +3 -3
- pygpt_net/ui/widget/filesystem/explorer.py +1082 -142
- pygpt_net/ui/widget/lists/assistant.py +185 -24
- pygpt_net/ui/widget/lists/assistant_store.py +245 -42
- pygpt_net/ui/widget/lists/attachment.py +230 -47
- pygpt_net/ui/widget/lists/attachment_ctx.py +189 -33
- pygpt_net/ui/widget/lists/base_list_combo.py +2 -2
- pygpt_net/ui/widget/lists/context.py +1253 -70
- pygpt_net/ui/widget/lists/experts.py +110 -8
- pygpt_net/ui/widget/lists/model_editor.py +217 -14
- pygpt_net/ui/widget/lists/model_importer.py +125 -6
- pygpt_net/ui/widget/lists/preset.py +460 -71
- pygpt_net/ui/widget/lists/profile.py +149 -27
- pygpt_net/ui/widget/lists/uploaded.py +230 -38
- pygpt_net/ui/widget/option/combo.py +1046 -32
- pygpt_net/ui/widget/option/dictionary.py +35 -7
- {pygpt_net-2.6.67.dist-info → pygpt_net-2.7.0.dist-info}/METADATA +14 -57
- {pygpt_net-2.6.67.dist-info → pygpt_net-2.7.0.dist-info}/RECORD +69 -69
- {pygpt_net-2.6.67.dist-info → pygpt_net-2.7.0.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.67.dist-info → pygpt_net-2.7.0.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.67.dist-info → pygpt_net-2.7.0.dist-info}/entry_points.txt +0 -0
|
@@ -6,11 +6,11 @@
|
|
|
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.12.27 21:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
13
|
-
from typing import List, Dict, Any
|
|
13
|
+
from typing import List, Dict, Any, Union
|
|
14
14
|
|
|
15
15
|
from PySide6.QtCore import Slot, QObject
|
|
16
16
|
|
|
@@ -384,14 +384,14 @@ class Attachment(QObject):
|
|
|
384
384
|
|
|
385
385
|
def delete_by_idx(
|
|
386
386
|
self,
|
|
387
|
-
idx: int,
|
|
387
|
+
idx: Union[int, list],
|
|
388
388
|
force: bool = False,
|
|
389
389
|
remove_local: bool = True
|
|
390
390
|
):
|
|
391
391
|
"""
|
|
392
392
|
Delete attachment by index
|
|
393
393
|
|
|
394
|
-
:param idx: Index on list
|
|
394
|
+
:param idx: Index on list or list of indices
|
|
395
395
|
:param force: Force delete
|
|
396
396
|
:param remove_local: Remove local copies
|
|
397
397
|
"""
|
|
@@ -406,9 +406,14 @@ class Attachment(QObject):
|
|
|
406
406
|
if meta is None or not meta.has_additional_ctx():
|
|
407
407
|
return
|
|
408
408
|
items = self.window.core.attachments.context.get_all(meta)
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
409
|
+
ids = idx if isinstance(idx, list) else [idx]
|
|
410
|
+
updated = False
|
|
411
|
+
for idx in sorted(ids, reverse=True):
|
|
412
|
+
if idx < len(items):
|
|
413
|
+
item = items[idx]
|
|
414
|
+
self.window.core.attachments.context.delete(meta, item, delete_files=remove_local)
|
|
415
|
+
updated = True
|
|
416
|
+
if updated:
|
|
412
417
|
self.update_list(meta)
|
|
413
418
|
self.window.controller.ctx.update()
|
|
414
419
|
|
|
@@ -448,62 +453,68 @@ class Attachment(QObject):
|
|
|
448
453
|
"""
|
|
449
454
|
pass
|
|
450
455
|
|
|
451
|
-
def open_by_idx(self, idx: int):
|
|
456
|
+
def open_by_idx(self, idx: Union[int, list]):
|
|
452
457
|
"""
|
|
453
458
|
Open attachment by index
|
|
454
459
|
|
|
455
|
-
:param idx: Index on list
|
|
460
|
+
:param idx: Index on list or list of indices
|
|
456
461
|
"""
|
|
457
462
|
meta = self.window.core.ctx.get_current_meta()
|
|
458
463
|
if meta is None or not meta.has_additional_ctx():
|
|
459
464
|
return
|
|
460
465
|
items = self.window.core.attachments.context.get_all(meta)
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
path = item["
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
466
|
+
ids = idx if isinstance(idx, list) else [idx]
|
|
467
|
+
for idx in ids:
|
|
468
|
+
if idx < len(items):
|
|
469
|
+
item = items[idx]
|
|
470
|
+
path = item["path"]
|
|
471
|
+
if "real_path" in item:
|
|
472
|
+
path = item["real_path"]
|
|
473
|
+
if os.path.exists(path) and os.path.isfile(path):
|
|
474
|
+
print(f"Opening attachment: {path}")
|
|
475
|
+
self.window.controller.files.open(path)
|
|
476
|
+
|
|
477
|
+
def open_dir_src_by_idx(self, idx: Union[int, list]):
|
|
471
478
|
"""
|
|
472
479
|
Open source directory by index
|
|
473
480
|
|
|
474
|
-
:param idx: Index on list
|
|
481
|
+
:param idx: Index on list or list of indices
|
|
475
482
|
"""
|
|
476
483
|
meta = self.window.core.ctx.get_current_meta()
|
|
477
484
|
if meta is None or not meta.has_additional_ctx():
|
|
478
485
|
return
|
|
479
486
|
items = self.window.core.attachments.context.get_all(meta)
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
path = item["
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
487
|
+
ids = idx if isinstance(idx, list) else [idx]
|
|
488
|
+
for idx in ids:
|
|
489
|
+
if idx < len(items):
|
|
490
|
+
item = items[idx]
|
|
491
|
+
path = item["path"]
|
|
492
|
+
if "real_path" in item:
|
|
493
|
+
path = item["real_path"]
|
|
494
|
+
dir = os.path.dirname(path)
|
|
495
|
+
if os.path.exists(dir) and os.path.isdir(dir):
|
|
496
|
+
print(f"Opening source directory: {dir}")
|
|
497
|
+
self.window.controller.files.open(dir)
|
|
498
|
+
|
|
499
|
+
def open_dir_dest_by_idx(self, idx: Union[int, list]):
|
|
491
500
|
"""
|
|
492
501
|
Open destination directory by index
|
|
493
502
|
|
|
494
|
-
:param idx: Index on list
|
|
503
|
+
:param idx: Index on list or list of indices
|
|
495
504
|
"""
|
|
496
505
|
meta = self.window.core.ctx.get_current_meta()
|
|
497
506
|
if meta is None or not meta.has_additional_ctx():
|
|
498
507
|
return
|
|
499
508
|
items = self.window.core.attachments.context.get_all(meta)
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
509
|
+
ids = idx if isinstance(idx, list) else [idx]
|
|
510
|
+
for idx in ids:
|
|
511
|
+
if idx < len(items):
|
|
512
|
+
item = items[idx]
|
|
513
|
+
root_dir = self.window.core.attachments.context.get_dir(meta)
|
|
514
|
+
dir = os.path.join(root_dir, item["uuid"])
|
|
515
|
+
if os.path.exists(dir) and os.path.isdir(dir):
|
|
516
|
+
self.window.controller.files.open(dir)
|
|
517
|
+
print(f"Opening destination directory: {dir}")
|
|
507
518
|
|
|
508
519
|
def has_file_by_idx(self, idx: int) -> bool:
|
|
509
520
|
"""
|
|
@@ -6,10 +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.
|
|
9
|
+
# Updated Date: 2025.12.27 21:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
|
-
from typing import Dict, Any, List
|
|
12
|
+
from typing import Dict, Any, List, Union
|
|
13
13
|
|
|
14
14
|
from pygpt_net.ui.widget.option.dictionary import OptionDict
|
|
15
15
|
from pygpt_net.utils import trans
|
|
@@ -85,7 +85,7 @@ class Dictionary:
|
|
|
85
85
|
def delete_item(
|
|
86
86
|
self,
|
|
87
87
|
parent_object: OptionDict,
|
|
88
|
-
id
|
|
88
|
+
id, # Union[int, list[int]]
|
|
89
89
|
force: bool = False,
|
|
90
90
|
hooks: bool = True
|
|
91
91
|
):
|
|
@@ -93,11 +93,12 @@ class Dictionary:
|
|
|
93
93
|
Show delete item (from dict list) confirmation dialog or executes delete
|
|
94
94
|
|
|
95
95
|
:param parent_object: parent object
|
|
96
|
-
:param id: item id
|
|
96
|
+
:param id: item id or list of ids (row indexes)
|
|
97
97
|
:param force: force delete
|
|
98
98
|
:param hooks: run hooks
|
|
99
99
|
"""
|
|
100
100
|
if not force:
|
|
101
|
+
# Pass list as-is for batch confirmation
|
|
101
102
|
self.window.ui.dialogs.confirm(
|
|
102
103
|
type="settings.dict.delete",
|
|
103
104
|
id=id,
|
|
@@ -107,16 +108,27 @@ class Dictionary:
|
|
|
107
108
|
return
|
|
108
109
|
|
|
109
110
|
if parent_object is not None:
|
|
110
|
-
|
|
111
|
-
if
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
111
|
+
# Normalize to unique integer indexes and sort descending to avoid index shift on delete
|
|
112
|
+
ids = id if isinstance(id, list) else [id]
|
|
113
|
+
normalized = []
|
|
114
|
+
for v in ids:
|
|
115
|
+
try:
|
|
116
|
+
normalized.append(int(v))
|
|
117
|
+
except Exception:
|
|
118
|
+
continue
|
|
119
|
+
normalized = sorted(set(normalized), reverse=True)
|
|
120
|
+
|
|
121
|
+
ui = self.window.ui
|
|
122
|
+
for idx in normalized:
|
|
123
|
+
parent_object.delete_item_execute(idx)
|
|
124
|
+
if hooks:
|
|
125
|
+
hook_name = f"update.{parent_object}.{idx}"
|
|
126
|
+
if ui.has_hook(hook_name):
|
|
127
|
+
hook = ui.get_hook(hook_name)
|
|
128
|
+
try:
|
|
129
|
+
hook(idx, {}, "dictionary")
|
|
130
|
+
except Exception as e:
|
|
131
|
+
self.window.core.debug.log(e)
|
|
120
132
|
|
|
121
133
|
def to_options(
|
|
122
134
|
self,
|
|
@@ -6,10 +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.
|
|
9
|
+
# Updated Date: 2025.12.27 19:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
|
-
from typing import Optional
|
|
12
|
+
from typing import Optional, Union
|
|
13
13
|
|
|
14
14
|
from PySide6.QtCore import QTimer, QSignalBlocker
|
|
15
15
|
from PySide6.QtWidgets import QApplication
|
|
@@ -75,16 +75,22 @@ class Common:
|
|
|
75
75
|
label = f'{label} ({assistant.name})'
|
|
76
76
|
self.window.controller.ui.update_ctx_label(label)
|
|
77
77
|
|
|
78
|
-
def duplicate(self, meta_id: int):
|
|
78
|
+
def duplicate(self, meta_id: Union[int, list]):
|
|
79
79
|
"""
|
|
80
80
|
Duplicate context by meta id
|
|
81
81
|
|
|
82
|
-
:param meta_id: context id
|
|
82
|
+
:param meta_id: context id or list of ids
|
|
83
83
|
"""
|
|
84
|
-
|
|
85
|
-
if
|
|
86
|
-
|
|
87
|
-
self.window.
|
|
84
|
+
is_updated = False
|
|
85
|
+
ids = meta_id if isinstance(meta_id, list) else [meta_id]
|
|
86
|
+
for meta_id in ids:
|
|
87
|
+
new_id = self.window.core.ctx.duplicate(meta_id)
|
|
88
|
+
if new_id is not None:
|
|
89
|
+
self.window.core.attachments.context.duplicate(meta_id, new_id)
|
|
90
|
+
self.window.update_status(f"Context duplicated, new ctx id: {new_id}")
|
|
91
|
+
is_updated = True
|
|
92
|
+
|
|
93
|
+
if is_updated:
|
|
88
94
|
QTimer.singleShot(10, self._update_ctx_no_scroll)
|
|
89
95
|
|
|
90
96
|
def dismiss_rename(self):
|
|
@@ -162,25 +168,27 @@ class Common:
|
|
|
162
168
|
self.window.core.ctx.set_display_filters(filters)
|
|
163
169
|
self.window.controller.ctx.update()
|
|
164
170
|
|
|
165
|
-
def copy_id(self, id: int):
|
|
171
|
+
def copy_id(self, id: Union[int, list]):
|
|
166
172
|
"""
|
|
167
173
|
Copy id into clipboard and to iinput
|
|
168
174
|
|
|
169
|
-
:param id: context list idx
|
|
175
|
+
:param id: context list idx or list of ids
|
|
170
176
|
"""
|
|
171
|
-
|
|
177
|
+
ids = id if isinstance(id, list) else [id]
|
|
178
|
+
values = [f"@{i}" for i in ids]
|
|
179
|
+
value = " ".join(values)
|
|
172
180
|
self.window.controller.chat.common.append_to_input(value, separator=" ")
|
|
173
181
|
QApplication.clipboard().setText(value)
|
|
174
182
|
|
|
175
183
|
def reset(
|
|
176
184
|
self,
|
|
177
|
-
meta_id: int,
|
|
185
|
+
meta_id: Union[int, list],
|
|
178
186
|
force: bool = False
|
|
179
187
|
):
|
|
180
188
|
"""
|
|
181
189
|
Reset by meta id
|
|
182
190
|
|
|
183
|
-
:param meta_id: context id
|
|
191
|
+
:param meta_id: context id or list of ids
|
|
184
192
|
:param force: True to force reset
|
|
185
193
|
"""
|
|
186
194
|
if not force:
|
|
@@ -190,7 +198,9 @@ class Common:
|
|
|
190
198
|
msg=trans('ctx.reset_meta.confirm'),
|
|
191
199
|
)
|
|
192
200
|
return
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
self.window.
|
|
201
|
+
ids = meta_id if isinstance(meta_id, list) else [meta_id]
|
|
202
|
+
for meta_id in ids:
|
|
203
|
+
self.window.core.ctx.reset_meta(meta_id)
|
|
204
|
+
self.window.core.attachments.context.reset_by_meta_id(meta_id, delete_files=True)
|
|
205
|
+
if self.window.core.ctx.get_current() == meta_id:
|
|
206
|
+
self.window.controller.ctx.load(meta_id)
|