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.
- pygpt_net/CHANGELOG.txt +23 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/app.py +20 -1
- pygpt_net/config.py +55 -65
- pygpt_net/controller/__init__.py +5 -2
- pygpt_net/controller/calendar/note.py +101 -126
- pygpt_net/controller/chat/chat.py +38 -35
- pygpt_net/controller/chat/render.py +154 -214
- pygpt_net/controller/chat/response.py +5 -3
- pygpt_net/controller/chat/stream.py +92 -27
- pygpt_net/controller/config/config.py +39 -42
- pygpt_net/controller/config/field/checkbox.py +16 -12
- pygpt_net/controller/config/field/checkbox_list.py +36 -31
- pygpt_net/controller/config/field/cmd.py +51 -57
- pygpt_net/controller/config/field/combo.py +33 -16
- pygpt_net/controller/config/field/dictionary.py +48 -55
- pygpt_net/controller/config/field/input.py +50 -32
- pygpt_net/controller/config/field/slider.py +40 -45
- pygpt_net/controller/config/field/textarea.py +20 -6
- pygpt_net/controller/config/placeholder.py +110 -231
- pygpt_net/controller/ctx/common.py +48 -48
- pygpt_net/controller/ctx/ctx.py +91 -132
- pygpt_net/controller/lang/mapping.py +57 -95
- pygpt_net/controller/lang/plugins.py +64 -55
- pygpt_net/controller/lang/settings.py +39 -38
- pygpt_net/controller/layout/layout.py +176 -109
- pygpt_net/controller/mode/mode.py +88 -85
- pygpt_net/controller/model/model.py +73 -73
- pygpt_net/controller/plugins/plugins.py +209 -223
- pygpt_net/controller/plugins/presets.py +54 -55
- pygpt_net/controller/plugins/settings.py +54 -69
- pygpt_net/controller/presets/editor.py +33 -88
- pygpt_net/controller/presets/experts.py +20 -1
- pygpt_net/controller/presets/presets.py +293 -298
- pygpt_net/controller/settings/profile.py +16 -4
- pygpt_net/controller/theme/theme.py +72 -81
- pygpt_net/controller/ui/mode.py +118 -186
- pygpt_net/controller/ui/tabs.py +69 -90
- pygpt_net/controller/ui/ui.py +47 -56
- pygpt_net/controller/ui/vision.py +24 -23
- pygpt_net/core/agents/runner.py +15 -7
- pygpt_net/core/bridge/bridge.py +5 -5
- pygpt_net/core/command/command.py +149 -219
- pygpt_net/core/ctx/ctx.py +94 -146
- pygpt_net/core/debug/debug.py +48 -58
- pygpt_net/core/experts/experts.py +3 -3
- pygpt_net/core/models/models.py +74 -112
- pygpt_net/core/modes/modes.py +13 -21
- pygpt_net/core/plugins/plugins.py +154 -177
- pygpt_net/core/presets/presets.py +103 -176
- pygpt_net/core/render/web/body.py +217 -215
- pygpt_net/core/render/web/renderer.py +330 -474
- pygpt_net/core/text/utils.py +28 -44
- pygpt_net/core/tokens/tokens.py +104 -203
- pygpt_net/data/config/config.json +3 -3
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/locale/locale.de.ini +2 -0
- pygpt_net/data/locale/locale.en.ini +2 -0
- pygpt_net/data/locale/locale.es.ini +2 -0
- pygpt_net/data/locale/locale.fr.ini +2 -0
- pygpt_net/data/locale/locale.it.ini +2 -0
- pygpt_net/data/locale/locale.pl.ini +3 -1
- pygpt_net/data/locale/locale.uk.ini +2 -0
- pygpt_net/data/locale/locale.zh.ini +2 -0
- pygpt_net/item/ctx.py +141 -139
- pygpt_net/plugin/agent/plugin.py +2 -1
- pygpt_net/plugin/audio_output/plugin.py +5 -2
- pygpt_net/plugin/base/plugin.py +101 -85
- pygpt_net/plugin/bitbucket/__init__.py +12 -0
- pygpt_net/plugin/bitbucket/config.py +267 -0
- pygpt_net/plugin/bitbucket/plugin.py +126 -0
- pygpt_net/plugin/bitbucket/worker.py +569 -0
- pygpt_net/plugin/cmd_code_interpreter/plugin.py +3 -2
- pygpt_net/plugin/cmd_custom/plugin.py +3 -2
- pygpt_net/plugin/cmd_files/plugin.py +3 -2
- pygpt_net/plugin/cmd_history/plugin.py +3 -2
- pygpt_net/plugin/cmd_mouse_control/plugin.py +5 -2
- pygpt_net/plugin/cmd_serial/plugin.py +3 -2
- pygpt_net/plugin/cmd_system/plugin.py +3 -6
- pygpt_net/plugin/cmd_web/plugin.py +3 -2
- pygpt_net/plugin/experts/plugin.py +2 -2
- pygpt_net/plugin/facebook/__init__.py +12 -0
- pygpt_net/plugin/facebook/config.py +359 -0
- pygpt_net/plugin/facebook/plugin.py +113 -0
- pygpt_net/plugin/facebook/worker.py +698 -0
- pygpt_net/plugin/github/__init__.py +12 -0
- pygpt_net/plugin/github/config.py +441 -0
- pygpt_net/plugin/github/plugin.py +126 -0
- pygpt_net/plugin/github/worker.py +674 -0
- pygpt_net/plugin/google/__init__.py +12 -0
- pygpt_net/plugin/google/config.py +367 -0
- pygpt_net/plugin/google/plugin.py +126 -0
- pygpt_net/plugin/google/worker.py +826 -0
- pygpt_net/plugin/idx_llama_index/plugin.py +3 -2
- pygpt_net/plugin/mailer/plugin.py +3 -5
- pygpt_net/plugin/openai_vision/plugin.py +3 -2
- pygpt_net/plugin/real_time/plugin.py +52 -60
- pygpt_net/plugin/slack/__init__.py +12 -0
- pygpt_net/plugin/slack/config.py +349 -0
- pygpt_net/plugin/slack/plugin.py +115 -0
- pygpt_net/plugin/slack/worker.py +639 -0
- pygpt_net/plugin/telegram/__init__.py +12 -0
- pygpt_net/plugin/telegram/config.py +308 -0
- pygpt_net/plugin/telegram/plugin.py +117 -0
- pygpt_net/plugin/telegram/worker.py +563 -0
- pygpt_net/plugin/twitter/__init__.py +12 -0
- pygpt_net/plugin/twitter/config.py +491 -0
- pygpt_net/plugin/twitter/plugin.py +125 -0
- pygpt_net/plugin/twitter/worker.py +837 -0
- pygpt_net/provider/agents/llama_index/legacy/openai_assistant.py +35 -3
- pygpt_net/tools/code_interpreter/tool.py +0 -1
- pygpt_net/tools/translator/tool.py +1 -1
- pygpt_net/ui/base/config_dialog.py +86 -100
- pygpt_net/ui/base/context_menu.py +48 -46
- pygpt_net/ui/dialog/preset.py +34 -77
- pygpt_net/ui/layout/ctx/ctx_list.py +10 -6
- pygpt_net/ui/layout/toolbox/presets.py +41 -41
- pygpt_net/ui/main.py +49 -31
- pygpt_net/ui/tray.py +61 -60
- pygpt_net/ui/widget/calendar/select.py +86 -70
- pygpt_net/ui/widget/lists/attachment.py +86 -44
- pygpt_net/ui/widget/lists/base_list_combo.py +85 -33
- pygpt_net/ui/widget/lists/context.py +135 -188
- pygpt_net/ui/widget/lists/preset.py +59 -61
- pygpt_net/ui/widget/textarea/web.py +161 -48
- pygpt_net/utils.py +8 -1
- {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.6.dist-info}/METADATA +164 -2
- {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.6.dist-info}/RECORD +131 -103
- {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.6.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.6.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.6.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.
|
|
9
|
+
# Updated Date: 2025.08.15 03:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import re
|
|
@@ -29,6 +29,10 @@ from pygpt_net.item.preset import PresetItem
|
|
|
29
29
|
from pygpt_net.utils import trans
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
_FILENAME_SANITIZE_RE = re.compile(r'[^a-zA-Z0-9_\-\.]')
|
|
33
|
+
_VALIDATE_FILENAME_RE = re.compile(r'[^\w\s\-\.]')
|
|
34
|
+
|
|
35
|
+
|
|
32
36
|
class Presets:
|
|
33
37
|
def __init__(self, window=None):
|
|
34
38
|
"""
|
|
@@ -55,18 +59,20 @@ class Presets:
|
|
|
55
59
|
|
|
56
60
|
:return: True if bot
|
|
57
61
|
"""
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
w = self.window
|
|
63
|
+
cfg = w.core.config
|
|
64
|
+
if cfg.get('mode') != MODE_AGENT_OPENAI:
|
|
60
65
|
return False
|
|
61
|
-
|
|
62
|
-
if
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
preset_id = cfg.get('preset')
|
|
67
|
+
if not preset_id or preset_id == "*":
|
|
68
|
+
return False
|
|
69
|
+
preset_data = w.core.presets.get_by_id(MODE_AGENT_OPENAI, preset_id)
|
|
70
|
+
return bool(
|
|
71
|
+
preset_data
|
|
72
|
+
and preset_data.agent_openai
|
|
73
|
+
and preset_data.agent_provider_openai
|
|
74
|
+
and preset_data.agent_provider_openai.startswith("openai_agent_bot")
|
|
75
|
+
)
|
|
70
76
|
|
|
71
77
|
def select(self, idx: int):
|
|
72
78
|
"""
|
|
@@ -74,21 +80,19 @@ class Presets:
|
|
|
74
80
|
|
|
75
81
|
:param idx: value of the list (row idx)
|
|
76
82
|
"""
|
|
77
|
-
# check if preset change is not locked
|
|
78
83
|
if self.preset_change_locked():
|
|
79
84
|
return
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
self.window.dispatch(AppEvent(AppEvent.PRESET_SELECTED)) # app event
|
|
85
|
+
w = self.window
|
|
86
|
+
mode = w.core.config.get('mode')
|
|
87
|
+
self.set_by_idx(mode, idx)
|
|
88
|
+
preset_id = w.core.config.get('preset')
|
|
89
|
+
w.controller.ui.update()
|
|
90
|
+
w.controller.model.select_current()
|
|
91
|
+
w.dispatch(AppEvent(AppEvent.PRESET_SELECTED))
|
|
88
92
|
self.set_selected(idx)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
93
|
+
editor_ctrl = w.controller.presets.editor
|
|
94
|
+
if editor_ctrl.opened and editor_ctrl.current != preset_id:
|
|
95
|
+
self.editor.init(preset_id)
|
|
92
96
|
|
|
93
97
|
def get_current(self) -> Optional[PresetItem]:
|
|
94
98
|
"""
|
|
@@ -96,33 +100,39 @@ class Presets:
|
|
|
96
100
|
|
|
97
101
|
:return: preset item
|
|
98
102
|
"""
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
103
|
+
w = self.window
|
|
104
|
+
cfg = w.core.config
|
|
105
|
+
preset_id = cfg.get('preset')
|
|
106
|
+
mode = cfg.get('mode')
|
|
107
|
+
if preset_id and w.core.presets.has(mode, preset_id):
|
|
108
|
+
return w.core.presets.get_by_id(mode, preset_id)
|
|
104
109
|
return None
|
|
105
110
|
|
|
106
111
|
def next(self):
|
|
107
112
|
"""Select next preset"""
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
113
|
+
nodes = self.window.ui.nodes
|
|
114
|
+
models = self.window.ui.models
|
|
115
|
+
count = models['preset.presets'].rowCount()
|
|
116
|
+
if count <= 0:
|
|
117
|
+
return
|
|
118
|
+
idx = (nodes['preset.presets'].currentIndex().row() + 1) % count
|
|
112
119
|
self.select(idx)
|
|
113
120
|
|
|
114
121
|
def prev(self):
|
|
115
122
|
"""Select previous preset"""
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
123
|
+
nodes = self.window.ui.nodes
|
|
124
|
+
models = self.window.ui.models
|
|
125
|
+
count = models['preset.presets'].rowCount()
|
|
126
|
+
if count <= 0:
|
|
127
|
+
return
|
|
128
|
+
idx = (nodes['preset.presets'].currentIndex().row() - 1) % count
|
|
120
129
|
self.select(idx)
|
|
121
130
|
|
|
122
131
|
def use(self):
|
|
123
132
|
"""Copy preset prompt to input"""
|
|
124
|
-
self.window
|
|
125
|
-
|
|
133
|
+
w = self.window
|
|
134
|
+
w.controller.chat.common.append_to_input(
|
|
135
|
+
w.ui.nodes['preset.prompt'].toPlainText()
|
|
126
136
|
)
|
|
127
137
|
|
|
128
138
|
def paste_prompt(
|
|
@@ -136,15 +146,19 @@ class Presets:
|
|
|
136
146
|
:param idx: prompt index
|
|
137
147
|
:param parent: parent name
|
|
138
148
|
"""
|
|
139
|
-
|
|
149
|
+
w = self.window
|
|
150
|
+
template = w.core.prompt.template.get_by_id(idx)
|
|
140
151
|
if template is None:
|
|
141
152
|
return
|
|
153
|
+
target = None
|
|
142
154
|
if parent == "global":
|
|
143
|
-
|
|
155
|
+
target = w.ui.nodes['preset.prompt']
|
|
144
156
|
elif parent == "input":
|
|
145
|
-
|
|
157
|
+
target = w.ui.nodes['input']
|
|
146
158
|
elif parent == "editor":
|
|
147
|
-
|
|
159
|
+
target = w.ui.config["preset"]["prompt"]
|
|
160
|
+
if target is not None:
|
|
161
|
+
self.paste_to_textarea(target, template['prompt'])
|
|
148
162
|
|
|
149
163
|
def paste_custom_prompt(
|
|
150
164
|
self,
|
|
@@ -157,15 +171,19 @@ class Presets:
|
|
|
157
171
|
:param idx: prompt index
|
|
158
172
|
:param parent: parent name
|
|
159
173
|
"""
|
|
160
|
-
|
|
174
|
+
w = self.window
|
|
175
|
+
template = w.core.prompt.custom.get_by_id(idx)
|
|
161
176
|
if template is None:
|
|
162
177
|
return
|
|
178
|
+
target = None
|
|
163
179
|
if parent == "global":
|
|
164
|
-
|
|
180
|
+
target = w.ui.nodes['preset.prompt']
|
|
165
181
|
elif parent == "input":
|
|
166
|
-
|
|
182
|
+
target = w.ui.nodes['input']
|
|
167
183
|
elif parent == "editor":
|
|
168
|
-
|
|
184
|
+
target = w.ui.config["preset"]["prompt"]
|
|
185
|
+
if target is not None:
|
|
186
|
+
self.paste_to_textarea(target, template.content)
|
|
169
187
|
|
|
170
188
|
def save_prompt(
|
|
171
189
|
self,
|
|
@@ -178,19 +196,21 @@ class Presets:
|
|
|
178
196
|
:param name: prompt name
|
|
179
197
|
:param force: force save
|
|
180
198
|
"""
|
|
181
|
-
|
|
199
|
+
w = self.window
|
|
200
|
+
content = w.ui.nodes['input'].toPlainText()
|
|
182
201
|
if content.strip() == "":
|
|
183
|
-
|
|
202
|
+
w.update_status("Prompt is empty!")
|
|
184
203
|
return
|
|
185
204
|
if not force:
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
205
|
+
dlg = w.ui.dialog['rename']
|
|
206
|
+
dlg.id = 'prompt.custom.new'
|
|
207
|
+
dlg.input.setText(content[:40] + "...")
|
|
208
|
+
dlg.current = ""
|
|
209
|
+
dlg.show()
|
|
190
210
|
return
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
211
|
+
w.ui.dialog['rename'].close()
|
|
212
|
+
w.core.prompt.custom.new(name, content)
|
|
213
|
+
w.update_status("Prompt saved")
|
|
194
214
|
|
|
195
215
|
def rename_prompt(
|
|
196
216
|
self,
|
|
@@ -205,19 +225,21 @@ class Presets:
|
|
|
205
225
|
:param name: new name
|
|
206
226
|
:param force: force rename
|
|
207
227
|
"""
|
|
208
|
-
|
|
228
|
+
w = self.window
|
|
229
|
+
item = w.core.prompt.custom.get_by_id(uuid)
|
|
209
230
|
if item is None:
|
|
210
231
|
return
|
|
211
232
|
if not force:
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
233
|
+
dlg = w.ui.dialog['rename']
|
|
234
|
+
dlg.id = 'prompt.custom.rename'
|
|
235
|
+
dlg.input.setText(item.name)
|
|
236
|
+
dlg.current = uuid
|
|
237
|
+
dlg.show()
|
|
216
238
|
return
|
|
217
|
-
|
|
239
|
+
w.ui.dialog['rename'].close()
|
|
218
240
|
item.name = name
|
|
219
|
-
|
|
220
|
-
|
|
241
|
+
w.core.prompt.custom.save()
|
|
242
|
+
w.update_status("Prompt renamed")
|
|
221
243
|
|
|
222
244
|
def delete_prompt(
|
|
223
245
|
self,
|
|
@@ -230,18 +252,20 @@ class Presets:
|
|
|
230
252
|
:param uuid: prompt ID
|
|
231
253
|
:param force: force delete
|
|
232
254
|
"""
|
|
233
|
-
|
|
255
|
+
w = self.window
|
|
256
|
+
item = w.core.prompt.custom.get_by_id(uuid)
|
|
234
257
|
if item is None:
|
|
235
258
|
return
|
|
236
259
|
if not force:
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
260
|
+
dlg = w.ui.dialog['confirm']
|
|
261
|
+
dlg.type = 'prompt.custom.delete'
|
|
262
|
+
dlg.id = uuid
|
|
263
|
+
dlg.message = "Are you sure you want to delete this prompt?"
|
|
264
|
+
dlg.show()
|
|
241
265
|
return
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
266
|
+
w.ui.dialog['confirm'].close()
|
|
267
|
+
w.core.prompt.custom.delete(uuid)
|
|
268
|
+
w.update_status("Prompt deleted")
|
|
245
269
|
|
|
246
270
|
def paste_to_textarea(
|
|
247
271
|
self,
|
|
@@ -254,20 +278,16 @@ class Presets:
|
|
|
254
278
|
:param textarea: textarea widget
|
|
255
279
|
:param text: text to paste
|
|
256
280
|
"""
|
|
257
|
-
separator = "\n"
|
|
258
281
|
prev_text = textarea.toPlainText()
|
|
259
282
|
cur = textarea.textCursor()
|
|
283
|
+
cur.beginEditBlock()
|
|
260
284
|
cur.movePosition(QTextCursor.End)
|
|
261
|
-
|
|
285
|
+
txt = str(text).strip()
|
|
262
286
|
if prev_text.strip() != "":
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
cur.insertText(head)
|
|
268
|
-
if sep:
|
|
269
|
-
cur.insertBlock()
|
|
270
|
-
cur.movePosition(QTextCursor.End)
|
|
287
|
+
cur.insertText("\n")
|
|
288
|
+
if txt:
|
|
289
|
+
cur.insertText(txt)
|
|
290
|
+
cur.endEditBlock()
|
|
271
291
|
textarea.setTextCursor(cur)
|
|
272
292
|
textarea.setFocus()
|
|
273
293
|
|
|
@@ -282,12 +302,13 @@ class Presets:
|
|
|
282
302
|
:param mode: mode name
|
|
283
303
|
:param preset_id: preset ID
|
|
284
304
|
"""
|
|
285
|
-
|
|
305
|
+
w = self.window
|
|
306
|
+
if not w.core.presets.has(mode, preset_id):
|
|
286
307
|
return False
|
|
287
|
-
|
|
288
|
-
if 'current_preset' not in
|
|
289
|
-
|
|
290
|
-
|
|
308
|
+
w.core.config.data['preset'] = preset_id
|
|
309
|
+
if 'current_preset' not in w.core.config.data:
|
|
310
|
+
w.core.config.data['current_preset'] = {}
|
|
311
|
+
w.core.config.data['current_preset'][mode] = preset_id
|
|
291
312
|
|
|
292
313
|
def set_by_idx(
|
|
293
314
|
self,
|
|
@@ -300,15 +321,12 @@ class Presets:
|
|
|
300
321
|
:param mode: mode name
|
|
301
322
|
:param idx: preset index
|
|
302
323
|
"""
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
self.window.core.config.data['current_preset'][mode] = preset_id
|
|
310
|
-
|
|
311
|
-
# select model
|
|
324
|
+
w = self.window
|
|
325
|
+
preset_id = w.core.presets.get_by_idx(idx, mode)
|
|
326
|
+
w.core.config.set("preset", preset_id)
|
|
327
|
+
if 'current_preset' not in w.core.config.data:
|
|
328
|
+
w.core.config.data['current_preset'] = {}
|
|
329
|
+
w.core.config.data['current_preset'][mode] = preset_id
|
|
312
330
|
self.select_model()
|
|
313
331
|
|
|
314
332
|
def select_current(self, no_scroll: bool = False):
|
|
@@ -317,97 +335,87 @@ class Presets:
|
|
|
317
335
|
|
|
318
336
|
:param no_scroll: do not scroll to current preset
|
|
319
337
|
"""
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
338
|
+
w = self.window
|
|
339
|
+
cfg = w.core.config
|
|
340
|
+
mode = cfg.get('mode')
|
|
341
|
+
preset_id = cfg.get('preset')
|
|
342
|
+
if not preset_id:
|
|
343
|
+
return
|
|
344
|
+
idx = w.core.presets.get_idx_by_id(mode, preset_id)
|
|
345
|
+
if idx is None or idx < 0:
|
|
346
|
+
return
|
|
347
|
+
if no_scroll:
|
|
348
|
+
w.ui.nodes['preset.presets'].store_scroll_position()
|
|
349
|
+
w.ui.nodes['preset.presets'].select_by_idx(idx)
|
|
350
|
+
if no_scroll:
|
|
351
|
+
w.ui.nodes['preset.presets'].restore_scroll_position()
|
|
352
|
+
editor_ctrl = w.controller.presets.editor
|
|
353
|
+
if editor_ctrl.opened and editor_ctrl.current != preset_id:
|
|
354
|
+
self.editor.init(preset_id)
|
|
334
355
|
|
|
335
356
|
def select_default(self):
|
|
336
357
|
"""Set default preset"""
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
if
|
|
341
|
-
mode =
|
|
342
|
-
|
|
343
|
-
current
|
|
344
|
-
|
|
345
|
-
current[mode] is not None and \
|
|
346
|
-
current[mode] != "" and \
|
|
347
|
-
current[mode] in self.window.core.presets.get_by_mode(mode):
|
|
348
|
-
self.window.core.config.set('preset', current[mode])
|
|
358
|
+
w = self.window
|
|
359
|
+
cfg = w.core.config
|
|
360
|
+
preset_id = cfg.get('preset')
|
|
361
|
+
if not preset_id:
|
|
362
|
+
mode = cfg.get('mode')
|
|
363
|
+
current = cfg.get('current_preset')
|
|
364
|
+
if mode in current and current[mode] and current[mode] in w.core.presets.get_by_mode(mode):
|
|
365
|
+
cfg.set('preset', current[mode])
|
|
349
366
|
else:
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
367
|
+
cfg.set('preset', w.core.presets.get_default(mode))
|
|
368
|
+
new_id = cfg.get('preset')
|
|
369
|
+
editor_ctrl = w.controller.presets.editor
|
|
370
|
+
if editor_ctrl.opened and editor_ctrl.current != new_id:
|
|
371
|
+
self.editor.init(new_id)
|
|
355
372
|
|
|
356
373
|
def update_data(self):
|
|
357
374
|
"""Update preset data"""
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
375
|
+
w = self.window
|
|
376
|
+
cfg = w.core.config
|
|
377
|
+
preset_id = cfg.get('preset')
|
|
378
|
+
if not preset_id:
|
|
379
|
+
self.reset()
|
|
380
|
+
w.controller.mode.reset_current()
|
|
362
381
|
return
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
self.
|
|
366
|
-
|
|
367
|
-
self.window.controller.mode.reset_current()
|
|
382
|
+
if preset_id not in w.core.presets.items:
|
|
383
|
+
cfg.set('preset', "")
|
|
384
|
+
self.reset()
|
|
385
|
+
w.controller.mode.reset_current()
|
|
368
386
|
return
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
self.window.core.config.set('prompt', preset.prompt)
|
|
378
|
-
self.window.core.config.set('ai_name', preset.ai_name)
|
|
379
|
-
self.window.core.config.set('user_name', preset.user_name)
|
|
380
|
-
self.window.core.config.set('agent.llama.provider', preset.agent_provider)
|
|
381
|
-
self.window.core.config.set('agent.openai.provider', preset.agent_provider_openai)
|
|
382
|
-
self.window.core.config.set('agent.llama.idx', preset.idx)
|
|
387
|
+
preset = w.core.presets.items[preset_id]
|
|
388
|
+
w.ui.nodes['preset.prompt'].setPlainText(preset.prompt)
|
|
389
|
+
w.core.config.set('prompt', preset.prompt)
|
|
390
|
+
w.core.config.set('ai_name', preset.ai_name)
|
|
391
|
+
w.core.config.set('user_name', preset.user_name)
|
|
392
|
+
w.core.config.set('agent.llama.provider', preset.agent_provider)
|
|
393
|
+
w.core.config.set('agent.openai.provider', preset.agent_provider_openai)
|
|
394
|
+
w.core.config.set('agent.llama.idx', preset.idx)
|
|
383
395
|
|
|
384
396
|
def update_current(self):
|
|
385
397
|
"""Update current mode, model and preset"""
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
preset_id =
|
|
390
|
-
if preset_id
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
self.window.core.config.set('ai_name', None)
|
|
404
|
-
self.window.core.config.set('temperature', 1.0)
|
|
405
|
-
|
|
406
|
-
# set default prompt if mode is chat
|
|
398
|
+
w = self.window
|
|
399
|
+
cfg = w.core.config
|
|
400
|
+
mode = cfg.get('mode')
|
|
401
|
+
preset_id = cfg.get('preset')
|
|
402
|
+
if preset_id and preset_id in w.core.presets.items:
|
|
403
|
+
preset = w.core.presets.items[preset_id]
|
|
404
|
+
cfg.set('user_name', preset.user_name)
|
|
405
|
+
cfg.set('ai_name', preset.ai_name)
|
|
406
|
+
cfg.set('prompt', preset.prompt)
|
|
407
|
+
cfg.set('temperature', preset.temperature)
|
|
408
|
+
cfg.set('agent.llama.provider', preset.agent_provider)
|
|
409
|
+
cfg.set('agent.openai.provider', preset.agent_provider_openai)
|
|
410
|
+
cfg.set('agent.llama.idx', preset.idx)
|
|
411
|
+
return
|
|
412
|
+
cfg.set('user_name', None)
|
|
413
|
+
cfg.set('ai_name', None)
|
|
414
|
+
cfg.set('temperature', 1.0)
|
|
407
415
|
if mode == MODE_CHAT:
|
|
408
|
-
|
|
416
|
+
cfg.set('prompt', w.core.prompt.get('default'))
|
|
409
417
|
else:
|
|
410
|
-
|
|
418
|
+
cfg.set('prompt', None)
|
|
411
419
|
|
|
412
420
|
def get_current_functions(self) -> Optional[List[Dict]]:
|
|
413
421
|
"""
|
|
@@ -415,40 +423,45 @@ class Presets:
|
|
|
415
423
|
|
|
416
424
|
:return: list of functions
|
|
417
425
|
"""
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
426
|
+
w = self.window
|
|
427
|
+
preset_id = w.core.config.get('preset')
|
|
428
|
+
if preset_id and preset_id in w.core.presets.items:
|
|
429
|
+
preset = w.core.presets.items[preset_id]
|
|
430
|
+
if preset.has_functions():
|
|
431
|
+
return preset.get_functions()
|
|
424
432
|
return None
|
|
425
433
|
|
|
426
434
|
def from_global(self):
|
|
427
435
|
"""Update current preset from global prompt"""
|
|
428
436
|
if self.locked:
|
|
429
437
|
return
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
438
|
+
w = self.window
|
|
439
|
+
preset_id = w.core.config.get('preset')
|
|
440
|
+
if preset_id and preset_id in w.core.presets.items:
|
|
441
|
+
preset = w.core.presets.items[preset_id]
|
|
442
|
+
preset.prompt = w.core.config.get('prompt')
|
|
443
|
+
w.core.presets.save(preset)
|
|
436
444
|
|
|
437
445
|
def select_model(self):
|
|
438
446
|
"""Select model by current preset"""
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
447
|
+
w = self.window
|
|
448
|
+
cfg = w.core.config
|
|
449
|
+
mode = cfg.get('mode')
|
|
450
|
+
preset_id = cfg.get('preset')
|
|
451
|
+
if not preset_id or preset_id not in w.core.presets.items:
|
|
452
|
+
return
|
|
453
|
+
preset = w.core.presets.items[preset_id]
|
|
454
|
+
model = preset.model
|
|
455
|
+
if not model or model == "_":
|
|
456
|
+
return
|
|
457
|
+
models = w.core.models
|
|
458
|
+
if models.has(model) and models.is_allowed(model, mode):
|
|
459
|
+
if cfg.get('model') == model:
|
|
460
|
+
return
|
|
461
|
+
cfg.set('model', model)
|
|
462
|
+
w.controller.model.set(mode, model)
|
|
463
|
+
w.controller.model.init_list()
|
|
464
|
+
w.controller.model.select_current()
|
|
452
465
|
|
|
453
466
|
def refresh(self, no_scroll: bool = False):
|
|
454
467
|
"""
|
|
@@ -456,35 +469,32 @@ class Presets:
|
|
|
456
469
|
|
|
457
470
|
:param no_scroll: do not scroll to current
|
|
458
471
|
"""
|
|
459
|
-
|
|
460
|
-
if mode == MODE_ASSISTANT:
|
|
472
|
+
w = self.window
|
|
473
|
+
if w.core.config.get('mode') == MODE_ASSISTANT:
|
|
461
474
|
return
|
|
462
|
-
|
|
463
475
|
if no_scroll:
|
|
464
|
-
|
|
465
|
-
self.select_default()
|
|
466
|
-
self.update_current()
|
|
467
|
-
self.update_data()
|
|
468
|
-
|
|
469
|
-
self.update_list()
|
|
470
|
-
self.select_current()
|
|
476
|
+
w.ui.nodes['preset.presets'].store_scroll_position()
|
|
477
|
+
self.select_default()
|
|
478
|
+
self.update_current()
|
|
479
|
+
self.update_data()
|
|
480
|
+
w.controller.mode.update_temperature()
|
|
481
|
+
self.update_list()
|
|
482
|
+
self.select_current()
|
|
471
483
|
if no_scroll:
|
|
472
|
-
|
|
484
|
+
w.ui.nodes['preset.presets'].restore_scroll_position()
|
|
473
485
|
self.on_changed()
|
|
474
486
|
|
|
475
|
-
|
|
476
487
|
def update_list(self):
|
|
477
488
|
"""Update presets list"""
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
489
|
+
w = self.window
|
|
490
|
+
mode = w.core.config.get('mode')
|
|
491
|
+
items = w.core.presets.get_by_mode(mode)
|
|
492
|
+
w.ui.toolbox.presets.update_presets(items)
|
|
481
493
|
self.clear_selected()
|
|
482
494
|
|
|
483
495
|
def reset(self):
|
|
484
496
|
"""Reset preset data"""
|
|
485
497
|
self.window.ui.nodes['preset.prompt'].setPlainText("")
|
|
486
|
-
# self.window.ui.nodes['preset.ai_name'].setText("")
|
|
487
|
-
# self.window.ui.nodes['preset.user_name'].setText("")
|
|
488
498
|
|
|
489
499
|
def make_filename(self, name: str) -> str:
|
|
490
500
|
"""
|
|
@@ -493,9 +503,7 @@ class Presets:
|
|
|
493
503
|
:param name: preset name
|
|
494
504
|
:return: preset filename
|
|
495
505
|
"""
|
|
496
|
-
|
|
497
|
-
filename = re.sub(r'[^a-zA-Z0-9_\-\.]', '_', filename)
|
|
498
|
-
return filename
|
|
506
|
+
return _FILENAME_SANITIZE_RE.sub('_', name.lower())
|
|
499
507
|
|
|
500
508
|
def duplicate(self, idx: Optional[int] = None):
|
|
501
509
|
"""
|
|
@@ -504,19 +512,17 @@ class Presets:
|
|
|
504
512
|
:param idx: preset index (row index)
|
|
505
513
|
"""
|
|
506
514
|
if idx is not None:
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
515
|
+
w = self.window
|
|
516
|
+
mode = w.core.config.get('mode')
|
|
517
|
+
preset = w.core.presets.get_by_idx(idx, mode)
|
|
518
|
+
if preset:
|
|
519
|
+
if preset in w.core.presets.items:
|
|
520
|
+
new_id = w.core.presets.duplicate(preset)
|
|
513
521
|
self.update_list()
|
|
514
522
|
self.refresh(no_scroll=True)
|
|
515
|
-
idx =
|
|
523
|
+
idx = w.core.presets.get_idx_by_id(mode, new_id)
|
|
516
524
|
self.editor.edit(idx)
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
525
|
+
w.update_status(trans('status.preset.duplicated'))
|
|
520
526
|
|
|
521
527
|
def enable(self, idx: Optional[int] = None):
|
|
522
528
|
"""
|
|
@@ -525,12 +531,12 @@ class Presets:
|
|
|
525
531
|
:param idx: preset index (row index)
|
|
526
532
|
"""
|
|
527
533
|
if idx is not None:
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
+
w = self.window
|
|
535
|
+
mode = w.core.config.get('mode')
|
|
536
|
+
preset_id = w.core.presets.get_by_idx(idx, mode)
|
|
537
|
+
if preset_id and preset_id in w.core.presets.items:
|
|
538
|
+
w.core.presets.enable(preset_id)
|
|
539
|
+
QTimer.singleShot(100, self.refresh)
|
|
534
540
|
|
|
535
541
|
def disable(self, idx: Optional[int] = None):
|
|
536
542
|
"""
|
|
@@ -539,12 +545,12 @@ class Presets:
|
|
|
539
545
|
:param idx: preset index (row index)
|
|
540
546
|
"""
|
|
541
547
|
if idx is not None:
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
+
w = self.window
|
|
549
|
+
mode = w.core.config.get('mode')
|
|
550
|
+
preset_id = w.core.presets.get_by_idx(idx, mode)
|
|
551
|
+
if preset_id and preset_id in w.core.presets.items:
|
|
552
|
+
w.core.presets.disable(preset_id)
|
|
553
|
+
QTimer.singleShot(100, self.refresh)
|
|
548
554
|
|
|
549
555
|
def clear(self, force: bool = False):
|
|
550
556
|
"""
|
|
@@ -552,35 +558,30 @@ class Presets:
|
|
|
552
558
|
|
|
553
559
|
:param force: force clear data
|
|
554
560
|
"""
|
|
555
|
-
|
|
556
|
-
|
|
561
|
+
w = self.window
|
|
562
|
+
preset = w.core.config.get('preset')
|
|
557
563
|
if not force:
|
|
558
|
-
|
|
564
|
+
w.ui.dialogs.confirm(
|
|
559
565
|
type='preset_clear',
|
|
560
566
|
id='',
|
|
561
567
|
msg=trans('confirm.preset.clear'),
|
|
562
568
|
)
|
|
563
569
|
return
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
self.window.update_status(trans('status.preset.cleared'))
|
|
579
|
-
|
|
580
|
-
# reload assistant default instructions
|
|
581
|
-
mode = self.window.core.config.get('mode')
|
|
570
|
+
w.core.config.set('prompt', "")
|
|
571
|
+
w.core.config.set('ai_name', "")
|
|
572
|
+
w.core.config.set('user_name', "")
|
|
573
|
+
w.core.config.set('temperature', 1.0)
|
|
574
|
+
if preset and preset in w.core.presets.items:
|
|
575
|
+
p = w.core.presets.items[preset]
|
|
576
|
+
p.ai_name = ""
|
|
577
|
+
p.user_name = ""
|
|
578
|
+
p.prompt = ""
|
|
579
|
+
p.temperature = 1.0
|
|
580
|
+
self.refresh()
|
|
581
|
+
w.update_status(trans('status.preset.cleared'))
|
|
582
|
+
mode = w.core.config.get('mode')
|
|
582
583
|
if mode == MODE_ASSISTANT:
|
|
583
|
-
|
|
584
|
+
w.core.assistants.load()
|
|
584
585
|
|
|
585
586
|
def delete(
|
|
586
587
|
self,
|
|
@@ -594,25 +595,23 @@ class Presets:
|
|
|
594
595
|
:param force: force delete without confirmation
|
|
595
596
|
"""
|
|
596
597
|
if idx is not None:
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
self.refresh(no_scroll=True)
|
|
615
|
-
self.window.update_status(trans('status.preset.deleted'))
|
|
598
|
+
w = self.window
|
|
599
|
+
mode = w.core.config.get('mode')
|
|
600
|
+
preset_id = w.core.presets.get_by_idx(idx, mode)
|
|
601
|
+
if preset_id and preset_id in w.core.presets.items:
|
|
602
|
+
if not force:
|
|
603
|
+
w.ui.dialogs.confirm(
|
|
604
|
+
type='preset_delete',
|
|
605
|
+
id=idx,
|
|
606
|
+
msg=trans('confirm.preset.delete'),
|
|
607
|
+
)
|
|
608
|
+
return
|
|
609
|
+
if preset_id == w.core.config.get('preset'):
|
|
610
|
+
w.core.config.set('preset', None)
|
|
611
|
+
w.ui.nodes['preset.prompt'].setPlainText("")
|
|
612
|
+
w.core.presets.remove(preset_id, True)
|
|
613
|
+
self.refresh(no_scroll=True)
|
|
614
|
+
w.update_status(trans('status.preset.deleted'))
|
|
616
615
|
|
|
617
616
|
def restore(self, force: bool = False):
|
|
618
617
|
"""
|
|
@@ -620,17 +619,18 @@ class Presets:
|
|
|
620
619
|
|
|
621
620
|
:param force: force restore data
|
|
622
621
|
"""
|
|
622
|
+
w = self.window
|
|
623
623
|
if not force:
|
|
624
|
-
|
|
624
|
+
w.ui.dialogs.confirm(
|
|
625
625
|
type='preset_restore',
|
|
626
626
|
id='',
|
|
627
627
|
msg=trans('confirm.preset.restore'),
|
|
628
628
|
)
|
|
629
629
|
return
|
|
630
|
-
mode =
|
|
630
|
+
mode = w.core.config.get('mode')
|
|
631
631
|
if mode == MODE_AGENT:
|
|
632
|
-
mode = MODE_EXPERT
|
|
633
|
-
|
|
632
|
+
mode = MODE_EXPERT
|
|
633
|
+
w.core.presets.restore(mode)
|
|
634
634
|
self.refresh()
|
|
635
635
|
|
|
636
636
|
def is_current(self, idx: Optional[int] = None) -> bool:
|
|
@@ -641,11 +641,12 @@ class Presets:
|
|
|
641
641
|
:return: True if current
|
|
642
642
|
"""
|
|
643
643
|
if idx is not None:
|
|
644
|
-
|
|
644
|
+
w = self.window
|
|
645
|
+
mode = w.core.config.get('mode')
|
|
645
646
|
if mode == MODE_AGENT:
|
|
646
|
-
mode = MODE_EXPERT
|
|
647
|
-
preset_id =
|
|
648
|
-
if preset_id
|
|
647
|
+
mode = MODE_EXPERT
|
|
648
|
+
preset_id = w.core.presets.get_by_idx(idx, mode)
|
|
649
|
+
if preset_id:
|
|
649
650
|
if preset_id == "current." + mode:
|
|
650
651
|
return True
|
|
651
652
|
return False
|
|
@@ -657,8 +658,7 @@ class Presets:
|
|
|
657
658
|
:param value: filename
|
|
658
659
|
:return: sanitized filename
|
|
659
660
|
"""
|
|
660
|
-
|
|
661
|
-
return re.sub(r'[^\w\s\-\.]', '', value)
|
|
661
|
+
return _VALIDATE_FILENAME_RE.sub('', value)
|
|
662
662
|
|
|
663
663
|
def preset_change_locked(self) -> bool:
|
|
664
664
|
"""
|
|
@@ -666,12 +666,7 @@ class Presets:
|
|
|
666
666
|
|
|
667
667
|
:return: True if locked
|
|
668
668
|
"""
|
|
669
|
-
|
|
670
|
-
# return True
|
|
671
|
-
mode = self.window.core.config.get('mode')
|
|
672
|
-
if mode == MODE_ASSISTANT:
|
|
673
|
-
return True
|
|
674
|
-
return False
|
|
669
|
+
return self.window.core.config.get('mode') == MODE_ASSISTANT
|
|
675
670
|
|
|
676
671
|
def reload(self):
|
|
677
672
|
"""Reload presets"""
|
|
@@ -709,4 +704,4 @@ class Presets:
|
|
|
709
704
|
|
|
710
705
|
def clear_selected(self):
|
|
711
706
|
"""Clear selected list"""
|
|
712
|
-
self.selected = []
|
|
707
|
+
self.selected = []
|