pygpt-net 2.7.3__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 (157) hide show
  1. pygpt_net/CHANGELOG.txt +15 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +382 -350
  4. pygpt_net/app_core.py +4 -2
  5. pygpt_net/controller/__init__.py +5 -1
  6. pygpt_net/controller/assistant/assistant.py +1 -4
  7. pygpt_net/controller/assistant/batch.py +5 -504
  8. pygpt_net/controller/assistant/editor.py +5 -5
  9. pygpt_net/controller/assistant/files.py +16 -16
  10. pygpt_net/controller/chat/attachment.py +5 -1
  11. pygpt_net/controller/chat/handler/google_stream.py +307 -1
  12. pygpt_net/controller/chat/handler/worker.py +8 -1
  13. pygpt_net/controller/chat/image.py +15 -3
  14. pygpt_net/controller/dialogs/confirm.py +73 -101
  15. pygpt_net/controller/files/files.py +3 -1
  16. pygpt_net/controller/lang/mapping.py +9 -9
  17. pygpt_net/controller/layout/layout.py +2 -2
  18. pygpt_net/controller/painter/capture.py +50 -1
  19. pygpt_net/controller/presets/presets.py +2 -1
  20. pygpt_net/controller/remote_store/__init__.py +12 -0
  21. pygpt_net/{provider/core/assistant_file/db_sqlite → controller/remote_store/google}/__init__.py +2 -2
  22. pygpt_net/controller/remote_store/google/batch.py +402 -0
  23. pygpt_net/controller/remote_store/google/store.py +615 -0
  24. pygpt_net/controller/remote_store/openai/__init__.py +12 -0
  25. pygpt_net/controller/remote_store/openai/batch.py +524 -0
  26. pygpt_net/controller/{assistant → remote_store/openai}/store.py +63 -60
  27. pygpt_net/controller/remote_store/remote_store.py +35 -0
  28. pygpt_net/controller/theme/nodes.py +2 -1
  29. pygpt_net/controller/ui/mode.py +5 -1
  30. pygpt_net/controller/ui/ui.py +36 -2
  31. pygpt_net/core/assistants/assistants.py +3 -15
  32. pygpt_net/core/db/database.py +5 -3
  33. pygpt_net/core/filesystem/url.py +4 -1
  34. pygpt_net/core/locale/placeholder.py +35 -0
  35. pygpt_net/core/remote_store/__init__.py +12 -0
  36. pygpt_net/core/remote_store/google/__init__.py +11 -0
  37. pygpt_net/core/remote_store/google/files.py +224 -0
  38. pygpt_net/core/remote_store/google/store.py +248 -0
  39. pygpt_net/core/remote_store/openai/__init__.py +11 -0
  40. pygpt_net/core/{assistants → remote_store/openai}/files.py +26 -19
  41. pygpt_net/core/{assistants → remote_store/openai}/store.py +32 -15
  42. pygpt_net/core/remote_store/remote_store.py +24 -0
  43. pygpt_net/core/render/web/helpers.py +5 -0
  44. pygpt_net/data/config/config.json +8 -5
  45. pygpt_net/data/config/models.json +77 -3
  46. pygpt_net/data/config/settings.json +45 -14
  47. pygpt_net/data/css/web-blocks.css +3 -0
  48. pygpt_net/data/css/web-chatgpt.css +3 -0
  49. pygpt_net/data/locale/locale.de.ini +43 -41
  50. pygpt_net/data/locale/locale.en.ini +56 -44
  51. pygpt_net/data/locale/locale.es.ini +43 -41
  52. pygpt_net/data/locale/locale.fr.ini +43 -41
  53. pygpt_net/data/locale/locale.it.ini +43 -41
  54. pygpt_net/data/locale/locale.pl.ini +43 -41
  55. pygpt_net/data/locale/locale.uk.ini +43 -41
  56. pygpt_net/data/locale/locale.zh.ini +43 -41
  57. pygpt_net/data/locale/plugin.cmd_history.de.ini +1 -1
  58. pygpt_net/data/locale/plugin.cmd_history.en.ini +1 -1
  59. pygpt_net/data/locale/plugin.cmd_history.es.ini +1 -1
  60. pygpt_net/data/locale/plugin.cmd_history.fr.ini +1 -1
  61. pygpt_net/data/locale/plugin.cmd_history.it.ini +1 -1
  62. pygpt_net/data/locale/plugin.cmd_history.pl.ini +1 -1
  63. pygpt_net/data/locale/plugin.cmd_history.uk.ini +1 -1
  64. pygpt_net/data/locale/plugin.cmd_history.zh.ini +1 -1
  65. pygpt_net/data/locale/plugin.cmd_mouse_control.en.ini +14 -0
  66. pygpt_net/data/locale/plugin.cmd_web.de.ini +1 -1
  67. pygpt_net/data/locale/plugin.cmd_web.en.ini +1 -1
  68. pygpt_net/data/locale/plugin.cmd_web.es.ini +1 -1
  69. pygpt_net/data/locale/plugin.cmd_web.fr.ini +1 -1
  70. pygpt_net/data/locale/plugin.cmd_web.it.ini +1 -1
  71. pygpt_net/data/locale/plugin.cmd_web.pl.ini +1 -1
  72. pygpt_net/data/locale/plugin.cmd_web.uk.ini +1 -1
  73. pygpt_net/data/locale/plugin.cmd_web.zh.ini +1 -1
  74. pygpt_net/data/locale/plugin.idx_llama_index.de.ini +2 -2
  75. pygpt_net/data/locale/plugin.idx_llama_index.en.ini +2 -2
  76. pygpt_net/data/locale/plugin.idx_llama_index.es.ini +2 -2
  77. pygpt_net/data/locale/plugin.idx_llama_index.fr.ini +2 -2
  78. pygpt_net/data/locale/plugin.idx_llama_index.it.ini +2 -2
  79. pygpt_net/data/locale/plugin.idx_llama_index.pl.ini +2 -2
  80. pygpt_net/data/locale/plugin.idx_llama_index.uk.ini +2 -2
  81. pygpt_net/data/locale/plugin.idx_llama_index.zh.ini +2 -2
  82. pygpt_net/item/assistant.py +1 -211
  83. pygpt_net/item/ctx.py +3 -1
  84. pygpt_net/item/store.py +238 -0
  85. pygpt_net/launcher.py +115 -55
  86. pygpt_net/migrations/Version20260102190000.py +35 -0
  87. pygpt_net/migrations/__init__.py +3 -1
  88. pygpt_net/plugin/cmd_mouse_control/config.py +470 -1
  89. pygpt_net/plugin/cmd_mouse_control/plugin.py +488 -22
  90. pygpt_net/plugin/cmd_mouse_control/worker.py +464 -87
  91. pygpt_net/plugin/cmd_mouse_control/worker_sandbox.py +729 -0
  92. pygpt_net/plugin/idx_llama_index/config.py +2 -2
  93. pygpt_net/preload.py +243 -0
  94. pygpt_net/provider/api/google/__init__.py +16 -54
  95. pygpt_net/provider/api/google/chat.py +546 -129
  96. pygpt_net/provider/api/google/computer.py +190 -0
  97. pygpt_net/provider/api/google/image.py +74 -6
  98. pygpt_net/provider/api/google/realtime/realtime.py +2 -2
  99. pygpt_net/provider/api/google/remote_tools.py +93 -0
  100. pygpt_net/provider/api/google/store.py +546 -0
  101. pygpt_net/provider/api/google/video.py +9 -4
  102. pygpt_net/provider/api/google/worker/__init__.py +0 -0
  103. pygpt_net/provider/api/google/worker/importer.py +392 -0
  104. pygpt_net/provider/api/openai/computer.py +10 -1
  105. pygpt_net/provider/api/openai/image.py +42 -19
  106. pygpt_net/provider/api/openai/store.py +6 -6
  107. pygpt_net/provider/api/openai/video.py +27 -2
  108. pygpt_net/provider/api/openai/worker/importer.py +24 -24
  109. pygpt_net/provider/api/x_ai/image.py +25 -2
  110. pygpt_net/provider/core/config/patch.py +23 -1
  111. pygpt_net/provider/core/config/patches/patch_before_2_6_42.py +3 -3
  112. pygpt_net/provider/core/model/patch.py +17 -3
  113. pygpt_net/provider/core/preset/json_file.py +13 -7
  114. pygpt_net/provider/core/{assistant_file → remote_file}/__init__.py +1 -1
  115. pygpt_net/provider/core/{assistant_file → remote_file}/base.py +9 -9
  116. pygpt_net/provider/core/remote_file/db_sqlite/__init__.py +12 -0
  117. pygpt_net/provider/core/{assistant_file → remote_file}/db_sqlite/patch.py +1 -1
  118. pygpt_net/provider/core/{assistant_file → remote_file}/db_sqlite/provider.py +23 -20
  119. pygpt_net/provider/core/{assistant_file → remote_file}/db_sqlite/storage.py +35 -27
  120. pygpt_net/provider/core/{assistant_file → remote_file}/db_sqlite/utils.py +5 -4
  121. pygpt_net/provider/core/{assistant_store → remote_store}/__init__.py +1 -1
  122. pygpt_net/provider/core/{assistant_store → remote_store}/base.py +10 -10
  123. pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/__init__.py +1 -1
  124. pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/patch.py +1 -1
  125. pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/provider.py +16 -15
  126. pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/storage.py +30 -23
  127. pygpt_net/provider/core/{assistant_store → remote_store}/db_sqlite/utils.py +5 -4
  128. pygpt_net/provider/core/{assistant_store → remote_store}/json_file.py +9 -9
  129. pygpt_net/provider/llms/google.py +2 -2
  130. pygpt_net/ui/base/config_dialog.py +3 -2
  131. pygpt_net/ui/dialog/assistant.py +3 -3
  132. pygpt_net/ui/dialog/plugins.py +3 -1
  133. pygpt_net/ui/dialog/remote_store_google.py +539 -0
  134. pygpt_net/ui/dialog/{assistant_store.py → remote_store_openai.py} +95 -95
  135. pygpt_net/ui/dialogs.py +5 -3
  136. pygpt_net/ui/layout/chat/attachments_uploaded.py +3 -3
  137. pygpt_net/ui/layout/chat/input.py +20 -2
  138. pygpt_net/ui/layout/chat/painter.py +6 -4
  139. pygpt_net/ui/layout/toolbox/computer_env.py +26 -8
  140. pygpt_net/ui/layout/toolbox/image.py +5 -5
  141. pygpt_net/ui/layout/toolbox/video.py +5 -4
  142. pygpt_net/ui/main.py +84 -3
  143. pygpt_net/ui/menu/tools.py +13 -5
  144. pygpt_net/ui/widget/dialog/base.py +3 -10
  145. pygpt_net/ui/widget/dialog/remote_store_google.py +56 -0
  146. pygpt_net/ui/widget/dialog/{assistant_store.py → remote_store_openai.py} +9 -9
  147. pygpt_net/ui/widget/element/button.py +4 -4
  148. pygpt_net/ui/widget/lists/remote_store_google.py +248 -0
  149. pygpt_net/ui/widget/lists/{assistant_store.py → remote_store_openai.py} +21 -21
  150. pygpt_net/ui/widget/option/checkbox_list.py +47 -9
  151. pygpt_net/ui/widget/option/combo.py +158 -4
  152. pygpt_net/ui/widget/textarea/input_extra.py +664 -0
  153. {pygpt_net-2.7.3.dist-info → pygpt_net-2.7.5.dist-info}/METADATA +48 -9
  154. {pygpt_net-2.7.3.dist-info → pygpt_net-2.7.5.dist-info}/RECORD +157 -130
  155. {pygpt_net-2.7.3.dist-info → pygpt_net-2.7.5.dist-info}/LICENSE +0 -0
  156. {pygpt_net-2.7.3.dist-info → pygpt_net-2.7.5.dist-info}/WHEEL +0 -0
  157. {pygpt_net-2.7.3.dist-info → pygpt_net-2.7.5.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,238 @@
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 json
13
+ import time
14
+ from dataclasses import dataclass, field
15
+ from typing import Optional
16
+
17
+ from pygpt_net.item.attachment import AttachmentItem
18
+
19
+
20
+ @dataclass(slots=True)
21
+ class RemoteStoreItem:
22
+ id: Optional[object] = None
23
+ record_id: Optional[object] = None
24
+ uuid: Optional[object] = None
25
+ name: Optional[object] = None
26
+ provider: Optional[object] = None
27
+ description: Optional[object] = None
28
+ status: dict = field(default_factory=dict)
29
+ last_status: str = ""
30
+ expire_days: int = 0
31
+ usage_bytes: int = 0
32
+ bytes: int = 0
33
+ num_files: int = 0
34
+ is_thread: bool = False
35
+ created: int = 0
36
+ updated: int = 0
37
+ last_active: int = 0
38
+ last_sync: int = 0
39
+ file_ids: list = field(default_factory=list)
40
+
41
+ def __init__(self):
42
+ """Assistant vector store item"""
43
+ self.id = None
44
+ self.record_id = None
45
+ self.uuid = None
46
+ self.name = None
47
+ self.provider = None
48
+ self.description = None
49
+ self.status = {}
50
+ self.last_status = ""
51
+ self.expire_days = 0
52
+ self.usage_bytes = 0
53
+ self.bytes = 0
54
+ self.num_files = 0
55
+ self.is_thread = False
56
+ self.created = int(time.time())
57
+ self.updated = int(time.time())
58
+ self.last_active = int(time.time())
59
+ self.last_sync = int(time.time())
60
+
61
+ def reset(self):
62
+ """Reset store"""
63
+ self.id = None
64
+ self.record_id = None
65
+ self.uuid = None
66
+ self.name = None
67
+ self.provider = None
68
+ self.description = None
69
+ self.status = {}
70
+ self.last_status = ""
71
+ self.expire_days = 0
72
+ self.usage_bytes = 0
73
+ self.num_files = 0
74
+ self.bytes = 0
75
+ self.is_thread = False
76
+ self.last_active = int(time.time())
77
+ self.last_sync = int(time.time())
78
+
79
+ def to_dict(self) -> dict:
80
+ """
81
+ Return as dictionary
82
+
83
+ :return: dictionary
84
+ """
85
+ return {
86
+ "id": self.id,
87
+ "uuid": self.uuid,
88
+ "name": self.name,
89
+ "provider": self.provider,
90
+ "description": self.description,
91
+ "last_status": self.last_status,
92
+ "expire_days": self.expire_days,
93
+ "usage_bytes": self.usage_bytes,
94
+ "num_files": self.num_files,
95
+ "status": self.status,
96
+ "is_thread": self.is_thread,
97
+ }
98
+
99
+ def from_dict(self, data: dict):
100
+ """
101
+ Load from dictionary
102
+
103
+ :param data: dictionary
104
+ """
105
+ self.id = data.get('id', None)
106
+ self.name = data.get('name', None)
107
+ self.provider = data.get('provider', None)
108
+ self.uuid = data.get('uuid', None)
109
+ self.expire_days = data.get('expire_days', 0)
110
+ self.status = data.get('status', {})
111
+
112
+ def get_file_count(self):
113
+ """
114
+ Return number of files in store
115
+
116
+ :return: number of files
117
+ """
118
+ num = self.num_files
119
+ if self.status and isinstance(self.status, dict) and 'file_counts' in self.status:
120
+ if 'completed' in self.status['file_counts']:
121
+ num = int(self.status['file_counts']['completed'] or 0)
122
+ return num
123
+
124
+ def dump(self) -> str:
125
+ """
126
+ Dump item to string
127
+
128
+ :return: serialized item
129
+ """
130
+ try:
131
+ return json.dumps(self.to_dict())
132
+ except Exception as e:
133
+ pass
134
+ return ""
135
+
136
+ def __str__(self):
137
+ """To string"""
138
+ return self.dump()
139
+
140
+
141
+ @dataclass(slots=True)
142
+ class RemoteFileItem:
143
+ id: Optional[object] = None
144
+ record_id: Optional[object] = None
145
+ name: Optional[object] = None
146
+ provider: Optional[object] = None
147
+ path: Optional[object] = None
148
+ file_id: Optional[object] = None
149
+ store_id: Optional[object] = None
150
+ thread_id: Optional[object] = None
151
+ uuid: Optional[object] = None
152
+ size: int = 0
153
+ created: int = 0
154
+ updated: int = 0
155
+
156
+ def __init__(self):
157
+ """Assistant file item"""
158
+ self.id = None
159
+ self.record_id = None
160
+ self.name = None
161
+ self.provider = None
162
+ self.path = None
163
+ self.file_id = None
164
+ self.store_id = None
165
+ self.thread_id = None
166
+ self.uuid = None
167
+ self.size = 0
168
+ self.created = 0
169
+ self.updated = 0
170
+
171
+ def reset(self):
172
+ """Reset store"""
173
+ self.id = None
174
+ self.record_id = None
175
+ self.name = None
176
+ self.provider = None
177
+ self.path = None
178
+ self.file_id = None
179
+ self.store_id = None
180
+ self.thread_id = None
181
+ self.uuid = None
182
+ self.size = 0
183
+ self.created = 0
184
+ self.updated = 0
185
+
186
+ def to_dict(self) -> dict:
187
+ """
188
+ Return as dictionary
189
+
190
+ :return: dictionary
191
+ """
192
+ return {
193
+ "id": self.id,
194
+ "name": self.name,
195
+ "provider": self.provider,
196
+ "path": self.path,
197
+ "file_id": self.file_id,
198
+ "store_id": self.store_id,
199
+ "thread_id": self.thread_id,
200
+ "uuid": self.uuid,
201
+ "size": self.size,
202
+ "created": self.created,
203
+ "updated": self.updated,
204
+ }
205
+
206
+ def from_dict(self, data: dict):
207
+ """
208
+ Load from dictionary
209
+
210
+ :param data: dictionary
211
+ """
212
+ self.id = data.get('id', None)
213
+ self.name = data.get('name', None)
214
+ self.provider = data.get('provider', None)
215
+ self.path = data.get('path', None)
216
+ self.file_id = data.get('file_id', None)
217
+ self.store_id = data.get('store_id', None)
218
+ self.thread_id = data.get('thread_id', None)
219
+ self.uuid = data.get('uuid', None)
220
+ self.size = data.get('size', 0)
221
+ self.created = data.get('created', 0)
222
+ self.updated = data.get('updated', 0)
223
+
224
+ def dump(self) -> str:
225
+ """
226
+ Dump item to string
227
+
228
+ :return: serialized item
229
+ """
230
+ try:
231
+ return json.dumps(self.to_dict())
232
+ except Exception as e:
233
+ pass
234
+ return ""
235
+
236
+ def __str__(self):
237
+ """To string"""
238
+ return self.dump()
pygpt_net/launcher.py CHANGED
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.19 07:00:00 #
9
+ # Updated Date: 2025.12.31 17:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -50,6 +50,31 @@ class Launcher:
50
50
  self.force_disable_gpu = False
51
51
  self.shortcut_filter = None
52
52
  self.workdir = None
53
+ self._preloader = None
54
+
55
+ @staticmethod
56
+ def _clean_multiprocessing_argv(argv):
57
+ """
58
+ Clear multiprocessing flags from argv
59
+
60
+ :param argv: list of command line arguments
61
+ """
62
+ skip_flags = {
63
+ "--multiprocessing-fork",
64
+ "--multiprocessing-spawn",
65
+ "--billiard-fork",
66
+ "--billiard-spawn",
67
+ }
68
+ skip_prefixes = (
69
+ "parent_pid=",
70
+ "pipe_handle=",
71
+ "forkserver_port=",
72
+ "forkserver_authkey=",
73
+ )
74
+ return [
75
+ a for a in argv
76
+ if a not in skip_flags and not any(a.startswith(p) for p in skip_prefixes)
77
+ ]
53
78
 
54
79
  def setup(self) -> dict:
55
80
  """
@@ -57,59 +82,65 @@ class Launcher:
57
82
 
58
83
  :return: dict with launcher arguments
59
84
  """
60
- parser = argparse.ArgumentParser()
61
- parser.add_argument(
62
- "-d",
63
- "--debug",
64
- required=False,
65
- help="debug mode (0=disabled, 1=info, 2=debug)",
66
- )
67
- parser.add_argument(
68
- "-l",
69
- "--legacy",
70
- required=False,
71
- help="force enable legacy mode (0=disabled, 1=enable)",
72
- )
73
- parser.add_argument(
74
- "-n",
75
- "--disable-gpu",
76
- required=False,
77
- help="force disable OpenGL (1=disabled, 0=enabled)",
78
- )
79
- parser.add_argument(
80
- "-w",
81
- "--workdir",
82
- required=False,
83
- help="force set workdir",
84
- )
85
- args = vars(parser.parse_args())
86
-
87
- # set log level [ERROR|WARNING|INFO|DEBUG]
88
- if "debug" in args and args["debug"] == "1":
89
- print("** Debug mode enabled (1=INFO)")
90
- Debug.init(INFO)
91
- self.debug = True
92
- elif "debug" in args and args["debug"] == "2":
93
- print("** Debug mode enabled (2=DEBUG)")
94
- Debug.init(DEBUG)
95
- self.debug = True
96
- else:
97
- Debug.init(ERROR) # default log level
98
-
99
- # force legacy mode
100
- if "legacy" in args and args["legacy"] == "1":
101
- print("** Force legacy mode enabled")
102
- self.force_legacy = True
103
-
104
- # force disable GPU
105
- if "disable-gpu" in args and args["disable-gpu"] == "1":
106
- print("** Force disable GPU enabled")
107
- self.force_disable_gpu = True
108
-
109
- # force set workdir
110
- if "workdir" in args and args["workdir"] is not None:
111
- # set as environment variable
112
- os.environ["PYGPT_WORKDIR"] = args["workdir"]
85
+ args = {}
86
+ try:
87
+ parser = argparse.ArgumentParser()
88
+ parser.add_argument(
89
+ "-d",
90
+ "--debug",
91
+ required=False,
92
+ help="debug mode (0=disabled, 1=info, 2=debug)",
93
+ )
94
+ parser.add_argument(
95
+ "-l",
96
+ "--legacy",
97
+ required=False,
98
+ help="force enable legacy mode (0=disabled, 1=enable)",
99
+ )
100
+ parser.add_argument(
101
+ "-n",
102
+ "--disable-gpu",
103
+ required=False,
104
+ help="force disable OpenGL (1=disabled, 0=enabled)",
105
+ )
106
+ parser.add_argument(
107
+ "-w",
108
+ "--workdir",
109
+ required=False,
110
+ help="force set workdir",
111
+ )
112
+ safe_argv = self._clean_multiprocessing_argv(sys.argv[1:])
113
+ known, unknown = parser.parse_known_args(safe_argv)
114
+ args = vars(known)
115
+
116
+ # set log level [ERROR|WARNING|INFO|DEBUG]
117
+ if "debug" in args and args["debug"] == "1":
118
+ print("** Debug mode enabled (1=INFO)")
119
+ Debug.init(INFO)
120
+ self.debug = True
121
+ elif "debug" in args and args["debug"] == "2":
122
+ print("** Debug mode enabled (2=DEBUG)")
123
+ Debug.init(DEBUG)
124
+ self.debug = True
125
+ else:
126
+ Debug.init(ERROR) # default log level
127
+
128
+ # force legacy mode
129
+ if "legacy" in args and args["legacy"] == "1":
130
+ print("** Force legacy mode enabled")
131
+ self.force_legacy = True
132
+
133
+ # force disable GPU
134
+ if "disable_gpu" in args and args["disable_gpu"] == "1":
135
+ print("** Force disable GPU enabled")
136
+ self.force_disable_gpu = True
137
+
138
+ # force set workdir
139
+ if "workdir" in args and args["workdir"] is not None:
140
+ # set as environment variable
141
+ os.environ["PYGPT_WORKDIR"] = args["workdir"]
142
+ except Exception as e:
143
+ print(f"** Launcher setup error: {e}")
113
144
 
114
145
  return args
115
146
 
@@ -123,6 +154,13 @@ class Launcher:
123
154
  self.window = MainWindow(self.app, args=args)
124
155
  self.shortcut_filter = GlobalShortcutFilter(self.window)
125
156
 
157
+ # Connect the window "ready" signal to close the splash
158
+ if self._preloader is not None:
159
+ try:
160
+ self.window.appReady.connect(self._on_window_ready, Qt.QueuedConnection)
161
+ except Exception:
162
+ pass
163
+
126
164
  def handle_signal(self, signal_number, frame):
127
165
  """
128
166
  Handle termination signal (SIGTERM, SIGINT)
@@ -136,6 +174,28 @@ class Launcher:
136
174
  print("Shutting down...")
137
175
  self.window.close()
138
176
 
177
+ def attach_preloader(self, preloader):
178
+ """
179
+ Attach external splash controller. The splash will be closed
180
+ when the main window announces readiness.
181
+ """
182
+ self._preloader = preloader
183
+ if self.window is not None:
184
+ try:
185
+ self.window.appReady.connect(self._on_window_ready, Qt.QueuedConnection)
186
+ except Exception:
187
+ pass
188
+
189
+ def _on_window_ready(self):
190
+ """
191
+ Close preloader when the first frame of the main window is ready.
192
+ """
193
+ if self._preloader:
194
+ try:
195
+ self._preloader.close()
196
+ except Exception:
197
+ pass
198
+ self._preloader = None
139
199
 
140
200
  def add_plugin(self, plugin: BasePlugin):
141
201
  """
@@ -290,4 +350,4 @@ class Launcher:
290
350
  # self.window.core.debug.mem("INIT") # debug memory usage
291
351
  signal.signal(signal.SIGTERM, self.handle_signal)
292
352
  signal.signal(signal.SIGINT, self.handle_signal)
293
- sys.exit(self.app.exec())
353
+ sys.exit(self.app.exec())
@@ -0,0 +1,35 @@
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 sqlalchemy import text
13
+
14
+ from .base import BaseMigration
15
+
16
+
17
+ class Version20260102190000(BaseMigration):
18
+ def __init__(self, window=None):
19
+ super(Version20260102190000, self).__init__(window)
20
+ self.window = window
21
+
22
+ def up(self, conn):
23
+ conn.execute(text("""
24
+ ALTER TABLE remote_store ADD COLUMN provider TEXT;
25
+ """))
26
+ conn.execute(text("""
27
+ ALTER TABLE remote_file ADD COLUMN provider TEXT;
28
+ """))
29
+ # set all to OpenAI by default
30
+ conn.execute(text("""
31
+ UPDATE remote_store SET provider = 'openai' WHERE provider IS NULL;
32
+ """))
33
+ conn.execute(text("""
34
+ UPDATE remote_file SET provider = 'openai' WHERE provider IS NULL;
35
+ """))
@@ -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: 2024.12.15 11:00:00 #
9
+ # Updated Date: 2026.01.02 20:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from .Version20231227152900 import Version20231227152900 # 2.0.59
@@ -23,6 +23,7 @@ from .Version20240501030000 import Version20240501030000 # 2.2.7
23
23
  from .Version20241122130000 import Version20241122130000 # 2.4.21
24
24
  from .Version20241126170000 import Version20241126170000 # 2.4.34
25
25
  from .Version20241215110000 import Version20241215110000 # 2.4.43
26
+ from .Version20260102190000 import Version20260102190000 # 2.7.5
26
27
 
27
28
  class Migrations:
28
29
  def __init__(self):
@@ -50,4 +51,5 @@ class Migrations:
50
51
  Version20241122130000(), # 2.4.21
51
52
  Version20241126170000(), # 2.4.34
52
53
  Version20241215110000(), # 2.4.43
54
+ Version20260102190000(), # 2.7.5
53
55
  ]