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.

Files changed (43) hide show
  1. waldiez/__init__.py +1 -2
  2. waldiez/_version.py +1 -1
  3. waldiez/cli.py +65 -58
  4. waldiez/exporter.py +64 -9
  5. waldiez/exporting/agent/extras/group_manager_agent_extas.py +1 -1
  6. waldiez/exporting/core/context.py +12 -0
  7. waldiez/exporting/core/extras/flow_extras.py +2 -14
  8. waldiez/exporting/core/types.py +21 -0
  9. waldiez/exporting/flow/exporter.py +4 -0
  10. waldiez/exporting/flow/factory.py +16 -0
  11. waldiez/exporting/flow/orchestrator.py +12 -0
  12. waldiez/exporting/flow/utils/__init__.py +2 -0
  13. waldiez/exporting/flow/utils/common.py +96 -2
  14. waldiez/exporting/flow/utils/logging.py +5 -6
  15. waldiez/io/mqtt.py +7 -3
  16. waldiez/io/structured.py +5 -1
  17. waldiez/models/common/method_utils.py +1 -1
  18. waldiez/models/tool/tool.py +2 -1
  19. waldiez/runner.py +402 -321
  20. waldiez/running/__init__.py +6 -34
  21. waldiez/running/base_runner.py +907 -0
  22. waldiez/running/environment.py +74 -0
  23. waldiez/running/import_runner.py +424 -0
  24. waldiez/running/patch_io_stream.py +208 -0
  25. waldiez/running/post_run.py +26 -24
  26. waldiez/running/pre_run.py +2 -46
  27. waldiez/running/protocol.py +281 -0
  28. waldiez/running/run_results.py +22 -0
  29. waldiez/running/subprocess_runner.py +100 -0
  30. waldiez/utils/__init__.py +0 -4
  31. waldiez/utils/version.py +4 -2
  32. {waldiez-0.4.9.dist-info → waldiez-0.5.0.dist-info}/METADATA +39 -113
  33. {waldiez-0.4.9.dist-info → waldiez-0.5.0.dist-info}/RECORD +42 -37
  34. waldiez/utils/flaml_warnings.py +0 -17
  35. /waldiez/{utils/cli_extras → cli_extras}/__init__.py +0 -0
  36. /waldiez/{utils/cli_extras → cli_extras}/jupyter.py +0 -0
  37. /waldiez/{utils/cli_extras → cli_extras}/runner.py +0 -0
  38. /waldiez/{utils/cli_extras → cli_extras}/studio.py +0 -0
  39. /waldiez/running/{util.py → utils.py} +0 -0
  40. {waldiez-0.4.9.dist-info → waldiez-0.5.0.dist-info}/WHEEL +0 -0
  41. {waldiez-0.4.9.dist-info → waldiez-0.5.0.dist-info}/entry_points.txt +0 -0
  42. {waldiez-0.4.9.dist-info → waldiez-0.5.0.dist-info}/licenses/LICENSE +0 -0
  43. {waldiez-0.4.9.dist-info → waldiez-0.5.0.dist-info}/licenses/NOTICE.md +0 -0
waldiez/runner.py CHANGED
@@ -1,96 +1,161 @@
1
1
  # SPDX-License-Identifier: Apache-2.0.
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+
4
+ # pylint: disable=protected-access,too-many-arguments
5
+ # pylint: disable=too-many-positional-arguments
3
6
  """Run a waldiez flow.
4
7
 
5
8
  The flow is first converted to an autogen flow with agents, chats, and tools.
6
- We then chown to temporary directory, call the flow's `main()` and
7
- return the results. Before running the flow, any additional environment
9
+ We then chown to temporary directory and:
10
+ either import and call the flow's `main()` (if not isolated),
11
+ or run the flow in a subprocess (if isolated).
12
+ Before running the flow, any additional environment
8
13
  variables specified in the waldiez file are set.
9
14
  """
10
15
 
11
- # pylint: disable=import-outside-toplevel,reimported
12
-
13
- import gc
14
- import importlib.util
15
- import sys
16
- import tempfile
17
16
  from pathlib import Path
18
- from types import ModuleType, TracebackType
19
- from typing import (
20
- TYPE_CHECKING,
21
- Optional,
22
- Set,
23
- Type,
24
- Union,
25
- )
17
+ from typing import TYPE_CHECKING, Union
26
18
 
27
- from .exporter import WaldiezExporter
28
- from .io import StructuredIOStream
29
19
  from .models.waldiez import Waldiez
30
20
  from .running import (
31
- a_chdir,
32
- a_install_requirements,
33
- after_run,
34
- before_run,
35
- chdir,
36
- install_requirements,
37
- refresh_environment,
38
- reset_env_vars,
39
- set_env_vars,
21
+ WaldiezBaseRunner,
22
+ WaldiezImportRunner,
23
+ WaldiezSubprocessRunner,
40
24
  )
41
25
 
42
26
  if TYPE_CHECKING:
43
27
  from autogen import ChatResult # type: ignore
44
28
 
45
29
 
46
- class WaldiezRunner:
30
+ class WaldiezRunner(WaldiezBaseRunner):
47
31
  """Waldiez runner class."""
48
32
 
33
+ _implementation: WaldiezBaseRunner
34
+
49
35
  def __init__(
50
- self, waldiez: Waldiez, file_path: Optional[Union[str, Path]] = None
36
+ self,
37
+ waldiez: Waldiez,
38
+ output_path: str | Path | None = None,
39
+ uploads_root: str | Path | None = None,
40
+ structured_io: bool = False,
41
+ isolated: bool = False,
42
+ threaded: bool = False,
43
+ skip_patch_io: bool = True,
51
44
  ) -> None:
52
- """Initialize the Waldiez manager."""
53
- self._waldiez = waldiez
54
- self._running = False
55
- self._file_path = file_path
56
- self._exporter = WaldiezExporter(waldiez)
57
- self._called_install_requirements = False
45
+ """Create a new Waldiez runner.
46
+
47
+ Parameters
48
+ ----------
49
+ waldiez : Waldiez
50
+ The waldiez flow to run.
51
+ output_path : str | Path | None, optional
52
+ The path to the output directory where the results will be stored.
53
+ If None, a temporary directory will be used.
54
+ uploads_root : str | Path | None, optional
55
+ The root directory for uploads. If None, the default uploads
56
+ directory will be used.
57
+ structured_io : bool, optional
58
+ If True, the flow will use
59
+ structured IO instead of the default 'input/print'.
60
+ isolated : bool, optional
61
+ If True, the flow will be run in an isolated subprocess.
62
+ Defaults to False.
63
+ threaded : bool, optional
64
+ If True, the flow will be run in a threaded manner.
65
+ Defaults to False.
66
+ skip_patch_io : bool, optional
67
+ If True, the IO patching will be skipped.
68
+ Defaults to True.
69
+
70
+ Returns
71
+ -------
72
+ WaldiezBaseRunner
73
+ The runner instance that will execute the flow.
74
+ """
75
+ super().__init__(
76
+ waldiez,
77
+ output_path=output_path,
78
+ uploads_root=uploads_root,
79
+ structured_io=structured_io,
80
+ isolated=isolated,
81
+ threaded=threaded,
82
+ skip_patch_io=skip_patch_io,
83
+ )
84
+ if isolated:
85
+ self._implementation = WaldiezSubprocessRunner(
86
+ waldiez,
87
+ output_path=output_path,
88
+ uploads_root=uploads_root,
89
+ structured_io=structured_io,
90
+ isolated=True,
91
+ threaded=threaded,
92
+ skip_patch_io=skip_patch_io,
93
+ )
94
+ else:
95
+ self._implementation = WaldiezImportRunner(
96
+ waldiez,
97
+ output_path=output_path,
98
+ uploads_root=uploads_root,
99
+ structured_io=structured_io,
100
+ isolated=False,
101
+ threaded=threaded,
102
+ skip_patch_io=skip_patch_io,
103
+ )
58
104
 
59
105
  @classmethod
60
106
  def load(
61
107
  cls,
62
- waldiez_file: Union[str, Path],
63
- name: Optional[str] = None,
64
- description: Optional[str] = None,
65
- tags: Optional[list[str]] = None,
66
- requirements: Optional[list[str]] = None,
108
+ waldiez_file: str | Path,
109
+ name: str | None = None,
110
+ description: str | None = None,
111
+ tags: list[str] | None = None,
112
+ requirements: list[str] | None = None,
113
+ output_path: str | Path | None = None,
114
+ uploads_root: str | Path | None = None,
115
+ structured_io: bool = False,
116
+ isolated: bool = False,
117
+ threaded: bool = False,
118
+ skip_patch_io: bool = True,
67
119
  ) -> "WaldiezRunner":
68
- """Create a WaldiezRunner instance from a file.
120
+ """Load a waldiez flow from a file and create a runner.
69
121
 
70
122
  Parameters
71
123
  ----------
72
- waldiez_file : Union[str, Path]
73
- The file path.
74
- name : Optional[str], optional
75
- The name of the Waldiez, by default None.
76
- description : Optional[str], optional
77
- The description of the Waldiez, by default None.
78
- tags : Optional[list[str]], optional
79
- The tags of the Waldiez, by default None.
80
- requirements : Optional[list[str]], optional
81
- The requirements of the Waldiez, by default None.
124
+ waldiez_file : str | Path
125
+ The path to the waldiez file.
126
+ name : str | None, optional
127
+ The name of the flow.
128
+ If None, the name from the waldiez file will be used.
129
+ description : str | None, optional
130
+ The description of the flow.
131
+ If None, the description from the waldiez file will be used.
132
+ tags : list[str] | None, optional
133
+ The tags for the flow. If None, no tags will be set.
134
+ requirements : list[str] | None, optional
135
+ The requirements for the flow. If None, no requirements will be set.
136
+ output_path : str | Path | None, optional
137
+ The path to the output directory where the results will be stored.
138
+ If None, a temporary directory will be used.
139
+ uploads_root : str | Path | None, optional
140
+ The root directory for uploads. If None, the default uploads
141
+ directory will be used.
142
+ structured_io : bool, optional
143
+ If True, the flow will use
144
+ structured IO instead of the default 'input/print'.
145
+ isolated : bool, optional
146
+ If True, the flow will be run in an isolated subprocess.
147
+ Defaults to False.
148
+ threaded : bool, optional
149
+ If True, the flow will be run in a threaded manner.
150
+ Defaults to False.
151
+ skip_patch_io : bool, optional
152
+ If True, the IO patching will be skipped.
153
+ Defaults to True.
82
154
 
83
155
  Returns
84
156
  -------
85
- WaldiezRunner
86
- The Waldiez runner instance.
87
-
88
- Raises
89
- ------
90
- FileNotFoundError
91
- If the file is not found.
92
- RuntimeError
93
- If the file is not a valid Waldiez file.
157
+ WaldiezBaseRunner
158
+ The runner instance that will execute the flow.
94
159
  """
95
160
  waldiez = Waldiez.load(
96
161
  waldiez_file,
@@ -99,317 +164,333 @@ class WaldiezRunner:
99
164
  tags=tags,
100
165
  requirements=requirements,
101
166
  )
102
- return cls(waldiez, file_path=waldiez_file)
103
-
104
- def __enter__(
105
- self,
106
- ) -> "WaldiezRunner":
107
- """Enter the context manager."""
108
- return self
167
+ return cls(
168
+ waldiez,
169
+ output_path=output_path,
170
+ uploads_root=uploads_root,
171
+ structured_io=structured_io,
172
+ isolated=isolated,
173
+ threaded=threaded,
174
+ skip_patch_io=skip_patch_io,
175
+ )
109
176
 
110
- async def __aenter__(
177
+ def _before_run(
111
178
  self,
112
- ) -> "WaldiezRunner":
113
- """Enter the context manager asynchronously."""
114
- return self
179
+ output_file: Path,
180
+ uploads_root: Path | None,
181
+ ) -> Path:
182
+ """Actions to perform before running the flow.
115
183
 
116
- def __exit__(
117
- self,
118
- exc_type: Type[BaseException],
119
- exc_value: BaseException,
120
- traceback: TracebackType,
121
- ) -> None:
122
- """Exit the context manager."""
123
- if self._running:
124
- self._running = False
184
+ Parameters
185
+ ----------
186
+ output_file : Path
187
+ The output file.
188
+ uploads_root : Path | None
189
+ The runtime uploads root.
190
+ """
191
+ return self._implementation._before_run(
192
+ output_file=output_file,
193
+ uploads_root=uploads_root,
194
+ )
125
195
 
126
- async def __aexit__(
196
+ async def _a_before_run(
127
197
  self,
128
- exc_type: Type[BaseException],
129
- exc_value: BaseException,
130
- traceback: TracebackType,
131
- ) -> None:
132
- """Exit the context manager asynchronously."""
133
- if self._running:
134
- self._running = False
135
-
136
- @property
137
- def waldiez(self) -> Waldiez:
138
- """Get the Waldiez instance."""
139
- return self._waldiez
140
-
141
- @property
142
- def is_async(self) -> bool:
143
- """Check if the workflow is async."""
144
- return self.waldiez.is_async
198
+ output_file: Path,
199
+ uploads_root: Path | None,
200
+ ) -> Path:
201
+ """Asynchronously perform actions before running the flow.
145
202
 
146
- @property
147
- def running(self) -> bool:
148
- """Get the running status."""
149
- return self._running
150
-
151
- def gather_requirements(self) -> Set[str]:
152
- """Gather extra requirements to install before running the flow.
203
+ Parameters
204
+ ----------
205
+ output_file : str | Path
206
+ The output file.
207
+ uploads_root : Path | None
208
+ The runtime uploads root.
153
209
 
154
210
  Returns
155
211
  -------
156
- Set[str]
157
- The extra requirements.
212
+ Path
213
+ The path to the temporary directory created for the run.
158
214
  """
159
- extra_requirements = {
160
- req for req in self.waldiez.requirements if req not in sys.modules
161
- }
162
- return extra_requirements
163
-
164
- def install_requirements(self) -> None:
165
- """Install the requirements for the flow."""
166
- self._called_install_requirements = True
167
- extra_requirements = self.gather_requirements()
168
- if extra_requirements:
169
- install_requirements(extra_requirements)
170
-
171
- async def a_install_requirements(self) -> None:
172
- """Install the requirements for the flow asynchronously."""
173
- self._called_install_requirements = True
174
- extra_requirements = self.gather_requirements()
175
- if extra_requirements:
176
- await a_install_requirements(extra_requirements)
177
-
178
- def _before_run(
179
- self,
180
- temp_dir: Path,
181
- file_name: str,
182
- module_name: str,
183
- ) -> tuple[ModuleType, dict[str, str]]:
184
- self._exporter.export(Path(file_name))
185
- # unique_names = self._exporter.context.get_unique_names()
186
- spec = importlib.util.spec_from_file_location(
187
- module_name, temp_dir / file_name
215
+ return await self._implementation._a_before_run(
216
+ output_file, uploads_root
188
217
  )
189
- if not spec or not spec.loader:
190
- raise ImportError("Could not import the flow")
191
- sys.path.insert(0, str(temp_dir))
192
- old_vars = set_env_vars(self.waldiez.get_flow_env_vars())
193
- module = importlib.util.module_from_spec(spec)
194
- spec.loader.exec_module(module)
195
- print("<Waldiez> - Starting workflow...")
196
- print(self.waldiez.info.model_dump_json())
197
- return module, old_vars
198
218
 
199
219
  def _run(
200
220
  self,
201
- output_path: Optional[Union[str, Path]],
202
- uploads_root: Optional[Union[str, Path]],
203
- use_structured_io: bool = False,
221
+ temp_dir: Path,
222
+ output_file: Path,
223
+ uploads_root: Path | None,
204
224
  skip_mmd: bool = False,
205
- ) -> Union["ChatResult", list["ChatResult"], dict[int, "ChatResult"]]:
206
- """Run the Waldiez workflow.
225
+ ) -> Union[
226
+ "ChatResult",
227
+ list["ChatResult"],
228
+ dict[int, "ChatResult"],
229
+ ]:
230
+ """Run the flow.
207
231
 
208
232
  Parameters
209
233
  ----------
210
- output_path : Optional[Union[str, Path]]
211
- The output path.
212
- uploads_root : Optional[Union[str, Path]]
234
+ temp_dir : Path
235
+ The path to the temporary directory created for the run.
236
+ output_file : Path
237
+ The output file.
238
+ uploads_root : Path | None
213
239
  The runtime uploads root.
214
- use_structured_io : bool
215
- Whether to use structured IO instead of the default 'input/print'.
216
240
  skip_mmd : bool
217
- Whether to skip the Mermaid diagram generation.
241
+ Whether to skip generating the mermaid diagram.
218
242
 
219
243
  Returns
220
244
  -------
221
- Union[ChatResult, list[ChatResult]]
222
- The result(s) of the chat(s).
245
+ ChatResult | list[ChatResult] | dict[int, ChatResult]
246
+ The result of the run, which can be a single ChatResult,
247
+ a list of ChatResults,
248
+ or a dictionary mapping indices to ChatResults.
223
249
  """
224
- temp_dir = Path(tempfile.mkdtemp())
225
- file_name = before_run(output_path, uploads_root)
226
- module_name = file_name.replace(".py", "")
227
- if not self._called_install_requirements:
228
- self.install_requirements()
229
- refresh_environment()
230
- print(
231
- "Requirements installed.\n"
232
- "NOTE: If new packages were added and you are using Jupyter, "
233
- "you might need to restart the kernel."
234
- )
235
- results: Union[
236
- "ChatResult", list["ChatResult"], dict[int, "ChatResult"]
237
- ] = []
238
- with chdir(to=temp_dir):
239
- module, old_vars = self._before_run(
240
- temp_dir=temp_dir,
241
- file_name=file_name,
242
- module_name=module_name,
243
- )
244
- if use_structured_io:
245
- stream = StructuredIOStream(
246
- timeout=120, # 2 minutes
247
- uploads_root=uploads_root,
248
- )
249
- with StructuredIOStream.set_default(stream):
250
- results = module.main()
251
- else:
252
- results = module.main()
253
- print("<Waldiez> - Workflow finished")
254
- sys.path.pop(0)
255
- reset_env_vars(old_vars)
256
- after_run(
250
+ return self._implementation._run(
257
251
  temp_dir=temp_dir,
258
- output_path=output_path,
259
- flow_name=self.waldiez.name,
252
+ output_file=output_file,
253
+ uploads_root=uploads_root,
260
254
  skip_mmd=skip_mmd,
261
255
  )
262
- gc.collect()
263
- refresh_environment()
264
- return results
265
256
 
266
257
  async def _a_run(
267
258
  self,
268
- output_path: Optional[Union[str, Path]],
269
- uploads_root: Optional[Union[str, Path]],
270
- use_structured_io: bool = False,
271
- skip_mmd: bool = False,
272
- ) -> Union["ChatResult", list["ChatResult"], dict[int, "ChatResult"]]:
273
- """Run the Waldiez workflow asynchronously."""
274
- temp_dir = Path(tempfile.mkdtemp())
275
- file_name = before_run(output_path, uploads_root)
276
- module_name = file_name.replace(".py", "")
277
- if not self._called_install_requirements:
278
- await self.a_install_requirements()
279
- refresh_environment()
280
- print(
281
- "Requirements installed.\n"
282
- "NOTE: If new packages were added and you are using Jupyter, "
283
- "you might need to restart the kernel."
284
- )
285
- results: Union[
286
- "ChatResult", list["ChatResult"], dict[int, "ChatResult"]
287
- ] = []
288
- async with a_chdir(to=temp_dir):
289
- module, old_vars = self._before_run(
290
- temp_dir=temp_dir,
291
- file_name=file_name,
292
- module_name=module_name,
293
- )
294
- if use_structured_io:
295
- stream = StructuredIOStream(
296
- timeout=120, # 2 minutes
297
- uploads_root=uploads_root,
298
- )
299
- with StructuredIOStream.set_default(stream):
300
- results = await module.main()
301
- else:
302
- results = await module.main()
303
- sys.path.pop(0)
304
- reset_env_vars(old_vars)
305
- after_run(
259
+ temp_dir: Path,
260
+ output_file: Path,
261
+ uploads_root: Path | None,
262
+ skip_mmd: bool,
263
+ ) -> Union[
264
+ "ChatResult",
265
+ list["ChatResult"],
266
+ dict[int, "ChatResult"],
267
+ ]: # pyright: ignore
268
+ """Asynchronously run the flow.
269
+
270
+ Parameters
271
+ ----------
272
+ temp_dir : Path
273
+ The path to the temporary directory created for the run.
274
+ output_file : Path
275
+ The output file.
276
+ uploads_root : Path | None
277
+ The runtime uploads root.
278
+ skip_mmd : bool
279
+ Whether to skip generating the mermaid diagram.
280
+
281
+ Returns
282
+ -------
283
+ Union[ChatResult, list[ChatResult], dict[int, ChatResult]]
284
+ The result of the run, which can be a single ChatResult,
285
+ a list of ChatResults,
286
+ or a dictionary mapping indices to ChatResults.
287
+ """
288
+ return await self._implementation._a_run(
306
289
  temp_dir=temp_dir,
307
- output_path=output_path,
308
- flow_name=self.waldiez.name,
290
+ output_file=output_file,
291
+ uploads_root=uploads_root,
309
292
  skip_mmd=skip_mmd,
310
293
  )
311
- gc.collect()
312
- refresh_environment()
313
- return results
314
294
 
315
- def run(
295
+ def _after_run(
316
296
  self,
317
- output_path: Optional[Union[str, Path]] = None,
318
- uploads_root: Optional[Union[str, Path]] = None,
319
- use_structured_io: bool = False,
297
+ results: Union[
298
+ "ChatResult",
299
+ list["ChatResult"],
300
+ dict[int, "ChatResult"],
301
+ ],
302
+ output_file: Path,
303
+ uploads_root: Path | None,
304
+ temp_dir: Path,
305
+ skip_mmd: bool,
306
+ ) -> None:
307
+ """Actions to perform after running the flow.
308
+
309
+ Parameters
310
+ ----------
311
+ results : Union[ChatResult, list[ChatResult], dict[int, ChatResult]]
312
+ The results of the run, which can be a single ChatResult,
313
+ a list of ChatResults,
314
+ or a dictionary mapping indices to ChatResults.
315
+ output_file : Path
316
+ The path to the output file.
317
+ uploads_root : Path | None
318
+ The runtime uploads root.
319
+ structured_io : bool
320
+ Whether to use structured IO instead of the default 'input/print'.
321
+ temp_dir : Path
322
+ The path to the temporary directory created for the run.
323
+ skip_mmd : bool
324
+ Whether to skip generating the mermaid diagram.
325
+ """
326
+ self._implementation._after_run(
327
+ results,
328
+ output_file,
329
+ uploads_root,
330
+ temp_dir,
331
+ skip_mmd,
332
+ )
333
+
334
+ async def _a_after_run(
335
+ self,
336
+ results: Union[
337
+ "ChatResult",
338
+ list["ChatResult"],
339
+ dict[int, "ChatResult"],
340
+ ],
341
+ output_file: Path,
342
+ uploads_root: Path | None,
343
+ temp_dir: Path,
344
+ skip_mmd: bool,
345
+ ) -> None:
346
+ """Asynchronously perform actions after running the flow.
347
+
348
+ Parameters
349
+ ----------
350
+ output_file : Path
351
+ The path to the output file.
352
+ uploads_root : Path | None
353
+ The runtime uploads root.
354
+ structured_io : bool
355
+ Whether to use structured IO instead of the default 'input/print'.
356
+ temp_dir : Path
357
+ The path to the temporary directory created for the run.
358
+ skip_mmd : bool
359
+ Whether to skip generating the mermaid diagram.
360
+ """
361
+ await self._implementation._a_after_run(
362
+ results,
363
+ output_file,
364
+ uploads_root,
365
+ temp_dir,
366
+ skip_mmd,
367
+ )
368
+
369
+ def start(
370
+ self,
371
+ output_path: str | Path | None,
372
+ uploads_root: str | Path | None,
373
+ structured_io: bool | None = None,
374
+ skip_patch_io: bool | None = None,
320
375
  skip_mmd: bool = False,
321
- ) -> Union["ChatResult", list["ChatResult"], dict[int, "ChatResult"]]:
322
- """Run the Waldiez workflow.
376
+ ) -> None:
377
+ """Start the flow.
323
378
 
324
379
  Parameters
325
380
  ----------
326
- output_path : Optional[Union[str, Path]], optional
381
+ output_path : str | Path | None
327
382
  The output path, by default None.
328
- uploads_root : Optional[Union[str, Path]], optional
329
- The uploads root, to get user-uploaded files, by default None.
330
- use_structured_io : bool, optional
331
- Whether to use structured IO instead of the default 'input/print',
332
- by default False.
333
- skip_mmd : bool, optional
334
- Whether to skip the Mermaid diagram generation, by default False.
383
+ uploads_root : str | Path | None
384
+ The runtime uploads root.
385
+ structured_io : bool | None
386
+ Whether to use structured IO instead of the default 'input/print'.
387
+ If None, it will use the value from the context.
388
+ skip_patch_io : bool | None = None
389
+ Whether to skip patching I/O, by default None.
390
+ If None, it will use the value from the context.
391
+ skip_mmd : bool = False
392
+ Whether to skip generating the mermaid diagram.
393
+ """
394
+ self._implementation.start(
395
+ output_path=output_path,
396
+ uploads_root=uploads_root,
397
+ structured_io=structured_io,
398
+ skip_patch_io=skip_patch_io,
399
+ )
335
400
 
336
- Returns
337
- -------
338
- Union["ChatResult", list["ChatResult"], dict[int, "ChatResult"]]
339
- The result(s) of the chat(s).
401
+ def _start(
402
+ self,
403
+ temp_dir: Path,
404
+ output_file: Path,
405
+ uploads_root: Path | None,
406
+ skip_mmd: bool,
407
+ ) -> None:
408
+ """Start the flow.
340
409
 
341
- Raises
342
- ------
343
- RuntimeError
344
- If the workflow is already running.
410
+ Parameters
411
+ ----------
412
+ output_file : Path
413
+ The output file.
414
+ uploads_root : Path | None
415
+ The runtime uploads root.
416
+ skip_mmd : bool
417
+ Whether to skip generating the mermaid diagram.
345
418
  """
346
- if self.waldiez.is_async:
347
- # pylint: disable=import-outside-toplevel
348
- from anyio.from_thread import start_blocking_portal
349
-
350
- with start_blocking_portal(backend="asyncio") as portal:
351
- return portal.call(
352
- self._a_run,
353
- output_path,
354
- uploads_root,
355
- use_structured_io,
356
- skip_mmd,
357
- )
358
- if self._running is True:
359
- raise RuntimeError("Workflow already running")
360
- self._running = True
361
- file_path = output_path or self._file_path
362
- try:
363
- return self._run(
364
- file_path,
365
- uploads_root=uploads_root,
366
- use_structured_io=use_structured_io,
367
- skip_mmd=skip_mmd,
368
- )
369
- finally:
370
- self._running = False
419
+ self._implementation._start(
420
+ temp_dir=temp_dir,
421
+ output_file=output_file,
422
+ uploads_root=uploads_root,
423
+ skip_mmd=skip_mmd,
424
+ )
371
425
 
372
- async def a_run(
426
+ async def a_start(
373
427
  self,
374
- output_path: Optional[Union[str, Path]] = None,
375
- uploads_root: Optional[Union[str, Path]] = None,
376
- use_structured_io: bool = False,
428
+ output_path: str | Path | None,
429
+ uploads_root: str | Path | None,
430
+ structured_io: bool | None = None,
431
+ skip_patch_io: bool | None = None,
377
432
  skip_mmd: bool = False,
378
- ) -> Union["ChatResult", list["ChatResult"], dict[int, "ChatResult"]]:
379
- """Run the Waldiez workflow asynchronously.
433
+ ) -> None:
434
+ """Asynchronously start the flow.
380
435
 
381
436
  Parameters
382
437
  ----------
383
- output_path : Optional[Union[str, Path]], optional
438
+ output_path : str | Path | None
384
439
  The output path, by default None.
385
- uploads_root : Optional[Union[str, Path]], optional
386
- The uploads root, to get user-uploaded files, by default None.
387
- use_structured_io : bool, optional
388
- Whether to use structured IO instead of the default 'input/print',
389
- by default False.
390
- skip_mmd : bool, optional
391
- Whether to skip the Mermaid diagram generation, by default False.
440
+ uploads_root : str | Path | None
441
+ The runtime uploads root.
442
+ structured_io : bool | None
443
+ Whether to use structured IO instead of the default 'input/print'.
444
+ skip_patch_io : bool | None = None
445
+ Whether to skip patching I/O, by default None.
446
+ skip_mmd : bool = False
447
+ Whether to skip generating the mermaid diagram, by default False.
448
+ """
449
+ await self._implementation.a_start(
450
+ output_path=output_path,
451
+ uploads_root=uploads_root,
452
+ structured_io=structured_io,
453
+ skip_patch_io=skip_patch_io,
454
+ skip_mmd=skip_mmd,
455
+ )
392
456
 
393
- Returns
394
- -------
395
- Union[ChatResult, list[ChatResult]], dict[int, ChatResult]
396
- The result(s) of the chat(s).
457
+ async def _a_start(
458
+ self,
459
+ temp_dir: Path,
460
+ output_file: Path,
461
+ uploads_root: Path | None,
462
+ skip_mmd: bool,
463
+ ) -> None:
464
+ """Asynchronously start the flow.
397
465
 
398
- Raises
399
- ------
400
- RuntimeError
401
- If the workflow is already running.
466
+ Parameters
467
+ ----------
468
+ temp_dir : Path
469
+ The path to the temporary directory created for the run.
470
+ output_file : Path
471
+ The output file.
472
+ uploads_root : Path | None
473
+ The runtime uploads root.
474
+ skip_mmd : bool
475
+ Whether to skip generating the mermaid diagram.
402
476
  """
403
- if self._running is True:
404
- raise RuntimeError("Workflow already running")
405
- self._running = True
406
- file_path = output_path or self._file_path
407
- try:
408
- return await self._a_run(
409
- file_path,
410
- uploads_root=uploads_root,
411
- use_structured_io=use_structured_io,
412
- skip_mmd=skip_mmd,
413
- )
414
- finally:
415
- self._running = False
477
+ await self._implementation._a_start(
478
+ temp_dir=temp_dir,
479
+ output_file=output_file,
480
+ uploads_root=uploads_root,
481
+ skip_mmd=skip_mmd,
482
+ )
483
+
484
+ def _stop(self) -> None:
485
+ """Actions to perform when stopping the flow.
486
+
487
+ This method should be overridden in subclasses if needed.
488
+ """
489
+ self._implementation._stop()
490
+
491
+ async def _a_stop(self) -> None:
492
+ """Asynchronously perform actions when stopping the flow.
493
+
494
+ This method should be overridden in subclasses if needed.
495
+ """
496
+ await self._implementation._a_stop()