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.
Files changed (133) hide show
  1. pygpt_net/CHANGELOG.txt +7 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app_core.py +4 -2
  4. pygpt_net/controller/__init__.py +5 -1
  5. pygpt_net/controller/assistant/assistant.py +1 -4
  6. pygpt_net/controller/assistant/batch.py +5 -504
  7. pygpt_net/controller/assistant/editor.py +5 -5
  8. pygpt_net/controller/assistant/files.py +16 -16
  9. pygpt_net/controller/chat/handler/google_stream.py +307 -1
  10. pygpt_net/controller/chat/handler/worker.py +8 -1
  11. pygpt_net/controller/chat/image.py +2 -2
  12. pygpt_net/controller/dialogs/confirm.py +73 -101
  13. pygpt_net/controller/lang/mapping.py +9 -9
  14. pygpt_net/controller/painter/capture.py +50 -1
  15. pygpt_net/controller/presets/presets.py +2 -1
  16. pygpt_net/controller/remote_store/__init__.py +12 -0
  17. pygpt_net/{provider/core/assistant_file/db_sqlite → controller/remote_store/google}/__init__.py +2 -2
  18. pygpt_net/controller/remote_store/google/batch.py +402 -0
  19. pygpt_net/controller/remote_store/google/store.py +615 -0
  20. pygpt_net/controller/remote_store/openai/__init__.py +12 -0
  21. pygpt_net/controller/remote_store/openai/batch.py +524 -0
  22. pygpt_net/controller/{assistant → remote_store/openai}/store.py +63 -60
  23. pygpt_net/controller/remote_store/remote_store.py +35 -0
  24. pygpt_net/controller/ui/ui.py +20 -1
  25. pygpt_net/core/assistants/assistants.py +3 -15
  26. pygpt_net/core/db/database.py +5 -3
  27. pygpt_net/core/locale/placeholder.py +35 -0
  28. pygpt_net/core/remote_store/__init__.py +12 -0
  29. pygpt_net/core/remote_store/google/__init__.py +11 -0
  30. pygpt_net/core/remote_store/google/files.py +224 -0
  31. pygpt_net/core/remote_store/google/store.py +248 -0
  32. pygpt_net/core/remote_store/openai/__init__.py +11 -0
  33. pygpt_net/core/{assistants → remote_store/openai}/files.py +26 -19
  34. pygpt_net/core/{assistants → remote_store/openai}/store.py +32 -15
  35. pygpt_net/core/remote_store/remote_store.py +24 -0
  36. pygpt_net/data/config/config.json +8 -4
  37. pygpt_net/data/config/models.json +77 -3
  38. pygpt_net/data/config/settings.json +45 -0
  39. pygpt_net/data/locale/locale.de.ini +41 -41
  40. pygpt_net/data/locale/locale.en.ini +53 -43
  41. pygpt_net/data/locale/locale.es.ini +41 -41
  42. pygpt_net/data/locale/locale.fr.ini +41 -41
  43. pygpt_net/data/locale/locale.it.ini +41 -41
  44. pygpt_net/data/locale/locale.pl.ini +42 -42
  45. pygpt_net/data/locale/locale.uk.ini +41 -41
  46. pygpt_net/data/locale/locale.zh.ini +41 -41
  47. pygpt_net/data/locale/plugin.cmd_history.de.ini +1 -1
  48. pygpt_net/data/locale/plugin.cmd_history.en.ini +1 -1
  49. pygpt_net/data/locale/plugin.cmd_history.es.ini +1 -1
  50. pygpt_net/data/locale/plugin.cmd_history.fr.ini +1 -1
  51. pygpt_net/data/locale/plugin.cmd_history.it.ini +1 -1
  52. pygpt_net/data/locale/plugin.cmd_history.pl.ini +1 -1
  53. pygpt_net/data/locale/plugin.cmd_history.uk.ini +1 -1
  54. pygpt_net/data/locale/plugin.cmd_history.zh.ini +1 -1
  55. pygpt_net/data/locale/plugin.cmd_mouse_control.en.ini +14 -0
  56. pygpt_net/data/locale/plugin.cmd_web.de.ini +1 -1
  57. pygpt_net/data/locale/plugin.cmd_web.en.ini +1 -1
  58. pygpt_net/data/locale/plugin.cmd_web.es.ini +1 -1
  59. pygpt_net/data/locale/plugin.cmd_web.fr.ini +1 -1
  60. pygpt_net/data/locale/plugin.cmd_web.it.ini +1 -1
  61. pygpt_net/data/locale/plugin.cmd_web.pl.ini +1 -1
  62. pygpt_net/data/locale/plugin.cmd_web.uk.ini +1 -1
  63. pygpt_net/data/locale/plugin.cmd_web.zh.ini +1 -1
  64. pygpt_net/data/locale/plugin.idx_llama_index.de.ini +2 -2
  65. pygpt_net/data/locale/plugin.idx_llama_index.en.ini +2 -2
  66. pygpt_net/data/locale/plugin.idx_llama_index.es.ini +2 -2
  67. pygpt_net/data/locale/plugin.idx_llama_index.fr.ini +2 -2
  68. pygpt_net/data/locale/plugin.idx_llama_index.it.ini +2 -2
  69. pygpt_net/data/locale/plugin.idx_llama_index.pl.ini +2 -2
  70. pygpt_net/data/locale/plugin.idx_llama_index.uk.ini +2 -2
  71. pygpt_net/data/locale/plugin.idx_llama_index.zh.ini +2 -2
  72. pygpt_net/item/assistant.py +1 -211
  73. pygpt_net/item/ctx.py +3 -1
  74. pygpt_net/item/store.py +238 -0
  75. pygpt_net/migrations/Version20260102190000.py +35 -0
  76. pygpt_net/migrations/__init__.py +3 -1
  77. pygpt_net/plugin/cmd_mouse_control/config.py +470 -1
  78. pygpt_net/plugin/cmd_mouse_control/plugin.py +488 -22
  79. pygpt_net/plugin/cmd_mouse_control/worker.py +464 -87
  80. pygpt_net/plugin/cmd_mouse_control/worker_sandbox.py +729 -0
  81. pygpt_net/plugin/idx_llama_index/config.py +2 -2
  82. pygpt_net/provider/api/google/__init__.py +16 -54
  83. pygpt_net/provider/api/google/chat.py +546 -129
  84. pygpt_net/provider/api/google/computer.py +190 -0
  85. pygpt_net/provider/api/google/realtime/realtime.py +2 -2
  86. pygpt_net/provider/api/google/remote_tools.py +93 -0
  87. pygpt_net/provider/api/google/store.py +546 -0
  88. pygpt_net/provider/api/google/worker/__init__.py +0 -0
  89. pygpt_net/provider/api/google/worker/importer.py +392 -0
  90. pygpt_net/provider/api/openai/computer.py +10 -1
  91. pygpt_net/provider/api/openai/store.py +6 -6
  92. pygpt_net/provider/api/openai/worker/importer.py +24 -24
  93. pygpt_net/provider/core/config/patch.py +16 -1
  94. pygpt_net/provider/core/config/patches/patch_before_2_6_42.py +3 -3
  95. pygpt_net/provider/core/model/patch.py +17 -3
  96. pygpt_net/provider/core/preset/json_file.py +13 -7
  97. pygpt_net/provider/core/{assistant_file → remote_file}/__init__.py +1 -1
  98. pygpt_net/provider/core/{assistant_file → remote_file}/base.py +9 -9
  99. pygpt_net/provider/core/remote_file/db_sqlite/__init__.py +12 -0
  100. pygpt_net/provider/core/{assistant_file → remote_file}/db_sqlite/patch.py +1 -1
  101. pygpt_net/provider/core/{assistant_file → remote_file}/db_sqlite/provider.py +23 -20
  102. pygpt_net/provider/core/{assistant_file → remote_file}/db_sqlite/storage.py +35 -27
  103. pygpt_net/provider/core/{assistant_file → remote_file}/db_sqlite/utils.py +5 -4
  104. pygpt_net/provider/core/{assistant_store → remote_store}/__init__.py +1 -1
  105. pygpt_net/provider/core/{assistant_store → remote_store}/base.py +10 -10
  106. pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/__init__.py +1 -1
  107. pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/patch.py +1 -1
  108. pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/provider.py +16 -15
  109. pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/storage.py +30 -23
  110. pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/utils.py +5 -4
  111. pygpt_net/provider/core/{assistant_store → remote_store}/json_file.py +9 -9
  112. pygpt_net/provider/llms/google.py +2 -2
  113. pygpt_net/ui/base/config_dialog.py +3 -2
  114. pygpt_net/ui/dialog/assistant.py +3 -3
  115. pygpt_net/ui/dialog/plugins.py +3 -1
  116. pygpt_net/ui/dialog/remote_store_google.py +539 -0
  117. pygpt_net/ui/dialog/{assistant_store.py → remote_store_openai.py} +95 -95
  118. pygpt_net/ui/dialogs.py +5 -3
  119. pygpt_net/ui/layout/chat/attachments_uploaded.py +3 -3
  120. pygpt_net/ui/layout/toolbox/computer_env.py +26 -8
  121. pygpt_net/ui/menu/tools.py +13 -5
  122. pygpt_net/ui/widget/dialog/remote_store_google.py +56 -0
  123. pygpt_net/ui/widget/dialog/{assistant_store.py → remote_store_openai.py} +9 -9
  124. pygpt_net/ui/widget/element/button.py +4 -4
  125. pygpt_net/ui/widget/lists/remote_store_google.py +248 -0
  126. pygpt_net/ui/widget/lists/{assistant_store.py → remote_store_openai.py} +21 -21
  127. pygpt_net/ui/widget/option/checkbox_list.py +47 -9
  128. pygpt_net/ui/widget/option/combo.py +39 -3
  129. {pygpt_net-2.7.4.dist-info → pygpt_net-2.7.5.dist-info}/METADATA +33 -2
  130. {pygpt_net-2.7.4.dist-info → pygpt_net-2.7.5.dist-info}/RECORD +133 -108
  131. {pygpt_net-2.7.4.dist-info → pygpt_net-2.7.5.dist-info}/LICENSE +0 -0
  132. {pygpt_net-2.7.4.dist-info → pygpt_net-2.7.5.dist-info}/WHEEL +0 -0
  133. {pygpt_net-2.7.4.dist-info → pygpt_net-2.7.5.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,524 @@
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
+ from typing import Optional, Any, Union
13
+
14
+ from PySide6.QtCore import QTimer
15
+ from PySide6.QtWidgets import QFileDialog, QApplication
16
+
17
+ from pygpt_net.utils import trans
18
+
19
+
20
+ class Batch:
21
+ def __init__(self, window=None):
22
+ """
23
+ Assistants batch controller
24
+
25
+ :param window: Window instance
26
+ """
27
+ self.window = window
28
+ self.files_to_upload = []
29
+
30
+ def import_stores(self, force: bool = False):
31
+ """
32
+ Import vector stores from API
33
+
34
+ :param force: if true, imports without confirmation
35
+ """
36
+ if not force:
37
+ self.window.ui.dialogs.confirm(
38
+ type='remote_store.openai.import',
39
+ id='',
40
+ msg=trans('confirm.remote_store.import'),
41
+ )
42
+ return
43
+ # run asynchronous
44
+ self.window.update_status("Importing vector stores...please wait...")
45
+ self.window.core.remote_store.openai.truncate() # clear all stores
46
+ self.window.core.api.openai.assistants.importer.import_vector_stores()
47
+ self.window.controller.assistant.files.update()
48
+ self.window.controller.remote_store.openai.update()
49
+
50
+ def import_files_current(self):
51
+ """Import files from API"""
52
+ id = self.window.core.config.get('assistant')
53
+ if id is None or id == "":
54
+ return
55
+ if self.window.core.assistants.has(id):
56
+ assistant = self.window.core.assistants.get_by_id(id)
57
+ store_id = assistant.vector_store
58
+ if store_id is None or store_id == "":
59
+ self.window.ui.dialogs.alert(trans("dialog.remote_store.alert.assign"))
60
+ return
61
+ self.import_store_files(store_id)
62
+
63
+ def import_files(self, force: bool = False):
64
+ """
65
+ Sync files with API (all)
66
+
67
+ :param force: force sync files
68
+ """
69
+ if not force:
70
+ self.window.ui.dialogs.confirm(
71
+ type='remote_store.openai.files.import.all',
72
+ id='',
73
+ msg=trans('confirm.remote_store.import_files'),
74
+ )
75
+ return
76
+ try:
77
+ self.window.controller.assistant.files.import_files() # all
78
+ except Exception as e:
79
+ self.window.core.debug.log(e)
80
+ self.window.ui.dialogs.alert(e)
81
+
82
+ def import_store_files(
83
+ self,
84
+ store_id: str,
85
+ force: bool = False
86
+ ):
87
+ """
88
+ Sync files with API (store)
89
+
90
+ :param store_id: vector store ID
91
+ :param force: force sync files
92
+ """
93
+ if store_id is None:
94
+ self.window.ui.dialogs.alert(trans("dialog.remote_store.alert.select"))
95
+ return
96
+
97
+ if not force:
98
+ self.window.ui.dialogs.confirm(
99
+ type='remote_store.openai.files.import.store',
100
+ id=store_id,
101
+ msg=trans('confirm.remote_store.import_files.store'),
102
+ )
103
+ return
104
+ try:
105
+ self.window.controller.assistant.files.import_files(store_id) # by store
106
+ except Exception as e:
107
+ self.window.core.debug.log(e)
108
+ self.window.ui.dialogs.alert(e)
109
+
110
+ def truncate_files(self, force: bool = False):
111
+ """
112
+ Truncate all files in API
113
+
114
+ :param force: if True, imports without confirmation
115
+ """
116
+ if not force:
117
+ self.window.ui.dialogs.confirm(
118
+ type='remote_store.openai.files.truncate',
119
+ id='',
120
+ msg=trans('confirm.remote_store.openai.files.truncate'),
121
+ )
122
+ return
123
+ # run asynchronous
124
+ self.window.update_status("Removing files...please wait...")
125
+ QApplication.processEvents()
126
+ self.window.core.api.openai.assistants.importer.truncate_files() # remove all files from API
127
+
128
+ def truncate_store_files_by_idx(self, idx: Union[int, list], force: bool = False):
129
+ """
130
+ Truncate all files in API (store)
131
+
132
+ :param idx: store index or list of indexes
133
+ :param force: if True, imports without confirmation
134
+ """
135
+ store_ids = []
136
+ ids = idx if isinstance(idx, list) else [idx]
137
+ for i in ids:
138
+ store_id = self.window.controller.remote_store.openai.get_by_tab_idx(i)
139
+ store_ids.append(store_id)
140
+ self.truncate_store_files(store_ids, force)
141
+
142
+ def truncate_store_files(self, store_id: Union[str, list], force: bool = False):
143
+ """
144
+ Truncate all files in API (store)
145
+
146
+ :param store_id: store ID
147
+ :param force: if True, imports without confirmation
148
+ """
149
+ if store_id is None:
150
+ self.window.ui.dialogs.alert(trans("dialog.remote_store.alert.select"))
151
+ return
152
+
153
+ if not force:
154
+ self.window.ui.dialogs.confirm(
155
+ type='remote_store.openai.files.truncate.store',
156
+ id=store_id,
157
+ msg=trans('confirm.remote_store.openai.files.truncate.store'),
158
+ )
159
+ return
160
+ # run asynchronous
161
+ self.window.update_status("Removing files...please wait...")
162
+ QApplication.processEvents()
163
+ ids = store_id if isinstance(store_id, list) else [store_id]
164
+ for store_id in ids:
165
+ self.window.core.api.openai.assistants.importer.truncate_files(store_id) # remove all files from API
166
+
167
+ def clear_store_files_by_idx(
168
+ self,
169
+ idx: Union[int, list],
170
+ force: bool = False
171
+ ):
172
+ """
173
+ Clear files (store, local only)
174
+
175
+ :param idx: store index or list of indexes
176
+ :param force: if True, clears without confirmation
177
+ """
178
+ store_ids = []
179
+ ids = idx if isinstance(idx, list) else [idx]
180
+ for i in ids:
181
+ store_id = self.window.controller.remote_store.openai.get_by_tab_idx(i)
182
+ store_ids.append(store_id)
183
+ self.clear_store_files(store_ids, force)
184
+
185
+ def clear_store_files(
186
+ self,
187
+ store_id: Optional[Union[str, list]] = None,
188
+ force: bool = False
189
+ ):
190
+ """
191
+ Clear files (store, local only)
192
+
193
+ :param store_id: store ID or list of store IDs
194
+ :param force: if True, clears without confirmation
195
+ """
196
+ if store_id is None:
197
+ self.window.ui.dialogs.alert(trans("dialog.remote_store.alert.select"))
198
+ return
199
+
200
+ if not force:
201
+ self.window.ui.dialogs.confirm(
202
+ type='remote_store.openai.files.clear.store',
203
+ id=store_id,
204
+ msg=trans('confirm.assistant.files.clear'),
205
+ )
206
+ return
207
+ self.window.update_status("Clearing store files...please wait...")
208
+ QApplication.processEvents()
209
+
210
+ ids = store_id if isinstance(store_id, list) else [store_id]
211
+ for store_id in ids:
212
+ self.window.core.remote_store.openai.files.truncate_local(store_id) # clear files local
213
+
214
+ self.window.controller.assistant.files.update()
215
+ self.window.update_status("OK. All store files cleared.")
216
+ self.window.ui.dialogs.alert(trans("status.finished"))
217
+
218
+ def clear_files(self, force: bool = False):
219
+ """
220
+ Clear files (all, local only)
221
+
222
+ :param force: if True, clears without confirmation
223
+ """
224
+ if not force:
225
+ self.window.ui.dialogs.confirm(
226
+ type='remote_store.openai.files.clear.all',
227
+ id='',
228
+ msg=trans('confirm.assistant.files.clear'),
229
+ )
230
+ return
231
+ self.window.update_status("Clearing files...please wait...")
232
+ QApplication.processEvents()
233
+ self.window.core.remote_store.openai.files.truncate_local() # clear files local
234
+ self.window.controller.assistant.files.update()
235
+ self.window.update_status("OK. All files cleared.")
236
+ self.window.ui.dialogs.alert(trans("status.finished"))
237
+
238
+ def clear_stores(self, force: bool = False):
239
+ """
240
+ Clear vector stores (local only)
241
+
242
+ :param force: if True, clears without confirmation
243
+ """
244
+ if not force:
245
+ self.window.ui.dialogs.confirm(
246
+ type='remote_store.openai.clear',
247
+ id='',
248
+ msg=trans('confirm.remote_store.clear'),
249
+ )
250
+ return
251
+ self.window.update_status("Clearing vector stores...please wait...")
252
+ QApplication.processEvents()
253
+ self.window.core.remote_store.openai.truncate() # clear all stores
254
+ self.window.controller.assistant.files.update()
255
+ self.window.controller.remote_store.openai.update()
256
+ self.window.update_status("OK. All stores cleared.")
257
+ self.window.controller.remote_store.openai.current = None
258
+ self.window.controller.remote_store.openai.init()
259
+
260
+ def truncate_stores(self, force: bool = False):
261
+ """
262
+ Truncate vector stores in API
263
+
264
+ :param force: if True, truncates without confirmation
265
+ """
266
+ if not force:
267
+ self.window.ui.dialogs.confirm(
268
+ type='remote_store.openai.truncate',
269
+ id='',
270
+ msg=trans('confirm.remote_store.truncate'),
271
+ )
272
+ return
273
+ # run asynchronous
274
+ self.window.update_status("Removing vector stores...please wait...")
275
+ QApplication.processEvents()
276
+ self.window.core.remote_store.openai.truncate() # clear all stores
277
+ self.window.core.api.openai.assistants.importer.truncate_vector_stores()
278
+ self.window.controller.assistant.files.update()
279
+ self.window.controller.remote_store.openai.update()
280
+ self.window.controller.remote_store.openai.current = None
281
+ self.window.controller.remote_store.openai.init()
282
+
283
+ def refresh_stores(self, force: bool = False):
284
+ """
285
+ Refresh all vector stores
286
+
287
+ :param force: if True, refresh without confirmation
288
+ """
289
+ if not force:
290
+ self.window.ui.dialogs.confirm(
291
+ type='remote_store.openai.refresh',
292
+ id='',
293
+ msg=trans('confirm.remote_store.refresh'),
294
+ )
295
+ return
296
+ self.window.update_status("Refreshing vector stores...please wait...")
297
+ QApplication.processEvents()
298
+ self.window.core.api.openai.assistants.importer.refresh_vector_stores()
299
+
300
+ def handle_refreshed_stores(self, num: int):
301
+ """
302
+ Handle refreshed stores
303
+
304
+ :param num: number of refreshed files
305
+ """
306
+ self.window.controller.remote_store.openai.update_current()
307
+ self.window.controller.remote_store.openai.update()
308
+ self.window.ui.dialogs.alert(trans("status.finished"))
309
+ self.window.update_status("OK. All stores refreshed.")
310
+
311
+ def handle_refreshed_stores_failed(self, error: Any):
312
+ """
313
+ Handle error on refreshing stores
314
+
315
+ :param error: error message
316
+ """
317
+ self.window.core.debug.log(error)
318
+ print("Error refreshing stores", error)
319
+ self.window.controller.assistant.files.update()
320
+ self.window.controller.remote_store.openai.update()
321
+ self.window.update_status("Error refreshing stores.")
322
+ self.window.ui.dialogs.alert(error)
323
+
324
+ def handle_imported_stores(self, num: int):
325
+ """
326
+ Handle imported stores
327
+
328
+ :param num: number of imported files
329
+ """
330
+ self.window.controller.assistant.files.update()
331
+ self.window.controller.remote_store.openai.update()
332
+ self.window.update_status("OK. Imported stores: " + str(num) + ".")
333
+ # alert on files import after stores
334
+ # self.window.ui.dialogs.alert(trans("status.finished"))
335
+
336
+ def handle_imported_stores_failed(self, error: Any):
337
+ """
338
+ Handle error on importing stores
339
+
340
+ :param error: error message
341
+ """
342
+ self.window.core.debug.log(error)
343
+ self.window.controller.assistant.files.update()
344
+ self.window.controller.remote_store.openai.update()
345
+ print("Error importing stores", error)
346
+ self.window.update_status("Error importing stores.")
347
+ self.window.ui.dialogs.alert(error)
348
+
349
+ def handle_truncated_stores(self, num: int):
350
+ """
351
+ Handle truncated stores
352
+
353
+ :param num: number of removed files
354
+ """
355
+ self.window.core.remote_store.openai.truncate()
356
+ self.window.controller.assistant.batch.remove_all_stores_from_assistants()
357
+ self.window.controller.assistant.files.update()
358
+ self.window.controller.remote_store.openai.update()
359
+ self.window.controller.remote_store.openai.current = None
360
+ self.window.controller.remote_store.openai.init()
361
+ self.window.update_status("OK. Removed stores: " + str(num) + ".")
362
+ self.window.ui.dialogs.alert(trans("status.finished"))
363
+
364
+ def handle_truncated_stores_failed(self, error: Any):
365
+ """
366
+ Handle error on truncating stores
367
+
368
+ :param error: error message
369
+ """
370
+ self.window.core.debug.log(error)
371
+ print("Error removing stores", error)
372
+ self.window.controller.assistant.files.update()
373
+ self.window.controller.remote_store.openai.update()
374
+ self.window.update_status("Error removing stores.")
375
+ self.window.ui.dialogs.alert(error)
376
+
377
+ def handle_imported_files(self, num: int):
378
+ """
379
+ Handle imported files
380
+
381
+ :param num: number of imported files
382
+ """
383
+ self.window.controller.assistant.files.update()
384
+ self.window.update_status("OK. Imported files: " + str(num) + ".")
385
+ self.window.ui.dialogs.alert(trans("status.finished"))
386
+
387
+ def handle_imported_files_failed(self, error: Any):
388
+ """
389
+ Handle error on importing files
390
+
391
+ :param error: error message
392
+ """
393
+ self.window.core.debug.log(error)
394
+ self.window.controller.assistant.files.update()
395
+ print("Error importing files")
396
+ self.window.update_status("Error importing files.")
397
+ self.window.ui.dialogs.alert(error)
398
+
399
+ def handle_truncated_files(
400
+ self,
401
+ store_id: Optional[str] = None,
402
+ num: int = 0
403
+ ):
404
+ """
405
+ Handle truncated (in API) files
406
+
407
+ :param store_id: vector store ID
408
+ :param num: number of truncated files
409
+ """
410
+ self.window.update_status("OK. Truncated files: " + str(num) + ".")
411
+ if store_id is not None:
412
+ self.window.controller.remote_store.openai.refresh_by_store_id(store_id)
413
+ self.window.controller.assistant.files.update()
414
+ self.window.ui.dialogs.alert(trans("status.finished"))
415
+
416
+ def handle_truncated_files_failed(self, error: Any):
417
+ """
418
+ Handle error on truncated files
419
+
420
+ :param error: error message
421
+ """
422
+ self.window.core.debug.log(error)
423
+ print("Error truncating files")
424
+ self.window.controller.assistant.files.update()
425
+ self.window.update_status("Error truncating files.")
426
+ self.window.ui.dialogs.alert(error)
427
+
428
+ def open_upload_files(self):
429
+ """Open upload files dialog"""
430
+ if self.window.controller.remote_store.openai.current is None:
431
+ self.window.ui.dialogs.alert("Please select vector store first.")
432
+ return
433
+
434
+ options = QFileDialog.Options()
435
+ files, _ = QFileDialog.getOpenFileNames(
436
+ self.window,
437
+ "Select file(s)...",
438
+ "",
439
+ "All Files (*)",
440
+ options=options
441
+ )
442
+ if files:
443
+ self.files_to_upload = files
444
+
445
+ if self.files_to_upload:
446
+ msg = "Are you sure you want to upload {} file(s)?".format(len(self.files_to_upload))
447
+ self.window.ui.dialogs.confirm(
448
+ type="remote_store.openai.files.upload",
449
+ id=0,
450
+ msg=msg,
451
+ )
452
+
453
+ def open_upload_dir(self):
454
+ """Open upload files dialog"""
455
+ if self.window.controller.remote_store.openai.current is None:
456
+ self.window.ui.dialogs.alert("Please select vector store first.")
457
+ return
458
+
459
+ options = QFileDialog.Options()
460
+ directory = QFileDialog.getExistingDirectory(
461
+ self.window,
462
+ "Select directory...",
463
+ options=options
464
+ )
465
+ if directory:
466
+ self.files_to_upload = self.window.core.filesystem.get_files_from_dir(directory)
467
+
468
+ if self.files_to_upload:
469
+ msg = ("Are you sure you want to upload {} file(s) from directory {}?".
470
+ format(len(self.files_to_upload), directory))
471
+ self.window.ui.dialogs.confirm(
472
+ type="remote_store.openai.files.upload",
473
+ id=0,
474
+ msg=msg,
475
+ )
476
+
477
+ def refresh_delayed(self, ms: int = 1000):
478
+ """
479
+ Refresh UI after delay
480
+
481
+ :param ms: milliseconds to wait
482
+ """
483
+ self.window.update_status("Refreshing status...")
484
+ QTimer.singleShot(ms, lambda: self.window.controller.remote_store.openai.refresh_status())
485
+
486
+ def upload(self, force: bool = False):
487
+ """
488
+ Upload files to vector store
489
+
490
+ :param force: if true, uploads without confirmation
491
+ """
492
+ if self.window.controller.remote_store.openai.current is None:
493
+ self.window.ui.dialogs.alert(trans("dialog.remote_store.alert.select"))
494
+ return
495
+
496
+ store_id = self.window.controller.remote_store.openai.current
497
+ self.window.update_status("Uploading files...please wait...")
498
+ QApplication.processEvents()
499
+ self.window.core.api.openai.assistants.importer.upload_files(store_id, self.files_to_upload)
500
+ self.files_to_upload = [] # clear files
501
+
502
+ def handle_uploaded_files(self, num: int):
503
+ """
504
+ Handle uploaded files
505
+
506
+ :param num: number of uploaded files
507
+ """
508
+ self.window.controller.assistant.files.update()
509
+ self.window.update_status("OK. Uploaded files: " + str(num) + ".")
510
+ self.window.ui.dialogs.alert("OK. Uploaded files: " + str(num) + ".")
511
+ self.refresh_delayed(1500)
512
+
513
+ def handle_uploaded_files_failed(self, error: Any):
514
+ """
515
+ Handle error on uploading files
516
+
517
+ :param error: error message
518
+ """
519
+ self.window.core.debug.log(error)
520
+ print("Error uploading files")
521
+ self.window.controller.assistant.files.update()
522
+ self.refresh_delayed(1500)
523
+ self.window.update_status("Error uploading files.")
524
+ self.window.ui.dialogs.alert(error)