pygpt-net 2.6.55__py3-none-any.whl → 2.6.57__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 +12 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/app.py +26 -22
- pygpt_net/config.py +44 -0
- pygpt_net/controller/audio/audio.py +0 -0
- pygpt_net/controller/calendar/calendar.py +0 -0
- pygpt_net/controller/calendar/note.py +0 -0
- pygpt_net/controller/chat/chat.py +0 -0
- pygpt_net/controller/chat/handler/openai_stream.py +2 -1
- pygpt_net/controller/chat/handler/worker.py +0 -0
- pygpt_net/controller/chat/remote_tools.py +5 -3
- pygpt_net/controller/chat/render.py +0 -0
- pygpt_net/controller/chat/text.py +0 -0
- pygpt_net/controller/ctx/common.py +0 -0
- pygpt_net/controller/debug/debug.py +26 -2
- pygpt_net/controller/debug/fixtures.py +1 -1
- pygpt_net/controller/dialogs/confirm.py +15 -1
- pygpt_net/controller/dialogs/debug.py +2 -0
- pygpt_net/controller/lang/mapping.py +0 -0
- pygpt_net/controller/launcher/launcher.py +0 -0
- pygpt_net/controller/mode/mode.py +0 -0
- pygpt_net/controller/presets/presets.py +0 -0
- pygpt_net/controller/realtime/realtime.py +0 -0
- pygpt_net/controller/theme/theme.py +0 -0
- pygpt_net/controller/ui/mode.py +5 -3
- pygpt_net/controller/ui/tabs.py +0 -0
- pygpt_net/core/agents/agents.py +3 -1
- pygpt_net/core/agents/custom.py +150 -0
- pygpt_net/core/agents/provider.py +0 -0
- pygpt_net/core/builder/__init__.py +12 -0
- pygpt_net/core/builder/graph.py +478 -0
- pygpt_net/core/calendar/calendar.py +0 -0
- pygpt_net/core/ctx/ctx.py +0 -0
- pygpt_net/core/ctx/output.py +0 -0
- pygpt_net/core/debug/agent.py +0 -0
- pygpt_net/core/debug/agent_builder.py +29 -0
- pygpt_net/core/debug/console/console.py +0 -0
- pygpt_net/core/debug/db.py +0 -0
- pygpt_net/core/debug/debug.py +0 -0
- pygpt_net/core/debug/events.py +0 -0
- pygpt_net/core/debug/indexes.py +0 -0
- pygpt_net/core/debug/kernel.py +0 -0
- pygpt_net/core/debug/tabs.py +0 -0
- pygpt_net/core/filesystem/filesystem.py +0 -0
- pygpt_net/core/fixtures/__init__ +0 -0
- pygpt_net/core/fixtures/stream/__init__.py +0 -0
- pygpt_net/core/fixtures/stream/generator.py +0 -0
- pygpt_net/core/models/models.py +2 -1
- pygpt_net/core/plugins/plugins.py +60 -0
- pygpt_net/core/render/plain/pid.py +0 -0
- pygpt_net/core/render/plain/renderer.py +26 -4
- pygpt_net/core/render/web/body.py +46 -4
- pygpt_net/core/render/web/debug.py +0 -0
- pygpt_net/core/render/web/helpers.py +0 -0
- pygpt_net/core/render/web/pid.py +0 -0
- pygpt_net/core/render/web/renderer.py +15 -20
- pygpt_net/core/tabs/tab.py +0 -0
- pygpt_net/core/tabs/tabs.py +0 -0
- pygpt_net/core/text/utils.py +0 -0
- pygpt_net/css.qrc +0 -0
- pygpt_net/css_rc.py +0 -0
- pygpt_net/data/config/config.json +8 -7
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/config/settings.json +14 -0
- pygpt_net/data/css/web-blocks.css +9 -0
- pygpt_net/data/css/web-blocks.dark.css +6 -0
- pygpt_net/data/css/web-blocks.darkest.css +6 -0
- pygpt_net/data/css/web-chatgpt.css +14 -6
- pygpt_net/data/css/web-chatgpt.dark.css +6 -0
- pygpt_net/data/css/web-chatgpt.darkest.css +6 -0
- pygpt_net/data/css/web-chatgpt.light.css +6 -0
- pygpt_net/data/css/web-chatgpt_wide.css +14 -6
- pygpt_net/data/css/web-chatgpt_wide.dark.css +6 -0
- pygpt_net/data/css/web-chatgpt_wide.darkest.css +6 -0
- pygpt_net/data/css/web-chatgpt_wide.light.css +6 -0
- pygpt_net/data/fixtures/fake_stream.txt +14 -1
- pygpt_net/data/icons/case.svg +0 -0
- pygpt_net/data/icons/chat1.svg +0 -0
- pygpt_net/data/icons/chat2.svg +0 -0
- pygpt_net/data/icons/chat3.svg +0 -0
- pygpt_net/data/icons/chat4.svg +0 -0
- pygpt_net/data/icons/fit.svg +0 -0
- pygpt_net/data/icons/note1.svg +0 -0
- pygpt_net/data/icons/note2.svg +0 -0
- pygpt_net/data/icons/note3.svg +0 -0
- pygpt_net/data/icons/stt.svg +0 -0
- pygpt_net/data/icons/translate.svg +0 -0
- pygpt_net/data/icons/tts.svg +0 -0
- pygpt_net/data/icons/url.svg +0 -0
- pygpt_net/data/icons/vision.svg +0 -0
- pygpt_net/data/icons/web_off.svg +0 -0
- pygpt_net/data/icons/web_on.svg +0 -0
- pygpt_net/data/js/app/async.js +166 -0
- pygpt_net/data/js/app/bridge.js +88 -0
- pygpt_net/data/js/app/common.js +212 -0
- pygpt_net/data/js/app/config.js +223 -0
- pygpt_net/data/js/app/custom.js +961 -0
- pygpt_net/data/js/app/data.js +84 -0
- pygpt_net/data/js/app/dom.js +322 -0
- pygpt_net/data/js/app/events.js +400 -0
- pygpt_net/data/js/app/highlight.js +542 -0
- pygpt_net/data/js/app/logger.js +305 -0
- pygpt_net/data/js/app/markdown.js +1137 -0
- pygpt_net/data/js/app/math.js +167 -0
- pygpt_net/data/js/app/nodes.js +395 -0
- pygpt_net/data/js/app/queue.js +260 -0
- pygpt_net/data/js/app/raf.js +250 -0
- pygpt_net/data/js/app/runtime.js +582 -0
- pygpt_net/data/js/app/scroll.js +433 -0
- pygpt_net/data/js/app/stream.js +2708 -0
- pygpt_net/data/js/app/template.js +287 -0
- pygpt_net/data/js/app/tool.js +87 -0
- pygpt_net/data/js/app/ui.js +86 -0
- pygpt_net/data/js/app/user.js +380 -0
- pygpt_net/data/js/app/utils.js +64 -0
- pygpt_net/data/js/app.min.js +880 -0
- pygpt_net/data/js/markdown-it/markdown-it-katex.min.js +1 -1
- pygpt_net/data/js/markdown-it/markdown-it.min.js +0 -0
- pygpt_net/data/locale/locale.de.ini +3 -1
- pygpt_net/data/locale/locale.en.ini +8 -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 +3 -1
- pygpt_net/data/locale/locale.zh.ini +2 -0
- pygpt_net/data/locale/plugin.osm.en.ini +24 -24
- pygpt_net/data/locale/plugin.wolfram.en.ini +9 -9
- pygpt_net/fonts.qrc +0 -0
- pygpt_net/fonts_rc.py +0 -0
- pygpt_net/icons.qrc +0 -0
- pygpt_net/icons_rc.py +0 -0
- pygpt_net/item/agent.py +62 -0
- pygpt_net/item/builder_layout.py +62 -0
- pygpt_net/js.qrc +24 -1
- pygpt_net/js_rc.py +51394 -33687
- pygpt_net/plugin/base/worker.py +0 -0
- pygpt_net/plugin/cmd_web/config.py +17 -17
- pygpt_net/plugin/cmd_web/worker.py +325 -171
- pygpt_net/plugin/mcp/__init__.py +0 -0
- pygpt_net/plugin/mcp/config.py +0 -0
- pygpt_net/plugin/mcp/plugin.py +0 -0
- pygpt_net/plugin/mcp/worker.py +0 -0
- pygpt_net/plugin/osm/__init__.py +0 -0
- pygpt_net/plugin/osm/config.py +0 -0
- pygpt_net/plugin/osm/plugin.py +0 -0
- pygpt_net/plugin/osm/worker.py +0 -0
- pygpt_net/plugin/wolfram/__init__.py +0 -0
- pygpt_net/plugin/wolfram/config.py +0 -0
- pygpt_net/plugin/wolfram/plugin.py +0 -0
- pygpt_net/plugin/wolfram/worker.py +0 -0
- pygpt_net/provider/api/anthropic/tools.py +0 -0
- pygpt_net/provider/api/google/__init__.py +0 -0
- pygpt_net/provider/api/google/video.py +0 -0
- pygpt_net/provider/api/openai/agents/experts.py +0 -0
- pygpt_net/provider/api/openai/agents/remote_tools.py +0 -0
- pygpt_net/provider/api/openai/remote_tools.py +0 -0
- pygpt_net/provider/api/openai/responses.py +0 -0
- pygpt_net/provider/api/x_ai/__init__.py +2 -0
- pygpt_net/provider/api/x_ai/remote.py +0 -0
- pygpt_net/provider/core/agent/__init__.py +10 -0
- pygpt_net/provider/core/agent/base.py +51 -0
- pygpt_net/provider/core/agent/json_file.py +200 -0
- pygpt_net/provider/core/config/patch.py +33 -0
- pygpt_net/provider/core/config/patches/__init__.py +0 -0
- pygpt_net/provider/core/config/patches/patch_before_2_6_42.py +1 -0
- pygpt_net/provider/core/ctx/db_sqlite/storage.py +0 -0
- pygpt_net/provider/core/model/patches/__init__.py +0 -0
- pygpt_net/provider/core/model/patches/patch_before_2_6_42.py +0 -0
- pygpt_net/provider/core/preset/patch.py +0 -0
- pygpt_net/provider/core/preset/patches/__init__.py +0 -0
- pygpt_net/provider/core/preset/patches/patch_before_2_6_42.py +0 -0
- pygpt_net/provider/llms/anthropic.py +4 -0
- pygpt_net/provider/llms/base.py +2 -0
- pygpt_net/provider/llms/deepseek_api.py +2 -0
- pygpt_net/provider/llms/google.py +2 -0
- pygpt_net/provider/llms/hugging_face_api.py +4 -0
- pygpt_net/provider/llms/hugging_face_embedding.py +0 -0
- pygpt_net/provider/llms/hugging_face_router.py +2 -0
- pygpt_net/provider/llms/local.py +0 -0
- pygpt_net/provider/llms/mistral.py +4 -0
- pygpt_net/provider/llms/open_router.py +0 -0
- pygpt_net/provider/llms/perplexity.py +2 -0
- pygpt_net/provider/llms/utils.py +0 -0
- pygpt_net/provider/llms/voyage.py +0 -0
- pygpt_net/provider/llms/x_ai.py +2 -0
- pygpt_net/tools/agent_builder/__init__.py +12 -0
- pygpt_net/tools/agent_builder/tool.py +292 -0
- pygpt_net/tools/agent_builder/ui/__init__.py +0 -0
- pygpt_net/tools/agent_builder/ui/dialogs.py +152 -0
- pygpt_net/tools/agent_builder/ui/list.py +228 -0
- pygpt_net/tools/code_interpreter/ui/html.py +0 -0
- pygpt_net/tools/code_interpreter/ui/widgets.py +0 -0
- pygpt_net/tools/html_canvas/tool.py +23 -6
- pygpt_net/tools/html_canvas/ui/widgets.py +224 -2
- pygpt_net/ui/layout/chat/chat.py +0 -0
- pygpt_net/ui/layout/chat/output.py +5 -5
- pygpt_net/ui/main.py +10 -9
- pygpt_net/ui/menu/debug.py +39 -1
- pygpt_net/ui/widget/builder/__init__.py +12 -0
- pygpt_net/ui/widget/builder/editor.py +2001 -0
- pygpt_net/ui/widget/dialog/base.py +4 -1
- pygpt_net/ui/widget/draw/painter.py +0 -0
- pygpt_net/ui/widget/element/labels.py +9 -4
- pygpt_net/ui/widget/lists/db.py +0 -0
- pygpt_net/ui/widget/lists/debug.py +0 -0
- pygpt_net/ui/widget/tabs/body.py +0 -0
- pygpt_net/ui/widget/textarea/html.py +1 -0
- pygpt_net/ui/widget/textarea/input.py +28 -10
- pygpt_net/ui/widget/textarea/output.py +21 -1
- pygpt_net/ui/widget/textarea/web.py +31 -3
- pygpt_net/utils.py +40 -0
- {pygpt_net-2.6.55.dist-info → pygpt_net-2.6.57.dist-info}/METADATA +16 -2
- {pygpt_net-2.6.55.dist-info → pygpt_net-2.6.57.dist-info}/RECORD +116 -77
- pygpt_net/data/js/app.js +0 -5869
- {pygpt_net-2.6.55.dist-info → pygpt_net-2.6.57.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.55.dist-info → pygpt_net-2.6.57.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.55.dist-info → pygpt_net-2.6.57.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.
|
|
9
|
+
# Updated Date: 2025.09.22 15:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import json
|
|
@@ -32,6 +32,73 @@ class Worker(BaseWorker):
|
|
|
32
32
|
self.ctx = None
|
|
33
33
|
self.msg = None
|
|
34
34
|
|
|
35
|
+
# --- helpers ---
|
|
36
|
+
|
|
37
|
+
def _to_list(self, value):
|
|
38
|
+
"""Normalize any value to a flat list of strings."""
|
|
39
|
+
# Accept list-like values
|
|
40
|
+
if value is None:
|
|
41
|
+
return []
|
|
42
|
+
if isinstance(value, list):
|
|
43
|
+
result = []
|
|
44
|
+
for v in value:
|
|
45
|
+
result.extend(self._to_list(v))
|
|
46
|
+
return result
|
|
47
|
+
if isinstance(value, (tuple, set)):
|
|
48
|
+
result = []
|
|
49
|
+
for v in value:
|
|
50
|
+
result.extend(self._to_list(v))
|
|
51
|
+
return result
|
|
52
|
+
# Accept string (also split by whitespace/newlines to support multiple URLs pasted together)
|
|
53
|
+
if isinstance(value, str):
|
|
54
|
+
# Split by any whitespace; do not split by comma/semicolon to avoid breaking data: URLs etc.
|
|
55
|
+
parts = value.split()
|
|
56
|
+
return [p.strip() for p in parts if p and isinstance(p, str)]
|
|
57
|
+
# Fallback: try to cast to str
|
|
58
|
+
try:
|
|
59
|
+
s = str(value).strip()
|
|
60
|
+
return [s] if s else []
|
|
61
|
+
except Exception:
|
|
62
|
+
return []
|
|
63
|
+
|
|
64
|
+
def _extract_urls(self, item: dict, allow_args: bool = True) -> list:
|
|
65
|
+
"""Extract and normalize URLs from item (supports url, urls; also from args if present)."""
|
|
66
|
+
urls = []
|
|
67
|
+
try:
|
|
68
|
+
if self.has_param(item, "urls"):
|
|
69
|
+
urls.extend(self._to_list(self.get_param(item, "urls")))
|
|
70
|
+
if self.has_param(item, "url"):
|
|
71
|
+
urls.extend(self._to_list(self.get_param(item, "url")))
|
|
72
|
+
if allow_args and self.has_param(item, "args"):
|
|
73
|
+
args = self.get_param(item, "args")
|
|
74
|
+
if isinstance(args, dict):
|
|
75
|
+
if "urls" in args:
|
|
76
|
+
urls.extend(self._to_list(args.get("urls")))
|
|
77
|
+
if "url" in args:
|
|
78
|
+
urls.extend(self._to_list(args.get("url")))
|
|
79
|
+
except Exception:
|
|
80
|
+
pass
|
|
81
|
+
|
|
82
|
+
# Deduplicate and cleanup
|
|
83
|
+
cleaned = []
|
|
84
|
+
seen = set()
|
|
85
|
+
for u in urls:
|
|
86
|
+
if not u:
|
|
87
|
+
continue
|
|
88
|
+
if not isinstance(u, str):
|
|
89
|
+
try:
|
|
90
|
+
u = str(u)
|
|
91
|
+
except Exception:
|
|
92
|
+
continue
|
|
93
|
+
u = u.strip()
|
|
94
|
+
if not u:
|
|
95
|
+
continue
|
|
96
|
+
if u in seen:
|
|
97
|
+
continue
|
|
98
|
+
seen.add(u)
|
|
99
|
+
cleaned.append(u)
|
|
100
|
+
return cleaned
|
|
101
|
+
|
|
35
102
|
@Slot()
|
|
36
103
|
def run(self):
|
|
37
104
|
try:
|
|
@@ -111,7 +178,7 @@ class Worker(BaseWorker):
|
|
|
111
178
|
page,
|
|
112
179
|
prompt,
|
|
113
180
|
)
|
|
114
|
-
self.msg = "Web search finished: '{}'"
|
|
181
|
+
self.msg = f"Web search finished: '{query}'"
|
|
115
182
|
result = {
|
|
116
183
|
'query': query,
|
|
117
184
|
'content': content,
|
|
@@ -123,7 +190,8 @@ class Worker(BaseWorker):
|
|
|
123
190
|
self.ctx.urls_before.append(url)
|
|
124
191
|
if img:
|
|
125
192
|
result["thumb_img"] = img
|
|
126
|
-
self.ctx.images_before
|
|
193
|
+
if img not in self.ctx.images_before:
|
|
194
|
+
self.ctx.images_before.append(img)
|
|
127
195
|
|
|
128
196
|
self.ctx.save_reply = True # leave links in context
|
|
129
197
|
return self.make_response(item, result)
|
|
@@ -138,28 +206,43 @@ class Worker(BaseWorker):
|
|
|
138
206
|
prompt = None
|
|
139
207
|
if self.has_param(item, "summarize_prompt"):
|
|
140
208
|
prompt = self.get_param(item, "summarize_prompt")
|
|
141
|
-
url = self.get_param(item, "url", "")
|
|
142
209
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
210
|
+
# Get URLs with robust fallback (urls/url; also supports lists)
|
|
211
|
+
urls = self._extract_urls(item, allow_args=False)
|
|
212
|
+
|
|
213
|
+
results = []
|
|
214
|
+
context = ""
|
|
215
|
+
for url in urls:
|
|
216
|
+
try:
|
|
217
|
+
self.msg = f"Opening Web URL: '{url}'"
|
|
218
|
+
content, url_resolved, img = self.websearch.open_url(
|
|
219
|
+
url,
|
|
220
|
+
prompt,
|
|
221
|
+
)
|
|
222
|
+
# Always include the URL the result refers to
|
|
223
|
+
result = {
|
|
224
|
+
'url': url_resolved or url,
|
|
225
|
+
'content': content,
|
|
226
|
+
}
|
|
227
|
+
context += f"From: {url_resolved or url} + :\n--------------------------------\n{content}"
|
|
228
|
+
if url_resolved or url:
|
|
229
|
+
self.ctx.urls_before.append(url_resolved or url)
|
|
230
|
+
if img:
|
|
231
|
+
result["thumb_img"] = img
|
|
232
|
+
if img not in self.ctx.images_before:
|
|
233
|
+
self.ctx.images_before.append(img)
|
|
234
|
+
results.append(result)
|
|
235
|
+
except Exception as e:
|
|
236
|
+
results.append({
|
|
237
|
+
'url': url,
|
|
238
|
+
'content': f"Error: {e}",
|
|
239
|
+
})
|
|
240
|
+
self.log(f"Error opening URL '{url}': {e}")
|
|
158
241
|
|
|
159
242
|
extra = {
|
|
160
243
|
"context": context,
|
|
161
244
|
}
|
|
162
|
-
return self.make_response(item,
|
|
245
|
+
return self.make_response(item, results, extra=extra)
|
|
163
246
|
|
|
164
247
|
def cmd_web_url_raw(self, item: dict) -> dict:
|
|
165
248
|
"""
|
|
@@ -168,26 +251,40 @@ class Worker(BaseWorker):
|
|
|
168
251
|
:param item: command item
|
|
169
252
|
:return: response item
|
|
170
253
|
"""
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
254
|
+
# Get URLs with robust fallback (urls/url; also supports lists)
|
|
255
|
+
urls = self._extract_urls(item, allow_args=False)
|
|
256
|
+
|
|
257
|
+
results = []
|
|
258
|
+
context = ""
|
|
259
|
+
for url in urls:
|
|
260
|
+
try:
|
|
261
|
+
self.msg = f"Opening Web URL: '{url}'"
|
|
262
|
+
content, url_resolved, img = self.websearch.open_url_raw(
|
|
263
|
+
url,
|
|
264
|
+
)
|
|
265
|
+
result = {
|
|
266
|
+
'url': url_resolved or url,
|
|
267
|
+
'content': content,
|
|
268
|
+
}
|
|
269
|
+
context += f"From: {url_resolved or url} + :\n--------------------------------\n{content}"
|
|
270
|
+
if url_resolved or url:
|
|
271
|
+
self.ctx.urls_before.append(url_resolved or url)
|
|
272
|
+
if img:
|
|
273
|
+
result["thumb_img"] = img
|
|
274
|
+
if img not in self.ctx.images_before:
|
|
275
|
+
self.ctx.images_before.append(img)
|
|
276
|
+
results.append(result)
|
|
277
|
+
except Exception as e:
|
|
278
|
+
results.append({
|
|
279
|
+
'url': url,
|
|
280
|
+
'content': f"Error: {e}",
|
|
281
|
+
})
|
|
282
|
+
self.log(f"Error opening URL '{url}': {e}")
|
|
186
283
|
|
|
187
284
|
extra = {
|
|
188
285
|
"context": context,
|
|
189
286
|
}
|
|
190
|
-
return self.make_response(item,
|
|
287
|
+
return self.make_response(item, results, extra=extra)
|
|
191
288
|
|
|
192
289
|
def cmd_web_urls(self, item: dict) -> dict:
|
|
193
290
|
"""
|
|
@@ -216,7 +313,7 @@ class Worker(BaseWorker):
|
|
|
216
313
|
num,
|
|
217
314
|
offset,
|
|
218
315
|
)
|
|
219
|
-
self.msg = "Web search finished: '{}'"
|
|
316
|
+
self.msg = f"Web search finished: '{query}'"
|
|
220
317
|
result = {
|
|
221
318
|
'query': query,
|
|
222
319
|
'urls': json.dumps(urls),
|
|
@@ -226,7 +323,8 @@ class Worker(BaseWorker):
|
|
|
226
323
|
}
|
|
227
324
|
if urls:
|
|
228
325
|
for url in urls:
|
|
229
|
-
self.ctx.urls_before
|
|
326
|
+
if url not in self.ctx.urls_before:
|
|
327
|
+
self.ctx.urls_before.append(url)
|
|
230
328
|
|
|
231
329
|
return self.make_response(item, result)
|
|
232
330
|
|
|
@@ -245,39 +343,38 @@ class Worker(BaseWorker):
|
|
|
245
343
|
if self.has_param(item, "args"):
|
|
246
344
|
args = self.get_param(item, "args")
|
|
247
345
|
|
|
248
|
-
url
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
if "url" in args:
|
|
252
|
-
url = args["url"] # override from args
|
|
253
|
-
|
|
254
|
-
if not url:
|
|
346
|
+
# Extract URLs with fallback: url(s) from item and args
|
|
347
|
+
urls = self._extract_urls(item, allow_args=True)
|
|
348
|
+
if not urls:
|
|
255
349
|
return self.make_response(item, "No URL provided")
|
|
256
350
|
|
|
257
|
-
self.msg = "Indexing URL: '{}'".format(url)
|
|
258
351
|
idx_name = self.plugin.get_option_value("idx")
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
# index URL via Llama-index
|
|
262
|
-
num, errors = self.plugin.window.core.idx.index_urls(
|
|
263
|
-
idx=idx_name,
|
|
264
|
-
urls=[url],
|
|
265
|
-
type=type,
|
|
266
|
-
extra_args=args,
|
|
267
|
-
)
|
|
268
|
-
result = {
|
|
269
|
-
'url': url,
|
|
270
|
-
'num_indexed': num,
|
|
271
|
-
'index': idx_name,
|
|
272
|
-
'errors': errors,
|
|
273
|
-
}
|
|
274
|
-
if url and (url.startswith("http://") or url.startswith("https://")):
|
|
275
|
-
self.ctx.urls_before.append(url)
|
|
352
|
+
results = []
|
|
276
353
|
|
|
277
|
-
|
|
278
|
-
"
|
|
279
|
-
|
|
280
|
-
|
|
354
|
+
for url in urls:
|
|
355
|
+
self.msg = f"Indexing URL: '{url}'"
|
|
356
|
+
self.status(f"Please wait... indexing: {url}...")
|
|
357
|
+
|
|
358
|
+
# index URL via Llama-index per URL to keep per-URL result
|
|
359
|
+
num, errors = self.plugin.window.core.idx.index_urls(
|
|
360
|
+
idx=idx_name,
|
|
361
|
+
urls=[url],
|
|
362
|
+
type=type,
|
|
363
|
+
extra_args=args,
|
|
364
|
+
)
|
|
365
|
+
result = {
|
|
366
|
+
'url': url,
|
|
367
|
+
'num_indexed': num,
|
|
368
|
+
'index': idx_name,
|
|
369
|
+
'errors': errors,
|
|
370
|
+
}
|
|
371
|
+
if url and (url.startswith("http://") or url.startswith("https://")):
|
|
372
|
+
if url not in self.ctx.urls_before:
|
|
373
|
+
self.ctx.urls_before.append(url)
|
|
374
|
+
results.append(result)
|
|
375
|
+
|
|
376
|
+
# Return list of results with URLs included
|
|
377
|
+
return self.make_response(item, results)
|
|
281
378
|
|
|
282
379
|
def cmd_web_index_query(self, item: dict) -> dict:
|
|
283
380
|
"""
|
|
@@ -295,69 +392,85 @@ class Worker(BaseWorker):
|
|
|
295
392
|
if self.has_param(item, "args"):
|
|
296
393
|
args = self.get_param(item, "args")
|
|
297
394
|
|
|
298
|
-
url
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
if isinstance(args, dict) and "url" in args:
|
|
302
|
-
url = args["url"] # override from args
|
|
303
|
-
|
|
304
|
-
if not url:
|
|
395
|
+
# Extract URLs with fallback: url(s) from item and args
|
|
396
|
+
urls = self._extract_urls(item, allow_args=True)
|
|
397
|
+
if not urls:
|
|
305
398
|
result = "No URL provided"
|
|
306
399
|
return self.make_response(item, result)
|
|
307
400
|
|
|
308
401
|
if self.has_param(item, "query"):
|
|
309
402
|
query = self.get_param(item, "query")
|
|
310
403
|
|
|
311
|
-
|
|
312
|
-
context =
|
|
313
|
-
if query is not None:
|
|
314
|
-
# query file using temp index (created on the fly)
|
|
315
|
-
self.log("Querying web: {}".format(url))
|
|
404
|
+
results = []
|
|
405
|
+
context = ""
|
|
316
406
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
407
|
+
# get tmp query model (shared for all URLs)
|
|
408
|
+
model = self.plugin.window.core.models.from_defaults()
|
|
409
|
+
tmp_model = self.plugin.get_option_value("model_tmp_query")
|
|
410
|
+
if self.plugin.window.core.models.has(tmp_model):
|
|
411
|
+
model = self.plugin.window.core.models.get(tmp_model)
|
|
322
412
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
413
|
+
if query is not None:
|
|
414
|
+
for url in urls:
|
|
415
|
+
try:
|
|
416
|
+
# query file using temp index (created on the fly)
|
|
417
|
+
self.log(f"Querying web: {url}")
|
|
418
|
+
|
|
419
|
+
answer = self.plugin.window.core.idx.chat.query_web(
|
|
420
|
+
ctx=self.ctx,
|
|
421
|
+
type=type,
|
|
422
|
+
url=url,
|
|
423
|
+
args=args,
|
|
424
|
+
query=query,
|
|
425
|
+
model=model,
|
|
426
|
+
)
|
|
427
|
+
self.log(f"Response from temporary in-memory index: {answer}")
|
|
428
|
+
content = answer if answer else "No data"
|
|
429
|
+
from_str = type
|
|
430
|
+
if url:
|
|
431
|
+
from_str += ", URL: " + url
|
|
432
|
+
context += "From: " + from_str + ":\n--------------------------------\n" + content
|
|
433
|
+
|
|
434
|
+
# + auto-index to main index using Llama-index
|
|
435
|
+
if self.plugin.get_option_value("auto_index"):
|
|
436
|
+
self.msg = f"Indexing URL: '{url}'"
|
|
437
|
+
idx_name = self.plugin.get_option_value("idx")
|
|
438
|
+
# show status
|
|
439
|
+
self.status(f"Please wait... indexing: {url}...")
|
|
440
|
+
# index URL via Llama-index
|
|
441
|
+
self.plugin.window.core.idx.index_urls(
|
|
442
|
+
idx=idx_name,
|
|
443
|
+
urls=[url],
|
|
444
|
+
type=type,
|
|
445
|
+
extra_args=args,
|
|
446
|
+
)
|
|
352
447
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
448
|
+
# add URL to context
|
|
449
|
+
if url and (url.startswith("http://") or url.startswith("https://")):
|
|
450
|
+
self.ctx.urls_before.append(url)
|
|
451
|
+
|
|
452
|
+
results.append({
|
|
453
|
+
'url': url,
|
|
454
|
+
'content': content,
|
|
455
|
+
})
|
|
456
|
+
except Exception as e:
|
|
457
|
+
results.append({
|
|
458
|
+
'url': url,
|
|
459
|
+
'content': f"Error: {e}",
|
|
460
|
+
})
|
|
461
|
+
self.log(f"Error querying/indexing URL '{url}': {e}")
|
|
462
|
+
else:
|
|
463
|
+
# No query provided - return info per URL to keep URL in response
|
|
464
|
+
for url in urls:
|
|
465
|
+
results.append({
|
|
466
|
+
'url': url,
|
|
467
|
+
'content': "No data",
|
|
468
|
+
})
|
|
356
469
|
|
|
357
470
|
extra = {
|
|
358
|
-
"context": context,
|
|
471
|
+
"context": context if context else None,
|
|
359
472
|
}
|
|
360
|
-
return self.make_response(item,
|
|
473
|
+
return self.make_response(item, results, extra=extra)
|
|
361
474
|
|
|
362
475
|
def cmd_web_extract_links(self, item: dict) -> dict:
|
|
363
476
|
"""
|
|
@@ -366,17 +479,30 @@ class Worker(BaseWorker):
|
|
|
366
479
|
:param item: command item
|
|
367
480
|
:return: response item
|
|
368
481
|
"""
|
|
369
|
-
|
|
370
|
-
if
|
|
371
|
-
url = self.get_param(item, "url")
|
|
372
|
-
if not url:
|
|
482
|
+
urls = self._extract_urls(item, allow_args=False)
|
|
483
|
+
if not urls:
|
|
373
484
|
return self.make_response(item, "No URL provided")
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
485
|
+
|
|
486
|
+
results = []
|
|
487
|
+
for url in urls:
|
|
488
|
+
try:
|
|
489
|
+
links = self.plugin.window.core.web.helpers.get_links(url)
|
|
490
|
+
result = {
|
|
491
|
+
'url': url,
|
|
492
|
+
'links': links,
|
|
493
|
+
}
|
|
494
|
+
if url not in self.ctx.urls_before:
|
|
495
|
+
self.ctx.urls_before.append(url)
|
|
496
|
+
results.append(result)
|
|
497
|
+
except Exception as e:
|
|
498
|
+
results.append({
|
|
499
|
+
'url': url,
|
|
500
|
+
'links': [],
|
|
501
|
+
'content': f"Error: {e}",
|
|
502
|
+
})
|
|
503
|
+
self.log(f"Error extracting links from '{url}': {e}")
|
|
504
|
+
|
|
505
|
+
return self.make_response(item, results)
|
|
380
506
|
|
|
381
507
|
def cmd_web_extract_images(self, item: dict) -> dict:
|
|
382
508
|
"""
|
|
@@ -386,27 +512,43 @@ class Worker(BaseWorker):
|
|
|
386
512
|
:return: response item
|
|
387
513
|
"""
|
|
388
514
|
download = False
|
|
389
|
-
url = ""
|
|
390
|
-
if self.has_param(item, "url"):
|
|
391
|
-
url = self.get_param(item, "url")
|
|
392
515
|
if self.has_param(item, "download"):
|
|
393
516
|
download = bool(self.get_param(item, "download"))
|
|
394
|
-
|
|
517
|
+
|
|
518
|
+
urls = self._extract_urls(item, allow_args=False)
|
|
519
|
+
if not urls:
|
|
395
520
|
return self.make_response(item, "No URL provided")
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
521
|
+
|
|
522
|
+
results = []
|
|
523
|
+
for url in urls:
|
|
524
|
+
try:
|
|
525
|
+
images = self.plugin.window.core.web.helpers.get_images(url)
|
|
526
|
+
result = {
|
|
527
|
+
'url': url,
|
|
528
|
+
'images': images,
|
|
529
|
+
}
|
|
530
|
+
if images and download:
|
|
531
|
+
for img in images:
|
|
532
|
+
try:
|
|
533
|
+
path = self.plugin.window.core.web.helpers.download_image(img)
|
|
534
|
+
if path:
|
|
535
|
+
if path not in self.ctx.images_before:
|
|
536
|
+
self.ctx.images_before.append(path)
|
|
537
|
+
except Exception as e:
|
|
538
|
+
# Keep downloading independent per image
|
|
539
|
+
print(e)
|
|
540
|
+
if url not in self.ctx.urls_before:
|
|
541
|
+
self.ctx.urls_before.append(url)
|
|
542
|
+
results.append(result)
|
|
543
|
+
except Exception as e:
|
|
544
|
+
results.append({
|
|
545
|
+
'url': url,
|
|
546
|
+
'images': [],
|
|
547
|
+
'content': f"Error: {e}",
|
|
548
|
+
})
|
|
549
|
+
self.log(f"Error extracting images from '{url}': {e}")
|
|
550
|
+
|
|
551
|
+
return self.make_response(item, results)
|
|
410
552
|
|
|
411
553
|
def cmd_web_request(self, item: dict) -> dict:
|
|
412
554
|
"""
|
|
@@ -415,7 +557,6 @@ class Worker(BaseWorker):
|
|
|
415
557
|
:param item: command item
|
|
416
558
|
:return: response item
|
|
417
559
|
"""
|
|
418
|
-
url = ""
|
|
419
560
|
method = "GET"
|
|
420
561
|
data = None
|
|
421
562
|
raw = None
|
|
@@ -425,10 +566,10 @@ class Worker(BaseWorker):
|
|
|
425
566
|
cookies = None
|
|
426
567
|
files = None
|
|
427
568
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
if not url:
|
|
569
|
+
urls = self._extract_urls(item, allow_args=False)
|
|
570
|
+
if not urls:
|
|
431
571
|
return self.make_response(item, "No URL provided")
|
|
572
|
+
|
|
432
573
|
if self.has_param(item, "method"):
|
|
433
574
|
method = self.get_param(item, "method")
|
|
434
575
|
if self.has_param(item, "data_form"):
|
|
@@ -446,24 +587,37 @@ class Worker(BaseWorker):
|
|
|
446
587
|
if self.has_param(item, "files"):
|
|
447
588
|
files = self.get_param(item, "files")
|
|
448
589
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
590
|
+
results = []
|
|
591
|
+
for url in urls:
|
|
592
|
+
try:
|
|
593
|
+
code, response = self.window.core.web.helpers.request(
|
|
594
|
+
url=url,
|
|
595
|
+
method=method,
|
|
596
|
+
headers=headers,
|
|
597
|
+
params=params,
|
|
598
|
+
data=data if data else raw,
|
|
599
|
+
json=json,
|
|
600
|
+
cookies=cookies,
|
|
601
|
+
files=files,
|
|
602
|
+
timeout=self.plugin.get_option_value("timeout"),
|
|
603
|
+
disable_ssl_verify=self.plugin.get_option_value("disable_ssl"),
|
|
604
|
+
allow_redirects=True,
|
|
605
|
+
stream=False,
|
|
606
|
+
user_agent=self.plugin.get_option_value("user_agent"))
|
|
607
|
+
result = {
|
|
608
|
+
'url': url,
|
|
609
|
+
'code': code,
|
|
610
|
+
'response': response,
|
|
611
|
+
}
|
|
612
|
+
if url not in self.ctx.urls_before:
|
|
613
|
+
self.ctx.urls_before.append(url)
|
|
614
|
+
results.append(result)
|
|
615
|
+
except Exception as e:
|
|
616
|
+
results.append({
|
|
617
|
+
'url': url,
|
|
618
|
+
'code': None,
|
|
619
|
+
'response': f"Error: {e}",
|
|
620
|
+
})
|
|
621
|
+
self.log(f"Error during web request to '{url}': {e}")
|
|
622
|
+
|
|
623
|
+
return self.make_response(item, results)
|
pygpt_net/plugin/mcp/__init__.py
CHANGED
|
File without changes
|
pygpt_net/plugin/mcp/config.py
CHANGED
|
File without changes
|
pygpt_net/plugin/mcp/plugin.py
CHANGED
|
File without changes
|
pygpt_net/plugin/mcp/worker.py
CHANGED
|
File without changes
|
pygpt_net/plugin/osm/__init__.py
CHANGED
|
File without changes
|
pygpt_net/plugin/osm/config.py
CHANGED
|
File without changes
|
pygpt_net/plugin/osm/plugin.py
CHANGED
|
File without changes
|
pygpt_net/plugin/osm/worker.py
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|