waldiez 0.5.10__py3-none-any.whl → 0.6.1__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 (192) hide show
  1. waldiez/__init__.py +1 -1
  2. waldiez/_version.py +1 -1
  3. waldiez/cli.py +19 -7
  4. waldiez/cli_extras/jupyter.py +3 -0
  5. waldiez/cli_extras/runner.py +3 -1
  6. waldiez/cli_extras/studio.py +3 -1
  7. waldiez/exporter.py +9 -3
  8. waldiez/exporting/agent/exporter.py +15 -16
  9. waldiez/exporting/agent/extras/captain_agent_extras.py +6 -6
  10. waldiez/exporting/agent/extras/doc_agent_extras.py +6 -6
  11. waldiez/exporting/agent/extras/group_manager_agent_extas.py +40 -24
  12. waldiez/exporting/agent/extras/group_member_extras.py +6 -5
  13. waldiez/exporting/agent/extras/handoffs/after_work.py +2 -1
  14. waldiez/exporting/agent/extras/handoffs/available.py +2 -1
  15. waldiez/exporting/agent/extras/handoffs/condition.py +3 -2
  16. waldiez/exporting/agent/extras/handoffs/handoff.py +2 -1
  17. waldiez/exporting/agent/extras/handoffs/target.py +7 -4
  18. waldiez/exporting/agent/extras/rag/chroma_extras.py +27 -19
  19. waldiez/exporting/agent/extras/rag/mongo_extras.py +8 -8
  20. waldiez/exporting/agent/extras/rag/pgvector_extras.py +5 -5
  21. waldiez/exporting/agent/extras/rag/qdrant_extras.py +5 -4
  22. waldiez/exporting/agent/extras/rag/vector_db_extras.py +1 -1
  23. waldiez/exporting/agent/extras/rag_user_proxy_agent_extras.py +5 -7
  24. waldiez/exporting/agent/extras/reasoning_agent_extras.py +3 -5
  25. waldiez/exporting/agent/termination.py +1 -0
  26. waldiez/exporting/chats/exporter.py +4 -4
  27. waldiez/exporting/chats/processor.py +1 -2
  28. waldiez/exporting/chats/utils/common.py +89 -48
  29. waldiez/exporting/chats/utils/group.py +9 -9
  30. waldiez/exporting/chats/utils/nested.py +7 -7
  31. waldiez/exporting/chats/utils/sequential.py +1 -1
  32. waldiez/exporting/chats/utils/single.py +2 -2
  33. waldiez/exporting/core/constants.py +3 -1
  34. waldiez/exporting/core/content.py +7 -7
  35. waldiez/exporting/core/context.py +5 -3
  36. waldiez/exporting/core/exporter.py +5 -3
  37. waldiez/exporting/core/exporters.py +2 -2
  38. waldiez/exporting/core/extras/agent_extras/captain_extras.py +2 -2
  39. waldiez/exporting/core/extras/agent_extras/group_manager_extras.py +2 -2
  40. waldiez/exporting/core/extras/agent_extras/rag_user_extras.py +2 -2
  41. waldiez/exporting/core/extras/agent_extras/standard_extras.py +3 -8
  42. waldiez/exporting/core/extras/base.py +7 -5
  43. waldiez/exporting/core/extras/flow_extras.py +4 -5
  44. waldiez/exporting/core/extras/model_extras.py +2 -2
  45. waldiez/exporting/core/extras/path_resolver.py +1 -2
  46. waldiez/exporting/core/extras/serializer.py +13 -11
  47. waldiez/exporting/core/protocols.py +6 -5
  48. waldiez/exporting/core/result.py +25 -28
  49. waldiez/exporting/core/types.py +11 -10
  50. waldiez/exporting/core/utils/llm_config.py +4 -4
  51. waldiez/exporting/core/validation.py +10 -11
  52. waldiez/exporting/flow/execution_generator.py +99 -10
  53. waldiez/exporting/flow/exporter.py +2 -2
  54. waldiez/exporting/flow/factory.py +2 -2
  55. waldiez/exporting/flow/file_generator.py +4 -2
  56. waldiez/exporting/flow/merger.py +5 -3
  57. waldiez/exporting/flow/orchestrator.py +72 -2
  58. waldiez/exporting/flow/utils/common.py +6 -6
  59. waldiez/exporting/flow/utils/importing.py +7 -8
  60. waldiez/exporting/flow/utils/linting.py +25 -9
  61. waldiez/exporting/flow/utils/logging.py +5 -77
  62. waldiez/exporting/models/exporter.py +8 -8
  63. waldiez/exporting/models/processor.py +5 -5
  64. waldiez/exporting/tools/exporter.py +2 -2
  65. waldiez/exporting/tools/processor.py +7 -4
  66. waldiez/io/__init__.py +11 -5
  67. waldiez/io/_ws.py +12 -6
  68. waldiez/io/models/constants.py +10 -10
  69. waldiez/io/models/content/audio.py +1 -0
  70. waldiez/io/models/content/base.py +20 -18
  71. waldiez/io/models/content/file.py +1 -0
  72. waldiez/io/models/content/image.py +1 -0
  73. waldiez/io/models/content/text.py +1 -0
  74. waldiez/io/models/content/video.py +1 -0
  75. waldiez/io/models/user_input.py +10 -5
  76. waldiez/io/models/user_response.py +17 -16
  77. waldiez/io/mqtt.py +18 -31
  78. waldiez/io/redis.py +18 -22
  79. waldiez/io/structured.py +122 -70
  80. waldiez/io/utils.py +19 -10
  81. waldiez/io/ws.py +7 -3
  82. waldiez/logger.py +16 -3
  83. waldiez/models/agents/__init__.py +3 -0
  84. waldiez/models/agents/agent/agent.py +25 -17
  85. waldiez/models/agents/agent/agent_data.py +25 -22
  86. waldiez/models/agents/agent/code_execution.py +9 -11
  87. waldiez/models/agents/agent/termination_message.py +10 -12
  88. waldiez/models/agents/agent/update_system_message.py +2 -4
  89. waldiez/models/agents/agents.py +8 -8
  90. waldiez/models/agents/assistant/assistant.py +6 -3
  91. waldiez/models/agents/assistant/assistant_data.py +2 -2
  92. waldiez/models/agents/captain/captain_agent.py +7 -4
  93. waldiez/models/agents/captain/captain_agent_data.py +5 -7
  94. waldiez/models/agents/doc_agent/doc_agent.py +7 -4
  95. waldiez/models/agents/doc_agent/doc_agent_data.py +9 -10
  96. waldiez/models/agents/doc_agent/rag_query_engine.py +10 -12
  97. waldiez/models/agents/extra_requirements.py +3 -3
  98. waldiez/models/agents/group_manager/group_manager.py +12 -7
  99. waldiez/models/agents/group_manager/group_manager_data.py +13 -12
  100. waldiez/models/agents/group_manager/speakers.py +17 -19
  101. waldiez/models/agents/rag_user_proxy/rag_user_proxy.py +7 -4
  102. waldiez/models/agents/rag_user_proxy/rag_user_proxy_data.py +4 -1
  103. waldiez/models/agents/rag_user_proxy/retrieve_config.py +69 -63
  104. waldiez/models/agents/rag_user_proxy/vector_db_config.py +19 -19
  105. waldiez/models/agents/reasoning/reasoning_agent.py +7 -4
  106. waldiez/models/agents/reasoning/reasoning_agent_data.py +3 -2
  107. waldiez/models/agents/reasoning/reasoning_agent_reason_config.py +8 -8
  108. waldiez/models/agents/user_proxy/user_proxy.py +6 -3
  109. waldiez/models/agents/user_proxy/user_proxy_data.py +1 -1
  110. waldiez/models/chat/chat.py +28 -20
  111. waldiez/models/chat/chat_data.py +22 -21
  112. waldiez/models/chat/chat_message.py +9 -9
  113. waldiez/models/chat/chat_nested.py +9 -9
  114. waldiez/models/chat/chat_summary.py +6 -6
  115. waldiez/models/common/__init__.py +2 -0
  116. waldiez/models/common/ag2_version.py +2 -0
  117. waldiez/models/common/base.py +2 -0
  118. waldiez/models/common/dict_utils.py +8 -6
  119. waldiez/models/common/handoff.py +20 -17
  120. waldiez/models/common/method_utils.py +9 -7
  121. waldiez/models/common/naming.py +49 -0
  122. waldiez/models/flow/flow.py +11 -6
  123. waldiez/models/flow/flow_data.py +23 -17
  124. waldiez/models/flow/info.py +3 -3
  125. waldiez/models/flow/naming.py +2 -1
  126. waldiez/models/model/_aws.py +11 -13
  127. waldiez/models/model/_llm.py +8 -0
  128. waldiez/models/model/_price.py +2 -4
  129. waldiez/models/model/extra_requirements.py +1 -3
  130. waldiez/models/model/model.py +2 -2
  131. waldiez/models/model/model_data.py +21 -21
  132. waldiez/models/tool/extra_requirements.py +2 -4
  133. waldiez/models/tool/predefined/_duckduckgo.py +1 -0
  134. waldiez/models/tool/predefined/_email.py +4 -0
  135. waldiez/models/tool/predefined/_google.py +1 -0
  136. waldiez/models/tool/predefined/_perplexity.py +2 -1
  137. waldiez/models/tool/predefined/_searxng.py +2 -1
  138. waldiez/models/tool/predefined/_tavily.py +1 -0
  139. waldiez/models/tool/predefined/_wikipedia.py +2 -1
  140. waldiez/models/tool/predefined/_youtube.py +1 -0
  141. waldiez/models/tool/tool.py +8 -5
  142. waldiez/models/tool/tool_data.py +2 -2
  143. waldiez/models/waldiez.py +152 -4
  144. waldiez/runner.py +11 -5
  145. waldiez/running/async_utils.py +192 -0
  146. waldiez/running/base_runner.py +155 -241
  147. waldiez/running/dir_utils.py +52 -0
  148. waldiez/running/environment.py +10 -44
  149. waldiez/running/events_mixin.py +252 -0
  150. waldiez/running/exceptions.py +20 -0
  151. waldiez/running/gen_seq_diagram.py +18 -15
  152. waldiez/running/io_utils.py +216 -0
  153. waldiez/running/protocol.py +11 -5
  154. waldiez/running/requirements_mixin.py +65 -0
  155. waldiez/running/results_mixin.py +926 -0
  156. waldiez/running/standard_runner.py +24 -27
  157. waldiez/running/step_by_step/breakpoints_mixin.py +503 -47
  158. waldiez/running/step_by_step/command_handler.py +154 -0
  159. waldiez/running/step_by_step/events_processor.py +379 -0
  160. waldiez/running/step_by_step/step_by_step_models.py +425 -41
  161. waldiez/running/step_by_step/step_by_step_runner.py +437 -382
  162. waldiez/running/subprocess_runner/__base__.py +13 -8
  163. waldiez/running/subprocess_runner/_async_runner.py +6 -4
  164. waldiez/running/subprocess_runner/_sync_runner.py +11 -6
  165. waldiez/running/subprocess_runner/runner.py +48 -23
  166. waldiez/running/timeline_processor.py +1 -1
  167. waldiez/utils/__init__.py +2 -0
  168. waldiez/utils/conflict_checker.py +4 -4
  169. waldiez/utils/python_manager.py +415 -0
  170. waldiez/ws/__init__.py +8 -7
  171. waldiez/ws/_file_handler.py +18 -20
  172. waldiez/ws/_mock.py +75 -0
  173. waldiez/ws/cli.py +58 -10
  174. waldiez/ws/client_manager.py +77 -53
  175. waldiez/ws/errors.py +3 -0
  176. waldiez/ws/models.py +61 -53
  177. waldiez/ws/reloader.py +33 -4
  178. waldiez/ws/server.py +121 -52
  179. waldiez/ws/session_manager.py +8 -9
  180. waldiez/ws/session_stats.py +1 -1
  181. waldiez/ws/utils.py +33 -5
  182. {waldiez-0.5.10.dist-info → waldiez-0.6.1.dist-info}/METADATA +107 -109
  183. waldiez-0.6.1.dist-info/RECORD +254 -0
  184. waldiez/running/post_run.py +0 -180
  185. waldiez/running/pre_run.py +0 -159
  186. waldiez/running/run_results.py +0 -14
  187. waldiez/running/utils.py +0 -511
  188. waldiez-0.5.10.dist-info/RECORD +0 -248
  189. {waldiez-0.5.10.dist-info → waldiez-0.6.1.dist-info}/WHEEL +0 -0
  190. {waldiez-0.5.10.dist-info → waldiez-0.6.1.dist-info}/entry_points.txt +0 -0
  191. {waldiez-0.5.10.dist-info → waldiez-0.6.1.dist-info}/licenses/LICENSE +0 -0
  192. {waldiez-0.5.10.dist-info → waldiez-0.6.1.dist-info}/licenses/NOTICE.md +0 -0
@@ -82,47 +82,13 @@ def get_start_logging(is_async: bool, for_notebook: bool) -> str:
82
82
  '''
83
83
 
84
84
 
85
- # pylint: disable=differing-param-doc,differing-type-doc
86
- # noinspection PyUnresolvedReferences
87
85
  def get_sync_sqlite_out() -> str:
88
- r"""Get the sqlite to csv and json conversion code string.
86
+ """Get the sqlite to csv and json conversion code string.
89
87
 
90
88
  Returns
91
89
  -------
92
90
  str
93
91
  The sqlite to csv and json conversion code string.
94
-
95
- Example
96
- -------
97
- ```python
98
- >>> get_sqlite_outputs()
99
- def get_sqlite_out(dbname: str, table: str, csv_file: str) -> None:
100
- \"\"\"Convert a sqlite table to csv and json files.
101
-
102
- Parameters
103
- ----------
104
- dbname : str
105
- The sqlite database name.
106
- table : str
107
- The table name.
108
- csv_file : str
109
- The csv file name.
110
- \"\"\"
111
- conn = sqlite3.connect(dbname)
112
- query = f"SELECT * FROM {table}" # nosec
113
- cursor = conn.execute(query)
114
- rows = cursor.fetchall()
115
- column_names = [description[0] for description in cursor.description]
116
- data = [dict(zip(column_names, row, strict=True)) for row in rows]
117
- conn.close()
118
- with open(csv_file, "w", newline="", encoding="utf-8") as file:
119
- csv_writer = csv.DictWriter(file, fieldnames=column_names)
120
- csv_writer.writeheader()
121
- csv_writer.writerows(data)
122
- json_file = csv_file.replace(".csv", ".json")
123
- with open(json_file, "w", encoding="utf-8") as file:
124
- json.dump(data, file, indent=4, ensure_ascii=False)
125
- ```
126
92
  """
127
93
  content = "\n\n"
128
94
  content += (
@@ -160,58 +126,20 @@ def get_sync_sqlite_out() -> str:
160
126
  content += " csv_writer.writeheader()\n"
161
127
  content += " csv_writer.writerows(data)\n"
162
128
  content += ' json_file = csv_file.replace(".csv", ".json")\n'
163
- content += ' with open(json_file, "w", encoding="utf-8") as file:\n'
129
+ content += ' with open(json_file, "w", encoding="utf-8", newline="\\n") as file:\n'
164
130
  content += " json.dump(data, file, indent=4, ensure_ascii=False)\n"
165
131
  content += "\n"
166
132
  return content
167
133
 
168
134
 
169
- # pylint: disable=differing-param-doc,differing-type-doc,line-too-long
170
- # noinspection PyUnresolvedReferences
135
+ # pylint: disable=line-too-long
171
136
  def get_async_sqlite_out() -> str:
172
- r"""Get the sqlite to csv and json conversion code string.
137
+ """Get the sqlite to csv and json conversion code string.
173
138
 
174
139
  Returns
175
140
  -------
176
141
  str
177
142
  The sqlite to csv and json conversion code string.
178
-
179
- Example
180
- -------
181
- ```python
182
- >>> get_sqlite_outputs()
183
- async def get_sqlite_out(dbname: str, table: str, csv_file: str) -> None:
184
- \"\"\"Convert a sqlite table to csv and json files.
185
-
186
- Parameters
187
- ----------
188
- dbname : str
189
- The sqlite database name.
190
- table : str
191
- The table name.
192
- csv_file : str
193
- The csv file name.
194
- \"\"\"
195
- conn = await aiosqlite.connect(dbname)
196
- query = f"SELECT * FROM {table}" # nosec
197
- try:
198
- cursor = await conn.execute(query)
199
- except BaseException: # pylint: disable=broad-exception-caught
200
- await conn.close()
201
- return
202
- rows = await cursor.fetchall()
203
- column_names = [description[0] for description in cursor.description]
204
- data = [dict(zip(column_names, row, strict=True)) for row in rows]
205
- await cursor.close()
206
- await conn.close()
207
- async with aiofiles.open(csv_file, "w", newline="", encoding="utf-8") as file:
208
- csv_writer = csv.DictWriter(file, fieldnames=column_names)
209
- csv_writer.writeheader()
210
- csv_writer.writerows(data)
211
- json_file = csv_file.replace(".csv", ".json")
212
- async with aiofiles.open(json_file, "w", encoding="utf-8") as file:
213
- await file.write(json.dumps(data, indent=4, ensure_ascii=False)
214
- ```
215
143
  """
216
144
  # fmt: off
217
145
  content = "\n\n"
@@ -244,7 +172,7 @@ def get_async_sqlite_out() -> str:
244
172
  content += " await csv_writer.writeheader()\n"
245
173
  content += " await csv_writer.writerows(data)\n"
246
174
  content += ' json_file = csv_file.replace(".csv", ".json")\n'
247
- content += ' async with aiofiles.open(json_file, "w", encoding="utf-8") as file:\n'
175
+ content += ' async with aiofiles.open(json_file, "w", encoding="utf-8", newline="\\n") as file:\n'
248
176
  content += " await file.write(json.dumps(data, indent=4, ensure_ascii=False))\n"
249
177
  content += "\n"
250
178
  # fmt: on
@@ -3,7 +3,7 @@
3
3
  """Models exporter module."""
4
4
 
5
5
  from pathlib import Path
6
- from typing import Any, Optional, Union
6
+ from typing import Any
7
7
 
8
8
  from waldiez.models import WaldiezAgent, WaldiezModel
9
9
 
@@ -31,9 +31,9 @@ class ModelsExporter(Exporter[ModelExtras]):
31
31
  models: list[WaldiezModel],
32
32
  model_names: dict[str, str],
33
33
  for_notebook: bool = False,
34
- cache_seed: Optional[int] = None,
35
- output_dir: Optional[Union[str, Path]] = None,
36
- context: Optional[ExporterContext] = None,
34
+ cache_seed: int | None = None,
35
+ output_dir: str | Path | None = None,
36
+ context: ExporterContext | None = None,
37
37
  **kwargs: Any,
38
38
  ):
39
39
  """Initialize the models exporter."""
@@ -94,7 +94,7 @@ class ModelsExporter(Exporter[ModelExtras]):
94
94
 
95
95
  return extras
96
96
 
97
- def generate_main_content(self) -> Optional[str]:
97
+ def generate_main_content(self) -> str | None:
98
98
  """Generate the main models content (LLM configs).
99
99
 
100
100
  Returns
@@ -146,7 +146,7 @@ class ModelsExporter(Exporter[ModelExtras]):
146
146
  or "llm_config=False" if no models are configured.
147
147
  """
148
148
  if not agent.data.model_ids:
149
- return " llm_config=False, # pyright: ignore\n"
149
+ return " llm_config=False,\n"
150
150
 
151
151
  # Get model configs for this agent
152
152
  model_configs: list[str] = []
@@ -154,9 +154,9 @@ class ModelsExporter(Exporter[ModelExtras]):
154
154
  model_name = self.model_names.get(model_id)
155
155
  if model_name:
156
156
  model_configs.append(f"{model_name}_llm_config")
157
- tab = " " * 4
157
+ tab: str = " " * 4
158
158
  if not model_configs:
159
- return f"{tab}llm_config=False, # pyright: ignore\n"
159
+ return f"{tab}llm_config=False,\n"
160
160
 
161
161
  config_list = f",\n{tab}{tab}{tab}".join(model_configs)
162
162
  llm_config = f"""{tab}llm_config=autogen.LLMConfig(
@@ -5,7 +5,6 @@
5
5
 
6
6
  from dataclasses import dataclass
7
7
  from pathlib import Path
8
- from typing import Optional
9
8
 
10
9
  from waldiez.models import WaldiezModel
11
10
 
@@ -20,7 +19,7 @@ class ModelProcessingResult:
20
19
  """Result from processing models."""
21
20
 
22
21
  llm_configs_content: str = ""
23
- api_keys_file: Optional[Path] = None
22
+ api_keys_file: Path | None = None
24
23
  needs_api_key_loader: bool = False
25
24
 
26
25
 
@@ -32,8 +31,8 @@ class ModelProcessor:
32
31
  flow_name: str,
33
32
  models: list[WaldiezModel],
34
33
  model_names: dict[str, str],
35
- serializer: Optional[Serializer] = None,
36
- output_dir: Optional[Path] = None,
34
+ serializer: Serializer | None = None,
35
+ output_dir: Path | None = None,
37
36
  ):
38
37
  self.flow_name = flow_name
39
38
  self.models = models
@@ -93,8 +92,9 @@ __{flow_name_upper}_MODEL_API_KEYS__ = {{'''
93
92
  for model in self.models:
94
93
  model_name = self.model_names[model.id]
95
94
  key_env = model.api_key_env_key
95
+ api_keys_content += "\n"
96
96
  api_keys_content += (
97
- "\n" + f' "{model_name}": '
97
+ f' "{model_name}": '
98
98
  f'{{"key": "{model.api_key}", "env_key": "{key_env}"}},'
99
99
  )
100
100
 
@@ -4,7 +4,7 @@
4
4
  """Tools exporter."""
5
5
 
6
6
  from pathlib import Path
7
- from typing import Any, Optional
7
+ from typing import Any
8
8
 
9
9
  from waldiez.models import WaldiezAgent, WaldiezTool
10
10
 
@@ -148,7 +148,7 @@ class ToolsExporter(Exporter[ToolExtras]):
148
148
  )
149
149
  return extras
150
150
 
151
- def generate_main_content(self) -> Optional[str]:
151
+ def generate_main_content(self) -> str | None:
152
152
  """Generate the main tools content."""
153
153
  # handled as positioned content
154
154
  return None
@@ -18,10 +18,12 @@ class ToolProcessingResult:
18
18
  """Result from processing tools."""
19
19
 
20
20
  content: str = ""
21
- builtin_imports: list[str] = field(default_factory=list[str])
22
- third_party_imports: list[str] = field(default_factory=list[str])
21
+ builtin_imports: list[str] = field(default_factory=list)
22
+ third_party_imports: list[str] = field(
23
+ default_factory=list,
24
+ )
23
25
  environment_variables: list[EnvironmentVariable] = field(
24
- default_factory=list[EnvironmentVariable]
26
+ default_factory=list,
25
27
  )
26
28
 
27
29
 
@@ -198,10 +200,11 @@ ag2_{tool_name} = ag2_{tool_name}_interop.convert_tool(
198
200
  for key, value in tool.secrets.items():
199
201
  # f.write(f'os.environ["{key}"] = "{value}"\n')
200
202
  # check first if the key already exists in os.environ
201
- f.write(
203
+ to_write = (
202
204
  f'os.environ["{key}"] = '
203
205
  f'os.environ.get("{key}", "{value}")\n'
204
206
  )
207
+ f.write(to_write)
205
208
  except Exception as exc: # pragma: no cover
206
209
  raise ExporterContentError(
207
210
  f"Failed to write secrets file for tool '{tool_name}': {exc}"
waldiez/io/__init__.py CHANGED
@@ -2,7 +2,8 @@
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
3
 
4
4
  # flake8: noqa: F401
5
- # pylint: disable=unused-import,too-few-public-methods
5
+ # pylint: disable=unused-import,unused-argument,too-few-public-methods
6
+ # pyright: reportAssignmentType=false
6
7
 
7
8
  """IOSTream extensions.
8
9
 
@@ -30,7 +31,7 @@ from .models import (
30
31
  VideoMediaContent,
31
32
  )
32
33
  from .structured import StructuredIOStream
33
- from .utils import MediaType, MessageType
34
+ from .utils import DEBUG_INPUT_PROMPT, START_CHAT_PROMPT, MediaType, MessageType
34
35
 
35
36
  try:
36
37
  from .redis import RedisIOStream # type: ignore[no-redef,unused-ignore]
@@ -49,10 +50,11 @@ except ImportError: # pragma: no cover
49
50
  kwargs : dict
50
51
  Keyword arguments.
51
52
  """
52
- raise ImportError(
53
+ msg = (
53
54
  "RedisIOStream is not available. "
54
55
  "Please install the required package."
55
56
  )
57
+ raise ImportError(msg)
56
58
 
57
59
 
58
60
  try:
@@ -74,10 +76,11 @@ except ImportError: # pragma: no cover
74
76
  kwargs : dict
75
77
  Keyword arguments.
76
78
  """
77
- raise ImportError(
79
+ msg = (
78
80
  "AsyncWebsocketsIOStream is not available. "
79
81
  "Please install the required package."
80
82
  )
83
+ raise ImportError(msg)
81
84
 
82
85
 
83
86
  try:
@@ -97,10 +100,11 @@ except ImportError: # pragma: no cover
97
100
  kwargs : dict
98
101
  Keyword arguments.
99
102
  """
100
- raise ImportError(
103
+ msg = (
101
104
  "MqttIOStream is not available. "
102
105
  "Please install the required package."
103
106
  )
107
+ raise ImportError(msg)
104
108
 
105
109
 
106
110
  __all__ = [
@@ -125,4 +129,6 @@ __all__ = [
125
129
  "AudioContent",
126
130
  "VideoMediaContent",
127
131
  "VideoContent",
132
+ "DEBUG_INPUT_PROMPT",
133
+ "START_CHAT_PROMPT",
128
134
  ]
waldiez/io/_ws.py CHANGED
@@ -1,7 +1,12 @@
1
1
  # SPDX-License-Identifier: Apache-2.0.
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
3
  # flake8: noqa: E501
4
- # pylint: disable=line-too-long
4
+ # pylint: disable=line-too-long,invalid-name
5
+ # pyright: reportUnknownMemberType=false,reportUnknownParameterType=false
6
+ # pyright: reportUnknownVariableType=false,reportUnknownArgumentType=false
7
+ # pyright: reportConstantRedefinition=false,reportUnnecessaryIsInstance=false
8
+ # pyright: reportMissingImports=false
9
+
5
10
  """WebSocket IOStream implementation for AsyncIO."""
6
11
 
7
12
  import asyncio
@@ -13,14 +18,14 @@ HAS_WS_LIB = False
13
18
  try:
14
19
  from starlette.websockets import WebSocket # type: ignore[unused-ignore, unused-import, import-not-found, import-untyped] # noqa
15
20
 
16
- HAS_WS_LIB = True # pyright: ignore
21
+ HAS_WS_LIB = True
17
22
  except ImportError: # pragma: no cover
18
23
  pass
19
24
 
20
25
  try:
21
26
  import websockets # type: ignore[unused-ignore, unused-import, import-not-found, import-untyped] # noqa
22
27
 
23
- HAS_WS_LIB = True # pyright: ignore
28
+ HAS_WS_LIB = True
24
29
  except ImportError: # pragma: no cover
25
30
  pass
26
31
 
@@ -40,7 +45,7 @@ class WebSocketConnection(Protocol):
40
45
  async def receive_message(
41
46
  self,
42
47
  timeout: float = 120,
43
- ) -> str: # pyright: ignore
48
+ ) -> str: # pyright: ignore[reportReturnType]
44
49
  """Receive a message from the WebSocket connection.
45
50
 
46
51
  Parameters
@@ -101,7 +106,7 @@ class WebSocketsAdapter:
101
106
  self.websocket.recv(), timeout=timeout
102
107
  )
103
108
  if isinstance(response, bytes):
104
- return response.decode("utf-8")
109
+ return response.decode("utf-8", errors="replace")
105
110
  # noinspection PyUnreachableCode
106
111
  return response if isinstance(response, str) else str(response)
107
112
  except asyncio.TimeoutError:
@@ -190,12 +195,13 @@ def create_websocket_adapter(websocket: Any) -> WebSocketConnection:
190
195
  if hasattr(websocket, "send") and hasattr(websocket, "recv"):
191
196
  return WebSocketsAdapter(websocket)
192
197
 
193
- raise ValueError(
198
+ msg = (
194
199
  "Unsupported WebSocket type. "
195
200
  "Must be either websockets.ServerConnection "
196
201
  "or starlette.websockets.WebSocket. "
197
202
  f"Received: {type(websocket)}"
198
203
  )
204
+ raise ValueError(msg)
199
205
 
200
206
 
201
207
  def is_websocket_available() -> bool:
@@ -3,7 +3,7 @@
3
3
 
4
4
  """Constants and type mappings for content models."""
5
5
 
6
- from typing import Type, TypedDict, Union
6
+ from typing import TypedDict
7
7
 
8
8
  from typing_extensions import Literal
9
9
 
@@ -13,14 +13,14 @@ from .content.image import ImageMediaContent, ImageUrlMediaContent
13
13
  from .content.text import TextMediaContent
14
14
  from .content.video import VideoMediaContent
15
15
 
16
- MediaContent = Union[
17
- TextMediaContent,
18
- ImageMediaContent,
19
- ImageUrlMediaContent,
20
- VideoMediaContent,
21
- AudioMediaContent,
22
- FileMediaContent,
23
- ]
16
+ MediaContent = (
17
+ TextMediaContent
18
+ | ImageMediaContent
19
+ | ImageUrlMediaContent
20
+ | VideoMediaContent
21
+ | AudioMediaContent
22
+ | FileMediaContent
23
+ )
24
24
 
25
25
  ContentTypeKey = Literal["text", "image", "image_url", "video", "audio", "file"]
26
26
  """Possible content types for the mapping."""
@@ -40,7 +40,7 @@ class ContentMappingEntry(TypedDict):
40
40
  """
41
41
 
42
42
  fields: list[str]
43
- cls: Type[MediaContent]
43
+ cls: type[MediaContent]
44
44
  required_field: str
45
45
 
46
46
 
@@ -1,6 +1,7 @@
1
1
  # SPDX-License-Identifier: Apache-2.0.
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
3
  # pylint: disable=unused-argument
4
+ # pyright: reportUnusedParameter=false
4
5
  """Audio media content models."""
5
6
 
6
7
  from pathlib import Path
@@ -1,8 +1,10 @@
1
1
  # SPDX-License-Identifier: Apache-2.0.
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+
4
+
3
5
  """Base content models for media types."""
4
6
 
5
- from typing import Any, Optional
7
+ from typing import Any
6
8
 
7
9
  from pydantic import BaseModel
8
10
 
@@ -10,36 +12,36 @@ from pydantic import BaseModel
10
12
  class ImageContent(BaseModel):
11
13
  """Image content model."""
12
14
 
13
- url: Optional[str] = None
14
- file: Optional[Any] = None # File type not directly mappable in Python
15
- alt: Optional[str] = None
15
+ url: str | None = None
16
+ file: Any | None = None # File type not directly mappable in Python
17
+ alt: str | None = None
16
18
 
17
19
 
18
20
  class VideoContent(BaseModel):
19
21
  """Video content model."""
20
22
 
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
23
+ url: str | None = None
24
+ file: Any | None = None
25
+ duration: int | None = None
26
+ thumbnailUrl: str | None = None
27
+ mimeType: str | None = None
26
28
 
27
29
 
28
30
  class AudioContent(BaseModel):
29
31
  """Audio content model."""
30
32
 
31
- url: Optional[str] = None
32
- file: Optional[Any] = None
33
- duration: Optional[int] = None
34
- transcript: Optional[str] = None
33
+ url: str | None = None
34
+ file: Any | None = None
35
+ duration: int | None = None
36
+ transcript: str | None = None
35
37
 
36
38
 
37
39
  class FileContent(BaseModel):
38
40
  """File content model."""
39
41
 
40
- url: Optional[str] = None
41
- file: Optional[Any] = None
42
+ url: str | None = None
43
+ file: Any | None = None
42
44
  name: str
43
- size: Optional[int] = None
44
- type: Optional[str] = None
45
- previewUrl: Optional[str] = None
45
+ size: int | None = None
46
+ type: str | None = None
47
+ previewUrl: str | None = None
@@ -1,6 +1,7 @@
1
1
  # SPDX-License-Identifier: Apache-2.0.
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
3
  # pylint: disable=unused-argument
4
+ # pyright: reportUnusedParameter=false
4
5
  """File media content models."""
5
6
 
6
7
  from pathlib import Path
@@ -1,6 +1,7 @@
1
1
  # SPDX-License-Identifier: Apache-2.0.
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
3
  # pylint: disable=unused-argument
4
+ # pyright: reportUnusedParameter=false
4
5
  """Image media content models."""
5
6
 
6
7
  from pathlib import Path
@@ -1,6 +1,7 @@
1
1
  # SPDX-License-Identifier: Apache-2.0.
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
3
  # pylint: disable=unused-argument
4
+ # pyright: reportUnusedParameter=false
4
5
  """Text media content models."""
5
6
 
6
7
  from pathlib import Path
@@ -1,6 +1,7 @@
1
1
  # SPDX-License-Identifier: Apache-2.0.
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
3
  # pylint: disable=unused-argument
4
+ # pyright: reportUnusedParameter=false
4
5
  """Video and audio media content models."""
5
6
 
6
7
  from pathlib import Path
@@ -1,12 +1,16 @@
1
1
  # SPDX-License-Identifier: Apache-2.0.
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
3
 
4
+ # pyright: reportUnnecessaryIsInstance=false,reportUnknownVariableType=false
5
+ # pyright: reportUnknownArgumentType=false,reportArgumentType=false
6
+ # pyright: reportReturnType=false
7
+
4
8
  """User input data models and validation."""
5
9
 
6
10
  import json
7
11
  import os
8
12
  from pathlib import Path
9
- from typing import Any, Union
13
+ from typing import Any
10
14
  from urllib.parse import urlparse
11
15
 
12
16
  from pydantic import BaseModel, Field, field_validator
@@ -31,7 +35,7 @@ class UserInputData(BaseModel):
31
35
  """User's input data model."""
32
36
 
33
37
  content: Annotated[
34
- Union[MediaContent, list[MediaContent]],
38
+ MediaContent | list[MediaContent],
35
39
  Field(
36
40
  description="The content of the input data.",
37
41
  title="Content",
@@ -68,7 +72,7 @@ class UserInputData(BaseModel):
68
72
  if isinstance(self.content, list):
69
73
  return " ".join(
70
74
  [
71
- item.to_string(uploads_root, base_name) # pyright: ignore
75
+ item.to_string(uploads_root, base_name)
72
76
  for item in self.content
73
77
  ]
74
78
  )
@@ -161,10 +165,11 @@ class UserInputData(BaseModel):
161
165
  **{mapping["required_field"]: converted} # type: ignore
162
166
  )
163
167
 
164
- raise ValueError(
168
+ msg = (
165
169
  "Missing required field for content type "
166
170
  f"'{content_type}' in: {value}"
167
171
  )
172
+ raise ValueError(msg)
168
173
 
169
174
  @staticmethod
170
175
  def _convert_simple_content(
@@ -226,7 +231,7 @@ class UserInputData(BaseModel):
226
231
 
227
232
  # If it's a dictionary, check if it has a 'type' field
228
233
  if isinstance(v, dict):
229
- return cls.content_from_dict(v) # pyright: ignore
234
+ return cls.content_from_dict(v)
230
235
 
231
236
  # If it's a list
232
237
  if isinstance(v, list):