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.
- waldiez/__init__.py +1 -1
- waldiez/_version.py +1 -1
- waldiez/cli.py +18 -7
- waldiez/cli_extras/jupyter.py +3 -0
- waldiez/cli_extras/runner.py +3 -1
- waldiez/cli_extras/studio.py +3 -1
- waldiez/exporter.py +9 -3
- waldiez/exporting/agent/exporter.py +9 -10
- waldiez/exporting/agent/extras/captain_agent_extras.py +6 -6
- waldiez/exporting/agent/extras/doc_agent_extras.py +6 -6
- waldiez/exporting/agent/extras/group_manager_agent_extas.py +34 -23
- waldiez/exporting/agent/extras/group_member_extras.py +6 -5
- waldiez/exporting/agent/extras/handoffs/after_work.py +1 -1
- waldiez/exporting/agent/extras/handoffs/available.py +1 -1
- waldiez/exporting/agent/extras/handoffs/condition.py +3 -2
- waldiez/exporting/agent/extras/handoffs/handoff.py +1 -1
- waldiez/exporting/agent/extras/handoffs/target.py +6 -4
- waldiez/exporting/agent/extras/rag/chroma_extras.py +27 -19
- waldiez/exporting/agent/extras/rag/mongo_extras.py +8 -8
- waldiez/exporting/agent/extras/rag/pgvector_extras.py +5 -5
- waldiez/exporting/agent/extras/rag/qdrant_extras.py +5 -4
- waldiez/exporting/agent/extras/rag/vector_db_extras.py +1 -1
- waldiez/exporting/agent/extras/rag_user_proxy_agent_extras.py +5 -7
- waldiez/exporting/agent/extras/reasoning_agent_extras.py +3 -5
- waldiez/exporting/chats/exporter.py +4 -4
- waldiez/exporting/chats/processor.py +1 -2
- waldiez/exporting/chats/utils/common.py +89 -48
- waldiez/exporting/chats/utils/group.py +9 -9
- waldiez/exporting/chats/utils/nested.py +7 -7
- waldiez/exporting/chats/utils/sequential.py +1 -1
- waldiez/exporting/chats/utils/single.py +2 -2
- waldiez/exporting/core/content.py +7 -7
- waldiez/exporting/core/context.py +5 -3
- waldiez/exporting/core/exporter.py +5 -3
- waldiez/exporting/core/exporters.py +2 -2
- waldiez/exporting/core/extras/agent_extras/captain_extras.py +2 -2
- waldiez/exporting/core/extras/agent_extras/group_manager_extras.py +2 -2
- waldiez/exporting/core/extras/agent_extras/rag_user_extras.py +2 -2
- waldiez/exporting/core/extras/agent_extras/standard_extras.py +3 -8
- waldiez/exporting/core/extras/base.py +7 -5
- waldiez/exporting/core/extras/flow_extras.py +4 -5
- waldiez/exporting/core/extras/model_extras.py +2 -2
- waldiez/exporting/core/extras/path_resolver.py +1 -2
- waldiez/exporting/core/extras/serializer.py +2 -2
- waldiez/exporting/core/protocols.py +6 -5
- waldiez/exporting/core/result.py +25 -28
- waldiez/exporting/core/types.py +10 -10
- waldiez/exporting/core/utils/llm_config.py +2 -2
- waldiez/exporting/core/validation.py +10 -11
- waldiez/exporting/flow/execution_generator.py +98 -10
- waldiez/exporting/flow/exporter.py +2 -2
- waldiez/exporting/flow/factory.py +2 -2
- waldiez/exporting/flow/file_generator.py +4 -2
- waldiez/exporting/flow/merger.py +5 -3
- waldiez/exporting/flow/orchestrator.py +72 -2
- waldiez/exporting/flow/utils/common.py +5 -5
- waldiez/exporting/flow/utils/importing.py +6 -7
- waldiez/exporting/flow/utils/linting.py +25 -9
- waldiez/exporting/flow/utils/logging.py +2 -2
- waldiez/exporting/models/exporter.py +8 -8
- waldiez/exporting/models/processor.py +5 -5
- waldiez/exporting/tools/exporter.py +2 -2
- waldiez/exporting/tools/processor.py +7 -4
- waldiez/io/__init__.py +8 -4
- waldiez/io/_ws.py +10 -6
- waldiez/io/models/constants.py +10 -10
- waldiez/io/models/content/audio.py +1 -0
- waldiez/io/models/content/base.py +20 -18
- waldiez/io/models/content/file.py +1 -0
- waldiez/io/models/content/image.py +1 -0
- waldiez/io/models/content/text.py +1 -0
- waldiez/io/models/content/video.py +1 -0
- waldiez/io/models/user_input.py +10 -5
- waldiez/io/models/user_response.py +17 -16
- waldiez/io/mqtt.py +18 -31
- waldiez/io/redis.py +18 -22
- waldiez/io/structured.py +52 -53
- waldiez/io/utils.py +3 -0
- waldiez/io/ws.py +5 -1
- waldiez/logger.py +16 -3
- waldiez/models/agents/__init__.py +3 -0
- waldiez/models/agents/agent/agent.py +23 -16
- waldiez/models/agents/agent/agent_data.py +25 -22
- waldiez/models/agents/agent/code_execution.py +9 -11
- waldiez/models/agents/agent/termination_message.py +10 -12
- waldiez/models/agents/agent/update_system_message.py +2 -4
- waldiez/models/agents/agents.py +8 -8
- waldiez/models/agents/assistant/assistant.py +6 -3
- waldiez/models/agents/assistant/assistant_data.py +2 -2
- waldiez/models/agents/captain/captain_agent.py +7 -4
- waldiez/models/agents/captain/captain_agent_data.py +5 -7
- waldiez/models/agents/doc_agent/doc_agent.py +7 -4
- waldiez/models/agents/doc_agent/doc_agent_data.py +9 -10
- waldiez/models/agents/doc_agent/rag_query_engine.py +10 -12
- waldiez/models/agents/extra_requirements.py +3 -3
- waldiez/models/agents/group_manager/group_manager.py +12 -7
- waldiez/models/agents/group_manager/group_manager_data.py +13 -12
- waldiez/models/agents/group_manager/speakers.py +17 -19
- waldiez/models/agents/rag_user_proxy/rag_user_proxy.py +7 -4
- waldiez/models/agents/rag_user_proxy/rag_user_proxy_data.py +4 -1
- waldiez/models/agents/rag_user_proxy/retrieve_config.py +69 -63
- waldiez/models/agents/rag_user_proxy/vector_db_config.py +19 -19
- waldiez/models/agents/reasoning/reasoning_agent.py +7 -4
- waldiez/models/agents/reasoning/reasoning_agent_data.py +3 -2
- waldiez/models/agents/reasoning/reasoning_agent_reason_config.py +8 -8
- waldiez/models/agents/user_proxy/user_proxy.py +6 -3
- waldiez/models/agents/user_proxy/user_proxy_data.py +1 -1
- waldiez/models/chat/chat.py +27 -20
- waldiez/models/chat/chat_data.py +22 -19
- waldiez/models/chat/chat_message.py +9 -9
- waldiez/models/chat/chat_nested.py +9 -9
- waldiez/models/chat/chat_summary.py +6 -6
- waldiez/models/common/__init__.py +2 -0
- waldiez/models/common/ag2_version.py +2 -0
- waldiez/models/common/dict_utils.py +8 -6
- waldiez/models/common/handoff.py +18 -17
- waldiez/models/common/method_utils.py +7 -7
- waldiez/models/common/naming.py +49 -0
- waldiez/models/flow/flow.py +11 -6
- waldiez/models/flow/flow_data.py +23 -17
- waldiez/models/flow/info.py +3 -3
- waldiez/models/flow/naming.py +2 -1
- waldiez/models/model/_aws.py +11 -13
- waldiez/models/model/_llm.py +5 -0
- waldiez/models/model/_price.py +2 -4
- waldiez/models/model/extra_requirements.py +1 -3
- waldiez/models/model/model.py +2 -2
- waldiez/models/model/model_data.py +21 -21
- waldiez/models/tool/extra_requirements.py +2 -4
- waldiez/models/tool/predefined/_duckduckgo.py +1 -0
- waldiez/models/tool/predefined/_email.py +1 -0
- waldiez/models/tool/predefined/_google.py +1 -0
- waldiez/models/tool/predefined/_perplexity.py +1 -0
- waldiez/models/tool/predefined/_searxng.py +1 -0
- waldiez/models/tool/predefined/_tavily.py +1 -0
- waldiez/models/tool/predefined/_wikipedia.py +1 -0
- waldiez/models/tool/predefined/_youtube.py +1 -0
- waldiez/models/tool/tool.py +8 -5
- waldiez/models/tool/tool_data.py +2 -2
- waldiez/models/waldiez.py +152 -4
- waldiez/runner.py +11 -5
- waldiez/running/async_utils.py +192 -0
- waldiez/running/base_runner.py +117 -264
- waldiez/running/dir_utils.py +52 -0
- waldiez/running/environment.py +10 -44
- waldiez/running/events_mixin.py +252 -0
- waldiez/running/exceptions.py +20 -0
- waldiez/running/gen_seq_diagram.py +18 -15
- waldiez/running/io_utils.py +216 -0
- waldiez/running/protocol.py +11 -5
- waldiez/running/requirements_mixin.py +65 -0
- waldiez/running/results_mixin.py +926 -0
- waldiez/running/standard_runner.py +22 -25
- waldiez/running/step_by_step/breakpoints_mixin.py +192 -60
- waldiez/running/step_by_step/command_handler.py +3 -0
- waldiez/running/step_by_step/events_processor.py +194 -14
- waldiez/running/step_by_step/step_by_step_models.py +110 -43
- waldiez/running/step_by_step/step_by_step_runner.py +107 -57
- waldiez/running/subprocess_runner/__base__.py +9 -1
- waldiez/running/subprocess_runner/_async_runner.py +5 -3
- waldiez/running/subprocess_runner/_sync_runner.py +6 -2
- waldiez/running/subprocess_runner/runner.py +39 -23
- waldiez/running/timeline_processor.py +1 -1
- waldiez/utils/__init__.py +2 -0
- waldiez/utils/conflict_checker.py +4 -4
- waldiez/utils/python_manager.py +415 -0
- waldiez/ws/_file_handler.py +18 -18
- waldiez/ws/_mock.py +2 -1
- waldiez/ws/cli.py +36 -12
- waldiez/ws/client_manager.py +35 -27
- waldiez/ws/errors.py +3 -0
- waldiez/ws/models.py +43 -52
- waldiez/ws/reloader.py +12 -4
- waldiez/ws/server.py +85 -55
- waldiez/ws/session_manager.py +8 -9
- waldiez/ws/session_stats.py +1 -1
- waldiez/ws/utils.py +4 -1
- {waldiez-0.6.0.dist-info → waldiez-0.6.1.dist-info}/METADATA +82 -93
- waldiez-0.6.1.dist-info/RECORD +254 -0
- waldiez/running/post_run.py +0 -186
- waldiez/running/pre_run.py +0 -281
- waldiez/running/run_results.py +0 -14
- waldiez/running/utils.py +0 -625
- waldiez-0.6.0.dist-info/RECORD +0 -251
- {waldiez-0.6.0.dist-info → waldiez-0.6.1.dist-info}/WHEEL +0 -0
- {waldiez-0.6.0.dist-info → waldiez-0.6.1.dist-info}/entry_points.txt +0 -0
- {waldiez-0.6.0.dist-info → waldiez-0.6.1.dist-info}/licenses/LICENSE +0 -0
- {waldiez-0.6.0.dist-info → waldiez-0.6.1.dist-info}/licenses/NOTICE.md +0 -0
waldiez/running/environment.py
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
131
|
+
if not chromadb_modules:
|
|
166
132
|
return
|
|
167
133
|
|
|
168
|
-
for mod_name in sorted(
|
|
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
|
-
# (
|
|
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]
|
waldiez/running/exceptions.py
CHANGED
|
@@ -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
|
|
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
|
|
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:
|
|
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"])):
|
|
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]
|
|
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"])
|
|
105
|
+
content = str(df_j["message"]["content"])
|
|
103
106
|
message = "Content: " + content
|
|
104
107
|
else:
|
|
105
|
-
message = str(df_j["message"])
|
|
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)
|
|
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:
|
|
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 :
|
|
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:
|
|
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 :
|
|
162
|
+
file_path : str | Path
|
|
160
163
|
The path to the JSON or CSV file containing the events' data.
|
|
161
|
-
output_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)
|
|
184
|
+
df_events = pd.read_csv(file_path)
|
|
182
185
|
else:
|
|
183
|
-
df_events = pd.read_json(file_path)
|
|
186
|
+
df_events = pd.read_json(file_path)
|
|
184
187
|
except pd.errors.EmptyDataError: # pragma: no cover
|
|
185
188
|
return
|
|
186
189
|
|