pygpt-net 2.7.4__py3-none-any.whl → 2.7.5__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/app_core.py +4 -2
- pygpt_net/controller/__init__.py +5 -1
- pygpt_net/controller/assistant/assistant.py +1 -4
- pygpt_net/controller/assistant/batch.py +5 -504
- pygpt_net/controller/assistant/editor.py +5 -5
- pygpt_net/controller/assistant/files.py +16 -16
- pygpt_net/controller/chat/handler/google_stream.py +307 -1
- pygpt_net/controller/chat/handler/worker.py +8 -1
- pygpt_net/controller/chat/image.py +2 -2
- pygpt_net/controller/dialogs/confirm.py +73 -101
- pygpt_net/controller/lang/mapping.py +9 -9
- pygpt_net/controller/painter/capture.py +50 -1
- pygpt_net/controller/presets/presets.py +2 -1
- pygpt_net/controller/remote_store/__init__.py +12 -0
- pygpt_net/{provider/core/assistant_file/db_sqlite → controller/remote_store/google}/__init__.py +2 -2
- pygpt_net/controller/remote_store/google/batch.py +402 -0
- pygpt_net/controller/remote_store/google/store.py +615 -0
- pygpt_net/controller/remote_store/openai/__init__.py +12 -0
- pygpt_net/controller/remote_store/openai/batch.py +524 -0
- pygpt_net/controller/{assistant → remote_store/openai}/store.py +63 -60
- pygpt_net/controller/remote_store/remote_store.py +35 -0
- pygpt_net/controller/ui/ui.py +20 -1
- pygpt_net/core/assistants/assistants.py +3 -15
- pygpt_net/core/db/database.py +5 -3
- pygpt_net/core/locale/placeholder.py +35 -0
- pygpt_net/core/remote_store/__init__.py +12 -0
- pygpt_net/core/remote_store/google/__init__.py +11 -0
- pygpt_net/core/remote_store/google/files.py +224 -0
- pygpt_net/core/remote_store/google/store.py +248 -0
- pygpt_net/core/remote_store/openai/__init__.py +11 -0
- pygpt_net/core/{assistants → remote_store/openai}/files.py +26 -19
- pygpt_net/core/{assistants → remote_store/openai}/store.py +32 -15
- pygpt_net/core/remote_store/remote_store.py +24 -0
- pygpt_net/data/config/config.json +8 -4
- pygpt_net/data/config/models.json +77 -3
- pygpt_net/data/config/settings.json +45 -0
- pygpt_net/data/locale/locale.de.ini +41 -41
- pygpt_net/data/locale/locale.en.ini +53 -43
- pygpt_net/data/locale/locale.es.ini +41 -41
- pygpt_net/data/locale/locale.fr.ini +41 -41
- pygpt_net/data/locale/locale.it.ini +41 -41
- pygpt_net/data/locale/locale.pl.ini +42 -42
- pygpt_net/data/locale/locale.uk.ini +41 -41
- pygpt_net/data/locale/locale.zh.ini +41 -41
- pygpt_net/data/locale/plugin.cmd_history.de.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_history.en.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_history.es.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_history.fr.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_history.it.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_history.pl.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_history.uk.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_history.zh.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_mouse_control.en.ini +14 -0
- pygpt_net/data/locale/plugin.cmd_web.de.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_web.en.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_web.es.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_web.fr.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_web.it.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_web.pl.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_web.uk.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_web.zh.ini +1 -1
- pygpt_net/data/locale/plugin.idx_llama_index.de.ini +2 -2
- pygpt_net/data/locale/plugin.idx_llama_index.en.ini +2 -2
- pygpt_net/data/locale/plugin.idx_llama_index.es.ini +2 -2
- pygpt_net/data/locale/plugin.idx_llama_index.fr.ini +2 -2
- pygpt_net/data/locale/plugin.idx_llama_index.it.ini +2 -2
- pygpt_net/data/locale/plugin.idx_llama_index.pl.ini +2 -2
- pygpt_net/data/locale/plugin.idx_llama_index.uk.ini +2 -2
- pygpt_net/data/locale/plugin.idx_llama_index.zh.ini +2 -2
- pygpt_net/item/assistant.py +1 -211
- pygpt_net/item/ctx.py +3 -1
- pygpt_net/item/store.py +238 -0
- pygpt_net/migrations/Version20260102190000.py +35 -0
- pygpt_net/migrations/__init__.py +3 -1
- pygpt_net/plugin/cmd_mouse_control/config.py +470 -1
- pygpt_net/plugin/cmd_mouse_control/plugin.py +488 -22
- pygpt_net/plugin/cmd_mouse_control/worker.py +464 -87
- pygpt_net/plugin/cmd_mouse_control/worker_sandbox.py +729 -0
- pygpt_net/plugin/idx_llama_index/config.py +2 -2
- pygpt_net/provider/api/google/__init__.py +16 -54
- pygpt_net/provider/api/google/chat.py +546 -129
- pygpt_net/provider/api/google/computer.py +190 -0
- pygpt_net/provider/api/google/realtime/realtime.py +2 -2
- pygpt_net/provider/api/google/remote_tools.py +93 -0
- pygpt_net/provider/api/google/store.py +546 -0
- pygpt_net/provider/api/google/worker/__init__.py +0 -0
- pygpt_net/provider/api/google/worker/importer.py +392 -0
- pygpt_net/provider/api/openai/computer.py +10 -1
- pygpt_net/provider/api/openai/store.py +6 -6
- pygpt_net/provider/api/openai/worker/importer.py +24 -24
- pygpt_net/provider/core/config/patch.py +16 -1
- pygpt_net/provider/core/config/patches/patch_before_2_6_42.py +3 -3
- pygpt_net/provider/core/model/patch.py +17 -3
- pygpt_net/provider/core/preset/json_file.py +13 -7
- pygpt_net/provider/core/{assistant_file → remote_file}/__init__.py +1 -1
- pygpt_net/provider/core/{assistant_file → remote_file}/base.py +9 -9
- pygpt_net/provider/core/remote_file/db_sqlite/__init__.py +12 -0
- pygpt_net/provider/core/{assistant_file → remote_file}/db_sqlite/patch.py +1 -1
- pygpt_net/provider/core/{assistant_file → remote_file}/db_sqlite/provider.py +23 -20
- pygpt_net/provider/core/{assistant_file → remote_file}/db_sqlite/storage.py +35 -27
- pygpt_net/provider/core/{assistant_file → remote_file}/db_sqlite/utils.py +5 -4
- pygpt_net/provider/core/{assistant_store → remote_store}/__init__.py +1 -1
- pygpt_net/provider/core/{assistant_store → remote_store}/base.py +10 -10
- pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/__init__.py +1 -1
- pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/patch.py +1 -1
- pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/provider.py +16 -15
- pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/storage.py +30 -23
- pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/utils.py +5 -4
- pygpt_net/provider/core/{assistant_store → remote_store}/json_file.py +9 -9
- pygpt_net/provider/llms/google.py +2 -2
- pygpt_net/ui/base/config_dialog.py +3 -2
- pygpt_net/ui/dialog/assistant.py +3 -3
- pygpt_net/ui/dialog/plugins.py +3 -1
- pygpt_net/ui/dialog/remote_store_google.py +539 -0
- pygpt_net/ui/dialog/{assistant_store.py → remote_store_openai.py} +95 -95
- pygpt_net/ui/dialogs.py +5 -3
- pygpt_net/ui/layout/chat/attachments_uploaded.py +3 -3
- pygpt_net/ui/layout/toolbox/computer_env.py +26 -8
- pygpt_net/ui/menu/tools.py +13 -5
- pygpt_net/ui/widget/dialog/remote_store_google.py +56 -0
- pygpt_net/ui/widget/dialog/{assistant_store.py → remote_store_openai.py} +9 -9
- pygpt_net/ui/widget/element/button.py +4 -4
- pygpt_net/ui/widget/lists/remote_store_google.py +248 -0
- pygpt_net/ui/widget/lists/{assistant_store.py → remote_store_openai.py} +21 -21
- pygpt_net/ui/widget/option/checkbox_list.py +47 -9
- pygpt_net/ui/widget/option/combo.py +39 -3
- {pygpt_net-2.7.4.dist-info → pygpt_net-2.7.5.dist-info}/METADATA +33 -2
- {pygpt_net-2.7.4.dist-info → pygpt_net-2.7.5.dist-info}/RECORD +133 -108
- {pygpt_net-2.7.4.dist-info → pygpt_net-2.7.5.dist-info}/LICENSE +0 -0
- {pygpt_net-2.7.4.dist-info → pygpt_net-2.7.5.dist-info}/WHEEL +0 -0
- {pygpt_net-2.7.4.dist-info → pygpt_net-2.7.5.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# ================================================== #
|
|
4
|
+
# This file is a part of PYGPT package #
|
|
5
|
+
# Website: https://pygpt.net #
|
|
6
|
+
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
|
7
|
+
# MIT License #
|
|
8
|
+
# Created By : Marcin Szczygliński #
|
|
9
|
+
# Updated Date: 2026.01.02 20:00:00 #
|
|
10
|
+
# ================================================== #
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
|
|
14
|
+
from PySide6.QtCore import QObject, Signal, QRunnable, Slot
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Importer(QObject):
|
|
18
|
+
def __init__(self, window=None):
|
|
19
|
+
"""
|
|
20
|
+
Importer core (Google File Search)
|
|
21
|
+
|
|
22
|
+
:param window: Window instance
|
|
23
|
+
"""
|
|
24
|
+
super(Importer, self).__init__()
|
|
25
|
+
self.window = window
|
|
26
|
+
self.worker = None
|
|
27
|
+
|
|
28
|
+
@Slot(str, object)
|
|
29
|
+
def handle_error(self, mode: str, err: any):
|
|
30
|
+
"""
|
|
31
|
+
Handle thread error signal
|
|
32
|
+
|
|
33
|
+
:param mode: mode
|
|
34
|
+
:param err: error message
|
|
35
|
+
"""
|
|
36
|
+
if mode == "import_files":
|
|
37
|
+
self.window.controller.remote_store.google.batch.handle_imported_files_failed(err)
|
|
38
|
+
elif mode == "truncate_files":
|
|
39
|
+
self.window.controller.remote_store.google.batch.handle_truncated_files_failed(err)
|
|
40
|
+
elif mode == "upload_files":
|
|
41
|
+
self.window.controller.remote_store.google.batch.handle_uploaded_files_failed(err)
|
|
42
|
+
elif mode in "vector_stores":
|
|
43
|
+
self.window.controller.remote_store.google.batch.handle_imported_stores_failed(err)
|
|
44
|
+
elif mode in "truncate_vector_stores":
|
|
45
|
+
self.window.controller.remote_store.google.batch.handle_truncated_stores_failed(err)
|
|
46
|
+
elif mode in "refresh_vector_stores":
|
|
47
|
+
self.window.controller.remote_store.google.batch.handle_refreshed_stores_failed(err)
|
|
48
|
+
|
|
49
|
+
@Slot(str, str, int)
|
|
50
|
+
def handle_finished(self, mode: str, store_id: str = None, num: int = 0):
|
|
51
|
+
"""
|
|
52
|
+
Handle thread finished signal
|
|
53
|
+
|
|
54
|
+
:param mode: mode
|
|
55
|
+
:param store_id: store ID
|
|
56
|
+
:param num: number of affected items
|
|
57
|
+
"""
|
|
58
|
+
if mode == "import_files":
|
|
59
|
+
self.window.controller.remote_store.google.batch.handle_imported_files(num)
|
|
60
|
+
elif mode == "truncate_files":
|
|
61
|
+
self.window.controller.remote_store.google.batch.handle_truncated_files(store_id, num)
|
|
62
|
+
elif mode == "upload_files":
|
|
63
|
+
self.window.controller.remote_store.google.batch.handle_uploaded_files(num)
|
|
64
|
+
elif mode == "vector_stores":
|
|
65
|
+
self.window.controller.remote_store.google.batch.handle_imported_stores(num)
|
|
66
|
+
elif mode == "truncate_vector_stores":
|
|
67
|
+
self.window.controller.remote_store.google.batch.handle_truncated_stores(num)
|
|
68
|
+
elif mode == "refresh_vector_stores":
|
|
69
|
+
self.window.controller.remote_store.google.batch.handle_refreshed_stores(num)
|
|
70
|
+
|
|
71
|
+
@Slot(str, str)
|
|
72
|
+
def handle_status(self, mode: str, msg: str):
|
|
73
|
+
"""
|
|
74
|
+
Handle thread status change signal
|
|
75
|
+
|
|
76
|
+
:param mode: mode
|
|
77
|
+
:param msg: message
|
|
78
|
+
"""
|
|
79
|
+
self.window.controller.assistant.batch.handle_status_change(mode, msg)
|
|
80
|
+
|
|
81
|
+
@Slot(str, str)
|
|
82
|
+
def handle_log(self, mode: str, msg: str):
|
|
83
|
+
"""
|
|
84
|
+
Handle thread log message signal
|
|
85
|
+
|
|
86
|
+
:param mode: mode
|
|
87
|
+
:param msg: message
|
|
88
|
+
"""
|
|
89
|
+
self.window.controller.assistant.threads.log(mode + ": " + msg)
|
|
90
|
+
|
|
91
|
+
def import_assistants(self):
|
|
92
|
+
"""Import assistants (kept for parity; no-op for Google if unused)"""
|
|
93
|
+
self.worker = ImportWorker()
|
|
94
|
+
self.worker.window = self.window
|
|
95
|
+
self.worker.mode = "assistants"
|
|
96
|
+
self.connect_signals(self.worker)
|
|
97
|
+
self.window.threadpool.start(self.worker)
|
|
98
|
+
|
|
99
|
+
def import_vector_stores(self):
|
|
100
|
+
"""Import File Search stores"""
|
|
101
|
+
self.worker = ImportWorker()
|
|
102
|
+
self.worker.window = self.window
|
|
103
|
+
self.worker.mode = "vector_stores"
|
|
104
|
+
self.connect_signals(self.worker)
|
|
105
|
+
self.window.threadpool.start(self.worker)
|
|
106
|
+
|
|
107
|
+
def truncate_vector_stores(self):
|
|
108
|
+
"""Truncate File Search stores"""
|
|
109
|
+
self.worker = ImportWorker()
|
|
110
|
+
self.worker.window = self.window
|
|
111
|
+
self.worker.mode = "truncate_vector_stores"
|
|
112
|
+
self.connect_signals(self.worker)
|
|
113
|
+
self.window.threadpool.start(self.worker)
|
|
114
|
+
|
|
115
|
+
def truncate_files(self, store_id: str = None):
|
|
116
|
+
"""
|
|
117
|
+
Truncate documents
|
|
118
|
+
|
|
119
|
+
:param store_id: store name ('fileSearchStores/...').
|
|
120
|
+
"""
|
|
121
|
+
self.worker = ImportWorker()
|
|
122
|
+
self.worker.window = self.window
|
|
123
|
+
self.worker.mode = "truncate_files"
|
|
124
|
+
self.worker.store_id = store_id
|
|
125
|
+
self.connect_signals(self.worker)
|
|
126
|
+
self.window.threadpool.start(self.worker)
|
|
127
|
+
|
|
128
|
+
def upload_files(self, store_id: str, files: list = None):
|
|
129
|
+
"""
|
|
130
|
+
Upload files
|
|
131
|
+
|
|
132
|
+
:param store_id: store name ('fileSearchStores/...').
|
|
133
|
+
:param files: list of file paths
|
|
134
|
+
"""
|
|
135
|
+
print("Uploading files: {}".format(files))
|
|
136
|
+
print("Store ID: {}".format(store_id))
|
|
137
|
+
self.worker = ImportWorker()
|
|
138
|
+
self.worker.window = self.window
|
|
139
|
+
self.worker.mode = "upload_files"
|
|
140
|
+
self.worker.store_id = store_id
|
|
141
|
+
self.worker.files = files or []
|
|
142
|
+
self.connect_signals(self.worker)
|
|
143
|
+
self.window.threadpool.start(self.worker)
|
|
144
|
+
|
|
145
|
+
def refresh_vector_stores(self):
|
|
146
|
+
"""Refresh File Search stores"""
|
|
147
|
+
self.worker = ImportWorker()
|
|
148
|
+
self.worker.window = self.window
|
|
149
|
+
self.worker.mode = "refresh_vector_stores"
|
|
150
|
+
self.connect_signals(self.worker)
|
|
151
|
+
self.window.threadpool.start(self.worker)
|
|
152
|
+
|
|
153
|
+
def import_files(self, store_id: str = None):
|
|
154
|
+
"""
|
|
155
|
+
Import File Search documents
|
|
156
|
+
|
|
157
|
+
:param store_id: store name ('fileSearchStores/...').
|
|
158
|
+
"""
|
|
159
|
+
self.worker = ImportWorker()
|
|
160
|
+
self.worker.window = self.window
|
|
161
|
+
self.worker.mode = "import_files"
|
|
162
|
+
self.worker.store_id = store_id
|
|
163
|
+
self.connect_signals(self.worker)
|
|
164
|
+
self.window.threadpool.start(self.worker)
|
|
165
|
+
|
|
166
|
+
def connect_signals(self, worker):
|
|
167
|
+
"""
|
|
168
|
+
Connect signals
|
|
169
|
+
|
|
170
|
+
:param worker: worker instance
|
|
171
|
+
"""
|
|
172
|
+
worker.signals.finished.connect(self.handle_finished)
|
|
173
|
+
worker.signals.error.connect(self.handle_error)
|
|
174
|
+
worker.signals.status.connect(self.handle_status)
|
|
175
|
+
worker.signals.log.connect(self.handle_log)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class ImportWorkerSignals(QObject):
|
|
179
|
+
"""Import worker signals"""
|
|
180
|
+
status = Signal(str, str) # mode, message
|
|
181
|
+
finished = Signal(str, str, int) # mode, store_id, num
|
|
182
|
+
error = Signal(str, object) # mode, error
|
|
183
|
+
log = Signal(str, str) # mode, message
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class ImportWorker(QRunnable):
|
|
187
|
+
"""Import worker (Google)"""
|
|
188
|
+
def __init__(self, *args, **kwargs):
|
|
189
|
+
super().__init__()
|
|
190
|
+
self.signals = ImportWorkerSignals()
|
|
191
|
+
self.window = None
|
|
192
|
+
self.mode = "assistants"
|
|
193
|
+
self.assistant = None
|
|
194
|
+
self.store_id = None
|
|
195
|
+
self.files = []
|
|
196
|
+
|
|
197
|
+
@Slot()
|
|
198
|
+
def run(self):
|
|
199
|
+
"""Importer thread"""
|
|
200
|
+
try:
|
|
201
|
+
if self.mode == "vector_stores":
|
|
202
|
+
if self.import_vector_stores():
|
|
203
|
+
self.import_files()
|
|
204
|
+
elif self.mode == "truncate_vector_stores":
|
|
205
|
+
self.truncate_vector_stores()
|
|
206
|
+
elif self.mode == "refresh_vector_stores":
|
|
207
|
+
self.refresh_vector_stores()
|
|
208
|
+
elif self.mode == "truncate_files":
|
|
209
|
+
self.truncate_files()
|
|
210
|
+
elif self.mode == "import_files":
|
|
211
|
+
self.import_files()
|
|
212
|
+
elif self.mode == "upload_files":
|
|
213
|
+
self.upload_files()
|
|
214
|
+
except Exception as e:
|
|
215
|
+
self.signals.error.emit(self.mode, e)
|
|
216
|
+
finally:
|
|
217
|
+
self.cleanup()
|
|
218
|
+
|
|
219
|
+
def import_assistants(self, silent: bool = False) -> bool:
|
|
220
|
+
"""
|
|
221
|
+
Import assistants (not used for Google by default; kept for parity)
|
|
222
|
+
|
|
223
|
+
:param silent: silent mode
|
|
224
|
+
"""
|
|
225
|
+
try:
|
|
226
|
+
if not silent:
|
|
227
|
+
self.signals.finished.emit("assistants", self.store_id, 0)
|
|
228
|
+
return True
|
|
229
|
+
except Exception as e:
|
|
230
|
+
self.signals.error.emit("assistants", e)
|
|
231
|
+
return False
|
|
232
|
+
|
|
233
|
+
def import_vector_stores(self, silent: bool = False) -> bool:
|
|
234
|
+
"""
|
|
235
|
+
Import File Search stores
|
|
236
|
+
|
|
237
|
+
:param silent: silent mode (no signals emit)
|
|
238
|
+
"""
|
|
239
|
+
try:
|
|
240
|
+
self.log("Importing File Search stores...")
|
|
241
|
+
self.window.core.remote_store.google.clear()
|
|
242
|
+
items = {}
|
|
243
|
+
self.window.core.api.google.store.import_stores(items, callback=self.callback)
|
|
244
|
+
self.window.core.remote_store.google.import_items(items)
|
|
245
|
+
if not silent:
|
|
246
|
+
self.signals.finished.emit("vector_stores", self.store_id, len(items))
|
|
247
|
+
return True
|
|
248
|
+
except Exception as e:
|
|
249
|
+
self.log("API error: {}".format(e))
|
|
250
|
+
self.signals.error.emit("vector_stores", e)
|
|
251
|
+
return False
|
|
252
|
+
|
|
253
|
+
def truncate_vector_stores(self, silent: bool = False) -> bool:
|
|
254
|
+
"""
|
|
255
|
+
Truncate all File Search stores in API
|
|
256
|
+
|
|
257
|
+
:param silent: silent mode
|
|
258
|
+
"""
|
|
259
|
+
try:
|
|
260
|
+
self.log("Truncating stores...")
|
|
261
|
+
num = self.window.core.api.google.store.remove_all(callback=self.callback)
|
|
262
|
+
self.window.core.remote_store.google.items = {}
|
|
263
|
+
self.window.core.remote_store.google.save()
|
|
264
|
+
if not silent:
|
|
265
|
+
self.signals.finished.emit("truncate_vector_stores", self.store_id, num)
|
|
266
|
+
return True
|
|
267
|
+
except Exception as e:
|
|
268
|
+
self.log("API error: {}".format(e))
|
|
269
|
+
self.signals.error.emit("truncate_vector_stores", e)
|
|
270
|
+
return False
|
|
271
|
+
|
|
272
|
+
def refresh_vector_stores(self, silent: bool = False) -> bool:
|
|
273
|
+
"""
|
|
274
|
+
Refresh all File Search stores in API
|
|
275
|
+
|
|
276
|
+
:param silent: silent mode
|
|
277
|
+
"""
|
|
278
|
+
try:
|
|
279
|
+
self.log("Refreshing stores...")
|
|
280
|
+
num = 0
|
|
281
|
+
stores = self.window.core.remote_store.google.items
|
|
282
|
+
for id in stores:
|
|
283
|
+
store = stores[id]
|
|
284
|
+
try:
|
|
285
|
+
self.window.controller.remote_store.google.refresh_store(store, update=False)
|
|
286
|
+
num += 1
|
|
287
|
+
except Exception as e:
|
|
288
|
+
self.log("Failed to refresh store: {}".format(id))
|
|
289
|
+
self.window.core.debug.log(e)
|
|
290
|
+
if not silent:
|
|
291
|
+
self.signals.finished.emit("refresh_vector_stores", self.store_id, num)
|
|
292
|
+
return True
|
|
293
|
+
except Exception as e:
|
|
294
|
+
self.log("API error: {}".format(e))
|
|
295
|
+
self.signals.error.emit("refresh_vector_stores", e)
|
|
296
|
+
return False
|
|
297
|
+
|
|
298
|
+
def truncate_files(self, silent: bool = False) -> bool:
|
|
299
|
+
"""
|
|
300
|
+
Truncate documents in API
|
|
301
|
+
|
|
302
|
+
:param silent: silent mode
|
|
303
|
+
"""
|
|
304
|
+
try:
|
|
305
|
+
if self.store_id is None:
|
|
306
|
+
self.log("Truncating all documents in all stores...")
|
|
307
|
+
self.window.core.remote_store.google.files.truncate() # clear all locally and remote
|
|
308
|
+
num = self.window.core.api.google.store.remove_from_stores()
|
|
309
|
+
else:
|
|
310
|
+
self.log("Truncating documents for store: {}".format(self.store_id))
|
|
311
|
+
self.window.core.remote_store.google.files.truncate(self.store_id)
|
|
312
|
+
num = self.window.core.api.google.store.remove_from_store(self.store_id)
|
|
313
|
+
if not silent:
|
|
314
|
+
self.signals.finished.emit("truncate_files", self.store_id, num)
|
|
315
|
+
return True
|
|
316
|
+
except Exception as e:
|
|
317
|
+
self.log("API error: {}".format(e))
|
|
318
|
+
self.signals.error.emit("truncate_files", e)
|
|
319
|
+
return False
|
|
320
|
+
|
|
321
|
+
def upload_files(self, silent: bool = False) -> bool:
|
|
322
|
+
"""
|
|
323
|
+
Upload files directly to a File Search store (creates Documents)
|
|
324
|
+
|
|
325
|
+
:param silent: silent mode
|
|
326
|
+
"""
|
|
327
|
+
num = 0
|
|
328
|
+
try:
|
|
329
|
+
self.log("Uploading files to File Search store...")
|
|
330
|
+
for file in self.files:
|
|
331
|
+
try:
|
|
332
|
+
doc = self.window.core.api.google.store.upload_to_store(self.store_id, file)
|
|
333
|
+
if doc is not None:
|
|
334
|
+
self.window.core.remote_store.google.files.insert(self.store_id, doc)
|
|
335
|
+
msg = "Uploaded file: {}/{}".format((num + 1), len(self.files))
|
|
336
|
+
self.signals.status.emit("upload_files", msg)
|
|
337
|
+
self.log(msg)
|
|
338
|
+
num += 1
|
|
339
|
+
else:
|
|
340
|
+
self.signals.status.emit("upload_files", "Failed to upload file: {}".format(os.path.basename(file)))
|
|
341
|
+
except Exception as e:
|
|
342
|
+
self.window.core.debug.log(e)
|
|
343
|
+
self.signals.status.emit("upload_files", "Failed to upload file: {}".format(os.path.basename(file)))
|
|
344
|
+
if not silent:
|
|
345
|
+
self.signals.finished.emit("upload_files", self.store_id, num)
|
|
346
|
+
return True
|
|
347
|
+
except Exception as e:
|
|
348
|
+
self.log("API error: {}".format(e))
|
|
349
|
+
self.signals.error.emit("upload_files", e)
|
|
350
|
+
return False
|
|
351
|
+
|
|
352
|
+
def import_files(self, silent: bool = False) -> bool:
|
|
353
|
+
"""
|
|
354
|
+
Import documents from API
|
|
355
|
+
|
|
356
|
+
:param silent: silent mode
|
|
357
|
+
"""
|
|
358
|
+
try:
|
|
359
|
+
if self.store_id is None:
|
|
360
|
+
self.log("Importing all documents...")
|
|
361
|
+
self.window.core.remote_store.google.files.truncate_local() # clear local DB (all)
|
|
362
|
+
num = self.window.core.api.google.store.import_stores_files(self.callback) # import all
|
|
363
|
+
else:
|
|
364
|
+
self.log("Importing documents for store: {}".format(self.store_id))
|
|
365
|
+
self.window.core.remote_store.google.files.truncate_local(self.store_id)
|
|
366
|
+
items = self.window.core.api.google.store.import_store_files(self.store_id, [], callback=self.callback)
|
|
367
|
+
num = len(items)
|
|
368
|
+
if not silent:
|
|
369
|
+
self.signals.finished.emit("import_files", self.store_id, num)
|
|
370
|
+
return True
|
|
371
|
+
except Exception as e:
|
|
372
|
+
self.log("API error: {}".format(e))
|
|
373
|
+
self.signals.error.emit("import_files", e)
|
|
374
|
+
return False
|
|
375
|
+
|
|
376
|
+
def callback(self, msg: str):
|
|
377
|
+
"""Log callback"""
|
|
378
|
+
self.log(msg)
|
|
379
|
+
|
|
380
|
+
def log(self, msg: str):
|
|
381
|
+
"""Log message"""
|
|
382
|
+
self.signals.log.emit(self.mode, msg)
|
|
383
|
+
|
|
384
|
+
def cleanup(self):
|
|
385
|
+
"""Cleanup resources after worker execution."""
|
|
386
|
+
sig = self.signals
|
|
387
|
+
self.signals = None
|
|
388
|
+
if sig is not None:
|
|
389
|
+
try:
|
|
390
|
+
sig.deleteLater()
|
|
391
|
+
except RuntimeError:
|
|
392
|
+
pass
|
|
@@ -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: 2026.01.02 02:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import json
|
|
@@ -39,11 +39,20 @@ class Computer:
|
|
|
39
39
|
Get Computer use tool
|
|
40
40
|
:return: dict
|
|
41
41
|
"""
|
|
42
|
+
is_sandbox = bool(self.window.core.config.get("remote_tools.computer_use.sandbox", False))
|
|
42
43
|
env = self.get_current_env()
|
|
43
44
|
screen = self.window.app.primaryScreen()
|
|
44
45
|
size = screen.size()
|
|
45
46
|
screen_x = size.width()
|
|
46
47
|
screen_y = size.height()
|
|
48
|
+
|
|
49
|
+
# if sandbox, get resolution from plugin settings (Playwright viewport)
|
|
50
|
+
if is_sandbox:
|
|
51
|
+
try:
|
|
52
|
+
screen_x = int(self.window.core.plugins.get_option("cmd_mouse_control", "sandbox_viewport_w"))
|
|
53
|
+
screen_y = int(self.window.core.plugins.get_option("cmd_mouse_control", "sandbox_viewport_h"))
|
|
54
|
+
except Exception:
|
|
55
|
+
pass
|
|
47
56
|
return {
|
|
48
57
|
"type": "computer_use_preview",
|
|
49
58
|
"display_width": screen_x,
|
|
@@ -6,13 +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:
|
|
9
|
+
# Updated Date: 2026.01.02 20:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
13
13
|
from typing import Optional, List
|
|
14
14
|
|
|
15
|
-
from pygpt_net.item.
|
|
15
|
+
from pygpt_net.item.store import RemoteStoreItem
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class Store:
|
|
@@ -273,7 +273,7 @@ class Store:
|
|
|
273
273
|
for remote in stores.data:
|
|
274
274
|
id = remote.id
|
|
275
275
|
if id not in items:
|
|
276
|
-
items[id] =
|
|
276
|
+
items[id] = RemoteStoreItem()
|
|
277
277
|
tmp_name = remote.name
|
|
278
278
|
if tmp_name is None:
|
|
279
279
|
items[id].is_thread = True # tmp store for thread
|
|
@@ -281,8 +281,8 @@ class Store:
|
|
|
281
281
|
items[id].id = id
|
|
282
282
|
items[id].name = tmp_name
|
|
283
283
|
items[id].file_ids = []
|
|
284
|
-
items[id].status = self.window.core.
|
|
285
|
-
self.window.core.
|
|
284
|
+
items[id].status = self.window.core.remote_store.openai.parse_status(remote)
|
|
285
|
+
self.window.core.remote_store.openai.append_status(items[id], items[id].status)
|
|
286
286
|
self.log("Imported vector store: " + id, callback)
|
|
287
287
|
# next page
|
|
288
288
|
if stores.has_more:
|
|
@@ -633,7 +633,7 @@ class Store:
|
|
|
633
633
|
if id not in items:
|
|
634
634
|
items.append(id)
|
|
635
635
|
data = self.get_file(remote.id)
|
|
636
|
-
self.window.core.
|
|
636
|
+
self.window.core.remote_store.openai.files.insert(store_id, data) # add remote file to DB
|
|
637
637
|
msg = "Imported file ID {} to store {}".format(remote.id, store_id)
|
|
638
638
|
self.log(msg, callback)
|
|
639
639
|
except Exception as e:
|
|
@@ -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: 2026.01.02 19:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -36,17 +36,17 @@ class Importer(QObject):
|
|
|
36
36
|
if mode == "assistants":
|
|
37
37
|
self.window.controller.assistant.batch.handle_imported_assistants_failed(err)
|
|
38
38
|
elif mode == "import_files":
|
|
39
|
-
self.window.controller.
|
|
39
|
+
self.window.controller.remote_store.openai.batch.handle_imported_files_failed(err)
|
|
40
40
|
elif mode == "truncate_files":
|
|
41
|
-
self.window.controller.
|
|
41
|
+
self.window.controller.remote_store.openai.batch.handle_truncated_files_failed(err)
|
|
42
42
|
elif mode == "upload_files":
|
|
43
|
-
self.window.controller.
|
|
43
|
+
self.window.controller.remote_store.openai.batch.handle_uploaded_files_failed(err)
|
|
44
44
|
elif mode in "vector_stores":
|
|
45
|
-
self.window.controller.
|
|
45
|
+
self.window.controller.remote_store.openai.batch.handle_imported_stores_failed(err)
|
|
46
46
|
elif mode in "truncate_vector_stores":
|
|
47
|
-
self.window.controller.
|
|
47
|
+
self.window.controller.remote_store.openai.batch.handle_truncated_stores_failed(err)
|
|
48
48
|
elif mode in "refresh_vector_stores":
|
|
49
|
-
self.window.controller.
|
|
49
|
+
self.window.controller.remote_store.openai.batch.handle_refreshed_stores_failed(err)
|
|
50
50
|
|
|
51
51
|
@Slot(str, str, int)
|
|
52
52
|
def handle_finished(self, mode: str, store_id: str = None, num: int = 0):
|
|
@@ -60,17 +60,17 @@ class Importer(QObject):
|
|
|
60
60
|
if mode == "assistants":
|
|
61
61
|
self.window.controller.assistant.batch.handle_imported_assistants(num)
|
|
62
62
|
elif mode == "import_files":
|
|
63
|
-
self.window.controller.
|
|
63
|
+
self.window.controller.remote_store.openai.batch.handle_imported_files(num)
|
|
64
64
|
elif mode == "truncate_files":
|
|
65
|
-
self.window.controller.
|
|
65
|
+
self.window.controller.remote_store.openai.batch.handle_truncated_files(store_id, num)
|
|
66
66
|
elif mode == "upload_files":
|
|
67
|
-
self.window.controller.
|
|
67
|
+
self.window.controller.remote_store.openai.batch.handle_uploaded_files(num)
|
|
68
68
|
elif mode == "vector_stores":
|
|
69
|
-
self.window.controller.
|
|
69
|
+
self.window.controller.remote_store.openai.batch.handle_imported_stores(num)
|
|
70
70
|
elif mode == "truncate_vector_stores":
|
|
71
|
-
self.window.controller.
|
|
71
|
+
self.window.controller.remote_store.openai.batch.handle_truncated_stores(num)
|
|
72
72
|
elif mode == "refresh_vector_stores":
|
|
73
|
-
self.window.controller.
|
|
73
|
+
self.window.controller.remote_store.openai.batch.handle_refreshed_stores(num)
|
|
74
74
|
|
|
75
75
|
@Slot(str, str)
|
|
76
76
|
def handle_status(self, mode: str, msg: str):
|
|
@@ -264,10 +264,10 @@ class ImportWorker(QRunnable):
|
|
|
264
264
|
"""
|
|
265
265
|
try:
|
|
266
266
|
self.log("Importing vector stores...")
|
|
267
|
-
self.window.core.
|
|
267
|
+
self.window.core.remote_store.openai.clear()
|
|
268
268
|
items = {}
|
|
269
269
|
self.window.core.api.openai.store.import_stores(items, callback=self.callback)
|
|
270
|
-
self.window.core.
|
|
270
|
+
self.window.core.remote_store.openai.import_items(items)
|
|
271
271
|
if not silent:
|
|
272
272
|
self.signals.finished.emit("vector_stores", self.store_id, len(items))
|
|
273
273
|
return True
|
|
@@ -286,8 +286,8 @@ class ImportWorker(QRunnable):
|
|
|
286
286
|
try:
|
|
287
287
|
self.log("Truncating stores...")
|
|
288
288
|
num = self.window.core.api.openai.store.remove_all(callback=self.callback)
|
|
289
|
-
self.window.core.
|
|
290
|
-
self.window.core.
|
|
289
|
+
self.window.core.remote_store.openai.items = {}
|
|
290
|
+
self.window.core.remote_store.openai.save()
|
|
291
291
|
if not silent:
|
|
292
292
|
self.signals.finished.emit("truncate_vector_stores", self.store_id, num)
|
|
293
293
|
return True
|
|
@@ -306,11 +306,11 @@ class ImportWorker(QRunnable):
|
|
|
306
306
|
try:
|
|
307
307
|
self.log("Refreshing stores...")
|
|
308
308
|
num = 0
|
|
309
|
-
stores = self.window.core.
|
|
309
|
+
stores = self.window.core.remote_store.openai.items
|
|
310
310
|
for id in stores:
|
|
311
311
|
store = stores[id]
|
|
312
312
|
try:
|
|
313
|
-
self.window.controller.
|
|
313
|
+
self.window.controller.remote_store.openai.refresh_store(store, update=False)
|
|
314
314
|
num += 1
|
|
315
315
|
except Exception as e:
|
|
316
316
|
self.log("Failed to refresh store: {}".format(id))
|
|
@@ -334,12 +334,12 @@ class ImportWorker(QRunnable):
|
|
|
334
334
|
# if empty store_id, truncate all files, otherwise truncate only store files
|
|
335
335
|
if self.store_id is None:
|
|
336
336
|
self.log("Truncating all files...")
|
|
337
|
-
self.window.core.
|
|
337
|
+
self.window.core.remote_store.openai.files.truncate() # clear all files
|
|
338
338
|
# remove all files in API
|
|
339
339
|
num = self.window.core.api.openai.store.remove_files(callback=self.callback)
|
|
340
340
|
else:
|
|
341
341
|
self.log("Truncating files for store: {}".format(self.store_id))
|
|
342
|
-
self.window.core.
|
|
342
|
+
self.window.core.remote_store.openai.files.truncate(self.store_id) # clear store files, remove from stores / DB
|
|
343
343
|
# remove store files in API
|
|
344
344
|
num = self.window.core.api.openai.store.remove_store_files(
|
|
345
345
|
self.store_id,
|
|
@@ -373,7 +373,7 @@ class ImportWorker(QRunnable):
|
|
|
373
373
|
)
|
|
374
374
|
if stored_file is not None:
|
|
375
375
|
data = self.window.core.api.openai.store.get_file(file_id)
|
|
376
|
-
self.window.core.
|
|
376
|
+
self.window.core.remote_store.openai.files.insert(self.store_id, data) # insert to DB
|
|
377
377
|
msg = "Uploaded file: {}/{}".format((num + 1), len(self.files))
|
|
378
378
|
self.signals.status.emit("upload_files", msg)
|
|
379
379
|
self.log(msg)
|
|
@@ -402,11 +402,11 @@ class ImportWorker(QRunnable):
|
|
|
402
402
|
try:
|
|
403
403
|
if self.store_id is None:
|
|
404
404
|
self.log("Importing all files...")
|
|
405
|
-
self.window.core.
|
|
405
|
+
self.window.core.remote_store.openai.files.truncate_local() # clear local DB (all)
|
|
406
406
|
num = self.window.core.api.openai.store.import_stores_files(self.callback) # import all files
|
|
407
407
|
else:
|
|
408
408
|
self.log("Importing files for store: {}".format(self.store_id))
|
|
409
|
-
self.window.core.
|
|
409
|
+
self.window.core.remote_store.openai.files.truncate_local(self.store_id) # clear local DB (all)
|
|
410
410
|
items = self.window.core.api.openai.store.import_store_files(
|
|
411
411
|
self.store_id,
|
|
412
412
|
[],
|
|
@@ -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: 2026.01.02 02:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import copy
|
|
@@ -223,6 +223,21 @@ class Patch:
|
|
|
223
223
|
patch_css('web-blocks.css', True)
|
|
224
224
|
updated = True
|
|
225
225
|
|
|
226
|
+
# < 2.7.5
|
|
227
|
+
if old < parse_version("2.7.5"):
|
|
228
|
+
print("Migrating config from < 2.7.5...")
|
|
229
|
+
if "remote_tools.computer_use.sandbox" not in data:
|
|
230
|
+
data["remote_tools.computer_use.sandbox"] = False
|
|
231
|
+
if "remote_tools.google.file_search" not in data:
|
|
232
|
+
data["remote_tools.google.file_search"] = False
|
|
233
|
+
if "remote_tools.google.file_search.args" not in data:
|
|
234
|
+
data["remote_tools.google.file_search.args"] = ""
|
|
235
|
+
if "remote_tools.google.maps" not in data:
|
|
236
|
+
data["remote_tools.google.maps"] = False
|
|
237
|
+
if "remote_store.openai.hide_threads" not in data:
|
|
238
|
+
data["remote_store.openai.hide_threads"] = True
|
|
239
|
+
updated = True
|
|
240
|
+
|
|
226
241
|
# update file
|
|
227
242
|
migrated = False
|
|
228
243
|
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:
|
|
9
|
+
# Updated Date: 2026.01.02 20:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import copy
|
|
@@ -1404,8 +1404,8 @@ class Patch:
|
|
|
1404
1404
|
# < 2.1.79
|
|
1405
1405
|
if old < parse_version("2.1.79"):
|
|
1406
1406
|
print("Migrating config from < 2.1.79...")
|
|
1407
|
-
if '
|
|
1408
|
-
data["
|
|
1407
|
+
if 'remote_store.openai.hide_threads' not in data:
|
|
1408
|
+
data["remote_store.openai.hide_threads"] = True
|
|
1409
1409
|
updated = True
|
|
1410
1410
|
|
|
1411
1411
|
# < 2.2.2
|