waldiez 0.6.0__py3-none-any.whl → 0.6.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of waldiez might be problematic. Click here for more details.

Files changed (188) hide show
  1. waldiez/__init__.py +1 -1
  2. waldiez/_version.py +1 -1
  3. waldiez/cli.py +18 -7
  4. waldiez/cli_extras/jupyter.py +3 -0
  5. waldiez/cli_extras/runner.py +3 -1
  6. waldiez/cli_extras/studio.py +3 -1
  7. waldiez/exporter.py +9 -3
  8. waldiez/exporting/agent/exporter.py +9 -10
  9. waldiez/exporting/agent/extras/captain_agent_extras.py +6 -6
  10. waldiez/exporting/agent/extras/doc_agent_extras.py +6 -6
  11. waldiez/exporting/agent/extras/group_manager_agent_extas.py +34 -23
  12. waldiez/exporting/agent/extras/group_member_extras.py +6 -5
  13. waldiez/exporting/agent/extras/handoffs/after_work.py +1 -1
  14. waldiez/exporting/agent/extras/handoffs/available.py +1 -1
  15. waldiez/exporting/agent/extras/handoffs/condition.py +3 -2
  16. waldiez/exporting/agent/extras/handoffs/handoff.py +1 -1
  17. waldiez/exporting/agent/extras/handoffs/target.py +6 -4
  18. waldiez/exporting/agent/extras/rag/chroma_extras.py +27 -19
  19. waldiez/exporting/agent/extras/rag/mongo_extras.py +8 -8
  20. waldiez/exporting/agent/extras/rag/pgvector_extras.py +5 -5
  21. waldiez/exporting/agent/extras/rag/qdrant_extras.py +5 -4
  22. waldiez/exporting/agent/extras/rag/vector_db_extras.py +1 -1
  23. waldiez/exporting/agent/extras/rag_user_proxy_agent_extras.py +5 -7
  24. waldiez/exporting/agent/extras/reasoning_agent_extras.py +3 -5
  25. waldiez/exporting/chats/exporter.py +4 -4
  26. waldiez/exporting/chats/processor.py +1 -2
  27. waldiez/exporting/chats/utils/common.py +89 -48
  28. waldiez/exporting/chats/utils/group.py +9 -9
  29. waldiez/exporting/chats/utils/nested.py +7 -7
  30. waldiez/exporting/chats/utils/sequential.py +1 -1
  31. waldiez/exporting/chats/utils/single.py +2 -2
  32. waldiez/exporting/core/content.py +7 -7
  33. waldiez/exporting/core/context.py +5 -3
  34. waldiez/exporting/core/exporter.py +5 -3
  35. waldiez/exporting/core/exporters.py +2 -2
  36. waldiez/exporting/core/extras/agent_extras/captain_extras.py +2 -2
  37. waldiez/exporting/core/extras/agent_extras/group_manager_extras.py +2 -2
  38. waldiez/exporting/core/extras/agent_extras/rag_user_extras.py +2 -2
  39. waldiez/exporting/core/extras/agent_extras/standard_extras.py +3 -8
  40. waldiez/exporting/core/extras/base.py +7 -5
  41. waldiez/exporting/core/extras/flow_extras.py +4 -5
  42. waldiez/exporting/core/extras/model_extras.py +2 -2
  43. waldiez/exporting/core/extras/path_resolver.py +1 -2
  44. waldiez/exporting/core/extras/serializer.py +2 -2
  45. waldiez/exporting/core/protocols.py +6 -5
  46. waldiez/exporting/core/result.py +25 -28
  47. waldiez/exporting/core/types.py +10 -10
  48. waldiez/exporting/core/utils/llm_config.py +2 -2
  49. waldiez/exporting/core/validation.py +10 -11
  50. waldiez/exporting/flow/execution_generator.py +98 -10
  51. waldiez/exporting/flow/exporter.py +2 -2
  52. waldiez/exporting/flow/factory.py +2 -2
  53. waldiez/exporting/flow/file_generator.py +4 -2
  54. waldiez/exporting/flow/merger.py +5 -3
  55. waldiez/exporting/flow/orchestrator.py +72 -2
  56. waldiez/exporting/flow/utils/common.py +5 -5
  57. waldiez/exporting/flow/utils/importing.py +6 -7
  58. waldiez/exporting/flow/utils/linting.py +25 -9
  59. waldiez/exporting/flow/utils/logging.py +2 -2
  60. waldiez/exporting/models/exporter.py +8 -8
  61. waldiez/exporting/models/processor.py +5 -5
  62. waldiez/exporting/tools/exporter.py +2 -2
  63. waldiez/exporting/tools/processor.py +7 -4
  64. waldiez/io/__init__.py +8 -4
  65. waldiez/io/_ws.py +10 -6
  66. waldiez/io/models/constants.py +10 -10
  67. waldiez/io/models/content/audio.py +1 -0
  68. waldiez/io/models/content/base.py +20 -18
  69. waldiez/io/models/content/file.py +1 -0
  70. waldiez/io/models/content/image.py +1 -0
  71. waldiez/io/models/content/text.py +1 -0
  72. waldiez/io/models/content/video.py +1 -0
  73. waldiez/io/models/user_input.py +10 -5
  74. waldiez/io/models/user_response.py +17 -16
  75. waldiez/io/mqtt.py +18 -31
  76. waldiez/io/redis.py +18 -22
  77. waldiez/io/structured.py +52 -53
  78. waldiez/io/utils.py +3 -0
  79. waldiez/io/ws.py +5 -1
  80. waldiez/logger.py +16 -3
  81. waldiez/models/agents/__init__.py +3 -0
  82. waldiez/models/agents/agent/agent.py +23 -16
  83. waldiez/models/agents/agent/agent_data.py +25 -22
  84. waldiez/models/agents/agent/code_execution.py +9 -11
  85. waldiez/models/agents/agent/termination_message.py +10 -12
  86. waldiez/models/agents/agent/update_system_message.py +2 -4
  87. waldiez/models/agents/agents.py +8 -8
  88. waldiez/models/agents/assistant/assistant.py +6 -3
  89. waldiez/models/agents/assistant/assistant_data.py +2 -2
  90. waldiez/models/agents/captain/captain_agent.py +7 -4
  91. waldiez/models/agents/captain/captain_agent_data.py +5 -7
  92. waldiez/models/agents/doc_agent/doc_agent.py +7 -4
  93. waldiez/models/agents/doc_agent/doc_agent_data.py +9 -10
  94. waldiez/models/agents/doc_agent/rag_query_engine.py +10 -12
  95. waldiez/models/agents/extra_requirements.py +3 -3
  96. waldiez/models/agents/group_manager/group_manager.py +12 -7
  97. waldiez/models/agents/group_manager/group_manager_data.py +13 -12
  98. waldiez/models/agents/group_manager/speakers.py +17 -19
  99. waldiez/models/agents/rag_user_proxy/rag_user_proxy.py +7 -4
  100. waldiez/models/agents/rag_user_proxy/rag_user_proxy_data.py +4 -1
  101. waldiez/models/agents/rag_user_proxy/retrieve_config.py +69 -63
  102. waldiez/models/agents/rag_user_proxy/vector_db_config.py +19 -19
  103. waldiez/models/agents/reasoning/reasoning_agent.py +7 -4
  104. waldiez/models/agents/reasoning/reasoning_agent_data.py +3 -2
  105. waldiez/models/agents/reasoning/reasoning_agent_reason_config.py +8 -8
  106. waldiez/models/agents/user_proxy/user_proxy.py +6 -3
  107. waldiez/models/agents/user_proxy/user_proxy_data.py +1 -1
  108. waldiez/models/chat/chat.py +27 -20
  109. waldiez/models/chat/chat_data.py +22 -19
  110. waldiez/models/chat/chat_message.py +9 -9
  111. waldiez/models/chat/chat_nested.py +9 -9
  112. waldiez/models/chat/chat_summary.py +6 -6
  113. waldiez/models/common/__init__.py +2 -0
  114. waldiez/models/common/ag2_version.py +2 -0
  115. waldiez/models/common/dict_utils.py +8 -6
  116. waldiez/models/common/handoff.py +18 -17
  117. waldiez/models/common/method_utils.py +7 -7
  118. waldiez/models/common/naming.py +49 -0
  119. waldiez/models/flow/flow.py +11 -6
  120. waldiez/models/flow/flow_data.py +23 -17
  121. waldiez/models/flow/info.py +3 -3
  122. waldiez/models/flow/naming.py +2 -1
  123. waldiez/models/model/_aws.py +11 -13
  124. waldiez/models/model/_llm.py +5 -0
  125. waldiez/models/model/_price.py +2 -4
  126. waldiez/models/model/extra_requirements.py +1 -3
  127. waldiez/models/model/model.py +2 -2
  128. waldiez/models/model/model_data.py +21 -21
  129. waldiez/models/tool/extra_requirements.py +2 -4
  130. waldiez/models/tool/predefined/_duckduckgo.py +1 -0
  131. waldiez/models/tool/predefined/_email.py +1 -0
  132. waldiez/models/tool/predefined/_google.py +1 -0
  133. waldiez/models/tool/predefined/_perplexity.py +1 -0
  134. waldiez/models/tool/predefined/_searxng.py +1 -0
  135. waldiez/models/tool/predefined/_tavily.py +1 -0
  136. waldiez/models/tool/predefined/_wikipedia.py +1 -0
  137. waldiez/models/tool/predefined/_youtube.py +1 -0
  138. waldiez/models/tool/tool.py +8 -5
  139. waldiez/models/tool/tool_data.py +2 -2
  140. waldiez/models/waldiez.py +152 -4
  141. waldiez/runner.py +11 -5
  142. waldiez/running/async_utils.py +192 -0
  143. waldiez/running/base_runner.py +117 -264
  144. waldiez/running/dir_utils.py +52 -0
  145. waldiez/running/environment.py +10 -44
  146. waldiez/running/events_mixin.py +252 -0
  147. waldiez/running/exceptions.py +20 -0
  148. waldiez/running/gen_seq_diagram.py +18 -15
  149. waldiez/running/io_utils.py +216 -0
  150. waldiez/running/protocol.py +11 -5
  151. waldiez/running/requirements_mixin.py +65 -0
  152. waldiez/running/results_mixin.py +926 -0
  153. waldiez/running/standard_runner.py +22 -25
  154. waldiez/running/step_by_step/breakpoints_mixin.py +192 -60
  155. waldiez/running/step_by_step/command_handler.py +3 -0
  156. waldiez/running/step_by_step/events_processor.py +194 -14
  157. waldiez/running/step_by_step/step_by_step_models.py +110 -43
  158. waldiez/running/step_by_step/step_by_step_runner.py +107 -57
  159. waldiez/running/subprocess_runner/__base__.py +9 -1
  160. waldiez/running/subprocess_runner/_async_runner.py +5 -3
  161. waldiez/running/subprocess_runner/_sync_runner.py +6 -2
  162. waldiez/running/subprocess_runner/runner.py +39 -23
  163. waldiez/running/timeline_processor.py +1 -1
  164. waldiez/utils/__init__.py +2 -0
  165. waldiez/utils/conflict_checker.py +4 -4
  166. waldiez/utils/python_manager.py +415 -0
  167. waldiez/ws/_file_handler.py +18 -18
  168. waldiez/ws/_mock.py +2 -1
  169. waldiez/ws/cli.py +36 -12
  170. waldiez/ws/client_manager.py +35 -27
  171. waldiez/ws/errors.py +3 -0
  172. waldiez/ws/models.py +43 -52
  173. waldiez/ws/reloader.py +12 -4
  174. waldiez/ws/server.py +85 -55
  175. waldiez/ws/session_manager.py +8 -9
  176. waldiez/ws/session_stats.py +1 -1
  177. waldiez/ws/utils.py +4 -1
  178. {waldiez-0.6.0.dist-info → waldiez-0.6.1.dist-info}/METADATA +82 -93
  179. waldiez-0.6.1.dist-info/RECORD +254 -0
  180. waldiez/running/post_run.py +0 -186
  181. waldiez/running/pre_run.py +0 -281
  182. waldiez/running/run_results.py +0 -14
  183. waldiez/running/utils.py +0 -625
  184. waldiez-0.6.0.dist-info/RECORD +0 -251
  185. {waldiez-0.6.0.dist-info → waldiez-0.6.1.dist-info}/WHEEL +0 -0
  186. {waldiez-0.6.0.dist-info → waldiez-0.6.1.dist-info}/entry_points.txt +0 -0
  187. {waldiez-0.6.0.dist-info → waldiez-0.6.1.dist-info}/licenses/LICENSE +0 -0
  188. {waldiez-0.6.0.dist-info → waldiez-0.6.1.dist-info}/licenses/NOTICE.md +0 -0
@@ -2,50 +2,16 @@
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
3
  # pylint: disable=import-outside-toplevel,reimported,line-too-long
4
4
  # flake8: noqa: E501, F401
5
- # pyright: reportUnusedImport=false
5
+ # pyright: reportUnusedImport=false, reportMissingTypeStubs=false
6
+ # pyright: reportMissingImports=false
7
+
6
8
  """Environment related utilities."""
7
9
 
8
10
  import importlib
9
11
  import os
10
12
  import site
11
13
  import sys
12
- from typing import Generator
13
-
14
-
15
- def in_virtualenv() -> bool:
16
- """Check if we are inside a virtualenv.
17
-
18
- Returns
19
- -------
20
- bool
21
- True if inside a virtualenv, False otherwise.
22
- """
23
- return hasattr(sys, "real_prefix") or (
24
- hasattr(sys, "base_prefix")
25
- and os.path.realpath(sys.base_prefix) != os.path.realpath(sys.prefix)
26
- )
27
-
28
-
29
- def is_root() -> bool: # pragma: no cover # os specific
30
- """Check if the script is running as root/administrator.
31
-
32
- Returns
33
- -------
34
- bool
35
- True if running as root/administrator, False otherwise.
36
- """
37
- # pylint: disable=import-outside-toplevel,line-too-long,no-member
38
- if os.name == "nt":
39
- # noinspection PyBroadException
40
- # pylint: disable=broad-exception-caught
41
- try:
42
- import ctypes
43
-
44
- return ctypes.windll.shell32.IsUserAnAdmin() != 0 # type: ignore[unused-ignore,attr-defined] # noqa: E501
45
- except Exception:
46
- return False
47
- else:
48
- return os.getuid() == 0
14
+ from collections.abc import Generator
49
15
 
50
16
 
51
17
  def refresh_environment() -> None:
@@ -114,7 +80,7 @@ def reload_autogen() -> None: # noqa: C901 # pragma: no cover
114
80
  site.main() # Rebuild the site module cache
115
81
  # Re-import autogen
116
82
  # pylint: disable=unused-import
117
- import autogen # pyright: ignore
83
+ import autogen
118
84
 
119
85
  for mod_name in sorted(autogen_modules, key=len, reverse=False):
120
86
  # Re-import each module
@@ -127,7 +93,7 @@ def reload_autogen() -> None: # noqa: C901 # pragma: no cover
127
93
  # Restore IOStream state if we had it
128
94
  if default_io_stream is not None:
129
95
  try:
130
- from autogen.io import IOStream # pyright: ignore
96
+ from autogen.io import IOStream
131
97
 
132
98
  IOStream.set_default(default_io_stream)
133
99
  except (ImportError, AttributeError, TypeError):
@@ -157,15 +123,15 @@ def reload_autogen() -> None: # noqa: C901 # pragma: no cover
157
123
 
158
124
  def reload_chroma_if_needed() -> None: # pragma: no cover
159
125
  """Reload the chroma package if it is installed."""
160
- cheomadb_modules = [
126
+ chromadb_modules = [
161
127
  name
162
128
  for name in sys.modules
163
129
  if name.startswith("chromadb.") or name == "chromadb"
164
130
  ]
165
- if not cheomadb_modules:
131
+ if not chromadb_modules:
166
132
  return
167
133
 
168
- for mod_name in sorted(cheomadb_modules, key=len, reverse=True):
134
+ for mod_name in sorted(chromadb_modules, key=len, reverse=True):
169
135
  # Remove chromadb modules in reverse dependency order
170
136
  if mod_name in sys.modules:
171
137
  del sys.modules[mod_name]
@@ -181,7 +147,7 @@ def try_handle_the_np_thing() -> None:
181
147
  """Try to handle the numpy deprecation warning."""
182
148
  # we might get:
183
149
  # module 'numpy' has no attribute '_no_nep50_warning'
184
- # (sentnence_transformers?)
150
+ # (sentence_transformers?)
185
151
  # in autogen/agentchat/contrib/captainagent/tool_retriever.py
186
152
  os.environ["NEP50_DEPRECATION_WARNING"] = "0"
187
153
  os.environ["NEP50_DISABLE_WARNING"] = "1"
@@ -0,0 +1,252 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+
4
+ # pyright: reportUnknownMemberType=false, reportAttributeAccessIssue=false
5
+ # pyright: reportUnknownArgumentType=false, reportMissingTypeStubs=false
6
+ # pyright: reportDeprecated=false, reportUninitializedInstanceVariable=false
7
+ # pyright: reportGeneralTypeIssues=false, reportUnknownVariableType=false
8
+ # pyright: reportUnusedParameter=false
9
+ """Workflow events mixin."""
10
+
11
+ import inspect
12
+ from collections.abc import Coroutine
13
+ from typing import TYPE_CHECKING, Any, Callable, Union
14
+
15
+ from .async_utils import is_async_callable, syncify
16
+ from .io_utils import input_async, input_sync
17
+
18
+ if TYPE_CHECKING:
19
+ from autogen.agentchat import ConversableAgent # type: ignore
20
+ from autogen.events import BaseEvent # type: ignore
21
+ from autogen.messages import BaseMessage # type: ignore
22
+
23
+
24
+ class EventsMixin:
25
+ """Event processing mixin."""
26
+
27
+ _input: Callable[..., str] | Callable[..., Coroutine[Any, Any, str]]
28
+ _print: Callable[..., None]
29
+ _send: Union[Callable[["BaseMessage"], None], Callable[["BaseEvent"], None]]
30
+ _is_async: bool
31
+
32
+ @staticmethod
33
+ def set_input_function(
34
+ input_fn: Callable[..., str] | Callable[..., Coroutine[Any, Any, str]],
35
+ ) -> None:
36
+ """Set the input function.
37
+
38
+ Parameters
39
+ ----------
40
+ input_fn: Callable[..., str] | Callable[..., Coroutine[Any, Any, str]],
41
+ The function that handles input.
42
+ """
43
+ EventsMixin._input = input_fn
44
+
45
+ @staticmethod
46
+ def set_print_function(print_fn: Callable[..., None]) -> None:
47
+ """Set the print function.
48
+
49
+ Parameters
50
+ ----------
51
+ print_fn: Callable[..., None]
52
+ The function that handles printing messages.
53
+ """
54
+ EventsMixin._print = print_fn
55
+
56
+ @staticmethod
57
+ def set_send_function(
58
+ send_fn: Union[
59
+ Callable[["BaseMessage"], None], Callable[["BaseEvent"], None]
60
+ ],
61
+ ) -> None:
62
+ """Set the send function.
63
+
64
+ Parameters
65
+ ----------
66
+ send_fn: Callable[[Union["BaseEvent", "BaseMessage"]], None],
67
+ The function to use for sending events and messages.
68
+ """
69
+ EventsMixin._send = send_fn
70
+
71
+ @staticmethod
72
+ def set_async(value: bool) -> None:
73
+ """Set the _is_async flag.
74
+
75
+ Parameters
76
+ ----------
77
+ value : bool
78
+ The value to set.
79
+ """
80
+ EventsMixin._is_async = value
81
+
82
+ @staticmethod
83
+ def do_print(*args: Any, **kwargs: Any) -> None:
84
+ """Print a message to the output stream.
85
+
86
+ Parameters
87
+ ----------
88
+ *args : Any
89
+ Positional arguments to print.
90
+ **kwargs : Any
91
+ Keyword arguments to print.
92
+ """
93
+ EventsMixin._print(*args, **kwargs)
94
+
95
+ @staticmethod
96
+ def get_input_function() -> (
97
+ Callable[..., str] | Callable[..., Coroutine[Any, Any, str]]
98
+ ):
99
+ """Get the input function for user interaction.
100
+
101
+ Returns
102
+ -------
103
+ Callable[[str, bool], str]
104
+ A function that takes a prompt and a password flag,
105
+ returning user input.
106
+ """
107
+ if hasattr(EventsMixin, "_input") and callable(EventsMixin._input):
108
+ return EventsMixin._input
109
+ if EventsMixin._is_async:
110
+ return input_async
111
+ return input_sync
112
+
113
+ @staticmethod
114
+ async def a_get_user_input(
115
+ prompt: str, *, password: bool = False, **kwargs: Any
116
+ ) -> str:
117
+ """Get user input with an optional password prompt.
118
+
119
+ Parameters
120
+ ----------
121
+ prompt : str
122
+ The prompt to display to the user.
123
+ password : bool, optional
124
+ If True, the input will be hidden (default is False).
125
+ **kwargs : Any
126
+ Additional keyword arguments to pass to the input function.
127
+
128
+ Returns
129
+ -------
130
+ str
131
+ The user input.
132
+ """
133
+ input_function = EventsMixin.get_input_function()
134
+ if is_async_callable(input_function):
135
+ try:
136
+ result = await input_function( # type: ignore
137
+ prompt,
138
+ password=password,
139
+ **kwargs,
140
+ )
141
+ except TypeError:
142
+ result = await input_function(prompt) # type: ignore
143
+ else:
144
+ try:
145
+ result = input_function(prompt, password=password, **kwargs)
146
+ except TypeError:
147
+ result = input_function(prompt)
148
+ return result # pyright: ignore[reportReturnType]
149
+
150
+ @staticmethod
151
+ def get_user_input(
152
+ prompt: str,
153
+ *,
154
+ password: bool = False,
155
+ **kwargs: Any,
156
+ ) -> str:
157
+ """Get user input with an optional password prompt.
158
+
159
+ Parameters
160
+ ----------
161
+ prompt : str
162
+ The prompt to display to the user.
163
+ password : bool, optional
164
+ If True, the input will be hidden (default is False).
165
+ **kwargs : Any
166
+ Additional keyword arguments to pass to the input function.
167
+
168
+ Returns
169
+ -------
170
+ str
171
+ The user input.
172
+ """
173
+ input_function = EventsMixin.get_input_function()
174
+ if inspect.iscoroutinefunction(input_function):
175
+ try:
176
+ return syncify(input_function)(
177
+ prompt, password=password, **kwargs
178
+ )
179
+ except TypeError:
180
+ return syncify(input_function)(prompt)
181
+ try:
182
+ return str(input_function(prompt, password=password, **kwargs))
183
+ except TypeError:
184
+ return str(input_function(prompt))
185
+
186
+ @staticmethod
187
+ async def a_process_event(
188
+ event: Union["BaseEvent", "BaseMessage"],
189
+ agents: list["ConversableAgent"], # pylint: disable=unused-argument
190
+ skip_send: bool = False,
191
+ ) -> None:
192
+ """Process an event or message asynchronously.
193
+
194
+ Parameters
195
+ ----------
196
+ event : Union[BaseEvent, BaseMessage]
197
+ The event or message to process.
198
+ agents : list["ConversableAgent"]
199
+ The known agents in the flow.
200
+ skip_send : bool
201
+ Skip sending the event.
202
+ """
203
+ if hasattr(event, "type"): # pragma: no branch
204
+ if getattr(event, "type", "") == "input_request":
205
+ prompt = getattr(
206
+ event, "prompt", getattr(event.content, "prompt", "> ")
207
+ )
208
+ password = getattr(
209
+ event,
210
+ "password",
211
+ getattr(event.content, "password", False),
212
+ )
213
+ user_input = await EventsMixin.a_get_user_input(
214
+ prompt, password=password
215
+ )
216
+ await event.content.respond(user_input)
217
+ elif not skip_send:
218
+ EventsMixin._send(event) # pyright: ignore[reportArgumentType]
219
+
220
+ @staticmethod
221
+ def process_event(
222
+ event: Union["BaseEvent", "BaseMessage"],
223
+ agents: list["ConversableAgent"], # pylint: disable=unused-argument
224
+ skip_send: bool = False,
225
+ ) -> None:
226
+ """Process an event or message synchronously.
227
+
228
+ Parameters
229
+ ----------
230
+ event : Union[BaseEvent, BaseMessage]
231
+ The event or message to process.
232
+ agents : list["ConversableAgent"]
233
+ The known agents in the flow.
234
+ skip_send : bool
235
+ Skip sending the event.
236
+ """
237
+ if hasattr(event, "type"): # pragma: no branch
238
+ if event.type == "input_request":
239
+ prompt = getattr(
240
+ event, "prompt", getattr(event.content, "prompt", "> ")
241
+ )
242
+ password = getattr(
243
+ event,
244
+ "password",
245
+ getattr(event.content, "password", False),
246
+ )
247
+ user_input = EventsMixin.get_user_input(
248
+ prompt, password=password
249
+ )
250
+ event.content.respond(user_input)
251
+ elif not skip_send:
252
+ EventsMixin._send(event) # pyright: ignore[reportArgumentType]
@@ -7,3 +7,23 @@ class StopRunningException(Exception):
7
7
  """Exception to stop the running process."""
8
8
 
9
9
  reason: str = "Execution stopped by user"
10
+
11
+ def __str__(self) -> str:
12
+ """Get the string representation of the exception.
13
+
14
+ Returns
15
+ -------
16
+ str
17
+ The string representation of the exception.
18
+ """
19
+ return self.reason
20
+
21
+ def __repr__(self) -> str:
22
+ """Get the string representation of the exception.
23
+
24
+ Returns
25
+ -------
26
+ str
27
+ The string representation of the exception.
28
+ """
29
+ return self.reason
@@ -1,11 +1,14 @@
1
1
  # SPDX-License-Identifier: Apache-2.0.
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+
4
+ # pyright: reportUnknownArgumentType=false,reportUnknownVariableType=false
5
+ # pyright: reportUnknownMemberType=false
3
6
  """Generate a Mermaid sequence diagram from a file containing event data."""
4
7
 
5
8
  import json
6
9
  import re
7
10
  from pathlib import Path
8
- from typing import Any, Set, Union
11
+ from typing import Any
9
12
 
10
13
  import pandas as pd
11
14
 
@@ -52,7 +55,7 @@ def get_json_state(json_state: Any) -> dict[str, Any]:
52
55
  The JSON state of the event.
53
56
  """
54
57
  if isinstance(json_state, dict):
55
- return json_state # pyright: ignore
58
+ return json_state
56
59
  if isinstance(json_state, str):
57
60
  try:
58
61
  return json.loads(json_state)
@@ -76,14 +79,14 @@ def process_events(df_events: pd.DataFrame) -> str:
76
79
  The Mermaid sequence diagram text.
77
80
  """
78
81
  # Set to store participants (senders and recipients)
79
- participants: Set[str] = set()
82
+ participants: set[str] = set()
80
83
  recipient: str
81
84
 
82
85
  # Initialize the sequence diagram text
83
86
  seq_text = SEQ_TXT
84
87
 
85
88
  # Loop through each event in the DataFrame
86
- for i in range(len(df_events["json_state"])): # pyright: ignore
89
+ for i in range(len(df_events["json_state"])):
87
90
  # Parse the JSON state of the event
88
91
  df_j = get_json_state(df_events["json_state"][i])
89
92
  # Skip events that are not relevant (e.g., replies or missing messages)
@@ -92,24 +95,24 @@ def process_events(df_events: pd.DataFrame) -> str:
92
95
  ):
93
96
  sender = df_j["sender"]
94
97
  # noinspection PyTypeChecker
95
- recipient = df_events["source_name"][i] # pyright: ignore
98
+ recipient = df_events["source_name"][i]
96
99
 
97
100
  # Extract message content if available
98
101
  if (
99
102
  isinstance(df_j["message"], dict)
100
103
  and "content" in df_j["message"]
101
104
  ):
102
- content = str(df_j["message"]["content"]) # pyright: ignore
105
+ content = str(df_j["message"]["content"])
103
106
  message = "Content: " + content
104
107
  else:
105
- message = str(df_j["message"]) # pyright: ignore
108
+ message = str(df_j["message"])
106
109
 
107
110
  # Escape the message for Mermaid compatibility and
108
111
  # truncate long messages
109
112
  message = escape_mermaid_text(message)
110
113
 
111
114
  # Add sender and recipient to participants set
112
- participants.add(recipient) # pyright: ignore
115
+ participants.add(recipient)
113
116
  participants.add(sender)
114
117
 
115
118
  # Split into the main message and the context
@@ -135,14 +138,14 @@ def process_events(df_events: pd.DataFrame) -> str:
135
138
  return mermaid_text
136
139
 
137
140
 
138
- def save_diagram(mermaid_text: str, output_path: Union[str, Path]) -> None:
141
+ def save_diagram(mermaid_text: str, output_path: str | Path) -> None:
139
142
  """Save the Mermaid diagram to a .mmd file.
140
143
 
141
144
  Parameters
142
145
  ----------
143
146
  mermaid_text : str
144
147
  The Mermaid sequence diagram text.
145
- output_path : Union[str, Path]
148
+ output_path : str | Path
146
149
  The path to save the Mermaid diagram.
147
150
  """
148
151
  with open(output_path, "w", encoding="utf-8", newline="\n") as file:
@@ -150,15 +153,15 @@ def save_diagram(mermaid_text: str, output_path: Union[str, Path]) -> None:
150
153
 
151
154
 
152
155
  def generate_sequence_diagram(
153
- file_path: Union[str, Path], output_path: Union[str, Path]
156
+ file_path: str | Path, output_path: str | Path
154
157
  ) -> None:
155
158
  """Generate the Mermaid diagram.
156
159
 
157
160
  Parameters
158
161
  ----------
159
- file_path : Union[str, Path]
162
+ file_path : str | Path
160
163
  The path to the JSON or CSV file containing the events' data.
161
- output_path : Union[str, Path]
164
+ output_path : str | Path
162
165
  The path to save the Mermaid diagram.
163
166
 
164
167
  Raises
@@ -178,9 +181,9 @@ def generate_sequence_diagram(
178
181
  is_csv = file_path.suffix == ".csv"
179
182
  try:
180
183
  if is_csv:
181
- df_events = pd.read_csv(file_path) # pyright: ignore
184
+ df_events = pd.read_csv(file_path)
182
185
  else:
183
- df_events = pd.read_json(file_path) # pyright: ignore
186
+ df_events = pd.read_json(file_path)
184
187
  except pd.errors.EmptyDataError: # pragma: no cover
185
188
  return
186
189