pygpt-net 2.7.7__py3-none-any.whl → 2.7.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pygpt_net/CHANGELOG.txt +12 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/app.py +5 -1
- pygpt_net/controller/assistant/batch.py +2 -2
- pygpt_net/controller/assistant/files.py +7 -6
- pygpt_net/controller/assistant/threads.py +0 -0
- pygpt_net/controller/chat/command.py +0 -0
- pygpt_net/controller/dialogs/confirm.py +35 -58
- pygpt_net/controller/lang/mapping.py +9 -9
- pygpt_net/controller/realtime/realtime.py +13 -1
- pygpt_net/controller/remote_store/{google/batch.py → batch.py} +209 -252
- pygpt_net/controller/remote_store/remote_store.py +982 -13
- pygpt_net/core/command/command.py +0 -0
- pygpt_net/core/db/viewer.py +1 -1
- pygpt_net/core/realtime/worker.py +3 -1
- pygpt_net/{controller/remote_store/google → core/remote_store/anthropic}/__init__.py +0 -1
- pygpt_net/core/remote_store/anthropic/files.py +211 -0
- pygpt_net/core/remote_store/anthropic/store.py +208 -0
- pygpt_net/core/remote_store/openai/store.py +5 -4
- pygpt_net/core/remote_store/remote_store.py +5 -1
- pygpt_net/{controller/remote_store/openai → core/remote_store/xai}/__init__.py +0 -1
- pygpt_net/core/remote_store/xai/files.py +225 -0
- pygpt_net/core/remote_store/xai/store.py +219 -0
- pygpt_net/data/config/config.json +10 -6
- pygpt_net/data/config/models.json +38 -22
- pygpt_net/data/config/settings.json +54 -1
- pygpt_net/data/icons/folder_eye.svg +1 -0
- pygpt_net/data/icons/folder_eye_filled.svg +1 -0
- pygpt_net/data/icons/folder_open.svg +1 -0
- pygpt_net/data/icons/folder_open_filled.svg +1 -0
- pygpt_net/data/locale/locale.de.ini +4 -3
- pygpt_net/data/locale/locale.en.ini +14 -4
- pygpt_net/data/locale/locale.es.ini +4 -3
- pygpt_net/data/locale/locale.fr.ini +4 -3
- pygpt_net/data/locale/locale.it.ini +4 -3
- pygpt_net/data/locale/locale.pl.ini +5 -4
- pygpt_net/data/locale/locale.uk.ini +4 -3
- pygpt_net/data/locale/locale.zh.ini +4 -3
- pygpt_net/icons.qrc +4 -0
- pygpt_net/icons_rc.py +282 -138
- pygpt_net/provider/api/anthropic/__init__.py +2 -0
- pygpt_net/provider/api/anthropic/chat.py +84 -1
- pygpt_net/provider/api/anthropic/store.py +307 -0
- pygpt_net/provider/api/anthropic/stream.py +75 -0
- pygpt_net/provider/api/anthropic/worker/__init__.py +0 -0
- pygpt_net/provider/api/anthropic/worker/importer.py +278 -0
- pygpt_net/provider/api/google/chat.py +59 -2
- pygpt_net/provider/api/google/realtime/client.py +70 -24
- pygpt_net/provider/api/google/realtime/realtime.py +48 -12
- pygpt_net/provider/api/google/store.py +124 -3
- pygpt_net/provider/api/google/stream.py +91 -24
- pygpt_net/provider/api/google/worker/importer.py +16 -28
- pygpt_net/provider/api/openai/assistants.py +2 -2
- pygpt_net/provider/api/openai/realtime/realtime.py +26 -6
- pygpt_net/provider/api/openai/store.py +4 -1
- pygpt_net/provider/api/openai/worker/importer.py +19 -61
- pygpt_net/provider/api/openai/worker/importer_assistants.py +230 -0
- pygpt_net/provider/api/x_ai/__init__.py +27 -6
- pygpt_net/provider/api/x_ai/audio.py +43 -11
- pygpt_net/provider/api/x_ai/chat.py +92 -4
- pygpt_net/provider/api/x_ai/realtime/__init__.py +12 -0
- pygpt_net/provider/api/x_ai/realtime/client.py +1864 -0
- pygpt_net/provider/api/x_ai/realtime/realtime.py +213 -0
- pygpt_net/provider/api/x_ai/remote_tools.py +102 -1
- pygpt_net/provider/api/x_ai/store.py +610 -0
- pygpt_net/provider/api/x_ai/stream.py +30 -9
- pygpt_net/provider/api/x_ai/tools.py +51 -0
- pygpt_net/provider/api/x_ai/worker/importer.py +308 -0
- pygpt_net/provider/audio_input/xai_grok_voice.py +390 -0
- pygpt_net/provider/audio_output/xai_tts.py +325 -0
- pygpt_net/provider/core/config/patch.py +29 -3
- pygpt_net/provider/core/config/patches/patch_before_2_6_42.py +2 -2
- pygpt_net/provider/core/model/patch.py +49 -1
- pygpt_net/tools/image_viewer/tool.py +334 -34
- pygpt_net/tools/image_viewer/ui/dialogs.py +317 -21
- pygpt_net/ui/dialog/assistant.py +1 -1
- pygpt_net/ui/dialog/plugins.py +13 -5
- pygpt_net/ui/dialog/remote_store.py +552 -0
- pygpt_net/ui/dialogs.py +3 -5
- pygpt_net/ui/layout/ctx/ctx_list.py +58 -7
- pygpt_net/ui/menu/tools.py +6 -13
- pygpt_net/ui/widget/dialog/{remote_store_google.py → remote_store.py} +10 -10
- pygpt_net/ui/widget/element/button.py +4 -4
- pygpt_net/ui/widget/image/display.py +2 -2
- pygpt_net/ui/widget/lists/context.py +2 -2
- {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/METADATA +14 -2
- {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/RECORD +87 -75
- pygpt_net/controller/remote_store/google/store.py +0 -615
- pygpt_net/controller/remote_store/openai/batch.py +0 -524
- pygpt_net/controller/remote_store/openai/store.py +0 -699
- pygpt_net/ui/dialog/remote_store_google.py +0 -539
- pygpt_net/ui/dialog/remote_store_openai.py +0 -539
- pygpt_net/ui/widget/dialog/remote_store_openai.py +0 -56
- pygpt_net/ui/widget/lists/remote_store_google.py +0 -248
- pygpt_net/ui/widget/lists/remote_store_openai.py +0 -317
- {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/LICENSE +0 -0
- {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/WHEEL +0 -0
- {pygpt_net-2.7.7.dist-info → pygpt_net-2.7.9.dist-info}/entry_points.txt +0 -0
|
@@ -6,27 +6,59 @@
|
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
|
7
7
|
# MIT License #
|
|
8
8
|
# Created By : Marcin Szczygliński #
|
|
9
|
-
# Updated Date:
|
|
9
|
+
# Updated Date: 2026.01.06 20:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
import base64
|
|
13
|
+
from typing import Optional, Union, List, Dict, Any
|
|
14
|
+
|
|
15
|
+
from pygpt_net.core.bridge.context import MultimodalContext
|
|
13
16
|
|
|
14
17
|
|
|
15
18
|
class Audio:
|
|
16
19
|
def __init__(self, window=None):
|
|
17
20
|
"""
|
|
18
|
-
Audio
|
|
19
|
-
|
|
20
|
-
Note: As of now, the public xAI Python SDK does not expose TTS/STT or realtime audio APIs.
|
|
21
|
-
This class exists to keep provider surface compatible.
|
|
21
|
+
Audio input wrapper
|
|
22
22
|
|
|
23
23
|
:param window: Window instance
|
|
24
24
|
"""
|
|
25
25
|
self.window = window
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
def build_content(
|
|
28
|
+
self,
|
|
29
|
+
content: Optional[Union[str, list]] = None,
|
|
30
|
+
multimodal_ctx: Optional[MultimodalContext] = None,
|
|
31
|
+
) -> List[Dict[str, Any]]:
|
|
32
|
+
"""
|
|
33
|
+
Build audio content from multimodal context
|
|
34
|
+
|
|
35
|
+
:param content: previous content or input prompt
|
|
36
|
+
:param multimodal_ctx: multimodal context
|
|
37
|
+
:return: List of contents
|
|
38
|
+
"""
|
|
39
|
+
if not isinstance(content, list):
|
|
40
|
+
if content:
|
|
41
|
+
content = [
|
|
42
|
+
{
|
|
43
|
+
"type": "text",
|
|
44
|
+
"text": str(content),
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
else:
|
|
48
|
+
content = [] # if empty input return empty list
|
|
49
|
+
|
|
50
|
+
# abort if no audio input provided
|
|
51
|
+
if not multimodal_ctx.is_audio_input:
|
|
52
|
+
return content
|
|
30
53
|
|
|
31
|
-
|
|
32
|
-
|
|
54
|
+
encoded = base64.b64encode(multimodal_ctx.audio_data).decode('utf-8')
|
|
55
|
+
audio_format = multimodal_ctx.audio_format # wav by default
|
|
56
|
+
audio_data = {
|
|
57
|
+
"type": "input_audio",
|
|
58
|
+
"input_audio": {
|
|
59
|
+
"data": encoded,
|
|
60
|
+
"format": audio_format,
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
content.append(audio_data)
|
|
64
|
+
return content
|
|
@@ -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.
|
|
9
|
+
# Updated Date: 2026.01.05 20:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from __future__ import annotations
|
|
@@ -34,7 +34,6 @@ class Chat:
|
|
|
34
34
|
"""
|
|
35
35
|
self.window = window
|
|
36
36
|
self.input_tokens = 0
|
|
37
|
-
# Image constraints (can be overridden by config keys below)
|
|
38
37
|
self.allowed_mimes = {"image/jpeg", "image/png"}
|
|
39
38
|
self.default_image_max_bytes = 10 * 1024 * 1024 # 10 MiB default
|
|
40
39
|
|
|
@@ -319,6 +318,12 @@ class Chat:
|
|
|
319
318
|
except Exception:
|
|
320
319
|
pass
|
|
321
320
|
|
|
321
|
+
try:
|
|
322
|
+
# Attempt to auto-download file parts or references (file id)
|
|
323
|
+
self._maybe_download_files_from_response(response, ctx)
|
|
324
|
+
except Exception:
|
|
325
|
+
pass
|
|
326
|
+
|
|
322
327
|
# Usage
|
|
323
328
|
try:
|
|
324
329
|
if isinstance(response, dict) and response.get("usage"):
|
|
@@ -1089,7 +1094,7 @@ class Chat:
|
|
|
1089
1094
|
|
|
1090
1095
|
def _collect_images_from_message_parts(self, parts: List[dict], ctx: CtxItem):
|
|
1091
1096
|
"""
|
|
1092
|
-
Inspect assistant message parts for image_url outputs and
|
|
1097
|
+
Inspect assistant message parts for image_url outputs and URLs.
|
|
1093
1098
|
For http(s) URLs -> add to ctx.urls; for data URLs -> save to file and add to ctx.images.
|
|
1094
1099
|
"""
|
|
1095
1100
|
try:
|
|
@@ -1098,6 +1103,25 @@ class Chat:
|
|
|
1098
1103
|
for p in parts:
|
|
1099
1104
|
if not isinstance(p, dict):
|
|
1100
1105
|
continue
|
|
1106
|
+
if p.get("type") == "file":
|
|
1107
|
+
file_id = p.get("id") or p.get("file_id")
|
|
1108
|
+
if isinstance(file_id, str):
|
|
1109
|
+
try:
|
|
1110
|
+
save = self.window.core.api.xai.store.download_to_dir(file_id)
|
|
1111
|
+
if save:
|
|
1112
|
+
if not isinstance(ctx.files, list):
|
|
1113
|
+
ctx.files = []
|
|
1114
|
+
if save not in ctx.files:
|
|
1115
|
+
ctx.files.append(save)
|
|
1116
|
+
ext = os.path.splitext(save)[1].lower().lstrip(".")
|
|
1117
|
+
if ext in ["png", "jpg", "jpeg", "gif", "bmp", "tiff", "webp"]:
|
|
1118
|
+
if not isinstance(ctx.images, list):
|
|
1119
|
+
ctx.images = []
|
|
1120
|
+
if save not in ctx.images:
|
|
1121
|
+
ctx.images.append(save)
|
|
1122
|
+
except Exception:
|
|
1123
|
+
pass
|
|
1124
|
+
continue
|
|
1101
1125
|
if p.get("type") != "image_url":
|
|
1102
1126
|
continue
|
|
1103
1127
|
img = p.get("image_url") or {}
|
|
@@ -1135,4 +1159,68 @@ class Chat:
|
|
|
1135
1159
|
"""
|
|
1136
1160
|
Return the locally estimated input tokens count.
|
|
1137
1161
|
"""
|
|
1138
|
-
return self.input_tokens
|
|
1162
|
+
return self.input_tokens
|
|
1163
|
+
|
|
1164
|
+
def _maybe_download_files_from_response(self, response, ctx: CtxItem) -> None:
|
|
1165
|
+
"""
|
|
1166
|
+
Attempt to download any files referenced by id in response payloads (dict/SDK/proto).
|
|
1167
|
+
"""
|
|
1168
|
+
def _walk(o, acc: set):
|
|
1169
|
+
if o is None:
|
|
1170
|
+
return
|
|
1171
|
+
if isinstance(o, dict):
|
|
1172
|
+
fid = o.get("file_id") or o.get("id") if o.get("type") == "file" else None
|
|
1173
|
+
if isinstance(fid, str) and fid.startswith("file-"):
|
|
1174
|
+
acc.add(fid)
|
|
1175
|
+
for v in o.values():
|
|
1176
|
+
_walk(v, acc)
|
|
1177
|
+
elif isinstance(o, (list, tuple)):
|
|
1178
|
+
for it in o:
|
|
1179
|
+
_walk(it, acc)
|
|
1180
|
+
|
|
1181
|
+
ids = set()
|
|
1182
|
+
try:
|
|
1183
|
+
if isinstance(response, dict):
|
|
1184
|
+
_walk(response, ids)
|
|
1185
|
+
else:
|
|
1186
|
+
msg = getattr(response, "message", None) or getattr(response, "output_message", None)
|
|
1187
|
+
if msg:
|
|
1188
|
+
_walk(getattr(msg, "content", None), ids)
|
|
1189
|
+
proto = getattr(response, "proto", None)
|
|
1190
|
+
if proto:
|
|
1191
|
+
ch = getattr(proto, "choices", None) or []
|
|
1192
|
+
if ch:
|
|
1193
|
+
m = getattr(ch[0], "message", None)
|
|
1194
|
+
if m:
|
|
1195
|
+
_walk(getattr(m, "content", None), ids)
|
|
1196
|
+
except Exception:
|
|
1197
|
+
pass
|
|
1198
|
+
|
|
1199
|
+
if not ids:
|
|
1200
|
+
return
|
|
1201
|
+
saved = []
|
|
1202
|
+
for fid in ids:
|
|
1203
|
+
try:
|
|
1204
|
+
p = self.window.core.api.xai.store.download_to_dir(fid)
|
|
1205
|
+
if p:
|
|
1206
|
+
saved.append(p)
|
|
1207
|
+
except Exception:
|
|
1208
|
+
continue
|
|
1209
|
+
if saved:
|
|
1210
|
+
saved = self.window.core.filesystem.make_local_list(saved)
|
|
1211
|
+
if not isinstance(ctx.files, list):
|
|
1212
|
+
ctx.files = []
|
|
1213
|
+
for p in saved:
|
|
1214
|
+
if p not in ctx.files:
|
|
1215
|
+
ctx.files.append(p)
|
|
1216
|
+
imgs = []
|
|
1217
|
+
for p in saved:
|
|
1218
|
+
ext = os.path.splitext(p)[1].lower().lstrip(".")
|
|
1219
|
+
if ext in ["png", "jpg", "jpeg", "gif", "bmp", "tiff", "webp"]:
|
|
1220
|
+
imgs.append(p)
|
|
1221
|
+
if imgs:
|
|
1222
|
+
if not isinstance(ctx.images, list):
|
|
1223
|
+
ctx.images = []
|
|
1224
|
+
for p in imgs:
|
|
1225
|
+
if p not in ctx.images:
|
|
1226
|
+
ctx.images.append(p)
|
|
@@ -0,0 +1,12 @@
|
|
|
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: 2025.08.31 23:00:00 #
|
|
10
|
+
# ================================================== #
|
|
11
|
+
|
|
12
|
+
from .realtime import Realtime
|