pygpt-net 2.6.66__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 +18 -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/config/field/textarea.py +2 -2
- pygpt_net/controller/ctx/common.py +27 -17
- pygpt_net/controller/ctx/ctx.py +182 -101
- pygpt_net/controller/dialogs/info.py +2 -2
- 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/media/media.py +29 -1
- pygpt_net/controller/mode/mode.py +3 -3
- pygpt_net/controller/model/editor.py +141 -21
- 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/editor.py +25 -1
- 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/core/types/image.py +10 -1
- pygpt_net/core/video/video.py +43 -3
- pygpt_net/data/config/config.json +3 -3
- pygpt_net/data/config/models.json +25 -14
- 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 +4 -1
- pygpt_net/data/locale/locale.en.ini +4 -1
- pygpt_net/data/locale/locale.es.ini +4 -1
- pygpt_net/data/locale/locale.fr.ini +4 -1
- pygpt_net/data/locale/locale.it.ini +4 -1
- pygpt_net/data/locale/locale.pl.ini +5 -2
- pygpt_net/data/locale/locale.uk.ini +4 -1
- pygpt_net/data/locale/locale.zh.ini +4 -1
- pygpt_net/item/model.py +1 -1
- pygpt_net/provider/api/openai/__init__.py +4 -2
- pygpt_net/provider/api/openai/video.py +2 -2
- pygpt_net/provider/core/config/patch.py +9 -1
- pygpt_net/provider/core/model/patch.py +26 -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/dialog/models.py +10 -1
- pygpt_net/ui/layout/ctx/ctx_list.py +16 -6
- pygpt_net/ui/layout/toolbox/video.py +14 -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/ui/widget/option/input.py +3 -1
- {pygpt_net-2.6.66.dist-info → pygpt_net-2.7.0.dist-info}/METADATA +20 -57
- {pygpt_net-2.6.66.dist-info → pygpt_net-2.7.0.dist-info}/RECORD +81 -81
- {pygpt_net-2.6.66.dist-info → pygpt_net-2.7.0.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.66.dist-info → pygpt_net-2.7.0.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.66.dist-info → pygpt_net-2.7.0.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.
|
|
9
|
+
# Updated Date: 2025.12.27 02:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import copy
|
|
@@ -183,6 +183,14 @@ class Patch:
|
|
|
183
183
|
data["img_mode"] = "image"
|
|
184
184
|
updated = True
|
|
185
185
|
|
|
186
|
+
# < 2.7.0
|
|
187
|
+
if old < parse_version("2.7.0"):
|
|
188
|
+
print("Migrating config from < 2.7.0...")
|
|
189
|
+
# add: combo boxes css
|
|
190
|
+
patch_css('style.light.css', True)
|
|
191
|
+
patch_css('style.dark.css', True)
|
|
192
|
+
updated = True
|
|
193
|
+
|
|
186
194
|
# update file
|
|
187
195
|
migrated = False
|
|
188
196
|
if updated:
|
|
@@ -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.12.
|
|
9
|
+
# Updated Date: 2025.12.26 11:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from packaging.version import parse as parse_version, Version
|
|
@@ -77,6 +77,31 @@ class Patch:
|
|
|
77
77
|
data[model] = base_model
|
|
78
78
|
updated = True
|
|
79
79
|
|
|
80
|
+
# < 2.6.67 <--- add missing image input
|
|
81
|
+
if old < parse_version("2.6.67"):
|
|
82
|
+
print("Migrating models from < 2.6.67...")
|
|
83
|
+
models_to_update = [
|
|
84
|
+
"claude-opus-4-5",
|
|
85
|
+
"claude-sonnet-4-5",
|
|
86
|
+
"gemini-3-flash-preview",
|
|
87
|
+
"gemini-3-pro-image-preview",
|
|
88
|
+
"gemini-3-pro-preview",
|
|
89
|
+
"gpt-5.2-low",
|
|
90
|
+
"gpt-5.2-medium",
|
|
91
|
+
"gpt-5.2-high",
|
|
92
|
+
"gpt-image-1.5",
|
|
93
|
+
"nano-banana-pro-preview",
|
|
94
|
+
"sora-2",
|
|
95
|
+
"veo-3.1-fast-generate-preview",
|
|
96
|
+
"veo-3.1-generate-preview"
|
|
97
|
+
]
|
|
98
|
+
for model in models_to_update:
|
|
99
|
+
if model in data:
|
|
100
|
+
m = data[model]
|
|
101
|
+
if not m.is_image_input():
|
|
102
|
+
m.input.append("image")
|
|
103
|
+
updated = True
|
|
104
|
+
|
|
80
105
|
# update file
|
|
81
106
|
if updated:
|
|
82
107
|
# fix empty/broken data
|
|
@@ -70,6 +70,23 @@ class ImageViewer(BaseTool):
|
|
|
70
70
|
if path:
|
|
71
71
|
self.open_preview(path, id, auto_close)
|
|
72
72
|
|
|
73
|
+
def open_preview_batch(
|
|
74
|
+
self,
|
|
75
|
+
paths: list,
|
|
76
|
+
current_id: str = None,
|
|
77
|
+
auto_close: bool = True):
|
|
78
|
+
"""
|
|
79
|
+
Open image preview batch in dialog
|
|
80
|
+
|
|
81
|
+
:param paths:
|
|
82
|
+
:param current_id:
|
|
83
|
+
:param auto_close:
|
|
84
|
+
:return:
|
|
85
|
+
"""
|
|
86
|
+
for path in paths:
|
|
87
|
+
self.open_preview(path, current_id, auto_close)
|
|
88
|
+
|
|
89
|
+
|
|
73
90
|
def open_preview(
|
|
74
91
|
self,
|
|
75
92
|
path: str = None,
|
|
@@ -112,6 +112,15 @@ class TextEditor(BaseTool):
|
|
|
112
112
|
"""Open new instance"""
|
|
113
113
|
self.open()
|
|
114
114
|
|
|
115
|
+
def open_batch(self, files: list):
|
|
116
|
+
"""
|
|
117
|
+
Open multiple files in editor instances
|
|
118
|
+
|
|
119
|
+
:param files: list of files to open
|
|
120
|
+
"""
|
|
121
|
+
for file in files:
|
|
122
|
+
self.open(file, auto_close=False, force=True)
|
|
123
|
+
|
|
115
124
|
def open(
|
|
116
125
|
self,
|
|
117
126
|
file: Optional[str] = None,
|
pygpt_net/ui/__init__.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.
|
|
9
|
+
# Updated Date: 2025.12.27 17:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -143,7 +143,7 @@ class UI:
|
|
|
143
143
|
suffix = self.window.core.platforms.get_env_suffix()
|
|
144
144
|
profile_name = self.window.core.config.profile.get_current_name()
|
|
145
145
|
self.window.setWindowTitle(
|
|
146
|
-
f"PyGPT
|
|
146
|
+
f"PyGPT {self.window.meta['version']} | "
|
|
147
147
|
f"build {self.window.meta['build'].replace('.', '-')}{suffix} ({profile_name})"
|
|
148
148
|
)
|
|
149
149
|
|
pygpt_net/ui/dialog/models.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.
|
|
9
|
+
# Updated Date: 2025.12.26 13:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import copy
|
|
@@ -166,11 +166,20 @@ class Models:
|
|
|
166
166
|
self.window.ui.nodes['models.editor.search'].on_search = self._on_search_models
|
|
167
167
|
self.window.ui.nodes['models.editor.search'].on_clear = self._on_clear_models # clear via "X" button
|
|
168
168
|
|
|
169
|
+
# provider select
|
|
170
|
+
option_provider = self.window.controller.model.editor.get_provider_option()
|
|
171
|
+
self.window.ui.config[parent_id]['provider_global'] = OptionCombo(self.window, parent_id, 'provider_global',
|
|
172
|
+
option_provider)
|
|
173
|
+
provider_keys = self.window.controller.config.placeholder.apply_by_id('llm_providers')
|
|
174
|
+
provider_keys.insert(0, {"-": trans("list.all")}) # add "All" option
|
|
175
|
+
self.window.ui.config[parent_id]['provider_global'].set_keys(provider_keys)
|
|
176
|
+
|
|
169
177
|
# container for search + list (left panel)
|
|
170
178
|
left_layout = QVBoxLayout()
|
|
171
179
|
left_layout.setContentsMargins(0, 0, 0, 0)
|
|
172
180
|
left_layout.setSpacing(6)
|
|
173
181
|
left_layout.addWidget(self.window.ui.nodes['models.editor.search'])
|
|
182
|
+
left_layout.addWidget(self.window.ui.config[parent_id]['provider_global'])
|
|
174
183
|
left_layout.addWidget(self.window.ui.nodes[id])
|
|
175
184
|
left_widget = QWidget()
|
|
176
185
|
left_widget.setLayout(left_layout)
|
|
@@ -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.12.28 12:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6 import QtCore
|
|
@@ -69,6 +69,14 @@ class CtxList:
|
|
|
69
69
|
models[ctx_id] = model
|
|
70
70
|
ctx_list.setModel(model)
|
|
71
71
|
|
|
72
|
+
# Expose force scroll on model as a thin proxy to the view method for external callers
|
|
73
|
+
try:
|
|
74
|
+
def _model_force_scroll_to_current(*args, **kwargs):
|
|
75
|
+
return ctx_list.force_scroll_to_current(*args, **kwargs)
|
|
76
|
+
setattr(model, "force_scroll_to_current", _model_force_scroll_to_current)
|
|
77
|
+
except Exception:
|
|
78
|
+
pass
|
|
79
|
+
|
|
72
80
|
ctx = self.window.controller.ctx
|
|
73
81
|
ctx_list.selectionModel().selectionChanged.connect(lambda *_: ctx.selection_change())
|
|
74
82
|
|
|
@@ -265,14 +273,17 @@ class CtxList:
|
|
|
265
273
|
if c == 0 and search_string:
|
|
266
274
|
continue
|
|
267
275
|
|
|
268
|
-
|
|
276
|
+
# Display only the group name; the counter is drawn by delegate on the right
|
|
269
277
|
is_attachment = group.has_additional_ctx()
|
|
270
|
-
group_name = group.name
|
|
278
|
+
group_name = group.name
|
|
271
279
|
group_item = GroupItem(folder_icon, group_name, group.id)
|
|
272
280
|
group_item.hasAttachments = is_attachment
|
|
281
|
+
|
|
282
|
+
# Provide all metadata required by the delegate
|
|
273
283
|
custom_data = {
|
|
274
284
|
"is_group": True,
|
|
275
285
|
"is_attachment": is_attachment,
|
|
286
|
+
"count": c,
|
|
276
287
|
}
|
|
277
288
|
|
|
278
289
|
if is_attachment:
|
|
@@ -299,12 +310,11 @@ class CtxList:
|
|
|
299
310
|
|
|
300
311
|
model.appendRow(group_item)
|
|
301
312
|
|
|
313
|
+
# Always reflect persisted expansion state so groups stay open after actions
|
|
302
314
|
desired = group.id in node.expanded_items
|
|
303
315
|
idx = group_item.index()
|
|
304
|
-
if node.isExpanded(idx) != desired
|
|
316
|
+
if node.isExpanded(idx) != desired:
|
|
305
317
|
node.setExpanded(idx, desired)
|
|
306
|
-
else:
|
|
307
|
-
node.setExpanded(idx, False)
|
|
308
318
|
|
|
309
319
|
def count_in_group(self, group_id: int, data: dict) -> int:
|
|
310
320
|
"""
|
|
@@ -6,12 +6,13 @@
|
|
|
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.26 12:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
|
-
from PySide6.QtWidgets import
|
|
12
|
+
from PySide6.QtWidgets import QWidget, QHBoxLayout
|
|
13
13
|
|
|
14
14
|
from pygpt_net.ui.widget.option.combo import OptionCombo
|
|
15
|
+
from pygpt_net.ui.widget.option.input import OptionInput
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class Video:
|
|
@@ -36,11 +37,18 @@ class Video:
|
|
|
36
37
|
container = QWidget()
|
|
37
38
|
ui.nodes['video.options'] = container
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
option_ratio = self.window.core.video.get_aspect_ratio_option()
|
|
41
|
+
option_resolution = self.window.core.video.get_resolution_option()
|
|
42
|
+
option_duration = self.window.core.video.get_duration_option()
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
conf_global['video.aspect_ratio'] = OptionCombo(self.window, 'global', 'video.aspect_ratio', option_ratio)
|
|
45
|
+
conf_global['video.resolution'] = OptionCombo(self.window, 'global', 'video.resolution', option_resolution)
|
|
46
|
+
conf_global['video.duration'] = OptionInput(self.window, 'global', 'video.duration', option_duration)
|
|
47
|
+
|
|
48
|
+
rows = QHBoxLayout()
|
|
49
|
+
rows.addWidget(conf_global['video.resolution'], 2)
|
|
50
|
+
rows.addWidget(conf_global['video.aspect_ratio'], 2)
|
|
51
|
+
rows.addWidget(conf_global['video.duration'], 1)
|
|
44
52
|
rows.setContentsMargins(2, 5, 5, 5)
|
|
45
53
|
|
|
46
54
|
container.setLayout(rows)
|
pygpt_net/ui/main.py
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
|
7
7
|
# MIT License #
|
|
8
8
|
# Created By : Marcin Szczygliński #
|
|
9
|
-
# Updated Date: 2025.
|
|
9
|
+
# Updated Date: 2025.12.28 00:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -335,6 +335,8 @@ class MainWindow(QMainWindow, QtStyleTools):
|
|
|
335
335
|
self.controller.plugins.save_all()
|
|
336
336
|
print("Saving tools...")
|
|
337
337
|
self.tools.on_exit()
|
|
338
|
+
print("Closing clients...")
|
|
339
|
+
self.controller.kernel.close_clients()
|
|
338
340
|
print("Saving layout state...")
|
|
339
341
|
self.controller.layout.save()
|
|
340
342
|
print("Stopping timers...")
|
|
@@ -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.12.27 23:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import Tuple
|
|
@@ -98,10 +98,10 @@ class CalendarSelect(QCalendarWidget):
|
|
|
98
98
|
if theme != self._theme_cached:
|
|
99
99
|
self._theme_cached = theme
|
|
100
100
|
if isinstance(theme, str) and theme.startswith('dark'):
|
|
101
|
-
self._counter_bg = QColor(
|
|
101
|
+
self._counter_bg = QColor(70, 70, 70)
|
|
102
102
|
self._counter_font = QColor(255, 255, 255)
|
|
103
103
|
else:
|
|
104
|
-
self._counter_bg = QColor(
|
|
104
|
+
self._counter_bg = QColor(200, 200, 200)
|
|
105
105
|
self._counter_font = QColor(0, 0, 0)
|
|
106
106
|
|
|
107
107
|
def paintCell(self, painter, rect, date: QDate):
|