waldiez 0.5.6__py3-none-any.whl → 0.5.8__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 (116) hide show
  1. waldiez/_version.py +1 -1
  2. waldiez/cli.py +17 -2
  3. waldiez/exporter.py +1 -1
  4. waldiez/exporting/agent/code_execution.py +8 -1
  5. waldiez/exporting/agent/exporter.py +2 -1
  6. waldiez/exporting/agent/extras/captain_agent_extras.py +1 -0
  7. waldiez/exporting/agent/extras/doc_agent_extras.py +2 -3
  8. waldiez/exporting/agent/extras/group_manager_agent_extas.py +1 -0
  9. waldiez/exporting/agent/extras/handoffs/after_work.py +4 -4
  10. waldiez/exporting/agent/extras/handoffs/target.py +3 -0
  11. waldiez/exporting/agent/extras/rag/chroma_extras.py +0 -4
  12. waldiez/exporting/agent/extras/rag/mongo_extras.py +0 -1
  13. waldiez/exporting/agent/extras/rag/pgvector_extras.py +0 -2
  14. waldiez/exporting/agent/extras/rag/qdrant_extras.py +0 -3
  15. waldiez/exporting/agent/extras/rag/vector_db_extras.py +3 -2
  16. waldiez/exporting/agent/factory.py +11 -11
  17. waldiez/exporting/agent/processor.py +3 -2
  18. waldiez/exporting/chats/exporter.py +2 -2
  19. waldiez/exporting/chats/factory.py +5 -5
  20. waldiez/exporting/chats/processor.py +22 -1
  21. waldiez/exporting/chats/utils/common.py +45 -1
  22. waldiez/exporting/chats/utils/group.py +1 -1
  23. waldiez/exporting/chats/utils/sequential.py +3 -68
  24. waldiez/exporting/chats/utils/single.py +1 -38
  25. waldiez/exporting/core/context.py +39 -38
  26. waldiez/exporting/core/exporter.py +10 -10
  27. waldiez/exporting/core/exporters.py +36 -0
  28. waldiez/exporting/core/extras/base.py +2 -2
  29. waldiez/exporting/core/extras/chat_extras.py +4 -2
  30. waldiez/exporting/core/extras/path_resolver.py +6 -4
  31. waldiez/exporting/core/extras/serializer.py +1 -0
  32. waldiez/exporting/core/protocols.py +6 -0
  33. waldiez/exporting/core/result.py +8 -7
  34. waldiez/exporting/core/types.py +2 -2
  35. waldiez/exporting/core/utils/llm_config.py +2 -0
  36. waldiez/exporting/flow/execution_generator.py +54 -32
  37. waldiez/exporting/flow/factory.py +2 -2
  38. waldiez/exporting/flow/file_generator.py +8 -7
  39. waldiez/exporting/flow/merger.py +8 -7
  40. waldiez/exporting/flow/orchestrator.py +22 -8
  41. waldiez/exporting/flow/utils/__init__.py +2 -0
  42. waldiez/exporting/flow/utils/common.py +20 -11
  43. waldiez/exporting/flow/utils/importing.py +2 -1
  44. waldiez/exporting/flow/utils/logging.py +5 -2
  45. waldiez/exporting/models/exporter.py +2 -1
  46. waldiez/exporting/models/factory.py +6 -7
  47. waldiez/exporting/tools/exporter.py +7 -6
  48. waldiez/exporting/tools/factory.py +4 -5
  49. waldiez/exporting/tools/processor.py +9 -4
  50. waldiez/exporting/tools/registration.py +1 -0
  51. waldiez/io/_ws.py +2 -0
  52. waldiez/io/models/content/audio.py +1 -0
  53. waldiez/io/models/content/file.py +1 -0
  54. waldiez/io/models/content/image.py +1 -0
  55. waldiez/io/models/content/text.py +1 -0
  56. waldiez/io/models/content/video.py +1 -0
  57. waldiez/io/models/user_input.py +1 -0
  58. waldiez/io/models/user_response.py +1 -0
  59. waldiez/io/mqtt.py +6 -3
  60. waldiez/io/redis.py +7 -9
  61. waldiez/io/structured.py +8 -6
  62. waldiez/io/utils.py +11 -4
  63. waldiez/io/ws.py +4 -3
  64. waldiez/logger.py +11 -1
  65. waldiez/models/agents/agent/agent.py +1 -0
  66. waldiez/models/agents/agent/agent_data.py +2 -2
  67. waldiez/models/agents/agent/nested_chat.py +1 -4
  68. waldiez/models/agents/agent/termination_message.py +0 -7
  69. waldiez/models/agents/agent/update_system_message.py +2 -2
  70. waldiez/models/agents/doc_agent/doc_agent_data.py +33 -26
  71. waldiez/models/agents/doc_agent/rag_query_engine.py +1 -1
  72. waldiez/models/agents/extra_requirements.py +5 -5
  73. waldiez/models/agents/group_manager/group_manager.py +3 -7
  74. waldiez/models/agents/group_manager/speakers.py +0 -7
  75. waldiez/models/agents/rag_user_proxy/rag_user_proxy.py +0 -2
  76. waldiez/models/agents/rag_user_proxy/rag_user_proxy_data.py +0 -2
  77. waldiez/models/agents/rag_user_proxy/retrieve_config.py +1 -17
  78. waldiez/models/agents/rag_user_proxy/vector_db_config.py +0 -5
  79. waldiez/models/chat/chat_data.py +0 -2
  80. waldiez/models/chat/chat_summary.py +5 -3
  81. waldiez/models/common/handoff.py +26 -18
  82. waldiez/models/common/naming.py +1 -0
  83. waldiez/models/flow/flow.py +9 -7
  84. waldiez/models/model/_llm.py +4 -2
  85. waldiez/models/model/extra_requirements.py +3 -3
  86. waldiez/models/model/model.py +5 -4
  87. waldiez/models/tool/extra_requirements.py +2 -2
  88. waldiez/models/tool/predefined/_google.py +7 -12
  89. waldiez/models/tool/predefined/_perplexity.py +13 -9
  90. waldiez/models/tool/predefined/_searxng.py +4 -1
  91. waldiez/models/tool/predefined/_tavily.py +0 -6
  92. waldiez/models/tool/predefined/_wikipedia.py +5 -1
  93. waldiez/models/tool/predefined/_youtube.py +0 -4
  94. waldiez/models/tool/tool.py +7 -7
  95. waldiez/models/tool/tool_data.py +39 -2
  96. waldiez/models/waldiez.py +29 -29
  97. waldiez/runner.py +18 -13
  98. waldiez/running/base_runner.py +96 -40
  99. waldiez/running/environment.py +2 -0
  100. waldiez/running/patch_io_stream.py +2 -0
  101. waldiez/running/post_run.py +3 -0
  102. waldiez/running/pre_run.py +1 -0
  103. waldiez/running/protocol.py +50 -48
  104. waldiez/running/run_results.py +2 -10
  105. waldiez/running/standard_runner.py +37 -13
  106. waldiez/running/timeline_processor.py +12 -1
  107. waldiez/running/utils.py +2 -0
  108. waldiez/utils/conflict_checker.py +1 -1
  109. waldiez/utils/version.py +1 -0
  110. {waldiez-0.5.6.dist-info → waldiez-0.5.8.dist-info}/METADATA +68 -65
  111. {waldiez-0.5.6.dist-info → waldiez-0.5.8.dist-info}/RECORD +115 -116
  112. waldiez/exporting/agent/extras/group/target.py +0 -178
  113. {waldiez-0.5.6.dist-info → waldiez-0.5.8.dist-info}/WHEEL +0 -0
  114. {waldiez-0.5.6.dist-info → waldiez-0.5.8.dist-info}/entry_points.txt +0 -0
  115. {waldiez-0.5.6.dist-info → waldiez-0.5.8.dist-info}/licenses/LICENSE +0 -0
  116. {waldiez-0.5.6.dist-info → waldiez-0.5.8.dist-info}/licenses/NOTICE.md +0 -0
@@ -4,7 +4,7 @@
4
4
  # pylint: disable=line-too-long
5
5
  """Utilities for exporting a single chat in a flow."""
6
6
 
7
- from typing import Any, Callable, Optional
7
+ from typing import Any, Callable
8
8
 
9
9
  from waldiez.models import (
10
10
  WaldiezAgent,
@@ -57,42 +57,6 @@ def export_single_chat(
57
57
  -------
58
58
  tuple[str, str]
59
59
  The chat string and additional methods string if any
60
-
61
- Example
62
- -------
63
- ```python
64
- >>> from waldiez.models import WaldiezAgent, WaldiezChat, WaldiezChatData, WaldiezChatMessage
65
- >>> chat = WaldiezChat(
66
- ... id="wc-1",
67
- ... name="chat1",
68
- ... description="A chat between two agents.",
69
- ... tags=["chat", "chat1"],
70
- ... requirements=[],
71
- ... data=WaldiezChatData(
72
- ... sender="wa-1",
73
- ... recipient="wa-2",
74
- ... message=WaldiezChatMessage(
75
- ... type="string",
76
- ... content="Hello, how are you?",
77
- ... ),
78
- ... ),
79
- ... )
80
- >>> agent_names = {"wa-1": "agent1", "wa-2": "agent2"}
81
- >>> chat_names = {"wc-1": "chat1"}
82
- >>> export_single_chat_string(
83
- ... sender=agent1,
84
- ... recipient=agent2,
85
- ... chat=chat,
86
- ... agent_names=agent_names,
87
- ... chat_names=chat_names,
88
- ... tabs=0,
89
- ... )
90
- agent1.initiate_chat(
91
- agent2,
92
- message="Hello, how are you?",
93
- cache=cache,
94
- )
95
- ```
96
60
  """
97
61
  tab = " " * tab_length * tabs if tabs > 0 else ""
98
62
  chat_args = chat.get_chat_args(for_queue=False, sender=sender)
@@ -280,7 +244,6 @@ def get_chat_message(
280
244
  The message argument and additional methods string if any.
281
245
  """
282
246
  additional_methods_string = ""
283
- method_content: Optional[str] = None
284
247
  if (
285
248
  sender.is_rag_user
286
249
  and isinstance(sender, WaldiezRagUserProxy)
@@ -18,11 +18,11 @@ from .types import ExportConfig
18
18
  class ExporterContext:
19
19
  """Context object containing common exporter dependencies."""
20
20
 
21
- serializer: Optional[Serializer] = None
22
- path_resolver: Optional[PathResolver] = None
23
- validator: Optional[Validator] = None
24
- config: Optional[ExportConfig] = None
25
- logger: Optional[ExportingLogger] = None
21
+ serializer: Serializer | None = None
22
+ path_resolver: PathResolver | None = None
23
+ validator: Validator | None = None
24
+ config: ExportConfig | None = None
25
+ logger: ExportingLogger | None = None
26
26
 
27
27
  def get_serializer(self) -> Serializer:
28
28
  """Get serializer or raise if not set.
@@ -46,34 +46,34 @@ class ExporterContext:
46
46
 
47
47
  def get_config(
48
48
  self,
49
- name: Optional[str] = None,
50
- description: Optional[str] = None,
51
- requirements: Optional[list[str]] = None,
52
- tags: Optional[list[str]] = None,
53
- output_extension: Optional[str] = None,
49
+ name: str | None = None,
50
+ description: str | None = None,
51
+ requirements: list[str] | None = None,
52
+ tags: list[str] | None = None,
53
+ output_extension: str | None = None,
54
54
  is_async: bool = False,
55
- output_directory: Optional[str] = None,
56
- cache_seed: Optional[int] = None,
55
+ output_directory: str | None = None,
56
+ cache_seed: int | None = None,
57
57
  ) -> ExportConfig:
58
58
  """Get export config or return default.
59
59
 
60
60
  Parameters
61
61
  ----------
62
- name : Optional[str], optional
62
+ name : str], optional
63
63
  The name of the export, by default None
64
- description : Optional[str], optional
64
+ description : str], optional
65
65
  A brief description of the export, by default None
66
- requirements : Optional[list[str]], optional
66
+ requirements : list[str]], optional
67
67
  A list of requirements for the export, by default None
68
- tags : Optional[list[str]], optional
68
+ tags : list[str]], optional
69
69
  A list of tags associated with the export, by default None
70
- output_extension : Optional[str], optional
70
+ output_extension : str], optional
71
71
  The file extension for the output, by default None
72
72
  is_async : bool, optional
73
73
  Whether the export is asynchronous, by default False
74
- output_directory : Optional[str], optional
74
+ output_directory : str], optional
75
75
  The directory where the output will be saved, by default None
76
- cache_seed : Optional[int], optional
76
+ cache_seed : int], optional
77
77
  The seed for caching, by default None
78
78
 
79
79
  Returns
@@ -124,6 +124,7 @@ class ExporterContext:
124
124
 
125
125
 
126
126
  # pylint: disable=too-few-public-methods
127
+ # noinspection PyUnresolvedReferences,PyTypeChecker
127
128
  class DefaultExporterContext(ExporterContext):
128
129
  """Singleton context for exporters.
129
130
 
@@ -164,11 +165,11 @@ class DefaultExporterContext(ExporterContext):
164
165
 
165
166
  def __init__(
166
167
  self,
167
- serializer: Optional[Serializer] = None,
168
- validator: Optional[Validator] = None,
169
- path_resolver: Optional[PathResolver] = None,
170
- logger: Optional[ExportingLogger] = None,
171
- config: Optional[ExportConfig] = None,
168
+ serializer: Serializer | None = None,
169
+ validator: Validator | None = None,
170
+ path_resolver: PathResolver | None = None,
171
+ logger: ExportingLogger | None = None,
172
+ config: ExportConfig | None = None,
172
173
  ) -> None:
173
174
  if hasattr(self, "_initialized"):
174
175
  return
@@ -183,16 +184,16 @@ class DefaultExporterContext(ExporterContext):
183
184
 
184
185
 
185
186
  def get_default_exporter_context(
186
- config: Optional[ExportConfig] = None,
187
- logger: Optional[ExportingLogger] = None,
187
+ config: ExportConfig | None = None,
188
+ logger: ExportingLogger | None = None,
188
189
  ) -> ExporterContext:
189
190
  """Get the default exporter context.
190
191
 
191
192
  Parameters
192
193
  ----------
193
- config : Optional[ExportConfig], optional
194
+ config : ExportConfig | None, optional
194
195
  The export configuration, by default None
195
- logger : Optional[ExportingLogger], optional
196
+ logger : ExportingLogger | None, optional
196
197
  The logger instance, by default None
197
198
 
198
199
  Returns
@@ -209,25 +210,25 @@ def get_default_exporter_context(
209
210
 
210
211
 
211
212
  def create_exporter_context(
212
- serializer: Optional[Serializer] = None,
213
- validator: Optional[Validator] = None,
214
- path_resolver: Optional[PathResolver] = None,
215
- config: Optional[ExportConfig] = None,
216
- logger: Optional[ExportingLogger] = None,
213
+ serializer: Serializer | None = None,
214
+ validator: Validator | None = None,
215
+ path_resolver: PathResolver | None = None,
216
+ config: ExportConfig | None = None,
217
+ logger: ExportingLogger | None = None,
217
218
  ) -> ExporterContext:
218
219
  """Create an exporter context with the given components.
219
220
 
220
221
  Parameters
221
222
  ----------
222
- serializer : Optional[Serializer], optional
223
+ serializer : Serializer | None, optional
223
224
  The serializer component, by default None
224
- path_resolver : Optional[PathResolver], optional
225
+ path_resolver : PathResolver | None, optional
225
226
  The path resolver component, by default None
226
- validator : Optional[Validator], optional
227
+ validator : Validator | None, optional
227
228
  The validator component, by default None
228
- config : Optional[ExportConfig], optional
229
+ config : ExportConfig | None, optional
229
230
  The export configuration, by default None
230
- logger : Optional[ExportingLogger], optional
231
+ logger : ExportingLogger | None, optional
231
232
  The logger instance, by default None
232
233
 
233
234
  Returns
@@ -90,12 +90,12 @@ class Exporter(abc.ABC, Generic[Extras]):
90
90
  """
91
91
 
92
92
  @abc.abstractmethod
93
- def generate_main_content(self) -> Optional[str]:
93
+ def generate_main_content(self) -> str | None:
94
94
  """Generate the main export content.
95
95
 
96
96
  Returns
97
97
  -------
98
- Optional[str]
98
+ str | None
99
99
  The main content, or None if no content should be generated.
100
100
  """
101
101
 
@@ -182,8 +182,8 @@ class Exporter(abc.ABC, Generic[Extras]):
182
182
  content: str,
183
183
  position: ExportPosition,
184
184
  order: ContentOrder = ContentOrder.MAIN_CONTENT,
185
- agent_id: Optional[str] = None,
186
- agent_position: Optional[AgentPosition] = None,
185
+ agent_id: str | None = None,
186
+ agent_position: AgentPosition | None = None,
187
187
  skip_strip: bool | None = None,
188
188
  **metadata: Any,
189
189
  ) -> None:
@@ -195,11 +195,11 @@ class Exporter(abc.ABC, Generic[Extras]):
195
195
  The content to add.
196
196
  position : ExportPosition
197
197
  The position of the content.
198
- order : int, optional
199
- The order within the position, by default 0
200
- agent_id : Optional[str], optional
198
+ order : ContentOrder, optional
199
+ The order within the position, by default ContentOrder.MAIN_CONTENT
200
+ agent_id : str | None, optional
201
201
  Agent ID for agent-relative positioning, by default None
202
- agent_position : Optional[AgentPosition], optional
202
+ agent_position : AgentPosition | None, optional
203
203
  Position relative to agent, by default None
204
204
  skip_strip : bool | None, optional
205
205
  Whether to skip stripping whitespace, by default None
@@ -223,7 +223,7 @@ class Exporter(abc.ABC, Generic[Extras]):
223
223
  self,
224
224
  name: str,
225
225
  value: str,
226
- description: Optional[str] = None,
226
+ description: str | None = None,
227
227
  required: bool = True,
228
228
  ) -> None:
229
229
  """Add environment variable.
@@ -234,7 +234,7 @@ class Exporter(abc.ABC, Generic[Extras]):
234
234
  The name of the environment variable.
235
235
  value : str
236
236
  The value of the environment variable.
237
- description : Optional[str], optional
237
+ description : str | None, optional
238
238
  Description of the variable, by default None
239
239
  required : bool, optional
240
240
  Whether the variable is required, by default True
@@ -12,6 +12,16 @@ from .types import Extras
12
12
  class SimpleExporter(Exporter[None]):
13
13
  """Simple exporter that doesn't use extras system."""
14
14
 
15
+ def generate_main_content(self) -> str | None:
16
+ """Generate main content for the exporter.
17
+
18
+ Returns
19
+ -------
20
+ str | None
21
+ The main content as a string or None if not applicable.
22
+ """
23
+ raise NotImplementedError("Subclasses must implement this method.")
24
+
15
25
  @property
16
26
  def extras(self) -> None:
17
27
  """Simple exporters don't have extras."""
@@ -24,6 +34,22 @@ class SimpleExporter(Exporter[None]):
24
34
  class ConfigurableExporter(Exporter[Extras]):
25
35
  """Exporter with configuration support."""
26
36
 
37
+ @property
38
+ def extras(self) -> Extras:
39
+ """Get the extras for this exporter.
40
+
41
+ Returns
42
+ -------
43
+ Extras
44
+ The extras associated with this exporter.
45
+
46
+ Raises
47
+ ------
48
+ NotImplementedError
49
+ If the method is not implemented in a subclass.
50
+ """
51
+ raise NotImplementedError("Subclasses must implement this method.")
52
+
27
53
  def __init__(self, config: Optional[dict[str, Any]] = None, **kwargs: Any):
28
54
  """Initialize with configuration.
29
55
 
@@ -37,6 +63,16 @@ class ConfigurableExporter(Exporter[Extras]):
37
63
  super().__init__(**kwargs)
38
64
  self._config = config or {}
39
65
 
66
+ def generate_main_content(self) -> str | None:
67
+ """Generate main content for the exporter.
68
+
69
+ Returns
70
+ -------
71
+ str | None
72
+ The main content as a string or None if not applicable.
73
+ """
74
+ raise NotImplementedError("Subclasses must implement this method.")
75
+
40
76
  def get_config_value(self, key: str, default: Any = None) -> Any:
41
77
  """Get a configuration value.
42
78
 
@@ -43,7 +43,7 @@ class BaseExtras(ExportContributor):
43
43
 
44
44
  Parameters
45
45
  ----------
46
- arg : InstanceArgument
46
+ arg : InstanceArgument | str
47
47
  The argument to add.
48
48
  tabs : int, optional
49
49
  The number of tabs to indent the argument, by default 0.
@@ -76,7 +76,7 @@ class BaseExtras(ExportContributor):
76
76
 
77
77
  Parameters
78
78
  ----------
79
- import_statement : str
79
+ import_statement : ImportStatement
80
80
  The import statement to add.
81
81
  """
82
82
  if import_statement and import_statement.statement.strip():
@@ -16,10 +16,12 @@ class ChatExtras(BaseExtras):
16
16
 
17
17
  Attributes
18
18
  ----------
19
- chat_definition : str
20
- The chat definition content.
19
+ chat_prerequisites : str
20
+ The chat prerequisites content.
21
21
  chat_initiation : str
22
22
  The chat initiation content.
23
+ chat_registration : str
24
+ The chat registration content.
23
25
  """
24
26
 
25
27
  chat_prerequisites: str = ""
@@ -3,7 +3,7 @@
3
3
  """Default path resolver for Waldiez items."""
4
4
 
5
5
  from pathlib import Path
6
- from typing import Optional, Union
6
+ from typing import Union
7
7
 
8
8
  from ..protocols import PathResolver
9
9
 
@@ -45,7 +45,7 @@ class DefaultPathResolver(PathResolver):
45
45
  return DefaultPathResolver._check_local_path(path) is not None
46
46
 
47
47
  @staticmethod
48
- def _check_local_path(string: str) -> Optional[Path]:
48
+ def _check_local_path(string: str) -> Path | None:
49
49
  """Check if a string is a local path.
50
50
 
51
51
  Parameters
@@ -55,10 +55,12 @@ class DefaultPathResolver(PathResolver):
55
55
 
56
56
  Returns
57
57
  -------
58
- bool
59
- True if the path is a local path.
58
+ Path | None
59
+ The resolved local path string (raw path format) or
60
+ None if it does not exist.
60
61
  """
61
62
  # pylint: disable=broad-exception-caught
63
+ # noinspection PyBroadException
62
64
  try:
63
65
  path = Path(string).resolve()
64
66
  except BaseException: # pragma: no cover
@@ -14,6 +14,7 @@ from ..protocols import Serializer
14
14
  class DefaultSerializer(Serializer):
15
15
  """Default serializer for Waldiez items."""
16
16
 
17
+ # noinspection PyProtocol
17
18
  def serialize(self, obj: Any, **kwargs: Any) -> str:
18
19
  """Serialize an item to a formatted string.
19
20
 
@@ -132,6 +132,12 @@ class ContentGenerator(Protocol):
132
132
  -------
133
133
  str
134
134
  The generated content.
135
+
136
+
137
+ Raises
138
+ ------
139
+ ExporterContentError
140
+ If exporting fails.
135
141
  """
136
142
 
137
143
 
@@ -215,7 +215,7 @@ class ExportResult:
215
215
  self,
216
216
  content: str,
217
217
  position: ExportPosition = DEFAULT_EXPORT_POSITION,
218
- order: Union[ContentOrder, int] = ContentOrder.MAIN_CONTENT,
218
+ order: ContentOrder | int = ContentOrder.MAIN_CONTENT,
219
219
  skip_strip: bool = False,
220
220
  agent_id: Optional[str] = None,
221
221
  agent_position: Optional[AgentPosition] = None,
@@ -229,15 +229,15 @@ class ExportResult:
229
229
  The content to add.
230
230
  position : ExportPosition, optional
231
231
  The position of the content, by default AGENTS
232
- order : int, optional
232
+ order : ContentOrder | int, optional
233
233
  The order within the position, by default 0
234
234
  skip_strip : bool, optional
235
235
  Whether to skip stripping whitespace from content, by default False
236
- agent_id : Optional[str], optional
236
+ agent_id : str | None, optional
237
237
  The agent ID if positioned relative to an agent, by default None
238
- agent_position : Optional[AgentPosition], optional
238
+ agent_position : AgentPosition | None, optional
239
239
  The position relative to the agent, by default None
240
- metadata : Optional[dict[str, Any]], optional
240
+ metadata : dict[str, Any] | None, optional
241
241
  Additional metadata for the content, by default None
242
242
  """
243
243
  order_value = order.value if isinstance(order, ContentOrder) else order
@@ -662,6 +662,7 @@ def merge_export_results(*results: ExportResult) -> ExportResult:
662
662
  return ExportResult()
663
663
 
664
664
  merged = ExportResult()
665
+ # noinspection PyTypeChecker
665
666
  for result in results:
666
667
  merged.merge_with(result)
667
668
 
@@ -681,7 +682,7 @@ def create_empty_result() -> ExportResult:
681
682
 
682
683
  def create_result_with_content(
683
684
  main_content: str,
684
- imports: Optional[list[str]] = None,
685
+ imports: list[str] | None = None,
685
686
  ) -> ExportResult:
686
687
  """Create an ExportResult with basic content.
687
688
 
@@ -689,7 +690,7 @@ def create_result_with_content(
689
690
  ----------
690
691
  main_content : str
691
692
  The main content.
692
- imports : Optional[list[str]], optional
693
+ imports : list[str], optional
693
694
  list of import statements, by default None
694
695
 
695
696
  Returns
@@ -133,7 +133,7 @@ class EnvironmentVariable:
133
133
  tuple[str, str]
134
134
  The environment variable as a tuple.
135
135
  """
136
- return (self.name, self.value)
136
+ return self.name, self.value
137
137
 
138
138
 
139
139
  # Instance Argument
@@ -311,7 +311,7 @@ class ExportConfig:
311
311
  valid_fields = {f.name for f in fields(cls)}
312
312
  output_extension = kwargs.pop("output_extension", "py")
313
313
  for_notebook = kwargs.pop("for_notebook", output_extension == "ipynb")
314
- if for_notebook is True:
314
+ if for_notebook:
315
315
  output_extension = "ipynb"
316
316
  cache_seed = kwargs.pop("cache_seed", None)
317
317
  if cache_seed is not None and not isinstance(cache_seed, int):
@@ -52,6 +52,7 @@ def get_agent_llm_config_arg(
52
52
  )
53
53
 
54
54
 
55
+ # noinspection DuplicatedCode
55
56
  def _get_agent_llm_config_arg_as_arg(
56
57
  agent: WaldiezAgent,
57
58
  all_models: list[WaldiezModel],
@@ -85,6 +86,7 @@ def _get_agent_llm_config_arg_as_arg(
85
86
  return content
86
87
 
87
88
 
89
+ # noinspection DuplicatedCode
88
90
  def _get_agent_llm_config_arg_as_dict(
89
91
  agent: WaldiezAgent,
90
92
  all_models: list[WaldiezModel],
@@ -115,11 +115,14 @@ class ExecutionGenerator:
115
115
  "Callable[[BaseEvent], Coroutine[None, None, bool]]"
116
116
  "] = None"
117
117
  )
118
- return_type_hint = (
119
- "AsyncRunResponseProtocol" if is_async else "RunResponseProtocol"
120
- )
118
+ return_type_hint = "list[dict[str, Any]]"
121
119
  flow_content += f"def main({on_event_arg}) -> {return_type_hint}:\n"
122
- flow_content += f" {main_doc_string(is_async=is_async)}\n"
120
+ flow_content += f" {main_doc_string()}\n"
121
+ if not is_async:
122
+ flow_content += " results: list[RunResponseProtocol] | RunResponseProtocol = []\n"
123
+ else:
124
+ flow_content += " results: list[AsyncRunResponseProtocol] | AsyncRunResponseProtocol = []\n"
125
+ flow_content += " result_dicts: list[dict[str, Any]] = []\n"
123
126
  space = " "
124
127
  if cache_seed is not None:
125
128
  flow_content += (
@@ -138,7 +141,7 @@ class ExecutionGenerator:
138
141
  flow_content += after_run + "\n"
139
142
  if cache_seed is not None:
140
143
  space = space[4:]
141
- flow_content += f"{space}return results\n"
144
+ flow_content += f"{space}return result_dicts\n"
142
145
  return flow_content
143
146
 
144
147
  @staticmethod
@@ -163,42 +166,19 @@ class ExecutionGenerator:
163
166
  if is_async:
164
167
  return "# %%\nawait main()\n"
165
168
  return "# %%\nmain()\n"
169
+ return_type_hint = "list[dict[str, Any]]"
166
170
  if is_async:
167
171
  content += "async def call_main() -> None:\n"
168
- return_type_hint = "list[AsyncRunResponseProtocol]"
169
172
  else:
170
173
  content += "def call_main() -> None:\n"
171
- return_type_hint = "list[RunResponseProtocol]"
172
174
  content += f'{tab}"""Run the main function and print the results."""\n'
173
175
  content += f"{tab}results: {return_type_hint} = "
174
176
  if is_async:
175
177
  content += "await "
176
178
  content += "main()\n"
177
- content += f"{tab}results_dicts: list[dict[str, Any]] = []\n"
178
- content += f"{tab}for result in results:\n"
179
- if is_async:
180
- content += f"{tab}{tab}result_summary = await result.summary\n"
181
- content += f"{tab}{tab}result_messages = await result.messages\n"
182
- content += f"{tab}{tab}result_cost = await result.cost\n"
183
- else:
184
- content += f"{tab}{tab}result_summary = result.summary\n"
185
- content += f"{tab}{tab}result_messages = result.messages\n"
186
- content += f"{tab}{tab}result_cost = result.cost\n"
187
- content += f"{tab}{tab}cost: dict[str, Any] | None = None\n"
188
- content += f"{tab}{tab}if result_cost:\n"
189
- content += f'{tab}{tab}{tab}cost = result_cost.model_dump(mode="json", fallback=str)\n'
190
- content += f"{tab}{tab}results_dicts.append(\n"
191
- content += f"{tab}{tab}{tab}{{\n"
192
- content += f"{tab}{tab}{tab}{tab}'summary': result_summary,\n"
193
- content += f"{tab}{tab}{tab}{tab}'messages': result_messages,\n"
194
- content += f"{tab}{tab}{tab}{tab}'cost': cost,\n"
195
- content += f"{tab}{tab}{tab}}}\n"
196
- content += f"{tab}{tab})\n"
197
- content += "\n"
198
- content += f"{tab}results_dict = {{\n"
199
- content += f"{tab}{tab}'results': results_dicts,\n"
200
- content += f"{tab}}}\n"
201
- content += f"{tab}print(json.dumps(results_dict, indent=2))\n"
179
+ content += (
180
+ f"{tab}print(json.dumps(results, indent=2, ensure_ascii=False))\n"
181
+ )
202
182
  return content
203
183
 
204
184
  @staticmethod
@@ -226,3 +206,45 @@ class ExecutionGenerator:
226
206
  else:
227
207
  content += " call_main()\n"
228
208
  return content
209
+
210
+
211
+ def get_result_dicts_string(space: str, is_async: bool) -> str:
212
+ """Get the result dicts string.
213
+
214
+ Parameters
215
+ ----------
216
+ space : str
217
+ The space string to use for indentation.
218
+ is_async : bool
219
+ Whether the function is asynchronous.
220
+
221
+ Returns
222
+ -------
223
+ str
224
+ The result dicts string.
225
+ """
226
+ flow_content = f"{space}for index, result in enumerate(results):\n"
227
+ if not is_async:
228
+ flow_content += f"{space} result_dict = {{\n"
229
+ flow_content += f"{space} 'index': index,\n"
230
+ flow_content += f"{space} 'messages': result.messages,\n"
231
+ flow_content += f"{space} 'summary': result.summary,\n"
232
+ flow_content += f"{space} 'cost': result.cost.model_dump(mode='json', fallback=str) if result.cost else None,\n"
233
+ flow_content += f"{space} 'context_variables': result.context_variables.model_dump(mode='json', fallback=str) if result.context_variables else None,\n"
234
+ flow_content += f"{space} 'last_speaker': result.last_speaker,\n"
235
+ flow_content += f"{space} 'uuid': str(result.uuid),\n"
236
+ flow_content += f"{space} }}\n"
237
+ else:
238
+ flow_content += f"{space} result_dict = {{\n"
239
+ flow_content += f"{space} 'index': index,\n"
240
+ flow_content += f"{space} 'messages': await result.messages,\n"
241
+ flow_content += f"{space} 'summary': await result.summary,\n"
242
+ flow_content += f"{space} 'cost': (await result.cost).model_dump(mode='json', fallback=str) if await result.cost else None,\n"
243
+ flow_content += f"{space} 'context_variables': (await result.context_variables).model_dump(mode='json', fallback=str) if await result.context_variables else None,\n"
244
+ flow_content += (
245
+ f"{space} 'last_speaker': await result.last_speaker,\n"
246
+ )
247
+ flow_content += f"{space} 'uuid': str(result.uuid),\n"
248
+ flow_content += f"{space} }}\n"
249
+ flow_content += f"{space} result_dicts.append(result_dict)\n"
250
+ return flow_content
@@ -31,9 +31,9 @@ def create_flow_exporter(
31
31
  ----------
32
32
  waldiez : Waldiez
33
33
  The Waldiez instance containing the flow data.
34
- output_dir : Path
34
+ output_dir : Path | None
35
35
  The directory where the exported flow will be saved.
36
- uploads_root : Path
36
+ uploads_root : Path | None
37
37
  The root directory for uploads, if applicable.
38
38
  for_notebook : bool
39
39
  Whether the export is intended for a notebook environment.