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.
- waldiez/__init__.py +1 -1
- waldiez/_version.py +1 -1
- waldiez/cli.py +19 -7
- waldiez/cli_extras/jupyter.py +3 -0
- waldiez/cli_extras/runner.py +3 -1
- waldiez/cli_extras/studio.py +3 -1
- waldiez/exporter.py +9 -3
- waldiez/exporting/agent/exporter.py +15 -16
- waldiez/exporting/agent/extras/captain_agent_extras.py +6 -6
- waldiez/exporting/agent/extras/doc_agent_extras.py +6 -6
- waldiez/exporting/agent/extras/group_manager_agent_extas.py +40 -24
- waldiez/exporting/agent/extras/group_member_extras.py +6 -5
- waldiez/exporting/agent/extras/handoffs/after_work.py +2 -1
- waldiez/exporting/agent/extras/handoffs/available.py +2 -1
- waldiez/exporting/agent/extras/handoffs/condition.py +3 -2
- waldiez/exporting/agent/extras/handoffs/handoff.py +2 -1
- waldiez/exporting/agent/extras/handoffs/target.py +7 -4
- waldiez/exporting/agent/extras/rag/chroma_extras.py +27 -19
- waldiez/exporting/agent/extras/rag/mongo_extras.py +8 -8
- waldiez/exporting/agent/extras/rag/pgvector_extras.py +5 -5
- waldiez/exporting/agent/extras/rag/qdrant_extras.py +5 -4
- waldiez/exporting/agent/extras/rag/vector_db_extras.py +1 -1
- waldiez/exporting/agent/extras/rag_user_proxy_agent_extras.py +5 -7
- waldiez/exporting/agent/extras/reasoning_agent_extras.py +3 -5
- waldiez/exporting/agent/termination.py +1 -0
- waldiez/exporting/chats/exporter.py +4 -4
- waldiez/exporting/chats/processor.py +1 -2
- waldiez/exporting/chats/utils/common.py +89 -48
- waldiez/exporting/chats/utils/group.py +9 -9
- waldiez/exporting/chats/utils/nested.py +7 -7
- waldiez/exporting/chats/utils/sequential.py +1 -1
- waldiez/exporting/chats/utils/single.py +2 -2
- waldiez/exporting/core/constants.py +3 -1
- waldiez/exporting/core/content.py +7 -7
- waldiez/exporting/core/context.py +5 -3
- waldiez/exporting/core/exporter.py +5 -3
- waldiez/exporting/core/exporters.py +2 -2
- waldiez/exporting/core/extras/agent_extras/captain_extras.py +2 -2
- waldiez/exporting/core/extras/agent_extras/group_manager_extras.py +2 -2
- waldiez/exporting/core/extras/agent_extras/rag_user_extras.py +2 -2
- waldiez/exporting/core/extras/agent_extras/standard_extras.py +3 -8
- waldiez/exporting/core/extras/base.py +7 -5
- waldiez/exporting/core/extras/flow_extras.py +4 -5
- waldiez/exporting/core/extras/model_extras.py +2 -2
- waldiez/exporting/core/extras/path_resolver.py +1 -2
- waldiez/exporting/core/extras/serializer.py +13 -11
- waldiez/exporting/core/protocols.py +6 -5
- waldiez/exporting/core/result.py +25 -28
- waldiez/exporting/core/types.py +11 -10
- waldiez/exporting/core/utils/llm_config.py +4 -4
- waldiez/exporting/core/validation.py +10 -11
- waldiez/exporting/flow/execution_generator.py +99 -10
- waldiez/exporting/flow/exporter.py +2 -2
- waldiez/exporting/flow/factory.py +2 -2
- waldiez/exporting/flow/file_generator.py +4 -2
- waldiez/exporting/flow/merger.py +5 -3
- waldiez/exporting/flow/orchestrator.py +72 -2
- waldiez/exporting/flow/utils/common.py +6 -6
- waldiez/exporting/flow/utils/importing.py +7 -8
- waldiez/exporting/flow/utils/linting.py +25 -9
- waldiez/exporting/flow/utils/logging.py +5 -77
- waldiez/exporting/models/exporter.py +8 -8
- waldiez/exporting/models/processor.py +5 -5
- waldiez/exporting/tools/exporter.py +2 -2
- waldiez/exporting/tools/processor.py +7 -4
- waldiez/io/__init__.py +11 -5
- waldiez/io/_ws.py +12 -6
- waldiez/io/models/constants.py +10 -10
- waldiez/io/models/content/audio.py +1 -0
- waldiez/io/models/content/base.py +20 -18
- waldiez/io/models/content/file.py +1 -0
- waldiez/io/models/content/image.py +1 -0
- waldiez/io/models/content/text.py +1 -0
- waldiez/io/models/content/video.py +1 -0
- waldiez/io/models/user_input.py +10 -5
- waldiez/io/models/user_response.py +17 -16
- waldiez/io/mqtt.py +18 -31
- waldiez/io/redis.py +18 -22
- waldiez/io/structured.py +122 -70
- waldiez/io/utils.py +19 -10
- waldiez/io/ws.py +7 -3
- waldiez/logger.py +16 -3
- waldiez/models/agents/__init__.py +3 -0
- waldiez/models/agents/agent/agent.py +25 -17
- waldiez/models/agents/agent/agent_data.py +25 -22
- waldiez/models/agents/agent/code_execution.py +9 -11
- waldiez/models/agents/agent/termination_message.py +10 -12
- waldiez/models/agents/agent/update_system_message.py +2 -4
- waldiez/models/agents/agents.py +8 -8
- waldiez/models/agents/assistant/assistant.py +6 -3
- waldiez/models/agents/assistant/assistant_data.py +2 -2
- waldiez/models/agents/captain/captain_agent.py +7 -4
- waldiez/models/agents/captain/captain_agent_data.py +5 -7
- waldiez/models/agents/doc_agent/doc_agent.py +7 -4
- waldiez/models/agents/doc_agent/doc_agent_data.py +9 -10
- waldiez/models/agents/doc_agent/rag_query_engine.py +10 -12
- waldiez/models/agents/extra_requirements.py +3 -3
- waldiez/models/agents/group_manager/group_manager.py +12 -7
- waldiez/models/agents/group_manager/group_manager_data.py +13 -12
- waldiez/models/agents/group_manager/speakers.py +17 -19
- waldiez/models/agents/rag_user_proxy/rag_user_proxy.py +7 -4
- waldiez/models/agents/rag_user_proxy/rag_user_proxy_data.py +4 -1
- waldiez/models/agents/rag_user_proxy/retrieve_config.py +69 -63
- waldiez/models/agents/rag_user_proxy/vector_db_config.py +19 -19
- waldiez/models/agents/reasoning/reasoning_agent.py +7 -4
- waldiez/models/agents/reasoning/reasoning_agent_data.py +3 -2
- waldiez/models/agents/reasoning/reasoning_agent_reason_config.py +8 -8
- waldiez/models/agents/user_proxy/user_proxy.py +6 -3
- waldiez/models/agents/user_proxy/user_proxy_data.py +1 -1
- waldiez/models/chat/chat.py +28 -20
- waldiez/models/chat/chat_data.py +22 -21
- waldiez/models/chat/chat_message.py +9 -9
- waldiez/models/chat/chat_nested.py +9 -9
- waldiez/models/chat/chat_summary.py +6 -6
- waldiez/models/common/__init__.py +2 -0
- waldiez/models/common/ag2_version.py +2 -0
- waldiez/models/common/base.py +2 -0
- waldiez/models/common/dict_utils.py +8 -6
- waldiez/models/common/handoff.py +20 -17
- waldiez/models/common/method_utils.py +9 -7
- waldiez/models/common/naming.py +49 -0
- waldiez/models/flow/flow.py +11 -6
- waldiez/models/flow/flow_data.py +23 -17
- waldiez/models/flow/info.py +3 -3
- waldiez/models/flow/naming.py +2 -1
- waldiez/models/model/_aws.py +11 -13
- waldiez/models/model/_llm.py +8 -0
- waldiez/models/model/_price.py +2 -4
- waldiez/models/model/extra_requirements.py +1 -3
- waldiez/models/model/model.py +2 -2
- waldiez/models/model/model_data.py +21 -21
- waldiez/models/tool/extra_requirements.py +2 -4
- waldiez/models/tool/predefined/_duckduckgo.py +1 -0
- waldiez/models/tool/predefined/_email.py +4 -0
- waldiez/models/tool/predefined/_google.py +1 -0
- waldiez/models/tool/predefined/_perplexity.py +2 -1
- waldiez/models/tool/predefined/_searxng.py +2 -1
- waldiez/models/tool/predefined/_tavily.py +1 -0
- waldiez/models/tool/predefined/_wikipedia.py +2 -1
- waldiez/models/tool/predefined/_youtube.py +1 -0
- waldiez/models/tool/tool.py +8 -5
- waldiez/models/tool/tool_data.py +2 -2
- waldiez/models/waldiez.py +152 -4
- waldiez/runner.py +11 -5
- waldiez/running/async_utils.py +192 -0
- waldiez/running/base_runner.py +155 -241
- waldiez/running/dir_utils.py +52 -0
- waldiez/running/environment.py +10 -44
- waldiez/running/events_mixin.py +252 -0
- waldiez/running/exceptions.py +20 -0
- waldiez/running/gen_seq_diagram.py +18 -15
- waldiez/running/io_utils.py +216 -0
- waldiez/running/protocol.py +11 -5
- waldiez/running/requirements_mixin.py +65 -0
- waldiez/running/results_mixin.py +926 -0
- waldiez/running/standard_runner.py +24 -27
- waldiez/running/step_by_step/breakpoints_mixin.py +503 -47
- waldiez/running/step_by_step/command_handler.py +154 -0
- waldiez/running/step_by_step/events_processor.py +379 -0
- waldiez/running/step_by_step/step_by_step_models.py +425 -41
- waldiez/running/step_by_step/step_by_step_runner.py +437 -382
- waldiez/running/subprocess_runner/__base__.py +13 -8
- waldiez/running/subprocess_runner/_async_runner.py +6 -4
- waldiez/running/subprocess_runner/_sync_runner.py +11 -6
- waldiez/running/subprocess_runner/runner.py +48 -23
- waldiez/running/timeline_processor.py +1 -1
- waldiez/utils/__init__.py +2 -0
- waldiez/utils/conflict_checker.py +4 -4
- waldiez/utils/python_manager.py +415 -0
- waldiez/ws/__init__.py +8 -7
- waldiez/ws/_file_handler.py +18 -20
- waldiez/ws/_mock.py +75 -0
- waldiez/ws/cli.py +58 -10
- waldiez/ws/client_manager.py +77 -53
- waldiez/ws/errors.py +3 -0
- waldiez/ws/models.py +61 -53
- waldiez/ws/reloader.py +33 -4
- waldiez/ws/server.py +121 -52
- waldiez/ws/session_manager.py +8 -9
- waldiez/ws/session_stats.py +1 -1
- waldiez/ws/utils.py +33 -5
- {waldiez-0.5.10.dist-info → waldiez-0.6.1.dist-info}/METADATA +107 -109
- waldiez-0.6.1.dist-info/RECORD +254 -0
- waldiez/running/post_run.py +0 -180
- waldiez/running/pre_run.py +0 -159
- waldiez/running/run_results.py +0 -14
- waldiez/running/utils.py +0 -511
- waldiez-0.5.10.dist-info/RECORD +0 -248
- {waldiez-0.5.10.dist-info → waldiez-0.6.1.dist-info}/WHEEL +0 -0
- {waldiez-0.5.10.dist-info → waldiez-0.6.1.dist-info}/entry_points.txt +0 -0
- {waldiez-0.5.10.dist-info → waldiez-0.6.1.dist-info}/licenses/LICENSE +0 -0
- {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
|
-
|
|
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=
|
|
170
|
-
# noinspection PyUnresolvedReferences
|
|
135
|
+
# pylint: disable=line-too-long
|
|
171
136
|
def get_async_sqlite_out() -> str:
|
|
172
|
-
|
|
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
|
|
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:
|
|
35
|
-
output_dir:
|
|
36
|
-
context:
|
|
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) ->
|
|
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
|
|
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
|
|
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:
|
|
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:
|
|
36
|
-
output_dir:
|
|
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
|
-
|
|
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
|
|
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) ->
|
|
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
|
|
22
|
-
third_party_imports: list[str] = field(
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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:
|
waldiez/io/models/constants.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
"""Constants and type mappings for content models."""
|
|
5
5
|
|
|
6
|
-
from typing import
|
|
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 =
|
|
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:
|
|
43
|
+
cls: type[MediaContent]
|
|
44
44
|
required_field: str
|
|
45
45
|
|
|
46
46
|
|
|
@@ -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
|
|
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:
|
|
14
|
-
file:
|
|
15
|
-
alt:
|
|
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:
|
|
22
|
-
file:
|
|
23
|
-
duration:
|
|
24
|
-
thumbnailUrl:
|
|
25
|
-
mimeType:
|
|
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:
|
|
32
|
-
file:
|
|
33
|
-
duration:
|
|
34
|
-
transcript:
|
|
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:
|
|
41
|
-
file:
|
|
42
|
+
url: str | None = None
|
|
43
|
+
file: Any | None = None
|
|
42
44
|
name: str
|
|
43
|
-
size:
|
|
44
|
-
type:
|
|
45
|
-
previewUrl:
|
|
45
|
+
size: int | None = None
|
|
46
|
+
type: str | None = None
|
|
47
|
+
previewUrl: str | None = None
|
waldiez/io/models/user_input.py
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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)
|
|
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
|
-
|
|
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)
|
|
234
|
+
return cls.content_from_dict(v)
|
|
230
235
|
|
|
231
236
|
# If it's a list
|
|
232
237
|
if isinstance(v, list):
|