pygpt-net 2.6.1__py3-none-any.whl → 2.6.6__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 (131) hide show
  1. pygpt_net/CHANGELOG.txt +23 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +20 -1
  4. pygpt_net/config.py +55 -65
  5. pygpt_net/controller/__init__.py +5 -2
  6. pygpt_net/controller/calendar/note.py +101 -126
  7. pygpt_net/controller/chat/chat.py +38 -35
  8. pygpt_net/controller/chat/render.py +154 -214
  9. pygpt_net/controller/chat/response.py +5 -3
  10. pygpt_net/controller/chat/stream.py +92 -27
  11. pygpt_net/controller/config/config.py +39 -42
  12. pygpt_net/controller/config/field/checkbox.py +16 -12
  13. pygpt_net/controller/config/field/checkbox_list.py +36 -31
  14. pygpt_net/controller/config/field/cmd.py +51 -57
  15. pygpt_net/controller/config/field/combo.py +33 -16
  16. pygpt_net/controller/config/field/dictionary.py +48 -55
  17. pygpt_net/controller/config/field/input.py +50 -32
  18. pygpt_net/controller/config/field/slider.py +40 -45
  19. pygpt_net/controller/config/field/textarea.py +20 -6
  20. pygpt_net/controller/config/placeholder.py +110 -231
  21. pygpt_net/controller/ctx/common.py +48 -48
  22. pygpt_net/controller/ctx/ctx.py +91 -132
  23. pygpt_net/controller/lang/mapping.py +57 -95
  24. pygpt_net/controller/lang/plugins.py +64 -55
  25. pygpt_net/controller/lang/settings.py +39 -38
  26. pygpt_net/controller/layout/layout.py +176 -109
  27. pygpt_net/controller/mode/mode.py +88 -85
  28. pygpt_net/controller/model/model.py +73 -73
  29. pygpt_net/controller/plugins/plugins.py +209 -223
  30. pygpt_net/controller/plugins/presets.py +54 -55
  31. pygpt_net/controller/plugins/settings.py +54 -69
  32. pygpt_net/controller/presets/editor.py +33 -88
  33. pygpt_net/controller/presets/experts.py +20 -1
  34. pygpt_net/controller/presets/presets.py +293 -298
  35. pygpt_net/controller/settings/profile.py +16 -4
  36. pygpt_net/controller/theme/theme.py +72 -81
  37. pygpt_net/controller/ui/mode.py +118 -186
  38. pygpt_net/controller/ui/tabs.py +69 -90
  39. pygpt_net/controller/ui/ui.py +47 -56
  40. pygpt_net/controller/ui/vision.py +24 -23
  41. pygpt_net/core/agents/runner.py +15 -7
  42. pygpt_net/core/bridge/bridge.py +5 -5
  43. pygpt_net/core/command/command.py +149 -219
  44. pygpt_net/core/ctx/ctx.py +94 -146
  45. pygpt_net/core/debug/debug.py +48 -58
  46. pygpt_net/core/experts/experts.py +3 -3
  47. pygpt_net/core/models/models.py +74 -112
  48. pygpt_net/core/modes/modes.py +13 -21
  49. pygpt_net/core/plugins/plugins.py +154 -177
  50. pygpt_net/core/presets/presets.py +103 -176
  51. pygpt_net/core/render/web/body.py +217 -215
  52. pygpt_net/core/render/web/renderer.py +330 -474
  53. pygpt_net/core/text/utils.py +28 -44
  54. pygpt_net/core/tokens/tokens.py +104 -203
  55. pygpt_net/data/config/config.json +3 -3
  56. pygpt_net/data/config/models.json +3 -3
  57. pygpt_net/data/locale/locale.de.ini +2 -0
  58. pygpt_net/data/locale/locale.en.ini +2 -0
  59. pygpt_net/data/locale/locale.es.ini +2 -0
  60. pygpt_net/data/locale/locale.fr.ini +2 -0
  61. pygpt_net/data/locale/locale.it.ini +2 -0
  62. pygpt_net/data/locale/locale.pl.ini +3 -1
  63. pygpt_net/data/locale/locale.uk.ini +2 -0
  64. pygpt_net/data/locale/locale.zh.ini +2 -0
  65. pygpt_net/item/ctx.py +141 -139
  66. pygpt_net/plugin/agent/plugin.py +2 -1
  67. pygpt_net/plugin/audio_output/plugin.py +5 -2
  68. pygpt_net/plugin/base/plugin.py +101 -85
  69. pygpt_net/plugin/bitbucket/__init__.py +12 -0
  70. pygpt_net/plugin/bitbucket/config.py +267 -0
  71. pygpt_net/plugin/bitbucket/plugin.py +126 -0
  72. pygpt_net/plugin/bitbucket/worker.py +569 -0
  73. pygpt_net/plugin/cmd_code_interpreter/plugin.py +3 -2
  74. pygpt_net/plugin/cmd_custom/plugin.py +3 -2
  75. pygpt_net/plugin/cmd_files/plugin.py +3 -2
  76. pygpt_net/plugin/cmd_history/plugin.py +3 -2
  77. pygpt_net/plugin/cmd_mouse_control/plugin.py +5 -2
  78. pygpt_net/plugin/cmd_serial/plugin.py +3 -2
  79. pygpt_net/plugin/cmd_system/plugin.py +3 -6
  80. pygpt_net/plugin/cmd_web/plugin.py +3 -2
  81. pygpt_net/plugin/experts/plugin.py +2 -2
  82. pygpt_net/plugin/facebook/__init__.py +12 -0
  83. pygpt_net/plugin/facebook/config.py +359 -0
  84. pygpt_net/plugin/facebook/plugin.py +113 -0
  85. pygpt_net/plugin/facebook/worker.py +698 -0
  86. pygpt_net/plugin/github/__init__.py +12 -0
  87. pygpt_net/plugin/github/config.py +441 -0
  88. pygpt_net/plugin/github/plugin.py +126 -0
  89. pygpt_net/plugin/github/worker.py +674 -0
  90. pygpt_net/plugin/google/__init__.py +12 -0
  91. pygpt_net/plugin/google/config.py +367 -0
  92. pygpt_net/plugin/google/plugin.py +126 -0
  93. pygpt_net/plugin/google/worker.py +826 -0
  94. pygpt_net/plugin/idx_llama_index/plugin.py +3 -2
  95. pygpt_net/plugin/mailer/plugin.py +3 -5
  96. pygpt_net/plugin/openai_vision/plugin.py +3 -2
  97. pygpt_net/plugin/real_time/plugin.py +52 -60
  98. pygpt_net/plugin/slack/__init__.py +12 -0
  99. pygpt_net/plugin/slack/config.py +349 -0
  100. pygpt_net/plugin/slack/plugin.py +115 -0
  101. pygpt_net/plugin/slack/worker.py +639 -0
  102. pygpt_net/plugin/telegram/__init__.py +12 -0
  103. pygpt_net/plugin/telegram/config.py +308 -0
  104. pygpt_net/plugin/telegram/plugin.py +117 -0
  105. pygpt_net/plugin/telegram/worker.py +563 -0
  106. pygpt_net/plugin/twitter/__init__.py +12 -0
  107. pygpt_net/plugin/twitter/config.py +491 -0
  108. pygpt_net/plugin/twitter/plugin.py +125 -0
  109. pygpt_net/plugin/twitter/worker.py +837 -0
  110. pygpt_net/provider/agents/llama_index/legacy/openai_assistant.py +35 -3
  111. pygpt_net/tools/code_interpreter/tool.py +0 -1
  112. pygpt_net/tools/translator/tool.py +1 -1
  113. pygpt_net/ui/base/config_dialog.py +86 -100
  114. pygpt_net/ui/base/context_menu.py +48 -46
  115. pygpt_net/ui/dialog/preset.py +34 -77
  116. pygpt_net/ui/layout/ctx/ctx_list.py +10 -6
  117. pygpt_net/ui/layout/toolbox/presets.py +41 -41
  118. pygpt_net/ui/main.py +49 -31
  119. pygpt_net/ui/tray.py +61 -60
  120. pygpt_net/ui/widget/calendar/select.py +86 -70
  121. pygpt_net/ui/widget/lists/attachment.py +86 -44
  122. pygpt_net/ui/widget/lists/base_list_combo.py +85 -33
  123. pygpt_net/ui/widget/lists/context.py +135 -188
  124. pygpt_net/ui/widget/lists/preset.py +59 -61
  125. pygpt_net/ui/widget/textarea/web.py +161 -48
  126. pygpt_net/utils.py +8 -1
  127. {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.6.dist-info}/METADATA +164 -2
  128. {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.6.dist-info}/RECORD +131 -103
  129. {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.6.dist-info}/LICENSE +0 -0
  130. {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.6.dist-info}/WHEEL +0 -0
  131. {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.6.dist-info}/entry_points.txt +0 -0
@@ -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.07.18 00:00:00 #
9
+ # Updated Date: 2025.08.16 00:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
13
13
  from pathlib import Path
14
14
  from typing import Optional, Dict, Any
15
15
 
16
- from PySide6.QtCore import Slot
16
+ from PySide6.QtCore import Slot, QTimer
17
17
  from PySide6.QtGui import QAction
18
18
 
19
19
  from pygpt_net.utils import trans
@@ -84,7 +84,7 @@ class Profile:
84
84
  self.window.controller.settings.workdir.update(
85
85
  path,
86
86
  force=True,
87
- profile_name= profile['name']
87
+ profile_name=profile['name']
88
88
  ) # self.after_update() is called in update worker on success
89
89
  else:
90
90
  self.after_update(profile['name'])
@@ -224,7 +224,8 @@ class Profile:
224
224
  uuid = self.window.core.config.profile.add(name, path)
225
225
  self.window.update_status(trans("dialog.profile.status.created"))
226
226
  if self.window.ui.nodes['dialog.profile.checkbox.switch'].isChecked():
227
- self.switch(uuid, force=True)
227
+ QTimer.singleShot(100, lambda: self.after_create(uuid))
228
+ return
228
229
 
229
230
  elif mode == 'edit':
230
231
  # update profile
@@ -284,6 +285,17 @@ class Profile:
284
285
  self.update_menu()
285
286
  self.update_list()
286
287
 
288
+ def after_create(self, uuid: str):
289
+ """
290
+ After profile creation
291
+
292
+ :param uuid: profile UUID
293
+ """
294
+ self.switch(uuid, force=True)
295
+ self.window.ui.dialogs.close('profile.item')
296
+ self.update_menu()
297
+ self.update_list()
298
+
287
299
  def dismiss_update(self):
288
300
  """Dismiss update dialog"""
289
301
  self.window.ui.dialogs.close('profile.item')
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.07.23 01:00:00 #
9
+ # Updated Date: 2025.08.15 03:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -34,18 +34,11 @@ class Theme:
34
34
 
35
35
  def setup(self):
36
36
  """Setup theme"""
37
- # load markdown CSS
38
37
  self.markdown.load()
39
-
40
- # setup menus
41
38
  self.menu.setup_list()
42
39
  self.menu.setup_density()
43
40
  self.menu.setup_syntax()
44
-
45
- # show or hide tooltips
46
41
  self.common.toggle_tooltips()
47
-
48
- # apply current theme to nodes
49
42
  self.reload(force=False)
50
43
 
51
44
  def toggle(
@@ -59,33 +52,32 @@ class Theme:
59
52
  :param name: theme name
60
53
  :param force: force theme change (manual trigger)
61
54
  """
55
+ window = self.window
56
+ core = window.core
57
+ controller = window.controller
58
+
62
59
  if force:
63
- self.window.controller.ui.store_state() # store state before theme change
60
+ controller.ui.store_state()
64
61
 
65
- self.window.core.config.set('theme', name)
66
- self.window.core.config.save()
62
+ core.config.set('theme', name)
63
+ core.config.save()
67
64
  self.nodes.apply_all()
68
65
 
69
- is_custom = False
70
- custom_themes = self.window.controller.theme.common.get_custom_themes_list()
71
- if name in custom_themes:
72
- is_custom = True
66
+ custom_themes = controller.theme.common.get_custom_themes_list()
67
+ is_custom = name in custom_themes
73
68
 
74
69
  self.apply(
75
- name + '.xml',
70
+ f'{name}.xml',
76
71
  self.common.get_extra_css(name),
77
72
  is_custom=is_custom,
78
- ) # style.css = additional custom stylesheet
73
+ )
79
74
 
80
- # apply markdown CSS
81
75
  self.markdown.update(force=False)
82
-
83
- # update themes menu
84
76
  self.menu.update_list()
85
77
  self.menu.update_syntax()
86
78
 
87
79
  if force:
88
- self.window.controller.ui.restore_state() # restore state after theme change
80
+ controller.ui.restore_state()
89
81
 
90
82
  def toggle_style(self, name: str):
91
83
  """
@@ -93,8 +85,9 @@ class Theme:
93
85
 
94
86
  :param name: web style name
95
87
  """
96
- self.window.core.config.set('theme.style', name)
97
- self.window.core.config.save()
88
+ core = self.window.core
89
+ core.config.set('theme.style', name)
90
+ core.config.save()
98
91
  event = RenderEvent(RenderEvent.ON_THEME_CHANGE)
99
92
  self.window.dispatch(event)
100
93
  self.reload()
@@ -110,30 +103,29 @@ class Theme:
110
103
  :param name: option name
111
104
  :param value: option value
112
105
  """
106
+ window = self.window
107
+ core = window.core
108
+ cfg = core.config
109
+
113
110
  if name == 'layout.tooltips':
114
- if self.window.core.config.get(name):
115
- state = False
116
- else:
117
- state = True
118
- self.window.core.config.set(name, state)
119
- self.window.controller.config.checkbox.apply('config', 'layout.tooltips', {'value': state})
111
+ state = not bool(cfg.get(name))
112
+ cfg.set(name, state)
113
+ window.controller.config.checkbox.apply('config', 'layout.tooltips', {'value': state})
120
114
  self.common.toggle_tooltips()
121
115
  elif name == 'layout.density':
122
- value = int(value)
123
- self.window.core.config.set(name, value)
124
- self.window.controller.config.slider.apply('config', 'layout.density', {'value': value})
116
+ val = int(value)
117
+ cfg.set(name, val)
118
+ window.controller.config.slider.apply('config', 'layout.density', {'value': val})
125
119
  self.reload()
126
120
  self.menu.update_density()
127
121
  elif name == 'render.blocks':
128
- if self.window.core.config.get(name):
129
- state = False
130
- else:
131
- state = True
132
- self.window.core.config.set(name, state)
122
+ state = not bool(cfg.get(name))
123
+ cfg.set(name, state)
133
124
  event = RenderEvent(RenderEvent.ON_THEME_CHANGE)
134
- self.window.dispatch(event)
125
+ window.dispatch(event)
135
126
  self.reload()
136
- self.window.core.config.save()
127
+
128
+ cfg.save()
137
129
  self.nodes.apply_all()
138
130
 
139
131
  def toggle_syntax(
@@ -147,8 +139,9 @@ class Theme:
147
139
  :param name: syntax style name
148
140
  :param update_menu: update menu
149
141
  """
150
- self.window.core.config.set("render.code_syntax", name)
151
- self.window.core.config.save()
142
+ core = self.window.core
143
+ core.config.set("render.code_syntax", name)
144
+ core.config.save()
152
145
  event = RenderEvent(RenderEvent.ON_THEME_CHANGE)
153
146
  self.window.dispatch(event)
154
147
  if update_menu:
@@ -194,59 +187,57 @@ class Theme:
194
187
  :param custom: additional stylesheet filename (e.g. style.css)
195
188
  :param is_custom: is custom base theme
196
189
  """
197
- inverse = False
198
- theme_name = theme.split('.')[0] # get theme name without extension
199
- if theme.startswith('light'):
200
- inverse = True
190
+ window = self.window
191
+ core = window.core
192
+ cfg = core.config
193
+
194
+ base_name = os.path.splitext(os.path.basename(theme))[0]
195
+ is_light = base_name.startswith('light')
201
196
  extra = {
202
- 'density_scale': self.window.core.config.get('layout.density'),
197
+ 'density_scale': cfg.get('layout.density'),
203
198
  'pyside6': True,
204
199
  }
205
200
 
206
- if is_custom: # load from app path
207
- theme = os.path.join(self.window.core.config.get_app_path(), 'data', 'themes', theme)
201
+ if is_custom:
202
+ theme = os.path.join(cfg.get_app_path(), 'data', 'themes', theme)
208
203
 
209
- self.window.apply_stylesheet(self.window, theme, invert_secondary=inverse, extra=extra)
204
+ window.apply_stylesheet(window, theme, invert_secondary=is_light, extra=extra)
210
205
 
211
- # append custom stylesheets
212
- content = ''
213
- stylesheet = self.window.styleSheet() # get current stylesheet
206
+ content_parts = []
214
207
  if custom is not None:
215
- paths = []
216
- paths.append(os.path.join(self.window.core.config.get_app_path(), 'data', 'css', custom))
217
- paths.append(os.path.join(self.window.core.config.get_user_path(), 'css', custom))
208
+ app_css = os.path.join(cfg.get_app_path(), 'data', 'css', custom)
209
+ user_css = os.path.join(cfg.get_user_path(), 'css', custom)
218
210
 
219
- for path in paths:
220
- if os.path.exists(path):
221
- with open(path) as file:
222
- content += file.read()
211
+ if os.path.exists(app_css):
212
+ with open(app_css, 'r', encoding='utf-8') as file:
213
+ content_parts.append(file.read())
214
+ if os.path.exists(user_css):
215
+ with open(user_css, 'r', encoding='utf-8') as file:
216
+ content_parts.append(file.read())
223
217
 
224
- # Windows checkbox button + radio button fix (if no SVG support)
225
- # when missing DLLs in PySide6, VC++ redistributable required
226
- if self.window.core.platforms.is_windows() and not self.window.core.config.is_compiled():
227
- content += self.common.get_windows_fix()
218
+ if core.platforms.is_windows() and not cfg.is_compiled():
219
+ content_parts.append(self.common.get_windows_fix())
228
220
 
229
221
  if is_custom:
230
- path = os.path.join(self.window.core.config.get_app_path(), 'data', 'themes', theme_name + '.css')
231
- if os.path.exists(path):
232
- with open(path) as file:
233
- content += file.read()
234
-
235
- # windows fixes
236
- if self.window.core.platforms.is_windows():
237
- if theme.startswith('light'):
238
- path = os.path.join(self.window.core.config.get_app_path(), 'data', 'css', 'fix_windows.light.css')
239
- else:
240
- path = os.path.join(self.window.core.config.get_app_path(), 'data', 'css', 'fix_windows.dark.css')
222
+ theme_css = os.path.join(cfg.get_app_path(), 'data', 'themes', f'{base_name}.css')
223
+ if os.path.exists(theme_css):
224
+ with open(theme_css, 'r', encoding='utf-8') as file:
225
+ content_parts.append(file.read())
226
+
227
+ if core.platforms.is_windows():
228
+ fix_css = 'fix_windows.light.css' if is_light else 'fix_windows.dark.css'
229
+ path = os.path.join(cfg.get_app_path(), 'data', 'css', fix_css)
241
230
  if os.path.exists(path):
242
- with open(path) as file:
243
- content += file.read()
231
+ with open(path, 'r', encoding='utf-8') as file:
232
+ content_parts.append(file.read())
244
233
 
245
234
  if custom is not None or is_custom:
246
- try:
247
- self.window.setStyleSheet(stylesheet + content.format(**os.environ)) # apply stylesheet
248
- except KeyError as e:
249
- pass # ignore missing env variables
235
+ if content_parts:
236
+ try:
237
+ stylesheet = window.styleSheet()
238
+ window.setStyleSheet(stylesheet + ''.join(content_parts).format(**os.environ))
239
+ except KeyError:
240
+ pass
250
241
 
251
242
  def style(self, element: str) -> str:
252
243
  """
@@ -261,4 +252,4 @@ class Theme:
261
252
  """Reload all"""
262
253
  self.setup()
263
254
  self.update_style()
264
- self.update_syntax()
255
+ self.update_syntax()