waldiez 0.5.9__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 (109) hide show
  1. waldiez/_version.py +1 -1
  2. waldiez/cli.py +113 -24
  3. waldiez/exporting/agent/exporter.py +9 -6
  4. waldiez/exporting/agent/extras/captain_agent_extras.py +44 -7
  5. waldiez/exporting/agent/extras/group_manager_agent_extas.py +6 -1
  6. waldiez/exporting/agent/extras/handoffs/after_work.py +1 -0
  7. waldiez/exporting/agent/extras/handoffs/available.py +1 -0
  8. waldiez/exporting/agent/extras/handoffs/condition.py +3 -1
  9. waldiez/exporting/agent/extras/handoffs/handoff.py +1 -0
  10. waldiez/exporting/agent/extras/handoffs/target.py +1 -0
  11. waldiez/exporting/agent/termination.py +1 -0
  12. waldiez/exporting/chats/utils/common.py +25 -23
  13. waldiez/exporting/core/__init__.py +0 -2
  14. waldiez/exporting/core/constants.py +3 -1
  15. waldiez/exporting/core/context.py +13 -13
  16. waldiez/exporting/core/extras/serializer.py +12 -10
  17. waldiez/exporting/core/protocols.py +0 -141
  18. waldiez/exporting/core/result.py +5 -5
  19. waldiez/exporting/core/types.py +1 -0
  20. waldiez/exporting/core/utils/llm_config.py +2 -2
  21. waldiez/exporting/flow/execution_generator.py +1 -0
  22. waldiez/exporting/flow/merger.py +2 -2
  23. waldiez/exporting/flow/orchestrator.py +1 -0
  24. waldiez/exporting/flow/utils/common.py +3 -3
  25. waldiez/exporting/flow/utils/importing.py +1 -0
  26. waldiez/exporting/flow/utils/logging.py +7 -80
  27. waldiez/exporting/tools/exporter.py +5 -0
  28. waldiez/exporting/tools/factory.py +4 -0
  29. waldiez/exporting/tools/processor.py +5 -1
  30. waldiez/io/__init__.py +3 -1
  31. waldiez/io/_ws.py +15 -5
  32. waldiez/io/models/content/image.py +1 -0
  33. waldiez/io/models/user_input.py +4 -4
  34. waldiez/io/models/user_response.py +1 -0
  35. waldiez/io/mqtt.py +1 -1
  36. waldiez/io/structured.py +98 -45
  37. waldiez/io/utils.py +17 -11
  38. waldiez/io/ws.py +10 -12
  39. waldiez/logger.py +180 -63
  40. waldiez/models/agents/agent/agent.py +2 -1
  41. waldiez/models/agents/agent/update_system_message.py +0 -2
  42. waldiez/models/agents/doc_agent/doc_agent.py +8 -1
  43. waldiez/models/chat/chat.py +1 -0
  44. waldiez/models/chat/chat_data.py +0 -2
  45. waldiez/models/common/base.py +2 -0
  46. waldiez/models/common/dict_utils.py +169 -40
  47. waldiez/models/common/handoff.py +2 -0
  48. waldiez/models/common/method_utils.py +2 -0
  49. waldiez/models/flow/flow.py +6 -6
  50. waldiez/models/flow/info.py +5 -1
  51. waldiez/models/model/_llm.py +31 -14
  52. waldiez/models/model/model.py +4 -1
  53. waldiez/models/model/model_data.py +18 -5
  54. waldiez/models/tool/predefined/_config.py +5 -1
  55. waldiez/models/tool/predefined/_duckduckgo.py +4 -0
  56. waldiez/models/tool/predefined/_email.py +477 -0
  57. waldiez/models/tool/predefined/_google.py +4 -1
  58. waldiez/models/tool/predefined/_perplexity.py +4 -1
  59. waldiez/models/tool/predefined/_searxng.py +4 -1
  60. waldiez/models/tool/predefined/_tavily.py +4 -1
  61. waldiez/models/tool/predefined/_wikipedia.py +5 -2
  62. waldiez/models/tool/predefined/_youtube.py +4 -1
  63. waldiez/models/tool/predefined/protocol.py +3 -0
  64. waldiez/models/tool/tool.py +22 -4
  65. waldiez/models/waldiez.py +12 -0
  66. waldiez/runner.py +37 -54
  67. waldiez/running/__init__.py +6 -0
  68. waldiez/running/base_runner.py +381 -363
  69. waldiez/running/environment.py +1 -0
  70. waldiez/running/exceptions.py +9 -0
  71. waldiez/running/post_run.py +10 -4
  72. waldiez/running/pre_run.py +199 -66
  73. waldiez/running/protocol.py +21 -101
  74. waldiez/running/run_results.py +1 -1
  75. waldiez/running/standard_runner.py +83 -276
  76. waldiez/running/step_by_step/__init__.py +46 -0
  77. waldiez/running/step_by_step/breakpoints_mixin.py +512 -0
  78. waldiez/running/step_by_step/command_handler.py +151 -0
  79. waldiez/running/step_by_step/events_processor.py +199 -0
  80. waldiez/running/step_by_step/step_by_step_models.py +541 -0
  81. waldiez/running/step_by_step/step_by_step_runner.py +750 -0
  82. waldiez/running/subprocess_runner/__base__.py +279 -0
  83. waldiez/running/subprocess_runner/__init__.py +16 -0
  84. waldiez/running/subprocess_runner/_async_runner.py +362 -0
  85. waldiez/running/subprocess_runner/_sync_runner.py +456 -0
  86. waldiez/running/subprocess_runner/runner.py +570 -0
  87. waldiez/running/timeline_processor.py +1 -1
  88. waldiez/running/utils.py +492 -3
  89. waldiez/utils/version.py +2 -6
  90. waldiez/ws/__init__.py +71 -0
  91. waldiez/ws/__main__.py +15 -0
  92. waldiez/ws/_file_handler.py +199 -0
  93. waldiez/ws/_mock.py +74 -0
  94. waldiez/ws/cli.py +235 -0
  95. waldiez/ws/client_manager.py +851 -0
  96. waldiez/ws/errors.py +416 -0
  97. waldiez/ws/models.py +988 -0
  98. waldiez/ws/reloader.py +363 -0
  99. waldiez/ws/server.py +508 -0
  100. waldiez/ws/session_manager.py +393 -0
  101. waldiez/ws/session_stats.py +83 -0
  102. waldiez/ws/utils.py +410 -0
  103. {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/METADATA +105 -96
  104. {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/RECORD +108 -83
  105. waldiez/running/patch_io_stream.py +0 -210
  106. {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/WHEEL +0 -0
  107. {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/entry_points.txt +0 -0
  108. {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/licenses/LICENSE +0 -0
  109. {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/licenses/NOTICE.md +0 -0
waldiez/_version.py CHANGED
@@ -5,4 +5,4 @@
5
5
  This file is automatically generated by Hatchling.
6
6
  Do not edit this file directly.
7
7
  """
8
- __version__ = VERSION = "0.5.9"
8
+ __version__ = VERSION = "0.6.0"
waldiez/cli.py CHANGED
@@ -7,8 +7,9 @@
7
7
 
8
8
  import json
9
9
  import os
10
+ import sys
10
11
  from pathlib import Path
11
- from typing import Optional
12
+ from typing import TYPE_CHECKING, Literal, Optional
12
13
 
13
14
  import anyio
14
15
  import typer
@@ -19,9 +20,14 @@ from .cli_extras import add_cli_extras
19
20
  from .logger import get_logger
20
21
  from .models import Waldiez
21
22
  from .utils import get_waldiez_version
23
+ from .ws import add_ws_app
24
+
25
+ if TYPE_CHECKING:
26
+ # noinspection PyUnusedImports
27
+ from waldiez.running import WaldiezBaseRunner
22
28
 
23
29
  load_dotenv()
24
- LOG = get_logger()
30
+ LOG = get_logger(level="debug")
25
31
 
26
32
  app = typer.Typer(
27
33
  name="waldiez",
@@ -55,7 +61,13 @@ def show_version(
55
61
  raise typer.Exit()
56
62
 
57
63
 
58
- @app.command()
64
+ @app.command(
65
+ context_settings={
66
+ "help_option_names": ["-h", "--help"],
67
+ "allow_extra_args": True,
68
+ "ignore_unknown_options": True,
69
+ },
70
+ )
59
71
  def run(
60
72
  file: Annotated[
61
73
  Path,
@@ -113,15 +125,53 @@ def run(
113
125
  readable=True,
114
126
  resolve_path=True,
115
127
  ),
128
+ step: bool = typer.Option( # noqa: B008
129
+ False,
130
+ "--step",
131
+ "-s",
132
+ help=(
133
+ "Run the flow in step-by-step mode. "
134
+ "This will pause execution after each step, allowing for debugging."
135
+ ),
136
+ is_eager=True,
137
+ rich_help_panel="Debug",
138
+ ),
139
+ subprocess: bool = typer.Option(
140
+ False,
141
+ "--subprocess",
142
+ "-p",
143
+ help=(
144
+ "Run the flow using the subprocess runner. "
145
+ "This will execute the flow in a separate process."
146
+ ),
147
+ is_eager=True,
148
+ ),
116
149
  ) -> None:
117
150
  """Run a Waldiez flow."""
118
151
  os.environ["AUTOGEN_USE_DOCKER"] = "0"
119
152
  os.environ["NEP50_DISABLE_WARNING"] = "1"
120
153
  output_path = _get_output_path(output, force)
121
- from waldiez.runner import WaldiezRunner
154
+ from waldiez.runner import create_runner
122
155
 
156
+ run_mode: Literal["standard", "debug", "subprocess"] = "standard"
157
+ if subprocess:
158
+ run_mode = "subprocess"
159
+ elif step:
160
+ run_mode = "debug"
161
+ subprocess_mode = "run"
162
+ if run_mode == "subprocess":
163
+ subprocess_mode = "debug" if step else "run"
123
164
  try:
124
- runner = WaldiezRunner.load(file)
165
+ runner = create_runner(
166
+ Waldiez.load(file),
167
+ mode=run_mode,
168
+ output_path=output_path,
169
+ uploads_root=uploads_root,
170
+ structured_io=structured,
171
+ dot_env=env_file,
172
+ subprocess_mode=subprocess_mode,
173
+ waldiez_file=file,
174
+ )
125
175
  except FileNotFoundError as error:
126
176
  typer.echo(f"File not found: {file}")
127
177
  raise typer.Exit(code=1) from error
@@ -131,25 +181,7 @@ def run(
131
181
  except ValueError as error:
132
182
  typer.echo(f"Invalid .waldiez file: {error}")
133
183
  raise typer.Exit(code=1) from error
134
- if runner.is_async:
135
- anyio.run(
136
- runner.a_run,
137
- output_path,
138
- uploads_root,
139
- structured, # structured_io
140
- False, # skip_mmd
141
- False, # skip_timeline
142
- env_file,
143
- )
144
- else:
145
- runner.run(
146
- output_path=output_path,
147
- uploads_root=uploads_root,
148
- structured_io=structured,
149
- skip_mmd=False,
150
- skip_timeline=False,
151
- dot_env=env_file,
152
- )
184
+ _do_run(runner, output_path, uploads_root, structured, env_file)
153
185
 
154
186
 
155
187
  @app.command()
@@ -252,7 +284,64 @@ def _get_output_path(output: Optional[Path], force: bool) -> Optional[Path]:
252
284
  return output
253
285
 
254
286
 
287
+ def _do_run(
288
+ runner: "WaldiezBaseRunner", # noqa: F821
289
+ output_path: Path | None,
290
+ uploads_root: Path | None,
291
+ structured: bool,
292
+ env_file: Path | None,
293
+ ) -> None:
294
+ _error: Exception | None = None
295
+ _stopped: bool = False
296
+ from waldiez.running import StopRunningException
297
+
298
+ try:
299
+ if runner.waldiez.is_async:
300
+ anyio.run(
301
+ runner.a_run,
302
+ output_path,
303
+ uploads_root,
304
+ structured, # structured_io
305
+ False, # skip_mmd
306
+ False, # skip_timeline
307
+ env_file,
308
+ )
309
+ # os._exit(0 if _error is None else 1)
310
+ else:
311
+ runner.run(
312
+ output_path=output_path,
313
+ uploads_root=uploads_root,
314
+ structured_io=structured,
315
+ skip_mmd=False,
316
+ skip_timeline=False,
317
+ dot_env=env_file,
318
+ )
319
+ except Exception as error:
320
+ _error = (
321
+ error if StopRunningException.reason not in str(error) else None
322
+ )
323
+ _stopped = StopRunningException.reason in str(error)
324
+ _error = error if not _stopped else None
325
+ if _error:
326
+ LOG.error("Execution failed: %s", error)
327
+ else:
328
+ LOG.warning(StopRunningException.reason)
329
+ raise typer.Exit(code=1 if error else 0) from error
330
+ except KeyboardInterrupt:
331
+ LOG.warning("Execution interrupted.")
332
+ _stopped = True
333
+ typer.echo("Execution stopped by user.")
334
+ finally:
335
+ if _stopped:
336
+ os._exit(0)
337
+ elif _error:
338
+ os._exit(1)
339
+ else:
340
+ sys.exit(0)
341
+
342
+
255
343
  add_cli_extras(app)
344
+ add_ws_app(app)
256
345
 
257
346
  if __name__ == "__main__":
258
347
  app()
@@ -73,17 +73,17 @@ class AgentExporter(Exporter[StandardExtras]):
73
73
  Whether the flow is async, by default False
74
74
  for_notebook : bool, optional
75
75
  Whether exporting for notebook, by default False
76
- cache_seed : Optional[int], optional
76
+ cache_seed : int, optional
77
77
  Cache seed if any, by default None
78
- initial_chats : Optional[list[WaldiezAgentConnection]], optional
78
+ initial_chats : list[WaldiezAgentConnection], optional
79
79
  Initial chats for group managers, by default None
80
- group_chat_members : Optional[list[WaldiezAgent]], optional
80
+ group_chat_members : list[WaldiezAgent], optional
81
81
  Group chat members if group manager, by default None
82
- arguments_resolver : Optional[Callable], optional
82
+ arguments_resolver : Callable, optional
83
83
  Function to resolve additional arguments, by default None
84
- output_dir : Optional[Union[str, Path]], optional
84
+ output_dir : str | Path, optional
85
85
  Output directory for generated files, by default None
86
- context : Optional[ExporterContext], optional
86
+ context : ExporterContext, optional
87
87
  Exporter context with dependencies, by default None
88
88
  **kwargs : Any
89
89
  Additional keyword arguments.
@@ -300,6 +300,9 @@ class AgentExporter(Exporter[StandardExtras]):
300
300
  if captain_result.before_agent:
301
301
  extras.append_before_agent(captain_result.before_agent)
302
302
 
303
+ if captain_result.after_agent:
304
+ extras.append_after_agent(captain_result.after_agent)
305
+
303
306
  return extras
304
307
 
305
308
  def create_reasoning_extras(self) -> StandardExtras:
@@ -1,6 +1,8 @@
1
1
  # SPDX-License-Identifier: Apache-2.0.
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
3
  # pylint: disable=too-few-public-methods,no-self-use
4
+ # pylint: disable=line-too-long
5
+ # flake8: noqa: E501
4
6
  """Captain agent configuration processor."""
5
7
 
6
8
  import json
@@ -102,8 +104,32 @@ class CaptainAgentProcessor:
102
104
  result.set_nested_config(nested_config)
103
105
  serialized_nested_config = self.serializer.serialize(nested_config)
104
106
  result.add_arg(f"nested_config={serialized_nested_config}", tabs=1)
107
+ result.append_before_agent(
108
+ self._patch_default_nested_config(),
109
+ )
105
110
  return result
106
111
 
112
+ @staticmethod
113
+ def _patch_default_nested_config() -> str:
114
+ """Patch the default nested configuration.
115
+
116
+ Returns
117
+ -------
118
+ str
119
+ The patched nested configuration.
120
+ """
121
+ content = """
122
+ # try to avoid having both temperature and top_p in the config
123
+ try:
124
+ _CAPTAIN_AGENT_DEFAULT_CONFIG = CaptainAgent.DEFAULT_NESTED_CONFIG
125
+ _CAPTAIN_AGENT_DEFAULT_CONFIG.get("autobuild_build_config", {}).get("default_llm_config", {}).pop("top_p", None)
126
+ CaptainAgent.DEFAULT_NESTED_CONFIG = _CAPTAIN_AGENT_DEFAULT_CONFIG
127
+ except Exception as e:
128
+ print(f"Error occurred while patching default nested config: {e}")
129
+ """
130
+
131
+ return content
132
+
107
133
  def _generate_nested_config(
108
134
  self,
109
135
  agent: WaldiezCaptainAgent,
@@ -135,9 +161,9 @@ class CaptainAgentProcessor:
135
161
  ) as f:
136
162
  json.dump(llm_config_list, f, ensure_ascii=False, indent=4)
137
163
  llm_config = llm_config_list[0]
138
- if "temperature" not in llm_config:
164
+ if "temperature" not in llm_config and "top_p" not in llm_config:
139
165
  llm_config["temperature"] = 1
140
- if "top_p" not in llm_config:
166
+ if "top_p" not in llm_config and "temperature" not in llm_config:
141
167
  llm_config["top_p"] = 0.95
142
168
  if "max_tokens" not in llm_config:
143
169
  llm_config["max_tokens"] = 2048
@@ -177,9 +203,15 @@ class CaptainAgentProcessor:
177
203
  if not config_list:
178
204
  default_model = self._get_default_model(uuid.uuid4().hex)
179
205
  default_llm_config = default_model.get_llm_config(skip_price=True)
180
- if "temperature" not in default_llm_config:
206
+ if (
207
+ "temperature" not in default_llm_config
208
+ and "top_p" not in default_llm_config
209
+ ):
181
210
  default_llm_config["temperature"] = temperature
182
- if "top_p" not in default_llm_config:
211
+ if (
212
+ "top_p" not in default_llm_config
213
+ and "temperature" not in default_llm_config
214
+ ):
183
215
  default_llm_config["top_p"] = top_p
184
216
  if "max_tokens" not in default_llm_config:
185
217
  default_llm_config["max_tokens"] = max_tokens
@@ -220,15 +252,20 @@ class CaptainAgentProcessor:
220
252
  code_execution_config["timeout"] = (
221
253
  self.agent.data.code_execution_config.timeout or 300
222
254
  )
223
- return {
255
+ to_return: dict[str, Any] = {
224
256
  "default_llm_config": {
225
- "temperature": llm_config["temperature"],
226
- "top_p": llm_config["top_p"],
227
257
  "max_tokens": llm_config["max_tokens"],
228
258
  },
229
259
  "code_execution_config": code_execution_config,
230
260
  "coding": coding,
231
261
  }
262
+ if llm_config.get("temperature") is not None:
263
+ to_return["default_llm_config"]["temperature"] = llm_config[
264
+ "temperature"
265
+ ]
266
+ elif llm_config.get("top_p") is not None:
267
+ to_return["default_llm_config"]["top_p"] = llm_config["top_p"]
268
+ return to_return
232
269
 
233
270
  def _get_waldiez_model(self, model_id: str) -> WaldiezModel:
234
271
  """Get the Waldiez model by its ID.
@@ -252,8 +252,12 @@ class GroupManagerProcessor:
252
252
  cache_seed=self.cache_seed,
253
253
  as_dict=True,
254
254
  )
255
+ manager_name = self.agent_names[self.agent.id]
255
256
  pattern_lines.append(
256
- f" group_manager_args={{\n{llm_config_arg} }},"
257
+ " group_manager_args={\n"
258
+ f"{llm_config_arg}"
259
+ f' "name": "{manager_name}",\n'
260
+ " },"
257
261
  )
258
262
 
259
263
  # Add context variables if present
@@ -445,6 +449,7 @@ class GroupManagerProcessor:
445
449
 
446
450
  return self._get_transition_target(self.agent.data.after_work)
447
451
 
452
+ # noinspection PyTypeHints
448
453
  def _get_transition_target(
449
454
  self, target: WaldiezTransitionTarget
450
455
  ) -> tuple[str, str]:
@@ -49,6 +49,7 @@ class AfterWorkProcessor:
49
49
  self.all_chats = all_chats
50
50
  self.serializer = serializer
51
51
 
52
+ # noinspection PyTypeHints
52
53
  def process(self, after_work: WaldiezTransitionTarget) -> AfterWorkResult:
53
54
  """Process after-work configuration.
54
55
 
@@ -69,6 +69,7 @@ class TransitionAvailableProcessor:
69
69
  )
70
70
  result.extra_imports.add(f"{import_prefix}ContextExpression")
71
71
  return result
72
+ # noinspection PyUnreachableCode
72
73
  raise ValueError(
73
74
  f"Unsupported transition availability type: {available.type}"
74
75
  )
@@ -151,8 +151,10 @@ class ConditionProcessor:
151
151
  """Process an expression context condition handoff."""
152
152
  expression = self.serializer(condition.expression)
153
153
  condition_string = (
154
- f"ExpressionContextCondition(expression={expression})"
154
+ "ExpressionContextCondition("
155
+ f"expression=ContextExpression({expression}))"
155
156
  )
156
157
  self.result.content += condition_string
157
158
  extra_import = f"{self.IMPORT_PREFIX}ExpressionContextCondition"
158
159
  self.result.extra_imports.add(extra_import)
160
+ self.result.extra_imports.add(f"{self.IMPORT_PREFIX}ContextExpression")
@@ -146,6 +146,7 @@ class HandoffProcessor:
146
146
  reg_string += ")"
147
147
  return reg_string
148
148
 
149
+ # noinspection PyTypeHints
149
150
  def _process_after_work(
150
151
  self, after_work: WaldiezTransitionTarget
151
152
  ) -> TargetResult:
@@ -36,6 +36,7 @@ class TargetResult:
36
36
  extra_imports: Set[str] = field(default_factory=set) # pyright: ignore
37
37
 
38
38
 
39
+ # noinspection PyTypeHints
39
40
  class TransitionTargetProcessor:
40
41
  """Processor for transition targets."""
41
42
 
@@ -47,4 +47,5 @@ class TerminationProcessor:
47
47
  termination_arg=function_name,
48
48
  before_content="\n\n" + content + "\n",
49
49
  )
50
+ # noinspection PyUnreachableCode
50
51
  return TerminationConfig()
@@ -73,7 +73,7 @@ def get_event_handler_string(
73
73
  content = (
74
74
  f"{tab}if on_event:\n"
75
75
  f"{tab} if not isinstance(results, list):\n"
76
- f"{tab} results = [results]\n"
76
+ f"{tab} results = [results] # pylint: disable=redefined-variable-type\n"
77
77
  f"{tab} for index, result in enumerate(results):\n"
78
78
  )
79
79
  if is_async:
@@ -81,9 +81,10 @@ def get_event_handler_string(
81
81
  f"{tab} async for event in result.events:\n"
82
82
  f"{tab} try:\n"
83
83
  f"{tab} should_continue = await on_event(event)\n"
84
- f"{tab} except Exception as e:\n"
85
- f"{tab} raise RuntimeError(\n"
86
- f"{tab} 'Error in event handler: ' + str(e)\n"
84
+ f"{tab} except BaseException as e:\n"
85
+ f'{tab} print(f"Error in event handler: {{e}}")\n'
86
+ f"{tab} raise SystemExit(\n"
87
+ f'{tab} "Error in event handler: " + str(e)\n'
87
88
  f"{tab} ) from e\n"
88
89
  )
89
90
  else:
@@ -91,22 +92,23 @@ def get_event_handler_string(
91
92
  f"{tab} for event in result.events:\n"
92
93
  f"{tab} try:\n"
93
94
  f"{tab} should_continue = on_event(event)\n"
94
- f"{tab} except Exception as e:\n"
95
- f"{tab} raise RuntimeError(\n"
96
- f"{tab} 'Error in event handler: ' + str(e)\n"
95
+ f"{tab} except BaseException as e:\n"
96
+ f'{tab} print(f"Error in event handler: {{e}}")\n'
97
+ f"{tab} raise SystemExit(\n"
98
+ f'{tab} "Error in event handler: " + str(e)\n'
97
99
  f"{tab} ) from e\n"
98
100
  )
99
101
  content += (
100
- f"{tab} if event.type == 'run_completion':\n"
101
- f"{tab} should_continue = False\n"
102
- f"{tab} if not should_continue:\n"
102
+ f'{tab} if event.type == "run_completion":\n'
103
103
  f"{tab} break\n"
104
+ f"{tab} if not should_continue:\n"
105
+ f'{tab} raise SystemExit("Event handler stopped processing")\n'
104
106
  )
105
107
  content += get_result_dicts_string(tab, is_async)
106
108
  content += (
107
109
  f"{tab}else:\n"
108
110
  f"{tab} if not isinstance(results, list):\n"
109
- f"{tab} results = [results]\n"
111
+ f"{tab} results = [results] # pylint: disable=redefined-variable-type\n"
110
112
  f"{tab} for index, result in enumerate(results):\n"
111
113
  )
112
114
  if is_async:
@@ -135,22 +137,22 @@ def get_result_dicts_string(tab: str, is_async: bool) -> str:
135
137
  """
136
138
  space = f"{tab} "
137
139
  flow_content = f"{space}result_dict = {{\n"
138
- flow_content += f"{space} 'index': index,\n"
140
+ flow_content += f'{space} "index": index,\n'
139
141
  if is_async:
140
- flow_content += f"{space} 'messages': await result.messages,\n"
141
- flow_content += f"{space} 'summary': await result.summary,\n"
142
- flow_content += f"{space} 'cost': (await result.cost).model_dump(mode='json', fallback=str) if await result.cost else None,\n"
143
- flow_content += f"{space} 'context_variables': (await result.context_variables).model_dump(mode='json', fallback=str) if await result.context_variables else None,\n"
142
+ flow_content += f'{space} "messages": await result.messages,\n'
143
+ flow_content += f'{space} "summary": await result.summary,\n'
144
+ flow_content += f'{space} "cost": (await result.cost).model_dump(mode="json", fallback=str) if await result.cost else None,\n'
145
+ flow_content += f'{space} "context_variables": (await result.context_variables).model_dump(mode="json", fallback=str) if await result.context_variables else None,\n'
144
146
  flow_content += (
145
- f"{space} 'last_speaker': await result.last_speaker,\n"
147
+ f'{space} "last_speaker": await result.last_speaker,\n'
146
148
  )
147
149
  else:
148
- flow_content += f"{space} 'messages': result.messages,\n"
149
- flow_content += f"{space} 'summary': result.summary,\n"
150
- flow_content += f"{space} 'cost': result.cost.model_dump(mode='json', fallback=str) if result.cost else None,\n"
151
- flow_content += f"{space} 'context_variables': result.context_variables.model_dump(mode='json', fallback=str) if result.context_variables else None,\n"
152
- flow_content += f"{space} 'last_speaker': result.last_speaker,\n"
153
- flow_content += f"{space} 'uuid': str(result.uuid),\n"
150
+ flow_content += f'{space} "messages": result.messages,\n'
151
+ flow_content += f'{space} "summary": result.summary,\n'
152
+ flow_content += f'{space} "cost": result.cost.model_dump(mode="json", fallback=str) if result.cost else None,\n'
153
+ flow_content += f'{space} "context_variables": result.context_variables.model_dump(mode="json", fallback=str) if result.context_variables else None,\n'
154
+ flow_content += f'{space} "last_speaker": result.last_speaker,\n'
155
+ flow_content += f'{space} "uuid": str(result.uuid),\n'
154
156
  flow_content += f"{space}}}\n"
155
157
  flow_content += f"{space}result_dicts.append(result_dict)\n"
156
158
  return flow_content
@@ -90,7 +90,6 @@ from .extras.tool_extras import (
90
90
  from .protocols import (
91
91
  ContentGenerator,
92
92
  ExportContributor,
93
- ExportingLogger,
94
93
  PathResolver,
95
94
  Serializer,
96
95
  Validator,
@@ -128,7 +127,6 @@ __all__ = [
128
127
  "ConfigurableExporter",
129
128
  # Protocols
130
129
  "ContentGenerator",
131
- "ExportingLogger",
132
130
  "ExportContributor",
133
131
  "Validator",
134
132
  "Serializer",
@@ -2,6 +2,8 @@
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
3
  """Constants for Waldiez exporting core."""
4
4
 
5
+ from datetime import datetime
6
+
5
7
  from .enums import (
6
8
  AgentPosition,
7
9
  ExportPosition,
@@ -10,7 +12,7 @@ from .enums import (
10
12
 
11
13
  FILE_HEADER = (
12
14
  "# SPDX-License-Identifier: Apache-2.0.\n"
13
- "# Copyright (c) 2024 - 2025 Waldiez and contributors."
15
+ f"# Copyright (c) 2024 - {datetime.now().year} Waldiez and contributors."
14
16
  )
15
17
  DEFAULT_IMPORT_POSITION = ImportPosition.THIRD_PARTY
16
18
  DEFAULT_EXPORT_POSITION = ExportPosition.AGENTS
@@ -6,11 +6,11 @@ import threading
6
6
  from dataclasses import dataclass
7
7
  from typing import Any, Optional
8
8
 
9
- from waldiez.logger import WaldiezLogger
9
+ from waldiez.logger import WaldiezLogger, get_logger
10
10
 
11
11
  from .extras.path_resolver import DefaultPathResolver
12
12
  from .extras.serializer import DefaultSerializer
13
- from .protocols import ExportingLogger, PathResolver, Serializer, Validator
13
+ from .protocols import PathResolver, Serializer, Validator
14
14
  from .types import ExportConfig
15
15
 
16
16
 
@@ -22,7 +22,7 @@ class ExporterContext:
22
22
  path_resolver: PathResolver | None = None
23
23
  validator: Validator | None = None
24
24
  config: ExportConfig | None = None
25
- logger: ExportingLogger | None = None
25
+ logger: WaldiezLogger | None = None
26
26
 
27
27
  def get_serializer(self) -> Serializer:
28
28
  """Get serializer or raise if not set.
@@ -112,15 +112,15 @@ class ExporterContext:
112
112
  """
113
113
  self.config = config
114
114
 
115
- def get_logger(self) -> ExportingLogger:
115
+ def get_logger(self) -> WaldiezLogger:
116
116
  """Get logger or create a default one.
117
117
 
118
118
  Returns
119
119
  -------
120
- ExportingLogger
120
+ WaldiezLogger
121
121
  The logger instance.
122
122
  """
123
- return self.logger or WaldiezLogger()
123
+ return self.logger or get_logger()
124
124
 
125
125
 
126
126
  # pylint: disable=too-few-public-methods
@@ -168,7 +168,7 @@ class DefaultExporterContext(ExporterContext):
168
168
  serializer: Serializer | None = None,
169
169
  validator: Validator | None = None,
170
170
  path_resolver: PathResolver | None = None,
171
- logger: ExportingLogger | None = None,
171
+ logger: WaldiezLogger | None = None,
172
172
  config: ExportConfig | None = None,
173
173
  ) -> None:
174
174
  if hasattr(self, "_initialized"):
@@ -176,7 +176,7 @@ class DefaultExporterContext(ExporterContext):
176
176
  super().__init__(
177
177
  serializer=serializer or DefaultSerializer(),
178
178
  path_resolver=path_resolver or DefaultPathResolver(),
179
- logger=logger or WaldiezLogger(),
179
+ logger=logger or get_logger(),
180
180
  validator=validator,
181
181
  config=config,
182
182
  )
@@ -185,7 +185,7 @@ class DefaultExporterContext(ExporterContext):
185
185
 
186
186
  def get_default_exporter_context(
187
187
  config: ExportConfig | None = None,
188
- logger: ExportingLogger | None = None,
188
+ logger: WaldiezLogger | None = None,
189
189
  ) -> ExporterContext:
190
190
  """Get the default exporter context.
191
191
 
@@ -204,7 +204,7 @@ def get_default_exporter_context(
204
204
  return DefaultExporterContext(
205
205
  serializer=DefaultSerializer(),
206
206
  path_resolver=DefaultPathResolver(),
207
- logger=logger or WaldiezLogger(),
207
+ logger=logger or get_logger(),
208
208
  config=config,
209
209
  )
210
210
 
@@ -214,7 +214,7 @@ def create_exporter_context(
214
214
  validator: Validator | None = None,
215
215
  path_resolver: PathResolver | None = None,
216
216
  config: ExportConfig | None = None,
217
- logger: ExportingLogger | None = None,
217
+ logger: WaldiezLogger | None = None,
218
218
  ) -> ExporterContext:
219
219
  """Create an exporter context with the given components.
220
220
 
@@ -228,7 +228,7 @@ def create_exporter_context(
228
228
  The validator component, by default None
229
229
  config : ExportConfig | None, optional
230
230
  The export configuration, by default None
231
- logger : ExportingLogger | None, optional
231
+ logger : WaldiezLogger | None, optional
232
232
  The logger instance, by default None
233
233
 
234
234
  Returns
@@ -240,6 +240,6 @@ def create_exporter_context(
240
240
  serializer=serializer or DefaultSerializer(),
241
241
  path_resolver=path_resolver or DefaultPathResolver(),
242
242
  validator=validator,
243
- logger=logger or WaldiezLogger(),
243
+ logger=logger or get_logger(),
244
244
  config=config,
245
245
  )