waldiez 0.4.8__py3-none-any.whl → 0.4.11__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 (40) hide show
  1. waldiez/__init__.py +1 -2
  2. waldiez/_version.py +1 -1
  3. waldiez/cli.py +90 -96
  4. waldiez/exporter.py +64 -9
  5. waldiez/exporting/agent/extras/rag/chroma_extras.py +21 -9
  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 +26 -2
  17. waldiez/models/common/method_utils.py +1 -1
  18. waldiez/models/tool/tool.py +2 -1
  19. waldiez/runner.py +402 -332
  20. waldiez/running/__init__.py +6 -28
  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 +121 -0
  26. waldiez/running/pre_run.py +105 -0
  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/running/utils.py +134 -0
  31. waldiez/utils/__init__.py +2 -2
  32. waldiez/utils/version.py +49 -0
  33. {waldiez-0.4.8.dist-info → waldiez-0.4.11.dist-info}/METADATA +11 -11
  34. {waldiez-0.4.8.dist-info → waldiez-0.4.11.dist-info}/RECORD +38 -30
  35. waldiez/running/running.py +0 -388
  36. waldiez/utils/flaml_warnings.py +0 -17
  37. {waldiez-0.4.8.dist-info → waldiez-0.4.11.dist-info}/WHEEL +0 -0
  38. {waldiez-0.4.8.dist-info → waldiez-0.4.11.dist-info}/entry_points.txt +0 -0
  39. {waldiez-0.4.8.dist-info → waldiez-0.4.11.dist-info}/licenses/LICENSE +0 -0
  40. {waldiez-0.4.8.dist-info → waldiez-0.4.11.dist-info}/licenses/NOTICE.md +0 -0
waldiez/runner.py CHANGED
@@ -1,98 +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
- Callable,
22
- Optional,
23
- Set,
24
- Type,
25
- Union,
26
- )
17
+ from typing import TYPE_CHECKING, Union
27
18
 
28
- from .exporter import WaldiezExporter
29
- from .io import StructuredIOStream
30
19
  from .models.waldiez import Waldiez
31
20
  from .running import (
32
- a_chdir,
33
- a_install_requirements,
34
- after_run,
35
- before_run,
36
- chdir,
37
- get_printer,
38
- install_requirements,
39
- refresh_environment,
40
- reset_env_vars,
41
- set_env_vars,
21
+ WaldiezBaseRunner,
22
+ WaldiezImportRunner,
23
+ WaldiezSubprocessRunner,
42
24
  )
43
25
 
44
26
  if TYPE_CHECKING:
45
27
  from autogen import ChatResult # type: ignore
46
28
 
47
29
 
48
- class WaldiezRunner:
30
+ class WaldiezRunner(WaldiezBaseRunner):
49
31
  """Waldiez runner class."""
50
32
 
33
+ _implementation: WaldiezBaseRunner
34
+
51
35
  def __init__(
52
- 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,
53
44
  ) -> None:
54
- """Initialize the Waldiez manager."""
55
- self._waldiez = waldiez
56
- self._running = False
57
- self._file_path = file_path
58
- self._exporter = WaldiezExporter(waldiez)
59
- 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
+ )
60
104
 
61
105
  @classmethod
62
106
  def load(
63
107
  cls,
64
- waldiez_file: Union[str, Path],
65
- name: Optional[str] = None,
66
- description: Optional[str] = None,
67
- tags: Optional[list[str]] = None,
68
- 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,
69
119
  ) -> "WaldiezRunner":
70
- """Create a WaldiezRunner instance from a file.
120
+ """Load a waldiez flow from a file and create a runner.
71
121
 
72
122
  Parameters
73
123
  ----------
74
- waldiez_file : Union[str, Path]
75
- The file path.
76
- name : Optional[str], optional
77
- The name of the Waldiez, by default None.
78
- description : Optional[str], optional
79
- The description of the Waldiez, by default None.
80
- tags : Optional[list[str]], optional
81
- The tags of the Waldiez, by default None.
82
- requirements : Optional[list[str]], optional
83
- 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.
84
154
 
85
155
  Returns
86
156
  -------
87
- WaldiezRunner
88
- The Waldiez runner instance.
89
-
90
- Raises
91
- ------
92
- FileNotFoundError
93
- If the file is not found.
94
- RuntimeError
95
- If the file is not a valid Waldiez file.
157
+ WaldiezBaseRunner
158
+ The runner instance that will execute the flow.
96
159
  """
97
160
  waldiez = Waldiez.load(
98
161
  waldiez_file,
@@ -101,326 +164,333 @@ class WaldiezRunner:
101
164
  tags=tags,
102
165
  requirements=requirements,
103
166
  )
104
- return cls(waldiez, file_path=waldiez_file)
105
-
106
- def __enter__(
107
- self,
108
- ) -> "WaldiezRunner":
109
- """Enter the context manager."""
110
- 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
+ )
111
176
 
112
- async def __aenter__(
177
+ def _before_run(
113
178
  self,
114
- ) -> "WaldiezRunner":
115
- """Enter the context manager asynchronously."""
116
- return self
179
+ output_file: Path,
180
+ uploads_root: Path | None,
181
+ ) -> Path:
182
+ """Actions to perform before running the flow.
117
183
 
118
- def __exit__(
119
- self,
120
- exc_type: Type[BaseException],
121
- exc_value: BaseException,
122
- traceback: TracebackType,
123
- ) -> None:
124
- """Exit the context manager."""
125
- if self._running:
126
- 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
+ )
127
195
 
128
- async def __aexit__(
196
+ async def _a_before_run(
129
197
  self,
130
- exc_type: Type[BaseException],
131
- exc_value: BaseException,
132
- traceback: TracebackType,
133
- ) -> None:
134
- """Exit the context manager asynchronously."""
135
- if self._running:
136
- self._running = False
137
-
138
- @property
139
- def waldiez(self) -> Waldiez:
140
- """Get the Waldiez instance."""
141
- return self._waldiez
142
-
143
- @property
144
- def is_async(self) -> bool:
145
- """Check if the workflow is async."""
146
- return self.waldiez.is_async
198
+ output_file: Path,
199
+ uploads_root: Path | None,
200
+ ) -> Path:
201
+ """Asynchronously perform actions before running the flow.
147
202
 
148
- @property
149
- def running(self) -> bool:
150
- """Get the running status."""
151
- return self._running
152
-
153
- def gather_requirements(self) -> Set[str]:
154
- """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.
155
209
 
156
210
  Returns
157
211
  -------
158
- Set[str]
159
- The extra requirements.
212
+ Path
213
+ The path to the temporary directory created for the run.
160
214
  """
161
- extra_requirements = {
162
- req for req in self.waldiez.requirements if req not in sys.modules
163
- }
164
- return extra_requirements
165
-
166
- def install_requirements(self) -> None:
167
- """Install the requirements for the flow."""
168
- self._called_install_requirements = True
169
- printer = get_printer()
170
- extra_requirements = self.gather_requirements()
171
- if extra_requirements:
172
- install_requirements(extra_requirements, printer)
173
-
174
- async def a_install_requirements(self) -> None:
175
- """Install the requirements for the flow asynchronously."""
176
- self._called_install_requirements = True
177
- printer = get_printer()
178
- extra_requirements = self.gather_requirements()
179
- if extra_requirements:
180
- await a_install_requirements(extra_requirements, printer)
181
-
182
- def _before_run(
183
- self,
184
- temp_dir: Path,
185
- file_name: str,
186
- module_name: str,
187
- printer: Callable[..., None],
188
- ) -> tuple[ModuleType, dict[str, str]]:
189
- self._exporter.export(Path(file_name))
190
- # unique_names = self._exporter.context.get_unique_names()
191
- spec = importlib.util.spec_from_file_location(
192
- module_name, temp_dir / file_name
215
+ return await self._implementation._a_before_run(
216
+ output_file, uploads_root
193
217
  )
194
- if not spec or not spec.loader:
195
- raise ImportError("Could not import the flow")
196
- sys.path.insert(0, str(temp_dir))
197
- old_vars = set_env_vars(self.waldiez.get_flow_env_vars())
198
- module = importlib.util.module_from_spec(spec)
199
- spec.loader.exec_module(module)
200
- printer("<Waldiez> - Starting workflow...")
201
- printer(self.waldiez.info.model_dump_json())
202
- return module, old_vars
203
218
 
204
219
  def _run(
205
220
  self,
206
- output_path: Optional[Union[str, Path]],
207
- uploads_root: Optional[Union[str, Path]],
208
- use_structured_io: bool = False,
221
+ temp_dir: Path,
222
+ output_file: Path,
223
+ uploads_root: Path | None,
209
224
  skip_mmd: bool = False,
210
- ) -> Union["ChatResult", list["ChatResult"], dict[int, "ChatResult"]]:
211
- """Run the Waldiez workflow.
225
+ ) -> Union[
226
+ "ChatResult",
227
+ list["ChatResult"],
228
+ dict[int, "ChatResult"],
229
+ ]:
230
+ """Run the flow.
212
231
 
213
232
  Parameters
214
233
  ----------
215
- output_path : Optional[Union[str, Path]]
216
- The output path.
217
- 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
218
239
  The runtime uploads root.
219
- use_structured_io : bool
220
- Whether to use structured IO instead of the default 'input/print'.
221
240
  skip_mmd : bool
222
- Whether to skip the Mermaid diagram generation.
241
+ Whether to skip generating the mermaid diagram.
223
242
 
224
243
  Returns
225
244
  -------
226
- Union[ChatResult, list[ChatResult]]
227
- 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.
228
249
  """
229
- temp_dir = Path(tempfile.mkdtemp())
230
- file_name = before_run(output_path, uploads_root)
231
- module_name = file_name.replace(".py", "")
232
- if not self._called_install_requirements:
233
- self.install_requirements()
234
- refresh_environment()
235
- printer = get_printer()
236
- printer(
237
- "Requirements installed.\n"
238
- "NOTE: If new packages were added and you are using Jupyter, "
239
- "you might need to restart the kernel."
240
- )
241
- results: Union[
242
- "ChatResult", list["ChatResult"], dict[int, "ChatResult"]
243
- ] = []
244
- with chdir(to=temp_dir):
245
- module, old_vars = self._before_run(
246
- temp_dir=temp_dir,
247
- file_name=file_name,
248
- module_name=module_name,
249
- printer=printer,
250
- )
251
- if use_structured_io:
252
- stream = StructuredIOStream(
253
- timeout=120, # 2 minutes
254
- uploads_root=uploads_root,
255
- )
256
- with StructuredIOStream.set_default(stream):
257
- results = module.main()
258
- else:
259
- results = module.main()
260
- printer("<Waldiez> - Workflow finished")
261
- sys.path.pop(0)
262
- reset_env_vars(old_vars)
263
- after_run(
250
+ return self._implementation._run(
264
251
  temp_dir=temp_dir,
265
- output_path=output_path,
266
- printer=printer,
267
- flow_name=self.waldiez.name,
252
+ output_file=output_file,
253
+ uploads_root=uploads_root,
268
254
  skip_mmd=skip_mmd,
269
255
  )
270
- gc.collect()
271
- refresh_environment()
272
- return results
273
256
 
274
257
  async def _a_run(
275
258
  self,
276
- output_path: Optional[Union[str, Path]],
277
- uploads_root: Optional[Union[str, Path]],
278
- use_structured_io: bool = False,
279
- skip_mmd: bool = False,
280
- ) -> Union["ChatResult", list["ChatResult"], dict[int, "ChatResult"]]:
281
- """Run the Waldiez workflow asynchronously."""
282
- temp_dir = Path(tempfile.mkdtemp())
283
- file_name = before_run(output_path, uploads_root)
284
- module_name = file_name.replace(".py", "")
285
- if not self._called_install_requirements:
286
- await self.a_install_requirements()
287
- refresh_environment()
288
- printer = get_printer()
289
- printer(
290
- "Requirements installed.\n"
291
- "NOTE: If new packages were added and you are using Jupyter, "
292
- "you might need to restart the kernel."
293
- )
294
- results: Union[
295
- "ChatResult", list["ChatResult"], dict[int, "ChatResult"]
296
- ] = []
297
- async with a_chdir(to=temp_dir):
298
- module, old_vars = self._before_run(
299
- temp_dir=temp_dir,
300
- file_name=file_name,
301
- module_name=module_name,
302
- printer=printer,
303
- )
304
- if use_structured_io:
305
- stream = StructuredIOStream(
306
- timeout=120, # 2 minutes
307
- uploads_root=uploads_root,
308
- )
309
- with StructuredIOStream.set_default(stream):
310
- results = await module.main()
311
- else:
312
- results = await module.main()
313
- sys.path.pop(0)
314
- reset_env_vars(old_vars)
315
- 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(
316
289
  temp_dir=temp_dir,
317
- output_path=output_path,
318
- printer=printer,
319
- flow_name=self.waldiez.name,
290
+ output_file=output_file,
291
+ uploads_root=uploads_root,
320
292
  skip_mmd=skip_mmd,
321
293
  )
322
- gc.collect()
323
- refresh_environment()
324
- return results
325
294
 
326
- def run(
295
+ def _after_run(
327
296
  self,
328
- output_path: Optional[Union[str, Path]] = None,
329
- uploads_root: Optional[Union[str, Path]] = None,
330
- 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,
331
375
  skip_mmd: bool = False,
332
- ) -> Union["ChatResult", list["ChatResult"], dict[int, "ChatResult"]]:
333
- """Run the Waldiez workflow.
376
+ ) -> None:
377
+ """Start the flow.
334
378
 
335
379
  Parameters
336
380
  ----------
337
- output_path : Optional[Union[str, Path]], optional
381
+ output_path : str | Path | None
338
382
  The output path, by default None.
339
- uploads_root : Optional[Union[str, Path]], optional
340
- The uploads root, to get user-uploaded files, by default None.
341
- use_structured_io : bool, optional
342
- Whether to use structured IO instead of the default 'input/print',
343
- by default False.
344
- skip_mmd : bool, optional
345
- 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
+ )
346
400
 
347
- Returns
348
- -------
349
- Union["ChatResult", list["ChatResult"], dict[int, "ChatResult"]]
350
- 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.
351
409
 
352
- Raises
353
- ------
354
- RuntimeError
355
- 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.
356
418
  """
357
- if self.waldiez.is_async:
358
- # pylint: disable=import-outside-toplevel
359
- from anyio.from_thread import start_blocking_portal
360
-
361
- with start_blocking_portal(backend="asyncio") as portal:
362
- return portal.call(
363
- self._a_run,
364
- output_path,
365
- uploads_root,
366
- use_structured_io,
367
- skip_mmd,
368
- )
369
- if self._running is True:
370
- raise RuntimeError("Workflow already running")
371
- self._running = True
372
- file_path = output_path or self._file_path
373
- try:
374
- return self._run(
375
- file_path,
376
- uploads_root=uploads_root,
377
- use_structured_io=use_structured_io,
378
- skip_mmd=skip_mmd,
379
- )
380
- finally:
381
- 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
+ )
382
425
 
383
- async def a_run(
426
+ async def a_start(
384
427
  self,
385
- output_path: Optional[Union[str, Path]] = None,
386
- uploads_root: Optional[Union[str, Path]] = None,
387
- 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,
388
432
  skip_mmd: bool = False,
389
- ) -> Union["ChatResult", list["ChatResult"], dict[int, "ChatResult"]]:
390
- """Run the Waldiez workflow asynchronously.
433
+ ) -> None:
434
+ """Asynchronously start the flow.
391
435
 
392
436
  Parameters
393
437
  ----------
394
- output_path : Optional[Union[str, Path]], optional
438
+ output_path : str | Path | None
395
439
  The output path, by default None.
396
- uploads_root : Optional[Union[str, Path]], optional
397
- The uploads root, to get user-uploaded files, by default None.
398
- use_structured_io : bool, optional
399
- Whether to use structured IO instead of the default 'input/print',
400
- by default False.
401
- skip_mmd : bool, optional
402
- 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
+ )
403
456
 
404
- Returns
405
- -------
406
- Union[ChatResult, list[ChatResult]], dict[int, ChatResult]
407
- 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.
408
465
 
409
- Raises
410
- ------
411
- RuntimeError
412
- 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.
413
476
  """
414
- if self._running is True:
415
- raise RuntimeError("Workflow already running")
416
- self._running = True
417
- file_path = output_path or self._file_path
418
- try:
419
- return await self._a_run(
420
- file_path,
421
- uploads_root=uploads_root,
422
- use_structured_io=use_structured_io,
423
- skip_mmd=skip_mmd,
424
- )
425
- finally:
426
- 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()