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,459 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ """Waldiez Agent Handoff class."""
4
+
5
+ from typing import Any, Union
6
+
7
+ from pydantic import Field
8
+ from typing_extensions import Annotated, Literal
9
+
10
+ from .base import WaldiezBase
11
+
12
+ __all__ = [
13
+ "WaldiezTransitionAvailability",
14
+ "WaldiezTransitionTarget",
15
+ "WaldiezAgentTarget",
16
+ "WaldiezRandomAgentTarget",
17
+ "WaldiezSimpleTarget",
18
+ "WaldiezGroupOrNestedTarget",
19
+ "WaldiezStringLLMCondition",
20
+ "WaldiezContextStrLLMCondition",
21
+ "WaldiezStringContextCondition",
22
+ "WaldiezExpressionContextCondition",
23
+ "WaldiezLLMBasedTransition",
24
+ "WaldiezContextBasedTransition",
25
+ "WaldiezHandoff",
26
+ "WaldiezHandoffCondition",
27
+ "WaldiezHandoffTransition",
28
+ "WaldiezLLMBasedCondition",
29
+ "WaldiezContextBasedCondition",
30
+ ]
31
+
32
+
33
+ class WaldiezAgentTarget(WaldiezBase):
34
+ """Agent target for handoff.
35
+
36
+ Attributes
37
+ ----------
38
+ target_type : Literal["AgentTarget"]
39
+ The type of the transition target.
40
+ value : str
41
+ The agent id to transfer control to.
42
+ order : int
43
+ The order of the target in the list of targets.
44
+ If -1, the order is automatically determined by the json data.
45
+ """
46
+
47
+ target_type: Annotated[
48
+ Literal["AgentTarget"],
49
+ Field("AgentTarget", description="The type of the transition target."),
50
+ ]
51
+ value: Annotated[
52
+ list[str],
53
+ Field(
54
+ min_length=1,
55
+ max_length=1,
56
+ description="The agent id to transfer control to.",
57
+ ),
58
+ ]
59
+
60
+
61
+ class WaldiezRandomAgentTarget(WaldiezBase):
62
+ """Random agent target for handoff.
63
+
64
+ Attributes
65
+ ----------
66
+ target_type : Literal["RandomAgentTarget"]
67
+ The type of the transition target.
68
+ value : list[str]
69
+ A list of agent ids to randomly select from.
70
+ order : int
71
+ The order of the target in the list of targets.
72
+ If -1, the order is automatically determined by the json data.
73
+ """
74
+
75
+ target_type: Annotated[
76
+ Literal["RandomAgentTarget"],
77
+ Field(
78
+ "RandomAgentTarget",
79
+ description="The type of the transition target.",
80
+ ),
81
+ ]
82
+ value: Annotated[
83
+ list[str],
84
+ Field(
85
+ min_length=2,
86
+ description=(
87
+ "A list of agent ids to randomly select from. "
88
+ "The list must contain at least 2 agents."
89
+ ),
90
+ ),
91
+ ]
92
+
93
+
94
+ class WaldiezSimpleTarget(WaldiezBase):
95
+ """Simple target for handoff.
96
+
97
+ Attributes
98
+ ----------
99
+ target_type : Literal[
100
+ "AskUserTarget",
101
+ "GroupManagerTarget",
102
+ "RevertToUserTarget",
103
+ "StayTarget",
104
+ "TerminateTarget"
105
+ ]
106
+ The type of the transition target.
107
+ order : int
108
+ The order of the target in the list of targets.
109
+ If -1, the order is automatically determined by the json data.
110
+ target : str
111
+ The id of the group or nested chat to transfer control to.
112
+ """
113
+
114
+ target_type: Annotated[
115
+ Literal[
116
+ "AskUserTarget",
117
+ "GroupManagerTarget",
118
+ "RevertToUserTarget",
119
+ "StayTarget",
120
+ "TerminateTarget",
121
+ ],
122
+ Field(
123
+ "TerminateTarget", description="The type of the transition target."
124
+ ),
125
+ ] = "TerminateTarget"
126
+ value: Annotated[
127
+ list[str],
128
+ Field(
129
+ default_factory=list,
130
+ ),
131
+ ] = [] # not actually used (just for consistency with other targets)
132
+
133
+
134
+ class WaldiezGroupOrNestedTarget(WaldiezBase):
135
+ """Group or nested chat target for handoff.
136
+
137
+ Attributes
138
+ ----------
139
+ target_type : Literal["GroupChatTarget", "NestedChatTarget"]
140
+ The type of the transition target.
141
+ value : str
142
+ The id of the group or nested chat to transfer control to.
143
+ order : int
144
+ The order of the target in the list of targets.
145
+ """
146
+
147
+ target_type: Annotated[
148
+ Literal["GroupChatTarget", "NestedChatTarget"],
149
+ Field(
150
+ ...,
151
+ description="The type of the transition target.",
152
+ alias="targetType",
153
+ ),
154
+ ]
155
+ value: Annotated[
156
+ list[str],
157
+ Field(
158
+ ...,
159
+ min_length=1,
160
+ description=(
161
+ "The id of the group (manager) "
162
+ "or nested chat (source) to transfer control to."
163
+ ),
164
+ ),
165
+ ]
166
+
167
+
168
+ WaldiezTransitionTarget = Annotated[
169
+ Union[
170
+ WaldiezAgentTarget,
171
+ WaldiezRandomAgentTarget,
172
+ WaldiezGroupOrNestedTarget,
173
+ WaldiezSimpleTarget,
174
+ ],
175
+ Field(discriminator="target_type"),
176
+ ]
177
+
178
+
179
+ class WaldiezStringLLMCondition(WaldiezBase):
180
+ """String-based LLM condition."""
181
+
182
+ condition_type: Literal["string_llm"]
183
+ prompt: str
184
+ data: dict[str, Any] = Field(default_factory=dict)
185
+
186
+ def is_not_empty(self) -> bool:
187
+ """Check if the condition is not empty.
188
+
189
+ Returns
190
+ -------
191
+ bool
192
+ True if the condition has a non-empty prompt,
193
+ False otherwise.
194
+ """
195
+ return bool(self.prompt.strip()) or bool(self.data)
196
+
197
+ def is_empty(self) -> bool:
198
+ """Check if the condition is empty.
199
+
200
+ Returns
201
+ -------
202
+ bool
203
+ True if the condition has an empty prompt,
204
+ False otherwise.
205
+ """
206
+ return not self.is_not_empty()
207
+
208
+
209
+ class WaldiezContextStrLLMCondition(WaldiezBase):
210
+ """Context variable-based LLM condition."""
211
+
212
+ condition_type: Literal["context_str_llm"]
213
+ context_str: str
214
+ data: dict[str, Any] = Field(default_factory=dict)
215
+
216
+ def is_not_empty(self) -> bool:
217
+ """Check if the condition is not empty.
218
+
219
+ Returns
220
+ -------
221
+ bool
222
+ True if the condition has a non-empty context string,
223
+ False otherwise.
224
+ """
225
+ return bool(self.context_str.strip()) or bool(self.data)
226
+
227
+ def is_empty(self) -> bool:
228
+ """Check if the condition is empty.
229
+
230
+ Returns
231
+ -------
232
+ bool
233
+ True if the condition has an empty context string,
234
+ False otherwise.
235
+ """
236
+ return not self.is_not_empty()
237
+
238
+
239
+ WaldiezLLMBasedCondition = Annotated[
240
+ Union[WaldiezStringLLMCondition, WaldiezContextStrLLMCondition],
241
+ Field(discriminator="condition_type"),
242
+ ]
243
+
244
+
245
+ class WaldiezStringContextCondition(WaldiezBase):
246
+ """String-based context condition."""
247
+
248
+ condition_type: Literal["string_context"]
249
+ variable_name: str
250
+
251
+ def is_not_empty(self) -> bool:
252
+ """Check if the condition is not empty.
253
+
254
+ Returns
255
+ -------
256
+ bool
257
+ True if the condition has a non-empty variable name,
258
+ False otherwise.
259
+ """
260
+ return bool(self.variable_name.strip())
261
+
262
+ def is_empty(self) -> bool:
263
+ """Check if the condition is empty.
264
+
265
+ Returns
266
+ -------
267
+ bool
268
+ True if the condition has an empty variable name,
269
+ False otherwise.
270
+ """
271
+ return not self.is_not_empty()
272
+
273
+
274
+ class WaldiezExpressionContextCondition(WaldiezBase):
275
+ """Expression-based context condition."""
276
+
277
+ condition_type: Literal["expression_context"]
278
+ expression: str
279
+ data: dict[str, Any] = Field(default_factory=dict)
280
+
281
+ def is_not_empty(self) -> bool:
282
+ """Check if the condition is not empty.
283
+
284
+ Returns
285
+ -------
286
+ bool
287
+ True if the condition has a non-empty expression,
288
+ False otherwise.
289
+ """
290
+ return bool(self.expression.strip()) or bool(self.data)
291
+
292
+ def is_empty(self) -> bool:
293
+ """Check if the condition is empty.
294
+
295
+ Returns
296
+ -------
297
+ bool
298
+ True if the condition has an empty expression,
299
+ False otherwise.
300
+ """
301
+ return not self.is_not_empty()
302
+
303
+
304
+ WaldiezContextBasedCondition = Annotated[
305
+ Union[WaldiezStringContextCondition, WaldiezExpressionContextCondition],
306
+ Field(discriminator="condition_type"),
307
+ ]
308
+
309
+
310
+ # Union type for just the condition types (without targets)
311
+ WaldiezHandoffCondition = Union[
312
+ WaldiezLLMBasedCondition, WaldiezContextBasedCondition
313
+ ]
314
+
315
+
316
+ # pylint: disable=too-few-public-methods
317
+ class WaldiezDefaultCondition:
318
+ """Get the default condition for handoff transitions."""
319
+
320
+ @classmethod
321
+ def create(cls) -> WaldiezHandoffCondition:
322
+ """Get the default condition for handoff transitions.
323
+
324
+ Returns
325
+ -------
326
+ WaldiezStringLLMCondition
327
+ A default LLM condition with empty prompt and data.
328
+ """
329
+ return WaldiezStringLLMCondition(
330
+ condition_type="string_llm",
331
+ prompt="",
332
+ data={},
333
+ )
334
+
335
+
336
+ class WaldiezTransitionAvailability(WaldiezBase):
337
+ """Availability condition for transitions.
338
+
339
+ Attributes
340
+ ----------
341
+ available : bool
342
+ Whether the transition is available.
343
+ data : dict[str, Any]
344
+ Additional data for the availability condition.
345
+ """
346
+
347
+ type: Literal["string", "expression", "none"] = "none"
348
+ value: str = ""
349
+
350
+
351
+ class WaldiezLLMBasedTransition(WaldiezBase):
352
+ """Condition wrapper for LLM conditions."""
353
+
354
+ target: WaldiezTransitionTarget
355
+ condition: WaldiezLLMBasedCondition
356
+ available: WaldiezTransitionAvailability
357
+
358
+
359
+ class WaldiezContextBasedTransition(WaldiezBase):
360
+ """Condition wrapper for context conditions."""
361
+
362
+ target: WaldiezTransitionTarget
363
+ condition: WaldiezContextBasedCondition
364
+ available: WaldiezTransitionAvailability
365
+
366
+
367
+ # Union type for complete transitions (condition + target)
368
+ WaldiezHandoffTransition = Union[
369
+ WaldiezLLMBasedTransition, WaldiezContextBasedTransition
370
+ ]
371
+
372
+
373
+ class WaldiezHandoff(WaldiezBase):
374
+ """Handoff class for Waldiez agents and chats."""
375
+
376
+ target: Annotated[
377
+ WaldiezTransitionTarget,
378
+ Field(
379
+ ...,
380
+ description=(
381
+ "The target to transfer control to. "
382
+ "Can be an agent, group, nested chat, or simple target."
383
+ ),
384
+ discriminator="target_type",
385
+ ),
386
+ ]
387
+ condition: Annotated[
388
+ WaldiezHandoffCondition,
389
+ Field(
390
+ default_factory=WaldiezDefaultCondition.create,
391
+ title="Condition",
392
+ description=(
393
+ "The condition to use for the handoff. "
394
+ "If not provided, the handoff will always be available."
395
+ ),
396
+ discriminator="condition_type",
397
+ ),
398
+ ]
399
+ available: Annotated[
400
+ WaldiezTransitionAvailability,
401
+ Field(
402
+ default_factory=WaldiezTransitionAvailability,
403
+ title="Available",
404
+ description=(
405
+ "The availability of the handoff. "
406
+ "If not provided, the handoff will always be available."
407
+ ),
408
+ ),
409
+ ]
410
+
411
+ def is_llm_based(self) -> bool:
412
+ """Check if the handoff is LLM-based.
413
+
414
+ Returns
415
+ -------
416
+ bool
417
+ True if the handoff condition is LLM-based,
418
+ False otherwise.
419
+ """
420
+ return self.condition.condition_type in {
421
+ "string_llm",
422
+ "context_str_llm",
423
+ }
424
+
425
+ def is_context_based(self) -> bool:
426
+ """Check if the handoff is context-based.
427
+
428
+ Returns
429
+ -------
430
+ bool
431
+ True if the handoff condition is context-based,
432
+ False otherwise.
433
+ """
434
+ return self.condition.condition_type in {
435
+ "string_context",
436
+ "expression_context",
437
+ }
438
+
439
+ def is_not_empty(self) -> bool:
440
+ """Check if the handoff is not empty.
441
+
442
+ Returns
443
+ -------
444
+ bool
445
+ True if the handoff has a non-empty target,
446
+ condition, or availability, False otherwise.
447
+ """
448
+ return self.condition.is_not_empty() or self.available.type != "none"
449
+
450
+ def is_empty(self) -> bool:
451
+ """Check if the handoff is empty.
452
+
453
+ Returns
454
+ -------
455
+ bool
456
+ True if the handoff has an empty target,
457
+ condition, and availability, False otherwise.
458
+ """
459
+ return not self.is_not_empty()
@@ -0,0 +1,19 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ """Generate a unique ID."""
4
+
5
+ import uuid
6
+ from datetime import datetime, timezone
7
+
8
+
9
+ def get_id() -> str:
10
+ """Generate a unique ID.
11
+
12
+ Returns
13
+ -------
14
+ str
15
+ The unique ID.
16
+ """
17
+ now_td = datetime.now(timezone.utc)
18
+ now_str = now_td.strftime("%Y%m%d%H%M%S%f")
19
+ return f"{now_str}-{uuid.uuid4().hex}"