pygpt-net 2.6.60__py3-none-any.whl → 2.6.62__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 +14 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/controller/chat/common.py +115 -6
- pygpt_net/controller/chat/input.py +4 -1
- pygpt_net/controller/chat/response.py +8 -2
- pygpt_net/controller/presets/presets.py +121 -6
- pygpt_net/controller/settings/editor.py +0 -15
- pygpt_net/controller/settings/profile.py +16 -4
- pygpt_net/controller/settings/workdir.py +30 -5
- pygpt_net/controller/theme/common.py +4 -2
- pygpt_net/controller/theme/markdown.py +4 -7
- pygpt_net/controller/theme/theme.py +2 -1
- pygpt_net/controller/ui/ui.py +32 -7
- pygpt_net/core/agents/custom/__init__.py +7 -1
- pygpt_net/core/agents/custom/llama_index/factory.py +17 -6
- pygpt_net/core/agents/custom/llama_index/runner.py +52 -4
- pygpt_net/core/agents/custom/llama_index/utils.py +12 -1
- pygpt_net/core/agents/custom/router.py +45 -6
- pygpt_net/core/agents/custom/runner.py +11 -5
- pygpt_net/core/agents/custom/schema.py +3 -1
- pygpt_net/core/agents/custom/utils.py +13 -1
- pygpt_net/core/agents/runners/llama_workflow.py +65 -5
- pygpt_net/core/agents/runners/openai_workflow.py +2 -1
- pygpt_net/core/db/viewer.py +11 -5
- pygpt_net/core/node_editor/graph.py +18 -9
- pygpt_net/core/node_editor/models.py +9 -2
- pygpt_net/core/node_editor/types.py +15 -1
- pygpt_net/core/presets/presets.py +216 -29
- pygpt_net/core/render/markdown/parser.py +0 -2
- pygpt_net/core/render/web/renderer.py +76 -11
- pygpt_net/data/config/config.json +5 -6
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/config/settings.json +2 -38
- pygpt_net/data/css/style.dark.css +18 -0
- pygpt_net/data/css/style.light.css +20 -1
- pygpt_net/data/locale/locale.de.ini +66 -1
- pygpt_net/data/locale/locale.en.ini +64 -3
- pygpt_net/data/locale/locale.es.ini +66 -1
- pygpt_net/data/locale/locale.fr.ini +66 -1
- pygpt_net/data/locale/locale.it.ini +66 -1
- pygpt_net/data/locale/locale.pl.ini +67 -2
- pygpt_net/data/locale/locale.uk.ini +66 -1
- pygpt_net/data/locale/locale.zh.ini +66 -1
- pygpt_net/data/locale/plugin.cmd_system.en.ini +62 -66
- pygpt_net/item/ctx.py +23 -1
- pygpt_net/provider/agents/llama_index/flow_from_schema.py +2 -2
- pygpt_net/provider/agents/llama_index/workflow/codeact.py +9 -6
- pygpt_net/provider/agents/llama_index/workflow/openai.py +38 -11
- pygpt_net/provider/agents/llama_index/workflow/planner.py +36 -16
- pygpt_net/provider/agents/llama_index/workflow/supervisor.py +60 -10
- pygpt_net/provider/agents/openai/agent.py +3 -1
- pygpt_net/provider/agents/openai/agent_b2b.py +13 -9
- pygpt_net/provider/agents/openai/agent_planner.py +6 -2
- pygpt_net/provider/agents/openai/agent_with_experts.py +4 -1
- pygpt_net/provider/agents/openai/agent_with_experts_feedback.py +4 -2
- pygpt_net/provider/agents/openai/agent_with_feedback.py +4 -2
- pygpt_net/provider/agents/openai/evolve.py +6 -2
- pygpt_net/provider/agents/openai/supervisor.py +3 -1
- pygpt_net/provider/api/openai/agents/response.py +1 -0
- pygpt_net/provider/core/config/patch.py +18 -1
- pygpt_net/provider/core/config/patches/patch_before_2_6_42.py +0 -6
- pygpt_net/tools/agent_builder/tool.py +48 -26
- pygpt_net/tools/agent_builder/ui/dialogs.py +36 -28
- pygpt_net/ui/__init__.py +2 -4
- pygpt_net/ui/dialog/about.py +58 -38
- pygpt_net/ui/dialog/db.py +142 -3
- pygpt_net/ui/dialog/preset.py +47 -8
- pygpt_net/ui/layout/toolbox/presets.py +64 -16
- pygpt_net/ui/main.py +2 -2
- pygpt_net/ui/widget/dialog/confirm.py +27 -3
- pygpt_net/ui/widget/dialog/db.py +0 -0
- pygpt_net/ui/widget/draw/painter.py +90 -1
- pygpt_net/ui/widget/lists/preset.py +908 -60
- pygpt_net/ui/widget/node_editor/command.py +10 -10
- pygpt_net/ui/widget/node_editor/config.py +157 -0
- pygpt_net/ui/widget/node_editor/editor.py +223 -153
- pygpt_net/ui/widget/node_editor/item.py +12 -11
- pygpt_net/ui/widget/node_editor/node.py +246 -13
- pygpt_net/ui/widget/node_editor/view.py +179 -63
- pygpt_net/ui/widget/tabs/output.py +1 -1
- pygpt_net/ui/widget/textarea/input.py +157 -23
- pygpt_net/utils.py +114 -2
- {pygpt_net-2.6.60.dist-info → pygpt_net-2.6.62.dist-info}/METADATA +26 -100
- {pygpt_net-2.6.60.dist-info → pygpt_net-2.6.62.dist-info}/RECORD +86 -85
- {pygpt_net-2.6.60.dist-info → pygpt_net-2.6.62.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.60.dist-info → pygpt_net-2.6.62.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.60.dist-info → pygpt_net-2.6.62.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.26 15:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from __future__ import annotations
|
|
@@ -34,6 +34,7 @@ from llama_index.core.agent.workflow import (
|
|
|
34
34
|
ToolCallResult,
|
|
35
35
|
AgentStream,
|
|
36
36
|
AgentOutput,
|
|
37
|
+
AgentInput, # ensure AgentInput propagation includes agent name
|
|
37
38
|
)
|
|
38
39
|
|
|
39
40
|
# v12/v13 compatibility imports
|
|
@@ -167,6 +168,9 @@ class OpenAIWorkflowAgent(Workflow):
|
|
|
167
168
|
self._on_stop = on_stop
|
|
168
169
|
self.verbose = verbose
|
|
169
170
|
|
|
171
|
+
# human-friendly display name propagated to UI via workflow events
|
|
172
|
+
self._display_agent_name: str = "FunctionAgent"
|
|
173
|
+
|
|
170
174
|
# construct FunctionAgent once, will override tools/system_prompt/memory per run
|
|
171
175
|
self._agent = FunctionAgent(
|
|
172
176
|
name="OpenAIWorkflowAgent",
|
|
@@ -287,9 +291,13 @@ class OpenAIWorkflowAgent(Workflow):
|
|
|
287
291
|
:param total: Total number of steps (optional)
|
|
288
292
|
:param meta: Optional metadata dictionary for the step event
|
|
289
293
|
"""
|
|
294
|
+
# Always include agent_name so UI can set it before first token arrives.
|
|
295
|
+
m = dict(meta or {})
|
|
296
|
+
m.setdefault("agent_name", self._display_agent_name)
|
|
297
|
+
|
|
290
298
|
try:
|
|
291
299
|
if StepEvent is not None:
|
|
292
|
-
ctx.write_event_to_stream(StepEvent(name=name, index=index, total=total, meta=
|
|
300
|
+
ctx.write_event_to_stream(StepEvent(name=name, index=index, total=total, meta=m))
|
|
293
301
|
return
|
|
294
302
|
except Exception:
|
|
295
303
|
pass
|
|
@@ -300,9 +308,9 @@ class OpenAIWorkflowAgent(Workflow):
|
|
|
300
308
|
AgentStream(
|
|
301
309
|
delta="",
|
|
302
310
|
response="",
|
|
303
|
-
current_agent_name=
|
|
311
|
+
current_agent_name=self._display_agent_name,
|
|
304
312
|
tool_calls=[],
|
|
305
|
-
raw={"StepEvent": {"name": name, "index": index, "total": total, "meta":
|
|
313
|
+
raw={"StepEvent": {"name": name, "index": index, "total": total, "meta": m}},
|
|
306
314
|
)
|
|
307
315
|
)
|
|
308
316
|
except Exception:
|
|
@@ -499,14 +507,14 @@ class OpenAIWorkflowAgent(Workflow):
|
|
|
499
507
|
self,
|
|
500
508
|
ctx: Context,
|
|
501
509
|
text: str,
|
|
502
|
-
agent_name: str = "
|
|
510
|
+
agent_name: str = "FunctionAgent"
|
|
503
511
|
):
|
|
504
512
|
"""
|
|
505
513
|
Emit text to the context stream, handling validation errors gracefully.
|
|
506
514
|
|
|
507
515
|
:param ctx: Context for the workflow
|
|
508
516
|
:param text: Text to emit to the stream
|
|
509
|
-
:param agent_name: Name of the agent to set in the event (default: "
|
|
517
|
+
:param agent_name: Name of the agent to set in the event (default: "FunctionAgent")
|
|
510
518
|
"""
|
|
511
519
|
try:
|
|
512
520
|
ctx.write_event_to_stream(AgentStream(delta=text))
|
|
@@ -561,12 +569,31 @@ class OpenAIWorkflowAgent(Workflow):
|
|
|
561
569
|
pass
|
|
562
570
|
return last_answer
|
|
563
571
|
|
|
572
|
+
if isinstance(e, AgentInput):
|
|
573
|
+
# Ensure the input event also carries the display name for UI
|
|
574
|
+
try:
|
|
575
|
+
e.current_agent_name = self._display_agent_name
|
|
576
|
+
except Exception:
|
|
577
|
+
pass
|
|
578
|
+
ctx.write_event_to_stream(e)
|
|
579
|
+
continue
|
|
580
|
+
|
|
564
581
|
if isinstance(e, AgentStream):
|
|
565
582
|
if getattr(e, "delta", None):
|
|
566
583
|
has_stream = True
|
|
567
|
-
|
|
584
|
+
# Always enforce agent name for consistency in UI
|
|
585
|
+
try:
|
|
586
|
+
e.current_agent_name = self._display_agent_name
|
|
587
|
+
except Exception:
|
|
588
|
+
# If immutable, rebuild a compatible event object
|
|
568
589
|
try:
|
|
569
|
-
e
|
|
590
|
+
e = AgentStream(
|
|
591
|
+
delta=getattr(e, "delta", ""),
|
|
592
|
+
response=getattr(e, "response", ""),
|
|
593
|
+
current_agent_name=self._display_agent_name,
|
|
594
|
+
tool_calls=getattr(e, "tool_calls", []),
|
|
595
|
+
raw=getattr(e, "raw", {}),
|
|
596
|
+
)
|
|
570
597
|
except Exception:
|
|
571
598
|
pass
|
|
572
599
|
ctx.write_event_to_stream(e)
|
|
@@ -581,9 +608,9 @@ class OpenAIWorkflowAgent(Workflow):
|
|
|
581
608
|
AgentStream(
|
|
582
609
|
delta=content,
|
|
583
610
|
response=content,
|
|
584
|
-
current_agent_name=
|
|
585
|
-
tool_calls=e
|
|
586
|
-
raw=e
|
|
611
|
+
current_agent_name=self._display_agent_name,
|
|
612
|
+
tool_calls=getattr(e, "tool_calls", []),
|
|
613
|
+
raw=getattr(e, "raw", {}),
|
|
587
614
|
)
|
|
588
615
|
)
|
|
589
616
|
continue
|
|
@@ -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.26 15:20:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import List, Optional, Callable
|
|
@@ -134,6 +134,10 @@ class PlannerWorkflow(Workflow):
|
|
|
134
134
|
self._memory_char_limit = memory_char_limit
|
|
135
135
|
self._on_stop = on_stop
|
|
136
136
|
|
|
137
|
+
# Human-friendly display names propagated to UI via workflow events.
|
|
138
|
+
self._display_planner_name: str = "PlannerWorkflow"
|
|
139
|
+
self._display_executor_name: str = "FunctionAgent"
|
|
140
|
+
|
|
137
141
|
self._executor = FunctionAgent(
|
|
138
142
|
name="PlannerExecutor",
|
|
139
143
|
description="Executes planner sub-tasks using available tools.",
|
|
@@ -184,9 +188,13 @@ class PlannerWorkflow(Workflow):
|
|
|
184
188
|
:param total: The total number of steps (optional).
|
|
185
189
|
:param meta: Additional metadata for the step (optional).
|
|
186
190
|
"""
|
|
191
|
+
# Always pass a friendly agent name; for 'subtask' we signal the executor agent to the UI.
|
|
192
|
+
m = dict(meta or {})
|
|
193
|
+
m.setdefault("agent_name", self._display_executor_name if name == "subtask" else self._display_planner_name)
|
|
194
|
+
|
|
187
195
|
try:
|
|
188
196
|
ctx.write_event_to_stream(
|
|
189
|
-
StepEvent(name=name, index=index, total=total, meta=
|
|
197
|
+
StepEvent(name=name, index=index, total=total, meta=m)
|
|
190
198
|
)
|
|
191
199
|
except Exception:
|
|
192
200
|
# fallback for older versions of AgentStream
|
|
@@ -195,9 +203,9 @@ class PlannerWorkflow(Workflow):
|
|
|
195
203
|
AgentStream(
|
|
196
204
|
delta="",
|
|
197
205
|
response="",
|
|
198
|
-
current_agent_name="
|
|
206
|
+
current_agent_name=m.get("agent_name", self._display_planner_name),
|
|
199
207
|
tool_calls=[],
|
|
200
|
-
raw={"StepEvent": {"name": name, "index": index, "total": total, "meta":
|
|
208
|
+
raw={"StepEvent": {"name": name, "index": index, "total": total, "meta": m}}
|
|
201
209
|
)
|
|
202
210
|
)
|
|
203
211
|
except Exception:
|
|
@@ -308,9 +316,8 @@ class PlannerWorkflow(Workflow):
|
|
|
308
316
|
:param text: The text message to emit.
|
|
309
317
|
:param agent_name: The name of the agent emitting the text (default: "PlannerWorkflow").
|
|
310
318
|
"""
|
|
319
|
+
# Always try to include agent name; fall back to minimal event for older validators.
|
|
311
320
|
try:
|
|
312
|
-
ctx.write_event_to_stream(AgentStream(delta=text))
|
|
313
|
-
except ValidationError:
|
|
314
321
|
ctx.write_event_to_stream(
|
|
315
322
|
AgentStream(
|
|
316
323
|
delta=text,
|
|
@@ -320,6 +327,8 @@ class PlannerWorkflow(Workflow):
|
|
|
320
327
|
raw={},
|
|
321
328
|
)
|
|
322
329
|
)
|
|
330
|
+
except ValidationError:
|
|
331
|
+
ctx.write_event_to_stream(AgentStream(delta=text))
|
|
323
332
|
|
|
324
333
|
def _to_text(self, resp) -> str:
|
|
325
334
|
"""
|
|
@@ -443,9 +452,18 @@ class PlannerWorkflow(Workflow):
|
|
|
443
452
|
if delta:
|
|
444
453
|
has_stream = True
|
|
445
454
|
stream_buf.append(str(delta))
|
|
446
|
-
|
|
455
|
+
# Always enforce a stable display name for executor events.
|
|
456
|
+
try:
|
|
457
|
+
e.current_agent_name = self._display_executor_name
|
|
458
|
+
except Exception:
|
|
447
459
|
try:
|
|
448
|
-
e
|
|
460
|
+
e = AgentStream(
|
|
461
|
+
delta=getattr(e, "delta", ""),
|
|
462
|
+
response=getattr(e, "response", ""),
|
|
463
|
+
current_agent_name=self._display_executor_name,
|
|
464
|
+
tool_calls=getattr(e, "tool_calls", []),
|
|
465
|
+
raw=getattr(e, "raw", {}),
|
|
466
|
+
)
|
|
449
467
|
except Exception:
|
|
450
468
|
pass
|
|
451
469
|
ctx.write_event_to_stream(e)
|
|
@@ -460,7 +478,7 @@ class PlannerWorkflow(Workflow):
|
|
|
460
478
|
AgentStream(
|
|
461
479
|
delta=last_answer,
|
|
462
480
|
response=last_answer,
|
|
463
|
-
current_agent_name=
|
|
481
|
+
current_agent_name=self._display_executor_name,
|
|
464
482
|
tool_calls=e.tool_calls,
|
|
465
483
|
raw=e.raw,
|
|
466
484
|
)
|
|
@@ -484,7 +502,7 @@ class PlannerWorkflow(Workflow):
|
|
|
484
502
|
try:
|
|
485
503
|
return await _stream()
|
|
486
504
|
except Exception as ex:
|
|
487
|
-
await self._emit_text(ctx, f"\n`Sub-task failed: {ex}`")
|
|
505
|
+
await self._emit_text(ctx, f"\n`Sub-task failed: {ex}`", agent_name=self._display_executor_name)
|
|
488
506
|
return last_answer or ("".join(stream_buf).strip() if stream_buf else "")
|
|
489
507
|
|
|
490
508
|
@step
|
|
@@ -520,7 +538,7 @@ class PlannerWorkflow(Workflow):
|
|
|
520
538
|
f"Expected output: {st.expected_output}\n"
|
|
521
539
|
f"Dependencies: {st.dependencies}\n\n"
|
|
522
540
|
)
|
|
523
|
-
await self._emit_text(ctx, "\n".join(lines))
|
|
541
|
+
await self._emit_text(ctx, "\n".join(lines), agent_name=self._display_planner_name)
|
|
524
542
|
return PlanReady(plan=plan, query=ev.query)
|
|
525
543
|
|
|
526
544
|
@step
|
|
@@ -537,7 +555,7 @@ class PlannerWorkflow(Workflow):
|
|
|
537
555
|
last_answer = ""
|
|
538
556
|
completed: list[tuple[str, str]] = [] # (name, output)
|
|
539
557
|
|
|
540
|
-
await self._emit_text(ctx, "\n\n`Executing plan...`")
|
|
558
|
+
await self._emit_text(ctx, "\n\n`Executing plan...`", agent_name=self._display_planner_name)
|
|
541
559
|
|
|
542
560
|
for i, st in enumerate(plan_sub_tasks, 1):
|
|
543
561
|
self._emit_step_event(
|
|
@@ -550,6 +568,8 @@ class PlannerWorkflow(Workflow):
|
|
|
550
568
|
"expected_output": st.expected_output,
|
|
551
569
|
"dependencies": st.dependencies,
|
|
552
570
|
"input": st.input,
|
|
571
|
+
# Signal that the next stream will come from the executor.
|
|
572
|
+
"agent_name": self._display_executor_name,
|
|
553
573
|
},
|
|
554
574
|
)
|
|
555
575
|
|
|
@@ -561,10 +581,10 @@ class PlannerWorkflow(Workflow):
|
|
|
561
581
|
|
|
562
582
|
# stop callback
|
|
563
583
|
if self._stopped():
|
|
564
|
-
await self._emit_text(ctx, "\n`Plan execution stopped.`")
|
|
584
|
+
await self._emit_text(ctx, "\n`Plan execution stopped.`", agent_name=self._display_planner_name)
|
|
565
585
|
return FinalEvent(result=last_answer or "Plan execution stopped.")
|
|
566
586
|
|
|
567
|
-
await self._emit_text(ctx, header)
|
|
587
|
+
await self._emit_text(ctx, header, agent_name=self._display_planner_name)
|
|
568
588
|
|
|
569
589
|
# build context for sub-task
|
|
570
590
|
ctx_text = self._build_context_for_subtask(
|
|
@@ -588,7 +608,7 @@ class PlannerWorkflow(Workflow):
|
|
|
588
608
|
sub_answer = await self._run_subtask(ctx, composed_prompt)
|
|
589
609
|
sub_answer = (sub_answer or "").strip()
|
|
590
610
|
|
|
591
|
-
await self._emit_text(ctx, f"\n\n`Finished Sub Task {i}/{total}: {st.name}`")
|
|
611
|
+
await self._emit_text(ctx, f"\n\n`Finished Sub Task {i}/{total}: {st.name}`", agent_name=self._display_planner_name)
|
|
592
612
|
|
|
593
613
|
# save completed sub-task
|
|
594
614
|
completed.append((st.name, sub_answer))
|
|
@@ -597,5 +617,5 @@ class PlannerWorkflow(Workflow):
|
|
|
597
617
|
|
|
598
618
|
# TODO: refine plan if needed
|
|
599
619
|
|
|
600
|
-
await self._emit_text(ctx, "\n\n`Plan execution finished.`")
|
|
620
|
+
await self._emit_text(ctx, "\n\n`Plan execution finished.`", agent_name=self._display_planner_name)
|
|
601
621
|
return FinalEvent(result=last_answer or "Plan finished.")
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# workflow/supervisor.py
|
|
2
|
+
|
|
1
3
|
#!/usr/bin/env python3
|
|
2
4
|
# -*- coding: utf-8 -*-
|
|
3
5
|
# ================================================== #
|
|
@@ -6,11 +8,11 @@
|
|
|
6
8
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
|
7
9
|
# MIT License #
|
|
8
10
|
# Created By : Marcin Szczygliński #
|
|
9
|
-
# Updated Date: 2025.
|
|
11
|
+
# Updated Date: 2025.09.26 22:25:00 #
|
|
10
12
|
# ================================================== #
|
|
11
13
|
|
|
12
14
|
import re
|
|
13
|
-
from typing import Optional, Literal, List
|
|
15
|
+
from typing import Optional, Literal, List, Callable, Any
|
|
14
16
|
from pydantic import BaseModel, ValidationError
|
|
15
17
|
from llama_index.core.workflow import Workflow, Context, StartEvent, StopEvent, Event, step
|
|
16
18
|
from llama_index.core.agent.workflow import FunctionAgent, AgentStream
|
|
@@ -173,8 +175,6 @@ class SupervisorWorkflow(Workflow):
|
|
|
173
175
|
:param agent_name: The name of the agent emitting the text (default: "PlannerWorkflow").
|
|
174
176
|
"""
|
|
175
177
|
try:
|
|
176
|
-
ctx.write_event_to_stream(AgentStream(delta=text))
|
|
177
|
-
except ValidationError:
|
|
178
178
|
ctx.write_event_to_stream(
|
|
179
179
|
AgentStream(
|
|
180
180
|
delta=text,
|
|
@@ -184,11 +184,47 @@ class SupervisorWorkflow(Workflow):
|
|
|
184
184
|
raw={},
|
|
185
185
|
)
|
|
186
186
|
)
|
|
187
|
+
except ValidationError:
|
|
188
|
+
ctx.write_event_to_stream(AgentStream(delta=text))
|
|
189
|
+
|
|
190
|
+
async def _emit_step(self, ctx: Context, agent_name: str, index: int, total: int, meta: Optional[dict] = None):
|
|
191
|
+
"""
|
|
192
|
+
Emit a StepEvent that your runner uses to split UI into blocks.
|
|
193
|
+
Mirrors the behavior used by the schema-driven workflow.
|
|
194
|
+
"""
|
|
195
|
+
from pygpt_net.provider.agents.llama_index.workflow.events import StepEvent
|
|
196
|
+
try:
|
|
197
|
+
ctx.write_event_to_stream(
|
|
198
|
+
StepEvent(
|
|
199
|
+
name="next",
|
|
200
|
+
index=index,
|
|
201
|
+
total=total,
|
|
202
|
+
meta={"agent_name": agent_name, **(meta or {})},
|
|
203
|
+
)
|
|
204
|
+
)
|
|
205
|
+
except Exception:
|
|
206
|
+
pass
|
|
207
|
+
|
|
208
|
+
async def _run_muted(self, ctx: Context, awaitable) -> Any:
|
|
209
|
+
"""
|
|
210
|
+
Execute an agent call while muting all events sent to ctx.
|
|
211
|
+
Matches schema-style emission: we control all UI events ourselves.
|
|
212
|
+
"""
|
|
213
|
+
orig_write = ctx.write_event_to_stream
|
|
214
|
+
|
|
215
|
+
def _noop(ev: Any) -> None:
|
|
216
|
+
return None
|
|
217
|
+
|
|
218
|
+
ctx.write_event_to_stream = _noop
|
|
219
|
+
try:
|
|
220
|
+
return await awaitable
|
|
221
|
+
finally:
|
|
222
|
+
ctx.write_event_to_stream = orig_write
|
|
187
223
|
|
|
188
224
|
@step
|
|
189
225
|
async def supervisor_step(self, ctx: Context, ev: InputEvent) -> ExecuteEvent | OutputEvent:
|
|
190
226
|
"""
|
|
191
|
-
Supervisor step
|
|
227
|
+
Supervisor step: run Supervisor silently, then emit exactly one UI block like schema.
|
|
192
228
|
|
|
193
229
|
:param ctx: Context for the workflow
|
|
194
230
|
:param ev: InputEvent containing the user's message and context.
|
|
@@ -206,21 +242,33 @@ class SupervisorWorkflow(Workflow):
|
|
|
206
242
|
"Return ONE JSON following the schema.\n</control>"
|
|
207
243
|
)
|
|
208
244
|
sup_input = "\n".join(parts)
|
|
209
|
-
|
|
245
|
+
|
|
246
|
+
# Run Supervisor with stream muted to avoid extra blocks/finishes.
|
|
247
|
+
sup_resp = await self._run_muted(ctx, self._supervisor.run(user_msg=sup_input, memory=self._supervisor_memory))
|
|
210
248
|
directive = parse_supervisor_json(str(sup_resp))
|
|
211
249
|
|
|
250
|
+
# Final/ask_user/max_rounds -> emit single Supervisor block and stop (schema-like).
|
|
212
251
|
if directive.action == "final":
|
|
252
|
+
await self._emit_step(ctx, agent_name=self._supervisor.name, index=ev.round_idx + 1, total=ev.max_rounds)
|
|
213
253
|
await self._emit_text(ctx, f"\n\n{directive.final_answer or str(sup_resp)}", agent_name=self._supervisor.name)
|
|
214
254
|
return OutputEvent(status="final", final_answer=directive.final_answer or str(sup_resp), rounds_used=ev.round_idx)
|
|
255
|
+
|
|
215
256
|
if directive.action == "ask_user" and ev.stop_on_ask_user:
|
|
257
|
+
await self._emit_step(ctx, agent_name=self._supervisor.name, index=ev.round_idx + 1, total=ev.max_rounds)
|
|
216
258
|
q = directive.question or "I need more information, please clarify."
|
|
217
259
|
await self._emit_text(ctx, f"\n\n{q}", agent_name=self._supervisor.name)
|
|
218
260
|
return OutputEvent(status="ask_user", final_answer=q, rounds_used=ev.round_idx)
|
|
261
|
+
|
|
219
262
|
if ev.round_idx >= ev.max_rounds:
|
|
263
|
+
await self._emit_step(ctx, agent_name=self._supervisor.name, index=ev.round_idx + 1, total=ev.max_rounds)
|
|
220
264
|
await self._emit_text(ctx, "\n\nMax rounds exceeded.", agent_name=self._supervisor.name)
|
|
221
265
|
return OutputEvent(status="max_rounds", final_answer="Exceeded maximum number of iterations.", rounds_used=ev.round_idx)
|
|
222
266
|
|
|
267
|
+
# Emit exactly one Supervisor block with the instruction (no JSON leakage, no duplicates).
|
|
223
268
|
instruction = (directive.instruction or "").strip() or "Perform a step that gets closest to fulfilling the DoD."
|
|
269
|
+
await self._emit_step(ctx, agent_name=self._supervisor.name, index=ev.round_idx + 1, total=ev.max_rounds)
|
|
270
|
+
await self._emit_text(ctx, f"\n\n{instruction}", agent_name=self._supervisor.name)
|
|
271
|
+
|
|
224
272
|
return ExecuteEvent(
|
|
225
273
|
instruction=instruction,
|
|
226
274
|
round_idx=ev.round_idx,
|
|
@@ -232,17 +280,19 @@ class SupervisorWorkflow(Workflow):
|
|
|
232
280
|
@step
|
|
233
281
|
async def worker_step(self, ctx: Context, ev: ExecuteEvent) -> InputEvent:
|
|
234
282
|
"""
|
|
235
|
-
Worker step
|
|
283
|
+
Worker step: run Worker silently and emit exactly one UI block like schema.
|
|
236
284
|
|
|
237
285
|
:param ctx: Context for the workflow
|
|
238
286
|
:param ev: ExecuteEvent containing the instruction and context.
|
|
239
287
|
:return: InputEvent for the next round or final output.
|
|
240
288
|
"""
|
|
289
|
+
# Run Worker with stream muted; we will emit a single block with the final text.
|
|
241
290
|
worker_input = f"Instruction from Supervisor:\n{ev.instruction}\n"
|
|
242
|
-
await self.
|
|
291
|
+
worker_resp = await self._run_muted(ctx, self._worker.run(user_msg=worker_input, memory=self._worker_memory))
|
|
243
292
|
|
|
244
|
-
|
|
245
|
-
await self.
|
|
293
|
+
# Emit exactly one Worker block (schema-style: one AgentStream per node).
|
|
294
|
+
await self._emit_step(ctx, agent_name=self._worker.name, index=ev.round_idx + 1, total=ev.max_rounds)
|
|
295
|
+
await self._emit_text(ctx, f"\n\n{str(worker_resp)}", agent_name=self._worker.name)
|
|
246
296
|
|
|
247
297
|
return InputEvent(
|
|
248
298
|
user_msg="",
|
|
@@ -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.26 17:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import Dict, Any, Tuple, Optional
|
|
@@ -133,6 +133,8 @@ class Agent(BaseAgent):
|
|
|
133
133
|
"preset": preset,
|
|
134
134
|
"is_expert_call": False,
|
|
135
135
|
}
|
|
136
|
+
|
|
137
|
+
ctx.set_agent_name(agent.name)
|
|
136
138
|
# call computer agent if computer tool is enabled
|
|
137
139
|
if is_computer_tool(**tool_kwargs):
|
|
138
140
|
computer = LocalComputer(window)
|
|
@@ -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.26 17:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import copy
|
|
@@ -265,6 +265,7 @@ class Agent(BaseAgent):
|
|
|
265
265
|
break
|
|
266
266
|
|
|
267
267
|
kwargs = self.prepare_model(model, window, previous_response_id, kwargs)
|
|
268
|
+
ctx.set_agent_name(bot_1.name)
|
|
268
269
|
result = await Runner.run(
|
|
269
270
|
bot_1,
|
|
270
271
|
**kwargs
|
|
@@ -296,6 +297,7 @@ class Agent(BaseAgent):
|
|
|
296
297
|
# -------- bot 2 --------
|
|
297
298
|
kwargs["input"] = input_items
|
|
298
299
|
kwargs = self.prepare_model(model_2, window, previous_response_id, kwargs)
|
|
300
|
+
ctx.set_agent_name(bot_2.name)
|
|
299
301
|
result = await Runner.run(
|
|
300
302
|
bot_2,
|
|
301
303
|
**kwargs
|
|
@@ -329,6 +331,7 @@ class Agent(BaseAgent):
|
|
|
329
331
|
# -------- bot 1 --------
|
|
330
332
|
kwargs["input"] = input_items
|
|
331
333
|
kwargs = self.prepare_model(model, window, previous_response_id, kwargs)
|
|
334
|
+
ctx.set_agent_name(bot_1.name)
|
|
332
335
|
result = Runner.run_streamed(
|
|
333
336
|
bot_1,
|
|
334
337
|
**kwargs
|
|
@@ -337,13 +340,13 @@ class Agent(BaseAgent):
|
|
|
337
340
|
handler.reset()
|
|
338
341
|
|
|
339
342
|
# bot 1 title
|
|
340
|
-
title = f"\n\n**{bot_1_name}**\n\n"
|
|
341
|
-
ctx.stream = title
|
|
343
|
+
# title = f"\n\n**{bot_1_name}**\n\n"
|
|
344
|
+
# ctx.stream = title
|
|
342
345
|
bridge.on_step(ctx, begin)
|
|
343
346
|
begin = False
|
|
344
347
|
handler.begin = begin
|
|
345
|
-
if not use_partial_ctx:
|
|
346
|
-
handler.to_buffer(title)
|
|
348
|
+
# if not use_partial_ctx:
|
|
349
|
+
# handler.to_buffer(title)
|
|
347
350
|
async for event in result.stream_events():
|
|
348
351
|
if bridge.stopped():
|
|
349
352
|
result.cancel()
|
|
@@ -376,6 +379,7 @@ class Agent(BaseAgent):
|
|
|
376
379
|
# -------- bot 2 --------
|
|
377
380
|
kwargs["input"] = input_items
|
|
378
381
|
kwargs = self.prepare_model(model_2, window, previous_response_id, kwargs)
|
|
382
|
+
ctx.set_agent_name(bot_2.name)
|
|
379
383
|
result = Runner.run_streamed(
|
|
380
384
|
bot_2,
|
|
381
385
|
**kwargs
|
|
@@ -383,11 +387,11 @@ class Agent(BaseAgent):
|
|
|
383
387
|
handler.reset()
|
|
384
388
|
|
|
385
389
|
# bot 2 title
|
|
386
|
-
title = f"\n\n**{bot_2_name}**\n\n"
|
|
387
|
-
ctx.stream = title
|
|
390
|
+
# title = f"\n\n**{bot_2_name}**\n\n"
|
|
391
|
+
# ctx.stream = title
|
|
388
392
|
bridge.on_step(ctx, False)
|
|
389
|
-
if not use_partial_ctx:
|
|
390
|
-
handler.to_buffer(title)
|
|
393
|
+
# if not use_partial_ctx:
|
|
394
|
+
# handler.to_buffer(title)
|
|
391
395
|
async for event in result.stream_events():
|
|
392
396
|
if bridge.stopped():
|
|
393
397
|
result.cancel()
|
|
@@ -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.26 17:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from dataclasses import dataclass
|
|
@@ -153,7 +153,7 @@ class Agent(BaseAgent):
|
|
|
153
153
|
:return: Agent provider instance
|
|
154
154
|
"""
|
|
155
155
|
kwargs = {
|
|
156
|
-
"name": "
|
|
156
|
+
"name": "Evaluator",
|
|
157
157
|
"instructions": instructions,
|
|
158
158
|
"model": window.core.agents.provider.get_openai_model(model),
|
|
159
159
|
"output_type": EvaluationFeedback,
|
|
@@ -313,6 +313,7 @@ class Agent(BaseAgent):
|
|
|
313
313
|
if not stream:
|
|
314
314
|
while True:
|
|
315
315
|
kwargs["input"] = input_items
|
|
316
|
+
ctx.set_agent_name(agent.name)
|
|
316
317
|
if bridge.stopped():
|
|
317
318
|
bridge.on_stop(ctx)
|
|
318
319
|
break
|
|
@@ -333,6 +334,7 @@ class Agent(BaseAgent):
|
|
|
333
334
|
break
|
|
334
335
|
|
|
335
336
|
evaluator_result = await Runner.run(evaluator, input_items)
|
|
337
|
+
ctx.set_agent_name(evaluator.name)
|
|
336
338
|
result: EvaluationFeedback = evaluator_result.final_output
|
|
337
339
|
|
|
338
340
|
print(f"Evaluator score: {result.score}")
|
|
@@ -366,6 +368,7 @@ class Agent(BaseAgent):
|
|
|
366
368
|
handler = StreamHandler(window, bridge, final_output)
|
|
367
369
|
while True:
|
|
368
370
|
kwargs["input"] = input_items
|
|
371
|
+
ctx.set_agent_name(agent.name)
|
|
369
372
|
result = Runner.run_streamed(
|
|
370
373
|
agent,
|
|
371
374
|
**kwargs
|
|
@@ -386,6 +389,7 @@ class Agent(BaseAgent):
|
|
|
386
389
|
break
|
|
387
390
|
|
|
388
391
|
input_items = result.to_input_list()
|
|
392
|
+
ctx.set_agent_name(evaluator.name)
|
|
389
393
|
evaluator_result = await Runner.run(evaluator, input_items)
|
|
390
394
|
result: EvaluationFeedback = evaluator_result.final_output
|
|
391
395
|
|
|
@@ -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.26 17:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import Dict, Any, Tuple, Optional
|
|
@@ -123,6 +123,7 @@ class Agent(BaseAgent):
|
|
|
123
123
|
agent_kwargs["handoffs"] = experts
|
|
124
124
|
|
|
125
125
|
agent = self.get_agent(window, agent_kwargs)
|
|
126
|
+
ctx.set_agent_name(agent.name)
|
|
126
127
|
|
|
127
128
|
kwargs = {
|
|
128
129
|
"input": messages,
|
|
@@ -137,6 +138,7 @@ class Agent(BaseAgent):
|
|
|
137
138
|
agent,
|
|
138
139
|
**kwargs
|
|
139
140
|
)
|
|
141
|
+
ctx.set_agent_name(agent.name)
|
|
140
142
|
final_output, last_response_id = window.core.api.openai.responses.unpack_agent_response(result, ctx)
|
|
141
143
|
response_id = result.last_response_id
|
|
142
144
|
if verbose:
|
|
@@ -152,6 +154,7 @@ class Agent(BaseAgent):
|
|
|
152
154
|
result.cancel()
|
|
153
155
|
bridge.on_stop(ctx)
|
|
154
156
|
break
|
|
157
|
+
ctx.set_agent_name(agent.name)
|
|
155
158
|
final_output, response_id = handler.handle(event, ctx)
|
|
156
159
|
|
|
157
160
|
return ctx, final_output, response_id
|
|
@@ -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.26 17:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from dataclasses import dataclass
|
|
@@ -119,7 +119,7 @@ class Agent(BaseAgent):
|
|
|
119
119
|
:return: Agent provider instance
|
|
120
120
|
"""
|
|
121
121
|
kwargs = {
|
|
122
|
-
"name": "
|
|
122
|
+
"name": "Evaluator",
|
|
123
123
|
"instructions": instructions,
|
|
124
124
|
"model": window.core.agents.provider.get_openai_model(model),
|
|
125
125
|
"output_type": EvaluationFeedback,
|
|
@@ -212,6 +212,7 @@ class Agent(BaseAgent):
|
|
|
212
212
|
bridge.on_stop(ctx)
|
|
213
213
|
break
|
|
214
214
|
|
|
215
|
+
ctx.set_agent_name(agent.name)
|
|
215
216
|
result = await Runner.run(
|
|
216
217
|
agent,
|
|
217
218
|
**kwargs
|
|
@@ -259,6 +260,7 @@ class Agent(BaseAgent):
|
|
|
259
260
|
handler = StreamHandler(window, bridge)
|
|
260
261
|
while True:
|
|
261
262
|
kwargs["input"] = input_items
|
|
263
|
+
ctx.set_agent_name(agent.name)
|
|
262
264
|
result = Runner.run_streamed(
|
|
263
265
|
agent,
|
|
264
266
|
**kwargs
|
|
@@ -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.26 17:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from dataclasses import dataclass
|
|
@@ -119,7 +119,7 @@ class Agent(BaseAgent):
|
|
|
119
119
|
:return: Agent provider instance
|
|
120
120
|
"""
|
|
121
121
|
kwargs = {
|
|
122
|
-
"name": "
|
|
122
|
+
"name": "Evaluator",
|
|
123
123
|
"instructions": instructions,
|
|
124
124
|
"model": window.core.agents.provider.get_openai_model(model),
|
|
125
125
|
"output_type": EvaluationFeedback,
|
|
@@ -212,6 +212,7 @@ class Agent(BaseAgent):
|
|
|
212
212
|
bridge.on_stop(ctx)
|
|
213
213
|
break
|
|
214
214
|
|
|
215
|
+
ctx.set_agent_name(agent.name)
|
|
215
216
|
result = await Runner.run(
|
|
216
217
|
agent,
|
|
217
218
|
**kwargs
|
|
@@ -259,6 +260,7 @@ class Agent(BaseAgent):
|
|
|
259
260
|
handler = StreamHandler(window, bridge)
|
|
260
261
|
while True:
|
|
261
262
|
kwargs["input"] = input_items
|
|
263
|
+
ctx.set_agent_name(agent.name)
|
|
262
264
|
result = Runner.run_streamed(
|
|
263
265
|
agent,
|
|
264
266
|
**kwargs
|