pygpt-net 2.6.8__py3-none-any.whl → 2.6.9__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 +4 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/app.py +4 -0
- pygpt_net/controller/kernel/kernel.py +1 -2
- pygpt_net/core/render/web/body.py +11 -33
- pygpt_net/core/render/web/renderer.py +52 -79
- pygpt_net/data/config/config.json +3 -3
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/config/presets/agent_openai_supervisor.json +54 -0
- pygpt_net/data/config/presets/agent_supervisor.json +52 -0
- pygpt_net/provider/agents/llama_index/supervisor_workflow.py +116 -0
- pygpt_net/provider/agents/llama_index/workflow/supervisor.py +303 -0
- pygpt_net/provider/agents/openai/supervisor.py +361 -0
- pygpt_net/provider/core/preset/patch.py +18 -0
- pygpt_net/ui/widget/textarea/web.py +47 -4
- {pygpt_net-2.6.8.dist-info → pygpt_net-2.6.9.dist-info}/METADATA +17 -2
- {pygpt_net-2.6.8.dist-info → pygpt_net-2.6.9.dist-info}/RECORD +20 -15
- {pygpt_net-2.6.8.dist-info → pygpt_net-2.6.9.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.8.dist-info → pygpt_net-2.6.9.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.8.dist-info → pygpt_net-2.6.9.dist-info}/entry_points.txt +0 -0
pygpt_net/CHANGELOG.txt
CHANGED
pygpt_net/__init__.py
CHANGED
|
@@ -6,15 +6,15 @@
|
|
|
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.17 00:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
__author__ = "Marcin Szczygliński"
|
|
13
13
|
__copyright__ = "Copyright 2025, Marcin Szczygliński"
|
|
14
14
|
__credits__ = ["Marcin Szczygliński"]
|
|
15
15
|
__license__ = "MIT"
|
|
16
|
-
__version__ = "2.6.
|
|
17
|
-
__build__ = "2025-08-
|
|
16
|
+
__version__ = "2.6.9"
|
|
17
|
+
__build__ = "2025-08-17"
|
|
18
18
|
__maintainer__ = "Marcin Szczygliński"
|
|
19
19
|
__github__ = "https://github.com/szczyglis-dev/py-gpt"
|
|
20
20
|
__report__ = "https://github.com/szczyglis-dev/py-gpt/issues"
|
pygpt_net/app.py
CHANGED
|
@@ -88,6 +88,7 @@ from pygpt_net.provider.agents.llama_index.openai_workflow import OpenAIAgent as
|
|
|
88
88
|
# from pygpt_net.provider.agents.llama_index.legacy.react import ReactAgent
|
|
89
89
|
from pygpt_net.provider.agents.llama_index.react_workflow import ReactWorkflowAgent
|
|
90
90
|
from pygpt_net.provider.agents.llama_index.codeact_workflow import CodeActAgent
|
|
91
|
+
from pygpt_net.provider.agents.llama_index.supervisor_workflow import SupervisorAgent as LlamaSupervisorAgent
|
|
91
92
|
from pygpt_net.provider.agents.openai.agent import Agent as OpenAIAgentsBase
|
|
92
93
|
from pygpt_net.provider.agents.openai.agent_with_experts import Agent as OpenAIAgentsExperts
|
|
93
94
|
from pygpt_net.provider.agents.openai.agent_with_experts_feedback import Agent as OpenAIAgentsExpertsFeedback
|
|
@@ -96,6 +97,7 @@ from pygpt_net.provider.agents.openai.bot_researcher import Agent as OpenAIAgent
|
|
|
96
97
|
from pygpt_net.provider.agents.openai.agent_planner import Agent as OpenAIAgentPlanner
|
|
97
98
|
from pygpt_net.provider.agents.openai.evolve import Agent as OpenAIAgentsEvolve
|
|
98
99
|
from pygpt_net.provider.agents.openai.agent_b2b import Agent as OpenAIAgentsB2B
|
|
100
|
+
from pygpt_net.provider.agents.openai.supervisor import Agent as OpenAIAgentSupervisor
|
|
99
101
|
|
|
100
102
|
# LLM wrapper providers (langchain, llama-index, embeddings)
|
|
101
103
|
from pygpt_net.provider.llms.anthropic import AnthropicLLM
|
|
@@ -445,6 +447,7 @@ def run(**kwargs):
|
|
|
445
447
|
# launcher.add_agent(ReactAgent()) # llama-index
|
|
446
448
|
launcher.add_agent(ReactWorkflowAgent()) # llama-index
|
|
447
449
|
launcher.add_agent(CodeActAgent()) # llama-index
|
|
450
|
+
launcher.add_agent(LlamaSupervisorAgent()) # llama-index
|
|
448
451
|
launcher.add_agent(OpenAIAgentsBase()) # openai-agents
|
|
449
452
|
launcher.add_agent(OpenAIAgentsExperts()) # openai-agents
|
|
450
453
|
launcher.add_agent(OpenAIAgentFeedback()) # openai-agents
|
|
@@ -453,6 +456,7 @@ def run(**kwargs):
|
|
|
453
456
|
launcher.add_agent(OpenAIAgentsExpertsFeedback()) # openai-agents
|
|
454
457
|
launcher.add_agent(OpenAIAgentsEvolve()) # openai-agents
|
|
455
458
|
launcher.add_agent(OpenAIAgentsB2B()) # openai-agents
|
|
459
|
+
launcher.add_agent(OpenAIAgentSupervisor()) # openai-agents
|
|
456
460
|
|
|
457
461
|
# register custom agents
|
|
458
462
|
agents = kwargs.get('agents', None)
|
|
@@ -31,7 +31,7 @@ from .reply import Reply
|
|
|
31
31
|
from .stack import Stack
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
class Kernel
|
|
34
|
+
class Kernel:
|
|
35
35
|
|
|
36
36
|
STATE_IDLE = "idle"
|
|
37
37
|
STATE_BUSY = "busy"
|
|
@@ -81,7 +81,6 @@ class Kernel(QObject):
|
|
|
81
81
|
|
|
82
82
|
:param window: The window context to which the kernel will be bound.
|
|
83
83
|
"""
|
|
84
|
-
super(Kernel, self).__init__(window)
|
|
85
84
|
self.window = window
|
|
86
85
|
self.replies = Reply(window)
|
|
87
86
|
self.stack = Stack(window)
|
|
@@ -985,9 +985,9 @@ class Body:
|
|
|
985
985
|
syntax_style = self.window.core.config.get("render.code_syntax") or "default"
|
|
986
986
|
|
|
987
987
|
theme_css = self.window.controller.theme.markdown.get_web_css().replace('%fonts%', fonts_path)
|
|
988
|
-
parts = [self._SPINNER, theme_css
|
|
989
|
-
|
|
990
|
-
|
|
988
|
+
parts = [self._SPINNER, theme_css,
|
|
989
|
+
"pre { color: #fff; }" if syntax_style in self._syntax_dark else "pre { color: #000; }",
|
|
990
|
+
self.highlight.get_style_defs()]
|
|
991
991
|
return "\n".join(parts)
|
|
992
992
|
|
|
993
993
|
def prepare_action_icons(self, ctx: CtxItem) -> str:
|
|
@@ -1014,32 +1014,19 @@ class Body:
|
|
|
1014
1014
|
if ctx.output:
|
|
1015
1015
|
cid = ctx.id
|
|
1016
1016
|
t = trans
|
|
1017
|
-
|
|
1018
1017
|
icons.append(
|
|
1019
|
-
f'<a href="extra-audio-read:{cid}" class="action-icon" data-id="{cid}" role="button">'
|
|
1020
|
-
f'<span class="cmd">{self.get_icon("volume", t("ctx.extra.audio"), ctx)}</span></a>'
|
|
1021
|
-
)
|
|
1018
|
+
f'<a href="extra-audio-read:{cid}" class="action-icon" data-id="{cid}" role="button"><span class="cmd">{self.get_icon("volume", t("ctx.extra.audio"), ctx)}</span></a>')
|
|
1022
1019
|
icons.append(
|
|
1023
|
-
f'<a href="extra-copy:{cid}" class="action-icon" data-id="{cid}" role="button">'
|
|
1024
|
-
f'<span class="cmd">{self.get_icon("copy", t("ctx.extra.copy"), ctx)}</span></a>'
|
|
1025
|
-
)
|
|
1020
|
+
f'<a href="extra-copy:{cid}" class="action-icon" data-id="{cid}" role="button"><span class="cmd">{self.get_icon("copy", t("ctx.extra.copy"), ctx)}</span></a>')
|
|
1026
1021
|
icons.append(
|
|
1027
|
-
f'<a href="extra-replay:{cid}" class="action-icon" data-id="{cid}" role="button">'
|
|
1028
|
-
f'<span class="cmd">{self.get_icon("reload", t("ctx.extra.reply"), ctx)}</span></a>'
|
|
1029
|
-
)
|
|
1022
|
+
f'<a href="extra-replay:{cid}" class="action-icon" data-id="{cid}" role="button"><span class="cmd">{self.get_icon("reload", t("ctx.extra.reply"), ctx)}</span></a>')
|
|
1030
1023
|
icons.append(
|
|
1031
|
-
f'<a href="extra-edit:{cid}" class="action-icon edit-icon" data-id="{cid}" role="button">'
|
|
1032
|
-
f'<span class="cmd">{self.get_icon("edit", t("ctx.extra.edit"), ctx)}</span></a>'
|
|
1033
|
-
)
|
|
1024
|
+
f'<a href="extra-edit:{cid}" class="action-icon edit-icon" data-id="{cid}" role="button"><span class="cmd">{self.get_icon("edit", t("ctx.extra.edit"), ctx)}</span></a>')
|
|
1034
1025
|
icons.append(
|
|
1035
|
-
f'<a href="extra-delete:{cid}" class="action-icon edit-icon" data-id="{cid}" role="button">'
|
|
1036
|
-
f'<span class="cmd">{self.get_icon("delete", t("ctx.extra.delete"), ctx)}</span></a>'
|
|
1037
|
-
)
|
|
1026
|
+
f'<a href="extra-delete:{cid}" class="action-icon edit-icon" data-id="{cid}" role="button"><span class="cmd">{self.get_icon("delete", t("ctx.extra.delete"), ctx)}</span></a>')
|
|
1038
1027
|
if not self.window.core.ctx.is_first_item(cid):
|
|
1039
1028
|
icons.append(
|
|
1040
|
-
f'<a href="extra-join:{cid}" class="action-icon edit-icon" data-id="{cid}" role="button">'
|
|
1041
|
-
f'<span class="cmd">{self.get_icon("playlist_add", t("ctx.extra.join"), ctx)}</span></a>'
|
|
1042
|
-
)
|
|
1029
|
+
f'<a href="extra-join:{cid}" class="action-icon edit-icon" data-id="{cid}" role="button"><span class="cmd">{self.get_icon("playlist_add", t("ctx.extra.join"), ctx)}</span></a>')
|
|
1043
1030
|
return icons
|
|
1044
1031
|
|
|
1045
1032
|
def get_icon(
|
|
@@ -1058,9 +1045,7 @@ class Body:
|
|
|
1058
1045
|
"""
|
|
1059
1046
|
app_path = self.window.core.config.get_app_path()
|
|
1060
1047
|
icon_path = os.path.join(app_path, "data", "icons", f"{icon}.svg")
|
|
1061
|
-
return
|
|
1062
|
-
f'<img src="file://{icon_path}" class="action-img" title="{title}" alt="{title}" data-id="{item.id}">'
|
|
1063
|
-
)
|
|
1048
|
+
return f'<img src="file://{icon_path}" class="action-img" title="{title}" alt="{title}" data-id="{item.id}">'
|
|
1064
1049
|
|
|
1065
1050
|
def get_image_html(
|
|
1066
1051
|
self,
|
|
@@ -1078,14 +1063,7 @@ class Body:
|
|
|
1078
1063
|
"""
|
|
1079
1064
|
url, path = self.window.core.filesystem.extract_local_url(url)
|
|
1080
1065
|
basename = os.path.basename(path)
|
|
1081
|
-
return
|
|
1082
|
-
f'<div class="extra-src-img-box" title="{url}">'
|
|
1083
|
-
f'<div class="img-outer"><div class="img-wrapper">'
|
|
1084
|
-
f'<a href="{url}"><img src="{path}" class="image"></a>'
|
|
1085
|
-
f'</div>'
|
|
1086
|
-
f'<a href="{url}" class="title">{basename}</a>'
|
|
1087
|
-
f'</div></div><br/>'
|
|
1088
|
-
)
|
|
1066
|
+
return f'<div class="extra-src-img-box" title="{url}"><div class="img-outer"><div class="img-wrapper"><a href="{url}"><img src="{path}" class="image"></a></div><a href="{url}" class="title">{basename}</a></div></div><br/>'
|
|
1089
1067
|
|
|
1090
1068
|
def get_url_html(
|
|
1091
1069
|
self,
|
|
@@ -13,7 +13,7 @@ import json
|
|
|
13
13
|
import os
|
|
14
14
|
import re
|
|
15
15
|
from datetime import datetime
|
|
16
|
-
from typing import Optional, List
|
|
16
|
+
from typing import Optional, List, Any
|
|
17
17
|
|
|
18
18
|
from pygpt_net.core.render.base import BaseRenderer
|
|
19
19
|
from pygpt_net.core.text.utils import has_unclosed_code_tag
|
|
@@ -159,6 +159,15 @@ class Renderer(BaseRenderer):
|
|
|
159
159
|
else:
|
|
160
160
|
self.clear_chunks(pid)
|
|
161
161
|
|
|
162
|
+
def to_json(self, data: Any) -> str:
|
|
163
|
+
"""
|
|
164
|
+
Convert data to JSON object
|
|
165
|
+
|
|
166
|
+
:param data: data to convert
|
|
167
|
+
:return: JSON object or None
|
|
168
|
+
"""
|
|
169
|
+
return json.dumps(data, ensure_ascii=False, separators=(',', ':'))
|
|
170
|
+
|
|
162
171
|
def state_changed(
|
|
163
172
|
self,
|
|
164
173
|
state: str,
|
|
@@ -510,6 +519,15 @@ class Renderer(BaseRenderer):
|
|
|
510
519
|
text_chunk = "".join(("\n", text_chunk)) # add newline to chunk
|
|
511
520
|
|
|
512
521
|
self.prev_chunk_replace = replace_bool
|
|
522
|
+
|
|
523
|
+
# hide loading spinner if it is the beginning of the text
|
|
524
|
+
if begin:
|
|
525
|
+
try:
|
|
526
|
+
self.get_output_node(meta).page().runJavaScript("hideLoading();")
|
|
527
|
+
except Exception as e:
|
|
528
|
+
pass
|
|
529
|
+
|
|
530
|
+
# emit chunk to output node
|
|
513
531
|
try:
|
|
514
532
|
self.get_output_node(meta).page().bridge.chunk.emit(
|
|
515
533
|
name_header_str or "",
|
|
@@ -566,10 +584,10 @@ class Renderer(BaseRenderer):
|
|
|
566
584
|
|
|
567
585
|
pid = self.get_or_create_pid(meta)
|
|
568
586
|
self.clear_chunks_input(pid)
|
|
569
|
-
chunk = self.helpers.format_chunk(text_chunk)
|
|
570
|
-
escaped_chunk = json.dumps(chunk)
|
|
571
587
|
try:
|
|
572
|
-
self.get_output_node(meta).page().runJavaScript(
|
|
588
|
+
self.get_output_node(meta).page().runJavaScript(
|
|
589
|
+
f"appendToInput({self.to_json(self.helpers.format_chunk(text_chunk))});"
|
|
590
|
+
)
|
|
573
591
|
except Exception as e:
|
|
574
592
|
pass
|
|
575
593
|
|
|
@@ -610,11 +628,10 @@ class Renderer(BaseRenderer):
|
|
|
610
628
|
to_append = self.pids[pid].live_buffer
|
|
611
629
|
if has_unclosed_code_tag(self.pids[pid].live_buffer):
|
|
612
630
|
to_append += "\n```"
|
|
613
|
-
html = self.parser.parse(to_append)
|
|
614
|
-
escaped_chunk = json.dumps(html)
|
|
615
631
|
try:
|
|
616
632
|
self.get_output_node(meta).page().runJavaScript(
|
|
617
|
-
f"replaceLive({
|
|
633
|
+
f"replaceLive({self.to_json(self.parser.parse(to_append))});"
|
|
634
|
+
)
|
|
618
635
|
except Exception as e:
|
|
619
636
|
pass
|
|
620
637
|
|
|
@@ -629,7 +646,7 @@ class Renderer(BaseRenderer):
|
|
|
629
646
|
return
|
|
630
647
|
pid = self.get_or_create_pid(meta)
|
|
631
648
|
if not self.pids[pid].loaded:
|
|
632
|
-
js = "var element = document.getElementById('_append_live_');if (element) { element.
|
|
649
|
+
js = "var element = document.getElementById('_append_live_');if (element) { element.replaceChildren(); }"
|
|
633
650
|
else:
|
|
634
651
|
js = "clearLive();"
|
|
635
652
|
try:
|
|
@@ -806,9 +823,8 @@ class Renderer(BaseRenderer):
|
|
|
806
823
|
if footer:
|
|
807
824
|
self.append(pid, html)
|
|
808
825
|
else:
|
|
809
|
-
escaped_html = json.dumps(html)
|
|
810
826
|
try:
|
|
811
|
-
self.get_output_node(meta).page().runJavaScript(f"appendExtra('{ctx.id}',{
|
|
827
|
+
self.get_output_node(meta).page().runJavaScript(f"appendExtra('{ctx.id}',{self.to_json(html)});")
|
|
812
828
|
except Exception as e:
|
|
813
829
|
pass
|
|
814
830
|
|
|
@@ -918,7 +934,7 @@ class Renderer(BaseRenderer):
|
|
|
918
934
|
if pid is None:
|
|
919
935
|
return
|
|
920
936
|
if not self.pids[pid].loaded:
|
|
921
|
-
js = "var element = document.getElementById('_append_input_');if (element) { element.
|
|
937
|
+
js = "var element = document.getElementById('_append_input_');if (element) { element.replaceChildren(); }"
|
|
922
938
|
else:
|
|
923
939
|
js = "clearInput();"
|
|
924
940
|
try:
|
|
@@ -937,7 +953,7 @@ class Renderer(BaseRenderer):
|
|
|
937
953
|
"""
|
|
938
954
|
self.prev_chunk_replace = False
|
|
939
955
|
if not self.pids[pid].loaded:
|
|
940
|
-
js = "var element = document.getElementById('_append_output_');if (element) { element.
|
|
956
|
+
js = "var element = document.getElementById('_append_output_');if (element) { element.replaceChildren(); }"
|
|
941
957
|
else:
|
|
942
958
|
js = "clearOutput();"
|
|
943
959
|
try:
|
|
@@ -955,7 +971,7 @@ class Renderer(BaseRenderer):
|
|
|
955
971
|
:pid: context PID
|
|
956
972
|
"""
|
|
957
973
|
if not self.pids[pid].loaded:
|
|
958
|
-
js = "var element = document.getElementById('_nodes_');if (element) { element.
|
|
974
|
+
js = "var element = document.getElementById('_nodes_');if (element) { element.replaceChildren(); }"
|
|
959
975
|
else:
|
|
960
976
|
js = "clearNodes();"
|
|
961
977
|
try:
|
|
@@ -1043,18 +1059,8 @@ class Renderer(BaseRenderer):
|
|
|
1043
1059
|
if ctx.extra is not None and "footer" in ctx.extra:
|
|
1044
1060
|
extra = ctx.extra["footer"]
|
|
1045
1061
|
extra_style = "display:block;"
|
|
1046
|
-
html = (
|
|
1047
|
-
f'<div class="msg-box msg-user" id="{msg_id}">'
|
|
1048
|
-
f'<div class="name-header name-user">{name}</div>'
|
|
1049
|
-
f'<div class="msg">'
|
|
1050
|
-
f'{html}'
|
|
1051
|
-
f'<div class="msg-extra" style="{extra_style}">{extra}</div>'
|
|
1052
|
-
f'{debug}'
|
|
1053
|
-
f'</div>'
|
|
1054
|
-
f'</div>'
|
|
1055
|
-
)
|
|
1056
1062
|
|
|
1057
|
-
return html
|
|
1063
|
+
return f'<div class="msg-box msg-user" id="{msg_id}"><div class="name-header name-user">{name}</div><div class="msg">{html}<div class="msg-extra" style="{extra_style}">{extra}</div>{debug}</div></div>'
|
|
1058
1064
|
|
|
1059
1065
|
def prepare_node_output(
|
|
1060
1066
|
self,
|
|
@@ -1091,11 +1097,6 @@ class Renderer(BaseRenderer):
|
|
|
1091
1097
|
tool_output = ""
|
|
1092
1098
|
spinner = ""
|
|
1093
1099
|
output_class = "display:none"
|
|
1094
|
-
cmd_icon = f'<img src="{self._file_prefix}{self._icon_expand}" width="25" height="25" valign="middle">'
|
|
1095
|
-
expand_btn = (
|
|
1096
|
-
f"<span class='toggle-cmd-output' onclick='toggleToolOutput({ctx.id});' title='{trans('action.cmd.expand')}' "
|
|
1097
|
-
f"role='button'>{cmd_icon}</span>"
|
|
1098
|
-
)
|
|
1099
1100
|
|
|
1100
1101
|
if is_cmd:
|
|
1101
1102
|
if ctx.results is not None and len(ctx.results) > 0 \
|
|
@@ -1118,42 +1119,13 @@ class Renderer(BaseRenderer):
|
|
|
1118
1119
|
or out.rstrip().endswith(('}</tool>', '}</tool>'))
|
|
1119
1120
|
):
|
|
1120
1121
|
spinner_class = "" if ctx.live else "display:none"
|
|
1121
|
-
spinner =
|
|
1122
|
-
f'<span class="spinner" style="{spinner_class}">'
|
|
1123
|
-
f'<img src="{self._file_prefix}{self._icon_sync}" width="30" height="30" '
|
|
1124
|
-
f'class="loading"></span>'
|
|
1125
|
-
)
|
|
1126
|
-
|
|
1127
|
-
html_tools = (
|
|
1128
|
-
f'<div class="tool-output" style="{output_class}">' +
|
|
1129
|
-
expand_btn +
|
|
1130
|
-
'<div class="content" style="display:none">' +
|
|
1131
|
-
tool_output +
|
|
1132
|
-
'</div></div>'
|
|
1133
|
-
)
|
|
1134
|
-
tool_extra = self.body.prepare_tool_extra(ctx)
|
|
1135
|
-
|
|
1136
|
-
debug = ""
|
|
1137
|
-
if self.is_debug():
|
|
1138
|
-
debug = self.append_debug(ctx, pid, "output")
|
|
1122
|
+
spinner = f"<span class=\"spinner\" style=\"{spinner_class}\"><img src=\"{self._file_prefix}{self._icon_sync}\" width=\"30\" height=\"30\" class=\"loading\"></span>"
|
|
1139
1123
|
|
|
1124
|
+
tool_extra = self.body.prepare_tool_extra(ctx)
|
|
1125
|
+
debug = self.append_debug(ctx, pid, "output") if self.is_debug() else ""
|
|
1140
1126
|
name_header = self.get_name_header(ctx)
|
|
1141
|
-
html = (
|
|
1142
|
-
f'<div class="msg-box msg-bot" id="{msg_id}">' +
|
|
1143
|
-
name_header +
|
|
1144
|
-
'<div class="msg">' +
|
|
1145
|
-
f'{html}' +
|
|
1146
|
-
f'{spinner}' +
|
|
1147
|
-
f'<div class="msg-tool-extra">{tool_extra}</div>' +
|
|
1148
|
-
f'{html_tools}' +
|
|
1149
|
-
f'<div class="msg-extra">{extra}</div>' +
|
|
1150
|
-
f'{footer}' +
|
|
1151
|
-
f'{debug}' +
|
|
1152
|
-
'</div>' +
|
|
1153
|
-
'</div>'
|
|
1154
|
-
)
|
|
1155
1127
|
|
|
1156
|
-
return html
|
|
1128
|
+
return f"<div class='msg-box msg-bot' id='{msg_id}'>{name_header}<div class='msg'>{html}{spinner}<div class='msg-tool-extra'>{tool_extra}</div><div class='tool-output' style='{output_class}'><span class='toggle-cmd-output' onclick='toggleToolOutput({ctx.id});' title='{trans('action.cmd.expand')}' role='button'><img src='{self._file_prefix}{self._icon_expand}' width='25' height='25' valign='middle'></span><div class='content' style='display:none'>{tool_output}</div></div><div class='msg-extra'>{extra}</div>{footer}{debug}</div></div>"
|
|
1157
1129
|
|
|
1158
1130
|
def get_name_header(self, ctx: CtxItem) -> str:
|
|
1159
1131
|
"""
|
|
@@ -1200,10 +1172,10 @@ class Renderer(BaseRenderer):
|
|
|
1200
1172
|
:param pid: context PID
|
|
1201
1173
|
:param html: HTML code
|
|
1202
1174
|
"""
|
|
1203
|
-
escaped_html = json.dumps(html)
|
|
1204
1175
|
try:
|
|
1205
|
-
|
|
1206
|
-
|
|
1176
|
+
self.get_output_node_by_pid(pid).page().runJavaScript(
|
|
1177
|
+
f"if (typeof window.appendNode !== 'undefined') appendNode({self.to_json(html)});"
|
|
1178
|
+
)
|
|
1207
1179
|
except Exception as e:
|
|
1208
1180
|
pass
|
|
1209
1181
|
|
|
@@ -1251,6 +1223,7 @@ class Renderer(BaseRenderer):
|
|
|
1251
1223
|
# self.window.ui.nodes['output'][pid] = new_view
|
|
1252
1224
|
node.resetPage()
|
|
1253
1225
|
node.setHtml(html, baseUrl="file://")
|
|
1226
|
+
self.pids[pid].html = ""
|
|
1254
1227
|
|
|
1255
1228
|
def get_output_node(
|
|
1256
1229
|
self,
|
|
@@ -1291,9 +1264,8 @@ class Renderer(BaseRenderer):
|
|
|
1291
1264
|
:param ctx: context item
|
|
1292
1265
|
"""
|
|
1293
1266
|
try:
|
|
1294
|
-
_id = json.dumps(ctx.id)
|
|
1295
1267
|
self.get_output_node(ctx.meta).page().runJavaScript(
|
|
1296
|
-
f"if (typeof window.removeNode !== 'undefined') removeNode({
|
|
1268
|
+
f"if (typeof window.removeNode !== 'undefined') removeNode({self.to_json(ctx.id)});")
|
|
1297
1269
|
except Exception as e:
|
|
1298
1270
|
pass
|
|
1299
1271
|
|
|
@@ -1304,9 +1276,8 @@ class Renderer(BaseRenderer):
|
|
|
1304
1276
|
:param ctx: context item
|
|
1305
1277
|
"""
|
|
1306
1278
|
try:
|
|
1307
|
-
_id = json.dumps(ctx.id)
|
|
1308
1279
|
self.get_output_node(ctx.meta).page().runJavaScript(
|
|
1309
|
-
f"if (typeof window.removeNodesFromId !== 'undefined') removeNodesFromId({
|
|
1280
|
+
f"if (typeof window.removeNodesFromId !== 'undefined') removeNodesFromId({self.to_json(ctx.id)});")
|
|
1310
1281
|
except Exception as e:
|
|
1311
1282
|
pass
|
|
1312
1283
|
|
|
@@ -1460,7 +1431,7 @@ class Renderer(BaseRenderer):
|
|
|
1460
1431
|
|
|
1461
1432
|
def reload_css(self):
|
|
1462
1433
|
"""Reload CSS - all, global"""
|
|
1463
|
-
to_json =
|
|
1434
|
+
to_json = self.to_json(self.body.prepare_styles())
|
|
1464
1435
|
nodes = self.get_all_nodes()
|
|
1465
1436
|
for pid in self.pids:
|
|
1466
1437
|
if self.pids[pid].loaded:
|
|
@@ -1496,10 +1467,10 @@ class Renderer(BaseRenderer):
|
|
|
1496
1467
|
:param meta: context meta
|
|
1497
1468
|
:param content: content
|
|
1498
1469
|
"""
|
|
1499
|
-
escaped_content = json.dumps(content)
|
|
1500
1470
|
try:
|
|
1501
1471
|
self.get_output_node(meta).page().runJavaScript(
|
|
1502
|
-
f"if (typeof window.appendToolOutput !== 'undefined') appendToolOutput({
|
|
1472
|
+
f"if (typeof window.appendToolOutput !== 'undefined') appendToolOutput({self.to_json(content)});"
|
|
1473
|
+
)
|
|
1503
1474
|
except Exception as e:
|
|
1504
1475
|
pass
|
|
1505
1476
|
|
|
@@ -1514,10 +1485,10 @@ class Renderer(BaseRenderer):
|
|
|
1514
1485
|
:param meta: context meta
|
|
1515
1486
|
:param content: content
|
|
1516
1487
|
"""
|
|
1517
|
-
escaped_content = json.dumps(content)
|
|
1518
1488
|
try:
|
|
1519
1489
|
self.get_output_node(meta).page().runJavaScript(
|
|
1520
|
-
f"if (typeof window.updateToolOutput !== 'undefined') updateToolOutput({
|
|
1490
|
+
f"if (typeof window.updateToolOutput !== 'undefined') updateToolOutput({self.to_json(content)});"
|
|
1491
|
+
)
|
|
1521
1492
|
except Exception as e:
|
|
1522
1493
|
pass
|
|
1523
1494
|
|
|
@@ -1529,7 +1500,8 @@ class Renderer(BaseRenderer):
|
|
|
1529
1500
|
"""
|
|
1530
1501
|
try:
|
|
1531
1502
|
self.get_output_node(meta).page().runJavaScript(
|
|
1532
|
-
f"if (typeof window.clearToolOutput !== 'undefined') clearToolOutput();"
|
|
1503
|
+
f"if (typeof window.clearToolOutput !== 'undefined') clearToolOutput();"
|
|
1504
|
+
)
|
|
1533
1505
|
except Exception as e:
|
|
1534
1506
|
pass
|
|
1535
1507
|
|
|
@@ -1541,7 +1513,8 @@ class Renderer(BaseRenderer):
|
|
|
1541
1513
|
"""
|
|
1542
1514
|
try:
|
|
1543
1515
|
self.get_output_node(meta).page().runJavaScript(
|
|
1544
|
-
f"if (typeof window.beginToolOutput !== 'undefined') beginToolOutput();"
|
|
1516
|
+
f"if (typeof window.beginToolOutput !== 'undefined') beginToolOutput();"
|
|
1517
|
+
)
|
|
1545
1518
|
except Exception as e:
|
|
1546
1519
|
pass
|
|
1547
1520
|
|
|
@@ -1549,7 +1522,8 @@ class Renderer(BaseRenderer):
|
|
|
1549
1522
|
"""End tool output"""
|
|
1550
1523
|
try:
|
|
1551
1524
|
self.get_output_node().page().runJavaScript(
|
|
1552
|
-
f"if (typeof window.endToolOutput !== 'undefined') endToolOutput();"
|
|
1525
|
+
f"if (typeof window.endToolOutput !== 'undefined') endToolOutput();"
|
|
1526
|
+
)
|
|
1553
1527
|
except Exception as e:
|
|
1554
1528
|
pass
|
|
1555
1529
|
|
|
@@ -1568,8 +1542,7 @@ class Renderer(BaseRenderer):
|
|
|
1568
1542
|
"""
|
|
1569
1543
|
if title is None:
|
|
1570
1544
|
title = "debug"
|
|
1571
|
-
|
|
1572
|
-
return "<div class='debug'>" + debug + "</div>"
|
|
1545
|
+
return f"<div class='debug'><b>{title}:</b> pid: {pid}, ctx: {ctx.to_dict()}</div>"
|
|
1573
1546
|
|
|
1574
1547
|
def is_debug(self) -> bool:
|
|
1575
1548
|
"""
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"__meta__": {
|
|
3
|
-
"version": "2.6.
|
|
4
|
-
"app.version": "2.6.
|
|
5
|
-
"updated_at": "2025-08-
|
|
3
|
+
"version": "2.6.9",
|
|
4
|
+
"app.version": "2.6.9",
|
|
5
|
+
"updated_at": "2025-08-17T00:00:00"
|
|
6
6
|
},
|
|
7
7
|
"access.audio.event.speech": false,
|
|
8
8
|
"access.audio.event.speech.disabled": [],
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"uuid": "a424e13a-b3c2-4cc7-81b5-f74821f47ec3",
|
|
3
|
+
"name": "Supervisor + worker",
|
|
4
|
+
"ai_name": "",
|
|
5
|
+
"ai_avatar": "",
|
|
6
|
+
"ai_personalize": false,
|
|
7
|
+
"user_name": "",
|
|
8
|
+
"prompt": "",
|
|
9
|
+
"chat": false,
|
|
10
|
+
"completion": false,
|
|
11
|
+
"img": false,
|
|
12
|
+
"vision": false,
|
|
13
|
+
"assistant": false,
|
|
14
|
+
"llama_index": false,
|
|
15
|
+
"agent": false,
|
|
16
|
+
"agent_llama": false,
|
|
17
|
+
"agent_openai": true,
|
|
18
|
+
"expert": false,
|
|
19
|
+
"audio": false,
|
|
20
|
+
"research": false,
|
|
21
|
+
"computer": false,
|
|
22
|
+
"temperature": 1.0,
|
|
23
|
+
"filename": "agent_openai_supervisor",
|
|
24
|
+
"model": "gpt-4o",
|
|
25
|
+
"tools": {
|
|
26
|
+
"function": []
|
|
27
|
+
},
|
|
28
|
+
"experts": [],
|
|
29
|
+
"idx": "_",
|
|
30
|
+
"agent_provider": "supervisor",
|
|
31
|
+
"agent_provider_openai": "openai_agent_supervisor",
|
|
32
|
+
"assistant_id": "",
|
|
33
|
+
"enabled": true,
|
|
34
|
+
"description": "",
|
|
35
|
+
"remote_tools": "",
|
|
36
|
+
"extra": {
|
|
37
|
+
"openai_agent_supervisor": {
|
|
38
|
+
"supervisor": {
|
|
39
|
+
"prompt": "\n You are the \u201cSupervisor\u201d (orchestrator). You never use tools directly except the tool that runs the Worker.\n Process:\n - Decompose the user's task into actionable instructions for the Worker.\n - Do NOT pass your conversation history to the Worker. Pass ONLY a concise, self-contained instruction.\n - After each Worker result, evaluate against a clear Definition of Done (DoD). If not met, call the Worker again with a refined instruction.\n - Ask the user only if absolutely necessary. If you must, STOP and output a single JSON with:\n {\"action\":\"ask_user\",\"question\":\"...\",\"reasoning\":\"...\"}\n - When done, output a single JSON:\n {\"action\":\"final\",\"final_answer\":\"...\",\"reasoning\":\"...\"}\n - Otherwise, to run the Worker, call the run_worker tool with a short instruction.\n Respond in the user's language. Keep outputs short and precise.\n "
|
|
40
|
+
},
|
|
41
|
+
"worker": {
|
|
42
|
+
"model": "gpt-4o",
|
|
43
|
+
"prompt": "\n You are the \u201cWorker\u201d. You execute Supervisor instructions strictly, using your tools.\n - Keep your own memory across calls (Worker session).\n - Return a concise result with key evidence/extracts from tools when applicable.\n - Do not ask the user questions directly; if instruction is underspecified, clearly state what is missing.\n Respond in the user's language.\n ",
|
|
44
|
+
"allow_local_tools": true,
|
|
45
|
+
"allow_remote_tools": true
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"__meta__": {
|
|
50
|
+
"version": "2.6.8",
|
|
51
|
+
"app.version": "2.6.8",
|
|
52
|
+
"updated_at": "2025-08-17T03:03:45"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"uuid": "f5dd895c-3be8-4a73-aac9-7a20845e57b2",
|
|
3
|
+
"name": "Supervisor + worker",
|
|
4
|
+
"ai_name": "",
|
|
5
|
+
"ai_avatar": "",
|
|
6
|
+
"ai_personalize": false,
|
|
7
|
+
"user_name": "",
|
|
8
|
+
"prompt": "",
|
|
9
|
+
"chat": false,
|
|
10
|
+
"completion": false,
|
|
11
|
+
"img": false,
|
|
12
|
+
"vision": false,
|
|
13
|
+
"assistant": false,
|
|
14
|
+
"llama_index": false,
|
|
15
|
+
"agent": false,
|
|
16
|
+
"agent_llama": true,
|
|
17
|
+
"agent_openai": false,
|
|
18
|
+
"expert": false,
|
|
19
|
+
"audio": false,
|
|
20
|
+
"research": false,
|
|
21
|
+
"computer": false,
|
|
22
|
+
"temperature": 1.0,
|
|
23
|
+
"filename": "agent_supervisor",
|
|
24
|
+
"model": "gpt-4o",
|
|
25
|
+
"tools": {
|
|
26
|
+
"function": []
|
|
27
|
+
},
|
|
28
|
+
"experts": [],
|
|
29
|
+
"idx": "_",
|
|
30
|
+
"agent_provider": "supervisor",
|
|
31
|
+
"agent_provider_openai": "openai_agent_supervisor",
|
|
32
|
+
"assistant_id": "",
|
|
33
|
+
"enabled": true,
|
|
34
|
+
"description": "",
|
|
35
|
+
"remote_tools": "",
|
|
36
|
+
"extra": {
|
|
37
|
+
"supervisor": {
|
|
38
|
+
"supervisor": {
|
|
39
|
+
"prompt": "\nYou are the \u201cSupervisor\u201d \u2013 the main orchestrator. Do not use tools directly.\nYour tasks:\n- Break down the user's task into steps and create precise instructions for the \u201cWorker\u201d agent.\n- Do not pass your history/memory to the Worker. Only pass minimal, self-sufficient instructions.\n- After each Worker response, assess progress towards the Definition of Done (DoD). If not met \u2013 generate a better instruction.\n- Ask the user only when absolutely necessary. Then stop and return the question.\n- When the task is complete \u2013 return the final answer to the user.\nAlways return only ONE JSON object:\n{\n \"action\": \"task\" | \"final\" | \"ask_user\",\n \"instruction\": \"<Worker's instruction or ''>\",\n \"final_answer\": \"<final answer or ''>\",\n \"question\": \"<user question or ''>\",\n \"reasoning\": \"<brief reasoning and quality control>\",\n \"done_criteria\": \"<list/text of DoD criteria>\"\n}\nEnsure proper JSON (no comments, no trailing commas). Respond in the user's language.\n"
|
|
40
|
+
},
|
|
41
|
+
"worker": {
|
|
42
|
+
"model": "gpt-4o",
|
|
43
|
+
"prompt": "\nYou are the \u201cWorker\u201d \u2013 executor of the Supervisor's instructions. You have your own memory and tools.\n- Execute the Supervisor's instructions precisely and concisely.\n- Use the available tools and return a brief result + relevant data/reasoning.\n- Maintain the working context in your memory (only Worker).\n- Return plain text (not JSON) unless instructed otherwise by the Supervisor.\n- Respond in the user's language.\n"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"__meta__": {
|
|
48
|
+
"version": "2.6.8",
|
|
49
|
+
"app.version": "2.6.8",
|
|
50
|
+
"updated_at": "2025-08-17T03:03:21"
|
|
51
|
+
}
|
|
52
|
+
}
|