pygpt-net 2.6.33__py3-none-any.whl → 2.6.34__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 +7 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/controller/assistant/batch.py +14 -4
- pygpt_net/controller/assistant/files.py +1 -0
- pygpt_net/controller/assistant/store.py +195 -1
- pygpt_net/controller/camera/camera.py +1 -1
- pygpt_net/controller/chat/common.py +50 -46
- pygpt_net/controller/config/placeholder.py +95 -75
- pygpt_net/controller/dialogs/confirm.py +3 -1
- pygpt_net/controller/media/media.py +11 -3
- pygpt_net/controller/painter/common.py +231 -13
- pygpt_net/core/assistants/files.py +18 -0
- pygpt_net/core/camera/camera.py +31 -402
- pygpt_net/core/camera/worker.py +430 -0
- pygpt_net/core/filesystem/url.py +3 -0
- pygpt_net/core/render/web/body.py +65 -9
- pygpt_net/core/text/utils.py +3 -0
- pygpt_net/data/config/config.json +3 -3
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/config/settings.json +10 -5
- pygpt_net/data/locale/locale.de.ini +8 -7
- pygpt_net/data/locale/locale.en.ini +9 -6
- pygpt_net/data/locale/locale.es.ini +8 -7
- pygpt_net/data/locale/locale.fr.ini +8 -7
- pygpt_net/data/locale/locale.it.ini +8 -7
- pygpt_net/data/locale/locale.pl.ini +8 -7
- pygpt_net/data/locale/locale.uk.ini +8 -7
- pygpt_net/data/locale/locale.zh.ini +8 -7
- pygpt_net/item/assistant.py +13 -1
- pygpt_net/provider/api/google/__init__.py +32 -23
- pygpt_net/provider/api/openai/store.py +45 -1
- pygpt_net/provider/llms/google.py +4 -0
- pygpt_net/ui/dialog/assistant_store.py +213 -203
- pygpt_net/ui/layout/chat/input.py +3 -3
- pygpt_net/ui/widget/draw/painter.py +16 -1
- pygpt_net/ui/widget/option/combo.py +5 -1
- pygpt_net/ui/widget/textarea/input.py +273 -3
- {pygpt_net-2.6.33.dist-info → pygpt_net-2.6.34.dist-info}/METADATA +9 -2
- {pygpt_net-2.6.33.dist-info → pygpt_net-2.6.34.dist-info}/RECORD +42 -41
- {pygpt_net-2.6.33.dist-info → pygpt_net-2.6.34.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.33.dist-info → pygpt_net-2.6.34.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.33.dist-info → pygpt_net-2.6.34.dist-info}/entry_points.txt +0 -0
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.09.02 22:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import copy
|
|
13
13
|
|
|
14
|
-
from PySide6.QtCore import Qt
|
|
14
|
+
from PySide6.QtCore import Qt, QPoint
|
|
15
15
|
from PySide6.QtGui import QStandardItemModel, QAction, QIcon
|
|
16
16
|
from PySide6.QtWidgets import QPushButton, QHBoxLayout, QLabel, QVBoxLayout, QScrollArea, QWidget, QTabWidget, QFrame, \
|
|
17
|
-
QSplitter, QSizePolicy, QMenuBar, QCheckBox
|
|
17
|
+
QSplitter, QSizePolicy, QMenuBar, QCheckBox, QMenu, QListView
|
|
18
18
|
|
|
19
19
|
from pygpt_net.ui.widget.dialog.assistant_store import AssistantVectorStoreDialog
|
|
20
20
|
from pygpt_net.ui.widget.element.group import CollapsedGroup
|
|
@@ -46,122 +46,83 @@ class AssistantVectorStore:
|
|
|
46
46
|
|
|
47
47
|
:param idx: current model tab index
|
|
48
48
|
"""
|
|
49
|
-
self.window.ui
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
self.window.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
49
|
+
ui = self.window.ui
|
|
50
|
+
nodes = ui.nodes
|
|
51
|
+
models = ui.models
|
|
52
|
+
splitters = ui.splitters
|
|
53
|
+
controller = self.window.controller
|
|
54
|
+
core = self.window.core
|
|
55
|
+
|
|
56
|
+
nodes['assistant.store.btn.new'] = QPushButton(trans("dialog.assistant.store.btn.new"))
|
|
57
|
+
nodes['assistant.store.btn.save'] = QPushButton(trans("dialog.assistant.store.btn.save"))
|
|
58
|
+
nodes['assistant.store.btn.refresh_status'] = QPushButton(QIcon(":/icons/reload.svg"), "")
|
|
59
|
+
nodes['assistant.store.btn.close'] = QPushButton(trans("dialog.assistant.store.btn.close"))
|
|
60
|
+
|
|
61
|
+
nodes['assistant.store.btn.refresh_status'].setToolTip(
|
|
59
62
|
trans("dialog.assistant.store.btn.refresh_status")
|
|
60
63
|
)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
self.window.ui.nodes['assistant.store.btn.upload.files'] = \
|
|
64
|
-
QPushButton(trans("dialog.assistant.store.btn.upload.files"))
|
|
65
|
-
self.window.ui.nodes['assistant.store.btn.upload.dir'] = \
|
|
66
|
-
QPushButton(trans("dialog.assistant.store.btn.upload.dir"))
|
|
67
|
-
|
|
68
|
-
self.window.ui.nodes['assistant.store.hide_thread'] = QCheckBox(trans("assistant.store.hide_threads"))
|
|
69
|
-
self.window.ui.nodes['assistant.store.hide_thread'].setChecked(True)
|
|
70
|
-
self.window.ui.nodes['assistant.store.hide_thread'].stateChanged.connect(
|
|
71
|
-
lambda: self.window.controller.assistant.store.set_hide_thread(
|
|
72
|
-
self.window.ui.nodes['assistant.store.hide_thread'].isChecked()
|
|
73
|
-
)
|
|
74
|
-
)
|
|
75
|
-
if not self.window.core.config.get("assistant.store.hide_threads"):
|
|
76
|
-
self.window.ui.nodes['assistant.store.hide_thread'].setChecked(False)
|
|
64
|
+
nodes['assistant.store.btn.refresh_status'].setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
|
|
77
65
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
lambda: self.window.controller.assistant.store.close()
|
|
86
|
-
)
|
|
87
|
-
self.window.ui.nodes['assistant.store.btn.refresh_status'].clicked.connect(
|
|
88
|
-
lambda: self.window.controller.assistant.store.refresh_status()
|
|
89
|
-
)
|
|
90
|
-
self.window.ui.nodes['assistant.store.btn.upload.files'].clicked.connect(
|
|
91
|
-
lambda: self.window.controller.assistant.batch.open_upload_files()
|
|
92
|
-
)
|
|
93
|
-
self.window.ui.nodes['assistant.store.btn.upload.dir'].clicked.connect(
|
|
94
|
-
lambda: self.window.controller.assistant.batch.open_upload_dir()
|
|
66
|
+
nodes['assistant.store.btn.upload.files'] = QPushButton(trans("dialog.assistant.store.btn.upload.files"))
|
|
67
|
+
nodes['assistant.store.btn.upload.dir'] = QPushButton(trans("dialog.assistant.store.btn.upload.dir"))
|
|
68
|
+
|
|
69
|
+
nodes['assistant.store.hide_thread'] = QCheckBox(trans("assistant.store.hide_threads"))
|
|
70
|
+
nodes['assistant.store.hide_thread'].setChecked(bool(core.config.get("assistant.store.hide_threads")))
|
|
71
|
+
nodes['assistant.store.hide_thread'].toggled.connect(
|
|
72
|
+
controller.assistant.store.set_hide_thread
|
|
95
73
|
)
|
|
96
74
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
75
|
+
nodes['assistant.store.btn.new'].clicked.connect(controller.assistant.store.new)
|
|
76
|
+
nodes['assistant.store.btn.save'].clicked.connect(controller.assistant.store.save_btn)
|
|
77
|
+
nodes['assistant.store.btn.close'].clicked.connect(controller.assistant.store.close)
|
|
78
|
+
nodes['assistant.store.btn.refresh_status'].clicked.connect(controller.assistant.store.refresh_status)
|
|
79
|
+
nodes['assistant.store.btn.upload.files'].clicked.connect(controller.assistant.batch.open_upload_files)
|
|
80
|
+
nodes['assistant.store.btn.upload.dir'].clicked.connect(controller.assistant.batch.open_upload_dir)
|
|
101
81
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
footer.addWidget(self.window.ui.nodes['assistant.store.btn.save'])
|
|
82
|
+
nodes['assistant.store.btn.new'].setAutoDefault(False)
|
|
83
|
+
nodes['assistant.store.btn.refresh_status'].setAutoDefault(False)
|
|
84
|
+
nodes['assistant.store.btn.save'].setAutoDefault(True)
|
|
106
85
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
upload_layout.addWidget(self.window.ui.nodes['assistant.store.btn.upload.files'])
|
|
111
|
-
upload_layout.addWidget(self.window.ui.nodes['assistant.store.btn.upload.dir'])
|
|
112
|
-
upload_layout.setContentsMargins(0, 0, 0, 0)
|
|
86
|
+
footer = QHBoxLayout()
|
|
87
|
+
footer.addWidget(nodes['assistant.store.btn.close'])
|
|
88
|
+
footer.addWidget(nodes['assistant.store.btn.save'])
|
|
113
89
|
|
|
114
|
-
|
|
115
|
-
self.window.ui.tabs['assistant.store'] = QTabWidget()
|
|
90
|
+
ui.tabs['assistant.store'] = QTabWidget()
|
|
116
91
|
|
|
117
|
-
# build settings tabs
|
|
118
92
|
parent_id = "assistant.store"
|
|
119
93
|
|
|
120
94
|
scroll = QScrollArea()
|
|
121
95
|
scroll.setWidgetResizable(True)
|
|
122
96
|
content = QVBoxLayout()
|
|
123
97
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
self.window.ui.config[parent_id] = {}
|
|
98
|
+
if parent_id not in ui.config:
|
|
99
|
+
ui.config[parent_id] = {}
|
|
127
100
|
|
|
128
|
-
|
|
129
|
-
options = copy.deepcopy(self.window.controller.assistant.store.get_options())
|
|
101
|
+
options = copy.deepcopy(controller.assistant.store.get_options())
|
|
130
102
|
widgets = self.build_widgets(options)
|
|
131
|
-
advanced_keys = []
|
|
132
|
-
for key in options:
|
|
133
|
-
if 'advanced' in options[key] and options[key]['advanced']:
|
|
134
|
-
advanced_keys.append(key)
|
|
103
|
+
advanced_keys = [k for k, v in options.items() if v.get('advanced')]
|
|
135
104
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
self.window.ui.config[parent_id][key] = widgets[key]
|
|
105
|
+
for key, w in widgets.items():
|
|
106
|
+
ui.config[parent_id][key] = w
|
|
139
107
|
|
|
140
108
|
for key in widgets:
|
|
141
|
-
if key in advanced_keys:
|
|
109
|
+
if key in advanced_keys:
|
|
142
110
|
continue
|
|
143
|
-
content.addLayout(self.add_option(widgets[key], options[key]))
|
|
111
|
+
content.addLayout(self.add_option(widgets[key], options[key]))
|
|
144
112
|
|
|
145
|
-
|
|
146
|
-
if len(advanced_keys) > 0:
|
|
113
|
+
if advanced_keys:
|
|
147
114
|
group_id = 'assistant.store.advanced'
|
|
148
|
-
|
|
149
|
-
|
|
115
|
+
ui.groups[group_id] = CollapsedGroup(self.window, group_id, None, False, None)
|
|
116
|
+
ui.groups[group_id].box.setText(trans('settings.advanced.collapse'))
|
|
150
117
|
for key in widgets:
|
|
151
|
-
if key not in advanced_keys:
|
|
118
|
+
if key not in advanced_keys:
|
|
152
119
|
continue
|
|
120
|
+
option = self.add_option(widgets[key], options[key])
|
|
121
|
+
ui.groups[group_id].add_layout(option)
|
|
122
|
+
content.addWidget(ui.groups[group_id])
|
|
153
123
|
|
|
154
|
-
option = self.add_option(widgets[key], options[key]) # build option
|
|
155
|
-
self.window.ui.groups[group_id].add_layout(option) # add option to group
|
|
156
|
-
|
|
157
|
-
# add advanced options group to scroll
|
|
158
|
-
content.addWidget(self.window.ui.groups[group_id])
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
content.addLayout(upload_layout) # upload buttons
|
|
162
124
|
content.setContentsMargins(0, 0, 0, 0)
|
|
163
125
|
|
|
164
|
-
# scroll widget
|
|
165
126
|
scroll_widget = QWidget()
|
|
166
127
|
scroll_widget.setLayout(content)
|
|
167
128
|
scroll.setWidget(scroll_widget)
|
|
@@ -173,65 +134,93 @@ class AssistantVectorStore:
|
|
|
173
134
|
area_widget = QWidget()
|
|
174
135
|
area_widget.setLayout(area)
|
|
175
136
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
# storage list
|
|
182
|
-
id = 'assistant.store.list'
|
|
183
|
-
self.window.ui.nodes[id] = AssistantVectorStoreEditorList(self.window, id)
|
|
184
|
-
self.window.ui.models[id] = self.create_model(self.window)
|
|
185
|
-
self.window.ui.nodes[id].setModel(self.window.ui.models[id])
|
|
137
|
+
list_id = 'assistant.store.list'
|
|
138
|
+
nodes[list_id] = AssistantVectorStoreEditorList(self.window, list_id)
|
|
139
|
+
models[list_id] = self.create_model(self.window)
|
|
140
|
+
nodes[list_id].setModel(models[list_id])
|
|
141
|
+
nodes[list_id].setMinimumWidth(250)
|
|
186
142
|
|
|
187
|
-
# left widget
|
|
188
143
|
left_layout = QVBoxLayout()
|
|
189
|
-
left_layout.addWidget(
|
|
190
|
-
left_layout.addWidget(
|
|
191
|
-
left_layout.addWidget(
|
|
192
|
-
|
|
144
|
+
left_layout.addWidget(nodes['assistant.store.btn.new'])
|
|
145
|
+
left_layout.addWidget(nodes[list_id])
|
|
146
|
+
left_layout.addWidget(nodes['assistant.store.hide_thread'])
|
|
193
147
|
left_layout.setContentsMargins(0, 0, 0, 0)
|
|
194
148
|
left_widget = QWidget()
|
|
195
149
|
left_widget.setLayout(left_layout)
|
|
196
150
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
151
|
+
self.update_list(list_id, core.assistants.store.items)
|
|
152
|
+
|
|
153
|
+
# ==================== Files panel ====================
|
|
154
|
+
files_panel = QVBoxLayout()
|
|
155
|
+
files_label = QLabel("Files")
|
|
156
|
+
files_label.setStyleSheet("font-weight: bold;")
|
|
157
|
+
files_panel.addWidget(files_label)
|
|
158
|
+
|
|
159
|
+
files_list_id = 'assistant.store.files.list'
|
|
160
|
+
nodes[files_list_id] = QListView()
|
|
161
|
+
nodes[files_list_id].setEditTriggers(QListView.NoEditTriggers)
|
|
162
|
+
nodes[files_list_id].setSelectionMode(QListView.SingleSelection)
|
|
163
|
+
nodes[files_list_id].setContextMenuPolicy(Qt.CustomContextMenu)
|
|
164
|
+
nodes[files_list_id].customContextMenuRequested.connect(self.on_files_context_menu)
|
|
165
|
+
|
|
166
|
+
models[files_list_id] = self.create_model(self.window)
|
|
167
|
+
nodes[files_list_id].setModel(models[files_list_id])
|
|
168
|
+
nodes[files_list_id].setMinimumWidth(280)
|
|
169
|
+
|
|
170
|
+
files_bottom = QHBoxLayout()
|
|
171
|
+
files_bottom.setContentsMargins(0, 0, 0, 0)
|
|
172
|
+
files_bottom.addWidget(nodes['assistant.store.btn.upload.files'])
|
|
173
|
+
files_bottom.addWidget(nodes['assistant.store.btn.upload.dir'])
|
|
174
|
+
files_bottom.addWidget(nodes['assistant.store.btn.refresh_status'])
|
|
175
|
+
|
|
176
|
+
files_panel.addWidget(nodes[files_list_id])
|
|
177
|
+
files_panel.setContentsMargins(0, 0, 0, 5)
|
|
178
|
+
files_panel.addLayout(files_bottom)
|
|
179
|
+
files_widget = QWidget()
|
|
180
|
+
files_widget.setLayout(files_panel)
|
|
181
|
+
# ========================================================================
|
|
182
|
+
|
|
183
|
+
splitters['dialog.assistant.store'] = QSplitter(Qt.Horizontal)
|
|
184
|
+
splitters['dialog.assistant.store'].addWidget(left_widget)
|
|
185
|
+
|
|
186
|
+
splitters['dialog.assistant.store.right'] = QSplitter(Qt.Horizontal)
|
|
187
|
+
splitters['dialog.assistant.store.right'].addWidget(files_widget)
|
|
188
|
+
splitters['dialog.assistant.store.right'].addWidget(area_widget)
|
|
189
|
+
splitters['dialog.assistant.store.right'].setStretchFactor(1, 7)
|
|
190
|
+
splitters['dialog.assistant.store.right'].setStretchFactor(0, 3)
|
|
191
|
+
|
|
192
|
+
splitters['dialog.assistant.store'].addWidget(splitters['dialog.assistant.store.right'])
|
|
193
|
+
splitters['dialog.assistant.store'].setStretchFactor(0, 2)
|
|
194
|
+
splitters['dialog.assistant.store'].setStretchFactor(1, 8)
|
|
195
|
+
splitters['dialog.assistant.store'].setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
210
196
|
|
|
211
197
|
main_layout = QHBoxLayout()
|
|
212
|
-
main_layout.addWidget(
|
|
198
|
+
main_layout.addWidget(splitters['dialog.assistant.store'])
|
|
213
199
|
main_layout.setContentsMargins(0, 0, 0, 0)
|
|
214
200
|
|
|
215
201
|
layout = QVBoxLayout()
|
|
216
|
-
layout.addLayout(main_layout)
|
|
217
|
-
layout.addLayout(footer)
|
|
202
|
+
layout.addLayout(main_layout)
|
|
203
|
+
layout.addLayout(footer)
|
|
218
204
|
|
|
219
|
-
# add menu
|
|
220
205
|
layout.setMenuBar(self.setup_menu())
|
|
221
206
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
207
|
+
ui.dialog[self.dialog_id] = AssistantVectorStoreDialog(self.window, self.dialog_id)
|
|
208
|
+
ui.dialog[self.dialog_id].setLayout(layout)
|
|
209
|
+
ui.dialog[self.dialog_id].setWindowTitle(trans('dialog.assistant.store'))
|
|
225
210
|
|
|
226
|
-
# restore current opened tab if idx is set
|
|
227
211
|
if idx is not None:
|
|
228
212
|
try:
|
|
229
|
-
|
|
213
|
+
controller.assistant.store.set_by_tab(idx)
|
|
230
214
|
except Exception as e:
|
|
231
215
|
print('Failed restore store editor tab: {}'.format(idx))
|
|
232
216
|
else:
|
|
233
|
-
if
|
|
234
|
-
|
|
217
|
+
if controller.assistant.store.current is None:
|
|
218
|
+
controller.assistant.store.set_by_tab(0)
|
|
219
|
+
|
|
220
|
+
try:
|
|
221
|
+
controller.assistant.store.update_files_list()
|
|
222
|
+
except Exception:
|
|
223
|
+
pass
|
|
235
224
|
|
|
236
225
|
def setup_menu(self) -> QMenuBar:
|
|
237
226
|
"""
|
|
@@ -246,107 +235,104 @@ class AssistantVectorStore:
|
|
|
246
235
|
self.menu["current"] = self.menu_bar.addMenu(trans("dialog.assistant.store.menu.current"))
|
|
247
236
|
self.menu["all"] = self.menu_bar.addMenu(trans("dialog.assistant.store.menu.all"))
|
|
248
237
|
|
|
249
|
-
# --------------------------------------------
|
|
250
|
-
|
|
251
|
-
# import files (current)
|
|
252
238
|
self.actions["current.import_files"] = QAction(QIcon(":/icons/download.svg"),
|
|
253
|
-
trans("dialog.assistant.store.menu.current.import_files")
|
|
239
|
+
trans("dialog.assistant.store.menu.current.import_files"),
|
|
240
|
+
self.menu_bar)
|
|
254
241
|
self.actions["current.import_files"].triggered.connect(
|
|
255
242
|
lambda: self.window.controller.assistant.batch.import_store_files(
|
|
256
|
-
self.window.controller.assistant.store.current
|
|
243
|
+
self.window.controller.assistant.store.current
|
|
257
244
|
)
|
|
258
245
|
)
|
|
259
246
|
|
|
260
|
-
# refresh (current)
|
|
261
247
|
self.actions["current.refresh_store"] = QAction(QIcon(":/icons/reload.svg"),
|
|
262
|
-
trans("dialog.assistant.store.menu.current.refresh_store")
|
|
248
|
+
trans("dialog.assistant.store.menu.current.refresh_store"),
|
|
249
|
+
self.menu_bar)
|
|
263
250
|
self.actions["current.refresh_store"].triggered.connect(
|
|
264
|
-
|
|
251
|
+
self.window.controller.assistant.store.refresh_status
|
|
265
252
|
)
|
|
266
253
|
|
|
267
|
-
# clear files (current, local)
|
|
268
254
|
self.actions["current.clear_files"] = QAction(QIcon(":/icons/close.svg"),
|
|
269
|
-
trans("dialog.assistant.store.menu.current.clear_files")
|
|
255
|
+
trans("dialog.assistant.store.menu.current.clear_files"),
|
|
256
|
+
self.menu_bar)
|
|
270
257
|
self.actions["current.clear_files"].triggered.connect(
|
|
271
258
|
lambda: self.window.controller.assistant.batch.clear_store_files(
|
|
272
|
-
self.window.controller.assistant.store.current
|
|
259
|
+
self.window.controller.assistant.store.current
|
|
273
260
|
)
|
|
274
261
|
)
|
|
275
262
|
|
|
276
|
-
# truncate files (current, local + remote)
|
|
277
263
|
self.actions["current.truncate_files"] = QAction(QIcon(":/icons/delete.svg"),
|
|
278
|
-
trans("dialog.assistant.store.menu.current.truncate_files")
|
|
264
|
+
trans("dialog.assistant.store.menu.current.truncate_files"),
|
|
265
|
+
self.menu_bar)
|
|
279
266
|
self.actions["current.truncate_files"].triggered.connect(
|
|
280
267
|
lambda: self.window.controller.assistant.batch.truncate_store_files(
|
|
281
|
-
self.window.controller.assistant.store.current
|
|
268
|
+
self.window.controller.assistant.store.current
|
|
282
269
|
)
|
|
283
270
|
)
|
|
284
271
|
|
|
285
|
-
# delete (current, local + remote)
|
|
286
272
|
self.actions["current.delete"] = QAction(QIcon(":/icons/delete.svg"),
|
|
287
|
-
trans("dialog.assistant.store.menu.current.delete")
|
|
273
|
+
trans("dialog.assistant.store.menu.current.delete"),
|
|
274
|
+
self.menu_bar)
|
|
288
275
|
self.actions["current.delete"].triggered.connect(
|
|
289
276
|
lambda: self.window.controller.assistant.store.delete(
|
|
290
|
-
self.window.controller.assistant.store.current
|
|
277
|
+
self.window.controller.assistant.store.current
|
|
291
278
|
)
|
|
292
279
|
)
|
|
293
280
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
self.actions["all.import_all"] = QAction(QIcon(":/icons/download.svg"), trans("dialog.assistant.store.menu.all.import_all"))
|
|
281
|
+
self.actions["all.import_all"] = QAction(QIcon(":/icons/download.svg"),
|
|
282
|
+
trans("dialog.assistant.store.menu.all.import_all"),
|
|
283
|
+
self.menu_bar)
|
|
298
284
|
self.actions["all.import_all"].triggered.connect(
|
|
299
|
-
|
|
285
|
+
self.window.controller.assistant.batch.import_stores
|
|
300
286
|
)
|
|
301
287
|
|
|
302
|
-
# import files (all)
|
|
303
288
|
self.actions["all.import_files"] = QAction(QIcon(":/icons/download.svg"),
|
|
304
|
-
trans("dialog.assistant.store.menu.all.import_files")
|
|
289
|
+
trans("dialog.assistant.store.menu.all.import_files"),
|
|
290
|
+
self.menu_bar)
|
|
305
291
|
self.actions["all.import_files"].triggered.connect(
|
|
306
|
-
|
|
292
|
+
self.window.controller.assistant.batch.import_files
|
|
307
293
|
)
|
|
308
294
|
|
|
309
|
-
# refresh (local)
|
|
310
295
|
self.actions["all.refresh_stores"] = QAction(QIcon(":/icons/reload.svg"),
|
|
311
|
-
trans("dialog.assistant.store.menu.all.refresh_store")
|
|
296
|
+
trans("dialog.assistant.store.menu.all.refresh_store"),
|
|
297
|
+
self.menu_bar)
|
|
312
298
|
self.actions["all.refresh_stores"].triggered.connect(
|
|
313
|
-
|
|
299
|
+
self.window.controller.assistant.batch.refresh_stores
|
|
314
300
|
)
|
|
315
301
|
|
|
316
|
-
# clear stores (all, local)
|
|
317
302
|
self.actions["all.clear_stores"] = QAction(QIcon(":/icons/close.svg"),
|
|
318
|
-
trans("dialog.assistant.store.menu.all.clear_store")
|
|
303
|
+
trans("dialog.assistant.store.menu.all.clear_store"),
|
|
304
|
+
self.menu_bar)
|
|
319
305
|
self.actions["all.clear_stores"].triggered.connect(
|
|
320
|
-
|
|
306
|
+
self.window.controller.assistant.batch.clear_stores
|
|
321
307
|
)
|
|
322
308
|
|
|
323
|
-
# clear files (all, local)
|
|
324
309
|
self.actions["all.clear_files"] = QAction(QIcon(":/icons/close.svg"),
|
|
325
|
-
trans("dialog.assistant.store.menu.all.clear_files")
|
|
310
|
+
trans("dialog.assistant.store.menu.all.clear_files"),
|
|
311
|
+
self.menu_bar)
|
|
326
312
|
self.actions["all.clear_files"].triggered.connect(
|
|
327
|
-
|
|
313
|
+
self.window.controller.assistant.batch.clear_files
|
|
328
314
|
)
|
|
329
315
|
|
|
330
|
-
|
|
331
|
-
|
|
316
|
+
self.actions["all.truncate_stores"] = QAction(QIcon(":/icons/delete.svg"),
|
|
317
|
+
trans("dialog.assistant.store.menu.all.truncate_store"),
|
|
318
|
+
self.menu_bar)
|
|
332
319
|
self.actions["all.truncate_stores"].triggered.connect(
|
|
333
|
-
|
|
320
|
+
self.window.controller.assistant.batch.truncate_stores
|
|
334
321
|
)
|
|
335
322
|
|
|
336
|
-
|
|
337
|
-
|
|
323
|
+
self.actions["all.truncate_files"] = QAction(QIcon(":/icons/delete.svg"),
|
|
324
|
+
trans("dialog.assistant.store.menu.all.truncate_files"),
|
|
325
|
+
self.menu_bar)
|
|
338
326
|
self.actions["all.truncate_files"].triggered.connect(
|
|
339
|
-
|
|
327
|
+
self.window.controller.assistant.batch.truncate_files
|
|
340
328
|
)
|
|
341
329
|
|
|
342
|
-
# current
|
|
343
330
|
self.menu["current"].addAction(self.actions["current.import_files"])
|
|
344
331
|
self.menu["current"].addAction(self.actions["current.refresh_store"])
|
|
345
332
|
self.menu["current"].addAction(self.actions["current.clear_files"])
|
|
346
333
|
self.menu["current"].addAction(self.actions["current.truncate_files"])
|
|
347
334
|
self.menu["current"].addAction(self.actions["current.delete"])
|
|
348
335
|
|
|
349
|
-
# all
|
|
350
336
|
self.menu["all"].addAction(self.actions["all.import_all"])
|
|
351
337
|
self.menu["all"].addAction(self.actions["all.import_files"])
|
|
352
338
|
self.menu["all"].addAction(self.actions["all.refresh_stores"])
|
|
@@ -370,30 +356,29 @@ class AssistantVectorStore:
|
|
|
370
356
|
for key in options:
|
|
371
357
|
option = options[key]
|
|
372
358
|
option['id'] = key
|
|
373
|
-
# create widget by option type
|
|
374
359
|
if option['type'] == 'text' or option['type'] == 'int' or option['type'] == 'float':
|
|
375
360
|
if 'slider' in option and option['slider'] \
|
|
376
361
|
and (option['type'] == 'int' or option['type'] == 'float'):
|
|
377
|
-
widgets[key] = OptionSlider(self.window, parent, key, option)
|
|
362
|
+
widgets[key] = OptionSlider(self.window, parent, key, option)
|
|
378
363
|
else:
|
|
379
364
|
if 'secret' in option and option['secret']:
|
|
380
|
-
widgets[key] = PasswordInput(self.window, parent, key, option)
|
|
365
|
+
widgets[key] = PasswordInput(self.window, parent, key, option)
|
|
381
366
|
else:
|
|
382
|
-
widgets[key] = OptionInput(self.window, parent, key, option)
|
|
367
|
+
widgets[key] = OptionInput(self.window, parent, key, option)
|
|
383
368
|
elif option['type'] == 'textarea':
|
|
384
|
-
widgets[key] = OptionTextarea(self.window, parent, key, option)
|
|
369
|
+
widgets[key] = OptionTextarea(self.window, parent, key, option)
|
|
385
370
|
elif option['type'] == 'bool':
|
|
386
|
-
widgets[key] = OptionCheckbox(self.window, parent, key, option)
|
|
371
|
+
widgets[key] = OptionCheckbox(self.window, parent, key, option)
|
|
387
372
|
elif option['type'] == 'bool_list':
|
|
388
373
|
self.window.controller.config.placeholder.apply(option)
|
|
389
|
-
widgets[key] = OptionCheckboxList(self.window, parent, key, option)
|
|
374
|
+
widgets[key] = OptionCheckboxList(self.window, parent, key, option)
|
|
390
375
|
elif option['type'] == 'dict':
|
|
391
376
|
self.window.controller.config.placeholder.apply(option)
|
|
392
|
-
widgets[key] = OptionDict(self.window, parent, key, option)
|
|
377
|
+
widgets[key] = OptionDict(self.window, parent, key, option)
|
|
393
378
|
widgets[key].setMinimumHeight(200)
|
|
394
379
|
elif option['type'] == 'combo':
|
|
395
380
|
self.window.controller.config.placeholder.apply(option)
|
|
396
|
-
widgets[key] = OptionCombo(self.window, parent, key, option)
|
|
381
|
+
widgets[key] = OptionCombo(self.window, parent, key, option)
|
|
397
382
|
|
|
398
383
|
return widgets
|
|
399
384
|
|
|
@@ -448,10 +433,9 @@ class AssistantVectorStore:
|
|
|
448
433
|
desc = trans(option['description'])
|
|
449
434
|
desc_key = 'model.' + key + '.desc'
|
|
450
435
|
|
|
451
|
-
# 2-columns layout
|
|
452
436
|
if option['type'] not in one_column_types:
|
|
453
437
|
cols = QHBoxLayout()
|
|
454
|
-
cols.addWidget(self.window.ui.nodes[label_key])
|
|
438
|
+
cols.addWidget(self.window.ui.nodes[label_key])
|
|
455
439
|
cols.addWidget(widget)
|
|
456
440
|
|
|
457
441
|
cols_widget = QWidget()
|
|
@@ -461,12 +445,11 @@ class AssistantVectorStore:
|
|
|
461
445
|
layout = QVBoxLayout()
|
|
462
446
|
layout.addWidget(cols_widget)
|
|
463
447
|
else:
|
|
464
|
-
# 1-column layout: textarea and dict fields
|
|
465
448
|
layout = QVBoxLayout()
|
|
466
449
|
if option['type'] != 'bool':
|
|
467
450
|
layout.addWidget(self.window.ui.nodes[label_key])
|
|
468
451
|
else:
|
|
469
|
-
widget.box.setText(label)
|
|
452
|
+
widget.box.setText(label)
|
|
470
453
|
layout.addWidget(widget)
|
|
471
454
|
|
|
472
455
|
if desc:
|
|
@@ -507,23 +490,50 @@ class AssistantVectorStore:
|
|
|
507
490
|
:param id: ID of the list
|
|
508
491
|
:param data: Data to update
|
|
509
492
|
"""
|
|
510
|
-
|
|
493
|
+
models = self.window.ui.models
|
|
494
|
+
if id not in models:
|
|
511
495
|
return
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
496
|
+
model = models[id]
|
|
497
|
+
hide_threads = bool(self.window.core.config.get("assistant.store.hide_threads"))
|
|
498
|
+
suffix = trans("assistant.store.files.suffix")
|
|
499
|
+
|
|
500
|
+
names = []
|
|
501
|
+
for n, store in data.items():
|
|
502
|
+
num_files = store.get_file_count()
|
|
503
|
+
name = store.name
|
|
504
|
+
extras = []
|
|
505
|
+
if not name:
|
|
506
|
+
if hide_threads:
|
|
519
507
|
continue
|
|
520
|
-
name =
|
|
521
|
-
if
|
|
522
|
-
|
|
523
|
-
if
|
|
524
|
-
|
|
525
|
-
if
|
|
526
|
-
name
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
508
|
+
name = store.id
|
|
509
|
+
if num_files > 0:
|
|
510
|
+
extras.append(f"{num_files} {suffix}")
|
|
511
|
+
if store.usage_bytes > 0:
|
|
512
|
+
extras.append(self.window.core.filesystem.sizeof_fmt(store.usage_bytes))
|
|
513
|
+
if extras:
|
|
514
|
+
name = f"{name} ({' - '.join(extras)})"
|
|
515
|
+
names.append(name)
|
|
516
|
+
|
|
517
|
+
model.setRowCount(len(names))
|
|
518
|
+
for i, name in enumerate(names):
|
|
519
|
+
model.setData(model.index(i, 0), name)
|
|
520
|
+
|
|
521
|
+
# ==================== files context menu handler ====================
|
|
522
|
+
def on_files_context_menu(self, pos: QPoint):
|
|
523
|
+
"""
|
|
524
|
+
Context menu for the files list: provides Delete action.
|
|
525
|
+
"""
|
|
526
|
+
view_id = 'assistant.store.files.list'
|
|
527
|
+
if view_id not in self.window.ui.nodes:
|
|
528
|
+
return
|
|
529
|
+
view = self.window.ui.nodes[view_id]
|
|
530
|
+
index = view.indexAt(pos)
|
|
531
|
+
if not index.isValid():
|
|
532
|
+
return
|
|
533
|
+
|
|
534
|
+
row = index.row()
|
|
535
|
+
menu = QMenu(view)
|
|
536
|
+
act_delete = QAction(QIcon(":/icons/delete.svg"), trans("assistant.store.menu.file.delete") if hasattr(self.window, 'tr') else "Delete", view)
|
|
537
|
+
act_delete.triggered.connect(lambda r=row: self.window.controller.assistant.store.delete_file_by_idx(r))
|
|
538
|
+
menu.addAction(act_delete)
|
|
539
|
+
menu.exec(view.mapToGlobal(pos))
|
|
@@ -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.09.03 00:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from functools import partial
|
|
@@ -246,7 +246,7 @@ class Input:
|
|
|
246
246
|
|
|
247
247
|
idx = tabs.currentIndex()
|
|
248
248
|
if idx == 0:
|
|
249
|
-
nodes['input'].setMinimumHeight(self.min_height_input)
|
|
249
|
+
# nodes['input'].setMinimumHeight(self.min_height_input)
|
|
250
250
|
tabs.setMinimumHeight(self.min_height_input_tab)
|
|
251
251
|
sizes = controller_ui.splitter_output_size_input
|
|
252
252
|
if sizes and sizes != [0, 0]:
|
|
@@ -255,5 +255,5 @@ class Input:
|
|
|
255
255
|
sizes = controller_ui.splitter_output_size_files
|
|
256
256
|
if sizes and controller_ui.splitter_output_size_input != [0, 0]:
|
|
257
257
|
splitters['main.output'].setSizes(sizes)
|
|
258
|
-
nodes['input'].setMinimumHeight(self.min_height_files_tab)
|
|
258
|
+
# nodes['input'].setMinimumHeight(self.min_height_files_tab)
|
|
259
259
|
tabs.setMinimumHeight(self.min_height_files_tab + 90)
|