pygpt-net 2.4.28__py3-none-any.whl → 2.4.34__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 (168) hide show
  1. CHANGELOG.md +40 -0
  2. README.md +62 -5
  3. pygpt_net/CHANGELOG.txt +40 -0
  4. pygpt_net/__init__.py +3 -3
  5. pygpt_net/controller/access/__init__.py +5 -5
  6. pygpt_net/controller/access/control.py +3 -2
  7. pygpt_net/controller/attachment.py +67 -1
  8. pygpt_net/controller/audio/__init__.py +34 -6
  9. pygpt_net/controller/chat/__init__.py +3 -1
  10. pygpt_net/controller/chat/attachment.py +239 -37
  11. pygpt_net/controller/chat/audio.py +99 -0
  12. pygpt_net/controller/chat/input.py +10 -3
  13. pygpt_net/controller/chat/output.py +4 -1
  14. pygpt_net/controller/chat/text.py +10 -5
  15. pygpt_net/controller/dialogs/confirm.py +17 -1
  16. pygpt_net/controller/kernel/reply.py +5 -8
  17. pygpt_net/controller/lang/custom.py +3 -1
  18. pygpt_net/controller/mode.py +2 -1
  19. pygpt_net/controller/presets/editor.py +11 -2
  20. pygpt_net/core/access/voice.py +2 -2
  21. pygpt_net/core/agents/legacy.py +3 -1
  22. pygpt_net/core/attachments/__init__.py +11 -7
  23. pygpt_net/core/attachments/context.py +226 -44
  24. pygpt_net/core/{audio.py → audio/__init__.py} +1 -1
  25. pygpt_net/core/audio/context.py +34 -0
  26. pygpt_net/core/bridge/context.py +29 -1
  27. pygpt_net/core/bridge/worker.py +16 -1
  28. pygpt_net/core/ctx/__init__.py +4 -1
  29. pygpt_net/core/db/__init__.py +4 -2
  30. pygpt_net/core/debug/attachments.py +3 -1
  31. pygpt_net/core/debug/context.py +5 -1
  32. pygpt_net/core/debug/presets.py +3 -1
  33. pygpt_net/core/docker/__init__.py +170 -16
  34. pygpt_net/core/docker/builder.py +6 -2
  35. pygpt_net/core/events/event.py +3 -1
  36. pygpt_net/core/experts/__init__.py +24 -6
  37. pygpt_net/core/idx/chat.py +55 -4
  38. pygpt_net/core/idx/indexing.py +123 -15
  39. pygpt_net/core/modes.py +3 -1
  40. pygpt_net/core/presets.py +13 -2
  41. pygpt_net/core/render/markdown/pid.py +2 -1
  42. pygpt_net/core/render/plain/pid.py +2 -1
  43. pygpt_net/core/render/web/body.py +34 -12
  44. pygpt_net/core/render/web/pid.py +2 -1
  45. pygpt_net/core/render/web/renderer.py +12 -3
  46. pygpt_net/core/tokens.py +4 -2
  47. pygpt_net/core/types/mode.py +2 -1
  48. pygpt_net/data/config/config.json +7 -4
  49. pygpt_net/data/config/models.json +191 -6
  50. pygpt_net/data/config/modes.json +11 -5
  51. pygpt_net/data/config/presets/current.audio.json +34 -0
  52. pygpt_net/data/config/settings.json +15 -1
  53. pygpt_net/data/css/web.css +70 -0
  54. pygpt_net/data/css/web.dark.css +4 -1
  55. pygpt_net/data/css/web.light.css +1 -1
  56. pygpt_net/data/locale/locale.de.ini +33 -20
  57. pygpt_net/data/locale/locale.en.ini +73 -58
  58. pygpt_net/data/locale/locale.es.ini +33 -20
  59. pygpt_net/data/locale/locale.fr.ini +35 -22
  60. pygpt_net/data/locale/locale.it.ini +33 -20
  61. pygpt_net/data/locale/locale.pl.ini +36 -23
  62. pygpt_net/data/locale/locale.uk.ini +33 -20
  63. pygpt_net/data/locale/locale.zh.ini +40 -27
  64. pygpt_net/data/locale/plugin.cmd_code_interpreter.de.ini +6 -0
  65. pygpt_net/data/locale/plugin.cmd_code_interpreter.en.ini +15 -7
  66. pygpt_net/data/locale/plugin.cmd_code_interpreter.es.ini +6 -0
  67. pygpt_net/data/locale/plugin.cmd_code_interpreter.fr.ini +6 -0
  68. pygpt_net/data/locale/plugin.cmd_code_interpreter.it.ini +6 -0
  69. pygpt_net/data/locale/plugin.cmd_code_interpreter.pl.ini +6 -0
  70. pygpt_net/data/locale/plugin.cmd_code_interpreter.uk.ini +6 -0
  71. pygpt_net/data/locale/plugin.cmd_code_interpreter.zh.ini +6 -0
  72. pygpt_net/data/locale/plugin.cmd_files.de.ini +4 -4
  73. pygpt_net/data/locale/plugin.cmd_files.en.ini +4 -4
  74. pygpt_net/data/locale/plugin.cmd_files.es.ini +4 -4
  75. pygpt_net/data/locale/plugin.cmd_files.fr.ini +4 -4
  76. pygpt_net/data/locale/plugin.cmd_files.it.ini +4 -4
  77. pygpt_net/data/locale/plugin.cmd_files.pl.ini +4 -4
  78. pygpt_net/data/locale/plugin.cmd_files.uk.ini +4 -4
  79. pygpt_net/data/locale/plugin.cmd_files.zh.ini +4 -4
  80. pygpt_net/data/locale/plugin.cmd_system.de.ini +6 -6
  81. pygpt_net/data/locale/plugin.cmd_system.en.ini +12 -6
  82. pygpt_net/data/locale/plugin.cmd_system.es.ini +6 -6
  83. pygpt_net/data/locale/plugin.cmd_system.fr.ini +6 -6
  84. pygpt_net/data/locale/plugin.cmd_system.it.ini +6 -6
  85. pygpt_net/data/locale/plugin.cmd_system.pl.ini +6 -6
  86. pygpt_net/data/locale/plugin.cmd_system.uk.ini +6 -6
  87. pygpt_net/data/locale/plugin.cmd_system.zh.ini +6 -6
  88. pygpt_net/data/locale/plugin.cmd_web.de.ini +5 -5
  89. pygpt_net/data/locale/plugin.cmd_web.en.ini +5 -5
  90. pygpt_net/data/locale/plugin.cmd_web.es.ini +5 -5
  91. pygpt_net/data/locale/plugin.cmd_web.fr.ini +5 -5
  92. pygpt_net/data/locale/plugin.cmd_web.it.ini +5 -5
  93. pygpt_net/data/locale/plugin.cmd_web.pl.ini +5 -5
  94. pygpt_net/data/locale/plugin.cmd_web.uk.ini +5 -5
  95. pygpt_net/data/locale/plugin.cmd_web.zh.ini +5 -5
  96. pygpt_net/data/locale/plugin.idx_llama_index.de.ini +12 -12
  97. pygpt_net/data/locale/plugin.idx_llama_index.en.ini +12 -12
  98. pygpt_net/data/locale/plugin.idx_llama_index.es.ini +12 -12
  99. pygpt_net/data/locale/plugin.idx_llama_index.fr.ini +12 -12
  100. pygpt_net/data/locale/plugin.idx_llama_index.it.ini +12 -12
  101. pygpt_net/data/locale/plugin.idx_llama_index.pl.ini +12 -12
  102. pygpt_net/data/locale/plugin.idx_llama_index.uk.ini +12 -12
  103. pygpt_net/data/locale/plugin.idx_llama_index.zh.ini +12 -12
  104. pygpt_net/item/attachment.py +9 -1
  105. pygpt_net/item/ctx.py +9 -1
  106. pygpt_net/item/preset.py +5 -1
  107. pygpt_net/launcher.py +3 -1
  108. pygpt_net/migrations/Version20241126170000.py +28 -0
  109. pygpt_net/migrations/__init__.py +3 -1
  110. pygpt_net/plugin/audio_input/__init__.py +11 -1
  111. pygpt_net/plugin/audio_input/worker.py +9 -1
  112. pygpt_net/plugin/audio_output/__init__.py +37 -7
  113. pygpt_net/plugin/audio_output/worker.py +38 -41
  114. pygpt_net/plugin/cmd_code_interpreter/__init__.py +51 -35
  115. pygpt_net/plugin/cmd_code_interpreter/builder.py +16 -4
  116. pygpt_net/plugin/cmd_code_interpreter/config.py +98 -39
  117. pygpt_net/plugin/cmd_code_interpreter/docker.py +4 -0
  118. pygpt_net/plugin/cmd_code_interpreter/ipython/__init__.py +13 -0
  119. pygpt_net/plugin/cmd_code_interpreter/{ipython.py → ipython/docker_kernel.py} +10 -3
  120. pygpt_net/plugin/cmd_code_interpreter/ipython/local_kernel.py +220 -0
  121. pygpt_net/plugin/cmd_code_interpreter/runner.py +5 -5
  122. pygpt_net/plugin/cmd_mouse_control/__init__.py +4 -2
  123. pygpt_net/plugin/cmd_system/config.py +50 -0
  124. pygpt_net/plugin/cmd_system/docker.py +4 -0
  125. pygpt_net/plugin/idx_llama_index/__init__.py +23 -1
  126. pygpt_net/plugin/idx_llama_index/worker.py +10 -0
  127. pygpt_net/plugin/openai_dalle/__init__.py +3 -1
  128. pygpt_net/plugin/openai_vision/__init__.py +3 -1
  129. pygpt_net/provider/core/attachment/json_file.py +4 -1
  130. pygpt_net/provider/core/config/patch.py +25 -0
  131. pygpt_net/provider/core/ctx/db_sqlite/storage.py +14 -4
  132. pygpt_net/provider/core/ctx/db_sqlite/utils.py +19 -2
  133. pygpt_net/provider/core/model/patch.py +7 -1
  134. pygpt_net/provider/core/preset/json_file.py +5 -1
  135. pygpt_net/provider/gpt/__init__.py +14 -2
  136. pygpt_net/provider/gpt/audio.py +63 -0
  137. pygpt_net/provider/gpt/chat.py +76 -44
  138. pygpt_net/provider/gpt/utils.py +27 -0
  139. pygpt_net/provider/gpt/vision.py +37 -15
  140. pygpt_net/provider/loaders/base.py +10 -1
  141. pygpt_net/provider/loaders/web_yt.py +19 -1
  142. pygpt_net/tools/code_interpreter/__init__.py +1 -0
  143. pygpt_net/tools/image_viewer/ui/dialogs.py +3 -1
  144. pygpt_net/ui/dialog/preset.py +3 -1
  145. pygpt_net/ui/dialog/url.py +29 -0
  146. pygpt_net/ui/dialogs.py +5 -1
  147. pygpt_net/ui/layout/chat/attachments.py +42 -6
  148. pygpt_net/ui/layout/chat/attachments_ctx.py +14 -4
  149. pygpt_net/ui/layout/chat/attachments_uploaded.py +8 -4
  150. pygpt_net/ui/layout/toolbox/agent.py +8 -7
  151. pygpt_net/ui/layout/toolbox/agent_llama.py +5 -4
  152. pygpt_net/ui/layout/toolbox/prompt.py +8 -6
  153. pygpt_net/ui/menu/tools.py +17 -11
  154. pygpt_net/ui/widget/anims/toggles.py +167 -0
  155. pygpt_net/ui/widget/dialog/url.py +59 -0
  156. pygpt_net/ui/widget/element/group.py +2 -1
  157. pygpt_net/ui/widget/lists/attachment.py +22 -17
  158. pygpt_net/ui/widget/lists/attachment_ctx.py +65 -3
  159. pygpt_net/ui/widget/option/checkbox.py +69 -5
  160. pygpt_net/ui/widget/option/cmd.py +4 -5
  161. pygpt_net/ui/widget/option/toggle.py +62 -0
  162. pygpt_net/ui/widget/option/toggle_label.py +79 -0
  163. pygpt_net/ui/widget/textarea/url.py +43 -0
  164. {pygpt_net-2.4.28.dist-info → pygpt_net-2.4.34.dist-info}/METADATA +65 -7
  165. {pygpt_net-2.4.28.dist-info → pygpt_net-2.4.34.dist-info}/RECORD +168 -154
  166. {pygpt_net-2.4.28.dist-info → pygpt_net-2.4.34.dist-info}/LICENSE +0 -0
  167. {pygpt_net-2.4.28.dist-info → pygpt_net-2.4.34.dist-info}/WHEEL +0 -0
  168. {pygpt_net-2.4.28.dist-info → pygpt_net-2.4.34.dist-info}/entry_points.txt +0 -0
@@ -6,18 +6,20 @@
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.11.26 02:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
13
13
 
14
- from PySide6.QtGui import QStandardItemModel, Qt
14
+ from PySide6.QtGui import QStandardItemModel, Qt, QIcon
15
15
  from PySide6.QtWidgets import QVBoxLayout, QPushButton, QHBoxLayout, QCheckBox, QWidget
16
16
 
17
+ from pygpt_net.item.attachment import AttachmentItem
17
18
  from pygpt_net.ui.widget.element.labels import HelpLabel
18
19
  from pygpt_net.ui.widget.lists.attachment import AttachmentList
19
20
  from pygpt_net.utils import trans
20
21
 
22
+ import pygpt_net.icons_rc
21
23
 
22
24
  class Attachments:
23
25
  def __init__(self, window=None):
@@ -38,12 +40,21 @@ class Attachments:
38
40
  self.setup_attachments()
39
41
  self.setup_buttons()
40
42
 
43
+ empty_widget = QWidget()
44
+ self.window.ui.nodes['input.attachments.options.label'] = HelpLabel(trans("attachments.options.label"))
45
+
41
46
  # buttons layout
42
47
  buttons = QHBoxLayout()
43
48
  buttons.addWidget(self.window.ui.nodes['attachments.btn.add'])
49
+ buttons.addWidget(self.window.ui.nodes['attachments.btn.add_url'])
44
50
  buttons.addWidget(self.window.ui.nodes['attachments.btn.clear'])
51
+ buttons.addWidget(empty_widget)
52
+ buttons.addWidget(self.window.ui.nodes['input.attachments.options.label'])
53
+
54
+ buttons.addWidget(self.setup_auto_index())
45
55
  buttons.addWidget(self.setup_send_clear())
46
56
  buttons.addWidget(self.setup_capture_clear())
57
+ buttons.addStretch()
47
58
 
48
59
  self.window.ui.nodes['tip.input.attachments'] = HelpLabel(trans('tip.input.attachments'), self.window)
49
60
 
@@ -88,15 +99,34 @@ class Attachments:
88
99
 
89
100
  return widget
90
101
 
102
+ def setup_auto_index(self) -> QWidget:
103
+ """
104
+ Setup auto index checkbox
105
+
106
+ :return: QWidget
107
+ """
108
+ layout = QHBoxLayout()
109
+ layout.setContentsMargins(0, 0, 0, 0)
110
+ layout.setAlignment(Qt.AlignCenter)
111
+ layout.addWidget(self.window.ui.nodes['attachments.auto_index'])
112
+
113
+ widget = QWidget()
114
+ widget.setLayout(layout)
115
+
116
+ return widget
117
+
91
118
  def setup_buttons(self):
92
119
  """
93
120
  Setup buttons
94
121
  """
95
- self.window.ui.nodes['attachments.btn.add'] = QPushButton(trans('attachments.btn.add'))
96
- self.window.ui.nodes['attachments.btn.clear'] = QPushButton(trans('attachments.btn.clear'))
122
+ self.window.ui.nodes['attachments.btn.add'] = QPushButton(QIcon(":/icons/add.svg"), trans('attachments.btn.add'))
123
+ self.window.ui.nodes['attachments.btn.add_url'] = QPushButton(QIcon(":/icons/add.svg"), trans('attachments.btn.add_url'))
124
+ self.window.ui.nodes['attachments.btn.clear'] = QPushButton(QIcon(":/icons/close.svg"), trans('attachments.btn.clear'))
97
125
 
98
126
  self.window.ui.nodes['attachments.btn.add'].clicked.connect(
99
127
  lambda: self.window.controller.attachment.open_add())
128
+ self.window.ui.nodes['attachments.btn.add_url'].clicked.connect(
129
+ lambda: self.window.controller.attachment.open_add_url())
100
130
  self.window.ui.nodes['attachments.btn.clear'].clicked.connect(
101
131
  lambda: self.window.controller.attachment.clear(remove_local=True))
102
132
 
@@ -110,6 +140,11 @@ class Attachments:
110
140
  lambda: self.window.controller.attachment.toggle_capture_clear(
111
141
  self.window.ui.nodes['attachments.capture_clear'].isChecked()))
112
142
 
143
+ self.window.ui.nodes['attachments.auto_index'] = QCheckBox(trans('attachments.auto_index'))
144
+ self.window.ui.nodes['attachments.auto_index'].stateChanged.connect(
145
+ lambda: self.window.controller.attachment.toggle_auto_index(
146
+ self.window.ui.nodes['attachments.auto_index'].isChecked()))
147
+
113
148
  def setup_attachments(self):
114
149
  """
115
150
  Setup attachments list
@@ -144,8 +179,9 @@ class Attachments:
144
179
  for id in data:
145
180
  path = data[id].path
146
181
  size = ""
147
- if path and os.path.exists(path):
148
- size = self.window.core.filesystem.sizeof_fmt(os.path.getsize(path))
182
+ if data[id].type == AttachmentItem.TYPE_FILE:
183
+ if path and os.path.exists(path):
184
+ size = self.window.core.filesystem.sizeof_fmt(os.path.getsize(path))
149
185
  ctx_str = ""
150
186
  if data[id].ctx:
151
187
  ctx_str = "YES"
@@ -6,19 +6,20 @@
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.11.26 02:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
13
13
 
14
14
  from PySide6 import QtCore
15
- from PySide6.QtGui import QStandardItemModel, Qt
15
+ from PySide6.QtGui import QStandardItemModel, Qt, QIcon
16
16
  from PySide6.QtWidgets import QVBoxLayout, QPushButton, QHBoxLayout, QWidget, QRadioButton
17
17
 
18
18
  from pygpt_net.ui.widget.element.labels import HelpLabel
19
19
  from pygpt_net.ui.widget.lists.attachment_ctx import AttachmentCtxList
20
20
  from pygpt_net.utils import trans
21
21
 
22
+ import pygpt_net.icons_rc
22
23
 
23
24
  class AttachmentsCtx:
24
25
  def __init__(self, window=None):
@@ -90,7 +91,7 @@ class AttachmentsCtx:
90
91
  self.window.ui.nodes[self.id] = AttachmentCtxList(self.window)
91
92
 
92
93
  # buttons
93
- self.window.ui.nodes['attachments_ctx.btn.clear'] = QPushButton(trans('attachments_uploaded.btn.clear'))
94
+ self.window.ui.nodes['attachments_ctx.btn.clear'] = QPushButton(QIcon(":/icons/close.svg"), trans('attachments_uploaded.btn.clear'))
94
95
  self.window.ui.nodes['attachments_ctx.btn.clear'].clicked.connect(
95
96
  lambda: self.window.controller.chat.attachment.clear()
96
97
  )
@@ -105,11 +106,12 @@ class AttachmentsCtx:
105
106
  :param parent: parent widget
106
107
  :return: QStandardItemModel
107
108
  """
108
- model = QStandardItemModel(0, 4, parent)
109
+ model = QStandardItemModel(0, 5, parent)
109
110
  model.setHeaderData(0, Qt.Horizontal, trans('attachments.header.name'))
110
111
  model.setHeaderData(1, Qt.Horizontal, trans('attachments.header.path'))
111
112
  model.setHeaderData(2, Qt.Horizontal, trans('attachments.header.size'))
112
113
  model.setHeaderData(3, Qt.Horizontal, trans('attachments.header.length'))
114
+ model.setHeaderData(4, Qt.Horizontal, trans('attachments.header.idx'))
113
115
  return model
114
116
 
115
117
  def update(self, data):
@@ -121,6 +123,7 @@ class AttachmentsCtx:
121
123
  self.window.ui.models[self.id].removeRows(0, self.window.ui.models[self.id].rowCount())
122
124
  i = 0
123
125
  for item in data:
126
+ indexed = False
124
127
  name = "No name"
125
128
  if 'name' in item:
126
129
  name = item['name']
@@ -136,6 +139,12 @@ class AttachmentsCtx:
136
139
  length = str(item['length'])
137
140
  if 'tokens' in item:
138
141
  length += ' / ~' + str(item['tokens'])
142
+ if 'indexed' in item and item['indexed']:
143
+ indexed = True
144
+
145
+ idx_str = ""
146
+ if indexed:
147
+ idx_str = trans("attachments.ctx.indexed")
139
148
 
140
149
  if os.path.exists(path):
141
150
  size = self.window.core.filesystem.sizeof_fmt(os.path.getsize(path))
@@ -149,4 +158,5 @@ class AttachmentsCtx:
149
158
  self.window.ui.models[self.id].setData(self.window.ui.models[self.id].index(i, 1), path)
150
159
  self.window.ui.models[self.id].setData(self.window.ui.models[self.id].index(i, 2), size)
151
160
  self.window.ui.models[self.id].setData(self.window.ui.models[self.id].index(i, 3), length)
161
+ self.window.ui.models[self.id].setData(self.window.ui.models[self.id].index(i, 4), idx_str)
152
162
  i += 1
@@ -12,7 +12,7 @@
12
12
  import os
13
13
 
14
14
  from PySide6 import QtCore
15
- from PySide6.QtGui import QStandardItemModel, Qt
15
+ from PySide6.QtGui import QStandardItemModel, Qt, QIcon
16
16
  from PySide6.QtWidgets import QVBoxLayout, QPushButton, QHBoxLayout, QCheckBox, QLabel, QWidget
17
17
 
18
18
  from pygpt_net.ui.widget.element.button import SyncButton
@@ -20,6 +20,7 @@ from pygpt_net.ui.widget.element.labels import HelpLabel
20
20
  from pygpt_net.ui.widget.lists.uploaded import UploadedFileList
21
21
  from pygpt_net.utils import trans
22
22
 
23
+ import pygpt_net.icons_rc
23
24
 
24
25
  class AttachmentsUploaded:
25
26
  def __init__(self, window=None):
@@ -38,10 +39,11 @@ class AttachmentsUploaded:
38
39
  :return: QVBoxLayout
39
40
  """
40
41
  self.setup_attachments()
42
+ empty_widget = QWidget()
41
43
 
42
- self.window.ui.nodes['attachments_uploaded.sync.tip'] = QLabel(trans('attachments_uploaded.sync.tip'))
44
+ self.window.ui.nodes['attachments_uploaded.sync.tip'] = HelpLabel(trans('attachments_uploaded.sync.tip'))
45
+ self.window.ui.nodes['attachments_uploaded.sync.tip'].setWordWrap(False)
43
46
  self.window.ui.nodes['attachments_uploaded.sync.tip'].setAlignment(Qt.AlignCenter)
44
- empty_widget = QWidget()
45
47
 
46
48
  self.window.ui.nodes['tip.input.attachments.uploaded'] = HelpLabel(trans('tip.input.attachments.uploaded'),
47
49
  self.window)
@@ -52,6 +54,8 @@ class AttachmentsUploaded:
52
54
  buttons_layout.addWidget(self.window.ui.nodes['attachments_uploaded.btn.clear'])
53
55
  buttons_layout.addWidget(empty_widget)
54
56
  buttons_layout.addWidget(self.window.ui.nodes['attachments_uploaded.sync.tip'])
57
+ buttons_layout.addStretch()
58
+
55
59
 
56
60
  # layout
57
61
  layout = QVBoxLayout()
@@ -70,7 +74,7 @@ class AttachmentsUploaded:
70
74
 
71
75
  # buttons
72
76
  self.window.ui.nodes['attachments_uploaded.btn.sync'] = SyncButton(trans('attachments_uploaded.btn.sync'), self.window)
73
- self.window.ui.nodes['attachments_uploaded.btn.clear'] = QPushButton(trans('attachments_uploaded.btn.clear'))
77
+ self.window.ui.nodes['attachments_uploaded.btn.clear'] = QPushButton(QIcon(":/icons/close.svg"), trans('attachments_uploaded.btn.clear'))
74
78
  self.window.ui.nodes['attachments_uploaded.btn.clear'].clicked.connect(
75
79
  lambda: self.window.controller.assistant.files.clear()
76
80
  )
@@ -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: 2024.11.21 20:00:00 #
9
+ # Updated Date: 2024.11.24 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtWidgets import QVBoxLayout, QLabel, QHBoxLayout, QWidget, QCheckBox
13
13
 
14
14
  from pygpt_net.ui.widget.option.slider import OptionSlider
15
+ from pygpt_net.ui.widget.option.toggle_label import ToggleLabel
15
16
  from pygpt_net.utils import trans
16
17
 
17
18
 
@@ -43,20 +44,20 @@ class Agent:
43
44
  self.window.ui.config['global']['agent.iterations'] = self.window.ui.nodes['agent.iterations']
44
45
 
45
46
  # auto stop
46
- self.window.ui.nodes['agent.auto_stop'] = QCheckBox(trans("toolbox.agent.auto_stop.label"))
47
- self.window.ui.nodes['agent.auto_stop'].stateChanged.connect(
47
+ self.window.ui.nodes['agent.auto_stop'] = ToggleLabel(trans("toolbox.agent.auto_stop.label"))
48
+ self.window.ui.nodes['agent.auto_stop'].box.stateChanged.connect(
48
49
  lambda:
49
50
  self.window.controller.agent.common.toggle_auto_stop(
50
- self.window.ui.config['global']['agent.auto_stop'].isChecked())
51
+ self.window.ui.config['global']['agent.auto_stop'].box.isChecked())
51
52
  )
52
53
  self.window.ui.config['global']['agent.auto_stop'] = self.window.ui.nodes['agent.auto_stop']
53
54
 
54
55
  # continue more
55
- self.window.ui.nodes['agent.continue'] = QCheckBox(trans("toolbox.agent.continue.label"))
56
- self.window.ui.nodes['agent.continue'].stateChanged.connect(
56
+ self.window.ui.nodes['agent.continue'] = ToggleLabel(trans("toolbox.agent.continue.label"))
57
+ self.window.ui.nodes['agent.continue'].box.stateChanged.connect(
57
58
  lambda:
58
59
  self.window.controller.agent.common.toggle_continue(
59
- self.window.ui.config['global']['agent.continue'].isChecked())
60
+ self.window.ui.config['global']['agent.continue'].box.isChecked())
60
61
  )
61
62
  self.window.ui.config['global']['agent.continue'] = self.window.ui.nodes['agent.continue']
62
63
 
@@ -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: 2024.11.21 20:00:00 #
9
+ # Updated Date: 2024.11.24 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtWidgets import QVBoxLayout, QLabel, QHBoxLayout, QWidget, QCheckBox
13
13
 
14
14
  from pygpt_net.ui.widget.option.slider import OptionSlider
15
+ from pygpt_net.ui.widget.option.toggle_label import ToggleLabel
15
16
  from pygpt_net.utils import trans
16
17
 
17
18
 
@@ -45,11 +46,11 @@ class AgentLlama:
45
46
  self.window.ui.config['global']['agent.llama.loop.score'] = self.window.ui.nodes['agent.llama.loop.score']
46
47
 
47
48
  # loop enabled
48
- self.window.ui.nodes['agent.llama.loop.enabled'] = QCheckBox(trans("toolbox.agent.llama.loop.enabled.label"))
49
- self.window.ui.nodes['agent.llama.loop.enabled'].stateChanged.connect(
49
+ self.window.ui.nodes['agent.llama.loop.enabled'] = ToggleLabel(trans("toolbox.agent.llama.loop.enabled.label"))
50
+ self.window.ui.nodes['agent.llama.loop.enabled'].box.stateChanged.connect(
50
51
  lambda:
51
52
  self.window.controller.agent.common.toggle_loop(
52
- self.window.ui.config['global']['agent.llama.loop.enabled'].isChecked())
53
+ self.window.ui.config['global']['agent.llama.loop.enabled'].box.isChecked())
53
54
  )
54
55
  self.window.ui.config['global']['agent.llama.loop.enabled'] = self.window.ui.nodes['agent.llama.loop.enabled']
55
56
 
@@ -6,14 +6,16 @@
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.11.24 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtGui import Qt, QIcon
13
13
  from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QPushButton, QWidget, QCheckBox, QSizePolicy
14
14
 
15
+ from pygpt_net.ui.widget.anims.toggles import AnimToggle
15
16
  from pygpt_net.ui.widget.element.labels import HelpLabel, TitleLabel
16
17
  from pygpt_net.ui.widget.option.prompt import PromptTextarea
18
+ from pygpt_net.ui.widget.option.toggle_label import ToggleLabel
17
19
  from pygpt_net.utils import trans
18
20
  import pygpt_net.icons_rc
19
21
 
@@ -33,12 +35,12 @@ class Prompt:
33
35
  :return: QWidget
34
36
  """
35
37
  # cmd enable/disable
36
- self.window.ui.nodes['cmd.enabled'] = QCheckBox(trans('cmd.enabled'))
37
- self.window.ui.nodes['cmd.enabled'].stateChanged.connect(
38
- lambda: self.window.controller.chat.common.toggle_cmd(self.window.ui.nodes['cmd.enabled'].isChecked())
38
+ self.window.ui.nodes['cmd.enabled'] = ToggleLabel(trans('cmd.enabled'), label_position="left",icon = ":/icons/build.svg")
39
+ self.window.ui.nodes['cmd.enabled'].box.stateChanged.connect(
40
+ lambda: self.window.controller.chat.common.toggle_cmd(self.window.ui.nodes['cmd.enabled'].box.isChecked())
39
41
  )
40
- self.window.ui.nodes['cmd.enabled'].setToolTip(trans('cmd.tip'))
41
- self.window.ui.nodes['cmd.enabled'].setIcon(QIcon(":/icons/add.svg"))
42
+ self.window.ui.nodes['cmd.enabled'].box.setToolTip(trans('cmd.tip'))
43
+ self.window.ui.nodes['cmd.enabled'].box.setIcon(QIcon(":/icons/add.svg"))
42
44
 
43
45
  # label
44
46
  self.window.ui.nodes['toolbox.prompt.label'] = TitleLabel(trans("toolbox.prompt"))
@@ -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.16 05:00:00 #
9
+ # Updated Date: 2024.11.24 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtGui import QAction, QIcon
@@ -55,23 +55,29 @@ class Tools:
55
55
  self.window.ui.menu[key] = actions[key]
56
56
  self.window.ui.menu['menu.tools'].addAction(self.window.ui.menu[key])
57
57
 
58
- # docker rebuild
59
- # ipython
58
+ # ------------------------------------------------- #
59
+
60
+ # Docker images rebuild:
61
+
62
+ # IPython container
60
63
  self.window.ui.menu['menu.tools'].addSeparator()
61
- self.window.ui.menu['menu.tools.ipython.rebuild'] = QAction(QIcon(":/icons/reload.svg"), "Rebuild IPython Docker Image", self.window)
64
+ self.window.ui.menu['menu.tools.ipython.rebuild'] = QAction(QIcon(":/icons/reload.svg"),
65
+ "Rebuild IPython Docker Image", self.window)
62
66
  self.window.ui.menu['menu.tools'].addAction(self.window.ui.menu['menu.tools.ipython.rebuild'])
63
67
  self.window.ui.menu['menu.tools.ipython.rebuild'].triggered.connect(
64
- lambda: self.window.core.plugins.get("cmd_code_interpreter").builder.build_image()
68
+ lambda: self.window.core.plugins.get("cmd_code_interpreter").builder.build_and_restart()
65
69
  )
66
- # legacy
67
- self.window.ui.menu['menu.tools.python_legacy.rebuild'] = QAction(QIcon(":/icons/reload.svg"), "Rebuild Python (Legacy) Docker Image", self.window)
70
+ # Python Legacy container
71
+ self.window.ui.menu['menu.tools.python_legacy.rebuild'] = QAction(QIcon(":/icons/reload.svg"),
72
+ "Rebuild Python (Legacy) Docker Image", self.window)
68
73
  self.window.ui.menu['menu.tools'].addAction(self.window.ui.menu['menu.tools.python_legacy.rebuild'])
69
74
  self.window.ui.menu['menu.tools.python_legacy.rebuild'].triggered.connect(
70
- lambda: self.window.core.plugins.get("cmd_code_interpreter").docker.build()
75
+ lambda: self.window.core.plugins.get("cmd_code_interpreter").docker.build_and_restart()
71
76
  )
72
- # sys
73
- self.window.ui.menu['menu.tools.system.rebuild'] = QAction(QIcon(":/icons/reload.svg"), "Rebuild System Sandbox Docker Image", self.window)
77
+ # System container
78
+ self.window.ui.menu['menu.tools.system.rebuild'] = QAction(QIcon(":/icons/reload.svg"),
79
+ "Rebuild System Sandbox Docker Image", self.window)
74
80
  self.window.ui.menu['menu.tools'].addAction(self.window.ui.menu['menu.tools.system.rebuild'])
75
81
  self.window.ui.menu['menu.tools.system.rebuild'].triggered.connect(
76
- lambda: self.window.core.plugins.get("cmd_system").docker.build()
82
+ lambda: self.window.core.plugins.get("cmd_system").docker.build_and_restart()
77
83
  )
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # ================================================== #
4
+ # This file is a part of PYGPT package #
5
+ # Website: https://pygpt.net #
6
+ # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
+ # MIT License #
8
+ # Created By : Marcin Szczygliński #
9
+ # Updated Date: 2024.11.24 22:00:00 #
10
+ # ================================================== #
11
+
12
+ from PySide6.QtCore import (
13
+ Qt, QSize, QPoint, QPointF, QRectF,
14
+ QEasingCurve, QPropertyAnimation, QSequentialAnimationGroup,
15
+ Slot, Property, QEvent)
16
+
17
+ from PySide6.QtWidgets import QCheckBox
18
+ from PySide6.QtGui import QColor, QBrush, QPaintEvent, QPen, QPainter, QPalette
19
+
20
+
21
+ class AnimToggle(QCheckBox):
22
+
23
+ # Based on widget from: https://www.pythonguis.com/tutorials/pyside6-animated-widgets/
24
+
25
+ _transparent_pen = QPen(Qt.transparent)
26
+ _light_grey_pen = QPen(Qt.lightGray)
27
+
28
+ def __init__(self, title="", parent=None):
29
+ super().__init__(parent)
30
+ self.setText(title)
31
+
32
+ # Initialize the colors based on the current palette
33
+ self.updateColors()
34
+
35
+ # Setup the rest of the widget.
36
+ self.setContentsMargins(8, 0, 8, 0)
37
+ self.setMaximumWidth(58)
38
+ self._handle_position = 0
39
+ self._pulse_radius = 0
40
+
41
+ # Setup animations
42
+ self.animation = QPropertyAnimation(self, b"handle_position", self)
43
+ self.animation.setEasingCurve(QEasingCurve.InOutCubic)
44
+ self.animation.setDuration(200) # time in ms
45
+
46
+ self.pulse_anim = QPropertyAnimation(self, b"pulse_radius", self)
47
+ self.pulse_anim.setDuration(350) # time in ms
48
+ self.pulse_anim.setStartValue(10)
49
+ self.pulse_anim.setEndValue(20)
50
+
51
+ self.animations_group = QSequentialAnimationGroup()
52
+ self.animations_group.addAnimation(self.animation)
53
+ self.animations_group.addAnimation(self.pulse_anim)
54
+
55
+ self.stateChanged.connect(self.setup_animation)
56
+
57
+ def updateColors(self):
58
+ # Get colors from the palette.
59
+ palette = self.palette()
60
+ #bar_color = QPen(Qt.lightGray).color()
61
+ bar_color = QColor("#969696")
62
+ #bar_checked_color = palette.color(QPalette.Dark)
63
+ bar_checked_color = QColor("#969696")
64
+ bar_color.setAlpha(0x80)
65
+ handle_color = palette.color(QPalette.Shadow)
66
+ handle_checked_color = palette.color(QPalette.ButtonText)
67
+
68
+ # Create semi-transparent colors for the pulse effect
69
+ pulse_unchecked_color = bar_color.darker(110)
70
+ pulse_checked_color = bar_checked_color.lighter(130)
71
+ pulse_unchecked_color.setAlpha(0x44)
72
+ pulse_checked_color.setAlpha(0x44)
73
+
74
+ # Now set the brushes
75
+ self._bar_brush = QBrush(bar_color)
76
+ self._bar_checked_brush = QBrush(bar_checked_color)
77
+ self._handle_brush = QBrush(handle_color)
78
+ self._handle_checked_brush = QBrush(handle_checked_color)
79
+ self._pulse_unchecked_animation = QBrush(pulse_unchecked_color)
80
+ self._pulse_checked_animation = QBrush(pulse_checked_color)
81
+
82
+ # Update the widget to redraw with new colors
83
+ self.update()
84
+
85
+ def event(self, e):
86
+ if e.type() == QEvent.PaletteChange:
87
+ self.updateColors()
88
+ return super().event(e)
89
+
90
+ def sizeHint(self):
91
+ return QSize(58, 45)
92
+
93
+ def hitButton(self, pos: QPoint):
94
+ return self.contentsRect().contains(pos)
95
+
96
+ @Slot(int)
97
+ def setup_animation(self, value):
98
+ self.animations_group.stop()
99
+ if value:
100
+ self.animation.setEndValue(1)
101
+ else:
102
+ self.animation.setEndValue(0)
103
+ self.animations_group.start()
104
+
105
+ def paintEvent(self, e: QPaintEvent):
106
+
107
+ contRect = self.contentsRect()
108
+ handleRadius = round(0.24 * contRect.height())
109
+
110
+ p = QPainter(self)
111
+ p.setRenderHint(QPainter.Antialiasing)
112
+ p.setPen(self._transparent_pen)
113
+
114
+ barRect = QRectF(
115
+ 0, 0,
116
+ contRect.width() - handleRadius, 0.40 * contRect.height()
117
+ )
118
+ barRect.moveCenter(contRect.center())
119
+ rounding = barRect.height() / 2
120
+
121
+ # The handle will move along this line
122
+ trailLength = contRect.width() - 2 * handleRadius
123
+
124
+ xPos = contRect.x() + handleRadius + trailLength * self._handle_position
125
+
126
+ if self.pulse_anim.state() == QPropertyAnimation.Running:
127
+ p.setBrush(
128
+ self._pulse_checked_animation if
129
+ self.isChecked() else self._pulse_unchecked_animation)
130
+ p.drawEllipse(QPointF(xPos, barRect.center().y()),
131
+ self._pulse_radius, self._pulse_radius)
132
+
133
+ if self.isChecked():
134
+ p.setBrush(self._bar_checked_brush)
135
+ p.drawRoundedRect(barRect, rounding, rounding)
136
+ p.setBrush(self._handle_checked_brush)
137
+ else:
138
+ p.setBrush(self._bar_brush)
139
+ p.drawRoundedRect(barRect, rounding, rounding)
140
+ p.setPen(self._light_grey_pen)
141
+ p.setBrush(self._handle_brush)
142
+
143
+ p.drawEllipse(
144
+ QPointF(xPos, barRect.center().y()),
145
+ handleRadius, handleRadius)
146
+
147
+ p.end()
148
+
149
+ @Property(float)
150
+ def handle_position(self):
151
+ return self._handle_position
152
+
153
+ @handle_position.setter
154
+ def handle_position(self, pos):
155
+ # Update the position and redraw
156
+ self._handle_position = pos
157
+ self.update()
158
+
159
+ @Property(float)
160
+ def pulse_radius(self):
161
+ return self._pulse_radius
162
+
163
+ @pulse_radius.setter
164
+ def pulse_radius(self, pos):
165
+ # Update the pulse radius and redraw
166
+ self._pulse_radius = pos
167
+ self.update()
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # ================================================== #
4
+ # This file is a part of PYGPT package #
5
+ # Website: https://pygpt.net #
6
+ # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
+ # MIT License #
8
+ # Created By : Marcin Szczygliński #
9
+ # Updated Date: 2024.11.26 02:00:00 #
10
+ # ================================================== #
11
+
12
+ from PySide6.QtWidgets import QDialog, QLabel, QHBoxLayout, QVBoxLayout, QPushButton
13
+
14
+ from pygpt_net.ui.widget.element.labels import HelpLabel
15
+ from pygpt_net.utils import trans
16
+ from pygpt_net.ui.widget.textarea.url import UrlInput
17
+
18
+
19
+ class UrlDialog(QDialog):
20
+ def __init__(self, window=None, id=None):
21
+ """
22
+ Url dialog
23
+
24
+ :param window: main window
25
+ :param id: info window id
26
+ """
27
+ super(UrlDialog, self).__init__(window)
28
+ self.window = window
29
+ self.id = id
30
+ self.current = None
31
+ self.input = UrlInput(window, id)
32
+ self.input.setMinimumWidth(400)
33
+
34
+ self.window.ui.nodes['dialog.url.btn.update'] = QPushButton(trans('dialog.url.update'))
35
+ self.window.ui.nodes['dialog.url.btn.update'].clicked.connect(
36
+ lambda: self.window.controller.dialogs.confirm.accept_url(
37
+ self.id,
38
+ self.window.ui.dialog['url'].current,
39
+ self.input.text()),
40
+ )
41
+
42
+ self.window.ui.nodes['dialog.url.btn.dismiss'] = QPushButton(trans('dialog.url.dismiss'))
43
+ self.window.ui.nodes['dialog.url.btn.dismiss'].clicked.connect(
44
+ lambda: self.window.controller.dialogs.confirm.dismiss_url())
45
+
46
+ bottom = QHBoxLayout()
47
+ bottom.addWidget(self.window.ui.nodes['dialog.url.btn.dismiss'])
48
+ bottom.addWidget(self.window.ui.nodes['dialog.url.btn.update'])
49
+
50
+ self.window.ui.nodes['dialog.url.label'] = QLabel(trans("dialog.url.title"))
51
+ self.window.ui.nodes['dialog.url.tip'] = HelpLabel(trans("dialog.url.tip"))
52
+
53
+ layout = QVBoxLayout()
54
+ layout.addWidget(self.window.ui.nodes['dialog.url.label'])
55
+ layout.addWidget(self.input)
56
+ layout.addWidget(self.window.ui.nodes['dialog.url.tip'])
57
+ layout.addLayout(bottom)
58
+
59
+ self.setLayout(layout)
@@ -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.01.27 11:00:00 #
9
+ # Updated Date: 2024.11.24 22:00:00 #
10
10
  # ================================================== #
11
11
  from PySide6.QtCore import Qt
12
12
  from PySide6.QtGui import QIcon
@@ -53,6 +53,7 @@ class CollapsedGroup(QWidget):
53
53
  height: 0px;
54
54
  }
55
55
  """)
56
+ self.update_icon(self.box.checkState())
56
57
 
57
58
  # options layout
58
59
  self.options = QVBoxLayout()