waldiez 0.5.9__py3-none-any.whl → 0.6.0__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/_version.py +1 -1
- waldiez/cli.py +113 -24
- waldiez/exporting/agent/exporter.py +9 -6
- waldiez/exporting/agent/extras/captain_agent_extras.py +44 -7
- waldiez/exporting/agent/extras/group_manager_agent_extas.py +6 -1
- waldiez/exporting/agent/extras/handoffs/after_work.py +1 -0
- waldiez/exporting/agent/extras/handoffs/available.py +1 -0
- waldiez/exporting/agent/extras/handoffs/condition.py +3 -1
- waldiez/exporting/agent/extras/handoffs/handoff.py +1 -0
- waldiez/exporting/agent/extras/handoffs/target.py +1 -0
- waldiez/exporting/agent/termination.py +1 -0
- waldiez/exporting/chats/utils/common.py +25 -23
- waldiez/exporting/core/__init__.py +0 -2
- waldiez/exporting/core/constants.py +3 -1
- waldiez/exporting/core/context.py +13 -13
- waldiez/exporting/core/extras/serializer.py +12 -10
- waldiez/exporting/core/protocols.py +0 -141
- waldiez/exporting/core/result.py +5 -5
- waldiez/exporting/core/types.py +1 -0
- waldiez/exporting/core/utils/llm_config.py +2 -2
- waldiez/exporting/flow/execution_generator.py +1 -0
- waldiez/exporting/flow/merger.py +2 -2
- waldiez/exporting/flow/orchestrator.py +1 -0
- waldiez/exporting/flow/utils/common.py +3 -3
- waldiez/exporting/flow/utils/importing.py +1 -0
- waldiez/exporting/flow/utils/logging.py +7 -80
- waldiez/exporting/tools/exporter.py +5 -0
- waldiez/exporting/tools/factory.py +4 -0
- waldiez/exporting/tools/processor.py +5 -1
- waldiez/io/__init__.py +3 -1
- waldiez/io/_ws.py +15 -5
- waldiez/io/models/content/image.py +1 -0
- waldiez/io/models/user_input.py +4 -4
- waldiez/io/models/user_response.py +1 -0
- waldiez/io/mqtt.py +1 -1
- waldiez/io/structured.py +98 -45
- waldiez/io/utils.py +17 -11
- waldiez/io/ws.py +10 -12
- waldiez/logger.py +180 -63
- waldiez/models/agents/agent/agent.py +2 -1
- waldiez/models/agents/agent/update_system_message.py +0 -2
- waldiez/models/agents/doc_agent/doc_agent.py +8 -1
- waldiez/models/chat/chat.py +1 -0
- waldiez/models/chat/chat_data.py +0 -2
- waldiez/models/common/base.py +2 -0
- waldiez/models/common/dict_utils.py +169 -40
- waldiez/models/common/handoff.py +2 -0
- waldiez/models/common/method_utils.py +2 -0
- waldiez/models/flow/flow.py +6 -6
- waldiez/models/flow/info.py +5 -1
- waldiez/models/model/_llm.py +31 -14
- waldiez/models/model/model.py +4 -1
- waldiez/models/model/model_data.py +18 -5
- waldiez/models/tool/predefined/_config.py +5 -1
- waldiez/models/tool/predefined/_duckduckgo.py +4 -0
- waldiez/models/tool/predefined/_email.py +477 -0
- waldiez/models/tool/predefined/_google.py +4 -1
- waldiez/models/tool/predefined/_perplexity.py +4 -1
- waldiez/models/tool/predefined/_searxng.py +4 -1
- waldiez/models/tool/predefined/_tavily.py +4 -1
- waldiez/models/tool/predefined/_wikipedia.py +5 -2
- waldiez/models/tool/predefined/_youtube.py +4 -1
- waldiez/models/tool/predefined/protocol.py +3 -0
- waldiez/models/tool/tool.py +22 -4
- waldiez/models/waldiez.py +12 -0
- waldiez/runner.py +37 -54
- waldiez/running/__init__.py +6 -0
- waldiez/running/base_runner.py +381 -363
- waldiez/running/environment.py +1 -0
- waldiez/running/exceptions.py +9 -0
- waldiez/running/post_run.py +10 -4
- waldiez/running/pre_run.py +199 -66
- waldiez/running/protocol.py +21 -101
- waldiez/running/run_results.py +1 -1
- waldiez/running/standard_runner.py +83 -276
- waldiez/running/step_by_step/__init__.py +46 -0
- waldiez/running/step_by_step/breakpoints_mixin.py +512 -0
- waldiez/running/step_by_step/command_handler.py +151 -0
- waldiez/running/step_by_step/events_processor.py +199 -0
- waldiez/running/step_by_step/step_by_step_models.py +541 -0
- waldiez/running/step_by_step/step_by_step_runner.py +750 -0
- waldiez/running/subprocess_runner/__base__.py +279 -0
- waldiez/running/subprocess_runner/__init__.py +16 -0
- waldiez/running/subprocess_runner/_async_runner.py +362 -0
- waldiez/running/subprocess_runner/_sync_runner.py +456 -0
- waldiez/running/subprocess_runner/runner.py +570 -0
- waldiez/running/timeline_processor.py +1 -1
- waldiez/running/utils.py +492 -3
- waldiez/utils/version.py +2 -6
- waldiez/ws/__init__.py +71 -0
- waldiez/ws/__main__.py +15 -0
- waldiez/ws/_file_handler.py +199 -0
- waldiez/ws/_mock.py +74 -0
- waldiez/ws/cli.py +235 -0
- waldiez/ws/client_manager.py +851 -0
- waldiez/ws/errors.py +416 -0
- waldiez/ws/models.py +988 -0
- waldiez/ws/reloader.py +363 -0
- waldiez/ws/server.py +508 -0
- waldiez/ws/session_manager.py +393 -0
- waldiez/ws/session_stats.py +83 -0
- waldiez/ws/utils.py +410 -0
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/METADATA +105 -96
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/RECORD +108 -83
- waldiez/running/patch_io_stream.py +0 -210
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/WHEEL +0 -0
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/entry_points.txt +0 -0
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/licenses/LICENSE +0 -0
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/licenses/NOTICE.md +0 -0
|
@@ -10,7 +10,7 @@ from typing import Any, Optional
|
|
|
10
10
|
from ..protocols import Serializer
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
# pylint: disable=too-few-public-methods
|
|
13
|
+
# pylint: disable=too-few-public-methods,no-self-use
|
|
14
14
|
class DefaultSerializer(Serializer):
|
|
15
15
|
"""Default serializer for Waldiez items."""
|
|
16
16
|
|
|
@@ -37,7 +37,7 @@ class DefaultSerializer(Serializer):
|
|
|
37
37
|
def serialize_item(
|
|
38
38
|
item: Any,
|
|
39
39
|
tabs: int = 1,
|
|
40
|
-
|
|
40
|
+
visited: Optional[set[int]] = None,
|
|
41
41
|
) -> str:
|
|
42
42
|
"""Convert an item to a formatted string with given indentation.
|
|
43
43
|
|
|
@@ -47,6 +47,8 @@ def serialize_item(
|
|
|
47
47
|
The item to convert.
|
|
48
48
|
tabs : int, optional
|
|
49
49
|
The number of tabs, by default 1.
|
|
50
|
+
visited : set[int], optional
|
|
51
|
+
A set of visited IDs, by default None
|
|
50
52
|
|
|
51
53
|
Returns
|
|
52
54
|
-------
|
|
@@ -81,8 +83,8 @@ def serialize_item(
|
|
|
81
83
|
}
|
|
82
84
|
```
|
|
83
85
|
"""
|
|
84
|
-
if
|
|
85
|
-
|
|
86
|
+
if visited is None:
|
|
87
|
+
visited = set()
|
|
86
88
|
|
|
87
89
|
if callable(item):
|
|
88
90
|
return item.__name__
|
|
@@ -92,37 +94,37 @@ def serialize_item(
|
|
|
92
94
|
return _format_primitive(item)
|
|
93
95
|
|
|
94
96
|
# Handle circular references in containers
|
|
95
|
-
if isinstance(item, (dict, list, tuple, set)) and id(item) in
|
|
97
|
+
if isinstance(item, (dict, list, tuple, set)) and id(item) in visited:
|
|
96
98
|
return '"<circular reference>"'
|
|
97
99
|
|
|
98
100
|
next_indent = " " * 4 * (tabs + 1)
|
|
99
|
-
|
|
101
|
+
visited.add(id(item))
|
|
100
102
|
|
|
101
103
|
if isinstance(item, dict):
|
|
102
104
|
items: list[str] = []
|
|
103
105
|
for key, value in item.items():
|
|
104
106
|
key_str = f'{next_indent}"{key}"'
|
|
105
|
-
value_str = serialize_item(value, tabs + 1,
|
|
107
|
+
value_str = serialize_item(value, tabs + 1, visited)
|
|
106
108
|
items.append(f"{key_str}: {value_str}")
|
|
107
109
|
return _format_container(items, "{", "}", tabs)
|
|
108
110
|
|
|
109
111
|
if isinstance(item, list):
|
|
110
112
|
items = [
|
|
111
|
-
f"{next_indent}{serialize_item(sub_item, tabs + 1,
|
|
113
|
+
f"{next_indent}{serialize_item(sub_item, tabs + 1, visited)}"
|
|
112
114
|
for sub_item in item
|
|
113
115
|
]
|
|
114
116
|
return _format_container(items, "[", "]", tabs)
|
|
115
117
|
|
|
116
118
|
if isinstance(item, tuple):
|
|
117
119
|
items = [
|
|
118
|
-
f"{next_indent}{serialize_item(sub_item, tabs + 1,
|
|
120
|
+
f"{next_indent}{serialize_item(sub_item, tabs + 1, visited)}"
|
|
119
121
|
for sub_item in item
|
|
120
122
|
]
|
|
121
123
|
return _format_container(items, "(", ")", tabs)
|
|
122
124
|
|
|
123
125
|
if isinstance(item, set):
|
|
124
126
|
items = [
|
|
125
|
-
f"{next_indent}{serialize_item(sub_item, tabs + 1,
|
|
127
|
+
f"{next_indent}{serialize_item(sub_item, tabs + 1, visited)}"
|
|
126
128
|
for sub_item in item
|
|
127
129
|
]
|
|
128
130
|
return _format_container(items, "{", "}", tabs)
|
|
@@ -139,144 +139,3 @@ class ContentGenerator(Protocol):
|
|
|
139
139
|
ExporterContentError
|
|
140
140
|
If exporting fails.
|
|
141
141
|
"""
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
@runtime_checkable
|
|
145
|
-
class ExportingLogger(Protocol):
|
|
146
|
-
"""Protocol for logging during exporting."""
|
|
147
|
-
|
|
148
|
-
def log(
|
|
149
|
-
self, message: Any, *args: Any, level: str = "info", **kwargs: Any
|
|
150
|
-
) -> None:
|
|
151
|
-
"""Log a message with the specified level.
|
|
152
|
-
|
|
153
|
-
Parameters
|
|
154
|
-
----------
|
|
155
|
-
message : Any
|
|
156
|
-
The message to log or message template for formatting.
|
|
157
|
-
level : str, optional
|
|
158
|
-
The logging level to use (e.g., "debug", "info", "warning", "error",
|
|
159
|
-
"critical"). Defaults to "info".
|
|
160
|
-
*args : Any
|
|
161
|
-
Arguments to format into the message using % formatting.
|
|
162
|
-
**kwargs : Any
|
|
163
|
-
Keyword arguments to format into the message using str.format().
|
|
164
|
-
"""
|
|
165
|
-
|
|
166
|
-
def error(self, message: Any, *args: Any, **kwargs: Any) -> None:
|
|
167
|
-
"""Log an error message.
|
|
168
|
-
|
|
169
|
-
Parameters
|
|
170
|
-
----------
|
|
171
|
-
message : Any
|
|
172
|
-
The error message to log or message template.
|
|
173
|
-
*args : Any
|
|
174
|
-
Arguments to format into the message.
|
|
175
|
-
**kwargs : Any
|
|
176
|
-
Keyword arguments to format into the message using str.format().
|
|
177
|
-
"""
|
|
178
|
-
|
|
179
|
-
def warning(self, message: Any, *args: Any, **kwargs: Any) -> None:
|
|
180
|
-
"""Log a warning message.
|
|
181
|
-
|
|
182
|
-
Parameters
|
|
183
|
-
----------
|
|
184
|
-
message : Any
|
|
185
|
-
The warning message to log or message template.
|
|
186
|
-
*args : Any
|
|
187
|
-
Arguments to format into the message.
|
|
188
|
-
**kwargs : Any
|
|
189
|
-
Keyword arguments to format into the message using str.format().
|
|
190
|
-
"""
|
|
191
|
-
|
|
192
|
-
def info(self, message: Any, *args: Any, **kwargs: Any) -> None:
|
|
193
|
-
"""Log an informational message.
|
|
194
|
-
|
|
195
|
-
Parameters
|
|
196
|
-
----------
|
|
197
|
-
message : Any
|
|
198
|
-
The informational message to log or message template.
|
|
199
|
-
*args : Any
|
|
200
|
-
Arguments to format into the message.
|
|
201
|
-
**kwargs : Any
|
|
202
|
-
Keyword arguments to format into the message using str.format().
|
|
203
|
-
"""
|
|
204
|
-
|
|
205
|
-
def success(self, message: Any, *args: Any, **kwargs: Any) -> None:
|
|
206
|
-
"""Log a success message.
|
|
207
|
-
|
|
208
|
-
Parameters
|
|
209
|
-
----------
|
|
210
|
-
message : Any
|
|
211
|
-
The success message to log or message template.
|
|
212
|
-
*args : Any
|
|
213
|
-
Arguments to format into the message.
|
|
214
|
-
**kwargs : Any
|
|
215
|
-
Keyword arguments to format into the message using str.format().
|
|
216
|
-
"""
|
|
217
|
-
|
|
218
|
-
def debug(self, message: Any, *args: Any, **kwargs: Any) -> None:
|
|
219
|
-
"""Log a debug message.
|
|
220
|
-
|
|
221
|
-
Parameters
|
|
222
|
-
----------
|
|
223
|
-
message : Any
|
|
224
|
-
The debug message to log or message template.
|
|
225
|
-
*args : Any
|
|
226
|
-
Arguments to format into the message.
|
|
227
|
-
**kwargs : Any
|
|
228
|
-
Keyword arguments to format into the message using str.format().
|
|
229
|
-
"""
|
|
230
|
-
self.log(message, *args, level="debug", **kwargs)
|
|
231
|
-
|
|
232
|
-
def critical(self, message: Any, *args: Any, **kwargs: Any) -> None:
|
|
233
|
-
"""Log a critical error message.
|
|
234
|
-
|
|
235
|
-
Parameters
|
|
236
|
-
----------
|
|
237
|
-
message : Any
|
|
238
|
-
The critical error message to log or message template.
|
|
239
|
-
*args : Any
|
|
240
|
-
Arguments to format into the message.
|
|
241
|
-
**kwargs : Any
|
|
242
|
-
Keyword arguments to format into the message using str.format().
|
|
243
|
-
"""
|
|
244
|
-
self.log(message, *args, level="critical", **kwargs)
|
|
245
|
-
|
|
246
|
-
def exception(self, message: Any, *args: Any, **kwargs: Any) -> None:
|
|
247
|
-
"""Log an exception message.
|
|
248
|
-
|
|
249
|
-
Parameters
|
|
250
|
-
----------
|
|
251
|
-
message : Any
|
|
252
|
-
The exception message to log or message template.
|
|
253
|
-
*args : Any
|
|
254
|
-
Arguments to format into the message.
|
|
255
|
-
**kwargs : Any
|
|
256
|
-
Keyword arguments to format into the message using str.format().
|
|
257
|
-
"""
|
|
258
|
-
self.log(message, *args, level="exception", **kwargs)
|
|
259
|
-
|
|
260
|
-
def set_level(self, level: str) -> None:
|
|
261
|
-
"""Set the logging level.
|
|
262
|
-
|
|
263
|
-
Parameters
|
|
264
|
-
----------
|
|
265
|
-
level : str
|
|
266
|
-
The logging level to set
|
|
267
|
-
(e.g., "debug", "info", "warning", "error", "critical").
|
|
268
|
-
|
|
269
|
-
Raises
|
|
270
|
-
------
|
|
271
|
-
ValueError
|
|
272
|
-
If the provided level is invalid.
|
|
273
|
-
"""
|
|
274
|
-
|
|
275
|
-
def get_level(self) -> str: # pyright: ignore
|
|
276
|
-
"""Get the current logging level.
|
|
277
|
-
|
|
278
|
-
Returns
|
|
279
|
-
-------
|
|
280
|
-
str
|
|
281
|
-
The current logging level.
|
|
282
|
-
"""
|
waldiez/exporting/core/result.py
CHANGED
|
@@ -59,7 +59,7 @@ class ExportResult:
|
|
|
59
59
|
position : ImportPosition, optional
|
|
60
60
|
The position of the import, by default THIRD_PARTY
|
|
61
61
|
"""
|
|
62
|
-
if statement and statement.strip():
|
|
62
|
+
if statement and statement.strip(): # pragma: no branch
|
|
63
63
|
self.imports.add(
|
|
64
64
|
ImportStatement(
|
|
65
65
|
statement=statement.strip(),
|
|
@@ -123,7 +123,7 @@ class ExportResult:
|
|
|
123
123
|
comment : Optional[str], optional
|
|
124
124
|
Optional comment for the argument, by default None
|
|
125
125
|
"""
|
|
126
|
-
if name and value is not None:
|
|
126
|
+
if name and value is not None: # pragma: no branch
|
|
127
127
|
arg = InstanceArgument(
|
|
128
128
|
instance_id=instance_id,
|
|
129
129
|
name=name,
|
|
@@ -173,7 +173,7 @@ class ExportResult:
|
|
|
173
173
|
position : ExportPosition, optional
|
|
174
174
|
The position for the merged content, by default AGENTS
|
|
175
175
|
"""
|
|
176
|
-
if other.main_content:
|
|
176
|
+
if other.main_content: # pragma: no branch
|
|
177
177
|
self.main_content = (
|
|
178
178
|
(self.main_content or "") + "\n" + other.main_content
|
|
179
179
|
).strip()
|
|
@@ -241,7 +241,7 @@ class ExportResult:
|
|
|
241
241
|
Additional metadata for the content, by default None
|
|
242
242
|
"""
|
|
243
243
|
order_value = order.value if isinstance(order, ContentOrder) else order
|
|
244
|
-
if content and content.strip():
|
|
244
|
+
if content and content.strip(): # pragma: no branch
|
|
245
245
|
positioned = PositionedContent(
|
|
246
246
|
content=content.strip() if not skip_strip else content,
|
|
247
247
|
position=position,
|
|
@@ -273,7 +273,7 @@ class ExportResult:
|
|
|
273
273
|
required : bool, optional
|
|
274
274
|
Whether the variable is required, by default True
|
|
275
275
|
"""
|
|
276
|
-
if name and value:
|
|
276
|
+
if name and value: # pragma: no branch
|
|
277
277
|
env_var = EnvironmentVariable(
|
|
278
278
|
name=name,
|
|
279
279
|
value=value,
|
waldiez/exporting/core/types.py
CHANGED
|
@@ -314,6 +314,7 @@ class ExportConfig:
|
|
|
314
314
|
if for_notebook:
|
|
315
315
|
output_extension = "ipynb"
|
|
316
316
|
cache_seed = kwargs.pop("cache_seed", None)
|
|
317
|
+
# noinspection PyUnreachableCode
|
|
317
318
|
if cache_seed is not None and not isinstance(cache_seed, int):
|
|
318
319
|
cache_seed = None
|
|
319
320
|
return cls(
|
|
@@ -97,7 +97,7 @@ def _get_agent_llm_config_arg_as_dict(
|
|
|
97
97
|
) -> str:
|
|
98
98
|
tab = " " * tab_leng * tabs if tabs > 0 else ""
|
|
99
99
|
if not agent.data.model_ids:
|
|
100
|
-
return f'{tab}"llm_config": False' + "\n"
|
|
100
|
+
return f'{tab}"llm_config": False,' + "\n"
|
|
101
101
|
content = f'{tab}"llm_config": autogen.LLMConfig(' + "\n"
|
|
102
102
|
content += f"{tab} config_list=["
|
|
103
103
|
got_at_least_one_model = False
|
|
@@ -110,7 +110,7 @@ def _get_agent_llm_config_arg_as_dict(
|
|
|
110
110
|
content += "\n" + f"{tab} {model_name}_llm_config,"
|
|
111
111
|
got_at_least_one_model = True
|
|
112
112
|
if not got_at_least_one_model: # pragma: no cover
|
|
113
|
-
return f'{tab}"llm_config": False' + "\n"
|
|
113
|
+
return f'{tab}"llm_config": False,' + "\n"
|
|
114
114
|
content += "\n" + f"{tab} ]," + "\n"
|
|
115
115
|
content += f"{tab} cache_seed={cache_seed}," + "\n"
|
|
116
116
|
if temperature is not None:
|
|
@@ -125,6 +125,7 @@ class ExecutionGenerator:
|
|
|
125
125
|
flow_content += " result_dicts: list[dict[str, Any]] = []\n"
|
|
126
126
|
space = " "
|
|
127
127
|
if cache_seed is not None:
|
|
128
|
+
# noinspection SqlDialectInspection
|
|
128
129
|
flow_content += (
|
|
129
130
|
f" with Cache.disk(cache_seed={cache_seed}"
|
|
130
131
|
") as cache: # pyright: ignore\n"
|
waldiez/exporting/flow/merger.py
CHANGED
|
@@ -167,7 +167,7 @@ class ContentMerger:
|
|
|
167
167
|
# Log conflicts but continue
|
|
168
168
|
for conflict in conflicts:
|
|
169
169
|
self.context.get_logger().warning(
|
|
170
|
-
|
|
170
|
+
"Import conflict: %s", conflict
|
|
171
171
|
)
|
|
172
172
|
|
|
173
173
|
return set(grouped.values())
|
|
@@ -309,7 +309,7 @@ class ContentMerger:
|
|
|
309
309
|
# Log conflicts but continue (non-fatal)
|
|
310
310
|
for conflict in conflicts:
|
|
311
311
|
self.context.get_logger().warning(
|
|
312
|
-
|
|
312
|
+
"Environment variable conflict: %s", conflict
|
|
313
313
|
)
|
|
314
314
|
|
|
315
315
|
return list(env_vars.values())
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
3
|
# pylint: disable=line-too-long
|
|
4
4
|
# flake8: noqa: E501
|
|
5
|
-
"""Common utils for the final
|
|
5
|
+
"""Common utils for the final flow generation."""
|
|
6
6
|
|
|
7
7
|
from waldiez.models import Waldiez
|
|
8
8
|
|
|
@@ -120,8 +120,8 @@ def main_doc_string() -> str:
|
|
|
120
120
|
|
|
121
121
|
Raises
|
|
122
122
|
------
|
|
123
|
-
|
|
124
|
-
If the chat session
|
|
123
|
+
SystemExit
|
|
124
|
+
If the user interrupts the chat session.
|
|
125
125
|
"""'''
|
|
126
126
|
|
|
127
127
|
|
|
@@ -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)) 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 += (
|
|
@@ -148,7 +114,8 @@ def get_sync_sqlite_out() -> str:
|
|
|
148
114
|
content += " rows = cursor.fetchall()\n"
|
|
149
115
|
content += " column_names = [description[0] for description "
|
|
150
116
|
content += "in cursor.description]\n"
|
|
151
|
-
|
|
117
|
+
# pylint: disable=line-too-long
|
|
118
|
+
content += " data = [dict(zip(column_names, row, strict=True)) for row in rows]\n"
|
|
152
119
|
content += " conn.close()\n"
|
|
153
120
|
content += (
|
|
154
121
|
' with open(csv_file, "w", newline="", encoding="utf-8") as file:\n'
|
|
@@ -165,52 +132,14 @@ def get_sync_sqlite_out() -> str:
|
|
|
165
132
|
return content
|
|
166
133
|
|
|
167
134
|
|
|
168
|
-
# pylint: disable=
|
|
169
|
-
# noinspection PyUnresolvedReferences
|
|
135
|
+
# pylint: disable=line-too-long
|
|
170
136
|
def get_async_sqlite_out() -> str:
|
|
171
|
-
|
|
137
|
+
"""Get the sqlite to csv and json conversion code string.
|
|
172
138
|
|
|
173
139
|
Returns
|
|
174
140
|
-------
|
|
175
141
|
str
|
|
176
142
|
The sqlite to csv and json conversion code string.
|
|
177
|
-
|
|
178
|
-
Example
|
|
179
|
-
-------
|
|
180
|
-
```python
|
|
181
|
-
>>> get_sqlite_outputs()
|
|
182
|
-
async def get_sqlite_out(dbname: str, table: str, csv_file: str) -> None:
|
|
183
|
-
\"\"\"Convert a sqlite table to csv and json files.
|
|
184
|
-
|
|
185
|
-
Parameters
|
|
186
|
-
----------
|
|
187
|
-
dbname : str
|
|
188
|
-
The sqlite database name.
|
|
189
|
-
table : str
|
|
190
|
-
The table name.
|
|
191
|
-
csv_file : str
|
|
192
|
-
The csv file name.
|
|
193
|
-
\"\"\"
|
|
194
|
-
conn = await aiosqlite.connect(dbname)
|
|
195
|
-
query = f"SELECT * FROM {table}" # nosec
|
|
196
|
-
try:
|
|
197
|
-
cursor = await conn.execute(query)
|
|
198
|
-
except BaseException: # pylint: disable=broad-exception-caught
|
|
199
|
-
await conn.close()
|
|
200
|
-
return
|
|
201
|
-
rows = await cursor.fetchall()
|
|
202
|
-
column_names = [description[0] for description in cursor.description]
|
|
203
|
-
data = [dict(zip(column_names, row)) for row in rows]
|
|
204
|
-
await cursor.close()
|
|
205
|
-
await conn.close()
|
|
206
|
-
async with aiofiles.open(csv_file, "w", newline="", encoding="utf-8") as file:
|
|
207
|
-
csv_writer = csv.DictWriter(file, fieldnames=column_names)
|
|
208
|
-
csv_writer.writeheader()
|
|
209
|
-
csv_writer.writerows(data)
|
|
210
|
-
json_file = csv_file.replace(".csv", ".json")
|
|
211
|
-
async with aiofiles.open(json_file, "w", encoding="utf-8") as file:
|
|
212
|
-
await file.write(json.dumps(data, indent=4, ensure_ascii=False)
|
|
213
|
-
```
|
|
214
143
|
"""
|
|
215
144
|
# fmt: off
|
|
216
145
|
content = "\n\n"
|
|
@@ -235,7 +164,7 @@ def get_async_sqlite_out() -> str:
|
|
|
235
164
|
content += " rows = await cursor.fetchall()\n"
|
|
236
165
|
content += " column_names = [description[0] for description "
|
|
237
166
|
content += "in cursor.description]\n"
|
|
238
|
-
content += " data = [dict(zip(column_names, row)) for row in rows]\n"
|
|
167
|
+
content += " data = [dict(zip(column_names, row, strict=True)) for row in rows]\n"
|
|
239
168
|
content += " await cursor.close()\n"
|
|
240
169
|
content += " await conn.close()\n"
|
|
241
170
|
content += ' async with aiofiles.open(csv_file, "w", newline="", encoding="utf-8") as file:\n'
|
|
@@ -369,9 +298,7 @@ def get_stop_logging(is_async: bool, tabs: int = 0) -> str:
|
|
|
369
298
|
content += "def stop_logging() -> None:\n"
|
|
370
299
|
content += ' """Stop logging."""\n'
|
|
371
300
|
if is_async:
|
|
372
|
-
content += f"{tab}
|
|
373
|
-
content += f"{tab} from asyncer import asyncify\n\n"
|
|
374
|
-
content += f"{tab} await asyncify(runtime_logging.stop)()\n"
|
|
301
|
+
content += f"{tab} await asyncio.to_thread(runtime_logging.stop)\n"
|
|
375
302
|
else:
|
|
376
303
|
content += f"{tab} runtime_logging.stop()\n"
|
|
377
304
|
content += get_sqlite_out_call(tabs + 1, is_async)
|
|
@@ -32,6 +32,7 @@ class ToolsExporter(Exporter[ToolExtras]):
|
|
|
32
32
|
agent_names: dict[str, str],
|
|
33
33
|
tools: list[WaldiezTool],
|
|
34
34
|
tool_names: dict[str, str],
|
|
35
|
+
is_async: bool,
|
|
35
36
|
output_dir: str | Path | None = None,
|
|
36
37
|
context: ExporterContext | None = None,
|
|
37
38
|
**kwargs: Any,
|
|
@@ -50,6 +51,8 @@ class ToolsExporter(Exporter[ToolExtras]):
|
|
|
50
51
|
The tools to export.
|
|
51
52
|
tool_names : dict[str, str]
|
|
52
53
|
Mapping of tool IDs to names.
|
|
54
|
+
is_async : bool
|
|
55
|
+
Whether the flow is asynchronous.
|
|
53
56
|
output_dir : str | Path | None
|
|
54
57
|
Output directory for generated files, by default None
|
|
55
58
|
context : ExporterContext | None
|
|
@@ -64,6 +67,7 @@ class ToolsExporter(Exporter[ToolExtras]):
|
|
|
64
67
|
self.agent_names = agent_names
|
|
65
68
|
self.tools = tools
|
|
66
69
|
self.tool_names = tool_names
|
|
70
|
+
self.is_async = is_async
|
|
67
71
|
self.output_dir = Path(output_dir) if output_dir else None
|
|
68
72
|
|
|
69
73
|
# Initialize extras with processed tool content
|
|
@@ -83,6 +87,7 @@ class ToolsExporter(Exporter[ToolExtras]):
|
|
|
83
87
|
flow_name=self.flow_name,
|
|
84
88
|
tools=self.tools,
|
|
85
89
|
tool_names=self.tool_names,
|
|
90
|
+
is_async=self.is_async,
|
|
86
91
|
output_dir=self.output_dir,
|
|
87
92
|
)
|
|
88
93
|
|
|
@@ -16,6 +16,7 @@ def create_tools_exporter(
|
|
|
16
16
|
agent_names: dict[str, str],
|
|
17
17
|
tools: list[WaldiezTool],
|
|
18
18
|
tool_names: dict[str, str],
|
|
19
|
+
is_async: bool,
|
|
19
20
|
output_dir: str | Path | None = None,
|
|
20
21
|
context: ExporterContext | None = None,
|
|
21
22
|
) -> ToolsExporter:
|
|
@@ -33,6 +34,8 @@ def create_tools_exporter(
|
|
|
33
34
|
The tools to export.
|
|
34
35
|
tool_names : dict[str, str]
|
|
35
36
|
Mapping of tool IDs to names.
|
|
37
|
+
is_async : bool
|
|
38
|
+
Whether the flow is asynchronous.
|
|
36
39
|
output_dir : str | Path | None, optional
|
|
37
40
|
Output directory for generated files, by default None
|
|
38
41
|
context : ExporterContext | None, optional
|
|
@@ -52,5 +55,6 @@ def create_tools_exporter(
|
|
|
52
55
|
tools=tools,
|
|
53
56
|
tool_names=tool_names,
|
|
54
57
|
output_dir=output_dir,
|
|
58
|
+
is_async=is_async,
|
|
55
59
|
context=context,
|
|
56
60
|
)
|
|
@@ -33,6 +33,7 @@ class ToolProcessor:
|
|
|
33
33
|
flow_name: str,
|
|
34
34
|
tools: list[WaldiezTool],
|
|
35
35
|
tool_names: dict[str, str],
|
|
36
|
+
is_async: bool,
|
|
36
37
|
output_dir: Path | None = None,
|
|
37
38
|
):
|
|
38
39
|
"""Initialize the tool processor.
|
|
@@ -52,6 +53,7 @@ class ToolProcessor:
|
|
|
52
53
|
self.tools = tools
|
|
53
54
|
self.tool_names = tool_names
|
|
54
55
|
self.output_dir = output_dir
|
|
56
|
+
self.is_async = is_async
|
|
55
57
|
|
|
56
58
|
def process(self) -> ToolProcessingResult:
|
|
57
59
|
"""Process all tools and return consolidated result.
|
|
@@ -94,7 +96,9 @@ class ToolProcessor:
|
|
|
94
96
|
The result to add processed content to.
|
|
95
97
|
"""
|
|
96
98
|
# Get tool content
|
|
97
|
-
tool_content = tool.get_content(
|
|
99
|
+
tool_content = tool.get_content(
|
|
100
|
+
runtime_kwargs={"is_async": self.is_async}
|
|
101
|
+
)
|
|
98
102
|
if tool_content: # pragma: no branch
|
|
99
103
|
# Add interop conversion if needed
|
|
100
104
|
if tool.is_interop:
|
waldiez/io/__init__.py
CHANGED
|
@@ -30,7 +30,7 @@ from .models import (
|
|
|
30
30
|
VideoMediaContent,
|
|
31
31
|
)
|
|
32
32
|
from .structured import StructuredIOStream
|
|
33
|
-
from .utils import MediaType, MessageType
|
|
33
|
+
from .utils import DEBUG_INPUT_PROMPT, START_CHAT_PROMPT, MediaType, MessageType
|
|
34
34
|
|
|
35
35
|
try:
|
|
36
36
|
from .redis import RedisIOStream # type: ignore[no-redef,unused-ignore]
|
|
@@ -125,4 +125,6 @@ __all__ = [
|
|
|
125
125
|
"AudioContent",
|
|
126
126
|
"VideoMediaContent",
|
|
127
127
|
"VideoContent",
|
|
128
|
+
"DEBUG_INPUT_PROMPT",
|
|
129
|
+
"START_CHAT_PROMPT",
|
|
128
130
|
]
|
waldiez/io/_ws.py
CHANGED
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
3
|
# flake8: noqa: E501
|
|
4
4
|
# pylint: disable=line-too-long
|
|
5
|
+
# pyright: reportUnknownMemberType=false,reportUnknownParameterType=false
|
|
6
|
+
# pyright: reportUnknownVariableType=false,reportUnknownArgumentType=false
|
|
5
7
|
"""WebSocket IOStream implementation for AsyncIO."""
|
|
6
8
|
|
|
7
9
|
import asyncio
|
|
10
|
+
import logging
|
|
8
11
|
from typing import Any, Protocol
|
|
9
12
|
|
|
10
13
|
HAS_WS_LIB = False
|
|
@@ -13,7 +16,7 @@ try:
|
|
|
13
16
|
from starlette.websockets import WebSocket # type: ignore[unused-ignore, unused-import, import-not-found, import-untyped] # noqa
|
|
14
17
|
|
|
15
18
|
HAS_WS_LIB = True # pyright: ignore
|
|
16
|
-
except ImportError:
|
|
19
|
+
except ImportError: # pragma: no cover
|
|
17
20
|
pass
|
|
18
21
|
|
|
19
22
|
try:
|
|
@@ -68,6 +71,7 @@ class WebSocketsAdapter:
|
|
|
68
71
|
The websockets library connection.
|
|
69
72
|
"""
|
|
70
73
|
self.websocket = websocket
|
|
74
|
+
self.log = logging.getLogger(__name__)
|
|
71
75
|
|
|
72
76
|
async def send_message(self, message: str) -> None:
|
|
73
77
|
"""Send a message using websockets library.
|
|
@@ -100,11 +104,14 @@ class WebSocketsAdapter:
|
|
|
100
104
|
)
|
|
101
105
|
if isinstance(response, bytes):
|
|
102
106
|
return response.decode("utf-8")
|
|
107
|
+
# noinspection PyUnreachableCode
|
|
103
108
|
return response if isinstance(response, str) else str(response)
|
|
104
109
|
except asyncio.TimeoutError:
|
|
105
110
|
return ""
|
|
106
|
-
except BaseException: # pylint: disable=broad-exception-caught
|
|
107
|
-
|
|
111
|
+
except BaseException as exc: # pylint: disable=broad-exception-caught
|
|
112
|
+
self.log.error(
|
|
113
|
+
"WebsocketsAdapter: Error receiving message: %s", exc
|
|
114
|
+
) # pragma: no cover
|
|
108
115
|
return ""
|
|
109
116
|
|
|
110
117
|
|
|
@@ -120,6 +127,7 @@ class StarletteAdapter:
|
|
|
120
127
|
The Starlette/FastAPI WebSocket connection.
|
|
121
128
|
"""
|
|
122
129
|
self.websocket = websocket
|
|
130
|
+
self.log = logging.getLogger(__name__)
|
|
123
131
|
|
|
124
132
|
async def send_message(self, message: str) -> None:
|
|
125
133
|
"""Send a message using Starlette WebSocket.
|
|
@@ -151,8 +159,10 @@ class StarletteAdapter:
|
|
|
151
159
|
)
|
|
152
160
|
except asyncio.TimeoutError:
|
|
153
161
|
return ""
|
|
154
|
-
except BaseException: # pylint: disable=broad-exception-caught
|
|
155
|
-
|
|
162
|
+
except BaseException as exc: # pylint: disable=broad-exception-caught
|
|
163
|
+
self.log.error(
|
|
164
|
+
"StarletteAdapter: Error receiving message: %s", exc
|
|
165
|
+
) # pragma: no cover
|
|
156
166
|
return ""
|
|
157
167
|
|
|
158
168
|
|