waldiez 0.5.10__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 +1 -0
- waldiez/exporting/agent/exporter.py +6 -6
- 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/handoff.py +1 -0
- waldiez/exporting/agent/extras/handoffs/target.py +1 -0
- waldiez/exporting/agent/termination.py +1 -0
- waldiez/exporting/core/constants.py +3 -1
- waldiez/exporting/core/extras/serializer.py +12 -10
- 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/utils/common.py +1 -1
- waldiez/exporting/flow/utils/importing.py +1 -1
- waldiez/exporting/flow/utils/logging.py +3 -75
- waldiez/io/__init__.py +3 -1
- waldiez/io/_ws.py +2 -0
- waldiez/io/structured.py +81 -28
- waldiez/io/utils.py +16 -10
- waldiez/io/ws.py +2 -2
- waldiez/models/agents/agent/agent.py +2 -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/handoff.py +2 -0
- waldiez/models/common/method_utils.py +2 -0
- waldiez/models/model/_llm.py +3 -0
- waldiez/models/tool/predefined/_email.py +3 -0
- waldiez/models/tool/predefined/_perplexity.py +1 -1
- waldiez/models/tool/predefined/_searxng.py +1 -1
- waldiez/models/tool/predefined/_wikipedia.py +1 -1
- waldiez/running/base_runner.py +81 -20
- waldiez/running/post_run.py +6 -0
- waldiez/running/pre_run.py +167 -45
- waldiez/running/standard_runner.py +5 -5
- waldiez/running/step_by_step/breakpoints_mixin.py +368 -44
- 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 +358 -41
- waldiez/running/step_by_step/step_by_step_runner.py +358 -353
- waldiez/running/subprocess_runner/__base__.py +4 -7
- waldiez/running/subprocess_runner/_async_runner.py +1 -1
- waldiez/running/subprocess_runner/_sync_runner.py +5 -4
- waldiez/running/subprocess_runner/runner.py +9 -0
- waldiez/running/utils.py +116 -2
- waldiez/ws/__init__.py +8 -7
- waldiez/ws/_file_handler.py +0 -2
- waldiez/ws/_mock.py +74 -0
- waldiez/ws/cli.py +27 -3
- waldiez/ws/client_manager.py +45 -29
- waldiez/ws/models.py +18 -1
- waldiez/ws/reloader.py +23 -2
- waldiez/ws/server.py +47 -8
- waldiez/ws/utils.py +29 -4
- {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/METADATA +53 -44
- {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/RECORD +62 -59
- {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/WHEEL +0 -0
- {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/entry_points.txt +0 -0
- {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/licenses/LICENSE +0 -0
- {waldiez-0.5.10.dist-info → waldiez-0.6.0.dist-info}/licenses/NOTICE.md +0 -0
waldiez/running/pre_run.py
CHANGED
|
@@ -7,12 +7,20 @@ 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
|
|
|
12
14
|
from waldiez.models import Waldiez
|
|
13
15
|
|
|
14
16
|
from .environment import in_virtualenv, is_root
|
|
15
|
-
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
|
+
)
|
|
16
24
|
|
|
17
25
|
|
|
18
26
|
class RequirementsMixin:
|
|
@@ -75,20 +83,12 @@ def install_requirements(
|
|
|
75
83
|
"""
|
|
76
84
|
requirements_string = ", ".join(extra_requirements)
|
|
77
85
|
printer(f"Installing requirements: {requirements_string}")
|
|
78
|
-
|
|
79
|
-
break_system_packages =
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
break_system_packages = os.environ.get("PIP_BREAK_SYSTEM_PACKAGES", "")
|
|
85
|
-
os.environ["PIP_BREAK_SYSTEM_PACKAGES"] = "1"
|
|
86
|
-
if not is_root():
|
|
87
|
-
pip_install.append("--user")
|
|
88
|
-
if upgrade: # pragma: no cover
|
|
89
|
-
pip_install.append("--upgrade")
|
|
90
|
-
pip_install.extend(extra_requirements)
|
|
91
|
-
# 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
|
|
92
92
|
try:
|
|
93
93
|
with subprocess.Popen(
|
|
94
94
|
pip_install,
|
|
@@ -97,17 +97,26 @@ def install_requirements(
|
|
|
97
97
|
) as proc:
|
|
98
98
|
if proc.stdout: # pragma: no branch
|
|
99
99
|
for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
|
|
100
|
-
|
|
100
|
+
stripped_line = strip_ansi(line.strip())
|
|
101
|
+
if stripped_line: # Only print non-empty lines
|
|
102
|
+
printer(stripped_line)
|
|
101
103
|
if proc.stderr: # pragma: no branch
|
|
102
104
|
for line in io.TextIOWrapper(proc.stderr, encoding="utf-8"):
|
|
103
|
-
|
|
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}")
|
|
104
118
|
finally:
|
|
105
|
-
|
|
106
|
-
# restore the old env var
|
|
107
|
-
if break_system_packages:
|
|
108
|
-
os.environ["PIP_BREAK_SYSTEM_PACKAGES"] = break_system_packages
|
|
109
|
-
else:
|
|
110
|
-
del os.environ["PIP_BREAK_SYSTEM_PACKAGES"]
|
|
119
|
+
_after_pip(break_system_packages, install_location)
|
|
111
120
|
|
|
112
121
|
|
|
113
122
|
async def a_install_requirements(
|
|
@@ -126,34 +135,147 @@ async def a_install_requirements(
|
|
|
126
135
|
printer : Callable[..., None]
|
|
127
136
|
The printer function to use, defaults to print.
|
|
128
137
|
"""
|
|
138
|
+
pip_install, break_system_packages, install_location = _before_pip(
|
|
139
|
+
extra_requirements, upgrade=upgrade
|
|
140
|
+
)
|
|
129
141
|
requirements_string = ", ".join(extra_requirements)
|
|
130
142
|
printer(f"Installing requirements: {requirements_string}")
|
|
131
|
-
|
|
132
|
-
break_system_packages = ""
|
|
133
|
-
if not in_virtualenv(): # pragma: no cover
|
|
134
|
-
break_system_packages = os.environ.get("PIP_BREAK_SYSTEM_PACKAGES", "")
|
|
135
|
-
os.environ["PIP_BREAK_SYSTEM_PACKAGES"] = "1"
|
|
136
|
-
if not is_root():
|
|
137
|
-
pip_install.extend(["--user"])
|
|
138
|
-
if upgrade: # pragma: no cover
|
|
139
|
-
pip_install.append("--upgrade")
|
|
140
|
-
pip_install.extend(extra_requirements)
|
|
141
|
-
# pylint: disable=too-many-try-statements
|
|
143
|
+
# pylint: disable=too-many-try-statements,broad-exception-caught
|
|
142
144
|
try:
|
|
143
145
|
proc = await asyncio.create_subprocess_exec(
|
|
144
146
|
*pip_install,
|
|
145
147
|
stdout=asyncio.subprocess.PIPE,
|
|
146
148
|
stderr=asyncio.subprocess.PIPE,
|
|
147
149
|
)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
async for
|
|
153
|
-
|
|
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}")
|
|
154
173
|
finally:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
174
|
+
_after_pip(break_system_packages, install_location)
|
|
175
|
+
|
|
176
|
+
|
|
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.
|
|
182
|
+
|
|
183
|
+
Parameters
|
|
184
|
+
----------
|
|
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.
|
|
194
|
+
"""
|
|
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 = ""
|
|
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")
|
|
217
|
+
|
|
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
|
|
227
|
+
) -> None:
|
|
228
|
+
"""Restore environment variables after pip installation.
|
|
229
|
+
|
|
230
|
+
Parameters
|
|
231
|
+
----------
|
|
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.
|
|
260
|
+
"""
|
|
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
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
3
|
|
|
4
4
|
# pyright: reportUnknownMemberType=false, reportAttributeAccessIssue=false
|
|
5
|
-
# pylint: disable=duplicate-code
|
|
5
|
+
# pylint: disable=duplicate-code,too-few-public-methods
|
|
6
6
|
"""Run a waldiez flow.
|
|
7
7
|
|
|
8
8
|
The flow is first converted to an autogen flow with agents, chats, and tools.
|
|
@@ -59,9 +59,8 @@ class WaldiezStandardRunner(WaldiezBaseRunner):
|
|
|
59
59
|
self._event_count = 0
|
|
60
60
|
self._processed_events = 0
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def print(self, *args: Any, **kwargs: Any) -> None:
|
|
62
|
+
@staticmethod
|
|
63
|
+
def print(*args: Any, **kwargs: Any) -> None:
|
|
65
64
|
"""Print.
|
|
66
65
|
|
|
67
66
|
Parameters
|
|
@@ -71,7 +70,7 @@ class WaldiezStandardRunner(WaldiezBaseRunner):
|
|
|
71
70
|
**kwargs : Any
|
|
72
71
|
Keyword arguments to print.
|
|
73
72
|
"""
|
|
74
|
-
WaldiezBaseRunner.
|
|
73
|
+
WaldiezBaseRunner.print(*args, **kwargs)
|
|
75
74
|
|
|
76
75
|
# pylint: disable=unused-argument
|
|
77
76
|
def _run(
|
|
@@ -214,6 +213,7 @@ class WaldiezStandardRunner(WaldiezBaseRunner):
|
|
|
214
213
|
"workflow event processing (async)"
|
|
215
214
|
)
|
|
216
215
|
return []
|
|
216
|
+
# noinspection DuplicatedCode
|
|
217
217
|
if self.structured_io:
|
|
218
218
|
stream = StructuredIOStream(
|
|
219
219
|
uploads_root=uploads_root, is_async=True
|