pygpt-net 2.4.51__py3-none-any.whl → 2.4.52__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.
CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 2.4.52 (2025-01-17)
4
+
5
+ - Improved audio input button visibility toggle.
6
+ - Fix: check for required arguments - issue #88.
7
+ - UI Fixes.
8
+
3
9
  ## 2.4.51 (2025-01-17)
4
10
 
5
11
  - Added a "Continuous recording" mode under Audio Input in the Notepad tab, allowing for recording long voice notes and real-time auto-transcription. (beta)
README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![pygpt](https://snapcraft.io/pygpt/badge.svg)](https://snapcraft.io/pygpt)
4
4
 
5
- Release: **2.4.51** | build: **2025.01.17** | Python: **>=3.10, <3.13**
5
+ Release: **2.4.52** | build: **2025.01.17** | Python: **>=3.10, <3.13**
6
6
 
7
7
  > Official website: https://pygpt.net | Documentation: https://pygpt.readthedocs.io
8
8
  >
@@ -3953,6 +3953,12 @@ may consume additional tokens that are not displayed in the main window.
3953
3953
 
3954
3954
  ## Recent changes:
3955
3955
 
3956
+ **2.4.52 (2025-01-17)**
3957
+
3958
+ - Improved audio input button visibility toggle.
3959
+ - Fix: check for required arguments - issue #88.
3960
+ - UI Fixes.
3961
+
3956
3962
  **2.4.51 (2025-01-17)**
3957
3963
 
3958
3964
  - Added a "Continuous recording" mode under Audio Input in the Notepad tab, allowing for recording long voice notes and real-time auto-transcription. (beta)
pygpt_net/CHANGELOG.txt CHANGED
@@ -1,3 +1,9 @@
1
+ 2.4.52 (2025-01-17)
2
+
3
+ - Improved audio input button visibility toggle.
4
+ - Fix: check for required arguments - issue #88.
5
+ - UI Fixes.
6
+
1
7
  2.4.51 (2025-01-17)
2
8
 
3
9
  - Added a "Continuous recording" mode under Audio Input in the Notepad tab, allowing for recording long voice notes and real-time auto-transcription. (beta)
pygpt_net/__init__.py CHANGED
@@ -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: 2025.01.17 03:00:00 #
9
+ # Updated Date: 2025.01.17 13: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.4.51"
16
+ __version__ = "2.4.52"
17
17
  __build__ = "2025.01.17"
18
18
  __maintainer__ = "Marcin Szczygliński"
19
19
  __github__ = "https://github.com/szczyglis-dev/py-gpt"
@@ -6,12 +6,13 @@
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.01.17 02:00:00 #
9
+ # Updated Date: 2025.01.17 13:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
13
13
  from typing import Optional
14
14
 
15
+ from pygpt_net.core.tabs.tab import Tab
15
16
  from pygpt_net.core.events import Event, BaseEvent
16
17
  from pygpt_net.item.ctx import CtxItem
17
18
  from pygpt_net.utils import trans
@@ -25,6 +26,11 @@ class Audio:
25
26
  :param window: Window instance
26
27
  """
27
28
  self.window = window
29
+ self.input_allowed_tabs = [
30
+ Tab.TAB_NOTEPAD,
31
+ Tab.TAB_CHAT,
32
+ Tab.TAB_TOOL_CALENDAR,
33
+ ]
28
34
 
29
35
  def setup(self):
30
36
  """Setup controller"""
@@ -68,6 +74,19 @@ class Audio:
68
74
  self.window.core.config.set("audio.input.continuous", False)
69
75
  self.window.core.config.save()
70
76
 
77
+ def on_tab_changed(self, tab: Tab):
78
+ """
79
+ On tab changed event
80
+
81
+ :param tab: Tab instance (current tab)
82
+ """
83
+ # input button visibility
84
+ if self.is_input_enabled():
85
+ if tab.type in self.input_allowed_tabs:
86
+ self.handle_audio_input(True) # show btn
87
+ else:
88
+ self.handle_audio_input(False) # hide btn
89
+
71
90
  def enable_output(self):
72
91
  """Enable audio output"""
73
92
  self.toggle_output_icon(True)
@@ -361,3 +380,55 @@ class Audio:
361
380
  except Exception as e:
362
381
  pass
363
382
  return False
383
+
384
+ def handle_audio_input(
385
+ self,
386
+ is_enabled: bool
387
+ ):
388
+ """
389
+ Handle audio input UI
390
+
391
+ :param is_enabled: enable/disable audio input
392
+ """
393
+ # get advanced audio input option
394
+ is_advanced = False
395
+ data = {
396
+ 'name': 'audio.input.advanced',
397
+ 'value': is_advanced,
398
+ }
399
+ event = Event(Event.PLUGIN_OPTION_GET, data)
400
+ self.window.dispatch(event)
401
+ if 'value' in event.data:
402
+ is_advanced = event.data['value']
403
+ if is_enabled:
404
+ # show/hide extra options
405
+ tab = self.window.controller.ui.tabs.get_current_tab()
406
+ if tab.type == Tab.TAB_NOTEPAD:
407
+ self.window.ui.plugin_addon['audio.input.btn'].notepad_footer.setVisible(True)
408
+ else:
409
+ self.window.ui.plugin_addon['audio.input.btn'].notepad_footer.setVisible(False)
410
+ if is_advanced:
411
+ self.window.ui.plugin_addon['audio.input.btn'].setVisible(False)
412
+ self.window.ui.plugin_addon['audio.input'].setVisible(True)
413
+ else:
414
+ self.window.ui.plugin_addon['audio.input.btn'].setVisible(True) # simple recording
415
+ self.window.ui.plugin_addon['audio.input'].setVisible(False) # advanced recording
416
+ self.toggle_input_icon(True)
417
+ else:
418
+ self.window.ui.plugin_addon['audio.input.btn'].setVisible(False) # simple recording
419
+ self.window.ui.plugin_addon['audio.input'].setVisible(False) # advanced recording
420
+ self.toggle_input_icon(False)
421
+
422
+ def handle_audio_output(self, is_enabled: bool):
423
+ """
424
+ Handle audio output UI
425
+
426
+ :param is_enabled: enable/disable audio output
427
+ """
428
+ if is_enabled:
429
+ self.toggle_output_icon(True)
430
+ # self.window.ui.plugin_addon['audio.output'].setVisible(True)
431
+ else:
432
+ self.window.ui.plugin_addon['audio.output'].setVisible(False)
433
+ self.toggle_output_icon(False)
434
+
@@ -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.01.17 13:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import List, Dict, Any
@@ -280,41 +280,16 @@ class Plugins:
280
280
  """Handle plugin type"""
281
281
  for type in self.window.core.plugins.allowed_types:
282
282
 
283
- # get advanced audio input option
284
- is_advanced = False
285
- data = {
286
- 'name': 'audio.input.advanced',
287
- 'value': is_advanced,
288
- }
289
- event = Event(Event.PLUGIN_OPTION_GET, data)
290
- self.window.dispatch(event)
291
- if 'value' in event.data:
292
- is_advanced = event.data['value']
283
+ enabled = self.is_type_enabled(type)
293
284
 
294
285
  if type == 'audio.input':
295
- if self.is_type_enabled(type):
296
- if is_advanced:
297
- self.window.ui.plugin_addon['audio.input.btn'].setVisible(False)
298
- self.window.ui.plugin_addon['audio.input'].setVisible(True)
299
- else:
300
- self.window.ui.plugin_addon['audio.input.btn'].setVisible(True) # simple recording
301
- self.window.ui.plugin_addon['audio.input'].setVisible(False) # advanced recording
302
- self.window.controller.audio.toggle_input_icon(True)
303
- else:
304
- self.window.ui.plugin_addon['audio.input.btn'].setVisible(False) # simple recording
305
- self.window.ui.plugin_addon['audio.input'].setVisible(False) # advanced recording
306
- self.window.controller.audio.toggle_input_icon(False)
286
+ self.window.controller.audio.handle_audio_input(enabled)
307
287
 
308
288
  elif type == 'audio.output':
309
- if self.is_type_enabled(type):
310
- self.window.controller.audio.toggle_output_icon(True)
311
- # self.window.ui.plugin_addon['audio.output'].setVisible(True)
312
- else:
313
- self.window.ui.plugin_addon['audio.output'].setVisible(False)
314
- self.window.controller.audio.toggle_output_icon(False)
289
+ self.window.controller.audio.handle_audio_output(enabled)
315
290
 
316
291
  elif type == 'schedule':
317
- if self.is_type_enabled(type):
292
+ if enabled:
318
293
  self.window.ui.plugin_addon['schedule'].setVisible(True)
319
294
  # get tasks count by throwing "get option" event
320
295
  num = 0
@@ -6,13 +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: 2025.01.17 02:00:00 #
9
+ # Updated Date: 2025.01.17 13:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Any, Optional
13
13
 
14
- from PySide6.QtCore import QTimer
15
-
16
14
  from pygpt_net.core.events import AppEvent, RenderEvent
17
15
  from pygpt_net.core.tabs.tab import Tab
18
16
  from pygpt_net.item.ctx import CtxMeta
@@ -182,15 +180,18 @@ class Tabs:
182
180
  if prev_tab != idx or prev_column != column_idx:
183
181
  self.window.dispatch(AppEvent(AppEvent.TAB_SELECTED)) # app event
184
182
 
185
- # show/hide audio record footer
186
- if tab.type == Tab.TAB_NOTEPAD:
187
- self.window.ui.plugin_addon['audio.input.btn'].notepad_footer.setVisible(True)
188
- else:
189
- self.window.ui.plugin_addon['audio.input.btn'].notepad_footer.setVisible(False)
183
+ self.on_changed()
190
184
 
191
185
  self.window.controller.ui.update()
192
186
  self.update_current()
193
187
 
188
+ def on_changed(self):
189
+ """On Tab or column changed event (any)"""
190
+ tab = self.get_current_tab()
191
+ if tab is None:
192
+ return
193
+ self.window.controller.audio.on_tab_changed(tab)
194
+
194
195
  def get_current_idx(self, column_idx: int = 0) -> int:
195
196
  """
196
197
  Get current tab index
@@ -297,6 +298,7 @@ class Tabs:
297
298
  self.current = idx
298
299
  self.column_idx = column_idx
299
300
  self.on_column_changed()
301
+ self.on_changed()
300
302
  self.update_current()
301
303
 
302
304
  def on_column_focus(self, idx: int):
@@ -307,6 +309,7 @@ class Tabs:
307
309
  """
308
310
  self.column_idx = idx
309
311
  self.on_column_changed()
312
+ self.on_changed()
310
313
  self.update_current()
311
314
 
312
315
  def on_tab_dbl_clicked(
@@ -338,6 +341,7 @@ class Tabs:
338
341
  if self.locked:
339
342
  return
340
343
  self.window.core.tabs.remove_tab_by_idx(idx, column_idx)
344
+ self.on_changed()
341
345
  self.update_current()
342
346
 
343
347
  def on_tab_moved(
@@ -393,6 +397,7 @@ class Tabs:
393
397
  return
394
398
  column_idx = self.tmp_column_idx
395
399
  self.window.core.tabs.remove_all_by_type(type, column_idx)
400
+ self.on_changed()
396
401
  self.update_current()
397
402
 
398
403
  def next_tab(self):
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.4.51",
4
- "app.version": "2.4.51",
3
+ "version": "2.4.52",
4
+ "app.version": "2.4.52",
5
5
  "updated_at": "2025-01-17T00:00:00"
6
6
  },
7
7
  "access.audio.event.speech": false,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.4.51",
4
- "app.version": "2.4.51",
3
+ "version": "2.4.52",
4
+ "app.version": "2.4.52",
5
5
  "updated_at": "2025-01-17T00:00:00"
6
6
  },
7
7
  "items": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.4.51",
4
- "app.version": "2.4.51",
3
+ "version": "2.4.52",
4
+ "app.version": "2.4.52",
5
5
  "updated_at": "2025-01-17T00:00:00"
6
6
  },
7
7
  "items": {
@@ -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.18 21:00:00 #
9
+ # Updated Date: 2025.01.17 13:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import fnmatch
@@ -160,6 +160,8 @@ class Worker(BaseWorker):
160
160
  :return: response item
161
161
  """
162
162
  try:
163
+ if "path" not in item["params"] or "data" not in item["params"]:
164
+ return self.make_response(item, "Path or data not provided")
163
165
  path = self.prepare_path(item["params"]['path'])
164
166
  data = item["params"]['data']
165
167
  self.msg = "Saving file: {}".format(path)
@@ -180,6 +182,8 @@ class Worker(BaseWorker):
180
182
  :return: response item
181
183
  """
182
184
  try:
185
+ if "path" not in item["params"] or "data" not in item["params"]:
186
+ return self.make_response(item, "Path or data not provided")
183
187
  path = self.prepare_path(item["params"]['path'])
184
188
  data = item["params"]['data']
185
189
  self.msg = "Appending file: {}".format(path)
@@ -201,6 +205,8 @@ class Worker(BaseWorker):
201
205
  """
202
206
  context_result = ""
203
207
  try:
208
+ if "path" not in item["params"]:
209
+ return self.make_response(item, "Path not provided")
204
210
  self.msg = "Reading file: {}".format(item["params"]['path'])
205
211
  self.log(self.msg)
206
212
  path = item["params"]['path']
@@ -232,6 +238,8 @@ class Worker(BaseWorker):
232
238
  context = None
233
239
  query = None
234
240
  try:
241
+ if "path" not in item["params"]:
242
+ return self.make_response(item, "Path not provided")
235
243
  path = self.prepare_path(item["params"]['path'])
236
244
  self.msg = "Reading path: {}".format(path)
237
245
  self.log(self.msg)
@@ -283,6 +291,8 @@ class Worker(BaseWorker):
283
291
  :return: response item
284
292
  """
285
293
  try:
294
+ if "path" not in item["params"]:
295
+ return self.make_response(item, "Path not provided")
286
296
  path = self.prepare_path(item["params"]['path'])
287
297
  self.msg = "Deleting file: {}".format(path)
288
298
  self.log(self.msg)
@@ -372,6 +382,8 @@ class Worker(BaseWorker):
372
382
  :return: response item
373
383
  """
374
384
  try:
385
+ if "path" not in item["params"]:
386
+ return self.make_response(item, "Path not provided")
375
387
  path = self.prepare_path(item["params"]['path'])
376
388
  self.msg = "Creating directory: {}".format(path)
377
389
  self.log(self.msg)
@@ -394,6 +406,8 @@ class Worker(BaseWorker):
394
406
  :return: response item
395
407
  """
396
408
  try:
409
+ if "path" not in item["params"]:
410
+ return self.make_response(item, "Path not provided")
397
411
  path = self.prepare_path(item["params"]['path'])
398
412
  self.msg = "Deleting directory: {}".format(path)
399
413
  self.log(self.msg)
@@ -416,6 +430,8 @@ class Worker(BaseWorker):
416
430
  :return: response item
417
431
  """
418
432
  try:
433
+ if "src" not in item["params"] or "dst" not in item["params"]:
434
+ return self.make_response(item, "Source or destination not provided")
419
435
  dst = self.prepare_path(item["params"]['dst'])
420
436
  self.msg = "Downloading file: {} into {}".format(item["params"]['src'], dst)
421
437
  self.log(self.msg)
@@ -468,6 +484,8 @@ class Worker(BaseWorker):
468
484
  :return: response item
469
485
  """
470
486
  try:
487
+ if "src" not in item["params"] or "dst" not in item["params"]:
488
+ return self.make_response(item, "Source or destination not provided")
471
489
  src = self.prepare_path(item["params"]['src'])
472
490
  dst = self.prepare_path(item["params"]['dst'])
473
491
  self.msg = "Copying file: {} into {}".format(src, dst)
@@ -487,6 +505,8 @@ class Worker(BaseWorker):
487
505
  :return: response item
488
506
  """
489
507
  try:
508
+ if "src" not in item["params"] or "dst" not in item["params"]:
509
+ return self.make_response(item, "Source or destination not provided")
490
510
  src = self.prepare_path(item["params"]['src'])
491
511
  dst = self.prepare_path(item["params"]['dst'])
492
512
  self.msg = "Copying directory: {} into {}".format(src, dst)
@@ -506,6 +526,8 @@ class Worker(BaseWorker):
506
526
  :return: response item
507
527
  """
508
528
  try:
529
+ if "src" not in item["params"] or "dst" not in item["params"]:
530
+ return self.make_response(item, "Source or destination not provided")
509
531
  src = self.prepare_path(item["params"]['src'])
510
532
  dst = self.prepare_path(item["params"]['dst'])
511
533
  self.msg = "Moving: {} into {}".format(src, dst)
@@ -525,6 +547,8 @@ class Worker(BaseWorker):
525
547
  :return: response item
526
548
  """
527
549
  try:
550
+ if "path" not in item["params"]:
551
+ return self.make_response(item, "Path not provided")
528
552
  path = self.prepare_path(item["params"]['path'])
529
553
  self.msg = "Checking if directory exists: {}".format(path)
530
554
  self.log(self.msg)
@@ -546,6 +570,8 @@ class Worker(BaseWorker):
546
570
  :return: response item
547
571
  """
548
572
  try:
573
+ if "path" not in item["params"]:
574
+ return self.make_response(item, "Path not provided")
549
575
  path = self.prepare_path(item["params"]['path'])
550
576
  self.msg = "Checking if file exists: {}".format(path)
551
577
  self.log(self.msg)
@@ -567,6 +593,8 @@ class Worker(BaseWorker):
567
593
  :return: response item
568
594
  """
569
595
  try:
596
+ if "path" not in item["params"]:
597
+ return self.make_response(item, "Path not provided")
570
598
  path = self.prepare_path(item["params"]['path'])
571
599
  self.msg = "Checking if path exists: {}".format(path)
572
600
  self.log(self.msg)
@@ -588,6 +616,8 @@ class Worker(BaseWorker):
588
616
  :return: response item
589
617
  """
590
618
  try:
619
+ if "path" not in item["params"]:
620
+ return self.make_response(item, "Path not provided")
591
621
  path = self.prepare_path(item["params"]['path'])
592
622
  self.msg = "Checking file size: {}".format(path)
593
623
  self.log(self.msg)
@@ -613,6 +643,8 @@ class Worker(BaseWorker):
613
643
  :return: response item
614
644
  """
615
645
  try:
646
+ if "path" not in item["params"]:
647
+ return self.make_response(item, "Path not provided")
616
648
  path = self.prepare_path(item["params"]['path'])
617
649
  self.msg = "Checking file info: {}".format(path)
618
650
  self.log(self.msg)
@@ -666,6 +698,8 @@ class Worker(BaseWorker):
666
698
  :return: response item
667
699
  """
668
700
  try:
701
+ if "path" not in item["params"]:
702
+ return self.make_response(item, "Path not provided")
669
703
  path = self.prepare_path(item["params"]['path'])
670
704
  self.msg = "Adding attachment: {}".format(path)
671
705
  self.log(self.msg)
@@ -728,6 +762,8 @@ class Worker(BaseWorker):
728
762
  :return: response item
729
763
  """
730
764
  try:
765
+ if "pattern" not in item["params"]:
766
+ return self.make_response(item, "Search pattern not provided")
731
767
  recursive = True
732
768
  path = self.plugin.window.core.config.get_user_dir('data')
733
769
  pattern = item["params"]['pattern']
pygpt_net/ui/__init__.py CHANGED
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.21 17:00:00 #
9
+ # Updated Date: 2025.01.17 13:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -109,9 +109,10 @@ class UI:
109
109
  def set_initial_size(self):
110
110
  """Set default sizes"""
111
111
  def set_initial_splitter_height():
112
+ """Set initial splitter height"""
112
113
  total_height = self.window.ui.splitters['main.output'].size().height()
113
114
  if total_height > 0:
114
- size_output = int(total_height * 0.8)
115
+ size_output = int(total_height * 0.9)
115
116
  size_input = total_height - size_output
116
117
  self.window.ui.splitters['main.output'].setSizes([size_output, size_input])
117
118
  else:
@@ -119,6 +120,7 @@ class UI:
119
120
  QTimer.singleShot(0, set_initial_splitter_height)
120
121
 
121
122
  def set_initial_splitter_width():
123
+ """Set initial splitter width"""
122
124
  total_width = self.window.ui.splitters['main'].size().width()
123
125
  if total_width > 0:
124
126
  size_output = int(total_width * 0.7)
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Marcin Szczygliński
3
+ Copyright (c) 2025 Marcin Szczygliński
4
4
 
5
5
  GitHub: https://github.com/szczyglis-dev/py-gpt
6
6
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pygpt-net
3
- Version: 2.4.51
3
+ Version: 2.4.52
4
4
  Summary: Desktop AI Assistant powered by models: OpenAI o1, GPT-4o, GPT-4, GPT-4 Vision, GPT-3.5, DALL-E 3, Llama 3, Mistral, Gemini, Claude, Bielik, and other models supported by Langchain, Llama Index, and Ollama. Features include chatbot, text completion, image generation, vision analysis, speech-to-text, internet access, file handling, command execution and more.
5
5
  Home-page: https://pygpt.net
6
6
  License: MIT
@@ -93,7 +93,7 @@ Description-Content-Type: text/markdown
93
93
 
94
94
  [![pygpt](https://snapcraft.io/pygpt/badge.svg)](https://snapcraft.io/pygpt)
95
95
 
96
- Release: **2.4.51** | build: **2025.01.17** | Python: **>=3.10, <3.13**
96
+ Release: **2.4.52** | build: **2025.01.17** | Python: **>=3.10, <3.13**
97
97
 
98
98
  > Official website: https://pygpt.net | Documentation: https://pygpt.readthedocs.io
99
99
  >
@@ -4044,6 +4044,12 @@ may consume additional tokens that are not displayed in the main window.
4044
4044
 
4045
4045
  ## Recent changes:
4046
4046
 
4047
+ **2.4.52 (2025-01-17)**
4048
+
4049
+ - Improved audio input button visibility toggle.
4050
+ - Fix: check for required arguments - issue #88.
4051
+ - UI Fixes.
4052
+
4047
4053
  **2.4.51 (2025-01-17)**
4048
4054
 
4049
4055
  - Added a "Continuous recording" mode under Audio Input in the Notepad tab, allowing for recording long voice notes and real-time auto-transcription. (beta)
@@ -1,9 +1,9 @@
1
- CHANGELOG.md,sha256=4oLoH3Rxw--zdbuyLwoQN8yrI-0mjd-f2xqJfAHU7gU,81319
2
- README.md,sha256=d0H5m0nxaqSnpqEM2179IJM0rWgjpX4PixvGuu8cPaE,162138
1
+ CHANGELOG.md,sha256=iQnFDJva4BVfDzpYshNUMQd8B2I3hbhaPOfp4r_Mu1U,81454
2
+ README.md,sha256=Oba5YDNJxVifaa6nZWPwm1p3Ck-dLQgJEkxnCYdXstc,162274
3
3
  icon.png,sha256=CzcINJaU23a9hNjsDlDNbyuiEvKZ4Wg6DQVYF6SpuRg,13970
4
- pygpt_net/CHANGELOG.txt,sha256=Fv2tiBgbirays-pRud2sRfvg4s_kwXfwQGcJ_HePcsg,79830
4
+ pygpt_net/CHANGELOG.txt,sha256=zcwBLh03uerNhwpnNGg6vGyqGq8-WqT5jPAnRewmTls,79962
5
5
  pygpt_net/LICENSE,sha256=dz9sfFgYahvu2NZbx4C1xCsVn9GVer2wXcMkFRBvqzY,1146
6
- pygpt_net/__init__.py,sha256=dB8ngXOeOLIyQL0RbhAyn3X-aWPlR7QwjKOqXj9O8iQ,1307
6
+ pygpt_net/__init__.py,sha256=e8ltSFYEJiqpKDvb1uie8ifgRBtv4MuqRlJ2uOLBYTk,1307
7
7
  pygpt_net/app.py,sha256=i02M96uLngAs_XZCS1Mi84vb3Okx8ZZewbTdhCqFolM,16029
8
8
  pygpt_net/config.py,sha256=Qc1FOBtTf3O6A6-6KoqUGtoJ0u8hXQeowvCVbZFwtik,16405
9
9
  pygpt_net/container.py,sha256=BemiVZPpPNIzfB-ZvnZeeBPFu-AcX2c30OqYFylEjJc,4023
@@ -23,7 +23,7 @@ pygpt_net/controller/assistant/files.py,sha256=0TmDcDyXpmDc7BsCFZaF6Oj-H4Yr4CxOg
23
23
  pygpt_net/controller/assistant/store.py,sha256=t0h5EeJ9d-Cc_KzV6gQ3kZneoIeECp4iVHxvpJhjP-Q,15771
24
24
  pygpt_net/controller/assistant/threads.py,sha256=IUAGvm1qYNXiu6AUOix6T6c3QJsdqHVgCZPHTvtcuJ0,21058
25
25
  pygpt_net/controller/attachment.py,sha256=to7QK1PwvvkW6gBUxXFIm0R_wh9HrgW8raZf9dJgVmo,20397
26
- pygpt_net/controller/audio/__init__.py,sha256=FKqbmikOdUTW7oUa9rz46otoA9SOOf2TsDg-M4tUqq8,10923
26
+ pygpt_net/controller/audio/__init__.py,sha256=j3mp94vLDjCtL5F6yALEKD4A_LzKhFkwtnTP56VPZw0,13542
27
27
  pygpt_net/controller/calendar/__init__.py,sha256=s55RkCFQPFzdDoQ2zp3kohlNdpiWxdSxQtsaROeiigw,4424
28
28
  pygpt_net/controller/calendar/note.py,sha256=y8Gkg35-aM1MfQ9P2NsRnmfSJw4Ps__9g6I1RhonR6s,11428
29
29
  pygpt_net/controller/camera.py,sha256=chf19kngEXzMJt54Gnj1bJGHVsYaCX0QimJnJa9uigE,16207
@@ -84,7 +84,7 @@ pygpt_net/controller/notepad.py,sha256=wgnvLtTBuq6W6Eio3BgjrESPRNLRRVyqUutpBNb9T
84
84
  pygpt_net/controller/painter/__init__.py,sha256=1Ekmr2a3irDkSb2wowiPXhW59rfdZOW1tdbxeubph-k,2747
85
85
  pygpt_net/controller/painter/capture.py,sha256=oLBh5emwjJUTddjT6hWErv2FFjSakC_9WSruxPhkJO8,6664
86
86
  pygpt_net/controller/painter/common.py,sha256=gTRCIcmAsgYhueUWNfEIwIJo-40YBVhoNSksOY1Oj34,6395
87
- pygpt_net/controller/plugins/__init__.py,sha256=-Y4K2-DovAh903cc7n4xYHv0ka9jI96zN8E08h0EOCQ,15930
87
+ pygpt_net/controller/plugins/__init__.py,sha256=yvzAjlrNvRoPihr7kkrU8eqjVD6zCoHLT9ZRl-01dk0,14466
88
88
  pygpt_net/controller/plugins/presets.py,sha256=SaMJTUENCsssz0lU__URBeFZXZHpkKiSjNEgKz-yYA4,12061
89
89
  pygpt_net/controller/plugins/settings.py,sha256=imKitT7FBCfuDQvCTy1Qz4dq4xaT4LKbh9qGdxg7aBQ,6110
90
90
  pygpt_net/controller/presets/__init__.py,sha256=nasEC4qE3OLzvh9l9YWv1h18cLXsab7-210oWeVTvkw,22367
@@ -102,7 +102,7 @@ pygpt_net/controller/theme/nodes.py,sha256=6SCKMGQ5SZdKgy4t69raiikTLQDPPkjoYTPwl
102
102
  pygpt_net/controller/tools/__init__.py,sha256=b_yt413iRUI9fWHzZGdtM4333UjzrJb-zmq_exYTgy4,2723
103
103
  pygpt_net/controller/ui/__init__.py,sha256=WsH7OzMS_ixCwuHeSajv2E3irPo9B4H3dQe7Svd_71k,5903
104
104
  pygpt_net/controller/ui/mode.py,sha256=8mw_tmRo7sArvgv-k1yfwx5SCfVOkwdc96U8ZiW83Q0,10231
105
- pygpt_net/controller/ui/tabs.py,sha256=ExwaheAkekD6tcU7BgriF2h8mO8dWiEQgSA1Xgw60AQ,20067
105
+ pygpt_net/controller/ui/tabs.py,sha256=efUwH0jOmD3WTxwRh0kXoWnDoCU7vjggkULR8n5F_C0,20100
106
106
  pygpt_net/controller/ui/vision.py,sha256=KrP8wFuuz-gsO9iwbLDnzvC5iqWVlWjFarQ27HkHdEg,2303
107
107
  pygpt_net/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
108
108
  pygpt_net/core/access/__init__.py,sha256=rFKp9xMsuJHS_wxiMEMMHVRd5lXdkPj7LuObAIdQFBY,942
@@ -247,9 +247,9 @@ pygpt_net/css_rc.py,sha256=i13kX7irhbYCWZ5yJbcMmnkFp_UfS4PYnvRFSPF7XXo,11349
247
247
  pygpt_net/data/audio/click_off.mp3,sha256=aNiRDP1pt-Jy7ija4YKCNFBwvGWbzU460F4pZWZDS90,65201
248
248
  pygpt_net/data/audio/click_on.mp3,sha256=qfdsSnthAEHVXzeyN4LlC0OvXuyW8p7stb7VXtlvZ1k,65201
249
249
  pygpt_net/data/audio/ok.mp3,sha256=LTiV32pEBkpUGBkKkcOdOFB7Eyt_QoP2Nv6c5AaXftk,32256
250
- pygpt_net/data/config/config.json,sha256=r7aECJ0qUjFSkla3PvvqnHZFRAsZ0So8g0kdbPQjB5U,19805
251
- pygpt_net/data/config/models.json,sha256=2SlfLD92btvwylPNro31J1uT4C_fC-7ERd9UrxnY8zE,61940
252
- pygpt_net/data/config/modes.json,sha256=hp_UAh4RCbeIe6iaYWtNLHm2DwBP7dz5h1LNlrFjd64,1923
250
+ pygpt_net/data/config/config.json,sha256=q3q0H-p2UwktnwrXaAlCOD16bSR1-gTg5DtwcYb1QUY,19805
251
+ pygpt_net/data/config/models.json,sha256=DpQZw_cirnUhkNro-bwBDKOS8jImwEOvGaAIx-Kf4jU,61940
252
+ pygpt_net/data/config/modes.json,sha256=WtYlrPlu_j42oK4S8PtQT_xdyxut_awY6UEcleVwN3M,1923
253
253
  pygpt_net/data/config/presets/agent_openai.json,sha256=vMTR-soRBiEZrpJJHuFLWyx8a3Ez_BqtqjyXgxCAM_Q,733
254
254
  pygpt_net/data/config/presets/agent_openai_assistant.json,sha256=awJw9lNTGpKML6SJUShVn7lv8AXh0oic7wBeyoN7AYs,798
255
255
  pygpt_net/data/config/presets/agent_planner.json,sha256=a6Rv58Bnm2STNWB0Rw_dGhnsz6Lb3J8_GwsUVZaTIXc,742
@@ -1730,7 +1730,7 @@ pygpt_net/plugin/cmd_custom/worker.py,sha256=iXMZK24rNYupvOQt-wB70gJsLUvi7Zpo7Tg
1730
1730
  pygpt_net/plugin/cmd_files/__init__.py,sha256=r8dWyiWBKkchSKRvaKtg_-qv0bxC4olyfS-vV-em8QE,4215
1731
1731
  pygpt_net/plugin/cmd_files/config.py,sha256=q3W8Ur6prnzRMg8hg1bbdwhUrfPiUKA3E-9hDw547cI,13293
1732
1732
  pygpt_net/plugin/cmd_files/output.py,sha256=PiSslXXc7TeTzeuXh_MBEh3I4PuIDStr_1i2ARuPXFM,1987
1733
- pygpt_net/plugin/cmd_files/worker.py,sha256=kcbt6EaBHDpcnGdbMQQkmySw9DQKnob3KI0aeVopL2c,31728
1733
+ pygpt_net/plugin/cmd_files/worker.py,sha256=cnbMQjxQaRpVshaKl_CvjduNJBmP6ThX5IorAA3Ct0Y,34061
1734
1734
  pygpt_net/plugin/cmd_history/__init__.py,sha256=uR7Wyly2StrLaazvkFSiPYxLb5EN4ua5mBlMhQHY4HM,11023
1735
1735
  pygpt_net/plugin/cmd_history/config.py,sha256=bp3-MDNd5tckiSs1mV-GWb5Y7_ZO_LHaerM9-4Yx7U4,9659
1736
1736
  pygpt_net/plugin/cmd_history/worker.py,sha256=-jGdiR94QHKOMISWIPtNLmCLFDG5UzibItvkbQx9KZo,6119
@@ -1995,7 +1995,7 @@ pygpt_net/tools/text_editor/__init__.py,sha256=NXgKl9XkA6ecRSn3q154KLsu4FHCz4XL9
1995
1995
  pygpt_net/tools/text_editor/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1996
1996
  pygpt_net/tools/text_editor/ui/dialogs.py,sha256=lOgogExJgnLzq0KdbcHli-HslEZ2uivCI1dFFzEpsRA,2906
1997
1997
  pygpt_net/tools/text_editor/ui/widgets.py,sha256=K_yxkyMyLfBfXXZ8iOczci10tPlsBJ5JlUDxrzObm0s,2754
1998
- pygpt_net/ui/__init__.py,sha256=K6lWxskW5wJUl5qr2RWOImJ5-jNiUdZKuBE-cUaDdbQ,9061
1998
+ pygpt_net/ui/__init__.py,sha256=Ruykl9whIfrg3E3iAfDaFaZri-vCLUii0lpeFgunWJ4,9152
1999
1999
  pygpt_net/ui/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2000
2000
  pygpt_net/ui/base/config_dialog.py,sha256=92CnUmDFv74BQ6mbwhHjn3L_s7IYhJX3sChFqAD_5Vo,9255
2001
2001
  pygpt_net/ui/base/context_menu.py,sha256=Mq2UPWBwc9eaHc9qVOMQEQ7a2343wsrMrMnEzYdvs6Q,3245
@@ -2175,8 +2175,8 @@ pygpt_net/ui/widget/textarea/web.py,sha256=9FoL02QY6mOxtc4t4fe8X7fVDIdPn9Sb_fwsv
2175
2175
  pygpt_net/ui/widget/vision/__init__.py,sha256=8HT4tQFqQogEEpGYTv2RplKBthlsFKcl5egnv4lzzEw,488
2176
2176
  pygpt_net/ui/widget/vision/camera.py,sha256=T8b5cmK6uhf_WSSxzPt_Qod8JgMnst6q8sQqRvgQiSA,2584
2177
2177
  pygpt_net/utils.py,sha256=Gsh_mITVke3bb8o-Ke57l__xA5a9Wv4t7tlsnSQULj8,6655
2178
- pygpt_net-2.4.51.dist-info/LICENSE,sha256=GLKQTnJOPK4dDIWfkAIM4GwOxKJXi5zcMGt7FjLR1xk,1126
2179
- pygpt_net-2.4.51.dist-info/METADATA,sha256=17IoHPi5cIRQnVucqPIKWoiFBigUJAVfnSXFOS5ZGJA,167017
2180
- pygpt_net-2.4.51.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
2181
- pygpt_net-2.4.51.dist-info/entry_points.txt,sha256=qvpII6UHIt8XfokmQWnCYQrTgty8FeJ9hJvOuUFCN-8,43
2182
- pygpt_net-2.4.51.dist-info/RECORD,,
2178
+ pygpt_net-2.4.52.dist-info/LICENSE,sha256=rbPqNB_xxANH8hKayJyIcTwD4bj4Y2G-Mcm85r1OImM,1126
2179
+ pygpt_net-2.4.52.dist-info/METADATA,sha256=XN4GCMydR0ficF0uSBLAGSz6AXGEU4pS9oyB62VRWF8,167153
2180
+ pygpt_net-2.4.52.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
2181
+ pygpt_net-2.4.52.dist-info/entry_points.txt,sha256=qvpII6UHIt8XfokmQWnCYQrTgty8FeJ9hJvOuUFCN-8,43
2182
+ pygpt_net-2.4.52.dist-info/RECORD,,