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.
Files changed (98) hide show
  1. pygpt_net/CHANGELOG.txt +12 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +5 -1
  4. pygpt_net/controller/assistant/batch.py +2 -2
  5. pygpt_net/controller/assistant/files.py +7 -6
  6. pygpt_net/controller/assistant/threads.py +0 -0
  7. pygpt_net/controller/chat/command.py +0 -0
  8. pygpt_net/controller/dialogs/confirm.py +35 -58
  9. pygpt_net/controller/lang/mapping.py +9 -9
  10. pygpt_net/controller/realtime/realtime.py +13 -1
  11. pygpt_net/controller/remote_store/{google/batch.py → batch.py} +209 -252
  12. pygpt_net/controller/remote_store/remote_store.py +982 -13
  13. pygpt_net/core/command/command.py +0 -0
  14. pygpt_net/core/db/viewer.py +1 -1
  15. pygpt_net/core/realtime/worker.py +3 -1
  16. pygpt_net/{controller/remote_store/google → core/remote_store/anthropic}/__init__.py +0 -1
  17. pygpt_net/core/remote_store/anthropic/files.py +211 -0
  18. pygpt_net/core/remote_store/anthropic/store.py +208 -0
  19. pygpt_net/core/remote_store/openai/store.py +5 -4
  20. pygpt_net/core/remote_store/remote_store.py +5 -1
  21. pygpt_net/{controller/remote_store/openai → core/remote_store/xai}/__init__.py +0 -1
  22. pygpt_net/core/remote_store/xai/files.py +225 -0
  23. pygpt_net/core/remote_store/xai/store.py +219 -0
  24. pygpt_net/data/config/config.json +10 -6
  25. pygpt_net/data/config/models.json +38 -22
  26. pygpt_net/data/config/settings.json +54 -1
  27. pygpt_net/data/icons/folder_eye.svg +1 -0
  28. pygpt_net/data/icons/folder_eye_filled.svg +1 -0
  29. pygpt_net/data/icons/folder_open.svg +1 -0
  30. pygpt_net/data/icons/folder_open_filled.svg +1 -0
  31. pygpt_net/data/locale/locale.de.ini +4 -3
  32. pygpt_net/data/locale/locale.en.ini +14 -4
  33. pygpt_net/data/locale/locale.es.ini +4 -3
  34. pygpt_net/data/locale/locale.fr.ini +4 -3
  35. pygpt_net/data/locale/locale.it.ini +4 -3
  36. pygpt_net/data/locale/locale.pl.ini +5 -4
  37. pygpt_net/data/locale/locale.uk.ini +4 -3
  38. pygpt_net/data/locale/locale.zh.ini +4 -3
  39. pygpt_net/icons.qrc +4 -0
  40. pygpt_net/icons_rc.py +282 -138
  41. pygpt_net/provider/api/anthropic/__init__.py +2 -0
  42. pygpt_net/provider/api/anthropic/chat.py +84 -1
  43. pygpt_net/provider/api/anthropic/store.py +307 -0
  44. pygpt_net/provider/api/anthropic/stream.py +75 -0
  45. pygpt_net/provider/api/anthropic/worker/__init__.py +0 -0
  46. pygpt_net/provider/api/anthropic/worker/importer.py +278 -0
  47. pygpt_net/provider/api/google/chat.py +59 -2
  48. pygpt_net/provider/api/google/realtime/client.py +70 -24
  49. pygpt_net/provider/api/google/realtime/realtime.py +48 -12
  50. pygpt_net/provider/api/google/store.py +124 -3
  51. pygpt_net/provider/api/google/stream.py +91 -24
  52. pygpt_net/provider/api/google/worker/importer.py +16 -28
  53. pygpt_net/provider/api/openai/assistants.py +2 -2
  54. pygpt_net/provider/api/openai/realtime/realtime.py +26 -6
  55. pygpt_net/provider/api/openai/store.py +4 -1
  56. pygpt_net/provider/api/openai/worker/importer.py +19 -61
  57. pygpt_net/provider/api/openai/worker/importer_assistants.py +230 -0
  58. pygpt_net/provider/api/x_ai/__init__.py +27 -6
  59. pygpt_net/provider/api/x_ai/audio.py +43 -11
  60. pygpt_net/provider/api/x_ai/chat.py +92 -4
  61. pygpt_net/provider/api/x_ai/realtime/__init__.py +12 -0
  62. pygpt_net/provider/api/x_ai/realtime/client.py +1864 -0
  63. pygpt_net/provider/api/x_ai/realtime/realtime.py +213 -0
  64. pygpt_net/provider/api/x_ai/remote_tools.py +102 -1
  65. pygpt_net/provider/api/x_ai/store.py +610 -0
  66. pygpt_net/provider/api/x_ai/stream.py +30 -9
  67. pygpt_net/provider/api/x_ai/tools.py +51 -0
  68. pygpt_net/provider/api/x_ai/worker/importer.py +308 -0
  69. pygpt_net/provider/audio_input/xai_grok_voice.py +390 -0
  70. pygpt_net/provider/audio_output/xai_tts.py +325 -0
  71. pygpt_net/provider/core/config/patch.py +29 -3
  72. pygpt_net/provider/core/config/patches/patch_before_2_6_42.py +2 -2
  73. pygpt_net/provider/core/model/patch.py +49 -1
  74. pygpt_net/tools/image_viewer/tool.py +334 -34
  75. pygpt_net/tools/image_viewer/ui/dialogs.py +317 -21
  76. pygpt_net/ui/dialog/assistant.py +1 -1
  77. pygpt_net/ui/dialog/plugins.py +13 -5
  78. pygpt_net/ui/dialog/remote_store.py +552 -0
  79. pygpt_net/ui/dialogs.py +3 -5
  80. pygpt_net/ui/layout/ctx/ctx_list.py +58 -7
  81. pygpt_net/ui/menu/tools.py +6 -13
  82. pygpt_net/ui/widget/dialog/{remote_store_google.py → remote_store.py} +10 -10
  83. pygpt_net/ui/widget/element/button.py +4 -4
  84. pygpt_net/ui/widget/image/display.py +2 -2
  85. pygpt_net/ui/widget/lists/context.py +2 -2
  86. {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/METADATA +14 -2
  87. {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/RECORD +87 -75
  88. pygpt_net/controller/remote_store/google/store.py +0 -615
  89. pygpt_net/controller/remote_store/openai/batch.py +0 -524
  90. pygpt_net/controller/remote_store/openai/store.py +0 -699
  91. pygpt_net/ui/dialog/remote_store_google.py +0 -539
  92. pygpt_net/ui/dialog/remote_store_openai.py +0 -539
  93. pygpt_net/ui/widget/dialog/remote_store_openai.py +0 -56
  94. pygpt_net/ui/widget/lists/remote_store_google.py +0 -248
  95. pygpt_net/ui/widget/lists/remote_store_openai.py +0 -317
  96. {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/LICENSE +0 -0
  97. {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/WHEEL +0 -0
  98. {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/entry_points.txt +0 -0
pygpt_net/CHANGELOG.txt CHANGED
@@ -1,3 +1,15 @@
1
+ 2.7.9 (2026-01-08)
2
+
3
+ - Improved realtime audio mode.
4
+ - Added xAI provider and Grok support in realtime audio mode.
5
+
6
+ 2.7.8 (2026-01-06)
7
+
8
+ - Added the xAI Collections remote tool and integrated collections management into the Remote Vector Stores tool.
9
+ - Unified the Remote Vector Stores tool into a single tool for all providers.
10
+ - Added xAI Grok audio input and output provider (realtime audio support for Grok coming soon!).
11
+ - Enhanced the Image Viewer tool with a toolbox featuring Prev/Next and more options.
12
+
1
13
  2.7.7 (2026-01-05)
2
14
 
3
15
  - Added support for Responses API in xAI.
pygpt_net/__init__.py CHANGED
@@ -6,15 +6,15 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2026-01-05 00:00:00 #
9
+ # Updated Date: 2026-01-08 00:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  __author__ = "Marcin Szczygliński"
13
13
  __copyright__ = "Copyright 2026, Marcin Szczygliński"
14
14
  __credits__ = ["Marcin Szczygliński"]
15
15
  __license__ = "MIT"
16
- __version__ = "2.7.7"
17
- __build__ = "2026-01-05"
16
+ __version__ = "2.7.9"
17
+ __build__ = "2026-01-08"
18
18
  __maintainer__ = "Marcin Szczygliński"
19
19
  __github__ = "https://github.com/szczyglis-dev/py-gpt"
20
20
  __report__ = "https://github.com/szczyglis-dev/py-gpt/issues"
pygpt_net/app.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.12.31 17:00:00 #
9
+ # Updated Date: 2026.01.06 20:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -329,11 +329,13 @@ def run(**kwargs):
329
329
  from pygpt_net.provider.audio_input.google_cloud_speech_recognition import GoogleCloudSpeechRecognition
330
330
  from pygpt_net.provider.audio_input.google_genai import GoogleGenAIAudioInput
331
331
  from pygpt_net.provider.audio_input.bing_speech_recognition import BingSpeechRecognition
332
+ from pygpt_net.provider.audio_input.xai_grok_voice import XAIGrokVoiceAudioInput
332
333
  from pygpt_net.provider.audio_output.openai_tts import OpenAITextToSpeech
333
334
  from pygpt_net.provider.audio_output.ms_azure_tts import MSAzureTextToSpeech
334
335
  from pygpt_net.provider.audio_output.google_tts import GoogleTextToSpeech
335
336
  from pygpt_net.provider.audio_output.google_genai_tts import GoogleGenAITextToSpeech
336
337
  from pygpt_net.provider.audio_output.eleven_labs import ElevenLabsTextToSpeech
338
+ from pygpt_net.provider.audio_output.xai_tts import XAITextToSpeech
337
339
 
338
340
  # web search engine providers
339
341
  from pygpt_net.provider.web.google_custom_search import GoogleCustomSearch
@@ -361,11 +363,13 @@ def run(**kwargs):
361
363
  launcher.add_audio_input(GoogleCloudSpeechRecognition())
362
364
  launcher.add_audio_input(GoogleGenAIAudioInput())
363
365
  launcher.add_audio_input(BingSpeechRecognition())
366
+ launcher.add_audio_input(XAIGrokVoiceAudioInput())
364
367
  launcher.add_audio_output(OpenAITextToSpeech())
365
368
  launcher.add_audio_output(MSAzureTextToSpeech())
366
369
  launcher.add_audio_output(GoogleTextToSpeech())
367
370
  launcher.add_audio_output(GoogleGenAITextToSpeech())
368
371
  launcher.add_audio_output(ElevenLabsTextToSpeech())
372
+ launcher.add_audio_output(XAITextToSpeech())
369
373
 
370
374
  # register custom audio providers
371
375
  providers = kwargs.get('audio_input', None)
@@ -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: 2026.01.02 19:00:00 #
9
+ # Updated Date: 2026.01.05 17:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Any
@@ -49,7 +49,7 @@ class Batch:
49
49
  :param num: number of imported assistants
50
50
  """
51
51
  self.window.controller.assistant.update()
52
- self.window.controller.remote_store.openai.update()
52
+ self.window.controller.remote_store.update()
53
53
  self.window.controller.assistant.files.update()
54
54
  self.window.update_status("OK. Imported assistants: " + str(num) + ".")
55
55
  self.window.ui.dialogs.alert(trans("status.finished"))
@@ -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: 2026.01.02 19:00:00 #
9
+ # Updated Date: 2026.01.05 17:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -31,7 +31,7 @@ class Files:
31
31
  def update(self):
32
32
  """Update assistants files list"""
33
33
  self.update_list()
34
- self.window.controller.remote_store.openai.update_files_list()
34
+ self.window.controller.remote_store.update_files_list()
35
35
 
36
36
  def select(self, idx: int):
37
37
  """
@@ -76,7 +76,7 @@ class Files:
76
76
  """
77
77
  # run asynchronous
78
78
  self.window.update_status("Importing files...please wait...")
79
- self.window.core.api.openai.assistants.importer.import_files(store_id)
79
+ self.window.core.api.openai.store.importer.import_files(store_id)
80
80
 
81
81
  def download(self, idx: Union[int, list]):
82
82
  """
@@ -181,7 +181,8 @@ class Files:
181
181
 
182
182
  # update store status
183
183
  if assistant.vector_store:
184
- self.window.controller.remote_store.openai.refresh_by_store_id(assistant.vector_store)
184
+ # TODO: only openai
185
+ self.window.controller.remote_store.refresh_by_store_id(assistant.vector_store, "openai")
185
186
 
186
187
  self.window.update_status(trans('status.deleted'))
187
188
 
@@ -228,7 +229,7 @@ class Files:
228
229
 
229
230
  # update store status
230
231
  if assistant.vector_store:
231
- self.window.controller.remote_store.openai.refresh_by_store_id(assistant.vector_store)
232
+ self.window.controller.remote_store.refresh_by_store_id(assistant.vector_store, "openai")
232
233
 
233
234
  self.window.update_status(trans('status.deleted'))
234
235
  except Exception as e:
@@ -341,7 +342,7 @@ class Files:
341
342
  if num > 0:
342
343
  # update store status
343
344
  if assistant.vector_store:
344
- self.window.controller.remote_store.openai.refresh_by_store_id(assistant.vector_store)
345
+ self.window.controller.remote_store.refresh_by_store_id(assistant.vector_store, "openai")
345
346
 
346
347
  self.update_list() # update uploaded list UI
347
348
 
File without changes
File without changes
@@ -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: 2026.01.02 20:00:00 #
9
+ # Updated Date: 2026.01.05 17:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Any, Optional
@@ -195,61 +195,38 @@ class Confirm:
195
195
  elif type == 'assistant.functions.clear':
196
196
  self.window.controller.assistant.editor.clear_functions(True)
197
197
 
198
- # OpenAI vector stores
199
- elif type == 'remote_store.openai.file.delete':
200
- self.window.controller.remote_store.openai.delete_file_by_idx(id, True)
201
- elif type == 'remote_store.openai.delete':
202
- self.window.controller.remote_store.openai.delete(id, True)
203
- elif type == 'remote_store.openai.import':
204
- self.window.controller.remote_store.openai.batch.import_stores(True)
205
- elif type == 'remote_store.openai.truncate':
206
- self.window.controller.remote_store.openai.batch.truncate_stores(True)
207
- elif type == 'remote_store.openai.clear':
208
- self.window.controller.remote_store.openai.batch.clear_stores(True)
209
- elif type == 'remote_store.openai.refresh':
210
- self.window.controller.remote_store.openai.batch.refresh_stores(True)
211
- elif type == 'remote_store.openai.files.import.all':
212
- self.window.controller.remote_store.openai.batch.import_files(True)
213
- elif type == 'remote_store.openai.files.import.store':
214
- self.window.controller.remote_store.openai.batch.import_store_files(id, True)
215
- elif type == 'remote_store.openai.files.truncate':
216
- self.window.controller.remote_store.openai.batch.truncate_files(True)
217
- elif type == 'remote_store.openai.files.truncate.store':
218
- self.window.controller.remote_store.openai.batch.truncate_store_files(id, True)
219
- elif type == 'remote_store.openai.files.clear.all':
220
- self.window.controller.remote_store.openai.batch.clear_files(True)
221
- elif type == 'remote_store.openai.files.clear.store':
222
- self.window.controller.remote_store.openai.batch.clear_store_files(id, True)
223
- elif type == 'remote_store.openai.files.upload':
224
- self.window.controller.remote_store.openai.batch.upload(True)
225
-
226
- # Google (Gemini) File Search stores
227
- elif type == 'remote_store.google.file.delete':
228
- self.window.controller.remote_store.google.delete_file_by_idx(id, True)
229
- elif type == 'remote_store.google.delete':
230
- self.window.controller.remote_store.google.delete(id, True)
231
- elif type == 'remote_store.google.import':
232
- self.window.controller.remote_store.google.batch.import_stores(True)
233
- elif type == 'remote_store.google.truncate':
234
- self.window.controller.remote_store.google.batch.truncate_stores(True)
235
- elif type == 'remote_store.google.clear':
236
- self.window.controller.remote_store.google.batch.clear_stores(True)
237
- elif type == 'remote_store.google.refresh':
238
- self.window.controller.remote_store.google.batch.refresh_stores(True)
239
- elif type == 'remote_store.google.files.import.all':
240
- self.window.controller.remote_store.google.batch.import_files(True)
241
- elif type == 'remote_store.google.files.import.store':
242
- self.window.controller.remote_store.google.batch.import_store_files(id, True)
243
- elif type == 'remote_store.google.files.truncate':
244
- self.window.controller.remote_store.google.batch.truncate_files(True)
245
- elif type == 'remote_store.google.files.truncate.store':
246
- self.window.controller.remote_store.google.batch.truncate_store_files(id, True)
247
- elif type == 'remote_store.google.files.clear.all':
248
- self.window.controller.remote_store.google.batch.clear_files(True)
249
- elif type == 'remote_store.google.files.clear.store':
250
- self.window.controller.remote_store.google.batch.clear_store_files(id, True)
251
- elif type == 'remote_store.google.files.upload':
252
- self.window.controller.remote_store.google.batch.upload(True)
198
+ # Remote vector stores
199
+ elif type == 'remote_store.delete':
200
+ self.window.controller.remote_store.delete(id, True)
201
+ elif type == 'remote_store.import':
202
+ self.window.controller.remote_store.batch.import_stores(True)
203
+ elif type == 'remote_store.truncate':
204
+ self.window.controller.remote_store.batch.truncate_stores(True)
205
+ elif type == 'remote_store.clear':
206
+ self.window.controller.remote_store.batch.clear_stores(True)
207
+ elif type == 'remote_store.refresh':
208
+ self.window.controller.remote_store.batch.refresh_stores(True)
209
+
210
+ elif type == 'remote_store.file.delete':
211
+ self.window.controller.remote_store.delete_file_by_idx(id, True)
212
+ elif type == 'remote_store.files.upload':
213
+ self.window.controller.remote_store.batch.upload(True)
214
+ elif type == 'remote_store.files.import.all':
215
+ self.window.controller.remote_store.batch.import_files(True)
216
+ elif type == 'remote_store.files.import.store':
217
+ self.window.controller.remote_store.batch.import_store_files(id, True)
218
+ elif type == 'remote_store.files.import.assistant.current':
219
+ self.window.controller.remote_store.batch.import_files_assistant_current(True) # from current assistant
220
+ elif type == 'remote_store.files.import.assistant.all':
221
+ self.window.controller.remote_store.batch.import_files_assistant_all(True) # from all assistants
222
+ elif type == 'remote_store.files.truncate':
223
+ self.window.controller.remote_store.batch.truncate_files(True)
224
+ elif type == 'remote_store.files.truncate.store':
225
+ self.window.controller.remote_store.batch.truncate_store_files(id, True)
226
+ elif type == 'remote_store.files.clear.all':
227
+ self.window.controller.remote_store.batch.clear_files(True)
228
+ elif type == 'remote_store.files.clear.store':
229
+ self.window.controller.remote_store.batch.clear_store_files(id, True)
253
230
 
254
231
  # settings
255
232
  elif type == 'settings.defaults.user':
@@ -390,8 +367,8 @@ class Confirm:
390
367
  self.window.controller.ctx.create_group(name, id)
391
368
  elif type == 'agent.builder.agent':
392
369
  self.window.tools.get("agent_builder").add_agent(name)
393
- elif type == 'remote_store.google.new':
394
- self.window.controller.remote_store.google.new(name, True)
370
+ elif type == 'remote_store.new':
371
+ self.window.controller.remote_store.new(name, True)
395
372
 
396
373
  def accept_url(self, type: str, id: any, url: str):
397
374
  """
@@ -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: 2026.01.02 20:00:00 #
9
+ # Updated Date: 2026.01.05 17:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Dict
@@ -164,12 +164,12 @@ class Mapping:
164
164
  nodes['assistant.tool.function.label'] = 'assistant.functions.label'
165
165
 
166
166
  # assistants: vector store
167
- nodes['remote_store.openai.btn.new'] = 'dialog.remote_store.btn.new'
168
- nodes['remote_store.openai.btn.save'] = 'dialog.remote_store.btn.save'
169
- nodes['remote_store.openai.btn.upload.files'] = 'dialog.remote_store.btn.upload.files'
170
- nodes['remote_store.openai.btn.upload.dir'] = 'dialog.remote_store.btn.upload.dir'
171
- nodes['remote_store.openai.btn.close'] = 'dialog.remote_store.btn.close'
172
- nodes['remote_store.openai.hide_thread'] = 'remote_store.openai.hide_threads'
167
+ nodes['remote_store.btn.new'] = 'dialog.remote_store.btn.new'
168
+ nodes['remote_store.btn.save'] = 'dialog.remote_store.btn.save'
169
+ nodes['remote_store.btn.upload.files'] = 'dialog.remote_store.btn.upload.files'
170
+ nodes['remote_store.btn.upload.dir'] = 'dialog.remote_store.btn.upload.dir'
171
+ nodes['remote_store.btn.close'] = 'dialog.remote_store.btn.close'
172
+ nodes['remote_store.hide_thread'] = 'remote_store.hide_threads'
173
173
 
174
174
  # vision
175
175
  nodes['inline.vision'] = 'inline.vision'
@@ -402,7 +402,7 @@ class Mapping:
402
402
  dialog_title['config.editor'] = 'dialog.editor.title'
403
403
  dialog_title['config.settings'] = 'dialog.settings'
404
404
  dialog_title['editor.assistants'] = 'dialog.assistant'
405
- dialog_title['remote_store.openai'] = 'dialog.remote_store.openai'
405
+ dialog_title['remote_store'] = 'dialog.remote_store'
406
406
  dialog_title['editor.preset.presets'] = 'dialog.preset'
407
407
  dialog_title['image'] = 'dialog.image.title'
408
408
  dialog_title['interpreter'] = 'dialog.interpreter.title'
@@ -424,7 +424,7 @@ class Mapping:
424
424
  tooltips['icon.audio.output'] = 'icon.audio.output'
425
425
  tooltips['icon.audio.input'] = 'icon.audio.input'
426
426
  tooltips['icon.remote_tool.web'] = 'icon.remote_tool.web'
427
- tooltips['remote_store.openai.btn.refresh_status'] = 'dialog.remote_store.btn.refresh_status'
427
+ tooltips['remote_store.btn.refresh_status'] = 'dialog.remote_store.btn.refresh_status'
428
428
  tooltips['agent.llama.loop.score'] = 'toolbox.agent.llama.loop.score.tooltip'
429
429
 
430
430
  menu_tooltips = {}
@@ -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.09.17 07:00:00 #
9
+ # Updated Date: 2026.01.07 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Slot, QTimer
@@ -87,6 +87,8 @@ class Realtime:
87
87
  self.window.core.api.google.realtime.handle_audio_input(event)
88
88
  elif self.current_active == "openai":
89
89
  self.window.core.api.openai.realtime.handle_audio_input(event)
90
+ elif self.current_active == "x_ai":
91
+ self.window.core.api.xai.realtime.handle_audio_input(event)
90
92
 
91
93
  # begin: first text chunk or audio chunk received, start rendering
92
94
  elif event.name == RealtimeEvent.RT_OUTPUT_READY:
@@ -216,6 +218,8 @@ class Realtime:
216
218
  self.window.core.api.google.realtime.manual_commit()
217
219
  elif self.current_active == "openai":
218
220
  self.window.core.api.openai.realtime.manual_commit()
221
+ elif self.current_active == "x_ai":
222
+ self.window.core.api.xai.realtime.manual_commit()
219
223
 
220
224
  def end_turn(self, ctx):
221
225
  """
@@ -252,6 +256,10 @@ class Realtime:
252
256
  self.window.core.api.google.realtime.shutdown()
253
257
  except Exception as e:
254
258
  self.window.core.debug.log(f"[google] Realtime shutdown error: {e}")
259
+ try:
260
+ self.window.core.api.xai.realtime.shutdown()
261
+ except Exception as e:
262
+ self.window.core.debug.log(f"[xAI] Realtime shutdown error: {e}")
255
263
  try:
256
264
  self.manager.shutdown()
257
265
  except Exception as e:
@@ -267,6 +275,10 @@ class Realtime:
267
275
  self.window.core.api.google.realtime.reset()
268
276
  except Exception as e:
269
277
  self.window.core.debug.log(f"[google] Realtime reset error: {e}")
278
+ try:
279
+ self.window.core.api.xai.realtime.reset()
280
+ except Exception as e:
281
+ self.window.core.debug.log(f"[xAI] Realtime reset error: {e}")
270
282
 
271
283
  def is_supported(self) -> bool:
272
284
  """