pygpt-net 2.4.37__py3-none-any.whl → 2.4.39__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 (81) hide show
  1. CHANGELOG.md +11 -0
  2. README.md +24 -5
  3. pygpt_net/CHANGELOG.txt +11 -0
  4. pygpt_net/__init__.py +3 -3
  5. pygpt_net/controller/__init__.py +3 -1
  6. pygpt_net/controller/calendar/__init__.py +3 -1
  7. pygpt_net/controller/chat/render.py +8 -5
  8. pygpt_net/controller/config/placeholder.py +29 -0
  9. pygpt_net/controller/ctx/__init__.py +32 -24
  10. pygpt_net/controller/ctx/common.py +3 -2
  11. pygpt_net/controller/dialogs/confirm.py +2 -2
  12. pygpt_net/controller/lang/custom.py +2 -7
  13. pygpt_net/controller/lang/mapping.py +2 -2
  14. pygpt_net/controller/layout.py +2 -2
  15. pygpt_net/controller/notepad.py +8 -5
  16. pygpt_net/controller/settings/editor.py +6 -0
  17. pygpt_net/controller/theme/__init__.py +33 -8
  18. pygpt_net/controller/theme/common.py +22 -1
  19. pygpt_net/controller/theme/markdown.py +26 -14
  20. pygpt_net/controller/theme/menu.py +26 -5
  21. pygpt_net/controller/ui/tabs.py +201 -58
  22. pygpt_net/core/attachments/context.py +14 -12
  23. pygpt_net/core/audio/__init__.py +59 -1
  24. pygpt_net/core/ctx/__init__.py +11 -1
  25. pygpt_net/core/ctx/container.py +16 -9
  26. pygpt_net/core/ctx/output.py +86 -67
  27. pygpt_net/core/debug/tabs.py +3 -2
  28. pygpt_net/core/filesystem/__init__.py +5 -19
  29. pygpt_net/core/filesystem/url.py +7 -3
  30. pygpt_net/core/render/base.py +14 -3
  31. pygpt_net/core/render/markdown/renderer.py +3 -1
  32. pygpt_net/core/render/plain/renderer.py +3 -3
  33. pygpt_net/core/render/web/body.py +39 -17
  34. pygpt_net/core/render/web/renderer.py +7 -5
  35. pygpt_net/core/tabs/__init__.py +180 -71
  36. pygpt_net/core/tabs/tab.py +13 -4
  37. pygpt_net/data/config/config.json +14 -4
  38. pygpt_net/data/config/models.json +3 -3
  39. pygpt_net/data/config/modes.json +3 -3
  40. pygpt_net/data/config/settings.json +55 -10
  41. pygpt_net/data/config/settings_section.json +3 -0
  42. pygpt_net/data/css/style.light.css +1 -0
  43. pygpt_net/data/css/{web.css → web-blocks.css} +144 -133
  44. pygpt_net/data/css/web-chatgpt.css +342 -0
  45. pygpt_net/data/css/web-chatgpt.dark.css +64 -0
  46. pygpt_net/data/css/web-chatgpt.light.css +75 -0
  47. pygpt_net/data/css/web-chatgpt_wide.css +342 -0
  48. pygpt_net/data/css/web-chatgpt_wide.dark.css +64 -0
  49. pygpt_net/data/css/web-chatgpt_wide.light.css +75 -0
  50. pygpt_net/data/locale/locale.de.ini +12 -0
  51. pygpt_net/data/locale/locale.en.ini +14 -1
  52. pygpt_net/data/locale/locale.es.ini +12 -0
  53. pygpt_net/data/locale/locale.fr.ini +12 -0
  54. pygpt_net/data/locale/locale.it.ini +12 -0
  55. pygpt_net/data/locale/locale.pl.ini +12 -0
  56. pygpt_net/data/locale/locale.uk.ini +12 -0
  57. pygpt_net/data/locale/locale.zh.ini +12 -0
  58. pygpt_net/plugin/audio_input/simple.py +21 -5
  59. pygpt_net/provider/core/config/patch.py +22 -1
  60. pygpt_net/provider/core/ctx/base.py +4 -1
  61. pygpt_net/provider/core/ctx/db_sqlite/__init__.py +10 -1
  62. pygpt_net/provider/core/ctx/db_sqlite/storage.py +22 -1
  63. pygpt_net/ui/layout/chat/input.py +10 -18
  64. pygpt_net/ui/layout/chat/output.py +26 -44
  65. pygpt_net/ui/layout/toolbox/footer.py +18 -2
  66. pygpt_net/ui/menu/config.py +7 -11
  67. pygpt_net/ui/menu/theme.py +9 -2
  68. pygpt_net/ui/widget/lists/context.py +1 -0
  69. pygpt_net/ui/widget/tabs/layout.py +195 -0
  70. pygpt_net/ui/widget/tabs/output.py +124 -35
  71. pygpt_net/ui/widget/textarea/html.py +11 -1
  72. pygpt_net/ui/widget/textarea/output.py +10 -1
  73. pygpt_net/ui/widget/textarea/search_input.py +4 -1
  74. pygpt_net/ui/widget/textarea/web.py +49 -9
  75. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.39.dist-info}/METADATA +25 -6
  76. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.39.dist-info}/RECORD +81 -74
  77. /pygpt_net/data/css/{web.dark.css → web-blocks.dark.css} +0 -0
  78. /pygpt_net/data/css/{web.light.css → web-blocks.light.css} +0 -0
  79. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.39.dist-info}/LICENSE +0 -0
  80. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.39.dist-info}/WHEEL +0 -0
  81. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.39.dist-info}/entry_points.txt +0 -0
@@ -49,6 +49,8 @@ action.tab.add.notepad = Aggiungi un nuovo blocco note
49
49
  action.tab.close = Chiudi
50
50
  action.tab.close_all.chat = Chiudi tutte le chat
51
51
  action.tab.close_all.notepad = Chiudi tutti i blocchi note
52
+ action.tab.move.left = Sposta nella colonna di sinistra
53
+ action.tab.move.right = Sposta nella colonna di destra
52
54
  action.touch = Crea file...
53
55
  action.truncate = Cancellare tutto
54
56
  action.undo = Annulla
@@ -548,6 +550,7 @@ ipython.docker.build.finish = Successo! L'immagine Docker per IPython è stata c
548
550
  ipython.docker.build.start = Creazione dell'immagine Docker... per favore aspetta...
549
551
  ipython.docker.install = L'esecuzione di IPython richiede l'installazione di Docker. Docker non è stato rilevato su questo sistema. Si prega di installare prima Docker; puoi trovare le istruzioni qui: https://docs.docker.com/engine/install/. L'esecuzione del comando corrente è stata messa in pausa.
550
552
  ipython.image.build = L'immagine Docker per IPython non è stata ancora costruita. Questo avverrà ora e potrebbe richiedere del tempo (ma è una procedura una tantum). L'esecuzione del comando è stata messa in pausa. Una volta costruita l'immagine, esegui nuovamente il comando.
553
+ layout.split = Schermo diviso (beta)
551
554
  menu.audio = Audio / Voce
552
555
  menu.audio.cache.clear = Cancella cache audio...
553
556
  menu.audio.control.global = Controllo vocale (globale)
@@ -612,6 +615,7 @@ menu.theme.dark = Colore scuro...
612
615
  menu.theme.density = Dimensione del layout
613
616
  menu.theme.light = Colore chiaro...
614
617
  menu.theme.settings = Impostazioni...
618
+ menu.theme.style = Stile...
615
619
  menu.theme.syntax = Evidenziazione della sintassi del codice...
616
620
  menu.theme.tooltips = Mostra suggerimenti
617
621
  menu.tools = Strumenti
@@ -753,6 +757,12 @@ settings.api_key = OpenAI API KEY
753
757
  settings.api_key.desc = Richiesto per l'API OpenAI. Se desideri utilizzare endpoint personalizzati o API locali, puoi inserire qui qualsiasi valore.
754
758
  settings.app.env = Ambiente dell'applicazione (os.environ)
755
759
  settings.app.env.desc = Variabili d'ambiente aggiuntive da impostare all'avvio dell'applicazione
760
+ settings.audio.input.channels = Canali
761
+ settings.audio.input.channels.desc = Canali di ingresso, predefinito: 1
762
+ settings.audio.input.device = Dispositivo di Ingresso Audio
763
+ settings.audio.input.device.desc = Seleziona il dispositivo audio per l'ingresso del microfono.
764
+ settings.audio.input.rate = Frequenza di campionamento
765
+ settings.audio.input.rate.desc = Frequenza di campionamento, predefinito: 44100
756
766
  settings.check_updates = Controlla aggiornamenti all'avvio
757
767
  settings.check_updates.bg = Controlla gli aggiornamenti in background
758
768
  settings.cmd.field.desc = Abilita lo strumento `{cmd}`.
@@ -857,6 +867,7 @@ settings.render.code_syntax = Stile di evidenziazione della sintassi del codice
857
867
  settings.restart.required = È necessario riavviare l'applicazione affinché le modifiche a questa opzione siano applicate.
858
868
  settings.section.access = Accessibilità
859
869
  settings.section.agent = Agenti ed esperti
870
+ settings.section.audio = Audio
860
871
  settings.section.ctx = Contesto
861
872
  settings.section.files = File e allegati
862
873
  settings.section.general = Generale
@@ -870,6 +881,7 @@ settings.store_history = Conserva la cronologia
870
881
  settings.store_history_time = Conserva l'orario nella cronologia
871
882
  settings.temperature = Temperatura
872
883
  settings.theme.markdown = Usa i colori del tema nella finestra della chat
884
+ settings.theme.style = Stile (chat)
873
885
  settings.top_p = Top-p
874
886
  settings.upload.data_dir = Memorizza immagini, catture e caricamenti nella directory dei dati
875
887
  settings.upload.data_dir.desc = Abilita per memorizzare tutto in una singola directory dei dati
@@ -49,6 +49,8 @@ action.tab.add.notepad = Dodaj nowy notatnik
49
49
  action.tab.close = Zamknij
50
50
  action.tab.close_all.chat = Zamknij wszystkie czaty
51
51
  action.tab.close_all.notepad = Zamknij wszystkie notatniki
52
+ action.tab.move.left = Przenieś do lewej kolumny
53
+ action.tab.move.right = Przenieś do prawej kolumny
52
54
  action.touch = Utwórz plik...
53
55
  action.truncate = Wyczyść wszystko
54
56
  action.undo = Cofnij
@@ -548,6 +550,7 @@ ipython.docker.build.finish = Sukces! Obraz Docker dla IPython został zbudowany
548
550
  ipython.docker.build.start = Budowanie obrazu Dockera... proszę czekać...
549
551
  ipython.docker.install = Uruchomienie IPython wymaga zainstalowania Dockera. Docker nie został wykryty na tym systemie. Proszę najpierw zainstalować Dockera; instrukcje można znaleźć tutaj: https://docs.docker.com/engine/install/. Wykonywanie bieżącego polecenia zostało wstrzymane.
550
552
  ipython.image.build = Obraz Dockera dla IPython nie został jeszcze zbudowany. Nastąpi to teraz i może to potrwać chwilę (ale to jednorazowa procedura). Wykonywanie polecenia zostało wstrzymane. Po zbudowaniu obrazu możesz ponownie poprosić o wykonanie polecenia.
553
+ layout.split = Podziel ekran (beta)
551
554
  menu.audio = Audio / Mowa
552
555
  menu.audio.cache.clear = Wyczyść pamięć podręczną audio...
553
556
  menu.audio.control.global = Kontrola głosowa (globalna)
@@ -612,6 +615,7 @@ menu.theme.dark = Ciemny kolor...
612
615
  menu.theme.density = Rozmiar układu
613
616
  menu.theme.light = Jasny kolor...
614
617
  menu.theme.settings = Ustawienia...
618
+ menu.theme.style = Styl...
615
619
  menu.theme.syntax = Podświetlanie składni kodu...
616
620
  menu.theme.tooltips = Pokaż podpowiedzi
617
621
  menu.tools = Narzędzia
@@ -753,6 +757,12 @@ settings.api_key = Klucz API OpenAI
753
757
  settings.api_key.desc = Wymagany dla API OpenAI. Jeśli chcesz używać niestandardowych punktów końcowych lub lokalnych API, możesz tutaj wprowadzić dowolną wartość.
754
758
  settings.app.env = Środowisko aplikacji (os.environ)
755
759
  settings.app.env.desc = Dodatkowe zmienne środowiskowe do ustawienia przy starcie aplikacji
760
+ settings.audio.input.channels = Kanały
761
+ settings.audio.input.channels.desc = Kanały wejściowe, domyślnie: 1
762
+ settings.audio.input.device = Urządzenie Wejściowe Audio
763
+ settings.audio.input.device.desc = Wybierz urządzenie audio dla wejścia mikrofonu.
764
+ settings.audio.input.rate = Częstotliwość próbkowania
765
+ settings.audio.input.rate.desc = Częstotliwość próbkowania, domyślnie: 44100
756
766
  settings.check_updates = Sprawdź aktualizacje przy starcie
757
767
  settings.check_updates.bg = Sprawdź aktualizacje w tle
758
768
  settings.cmd.field.desc = Włącz narzędzie `{cmd}`.
@@ -858,6 +868,7 @@ settings.render.plain = Wyłącz formatowanie markdown w wyjściu (tryb plain-te
858
868
  settings.restart.required = Restart aplikacji jest wymagany, aby zmiany dla tej opcji zostały wprowadzone.
859
869
  settings.section.access = Dostępność
860
870
  settings.section.agent = Agenci i eksperci
871
+ settings.section.audio = Audio
861
872
  settings.section.ctx = Kontekst
862
873
  settings.section.files = Pliki i załączniki
863
874
  settings.section.general = Ogólne
@@ -871,6 +882,7 @@ settings.store_history = Zapisuj historię
871
882
  settings.store_history_time = Zapisuj czas w historii
872
883
  settings.temperature = Temperatura
873
884
  settings.theme.markdown = Użyj motywu kolorystycznego w oknie czatu
885
+ settings.theme.style = Styl (czat)
874
886
  settings.top_p = Top-p
875
887
  settings.upload.data_dir = Przechowuj obrazy, zrzuty ekranu i przesyłane pliki w katalogu danych
876
888
  settings.upload.data_dir.desc = Włącz, aby przechowywać wszystko w jednym katalogu danych
@@ -49,6 +49,8 @@ action.tab.add.notepad = Додати новий блокнот
49
49
  action.tab.close = Закрити
50
50
  action.tab.close_all.chat = Закрити всі чати
51
51
  action.tab.close_all.notepad = Закрити всі блокноти
52
+ action.tab.move.left = Перемістити в ліву колонку
53
+ action.tab.move.right = Перемістити в праву колонку
52
54
  action.touch = Створити файл...
53
55
  action.truncate = Очистити все
54
56
  action.undo = Скасувати
@@ -547,6 +549,7 @@ ipython.docker.build.finish = Успіх! Образ Docker для IPython ст
547
549
  ipython.docker.build.start = Створення образу Docker... будь ласка, зачекайте...
548
550
  ipython.docker.install = Для запуску IPython необхідно встановити Docker. Docker не було виявлено на цій системі. Будь ласка, спочатку встановіть Docker; інструкції можна знайти тут: https://docs.docker.com/engine/install/. Виконання поточної команди було призупинено.
549
551
  ipython.image.build = Docker-образ для IPython ще не був створений. Це відбудеться зараз, і це може зайняти деякий час (але це одноразова процедура). Виконання команди було призупинено. Після створення образу, будь ласка, виконайте команду знову.
552
+ layout.split = Розділити екран (бета)
550
553
  menu.audio = Аудіо / Голос
551
554
  menu.audio.cache.clear = Очистити кеш аудіо...
552
555
  menu.audio.control.global = Контроль голосу (глобальний)
@@ -611,6 +614,7 @@ menu.theme.dark = Темний колір...
611
614
  menu.theme.density = Розмір компонування
612
615
  menu.theme.light = Світлий колір...
613
616
  menu.theme.settings = Налаштування...
617
+ menu.theme.style = Стиль...
614
618
  menu.theme.syntax = Підсвітка синтаксису коду...
615
619
  menu.theme.tooltips = Показувати підказки
616
620
  menu.tools = Інструменти
@@ -752,6 +756,12 @@ settings.api_key = OpenAI API КЛЮЧ
752
756
  settings.api_key.desc = Необхідний для API OpenAI. Якщо ви бажаєте використовувати налаштовані кінцеві точки або локальні API, тоді ви можете ввести будь-яке значення тут.
753
757
  settings.app.env = Оточення додатка (os.environ)
754
758
  settings.app.env.desc = Додаткові змінні середовища для встановлення при запуску додатка
759
+ settings.audio.input.channels = Канали
760
+ settings.audio.input.channels.desc = Вхідні канали, за замовчуванням: 1
761
+ settings.audio.input.device = Аудіо Вхідний Пристрій
762
+ settings.audio.input.device.desc = Виберіть аудіо пристрій для введення мікрофона.
763
+ settings.audio.input.rate = Частота дискретизації
764
+ settings.audio.input.rate.desc = Частота дискретизації, за замовчуванням: 44100
755
765
  settings.check_updates = Перевіряти оновлення при запуску
756
766
  settings.check_updates.bg = Перевіряти оновлення у фоновому режимі
757
767
  settings.cmd.field.desc = Увімкнути інструмент `{cmd}`.
@@ -857,6 +867,7 @@ settings.render.plain = Вимкнути форматування markdown у в
857
867
  settings.restart.required = Для внесення змін у цю опцію необхідно перезапустити програму.
858
868
  settings.section.access = Доступність
859
869
  settings.section.agent = Агенти та експерти
870
+ settings.section.audio = Аудіо
860
871
  settings.section.ctx = Контекст
861
872
  settings.section.files = Файли та вкладення
862
873
  settings.section.general = Загальні
@@ -870,6 +881,7 @@ settings.store_history = Зберігати історію
870
881
  settings.store_history_time = Зберігати час в історії
871
882
  settings.temperature = Температура
872
883
  settings.theme.markdown = Використовуйте кольори теми у вікні чату
884
+ settings.theme.style = Стиль (чат)
873
885
  settings.top_p = Top-p
874
886
  settings.upload.data_dir = Зберігайте зображення, знімки екрану та завантаження у директорії даних
875
887
  settings.upload.data_dir.desc = Увімкніть, щоб зберігати все в одній директорії даних
@@ -50,6 +50,8 @@ action.tab.add.notepad = 添加新记事本
50
50
  action.tab.close = 关闭
51
51
  action.tab.close_all.chat = 关闭所有聊天
52
52
  action.tab.close_all.notepad = 关闭所有记事本
53
+ action.tab.move.left = 移到左列
54
+ action.tab.move.right = 移到右列
53
55
  action.touch = 創建文件...
54
56
  action.truncate = 截斷
55
57
  action.undo = 撤銷
@@ -621,6 +623,7 @@ ipython.docker.build.finish = 成功!IPython 的 Docker 镜像已构建完成
621
623
  ipython.docker.build.start = 正在构建 Docker 镜像... 请稍候...
622
624
  ipython.docker.install = 运行 IPython 需要安装 Docker。系统上未检测到 Docker。请先安装 Docker;您可以在此处找到说明:https://docs.docker.com/engine/install/。当前命令的执行已暂停。
623
625
  ipython.image.build = IPython 的 Docker 镜像尚未构建。这将立即发生,可能需要一段时间(但这是一次性过程)。命令的执行已暂停。镜像构建完成后,请再次执行命令。
626
+ layout.split = 分屏 (测试版)
624
627
  menu.audio = 音頻/語音
625
628
  menu.audio.cache.clear = 清除音频缓存...
626
629
  menu.audio.control.global = 语音控制(全局)
@@ -687,6 +690,7 @@ menu.theme.dark = 深色主題...
687
690
  menu.theme.density = 布局大小
688
691
  menu.theme.light = 淺色主題...
689
692
  menu.theme.settings = 設置...
693
+ menu.theme.style = 风格...
690
694
  menu.theme.syntax = 代码语法高亮显示...
691
695
  menu.theme.tooltips = 顯示工具提示
692
696
  menu.tools = 工具
@@ -854,6 +858,12 @@ settings.api_key = OpenAI API KEY
854
858
  settings.api_key.desc = OpenAI API所需。如果您希望使用自定义终端或本地API,则可以在此输入任意值。
855
859
  settings.app.env = 应用程序环境 (os.environ)
856
860
  settings.app.env.desc = 在应用程序启动时要设置的额外环境变量
861
+ settings.audio.input.channels = 声道
862
+ settings.audio.input.channels.desc = 输入声道,默认: 1
863
+ settings.audio.input.device = 音频输入设备
864
+ settings.audio.input.device.desc = 选择用于麦克风输入的音频设备。
865
+ settings.audio.input.rate = 采样率
866
+ settings.audio.input.rate.desc = 采样率,默认: 44100
857
867
  settings.check_updates = 啟動時檢查更新
858
868
  settings.check_updates.bg = 在後台檢查更新
859
869
  settings.cmd.field.desc = 启用 `{cmd}` 工具。
@@ -967,6 +977,7 @@ settings.render.plain = 在輸出中禁用markdown格式化(RAW純文本模式
967
977
  settings.restart.required = 此選項生效需要重新啟動應用程序。
968
978
  settings.section.access = 可访问性
969
979
  settings.section.agent = 代理和专家
980
+ settings.section.audio = 音频
970
981
  settings.section.ctx = 上下文
971
982
  settings.section.developer = 開發者
972
983
  settings.section.files = 文件和附件
@@ -986,6 +997,7 @@ settings.store_history = 存儲歷史記錄
986
997
  settings.store_history_time = 在歷史記錄中存儲時間
987
998
  settings.temperature = 溫度
988
999
  settings.theme.markdown = 在聊天窗口中使用主題顏色
1000
+ settings.theme.style = 风格 (聊天)
989
1001
  settings.top_p = Top-p
990
1002
  settings.upload.data_dir = 在data目錄中存儲圖像、捕獲和上傳
991
1003
  settings.upload.data_dir.desc= 啟用以在單個data目錄中存儲所有內容
@@ -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.11.21 02:00:00 #
9
+ # Updated Date: 2024.12.08 00:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import pyaudio
@@ -84,11 +84,25 @@ class Simple:
84
84
  self.timer.timeout.connect(self.stop_timeout)
85
85
  self.timer.start(self.TIMEOUT_SECONDS * 1000)
86
86
 
87
+ # select audio input device
88
+ device_id = int(self.plugin.window.core.config.get('audio.input.device', 0))
89
+ rate = int(self.plugin.window.core.config.get('audio.input.rate', 44100))
90
+ channels = int(self.plugin.window.core.config.get('audio.input.channels', 1))
91
+ if not self.plugin.window.core.audio.is_device_compatible(device_id):
92
+ err = self.plugin.window.core.audio.get_last_error()
93
+ message = "Selected audio input device is not compatible. Please select another one. ERROR: " + str(err)
94
+ self.is_recording = False
95
+ self.plugin.window.core.debug.log(message)
96
+ self.plugin.window.ui.dialogs.alert(message)
97
+ self.switch_btn_start() # switch button to start
98
+ return
99
+
87
100
  self.p = pyaudio.PyAudio()
88
101
  self.stream = self.p.open(format=pyaudio.paInt16,
89
- channels=1,
90
- rate=44100,
102
+ channels=channels,
103
+ rate=rate,
91
104
  input=True,
105
+ input_device_index=device_id,
92
106
  frames_per_buffer=1024,
93
107
  stream_callback=callback)
94
108
 
@@ -137,9 +151,11 @@ class Simple:
137
151
  self.plugin.window.dispatch(AppEvent(AppEvent.VOICE_CONTROL_STOPPED)) # app event
138
152
  return
139
153
  wf = wave.open(path, 'wb')
140
- wf.setnchannels(1)
154
+ channels = int(self.plugin.window.core.config.get('audio.input.channels', 1))
155
+ rate = int(self.plugin.window.core.config.get('audio.input.rate', 44100))
156
+ wf.setnchannels(channels)
141
157
  wf.setsampwidth(self.p.get_sample_size(pyaudio.paInt16))
142
- wf.setframerate(44100)
158
+ wf.setframerate(rate)
143
159
  wf.writeframes(b''.join(self.frames))
144
160
  wf.close()
145
161
  self.plugin.handle_thread(True) # handle transcription in simple mode
@@ -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.11.29 23:00:00 #
9
+ # Updated Date: 2024.12.09 03:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import copy
@@ -1734,6 +1734,27 @@ class Patch:
1734
1734
  'ctx.attachment.rag.history.max_items')
1735
1735
  updated = True
1736
1736
 
1737
+ # < 2.4.38
1738
+ if old < parse_version("2.4.38"):
1739
+ print("Migrating config from < 2.4.38...")
1740
+ if 'theme.style' not in data:
1741
+ data["theme.style"] = "blocks"
1742
+ if 'audio.input.device' not in data:
1743
+ data["audio.input.device"] = "0"
1744
+ if 'audio.input.channels' not in data:
1745
+ data["audio.input.channels"] = 1
1746
+ if 'audio.input.rate' not in data:
1747
+ data["audio.input.rate"] = 44100
1748
+ self.window.core.updater.patch_css('style.light.css', True) # force update
1749
+ updated = True
1750
+
1751
+ # < 2.4.39
1752
+ if old < parse_version("2.4.39"):
1753
+ print("Migrating config from < 2.4.39...")
1754
+ if 'layout.split' not in data:
1755
+ data["layout.split"] = False
1756
+ updated = True
1757
+
1737
1758
  # update file
1738
1759
  migrated = False
1739
1760
  if updated:
@@ -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.04.08 21:00:00 #
9
+ # Updated Date: 2024.12.09 00:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from packaging.version import Version
@@ -71,6 +71,9 @@ class BaseProvider:
71
71
  def get_meta_indexed(self):
72
72
  pass
73
73
 
74
+ def get_item_by_id(self, id: int) -> CtxItem:
75
+ pass
76
+
74
77
  def dump(self, ctx: CtxItem):
75
78
  pass
76
79
 
@@ -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.08.29 04:00:00 #
9
+ # Updated Date: 2024.12.09 00:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import time
@@ -118,6 +118,15 @@ class DbSqliteProvider(BaseProvider):
118
118
  """
119
119
  return self.storage.get_last_meta_id()
120
120
 
121
+ def get_item_by_id(self, id: int) -> CtxItem:
122
+ """
123
+ Get ctx item by ID
124
+
125
+ :param id: ctx item ID
126
+ :return: ctx item
127
+ """
128
+ return self.storage.get_item_by_id(id)
129
+
121
130
  def load(self, id: int) -> list:
122
131
  """
123
132
  Load items for ctx ID
@@ -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.11.26 19:00:00 #
9
+ # Updated Date: 2024.12.09 00:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from datetime import datetime
@@ -189,6 +189,27 @@ class Storage:
189
189
  items[meta.id] = meta
190
190
  return items
191
191
 
192
+ def get_item_by_id(self, id: int) -> CtxItem:
193
+ """
194
+ Return ctx item by ID
195
+
196
+ :return: CtxItem
197
+ """
198
+ stmt = text("""
199
+ SELECT * FROM ctx_item WHERE id = :id
200
+ """).bindparams(id=id)
201
+ db = self.window.core.db.get_db()
202
+ with db.connect() as conn:
203
+ result = conn.execute(stmt)
204
+ row = result.fetchone()
205
+ if row:
206
+ item = CtxItem()
207
+ unpack_item(item, row._asdict())
208
+ meta = self.get_meta_by_id(item.meta_id) # append meta
209
+ item.meta = meta
210
+ return item
211
+ return None
212
+
192
213
  def get_meta_by_root_id_and_preset_id(self, root_id: int, preset_id: str) -> dict:
193
214
  """
194
215
  Return dict with indexed CtxMeta objects, indexed by ID
@@ -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.11.23 00:00:00 #
9
+ # Updated Date: 2024.12.09 03:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Qt
@@ -153,14 +153,6 @@ class Input:
153
153
  """
154
154
  # header (input label + input counter)
155
155
  self.window.ui.nodes['input.label'] = HelpLabel(trans("input.label"))
156
- self.window.ui.nodes['input.counter'] = QLabel("")
157
- self.window.ui.nodes['input.counter'].setToolTip(trans('tip.tokens.input'))
158
-
159
- # inline vision
160
- self.window.ui.nodes['inline.vision'] = HelpLabel(trans('inline.vision'))
161
- self.window.ui.nodes['inline.vision'].setVisible(False)
162
- self.window.ui.nodes['inline.vision'].setContentsMargins(0, 0, 0, 0)
163
- self.window.ui.nodes['inline.vision'].setToolTip(trans('vision.checkbox.tooltip'))
164
156
 
165
157
  # plugin audio input addon
166
158
  self.window.ui.plugin_addon['audio.input'] = AudioInput(self.window)
@@ -168,10 +160,10 @@ class Input:
168
160
 
169
161
  grid = QGridLayout()
170
162
 
171
- left_layout = QHBoxLayout()
172
- left_layout.addWidget(self.window.ui.nodes['input.label'])
173
- left_layout.addWidget(self.window.ui.nodes['inline.vision'])
174
- left_layout.addStretch(1)
163
+ #left_layout = QHBoxLayout()
164
+ #left_layout.addWidget(self.window.ui.nodes['input.label'])
165
+ #left_layout.addWidget(self.window.ui.nodes['inline.vision'])
166
+ #left_layout.addStretch(1)
175
167
 
176
168
  center_layout = QHBoxLayout()
177
169
  center_layout.addStretch()
@@ -179,13 +171,13 @@ class Input:
179
171
  center_layout.addWidget(self.window.ui.plugin_addon['audio.input.btn'])
180
172
  center_layout.addStretch()
181
173
 
182
- right_layout = QHBoxLayout()
183
- right_layout.addStretch(1)
184
- right_layout.addWidget(self.window.ui.nodes['input.counter'])
174
+ #right_layout = QHBoxLayout()
175
+ #right_layout.addStretch(1)
176
+ #right_layout.addWidget(self.window.ui.nodes['input.counter'])
185
177
 
186
- grid.addLayout(left_layout, 0, 0)
178
+ #grid.addLayout(left_layout, 0, 0)
187
179
  grid.addLayout(center_layout, 0, 1, alignment=Qt.AlignCenter)
188
- grid.addLayout(right_layout, 0, 2, alignment=Qt.AlignRight)
180
+ #grid.addLayout(right_layout, 0, 2, alignment=Qt.AlignRight)
189
181
 
190
182
  grid.setContentsMargins(0, 0, 0, 0)
191
183
  return grid
@@ -6,18 +6,17 @@
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.11.18 00:00:00 #
9
+ # Updated Date: 2024.12.09 03:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Qt
13
- from PySide6.QtGui import QIcon
14
13
  from PySide6.QtWidgets import QVBoxLayout, QLabel, QHBoxLayout, QCheckBox, QWidget, QSizePolicy, QPushButton, \
15
- QGridLayout, QSpacerItem, QWidgetItem, QLayout
14
+ QGridLayout, QWidgetItem, QLayout
16
15
 
17
16
  from pygpt_net.ui.widget.audio.output import AudioOutput
18
17
  from pygpt_net.ui.widget.element.labels import ChatStatusLabel, IconLabel, HelpLabel
19
- from pygpt_net.ui.widget.tabs.output import OutputTabs
20
- from pygpt_net.ui.widget.anims.loader import Loader, Loading
18
+ from pygpt_net.ui.widget.anims.loader import Loading
19
+ from pygpt_net.ui.widget.tabs.layout import OutputLayout
21
20
 
22
21
  from .explorer import Explorer
23
22
  from .input import Input
@@ -28,6 +27,7 @@ from pygpt_net.utils import trans
28
27
  import pygpt_net.icons_rc
29
28
 
30
29
 
30
+
31
31
  class Output:
32
32
  def __init__(self, window=None):
33
33
  """
@@ -47,46 +47,15 @@ class Output:
47
47
 
48
48
  :return: QWidget
49
49
  """
50
- # tabs
51
- self.window.ui.tabs['output'] = OutputTabs(self.window)
52
-
53
- # Create the [+] button
54
- plus_button = QPushButton(QIcon(":/icons/add.svg"), "")
55
- plus_button.setFixedSize(30, 25)
56
- plus_button.setFlat(True)
57
- plus_button.clicked.connect(self.window.controller.ui.tabs.new_tab)
58
- plus_button.setObjectName('tab-add')
59
- plus_button.setProperty('tabAdd', True)
60
- plus_button.setToolTip(trans('action.tab.add.chat'))
61
-
62
- # Add the button to the top right corner of the tab bar
63
- self.window.ui.tabs['output'].setCornerWidget(plus_button, corner=Qt.TopRightCorner)
64
-
65
- # create empty tabs
50
+ # prepare columns
51
+ self.window.ui.layout = OutputLayout(self.window)
52
+
53
+ # create empty containers for chat output
66
54
  self.window.ui.nodes['output'] = {}
67
55
  self.window.ui.nodes['output_plain'] = {}
68
56
 
69
- # connect signals
70
- self.window.ui.tabs['output'].currentChanged.connect(
71
- self.window.controller.ui.tabs.on_tab_changed
72
- )
73
- self.window.ui.tabs['output'].tabBarClicked.connect(
74
- self.window.controller.ui.tabs.on_tab_clicked
75
- )
76
- self.window.ui.tabs['output'].tabBarDoubleClicked.connect(
77
- self.window.controller.ui.tabs.on_tab_dbl_clicked
78
- )
79
- self.window.ui.tabs['output'].tabCloseRequested.connect(
80
- self.window.controller.ui.tabs.on_tab_closed
81
- )
82
-
83
- # tab bar signals
84
- self.window.ui.tabs['output'].tabBar().tabMoved.connect(
85
- self.window.controller.ui.tabs.on_tab_moved
86
- )
87
-
88
57
  layout = QVBoxLayout()
89
- layout.addWidget(self.window.ui.tabs['output'])
58
+ layout.addWidget(self.window.ui.layout)
90
59
  layout.addLayout(self.setup_bottom())
91
60
  layout.setContentsMargins(0, 5, 0, 0)
92
61
 
@@ -177,18 +146,29 @@ class Output:
177
146
  self.window.ui.nodes['prompt.context'].setToolTip(trans('tip.tokens.ctx'))
178
147
  self.window.ui.nodes['prompt.context'].setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
179
148
 
149
+ self.window.ui.nodes['input.counter'] = ChatStatusLabel("")
150
+ self.window.ui.nodes['input.counter'].setToolTip(trans('tip.tokens.input'))
151
+ self.window.ui.nodes['input.counter'].setWordWrap(False)
152
+
180
153
  # plugin audio output addon
181
154
  self.window.ui.plugin_addon['audio.output'] = AudioOutput(self.window)
182
155
 
183
156
  # schedule
184
157
  self.window.ui.plugin_addon['schedule'] = ChatStatusLabel("")
185
158
 
159
+ # inline vision
160
+ self.window.ui.nodes['inline.vision'] = HelpLabel(trans('inline.vision'))
161
+ self.window.ui.nodes['inline.vision'].setVisible(False)
162
+ self.window.ui.nodes['inline.vision'].setContentsMargins(0, 0, 0, 0)
163
+ self.window.ui.nodes['inline.vision'].setToolTip(trans('vision.checkbox.tooltip'))
164
+
186
165
  opts_layout = QHBoxLayout()
187
166
  # opts_layout.setSpacing(2) #
188
167
  opts_layout.setContentsMargins(0, 0, 0, 0)
189
168
  opts_layout.addWidget(self.window.ui.nodes['output.timestamp'])
190
169
  # opts_layout.addWidget(self.window.ui.nodes['output.edit'])
191
170
  opts_layout.addWidget(self.window.ui.nodes['output.raw'])
171
+ opts_layout.addWidget(self.window.ui.nodes['inline.vision'])
192
172
  opts_layout.setAlignment(Qt.AlignLeft)
193
173
 
194
174
  left_layout = QHBoxLayout()
@@ -210,6 +190,8 @@ class Output:
210
190
  right_layout.addWidget(self.window.ui.nodes['chat.model'])
211
191
  right_layout.addWidget(QLabel(" "))
212
192
  right_layout.addWidget(self.window.ui.nodes['prompt.context'])
193
+ right_layout.addWidget(QLabel(" "))
194
+ right_layout.addWidget(self.window.ui.nodes['input.counter'])
213
195
  right_layout.setContentsMargins(0, 0, 0, 0)
214
196
 
215
197
  left_widget = QWidget()
@@ -224,14 +206,14 @@ class Output:
224
206
 
225
207
  left_layout = QHBoxLayout()
226
208
  left_layout.addWidget(left_widget)
227
- left_layout.addStretch(1)
209
+ #left_layout.addStretch(1)
228
210
  left_layout.setContentsMargins(0, 0, 0, 0)
229
211
 
230
212
  center_layout = QHBoxLayout()
231
- center_layout.addStretch()
213
+ #center_layout.addStretch()
232
214
  center_layout.addWidget(self.window.ui.nodes['anim.loading'])
233
215
  center_layout.addStretch()
234
- center_layout.setContentsMargins(0, 0, 0, 0)
216
+ center_layout.setContentsMargins(20, 0, 0, 0)
235
217
 
236
218
  right_layout = QHBoxLayout()
237
219
  right_layout.addStretch(1)
@@ -6,14 +6,14 @@
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.11.17 03:00:00 #
9
+ # Updated Date: 2024.12.09 03:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
13
13
 
14
14
  from PySide6.QtCore import QSize
15
15
  from PySide6.QtGui import QIcon
16
- from PySide6.QtWidgets import QVBoxLayout, QLabel, QPushButton, QWidget, QSizePolicy
16
+ from PySide6.QtWidgets import QVBoxLayout, QLabel, QPushButton, QWidget, QSizePolicy, QHBoxLayout
17
17
 
18
18
  from pygpt_net.ui.widget.textarea.name import NameInput
19
19
  from pygpt_net.ui.widget.option.slider import OptionSlider
@@ -25,6 +25,7 @@ from .agent_llama import AgentLlama
25
25
  from .image import Image
26
26
  from .indexes import Indexes
27
27
  from .vision import Vision
28
+ from ...widget.option.toggle_label import ToggleLabel
28
29
 
29
30
 
30
31
  class Footer:
@@ -75,6 +76,21 @@ class Footer:
75
76
  rows.addWidget(self.window.ui.nodes['voice.control.btn'])
76
77
  rows.setContentsMargins(2, 0, 0, 0)
77
78
 
79
+ self.window.ui.nodes['layout.split'] = ToggleLabel(trans('layout.split'), label_position="left",
80
+ icon=":/icons/window.svg")
81
+ self.window.ui.nodes['layout.split'].box.stateChanged.connect(
82
+ lambda: self.window.controller.ui.tabs.toggle_split_screen(self.window.ui.nodes['layout.split'].box.isChecked())
83
+ )
84
+ split_layout = QHBoxLayout()
85
+
86
+ split_layout.addWidget(QLabel(""))
87
+ split_layout.addStretch(1)
88
+ split_layout.addWidget(self.window.ui.nodes['layout.split'])
89
+ split_layout.setContentsMargins(5, 0, 15, 0)
90
+ split_widget = QWidget()
91
+ split_widget.setLayout(split_layout)
92
+ rows.addWidget(split_widget)
93
+
78
94
  # logo
79
95
  logo_button = self.setup_logo()
80
96
 
@@ -6,9 +6,11 @@
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.05.02 19:00:00 #
9
+ # Updated Date: 2024.12.07 21:00:00 #
10
10
  # ================================================== #
11
11
 
12
+ import os
13
+
12
14
  from PySide6.QtGui import QAction, QIcon
13
15
  from PySide6.QtWidgets import QMenu
14
16
 
@@ -42,16 +44,10 @@ class Config:
42
44
  self.window.ui.menu['config.access'] = QAction(QIcon(":/icons/accessibility.svg"),
43
45
  trans("menu.config.access"), self.window)
44
46
 
45
- css_files = []
46
- css_files.append("style.css")
47
- css_files.append("style.dark.css")
48
- css_files.append("style.light.css")
49
- css_files.append("markdown.css")
50
- css_files.append("markdown.dark.css")
51
- css_files.append("markdown.light.css")
52
- css_files.append("web.css")
53
- css_files.append("web.dark.css")
54
- css_files.append("web.light.css")
47
+ css_dir = os.path.join(self.window.core.config.path, 'css')
48
+ css_files = os.listdir(css_dir)
49
+ css_files = [f for f in css_files if not f.endswith('.backup')] # remove .backup files
50
+ css_files = sorted(css_files) # sort by name
55
51
 
56
52
  json_files = []
57
53
  json_files.append("attachments.json")