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.
- waldiez/_version.py +1 -1
- waldiez/cli.py +1 -0
- waldiez/exporting/agent/exporter.py +6 -6
- waldiez/exporting/agent/extras/group_manager_agent_extas.py +6 -1
- waldiez/exporting/agent/extras/handoffs/after_work.py +1 -0
- waldiez/exporting/agent/extras/handoffs/available.py +1 -0
- waldiez/exporting/agent/extras/handoffs/handoff.py +1 -0
- waldiez/exporting/agent/extras/handoffs/target.py +1 -0
- waldiez/exporting/agent/termination.py +1 -0
- waldiez/exporting/core/constants.py +3 -1
- waldiez/exporting/core/extras/serializer.py +12 -10
- waldiez/exporting/core/types.py +1 -0
- waldiez/exporting/core/utils/llm_config.py +2 -2
- waldiez/exporting/flow/execution_generator.py +1 -0
- waldiez/exporting/flow/utils/common.py +1 -1
- waldiez/exporting/flow/utils/importing.py +1 -1
- waldiez/exporting/flow/utils/logging.py +3 -75
- waldiez/io/__init__.py +3 -1
- waldiez/io/_ws.py +2 -0
- waldiez/io/structured.py +81 -28
- waldiez/io/utils.py +16 -10
- waldiez/io/ws.py +2 -2
- waldiez/models/agents/agent/agent.py +2 -1
- waldiez/models/chat/chat.py +1 -0
- waldiez/models/chat/chat_data.py +0 -2
- waldiez/models/common/base.py +2 -0
- waldiez/models/common/handoff.py +2 -0
- waldiez/models/common/method_utils.py +2 -0
- waldiez/models/model/_llm.py +3 -0
- waldiez/models/tool/predefined/_email.py +3 -0
- waldiez/models/tool/predefined/_perplexity.py +1 -1
- waldiez/models/tool/predefined/_searxng.py +1 -1
- waldiez/models/tool/predefined/_wikipedia.py +1 -1
- waldiez/running/base_runner.py +81 -20
- waldiez/running/post_run.py +6 -0
- waldiez/running/pre_run.py +167 -45
- waldiez/running/standard_runner.py +5 -5
- waldiez/running/step_by_step/breakpoints_mixin.py +368 -44
- waldiez/running/step_by_step/command_handler.py +151 -0
- waldiez/running/step_by_step/events_processor.py +199 -0
- waldiez/running/step_by_step/step_by_step_models.py +358 -41
- waldiez/running/step_by_step/step_by_step_runner.py +358 -353
- waldiez/running/subprocess_runner/__base__.py +4 -7
- waldiez/running/subprocess_runner/_async_runner.py +1 -1
- waldiez/running/subprocess_runner/_sync_runner.py +5 -4
- waldiez/running/subprocess_runner/runner.py +9 -0
- waldiez/running/utils.py +116 -2
- waldiez/ws/__init__.py +8 -7
- waldiez/ws/_file_handler.py +0 -2
- waldiez/ws/_mock.py +74 -0
- waldiez/ws/cli.py +27 -3
- waldiez/ws/client_manager.py +45 -29
- waldiez/ws/models.py +18 -1
- waldiez/ws/reloader.py +23 -2
- waldiez/ws/server.py +47 -8
- waldiez/ws/utils.py +29 -4
- {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/METADATA +53 -44
- {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/RECORD +62 -59
- {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/WHEEL +0 -0
- {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/entry_points.txt +0 -0
- {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/licenses/LICENSE +0 -0
- {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/licenses/NOTICE.md +0 -0
|
@@ -12,21 +12,24 @@
|
|
|
12
12
|
import asyncio
|
|
13
13
|
import threading
|
|
14
14
|
import traceback
|
|
15
|
-
import
|
|
15
|
+
from collections import deque
|
|
16
16
|
from pathlib import Path
|
|
17
17
|
from typing import TYPE_CHECKING, Any, Iterable, Union
|
|
18
18
|
|
|
19
19
|
from pydantic import ValidationError
|
|
20
20
|
|
|
21
|
+
from waldiez.io.utils import DEBUG_INPUT_PROMPT, gen_id
|
|
21
22
|
from waldiez.models.waldiez import Waldiez
|
|
23
|
+
from waldiez.running.step_by_step.command_handler import CommandHandler
|
|
24
|
+
from waldiez.running.step_by_step.events_processor import EventProcessor
|
|
22
25
|
|
|
23
26
|
from ..base_runner import WaldiezBaseRunner
|
|
24
27
|
from ..exceptions import StopRunningException
|
|
25
28
|
from ..run_results import WaldiezRunResults
|
|
26
29
|
from .breakpoints_mixin import BreakpointsMixin
|
|
27
30
|
from .step_by_step_models import (
|
|
28
|
-
HELP_MESSAGE,
|
|
29
31
|
VALID_CONTROL_COMMANDS,
|
|
32
|
+
WaldiezDebugConfig,
|
|
30
33
|
WaldiezDebugError,
|
|
31
34
|
WaldiezDebugEventInfo,
|
|
32
35
|
WaldiezDebugInputRequest,
|
|
@@ -41,9 +44,6 @@ if TYPE_CHECKING:
|
|
|
41
44
|
from autogen.messages import BaseMessage # type: ignore
|
|
42
45
|
|
|
43
46
|
|
|
44
|
-
DEBUG_INPUT_PROMPT = (
|
|
45
|
-
"[Step] (c)ontinue, (r)un, (q)uit, (i)nfo, (h)elp, (st)ats: "
|
|
46
|
-
)
|
|
47
47
|
MESSAGES = {
|
|
48
48
|
"workflow_starting": "<Waldiez step-by-step> - Starting workflow...",
|
|
49
49
|
"workflow_finished": "<Waldiez step-by-step> - Workflow finished",
|
|
@@ -57,7 +57,7 @@ MESSAGES = {
|
|
|
57
57
|
# pylint: disable=too-many-instance-attributes
|
|
58
58
|
# noinspection DuplicatedCode,StrFormat
|
|
59
59
|
class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
60
|
-
"""
|
|
60
|
+
"""Refactored step-by-step runner with improved architecture."""
|
|
61
61
|
|
|
62
62
|
def __init__(
|
|
63
63
|
self,
|
|
@@ -68,6 +68,7 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
68
68
|
dot_env: str | Path | None = None,
|
|
69
69
|
auto_continue: bool = False,
|
|
70
70
|
breakpoints: Iterable[str] | None = None,
|
|
71
|
+
config: WaldiezDebugConfig | None = None,
|
|
71
72
|
**kwargs: Any,
|
|
72
73
|
) -> None:
|
|
73
74
|
"""Initialize the step-by-step runner."""
|
|
@@ -80,23 +81,42 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
80
81
|
**kwargs,
|
|
81
82
|
)
|
|
82
83
|
BreakpointsMixin.__init__(self)
|
|
84
|
+
|
|
85
|
+
# Configuration
|
|
86
|
+
self._config = config or WaldiezDebugConfig()
|
|
87
|
+
self._config.auto_continue = auto_continue
|
|
88
|
+
|
|
89
|
+
# Core state
|
|
83
90
|
self._event_count = 0
|
|
84
91
|
self._processed_events = 0
|
|
85
|
-
self._step_mode =
|
|
86
|
-
|
|
87
|
-
#
|
|
88
|
-
|
|
89
|
-
self.
|
|
90
|
-
|
|
92
|
+
self._step_mode = self._config.step_mode
|
|
93
|
+
|
|
94
|
+
# Use deque for efficient FIFO operations on event history
|
|
95
|
+
self._event_history: deque[dict[str, Any]] = deque(
|
|
96
|
+
maxlen=self._config.max_event_history
|
|
97
|
+
)
|
|
91
98
|
self._current_event: Union["BaseEvent", "BaseMessage", None] = None
|
|
99
|
+
|
|
100
|
+
# Participant tracking
|
|
92
101
|
self._known_participants = self.waldiez.info.participants
|
|
93
102
|
self._last_sender: str | None = None
|
|
94
103
|
self._last_recipient: str | None = None
|
|
95
104
|
|
|
105
|
+
# Initialize breakpoints
|
|
106
|
+
if breakpoints:
|
|
107
|
+
_, errors = self.import_breakpoints(list(breakpoints))
|
|
108
|
+
if errors:
|
|
109
|
+
for error in errors:
|
|
110
|
+
self.log.warning("Breakpoint import error: %s", error)
|
|
111
|
+
|
|
112
|
+
# Command handling
|
|
113
|
+
self._command_handler = CommandHandler(self)
|
|
114
|
+
self._event_processor = EventProcessor(self)
|
|
115
|
+
|
|
96
116
|
@property
|
|
97
117
|
def auto_continue(self) -> bool:
|
|
98
118
|
"""Get whether auto-continue is enabled."""
|
|
99
|
-
return self.
|
|
119
|
+
return self._config.auto_continue
|
|
100
120
|
|
|
101
121
|
@auto_continue.setter
|
|
102
122
|
def auto_continue(self, value: bool) -> None:
|
|
@@ -107,29 +127,89 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
107
127
|
value : bool
|
|
108
128
|
Whether to enable auto-continue.
|
|
109
129
|
"""
|
|
110
|
-
self.
|
|
130
|
+
self._config.auto_continue = value
|
|
131
|
+
self.log.debug("Auto-continue mode set to: %s", value)
|
|
111
132
|
|
|
112
133
|
@property
|
|
113
|
-
def
|
|
114
|
-
"""Get the
|
|
115
|
-
|
|
134
|
+
def step_mode(self) -> bool:
|
|
135
|
+
"""Get the step mode.
|
|
136
|
+
|
|
137
|
+
Returns
|
|
138
|
+
-------
|
|
139
|
+
bool
|
|
140
|
+
Whether the step mode is enabled.
|
|
141
|
+
"""
|
|
142
|
+
return self._step_mode
|
|
143
|
+
|
|
144
|
+
@step_mode.setter
|
|
145
|
+
def step_mode(self, value: bool) -> None:
|
|
146
|
+
"""Set the step mode.
|
|
147
|
+
|
|
148
|
+
Parameters
|
|
149
|
+
----------
|
|
150
|
+
value : bool
|
|
151
|
+
Whether to enable step mode.
|
|
152
|
+
"""
|
|
153
|
+
self._step_mode = value
|
|
154
|
+
self.log.debug("Step mode set to: %s", value)
|
|
155
|
+
|
|
156
|
+
@property
|
|
157
|
+
def last_sender(self) -> str | None:
|
|
158
|
+
"""Get the last sender.
|
|
159
|
+
|
|
160
|
+
Returns
|
|
161
|
+
-------
|
|
162
|
+
str | None
|
|
163
|
+
The last sender, if available.
|
|
164
|
+
"""
|
|
165
|
+
return self._last_sender
|
|
166
|
+
|
|
167
|
+
@last_sender.setter
|
|
168
|
+
def last_sender(self, value: str | None) -> None:
|
|
169
|
+
"""Set the last sender.
|
|
170
|
+
|
|
171
|
+
Parameters
|
|
172
|
+
----------
|
|
173
|
+
value : str | None
|
|
174
|
+
The last sender to set.
|
|
175
|
+
"""
|
|
176
|
+
self._last_sender = value
|
|
116
177
|
|
|
117
|
-
|
|
118
|
-
|
|
178
|
+
@property
|
|
179
|
+
def last_recipient(self) -> str | None:
|
|
180
|
+
"""Get the last recipient.
|
|
181
|
+
|
|
182
|
+
Returns
|
|
183
|
+
-------
|
|
184
|
+
str | None
|
|
185
|
+
The last recipient, if available.
|
|
186
|
+
"""
|
|
187
|
+
return self._last_recipient
|
|
188
|
+
|
|
189
|
+
@last_recipient.setter
|
|
190
|
+
def last_recipient(self, value: str | None) -> None:
|
|
191
|
+
"""Set the last recipient.
|
|
119
192
|
|
|
120
193
|
Parameters
|
|
121
194
|
----------
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
without waiting for user input.
|
|
195
|
+
value : str | None
|
|
196
|
+
The last recipient to set.
|
|
125
197
|
"""
|
|
126
|
-
self.
|
|
127
|
-
self.log.info("Auto-continue mode set to: %s", auto_continue)
|
|
198
|
+
self._last_recipient = value
|
|
128
199
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
200
|
+
@property
|
|
201
|
+
def stop_requested(self) -> threading.Event:
|
|
202
|
+
"""Get the stop requested event."""
|
|
203
|
+
return self._stop_requested
|
|
204
|
+
|
|
205
|
+
@property
|
|
206
|
+
def max_event_history(self) -> int:
|
|
207
|
+
"""Get the maximum event history size."""
|
|
208
|
+
return self._config.max_event_history
|
|
209
|
+
|
|
210
|
+
@staticmethod
|
|
211
|
+
def print(*args: Any, **kwargs: Any) -> None:
|
|
212
|
+
"""Print method.
|
|
133
213
|
|
|
134
214
|
Parameters
|
|
135
215
|
----------
|
|
@@ -138,24 +218,44 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
138
218
|
**kwargs : Any
|
|
139
219
|
Keyword arguments to print.
|
|
140
220
|
"""
|
|
141
|
-
WaldiezBaseRunner.
|
|
221
|
+
WaldiezBaseRunner.print(*args, **kwargs)
|
|
222
|
+
|
|
223
|
+
def add_to_history(self, event_info: dict[str, Any]) -> None:
|
|
224
|
+
"""Add an event to the history.
|
|
225
|
+
|
|
226
|
+
Parameters
|
|
227
|
+
----------
|
|
228
|
+
event_info : dict[str, Any]
|
|
229
|
+
The event information to add to the history.
|
|
230
|
+
"""
|
|
231
|
+
self._event_history.append(event_info)
|
|
142
232
|
|
|
143
|
-
def
|
|
233
|
+
def pop_event(self) -> None:
|
|
234
|
+
"""Pop event from the history."""
|
|
235
|
+
if self._event_history:
|
|
236
|
+
self._event_history.popleft()
|
|
237
|
+
|
|
238
|
+
def emit_event(
|
|
239
|
+
self, event: Union["BaseEvent", "BaseMessage", dict[str, Any]]
|
|
240
|
+
) -> None:
|
|
144
241
|
"""Emit an event.
|
|
145
242
|
|
|
146
243
|
Parameters
|
|
147
244
|
----------
|
|
148
|
-
event :
|
|
245
|
+
event : BaseEvent | BaseMessage | dict[str, Any]
|
|
149
246
|
The event to emit.
|
|
150
247
|
"""
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
248
|
+
if not isinstance(event, dict):
|
|
249
|
+
event_info = event.model_dump(
|
|
250
|
+
mode="json", exclude_none=True, fallback=str
|
|
251
|
+
)
|
|
252
|
+
event_info["count"] = self._event_count
|
|
253
|
+
event_info["sender"] = getattr(event, "sender", self._last_sender)
|
|
254
|
+
event_info["recipient"] = getattr(
|
|
255
|
+
event, "recipient", self._last_recipient
|
|
256
|
+
)
|
|
257
|
+
else:
|
|
258
|
+
event_info = event
|
|
159
259
|
self.emit(WaldiezDebugEventInfo(event=event_info))
|
|
160
260
|
|
|
161
261
|
# noinspection PyTypeHints
|
|
@@ -165,231 +265,264 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
165
265
|
Parameters
|
|
166
266
|
----------
|
|
167
267
|
message : WaldiezDebugMessage
|
|
168
|
-
The
|
|
268
|
+
The message to emit.
|
|
169
269
|
"""
|
|
170
270
|
message_dump = message.model_dump(
|
|
171
271
|
mode="json", exclude_none=True, fallback=str
|
|
172
272
|
)
|
|
173
273
|
self.print(message_dump)
|
|
174
274
|
|
|
175
|
-
|
|
275
|
+
@property
|
|
276
|
+
def current_event(self) -> Union["BaseEvent", "BaseMessage", None]:
|
|
277
|
+
"""Get the current event.
|
|
278
|
+
|
|
279
|
+
Returns
|
|
280
|
+
-------
|
|
281
|
+
Union["BaseEvent", "BaseMessage", None]
|
|
282
|
+
The current event, if available.
|
|
283
|
+
"""
|
|
284
|
+
return self._current_event
|
|
285
|
+
|
|
286
|
+
@current_event.setter
|
|
287
|
+
def current_event(
|
|
288
|
+
self, value: Union["BaseEvent", "BaseMessage", None]
|
|
289
|
+
) -> None:
|
|
290
|
+
"""Set the current event.
|
|
291
|
+
|
|
292
|
+
Parameters
|
|
293
|
+
----------
|
|
294
|
+
value : Union["BaseEvent", "BaseMessage", None]
|
|
295
|
+
The event to set as the current event.
|
|
296
|
+
"""
|
|
297
|
+
self._current_event = value
|
|
298
|
+
|
|
299
|
+
@property
|
|
300
|
+
def event_count(self) -> int:
|
|
301
|
+
"""Get the current event count.
|
|
302
|
+
|
|
303
|
+
Returns
|
|
304
|
+
-------
|
|
305
|
+
int
|
|
306
|
+
The current event count.
|
|
307
|
+
"""
|
|
308
|
+
return self._event_count
|
|
309
|
+
|
|
310
|
+
def event_plus_one(self) -> None:
|
|
311
|
+
"""Increment the current event count."""
|
|
312
|
+
self._event_count += 1
|
|
313
|
+
|
|
314
|
+
def show_event_info(self) -> None:
|
|
315
|
+
"""Show detailed information about the current event."""
|
|
176
316
|
if not self._current_event:
|
|
317
|
+
self.emit(WaldiezDebugError(error="No current event to display"))
|
|
177
318
|
return
|
|
319
|
+
|
|
178
320
|
event_info = self._current_event.model_dump(
|
|
179
321
|
mode="json", exclude_none=True, fallback=str
|
|
180
322
|
)
|
|
323
|
+
# Add additional context
|
|
324
|
+
event_info["_meta"] = {
|
|
325
|
+
"event_number": self._event_count,
|
|
326
|
+
"processed_events": self._processed_events,
|
|
327
|
+
"step_mode": self._step_mode,
|
|
328
|
+
"has_breakpoints": len(self._breakpoints) > 0,
|
|
329
|
+
}
|
|
181
330
|
self.emit(WaldiezDebugEventInfo(event=event_info))
|
|
182
331
|
|
|
183
|
-
def
|
|
332
|
+
def show_stats(self) -> None:
|
|
333
|
+
"""Show comprehensive execution statistics."""
|
|
334
|
+
base_stats: dict[str, Any] = {
|
|
335
|
+
"execution": {
|
|
336
|
+
"events_processed": self._processed_events,
|
|
337
|
+
"total_events": self._event_count,
|
|
338
|
+
"processing_rate": (
|
|
339
|
+
f"{(self._processed_events / self._event_count * 100):.1f}%"
|
|
340
|
+
if self._event_count > 0
|
|
341
|
+
else "0%"
|
|
342
|
+
),
|
|
343
|
+
},
|
|
344
|
+
"mode": {
|
|
345
|
+
"step_mode": self._step_mode,
|
|
346
|
+
"auto_continue": self._config.auto_continue,
|
|
347
|
+
},
|
|
348
|
+
"history": {
|
|
349
|
+
"event_history_count": len(self._event_history),
|
|
350
|
+
"max_history_size": self._config.max_event_history,
|
|
351
|
+
"memory_usage": f"{len(self._event_history) * 200}B (est.)",
|
|
352
|
+
},
|
|
353
|
+
"participants": {
|
|
354
|
+
"last_sender": self._last_sender,
|
|
355
|
+
"last_recipient": self._last_recipient,
|
|
356
|
+
"known_participants": len(self._known_participants),
|
|
357
|
+
},
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
# Merge with breakpoint stats
|
|
361
|
+
breakpoint_stats = self.get_breakpoint_stats()
|
|
184
362
|
stats_dict: dict[str, Any] = {
|
|
185
|
-
|
|
363
|
+
**base_stats,
|
|
364
|
+
"breakpoints": breakpoint_stats,
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
self.emit(WaldiezDebugStats(stats=stats_dict))
|
|
368
|
+
|
|
369
|
+
@property
|
|
370
|
+
def execution_stats(self) -> dict[str, Any]:
|
|
371
|
+
"""Get comprehensive execution statistics.
|
|
372
|
+
|
|
373
|
+
Returns
|
|
374
|
+
-------
|
|
375
|
+
dict[str, Any]
|
|
376
|
+
A dictionary containing execution statistics.
|
|
377
|
+
"""
|
|
378
|
+
base_stats: dict[str, Any] = {
|
|
186
379
|
"total_events": self._event_count,
|
|
380
|
+
"processed_events": self._processed_events,
|
|
381
|
+
"event_processing_rate": (
|
|
382
|
+
self._processed_events / self._event_count
|
|
383
|
+
if self._event_count > 0
|
|
384
|
+
else 0
|
|
385
|
+
),
|
|
187
386
|
"step_mode": self._step_mode,
|
|
188
|
-
"auto_continue": self.
|
|
189
|
-
"breakpoints": sorted(self.get_breakpoints()),
|
|
387
|
+
"auto_continue": self._config.auto_continue,
|
|
190
388
|
"event_history_count": len(self._event_history),
|
|
389
|
+
"last_sender": self._last_sender,
|
|
390
|
+
"last_recipient": self._last_recipient,
|
|
391
|
+
"known_participants": [
|
|
392
|
+
p.model_dump() for p in self._known_participants
|
|
393
|
+
],
|
|
394
|
+
"config": self._config.model_dump(),
|
|
191
395
|
}
|
|
192
|
-
self.emit(WaldiezDebugStats(stats=stats_dict))
|
|
193
396
|
|
|
194
|
-
|
|
195
|
-
self, user_response: str, request_id: str
|
|
196
|
-
) -> tuple[str | None, bool]:
|
|
197
|
-
"""Get user response for step-by-step execution.
|
|
397
|
+
return {**base_stats, "breakpoints": self.get_breakpoint_stats()}
|
|
198
398
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
The user's response.
|
|
203
|
-
request_id : str
|
|
204
|
-
The ID of the input request.
|
|
399
|
+
@property
|
|
400
|
+
def event_history(self) -> list[dict[str, Any]]:
|
|
401
|
+
"""Get the history of processed events.
|
|
205
402
|
|
|
206
403
|
Returns
|
|
207
404
|
-------
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
and a boolean indicating validity.
|
|
405
|
+
list[dict[str, Any]]
|
|
406
|
+
A list of dictionaries containing event history.
|
|
211
407
|
"""
|
|
408
|
+
return list(self._event_history)
|
|
409
|
+
|
|
410
|
+
def reset_session(self) -> None:
|
|
411
|
+
"""Reset the debugging session state."""
|
|
412
|
+
self._event_count = 0
|
|
413
|
+
self._processed_events = 0
|
|
414
|
+
self._event_history.clear()
|
|
415
|
+
self._current_event = None
|
|
416
|
+
self._last_sender = None
|
|
417
|
+
self._last_recipient = None
|
|
418
|
+
self.reset_stats()
|
|
419
|
+
self.log.info("Debug session reset")
|
|
420
|
+
|
|
421
|
+
def _get_user_response(
|
|
422
|
+
self,
|
|
423
|
+
user_response: str,
|
|
424
|
+
request_id: str,
|
|
425
|
+
skip_id_check: bool = False,
|
|
426
|
+
) -> tuple[str | None, bool]:
|
|
427
|
+
"""Get and validate user response."""
|
|
212
428
|
try:
|
|
213
429
|
response = WaldiezDebugInputResponse.model_validate_json(
|
|
214
430
|
user_response
|
|
215
431
|
)
|
|
216
432
|
except ValidationError as exc:
|
|
433
|
+
# Handle raw CLI input
|
|
217
434
|
got = user_response.strip().lower()
|
|
218
|
-
# in cli mode, let's see if got raw response
|
|
219
|
-
# instead of a structured one
|
|
220
435
|
if got in VALID_CONTROL_COMMANDS:
|
|
221
436
|
return got, True
|
|
222
437
|
self.emit(WaldiezDebugError(error=f"Invalid input: {exc}"))
|
|
223
438
|
return None, False
|
|
224
439
|
|
|
225
|
-
if response.request_id != request_id:
|
|
440
|
+
if not skip_id_check and response.request_id != request_id:
|
|
226
441
|
self.emit(
|
|
227
442
|
WaldiezDebugError(
|
|
228
|
-
error=
|
|
229
|
-
"Stale input received: "
|
|
230
|
-
f"{response.request_id} != {request_id}"
|
|
231
|
-
)
|
|
443
|
+
error=f"Stale input received: {response.request_id} != {request_id}"
|
|
232
444
|
)
|
|
233
445
|
)
|
|
234
446
|
return None, False
|
|
447
|
+
|
|
235
448
|
return response.data, True
|
|
236
449
|
|
|
237
|
-
|
|
238
|
-
def _parse_user_action( # noqa: C901
|
|
450
|
+
def _parse_user_action(
|
|
239
451
|
self, user_response: str, request_id: str
|
|
240
452
|
) -> WaldiezDebugStepAction:
|
|
241
|
-
"""Parse user action
|
|
242
|
-
|
|
243
|
-
Parameters
|
|
244
|
-
----------
|
|
245
|
-
user_response : str
|
|
246
|
-
The user's response.
|
|
247
|
-
request_id : str
|
|
248
|
-
The ID of the input request.
|
|
249
|
-
|
|
250
|
-
Returns
|
|
251
|
-
-------
|
|
252
|
-
WaldiezDebugStepAction
|
|
253
|
-
The action chosen by the user.
|
|
254
|
-
"""
|
|
453
|
+
"""Parse user action using the command handler."""
|
|
255
454
|
self.log.debug("Parsing user action... '%s'", user_response)
|
|
455
|
+
|
|
256
456
|
user_input, is_valid = self._get_user_response(
|
|
257
|
-
user_response,
|
|
457
|
+
user_response,
|
|
458
|
+
request_id=request_id,
|
|
459
|
+
skip_id_check=True,
|
|
258
460
|
)
|
|
259
461
|
if not is_valid:
|
|
260
462
|
return WaldiezDebugStepAction.UNKNOWN
|
|
261
|
-
if not user_input:
|
|
262
|
-
return WaldiezDebugStepAction.CONTINUE
|
|
263
|
-
match user_input:
|
|
264
|
-
case "c":
|
|
265
|
-
self._step_mode = True
|
|
266
|
-
return WaldiezDebugStepAction.CONTINUE
|
|
267
|
-
case "s":
|
|
268
|
-
self._step_mode = True
|
|
269
|
-
return WaldiezDebugStepAction.STEP
|
|
270
|
-
case "r":
|
|
271
|
-
self._step_mode = False
|
|
272
|
-
return WaldiezDebugStepAction.RUN
|
|
273
|
-
case "q":
|
|
274
|
-
self._stop_requested.set()
|
|
275
|
-
return WaldiezDebugStepAction.QUIT
|
|
276
|
-
case "i":
|
|
277
|
-
self._show_event_info()
|
|
278
|
-
return WaldiezDebugStepAction.INFO
|
|
279
|
-
case "h":
|
|
280
|
-
self.emit(HELP_MESSAGE)
|
|
281
|
-
return WaldiezDebugStepAction.HELP
|
|
282
|
-
case "st":
|
|
283
|
-
self._show_stats()
|
|
284
|
-
return WaldiezDebugStepAction.STATS
|
|
285
|
-
case "ab":
|
|
286
|
-
if self._current_event and hasattr(self._current_event, "type"):
|
|
287
|
-
self.add_breakpoint(self._current_event.type)
|
|
288
|
-
else:
|
|
289
|
-
self.emit(
|
|
290
|
-
WaldiezDebugError(
|
|
291
|
-
error="No current event to add breakpoint for"
|
|
292
|
-
)
|
|
293
|
-
)
|
|
294
|
-
return WaldiezDebugStepAction.ADD_BREAKPOINT
|
|
295
|
-
case "rb":
|
|
296
|
-
if self._current_event and hasattr(self._current_event, "type"):
|
|
297
|
-
self.remove_breakpoint(self._current_event.type)
|
|
298
|
-
else:
|
|
299
|
-
self.emit(
|
|
300
|
-
WaldiezDebugError(
|
|
301
|
-
error="No current event to remove breakpoint for"
|
|
302
|
-
)
|
|
303
|
-
)
|
|
304
|
-
return WaldiezDebugStepAction.REMOVE_BREAKPOINT
|
|
305
|
-
case "lb":
|
|
306
|
-
self.list_breakpoints()
|
|
307
|
-
return WaldiezDebugStepAction.LIST_BREAKPOINTS
|
|
308
|
-
case "cb":
|
|
309
|
-
self.clear_breakpoints()
|
|
310
|
-
return WaldiezDebugStepAction.CLEAR_BREAKPOINTS
|
|
311
|
-
case _:
|
|
312
|
-
self.emit(
|
|
313
|
-
WaldiezDebugError(
|
|
314
|
-
error=f"Unknown command: {user_input}, use 'h' for help"
|
|
315
|
-
)
|
|
316
|
-
)
|
|
317
|
-
return WaldiezDebugStepAction.UNKNOWN
|
|
318
463
|
|
|
319
|
-
|
|
320
|
-
"""Get user action for step-by-step execution.
|
|
464
|
+
return self._command_handler.handle_command(user_input or "")
|
|
321
465
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
"""
|
|
327
|
-
if self._auto_continue:
|
|
466
|
+
def _get_user_action(self) -> WaldiezDebugStepAction:
|
|
467
|
+
"""Get user action with timeout support."""
|
|
468
|
+
if self._config.auto_continue:
|
|
469
|
+
self.step_mode = True
|
|
328
470
|
return WaldiezDebugStepAction.CONTINUE
|
|
329
471
|
|
|
330
472
|
while True:
|
|
331
|
-
|
|
332
|
-
request_id = str(uuid.uuid4())
|
|
473
|
+
request_id = gen_id()
|
|
333
474
|
try:
|
|
334
|
-
self.
|
|
335
|
-
|
|
336
|
-
|
|
475
|
+
if not self.structured_io:
|
|
476
|
+
self.emit(
|
|
477
|
+
WaldiezDebugInputRequest(
|
|
478
|
+
prompt=DEBUG_INPUT_PROMPT, request_id=request_id
|
|
479
|
+
)
|
|
337
480
|
)
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
)
|
|
481
|
+
except Exception as e: # pylint: disable=broad-exception-caught
|
|
482
|
+
self.log.warning("Failed to emit input request: %s", e)
|
|
483
|
+
try:
|
|
484
|
+
user_input = WaldiezBaseRunner.get_user_input(
|
|
485
|
+
DEBUG_INPUT_PROMPT
|
|
486
|
+
).strip()
|
|
344
487
|
return self._parse_user_action(
|
|
345
488
|
user_input, request_id=request_id
|
|
346
489
|
)
|
|
490
|
+
|
|
347
491
|
except (KeyboardInterrupt, EOFError):
|
|
348
492
|
self._stop_requested.set()
|
|
349
493
|
return WaldiezDebugStepAction.QUIT
|
|
350
494
|
|
|
351
|
-
# pylint: disable=too-many-return-statements
|
|
352
495
|
async def _a_get_user_action(self) -> WaldiezDebugStepAction:
|
|
353
|
-
"""Get user action
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
-------
|
|
357
|
-
WaldiezDebugStepAction
|
|
358
|
-
The action chosen by the user.
|
|
359
|
-
"""
|
|
360
|
-
if self._auto_continue:
|
|
496
|
+
"""Get user action asynchronously."""
|
|
497
|
+
if self._config.auto_continue:
|
|
498
|
+
self.step_mode = True
|
|
361
499
|
return WaldiezDebugStepAction.CONTINUE
|
|
362
500
|
|
|
363
501
|
while True:
|
|
502
|
+
request_id = gen_id()
|
|
364
503
|
# pylint: disable=too-many-try-statements
|
|
365
|
-
request_id = str(uuid.uuid4())
|
|
366
504
|
try:
|
|
367
505
|
self.emit(
|
|
368
506
|
WaldiezDebugInputRequest(
|
|
369
507
|
prompt=DEBUG_INPUT_PROMPT, request_id=request_id
|
|
370
508
|
)
|
|
371
509
|
)
|
|
510
|
+
|
|
372
511
|
user_input = await WaldiezBaseRunner.a_get_user_input(
|
|
373
512
|
DEBUG_INPUT_PROMPT
|
|
374
513
|
)
|
|
375
|
-
user_input = user_input.strip()
|
|
514
|
+
user_input = user_input.strip()
|
|
376
515
|
return self._parse_user_action(
|
|
377
516
|
user_input, request_id=request_id
|
|
378
517
|
)
|
|
518
|
+
|
|
379
519
|
except (KeyboardInterrupt, EOFError):
|
|
380
520
|
return WaldiezDebugStepAction.QUIT
|
|
381
521
|
|
|
382
522
|
def _handle_step_interaction(self) -> bool:
|
|
383
|
-
"""Handle step-by-step user interaction.
|
|
384
|
-
|
|
385
|
-
Returns
|
|
386
|
-
-------
|
|
387
|
-
bool
|
|
388
|
-
True to continue execution, False to stop.
|
|
389
|
-
"""
|
|
390
|
-
while True: # pragma: no branch
|
|
523
|
+
"""Handle step-by-step user interaction."""
|
|
524
|
+
while True:
|
|
391
525
|
action = self._get_user_action()
|
|
392
|
-
|
|
393
526
|
if action in (
|
|
394
527
|
WaldiezDebugStepAction.CONTINUE,
|
|
395
528
|
WaldiezDebugStepAction.STEP,
|
|
@@ -397,20 +530,14 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
397
530
|
return True
|
|
398
531
|
if action == WaldiezDebugStepAction.RUN:
|
|
399
532
|
return True
|
|
400
|
-
if action == WaldiezDebugStepAction.QUIT:
|
|
533
|
+
if action == WaldiezDebugStepAction.QUIT:
|
|
401
534
|
return False
|
|
535
|
+
# For other actions (info, help, etc.), continue the loop
|
|
402
536
|
|
|
403
537
|
async def _a_handle_step_interaction(self) -> bool:
|
|
404
|
-
"""Handle step-by-step user interaction asynchronously.
|
|
405
|
-
|
|
406
|
-
Returns
|
|
407
|
-
-------
|
|
408
|
-
bool
|
|
409
|
-
True to continue execution, False to stop.
|
|
410
|
-
"""
|
|
411
|
-
while True: # pragma: no branch
|
|
538
|
+
"""Handle step-by-step user interaction asynchronously."""
|
|
539
|
+
while True:
|
|
412
540
|
action = await self._a_get_user_action()
|
|
413
|
-
|
|
414
541
|
if action in (
|
|
415
542
|
WaldiezDebugStepAction.CONTINUE,
|
|
416
543
|
WaldiezDebugStepAction.STEP,
|
|
@@ -418,10 +545,10 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
418
545
|
return True
|
|
419
546
|
if action == WaldiezDebugStepAction.RUN:
|
|
420
547
|
return True
|
|
421
|
-
if action == WaldiezDebugStepAction.QUIT:
|
|
548
|
+
if action == WaldiezDebugStepAction.QUIT:
|
|
422
549
|
return False
|
|
550
|
+
# For other actions (info, help, etc.), continue the loop
|
|
423
551
|
|
|
424
|
-
# pylint: disable=unused-argument
|
|
425
552
|
def _run(
|
|
426
553
|
self,
|
|
427
554
|
temp_dir: Path,
|
|
@@ -445,13 +572,13 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
445
572
|
# pylint: disable=too-many-try-statements,broad-exception-caught
|
|
446
573
|
try:
|
|
447
574
|
loaded_module = self._load_module(output_file, temp_dir)
|
|
448
|
-
if self._stop_requested.is_set():
|
|
575
|
+
if self._stop_requested.is_set():
|
|
449
576
|
self.log.debug(
|
|
450
577
|
"Step-by-step execution stopped before workflow start"
|
|
451
578
|
)
|
|
452
579
|
return []
|
|
453
580
|
|
|
454
|
-
#
|
|
581
|
+
# Setup I/O
|
|
455
582
|
if self.structured_io:
|
|
456
583
|
stream = StructuredIOStream(
|
|
457
584
|
uploads_root=uploads_root, is_async=False
|
|
@@ -475,7 +602,6 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
475
602
|
raise StopRunningException(StopRunningException.reason) from e
|
|
476
603
|
results_container["exception"] = e
|
|
477
604
|
traceback.print_exc()
|
|
478
|
-
# noinspection StrFormat
|
|
479
605
|
self.print(MESSAGES["workflow_failed"].format(error=str(e)))
|
|
480
606
|
finally:
|
|
481
607
|
results_container["completed"] = True
|
|
@@ -483,48 +609,20 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
483
609
|
return results_container["results"]
|
|
484
610
|
|
|
485
611
|
def _on_event(self, event: Union["BaseEvent", "BaseMessage"]) -> bool:
|
|
486
|
-
"""Process an event with step-by-step debugging.
|
|
487
|
-
|
|
488
|
-
Parameters
|
|
489
|
-
----------
|
|
490
|
-
event : Union[BaseEvent, BaseMessage]
|
|
491
|
-
The event to process.
|
|
492
|
-
|
|
493
|
-
Returns
|
|
494
|
-
-------
|
|
495
|
-
bool
|
|
496
|
-
True to continue, False to stop.
|
|
497
|
-
|
|
498
|
-
Raises
|
|
499
|
-
------
|
|
500
|
-
RuntimeError
|
|
501
|
-
If an error occurs while processing the event.
|
|
502
|
-
StopRunningException
|
|
503
|
-
If execution is stopped by user request.
|
|
504
|
-
"""
|
|
505
|
-
self._event_count += 1
|
|
506
|
-
self._current_event = event
|
|
507
|
-
|
|
508
|
-
if self._stop_requested.is_set():
|
|
509
|
-
self.log.debug(
|
|
510
|
-
"Step-by-step execution stopped before event processing"
|
|
511
|
-
)
|
|
512
|
-
return False
|
|
513
|
-
|
|
514
|
-
# Store event in history
|
|
515
|
-
event_info = event.model_dump(
|
|
516
|
-
mode="json", exclude_none=True, fallback=str
|
|
517
|
-
)
|
|
518
|
-
event_info["count"] = self._event_count
|
|
519
|
-
self._event_history.append(event_info)
|
|
520
|
-
|
|
521
|
-
# pylint: disable=too-many-try-statements
|
|
612
|
+
"""Process an event with step-by-step debugging."""
|
|
613
|
+
# pylint: disable=too-many-try-statements,broad-exception-caught
|
|
522
614
|
try:
|
|
523
|
-
#
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
self.
|
|
615
|
+
# Use the event processor for core logic
|
|
616
|
+
result = self._event_processor.process_event(event)
|
|
617
|
+
|
|
618
|
+
if result["action"] == "stop":
|
|
619
|
+
self.log.debug(
|
|
620
|
+
"Step-by-step execution stopped before event processing"
|
|
621
|
+
)
|
|
622
|
+
return False
|
|
623
|
+
self.emit_event(result["event_info"])
|
|
624
|
+
# Handle breakpoint logic
|
|
625
|
+
if result["should_break"]:
|
|
528
626
|
if not self._handle_step_interaction():
|
|
529
627
|
self._stop_requested.set()
|
|
530
628
|
if hasattr(event, "type") and event.type == "input_request":
|
|
@@ -532,17 +630,17 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
532
630
|
return True
|
|
533
631
|
raise StopRunningException(StopRunningException.reason)
|
|
534
632
|
|
|
535
|
-
# Process the event
|
|
536
|
-
WaldiezBaseRunner.process_event(event)
|
|
633
|
+
# Process the actual event
|
|
634
|
+
WaldiezBaseRunner.process_event(event, skip_send=True)
|
|
537
635
|
self._processed_events += 1
|
|
538
636
|
|
|
539
637
|
except Exception as e:
|
|
540
638
|
if not isinstance(e, StopRunningException):
|
|
541
639
|
raise RuntimeError(
|
|
542
|
-
f"Error processing event {event}: "
|
|
543
|
-
f"{e}\n{traceback.format_exc()}"
|
|
640
|
+
f"Error processing event {event}: {e}\n{traceback.format_exc()}"
|
|
544
641
|
) from e
|
|
545
642
|
raise StopRunningException(StopRunningException.reason) from e
|
|
643
|
+
|
|
546
644
|
return not self._stop_requested.is_set()
|
|
547
645
|
|
|
548
646
|
# pylint: disable=too-complex
|
|
@@ -558,19 +656,17 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
558
656
|
"""Run the Waldiez workflow with step-by-step debugging (async)."""
|
|
559
657
|
|
|
560
658
|
async def _execute_workflow() -> list[dict[str, Any]]:
|
|
561
|
-
"""Execute the workflow in an async context."""
|
|
562
659
|
# pylint: disable=import-outside-toplevel
|
|
563
660
|
from autogen.io import IOStream # pyright: ignore
|
|
564
661
|
|
|
565
662
|
from waldiez.io import StructuredIOStream
|
|
566
663
|
|
|
567
|
-
results: list[dict[str, Any]]
|
|
568
664
|
# pylint: disable=too-many-try-statements,broad-exception-caught
|
|
569
665
|
try:
|
|
570
666
|
loaded_module = self._load_module(output_file, temp_dir)
|
|
571
|
-
if self._stop_requested.is_set():
|
|
667
|
+
if self._stop_requested.is_set():
|
|
572
668
|
self.log.debug(
|
|
573
|
-
"
|
|
669
|
+
"Step-by-step execution stopped before workflow start"
|
|
574
670
|
)
|
|
575
671
|
return []
|
|
576
672
|
|
|
@@ -590,6 +686,7 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
590
686
|
|
|
591
687
|
results = await loaded_module.main(on_event=self._a_on_event)
|
|
592
688
|
self.print(MESSAGES["workflow_finished"])
|
|
689
|
+
return results
|
|
593
690
|
|
|
594
691
|
except Exception as e:
|
|
595
692
|
if StopRunningException.reason in str(e):
|
|
@@ -600,13 +697,9 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
600
697
|
traceback.print_exc()
|
|
601
698
|
return []
|
|
602
699
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
# Create cancellable task
|
|
700
|
+
# Create and monitor cancellable task
|
|
606
701
|
task = asyncio.create_task(_execute_workflow())
|
|
607
|
-
|
|
608
|
-
# Monitor for stop requests
|
|
609
|
-
# pylint: disable=too-many-try-statements
|
|
702
|
+
# pylint: disable=too-many-try-statements,broad-exception-caught
|
|
610
703
|
try:
|
|
611
704
|
while not task.done():
|
|
612
705
|
if self._stop_requested.is_set():
|
|
@@ -615,7 +708,6 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
615
708
|
break
|
|
616
709
|
await asyncio.sleep(0.1)
|
|
617
710
|
return await task
|
|
618
|
-
|
|
619
711
|
except asyncio.CancelledError:
|
|
620
712
|
self.log.debug("Step-by-step execution cancelled")
|
|
621
713
|
return []
|
|
@@ -623,50 +715,20 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
623
715
|
async def _a_on_event(
|
|
624
716
|
self, event: Union["BaseEvent", "BaseMessage"]
|
|
625
717
|
) -> bool:
|
|
626
|
-
"""Process an event with step-by-step debugging asynchronously.
|
|
627
|
-
|
|
628
|
-
Parameters
|
|
629
|
-
----------
|
|
630
|
-
event : Union[BaseEvent, BaseMessage]
|
|
631
|
-
The event to process.
|
|
632
|
-
|
|
633
|
-
Returns
|
|
634
|
-
-------
|
|
635
|
-
bool
|
|
636
|
-
True to continue, False to stop.
|
|
637
|
-
|
|
638
|
-
Raises
|
|
639
|
-
------
|
|
640
|
-
RuntimeError
|
|
641
|
-
If an error occurs while processing the event.
|
|
642
|
-
StopRunningException
|
|
643
|
-
If execution is stopped by user request.
|
|
644
|
-
"""
|
|
645
|
-
self._event_count += 1
|
|
646
|
-
self._current_event = event
|
|
647
|
-
|
|
648
|
-
if self._stop_requested.is_set():
|
|
649
|
-
self.log.debug(
|
|
650
|
-
"Async step-by-step execution stopped before event processing"
|
|
651
|
-
)
|
|
652
|
-
return False
|
|
653
|
-
|
|
654
|
-
# Store event in history
|
|
655
|
-
event_info = event.model_dump(
|
|
656
|
-
mode="json", exclude_none=True, fallback=str
|
|
657
|
-
)
|
|
658
|
-
event_info["count"] = self._event_count
|
|
659
|
-
self._event_history.append(event_info)
|
|
660
|
-
|
|
661
|
-
# pylint: disable=too-many-try-statements
|
|
718
|
+
"""Process an event with step-by-step debugging asynchronously."""
|
|
719
|
+
# pylint: disable=too-many-try-statements,broad-exception-caught
|
|
662
720
|
try:
|
|
663
|
-
#
|
|
664
|
-
|
|
665
|
-
event, self._step_mode
|
|
666
|
-
): # pragma: no branch
|
|
667
|
-
self.emit_event(event)
|
|
721
|
+
# Use the event processor for core logic
|
|
722
|
+
result = self._event_processor.process_event(event)
|
|
668
723
|
|
|
669
|
-
|
|
724
|
+
if result["action"] == "stop":
|
|
725
|
+
self.log.debug(
|
|
726
|
+
"Async step-by-step execution stopped before event processing"
|
|
727
|
+
)
|
|
728
|
+
return False
|
|
729
|
+
self.emit_event(result["event_info"])
|
|
730
|
+
# Handle breakpoint logic
|
|
731
|
+
if result["should_break"]:
|
|
670
732
|
if not await self._a_handle_step_interaction():
|
|
671
733
|
self._stop_requested.set()
|
|
672
734
|
if hasattr(event, "type") and event.type == "input_request":
|
|
@@ -674,72 +736,15 @@ class WaldiezStepByStepRunner(WaldiezBaseRunner, BreakpointsMixin):
|
|
|
674
736
|
return True
|
|
675
737
|
raise StopRunningException(StopRunningException.reason)
|
|
676
738
|
|
|
677
|
-
# Process the event
|
|
678
|
-
await WaldiezBaseRunner.a_process_event(event)
|
|
739
|
+
# Process the actual event
|
|
740
|
+
await WaldiezBaseRunner.a_process_event(event, skip_send=True)
|
|
679
741
|
self._processed_events += 1
|
|
680
742
|
|
|
681
743
|
except Exception as e:
|
|
682
744
|
if not isinstance(e, StopRunningException):
|
|
683
745
|
raise RuntimeError(
|
|
684
|
-
f"Error processing event {event}: "
|
|
685
|
-
f"{e}\n{traceback.format_exc()}"
|
|
746
|
+
f"Error processing event {event}: {e}\n{traceback.format_exc()}"
|
|
686
747
|
) from e
|
|
687
748
|
raise StopRunningException(StopRunningException.reason) from e
|
|
688
|
-
return not self._stop_requested.is_set()
|
|
689
749
|
|
|
690
|
-
|
|
691
|
-
"""Get execution statistics for step-by-step runner.
|
|
692
|
-
|
|
693
|
-
Returns
|
|
694
|
-
-------
|
|
695
|
-
dict[str, Any]
|
|
696
|
-
A dictionary containing execution statistics.
|
|
697
|
-
"""
|
|
698
|
-
return {
|
|
699
|
-
"total_events": self._event_count,
|
|
700
|
-
"processed_events": self._processed_events,
|
|
701
|
-
"event_processing_rate": (
|
|
702
|
-
self._processed_events / self._event_count
|
|
703
|
-
if self._event_count > 0
|
|
704
|
-
else 0
|
|
705
|
-
),
|
|
706
|
-
"step_mode": self._step_mode,
|
|
707
|
-
"auto_continue": self._auto_continue,
|
|
708
|
-
"breakpoints": sorted(self.get_breakpoints()),
|
|
709
|
-
"event_history_count": len(self._event_history),
|
|
710
|
-
"last_sender": self._last_sender,
|
|
711
|
-
"last_recipient": self._last_recipient,
|
|
712
|
-
"known_participants": [
|
|
713
|
-
p.model_dump() for p in self._known_participants
|
|
714
|
-
],
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
def get_event_history(self) -> list[dict[str, Any]]:
|
|
718
|
-
"""Get the history of processed events.
|
|
719
|
-
|
|
720
|
-
Returns
|
|
721
|
-
-------
|
|
722
|
-
list[dict[str, Any]]
|
|
723
|
-
List of event information dictionaries.
|
|
724
|
-
"""
|
|
725
|
-
return self._event_history.copy()
|
|
726
|
-
|
|
727
|
-
def enable_auto_continue(self, enabled: bool = True) -> None:
|
|
728
|
-
"""Enable or disable auto-continue mode.
|
|
729
|
-
|
|
730
|
-
Parameters
|
|
731
|
-
----------
|
|
732
|
-
enabled : bool, optional
|
|
733
|
-
Whether to enable auto-continue, by default True.
|
|
734
|
-
"""
|
|
735
|
-
self._auto_continue = enabled
|
|
736
|
-
|
|
737
|
-
def enable_step_mode(self, enabled: bool = True) -> None:
|
|
738
|
-
"""Enable or disable step mode.
|
|
739
|
-
|
|
740
|
-
Parameters
|
|
741
|
-
----------
|
|
742
|
-
enabled : bool, optional
|
|
743
|
-
Whether to enable step mode, by default True.
|
|
744
|
-
"""
|
|
745
|
-
self._step_mode = enabled
|
|
750
|
+
return not self._stop_requested.is_set()
|