pygpt-net 2.6.33__py3-none-any.whl → 2.6.36__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 (64) hide show
  1. pygpt_net/CHANGELOG.txt +18 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/controller/assistant/batch.py +14 -4
  4. pygpt_net/controller/assistant/files.py +1 -0
  5. pygpt_net/controller/assistant/store.py +195 -1
  6. pygpt_net/controller/camera/camera.py +1 -1
  7. pygpt_net/controller/chat/common.py +58 -48
  8. pygpt_net/controller/chat/handler/stream_worker.py +55 -43
  9. pygpt_net/controller/config/placeholder.py +95 -75
  10. pygpt_net/controller/dialogs/confirm.py +3 -1
  11. pygpt_net/controller/media/media.py +11 -3
  12. pygpt_net/controller/painter/common.py +243 -13
  13. pygpt_net/controller/painter/painter.py +11 -2
  14. pygpt_net/core/assistants/files.py +18 -0
  15. pygpt_net/core/bridge/bridge.py +1 -5
  16. pygpt_net/core/bridge/context.py +81 -36
  17. pygpt_net/core/bridge/worker.py +3 -1
  18. pygpt_net/core/camera/camera.py +31 -402
  19. pygpt_net/core/camera/worker.py +430 -0
  20. pygpt_net/core/ctx/bag.py +4 -0
  21. pygpt_net/core/events/app.py +10 -17
  22. pygpt_net/core/events/base.py +17 -25
  23. pygpt_net/core/events/control.py +9 -17
  24. pygpt_net/core/events/event.py +9 -62
  25. pygpt_net/core/events/kernel.py +8 -17
  26. pygpt_net/core/events/realtime.py +8 -17
  27. pygpt_net/core/events/render.py +9 -17
  28. pygpt_net/core/filesystem/url.py +3 -0
  29. pygpt_net/core/render/web/body.py +483 -40
  30. pygpt_net/core/render/web/pid.py +39 -24
  31. pygpt_net/core/render/web/renderer.py +142 -36
  32. pygpt_net/core/text/utils.py +3 -0
  33. pygpt_net/data/config/config.json +4 -3
  34. pygpt_net/data/config/models.json +3 -3
  35. pygpt_net/data/config/settings.json +10 -5
  36. pygpt_net/data/css/web-blocks.css +4 -3
  37. pygpt_net/data/css/web-chatgpt.css +4 -2
  38. pygpt_net/data/css/web-chatgpt_wide.css +4 -2
  39. pygpt_net/data/locale/locale.de.ini +9 -7
  40. pygpt_net/data/locale/locale.en.ini +10 -6
  41. pygpt_net/data/locale/locale.es.ini +9 -7
  42. pygpt_net/data/locale/locale.fr.ini +9 -7
  43. pygpt_net/data/locale/locale.it.ini +9 -7
  44. pygpt_net/data/locale/locale.pl.ini +9 -7
  45. pygpt_net/data/locale/locale.uk.ini +9 -7
  46. pygpt_net/data/locale/locale.zh.ini +9 -7
  47. pygpt_net/item/assistant.py +13 -1
  48. pygpt_net/provider/api/google/__init__.py +46 -28
  49. pygpt_net/provider/api/openai/__init__.py +13 -10
  50. pygpt_net/provider/api/openai/store.py +45 -1
  51. pygpt_net/provider/core/config/patch.py +18 -0
  52. pygpt_net/provider/llms/google.py +4 -0
  53. pygpt_net/ui/dialog/assistant_store.py +213 -203
  54. pygpt_net/ui/layout/chat/input.py +3 -3
  55. pygpt_net/ui/layout/chat/painter.py +63 -4
  56. pygpt_net/ui/widget/draw/painter.py +715 -104
  57. pygpt_net/ui/widget/option/combo.py +5 -1
  58. pygpt_net/ui/widget/textarea/input.py +273 -3
  59. pygpt_net/ui/widget/textarea/web.py +2 -0
  60. {pygpt_net-2.6.33.dist-info → pygpt_net-2.6.36.dist-info}/METADATA +20 -2
  61. {pygpt_net-2.6.33.dist-info → pygpt_net-2.6.36.dist-info}/RECORD +64 -63
  62. {pygpt_net-2.6.33.dist-info → pygpt_net-2.6.36.dist-info}/LICENSE +0 -0
  63. {pygpt_net-2.6.33.dist-info → pygpt_net-2.6.36.dist-info}/WHEEL +0 -0
  64. {pygpt_net-2.6.33.dist-info → pygpt_net-2.6.36.dist-info}/entry_points.txt +0 -0
@@ -958,10 +958,11 @@ output.tips.7 = Para un mejor rendimiento, desactiva las herramientas cuando uti
958
958
  output.tips.8 = Al utilizar modelos locales, recuerda establecer el modelo local también para el resumen de contexto y las incrustaciones.
959
959
  output.tips.9 = Para configurar los proveedores de entrada y salida de audio, ve a Plugins -> Configuración. Para configurar los dispositivos de audio, ve a Configuración -> Configuración -> Audio.
960
960
  output.tips.prefix = Consejo
961
- painter.btn.crop = Recortar
962
961
  painter.btn.camera.capture = De la cámara
963
962
  painter.btn.capture = Capturar imagen
964
963
  painter.btn.clear = Limpiar
964
+ painter.btn.crop = Recortar
965
+ painter.btn.fit = Ajustar
965
966
  painter.capture.manual.captured.success = Imagen capturada:
966
967
  painter.capture.name.prefix = Dibujo de
967
968
  painter.mode.erase = Borrar
@@ -1365,7 +1366,8 @@ settings.section.remote_tools = Herramientas remotas
1365
1366
  settings.section.remote_tools.openai = OpenAI
1366
1367
  settings.section.tab.general = General
1367
1368
  settings.section.updates = Actualizaciones
1368
- settings.section.vision = Visión
1369
+ settings.section.vision = Visión y cámara
1370
+ settings.section.vision.camera = Cámara
1369
1371
  settings.store_history = Almacenar historial
1370
1372
  settings.store_history_time = Almacenar hora en el historial
1371
1373
  settings.temperature = Temperatura
@@ -1395,11 +1397,11 @@ settings.video.seed = Semilla
1395
1397
  settings.video.seed.desc = Semilla aleatoria opcional para resultados reproducibles; déjelo vacío para aleatorio
1396
1398
  settings.vision.capture.auto = Captura automática
1397
1399
  settings.vision.capture.enabled = Cámara
1398
- settings.vision.capture.height = Altura de captura de cámara (px)
1399
- settings.vision.capture.idx = IDX de cámara (número)
1400
- settings.vision.capture.idx.desc = Índice de cámara para captura de video (índice de la cámara, predeterminado: 0)
1401
- settings.vision.capture.quality = Calidad de captura de imagen (%)
1402
- settings.vision.capture.width = Ancho de captura de cámara (px)
1400
+ settings.vision.capture.height = Altura de captura (en píxeles)
1401
+ settings.vision.capture.idx = Dispositivo de Cámara
1402
+ settings.vision.capture.idx.desc = Seleccione un dispositivo de cámara para la captura de video en tiempo real
1403
+ settings.vision.capture.quality = Calidad de captura (%)
1404
+ settings.vision.capture.width = Ancho de captura (en píxeles)
1403
1405
  settings.zoom = Zoom de ventana de salida del chat
1404
1406
  speech.enable = Hablar
1405
1407
  speech.listening = Hable ahora...
@@ -957,10 +957,11 @@ output.tips.7 = Pour de meilleures performances, désactivez les outils lorsque
957
957
  output.tips.8 = Lorsque vous utilisez des modèles locaux, n’oubliez pas de définir également le modèle local pour le résumé de contexte et les embeddings.
958
958
  output.tips.9 = Pour configurer les fournisseurs d'entrée et de sortie audio, allez dans Plugins -> Paramètres. Pour configurer les appareils audio, allez dans Configuration -> Paramètres -> Audio.
959
959
  output.tips.prefix = Astuce
960
- painter.btn.crop = Rogner
961
960
  painter.btn.camera.capture = De la caméra
962
961
  painter.btn.capture = Capturer l'image
963
962
  painter.btn.clear = Effacer
963
+ painter.btn.crop = Rogner
964
+ painter.btn.fit = Adapter
964
965
  painter.capture.manual.captured.success = Image capturée:
965
966
  painter.capture.name.prefix = Dessin de
966
967
  painter.mode.erase = Effacer
@@ -1364,7 +1365,8 @@ settings.section.remote_tools = Outils distants
1364
1365
  settings.section.remote_tools.openai = OpenAI
1365
1366
  settings.section.tab.general = Général
1366
1367
  settings.section.updates = Mises à jour
1367
- settings.section.vision = Vision
1368
+ settings.section.vision = Vision et caméra
1369
+ settings.section.vision.camera = Caméra
1368
1370
  settings.store_history = Stocker l'historique
1369
1371
  settings.store_history_time = Stocker l'heure dans l'historique
1370
1372
  settings.temperature = Température
@@ -1394,11 +1396,11 @@ settings.video.seed = Graine
1394
1396
  settings.video.seed.desc = Graine aléatoire facultative pour des résultats reproductibles; laisser vide pour aléatoire
1395
1397
  settings.vision.capture.auto = Capture automatique
1396
1398
  settings.vision.capture.enabled = Caméra
1397
- settings.vision.capture.height = Hauteur de capture par caméra (px)
1398
- settings.vision.capture.idx = IDX de la caméra (numéro)
1399
- settings.vision.capture.idx.desc = Indice de la caméra de capture vidéo (indice de la caméra, par défaut : 0)
1400
- settings.vision.capture.quality = Qualité de capture d'image (%)
1401
- settings.vision.capture.width = Largeur de capture par caméra (px)
1399
+ settings.vision.capture.height = Hauteur de capture (en pixels)
1400
+ settings.vision.capture.idx = Appareil Photo
1401
+ settings.vision.capture.idx.desc = Sélectionnez un appareil photo pour la capture vidéo en temps réel
1402
+ settings.vision.capture.quality = Qualité de capture (%)
1403
+ settings.vision.capture.width = Largeur de capture (en pixels)
1402
1404
  settings.zoom = Zoom de la fenêtre de sortie du chat
1403
1405
  speech.enable = Parler
1404
1406
  speech.listening = Parler maintenant...
@@ -957,10 +957,11 @@ output.tips.7 = Per prestazioni migliori, disattiva gli strumenti quando usi mod
957
957
  output.tips.8 = Quando usi modelli locali, ricorda di impostare anche il modello locale per il riassunto del contesto e gli embeddings.
958
958
  output.tips.9 = Per configurare i fornitori di input e output audio, vai su Plugin -> Impostazioni. Per configurare i dispositivi audio, vai su Configurazione -> Impostazioni -> Audio.
959
959
  output.tips.prefix = Suggerimento
960
- painter.btn.crop = Ritaglia
961
960
  painter.btn.camera.capture = Dalla fotocamera
962
961
  painter.btn.capture = Cattura immagine
963
962
  painter.btn.clear = Pulire
963
+ painter.btn.crop = Ritaglia
964
+ painter.btn.fit = Adatta
964
965
  painter.capture.manual.captured.success = Immagine catturata:
965
966
  painter.capture.name.prefix = Disegno da
966
967
  painter.mode.erase = Cancellare
@@ -1364,7 +1365,8 @@ settings.section.remote_tools = Strumenti remoti
1364
1365
  settings.section.remote_tools.openai = OpenAI
1365
1366
  settings.section.tab.general = Generale
1366
1367
  settings.section.updates = Aggiornamenti
1367
- settings.section.vision = Visione
1368
+ settings.section.vision = Visione e fotocamera
1369
+ settings.section.vision.camera = Fotocamera
1368
1370
  settings.store_history = Conserva la cronologia
1369
1371
  settings.store_history_time = Conserva l'orario nella cronologia
1370
1372
  settings.temperature = Temperatura
@@ -1394,11 +1396,11 @@ settings.video.seed = Seme
1394
1396
  settings.video.seed.desc = Seme casuale opzionale per risultati riproducibili; lascia vuoto per casuale
1395
1397
  settings.vision.capture.auto = Cattura automatica
1396
1398
  settings.vision.capture.enabled = Fotocamera
1397
- settings.vision.capture.height = Altezza cattura fotocamera (px)
1398
- settings.vision.capture.idx = IDX fotocamera (numero)
1399
- settings.vision.capture.idx.desc = Indice videocamera per la cattura video (indice della videocamera, predefinito: 0)
1400
- settings.vision.capture.quality = Qualità cattura immagine (%)
1401
- settings.vision.capture.width = Larghezza cattura fotocamera (px)
1399
+ settings.vision.capture.height = Altezza della cattura (in pixel)
1400
+ settings.vision.capture.idx = Dispositivo Fotocamera
1401
+ settings.vision.capture.idx.desc = Seleziona un dispositivo fotocamera per la cattura video in tempo reale
1402
+ settings.vision.capture.quality = Qualità della cattura (%)
1403
+ settings.vision.capture.width = Larghezza della cattura (in pixel)
1402
1404
  settings.zoom = Zoom finestra output chat
1403
1405
  speech.enable = Parla
1404
1406
  speech.listening = Parla ora...
@@ -961,10 +961,11 @@ output.tips.7 = Dla lepszej wydajności wyłącz narzędzia podczas korzystania
961
961
  output.tips.8 = Kiedy korzystasz z lokalnych modeli, pamiętaj o ustawieniu lokalnego modelu dla podsumowania kontekstu i osadzeń.
962
962
  output.tips.9 = Aby skonfigurować dostawców wejścia i wyjścia audio, przejdź do Pluginy -> Ustawienia. Aby skonfigurować urządzenia audio, przejdź do Opcje -> Ustawienia -> Audio.
963
963
  output.tips.prefix = Tip
964
- painter.btn.crop = Przytnij
965
964
  painter.btn.camera.capture = Z kamery
966
965
  painter.btn.capture = Użyj obrazu
967
966
  painter.btn.clear = Wyczyść
967
+ painter.btn.crop = Przytnij
968
+ painter.btn.fit = Dopasuj
968
969
  painter.capture.manual.captured.success = Image captured:
969
970
  painter.capture.name.prefix = Drawing from
970
971
  painter.mode.erase = Gumka
@@ -1368,7 +1369,8 @@ settings.section.remote_tools = Zdalne narzędzia
1368
1369
  settings.section.remote_tools.openai = OpenAI
1369
1370
  settings.section.tab.general = Ogólne
1370
1371
  settings.section.updates = Aktualizacje
1371
- settings.section.vision = Wizja
1372
+ settings.section.vision = Wizja i kamera
1373
+ settings.section.vision.camera = Kamera
1372
1374
  settings.store_history = Zapisuj historię
1373
1375
  settings.store_history_time = Zapisuj czas w historii
1374
1376
  settings.temperature = Temperatura
@@ -1398,11 +1400,11 @@ settings.video.seed = Seed
1398
1400
  settings.video.seed.desc = Optional random seed for reproducible results; leave empty for random
1399
1401
  settings.vision.capture.auto = Auto przechwyt.
1400
1402
  settings.vision.capture.enabled = Kamera
1401
- settings.vision.capture.height = Kamera - obraz szerokość (px)
1402
- settings.vision.capture.idx = Nr. kamery (index)
1403
- settings.vision.capture.idx.desc = Indeks kamery do przechwytywania wideo (indeks kamery, domyślnie: 0)
1404
- settings.vision.capture.quality = Jakość przechwyt. obrazu (%)
1405
- settings.vision.capture.width = Kamera - obraz wysokość (px)
1403
+ settings.vision.capture.height = Wysokość przechwytywania (w pikselach)
1404
+ settings.vision.capture.idx = Urządzenie Kamery
1405
+ settings.vision.capture.idx.desc = Wybierz urządzenie kamery do przechwytywania wideo w czasie rzeczywistym
1406
+ settings.vision.capture.quality = Jakość przechwytywania (%)
1407
+ settings.vision.capture.width = Szerokość przechwytywania (w pikselach)
1406
1408
  settings.zoom = Powiększenie okna outputu czatu
1407
1409
  speech.enable = Mowa
1408
1410
  speech.listening = Mów teraz...
@@ -957,10 +957,11 @@ output.tips.7 = Для кращої продуктивності відключ
957
957
  output.tips.8 = При використанні локальних моделей пам’ятайте встановлювати локальну модель також для зведення контексту та вбудовувань.
958
958
  output.tips.9 = Щоб налаштувати постачальників вхідних та вихідних аудіосигналів, перейдіть до Плагіни -> Налаштування. Щоб налаштувати аудіопристрої, перейдіть до Конфігурація -> Налаштування -> Аудіо.
959
959
  output.tips.prefix = Порада
960
- painter.btn.crop = Обрізати
961
960
  painter.btn.camera.capture = З камери
962
961
  painter.btn.capture = Захопити зображення
963
962
  painter.btn.clear = Очистити
963
+ painter.btn.crop = Обрізати
964
+ painter.btn.fit = Підігнати
964
965
  painter.capture.manual.captured.success = Зображення захоплено:
965
966
  painter.capture.name.prefix = Малюнок з
966
967
  painter.mode.erase = Стерти
@@ -1364,7 +1365,8 @@ settings.section.remote_tools = Віддалені інструменти
1364
1365
  settings.section.remote_tools.openai = OpenAI
1365
1366
  settings.section.tab.general = Загальні
1366
1367
  settings.section.updates = Оновлення
1367
- settings.section.vision = Візія
1368
+ settings.section.vision = Зір і камера
1369
+ settings.section.vision.camera = Камера
1368
1370
  settings.store_history = Зберігати історію
1369
1371
  settings.store_history_time = Зберігати час в історії
1370
1372
  settings.temperature = Температура
@@ -1394,11 +1396,11 @@ settings.video.seed = Seed
1394
1396
  settings.video.seed.desc = Опціональний випадковий seed для відтворюваних результатів; залиште порожнім для випадкового
1395
1397
  settings.vision.capture.auto = Автоматичне захоплення
1396
1398
  settings.vision.capture.enabled = Камера
1397
- settings.vision.capture.height = Висота захоплення з камери (пікселі)
1398
- settings.vision.capture.idx = IDX камери (число)
1399
- settings.vision.capture.idx.desc = Індекс камери для захоплення відео (індекс камери, за замовчуванням: 0)
1400
- settings.vision.capture.quality = Якість захоплення зображення (%)
1401
- settings.vision.capture.width = Ширина захоплення з камери (пікселі)
1399
+ settings.vision.capture.height = Висота зйомки пікселях)
1400
+ settings.vision.capture.idx = Пристрій Камери
1401
+ settings.vision.capture.idx.desc = Виберіть пристрій камери для відеозйомки в реальному часі
1402
+ settings.vision.capture.quality = Якість зйомки (%)
1403
+ settings.vision.capture.width = Ширина зйомки пікселях)
1402
1404
  settings.zoom = Збільшення вікна виводу чату
1403
1405
  speech.enable = Говоріть
1404
1406
  speech.listening = Говоріть зараз...
@@ -957,10 +957,11 @@ output.tips.7 = 为更好的性能,当不需要工具时,请在使用本地
957
957
  output.tips.8 = 在使用本地模型时,记得也为上下文摘要和嵌入设置本地模型。
958
958
  output.tips.9 = 要配置音频输入和输出提供商,请转到插件 -> 设置。要配置音频设备,请转到配置 -> 设置 -> 音频。
959
959
  output.tips.prefix = 提示
960
- painter.btn.crop = 裁剪
961
960
  painter.btn.camera.capture = 从相机
962
961
  painter.btn.capture = 使用图像
963
962
  painter.btn.clear = 清除
963
+ painter.btn.crop = 裁剪
964
+ painter.btn.fit = 适应
964
965
  painter.capture.manual.captured.success = 图像已捕获:
965
966
  painter.capture.name.prefix = 绘制自
966
967
  painter.mode.erase = 擦除
@@ -1364,7 +1365,8 @@ settings.section.remote_tools = 远程工具
1364
1365
  settings.section.remote_tools.openai = OpenAI
1365
1366
  settings.section.tab.general = 一般設置
1366
1367
  settings.section.updates = 更新
1367
- settings.section.vision = 視覺
1368
+ settings.section.vision = 视觉和摄像头
1369
+ settings.section.vision.camera = 摄像头
1368
1370
  settings.store_history = 存儲歷史記錄
1369
1371
  settings.store_history_time = 在歷史記錄中存儲時間
1370
1372
  settings.temperature = 溫度
@@ -1394,11 +1396,11 @@ settings.video.seed = 随机种子
1394
1396
  settings.video.seed.desc = 可选的随机种子以获得可重复的结果;留空为随机
1395
1397
  settings.vision.capture.auto = 自动捕获
1396
1398
  settings.vision.capture.enabled = 相机
1397
- settings.vision.capture.height = 相机高度(px)
1398
- settings.vision.capture.idx = 相机输入设备
1399
- settings.vision.capture.idx.desc = 视频捕获相机索引(相机索引,默认值:0)
1400
- settings.vision.capture.quality = 捕获质量(%)
1401
- settings.vision.capture.width = 相机宽度(px)
1399
+ settings.vision.capture.height = 拍摄高度(像素)
1400
+ settings.vision.capture.idx = 摄像设备
1401
+ settings.vision.capture.idx.desc = 选择实时视频捕捉的摄像设备
1402
+ settings.vision.capture.quality = 拍摄质量(%)
1403
+ settings.vision.capture.width = 拍摄宽度(像素)
1402
1404
  settings.zoom = 聊天输出窗口缩放
1403
1405
  speech.enable = 启用语音
1404
1406
  speech.listening = 现在说话...
@@ -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.06 19:00:00 #
9
+ # Updated Date: 2025.09.02 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import json
@@ -271,6 +271,18 @@ class AssistantStoreItem:
271
271
  self.expire_days = data.get('expire_days', 0)
272
272
  self.status = data.get('status', {})
273
273
 
274
+ def get_file_count(self):
275
+ """
276
+ Return number of files in store
277
+
278
+ :return: number of files
279
+ """
280
+ num = self.num_files
281
+ if self.status and isinstance(self.status, dict) and 'file_counts' in self.status:
282
+ if 'completed' in self.status['file_counts']:
283
+ num = int(self.status['file_counts']['completed'] or 0)
284
+ return num
285
+
274
286
  def dump(self) -> str:
275
287
  """
276
288
  Dump item to string
@@ -69,43 +69,19 @@ class ApiGoogle:
69
69
  model = ModelItem()
70
70
  model.provider = "google"
71
71
  args = self.window.core.models.prepare_client_args(mode, model)
72
- config = self.window.core.config
73
-
74
72
  filtered = {}
75
73
  if args.get("api_key"):
76
74
  filtered["api_key"] = args["api_key"]
77
75
 
78
- # setup VertexAI
79
- use_vertex = False
80
- if config.get("api_native_google.use_vertex", False):
81
- use_vertex = True
82
- os.environ["GOOGLE_GENAI_USE_VERTEXAI"] = "1"
83
- os.environ["GOOGLE_CLOUD_PROJECT"] = config.get("api_native_google.cloud_project", "")
84
- os.environ["GOOGLE_CLOUD_LOCATION"] = config.get("api_native_google.cloud_location", "us-central1")
85
- if config.get("api_native_google.app_credentials", ""):
86
- os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = config.get("api_native_google.app_credentials", "")
87
- else:
88
- if os.environ.get("GOOGLE_GENAI_USE_VERTEXAI"):
89
- del os.environ["GOOGLE_GENAI_USE_VERTEXAI"]
90
- if os.environ.get("GOOGLE_CLOUD_PROJECT"):
91
- del os.environ["GOOGLE_CLOUD_PROJECT"]
92
- if os.environ.get("GOOGLE_CLOUD_LOCATION"):
93
- del os.environ["GOOGLE_CLOUD_LOCATION"]
94
- if os.environ.get("GOOGLE_APPLICATION_CREDENTIALS"):
95
- del os.environ["GOOGLE_APPLICATION_CREDENTIALS"]
96
-
97
- # append VertexAI params to client args
76
+ # setup VertexAI if enabled
77
+ use_vertex = self.setup_env()
98
78
  if use_vertex:
99
79
  filtered["vertexai"] = True
100
80
  filtered["project"] = os.environ.get("GOOGLE_CLOUD_PROJECT")
101
81
  filtered["location"] = os.environ.get("GOOGLE_CLOUD_LOCATION", "us-central1")
102
82
  # filtered["http_options"] = gtypes.HttpOptions(api_version="v1")
103
83
 
104
- if self.client is None or self.last_client_args != filtered:
105
- self.client = genai.Client(**filtered)
106
- self.last_client_args = filtered
107
-
108
- return self.client
84
+ return genai.Client(**filtered)
109
85
 
110
86
  def call(
111
87
  self,
@@ -313,6 +289,36 @@ class ApiGoogle:
313
289
 
314
290
  return tools
315
291
 
292
+ def setup_env(self) -> bool:
293
+ """
294
+ Setup environment variables for VertexAI via Google GenAI API
295
+
296
+ - GOOGLE_GENAI_USE_VERTEXAI
297
+ - GOOGLE_CLOUD_PROJECT
298
+ - GOOGLE_CLOUD_LOCATION
299
+ - GOOGLE_APPLICATION_CREDENTIALS
300
+
301
+ :return: bool: True if VertexAI is used, False otherwise
302
+ """
303
+ config = self.window.core.config
304
+ use_vertex = False
305
+ if config.get("api_native_google.use_vertex", False):
306
+ use_vertex = True
307
+ os.environ["GOOGLE_GENAI_USE_VERTEXAI"] = "1"
308
+ os.environ["GOOGLE_CLOUD_PROJECT"] = config.get("api_native_google.cloud_project", "")
309
+ os.environ["GOOGLE_CLOUD_LOCATION"] = config.get("api_native_google.cloud_location", "us-central1")
310
+ if config.get("api_native_google.app_credentials", ""):
311
+ os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = config.get("api_native_google.app_credentials", "")
312
+ else:
313
+ if os.environ.get("GOOGLE_GENAI_USE_VERTEXAI"):
314
+ del os.environ["GOOGLE_GENAI_USE_VERTEXAI"]
315
+ if os.environ.get("GOOGLE_CLOUD_PROJECT"):
316
+ del os.environ["GOOGLE_CLOUD_PROJECT"]
317
+ if os.environ.get("GOOGLE_CLOUD_LOCATION"):
318
+ del os.environ["GOOGLE_CLOUD_LOCATION"]
319
+ if os.environ.get("GOOGLE_APPLICATION_CREDENTIALS"):
320
+ del os.environ["GOOGLE_APPLICATION_CREDENTIALS"]
321
+ return use_vertex
316
322
 
317
323
  def stop(self):
318
324
  """On global event stop"""
@@ -328,4 +334,16 @@ class ApiGoogle:
328
334
  # self.client.close()
329
335
  except Exception as e:
330
336
  self.window.core.debug.log(e)
331
- print("Error closing Google client:", e)
337
+ print("Error closing Google client:", e)
338
+
339
+ def safe_close(self):
340
+ """Close client"""
341
+ if self.locked:
342
+ return
343
+ if self.client is not None:
344
+ try:
345
+ self.client.close()
346
+ self.client = None
347
+ except Exception as e:
348
+ self.window.core.debug.log(e)
349
+ print("Error closing client:", e)
@@ -81,16 +81,7 @@ class ApiOpenAI:
81
81
  """
82
82
  # update client args by mode and model
83
83
  args = self.window.core.models.prepare_client_args(mode, model)
84
- if self.client is None or self.last_client_args != args:
85
- if self.client is not None:
86
- try:
87
- self.client.close() # close previous client if exists
88
- except Exception as e:
89
- self.window.core.debug.log(e)
90
- print("Error closing previous GPT client:", e)
91
- self.client = OpenAI(**args)
92
- self.last_client_args = args
93
- return self.client
84
+ return OpenAI(**args)
94
85
 
95
86
  def call(
96
87
  self,
@@ -342,3 +333,15 @@ class ApiOpenAI:
342
333
  except Exception as e:
343
334
  self.window.core.debug.log(e)
344
335
  print("Error closing GPT client:", e)
336
+
337
+ def safe_close(self):
338
+ """Close client"""
339
+ if self.locked:
340
+ return
341
+ if self.client is not None:
342
+ try:
343
+ self.client.close()
344
+ self.client = None
345
+ except Exception as e:
346
+ self.window.core.debug.log(e)
347
+ print("Error closing client:", e)
@@ -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.07.14 18:00:00 #
9
+ # Updated Date: 2025.09.02 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -175,6 +175,50 @@ class Store:
175
175
  self.log(msg, callback)
176
176
  return num
177
177
 
178
+ def remove_file(
179
+ self,
180
+ file_id: str,
181
+ callback: Optional[callable] = None
182
+ ) -> bool:
183
+ """
184
+ Remove a single file using the Files API.
185
+
186
+ :param file_id: file ID
187
+ :param callback: callback function for logging
188
+ :return: True if removed
189
+ """
190
+ self.log("Removing file: " + file_id, callback)
191
+ try:
192
+ res = self.delete_file(file_id)
193
+ return res is not None
194
+ except Exception as e:
195
+ msg = "Error removing file {}: {}".format(file_id, str(e))
196
+ self.log(msg, callback)
197
+ raise
198
+
199
+ def remove_store_file(
200
+ self,
201
+ store_id: str,
202
+ file_id: str,
203
+ callback: Optional[callable] = None
204
+ ) -> bool:
205
+ """
206
+ Remove a single file from a specific vector store.
207
+
208
+ :param store_id: store ID
209
+ :param file_id: file ID
210
+ :param callback: callback function for logging
211
+ :return: True if removed
212
+ """
213
+ self.log("Removing file from vector store [{}]: {}".format(store_id, file_id), callback)
214
+ try:
215
+ res = self.delete_store_file(store_id, file_id)
216
+ return res is not None
217
+ except Exception as e:
218
+ msg = "Error removing file {} from store {}: {}".format(file_id, store_id, str(e))
219
+ self.log(msg, callback)
220
+ raise
221
+
178
222
  def remove_store_files(
179
223
  self,
180
224
  store_id: str,
@@ -2429,6 +2429,24 @@ class Patch:
2429
2429
  patch_css('web-blocks.css', True)
2430
2430
  updated = True
2431
2431
 
2432
+ # < 2.6.35
2433
+ if old < parse_version("2.6.35"):
2434
+ print("Migrating config from < 2.6.35...")
2435
+ # remove will-change
2436
+ patch_css('web-chatgpt.css', True)
2437
+ patch_css('web-chatgpt_wide.css', True)
2438
+ patch_css('web-blocks.css', True)
2439
+ updated = True
2440
+
2441
+ # < 2.6.36
2442
+ if old < parse_version("2.6.36"):
2443
+ print("Migrating config from < 2.6.36...")
2444
+ # perf css
2445
+ patch_css('web-chatgpt.css', True)
2446
+ patch_css('web-chatgpt_wide.css', True)
2447
+ patch_css('web-blocks.css', True)
2448
+ updated = True
2449
+
2432
2450
  # update file
2433
2451
  migrated = False
2434
2452
  if updated:
@@ -55,6 +55,8 @@ class GoogleLLM(BaseLLM):
55
55
  args["model"] = model.id
56
56
  if "api_key" not in args or args["api_key"] == "":
57
57
  args["api_key"] = window.core.config.get("api_key_google", "")
58
+
59
+ window.core.api.google.setup_env() # setup VertexAI if configured
58
60
  return GoogleGenAI(**args)
59
61
 
60
62
  def get_embeddings_model(
@@ -79,6 +81,8 @@ class GoogleLLM(BaseLLM):
79
81
  args["api_key"] = window.core.config.get("api_key_google", "")
80
82
  if "model" in args and "model_name" not in args:
81
83
  args["model_name"] = args.pop("model")
84
+
85
+ window.core.api.google.setup_env() # setup VertexAI if configured
82
86
  return GoogleGenAIEmbedding(**args)
83
87
 
84
88
  def get_models(