waldiez 0.4.7__py3-none-any.whl → 0.4.8__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 (244) hide show
  1. waldiez/__init__.py +5 -5
  2. waldiez/_version.py +1 -1
  3. waldiez/cli.py +112 -73
  4. waldiez/exporter.py +61 -19
  5. waldiez/exporting/__init__.py +25 -6
  6. waldiez/exporting/agent/__init__.py +7 -3
  7. waldiez/exporting/agent/code_execution.py +114 -0
  8. waldiez/exporting/agent/exporter.py +354 -0
  9. waldiez/exporting/agent/extras/__init__.py +15 -0
  10. waldiez/exporting/agent/extras/captain_agent_extras.py +315 -0
  11. waldiez/exporting/agent/extras/group/target.py +178 -0
  12. waldiez/exporting/agent/extras/group_manager_agent_extas.py +500 -0
  13. waldiez/exporting/agent/extras/group_member_extras.py +181 -0
  14. waldiez/exporting/agent/extras/handoffs/__init__.py +19 -0
  15. waldiez/exporting/agent/extras/handoffs/after_work.py +78 -0
  16. waldiez/exporting/agent/extras/handoffs/available.py +74 -0
  17. waldiez/exporting/agent/extras/handoffs/condition.py +158 -0
  18. waldiez/exporting/agent/extras/handoffs/handoff.py +171 -0
  19. waldiez/exporting/agent/extras/handoffs/target.py +189 -0
  20. waldiez/exporting/agent/extras/rag/__init__.py +10 -0
  21. waldiez/exporting/agent/{utils/rag_user/chroma_utils.py → extras/rag/chroma_extras.py} +16 -15
  22. waldiez/exporting/agent/{utils/rag_user/mongo_utils.py → extras/rag/mongo_extras.py} +10 -10
  23. waldiez/exporting/agent/{utils/rag_user/pgvector_utils.py → extras/rag/pgvector_extras.py} +13 -13
  24. waldiez/exporting/agent/{utils/rag_user/qdrant_utils.py → extras/rag/qdrant_extras.py} +13 -13
  25. waldiez/exporting/agent/{utils/rag_user/vector_db.py → extras/rag/vector_db_extras.py} +59 -46
  26. waldiez/exporting/agent/extras/rag_user_proxy_agent_extras.py +245 -0
  27. waldiez/exporting/agent/extras/reasoning_agent_extras.py +88 -0
  28. waldiez/exporting/agent/factory.py +95 -0
  29. waldiez/exporting/agent/processor.py +150 -0
  30. waldiez/exporting/agent/system_message.py +36 -0
  31. waldiez/exporting/agent/termination.py +50 -0
  32. waldiez/exporting/chats/__init__.py +7 -3
  33. waldiez/exporting/chats/exporter.py +97 -0
  34. waldiez/exporting/chats/factory.py +65 -0
  35. waldiez/exporting/chats/processor.py +226 -0
  36. waldiez/exporting/chats/utils/__init__.py +6 -5
  37. waldiez/exporting/chats/utils/common.py +11 -45
  38. waldiez/exporting/chats/utils/group.py +55 -0
  39. waldiez/exporting/chats/utils/nested.py +37 -52
  40. waldiez/exporting/chats/utils/sequential.py +72 -61
  41. waldiez/exporting/chats/utils/{single_chat.py → single.py} +48 -50
  42. waldiez/exporting/core/__init__.py +196 -0
  43. waldiez/exporting/core/constants.py +17 -0
  44. waldiez/exporting/core/content.py +69 -0
  45. waldiez/exporting/core/context.py +244 -0
  46. waldiez/exporting/core/enums.py +89 -0
  47. waldiez/exporting/core/errors.py +19 -0
  48. waldiez/exporting/core/exporter.py +390 -0
  49. waldiez/exporting/core/exporters.py +67 -0
  50. waldiez/exporting/core/extras/__init__.py +39 -0
  51. waldiez/exporting/core/extras/agent_extras/__init__.py +27 -0
  52. waldiez/exporting/core/extras/agent_extras/captain_extras.py +57 -0
  53. waldiez/exporting/core/extras/agent_extras/group_manager_extras.py +102 -0
  54. waldiez/exporting/core/extras/agent_extras/rag_user_extras.py +53 -0
  55. waldiez/exporting/core/extras/agent_extras/reasoning_extras.py +68 -0
  56. waldiez/exporting/core/extras/agent_extras/standard_extras.py +263 -0
  57. waldiez/exporting/core/extras/base.py +241 -0
  58. waldiez/exporting/core/extras/chat_extras.py +118 -0
  59. waldiez/exporting/core/extras/flow_extras.py +70 -0
  60. waldiez/exporting/core/extras/model_extras.py +73 -0
  61. waldiez/exporting/core/extras/path_resolver.py +93 -0
  62. waldiez/exporting/core/extras/serializer.py +138 -0
  63. waldiez/exporting/core/extras/tool_extras.py +82 -0
  64. waldiez/exporting/core/protocols.py +259 -0
  65. waldiez/exporting/core/result.py +705 -0
  66. waldiez/exporting/core/types.py +329 -0
  67. waldiez/exporting/core/utils/__init__.py +11 -0
  68. waldiez/exporting/core/utils/comment.py +33 -0
  69. waldiez/exporting/core/utils/llm_config.py +117 -0
  70. waldiez/exporting/core/validation.py +96 -0
  71. waldiez/exporting/flow/__init__.py +6 -2
  72. waldiez/exporting/flow/execution_generator.py +193 -0
  73. waldiez/exporting/flow/exporter.py +107 -0
  74. waldiez/exporting/flow/factory.py +94 -0
  75. waldiez/exporting/flow/file_generator.py +214 -0
  76. waldiez/exporting/flow/merger.py +387 -0
  77. waldiez/exporting/flow/orchestrator.py +411 -0
  78. waldiez/exporting/flow/utils/__init__.py +9 -36
  79. waldiez/exporting/flow/utils/common.py +206 -0
  80. waldiez/exporting/flow/utils/importing.py +373 -0
  81. waldiez/exporting/flow/utils/linting.py +200 -0
  82. waldiez/exporting/flow/utils/{logging_utils.py → logging.py} +23 -9
  83. waldiez/exporting/models/__init__.py +3 -1
  84. waldiez/exporting/models/exporter.py +233 -0
  85. waldiez/exporting/models/factory.py +66 -0
  86. waldiez/exporting/models/processor.py +139 -0
  87. waldiez/exporting/tools/__init__.py +11 -0
  88. waldiez/exporting/tools/exporter.py +207 -0
  89. waldiez/exporting/tools/factory.py +57 -0
  90. waldiez/exporting/tools/processor.py +248 -0
  91. waldiez/exporting/tools/registration.py +133 -0
  92. waldiez/io/__init__.py +128 -0
  93. waldiez/io/_ws.py +199 -0
  94. waldiez/io/models/__init__.py +60 -0
  95. waldiez/io/models/base.py +66 -0
  96. waldiez/io/models/constants.py +78 -0
  97. waldiez/io/models/content/__init__.py +23 -0
  98. waldiez/io/models/content/audio.py +43 -0
  99. waldiez/io/models/content/base.py +45 -0
  100. waldiez/io/models/content/file.py +43 -0
  101. waldiez/io/models/content/image.py +96 -0
  102. waldiez/io/models/content/text.py +37 -0
  103. waldiez/io/models/content/video.py +43 -0
  104. waldiez/io/models/user_input.py +269 -0
  105. waldiez/io/models/user_response.py +215 -0
  106. waldiez/io/mqtt.py +681 -0
  107. waldiez/io/redis.py +782 -0
  108. waldiez/io/structured.py +419 -0
  109. waldiez/io/utils.py +184 -0
  110. waldiez/io/ws.py +298 -0
  111. waldiez/logger.py +481 -0
  112. waldiez/models/__init__.py +108 -51
  113. waldiez/models/agents/__init__.py +34 -70
  114. waldiez/models/agents/agent/__init__.py +10 -4
  115. waldiez/models/agents/agent/agent.py +466 -65
  116. waldiez/models/agents/agent/agent_data.py +119 -47
  117. waldiez/models/agents/agent/agent_type.py +13 -2
  118. waldiez/models/agents/agent/code_execution.py +12 -12
  119. waldiez/models/agents/agent/human_input_mode.py +8 -0
  120. waldiez/models/agents/agent/{linked_skill.py → linked_tool.py} +7 -7
  121. waldiez/models/agents/agent/nested_chat.py +35 -7
  122. waldiez/models/agents/agent/termination_message.py +30 -22
  123. waldiez/models/agents/{swarm_agent → agent}/update_system_message.py +22 -22
  124. waldiez/models/agents/agents.py +58 -63
  125. waldiez/models/agents/assistant/assistant.py +4 -4
  126. waldiez/models/agents/assistant/assistant_data.py +13 -1
  127. waldiez/models/agents/{captain_agent → captain}/captain_agent.py +5 -5
  128. waldiez/models/agents/{captain_agent → captain}/captain_agent_data.py +5 -5
  129. waldiez/models/agents/extra_requirements.py +11 -16
  130. waldiez/models/agents/group_manager/group_manager.py +103 -13
  131. waldiez/models/agents/group_manager/group_manager_data.py +36 -14
  132. waldiez/models/agents/group_manager/speakers.py +77 -24
  133. waldiez/models/agents/{rag_user → rag_user_proxy}/__init__.py +16 -16
  134. waldiez/models/agents/rag_user_proxy/rag_user_proxy.py +64 -0
  135. waldiez/models/agents/{rag_user/rag_user_data.py → rag_user_proxy/rag_user_proxy_data.py} +6 -5
  136. waldiez/models/agents/{rag_user → rag_user_proxy}/retrieve_config.py +182 -114
  137. waldiez/models/agents/{rag_user → rag_user_proxy}/vector_db_config.py +13 -13
  138. waldiez/models/agents/reasoning/reasoning_agent.py +6 -6
  139. waldiez/models/agents/reasoning/reasoning_agent_data.py +110 -63
  140. waldiez/models/agents/reasoning/reasoning_agent_reason_config.py +38 -10
  141. waldiez/models/agents/user_proxy/user_proxy.py +11 -7
  142. waldiez/models/agents/user_proxy/user_proxy_data.py +2 -2
  143. waldiez/models/chat/__init__.py +2 -1
  144. waldiez/models/chat/chat.py +166 -87
  145. waldiez/models/chat/chat_data.py +99 -136
  146. waldiez/models/chat/chat_message.py +33 -23
  147. waldiez/models/chat/chat_nested.py +31 -30
  148. waldiez/models/chat/chat_summary.py +10 -8
  149. waldiez/models/common/__init__.py +52 -2
  150. waldiez/models/common/ag2_version.py +1 -1
  151. waldiez/models/common/base.py +38 -7
  152. waldiez/models/common/dict_utils.py +42 -17
  153. waldiez/models/common/handoff.py +459 -0
  154. waldiez/models/common/id_generator.py +19 -0
  155. waldiez/models/common/method_utils.py +130 -68
  156. waldiez/{exporting/base/utils → models/common}/naming.py +38 -61
  157. waldiez/models/common/waldiez_version.py +37 -0
  158. waldiez/models/flow/__init__.py +9 -2
  159. waldiez/models/flow/connection.py +18 -0
  160. waldiez/models/flow/flow.py +311 -215
  161. waldiez/models/flow/flow_data.py +207 -40
  162. waldiez/models/flow/info.py +85 -0
  163. waldiez/models/flow/naming.py +131 -0
  164. waldiez/models/model/__init__.py +7 -1
  165. waldiez/models/model/extra_requirements.py +3 -12
  166. waldiez/models/model/model.py +76 -21
  167. waldiez/models/model/model_data.py +108 -20
  168. waldiez/models/tool/__init__.py +16 -0
  169. waldiez/models/tool/extra_requirements.py +36 -0
  170. waldiez/models/{skill/skill.py → tool/tool.py} +88 -88
  171. waldiez/models/tool/tool_data.py +51 -0
  172. waldiez/models/tool/tool_type.py +8 -0
  173. waldiez/models/waldiez.py +97 -80
  174. waldiez/runner.py +114 -49
  175. waldiez/running/__init__.py +1 -1
  176. waldiez/running/environment.py +49 -68
  177. waldiez/running/gen_seq_diagram.py +16 -14
  178. waldiez/running/running.py +53 -34
  179. waldiez/utils/__init__.py +0 -4
  180. waldiez/utils/cli_extras/jupyter.py +5 -3
  181. waldiez/utils/cli_extras/runner.py +6 -4
  182. waldiez/utils/cli_extras/studio.py +6 -4
  183. waldiez/utils/conflict_checker.py +15 -9
  184. waldiez/utils/flaml_warnings.py +5 -5
  185. {waldiez-0.4.7.dist-info → waldiez-0.4.8.dist-info}/METADATA +235 -91
  186. waldiez-0.4.8.dist-info/RECORD +200 -0
  187. waldiez/exporting/agent/agent_exporter.py +0 -297
  188. waldiez/exporting/agent/utils/__init__.py +0 -23
  189. waldiez/exporting/agent/utils/captain_agent.py +0 -263
  190. waldiez/exporting/agent/utils/code_execution.py +0 -65
  191. waldiez/exporting/agent/utils/group_manager.py +0 -220
  192. waldiez/exporting/agent/utils/rag_user/__init__.py +0 -7
  193. waldiez/exporting/agent/utils/rag_user/rag_user.py +0 -209
  194. waldiez/exporting/agent/utils/reasoning.py +0 -36
  195. waldiez/exporting/agent/utils/swarm_agent.py +0 -469
  196. waldiez/exporting/agent/utils/teachability.py +0 -41
  197. waldiez/exporting/agent/utils/termination_message.py +0 -44
  198. waldiez/exporting/base/__init__.py +0 -25
  199. waldiez/exporting/base/agent_position.py +0 -75
  200. waldiez/exporting/base/base_exporter.py +0 -118
  201. waldiez/exporting/base/export_position.py +0 -48
  202. waldiez/exporting/base/import_position.py +0 -23
  203. waldiez/exporting/base/mixin.py +0 -137
  204. waldiez/exporting/base/utils/__init__.py +0 -18
  205. waldiez/exporting/base/utils/comments.py +0 -96
  206. waldiez/exporting/base/utils/path_check.py +0 -68
  207. waldiez/exporting/base/utils/to_string.py +0 -84
  208. waldiez/exporting/chats/chats_exporter.py +0 -240
  209. waldiez/exporting/chats/utils/swarm.py +0 -210
  210. waldiez/exporting/flow/flow_exporter.py +0 -528
  211. waldiez/exporting/flow/utils/agent_utils.py +0 -204
  212. waldiez/exporting/flow/utils/chat_utils.py +0 -71
  213. waldiez/exporting/flow/utils/def_main.py +0 -77
  214. waldiez/exporting/flow/utils/flow_content.py +0 -202
  215. waldiez/exporting/flow/utils/flow_names.py +0 -116
  216. waldiez/exporting/flow/utils/importing_utils.py +0 -227
  217. waldiez/exporting/models/models_exporter.py +0 -199
  218. waldiez/exporting/models/utils.py +0 -174
  219. waldiez/exporting/skills/__init__.py +0 -9
  220. waldiez/exporting/skills/skills_exporter.py +0 -176
  221. waldiez/exporting/skills/utils.py +0 -369
  222. waldiez/models/agents/agent/teachability.py +0 -70
  223. waldiez/models/agents/rag_user/rag_user.py +0 -60
  224. waldiez/models/agents/swarm_agent/__init__.py +0 -50
  225. waldiez/models/agents/swarm_agent/after_work.py +0 -179
  226. waldiez/models/agents/swarm_agent/on_condition.py +0 -105
  227. waldiez/models/agents/swarm_agent/on_condition_available.py +0 -142
  228. waldiez/models/agents/swarm_agent/on_condition_target.py +0 -40
  229. waldiez/models/agents/swarm_agent/swarm_agent.py +0 -107
  230. waldiez/models/agents/swarm_agent/swarm_agent_data.py +0 -124
  231. waldiez/models/flow/utils.py +0 -232
  232. waldiez/models/skill/__init__.py +0 -16
  233. waldiez/models/skill/extra_requirements.py +0 -36
  234. waldiez/models/skill/skill_data.py +0 -53
  235. waldiez/models/skill/skill_type.py +0 -8
  236. waldiez/utils/pysqlite3_checker.py +0 -308
  237. waldiez/utils/rdps_checker.py +0 -122
  238. waldiez-0.4.7.dist-info/RECORD +0 -149
  239. /waldiez/models/agents/{captain_agent → captain}/__init__.py +0 -0
  240. /waldiez/models/agents/{captain_agent → captain}/captain_agent_lib_entry.py +0 -0
  241. {waldiez-0.4.7.dist-info → waldiez-0.4.8.dist-info}/WHEEL +0 -0
  242. {waldiez-0.4.7.dist-info → waldiez-0.4.8.dist-info}/entry_points.txt +0 -0
  243. {waldiez-0.4.7.dist-info → waldiez-0.4.8.dist-info}/licenses/LICENSE +0 -0
  244. {waldiez-0.4.7.dist-info → waldiez-0.4.8.dist-info}/licenses/NOTICE.md +0 -0
waldiez/__init__.py CHANGED
@@ -5,7 +5,7 @@
5
5
  from .exporter import WaldiezExporter
6
6
  from .models import Waldiez
7
7
  from .runner import WaldiezRunner
8
- from .utils import check_conflicts, check_flaml_warnings, check_rpds_py
8
+ from .utils import check_conflicts, check_flaml_warnings
9
9
 
10
10
  # flake8: noqa: F401
11
11
  # pylint: disable=import-error,line-too-long
@@ -22,13 +22,13 @@ except ImportError: # pragma: no cover
22
22
  )
23
23
  __version__ = "dev"
24
24
 
25
- __WALDIEZ_INITIALIZED = False
25
+ # pylint: disable=invalid-name
26
+ __waldiez_initialized = False
26
27
 
27
- if not __WALDIEZ_INITIALIZED:
28
- __WALDIEZ_INITIALIZED = True
28
+ if not __waldiez_initialized:
29
+ __waldiez_initialized = True
29
30
  check_conflicts()
30
31
  check_flaml_warnings()
31
- check_rpds_py()
32
32
 
33
33
  __all__ = [
34
34
  "Waldiez",
waldiez/_version.py CHANGED
@@ -5,4 +5,4 @@
5
5
  This file is automatically generated by Hatchling.
6
6
  Do not edit this file directly.
7
7
  """
8
- __version__ = VERSION = "0.4.7"
8
+ __version__ = VERSION = "0.4.8"
waldiez/cli.py CHANGED
@@ -5,22 +5,21 @@
5
5
  """Command line interface to convert or run a waldiez file."""
6
6
 
7
7
  import json
8
- import logging
9
8
  import os
10
- import sys
11
9
  from pathlib import Path
12
- from typing import TYPE_CHECKING, Optional
10
+ from typing import TYPE_CHECKING, Any, Optional, Union
13
11
 
14
12
  import anyio
15
13
  import typer
14
+ from dotenv import load_dotenv
16
15
  from typing_extensions import Annotated
17
16
 
18
17
  # pylint: disable=import-error,line-too-long
19
18
  # pyright: reportMissingImports=false
20
19
  try: # pragma: no cover
21
- from ._version import ( # type: ignore[unused-ignore, unused-import, import-not-found, import-untyped] # noqa
22
- __version__,
23
- )
20
+ # fmt: off
21
+ from ._version import __version__ # type: ignore[unused-ignore, unused-import, import-not-found, import-untyped] # noqa
22
+ # fmt: on
24
23
  except ImportError: # pragma: no cover
25
24
  import warnings
26
25
 
@@ -31,6 +30,8 @@ except ImportError: # pragma: no cover
31
30
 
32
31
 
33
32
  from .exporter import WaldiezExporter
33
+ from .io import StructuredIOStream
34
+ from .logger import get_logger
34
35
  from .models import Waldiez
35
36
  from .runner import WaldiezRunner
36
37
  from .utils import add_cli_extras
@@ -39,6 +40,9 @@ if TYPE_CHECKING:
39
40
  from autogen import ChatResult # type: ignore[import-untyped]
40
41
 
41
42
 
43
+ load_dotenv()
44
+ LOG = get_logger()
45
+
42
46
  app = typer.Typer(
43
47
  name="waldiez",
44
48
  help="Handle Waldiez flows.",
@@ -52,7 +56,7 @@ app = typer.Typer(
52
56
  invoke_without_command=True,
53
57
  add_help_option=True,
54
58
  pretty_exceptions_enable=False,
55
- epilog=("Use `waldiez [COMMAND] --help` for command-specific help. "),
59
+ epilog="Use `waldiez [COMMAND] --help` for command-specific help.",
56
60
  )
57
61
 
58
62
 
@@ -95,6 +99,22 @@ def run(
95
99
  dir_okay=False,
96
100
  resolve_path=True,
97
101
  ),
102
+ uploads_root: Optional[Path] = typer.Option( # noqa: B008
103
+ None,
104
+ help=(
105
+ "Path to the uploads root directory. "
106
+ "The directory will contain "
107
+ "any uploaded files."
108
+ ),
109
+ dir_okay=True,
110
+ resolve_path=True,
111
+ ),
112
+ structured: bool = typer.Option( # noqa: B008
113
+ False,
114
+ help=(
115
+ "If set, running the flow will use structured io stream instead of the default 'input/print' "
116
+ ),
117
+ ),
98
118
  force: bool = typer.Option( # noqa: B008
99
119
  False,
100
120
  help="Override the output file if it already exists.",
@@ -110,28 +130,27 @@ def run(
110
130
  except json.decoder.JSONDecodeError as error:
111
131
  typer.echo("Invalid .waldiez file. Not a valid json?")
112
132
  raise typer.Exit(code=1) from error
113
- waldiez = Waldiez.from_dict(data)
114
- runner = WaldiezRunner(waldiez)
115
- if waldiez.is_async:
116
- results = anyio.run(runner.a_run, output_path)
117
- else:
118
- results = runner.run(output_path=output_path)
119
- logger = _get_logger()
133
+ results = _do_run(
134
+ data,
135
+ structured=structured,
136
+ uploads_root=uploads_root,
137
+ output_path=output_path,
138
+ )
120
139
  if isinstance(results, list):
121
- logger.info("Results:")
140
+ LOG.info("Results:")
122
141
  for result in results:
123
- _log_result(result, logger)
142
+ _log_result(result)
124
143
  sep = "-" * 80
125
144
  print("\n" + f"{sep}" + "\n")
126
145
  elif isinstance(results, dict):
127
- logger.info("Results:")
146
+ LOG.info("Results:")
128
147
  for key, result in results.items():
129
- logger.info("Order: %s", key)
130
- _log_result(result, logger)
148
+ LOG.info("Order: %s", key)
149
+ _log_result(result)
131
150
  sep = "-" * 80
132
151
  print("\n" + f"{sep}" + "\n")
133
152
  else:
134
- _log_result(results, logger)
153
+ _log_result(results)
135
154
 
136
155
 
137
156
  @app.command()
@@ -148,24 +167,31 @@ def convert(
148
167
  resolve_path=True,
149
168
  ),
150
169
  ],
151
- output: Annotated[
152
- Path,
153
- typer.Option(
154
- ...,
155
- help=(
156
- "Path to the output file. "
157
- "The file extension determines the output format: "
158
- "`.py` for Python script, `.ipynb` for Jupyter notebook."
159
- ),
160
- file_okay=True,
161
- dir_okay=False,
162
- resolve_path=True,
170
+ output: Path | None = typer.Option( # noqa: B008
171
+ default=None,
172
+ help=(
173
+ "Path to the output file. "
174
+ "The file extension determines the output format: "
175
+ "`.py` for Python script, `.ipynb` for Jupyter notebook."
176
+ " If not provided, the output will be saved in the same directory as the input file."
177
+ " If the file already exists, it will not be overwritten unless --force is used."
163
178
  ),
164
- ],
179
+ file_okay=True,
180
+ dir_okay=False,
181
+ resolve_path=True,
182
+ ),
165
183
  force: bool = typer.Option(
166
184
  False,
167
185
  help="Override the output file if it already exists.",
168
186
  ),
187
+ debug: bool = typer.Option(
188
+ False,
189
+ "--debug",
190
+ "-d",
191
+ help="Enable debug logging.",
192
+ is_eager=True,
193
+ rich_help_panel="Debug",
194
+ ),
169
195
  ) -> None:
170
196
  """Convert a Waldiez flow to a Python script or a Jupyter notebook."""
171
197
  _get_output_path(output, force)
@@ -177,7 +203,11 @@ def convert(
177
203
  raise typer.Exit(code=1) from error
178
204
  waldiez = Waldiez.from_dict(data)
179
205
  exporter = WaldiezExporter(waldiez)
180
- exporter.export(output, force=force)
206
+ if debug:
207
+ LOG.set_level("DEBUG")
208
+ if output is None:
209
+ output = Path(file).with_suffix(".py").resolve()
210
+ exporter.export(output, force=force, debug=debug)
181
211
  generated = str(output).replace(os.getcwd(), ".")
182
212
  typer.echo(f"Generated: {generated}")
183
213
 
@@ -201,7 +231,46 @@ def check(
201
231
  with file.open("r", encoding="utf-8") as _file:
202
232
  data = json.load(_file)
203
233
  Waldiez.from_dict(data)
204
- typer.echo("Waldiez flow is valid.")
234
+ LOG.success("Waldiez flow seems valid.")
235
+
236
+
237
+ def _do_run(
238
+ data: dict[str, Any],
239
+ structured: bool,
240
+ uploads_root: Optional[Path],
241
+ output_path: Optional[Path],
242
+ ) -> Union["ChatResult", list["ChatResult"], dict[int, "ChatResult"]]:
243
+ """Run the Waldiez flow and get the results."""
244
+ waldiez = Waldiez.from_dict(data)
245
+ if structured:
246
+ stream = StructuredIOStream(uploads_root=uploads_root)
247
+ with StructuredIOStream.set_default(stream):
248
+ runner = WaldiezRunner(waldiez)
249
+ if waldiez.is_async:
250
+ results = anyio.run(
251
+ runner.a_run,
252
+ output_path,
253
+ uploads_root,
254
+ )
255
+ else:
256
+ results = runner.run(
257
+ output_path=output_path,
258
+ uploads_root=uploads_root,
259
+ )
260
+ else:
261
+ runner = WaldiezRunner(waldiez)
262
+ if waldiez.is_async:
263
+ results = anyio.run(
264
+ runner.a_run,
265
+ output_path,
266
+ uploads_root,
267
+ )
268
+ else:
269
+ results = runner.run(
270
+ output_path=output_path,
271
+ uploads_root=uploads_root,
272
+ )
273
+ return results
205
274
 
206
275
 
207
276
  def _get_output_path(output: Optional[Path], force: bool) -> Optional[Path]:
@@ -211,53 +280,23 @@ def _get_output_path(output: Optional[Path], force: bool) -> Optional[Path]:
211
280
  output.parent.mkdir(parents=True)
212
281
  if output is not None and output.exists():
213
282
  if force is False:
214
- typer.echo("Output file already exists.")
283
+ LOG.error("Output file already exists.")
215
284
  raise typer.Exit(code=1)
216
285
  output.unlink()
217
286
  return output
218
287
 
219
288
 
220
- def _get_logger(level: int = logging.INFO) -> logging.Logger:
221
- """Get the logger for the Waldiez package.
222
-
223
- Parameters
224
- ----------
225
- level : int or str, optional
226
- The logging level. Default is logging.INFO.
227
-
228
- Returns
229
- -------
230
- logging.Logger
231
- The logger.
232
- """
233
- # check if we already have setup a config
234
-
235
- if not logging.getLogger().handlers:
236
- logging.basicConfig(
237
- level=level,
238
- format="%(levelname)s %(message)s",
239
- stream=sys.stderr,
240
- force=True,
241
- )
242
- logger = logging.getLogger("waldiez::cli")
243
- current_level = logger.getEffectiveLevel()
244
- if current_level != level:
245
- logger.setLevel(level)
246
- return logger
247
-
248
-
249
- def _log_result(result: "ChatResult", logger: logging.Logger) -> None:
289
+ def _log_result(result: "ChatResult") -> None:
250
290
  """Log the result of the Waldiez flow."""
251
- logger.info("Chat History:\n")
252
- logger.info(result.chat_history)
253
- logger.info("Summary:\n")
254
- logger.info(result.summary)
255
- logger.info("Cost:\n")
256
- logger.info(result.cost)
291
+ LOG.info("Chat History:\n")
292
+ LOG.info(result.chat_history)
293
+ LOG.info("Summary:\n")
294
+ LOG.info(result.summary)
295
+ LOG.info("Cost:\n")
296
+ LOG.info(result.cost)
257
297
 
258
298
 
259
299
  add_cli_extras(app)
260
300
 
261
301
  if __name__ == "__main__":
262
- _get_logger()
263
302
  app()
waldiez/exporter.py CHANGED
@@ -14,8 +14,11 @@ from pathlib import Path
14
14
  from typing import Union
15
15
 
16
16
  import jupytext # type: ignore[import-untyped]
17
+ from jupytext.config import ( # type: ignore[import-untyped]
18
+ JupytextConfiguration,
19
+ )
17
20
 
18
- from .exporting import FlowExporter
21
+ from .exporting import FlowExtras, create_flow_exporter
19
22
  from .models import Waldiez
20
23
 
21
24
 
@@ -27,6 +30,8 @@ class WaldiezExporter:
27
30
  waldiez (Waldiez): The Waldiez instance.
28
31
  """
29
32
 
33
+ flow_extras: FlowExtras
34
+
30
35
  def __init__(self, waldiez: Waldiez) -> None:
31
36
  """Initialize the Waldiez exporter.
32
37
 
@@ -54,20 +59,27 @@ class WaldiezExporter:
54
59
  waldiez = Waldiez.load(file_path)
55
60
  return cls(waldiez)
56
61
 
57
- def export(self, path: Union[str, Path], force: bool = False) -> None:
62
+ def export(
63
+ self,
64
+ path: Union[str, Path],
65
+ force: bool = False,
66
+ debug: bool = False,
67
+ ) -> None:
58
68
  """Export the Waldiez instance.
59
69
 
60
70
  Parameters
61
71
  ----------
62
72
  path : Union[str, Path]
63
73
  The path to export to.
64
- force : bool, optional
74
+ force : bool, (optional)
65
75
  Override the output file if it already exists, by default False.
76
+ debug : bool, (optional)
77
+ Whether to enable debug mode, by default False.
66
78
 
67
79
  Raises
68
80
  ------
69
81
  FileExistsError
70
- If the file already exists and force is False.
82
+ If the file already exists, and force is False.
71
83
  IsADirectoryError
72
84
  If the output is a directory.
73
85
  ValueError
@@ -85,21 +97,27 @@ class WaldiezExporter:
85
97
  path.parent.mkdir(parents=True, exist_ok=True)
86
98
  extension = path.suffix
87
99
  if extension == ".waldiez":
88
- self.to_waldiez(path)
100
+ self.to_waldiez(path, debug=debug)
89
101
  elif extension == ".py":
90
- self.to_py(path)
102
+ self.to_py(path, debug=debug)
91
103
  elif extension == ".ipynb":
92
- self.to_ipynb(path)
104
+ self.to_ipynb(path, debug=debug)
93
105
  else:
94
106
  raise ValueError(f"Invalid extension: {extension}")
95
107
 
96
- def to_ipynb(self, path: Path) -> None:
108
+ def to_ipynb(
109
+ self,
110
+ path: Path,
111
+ debug: bool = False,
112
+ ) -> None:
97
113
  """Export flow to jupyter notebook.
98
114
 
99
115
  Parameters
100
116
  ----------
101
117
  path : Path
102
118
  The path to export to.
119
+ debug : bool, optional
120
+ Whether to enable debug mode, by default False.
103
121
 
104
122
  Raises
105
123
  ------
@@ -108,57 +126,81 @@ class WaldiezExporter:
108
126
  """
109
127
  # we first create a .py file with the content
110
128
  # and then convert it to a notebook using jupytext
111
- exporter = FlowExporter(
129
+ exporter = create_flow_exporter(
112
130
  waldiez=self.waldiez,
113
131
  output_dir=path.parent,
114
132
  for_notebook=True,
133
+ debug=debug,
115
134
  )
135
+ self.flow_extras = exporter.extras
116
136
  output = exporter.export()
117
- content = output["content"]
118
- if not content:
137
+ content_str = output.main_content
138
+ if not content_str:
119
139
  raise RuntimeError("Could not generate notebook")
120
140
  py_path = path.with_suffix(".tmp.py")
121
141
  with open(py_path, "w", encoding="utf-8", newline="\n") as f:
122
- f.write(content)
142
+ f.write(content_str)
143
+ config = JupytextConfiguration(
144
+ comment_magics=False,
145
+ hide_notebook_metadata=True,
146
+ cell_metadata_filter="-all",
147
+ )
123
148
  with open(py_path, "r", encoding="utf-8") as py_out:
124
- content = jupytext.read(py_out, fmt="py:light")
149
+ jp_content = jupytext.read( # pyright: ignore
150
+ py_out,
151
+ fmt="py:percent",
152
+ config=config,
153
+ )
125
154
  ipynb_path = str(py_path).replace(".tmp.py", ".tmp.ipynb")
126
- jupytext.write(content, ipynb_path, fmt="ipynb")
155
+ jupytext.write( # pyright: ignore
156
+ jp_content,
157
+ ipynb_path,
158
+ fmt="ipynb",
159
+ config=config,
160
+ )
127
161
  Path(ipynb_path).rename(ipynb_path.replace(".tmp.ipynb", ".ipynb"))
128
162
  py_path.unlink(missing_ok=True)
129
163
 
130
- def to_py(self, path: Path) -> None:
131
- """Export waldiez flow to python script.
164
+ def to_py(self, path: Path, debug: bool = False) -> None:
165
+ """Export waldiez flow to a python script.
132
166
 
133
167
  Parameters
134
168
  ----------
135
169
  path : Path
136
170
  The path to export to.
171
+ debug : bool, optional
172
+ Whether to enable debug mode, by default False.
137
173
 
138
174
  Raises
139
175
  ------
140
176
  RuntimeError
141
177
  If the python script could not be generated.
142
178
  """
143
- exporter = FlowExporter(
179
+ exporter = create_flow_exporter(
144
180
  waldiez=self.waldiez,
145
181
  output_dir=path.parent,
146
182
  for_notebook=False,
183
+ debug=debug,
147
184
  )
185
+ self.flow_extras = exporter.extras
148
186
  output = exporter.export()
149
- content = output["content"]
187
+ content = output.main_content
150
188
  if not content:
151
189
  raise RuntimeError("Could not generate python script")
152
190
  with open(path, "w", encoding="utf-8", newline="\n") as file:
153
191
  file.write(content)
154
192
 
155
- def to_waldiez(self, file_path: Path) -> None:
193
+ def to_waldiez(self, file_path: Path, debug: bool = False) -> None:
156
194
  """Export the Waldiez instance.
157
195
 
158
196
  Parameters
159
197
  ----------
160
198
  file_path : Path
161
199
  The file path.
200
+ debug : bool, optional
201
+ Whether to enable debug mode, by default False.
162
202
  """
163
203
  with open(file_path, "w", encoding="utf-8", newline="\n") as file:
164
204
  file.write(self.waldiez.model_dump_json())
205
+ if debug:
206
+ print(self.waldiez.model_dump_json(indent=2))
@@ -1,15 +1,34 @@
1
1
  # SPDX-License-Identifier: Apache-2.0.
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
- """Tools for exporting agents, models, skills and chats to strings."""
3
+ """Tools for exporting agents, models, tools and chats to strings."""
4
4
 
5
- from .agent import AgentExporter
6
- from .flow import FlowExporter
7
- from .models import ModelsExporter
8
- from .skills import SkillsExporter
5
+ from .agent import AgentExporter, create_agent_exporter
6
+ from .chats import ChatsExporter, create_chats_exporter
7
+ from .core.errors import (
8
+ ExporterContentError,
9
+ ExporterError,
10
+ ExporterInitializationError,
11
+ ExporterValidationError,
12
+ )
13
+ from .core.extras.flow_extras import FlowExtras
14
+ from .flow import FlowExporter, create_flow_exporter
15
+ from .models import ModelsExporter, create_models_exporter
16
+ from .tools import ToolsExporter, create_tools_exporter
9
17
 
10
18
  __all__ = [
11
19
  "AgentExporter",
20
+ "ChatsExporter",
21
+ "FlowExtras",
12
22
  "FlowExporter",
13
23
  "ModelsExporter",
14
- "SkillsExporter",
24
+ "ToolsExporter",
25
+ "ExporterContentError",
26
+ "ExporterError",
27
+ "ExporterInitializationError",
28
+ "ExporterValidationError",
29
+ "create_agent_exporter",
30
+ "create_chats_exporter",
31
+ "create_flow_exporter",
32
+ "create_models_exporter",
33
+ "create_tools_exporter",
15
34
  ]
@@ -1,7 +1,11 @@
1
1
  # SPDX-License-Identifier: Apache-2.0.
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
- """Agents exporter."""
3
+ """Agent exporter."""
4
4
 
5
- from .agent_exporter import AgentExporter
5
+ from .exporter import AgentExporter
6
+ from .factory import create_agent_exporter
6
7
 
7
- __all__ = ["AgentExporter"]
8
+ __all__ = [
9
+ "AgentExporter",
10
+ "create_agent_exporter",
11
+ ]
@@ -0,0 +1,114 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ # pylint: disable=too-few-public-methods,no-self-use
4
+ """Code execution processor for Waldiez agents."""
5
+
6
+ import json
7
+
8
+ from waldiez.models import WaldiezAgent, WaldiezAgentCodeExecutionConfig
9
+
10
+ from ..core import CodeExecutionConfig, ImportPosition, ImportStatement
11
+
12
+
13
+ class CodeExecutionProcessor:
14
+ """Processor for code execution configuration."""
15
+
16
+ def __init__(
17
+ self,
18
+ agent: WaldiezAgent,
19
+ agent_name: str,
20
+ tool_names: dict[str, str],
21
+ ):
22
+ self.agent = agent
23
+ self.agent_name = agent_name
24
+ self.tool_names = tool_names
25
+
26
+ def process(self) -> CodeExecutionConfig:
27
+ """Process code execution configuration.
28
+
29
+ Returns
30
+ -------
31
+ CodeExecutionConfig
32
+ The processed code execution configuration.
33
+ """
34
+ if self.agent.data.code_execution_config is False:
35
+ return CodeExecutionConfig(
36
+ executor_content="",
37
+ executor_argument="False",
38
+ executor_import=None,
39
+ )
40
+
41
+ config = self.agent.data.code_execution_config
42
+ use_docker = (
43
+ config.use_docker if config.use_docker is not None else False
44
+ )
45
+
46
+ executor_class = self._get_executor_class_name(use_docker)
47
+ executor_content = self._build_executor_content(config, use_docker)
48
+ executor_arg = f'{{"executor": {self.agent_name}_executor}}'
49
+ executor_import = f"from autogen.coding import {executor_class}"
50
+
51
+ return CodeExecutionConfig(
52
+ executor_content=executor_content,
53
+ executor_argument=executor_arg,
54
+ executor_import=ImportStatement(
55
+ statement=executor_import,
56
+ position=ImportPosition.THIRD_PARTY,
57
+ ),
58
+ )
59
+
60
+ def _get_executor_class_name(self, use_docker: bool) -> str:
61
+ """Get the appropriate executor class name."""
62
+ return (
63
+ "DockerCommandLineCodeExecutor"
64
+ if use_docker
65
+ else "LocalCommandLineCodeExecutor"
66
+ )
67
+
68
+ def _build_executor_content(
69
+ self, config: WaldiezAgentCodeExecutionConfig, use_docker: bool
70
+ ) -> str:
71
+ """Build the executor content string."""
72
+ executor_class = self._get_executor_class_name(use_docker)
73
+ lines = [f"{self.agent_name}_executor = {executor_class}("]
74
+
75
+ # Add work directory
76
+ if config.work_dir:
77
+ lines.append(f" work_dir={json.dumps(config.work_dir)},")
78
+
79
+ # Add timeout
80
+ if config.timeout:
81
+ lines.append(f" timeout={int(config.timeout)},")
82
+
83
+ # Add functions (only for local executor)
84
+ if not use_docker and config.functions:
85
+ function_names = self._get_function_names(config.functions)
86
+ if function_names:
87
+ function_names_str = ", ".join(function_names)
88
+ lines.append(f" functions=[{function_names_str}],")
89
+
90
+ lines.append(")")
91
+ lines.append("") # Add empty line
92
+
93
+ return "\n".join(lines)
94
+
95
+ def _get_function_names(self, function_ids: list[str]) -> list[str]:
96
+ """Get function names from function IDs.
97
+
98
+ Parameters
99
+ ----------
100
+ function_ids : list[str]
101
+ List of function IDs to resolve names for.
102
+
103
+ Returns
104
+ -------
105
+ list[str]
106
+ List of function names corresponding to the provided IDs.
107
+ """
108
+ function_names: list[str] = []
109
+ for tool_id in function_ids:
110
+ if tool_id in self.tool_names:
111
+ tool_name = self.tool_names[tool_id]
112
+ if tool_name:
113
+ function_names.append(tool_name)
114
+ return function_names