waldiez 0.5.10__py3-none-any.whl → 0.6.1__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.
Potentially problematic release.
This version of waldiez might be problematic. Click here for more details.
- waldiez/__init__.py +1 -1
- waldiez/_version.py +1 -1
- waldiez/cli.py +19 -7
- waldiez/cli_extras/jupyter.py +3 -0
- waldiez/cli_extras/runner.py +3 -1
- waldiez/cli_extras/studio.py +3 -1
- waldiez/exporter.py +9 -3
- waldiez/exporting/agent/exporter.py +15 -16
- waldiez/exporting/agent/extras/captain_agent_extras.py +6 -6
- waldiez/exporting/agent/extras/doc_agent_extras.py +6 -6
- waldiez/exporting/agent/extras/group_manager_agent_extas.py +40 -24
- waldiez/exporting/agent/extras/group_member_extras.py +6 -5
- waldiez/exporting/agent/extras/handoffs/after_work.py +2 -1
- waldiez/exporting/agent/extras/handoffs/available.py +2 -1
- waldiez/exporting/agent/extras/handoffs/condition.py +3 -2
- waldiez/exporting/agent/extras/handoffs/handoff.py +2 -1
- waldiez/exporting/agent/extras/handoffs/target.py +7 -4
- waldiez/exporting/agent/extras/rag/chroma_extras.py +27 -19
- waldiez/exporting/agent/extras/rag/mongo_extras.py +8 -8
- waldiez/exporting/agent/extras/rag/pgvector_extras.py +5 -5
- waldiez/exporting/agent/extras/rag/qdrant_extras.py +5 -4
- waldiez/exporting/agent/extras/rag/vector_db_extras.py +1 -1
- waldiez/exporting/agent/extras/rag_user_proxy_agent_extras.py +5 -7
- waldiez/exporting/agent/extras/reasoning_agent_extras.py +3 -5
- waldiez/exporting/agent/termination.py +1 -0
- waldiez/exporting/chats/exporter.py +4 -4
- waldiez/exporting/chats/processor.py +1 -2
- waldiez/exporting/chats/utils/common.py +89 -48
- waldiez/exporting/chats/utils/group.py +9 -9
- waldiez/exporting/chats/utils/nested.py +7 -7
- waldiez/exporting/chats/utils/sequential.py +1 -1
- waldiez/exporting/chats/utils/single.py +2 -2
- waldiez/exporting/core/constants.py +3 -1
- waldiez/exporting/core/content.py +7 -7
- waldiez/exporting/core/context.py +5 -3
- waldiez/exporting/core/exporter.py +5 -3
- waldiez/exporting/core/exporters.py +2 -2
- waldiez/exporting/core/extras/agent_extras/captain_extras.py +2 -2
- waldiez/exporting/core/extras/agent_extras/group_manager_extras.py +2 -2
- waldiez/exporting/core/extras/agent_extras/rag_user_extras.py +2 -2
- waldiez/exporting/core/extras/agent_extras/standard_extras.py +3 -8
- waldiez/exporting/core/extras/base.py +7 -5
- waldiez/exporting/core/extras/flow_extras.py +4 -5
- waldiez/exporting/core/extras/model_extras.py +2 -2
- waldiez/exporting/core/extras/path_resolver.py +1 -2
- waldiez/exporting/core/extras/serializer.py +13 -11
- waldiez/exporting/core/protocols.py +6 -5
- waldiez/exporting/core/result.py +25 -28
- waldiez/exporting/core/types.py +11 -10
- waldiez/exporting/core/utils/llm_config.py +4 -4
- waldiez/exporting/core/validation.py +10 -11
- waldiez/exporting/flow/execution_generator.py +99 -10
- waldiez/exporting/flow/exporter.py +2 -2
- waldiez/exporting/flow/factory.py +2 -2
- waldiez/exporting/flow/file_generator.py +4 -2
- waldiez/exporting/flow/merger.py +5 -3
- waldiez/exporting/flow/orchestrator.py +72 -2
- waldiez/exporting/flow/utils/common.py +6 -6
- waldiez/exporting/flow/utils/importing.py +7 -8
- waldiez/exporting/flow/utils/linting.py +25 -9
- waldiez/exporting/flow/utils/logging.py +5 -77
- waldiez/exporting/models/exporter.py +8 -8
- waldiez/exporting/models/processor.py +5 -5
- waldiez/exporting/tools/exporter.py +2 -2
- waldiez/exporting/tools/processor.py +7 -4
- waldiez/io/__init__.py +11 -5
- waldiez/io/_ws.py +12 -6
- waldiez/io/models/constants.py +10 -10
- waldiez/io/models/content/audio.py +1 -0
- waldiez/io/models/content/base.py +20 -18
- waldiez/io/models/content/file.py +1 -0
- waldiez/io/models/content/image.py +1 -0
- waldiez/io/models/content/text.py +1 -0
- waldiez/io/models/content/video.py +1 -0
- waldiez/io/models/user_input.py +10 -5
- waldiez/io/models/user_response.py +17 -16
- waldiez/io/mqtt.py +18 -31
- waldiez/io/redis.py +18 -22
- waldiez/io/structured.py +122 -70
- waldiez/io/utils.py +19 -10
- waldiez/io/ws.py +7 -3
- waldiez/logger.py +16 -3
- waldiez/models/agents/__init__.py +3 -0
- waldiez/models/agents/agent/agent.py +25 -17
- waldiez/models/agents/agent/agent_data.py +25 -22
- waldiez/models/agents/agent/code_execution.py +9 -11
- waldiez/models/agents/agent/termination_message.py +10 -12
- waldiez/models/agents/agent/update_system_message.py +2 -4
- waldiez/models/agents/agents.py +8 -8
- waldiez/models/agents/assistant/assistant.py +6 -3
- waldiez/models/agents/assistant/assistant_data.py +2 -2
- waldiez/models/agents/captain/captain_agent.py +7 -4
- waldiez/models/agents/captain/captain_agent_data.py +5 -7
- waldiez/models/agents/doc_agent/doc_agent.py +7 -4
- waldiez/models/agents/doc_agent/doc_agent_data.py +9 -10
- waldiez/models/agents/doc_agent/rag_query_engine.py +10 -12
- waldiez/models/agents/extra_requirements.py +3 -3
- waldiez/models/agents/group_manager/group_manager.py +12 -7
- waldiez/models/agents/group_manager/group_manager_data.py +13 -12
- waldiez/models/agents/group_manager/speakers.py +17 -19
- waldiez/models/agents/rag_user_proxy/rag_user_proxy.py +7 -4
- waldiez/models/agents/rag_user_proxy/rag_user_proxy_data.py +4 -1
- waldiez/models/agents/rag_user_proxy/retrieve_config.py +69 -63
- waldiez/models/agents/rag_user_proxy/vector_db_config.py +19 -19
- waldiez/models/agents/reasoning/reasoning_agent.py +7 -4
- waldiez/models/agents/reasoning/reasoning_agent_data.py +3 -2
- waldiez/models/agents/reasoning/reasoning_agent_reason_config.py +8 -8
- waldiez/models/agents/user_proxy/user_proxy.py +6 -3
- waldiez/models/agents/user_proxy/user_proxy_data.py +1 -1
- waldiez/models/chat/chat.py +28 -20
- waldiez/models/chat/chat_data.py +22 -21
- waldiez/models/chat/chat_message.py +9 -9
- waldiez/models/chat/chat_nested.py +9 -9
- waldiez/models/chat/chat_summary.py +6 -6
- waldiez/models/common/__init__.py +2 -0
- waldiez/models/common/ag2_version.py +2 -0
- waldiez/models/common/base.py +2 -0
- waldiez/models/common/dict_utils.py +8 -6
- waldiez/models/common/handoff.py +20 -17
- waldiez/models/common/method_utils.py +9 -7
- waldiez/models/common/naming.py +49 -0
- waldiez/models/flow/flow.py +11 -6
- waldiez/models/flow/flow_data.py +23 -17
- waldiez/models/flow/info.py +3 -3
- waldiez/models/flow/naming.py +2 -1
- waldiez/models/model/_aws.py +11 -13
- waldiez/models/model/_llm.py +8 -0
- waldiez/models/model/_price.py +2 -4
- waldiez/models/model/extra_requirements.py +1 -3
- waldiez/models/model/model.py +2 -2
- waldiez/models/model/model_data.py +21 -21
- waldiez/models/tool/extra_requirements.py +2 -4
- waldiez/models/tool/predefined/_duckduckgo.py +1 -0
- waldiez/models/tool/predefined/_email.py +4 -0
- waldiez/models/tool/predefined/_google.py +1 -0
- waldiez/models/tool/predefined/_perplexity.py +2 -1
- waldiez/models/tool/predefined/_searxng.py +2 -1
- waldiez/models/tool/predefined/_tavily.py +1 -0
- waldiez/models/tool/predefined/_wikipedia.py +2 -1
- waldiez/models/tool/predefined/_youtube.py +1 -0
- waldiez/models/tool/tool.py +8 -5
- waldiez/models/tool/tool_data.py +2 -2
- waldiez/models/waldiez.py +152 -4
- waldiez/runner.py +11 -5
- waldiez/running/async_utils.py +192 -0
- waldiez/running/base_runner.py +155 -241
- waldiez/running/dir_utils.py +52 -0
- waldiez/running/environment.py +10 -44
- waldiez/running/events_mixin.py +252 -0
- waldiez/running/exceptions.py +20 -0
- waldiez/running/gen_seq_diagram.py +18 -15
- waldiez/running/io_utils.py +216 -0
- waldiez/running/protocol.py +11 -5
- waldiez/running/requirements_mixin.py +65 -0
- waldiez/running/results_mixin.py +926 -0
- waldiez/running/standard_runner.py +24 -27
- waldiez/running/step_by_step/breakpoints_mixin.py +503 -47
- waldiez/running/step_by_step/command_handler.py +154 -0
- waldiez/running/step_by_step/events_processor.py +379 -0
- waldiez/running/step_by_step/step_by_step_models.py +425 -41
- waldiez/running/step_by_step/step_by_step_runner.py +437 -382
- waldiez/running/subprocess_runner/__base__.py +13 -8
- waldiez/running/subprocess_runner/_async_runner.py +6 -4
- waldiez/running/subprocess_runner/_sync_runner.py +11 -6
- waldiez/running/subprocess_runner/runner.py +48 -23
- waldiez/running/timeline_processor.py +1 -1
- waldiez/utils/__init__.py +2 -0
- waldiez/utils/conflict_checker.py +4 -4
- waldiez/utils/python_manager.py +415 -0
- waldiez/ws/__init__.py +8 -7
- waldiez/ws/_file_handler.py +18 -20
- waldiez/ws/_mock.py +75 -0
- waldiez/ws/cli.py +58 -10
- waldiez/ws/client_manager.py +77 -53
- waldiez/ws/errors.py +3 -0
- waldiez/ws/models.py +61 -53
- waldiez/ws/reloader.py +33 -4
- waldiez/ws/server.py +121 -52
- waldiez/ws/session_manager.py +8 -9
- waldiez/ws/session_stats.py +1 -1
- waldiez/ws/utils.py +33 -5
- {waldiez-0.5.10.dist-info → waldiez-0.6.1.dist-info}/METADATA +107 -109
- waldiez-0.6.1.dist-info/RECORD +254 -0
- waldiez/running/post_run.py +0 -180
- waldiez/running/pre_run.py +0 -159
- waldiez/running/run_results.py +0 -14
- waldiez/running/utils.py +0 -511
- waldiez-0.5.10.dist-info/RECORD +0 -248
- {waldiez-0.5.10.dist-info → waldiez-0.6.1.dist-info}/WHEEL +0 -0
- {waldiez-0.5.10.dist-info → waldiez-0.6.1.dist-info}/entry_points.txt +0 -0
- {waldiez-0.5.10.dist-info → waldiez-0.6.1.dist-info}/licenses/LICENSE +0 -0
- {waldiez-0.5.10.dist-info → waldiez-0.6.1.dist-info}/licenses/NOTICE.md +0 -0
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
# SPDX-License-Identifier: Apache-2.0.
|
|
2
2
|
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
|
|
4
|
+
# pylint: disable=unused-argument,disable=line-too-long
|
|
5
|
+
# pyright: reportUnusedParameter=false, reportUnnecessaryIsInstance=false
|
|
6
|
+
# pyright: reportDeprecated=false
|
|
7
|
+
# flake8: noqa: E501
|
|
3
8
|
"""Step-by-step execution models for Waldiez."""
|
|
4
9
|
|
|
10
|
+
import re
|
|
5
11
|
from enum import Enum
|
|
6
|
-
from typing import Annotated, Any,
|
|
12
|
+
from typing import Annotated, Any, Literal, Union
|
|
13
|
+
|
|
14
|
+
from pydantic import BaseModel, Field, ValidationInfo, field_validator
|
|
15
|
+
from typing_extensions import override
|
|
16
|
+
|
|
7
17
|
|
|
8
|
-
|
|
18
|
+
class WaldiezBreakpointType(Enum):
|
|
19
|
+
"""Types of breakpoints available."""
|
|
20
|
+
|
|
21
|
+
EVENT = "event" # Break on specific event type
|
|
22
|
+
AGENT = "agent" # Break on any event from specific agent
|
|
23
|
+
AGENT_EVENT = "agent_event" # Break on specific event from specific agent
|
|
24
|
+
ALL = "all" # Break on all events (default step mode)
|
|
9
25
|
|
|
10
26
|
|
|
11
27
|
class WaldiezDebugStepAction(Enum):
|
|
@@ -41,6 +57,364 @@ VALID_CONTROL_COMMANDS = {
|
|
|
41
57
|
}
|
|
42
58
|
|
|
43
59
|
|
|
60
|
+
class WaldiezBreakpoint(BaseModel):
|
|
61
|
+
"""Breakpoint definition with enhanced validation."""
|
|
62
|
+
|
|
63
|
+
type: WaldiezBreakpointType
|
|
64
|
+
event_type: str | None = None # Required for EVENT and AGENT_EVENT
|
|
65
|
+
agent: str | None = None # Required for AGENT and AGENT_EVENT
|
|
66
|
+
description: str | None = None # Human-readable description
|
|
67
|
+
|
|
68
|
+
# noinspection PyNestedDecorators,PyUnusedLocal
|
|
69
|
+
@field_validator("event_type")
|
|
70
|
+
@classmethod
|
|
71
|
+
def validate_event_type(
|
|
72
|
+
cls,
|
|
73
|
+
v: str | None,
|
|
74
|
+
info: ValidationInfo,
|
|
75
|
+
) -> str | None:
|
|
76
|
+
"""Validate event type format.
|
|
77
|
+
|
|
78
|
+
Parameters
|
|
79
|
+
----------
|
|
80
|
+
v : str | None
|
|
81
|
+
The event type to validate.
|
|
82
|
+
info : ValidationInfo
|
|
83
|
+
Validation context information.
|
|
84
|
+
|
|
85
|
+
Returns
|
|
86
|
+
-------
|
|
87
|
+
str | None
|
|
88
|
+
The validated event type or None if not provided.
|
|
89
|
+
|
|
90
|
+
Raises
|
|
91
|
+
------
|
|
92
|
+
ValueError
|
|
93
|
+
If the event type format is invalid.
|
|
94
|
+
"""
|
|
95
|
+
if v is None:
|
|
96
|
+
return v
|
|
97
|
+
|
|
98
|
+
# Basic validation - event types should be alphanumeric with underscores
|
|
99
|
+
if not re.match(r"^[a-zA-Z][a-zA-Z0-9_]*$", v):
|
|
100
|
+
msg = (
|
|
101
|
+
"Invalid breakpoint format. Event type must start with a letter and contain only "
|
|
102
|
+
"letters, numbers, and underscores"
|
|
103
|
+
)
|
|
104
|
+
raise ValueError(msg)
|
|
105
|
+
return v
|
|
106
|
+
|
|
107
|
+
# noinspection PyNestedDecorators,PyUnusedLocal
|
|
108
|
+
@field_validator("agent")
|
|
109
|
+
@classmethod
|
|
110
|
+
def validate_agent(
|
|
111
|
+
cls,
|
|
112
|
+
v: str | None,
|
|
113
|
+
info: ValidationInfo,
|
|
114
|
+
) -> str | None:
|
|
115
|
+
"""Validate agent name/id format.
|
|
116
|
+
|
|
117
|
+
Parameters
|
|
118
|
+
----------
|
|
119
|
+
v : str | None
|
|
120
|
+
The agent name or id to validate.
|
|
121
|
+
info : ValidationInfo
|
|
122
|
+
Validation context information.
|
|
123
|
+
|
|
124
|
+
Returns
|
|
125
|
+
-------
|
|
126
|
+
str | None
|
|
127
|
+
The validated agent or None if not provided.
|
|
128
|
+
|
|
129
|
+
Raises
|
|
130
|
+
------
|
|
131
|
+
ValueError
|
|
132
|
+
If the agent format is invalid.
|
|
133
|
+
"""
|
|
134
|
+
if v is None:
|
|
135
|
+
return v
|
|
136
|
+
|
|
137
|
+
# Agent name/id should not be empty or just whitespace
|
|
138
|
+
if not v.strip():
|
|
139
|
+
raise ValueError("Agent cannot be empty or just whitespace")
|
|
140
|
+
|
|
141
|
+
return v.strip()
|
|
142
|
+
|
|
143
|
+
@override
|
|
144
|
+
def model_post_init(self, __context: Any, /) -> None:
|
|
145
|
+
"""Validate breakpoint consistency after initialization.
|
|
146
|
+
|
|
147
|
+
Raises
|
|
148
|
+
------
|
|
149
|
+
ValueError
|
|
150
|
+
If the breakpoint configuration is invalid.
|
|
151
|
+
"""
|
|
152
|
+
if self.type == WaldiezBreakpointType.EVENT and not self.event_type:
|
|
153
|
+
raise ValueError("EVENT breakpoints require an event_type")
|
|
154
|
+
|
|
155
|
+
if self.type == WaldiezBreakpointType.AGENT and not self.agent:
|
|
156
|
+
raise ValueError("AGENT breakpoints require an agent_name")
|
|
157
|
+
|
|
158
|
+
if self.type == WaldiezBreakpointType.AGENT_EVENT:
|
|
159
|
+
if not self.event_type or not self.agent:
|
|
160
|
+
msg = (
|
|
161
|
+
"AGENT_EVENT breakpoints require both"
|
|
162
|
+
" event_type and agent_name"
|
|
163
|
+
)
|
|
164
|
+
raise ValueError(msg)
|
|
165
|
+
|
|
166
|
+
@override
|
|
167
|
+
def __hash__(self) -> int:
|
|
168
|
+
"""Get the hash value for the breakpoint."""
|
|
169
|
+
return hash((self.type, self.event_type, self.agent))
|
|
170
|
+
|
|
171
|
+
@override
|
|
172
|
+
def __str__(self) -> str:
|
|
173
|
+
"""Get the string representation for display."""
|
|
174
|
+
if self.type == WaldiezBreakpointType.EVENT:
|
|
175
|
+
return f"event:{self.event_type}"
|
|
176
|
+
if self.type == WaldiezBreakpointType.AGENT:
|
|
177
|
+
return f"agent:{self.agent}"
|
|
178
|
+
if self.type == WaldiezBreakpointType.AGENT_EVENT:
|
|
179
|
+
return f"{self.agent}:{self.event_type}"
|
|
180
|
+
# else: # ALL
|
|
181
|
+
return "all"
|
|
182
|
+
|
|
183
|
+
# pylint: disable=too-complex
|
|
184
|
+
@classmethod
|
|
185
|
+
def from_string( # noqa: C901
|
|
186
|
+
cls,
|
|
187
|
+
breakpoint_str: str,
|
|
188
|
+
) -> "WaldiezBreakpoint":
|
|
189
|
+
"""Parse breakpoint from string format with enhanced validation.
|
|
190
|
+
|
|
191
|
+
Parameters
|
|
192
|
+
----------
|
|
193
|
+
breakpoint_str : str
|
|
194
|
+
The string representation of the breakpoint.
|
|
195
|
+
|
|
196
|
+
Returns
|
|
197
|
+
-------
|
|
198
|
+
WaldiezBreakpoint
|
|
199
|
+
The parsed breakpoint object.
|
|
200
|
+
|
|
201
|
+
Raises
|
|
202
|
+
------
|
|
203
|
+
ValueError
|
|
204
|
+
If the breakpoint string format is invalid.
|
|
205
|
+
"""
|
|
206
|
+
if not breakpoint_str or not isinstance(
|
|
207
|
+
breakpoint_str,
|
|
208
|
+
str,
|
|
209
|
+
):
|
|
210
|
+
raise ValueError("Breakpoint specification cannot be empty")
|
|
211
|
+
|
|
212
|
+
breakpoint_str = breakpoint_str.strip()
|
|
213
|
+
if not breakpoint_str:
|
|
214
|
+
raise ValueError(
|
|
215
|
+
"Breakpoint specification cannot be just whitespace"
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
if breakpoint_str == "all":
|
|
219
|
+
return cls(type=WaldiezBreakpointType.ALL)
|
|
220
|
+
|
|
221
|
+
if breakpoint_str.startswith("event:"):
|
|
222
|
+
event_type = breakpoint_str[6:] # Remove "event:" prefix
|
|
223
|
+
if not event_type:
|
|
224
|
+
raise ValueError("Event type cannot be empty after 'event:'")
|
|
225
|
+
return cls(
|
|
226
|
+
type=WaldiezBreakpointType.EVENT,
|
|
227
|
+
event_type=event_type,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
if breakpoint_str.startswith("agent:"):
|
|
231
|
+
agent = breakpoint_str[6:] # Remove "agent:" prefix
|
|
232
|
+
if not agent:
|
|
233
|
+
raise ValueError(
|
|
234
|
+
"Agent identifier cannot be empty after 'agent:'"
|
|
235
|
+
)
|
|
236
|
+
return cls(
|
|
237
|
+
type=WaldiezBreakpointType.AGENT,
|
|
238
|
+
agent=agent,
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
if ":" in breakpoint_str and not breakpoint_str.startswith(
|
|
242
|
+
("event:", "agent:")
|
|
243
|
+
):
|
|
244
|
+
# Format: "agent:event_type"
|
|
245
|
+
parts = breakpoint_str.split(":", 1)
|
|
246
|
+
if len(parts) != 2:
|
|
247
|
+
raise ValueError("Invalid agent:event format")
|
|
248
|
+
|
|
249
|
+
agent, event_type = parts
|
|
250
|
+
if not agent or not event_type:
|
|
251
|
+
raise ValueError(
|
|
252
|
+
"Both agent identifier and event type must be specified"
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
return cls(
|
|
256
|
+
type=WaldiezBreakpointType.AGENT_EVENT,
|
|
257
|
+
agent=agent,
|
|
258
|
+
event_type=event_type,
|
|
259
|
+
)
|
|
260
|
+
if ":" in breakpoint_str:
|
|
261
|
+
msg = (
|
|
262
|
+
"Invalid breakpoint format. Use 'event:type', 'agent:name', "
|
|
263
|
+
"'agent:event', or 'all'"
|
|
264
|
+
)
|
|
265
|
+
raise ValueError(msg)
|
|
266
|
+
|
|
267
|
+
return cls(
|
|
268
|
+
type=WaldiezBreakpointType.EVENT,
|
|
269
|
+
event_type=breakpoint_str,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
def matches_agent(
|
|
273
|
+
self,
|
|
274
|
+
event: dict[str, Any],
|
|
275
|
+
agent_id_to_name: dict[str, str],
|
|
276
|
+
sender_only: bool,
|
|
277
|
+
) -> bool:
|
|
278
|
+
"""Check if the event's sender or recipient matches the breakpoint's agent.
|
|
279
|
+
|
|
280
|
+
Parameters
|
|
281
|
+
----------
|
|
282
|
+
event : dict[str, Any]
|
|
283
|
+
The event to check against.
|
|
284
|
+
agent_id_to_name : dict[str, str]
|
|
285
|
+
The mapping between an agent's id and its name.
|
|
286
|
+
sender_only : dict[str, Any]
|
|
287
|
+
Only check for sender match.
|
|
288
|
+
|
|
289
|
+
Returns
|
|
290
|
+
-------
|
|
291
|
+
bool
|
|
292
|
+
True if the event's sender or recipient matches the breakpoint's agent.
|
|
293
|
+
"""
|
|
294
|
+
if not self.agent:
|
|
295
|
+
return False
|
|
296
|
+
# Normalize both the event's sender/recipient and the breakpoint's agent
|
|
297
|
+
_event_sender = event.get("sender", "")
|
|
298
|
+
event_sender = agent_id_to_name.get(_event_sender, _event_sender)
|
|
299
|
+
_event_recipient = event.get("recipient", "")
|
|
300
|
+
event_recipient = agent_id_to_name.get(
|
|
301
|
+
_event_recipient, _event_recipient
|
|
302
|
+
)
|
|
303
|
+
breakpoint_agent = (
|
|
304
|
+
agent_id_to_name.get(self.agent, self.agent) if self.agent else ""
|
|
305
|
+
)
|
|
306
|
+
if not breakpoint_agent:
|
|
307
|
+
return False
|
|
308
|
+
if sender_only:
|
|
309
|
+
return breakpoint_agent == event_sender
|
|
310
|
+
return breakpoint_agent in (event_sender, event_recipient)
|
|
311
|
+
|
|
312
|
+
def matches(
|
|
313
|
+
self,
|
|
314
|
+
event: dict[str, Any],
|
|
315
|
+
agent_id_to_name: dict[str, str],
|
|
316
|
+
sender_only: bool,
|
|
317
|
+
) -> bool:
|
|
318
|
+
"""Check if this breakpoint matches the given event.
|
|
319
|
+
|
|
320
|
+
Parameters
|
|
321
|
+
----------
|
|
322
|
+
event : dict[str, Any]
|
|
323
|
+
The event to check against.
|
|
324
|
+
agent_id_to_name : dict[str, str]
|
|
325
|
+
The mapping between an agent's id and its name.
|
|
326
|
+
sender_only : dict[str, Any]
|
|
327
|
+
On agent events, only check for sender match.
|
|
328
|
+
|
|
329
|
+
Returns
|
|
330
|
+
-------
|
|
331
|
+
bool
|
|
332
|
+
True if the event matches the breakpoint, False otherwise.
|
|
333
|
+
"""
|
|
334
|
+
if self.type == WaldiezBreakpointType.ALL:
|
|
335
|
+
return True
|
|
336
|
+
|
|
337
|
+
if self.type == WaldiezBreakpointType.EVENT:
|
|
338
|
+
return event.get("type") == self.event_type
|
|
339
|
+
|
|
340
|
+
if self.type == WaldiezBreakpointType.AGENT:
|
|
341
|
+
return self.matches_agent(
|
|
342
|
+
event, agent_id_to_name, sender_only=sender_only
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
if self.type == WaldiezBreakpointType.AGENT_EVENT:
|
|
346
|
+
event_type = event.get("type", "")
|
|
347
|
+
if event_type != self.event_type:
|
|
348
|
+
return False
|
|
349
|
+
return self.matches_agent(
|
|
350
|
+
event, agent_id_to_name, sender_only=sender_only
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
# noinspection PyUnreachableCode
|
|
354
|
+
return False
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
class WaldiezDebugConfig(BaseModel):
|
|
358
|
+
"""Configuration for debug session settings."""
|
|
359
|
+
|
|
360
|
+
max_event_history: int = Field(default=1000, ge=1, le=10000)
|
|
361
|
+
auto_continue: bool = Field(default=False)
|
|
362
|
+
step_mode: bool = Field(default=True)
|
|
363
|
+
enable_stats_collection: bool = Field(default=True)
|
|
364
|
+
command_timeout_seconds: float = Field(default=300.0, gt=0)
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
class WaldiezDebugBreakpointsList(BaseModel):
|
|
368
|
+
"""Debug breakpoints message."""
|
|
369
|
+
|
|
370
|
+
type: Literal["debug_breakpoints_list"] = "debug_breakpoints_list"
|
|
371
|
+
breakpoints: (
|
|
372
|
+
list[str | WaldiezBreakpoint] | list[str] | list[WaldiezBreakpoint]
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
@property
|
|
376
|
+
def breakpoint_objects(self) -> list[WaldiezBreakpoint]:
|
|
377
|
+
"""Get all breakpoints as WaldiezBreakpoint objects."""
|
|
378
|
+
result: list[WaldiezBreakpoint] = []
|
|
379
|
+
for bp in self.breakpoints:
|
|
380
|
+
if isinstance(bp, str):
|
|
381
|
+
try:
|
|
382
|
+
result.append(WaldiezBreakpoint.from_string(bp))
|
|
383
|
+
except ValueError:
|
|
384
|
+
continue
|
|
385
|
+
else:
|
|
386
|
+
result.append(bp)
|
|
387
|
+
return result
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
class WaldiezDebugBreakpointAdded(BaseModel):
|
|
391
|
+
"""Debug breakpoint added message."""
|
|
392
|
+
|
|
393
|
+
type: Literal["debug_breakpoint_added"] = "debug_breakpoint_added"
|
|
394
|
+
breakpoint: str | WaldiezBreakpoint
|
|
395
|
+
|
|
396
|
+
@property
|
|
397
|
+
def breakpoint_object(self) -> WaldiezBreakpoint:
|
|
398
|
+
"""Get breakpoint as WaldiezBreakpoint object."""
|
|
399
|
+
if isinstance(self.breakpoint, str):
|
|
400
|
+
return WaldiezBreakpoint.from_string(self.breakpoint)
|
|
401
|
+
return self.breakpoint
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
class WaldiezDebugBreakpointRemoved(BaseModel):
|
|
405
|
+
"""Debug breakpoint removed message."""
|
|
406
|
+
|
|
407
|
+
type: Literal["debug_breakpoint_removed"] = "debug_breakpoint_removed"
|
|
408
|
+
breakpoint: str | WaldiezBreakpoint
|
|
409
|
+
|
|
410
|
+
@property
|
|
411
|
+
def breakpoint_object(self) -> WaldiezBreakpoint:
|
|
412
|
+
"""Get breakpoint as WaldiezBreakpoint object."""
|
|
413
|
+
if isinstance(self.breakpoint, str):
|
|
414
|
+
return WaldiezBreakpoint.from_string(self.breakpoint)
|
|
415
|
+
return self.breakpoint
|
|
416
|
+
|
|
417
|
+
|
|
44
418
|
class WaldiezDebugHelpCommand(BaseModel):
|
|
45
419
|
"""Help command information."""
|
|
46
420
|
|
|
@@ -84,14 +458,14 @@ class WaldiezDebugEventInfo(BaseModel):
|
|
|
84
458
|
"""Debug event info message."""
|
|
85
459
|
|
|
86
460
|
type: Literal["debug_event_info"] = "debug_event_info"
|
|
87
|
-
event:
|
|
461
|
+
event: dict[str, Any]
|
|
88
462
|
|
|
89
463
|
|
|
90
464
|
class WaldiezDebugStats(BaseModel):
|
|
91
465
|
"""Debug stats message."""
|
|
92
466
|
|
|
93
467
|
type: Literal["debug_stats"] = "debug_stats"
|
|
94
|
-
stats:
|
|
468
|
+
stats: dict[str, Any]
|
|
95
469
|
|
|
96
470
|
|
|
97
471
|
class WaldiezDebugHelp(BaseModel):
|
|
@@ -108,28 +482,6 @@ class WaldiezDebugError(BaseModel):
|
|
|
108
482
|
error: str
|
|
109
483
|
|
|
110
484
|
|
|
111
|
-
class WaldiezDebugBreakpointsList(BaseModel):
|
|
112
|
-
"""Debug breakpoints message."""
|
|
113
|
-
|
|
114
|
-
type: Literal["debug_breakpoints_list"] = "debug_breakpoints_list"
|
|
115
|
-
breakpoints: list[str] # Event types
|
|
116
|
-
# Optional: Could extend to include agent+event combinations
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
class WaldiezDebugBreakpointAdded(BaseModel):
|
|
120
|
-
"""Debug breakpoint added message."""
|
|
121
|
-
|
|
122
|
-
type: Literal["debug_breakpoint_added"] = "debug_breakpoint_added"
|
|
123
|
-
breakpoint: str
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
class WaldiezDebugBreakpointRemoved(BaseModel):
|
|
127
|
-
"""Debug breakpoint removed message."""
|
|
128
|
-
|
|
129
|
-
type: Literal["debug_breakpoint_removed"] = "debug_breakpoint_removed"
|
|
130
|
-
breakpoint: str
|
|
131
|
-
|
|
132
|
-
|
|
133
485
|
class WaldiezDebugBreakpointCleared(BaseModel):
|
|
134
486
|
"""Debug breakpoint cleared message."""
|
|
135
487
|
|
|
@@ -137,6 +489,7 @@ class WaldiezDebugBreakpointCleared(BaseModel):
|
|
|
137
489
|
message: str
|
|
138
490
|
|
|
139
491
|
|
|
492
|
+
# pylint: disable=invalid-name
|
|
140
493
|
WaldiezDebugMessage = Annotated[
|
|
141
494
|
Union[
|
|
142
495
|
WaldiezDebugPrint,
|
|
@@ -165,44 +518,69 @@ class WaldiezDebugMessageWrapper(BaseModel):
|
|
|
165
518
|
HELP_MESSAGE = WaldiezDebugHelp(
|
|
166
519
|
help=[
|
|
167
520
|
WaldiezDebugHelpCommandGroup(
|
|
168
|
-
title="Commands",
|
|
521
|
+
title="Basic Commands",
|
|
169
522
|
commands=[
|
|
170
523
|
WaldiezDebugHelpCommand(
|
|
171
|
-
cmds=["continue", "c"], desc="Continue to the next step
|
|
524
|
+
cmds=["continue", "c"], desc="Continue to the next step"
|
|
172
525
|
),
|
|
173
526
|
WaldiezDebugHelpCommand(
|
|
174
|
-
cmds=["step", "s"], desc="Step through the next event
|
|
527
|
+
cmds=["step", "s"], desc="Step through the next event"
|
|
175
528
|
),
|
|
176
529
|
WaldiezDebugHelpCommand(
|
|
177
|
-
cmds=["run", "r"], desc="Run without stopping
|
|
530
|
+
cmds=["run", "r"], desc="Run without stopping"
|
|
178
531
|
),
|
|
179
532
|
WaldiezDebugHelpCommand(
|
|
180
|
-
cmds=["quit", "q"], desc="Quit the debugger
|
|
533
|
+
cmds=["quit", "q"], desc="Quit the debugger"
|
|
181
534
|
),
|
|
182
535
|
WaldiezDebugHelpCommand(
|
|
183
|
-
cmds=["info", "i"], desc="Show detailed event information
|
|
536
|
+
cmds=["info", "i"], desc="Show detailed event information"
|
|
184
537
|
),
|
|
185
538
|
WaldiezDebugHelpCommand(
|
|
186
|
-
cmds=["help", "h"], desc="Show this help message
|
|
539
|
+
cmds=["help", "h"], desc="Show this help message"
|
|
187
540
|
),
|
|
188
541
|
WaldiezDebugHelpCommand(
|
|
189
|
-
cmds=["stats", "st"], desc="Show execution statistics
|
|
542
|
+
cmds=["stats", "st"], desc="Show execution statistics"
|
|
190
543
|
),
|
|
544
|
+
],
|
|
545
|
+
),
|
|
546
|
+
WaldiezDebugHelpCommandGroup(
|
|
547
|
+
title="Breakpoint Commands",
|
|
548
|
+
commands=[
|
|
191
549
|
WaldiezDebugHelpCommand(
|
|
192
550
|
cmds=["add_breakpoint", "ab"],
|
|
193
|
-
desc="Add breakpoint
|
|
551
|
+
desc="Add breakpoint. Usage: 'ab [spec]' where spec is 'event:<type>', 'agent:<name>', '<name>:<event>', or 'all'",
|
|
194
552
|
),
|
|
195
553
|
WaldiezDebugHelpCommand(
|
|
196
554
|
cmds=["remove_breakpoint", "rb"],
|
|
197
|
-
desc="Remove breakpoint
|
|
555
|
+
desc="Remove breakpoint. Usage: 'rb [spec]' with same format as add",
|
|
198
556
|
),
|
|
199
557
|
WaldiezDebugHelpCommand(
|
|
200
|
-
cmds=["list_breakpoints", "lb"],
|
|
201
|
-
desc="List all breakpoints.",
|
|
558
|
+
cmds=["list_breakpoints", "lb"], desc="List all breakpoints"
|
|
202
559
|
),
|
|
203
560
|
WaldiezDebugHelpCommand(
|
|
204
561
|
cmds=["clear_breakpoints", "cb"],
|
|
205
|
-
desc="Clear all breakpoints
|
|
562
|
+
desc="Clear all breakpoints",
|
|
563
|
+
),
|
|
564
|
+
],
|
|
565
|
+
),
|
|
566
|
+
WaldiezDebugHelpCommandGroup(
|
|
567
|
+
title="Breakpoint Examples",
|
|
568
|
+
commands=[
|
|
569
|
+
WaldiezDebugHelpCommand(
|
|
570
|
+
desc="'ab' - Add breakpoint for the current event type"
|
|
571
|
+
),
|
|
572
|
+
WaldiezDebugHelpCommand(
|
|
573
|
+
desc="'ab event:tool_call' - Break on all 'tool_call' events"
|
|
574
|
+
),
|
|
575
|
+
WaldiezDebugHelpCommand(
|
|
576
|
+
desc="'ab agent:user' - Break on any event from 'user' agent"
|
|
577
|
+
),
|
|
578
|
+
WaldiezDebugHelpCommand(
|
|
579
|
+
desc="'ab assistant:tool_call' - Break on 'tool_call' events from 'assistant'"
|
|
580
|
+
),
|
|
581
|
+
WaldiezDebugHelpCommand(desc="'ab all' - Break on all events"),
|
|
582
|
+
WaldiezDebugHelpCommand(
|
|
583
|
+
desc="'rb event:tool_call' - Remove 'tool_call' event breakpoint"
|
|
206
584
|
),
|
|
207
585
|
],
|
|
208
586
|
),
|
|
@@ -213,10 +591,16 @@ HELP_MESSAGE = WaldiezDebugHelp(
|
|
|
213
591
|
desc="Press Enter alone to continue (same as 'c')"
|
|
214
592
|
),
|
|
215
593
|
WaldiezDebugHelpCommand(
|
|
216
|
-
desc="Use (s)tep to go through events one by one
|
|
594
|
+
desc="Use (s)tep to go through events one by one"
|
|
595
|
+
),
|
|
596
|
+
WaldiezDebugHelpCommand(
|
|
597
|
+
desc="Use (r)un to continue without stopping"
|
|
598
|
+
),
|
|
599
|
+
WaldiezDebugHelpCommand(
|
|
600
|
+
desc="Set specific breakpoints to avoid noise: 'ab event:message'"
|
|
217
601
|
),
|
|
218
602
|
WaldiezDebugHelpCommand(
|
|
219
|
-
desc="
|
|
603
|
+
desc="Check (st)ats regularly to monitor progress"
|
|
220
604
|
),
|
|
221
605
|
],
|
|
222
606
|
),
|