waldiez 0.4.9__py3-none-any.whl → 0.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of waldiez might be problematic. Click here for more details.
- waldiez/__init__.py +1 -2
- waldiez/_version.py +1 -1
- waldiez/cli.py +65 -58
- waldiez/exporter.py +64 -9
- waldiez/exporting/agent/extras/group_manager_agent_extas.py +1 -1
- waldiez/exporting/core/context.py +12 -0
- waldiez/exporting/core/extras/flow_extras.py +2 -14
- waldiez/exporting/core/types.py +21 -0
- waldiez/exporting/flow/exporter.py +4 -0
- waldiez/exporting/flow/factory.py +16 -0
- waldiez/exporting/flow/orchestrator.py +12 -0
- waldiez/exporting/flow/utils/__init__.py +2 -0
- waldiez/exporting/flow/utils/common.py +96 -2
- waldiez/exporting/flow/utils/logging.py +5 -6
- waldiez/io/mqtt.py +7 -3
- waldiez/io/structured.py +5 -1
- waldiez/models/common/method_utils.py +1 -1
- waldiez/models/tool/tool.py +2 -1
- waldiez/runner.py +402 -321
- waldiez/running/__init__.py +6 -34
- waldiez/running/base_runner.py +907 -0
- waldiez/running/environment.py +74 -0
- waldiez/running/import_runner.py +424 -0
- waldiez/running/patch_io_stream.py +208 -0
- waldiez/running/post_run.py +26 -24
- waldiez/running/pre_run.py +2 -46
- waldiez/running/protocol.py +281 -0
- waldiez/running/run_results.py +22 -0
- waldiez/running/subprocess_runner.py +100 -0
- waldiez/utils/__init__.py +0 -4
- waldiez/utils/version.py +4 -2
- {waldiez-0.4.9.dist-info → waldiez-0.5.0.dist-info}/METADATA +39 -113
- {waldiez-0.4.9.dist-info → waldiez-0.5.0.dist-info}/RECORD +42 -37
- waldiez/utils/flaml_warnings.py +0 -17
- /waldiez/{utils/cli_extras → cli_extras}/__init__.py +0 -0
- /waldiez/{utils/cli_extras → cli_extras}/jupyter.py +0 -0
- /waldiez/{utils/cli_extras → cli_extras}/runner.py +0 -0
- /waldiez/{utils/cli_extras → cli_extras}/studio.py +0 -0
- /waldiez/running/{util.py → utils.py} +0 -0
- {waldiez-0.4.9.dist-info → waldiez-0.5.0.dist-info}/WHEEL +0 -0
- {waldiez-0.4.9.dist-info → waldiez-0.5.0.dist-info}/entry_points.txt +0 -0
- {waldiez-0.4.9.dist-info → waldiez-0.5.0.dist-info}/licenses/LICENSE +0 -0
- {waldiez-0.4.9.dist-info → waldiez-0.5.0.dist-info}/licenses/NOTICE.md +0 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
|
|
4
|
+
# pylint: disable=import-outside-toplevel, broad-exception-caught
|
|
5
|
+
# pylint: disable=too-many-try-statements, too-complex
|
|
6
|
+
# noqa: C901
|
|
7
|
+
"""Patch ag2's IOStream if a flow is async.
|
|
8
|
+
|
|
9
|
+
# let's keep an eye here:
|
|
10
|
+
# https://github.com/ag2ai/ag2/blob/main/autogen/agentchat/conversable_agent.py#L2973
|
|
11
|
+
# reply = await iostream.input(prompt) ???? (await???)
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import inspect
|
|
15
|
+
import sys
|
|
16
|
+
from typing import Any, Callable
|
|
17
|
+
|
|
18
|
+
from asyncer import syncify
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def patch_io_stream(is_async: bool) -> None:
|
|
22
|
+
"""Patch the IOStream to handle async flows.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
is_async : bool
|
|
27
|
+
Whether the flow is async or not.
|
|
28
|
+
"""
|
|
29
|
+
if is_async:
|
|
30
|
+
patch_async_io_stream()
|
|
31
|
+
else:
|
|
32
|
+
patch_sync_io_stream()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def patch_sync_io_stream() -> None:
|
|
36
|
+
"""Patch the IOStream to handle async flows."""
|
|
37
|
+
from autogen.io import IOStream # type: ignore
|
|
38
|
+
|
|
39
|
+
iostream = IOStream.get_default()
|
|
40
|
+
original_input = iostream.input
|
|
41
|
+
|
|
42
|
+
def _safe_input(prompt: str = "", *, password: bool = False) -> str:
|
|
43
|
+
"""Async input method."""
|
|
44
|
+
try:
|
|
45
|
+
input_or_coro = original_input(prompt, password=password)
|
|
46
|
+
if inspect.iscoroutine(input_or_coro):
|
|
47
|
+
|
|
48
|
+
async def _async_input() -> str:
|
|
49
|
+
reply = await input_or_coro
|
|
50
|
+
return reply
|
|
51
|
+
|
|
52
|
+
return syncify(_async_input)()
|
|
53
|
+
return input_or_coro
|
|
54
|
+
|
|
55
|
+
except EOFError:
|
|
56
|
+
# Handle EOFError gracefully
|
|
57
|
+
return ""
|
|
58
|
+
|
|
59
|
+
iostream.input = _safe_input # pyright: ignore
|
|
60
|
+
iostream.print = get_printer() # pyright: ignore
|
|
61
|
+
IOStream.set_default(iostream)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def patch_async_io_stream() -> None:
|
|
65
|
+
"""Patch the IOStream to handle async flows."""
|
|
66
|
+
from autogen.io import IOStream # pyright: ignore
|
|
67
|
+
|
|
68
|
+
iostream = IOStream.get_default()
|
|
69
|
+
original_input = iostream.input
|
|
70
|
+
|
|
71
|
+
async def _async_input(prompt: str = "", *, password: bool = False) -> str:
|
|
72
|
+
"""Async input method."""
|
|
73
|
+
try:
|
|
74
|
+
input_or_coro = original_input(prompt, password=password)
|
|
75
|
+
if inspect.iscoroutine(input_or_coro):
|
|
76
|
+
reply = await input_or_coro
|
|
77
|
+
else:
|
|
78
|
+
reply = input_or_coro
|
|
79
|
+
return reply
|
|
80
|
+
except EOFError:
|
|
81
|
+
# Handle EOFError gracefully
|
|
82
|
+
return ""
|
|
83
|
+
|
|
84
|
+
iostream.input = _async_input # pyright: ignore
|
|
85
|
+
iostream.print = get_printer() # pyright: ignore
|
|
86
|
+
IOStream.set_default(iostream)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def get_printer() -> Callable[..., None]: # noqa: C901
|
|
90
|
+
"""Get the printer function.
|
|
91
|
+
|
|
92
|
+
Returns
|
|
93
|
+
-------
|
|
94
|
+
Callable[..., None]
|
|
95
|
+
The printer function that handles Unicode encoding errors gracefully.
|
|
96
|
+
"""
|
|
97
|
+
try:
|
|
98
|
+
from autogen.io import IOStream # pyright: ignore
|
|
99
|
+
|
|
100
|
+
printer = IOStream.get_default().print
|
|
101
|
+
except ImportError:
|
|
102
|
+
# Fallback to standard print if autogen is not available
|
|
103
|
+
printer = print
|
|
104
|
+
|
|
105
|
+
def safe_printer(*args: Any, **kwargs: Any) -> None: # noqa: C901
|
|
106
|
+
"""Safe printer that handles Unicode encoding errors.
|
|
107
|
+
|
|
108
|
+
Parameters
|
|
109
|
+
----------
|
|
110
|
+
*args : Any
|
|
111
|
+
Arguments to pass to the printer
|
|
112
|
+
**kwargs : Any
|
|
113
|
+
Keyword arguments to pass to the printer
|
|
114
|
+
"""
|
|
115
|
+
try:
|
|
116
|
+
printer(*args, **kwargs)
|
|
117
|
+
except UnicodeEncodeError:
|
|
118
|
+
# First fallback: try to get a safe string representation
|
|
119
|
+
try:
|
|
120
|
+
msg, flush = get_what_to_print(*args, **kwargs)
|
|
121
|
+
# Convert problematic characters to safe representations
|
|
122
|
+
safe_msg = msg.encode("utf-8", errors="replace").decode("utf-8")
|
|
123
|
+
printer(safe_msg, end="", flush=flush)
|
|
124
|
+
except (UnicodeEncodeError, UnicodeDecodeError):
|
|
125
|
+
# Second fallback: use built-in print with safe encoding
|
|
126
|
+
try:
|
|
127
|
+
# Convert args to safe string representations
|
|
128
|
+
safe_args: list[str] = []
|
|
129
|
+
for arg in args:
|
|
130
|
+
try:
|
|
131
|
+
safe_args.append(
|
|
132
|
+
str(arg)
|
|
133
|
+
.encode("utf-8", errors="replace")
|
|
134
|
+
.decode("utf-8")
|
|
135
|
+
)
|
|
136
|
+
except (UnicodeEncodeError, UnicodeDecodeError):
|
|
137
|
+
safe_args.append(repr(arg))
|
|
138
|
+
|
|
139
|
+
# Use built-in print instead of the custom printer
|
|
140
|
+
print(*safe_args, **kwargs)
|
|
141
|
+
|
|
142
|
+
except Exception:
|
|
143
|
+
# Final fallback: write directly to stderr buffer
|
|
144
|
+
try:
|
|
145
|
+
error_msg = (
|
|
146
|
+
"Could not print the message "
|
|
147
|
+
"due to encoding issues.\n"
|
|
148
|
+
)
|
|
149
|
+
if hasattr(sys.stderr, "buffer"):
|
|
150
|
+
sys.stderr.buffer.write(
|
|
151
|
+
error_msg.encode("utf-8", errors="replace")
|
|
152
|
+
)
|
|
153
|
+
sys.stderr.buffer.flush()
|
|
154
|
+
else:
|
|
155
|
+
sys.stderr.write(error_msg)
|
|
156
|
+
sys.stderr.flush()
|
|
157
|
+
except Exception:
|
|
158
|
+
# If even this fails, we're in a very bad state
|
|
159
|
+
pass
|
|
160
|
+
except Exception as e:
|
|
161
|
+
# Handle any other unexpected errors
|
|
162
|
+
try:
|
|
163
|
+
error_msg = f"Unexpected error in printer: {str(e)}\n"
|
|
164
|
+
if hasattr(sys.stderr, "buffer"):
|
|
165
|
+
sys.stderr.buffer.write(
|
|
166
|
+
error_msg.encode("utf-8", errors="replace")
|
|
167
|
+
)
|
|
168
|
+
sys.stderr.buffer.flush()
|
|
169
|
+
else:
|
|
170
|
+
sys.stderr.write(error_msg)
|
|
171
|
+
sys.stderr.flush()
|
|
172
|
+
except Exception:
|
|
173
|
+
pass
|
|
174
|
+
|
|
175
|
+
return safe_printer
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def get_what_to_print(*args: Any, **kwargs: Any) -> tuple[str, bool]:
|
|
179
|
+
"""Extract message and flush flag from print arguments.
|
|
180
|
+
|
|
181
|
+
Parameters
|
|
182
|
+
----------
|
|
183
|
+
*args : Any
|
|
184
|
+
Arguments to print
|
|
185
|
+
**kwargs : Any
|
|
186
|
+
Keyword arguments for print function
|
|
187
|
+
|
|
188
|
+
Returns
|
|
189
|
+
-------
|
|
190
|
+
tuple[str, bool]
|
|
191
|
+
Message to print and flush flag
|
|
192
|
+
"""
|
|
193
|
+
# Convert all args to strings and join with spaces (like print does)
|
|
194
|
+
msg = " ".join(str(arg) for arg in args)
|
|
195
|
+
|
|
196
|
+
# Handle sep parameter
|
|
197
|
+
sep = kwargs.get("sep", " ")
|
|
198
|
+
if len(args) > 1:
|
|
199
|
+
msg = sep.join(str(arg) for arg in args)
|
|
200
|
+
|
|
201
|
+
# Handle end parameter
|
|
202
|
+
end = kwargs.get("end", "\n")
|
|
203
|
+
msg += end
|
|
204
|
+
|
|
205
|
+
# Handle flush parameter
|
|
206
|
+
flush = kwargs.get("flush", False)
|
|
207
|
+
|
|
208
|
+
return msg, flush
|
waldiez/running/post_run.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# SPDX-License-Identifier: Apache-2.0.
|
|
2
2
|
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
|
|
4
|
+
# pylint: disable=unused-argument
|
|
3
5
|
"""Utilities for running code."""
|
|
4
6
|
|
|
5
7
|
import datetime
|
|
@@ -12,8 +14,9 @@ from .gen_seq_diagram import generate_sequence_diagram
|
|
|
12
14
|
|
|
13
15
|
def after_run(
|
|
14
16
|
temp_dir: Path,
|
|
15
|
-
|
|
17
|
+
output_file: Optional[Union[str, Path]],
|
|
16
18
|
flow_name: str,
|
|
19
|
+
uploads_root: Optional[Path] = None,
|
|
17
20
|
skip_mmd: bool = False,
|
|
18
21
|
) -> None:
|
|
19
22
|
"""Actions to perform after running the flow.
|
|
@@ -22,17 +25,19 @@ def after_run(
|
|
|
22
25
|
----------
|
|
23
26
|
temp_dir : Path
|
|
24
27
|
The temporary directory.
|
|
25
|
-
|
|
26
|
-
The output
|
|
28
|
+
output_file : Optional[Union[str, Path]]
|
|
29
|
+
The output file.
|
|
27
30
|
flow_name : str
|
|
28
31
|
The flow name.
|
|
32
|
+
uploads_root : Optional[Path], optional
|
|
33
|
+
The runtime uploads root, by default None
|
|
29
34
|
skip_mmd : bool, optional
|
|
30
35
|
Whether to skip the mermaid sequence diagram generation,
|
|
31
36
|
by default, False
|
|
32
37
|
"""
|
|
33
|
-
if isinstance(
|
|
34
|
-
|
|
35
|
-
mmd_dir =
|
|
38
|
+
if isinstance(output_file, str):
|
|
39
|
+
output_file = Path(output_file)
|
|
40
|
+
mmd_dir = output_file.parent if output_file else Path.cwd()
|
|
36
41
|
if skip_mmd is False:
|
|
37
42
|
events_csv_path = temp_dir / "logs" / "events.csv"
|
|
38
43
|
if events_csv_path.exists():
|
|
@@ -40,7 +45,7 @@ def after_run(
|
|
|
40
45
|
mmd_path = temp_dir / f"{flow_name}.mmd"
|
|
41
46
|
generate_sequence_diagram(events_csv_path, mmd_path)
|
|
42
47
|
if (
|
|
43
|
-
not
|
|
48
|
+
not output_file
|
|
44
49
|
and mmd_path.exists()
|
|
45
50
|
and mmd_path != mmd_dir / f"{flow_name}.mmd"
|
|
46
51
|
):
|
|
@@ -48,8 +53,8 @@ def after_run(
|
|
|
48
53
|
shutil.copyfile(mmd_path, mmd_dir / f"{flow_name}.mmd")
|
|
49
54
|
except BaseException: # pylint: disable=broad-exception-caught
|
|
50
55
|
pass
|
|
51
|
-
if
|
|
52
|
-
destination_dir =
|
|
56
|
+
if output_file:
|
|
57
|
+
destination_dir = output_file.parent
|
|
53
58
|
destination_dir = (
|
|
54
59
|
destination_dir
|
|
55
60
|
/ "waldiez_out"
|
|
@@ -60,8 +65,7 @@ def after_run(
|
|
|
60
65
|
print(f"Copying the results to {destination_dir}")
|
|
61
66
|
copy_results(
|
|
62
67
|
temp_dir=temp_dir,
|
|
63
|
-
|
|
64
|
-
output_dir=output_path.parent,
|
|
68
|
+
output_file=output_file,
|
|
65
69
|
destination_dir=destination_dir,
|
|
66
70
|
)
|
|
67
71
|
shutil.rmtree(temp_dir)
|
|
@@ -69,8 +73,7 @@ def after_run(
|
|
|
69
73
|
|
|
70
74
|
def copy_results(
|
|
71
75
|
temp_dir: Path,
|
|
72
|
-
|
|
73
|
-
output_dir: Path,
|
|
76
|
+
output_file: Path,
|
|
74
77
|
destination_dir: Path,
|
|
75
78
|
) -> None:
|
|
76
79
|
"""Copy the results to the output directory.
|
|
@@ -79,14 +82,13 @@ def copy_results(
|
|
|
79
82
|
----------
|
|
80
83
|
temp_dir : Path
|
|
81
84
|
The temporary directory.
|
|
82
|
-
|
|
83
|
-
The output
|
|
84
|
-
output_dir : Path
|
|
85
|
-
The output directory.
|
|
85
|
+
output_file : Path
|
|
86
|
+
The output file.
|
|
86
87
|
destination_dir : Path
|
|
87
88
|
The destination directory.
|
|
88
89
|
"""
|
|
89
90
|
temp_dir.mkdir(parents=True, exist_ok=True)
|
|
91
|
+
output_dir = output_file.parent
|
|
90
92
|
for item in temp_dir.iterdir():
|
|
91
93
|
# skip cache files
|
|
92
94
|
if (
|
|
@@ -107,13 +109,13 @@ def copy_results(
|
|
|
107
109
|
shutil.copy(item, destination_dir)
|
|
108
110
|
else:
|
|
109
111
|
shutil.copytree(item, destination_dir / item.name)
|
|
110
|
-
if
|
|
111
|
-
if
|
|
112
|
-
|
|
113
|
-
if
|
|
114
|
-
src = temp_dir /
|
|
112
|
+
if output_file.is_file():
|
|
113
|
+
if output_file.suffix == ".waldiez":
|
|
114
|
+
output_file = output_file.with_suffix(".py")
|
|
115
|
+
if output_file.suffix == ".py":
|
|
116
|
+
src = temp_dir / output_file.name
|
|
115
117
|
if src.exists():
|
|
116
|
-
dst = destination_dir /
|
|
118
|
+
dst = destination_dir / output_file.name
|
|
117
119
|
if dst.exists():
|
|
118
120
|
dst.unlink()
|
|
119
|
-
shutil.copyfile(src, output_dir /
|
|
121
|
+
shutil.copyfile(src, output_dir / output_file.name)
|
waldiez/running/pre_run.py
CHANGED
|
@@ -7,54 +7,10 @@ import io
|
|
|
7
7
|
import os
|
|
8
8
|
import subprocess
|
|
9
9
|
import sys
|
|
10
|
-
import
|
|
11
|
-
from pathlib import Path
|
|
12
|
-
from typing import Callable, Optional, Union
|
|
10
|
+
from typing import Callable
|
|
13
11
|
|
|
14
12
|
from .environment import in_virtualenv, is_root
|
|
15
|
-
from .
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def before_run(
|
|
19
|
-
output_path: Optional[Union[str, Path]],
|
|
20
|
-
uploads_root: Optional[Union[str, Path]],
|
|
21
|
-
) -> str:
|
|
22
|
-
"""Actions to perform before running the flow.
|
|
23
|
-
|
|
24
|
-
Parameters
|
|
25
|
-
----------
|
|
26
|
-
output_path : Optional[Union[str, Path]]
|
|
27
|
-
The output path.
|
|
28
|
-
uploads_root : Optional[Union[str, Path]]
|
|
29
|
-
The runtime uploads root.
|
|
30
|
-
|
|
31
|
-
Returns
|
|
32
|
-
-------
|
|
33
|
-
str
|
|
34
|
-
The file name.
|
|
35
|
-
"""
|
|
36
|
-
if not uploads_root:
|
|
37
|
-
uploads_root = Path(tempfile.mkdtemp())
|
|
38
|
-
else:
|
|
39
|
-
uploads_root = Path(uploads_root)
|
|
40
|
-
if not uploads_root.exists():
|
|
41
|
-
uploads_root.mkdir(parents=True)
|
|
42
|
-
output_dir = Path.cwd()
|
|
43
|
-
if output_path and isinstance(output_path, str):
|
|
44
|
-
output_path = Path(output_path)
|
|
45
|
-
if output_path:
|
|
46
|
-
if output_path.is_dir():
|
|
47
|
-
output_dir = output_path
|
|
48
|
-
else:
|
|
49
|
-
output_dir = output_path.parent if output_path else Path.cwd()
|
|
50
|
-
if not output_dir.exists():
|
|
51
|
-
output_dir.mkdir(parents=True, exist_ok=True)
|
|
52
|
-
file_name = Path(output_path).name if output_path else "waldiez_flow.py"
|
|
53
|
-
if file_name.endswith((".json", ".waldiez")):
|
|
54
|
-
file_name = file_name.replace(".json", ".py").replace(".waldiez", ".py")
|
|
55
|
-
if not file_name.endswith(".py"):
|
|
56
|
-
file_name += ".py"
|
|
57
|
-
return file_name
|
|
13
|
+
from .utils import strip_ansi
|
|
58
14
|
|
|
59
15
|
|
|
60
16
|
def install_requirements(
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
|
|
4
|
+
"""Waldiez Runner protocol."""
|
|
5
|
+
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import TYPE_CHECKING, Protocol, Union, runtime_checkable
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from autogen import ChatResult # type: ignore[import-untyped]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@runtime_checkable
|
|
14
|
+
class WaldiezRunnerProtocol(Protocol):
|
|
15
|
+
"""Waldiez Runner protocol."""
|
|
16
|
+
|
|
17
|
+
def before_run(
|
|
18
|
+
self,
|
|
19
|
+
output_file: Path,
|
|
20
|
+
uploads_root: Path | None,
|
|
21
|
+
) -> Path: # pyright: ignore
|
|
22
|
+
"""Actions to perform before running the flow.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
output_file : Path
|
|
27
|
+
The output file.
|
|
28
|
+
uploads_root : Path | None
|
|
29
|
+
The runtime uploads root.
|
|
30
|
+
|
|
31
|
+
Returns
|
|
32
|
+
-------
|
|
33
|
+
Path
|
|
34
|
+
The path to the temporary directory created for the run.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
async def a_before_run(
|
|
38
|
+
self,
|
|
39
|
+
output_file: Path,
|
|
40
|
+
uploads_root: Path | None,
|
|
41
|
+
) -> Path: # pyright: ignore
|
|
42
|
+
"""Asynchronously perform actions before running the flow.
|
|
43
|
+
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
output_file : Path
|
|
47
|
+
The output file.
|
|
48
|
+
uploads_root : Path | None
|
|
49
|
+
The runtime uploads root.
|
|
50
|
+
|
|
51
|
+
Returns
|
|
52
|
+
-------
|
|
53
|
+
Path
|
|
54
|
+
The path to the temporary directory created for the run.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
def start(
|
|
58
|
+
self,
|
|
59
|
+
output_path: str | Path | None,
|
|
60
|
+
uploads_root: str | Path | None,
|
|
61
|
+
structured_io: bool | None = None,
|
|
62
|
+
skip_patch_io: bool | None = None,
|
|
63
|
+
skip_mmd: bool = False,
|
|
64
|
+
) -> None:
|
|
65
|
+
"""Start running the Waldiez flow in a non-blocking way.
|
|
66
|
+
|
|
67
|
+
To allow "stoping" it later.
|
|
68
|
+
|
|
69
|
+
Parameters
|
|
70
|
+
----------
|
|
71
|
+
output_path : str | Path | None
|
|
72
|
+
The output path.
|
|
73
|
+
uploads_root : str | Path | None
|
|
74
|
+
The runtime uploads root.
|
|
75
|
+
structured_io : bool
|
|
76
|
+
Whether to use structured IO instead of the default 'input/print'.
|
|
77
|
+
skip_patch_io : bool | None
|
|
78
|
+
Whether to skip patching I/O, by default None.
|
|
79
|
+
If None, it will use the value from the context.
|
|
80
|
+
skip_mmd : bool
|
|
81
|
+
Whether to skip generating the mermaid diagram.
|
|
82
|
+
|
|
83
|
+
Raises
|
|
84
|
+
------
|
|
85
|
+
RuntimeError
|
|
86
|
+
If the runner is already running.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
async def a_start(
|
|
90
|
+
self,
|
|
91
|
+
output_path: str | Path | None,
|
|
92
|
+
uploads_root: str | Path | None,
|
|
93
|
+
structured_io: bool | None = None,
|
|
94
|
+
skip_patch_io: bool | None = None,
|
|
95
|
+
skip_mmd: bool = False,
|
|
96
|
+
) -> None:
|
|
97
|
+
"""Asynchronously start running the Waldiez flow in a non-blocking way.
|
|
98
|
+
|
|
99
|
+
To allow "stoping" it later.
|
|
100
|
+
|
|
101
|
+
Parameters
|
|
102
|
+
----------
|
|
103
|
+
output_path : str | Path | None
|
|
104
|
+
The output path.
|
|
105
|
+
uploads_root : str | Path | None
|
|
106
|
+
The runtime uploads root.
|
|
107
|
+
structured_io : bool
|
|
108
|
+
Whether to use structured IO instead of the default 'input/print'.
|
|
109
|
+
skip_patch_io : bool | None
|
|
110
|
+
Whether to skip patching I/O, by default None.
|
|
111
|
+
If None, it will use the value from the context.
|
|
112
|
+
skip_mmd : bool
|
|
113
|
+
Whether to skip generating the mermaid diagram.
|
|
114
|
+
|
|
115
|
+
Raises
|
|
116
|
+
------
|
|
117
|
+
RuntimeError
|
|
118
|
+
If the runner is already running.
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
def run(
|
|
122
|
+
self,
|
|
123
|
+
output_path: str | Path | None,
|
|
124
|
+
uploads_root: str | Path | None,
|
|
125
|
+
structured_io: bool | None = None,
|
|
126
|
+
threaded: bool | None = None,
|
|
127
|
+
skip_patch_io: bool | None = None,
|
|
128
|
+
skip_mmd: bool = False,
|
|
129
|
+
) -> Union[
|
|
130
|
+
"ChatResult",
|
|
131
|
+
list["ChatResult"],
|
|
132
|
+
dict[int, "ChatResult"],
|
|
133
|
+
]: # pyright: ignore
|
|
134
|
+
"""Run the Waldiez flow in a blocking way.
|
|
135
|
+
|
|
136
|
+
Parameters
|
|
137
|
+
----------
|
|
138
|
+
output_path : str | Path | None
|
|
139
|
+
The output path, by default None.
|
|
140
|
+
uploads_root : str | Path | None
|
|
141
|
+
The runtime uploads root.
|
|
142
|
+
structured_io : bool
|
|
143
|
+
Whether to use structured IO instead of the default 'input/print'.
|
|
144
|
+
threaded : bool | None
|
|
145
|
+
Whether to run the flow in a separate thread.
|
|
146
|
+
skip_patch_io : bool
|
|
147
|
+
Whether to skip patching I/O, by default None.
|
|
148
|
+
If None, it will use the value from the context.
|
|
149
|
+
skip_mmd : bool
|
|
150
|
+
Whether to skip generating the mermaid diagram.
|
|
151
|
+
|
|
152
|
+
Returns
|
|
153
|
+
-------
|
|
154
|
+
Union[ChatResult, list[ChatResult], dict[int, ChatResult]]
|
|
155
|
+
The result of the run, which can be a single ChatResult,
|
|
156
|
+
a list of ChatResults,
|
|
157
|
+
or a dictionary mapping indices to ChatResults.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
async def a_run(
|
|
161
|
+
self,
|
|
162
|
+
output_path: str | Path | None,
|
|
163
|
+
uploads_root: str | Path | None,
|
|
164
|
+
structured_io: bool | None = None,
|
|
165
|
+
skip_patch_io: bool | None = None,
|
|
166
|
+
skip_mmd: bool = False,
|
|
167
|
+
) -> Union[
|
|
168
|
+
"ChatResult",
|
|
169
|
+
list["ChatResult"],
|
|
170
|
+
dict[int, "ChatResult"],
|
|
171
|
+
]: # pyright: ignore
|
|
172
|
+
"""Run the Waldiez flow.
|
|
173
|
+
|
|
174
|
+
Parameters
|
|
175
|
+
----------
|
|
176
|
+
output_path : str | Path | None
|
|
177
|
+
The output path, by default None.
|
|
178
|
+
uploads_root : str | Path | None
|
|
179
|
+
The runtime uploads root.
|
|
180
|
+
structured_io : bool
|
|
181
|
+
Whether to use structured IO instead of the default 'input/print'.
|
|
182
|
+
skip_patch_io : bool
|
|
183
|
+
Whether to skip patching I/O, by default None.
|
|
184
|
+
If None, it will use the value from the context.
|
|
185
|
+
skip_mmd : bool
|
|
186
|
+
Whether to skip generating the mermaid diagram.
|
|
187
|
+
|
|
188
|
+
Returns
|
|
189
|
+
-------
|
|
190
|
+
Union[ChatResult, list[ChatResult], dict[int, ChatResult]]
|
|
191
|
+
The result of the run, which can be a single ChatResult,
|
|
192
|
+
a list of ChatResults,
|
|
193
|
+
or a dictionary mapping indices to ChatResults.
|
|
194
|
+
"""
|
|
195
|
+
|
|
196
|
+
def after_run(
|
|
197
|
+
self,
|
|
198
|
+
results: Union[
|
|
199
|
+
"ChatResult",
|
|
200
|
+
list["ChatResult"],
|
|
201
|
+
dict[int, "ChatResult"],
|
|
202
|
+
],
|
|
203
|
+
output_file: Path,
|
|
204
|
+
uploads_root: Path | None,
|
|
205
|
+
temp_dir: Path,
|
|
206
|
+
skip_mmd: bool,
|
|
207
|
+
) -> None:
|
|
208
|
+
"""Actions to perform after running the flow.
|
|
209
|
+
|
|
210
|
+
Parameters
|
|
211
|
+
----------
|
|
212
|
+
results : Union[ChatResult, list[ChatResult], dict[int, ChatResult]]
|
|
213
|
+
The results of the run, which can be a single ChatResult,
|
|
214
|
+
a list of ChatResults,
|
|
215
|
+
or a dictionary mapping indices to ChatResults.
|
|
216
|
+
output_file : Path
|
|
217
|
+
The path to the output file.
|
|
218
|
+
uploads_root : Path | None
|
|
219
|
+
The runtime uploads root.
|
|
220
|
+
temp_dir : Path
|
|
221
|
+
The path to the temporary directory.
|
|
222
|
+
skip_mmd : bool
|
|
223
|
+
Whether to skip generating the mermaid diagram.
|
|
224
|
+
"""
|
|
225
|
+
|
|
226
|
+
async def a_after_run(
|
|
227
|
+
self,
|
|
228
|
+
results: Union[
|
|
229
|
+
"ChatResult",
|
|
230
|
+
list["ChatResult"],
|
|
231
|
+
dict[int, "ChatResult"],
|
|
232
|
+
],
|
|
233
|
+
output_file: Path,
|
|
234
|
+
uploads_root: Path | None,
|
|
235
|
+
temp_dir: Path,
|
|
236
|
+
skip_mmd: bool,
|
|
237
|
+
) -> None:
|
|
238
|
+
"""Asynchronously perform actions after running the flow.
|
|
239
|
+
|
|
240
|
+
Parameters
|
|
241
|
+
----------
|
|
242
|
+
results : Union[ChatResult, list[ChatResult], dict[int, ChatResult]]
|
|
243
|
+
The results of the run, which can be a single ChatResult,
|
|
244
|
+
a list of ChatResults,
|
|
245
|
+
or a dictionary mapping indices to ChatResults.
|
|
246
|
+
output_file : Path
|
|
247
|
+
The path to the output file.
|
|
248
|
+
uploads_root : Path | None
|
|
249
|
+
The runtime uploads root.
|
|
250
|
+
temp_dir : Path
|
|
251
|
+
The path to the temporary directory.
|
|
252
|
+
skip_mmd : bool
|
|
253
|
+
Whether to skip generating the mermaid diagram.
|
|
254
|
+
"""
|
|
255
|
+
|
|
256
|
+
def is_running(self) -> bool: # pyright: ignore
|
|
257
|
+
"""Check if the runner is currently running.
|
|
258
|
+
|
|
259
|
+
Returns
|
|
260
|
+
-------
|
|
261
|
+
bool
|
|
262
|
+
True if the runner is running, False otherwise.
|
|
263
|
+
"""
|
|
264
|
+
|
|
265
|
+
def stop(self) -> None:
|
|
266
|
+
"""Stop the runner if it is running.
|
|
267
|
+
|
|
268
|
+
Raises
|
|
269
|
+
------
|
|
270
|
+
RuntimeError
|
|
271
|
+
If the runner is not running.
|
|
272
|
+
"""
|
|
273
|
+
|
|
274
|
+
async def a_stop(self) -> None:
|
|
275
|
+
"""Asynchronously stop the runner if it is running.
|
|
276
|
+
|
|
277
|
+
Raises
|
|
278
|
+
------
|
|
279
|
+
RuntimeError
|
|
280
|
+
If the runner is not running.
|
|
281
|
+
"""
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
|
|
4
|
+
"""Waldiez run results module."""
|
|
5
|
+
|
|
6
|
+
from typing import TYPE_CHECKING, TypedDict, Union
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from autogen import ChatResult # type: ignore[import-untyped]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class WaldiezRunResults(TypedDict):
|
|
13
|
+
"""Results of the Waldiez run."""
|
|
14
|
+
|
|
15
|
+
results: Union[
|
|
16
|
+
"ChatResult",
|
|
17
|
+
list["ChatResult"],
|
|
18
|
+
dict[int, "ChatResult"],
|
|
19
|
+
None,
|
|
20
|
+
]
|
|
21
|
+
exception: Exception | None
|
|
22
|
+
completed: bool
|