waldiez 0.4.7__py3-none-any.whl → 0.4.9__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 (248) hide show
  1. waldiez/__init__.py +5 -5
  2. waldiez/_version.py +1 -1
  3. waldiez/cli.py +97 -102
  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} +37 -24
  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 +439 -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 +115 -61
  175. waldiez/running/__init__.py +13 -7
  176. waldiez/running/environment.py +49 -68
  177. waldiez/running/gen_seq_diagram.py +16 -14
  178. waldiez/running/post_run.py +119 -0
  179. waldiez/running/pre_run.py +149 -0
  180. waldiez/running/util.py +134 -0
  181. waldiez/utils/__init__.py +2 -4
  182. waldiez/utils/cli_extras/jupyter.py +5 -3
  183. waldiez/utils/cli_extras/runner.py +6 -4
  184. waldiez/utils/cli_extras/studio.py +6 -4
  185. waldiez/utils/conflict_checker.py +15 -9
  186. waldiez/utils/flaml_warnings.py +5 -5
  187. waldiez/utils/version.py +47 -0
  188. {waldiez-0.4.7.dist-info → waldiez-0.4.9.dist-info}/METADATA +235 -91
  189. waldiez-0.4.9.dist-info/RECORD +203 -0
  190. waldiez/exporting/agent/agent_exporter.py +0 -297
  191. waldiez/exporting/agent/utils/__init__.py +0 -23
  192. waldiez/exporting/agent/utils/captain_agent.py +0 -263
  193. waldiez/exporting/agent/utils/code_execution.py +0 -65
  194. waldiez/exporting/agent/utils/group_manager.py +0 -220
  195. waldiez/exporting/agent/utils/rag_user/__init__.py +0 -7
  196. waldiez/exporting/agent/utils/rag_user/rag_user.py +0 -209
  197. waldiez/exporting/agent/utils/reasoning.py +0 -36
  198. waldiez/exporting/agent/utils/swarm_agent.py +0 -469
  199. waldiez/exporting/agent/utils/teachability.py +0 -41
  200. waldiez/exporting/agent/utils/termination_message.py +0 -44
  201. waldiez/exporting/base/__init__.py +0 -25
  202. waldiez/exporting/base/agent_position.py +0 -75
  203. waldiez/exporting/base/base_exporter.py +0 -118
  204. waldiez/exporting/base/export_position.py +0 -48
  205. waldiez/exporting/base/import_position.py +0 -23
  206. waldiez/exporting/base/mixin.py +0 -137
  207. waldiez/exporting/base/utils/__init__.py +0 -18
  208. waldiez/exporting/base/utils/comments.py +0 -96
  209. waldiez/exporting/base/utils/path_check.py +0 -68
  210. waldiez/exporting/base/utils/to_string.py +0 -84
  211. waldiez/exporting/chats/chats_exporter.py +0 -240
  212. waldiez/exporting/chats/utils/swarm.py +0 -210
  213. waldiez/exporting/flow/flow_exporter.py +0 -528
  214. waldiez/exporting/flow/utils/agent_utils.py +0 -204
  215. waldiez/exporting/flow/utils/chat_utils.py +0 -71
  216. waldiez/exporting/flow/utils/def_main.py +0 -77
  217. waldiez/exporting/flow/utils/flow_content.py +0 -202
  218. waldiez/exporting/flow/utils/flow_names.py +0 -116
  219. waldiez/exporting/flow/utils/importing_utils.py +0 -227
  220. waldiez/exporting/models/models_exporter.py +0 -199
  221. waldiez/exporting/models/utils.py +0 -174
  222. waldiez/exporting/skills/__init__.py +0 -9
  223. waldiez/exporting/skills/skills_exporter.py +0 -176
  224. waldiez/exporting/skills/utils.py +0 -369
  225. waldiez/models/agents/agent/teachability.py +0 -70
  226. waldiez/models/agents/rag_user/rag_user.py +0 -60
  227. waldiez/models/agents/swarm_agent/__init__.py +0 -50
  228. waldiez/models/agents/swarm_agent/after_work.py +0 -179
  229. waldiez/models/agents/swarm_agent/on_condition.py +0 -105
  230. waldiez/models/agents/swarm_agent/on_condition_available.py +0 -142
  231. waldiez/models/agents/swarm_agent/on_condition_target.py +0 -40
  232. waldiez/models/agents/swarm_agent/swarm_agent.py +0 -107
  233. waldiez/models/agents/swarm_agent/swarm_agent_data.py +0 -124
  234. waldiez/models/flow/utils.py +0 -232
  235. waldiez/models/skill/__init__.py +0 -16
  236. waldiez/models/skill/extra_requirements.py +0 -36
  237. waldiez/models/skill/skill_data.py +0 -53
  238. waldiez/models/skill/skill_type.py +0 -8
  239. waldiez/running/running.py +0 -369
  240. waldiez/utils/pysqlite3_checker.py +0 -308
  241. waldiez/utils/rdps_checker.py +0 -122
  242. waldiez-0.4.7.dist-info/RECORD +0 -149
  243. /waldiez/models/agents/{captain_agent → captain}/__init__.py +0 -0
  244. /waldiez/models/agents/{captain_agent → captain}/captain_agent_lib_entry.py +0 -0
  245. {waldiez-0.4.7.dist-info → waldiez-0.4.9.dist-info}/WHEEL +0 -0
  246. {waldiez-0.4.7.dist-info → waldiez-0.4.9.dist-info}/entry_points.txt +0 -0
  247. {waldiez-0.4.7.dist-info → waldiez-0.4.9.dist-info}/licenses/LICENSE +0 -0
  248. {waldiez-0.4.7.dist-info → waldiez-0.4.9.dist-info}/licenses/NOTICE.md +0 -0
waldiez/io/_ws.py ADDED
@@ -0,0 +1,199 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ # flake8: noqa: E501
4
+ # pylint: disable=line-too-long
5
+ """WebSocket IOStream implementation for AsyncIO."""
6
+
7
+ import asyncio
8
+ from typing import Any, Protocol
9
+
10
+ HAS_WS_LIB = False
11
+
12
+ try:
13
+ from starlette.websockets import WebSocket # type: ignore[unused-ignore, unused-import, import-not-found, import-untyped] # noqa
14
+
15
+ HAS_WS_LIB = True # pyright: ignore
16
+ except ImportError:
17
+ pass
18
+
19
+ try:
20
+ import websockets # type: ignore[unused-ignore, unused-import, import-not-found, import-untyped] # noqa
21
+
22
+ HAS_WS_LIB = True # pyright: ignore
23
+ except ImportError: # pragma: no cover
24
+ pass
25
+
26
+
27
+ class WebSocketConnection(Protocol):
28
+ """Protocol for WebSocket connections."""
29
+
30
+ async def send_message(self, message: str) -> None:
31
+ """Send a message over the WebSocket connection.
32
+
33
+ Parameters
34
+ ----------
35
+ message : str
36
+ The message to send.
37
+ """
38
+
39
+ async def receive_message(
40
+ self,
41
+ timeout: float = 120,
42
+ ) -> str: # pyright: ignore
43
+ """Receive a message from the WebSocket connection.
44
+
45
+ Parameters
46
+ ----------
47
+ timeout : float, optional
48
+ The timeout for receiving the message. Defaults to 120 seconds.
49
+ If the timeout is reached, an empty string is returned.
50
+ If an error occurs, an empty string is returned.
51
+
52
+ Returns
53
+ -------
54
+ str
55
+ The received message.
56
+ """
57
+
58
+
59
+ class WebSocketsAdapter:
60
+ """Adapter for websockets library connections."""
61
+
62
+ def __init__(self, websocket: "websockets.ServerConnection"):
63
+ """Initialize the adapter.
64
+
65
+ Parameters
66
+ ----------
67
+ websocket : ServerConnection
68
+ The websockets library connection.
69
+ """
70
+ self.websocket = websocket
71
+
72
+ async def send_message(self, message: str) -> None:
73
+ """Send a message using websockets library.
74
+
75
+ Parameters
76
+ ----------
77
+ message : str
78
+ The message to send.
79
+ """
80
+ await self.websocket.send(message)
81
+
82
+ async def receive_message(self, timeout: float = 120) -> str:
83
+ """Receive a message using websockets library.
84
+
85
+ Parameters
86
+ ----------
87
+ timeout : float, optional
88
+ The timeout for receiving the message. Defaults to 120 seconds.
89
+
90
+ Returns
91
+ -------
92
+ str
93
+ The received message, decoded as a string.
94
+ """
95
+ # pylint: disable=too-many-try-statements
96
+ try:
97
+ response = await asyncio.wait_for(
98
+ self.websocket.recv(), timeout=timeout
99
+ )
100
+ if isinstance(response, bytes):
101
+ return response.decode("utf-8")
102
+ return response if isinstance(response, str) else str(response)
103
+ except asyncio.TimeoutError:
104
+ return ""
105
+ except BaseException: # pylint: disable=broad-exception-caught
106
+ # Handle other exceptions that may occur during receive
107
+ return ""
108
+
109
+
110
+ class StarletteAdapter:
111
+ """Adapter for Starlette/FastAPI WebSocket connections."""
112
+
113
+ def __init__(self, websocket: "WebSocket"):
114
+ """Initialize the adapter.
115
+
116
+ Parameters
117
+ ----------
118
+ websocket : WebSocket
119
+ The Starlette/FastAPI WebSocket connection.
120
+ """
121
+ self.websocket = websocket
122
+
123
+ async def send_message(self, message: str) -> None:
124
+ """Send a message using Starlette WebSocket.
125
+
126
+ Parameters
127
+ ----------
128
+ message : str
129
+ The message to send.
130
+ """
131
+ await self.websocket.send_text(message)
132
+
133
+ async def receive_message(self, timeout: float = 120) -> str:
134
+ """Receive a message using Starlette WebSocket.
135
+
136
+ Parameters
137
+ ----------
138
+ timeout : float, optional
139
+ The timeout for receiving the message. Defaults to 120 seconds.
140
+
141
+ Returns
142
+ -------
143
+ str
144
+ The received message, decoded as a string.
145
+ """
146
+ try:
147
+ return await asyncio.wait_for(
148
+ self.websocket.receive_text(), timeout=timeout
149
+ )
150
+ except asyncio.TimeoutError:
151
+ return ""
152
+ except BaseException: # pylint: disable=broad-exception-caught
153
+ # Handle other exceptions that may occur during receive
154
+ return ""
155
+
156
+
157
+ def create_websocket_adapter(websocket: Any) -> WebSocketConnection:
158
+ """Create an appropriate adapter for the given WebSocket connection.
159
+
160
+ Parameters
161
+ ----------
162
+ websocket : Any
163
+ The WebSocket connection (websockets or Starlette).
164
+
165
+ Returns
166
+ -------
167
+ WebSocketConnection
168
+ An adapter that implements the WebSocketConnection protocol.
169
+
170
+ Raises
171
+ ------
172
+ ValueError
173
+ If the WebSocket type is not supported.
174
+ """
175
+ # Check for Starlette/FastAPI WebSocket
176
+ if hasattr(websocket, "send_text") and hasattr(websocket, "receive_text"):
177
+ return StarletteAdapter(websocket)
178
+
179
+ # Check for websockets library
180
+ if hasattr(websocket, "send") and hasattr(websocket, "recv"):
181
+ return WebSocketsAdapter(websocket)
182
+
183
+ raise ValueError(
184
+ "Unsupported WebSocket type. "
185
+ "Must be either websockets.ServerConnection "
186
+ "or starlette.websockets.WebSocket. "
187
+ f"Received: {type(websocket)}"
188
+ )
189
+
190
+
191
+ def is_websocket_available() -> bool:
192
+ """Check if any WebSocket library is available.
193
+
194
+ Returns
195
+ -------
196
+ bool
197
+ True if websockets or starlette is available, False otherwise.
198
+ """
199
+ return HAS_WS_LIB
@@ -0,0 +1,60 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+
4
+ """Models package for structured I/O."""
5
+
6
+ # Base models
7
+ from .base import PrintMessage, StructuredBase, UserInputRequest
8
+
9
+ # Constants and mappings
10
+ from .constants import (
11
+ CONTENT_MAPPING,
12
+ ContentMappingEntry,
13
+ ContentTypeKey,
14
+ MediaContent,
15
+ )
16
+
17
+ # Content models
18
+ from .content import (
19
+ AudioContent,
20
+ AudioMediaContent,
21
+ FileContent,
22
+ FileMediaContent,
23
+ ImageContent,
24
+ ImageMediaContent,
25
+ ImageUrlMediaContent,
26
+ TextMediaContent,
27
+ VideoContent,
28
+ VideoMediaContent,
29
+ )
30
+
31
+ # User models
32
+ from .user_input import UserInputData
33
+ from .user_response import UserResponse
34
+
35
+ __all__ = [
36
+ # Base models
37
+ "StructuredBase",
38
+ "UserInputRequest",
39
+ "PrintMessage",
40
+ # Content base types
41
+ "ImageContent",
42
+ "VideoContent",
43
+ "AudioContent",
44
+ "FileContent",
45
+ "MediaContent",
46
+ # Content models
47
+ "TextMediaContent",
48
+ "ImageMediaContent",
49
+ "ImageUrlMediaContent",
50
+ "VideoMediaContent",
51
+ "AudioMediaContent",
52
+ "FileMediaContent",
53
+ # User models
54
+ "UserInputData",
55
+ "UserResponse",
56
+ # Constants
57
+ "ContentTypeKey",
58
+ "ContentMappingEntry",
59
+ "CONTENT_MAPPING",
60
+ ]
@@ -0,0 +1,66 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+
4
+ """Base models for structured data."""
5
+
6
+ from typing import Any
7
+
8
+ from pydantic import BaseModel, ConfigDict, Field
9
+
10
+ from ..utils import MessageType, gen_id, now
11
+
12
+
13
+ class StructuredBase(BaseModel):
14
+ """Base model for structured data."""
15
+
16
+ id: str = Field(default_factory=gen_id)
17
+ type: MessageType
18
+ timestamp: str = Field(default_factory=now)
19
+ model_config = ConfigDict(
20
+ extra="ignore",
21
+ arbitrary_types_allowed=True,
22
+ )
23
+
24
+
25
+ class UserInputRequest(StructuredBase):
26
+ """User input prompt model."""
27
+
28
+ type: MessageType = "input_request"
29
+ request_id: str
30
+ prompt: str
31
+ password: bool = False
32
+
33
+
34
+ class PrintMessage(StructuredBase):
35
+ """Model for print messages."""
36
+
37
+ type: MessageType = "print"
38
+ data: str
39
+
40
+ @classmethod
41
+ def create(cls, *args: Any, **kwargs: Any) -> "PrintMessage":
42
+ """Create a new print message.
43
+
44
+ Parameters
45
+ ----------
46
+ *args : Any
47
+ Positional arguments (not used).
48
+ **kwargs : Any
49
+ Keyword arguments
50
+
51
+ Returns
52
+ -------
53
+ PrintMessage
54
+ A new print message instance with the provided data.
55
+ """
56
+ message = " ".join(str(arg) for arg in args)
57
+ if "file" in kwargs:
58
+ file = kwargs.pop("file")
59
+ if hasattr(file, "getvalue"):
60
+ io_value = file.getvalue()
61
+ if isinstance(io_value, bytes):
62
+ io_value = io_value.decode("utf-8", errors="replace")
63
+ message += io_value
64
+ end = kwargs.get("end", "\n")
65
+ message += end
66
+ return cls(data=message)
@@ -0,0 +1,78 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+
4
+ """Constants and type mappings for content models."""
5
+
6
+ from typing import Type, TypedDict, Union
7
+
8
+ from typing_extensions import Literal
9
+
10
+ from .content.audio import AudioMediaContent
11
+ from .content.file import FileMediaContent
12
+ from .content.image import ImageMediaContent, ImageUrlMediaContent
13
+ from .content.text import TextMediaContent
14
+ from .content.video import VideoMediaContent
15
+
16
+ MediaContent = Union[
17
+ TextMediaContent,
18
+ ImageMediaContent,
19
+ ImageUrlMediaContent,
20
+ VideoMediaContent,
21
+ AudioMediaContent,
22
+ FileMediaContent,
23
+ ]
24
+
25
+ ContentTypeKey = Literal["text", "image", "image_url", "video", "audio", "file"]
26
+ """Possible content types for the mapping."""
27
+
28
+
29
+ class ContentMappingEntry(TypedDict):
30
+ """TypedDict for content mapping entries.
31
+
32
+ Attributes
33
+ ----------
34
+ fields: List[str]
35
+ List of possible field names for the content type
36
+ cls: Type[MediaContent]
37
+ The class to instantiate for this content type
38
+ required_field: str
39
+ The field name required by the class constructor
40
+ """
41
+
42
+ fields: list[str]
43
+ cls: Type[MediaContent]
44
+ required_field: str
45
+
46
+
47
+ CONTENT_MAPPING: dict[ContentTypeKey, ContentMappingEntry] = {
48
+ "text": {
49
+ "fields": ["text"],
50
+ "cls": TextMediaContent,
51
+ "required_field": "text",
52
+ },
53
+ "image": {
54
+ "fields": ["image"],
55
+ "cls": ImageMediaContent,
56
+ "required_field": "image",
57
+ },
58
+ "image_url": {
59
+ "fields": ["image_url", "url"],
60
+ "cls": ImageUrlMediaContent,
61
+ "required_field": "image_url",
62
+ },
63
+ "video": {
64
+ "fields": ["video"],
65
+ "cls": VideoMediaContent,
66
+ "required_field": "video",
67
+ },
68
+ "audio": {
69
+ "fields": ["audio"],
70
+ "cls": AudioMediaContent,
71
+ "required_field": "audio",
72
+ },
73
+ "file": {
74
+ "fields": ["file"],
75
+ "cls": FileMediaContent,
76
+ "required_field": "file",
77
+ },
78
+ }
@@ -0,0 +1,23 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ """Content models for media types."""
4
+
5
+ from .audio import AudioMediaContent
6
+ from .base import AudioContent, FileContent, ImageContent, VideoContent
7
+ from .file import FileMediaContent
8
+ from .image import ImageMediaContent, ImageUrlMediaContent
9
+ from .text import TextMediaContent
10
+ from .video import VideoMediaContent
11
+
12
+ __all__ = [
13
+ "AudioMediaContent",
14
+ "AudioContent",
15
+ "VideoMediaContent",
16
+ "VideoContent",
17
+ "ImageMediaContent",
18
+ "ImageUrlMediaContent",
19
+ "ImageContent",
20
+ "FileMediaContent",
21
+ "FileContent",
22
+ "TextMediaContent",
23
+ ]
@@ -0,0 +1,43 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ # pylint: disable=unused-argument
4
+ """Audio media content models."""
5
+
6
+ from pathlib import Path
7
+ from typing import Literal
8
+
9
+ from pydantic import BaseModel
10
+
11
+ from .base import AudioContent
12
+
13
+
14
+ class AudioMediaContent(BaseModel):
15
+ """Audio media content."""
16
+
17
+ type: Literal["audio"] = "audio"
18
+ audio: AudioContent
19
+
20
+ def to_string(
21
+ self,
22
+ uploads_root: Path | None,
23
+ base_name: str | None = None,
24
+ ) -> str:
25
+ """Convert the content to a string.
26
+
27
+ Parameters
28
+ ----------
29
+ uploads_root : Path | None
30
+ The root directory for storing images, optional.
31
+ base_name : str | None
32
+ The base name for the image file, optional.
33
+
34
+ Returns
35
+ -------
36
+ str
37
+ The string representation of the content.
38
+ """
39
+ if self.audio.url:
40
+ return f"<audio src='{self.audio.url}'></audio>"
41
+ if self.audio.file:
42
+ return f"<audio src='{self.audio.file}'></audio>"
43
+ return str(self.audio.file)
@@ -0,0 +1,45 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ """Base content models for media types."""
4
+
5
+ from typing import Any, Optional
6
+
7
+ from pydantic import BaseModel
8
+
9
+
10
+ class ImageContent(BaseModel):
11
+ """Image content model."""
12
+
13
+ url: Optional[str] = None
14
+ file: Optional[Any] = None # File type not directly mappable in Python
15
+ alt: Optional[str] = None
16
+
17
+
18
+ class VideoContent(BaseModel):
19
+ """Video content model."""
20
+
21
+ url: Optional[str] = None
22
+ file: Optional[Any] = None
23
+ duration: Optional[int] = None
24
+ thumbnailUrl: Optional[str] = None
25
+ mimeType: Optional[str] = None
26
+
27
+
28
+ class AudioContent(BaseModel):
29
+ """Audio content model."""
30
+
31
+ url: Optional[str] = None
32
+ file: Optional[Any] = None
33
+ duration: Optional[int] = None
34
+ transcript: Optional[str] = None
35
+
36
+
37
+ class FileContent(BaseModel):
38
+ """File content model."""
39
+
40
+ url: Optional[str] = None
41
+ file: Optional[Any] = None
42
+ name: str
43
+ size: Optional[int] = None
44
+ type: Optional[str] = None
45
+ previewUrl: Optional[str] = None
@@ -0,0 +1,43 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ # pylint: disable=unused-argument
4
+ """File media content models."""
5
+
6
+ from pathlib import Path
7
+ from typing import Literal
8
+
9
+ from pydantic import BaseModel
10
+
11
+ from .base import FileContent
12
+
13
+
14
+ class FileMediaContent(BaseModel):
15
+ """File media content."""
16
+
17
+ type: Literal["file"] = "file"
18
+ file: FileContent
19
+
20
+ def to_string(
21
+ self,
22
+ uploads_root: Path | None,
23
+ base_name: str | None = None,
24
+ ) -> str:
25
+ """Convert the content to a string.
26
+
27
+ Parameters
28
+ ----------
29
+ uploads_root : Path | None
30
+ The root directory for storing images, optional.
31
+ base_name : str | None
32
+ The base name for the image file, optional.
33
+
34
+ Returns
35
+ -------
36
+ str
37
+ The string representation of the content.
38
+ """
39
+ if self.file.url:
40
+ return f"<a href='{self.file.url}'>{self.file.name}</a>"
41
+ if self.file.file:
42
+ return f"<a href='{self.file.file}'>{self.file.name}</a>"
43
+ return str(self.file.file)
@@ -0,0 +1,96 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ # pylint: disable=unused-argument
4
+ """Image media content models."""
5
+
6
+ from pathlib import Path
7
+
8
+ from pydantic import BaseModel
9
+ from typing_extensions import Literal
10
+
11
+ from ...utils import get_image
12
+ from .base import ImageContent
13
+
14
+
15
+ class ImageMediaContent(BaseModel):
16
+ """Image media content."""
17
+
18
+ type: Literal["image"] = "image"
19
+ image: ImageContent
20
+
21
+ def to_string(
22
+ self,
23
+ uploads_root: Path | None,
24
+ base_name: str | None = None,
25
+ ) -> str:
26
+ """Convert the content to a string.
27
+
28
+ Parameters
29
+ ----------
30
+ uploads_root : Path | None
31
+ The root directory for storing images, optional.
32
+ base_name : str | None
33
+ The base name for the image file, optional.
34
+
35
+ Returns
36
+ -------
37
+ str
38
+ The string representation of the content.
39
+ """
40
+ if self.image.url:
41
+ image = get_image(
42
+ uploads_root=uploads_root,
43
+ image_data=self.image.url,
44
+ base_name=base_name,
45
+ )
46
+ return f"<img {image}>"
47
+ if self.image.file:
48
+ image = get_image(
49
+ uploads_root=uploads_root,
50
+ image_data=self.image.file,
51
+ base_name=base_name,
52
+ )
53
+ return f"<img {image}>"
54
+ return str(self.image.file)
55
+
56
+
57
+ class ImageUrlMediaContent(BaseModel):
58
+ """Image URL media content."""
59
+
60
+ type: Literal["image_url"] = "image_url"
61
+ image_url: ImageContent
62
+
63
+ def to_string(
64
+ self,
65
+ uploads_root: Path | None,
66
+ base_name: str | None = None,
67
+ ) -> str:
68
+ """Convert the content to a string.
69
+
70
+ Parameters
71
+ ----------
72
+ uploads_root : Path | None
73
+ The root directory for storing images, optional.
74
+ base_name : str | None
75
+ The base name for the image file, optional.
76
+
77
+ Returns
78
+ -------
79
+ str
80
+ The string representation of the content.
81
+ """
82
+ if self.image_url.url:
83
+ image = get_image(
84
+ uploads_root=uploads_root,
85
+ image_data=self.image_url.url,
86
+ base_name=base_name,
87
+ )
88
+ return f"<img {image}>"
89
+ if self.image_url.file:
90
+ image = get_image(
91
+ uploads_root=uploads_root,
92
+ image_data=self.image_url.file,
93
+ base_name=base_name,
94
+ )
95
+ return f"<img {image}>"
96
+ return str(self.image_url.file)
@@ -0,0 +1,37 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ # pylint: disable=unused-argument
4
+ """Text media content models."""
5
+
6
+ from pathlib import Path
7
+
8
+ from pydantic import BaseModel
9
+ from typing_extensions import Literal
10
+
11
+
12
+ class TextMediaContent(BaseModel):
13
+ """Text media content."""
14
+
15
+ type: Literal["text"] = "text"
16
+ text: str
17
+
18
+ def to_string(
19
+ self,
20
+ uploads_root: Path | None = None,
21
+ base_name: str | None = None,
22
+ ) -> str:
23
+ """Convert the content to a string.
24
+
25
+ Parameters
26
+ ----------
27
+ uploads_root : Path | None
28
+ The root directory for storing images, optional.
29
+ base_name : str | None
30
+ The base name for the image file, optional.
31
+
32
+ Returns
33
+ -------
34
+ str
35
+ The string representation of the content.
36
+ """
37
+ return self.text