waldiez 0.5.10__py3-none-any.whl → 0.6.0__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.

Files changed (62) hide show
  1. waldiez/_version.py +1 -1
  2. waldiez/cli.py +1 -0
  3. waldiez/exporting/agent/exporter.py +6 -6
  4. waldiez/exporting/agent/extras/group_manager_agent_extas.py +6 -1
  5. waldiez/exporting/agent/extras/handoffs/after_work.py +1 -0
  6. waldiez/exporting/agent/extras/handoffs/available.py +1 -0
  7. waldiez/exporting/agent/extras/handoffs/handoff.py +1 -0
  8. waldiez/exporting/agent/extras/handoffs/target.py +1 -0
  9. waldiez/exporting/agent/termination.py +1 -0
  10. waldiez/exporting/core/constants.py +3 -1
  11. waldiez/exporting/core/extras/serializer.py +12 -10
  12. waldiez/exporting/core/types.py +1 -0
  13. waldiez/exporting/core/utils/llm_config.py +2 -2
  14. waldiez/exporting/flow/execution_generator.py +1 -0
  15. waldiez/exporting/flow/utils/common.py +1 -1
  16. waldiez/exporting/flow/utils/importing.py +1 -1
  17. waldiez/exporting/flow/utils/logging.py +3 -75
  18. waldiez/io/__init__.py +3 -1
  19. waldiez/io/_ws.py +2 -0
  20. waldiez/io/structured.py +81 -28
  21. waldiez/io/utils.py +16 -10
  22. waldiez/io/ws.py +2 -2
  23. waldiez/models/agents/agent/agent.py +2 -1
  24. waldiez/models/chat/chat.py +1 -0
  25. waldiez/models/chat/chat_data.py +0 -2
  26. waldiez/models/common/base.py +2 -0
  27. waldiez/models/common/handoff.py +2 -0
  28. waldiez/models/common/method_utils.py +2 -0
  29. waldiez/models/model/_llm.py +3 -0
  30. waldiez/models/tool/predefined/_email.py +3 -0
  31. waldiez/models/tool/predefined/_perplexity.py +1 -1
  32. waldiez/models/tool/predefined/_searxng.py +1 -1
  33. waldiez/models/tool/predefined/_wikipedia.py +1 -1
  34. waldiez/running/base_runner.py +81 -20
  35. waldiez/running/post_run.py +6 -0
  36. waldiez/running/pre_run.py +167 -45
  37. waldiez/running/standard_runner.py +5 -5
  38. waldiez/running/step_by_step/breakpoints_mixin.py +368 -44
  39. waldiez/running/step_by_step/command_handler.py +151 -0
  40. waldiez/running/step_by_step/events_processor.py +199 -0
  41. waldiez/running/step_by_step/step_by_step_models.py +358 -41
  42. waldiez/running/step_by_step/step_by_step_runner.py +358 -353
  43. waldiez/running/subprocess_runner/__base__.py +4 -7
  44. waldiez/running/subprocess_runner/_async_runner.py +1 -1
  45. waldiez/running/subprocess_runner/_sync_runner.py +5 -4
  46. waldiez/running/subprocess_runner/runner.py +9 -0
  47. waldiez/running/utils.py +116 -2
  48. waldiez/ws/__init__.py +8 -7
  49. waldiez/ws/_file_handler.py +0 -2
  50. waldiez/ws/_mock.py +74 -0
  51. waldiez/ws/cli.py +27 -3
  52. waldiez/ws/client_manager.py +45 -29
  53. waldiez/ws/models.py +18 -1
  54. waldiez/ws/reloader.py +23 -2
  55. waldiez/ws/server.py +47 -8
  56. waldiez/ws/utils.py +29 -4
  57. {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/METADATA +53 -44
  58. {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/RECORD +62 -59
  59. {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/WHEEL +0 -0
  60. {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/entry_points.txt +0 -0
  61. {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/licenses/LICENSE +0 -0
  62. {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/licenses/NOTICE.md +0 -0
@@ -0,0 +1,199 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ # pylint: disable=unused-argument,no-self-use
4
+ """Command handler for step-by-step execution."""
5
+
6
+ from typing import TYPE_CHECKING, Any, Union
7
+
8
+ if TYPE_CHECKING:
9
+ from autogen.events.base_event import BaseEvent # type: ignore
10
+ from autogen.messages.base_message import BaseMessage # type: ignore
11
+
12
+ # noinspection PyUnusedImports
13
+ from .step_by_step_runner import WaldiezStepByStepRunner
14
+
15
+
16
+ # pylint: disable=too-few-public-methods
17
+ class EventProcessor:
18
+ """Processes events for the step-by-step runner."""
19
+
20
+ def __init__(self, runner: "WaldiezStepByStepRunner"):
21
+ self.runner = runner
22
+
23
+ def process_event(
24
+ self, event: Union["BaseEvent", "BaseMessage"]
25
+ ) -> dict[str, Any]:
26
+ """Shared logic for both sync and async event processing.
27
+
28
+ Parameters
29
+ ----------
30
+ event : BaseEvent | BaseMessage
31
+ The event to process.
32
+
33
+ Returns
34
+ -------
35
+ dict[str, Any]
36
+ The result of processing the event.
37
+ """
38
+ self.runner.event_plus_one()
39
+ self.runner.current_event = event
40
+
41
+ if self.runner.is_stop_requested():
42
+ return {"action": "stop", "reason": "stop_requested"}
43
+
44
+ event_info = self._create_event_info(event)
45
+ self._update_participant_info(event_info)
46
+ self._manage_event_history(event_info)
47
+ self._check_for_input_request(event_info)
48
+
49
+ should_break = self.runner.should_break_on_event(
50
+ event, self.runner.step_mode
51
+ )
52
+
53
+ return {
54
+ "action": "continue",
55
+ "should_break": should_break,
56
+ "event_info": event_info,
57
+ }
58
+
59
+ def _create_event_info(
60
+ self, event: Union["BaseEvent", "BaseMessage"]
61
+ ) -> dict[str, Any]:
62
+ """Create event info dictionary from event object.
63
+
64
+ Parameters
65
+ ----------
66
+ event : BaseEvent | BaseMessage
67
+ The event to convert to info dict.
68
+
69
+ Returns
70
+ -------
71
+ dict[str, Any]
72
+ Event information dictionary.
73
+ """
74
+ event_info = event.model_dump(
75
+ mode="json", exclude_none=True, fallback=str
76
+ )
77
+ event_info["count"] = self.runner.event_count
78
+ event_info["sender"] = getattr(event, "sender", self.runner.last_sender)
79
+ event_info["recipient"] = getattr(
80
+ event, "recipient", self.runner.last_recipient
81
+ )
82
+ return event_info
83
+
84
+ def _update_participant_info(self, event_info: dict[str, Any]) -> None:
85
+ """Update sender and recipient information in event_info.
86
+
87
+ Parameters
88
+ ----------
89
+ event_info : dict[str, Any]
90
+ Event information dictionary to update.
91
+ """
92
+ if not event_info["sender"] or not event_info["recipient"]:
93
+ self._extract_participants_from_content(event_info)
94
+
95
+ self._handle_group_chat_speaker(event_info)
96
+ self._extract_participants_from_direct_content(event_info)
97
+
98
+ # Update last known participants
99
+ self.runner.last_sender = event_info["sender"]
100
+ self.runner.last_recipient = event_info["recipient"]
101
+
102
+ def _extract_participants_from_content(
103
+ self, event_info: dict[str, Any]
104
+ ) -> None:
105
+ """Extract sender/recipient from nested content structure.
106
+
107
+ Parameters
108
+ ----------
109
+ event_info : dict[str, Any]
110
+ Event information dictionary to update.
111
+ """
112
+ content = event_info.get("content", {})
113
+ if (
114
+ isinstance(content, dict)
115
+ and "chat_info" in content
116
+ and isinstance(content["chat_info"], dict)
117
+ ):
118
+ content = content.get("chat_info", {}) # pyright: ignore
119
+
120
+ if not event_info["sender"] and "sender" in content:
121
+ event_info["sender"] = content["sender"]
122
+ if not event_info["recipient"] and "recipient" in content:
123
+ event_info["recipient"] = content["recipient"]
124
+
125
+ def _handle_group_chat_speaker(self, event_info: dict[str, Any]) -> None:
126
+ """Handle speaker information for group chat events.
127
+
128
+ Parameters
129
+ ----------
130
+ event_info : dict[str, Any]
131
+ Event information dictionary to update.
132
+ """
133
+ if (
134
+ event_info.get("type") == "group_chat_run_chat"
135
+ and "content" in event_info
136
+ and isinstance(event_info["content"], dict)
137
+ ):
138
+ content = event_info.get("content", {})
139
+ speaker = content.get("speaker")
140
+ if isinstance(speaker, str) and speaker:
141
+ event_info["sender"] = speaker
142
+
143
+ def _extract_participants_from_direct_content(
144
+ self, event_info: dict[str, Any]
145
+ ) -> None:
146
+ """Extract sender/recipient directly from content dictionary.
147
+
148
+ Parameters
149
+ ----------
150
+ event_info : dict[str, Any]
151
+ Event information dictionary to update.
152
+ """
153
+ if "content" in event_info and isinstance(event_info["content"], dict):
154
+ content = event_info.get("content", {})
155
+
156
+ sender = content.get("sender", "")
157
+ if isinstance(sender, str) and sender:
158
+ event_info["sender"] = sender
159
+
160
+ recipient = content.get("recipient", "")
161
+ if isinstance(recipient, str) and recipient:
162
+ event_info["recipient"] = recipient
163
+
164
+ def _manage_event_history(self, event_info: dict[str, Any]) -> None:
165
+ """Add event to history and manage history size limits.
166
+
167
+ Parameters
168
+ ----------
169
+ event_info : dict[str, Any]
170
+ Event information to add to history.
171
+ """
172
+ self.runner.add_to_history(event_info)
173
+ self._trim_history_if_needed()
174
+
175
+ def _trim_history_if_needed(self) -> None:
176
+ """Remove oldest events from history if over size limit."""
177
+ current_history = self.runner.event_history
178
+ if len(current_history) > self.runner.max_event_history:
179
+ excess = len(current_history) - self.runner.max_event_history
180
+ for _ in range(excess):
181
+ self.runner.pop_event()
182
+
183
+ def _check_for_input_request(self, event_info: dict[str, Any]) -> None:
184
+ """Swap participant names if we have an input request."""
185
+ if (
186
+ event_info["type"] in ("input_request", "debug_input_request")
187
+ and "sender" in event_info
188
+ and "recipient" in event_info
189
+ ):
190
+ # swap them,
191
+ # before:
192
+ # "recipient" is the user (the one received the input request),
193
+ # make her the "sender" (the one typing...)
194
+ sender = event_info["sender"]
195
+ recipient = event_info["recipient"]
196
+ event_info["sender"] = recipient
197
+ event_info["recipient"] = sender
198
+ self.runner.last_sender = recipient
199
+ self.runner.last_recipient = sender
@@ -1,11 +1,23 @@
1
1
  # SPDX-License-Identifier: Apache-2.0.
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ # pylint: disable=unused-argument,disable=line-too-long
4
+ # flake8: noqa: E501
3
5
  """Step-by-step execution models for Waldiez."""
4
6
 
7
+ import re
5
8
  from enum import Enum
6
- from typing import Annotated, Any, Dict, Literal, Union
9
+ from typing import Annotated, Any, Literal, Union
7
10
 
8
- from pydantic import BaseModel, Field
11
+ from pydantic import BaseModel, Field, ValidationInfo, field_validator
12
+
13
+
14
+ class WaldiezBreakpointType(Enum):
15
+ """Types of breakpoints available."""
16
+
17
+ EVENT = "event" # Break on specific event type
18
+ AGENT = "agent" # Break on any event from specific agent
19
+ AGENT_EVENT = "agent_event" # Break on specific event from specific agent
20
+ ALL = "all" # Break on all events (default step mode)
9
21
 
10
22
 
11
23
  class WaldiezDebugStepAction(Enum):
@@ -41,6 +53,302 @@ VALID_CONTROL_COMMANDS = {
41
53
  }
42
54
 
43
55
 
56
+ class WaldiezBreakpoint(BaseModel):
57
+ """Breakpoint definition with enhanced validation."""
58
+
59
+ type: WaldiezBreakpointType
60
+ event_type: str | None = None # Required for EVENT and AGENT_EVENT
61
+ agent_name: str | None = None # Required for AGENT and AGENT_EVENT
62
+ description: str | None = None # Human-readable description
63
+
64
+ # noinspection PyNestedDecorators,PyUnusedLocal
65
+ @field_validator("event_type")
66
+ @classmethod
67
+ def validate_event_type(
68
+ cls,
69
+ v: str | None,
70
+ info: ValidationInfo,
71
+ ) -> str | None:
72
+ """Validate event type format.
73
+
74
+ Parameters
75
+ ----------
76
+ v : str | None
77
+ The event type to validate.
78
+ info : ValidationInfo
79
+ Validation context information.
80
+
81
+ Returns
82
+ -------
83
+ str | None
84
+ The validated event type or None if not provided.
85
+
86
+ Raises
87
+ ------
88
+ ValueError
89
+ If the event type format is invalid.
90
+ """
91
+ if v is None:
92
+ return v
93
+
94
+ # Basic validation - event types should be alphanumeric with underscores
95
+ if not re.match(r"^[a-zA-Z][a-zA-Z0-9_]*$", v):
96
+ raise ValueError(
97
+ "Invalid breakpoint format. Event type must start with a letter and contain only "
98
+ "letters, numbers, and underscores"
99
+ )
100
+ return v
101
+
102
+ # noinspection PyNestedDecorators,PyUnusedLocal
103
+ @field_validator("agent_name")
104
+ @classmethod
105
+ def validate_agent_name(
106
+ cls,
107
+ v: str | None,
108
+ info: ValidationInfo,
109
+ ) -> str | None:
110
+ """Validate agent name format.
111
+
112
+ Parameters
113
+ ----------
114
+ v : str | None
115
+ The agent name to validate.
116
+ info : ValidationInfo
117
+ Validation context information.
118
+
119
+ Returns
120
+ -------
121
+ str | None
122
+ The validated agent name or None if not provided.
123
+
124
+ Raises
125
+ ------
126
+ ValueError
127
+ If the agent name format is invalid.
128
+ """
129
+ if v is None:
130
+ return v
131
+
132
+ # Agent names should not be empty or just whitespace
133
+ if not v.strip():
134
+ raise ValueError("Agent name cannot be empty or just whitespace")
135
+
136
+ return v.strip()
137
+
138
+ def model_post_init(self, __context: Any, /) -> None:
139
+ """Validate breakpoint consistency after initialization.
140
+
141
+ Raises
142
+ ------
143
+ ValueError
144
+ If the breakpoint configuration is invalid.
145
+ """
146
+ if self.type == WaldiezBreakpointType.EVENT and not self.event_type:
147
+ raise ValueError("EVENT breakpoints require an event_type")
148
+
149
+ if self.type == WaldiezBreakpointType.AGENT and not self.agent_name:
150
+ raise ValueError("AGENT breakpoints require an agent_name")
151
+
152
+ if self.type == WaldiezBreakpointType.AGENT_EVENT:
153
+ if not self.event_type or not self.agent_name:
154
+ raise ValueError(
155
+ "AGENT_EVENT breakpoints require both"
156
+ " event_type and agent_name"
157
+ )
158
+
159
+ def __hash__(self) -> int:
160
+ """Get the hash value for the breakpoint."""
161
+ return hash((self.type, self.event_type, self.agent_name))
162
+
163
+ def __str__(self) -> str:
164
+ """Get the string representation for display."""
165
+ if self.type == WaldiezBreakpointType.EVENT:
166
+ return f"event:{self.event_type}"
167
+ if self.type == WaldiezBreakpointType.AGENT:
168
+ return f"agent:{self.agent_name}"
169
+ if self.type == WaldiezBreakpointType.AGENT_EVENT:
170
+ return f"{self.agent_name}:{self.event_type}"
171
+ # else: # ALL
172
+ return "all"
173
+
174
+ # pylint: disable=too-complex
175
+ @classmethod
176
+ def from_string( # noqa: C901
177
+ cls,
178
+ breakpoint_str: str,
179
+ ) -> "WaldiezBreakpoint":
180
+ """Parse breakpoint from string format with enhanced validation.
181
+
182
+ Parameters
183
+ ----------
184
+ breakpoint_str : str
185
+ The string representation of the breakpoint.
186
+
187
+ Returns
188
+ -------
189
+ WaldiezBreakpoint
190
+ The parsed breakpoint object.
191
+
192
+ Raises
193
+ ------
194
+ ValueError
195
+ If the breakpoint string format is invalid.
196
+ """
197
+ if not breakpoint_str or not isinstance( # pyright: ignore
198
+ breakpoint_str,
199
+ str,
200
+ ):
201
+ raise ValueError("Breakpoint specification cannot be empty")
202
+
203
+ breakpoint_str = breakpoint_str.strip()
204
+ if not breakpoint_str:
205
+ raise ValueError(
206
+ "Breakpoint specification cannot be just whitespace"
207
+ )
208
+
209
+ if breakpoint_str == "all":
210
+ return cls(type=WaldiezBreakpointType.ALL)
211
+
212
+ if breakpoint_str.startswith("event:"):
213
+ event_type = breakpoint_str[6:] # Remove "event:" prefix
214
+ if not event_type:
215
+ raise ValueError("Event type cannot be empty after 'event:'")
216
+ return cls(type=WaldiezBreakpointType.EVENT, event_type=event_type)
217
+
218
+ if breakpoint_str.startswith("agent:"):
219
+ agent_name = breakpoint_str[6:] # Remove "agent:" prefix
220
+ if not agent_name:
221
+ raise ValueError("Agent name cannot be empty after 'agent:'")
222
+ return cls(type=WaldiezBreakpointType.AGENT, agent_name=agent_name)
223
+
224
+ if ":" in breakpoint_str and not breakpoint_str.startswith(
225
+ ("event:", "agent:")
226
+ ):
227
+ # Format: "agent_name:event_type"
228
+ parts = breakpoint_str.split(":", 1)
229
+ if len(parts) != 2:
230
+ raise ValueError("Invalid agent:event format")
231
+
232
+ agent_name, event_type = parts
233
+ if not agent_name or not event_type:
234
+ raise ValueError(
235
+ "Both agent name and event type must be specified"
236
+ )
237
+
238
+ return cls(
239
+ type=WaldiezBreakpointType.AGENT_EVENT,
240
+ agent_name=agent_name,
241
+ event_type=event_type,
242
+ )
243
+
244
+ # Default to event type - but validate it's reasonable
245
+ if ":" in breakpoint_str:
246
+ raise ValueError(
247
+ "Invalid breakpoint format. Use 'event:type', 'agent:name', "
248
+ "'agent:event', or 'all'"
249
+ )
250
+
251
+ return cls(type=WaldiezBreakpointType.EVENT, event_type=breakpoint_str)
252
+
253
+ def matches(self, event: dict[str, Any]) -> bool:
254
+ """Check if this breakpoint matches the given event.
255
+
256
+ Parameters
257
+ ----------
258
+ event : dict[str, Any]
259
+ The event to check against.
260
+
261
+ Returns
262
+ -------
263
+ bool
264
+ True if the event matches the breakpoint, False otherwise.
265
+ """
266
+ if self.type == WaldiezBreakpointType.ALL:
267
+ return True
268
+
269
+ if self.type == WaldiezBreakpointType.EVENT:
270
+ return event.get("type") == self.event_type
271
+
272
+ if self.type == WaldiezBreakpointType.AGENT:
273
+ return (
274
+ event.get("sender") == self.agent_name
275
+ or event.get("recipient") == self.agent_name
276
+ )
277
+
278
+ if self.type == WaldiezBreakpointType.AGENT_EVENT:
279
+ return event.get("type") == self.event_type and (
280
+ event.get("sender") == self.agent_name
281
+ or event.get("recipient") == self.agent_name
282
+ )
283
+
284
+ # noinspection PyUnreachableCode
285
+ return False
286
+
287
+
288
+ # Enhanced configuration class for runtime settings
289
+ class WaldiezDebugConfig(BaseModel):
290
+ """Configuration for debug session settings."""
291
+
292
+ max_event_history: int = Field(default=1000, ge=1, le=10000)
293
+ auto_continue: bool = Field(default=False)
294
+ step_mode: bool = Field(default=True)
295
+ enable_stats_collection: bool = Field(default=True)
296
+ command_timeout_seconds: float = Field(default=300.0, gt=0)
297
+
298
+
299
+ # Rest of the existing message classes remain the same...
300
+ class WaldiezDebugBreakpointsList(BaseModel):
301
+ """Debug breakpoints message."""
302
+
303
+ type: Literal["debug_breakpoints_list"] = "debug_breakpoints_list"
304
+ breakpoints: (
305
+ list[str | WaldiezBreakpoint] | list[str] | list[WaldiezBreakpoint]
306
+ )
307
+
308
+ @property
309
+ def breakpoint_objects(self) -> list[WaldiezBreakpoint]:
310
+ """Get all breakpoints as WaldiezBreakpoint objects."""
311
+ result: list[WaldiezBreakpoint] = []
312
+ for bp in self.breakpoints:
313
+ if isinstance(bp, str):
314
+ try:
315
+ result.append(WaldiezBreakpoint.from_string(bp))
316
+ except ValueError:
317
+ # Skip invalid breakpoints rather than failing
318
+ continue
319
+ else:
320
+ result.append(bp)
321
+ return result
322
+
323
+
324
+ class WaldiezDebugBreakpointAdded(BaseModel):
325
+ """Debug breakpoint added message."""
326
+
327
+ type: Literal["debug_breakpoint_added"] = "debug_breakpoint_added"
328
+ breakpoint: Union[str, WaldiezBreakpoint]
329
+
330
+ @property
331
+ def breakpoint_object(self) -> WaldiezBreakpoint:
332
+ """Get breakpoint as WaldiezBreakpoint object."""
333
+ if isinstance(self.breakpoint, str):
334
+ return WaldiezBreakpoint.from_string(self.breakpoint)
335
+ return self.breakpoint
336
+
337
+
338
+ class WaldiezDebugBreakpointRemoved(BaseModel):
339
+ """Debug breakpoint removed message."""
340
+
341
+ type: Literal["debug_breakpoint_removed"] = "debug_breakpoint_removed"
342
+ breakpoint: Union[str, WaldiezBreakpoint]
343
+
344
+ @property
345
+ def breakpoint_object(self) -> WaldiezBreakpoint:
346
+ """Get breakpoint as WaldiezBreakpoint object."""
347
+ if isinstance(self.breakpoint, str):
348
+ return WaldiezBreakpoint.from_string(self.breakpoint)
349
+ return self.breakpoint
350
+
351
+
44
352
  class WaldiezDebugHelpCommand(BaseModel):
45
353
  """Help command information."""
46
354
 
@@ -84,14 +392,14 @@ class WaldiezDebugEventInfo(BaseModel):
84
392
  """Debug event info message."""
85
393
 
86
394
  type: Literal["debug_event_info"] = "debug_event_info"
87
- event: Dict[str, Any]
395
+ event: dict[str, Any]
88
396
 
89
397
 
90
398
  class WaldiezDebugStats(BaseModel):
91
399
  """Debug stats message."""
92
400
 
93
401
  type: Literal["debug_stats"] = "debug_stats"
94
- stats: Dict[str, Any]
402
+ stats: dict[str, Any]
95
403
 
96
404
 
97
405
  class WaldiezDebugHelp(BaseModel):
@@ -108,28 +416,6 @@ class WaldiezDebugError(BaseModel):
108
416
  error: str
109
417
 
110
418
 
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
419
  class WaldiezDebugBreakpointCleared(BaseModel):
134
420
  """Debug breakpoint cleared message."""
135
421
 
@@ -165,44 +451,69 @@ class WaldiezDebugMessageWrapper(BaseModel):
165
451
  HELP_MESSAGE = WaldiezDebugHelp(
166
452
  help=[
167
453
  WaldiezDebugHelpCommandGroup(
168
- title="Commands",
454
+ title="Basic Commands",
169
455
  commands=[
170
456
  WaldiezDebugHelpCommand(
171
- cmds=["continue", "c"], desc="Continue to the next step."
457
+ cmds=["continue", "c"], desc="Continue to the next step"
172
458
  ),
173
459
  WaldiezDebugHelpCommand(
174
- cmds=["step", "s"], desc="Step through the next event."
460
+ cmds=["step", "s"], desc="Step through the next event"
175
461
  ),
176
462
  WaldiezDebugHelpCommand(
177
- cmds=["run", "r"], desc="Run without stopping."
463
+ cmds=["run", "r"], desc="Run without stopping"
178
464
  ),
179
465
  WaldiezDebugHelpCommand(
180
- cmds=["quit", "q"], desc="Quit the debugger."
466
+ cmds=["quit", "q"], desc="Quit the debugger"
181
467
  ),
182
468
  WaldiezDebugHelpCommand(
183
- cmds=["info", "i"], desc="Show detailed event information."
469
+ cmds=["info", "i"], desc="Show detailed event information"
184
470
  ),
185
471
  WaldiezDebugHelpCommand(
186
- cmds=["help", "h"], desc="Show this help message."
472
+ cmds=["help", "h"], desc="Show this help message"
187
473
  ),
188
474
  WaldiezDebugHelpCommand(
189
- cmds=["stats", "st"], desc="Show execution statistics."
475
+ cmds=["stats", "st"], desc="Show execution statistics"
190
476
  ),
477
+ ],
478
+ ),
479
+ WaldiezDebugHelpCommandGroup(
480
+ title="Breakpoint Commands",
481
+ commands=[
191
482
  WaldiezDebugHelpCommand(
192
483
  cmds=["add_breakpoint", "ab"],
193
- desc="Add breakpoint for event type.",
484
+ desc="Add breakpoint. Usage: 'ab [spec]' where spec is 'event:<type>', 'agent:<name>', '<name>:<event>', or 'all'",
194
485
  ),
195
486
  WaldiezDebugHelpCommand(
196
487
  cmds=["remove_breakpoint", "rb"],
197
- desc="Remove breakpoint for event type.",
488
+ desc="Remove breakpoint. Usage: 'rb [spec]' with same format as add",
198
489
  ),
199
490
  WaldiezDebugHelpCommand(
200
- cmds=["list_breakpoints", "lb"],
201
- desc="List all breakpoints.",
491
+ cmds=["list_breakpoints", "lb"], desc="List all breakpoints"
202
492
  ),
203
493
  WaldiezDebugHelpCommand(
204
494
  cmds=["clear_breakpoints", "cb"],
205
- desc="Clear all breakpoints.",
495
+ desc="Clear all breakpoints",
496
+ ),
497
+ ],
498
+ ),
499
+ WaldiezDebugHelpCommandGroup(
500
+ title="Breakpoint Examples",
501
+ commands=[
502
+ WaldiezDebugHelpCommand(
503
+ desc="'ab' - Add breakpoint for the current event type"
504
+ ),
505
+ WaldiezDebugHelpCommand(
506
+ desc="'ab event:tool_call' - Break on all 'tool_call' events"
507
+ ),
508
+ WaldiezDebugHelpCommand(
509
+ desc="'ab agent:user' - Break on any event from 'user' agent"
510
+ ),
511
+ WaldiezDebugHelpCommand(
512
+ desc="'ab assistant:tool_call' - Break on 'tool_call' events from 'assistant'"
513
+ ),
514
+ WaldiezDebugHelpCommand(desc="'ab all' - Break on all events"),
515
+ WaldiezDebugHelpCommand(
516
+ desc="'rb event:tool_call' - Remove 'tool_call' event breakpoint"
206
517
  ),
207
518
  ],
208
519
  ),
@@ -213,10 +524,16 @@ HELP_MESSAGE = WaldiezDebugHelp(
213
524
  desc="Press Enter alone to continue (same as 'c')"
214
525
  ),
215
526
  WaldiezDebugHelpCommand(
216
- desc="Use (s)tep to go through events one by one."
527
+ desc="Use (s)tep to go through events one by one"
528
+ ),
529
+ WaldiezDebugHelpCommand(
530
+ desc="Use (r)un to continue without stopping"
531
+ ),
532
+ WaldiezDebugHelpCommand(
533
+ desc="Set specific breakpoints to avoid noise: 'ab event:message'"
217
534
  ),
218
535
  WaldiezDebugHelpCommand(
219
- desc="Use (r)un to continue without stopping."
536
+ desc="Check (st)ats regularly to monitor progress"
220
537
  ),
221
538
  ],
222
539
  ),