pygpt-net 2.7.7__py3-none-any.whl → 2.7.9__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/app.py +5 -1
- pygpt_net/controller/assistant/batch.py +2 -2
- pygpt_net/controller/assistant/files.py +7 -6
- pygpt_net/controller/assistant/threads.py +0 -0
- pygpt_net/controller/chat/command.py +0 -0
- pygpt_net/controller/dialogs/confirm.py +35 -58
- pygpt_net/controller/lang/mapping.py +9 -9
- pygpt_net/controller/realtime/realtime.py +13 -1
- pygpt_net/controller/remote_store/{google/batch.py → batch.py} +209 -252
- pygpt_net/controller/remote_store/remote_store.py +982 -13
- pygpt_net/core/command/command.py +0 -0
- pygpt_net/core/db/viewer.py +1 -1
- pygpt_net/core/realtime/worker.py +3 -1
- pygpt_net/{controller/remote_store/google → core/remote_store/anthropic}/__init__.py +0 -1
- pygpt_net/core/remote_store/anthropic/files.py +211 -0
- pygpt_net/core/remote_store/anthropic/store.py +208 -0
- pygpt_net/core/remote_store/openai/store.py +5 -4
- pygpt_net/core/remote_store/remote_store.py +5 -1
- pygpt_net/{controller/remote_store/openai → core/remote_store/xai}/__init__.py +0 -1
- pygpt_net/core/remote_store/xai/files.py +225 -0
- pygpt_net/core/remote_store/xai/store.py +219 -0
- pygpt_net/data/config/config.json +10 -6
- pygpt_net/data/config/models.json +38 -22
- pygpt_net/data/config/settings.json +54 -1
- pygpt_net/data/icons/folder_eye.svg +1 -0
- pygpt_net/data/icons/folder_eye_filled.svg +1 -0
- pygpt_net/data/icons/folder_open.svg +1 -0
- pygpt_net/data/icons/folder_open_filled.svg +1 -0
- pygpt_net/data/locale/locale.de.ini +4 -3
- pygpt_net/data/locale/locale.en.ini +14 -4
- pygpt_net/data/locale/locale.es.ini +4 -3
- pygpt_net/data/locale/locale.fr.ini +4 -3
- pygpt_net/data/locale/locale.it.ini +4 -3
- pygpt_net/data/locale/locale.pl.ini +5 -4
- pygpt_net/data/locale/locale.uk.ini +4 -3
- pygpt_net/data/locale/locale.zh.ini +4 -3
- pygpt_net/icons.qrc +4 -0
- pygpt_net/icons_rc.py +282 -138
- pygpt_net/provider/api/anthropic/__init__.py +2 -0
- pygpt_net/provider/api/anthropic/chat.py +84 -1
- pygpt_net/provider/api/anthropic/store.py +307 -0
- pygpt_net/provider/api/anthropic/stream.py +75 -0
- pygpt_net/provider/api/anthropic/worker/__init__.py +0 -0
- pygpt_net/provider/api/anthropic/worker/importer.py +278 -0
- pygpt_net/provider/api/google/chat.py +59 -2
- pygpt_net/provider/api/google/realtime/client.py +70 -24
- pygpt_net/provider/api/google/realtime/realtime.py +48 -12
- pygpt_net/provider/api/google/store.py +124 -3
- pygpt_net/provider/api/google/stream.py +91 -24
- pygpt_net/provider/api/google/worker/importer.py +16 -28
- pygpt_net/provider/api/openai/assistants.py +2 -2
- pygpt_net/provider/api/openai/realtime/realtime.py +26 -6
- pygpt_net/provider/api/openai/store.py +4 -1
- pygpt_net/provider/api/openai/worker/importer.py +19 -61
- pygpt_net/provider/api/openai/worker/importer_assistants.py +230 -0
- pygpt_net/provider/api/x_ai/__init__.py +27 -6
- pygpt_net/provider/api/x_ai/audio.py +43 -11
- pygpt_net/provider/api/x_ai/chat.py +92 -4
- pygpt_net/provider/api/x_ai/realtime/__init__.py +12 -0
- pygpt_net/provider/api/x_ai/realtime/client.py +1864 -0
- pygpt_net/provider/api/x_ai/realtime/realtime.py +213 -0
- pygpt_net/provider/api/x_ai/remote_tools.py +102 -1
- pygpt_net/provider/api/x_ai/store.py +610 -0
- pygpt_net/provider/api/x_ai/stream.py +30 -9
- pygpt_net/provider/api/x_ai/tools.py +51 -0
- pygpt_net/provider/api/x_ai/worker/importer.py +308 -0
- pygpt_net/provider/audio_input/xai_grok_voice.py +390 -0
- pygpt_net/provider/audio_output/xai_tts.py +325 -0
- pygpt_net/provider/core/config/patch.py +29 -3
- pygpt_net/provider/core/config/patches/patch_before_2_6_42.py +2 -2
- pygpt_net/provider/core/model/patch.py +49 -1
- pygpt_net/tools/image_viewer/tool.py +334 -34
- pygpt_net/tools/image_viewer/ui/dialogs.py +317 -21
- pygpt_net/ui/dialog/assistant.py +1 -1
- pygpt_net/ui/dialog/plugins.py +13 -5
- pygpt_net/ui/dialog/remote_store.py +552 -0
- pygpt_net/ui/dialogs.py +3 -5
- pygpt_net/ui/layout/ctx/ctx_list.py +58 -7
- pygpt_net/ui/menu/tools.py +6 -13
- pygpt_net/ui/widget/dialog/{remote_store_google.py → remote_store.py} +10 -10
- pygpt_net/ui/widget/element/button.py +4 -4
- pygpt_net/ui/widget/image/display.py +2 -2
- pygpt_net/ui/widget/lists/context.py +2 -2
- {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/METADATA +14 -2
- {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/RECORD +87 -75
- pygpt_net/controller/remote_store/google/store.py +0 -615
- pygpt_net/controller/remote_store/openai/batch.py +0 -524
- pygpt_net/controller/remote_store/openai/store.py +0 -699
- pygpt_net/ui/dialog/remote_store_google.py +0 -539
- pygpt_net/ui/dialog/remote_store_openai.py +0 -539
- pygpt_net/ui/widget/dialog/remote_store_openai.py +0 -56
- pygpt_net/ui/widget/lists/remote_store_google.py +0 -248
- pygpt_net/ui/widget/lists/remote_store_openai.py +0 -317
- {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/LICENSE +0 -0
- {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/WHEEL +0 -0
- {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/entry_points.txt +0 -0
|
@@ -26,6 +26,7 @@ class Tools:
|
|
|
26
26
|
|
|
27
27
|
- prepare(): legacy OpenAI-compatible dicts (kept for compatibility if needed).
|
|
28
28
|
- prepare_sdk_tools(): xAI SDK client-side tool descriptors for Chat Responses.
|
|
29
|
+
- prepare_realtime(): Realtime/WebSocket-compatible function tools.
|
|
29
30
|
|
|
30
31
|
:param window: Window instance
|
|
31
32
|
"""
|
|
@@ -168,4 +169,54 @@ class Tools:
|
|
|
168
169
|
))
|
|
169
170
|
except Exception:
|
|
170
171
|
continue
|
|
172
|
+
return tools
|
|
173
|
+
|
|
174
|
+
def prepare_realtime(self, functions: list) -> List[dict]:
|
|
175
|
+
"""
|
|
176
|
+
Prepare function tools for Realtime/WebSocket sessions.
|
|
177
|
+
|
|
178
|
+
The returned structure matches the Realtime "tools" schema:
|
|
179
|
+
[
|
|
180
|
+
{
|
|
181
|
+
"type": "function",
|
|
182
|
+
"function": {
|
|
183
|
+
"name": "...",
|
|
184
|
+
"description": "...",
|
|
185
|
+
"parameters": { ... JSON Schema ... }
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
:param functions: List of functions with keys: name (str), desc (str), params (JSON Schema str)
|
|
191
|
+
:return: List of function tool descriptors
|
|
192
|
+
"""
|
|
193
|
+
if not functions or not isinstance(functions, list):
|
|
194
|
+
return []
|
|
195
|
+
|
|
196
|
+
tools: List[dict] = []
|
|
197
|
+
for fn in functions:
|
|
198
|
+
name = str(fn.get("name") or "").strip()
|
|
199
|
+
if not name:
|
|
200
|
+
continue
|
|
201
|
+
desc = fn.get("desc") or ""
|
|
202
|
+
params: Optional[dict] = {}
|
|
203
|
+
if fn.get("params"):
|
|
204
|
+
try:
|
|
205
|
+
params = json.loads(fn["params"])
|
|
206
|
+
except Exception:
|
|
207
|
+
params = {}
|
|
208
|
+
params = self._sanitize_schema(params or {})
|
|
209
|
+
if not params.get("type"):
|
|
210
|
+
params["type"] = "object"
|
|
211
|
+
else:
|
|
212
|
+
params = {"type": "object"}
|
|
213
|
+
|
|
214
|
+
tools.append({
|
|
215
|
+
"type": "function",
|
|
216
|
+
"function": {
|
|
217
|
+
"name": name,
|
|
218
|
+
"description": desc,
|
|
219
|
+
"parameters": params,
|
|
220
|
+
}
|
|
221
|
+
})
|
|
171
222
|
return tools
|
|
@@ -0,0 +1,308 @@
|
|
|
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.06 06: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 (xAI Collections)
|
|
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
|
+
batch = self.window.controller.remote_store.batch
|
|
31
|
+
if mode == "import_files":
|
|
32
|
+
batch.handle_imported_files_failed(err)
|
|
33
|
+
elif mode == "truncate_files":
|
|
34
|
+
batch.handle_truncated_files_failed(err)
|
|
35
|
+
elif mode == "upload_files":
|
|
36
|
+
batch.handle_uploaded_files_failed(err)
|
|
37
|
+
elif mode in "vector_stores":
|
|
38
|
+
batch.handle_imported_stores_failed(err)
|
|
39
|
+
elif mode in "truncate_vector_stores":
|
|
40
|
+
batch.handle_truncated_stores_failed(err)
|
|
41
|
+
elif mode in "refresh_vector_stores":
|
|
42
|
+
batch.handle_refreshed_stores_failed(err)
|
|
43
|
+
|
|
44
|
+
@Slot(str, str, int)
|
|
45
|
+
def handle_finished(self, mode: str, store_id: str = None, num: int = 0):
|
|
46
|
+
batch = self.window.controller.remote_store.batch
|
|
47
|
+
if mode == "import_files":
|
|
48
|
+
batch.handle_imported_files(num)
|
|
49
|
+
elif mode == "truncate_files":
|
|
50
|
+
batch.handle_truncated_files(store_id, num)
|
|
51
|
+
elif mode == "upload_files":
|
|
52
|
+
batch.handle_uploaded_files(num)
|
|
53
|
+
elif mode == "vector_stores":
|
|
54
|
+
batch.handle_imported_stores(num)
|
|
55
|
+
elif mode == "truncate_vector_stores":
|
|
56
|
+
batch.handle_truncated_stores(num)
|
|
57
|
+
elif mode == "refresh_vector_stores":
|
|
58
|
+
batch.handle_refreshed_stores(num)
|
|
59
|
+
|
|
60
|
+
@Slot(str, str)
|
|
61
|
+
def handle_status(self, mode: str, msg: str):
|
|
62
|
+
self.window.controller.assistant.batch.handle_status_change(mode, msg)
|
|
63
|
+
|
|
64
|
+
@Slot(str, str)
|
|
65
|
+
def handle_log(self, mode: str, msg: str):
|
|
66
|
+
self.window.controller.assistant.threads.log(mode + ": " + msg)
|
|
67
|
+
|
|
68
|
+
# ---------- Vector stores (Collections) ----------
|
|
69
|
+
|
|
70
|
+
def import_vector_stores(self):
|
|
71
|
+
"""Import collections"""
|
|
72
|
+
self.worker = ImportWorker()
|
|
73
|
+
self.worker.window = self.window
|
|
74
|
+
self.worker.mode = "vector_stores"
|
|
75
|
+
self.connect_signals(self.worker)
|
|
76
|
+
self.window.threadpool.start(self.worker)
|
|
77
|
+
|
|
78
|
+
def truncate_vector_stores(self):
|
|
79
|
+
"""Delete collections"""
|
|
80
|
+
self.worker = ImportWorker()
|
|
81
|
+
self.worker.window = self.window
|
|
82
|
+
self.worker.mode = "truncate_vector_stores"
|
|
83
|
+
self.connect_signals(self.worker)
|
|
84
|
+
self.window.threadpool.start(self.worker)
|
|
85
|
+
|
|
86
|
+
def refresh_vector_stores(self):
|
|
87
|
+
"""Refresh collections"""
|
|
88
|
+
self.worker = ImportWorker()
|
|
89
|
+
self.worker.window = self.window
|
|
90
|
+
self.worker.mode = "refresh_vector_stores"
|
|
91
|
+
self.connect_signals(self.worker)
|
|
92
|
+
self.window.threadpool.start(self.worker)
|
|
93
|
+
|
|
94
|
+
# ---------- Files (documents) ----------
|
|
95
|
+
|
|
96
|
+
def truncate_files(self, store_id: str = None):
|
|
97
|
+
"""Remove documents from one/all collections"""
|
|
98
|
+
self.worker = ImportWorker()
|
|
99
|
+
self.worker.window = self.window
|
|
100
|
+
self.worker.mode = "truncate_files"
|
|
101
|
+
self.worker.store_id = store_id
|
|
102
|
+
self.connect_signals(self.worker)
|
|
103
|
+
self.window.threadpool.start(self.worker)
|
|
104
|
+
|
|
105
|
+
def upload_files(self, store_id: str, files: list = None):
|
|
106
|
+
"""Upload files to a collection"""
|
|
107
|
+
self.worker = ImportWorker()
|
|
108
|
+
self.worker.window = self.window
|
|
109
|
+
self.worker.mode = "upload_files"
|
|
110
|
+
self.worker.store_id = store_id
|
|
111
|
+
self.worker.files = files or []
|
|
112
|
+
self.connect_signals(self.worker)
|
|
113
|
+
self.window.threadpool.start(self.worker)
|
|
114
|
+
|
|
115
|
+
def import_files(self, store_id: str = None):
|
|
116
|
+
"""Import documents from one/all collections"""
|
|
117
|
+
self.worker = ImportWorker()
|
|
118
|
+
self.worker.window = self.window
|
|
119
|
+
self.worker.mode = "import_files"
|
|
120
|
+
self.worker.store_id = store_id
|
|
121
|
+
self.connect_signals(self.worker)
|
|
122
|
+
self.window.threadpool.start(self.worker)
|
|
123
|
+
|
|
124
|
+
def connect_signals(self, worker):
|
|
125
|
+
worker.signals.finished.connect(self.handle_finished)
|
|
126
|
+
worker.signals.error.connect(self.handle_error)
|
|
127
|
+
worker.signals.status.connect(self.handle_status)
|
|
128
|
+
worker.signals.log.connect(self.handle_log)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class ImportWorkerSignals(QObject):
|
|
132
|
+
status = Signal(str, str) # mode, message
|
|
133
|
+
finished = Signal(str, str, int) # mode, store_id, num
|
|
134
|
+
error = Signal(str, object) # mode, error
|
|
135
|
+
log = Signal(str, str) # mode, message
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class ImportWorker(QRunnable):
|
|
139
|
+
"""Import worker (xAI Collections)"""
|
|
140
|
+
def __init__(self, *args, **kwargs):
|
|
141
|
+
super().__init__()
|
|
142
|
+
self.signals = ImportWorkerSignals()
|
|
143
|
+
self.window = None
|
|
144
|
+
self.mode = "vector_stores"
|
|
145
|
+
self.store_id = None
|
|
146
|
+
self.files = []
|
|
147
|
+
|
|
148
|
+
@Slot()
|
|
149
|
+
def run(self):
|
|
150
|
+
try:
|
|
151
|
+
if self.mode == "vector_stores":
|
|
152
|
+
if self.import_vector_stores():
|
|
153
|
+
self.import_files()
|
|
154
|
+
elif self.mode == "truncate_vector_stores":
|
|
155
|
+
self.truncate_vector_stores()
|
|
156
|
+
elif self.mode == "refresh_vector_stores":
|
|
157
|
+
self.refresh_vector_stores()
|
|
158
|
+
elif self.mode == "truncate_files":
|
|
159
|
+
self.truncate_files()
|
|
160
|
+
elif self.mode == "import_files":
|
|
161
|
+
self.import_files()
|
|
162
|
+
elif self.mode == "upload_files":
|
|
163
|
+
self.upload_files()
|
|
164
|
+
except Exception as e:
|
|
165
|
+
self.signals.error.emit(self.mode, e)
|
|
166
|
+
finally:
|
|
167
|
+
self.cleanup()
|
|
168
|
+
|
|
169
|
+
# ---------- Collections ----------
|
|
170
|
+
|
|
171
|
+
def import_vector_stores(self, silent: bool = False) -> bool:
|
|
172
|
+
try:
|
|
173
|
+
self.log("Importing collections...")
|
|
174
|
+
self.window.core.remote_store.xai.clear()
|
|
175
|
+
items = {}
|
|
176
|
+
self.window.core.api.xai.store.import_collections_collections(items, callback=self.callback)
|
|
177
|
+
self.window.core.remote_store.xai.import_items(items)
|
|
178
|
+
if not silent:
|
|
179
|
+
self.signals.finished.emit("vector_stores", self.store_id, len(items))
|
|
180
|
+
return True
|
|
181
|
+
except Exception as e:
|
|
182
|
+
self.log("API error: {}".format(e))
|
|
183
|
+
self.signals.error.emit("vector_stores", e)
|
|
184
|
+
return False
|
|
185
|
+
|
|
186
|
+
def truncate_vector_stores(self, silent: bool = False) -> bool:
|
|
187
|
+
try:
|
|
188
|
+
self.log("Truncating collections...")
|
|
189
|
+
num = self.window.core.api.xai.store.remove_all_collections_collections(callback=self.callback)
|
|
190
|
+
self.window.core.remote_store.xai.items = {}
|
|
191
|
+
self.window.core.remote_store.xai.save()
|
|
192
|
+
if not silent:
|
|
193
|
+
self.signals.finished.emit("truncate_vector_stores", self.store_id, num)
|
|
194
|
+
return True
|
|
195
|
+
except Exception as e:
|
|
196
|
+
self.log("API error: {}".format(e))
|
|
197
|
+
self.signals.error.emit("truncate_vector_stores", e)
|
|
198
|
+
return False
|
|
199
|
+
|
|
200
|
+
def refresh_vector_stores(self, silent: bool = False) -> bool:
|
|
201
|
+
try:
|
|
202
|
+
self.log("Refreshing collections...")
|
|
203
|
+
num = 0
|
|
204
|
+
stores = self.window.core.remote_store.xai.items
|
|
205
|
+
for id in list(stores.keys()):
|
|
206
|
+
store = stores[id]
|
|
207
|
+
try:
|
|
208
|
+
self.window.controller.remote_store.refresh_store(store, update=False, provider="xai")
|
|
209
|
+
num += 1
|
|
210
|
+
except Exception as e:
|
|
211
|
+
self.log("Failed to refresh collection: {}".format(id))
|
|
212
|
+
self.window.core.debug.log(e)
|
|
213
|
+
if not silent:
|
|
214
|
+
self.signals.finished.emit("refresh_vector_stores", self.store_id, num)
|
|
215
|
+
return True
|
|
216
|
+
except Exception as e:
|
|
217
|
+
self.log("API error: {}".format(e))
|
|
218
|
+
self.signals.error.emit("refresh_vector_stores", e)
|
|
219
|
+
return False
|
|
220
|
+
|
|
221
|
+
# ---------- Documents ----------
|
|
222
|
+
|
|
223
|
+
def truncate_files(self, silent: bool = False) -> bool:
|
|
224
|
+
try:
|
|
225
|
+
if self.store_id is None:
|
|
226
|
+
self.log("Truncating all collection documents...")
|
|
227
|
+
self.window.core.remote_store.xai.files.truncate() # clear all local + detach from all collections
|
|
228
|
+
num = self.window.core.api.xai.store.remove_files(callback=self.callback) # delete remote files
|
|
229
|
+
else:
|
|
230
|
+
self.log("Truncating documents for collection: {}".format(self.store_id))
|
|
231
|
+
self.window.core.remote_store.xai.files.truncate(self.store_id) # clear local + detach from this collection
|
|
232
|
+
num = self.window.core.api.xai.store.remove_from_collection_collections(
|
|
233
|
+
self.store_id,
|
|
234
|
+
callback=self.callback,
|
|
235
|
+
)
|
|
236
|
+
if not silent:
|
|
237
|
+
self.signals.finished.emit("truncate_files", self.store_id, num)
|
|
238
|
+
return True
|
|
239
|
+
except Exception as e:
|
|
240
|
+
self.log("API error: {}".format(e))
|
|
241
|
+
self.signals.error.emit("truncate_files", e)
|
|
242
|
+
return False
|
|
243
|
+
|
|
244
|
+
def upload_files(self, silent: bool = False) -> bool:
|
|
245
|
+
num = 0
|
|
246
|
+
try:
|
|
247
|
+
self.log("Uploading files to collection...")
|
|
248
|
+
for path in self.files:
|
|
249
|
+
try:
|
|
250
|
+
doc = self.window.core.api.xai.store.upload_to_collection_collections(self.store_id, path)
|
|
251
|
+
if doc is not None:
|
|
252
|
+
self.window.core.remote_store.xai.files.insert(self.store_id, doc.file_metadata)
|
|
253
|
+
num += 1
|
|
254
|
+
msg = "Uploaded file: {}/{}".format(num, len(self.files))
|
|
255
|
+
self.signals.status.emit("upload_files", msg)
|
|
256
|
+
self.log(msg)
|
|
257
|
+
else:
|
|
258
|
+
self.signals.status.emit("upload_files", "Failed to upload: {}".format(os.path.basename(path)))
|
|
259
|
+
except Exception as e:
|
|
260
|
+
self.window.core.debug.log(e)
|
|
261
|
+
self.signals.status.emit("upload_files", "Failed to upload: {}".format(os.path.basename(path)))
|
|
262
|
+
if not silent:
|
|
263
|
+
self.signals.finished.emit("upload_files", self.store_id, num)
|
|
264
|
+
return True
|
|
265
|
+
except Exception as e:
|
|
266
|
+
self.log("API error: {}".format(e))
|
|
267
|
+
self.signals.error.emit("upload_files", e)
|
|
268
|
+
return False
|
|
269
|
+
|
|
270
|
+
def import_files(self, silent: bool = False) -> bool:
|
|
271
|
+
try:
|
|
272
|
+
if self.store_id is None:
|
|
273
|
+
self.log("Importing all collection documents...")
|
|
274
|
+
self.window.core.remote_store.xai.files.truncate_local() # clear local DB (all)
|
|
275
|
+
num = self.window.core.api.xai.store.import_collections_files_collections(callback=self.callback)
|
|
276
|
+
else:
|
|
277
|
+
self.log("Importing documents for collection: {}".format(self.store_id))
|
|
278
|
+
self.window.core.remote_store.xai.files.truncate_local(self.store_id) # clear local DB (store)
|
|
279
|
+
items = self.window.core.api.xai.store.import_collection_files_collections(
|
|
280
|
+
self.store_id,
|
|
281
|
+
[],
|
|
282
|
+
callback=self.callback,
|
|
283
|
+
)
|
|
284
|
+
num = len(items)
|
|
285
|
+
if not silent:
|
|
286
|
+
self.signals.finished.emit("import_files", self.store_id, num)
|
|
287
|
+
return True
|
|
288
|
+
except Exception as e:
|
|
289
|
+
self.log("API error: {}".format(e))
|
|
290
|
+
self.signals.error.emit("import_files", e)
|
|
291
|
+
return False
|
|
292
|
+
|
|
293
|
+
# ---------- Utils ----------
|
|
294
|
+
|
|
295
|
+
def callback(self, msg: str):
|
|
296
|
+
self.log(msg)
|
|
297
|
+
|
|
298
|
+
def log(self, msg: str):
|
|
299
|
+
self.signals.log.emit(self.mode, msg)
|
|
300
|
+
|
|
301
|
+
def cleanup(self):
|
|
302
|
+
sig = self.signals
|
|
303
|
+
self.signals = None
|
|
304
|
+
if sig is not None:
|
|
305
|
+
try:
|
|
306
|
+
sig.deleteLater()
|
|
307
|
+
except RuntimeError:
|
|
308
|
+
pass
|