pygpt-net 2.6.42__py3-none-any.whl → 2.6.44__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 (43) hide show
  1. pygpt_net/CHANGELOG.txt +13 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/controller/__init__.py +2 -0
  4. pygpt_net/controller/debug/debug.py +7 -19
  5. pygpt_net/controller/debug/fixtures.py +103 -0
  6. pygpt_net/controller/launcher/launcher.py +2 -2
  7. pygpt_net/controller/presets/presets.py +10 -0
  8. pygpt_net/core/debug/debug.py +2 -2
  9. pygpt_net/core/fixtures/stream/__init__.py +0 -0
  10. pygpt_net/{provider/api/fake → core/fixtures/stream}/generator.py +1 -1
  11. pygpt_net/core/models/models.py +11 -1
  12. pygpt_net/core/render/web/body.py +5 -1
  13. pygpt_net/core/updater/updater.py +18 -7
  14. pygpt_net/data/config/config.json +10 -6
  15. pygpt_net/data/config/models.json +4 -10
  16. pygpt_net/data/config/settings.json +59 -19
  17. pygpt_net/data/css/web-blocks.css +4 -0
  18. pygpt_net/data/css/web-chatgpt.css +4 -0
  19. pygpt_net/data/css/web-chatgpt_wide.css +4 -0
  20. pygpt_net/data/js/app.js +727 -361
  21. pygpt_net/data/locale/locale.en.ini +8 -1
  22. pygpt_net/js_rc.py +11506 -10502
  23. pygpt_net/provider/api/openai/__init__.py +4 -12
  24. pygpt_net/provider/core/config/patch.py +26 -2457
  25. pygpt_net/provider/core/config/patches/__init__.py +0 -0
  26. pygpt_net/provider/core/config/patches/patch_before_2_6_42.py +2510 -0
  27. pygpt_net/provider/core/model/patch.py +12 -764
  28. pygpt_net/provider/core/model/patches/__init__.py +0 -0
  29. pygpt_net/provider/core/model/patches/patch_before_2_6_42.py +813 -0
  30. pygpt_net/provider/core/preset/patch.py +12 -221
  31. pygpt_net/provider/core/preset/patches/__init__.py +0 -0
  32. pygpt_net/provider/core/preset/patches/patch_before_2_6_42.py +272 -0
  33. pygpt_net/ui/base/context_menu.py +3 -2
  34. pygpt_net/ui/dialog/settings.py +5 -4
  35. pygpt_net/ui/layout/ctx/ctx_list.py +3 -3
  36. pygpt_net/ui/menu/debug.py +36 -23
  37. pygpt_net/ui/widget/lists/context.py +233 -51
  38. {pygpt_net-2.6.42.dist-info → pygpt_net-2.6.44.dist-info}/METADATA +18 -129
  39. {pygpt_net-2.6.42.dist-info → pygpt_net-2.6.44.dist-info}/RECORD +43 -35
  40. /pygpt_net/{provider/api/fake/__init__.py → core/fixtures/__init__} +0 -0
  41. {pygpt_net-2.6.42.dist-info → pygpt_net-2.6.44.dist-info}/LICENSE +0 -0
  42. {pygpt_net-2.6.42.dist-info → pygpt_net-2.6.44.dist-info}/WHEEL +0 -0
  43. {pygpt_net-2.6.42.dist-info → pygpt_net-2.6.44.dist-info}/entry_points.txt +0 -0
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.24 23:00:00 #
9
+ # Updated Date: 2025.09.12 20:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtGui import QAction
@@ -46,7 +46,7 @@ class Debug:
46
46
  'db',
47
47
  'logger',
48
48
  'app.log',
49
- 'fake_stream',
49
+ 'fixtures.stream',
50
50
  'kernel',
51
51
  'render'
52
52
  )
@@ -72,32 +72,45 @@ class Debug:
72
72
  m['debug.logger'].triggered.connect(dbg.toggle_logger)
73
73
  m['debug.app.log'].triggered.connect(dbg.toggle_app_log)
74
74
  m['debug.render'].triggered.connect(dbg.toggle_render)
75
- m['debug.fake_stream'].triggered.connect(dbg.toggle_fake_stream)
75
+ m['debug.fixtures.stream'].triggered.connect(
76
+ lambda _=False: dbg.fixtures.toggle_from_menu("stream")
77
+ )
76
78
 
77
79
  m['menu.debug'] = win.menuBar().addMenu(trans("menu.debug"))
78
80
  menu = m['menu.debug']
79
81
  menu.addActions(
80
- [m['debug.logger'],
81
- m['debug.render'],
82
- m['debug.db'],
83
- m['debug.app.log'],
84
- m['debug.fake_stream']]
82
+ [
83
+ m['debug.logger'],
84
+ m['debug.render'],
85
+ m['debug.db'],
86
+ m['debug.app.log']
87
+ ]
88
+ )
89
+
90
+ menu.addSeparator()
91
+ menu.addActions(
92
+ [
93
+ m['debug.fixtures.stream']
94
+ ]
85
95
  )
96
+
86
97
  menu.addSeparator()
87
- menu.addActions([
88
- m['debug.agent'],
89
- m['debug.assistants'],
90
- m['debug.attachments'],
91
- m['debug.config'],
92
- m['debug.context'],
93
- m['debug.events'],
94
- m['debug.indexes'],
95
- m['debug.kernel'],
96
- m['debug.models'],
97
- m['debug.plugins'],
98
- m['debug.presets'],
99
- m['debug.tabs'],
100
- m['debug.ui'],
101
- ])
98
+ menu.addActions(
99
+ [
100
+ m['debug.agent'],
101
+ m['debug.assistants'],
102
+ m['debug.attachments'],
103
+ m['debug.config'],
104
+ m['debug.context'],
105
+ m['debug.events'],
106
+ m['debug.indexes'],
107
+ m['debug.kernel'],
108
+ m['debug.models'],
109
+ m['debug.plugins'],
110
+ m['debug.presets'],
111
+ m['debug.tabs'],
112
+ m['debug.ui'],
113
+ ]
114
+ )
102
115
 
103
116
  m['debug.render'].setChecked(bool(win.core.config.get('debug.render')))
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.24 23:00:00 #
9
+ # Updated Date: 2025.09.12 23:47:47 #
10
10
  # ================================================== #
11
11
 
12
12
  import datetime
@@ -47,12 +47,26 @@ class ContextList(BaseList):
47
47
  'attachment': QIcon(":/icons/attachment.svg"),
48
48
  }
49
49
  self._color_icon_cache = {}
50
+
51
+ # Use a custom delegate for labels/pinned/attachment indicators and group border indicator
50
52
  self.setItemDelegate(ImportantItemDelegate(self, self._icons['attachment']))
53
+
54
+ # Ensure context menu works as before
51
55
  self.setContextMenuPolicy(Qt.CustomContextMenu)
52
56
  self.customContextMenuRequested.connect(self.show_context_menu)
53
57
  self._backup_selection = None
54
58
  self.restore_after_ctx_menu = True
55
59
 
60
+ # Make group rows visually stick to the left edge (if this is a tree view).
61
+ # Children remain indented by delegate's manual shift (+15 px), preserving structure.
62
+ try:
63
+ if hasattr(self, 'setIndentation'):
64
+ # Set tree indentation to 0 so group/folder rows do not look like children
65
+ self.setIndentation(0)
66
+ except Exception:
67
+ # Safe no-op if the underlying view does not support setIndentation
68
+ pass
69
+
56
70
  @property
57
71
  def _model(self):
58
72
  return self.window.ui.models['ctx.list']
@@ -62,6 +76,9 @@ class ContextList(BaseList):
62
76
  return self.window.ui.nodes['ctx.list']
63
77
 
64
78
  def _color_icon(self, color: QColor) -> QIcon:
79
+ """
80
+ Returns (and caches) a solid color icon pixmap for menu items.
81
+ """
65
82
  key = color.rgba()
66
83
  icon = self._color_icon_cache.get(key)
67
84
  if icon is None:
@@ -405,11 +422,19 @@ class ContextList(BaseList):
405
422
 
406
423
  class ImportantItemDelegate(QtWidgets.QStyledItemDelegate):
407
424
  """
408
- Label color delegate
425
+ Item delegate that paints:
426
+ - Attachment icon on the right side (centered vertically),
427
+ - Pinned indicator (small circle) in the top-right corner (overlays if needed),
428
+ - Label color as a full-height vertical bar on the left for labeled items,
429
+ - Group enclosure indicator for expanded groups:
430
+ - thin vertical bar (default 2 px) on the left side of child rows area,
431
+ - thin horizontal bar (default 2 px) at the bottom of the last child row.
409
432
  """
410
433
  def __init__(self, parent=None, attachment_icon: QIcon = None):
411
434
  super().__init__(parent)
412
435
  self._attachment_icon = attachment_icon or QIcon(":/icons/attachment.svg")
436
+
437
+ # Predefined label colors (status -> QColor)
413
438
  self._status_colors = {
414
439
  0: QColor(100, 100, 100),
415
440
  1: QColor(255, 0, 0),
@@ -420,64 +445,219 @@ class ImportantItemDelegate(QtWidgets.QStyledItemDelegate):
420
445
  6: QColor(75, 0, 130),
421
446
  7: QColor(238, 130, 238),
422
447
  }
423
- self._pin_pen = QtGui.QPen(QtCore.Qt.black, 0.5, QtCore.Qt.SolidLine)
424
448
 
425
- def paint(self, painter, option, index):
426
- if index.parent().isValid():
427
- option.rect.adjust(15, 0, 0, 0)
428
-
429
- super(ImportantItemDelegate, self).paint(painter, option, index)
449
+ # Visual tuning constants
450
+ self._pin_pen = QtGui.QPen(QtCore.Qt.black, 0.5, QtCore.Qt.SolidLine)
451
+ self._pin_diameter = 4 # Small pinned circle diameter
452
+ self._pin_margin = 3 # Margin from top and right edges
453
+ self._attach_spacing = 4 # Kept for potential future layout tweaks
454
+ self._label_bar_width = 4 # Full-height label bar width (left side)
455
+ self._label_v_margin = 3 # 3px top/bottom margin for the label bar
456
+
457
+ # Manual child indent to keep hierarchy visible when view indentation is 0
458
+ self._child_indent = 15
459
+
460
+ # Group indicator defaults (can be overridden by config)
461
+ self._group_indicator_enabled = True
462
+ self._group_indicator_width = 2
463
+ self._group_indicator_color = QColor(67, 75, 78) # soft gray
464
+ self._group_indicator_gap = 6 # gap between child content left and the vertical bar
465
+ self._group_indicator_bottom_offset = 6
466
+
467
+ # Try to load customization from application config (safe if missing)
468
+ self._init_group_indicator_from_config()
469
+
470
+ def _init_group_indicator_from_config(self):
471
+ """
472
+ Initialize group indicator settings from config if available.
473
+ Accepts:
474
+ - color: list/tuple [r,g,b], dict {'r','g','b'}, "#RRGGBB", or "r,g,b"
475
+ - width: int
476
+ - enabled: bool
477
+ - gap: int
478
+ """
479
+ try:
480
+ view = self.parent()
481
+ window = getattr(view, 'window', None)
482
+ cfg = getattr(getattr(window, 'core', None), 'config', None)
483
+ if not cfg:
484
+ return
430
485
 
431
- data = index.data(QtCore.Qt.ItemDataRole.UserRole)
432
- if data:
433
- label = data.get("label", 0)
434
- is_important = data.get("is_important", False)
435
- is_attachment = data.get("is_attachment", False)
486
+ enabled = cfg.get('ctx.records.groups.indicator.enabled')
487
+ if enabled is not None:
488
+ self._group_indicator_enabled = bool(enabled)
489
+
490
+ width = cfg.get('ctx.records.groups.indicator.width')
491
+ if isinstance(width, int) and width >= 0:
492
+ self._group_indicator_width = int(width)
493
+
494
+ gap = cfg.get('ctx.records.groups.indicator.gap')
495
+ if isinstance(gap, int) and gap >= 0:
496
+ self._group_indicator_gap = int(gap)
497
+
498
+ color = cfg.get('ctx.records.groups.indicator.color')
499
+ qcolor = self._parse_qcolor(color)
500
+ if qcolor is not None:
501
+ self._group_indicator_color = qcolor
502
+ except Exception:
503
+ # Fail-safe: keep defaults if anything goes wrong
504
+ pass
505
+
506
+ def _parse_qcolor(self, value):
507
+ """
508
+ Parses various color formats into QColor.
509
+ Supports:
510
+ - QColor
511
+ - list/tuple [r, g, b]
512
+ - dict {'r':..,'g':..,'b':..} or {'red':..,'green':..,'blue':..}
513
+ - "#RRGGBB"
514
+ - "r,g,b" (also "r;g;b")
515
+ """
516
+ if value is None:
517
+ return None
518
+ if isinstance(value, QColor):
519
+ return value
520
+ if isinstance(value, (list, tuple)) and len(value) >= 3:
521
+ try:
522
+ r, g, b = int(value[0]), int(value[1]), int(value[2])
523
+ return QColor(r, g, b)
524
+ except Exception:
525
+ return None
526
+ if isinstance(value, dict):
527
+ keys = value.keys()
528
+ try:
529
+ if all(k in keys for k in ('r', 'g', 'b')):
530
+ return QColor(int(value['r']), int(value['g']), int(value['b']))
531
+ if all(k in keys for k in ('red', 'green', 'blue')):
532
+ return QColor(int(value['red']), int(value['green']), int(value['blue']))
533
+ except Exception:
534
+ return None
535
+ if isinstance(value, str):
536
+ s = value.strip()
537
+ if s.startswith('#'):
538
+ qc = QColor(s)
539
+ return qc if qc.isValid() else None
540
+ s = s.replace(';', ',')
541
+ parts = [p.strip() for p in s.split(',') if p.strip()]
542
+ if len(parts) >= 3:
543
+ try:
544
+ r, g, b = int(parts[0]), int(parts[1]), int(parts[2])
545
+ return QColor(r, g, b)
546
+ except Exception:
547
+ return None
548
+ return None
436
549
 
550
+ def paint(self, painter, option, index):
551
+ # Shift children by +15 px to keep them visually nested.
552
+ is_child = index.parent().isValid()
553
+ if is_child:
554
+ option.rect.adjust(self._child_indent, 0, 0, 0)
555
+
556
+ # Detect if this row is a group/folder (top-level section).
557
+ is_group = False
558
+ try:
559
+ model = index.model()
560
+ item = model.itemFromIndex(index) if hasattr(model, "itemFromIndex") else None
561
+ is_group = bool(item is not None and getattr(item, 'isFolder', False))
562
+ except Exception:
563
+ is_group = False
564
+
565
+ # Default painting:
566
+ # - For groups: translate painter -8 px to push folder/icon closer to the left edge.
567
+ # - For others: paint normally.
568
+ if is_group:
437
569
  painter.save()
570
+ painter.translate(-2, 0)
571
+ super(ImportantItemDelegate, self).paint(painter, option, index)
572
+ painter.restore()
573
+ else:
574
+ super(ImportantItemDelegate, self).paint(painter, option, index)
575
+
576
+ # Group enclosure indicator (left bar + bottom bar on last child)
577
+ # This applies only to child rows (i.e., when a group is expanded).
578
+ if self._group_indicator_enabled and not is_group and is_child and self._group_indicator_width > 0:
579
+ try:
580
+ painter.save()
581
+ # Use solid fill for crisp 2px bars (no anti-alias blur)
582
+ painter.setRenderHint(QtGui.QPainter.Antialiasing, False)
583
+ color = self._group_indicator_color
584
+ painter.setPen(QtCore.Qt.NoPen)
585
+ painter.setBrush(color)
438
586
 
439
- if is_attachment:
587
+ # Compute vertical bar geometry:
588
+ # Place the bar to the LEFT of the child content area, leaving a small gap.
589
+ child_left = option.rect.x()
590
+ bar_w = self._group_indicator_width
591
+ # Left edge of the vertical bar (never below 0)
592
+ vbar_left = max(0, child_left - (self._group_indicator_gap + bar_w))
593
+ vbar_rect = QtCore.QRect(vbar_left, option.rect.y(), bar_w, option.rect.height())
594
+ painter.drawRect(vbar_rect)
595
+
596
+ painter.restore()
597
+ except Exception:
598
+ # Fail-safe: do not block painting if anything goes wrong
599
+ pass
600
+
601
+ # Custom data painting for non-group items only (labels, pinned, attachments).
602
+ if not is_group:
603
+ data = index.data(QtCore.Qt.ItemDataRole.UserRole)
604
+ if data:
605
+ label = data.get("label", 0)
606
+ is_important = data.get("is_important", False)
607
+ is_attachment = data.get("is_attachment", False)
608
+
609
+ painter.save()
610
+
611
+ # Draw attachment icon on the right (centered vertically).
612
+ # This is painted first, so the pin can overlay it when needed.
440
613
  icon_size = option.decorationSize or QtCore.QSize(16, 16)
441
- icon_pos = option.rect.right() - icon_size.width()
442
- y = option.rect.top() + (option.rect.height() - icon_size.height()) // 2
443
- icon_rect = QtCore.QRect(
444
- icon_pos,
445
- y,
446
- icon_size.width(),
447
- icon_size.height()
448
- )
449
- self._attachment_icon.paint(painter, icon_rect, QtCore.Qt.AlignCenter)
450
-
451
- if is_important:
452
- color = self.get_color_for_status(3)
453
- square_size = 3
454
- square_rect = QtCore.QRect(
455
- option.rect.left(),
456
- option.rect.top() + 2,
457
- square_size,
458
- square_size,
459
- )
460
- painter.setBrush(color)
461
- painter.setPen(self._pin_pen)
462
- painter.drawRect(square_rect)
463
-
464
- if label > 0:
465
- color = self.get_color_for_status(label)
466
- square_size = 5
467
- y = option.rect.center().y() - (square_size // 2) + 2
468
- square_rect = QtCore.QRect(
469
- option.rect.left(),
470
- y,
471
- square_size,
472
- square_size,
473
- )
474
- painter.setBrush(color)
475
- painter.setPen(QtCore.Qt.NoPen)
476
- painter.drawRect(square_rect)
614
+ if is_attachment:
615
+ icon_pos_x = option.rect.right() - icon_size.width()
616
+ icon_pos_y = option.rect.top() + (option.rect.height() - icon_size.height()) // 2
617
+ icon_rect = QtCore.QRect(
618
+ icon_pos_x,
619
+ icon_pos_y,
620
+ icon_size.width(),
621
+ icon_size.height()
622
+ )
623
+ self._attachment_icon.paint(painter, icon_rect, QtCore.Qt.AlignCenter)
477
624
 
478
- painter.restore()
625
+ # Pinned indicator (small circle) kept at a fixed top-right position.
626
+ # It does not shift left when the attachment is present; it overlays above it.
627
+ if is_important:
628
+ painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
629
+ painter.setCompositionMode(QtGui.QPainter.CompositionMode_SourceOver)
630
+ color = self.get_color_for_status(3)
631
+
632
+ x = option.rect.x() + option.rect.width() - self._pin_margin - self._pin_diameter
633
+ y = option.rect.y() + self._pin_margin
634
+ pin_rect = QtCore.QRect(x, y, self._pin_diameter, self._pin_diameter)
635
+
636
+ painter.setBrush(color)
637
+ painter.setPen(self._pin_pen)
638
+ painter.drawEllipse(pin_rect)
639
+
640
+ # Label bar on the left with 3px vertical margins
641
+ if label > 0:
642
+ color = self.get_color_for_status(label)
643
+ bar_y = option.rect.y() + self._label_v_margin
644
+ bar_h = max(1, option.rect.height() - 2 * self._label_v_margin)
645
+ bar_rect = QtCore.QRect(
646
+ option.rect.x(),
647
+ bar_y,
648
+ self._label_bar_width,
649
+ bar_h,
650
+ )
651
+ painter.setBrush(color)
652
+ painter.setPen(QtCore.Qt.NoPen)
653
+ painter.drawRect(bar_rect)
654
+
655
+ painter.restore()
479
656
 
480
657
  def get_color_for_status(self, status: int) -> QColor:
658
+ """
659
+ Returns color mapped for given status value.
660
+ """
481
661
  return self._status_colors.get(status, self._status_colors[0])
482
662
 
483
663
 
@@ -485,6 +665,7 @@ class GroupItem(QStandardItem):
485
665
  def __init__(self, icon, name, id):
486
666
  super().__init__(icon, name)
487
667
  self.id = id
668
+ # Keep name as provided; display text is handled by the model/view
488
669
  self.name = name
489
670
  self.isFolder = True
490
671
  self.isPinned = False
@@ -496,6 +677,7 @@ class Item(QStandardItem):
496
677
  def __init__(self, name, id):
497
678
  super().__init__(name)
498
679
  self.id = id
680
+ # Keep name as provided; display text is handled by the model/view
499
681
  self.name = name
500
682
  self.isFolder = False
501
683
  self.isPinned = False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pygpt-net
3
- Version: 2.6.42
3
+ Version: 2.6.44
4
4
  Summary: Desktop AI Assistant powered by: OpenAI GPT-5, GPT-4, o1, o3, Gemini, Claude, Grok, DeepSeek, and other models supported by Llama Index, and Ollama. Chatbot, agents, completion, image generation, vision analysis, speech-to-text, plugins, internet access, file handling, command execution and more.
5
5
  License: MIT
6
6
  Keywords: ai,api,api key,app,assistant,bielik,chat,chatbot,chatgpt,claude,dall-e,deepseek,desktop,gemini,gpt,gpt-3.5,gpt-4,gpt-4-vision,gpt-4o,gpt-5,gpt-oss,gpt3.5,gpt4,grok,langchain,llama-index,llama3,mistral,o1,o3,ollama,openai,presets,py-gpt,py_gpt,pygpt,pyside,qt,text completion,tts,ui,vision,whisper
@@ -118,7 +118,7 @@ Description-Content-Type: text/markdown
118
118
 
119
119
  [![pygpt](https://snapcraft.io/pygpt/badge.svg)](https://snapcraft.io/pygpt)
120
120
 
121
- Release: **2.6.42** | build: **2025-09-11** | Python: **>=3.10, <3.14**
121
+ Release: **2.6.44** | build: **2025-09-12** | Python: **>=3.10, <3.14**
122
122
 
123
123
  > Official website: https://pygpt.net | Documentation: https://pygpt.readthedocs.io
124
124
  >
@@ -3567,6 +3567,19 @@ may consume additional tokens that are not displayed in the main window.
3567
3567
 
3568
3568
  ## Recent changes:
3569
3569
 
3570
+ **2.6.44 (2025-09-12)**
3571
+
3572
+ - Added: Auto-collapse for large user input blocks.
3573
+ - Added: Configuration for syntax highlighting intervals.
3574
+ - Improved: Visibility of label icons.
3575
+ - Improved: Scrolling of code blocks.
3576
+ - Fixed: Parsing of quotes in custom markdown blocks.
3577
+
3578
+ **2.6.43 (2025-09-12)**
3579
+
3580
+ - Fixed: preset restoration when switching profiles.
3581
+ - Improved: faster application launch and exit.
3582
+
3570
3583
  **2.6.42 (2025-09-11)**
3571
3584
 
3572
3585
  - Fixed: Save/load zoom factor in the chat window when switched via Ctrl + mouse wheel.
@@ -3578,132 +3591,6 @@ may consume additional tokens that are not displayed in the main window.
3578
3591
 
3579
3592
  - Rendering engine optimizations: markdown parsing moved to JS, reduced CPU usage, added auto-memory clearing, and more.
3580
3593
 
3581
- **2.6.40 (2025-09-06)**
3582
-
3583
- - CSS fixes.
3584
-
3585
- **2.6.39 (2025-09-06)**
3586
-
3587
- - Added: Search input to the models editor.
3588
- - Fixed: Brush color switching when changing modes in the Painter.
3589
-
3590
- **2.6.38 (2025-09-05)**
3591
-
3592
- - Fixed: Detection of chunk type in Ollama.
3593
- - Fixed: Import of models with existing IDs.
3594
- - Fixed: Updating the Assistants UI list after creating a new Assistant.
3595
- - Refactored and optimized the code.
3596
-
3597
- **2.6.37 (2025-09-05)**
3598
-
3599
- - Fixed: Function parameters sanitization in the Google Gen AI SDK.
3600
- - Added: Native support for Anthropic SDK and xAI SDK (with remote tools).
3601
-
3602
- **2.6.36 (2025-09-04)**
3603
-
3604
- - Optimized rendering of large code blocks.
3605
-
3606
- **2.6.35 (2025-09-04)**
3607
-
3608
- - Improved responsiveness in chat streaming.
3609
- - Added zoom, fit, and auto-scroll on crop in Painter.
3610
- - Added a scroll-up button in the chat window.
3611
- - Optimized memory usage.
3612
-
3613
- **2.6.34 (2025-09-03)**
3614
-
3615
- - Added auto-resizing for input.
3616
- - Added file management to the OpenAI Vector Stores tool.
3617
- - Implemented removal of script tags when exporting HTML.
3618
- - Enabled maintaining custom resolution in Painter.
3619
-
3620
- **2.6.33 (2025-09-02)**
3621
-
3622
- - Added a "crop" option, auto-resize canvas, and layer support to Painter.
3623
- - Improved video capture from the camera.
3624
-
3625
- **2.6.32 (2025-09-02)**
3626
-
3627
- - Added video generation and support for Google Veo 3 models.
3628
- - Introduced new predefined models: veo-3.0-generate-preview and veo-3.0-fast-generate-preview.
3629
- - Integrated DuckDuckGo as a search provider in the WebSearch plugin.
3630
- - Added "Loop" mode to Realtime + audio mode for automatic turn handling and continuous conversation without manually enabling the microphone.
3631
-
3632
- **2.6.31 (2025-09-01)**
3633
-
3634
- - Chat with Audio mode renamed to Realtime + audio.
3635
- - Added support for real-time audio models from OpenAI (Realtime API) and Google (Live API), featuring real-time audio integration (beta).
3636
- - Introduced new predefined models: gpt-realtime, gpt-4o-realtime-preview, and gemini-2.5-flash-preview-native-audio-dialog.
3637
- - Included Google Gen AI audio input and output providers in the Audio Input/Output plugins.
3638
- - Added URL Context remote tool support in Google Gen AI.
3639
-
3640
- **2.6.30 (2025-08-29)**
3641
-
3642
- - Added native Google GenAI API support (beta); live audio is not supported yet (#132).
3643
- - Added new predefined models for image generation: Google Imagen3 and Imagen4.
3644
- - Optimized token usage in the Responses API.
3645
- - Removed Vision mode (it is now integrated into Chat).
3646
-
3647
- **2.6.29 (2025-08-28)**
3648
-
3649
- - Verbose options have been moved to the Developer section in settings.
3650
- - Enhanced logging of embeddings usage.
3651
- - Fixed styles list.
3652
-
3653
- **2.6.28 (2025-08-27)**
3654
-
3655
- - Added new plugins: Tuya (IoT) and Wikipedia.
3656
- - Improved formatting of JSON command output.
3657
- - Fixed CSS issues.
3658
-
3659
- **2.6.27 (2025-08-26)**
3660
-
3661
- - Simplified audio input: A microphone icon has been added to the input field.
3662
-
3663
- **2.6.26 (2025-08-26)**
3664
-
3665
- - Added new provider: OpenRouter (#133).
3666
-
3667
- **2.6.25 (2025-08-26)**
3668
-
3669
- - Fixed the empty agent ID issue in OpenAI Agents evaluation.
3670
- - Added the ability to select a custom model for evaluation.
3671
- - Added embedding providers: Anthropic, Deepseek, MistralAI, xAI, VoyageAI.
3672
-
3673
- **2.6.24 (2025-08-26)**
3674
-
3675
- - Added a new option: LlamaIndex -> Embeddings -> Default embedding providers for attachments.
3676
- - The same model provider is now used for both embedding and RAG query in attachment indexing.
3677
- - Translations have been added to Agents.
3678
- - Fixed fetching Anthropic models list.
3679
- - Added Google GenAI Embeddings.
3680
-
3681
- **2.6.23 (2025-08-25)**
3682
-
3683
- - Added an inline "Add a new chat" button to the right of the tabs.
3684
- - Added an "Add Attachment" button in the input field.
3685
- - Improved file open in the system's file manager
3686
- - Fixed the restoration of input text color when changing themes from light to dark.
3687
- - Fixed last eval step finish if 100% complete.
3688
- -
3689
- **2.6.22 (2025-08-25)**
3690
-
3691
- - UI refactor and optimizations.
3692
-
3693
- **2.6.21 (2025-08-24)**
3694
-
3695
- - Ollama models are now available in OpenAI Agents mode.
3696
- - Improved parsing of responses from Agents.
3697
- - Fix: do not initialize index in Agents mode if not provided.
3698
- - Fix: agent response evaluation steps limit.
3699
- - Fix: do not execute code in agents if Tools are disabled.
3700
- - Refactoring.
3701
-
3702
- **2.6.20 (2025-08-22)**
3703
-
3704
- - Added a new plugin: Server (FTP/SSH) - connect to remote servers using FTP, SFTP, and SSH. Execute remote commands, upload, download, and more (beta).
3705
- - Added support for Wayland in Snap/compiled versions.
3706
-
3707
3594
  # Credits and links
3708
3595
 
3709
3596
  **Official website:** <https://pygpt.net>
@@ -3770,5 +3657,7 @@ Awesome ChatGPT Prompts (used in templates): https://github.com/f/awesome-chatgp
3770
3657
 
3771
3658
  Code syntax highlight powered by: https://highlightjs.org
3772
3659
 
3773
- LaTeX support by: https://katex.org and https://github.com/mitya57/python-markdown-math
3660
+ Markdown parsing powered by: https://github.com/markdown-it/markdown-it
3661
+
3662
+ LaTeX support by: https://katex.org
3774
3663