pygpt-net 2.6.29__py3-none-any.whl → 2.6.31__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 (182) hide show
  1. pygpt_net/CHANGELOG.txt +15 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +4 -0
  4. pygpt_net/{container.py → app_core.py} +5 -6
  5. pygpt_net/controller/__init__.py +5 -2
  6. pygpt_net/controller/access/control.py +1 -9
  7. pygpt_net/controller/assistant/assistant.py +4 -4
  8. pygpt_net/controller/assistant/batch.py +7 -7
  9. pygpt_net/controller/assistant/files.py +4 -4
  10. pygpt_net/controller/assistant/threads.py +3 -3
  11. pygpt_net/controller/attachment/attachment.py +4 -7
  12. pygpt_net/controller/audio/audio.py +25 -1
  13. pygpt_net/controller/audio/ui.py +2 -2
  14. pygpt_net/controller/chat/audio.py +1 -8
  15. pygpt_net/controller/chat/common.py +30 -4
  16. pygpt_net/controller/chat/handler/stream_worker.py +1124 -0
  17. pygpt_net/controller/chat/output.py +8 -3
  18. pygpt_net/controller/chat/stream.py +4 -405
  19. pygpt_net/controller/chat/text.py +3 -2
  20. pygpt_net/controller/chat/vision.py +11 -19
  21. pygpt_net/controller/config/placeholder.py +1 -1
  22. pygpt_net/controller/ctx/ctx.py +1 -1
  23. pygpt_net/controller/ctx/summarizer.py +1 -1
  24. pygpt_net/controller/kernel/kernel.py +11 -3
  25. pygpt_net/controller/kernel/reply.py +5 -1
  26. pygpt_net/controller/mode/mode.py +21 -12
  27. pygpt_net/controller/plugins/settings.py +3 -2
  28. pygpt_net/controller/presets/editor.py +112 -99
  29. pygpt_net/controller/realtime/__init__.py +12 -0
  30. pygpt_net/controller/realtime/manager.py +53 -0
  31. pygpt_net/controller/realtime/realtime.py +268 -0
  32. pygpt_net/controller/theme/theme.py +3 -2
  33. pygpt_net/controller/ui/mode.py +7 -0
  34. pygpt_net/controller/ui/ui.py +19 -1
  35. pygpt_net/controller/ui/vision.py +4 -4
  36. pygpt_net/core/agents/legacy.py +2 -2
  37. pygpt_net/core/agents/runners/openai_workflow.py +2 -2
  38. pygpt_net/core/assistants/files.py +5 -5
  39. pygpt_net/core/assistants/store.py +4 -4
  40. pygpt_net/core/audio/audio.py +6 -1
  41. pygpt_net/core/audio/backend/native/__init__.py +12 -0
  42. pygpt_net/core/audio/backend/{native.py → native/native.py} +426 -127
  43. pygpt_net/core/audio/backend/native/player.py +139 -0
  44. pygpt_net/core/audio/backend/native/realtime.py +250 -0
  45. pygpt_net/core/audio/backend/pyaudio/__init__.py +12 -0
  46. pygpt_net/core/audio/backend/pyaudio/playback.py +194 -0
  47. pygpt_net/core/audio/backend/pyaudio/pyaudio.py +923 -0
  48. pygpt_net/core/audio/backend/pyaudio/realtime.py +275 -0
  49. pygpt_net/core/audio/backend/pygame/__init__.py +12 -0
  50. pygpt_net/core/audio/backend/{pygame.py → pygame/pygame.py} +130 -19
  51. pygpt_net/core/audio/backend/shared/__init__.py +38 -0
  52. pygpt_net/core/audio/backend/shared/conversions.py +211 -0
  53. pygpt_net/core/audio/backend/shared/envelope.py +38 -0
  54. pygpt_net/core/audio/backend/shared/player.py +137 -0
  55. pygpt_net/core/audio/backend/shared/rt.py +52 -0
  56. pygpt_net/core/audio/capture.py +5 -0
  57. pygpt_net/core/audio/output.py +13 -2
  58. pygpt_net/core/audio/whisper.py +6 -2
  59. pygpt_net/core/bridge/bridge.py +4 -3
  60. pygpt_net/core/bridge/worker.py +31 -9
  61. pygpt_net/core/debug/console/console.py +2 -2
  62. pygpt_net/core/debug/presets.py +2 -2
  63. pygpt_net/core/dispatcher/dispatcher.py +37 -1
  64. pygpt_net/core/events/__init__.py +2 -1
  65. pygpt_net/core/events/realtime.py +55 -0
  66. pygpt_net/core/experts/experts.py +2 -2
  67. pygpt_net/core/image/image.py +51 -1
  68. pygpt_net/core/modes/modes.py +2 -2
  69. pygpt_net/core/presets/presets.py +3 -3
  70. pygpt_net/core/realtime/options.py +87 -0
  71. pygpt_net/core/realtime/shared/__init__.py +0 -0
  72. pygpt_net/core/realtime/shared/audio.py +213 -0
  73. pygpt_net/core/realtime/shared/loop.py +64 -0
  74. pygpt_net/core/realtime/shared/session.py +59 -0
  75. pygpt_net/core/realtime/shared/text.py +37 -0
  76. pygpt_net/core/realtime/shared/tools.py +276 -0
  77. pygpt_net/core/realtime/shared/turn.py +38 -0
  78. pygpt_net/core/realtime/shared/types.py +16 -0
  79. pygpt_net/core/realtime/worker.py +164 -0
  80. pygpt_net/core/tokens/tokens.py +4 -4
  81. pygpt_net/core/types/__init__.py +1 -0
  82. pygpt_net/core/types/image.py +48 -0
  83. pygpt_net/core/types/mode.py +5 -2
  84. pygpt_net/core/vision/analyzer.py +1 -1
  85. pygpt_net/data/config/config.json +13 -4
  86. pygpt_net/data/config/models.json +219 -101
  87. pygpt_net/data/config/modes.json +3 -9
  88. pygpt_net/data/config/settings.json +135 -27
  89. pygpt_net/data/config/settings_section.json +2 -2
  90. pygpt_net/data/locale/locale.de.ini +7 -7
  91. pygpt_net/data/locale/locale.en.ini +25 -12
  92. pygpt_net/data/locale/locale.es.ini +7 -7
  93. pygpt_net/data/locale/locale.fr.ini +7 -7
  94. pygpt_net/data/locale/locale.it.ini +7 -7
  95. pygpt_net/data/locale/locale.pl.ini +8 -8
  96. pygpt_net/data/locale/locale.uk.ini +7 -7
  97. pygpt_net/data/locale/locale.zh.ini +3 -3
  98. pygpt_net/data/locale/plugin.audio_input.en.ini +4 -0
  99. pygpt_net/data/locale/plugin.audio_output.en.ini +4 -0
  100. pygpt_net/item/model.py +23 -3
  101. pygpt_net/plugin/audio_input/plugin.py +37 -4
  102. pygpt_net/plugin/audio_input/simple.py +57 -8
  103. pygpt_net/plugin/cmd_files/worker.py +3 -0
  104. pygpt_net/plugin/openai_dalle/plugin.py +4 -4
  105. pygpt_net/plugin/openai_vision/plugin.py +12 -13
  106. pygpt_net/provider/agents/openai/agent.py +5 -5
  107. pygpt_net/provider/agents/openai/agent_b2b.py +5 -5
  108. pygpt_net/provider/agents/openai/agent_planner.py +5 -6
  109. pygpt_net/provider/agents/openai/agent_with_experts.py +5 -5
  110. pygpt_net/provider/agents/openai/agent_with_experts_feedback.py +4 -4
  111. pygpt_net/provider/agents/openai/agent_with_feedback.py +4 -4
  112. pygpt_net/provider/agents/openai/bot_researcher.py +2 -2
  113. pygpt_net/provider/agents/openai/bots/research_bot/agents/planner_agent.py +1 -1
  114. pygpt_net/provider/agents/openai/bots/research_bot/agents/search_agent.py +1 -1
  115. pygpt_net/provider/agents/openai/bots/research_bot/agents/writer_agent.py +1 -1
  116. pygpt_net/provider/agents/openai/evolve.py +5 -5
  117. pygpt_net/provider/agents/openai/supervisor.py +4 -4
  118. pygpt_net/provider/api/__init__.py +27 -0
  119. pygpt_net/provider/api/anthropic/__init__.py +68 -0
  120. pygpt_net/provider/api/google/__init__.py +295 -0
  121. pygpt_net/provider/api/google/audio.py +121 -0
  122. pygpt_net/provider/api/google/chat.py +591 -0
  123. pygpt_net/provider/api/google/image.py +427 -0
  124. pygpt_net/provider/api/google/realtime/__init__.py +12 -0
  125. pygpt_net/provider/api/google/realtime/client.py +1945 -0
  126. pygpt_net/provider/api/google/realtime/realtime.py +186 -0
  127. pygpt_net/provider/api/google/tools.py +222 -0
  128. pygpt_net/provider/api/google/vision.py +129 -0
  129. pygpt_net/provider/{gpt → api/openai}/__init__.py +24 -4
  130. pygpt_net/provider/api/openai/agents/__init__.py +0 -0
  131. pygpt_net/provider/{gpt → api/openai}/agents/computer.py +1 -1
  132. pygpt_net/provider/{gpt → api/openai}/agents/experts.py +1 -1
  133. pygpt_net/provider/{gpt → api/openai}/agents/response.py +1 -1
  134. pygpt_net/provider/{gpt → api/openai}/assistants.py +1 -1
  135. pygpt_net/provider/{gpt → api/openai}/chat.py +15 -8
  136. pygpt_net/provider/{gpt → api/openai}/completion.py +1 -1
  137. pygpt_net/provider/{gpt → api/openai}/image.py +1 -1
  138. pygpt_net/provider/api/openai/realtime/__init__.py +12 -0
  139. pygpt_net/provider/api/openai/realtime/client.py +1828 -0
  140. pygpt_net/provider/api/openai/realtime/realtime.py +194 -0
  141. pygpt_net/provider/{gpt → api/openai}/remote_tools.py +1 -1
  142. pygpt_net/provider/{gpt → api/openai}/responses.py +34 -20
  143. pygpt_net/provider/{gpt → api/openai}/store.py +2 -2
  144. pygpt_net/provider/{gpt → api/openai}/vision.py +1 -1
  145. pygpt_net/provider/api/openai/worker/__init__.py +0 -0
  146. pygpt_net/provider/{gpt → api/openai}/worker/assistants.py +4 -4
  147. pygpt_net/provider/{gpt → api/openai}/worker/importer.py +10 -10
  148. pygpt_net/provider/audio_input/google_genai.py +103 -0
  149. pygpt_net/provider/audio_input/openai_whisper.py +1 -1
  150. pygpt_net/provider/audio_output/google_genai_tts.py +229 -0
  151. pygpt_net/provider/audio_output/openai_tts.py +9 -6
  152. pygpt_net/provider/core/config/patch.py +26 -0
  153. pygpt_net/provider/core/model/patch.py +20 -0
  154. pygpt_net/provider/core/preset/json_file.py +2 -4
  155. pygpt_net/provider/llms/anthropic.py +2 -5
  156. pygpt_net/provider/llms/base.py +4 -3
  157. pygpt_net/provider/llms/google.py +8 -9
  158. pygpt_net/provider/llms/openai.py +1 -1
  159. pygpt_net/provider/loaders/hub/image_vision/base.py +1 -1
  160. pygpt_net/ui/dialog/preset.py +71 -55
  161. pygpt_net/ui/layout/toolbox/footer.py +16 -0
  162. pygpt_net/ui/layout/toolbox/image.py +5 -0
  163. pygpt_net/ui/main.py +6 -4
  164. pygpt_net/ui/widget/option/combo.py +15 -1
  165. pygpt_net/utils.py +9 -0
  166. {pygpt_net-2.6.29.dist-info → pygpt_net-2.6.31.dist-info}/METADATA +55 -55
  167. {pygpt_net-2.6.29.dist-info → pygpt_net-2.6.31.dist-info}/RECORD +181 -135
  168. pygpt_net/core/audio/backend/pyaudio.py +0 -554
  169. /pygpt_net/{provider/gpt/agents → controller/chat/handler}/__init__.py +0 -0
  170. /pygpt_net/{provider/gpt/worker → core/realtime}/__init__.py +0 -0
  171. /pygpt_net/provider/{gpt → api/openai}/agents/client.py +0 -0
  172. /pygpt_net/provider/{gpt → api/openai}/agents/remote_tools.py +0 -0
  173. /pygpt_net/provider/{gpt → api/openai}/agents/utils.py +0 -0
  174. /pygpt_net/provider/{gpt → api/openai}/audio.py +0 -0
  175. /pygpt_net/provider/{gpt → api/openai}/computer.py +0 -0
  176. /pygpt_net/provider/{gpt → api/openai}/container.py +0 -0
  177. /pygpt_net/provider/{gpt → api/openai}/summarizer.py +0 -0
  178. /pygpt_net/provider/{gpt → api/openai}/tools.py +0 -0
  179. /pygpt_net/provider/{gpt → api/openai}/utils.py +0 -0
  180. {pygpt_net-2.6.29.dist-info → pygpt_net-2.6.31.dist-info}/LICENSE +0 -0
  181. {pygpt_net-2.6.29.dist-info → pygpt_net-2.6.31.dist-info}/WHEEL +0 -0
  182. {pygpt_net-2.6.29.dist-info → pygpt_net-2.6.31.dist-info}/entry_points.txt +0 -0
pygpt_net/CHANGELOG.txt CHANGED
@@ -1,3 +1,18 @@
1
+ 2.6.31 (2025-09-01)
2
+
3
+ - Chat with Audio mode renamed to Realtime + audio.
4
+ - Added support for real-time audio models from OpenAI (Realtime API) and Google (Live API), featuring real-time audio integration (beta).
5
+ - Introduced new predefined models: gpt-realtime, gpt-4o-realtime-preview, and gemini-2.5-flash-preview-native-audio-dialog.
6
+ - Included Google Gen AI audio input and output providers in the Audio Input/Output plugins.
7
+ - Added URL Context remote tool support in Google Gen AI.
8
+
9
+ 2.6.30 (2025-08-29)
10
+
11
+ - Added native Google GenAI API support (beta); live audio is not supported yet (#132).
12
+ - Added new predefined models for image generation: Google Imagen3 and Imagen4.
13
+ - Optimized token usage in the Responses API.
14
+ - Removed Vision mode (it is now integrated into Chat).
15
+
1
16
  2.6.29 (2025-08-28)
2
17
 
3
18
  - Verbose options have been moved to the Developer section in settings.
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: 2025.08.28 00:00:00 #
9
+ # Updated Date: 2025.09.01 00:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  __author__ = "Marcin Szczygliński"
13
13
  __copyright__ = "Copyright 2025, Marcin Szczygliński"
14
14
  __credits__ = ["Marcin Szczygliński"]
15
15
  __license__ = "MIT"
16
- __version__ = "2.6.29"
17
- __build__ = "2025-08-28"
16
+ __version__ = "2.6.31"
17
+ __build__ = "2025-09-01"
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
@@ -171,10 +171,12 @@ from pygpt_net.provider.audio_input.openai_whisper import OpenAIWhisper
171
171
  from pygpt_net.provider.audio_input.openai_whisper_local import OpenAIWhisperLocal
172
172
  from pygpt_net.provider.audio_input.google_speech_recognition import GoogleSpeechRecognition
173
173
  from pygpt_net.provider.audio_input.google_cloud_speech_recognition import GoogleCloudSpeechRecognition
174
+ from pygpt_net.provider.audio_input.google_genai import GoogleGenAIAudioInput
174
175
  from pygpt_net.provider.audio_input.bing_speech_recognition import BingSpeechRecognition
175
176
  from pygpt_net.provider.audio_output.openai_tts import OpenAITextToSpeech
176
177
  from pygpt_net.provider.audio_output.ms_azure_tts import MSAzureTextToSpeech
177
178
  from pygpt_net.provider.audio_output.google_tts import GoogleTextToSpeech
179
+ from pygpt_net.provider.audio_output.google_genai_tts import GoogleGenAITextToSpeech
178
180
  from pygpt_net.provider.audio_output.eleven_labs import ElevenLabsTextToSpeech
179
181
 
180
182
  # web search engine providers
@@ -318,10 +320,12 @@ def run(**kwargs):
318
320
  launcher.add_audio_input(OpenAIWhisperLocal())
319
321
  launcher.add_audio_input(GoogleSpeechRecognition())
320
322
  launcher.add_audio_input(GoogleCloudSpeechRecognition())
323
+ launcher.add_audio_input(GoogleGenAIAudioInput())
321
324
  launcher.add_audio_input(BingSpeechRecognition())
322
325
  launcher.add_audio_output(OpenAITextToSpeech())
323
326
  launcher.add_audio_output(MSAzureTextToSpeech())
324
327
  launcher.add_audio_output(GoogleTextToSpeech())
328
+ launcher.add_audio_output(GoogleGenAITextToSpeech())
325
329
  launcher.add_audio_output(ElevenLabsTextToSpeech())
326
330
 
327
331
  # register custom audio providers
@@ -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.08 05:00:00 #
9
+ # Updated Date: 2025.08.28 09:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.config import Config
@@ -45,21 +45,21 @@ from pygpt_net.core.tokens import Tokens
45
45
  from pygpt_net.core.updater import Updater
46
46
  from pygpt_net.core.vision import Vision
47
47
  from pygpt_net.core.web import Web
48
- from pygpt_net.provider.gpt import Gpt
49
48
 
49
+ from pygpt_net.provider.api import Api
50
50
 
51
- class Container:
51
+ class Core:
52
52
  def __init__(self, window=None):
53
53
  """
54
- Service container
54
+ App core
55
55
 
56
56
  :param window: Window instance
57
57
  """
58
58
  self.window = window
59
59
 
60
- # core
61
60
  self.access = Access(window)
62
61
  self.agents = Agents(window)
62
+ self.api = Api(window)
63
63
  self.assistants = Assistants(window)
64
64
  self.attachments = Attachments(window)
65
65
  self.audio = Audio(window)
@@ -75,7 +75,6 @@ class Container:
75
75
  self.dispatcher = Dispatcher(window)
76
76
  self.experts = Experts(window)
77
77
  self.filesystem = Filesystem(window)
78
- self.gpt = Gpt(window)
79
78
  self.history = History(window)
80
79
  self.idx = Idx(window)
81
80
  self.image = Image(window)
@@ -1,4 +1,4 @@
1
- # !/usr/bin/env python3
1
+ #!/usr/bin/env python3
2
2
  # -*- coding: utf-8 -*-
3
3
  # ================================================== #
4
4
  # This file is a part of PYGPT package #
@@ -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.24 23:00:00 #
9
+ # Updated Date: 2025.08.30 06:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.controller.access import Access
@@ -34,6 +34,7 @@ from pygpt_net.controller.model import Model
34
34
  from pygpt_net.controller.notepad import Notepad
35
35
  from pygpt_net.controller.painter import Painter
36
36
  from pygpt_net.controller.plugins import Plugins
37
+ from pygpt_net.controller.realtime import Realtime
37
38
  from pygpt_net.controller.presets import Presets
38
39
  from pygpt_net.controller.settings import Settings
39
40
  from pygpt_net.controller.theme import Theme
@@ -76,6 +77,7 @@ class Controller:
76
77
  self.painter = Painter(window)
77
78
  self.plugins = Plugins(window)
78
79
  self.presets = Presets(window)
80
+ self.realtime = Realtime(window)
79
81
  self.settings = Settings(window)
80
82
  self.theme = Theme(window)
81
83
  self.tools = Tools(window)
@@ -108,6 +110,7 @@ class Controller:
108
110
  self.attachment.setup()
109
111
  self.camera.setup_ui()
110
112
  self.access.setup()
113
+ self.realtime.setup()
111
114
 
112
115
  def post_setup(self):
113
116
  """Post-setup, after plugins are loaded"""
@@ -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.14 08:00:00 #
9
+ # Updated Date: 2025.08.28 09:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import re
@@ -14,16 +14,8 @@ import re
14
14
  from PySide6.QtCore import QTimer
15
15
 
16
16
  from pygpt_net.core.types import (
17
- MODE_AGENT,
18
- MODE_AGENT_LLAMA,
19
- MODE_ASSISTANT,
20
17
  MODE_CHAT,
21
- MODE_COMPLETION,
22
- MODE_EXPERT,
23
- MODE_LANGCHAIN,
24
18
  MODE_LLAMA_INDEX,
25
- MODE_VISION,
26
- MODE_IMAGE,
27
19
  )
28
20
  from pygpt_net.core.tabs.tab import Tab
29
21
  from pygpt_net.core.events import ControlEvent
@@ -91,7 +91,7 @@ class Assistant:
91
91
 
92
92
  # get status
93
93
  try:
94
- status = self.window.core.gpt.assistants.run_stop(ctx)
94
+ status = self.window.core.api.openai.assistants.run_stop(ctx)
95
95
  if status == "cancelling" or status == "cancelled":
96
96
  print("Run has been canceled.")
97
97
  self.threads.log("Run status: {}".format(status))
@@ -227,7 +227,7 @@ class Assistant:
227
227
  assistant = self.window.core.assistants.create()
228
228
  self.editor.assign_data(assistant)
229
229
  try:
230
- return self.window.core.gpt.assistants.create(assistant)
230
+ return self.window.core.api.openai.assistants.create(assistant)
231
231
  except Exception as e:
232
232
  self.window.core.debug.log(e)
233
233
  self.window.ui.dialogs.alert(e)
@@ -240,7 +240,7 @@ class Assistant:
240
240
  """
241
241
  self.editor.assign_data(assistant)
242
242
  try:
243
- return self.window.core.gpt.assistants.update(assistant)
243
+ return self.window.core.api.openai.assistants.update(assistant)
244
244
  except Exception as e:
245
245
  self.window.core.debug.log(e)
246
246
  self.window.ui.dialogs.alert(e)
@@ -300,7 +300,7 @@ class Assistant:
300
300
 
301
301
  # delete in API
302
302
  try:
303
- self.window.core.gpt.assistants.delete(id)
303
+ self.window.core.api.openai.assistants.delete(id)
304
304
  except Exception as e:
305
305
  self.window.ui.dialogs.alert(e)
306
306
 
@@ -42,7 +42,7 @@ class Batch:
42
42
 
43
43
  # run asynchronous
44
44
  self.window.update_status("Importing assistants...please wait...")
45
- self.window.core.gpt.assistants.importer.import_assistants()
45
+ self.window.core.api.openai.assistants.importer.import_assistants()
46
46
 
47
47
  def import_stores(self, force: bool = False):
48
48
  """
@@ -60,7 +60,7 @@ class Batch:
60
60
  # run asynchronous
61
61
  self.window.update_status("Importing vector stores...please wait...")
62
62
  self.window.core.assistants.store.truncate() # clear all stores
63
- self.window.core.gpt.assistants.importer.import_vector_stores()
63
+ self.window.core.api.openai.assistants.importer.import_vector_stores()
64
64
  self.window.controller.assistant.files.update()
65
65
  self.window.controller.assistant.store.update()
66
66
 
@@ -140,7 +140,7 @@ class Batch:
140
140
  # run asynchronous
141
141
  self.window.update_status("Removing files...please wait...")
142
142
  QApplication.processEvents()
143
- self.window.core.gpt.assistants.importer.truncate_files() # remove all files from API
143
+ self.window.core.api.openai.assistants.importer.truncate_files() # remove all files from API
144
144
 
145
145
  def truncate_store_files_by_idx(self, idx: int, force: bool = False):
146
146
  """
@@ -173,7 +173,7 @@ class Batch:
173
173
  # run asynchronous
174
174
  self.window.update_status("Removing files...please wait...")
175
175
  QApplication.processEvents()
176
- self.window.core.gpt.assistants.importer.truncate_files(store_id) # remove all files from API
176
+ self.window.core.api.openai.assistants.importer.truncate_files(store_id) # remove all files from API
177
177
 
178
178
  def clear_store_files_by_idx(
179
179
  self,
@@ -277,7 +277,7 @@ class Batch:
277
277
  self.window.update_status("Removing vector stores...please wait...")
278
278
  QApplication.processEvents()
279
279
  self.window.core.assistants.store.truncate() # clear all stores
280
- self.window.core.gpt.assistants.importer.truncate_vector_stores()
280
+ self.window.core.api.openai.assistants.importer.truncate_vector_stores()
281
281
  self.window.controller.assistant.files.update()
282
282
  self.window.controller.assistant.store.update()
283
283
  self.window.controller.assistant.store.current = None
@@ -298,7 +298,7 @@ class Batch:
298
298
  return
299
299
  self.window.update_status("Refreshing vector stores...please wait...")
300
300
  QApplication.processEvents()
301
- self.window.core.gpt.assistants.importer.refresh_vector_stores()
301
+ self.window.core.api.openai.assistants.importer.refresh_vector_stores()
302
302
 
303
303
  def handle_imported_assistants(self, num: int):
304
304
  """
@@ -539,7 +539,7 @@ class Batch:
539
539
  store_id = self.window.controller.assistant.store.current
540
540
  self.window.update_status("Uploading files...please wait...")
541
541
  QApplication.processEvents()
542
- self.window.core.gpt.assistants.importer.upload_files(store_id, self.files_to_upload)
542
+ self.window.core.api.openai.assistants.importer.upload_files(store_id, self.files_to_upload)
543
543
  self.files_to_upload = [] # clear files
544
544
 
545
545
  def handle_uploaded_files(self, num: int):
@@ -75,7 +75,7 @@ class Files:
75
75
  """
76
76
  # run asynchronous
77
77
  self.window.update_status("Importing files...please wait...")
78
- self.window.core.gpt.assistants.importer.import_files(store_id)
78
+ self.window.core.api.openai.assistants.importer.import_files(store_id)
79
79
 
80
80
  def download(self, idx: int):
81
81
  """
@@ -276,7 +276,7 @@ class Files:
276
276
  continue
277
277
 
278
278
  # upload local attachment file and get new ID (file_id)
279
- new_id = self.window.core.gpt.store.upload(
279
+ new_id = self.window.core.api.openai.store.upload(
280
280
  attachment.path,
281
281
  )
282
282
  if new_id is not None:
@@ -287,14 +287,14 @@ class Files:
287
287
 
288
288
  """
289
289
  if assistant.vector_store is None or assistant.vector_store == "":
290
- assistant.vector_store = self.window.core.gpt.store.create_store(
290
+ assistant.vector_store = self.window.core.api.openai.store.create_store(
291
291
  "thread-" + thread_id,
292
292
  )
293
293
  """
294
294
 
295
295
  # add to vector store if defined in assistant, otherwise file will be added to thread store
296
296
  if assistant.vector_store:
297
- self.window.core.gpt.store.add_file(
297
+ self.window.core.api.openai.store.add_file(
298
298
  assistant.vector_store,
299
299
  new_id,
300
300
  )
@@ -42,7 +42,7 @@ class Threads(QObject):
42
42
 
43
43
  :return: thread id
44
44
  """
45
- thread_id = self.window.core.gpt.assistants.thread_create()
45
+ thread_id = self.window.core.api.openai.assistants.thread_create()
46
46
  self.window.core.config.set('assistant_thread', thread_id)
47
47
  self.window.core.ctx.append_thread(thread_id)
48
48
  return thread_id
@@ -245,7 +245,7 @@ class Threads(QObject):
245
245
 
246
246
  :param ctx: CtxItem
247
247
  """
248
- data = self.window.core.gpt.assistants.msg_list(ctx.thread)
248
+ data = self.window.core.api.openai.assistants.msg_list(ctx.thread)
249
249
  for msg in data:
250
250
  if msg.role == "assistant":
251
251
  try:
@@ -640,7 +640,7 @@ class RunWorker(QRunnable):
640
640
  while self.check \
641
641
  and not self.window.is_closing \
642
642
  and not self.window.controller.assistant.threads.stop:
643
- run = self.window.core.gpt.assistants.run_get(self.ctx)
643
+ run = self.window.core.api.openai.assistants.run_get(self.ctx)
644
644
  status = None
645
645
  if run is not None:
646
646
  status = run.status
@@ -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.23 15:00:00 #
9
+ # Updated Date: 2025.08.28 09:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -17,9 +17,6 @@ from urllib.parse import urlparse
17
17
  from PySide6.QtGui import QImage
18
18
  from PySide6.QtWidgets import QFileDialog, QApplication
19
19
 
20
- from pygpt_net.core.types import (
21
- MODE_VISION,
22
- )
23
20
  from pygpt_net.core.events import AppEvent, KernelEvent
24
21
  from pygpt_net.item.attachment import AttachmentItem
25
22
  from pygpt_net.item.ctx import CtxItem
@@ -73,7 +70,7 @@ class Attachment:
73
70
  if not self.has(mode):
74
71
  self.window.controller.chat.vision.unavailable()
75
72
  else:
76
- if mode == MODE_VISION or self.window.controller.plugins.is_type_enabled('vision'):
73
+ if self.window.controller.chat.vision.allowed():
77
74
  self.window.controller.chat.vision.available()
78
75
 
79
76
  # update tokens counter (vision plugin, etc.)
@@ -480,7 +477,7 @@ class Attachment:
480
477
  """
481
478
  try:
482
479
  # get file info from assistant API
483
- data = self.window.core.gpt.store.get_file(file_id)
480
+ data = self.window.core.api.openai.store.get_file(file_id)
484
481
  if data is None:
485
482
  return
486
483
 
@@ -506,7 +503,7 @@ class Attachment:
506
503
  path = self.get_download_path(filename)
507
504
 
508
505
  # download file
509
- self.window.core.gpt.store.download(
506
+ self.window.core.api.openai.store.download(
510
507
  file_id=file_id,
511
508
  path=path,
512
509
  )
@@ -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.27 07:00:00 #
9
+ # Updated Date: 2025.08.31 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -43,6 +43,30 @@ class Audio:
43
43
  if self.window.core.config.get("audio.input.continuous", False):
44
44
  self.window.ui.plugin_addon['audio.input.btn'].continuous.setChecked(True)
45
45
 
46
+ if self.window.core.config.get("audio.input.auto_turn", False):
47
+ self.window.ui.nodes['audio.auto_turn'].box.setChecked(True)
48
+
49
+ def execute_input_stop(self):
50
+ """Execute input stop (from UI)"""
51
+ self.window.dispatch(Event(Event.AUDIO_INPUT_RECORD_TOGGLE, {
52
+ "state": False,
53
+ "auto": True, # do not emit manual event
54
+ }))
55
+
56
+ def is_recording(self) -> bool:
57
+ """
58
+ Check if audio input is recording
59
+
60
+ :return: True if recording
61
+ """
62
+ return self.window.core.plugins.get("audio_input").is_recording()
63
+
64
+ def toggle_auto_turn(self):
65
+ """Toggle auto turn setting"""
66
+ value = self.window.ui.nodes['audio.auto_turn'].box.isChecked()
67
+ self.window.core.config.set("audio.input.auto_turn", value)
68
+ self.window.core.config.save()
69
+
46
70
  def toggle_input(
47
71
  self,
48
72
  state: bool,
@@ -183,7 +183,7 @@ class UI:
183
183
  """
184
184
  self.recording = True
185
185
  self.window.ui.nodes['input'].set_icon_state("mic", True)
186
- if mode == "input":
186
+ if mode in ["input", "realtime"]:
187
187
  self.window.controller.chat.common.lock_input()
188
188
  return
189
189
  btn = self.get_input_btn() if mode == 'input' else self.get_input_control_btn()
@@ -198,7 +198,7 @@ class UI:
198
198
  """
199
199
  self.recording = False
200
200
  self.window.ui.nodes['input'].set_icon_state("mic", False)
201
- if mode == "input":
201
+ if mode in ["input", "realtime"]:
202
202
  self.window.controller.chat.common.unlock_input()
203
203
  return
204
204
  btn = self.get_input_btn() if mode == 'input' else self.get_input_control_btn()
@@ -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.14 18:00:00 #
9
+ # Updated Date: 2025.08.30 06:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import base64
@@ -40,19 +40,12 @@ class Audio:
40
40
  """Update input/output audio"""
41
41
  mode = self.window.core.config.get("mode")
42
42
  if mode == MODE_AUDIO:
43
- if not self.window.controller.audio.is_output_enabled():
44
- self.window.controller.audio.enable_output()
45
- self.tmp_output = True
46
- else:
47
- self.tmp_output = False
48
43
  if not self.window.controller.audio.is_input_enabled():
49
44
  self.window.controller.audio.enable_input()
50
45
  self.tmp_input = True
51
46
  else:
52
47
  self.tmp_input = False
53
48
  else:
54
- if self.tmp_output:
55
- self.window.controller.audio.disable_output()
56
49
  if self.tmp_input:
57
50
  self.window.controller.audio.disable_input()
58
51
 
@@ -10,12 +10,13 @@
10
10
  # ================================================== #
11
11
 
12
12
  import os
13
+ from typing import Any
13
14
 
14
15
  from PySide6.QtGui import QTextCursor
15
16
  from PySide6.QtWidgets import QFileDialog, QApplication
16
17
 
17
18
  from pygpt_net.core.events import Event, AppEvent, RenderEvent, KernelEvent
18
- from pygpt_net.core.types import MODE_ASSISTANT
19
+ from pygpt_net.core.types import MODE_ASSISTANT, MODE_AUDIO
19
20
  from pygpt_net.item.ctx import CtxItem
20
21
  from pygpt_net.item.model import ModelItem
21
22
  from pygpt_net.utils import trans
@@ -119,6 +120,17 @@ class Common:
119
120
  else:
120
121
  self.window.ui.config['global']['img_raw'].setChecked(False)
121
122
 
123
+ # image resolution
124
+ resolution = self.window.core.config.get('img_resolution', '1024x1024')
125
+ self.window.controller.config.apply_value(
126
+ parent_id="global",
127
+ key="img_resolution",
128
+ option=self.window.core.image.get_resolution_option(),
129
+ value=resolution,
130
+ )
131
+ if not self.initialized:
132
+ self.window.ui.add_hook("update.global.img_resolution", self.hook_update)
133
+
122
134
  # set focus to input
123
135
  self.window.ui.nodes['input'].setFocus()
124
136
  self.initialized = True
@@ -257,7 +269,7 @@ class Common:
257
269
  self.window.controller.access.voice.stop_recording(timeout=True)
258
270
 
259
271
  if self.window.core.plugins.get("audio_input").handler_simple.is_recording:
260
- self.window.core.plugins.get("audio_input").handler_simple.stop_recording(timeout=False)
272
+ self.window.dispatch(Event(Event.AUDIO_INPUT_RECORD_TOGGLE))
261
273
  return
262
274
 
263
275
  # stop audio output if playing
@@ -275,7 +287,8 @@ class Common:
275
287
  """
276
288
  # don't unlock input and leave stop btn if assistant mode or if agent/autonomous is enabled
277
289
  # send btn will be unlocked in agent mode on stop
278
- if self.can_unlock(ctx):
290
+ mode = self.window.core.config.get('mode')
291
+ if self.can_unlock(ctx) and mode != MODE_AUDIO:
279
292
  if not self.window.controller.kernel.stopped():
280
293
  self.unlock_input() # unlock input
281
294
  return True
@@ -307,7 +320,7 @@ class Common:
307
320
  controller.kernel.halt = True
308
321
  dispatch(RenderEvent(RenderEvent.TOOL_END)) # show waiting
309
322
 
310
- core.gpt.stop()
323
+ core.api.openai.stop()
311
324
  self.unlock_input()
312
325
 
313
326
  controller.chat.input.generating = False
@@ -452,6 +465,19 @@ class Common:
452
465
  else:
453
466
  self.img_enable_raw()
454
467
 
468
+ def hook_update(self, key: str, value: Any, caller, *args, **kwargs):
469
+ """
470
+ Hook for updating image resolution
471
+
472
+ :param key: config key
473
+ :param value: new value
474
+ :param caller: caller object
475
+ """
476
+ if key == "img_resolution":
477
+ if not value:
478
+ return
479
+ self.window.core.config.set('img_resolution', value)
480
+
455
481
  def save_text(
456
482
  self,
457
483
  text: str,