waldiez 0.5.9__py3-none-any.whl → 0.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of waldiez might be problematic. Click here for more details.
- waldiez/_version.py +1 -1
- waldiez/cli.py +113 -24
- waldiez/exporting/agent/exporter.py +9 -6
- waldiez/exporting/agent/extras/captain_agent_extras.py +44 -7
- waldiez/exporting/agent/extras/group_manager_agent_extas.py +6 -1
- waldiez/exporting/agent/extras/handoffs/after_work.py +1 -0
- waldiez/exporting/agent/extras/handoffs/available.py +1 -0
- waldiez/exporting/agent/extras/handoffs/condition.py +3 -1
- waldiez/exporting/agent/extras/handoffs/handoff.py +1 -0
- waldiez/exporting/agent/extras/handoffs/target.py +1 -0
- waldiez/exporting/agent/termination.py +1 -0
- waldiez/exporting/chats/utils/common.py +25 -23
- waldiez/exporting/core/__init__.py +0 -2
- waldiez/exporting/core/constants.py +3 -1
- waldiez/exporting/core/context.py +13 -13
- waldiez/exporting/core/extras/serializer.py +12 -10
- waldiez/exporting/core/protocols.py +0 -141
- waldiez/exporting/core/result.py +5 -5
- waldiez/exporting/core/types.py +1 -0
- waldiez/exporting/core/utils/llm_config.py +2 -2
- waldiez/exporting/flow/execution_generator.py +1 -0
- waldiez/exporting/flow/merger.py +2 -2
- waldiez/exporting/flow/orchestrator.py +1 -0
- waldiez/exporting/flow/utils/common.py +3 -3
- waldiez/exporting/flow/utils/importing.py +1 -0
- waldiez/exporting/flow/utils/logging.py +7 -80
- waldiez/exporting/tools/exporter.py +5 -0
- waldiez/exporting/tools/factory.py +4 -0
- waldiez/exporting/tools/processor.py +5 -1
- waldiez/io/__init__.py +3 -1
- waldiez/io/_ws.py +15 -5
- waldiez/io/models/content/image.py +1 -0
- waldiez/io/models/user_input.py +4 -4
- waldiez/io/models/user_response.py +1 -0
- waldiez/io/mqtt.py +1 -1
- waldiez/io/structured.py +98 -45
- waldiez/io/utils.py +17 -11
- waldiez/io/ws.py +10 -12
- waldiez/logger.py +180 -63
- waldiez/models/agents/agent/agent.py +2 -1
- waldiez/models/agents/agent/update_system_message.py +0 -2
- waldiez/models/agents/doc_agent/doc_agent.py +8 -1
- waldiez/models/chat/chat.py +1 -0
- waldiez/models/chat/chat_data.py +0 -2
- waldiez/models/common/base.py +2 -0
- waldiez/models/common/dict_utils.py +169 -40
- waldiez/models/common/handoff.py +2 -0
- waldiez/models/common/method_utils.py +2 -0
- waldiez/models/flow/flow.py +6 -6
- waldiez/models/flow/info.py +5 -1
- waldiez/models/model/_llm.py +31 -14
- waldiez/models/model/model.py +4 -1
- waldiez/models/model/model_data.py +18 -5
- waldiez/models/tool/predefined/_config.py +5 -1
- waldiez/models/tool/predefined/_duckduckgo.py +4 -0
- waldiez/models/tool/predefined/_email.py +477 -0
- waldiez/models/tool/predefined/_google.py +4 -1
- waldiez/models/tool/predefined/_perplexity.py +4 -1
- waldiez/models/tool/predefined/_searxng.py +4 -1
- waldiez/models/tool/predefined/_tavily.py +4 -1
- waldiez/models/tool/predefined/_wikipedia.py +5 -2
- waldiez/models/tool/predefined/_youtube.py +4 -1
- waldiez/models/tool/predefined/protocol.py +3 -0
- waldiez/models/tool/tool.py +22 -4
- waldiez/models/waldiez.py +12 -0
- waldiez/runner.py +37 -54
- waldiez/running/__init__.py +6 -0
- waldiez/running/base_runner.py +381 -363
- waldiez/running/environment.py +1 -0
- waldiez/running/exceptions.py +9 -0
- waldiez/running/post_run.py +10 -4
- waldiez/running/pre_run.py +199 -66
- waldiez/running/protocol.py +21 -101
- waldiez/running/run_results.py +1 -1
- waldiez/running/standard_runner.py +83 -276
- waldiez/running/step_by_step/__init__.py +46 -0
- waldiez/running/step_by_step/breakpoints_mixin.py +512 -0
- waldiez/running/step_by_step/command_handler.py +151 -0
- waldiez/running/step_by_step/events_processor.py +199 -0
- waldiez/running/step_by_step/step_by_step_models.py +541 -0
- waldiez/running/step_by_step/step_by_step_runner.py +750 -0
- waldiez/running/subprocess_runner/__base__.py +279 -0
- waldiez/running/subprocess_runner/__init__.py +16 -0
- waldiez/running/subprocess_runner/_async_runner.py +362 -0
- waldiez/running/subprocess_runner/_sync_runner.py +456 -0
- waldiez/running/subprocess_runner/runner.py +570 -0
- waldiez/running/timeline_processor.py +1 -1
- waldiez/running/utils.py +492 -3
- waldiez/utils/version.py +2 -6
- waldiez/ws/__init__.py +71 -0
- waldiez/ws/__main__.py +15 -0
- waldiez/ws/_file_handler.py +199 -0
- waldiez/ws/_mock.py +74 -0
- waldiez/ws/cli.py +235 -0
- waldiez/ws/client_manager.py +851 -0
- waldiez/ws/errors.py +416 -0
- waldiez/ws/models.py +988 -0
- waldiez/ws/reloader.py +363 -0
- waldiez/ws/server.py +508 -0
- waldiez/ws/session_manager.py +393 -0
- waldiez/ws/session_stats.py +83 -0
- waldiez/ws/utils.py +410 -0
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/METADATA +105 -96
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/RECORD +108 -83
- waldiez/running/patch_io_stream.py +0 -210
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/WHEEL +0 -0
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/entry_points.txt +0 -0
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/licenses/LICENSE +0 -0
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/licenses/NOTICE.md +0 -0
waldiez/running/environment.py
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
"""Custom exceptions for Waldiez runners."""
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class StopRunningException(Exception):
|
|
7
|
+
"""Exception to stop the running process."""
|
|
8
|
+
|
|
9
|
+
reason: str = "Execution stopped by user"
|
waldiez/running/post_run.py
CHANGED
|
@@ -11,8 +11,8 @@ from pathlib import Path
|
|
|
11
11
|
from typing import Optional, Union
|
|
12
12
|
|
|
13
13
|
from .gen_seq_diagram import generate_sequence_diagram
|
|
14
|
-
from .patch_io_stream import get_printer
|
|
15
14
|
from .timeline_processor import TimelineProcessor
|
|
15
|
+
from .utils import get_printer
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
# noinspection PyUnusedLocal
|
|
@@ -20,6 +20,7 @@ def after_run(
|
|
|
20
20
|
temp_dir: Path,
|
|
21
21
|
output_file: Optional[Union[str, Path]],
|
|
22
22
|
flow_name: str,
|
|
23
|
+
waldiez_file: Path,
|
|
23
24
|
uploads_root: Optional[Path] = None,
|
|
24
25
|
skip_mmd: bool = False,
|
|
25
26
|
skip_timeline: bool = False,
|
|
@@ -34,6 +35,8 @@ def after_run(
|
|
|
34
35
|
The output file.
|
|
35
36
|
flow_name : str
|
|
36
37
|
The flow name.
|
|
38
|
+
waldiez_file : Path
|
|
39
|
+
The path of the waldiez file used (or dumped) for the run.
|
|
37
40
|
uploads_root : Optional[Path], optional
|
|
38
41
|
The runtime uploads root, by default None
|
|
39
42
|
skip_mmd : bool, optional
|
|
@@ -52,7 +55,7 @@ def after_run(
|
|
|
52
55
|
flow_name=flow_name,
|
|
53
56
|
mmd_dir=mmd_dir,
|
|
54
57
|
)
|
|
55
|
-
if skip_timeline is False:
|
|
58
|
+
if skip_timeline is False: # pragma: no branch
|
|
56
59
|
_make_timeline_json(temp_dir=temp_dir)
|
|
57
60
|
if output_file:
|
|
58
61
|
destination_dir = output_file.parent
|
|
@@ -69,6 +72,9 @@ def after_run(
|
|
|
69
72
|
output_file=output_file,
|
|
70
73
|
destination_dir=destination_dir,
|
|
71
74
|
)
|
|
75
|
+
dst_waldiez = destination_dir / waldiez_file.name
|
|
76
|
+
if not dst_waldiez.exists() and waldiez_file.is_file():
|
|
77
|
+
shutil.copyfile(waldiez_file, dst_waldiez)
|
|
72
78
|
shutil.rmtree(temp_dir)
|
|
73
79
|
|
|
74
80
|
|
|
@@ -103,7 +109,7 @@ def _make_timeline_json(
|
|
|
103
109
|
events_csv_path = temp_dir / "logs" / "events.csv"
|
|
104
110
|
if events_csv_path.exists():
|
|
105
111
|
log_files = TimelineProcessor.get_files(temp_dir / "logs")
|
|
106
|
-
if any(log_files.values()):
|
|
112
|
+
if any(log_files.values()): # pragma: no branch
|
|
107
113
|
output_file = temp_dir / "timeline.json"
|
|
108
114
|
# pylint: disable=too-many-try-statements
|
|
109
115
|
try:
|
|
@@ -171,7 +177,7 @@ def copy_results(
|
|
|
171
177
|
if output_file.is_file():
|
|
172
178
|
if output_file.suffix == ".waldiez":
|
|
173
179
|
output_file = output_file.with_suffix(".py")
|
|
174
|
-
if output_file.suffix == ".py":
|
|
180
|
+
if output_file.suffix == ".py": # pragma: no branch
|
|
175
181
|
src = temp_dir / output_file.name
|
|
176
182
|
if src.exists():
|
|
177
183
|
dst = destination_dir / output_file.name
|
waldiez/running/pre_run.py
CHANGED
|
@@ -7,10 +7,61 @@ import io
|
|
|
7
7
|
import os
|
|
8
8
|
import subprocess
|
|
9
9
|
import sys
|
|
10
|
+
import tempfile
|
|
11
|
+
from pathlib import Path
|
|
10
12
|
from typing import Callable
|
|
11
13
|
|
|
14
|
+
from waldiez.models import Waldiez
|
|
15
|
+
|
|
12
16
|
from .environment import in_virtualenv, is_root
|
|
13
|
-
from .utils import
|
|
17
|
+
from .utils import (
|
|
18
|
+
ensure_pip,
|
|
19
|
+
get_pip_install_location,
|
|
20
|
+
get_python_executable,
|
|
21
|
+
safe_filename,
|
|
22
|
+
strip_ansi,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class RequirementsMixin:
|
|
27
|
+
"""Mixin class to handle requirements installation."""
|
|
28
|
+
|
|
29
|
+
_waldiez: Waldiez
|
|
30
|
+
_called_install_requirements: bool
|
|
31
|
+
|
|
32
|
+
def gather_requirements(self) -> set[str]:
|
|
33
|
+
"""Gather extra requirements to install before running the flow.
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
set[str]
|
|
38
|
+
A set of requirements that are not already installed and do not
|
|
39
|
+
include 'waldiez' in their name.
|
|
40
|
+
"""
|
|
41
|
+
extra_requirements = {
|
|
42
|
+
req
|
|
43
|
+
for req in self._waldiez.requirements
|
|
44
|
+
if req not in sys.modules and "waldiez" not in req
|
|
45
|
+
}
|
|
46
|
+
if "python-dotenv" not in extra_requirements: # pragma: no branch
|
|
47
|
+
extra_requirements.add("python-dotenv")
|
|
48
|
+
return extra_requirements
|
|
49
|
+
|
|
50
|
+
def install_requirements(self) -> None:
|
|
51
|
+
"""Install the requirements for the flow."""
|
|
52
|
+
if not self._called_install_requirements: # pragma: no branch
|
|
53
|
+
self._called_install_requirements = True
|
|
54
|
+
extra_requirements = self.gather_requirements()
|
|
55
|
+
if extra_requirements: # pragma: no branch
|
|
56
|
+
install_requirements(extra_requirements)
|
|
57
|
+
|
|
58
|
+
async def a_install_requirements(self) -> None:
|
|
59
|
+
"""Install the requirements for the flow asynchronously."""
|
|
60
|
+
if not self._called_install_requirements: # pragma: no branch
|
|
61
|
+
self._called_install_requirements = True
|
|
62
|
+
extra_requirements = self.gather_requirements()
|
|
63
|
+
if extra_requirements: # pragma: no branch
|
|
64
|
+
await a_install_requirements(extra_requirements)
|
|
14
65
|
|
|
15
66
|
|
|
16
67
|
# noinspection PyUnresolvedReferences
|
|
@@ -32,39 +83,40 @@ def install_requirements(
|
|
|
32
83
|
"""
|
|
33
84
|
requirements_string = ", ".join(extra_requirements)
|
|
34
85
|
printer(f"Installing requirements: {requirements_string}")
|
|
35
|
-
|
|
36
|
-
break_system_packages =
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
break_system_packages = os.environ.get("PIP_BREAK_SYSTEM_PACKAGES", "")
|
|
42
|
-
os.environ["PIP_BREAK_SYSTEM_PACKAGES"] = "1"
|
|
43
|
-
if not is_root():
|
|
44
|
-
pip_install.append("--user")
|
|
45
|
-
if upgrade:
|
|
46
|
-
pip_install.append("--upgrade")
|
|
47
|
-
pip_install.extend(extra_requirements)
|
|
48
|
-
# pylint: disable=too-many-try-statements
|
|
86
|
+
ensure_pip()
|
|
87
|
+
pip_install, break_system_packages, install_location = _before_pip(
|
|
88
|
+
extra_requirements, upgrade
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# pylint: disable=too-many-try-statements,broad-exception-caught
|
|
49
92
|
try:
|
|
50
93
|
with subprocess.Popen(
|
|
51
94
|
pip_install,
|
|
52
95
|
stdout=subprocess.PIPE,
|
|
53
96
|
stderr=subprocess.PIPE,
|
|
54
97
|
) as proc:
|
|
55
|
-
if proc.stdout:
|
|
98
|
+
if proc.stdout: # pragma: no branch
|
|
56
99
|
for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
|
|
57
|
-
|
|
58
|
-
|
|
100
|
+
stripped_line = strip_ansi(line.strip())
|
|
101
|
+
if stripped_line: # Only print non-empty lines
|
|
102
|
+
printer(stripped_line)
|
|
103
|
+
if proc.stderr: # pragma: no branch
|
|
59
104
|
for line in io.TextIOWrapper(proc.stderr, encoding="utf-8"):
|
|
60
|
-
|
|
105
|
+
stripped_line = strip_ansi(line.strip())
|
|
106
|
+
if stripped_line: # Only print non-empty lines
|
|
107
|
+
printer(stripped_line)
|
|
108
|
+
|
|
109
|
+
# Wait for process to complete and check return code
|
|
110
|
+
return_code = proc.wait()
|
|
111
|
+
if return_code != 0:
|
|
112
|
+
printer(
|
|
113
|
+
f"Package installation failed with exit code {return_code}"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
except Exception as e:
|
|
117
|
+
printer(f"Failed to install requirements: {e}")
|
|
61
118
|
finally:
|
|
62
|
-
|
|
63
|
-
# restore the old env var
|
|
64
|
-
if break_system_packages:
|
|
65
|
-
os.environ["PIP_BREAK_SYSTEM_PACKAGES"] = break_system_packages
|
|
66
|
-
else:
|
|
67
|
-
del os.environ["PIP_BREAK_SYSTEM_PACKAGES"]
|
|
119
|
+
_after_pip(break_system_packages, install_location)
|
|
68
120
|
|
|
69
121
|
|
|
70
122
|
async def a_install_requirements(
|
|
@@ -83,66 +135,147 @@ async def a_install_requirements(
|
|
|
83
135
|
printer : Callable[..., None]
|
|
84
136
|
The printer function to use, defaults to print.
|
|
85
137
|
"""
|
|
138
|
+
pip_install, break_system_packages, install_location = _before_pip(
|
|
139
|
+
extra_requirements, upgrade=upgrade
|
|
140
|
+
)
|
|
86
141
|
requirements_string = ", ".join(extra_requirements)
|
|
87
142
|
printer(f"Installing requirements: {requirements_string}")
|
|
88
|
-
|
|
89
|
-
break_system_packages = ""
|
|
90
|
-
if not in_virtualenv():
|
|
91
|
-
break_system_packages = os.environ.get("PIP_BREAK_SYSTEM_PACKAGES", "")
|
|
92
|
-
os.environ["PIP_BREAK_SYSTEM_PACKAGES"] = "1"
|
|
93
|
-
if not is_root():
|
|
94
|
-
pip_install.extend(["--user"])
|
|
95
|
-
if upgrade:
|
|
96
|
-
pip_install.append("--upgrade")
|
|
97
|
-
pip_install.extend(extra_requirements)
|
|
98
|
-
# pylint: disable=too-many-try-statements
|
|
143
|
+
# pylint: disable=too-many-try-statements,broad-exception-caught
|
|
99
144
|
try:
|
|
100
145
|
proc = await asyncio.create_subprocess_exec(
|
|
101
146
|
*pip_install,
|
|
102
147
|
stdout=asyncio.subprocess.PIPE,
|
|
103
148
|
stderr=asyncio.subprocess.PIPE,
|
|
104
149
|
)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
async for
|
|
110
|
-
|
|
150
|
+
|
|
151
|
+
async def _pump_stream(stream: asyncio.StreamReader | None) -> None:
|
|
152
|
+
if not stream:
|
|
153
|
+
return
|
|
154
|
+
async for raw in stream:
|
|
155
|
+
text = strip_ansi(raw.decode().rstrip())
|
|
156
|
+
if text:
|
|
157
|
+
printer(text)
|
|
158
|
+
|
|
159
|
+
# Create tasks for concurrent execution
|
|
160
|
+
tasks: list[asyncio.Task[int | None]] = [
|
|
161
|
+
asyncio.create_task(_pump_stream(proc.stdout)),
|
|
162
|
+
asyncio.create_task(_pump_stream(proc.stderr)),
|
|
163
|
+
asyncio.create_task(proc.wait()),
|
|
164
|
+
]
|
|
165
|
+
await asyncio.gather(*tasks, return_exceptions=True)
|
|
166
|
+
if proc.returncode != 0:
|
|
167
|
+
printer(
|
|
168
|
+
f"Package installation failed with exit code {proc.returncode}"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
except Exception as e:
|
|
172
|
+
printer(f"Failed to install requirements: {e}")
|
|
111
173
|
finally:
|
|
112
|
-
|
|
113
|
-
if break_system_packages:
|
|
114
|
-
os.environ["PIP_BREAK_SYSTEM_PACKAGES"] = break_system_packages
|
|
115
|
-
else:
|
|
116
|
-
del os.environ["PIP_BREAK_SYSTEM_PACKAGES"]
|
|
174
|
+
_after_pip(break_system_packages, install_location)
|
|
117
175
|
|
|
118
176
|
|
|
119
|
-
def
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
) -> None:
|
|
123
|
-
"""
|
|
177
|
+
def _before_pip(
|
|
178
|
+
packages: set[str],
|
|
179
|
+
upgrade: bool,
|
|
180
|
+
) -> tuple[list[str], str, str | None]:
|
|
181
|
+
"""Gather the pip command for installing requirements.
|
|
124
182
|
|
|
125
183
|
Parameters
|
|
126
184
|
----------
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
185
|
+
packages : set[str]
|
|
186
|
+
The packages to install.
|
|
187
|
+
upgrade : bool
|
|
188
|
+
Whether to upgrade the packages.
|
|
189
|
+
|
|
190
|
+
Returns
|
|
191
|
+
-------
|
|
192
|
+
tuple[list[str], str, str | None]
|
|
193
|
+
The pip command, break_system_packages flag, and install location.
|
|
131
194
|
"""
|
|
132
|
-
|
|
195
|
+
ensure_pip()
|
|
196
|
+
pip_install = [
|
|
197
|
+
get_python_executable(),
|
|
198
|
+
"-m",
|
|
199
|
+
"pip",
|
|
200
|
+
"install",
|
|
201
|
+
"--disable-pip-version-check",
|
|
202
|
+
"--no-input",
|
|
203
|
+
]
|
|
204
|
+
install_location = get_pip_install_location()
|
|
205
|
+
break_system_packages = ""
|
|
133
206
|
|
|
207
|
+
if install_location:
|
|
208
|
+
pip_install += ["--target", install_location]
|
|
209
|
+
elif not in_virtualenv(): # it should # pragma: no cover
|
|
210
|
+
# if not, let's try to install as user
|
|
211
|
+
# not sure if --break-system-packages is safe,
|
|
212
|
+
# but it might fail if we don't
|
|
213
|
+
break_system_packages = os.environ.get("PIP_BREAK_SYSTEM_PACKAGES", "")
|
|
214
|
+
os.environ["PIP_BREAK_SYSTEM_PACKAGES"] = "1"
|
|
215
|
+
if not is_root():
|
|
216
|
+
pip_install.append("--user")
|
|
134
217
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
218
|
+
if upgrade: # pragma: no cover
|
|
219
|
+
pip_install.append("--upgrade")
|
|
220
|
+
|
|
221
|
+
pip_install.extend(packages)
|
|
222
|
+
return pip_install, break_system_packages, install_location
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def _after_pip(
|
|
226
|
+
break_system_packages: str, install_location: str | None
|
|
138
227
|
) -> None:
|
|
139
|
-
"""
|
|
228
|
+
"""Restore environment variables after pip installation.
|
|
140
229
|
|
|
141
230
|
Parameters
|
|
142
231
|
----------
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
The
|
|
232
|
+
break_system_packages : str
|
|
233
|
+
The original value of PIP_BREAK_SYSTEM_PACKAGES.
|
|
234
|
+
install_location : str | None
|
|
235
|
+
The install location used (None if default).
|
|
236
|
+
"""
|
|
237
|
+
if install_location is None and not in_virtualenv(): # pragma: no cover
|
|
238
|
+
# restore the old env var
|
|
239
|
+
if break_system_packages:
|
|
240
|
+
os.environ["PIP_BREAK_SYSTEM_PACKAGES"] = break_system_packages
|
|
241
|
+
else:
|
|
242
|
+
# Use pop to avoid KeyError if the key doesn't exist
|
|
243
|
+
os.environ.pop("PIP_BREAK_SYSTEM_PACKAGES", None)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def dump_waldiez(waldiez: Waldiez, output_path: str | Path | None) -> Path:
|
|
247
|
+
"""Dump waldiez flow to a file.
|
|
248
|
+
|
|
249
|
+
Parameters
|
|
250
|
+
----------
|
|
251
|
+
waldiez : Waldiez
|
|
252
|
+
The waldiez instance to dump.
|
|
253
|
+
output_path : str | Path | None
|
|
254
|
+
Optional output path to determine the directory to save the flow to.
|
|
255
|
+
|
|
256
|
+
Returns
|
|
257
|
+
-------
|
|
258
|
+
Path
|
|
259
|
+
The path to the generated file.
|
|
147
260
|
"""
|
|
148
|
-
|
|
261
|
+
file_path = Path(output_path) if output_path else None
|
|
262
|
+
if file_path:
|
|
263
|
+
file_name = file_path.name
|
|
264
|
+
if not file_name.endswith(".waldiez"):
|
|
265
|
+
file_path.with_suffix(".waldiez")
|
|
266
|
+
|
|
267
|
+
else:
|
|
268
|
+
full_name = waldiez.name
|
|
269
|
+
file_name = safe_filename(full_name, "waldiez")
|
|
270
|
+
file_dir: Path
|
|
271
|
+
if file_path:
|
|
272
|
+
file_dir = file_path if file_path.is_dir() else file_path.parent
|
|
273
|
+
else:
|
|
274
|
+
file_dir = Path(tempfile.mkdtemp())
|
|
275
|
+
file_dir.mkdir(parents=True, exist_ok=True)
|
|
276
|
+
output_path = file_dir / file_name
|
|
277
|
+
with output_path.open(
|
|
278
|
+
"w", encoding="utf-8", errors="replace", newline="\n"
|
|
279
|
+
) as f_open:
|
|
280
|
+
f_open.write(waldiez.model_dump_json())
|
|
281
|
+
return output_path
|
waldiez/running/protocol.py
CHANGED
|
@@ -51,98 +51,24 @@ class WaldiezRunnerProtocol(Protocol):
|
|
|
51
51
|
The path to the temporary directory created for the run.
|
|
52
52
|
"""
|
|
53
53
|
|
|
54
|
-
def start(
|
|
55
|
-
self,
|
|
56
|
-
output_path: str | Path | None,
|
|
57
|
-
uploads_root: str | Path | None,
|
|
58
|
-
structured_io: bool | None = None,
|
|
59
|
-
skip_mmd: bool = False,
|
|
60
|
-
skip_timeline: bool = False,
|
|
61
|
-
dot_env: str | Path | None = None,
|
|
62
|
-
**kwargs: Any,
|
|
63
|
-
) -> None:
|
|
64
|
-
"""Start running the Waldiez flow in a non-blocking way.
|
|
65
|
-
|
|
66
|
-
To allow "stoping" it later.
|
|
67
|
-
|
|
68
|
-
Parameters
|
|
69
|
-
----------
|
|
70
|
-
output_path : str | Path | None
|
|
71
|
-
The output path.
|
|
72
|
-
uploads_root : str | Path | None
|
|
73
|
-
The runtime uploads root.
|
|
74
|
-
structured_io : bool
|
|
75
|
-
Whether to use structured IO instead of the default 'input/print'.
|
|
76
|
-
skip_mmd : bool
|
|
77
|
-
Whether to skip generating the mermaid diagram.
|
|
78
|
-
skip_timeline : bool
|
|
79
|
-
Whether to skip generating the timeline JSON.
|
|
80
|
-
dot_env : str | Path | None
|
|
81
|
-
The path to the .env file, if any.
|
|
82
|
-
**kwargs : Any
|
|
83
|
-
Additional keyword arguments for the start method.
|
|
84
|
-
|
|
85
|
-
Raises
|
|
86
|
-
------
|
|
87
|
-
RuntimeError
|
|
88
|
-
If the runner is already running.
|
|
89
|
-
"""
|
|
90
|
-
|
|
91
|
-
async def a_start(
|
|
92
|
-
self,
|
|
93
|
-
output_path: str | Path | None,
|
|
94
|
-
uploads_root: str | Path | None,
|
|
95
|
-
structured_io: bool | None = None,
|
|
96
|
-
skip_mmd: bool = False,
|
|
97
|
-
skip_timeline: bool = False,
|
|
98
|
-
dot_env: str | Path | None = None,
|
|
99
|
-
**kwargs: Any,
|
|
100
|
-
) -> None:
|
|
101
|
-
"""Asynchronously start running the Waldiez flow in a non-blocking way.
|
|
102
|
-
|
|
103
|
-
To allow "stoping" it later.
|
|
104
|
-
|
|
105
|
-
Parameters
|
|
106
|
-
----------
|
|
107
|
-
output_path : str | Path | None
|
|
108
|
-
The output path.
|
|
109
|
-
uploads_root : str | Path | None
|
|
110
|
-
The runtime uploads root.
|
|
111
|
-
structured_io : bool
|
|
112
|
-
Whether to use structured IO instead of the default 'input/print'.
|
|
113
|
-
skip_mmd : bool
|
|
114
|
-
Whether to skip generating the mermaid diagram.
|
|
115
|
-
skip_timeline : bool
|
|
116
|
-
Whether to skip generating the timeline JSON.
|
|
117
|
-
dot_env : str | Path | None
|
|
118
|
-
The path to the .env file, if any.
|
|
119
|
-
**kwargs : Any
|
|
120
|
-
Additional keyword arguments for the start method.
|
|
121
|
-
|
|
122
|
-
Raises
|
|
123
|
-
------
|
|
124
|
-
RuntimeError
|
|
125
|
-
If the runner is already running.
|
|
126
|
-
"""
|
|
127
|
-
|
|
128
54
|
def run(
|
|
129
55
|
self,
|
|
130
|
-
output_path: str | Path | None,
|
|
131
|
-
uploads_root: str | Path | None,
|
|
56
|
+
output_path: str | Path | None = None,
|
|
57
|
+
uploads_root: str | Path | None = None,
|
|
132
58
|
structured_io: bool | None = None,
|
|
133
59
|
skip_mmd: bool = False,
|
|
134
60
|
skip_timeline: bool = False,
|
|
135
61
|
dot_env: str | Path | None = None,
|
|
136
62
|
**kwargs: Any,
|
|
137
63
|
) -> list[dict[str, Any]]:
|
|
138
|
-
"""Run the Waldiez flow
|
|
64
|
+
"""Run the Waldiez flow.
|
|
139
65
|
|
|
140
66
|
Parameters
|
|
141
67
|
----------
|
|
142
68
|
output_path : str | Path | None
|
|
143
69
|
The output path, by default None.
|
|
144
70
|
uploads_root : str | Path | None
|
|
145
|
-
The runtime uploads root.
|
|
71
|
+
The runtime uploads root, by default None.
|
|
146
72
|
structured_io : bool
|
|
147
73
|
Whether to use structured IO instead of the default 'input/print'.
|
|
148
74
|
skip_mmd : bool
|
|
@@ -157,20 +83,26 @@ class WaldiezRunnerProtocol(Protocol):
|
|
|
157
83
|
Returns
|
|
158
84
|
-------
|
|
159
85
|
list[dict[str, Any]]
|
|
160
|
-
The
|
|
86
|
+
The results of the run.
|
|
87
|
+
|
|
88
|
+
Raises
|
|
89
|
+
------
|
|
90
|
+
RuntimeError
|
|
91
|
+
If the runner is already running
|
|
92
|
+
or an error occurs during the run.
|
|
161
93
|
"""
|
|
162
94
|
|
|
163
95
|
async def a_run(
|
|
164
96
|
self,
|
|
165
|
-
output_path: str | Path | None,
|
|
166
|
-
uploads_root: str | Path | None,
|
|
97
|
+
output_path: str | Path | None = None,
|
|
98
|
+
uploads_root: str | Path | None = None,
|
|
167
99
|
structured_io: bool | None = None,
|
|
168
100
|
skip_mmd: bool = False,
|
|
169
101
|
skip_timeline: bool = False,
|
|
170
102
|
dot_env: str | Path | None = None,
|
|
171
103
|
**kwargs: Any,
|
|
172
104
|
) -> list[dict[str, Any]]:
|
|
173
|
-
"""Run the Waldiez flow.
|
|
105
|
+
"""Run the Waldiez flow asynchronously.
|
|
174
106
|
|
|
175
107
|
Parameters
|
|
176
108
|
----------
|
|
@@ -192,7 +124,13 @@ class WaldiezRunnerProtocol(Protocol):
|
|
|
192
124
|
Returns
|
|
193
125
|
-------
|
|
194
126
|
list[dict[str, Any]]
|
|
195
|
-
The
|
|
127
|
+
The results of the run.
|
|
128
|
+
|
|
129
|
+
Raises
|
|
130
|
+
------
|
|
131
|
+
RuntimeError
|
|
132
|
+
If the runner is already running, the workflow is not async
|
|
133
|
+
or an error occurs during the run.
|
|
196
134
|
"""
|
|
197
135
|
|
|
198
136
|
def after_run(
|
|
@@ -257,21 +195,3 @@ class WaldiezRunnerProtocol(Protocol):
|
|
|
257
195
|
bool
|
|
258
196
|
True if the runner is running, False otherwise.
|
|
259
197
|
"""
|
|
260
|
-
|
|
261
|
-
def stop(self) -> None:
|
|
262
|
-
"""Stop the runner if it is running.
|
|
263
|
-
|
|
264
|
-
Raises
|
|
265
|
-
------
|
|
266
|
-
RuntimeError
|
|
267
|
-
If the runner is not running.
|
|
268
|
-
"""
|
|
269
|
-
|
|
270
|
-
async def a_stop(self) -> None:
|
|
271
|
-
"""Asynchronously stop the runner if it is running.
|
|
272
|
-
|
|
273
|
-
Raises
|
|
274
|
-
------
|
|
275
|
-
RuntimeError
|
|
276
|
-
If the runner is not running.
|
|
277
|
-
"""
|
waldiez/running/run_results.py
CHANGED