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
@@ -0,0 +1,57 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ """Factory function for creating a ToolsExporter instance."""
4
+
5
+ from pathlib import Path
6
+ from typing import Optional, Union
7
+
8
+ from waldiez.models import WaldiezAgent, WaldiezTool
9
+
10
+ from ..core import ExporterContext, get_default_exporter_context
11
+ from .exporter import ToolsExporter
12
+
13
+
14
+ def create_tools_exporter(
15
+ flow_name: str,
16
+ agents: list[WaldiezAgent],
17
+ agent_names: dict[str, str],
18
+ tools: list[WaldiezTool],
19
+ tool_names: dict[str, str],
20
+ output_dir: Optional[Union[str, Path]] = None,
21
+ context: Optional[ExporterContext] = None,
22
+ ) -> ToolsExporter:
23
+ """Create a tools exporter.
24
+
25
+ Parameters
26
+ ----------
27
+ flow_name : str
28
+ The name of the flow.
29
+ agents : list[WaldiezAgent]
30
+ The agents that use tools.
31
+ agent_names : dict[str, str]
32
+ Mapping of agent IDs to names.
33
+ tools : list[WaldiezTool]
34
+ The tools to export.
35
+ tool_names : dict[str, str]
36
+ Mapping of tool IDs to names.
37
+ output_dir : Optional[Union[str, Path]], optional
38
+ Output directory for generated files, by default None
39
+ context : Optional[ExporterContext], optional
40
+ Exporter context with dependencies, by default None
41
+
42
+ Returns
43
+ -------
44
+ ToolsExporter
45
+ The created tools exporter.
46
+ """
47
+ if context is None:
48
+ context = get_default_exporter_context()
49
+ return ToolsExporter(
50
+ flow_name=flow_name,
51
+ agents=agents,
52
+ agent_names=agent_names,
53
+ tools=tools,
54
+ tool_names=tool_names,
55
+ output_dir=output_dir,
56
+ context=context,
57
+ )
@@ -0,0 +1,248 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ # pylint: disable=too-few-public-methods
4
+ """Tool related utilities and processors."""
5
+
6
+ from dataclasses import dataclass, field
7
+ from pathlib import Path
8
+ from typing import Optional
9
+
10
+ from waldiez.models import WaldiezTool
11
+
12
+ from ..core.constants import FILE_HEADER
13
+ from ..core.errors import ExporterContentError
14
+ from ..core.types import EnvironmentVariable
15
+
16
+
17
+ @dataclass
18
+ class ToolProcessingResult:
19
+ """Result from processing tools."""
20
+
21
+ content: str = ""
22
+ builtin_imports: list[str] = field(default_factory=list[str])
23
+ third_party_imports: list[str] = field(default_factory=list[str])
24
+ environment_variables: list[EnvironmentVariable] = field(
25
+ default_factory=list[EnvironmentVariable]
26
+ )
27
+
28
+
29
+ class ToolProcessor:
30
+ """Processor for tool content generation."""
31
+
32
+ def __init__(
33
+ self,
34
+ flow_name: str,
35
+ tools: list[WaldiezTool],
36
+ tool_names: dict[str, str],
37
+ output_dir: Optional[Path] = None,
38
+ ):
39
+ """Initialize the tool processor.
40
+
41
+ Parameters
42
+ ----------
43
+ flow_name : str
44
+ The name of the flow.
45
+ tools : list[WaldiezTool]
46
+ The tools to process.
47
+ tool_names : dict[str, str]
48
+ Mapping of tool IDs to names.
49
+ output_dir : Optional[Path], optional
50
+ Output directory for generated files, by default None
51
+ """
52
+ self.flow_name = flow_name
53
+ self.tools = tools
54
+ self.tool_names = tool_names
55
+ self.output_dir = output_dir
56
+
57
+ def process(self) -> ToolProcessingResult:
58
+ """Process all tools and return consolidated result.
59
+
60
+ Returns
61
+ -------
62
+ ToolProcessingResult
63
+ The processed result containing tool content,
64
+ imports, and environment variables.
65
+ """
66
+ result = ToolProcessingResult()
67
+
68
+ # Separate shared and regular tools
69
+ shared_tools = [tool for tool in self.tools if tool.is_shared]
70
+ regular_tools = [tool for tool in self.tools if not tool.is_shared]
71
+
72
+ # Process shared tools first (they need to be available to other tools)
73
+ for tool in shared_tools:
74
+ self._process_single_tool(tool, result)
75
+
76
+ # Then regular tools
77
+ for tool in regular_tools:
78
+ self._process_single_tool(tool, result)
79
+
80
+ # Clean up and finalize result
81
+ self._finalize_result(result)
82
+
83
+ return result
84
+
85
+ def _process_single_tool(
86
+ self, tool: WaldiezTool, result: ToolProcessingResult
87
+ ) -> None:
88
+ """Process a single tool and add to result.
89
+
90
+ Parameters
91
+ ----------
92
+ tool : WaldiezTool
93
+ The tool to process.
94
+ result : ToolProcessingResult
95
+ The result to add processed content to.
96
+ """
97
+ # Get tool content
98
+ tool_content = tool.get_content()
99
+ if tool_content: # pragma: no branch
100
+ # Add interop conversion if needed
101
+ if tool.is_interop:
102
+ tool_content += self._get_interop_conversion(tool)
103
+
104
+ result.content += tool_content + "\n\n"
105
+
106
+ # Get imports
107
+ builtin_imports, third_party_imports = tool.get_imports()
108
+ if builtin_imports:
109
+ result.builtin_imports.extend(builtin_imports)
110
+ if third_party_imports:
111
+ result.third_party_imports.extend(third_party_imports)
112
+
113
+ # Handle secrets
114
+ if tool.secrets:
115
+ self._process_tool_secrets(tool, result)
116
+
117
+ def _get_interop_conversion(self, tool: WaldiezTool) -> str:
118
+ """Get interop conversion code for a tool.
119
+
120
+ Parameters
121
+ ----------
122
+ tool : WaldiezTool
123
+ The tool that needs interop conversion.
124
+
125
+ Returns
126
+ -------
127
+ str
128
+ The interop conversion code.
129
+ """
130
+ tool_name = self.tool_names[tool.id]
131
+ return f"""
132
+ ag2_{tool_name}_interop = Interoperability()
133
+ ag2_{tool_name} = ag2_{tool_name}_interop.convert_tool(
134
+ tool={tool_name},
135
+ type="{tool.tool_type}"
136
+ )"""
137
+
138
+ def _process_tool_secrets(
139
+ self, tool: WaldiezTool, result: ToolProcessingResult
140
+ ) -> None:
141
+ """Process tool secrets and add to result.
142
+
143
+ Parameters
144
+ ----------
145
+ tool : WaldiezTool
146
+ The tool with secrets.
147
+ result : ToolProcessingResult
148
+ The result to add secrets to.
149
+ """
150
+ tool_name = self.tool_names[tool.id]
151
+
152
+ # Add to environment variables
153
+ for key, value in tool.secrets.items():
154
+ result.environment_variables.append(
155
+ EnvironmentVariable(
156
+ name=key,
157
+ value=value,
158
+ description=f"Secret for tool '{tool_name}'",
159
+ )
160
+ )
161
+
162
+ # Write secrets file if output directory provided
163
+ if self.output_dir:
164
+ self._write_secrets_file(tool, tool_name)
165
+
166
+ def _write_secrets_file(self, tool: WaldiezTool, tool_name: str) -> None:
167
+ """Write tool secrets to a Python file.
168
+
169
+ Parameters
170
+ ----------
171
+ tool : WaldiezTool
172
+ The tool with secrets.
173
+ tool_name : str
174
+ The name of the tool.
175
+ """
176
+ if not self.output_dir or not tool.secrets: # pragma: no cover
177
+ return
178
+
179
+ self.output_dir.mkdir(parents=True, exist_ok=True)
180
+ secrets_file = (
181
+ self.output_dir / f"{self.flow_name}_{tool_name}_secrets.py"
182
+ )
183
+ # pylint: disable=too-many-try-statements
184
+ try:
185
+ with secrets_file.open("w", encoding="utf-8", newline="\n") as f:
186
+ f.write(
187
+ f'''{FILE_HEADER}
188
+ # flake8: noqa: E501
189
+ # pylint: disable=line-too-long
190
+ """Secrets for the tool: {tool_name}."""
191
+
192
+ '''
193
+ )
194
+ f.write("import os\n\n")
195
+ for key, value in tool.secrets.items():
196
+ f.write(f'os.environ["{key}"] = "{value}"\n')
197
+ except Exception as exc: # pragma: no cover
198
+ raise ExporterContentError(
199
+ f"Failed to write secrets file for tool '{tool_name}': {exc}"
200
+ ) from exc
201
+
202
+ def _finalize_result(self, result: ToolProcessingResult) -> None:
203
+ """Finalize the processing result.
204
+
205
+ Parameters
206
+ ----------
207
+ result : ToolProcessingResult
208
+ The result to finalize.
209
+ """
210
+ # Clean up content - remove excessive newlines
211
+ result.content = result.content.replace("\n\n\n", "\n\n").strip()
212
+
213
+ # Sort and deduplicate imports
214
+ result.builtin_imports = self._sort_imports(result.builtin_imports)
215
+ result.third_party_imports = self._sort_imports(
216
+ result.third_party_imports
217
+ )
218
+
219
+ # pylint: disable=no-self-use
220
+ def _sort_imports(self, imports: list[str]) -> list[str]:
221
+ """Sort imports: 'import' statements first, then 'from' statements.
222
+
223
+ Parameters
224
+ ----------
225
+ imports : list[str]
226
+ The import statements to sort.
227
+
228
+ Returns
229
+ -------
230
+ list[str]
231
+ The sorted import statements.
232
+ """
233
+ if not imports:
234
+ return []
235
+
236
+ # Remove duplicates
237
+ unique_imports = list(set(imports))
238
+
239
+ # Separate import types
240
+ import_statements = [
241
+ imp for imp in unique_imports if imp.startswith("import ")
242
+ ]
243
+ from_statements = [
244
+ imp for imp in unique_imports if imp.startswith("from ")
245
+ ]
246
+
247
+ # Sort each type
248
+ return sorted(import_statements) + sorted(from_statements)
@@ -0,0 +1,133 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ # pylint: disable=too-few-public-methods
4
+ """Tool registration processor."""
5
+
6
+ import json
7
+
8
+ from waldiez.models import WaldiezAgent, WaldiezTool
9
+
10
+
11
+ class ToolRegistrationProcessor:
12
+ """Processor for tool registration code."""
13
+
14
+ def __init__(
15
+ self,
16
+ agents: list[WaldiezAgent],
17
+ agent_names: dict[str, str],
18
+ tools: list[WaldiezTool],
19
+ tool_names: dict[str, str],
20
+ ):
21
+ """Initialize the tool registration processor.
22
+
23
+ Parameters
24
+ ----------
25
+ agents : list[WaldiezAgent]
26
+ The agents that use tools.
27
+ agent_names : dict[str, str]
28
+ Mapping of agent IDs to names.
29
+ tools : list[WaldiezTool]
30
+ The available tools.
31
+ tool_names : dict[str, str]
32
+ Mapping of tool IDs to names.
33
+ """
34
+ self.agents = agents
35
+ self.agent_names = agent_names
36
+ self.tools = tools
37
+ self.tool_names = tool_names
38
+
39
+ def process(self) -> str:
40
+ """Process tool registrations for all agents.
41
+
42
+ Returns
43
+ -------
44
+ str
45
+ The generated tool registration code for all agents.
46
+ """
47
+ registrations: list[str] = []
48
+
49
+ for agent in self.agents:
50
+ agent_registration = self._process_agent_registrations(agent)
51
+ if agent_registration:
52
+ registrations.append(agent_registration)
53
+
54
+ return "\n\n".join(registrations) if registrations else ""
55
+
56
+ def _process_agent_registrations(self, agent: WaldiezAgent) -> str:
57
+ """Process tool registrations for a single agent.
58
+
59
+ Parameters
60
+ ----------
61
+ agent : WaldiezAgent
62
+ The agent to process tool registrations for.
63
+
64
+ Returns
65
+ -------
66
+ str
67
+ The tool registration code for this agent.
68
+ """
69
+ if not agent.data.tools or agent.is_group_member:
70
+ # if group member, it's a handoff
71
+ return ""
72
+
73
+ registrations: list[str] = []
74
+ agent_name = self.agent_names[agent.id]
75
+
76
+ for tool_link in agent.data.tools:
77
+ # Find the actual tool
78
+ tool = next((t for t in self.tools if t.id == tool_link.id), None)
79
+ if not tool: # pragma: no cover
80
+ continue
81
+
82
+ tool_name = self.tool_names[tool_link.id]
83
+
84
+ # Use converted name for interop tools
85
+ if tool.is_interop:
86
+ tool_name = f"ag2_{tool_name}"
87
+
88
+ executor_name = self.agent_names[tool_link.executor_id]
89
+ description = tool.description or f"Description of {tool_name}"
90
+
91
+ registration = self._create_registration(
92
+ caller_name=agent_name,
93
+ executor_name=executor_name,
94
+ tool_name=tool_name,
95
+ description=description,
96
+ )
97
+ registrations.append(registration)
98
+
99
+ return "\n".join(registrations) if registrations else ""
100
+
101
+ # pylint: disable=no-self-use
102
+ def _create_registration(
103
+ self,
104
+ caller_name: str,
105
+ executor_name: str,
106
+ tool_name: str,
107
+ description: str,
108
+ ) -> str:
109
+ """Create a single tool registration statement.
110
+
111
+ Parameters
112
+ ----------
113
+ caller_name : str
114
+ The name of the agent calling the tool.
115
+ executor_name : str
116
+ The name of the agent executing the tool.
117
+ tool_name : str
118
+ The name of the tool.
119
+ description : str
120
+ The description of the tool.
121
+
122
+ Returns
123
+ -------
124
+ str
125
+ The tool registration code.
126
+ """
127
+ return f"""register_function(
128
+ {tool_name},
129
+ caller={caller_name},
130
+ executor={executor_name},
131
+ name="{tool_name}",
132
+ description={json.dumps(description)},
133
+ )"""
waldiez/io/__init__.py ADDED
@@ -0,0 +1,128 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+
4
+ # flake8: noqa: F401
5
+ # pylint: disable=unused-import,too-few-public-methods
6
+
7
+ """IOSTream extensions.
8
+
9
+ Let's keep the redis and websockets imports optional,
10
+ and have them in the optional requirements in the package.
11
+ """
12
+
13
+ from typing import Any
14
+
15
+ from .models import (
16
+ AudioContent,
17
+ AudioMediaContent,
18
+ FileContent,
19
+ FileMediaContent,
20
+ ImageContent,
21
+ ImageMediaContent,
22
+ ImageUrlMediaContent,
23
+ MediaContent,
24
+ PrintMessage,
25
+ TextMediaContent,
26
+ UserInputData,
27
+ UserInputRequest,
28
+ UserResponse,
29
+ VideoContent,
30
+ VideoMediaContent,
31
+ )
32
+ from .structured import StructuredIOStream
33
+ from .utils import MediaType, MessageType
34
+
35
+ try:
36
+ from .redis import RedisIOStream # type: ignore[no-redef,unused-ignore]
37
+ except ImportError: # pragma: no cover
38
+
39
+ class RedisIOStream: # type: ignore[no-redef,unused-ignore]
40
+ """Dummy class for RedisIOStream."""
41
+
42
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
43
+ """Initialize the RedisIOStream.
44
+
45
+ Parameters
46
+ ----------
47
+ args : tuple
48
+ Positional arguments.
49
+ kwargs : dict
50
+ Keyword arguments.
51
+ """
52
+ raise ImportError(
53
+ "RedisIOStream is not available. "
54
+ "Please install the required package."
55
+ )
56
+
57
+
58
+ try:
59
+ from .ws import (
60
+ AsyncWebsocketsIOStream, # type: ignore[no-redef,unused-ignore]
61
+ )
62
+ except ImportError: # pragma: no cover
63
+
64
+ class AsyncWebsocketsIOStream: # type: ignore[no-redef,unused-ignore]
65
+ """Dummy class for AsyncWebsocketsIOStream just for the linters."""
66
+
67
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
68
+ """Initialize the AsyncWebsocketsIOStream.
69
+
70
+ Parameters
71
+ ----------
72
+ args : tuple
73
+ Positional arguments.
74
+ kwargs : dict
75
+ Keyword arguments.
76
+ """
77
+ raise ImportError(
78
+ "AsyncWebsocketsIOStream is not available. "
79
+ "Please install the required package."
80
+ )
81
+
82
+
83
+ try:
84
+ from .mqtt import MqttIOStream # type: ignore[no-redef,unused-ignore]
85
+ except ImportError: # pragma: no cover
86
+
87
+ class MqttIOStream: # type: ignore[no-redef,unused-ignore]
88
+ """Dummy class for MqttIOStream."""
89
+
90
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
91
+ """Initialize the MqttIOStream.
92
+
93
+ Parameters
94
+ ----------
95
+ args : tuple
96
+ Positional arguments.
97
+ kwargs : dict
98
+ Keyword arguments.
99
+ """
100
+ raise ImportError(
101
+ "MqttIOStream is not available. "
102
+ "Please install the required package."
103
+ )
104
+
105
+
106
+ __all__ = [
107
+ "AsyncWebsocketsIOStream",
108
+ "StructuredIOStream",
109
+ "RedisIOStream",
110
+ "MqttIOStream",
111
+ "UserInputData",
112
+ "UserResponse",
113
+ "UserInputRequest",
114
+ "PrintMessage",
115
+ "MessageType",
116
+ "MediaType",
117
+ "MediaContent",
118
+ "TextMediaContent",
119
+ "ImageMediaContent",
120
+ "ImageUrlMediaContent",
121
+ "ImageContent",
122
+ "FileMediaContent",
123
+ "FileContent",
124
+ "AudioMediaContent",
125
+ "AudioContent",
126
+ "VideoMediaContent",
127
+ "VideoContent",
128
+ ]