waldiez 0.1.7__py3-none-any.whl → 0.1.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of waldiez might be problematic. Click here for more details.
- waldiez/_version.py +1 -1
- waldiez/exporting/agents/rag_user/chroma_utils.py +1 -2
- waldiez/exporting/chats/nested.py +2 -12
- waldiez/exporting/utils/logging_utils.py +1 -0
- waldiez/io/__init__.py +74 -113
- waldiez/models/agents/agent/nested_chat.py +4 -8
- waldiez/models/waldiez.py +5 -8
- {waldiez-0.1.7.dist-info → waldiez-0.1.8.dist-info}/METADATA +83 -51
- {waldiez-0.1.7.dist-info → waldiez-0.1.8.dist-info}/RECORD +12 -16
- {waldiez-0.1.7.dist-info → waldiez-0.1.8.dist-info}/WHEEL +1 -1
- waldiez/io/stream/__init__.py +0 -7
- waldiez/io/stream/consumer.py +0 -139
- waldiez/io/stream/provider.py +0 -343
- waldiez/io/stream/server.py +0 -438
- {waldiez-0.1.7.dist-info → waldiez-0.1.8.dist-info}/entry_points.txt +0 -0
- {waldiez-0.1.7.dist-info → waldiez-0.1.8.dist-info}/licenses/LICENSE +0 -0
waldiez/_version.py
CHANGED
|
@@ -109,8 +109,7 @@ def get_chroma_db_args(
|
|
|
109
109
|
f" embedding_function={embedding_function_arg},\n"
|
|
110
110
|
)
|
|
111
111
|
# The RAG example:
|
|
112
|
-
# https://
|
|
113
|
-
# notebooks/agentchat_groupchat_RAG
|
|
112
|
+
# https://ag2ai.github.io/ag2/docs/notebooks/agentchat_groupchat_RAG/
|
|
114
113
|
# raises `InvalidCollectionException`: Collection groupchat does not exist.
|
|
115
114
|
# https://github.com/chroma-core/chroma/issues/861
|
|
116
115
|
# https://github.com/microsoft/autogen/issues/3551#issuecomment-2366930994
|
|
@@ -14,7 +14,6 @@ from .helpers import escape_summary_args_quotes
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def get_nested_chat_trigger_agent_names(
|
|
17
|
-
all_chats: List[WaldiezChat],
|
|
18
17
|
nested_chat: WaldiezAgentNestedChat,
|
|
19
18
|
agent_names: Dict[str, str],
|
|
20
19
|
) -> str:
|
|
@@ -22,8 +21,6 @@ def get_nested_chat_trigger_agent_names(
|
|
|
22
21
|
|
|
23
22
|
Parameters
|
|
24
23
|
----------
|
|
25
|
-
all_chats : List[WaldiezChat]
|
|
26
|
-
All the chats in the flow.
|
|
27
24
|
nested_chat : WaldiezAgentNestedChat
|
|
28
25
|
The nested chat.
|
|
29
26
|
agent_names : Dict[str, str]
|
|
@@ -34,14 +31,7 @@ def get_nested_chat_trigger_agent_names(
|
|
|
34
31
|
str
|
|
35
32
|
The trigger agent names.
|
|
36
33
|
"""
|
|
37
|
-
|
|
38
|
-
for message in nested_chat.triggered_by:
|
|
39
|
-
waldiez_chat = next(chat for chat in all_chats if chat.id == message.id)
|
|
40
|
-
if message.is_reply:
|
|
41
|
-
trigger_agent_ids.append(waldiez_chat.target)
|
|
42
|
-
else:
|
|
43
|
-
trigger_agent_ids.append(waldiez_chat.source)
|
|
44
|
-
agents = [agent_names[agent_id] for agent_id in trigger_agent_ids]
|
|
34
|
+
agents = [agent_names[agent_id] for agent_id in nested_chat.triggered_by]
|
|
45
35
|
trigger_string = f'{[", ".join(agents)]}'
|
|
46
36
|
return trigger_string.replace("'", '"')
|
|
47
37
|
|
|
@@ -228,7 +218,7 @@ def export_nested_chat(
|
|
|
228
218
|
use_suffix = len(agent.data.nested_chats) > 1
|
|
229
219
|
for index, entry in enumerate(agent.data.nested_chats):
|
|
230
220
|
trigger_names = get_nested_chat_trigger_agent_names(
|
|
231
|
-
|
|
221
|
+
nested_chat=entry, agent_names=agent_names
|
|
232
222
|
)
|
|
233
223
|
chat_queue, extra_methods = get_nested_chat_queue(
|
|
234
224
|
nested_chat=entry,
|
|
@@ -14,6 +14,7 @@ get_sqlite_to_csv_call_string
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
# Check issue:
|
|
17
|
+
# Also check if in ag2 this still applies
|
|
17
18
|
# https://github.com/microsoft/autogen/issues/2286
|
|
18
19
|
# we cannot log new agents if they have code_execution enabled
|
|
19
20
|
# we get `Path` is not JSON serializable (on code_executor)
|
waldiez/io/__init__.py
CHANGED
|
@@ -5,100 +5,48 @@ It is meant to be used when we want to use custom
|
|
|
5
5
|
is used to trigger a UI element that requires user input.
|
|
6
6
|
and sends back the user's input to the websocket. In the same
|
|
7
7
|
way, we can use it to forward what is meant to be printed.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
We use:
|
|
11
|
-
|
|
12
|
-
- one tcp server to handle messaging between the clients
|
|
13
|
-
- one tcp client (provider) to set and forward the user's input
|
|
14
|
-
that we got elsewhere (e.g. from a websocket connection)
|
|
15
|
-
- one tcp client (consumer) to ask and get the input from the provider
|
|
16
8
|
"""
|
|
17
9
|
|
|
18
|
-
import
|
|
19
|
-
from contextlib import closing
|
|
10
|
+
import threading
|
|
20
11
|
from typing import Any, Callable, Optional
|
|
21
12
|
|
|
22
13
|
from autogen.io import IOStream # type: ignore[import-untyped]
|
|
23
14
|
|
|
24
|
-
from .stream import TCPConsumer, TCPProvider, TCPServer
|
|
25
|
-
|
|
26
15
|
|
|
27
16
|
class WaldiezIOStream(IOStream):
|
|
28
|
-
"""Custom IOStream class to handle
|
|
17
|
+
"""Custom IOStream class to handle `print` and `input` functions."""
|
|
29
18
|
|
|
30
19
|
def __init__(
|
|
31
20
|
self,
|
|
32
|
-
|
|
33
|
-
input_timeout: float = 60,
|
|
21
|
+
input_timeout: float = 60.0,
|
|
34
22
|
print_function: Optional[Callable[..., None]] = None,
|
|
35
23
|
on_prompt_input: Optional[Callable[[str], None]] = None,
|
|
36
24
|
) -> None:
|
|
37
|
-
"""
|
|
25
|
+
"""
|
|
26
|
+
Initialize the IOStream.
|
|
38
27
|
|
|
39
28
|
Parameters
|
|
40
29
|
----------
|
|
41
|
-
port : int, optional
|
|
42
|
-
The port to use, by default 0 (auto-assign).
|
|
43
30
|
input_timeout : float, optional
|
|
44
|
-
The input timeout, by default 60.
|
|
31
|
+
The input timeout in seconds, by default 60.0.
|
|
45
32
|
print_function : Optional[Callable[..., None]], optional
|
|
46
|
-
The
|
|
33
|
+
The function to handle print operations, by default None.
|
|
47
34
|
on_prompt_input : Optional[Callable[[str], None]], optional
|
|
48
|
-
The function to call for
|
|
35
|
+
The function to call for processing input prompts, by default None.
|
|
36
|
+
|
|
37
|
+
Notes
|
|
38
|
+
-----
|
|
39
|
+
- on_prompt_input: It does not return a string (like 'input' does).
|
|
40
|
+
Instead, it is meant to be used to forward the prompt somewhere else
|
|
41
|
+
(e.g., a websocket). When we get the input, we can call
|
|
42
|
+
`waldiez_io_stream.set_input(input_data)` with the input data.
|
|
49
43
|
"""
|
|
50
|
-
self.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
self.
|
|
54
|
-
self.
|
|
55
|
-
self.
|
|
56
|
-
self._server.start()
|
|
57
|
-
self._provider = TCPProvider("localhost", port, response=None)
|
|
58
|
-
self._on_prompt_input = on_prompt_input
|
|
59
|
-
|
|
60
|
-
@property
|
|
61
|
-
def print_function(self) -> Optional[Callable[..., None]]:
|
|
62
|
-
"""Get the print function."""
|
|
63
|
-
return self._print_function
|
|
64
|
-
|
|
65
|
-
def open(self) -> None:
|
|
66
|
-
"""Start the server."""
|
|
67
|
-
if not self._server.is_running():
|
|
68
|
-
self._server.start()
|
|
69
|
-
|
|
70
|
-
def close(self) -> None:
|
|
71
|
-
"""Stop the server and the provider."""
|
|
72
|
-
# pylint: disable=broad-except
|
|
73
|
-
if self._server.is_running():
|
|
74
|
-
try:
|
|
75
|
-
self._server.stop()
|
|
76
|
-
except BaseException: # pragma: no cover
|
|
77
|
-
pass
|
|
78
|
-
try:
|
|
79
|
-
self._provider.stop()
|
|
80
|
-
except BaseException: # pragma: no cover
|
|
81
|
-
pass
|
|
82
|
-
|
|
83
|
-
def __del__(self) -> None: # pragma: no cover
|
|
84
|
-
"""Delete the instance."""
|
|
85
|
-
self.close()
|
|
86
|
-
|
|
87
|
-
def forward_input(self, input_data: str) -> None:
|
|
88
|
-
"""Forward the user's input to the provider.
|
|
89
|
-
|
|
90
|
-
When we have the input data
|
|
91
|
-
e.g. from 'input(..)' or from a websocket connection,
|
|
92
|
-
we can forward it to the provider (the tcp client)
|
|
93
|
-
to make it available to the consumer (the other tcp client).
|
|
94
|
-
Parameters
|
|
95
|
-
----------
|
|
96
|
-
input_data : str
|
|
97
|
-
The input data to forward.
|
|
98
|
-
"""
|
|
99
|
-
if not self._provider.is_running():
|
|
100
|
-
self._provider.start()
|
|
101
|
-
self._provider.set_response(input_data)
|
|
44
|
+
self.input_timeout = input_timeout # Timeout for input
|
|
45
|
+
self.print_function = print_function # Custom print handler
|
|
46
|
+
self._on_prompt_input = on_prompt_input # Custom input prompt handler
|
|
47
|
+
self.current_input: Optional[str] = None # Store the current input
|
|
48
|
+
self._input_event = threading.Event() # Event to signal input readiness
|
|
49
|
+
self.allow_input = True # Flag to allow or block input setting
|
|
102
50
|
|
|
103
51
|
def print(
|
|
104
52
|
self,
|
|
@@ -107,7 +55,8 @@ class WaldiezIOStream(IOStream):
|
|
|
107
55
|
end: str = "\n",
|
|
108
56
|
flush: bool = False,
|
|
109
57
|
) -> None:
|
|
110
|
-
"""
|
|
58
|
+
"""
|
|
59
|
+
Mock the `print` function.
|
|
111
60
|
|
|
112
61
|
Parameters
|
|
113
62
|
----------
|
|
@@ -116,66 +65,78 @@ class WaldiezIOStream(IOStream):
|
|
|
116
65
|
sep : str, optional
|
|
117
66
|
The separator, by default " ".
|
|
118
67
|
end : str, optional
|
|
119
|
-
The
|
|
68
|
+
The ending string, by default a new line.
|
|
120
69
|
flush : bool, optional
|
|
121
|
-
Whether to flush, by default False.
|
|
70
|
+
Whether to flush the output, by default False.
|
|
122
71
|
"""
|
|
123
72
|
print_function: Callable[..., None] = self.print_function or print
|
|
124
73
|
print_function(*objects, sep=sep, end=end, flush=flush)
|
|
125
74
|
|
|
126
75
|
def input(self, prompt: str = "", *, password: bool = False) -> str:
|
|
127
|
-
"""
|
|
76
|
+
"""
|
|
77
|
+
Mock the `input` function with optional timeout handling.
|
|
128
78
|
|
|
129
79
|
Parameters
|
|
130
80
|
----------
|
|
131
81
|
prompt : str, optional
|
|
132
82
|
The prompt to show, by default "".
|
|
133
|
-
password : bool, optional
|
|
134
|
-
Whether to
|
|
83
|
+
password : bool, optional
|
|
84
|
+
Whether to hide the input as password (not used), by default False.
|
|
135
85
|
|
|
136
86
|
Returns
|
|
137
87
|
-------
|
|
138
88
|
str
|
|
139
|
-
The user's input.
|
|
89
|
+
The user's input or '\n' if timeout occurs.
|
|
140
90
|
"""
|
|
141
91
|
_prompt = prompt or "Your input:"
|
|
142
|
-
if _prompt in (">", "> "):
|
|
92
|
+
if _prompt in (">", "> "): # pragma: no cover
|
|
143
93
|
_prompt = "Your input:"
|
|
144
94
|
if prompt:
|
|
145
95
|
if self._on_prompt_input:
|
|
146
96
|
self._on_prompt_input(_prompt)
|
|
147
97
|
self.print(_prompt, end="")
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
#
|
|
151
|
-
self.
|
|
152
|
-
if not self.
|
|
153
|
-
self.
|
|
154
|
-
|
|
98
|
+
|
|
99
|
+
# Only reset if no input is currently set
|
|
100
|
+
# e.g. handle the case when we call set_input(..) before input(..)
|
|
101
|
+
already_set = self._input_event.is_set()
|
|
102
|
+
if not self._input_event.is_set():
|
|
103
|
+
self.current_input = None # Reset previous input
|
|
104
|
+
self._input_event.clear() # Clear the event before waiting
|
|
105
|
+
|
|
106
|
+
# Wait for input or timeout
|
|
107
|
+
if not self._input_event.wait(self.input_timeout):
|
|
108
|
+
# Timeout occurred, return what we have so far
|
|
109
|
+
to_return = (
|
|
110
|
+
self.current_input if self.current_input is not None else "\n"
|
|
155
111
|
)
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
112
|
+
self.current_input = None
|
|
113
|
+
self._input_event.clear()
|
|
114
|
+
# if we had already set the input, return it
|
|
115
|
+
return to_return if already_set else "\n"
|
|
116
|
+
|
|
117
|
+
# Input is ready, return it
|
|
118
|
+
to_return = (
|
|
119
|
+
self.current_input if self.current_input is not None else "\n"
|
|
159
120
|
)
|
|
160
|
-
|
|
161
|
-
#
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
121
|
+
self.current_input = None
|
|
122
|
+
self._input_event.clear() # Clear the event after waiting
|
|
123
|
+
return to_return
|
|
124
|
+
|
|
125
|
+
def set_input(self, value: str) -> None:
|
|
126
|
+
"""
|
|
127
|
+
Set the input value and signal that input is ready.
|
|
128
|
+
|
|
129
|
+
Parameters
|
|
130
|
+
----------
|
|
131
|
+
value : str
|
|
132
|
+
The value to set as input.
|
|
133
|
+
"""
|
|
134
|
+
if self.allow_input: # Respect the allow_input flag
|
|
135
|
+
self.current_input = value
|
|
136
|
+
self._input_event.set() # Signal that input is ready
|
|
137
|
+
|
|
138
|
+
def reset_state(self) -> None:
|
|
139
|
+
"""Reset the IOStream state for testing."""
|
|
140
|
+
self.current_input = None
|
|
141
|
+
self._input_event.clear()
|
|
142
|
+
self.allow_input = True # Re-enable input setting
|
|
@@ -40,22 +40,18 @@ class WaldiezAgentNestedChat(WaldiezBase):
|
|
|
40
40
|
|
|
41
41
|
Attributes
|
|
42
42
|
----------
|
|
43
|
-
triggered_by : List[
|
|
44
|
-
A list of
|
|
45
|
-
the triggering of the nested chat.
|
|
43
|
+
triggered_by : List[str]
|
|
44
|
+
A list of agent ids that trigger the nested chat.
|
|
46
45
|
messages : List[WaldiezAgentNestedChatMessage]
|
|
47
46
|
The list of messages (chat ids and 'is_reply'z)
|
|
48
47
|
to include the in the nested chat registration.
|
|
49
48
|
"""
|
|
50
49
|
|
|
51
50
|
triggered_by: Annotated[
|
|
52
|
-
List[
|
|
51
|
+
List[str],
|
|
53
52
|
Field(
|
|
54
53
|
title="Triggered By",
|
|
55
|
-
description=(
|
|
56
|
-
"A list of chats (id and is_reply) to determine"
|
|
57
|
-
"the triggering of the nested chat."
|
|
58
|
-
),
|
|
54
|
+
description=("A list of agent ids that trigger the nested chat."),
|
|
59
55
|
alias="triggeredBy",
|
|
60
56
|
default_factory=list,
|
|
61
57
|
),
|
waldiez/models/waldiez.py
CHANGED
|
@@ -205,18 +205,16 @@ class Waldiez:
|
|
|
205
205
|
requirements_list = filter(
|
|
206
206
|
lambda requirement: not (
|
|
207
207
|
requirement.startswith("pyautogen")
|
|
208
|
-
or requirement.startswith("
|
|
208
|
+
or requirement.startswith("ag2")
|
|
209
209
|
),
|
|
210
210
|
self.flow.requirements,
|
|
211
211
|
)
|
|
212
212
|
requirements = set(requirements_list)
|
|
213
213
|
if self.has_rag_agents:
|
|
214
|
-
requirements.add(
|
|
215
|
-
f"autogen-agentchat[retrievechat]=={autogen_version}"
|
|
216
|
-
)
|
|
214
|
+
requirements.add(f"ag2[retrievechat]=={autogen_version}")
|
|
217
215
|
else:
|
|
218
|
-
requirements.add(f"
|
|
219
|
-
# ref: https://github.com/
|
|
216
|
+
requirements.add(f"ag2=={autogen_version}")
|
|
217
|
+
# ref: https://github.com/ag2ai/ag2/blob/main/setup.py
|
|
220
218
|
models_with_additional_requirements = [
|
|
221
219
|
"together",
|
|
222
220
|
"gemini",
|
|
@@ -229,8 +227,7 @@ class Waldiez:
|
|
|
229
227
|
for model in self.models:
|
|
230
228
|
if model.data.api_type in models_with_additional_requirements:
|
|
231
229
|
requirements.add(
|
|
232
|
-
f"
|
|
233
|
-
f"{autogen_version}"
|
|
230
|
+
f"ag2[{model.data.api_type}]==" f"{autogen_version}"
|
|
234
231
|
)
|
|
235
232
|
return list(requirements)
|
|
236
233
|
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: waldiez
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
4
4
|
Summary: waldiez
|
|
5
|
-
Project-URL: homepage, https://waldiez.github.io/
|
|
6
|
-
Project-URL: repository, https://github.com/waldiez/
|
|
5
|
+
Project-URL: homepage, https://waldiez.github.io/waldiez/
|
|
6
|
+
Project-URL: repository, https://github.com/waldiez/waldiez.git
|
|
7
7
|
Author-email: Panagiotis Kasnesis <pkasnesis@thingenious.io>, Lazaros Toumanidis <laztoum@protonmail.com>
|
|
8
|
-
License-File: LICENSE
|
|
9
8
|
Classifier: Development Status :: 3 - Alpha
|
|
10
9
|
Classifier: Intended Audience :: Developers
|
|
11
10
|
Classifier: Intended Audience :: Science/Research
|
|
@@ -17,28 +16,26 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
18
|
Requires-Python: <3.13,>=3.10
|
|
20
|
-
Requires-Dist:
|
|
19
|
+
Requires-Dist: ag2==0.3.2
|
|
21
20
|
Requires-Dist: jupytext
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
Requires-Dist:
|
|
25
|
-
Requires-Dist:
|
|
26
|
-
Requires-Dist:
|
|
27
|
-
Requires-Dist:
|
|
28
|
-
Requires-Dist:
|
|
29
|
-
Requires-Dist:
|
|
30
|
-
Requires-Dist:
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist:
|
|
33
|
-
Requires-Dist:
|
|
34
|
-
Requires-Dist:
|
|
35
|
-
Requires-Dist:
|
|
36
|
-
Requires-Dist:
|
|
37
|
-
Requires-Dist:
|
|
38
|
-
Requires-Dist:
|
|
39
|
-
Requires-Dist:
|
|
40
|
-
Requires-Dist: pymongo==4.10.1; extra == 'autogen-extras'
|
|
41
|
-
Requires-Dist: qdrant-client==1.12.1; extra == 'autogen-extras'
|
|
21
|
+
Provides-Extra: ag2-extras
|
|
22
|
+
Requires-Dist: ag2[anthropic]==0.3.2; extra == 'ag2-extras'
|
|
23
|
+
Requires-Dist: ag2[bedrock]==0.3.2; extra == 'ag2-extras'
|
|
24
|
+
Requires-Dist: ag2[gemini]==0.3.2; extra == 'ag2-extras'
|
|
25
|
+
Requires-Dist: ag2[groq]==0.3.2; extra == 'ag2-extras'
|
|
26
|
+
Requires-Dist: ag2[mistral]==0.3.2; extra == 'ag2-extras'
|
|
27
|
+
Requires-Dist: ag2[retrievechat-mongodb]==0.3.2; extra == 'ag2-extras'
|
|
28
|
+
Requires-Dist: ag2[retrievechat-pgvector]==0.3.2; extra == 'ag2-extras'
|
|
29
|
+
Requires-Dist: ag2[retrievechat-qdrant]==0.3.2; extra == 'ag2-extras'
|
|
30
|
+
Requires-Dist: ag2[retrievechat]==0.3.2; extra == 'ag2-extras'
|
|
31
|
+
Requires-Dist: ag2[together]==0.3.2; extra == 'ag2-extras'
|
|
32
|
+
Requires-Dist: ag2[websurfer]==0.3.2; extra == 'ag2-extras'
|
|
33
|
+
Requires-Dist: chromadb==0.5.3; extra == 'ag2-extras'
|
|
34
|
+
Requires-Dist: fastembed==0.4.2; extra == 'ag2-extras'
|
|
35
|
+
Requires-Dist: pgvector>=0.2.5; extra == 'ag2-extras'
|
|
36
|
+
Requires-Dist: psycopg[binary]>=3.1.18; extra == 'ag2-extras'
|
|
37
|
+
Requires-Dist: pymongo==4.10.1; extra == 'ag2-extras'
|
|
38
|
+
Requires-Dist: qdrant-client==1.12.1; extra == 'ag2-extras'
|
|
42
39
|
Provides-Extra: dev
|
|
43
40
|
Requires-Dist: autoflake==2.3.1; extra == 'dev'
|
|
44
41
|
Requires-Dist: bandit==1.7.10; extra == 'dev'
|
|
@@ -50,7 +47,7 @@ Requires-Dist: pre-commit==4.0.1; extra == 'dev'
|
|
|
50
47
|
Requires-Dist: pydocstyle==6.3.0; extra == 'dev'
|
|
51
48
|
Requires-Dist: pylint==3.3.1; extra == 'dev'
|
|
52
49
|
Requires-Dist: python-dotenv==1.0.1; extra == 'dev'
|
|
53
|
-
Requires-Dist: ruff==0.7.
|
|
50
|
+
Requires-Dist: ruff==0.7.4; extra == 'dev'
|
|
54
51
|
Requires-Dist: types-pyyaml==6.0.12; extra == 'dev'
|
|
55
52
|
Requires-Dist: yamllint==1.35.1; extra == 'dev'
|
|
56
53
|
Provides-Extra: docs
|
|
@@ -58,11 +55,11 @@ Requires-Dist: mdx-include==1.4.2; extra == 'docs'
|
|
|
58
55
|
Requires-Dist: mdx-truly-sane-lists==1.3; extra == 'docs'
|
|
59
56
|
Requires-Dist: mkdocs-jupyter==0.25.1; extra == 'docs'
|
|
60
57
|
Requires-Dist: mkdocs-macros-plugin==1.3.7; extra == 'docs'
|
|
61
|
-
Requires-Dist: mkdocs-material==9.5.
|
|
58
|
+
Requires-Dist: mkdocs-material==9.5.44; extra == 'docs'
|
|
62
59
|
Requires-Dist: mkdocs-minify-html-plugin==0.2.3; extra == 'docs'
|
|
63
60
|
Requires-Dist: mkdocs==1.6.1; extra == 'docs'
|
|
64
61
|
Requires-Dist: mkdocstrings-python==1.12.2; extra == 'docs'
|
|
65
|
-
Requires-Dist: mkdocstrings[crystal,python]==0.
|
|
62
|
+
Requires-Dist: mkdocstrings[crystal,python]==0.27.0; extra == 'docs'
|
|
66
63
|
Provides-Extra: test
|
|
67
64
|
Requires-Dist: pytest-cov==6.0.0; extra == 'test'
|
|
68
65
|
Requires-Dist: pytest-html==4.1.1; extra == 'test'
|
|
@@ -74,20 +71,20 @@ Description-Content-Type: text/markdown
|
|
|
74
71
|
|
|
75
72
|
# Waldiez
|
|
76
73
|
|
|
77
|
-
 [](https://coveralls.io/github/waldiez/waldiez) [](https://badge.fury.io/py/waldiez)
|
|
78
75
|
|
|
79
76
|
Translate a Waldiez flow:
|
|
80
77
|
|
|
81
|
-

|
|
82
79
|
|
|
83
|
-
To a python script or a jupyter notebook with the corresponding [
|
|
80
|
+
To a python script or a jupyter notebook with the corresponding [ag2](https://github.com/ag2ai/ag2/) agents and chats.
|
|
84
81
|
|
|
85
82
|
## Features
|
|
86
83
|
|
|
87
84
|
- Export .waldiez flows to .py or .ipynb
|
|
88
85
|
- Run a .waldiez flow
|
|
89
86
|
- Include a `logs` folder with the logs of the flow in csv format
|
|
90
|
-
- Provide a custom [IOSStream](https://
|
|
87
|
+
- Provide a custom [IOSStream](https://ag2ai.github.io/ag2/docs/reference/io/base#iostream) to handle input and output.
|
|
91
88
|
|
|
92
89
|
## Installation
|
|
93
90
|
|
|
@@ -100,7 +97,7 @@ python -m pip install waldiez
|
|
|
100
97
|
From the repository:
|
|
101
98
|
|
|
102
99
|
```bash
|
|
103
|
-
python -m pip install git+https://github.com/waldiez/
|
|
100
|
+
python -m pip install git+https://github.com/waldiez/waldiez.git
|
|
104
101
|
```
|
|
105
102
|
|
|
106
103
|
## Usage
|
|
@@ -119,13 +116,13 @@ waldiez /path/to/a/flow.waldiez --output /path/to/an/output/flow[.py] [--force]
|
|
|
119
116
|
```shell
|
|
120
117
|
CONTAINER_COMMAND=docker # or podman
|
|
121
118
|
# pull the image
|
|
122
|
-
$CONTAINER_COMMAND pull waldiez/
|
|
119
|
+
$CONTAINER_COMMAND pull waldiez/waldiez
|
|
123
120
|
# Export a Waldiez flow to a python script or a jupyter notebook
|
|
124
121
|
$CONTAINER_COMMAND run \
|
|
125
122
|
--rm \
|
|
126
123
|
-v /path/to/a/flow.waldiez:/flow.waldiez \
|
|
127
124
|
-v /path/to/an/output:/output \
|
|
128
|
-
waldiez/
|
|
125
|
+
waldiez/waldiez --export /flow.waldiez --output /output/flow[.py|.ipynb]
|
|
129
126
|
|
|
130
127
|
# with selinux and/or podman, you might get permission (or file not found) errors, so you can try:
|
|
131
128
|
$CONTAINER_COMMAND run \
|
|
@@ -134,12 +131,12 @@ $CONTAINER_COMMAND run \
|
|
|
134
131
|
-v /path/to/an/output:/output \
|
|
135
132
|
--userns=keep-id \
|
|
136
133
|
--security-opt label=disable \
|
|
137
|
-
waldiez/
|
|
134
|
+
waldiez/waldiez --export /flow.waldiez --output /output/flow[.py|.ipynb]
|
|
138
135
|
```
|
|
139
136
|
|
|
140
137
|
```shell
|
|
141
138
|
# Export and run the script
|
|
142
|
-
$CONTAINER_COMMAND run --rm -v /path/to/a/flow.waldiez:/flow.waldiez -v /path/to/an/output:/output waldiez/
|
|
139
|
+
$CONTAINER_COMMAND run --rm -v /path/to/a/flow.waldiez:/flow.waldiez -v /path/to/an/output:/output waldiez/waldiez /flow.waldiez --output /output/output[.py]
|
|
143
140
|
```
|
|
144
141
|
|
|
145
142
|
### As a library
|
|
@@ -170,40 +167,75 @@ runner.run(output_path=output_path)
|
|
|
170
167
|
|
|
171
168
|
```python
|
|
172
169
|
# Run the flow with a custom IOStream
|
|
170
|
+
# In case the standard 'input' and 'print' functions cannot be used
|
|
171
|
+
import time
|
|
172
|
+
import threading
|
|
173
|
+
|
|
174
|
+
from typing import Any
|
|
175
|
+
|
|
173
176
|
from waldiez import WaldiezRunner
|
|
174
177
|
from waldiez.io import WaldiezIOStream
|
|
175
178
|
|
|
176
179
|
flow_path = "/path/to/a/flow.waldiez"
|
|
177
180
|
output_path = "/path/to/an/output.py"
|
|
178
181
|
|
|
179
|
-
def print_function(*values, **args) -> None:
|
|
180
|
-
"""A custom print function."""
|
|
181
|
-
print(values)
|
|
182
182
|
|
|
183
|
-
def
|
|
184
|
-
"""
|
|
185
|
-
|
|
183
|
+
def custom_print_function(*args: Any, sep: str = " ", **kwargs: Any) -> None:
|
|
184
|
+
"""Custom print function."""
|
|
185
|
+
print(*args, sep=sep, **kwargs)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
# Custom input handler
|
|
189
|
+
class InputProcessorWrapper:
|
|
190
|
+
"""Wrapper input processor.
|
|
191
|
+
|
|
192
|
+
To manage the interaction between the custom input processor and IOStream.
|
|
193
|
+
"""
|
|
194
|
+
|
|
195
|
+
def __init__(self):
|
|
196
|
+
self.stream = None # Placeholder for the WaldiezIOStream instance
|
|
197
|
+
self.lock = threading.Lock() # Ensure thread-safe operations
|
|
198
|
+
|
|
199
|
+
def custom_input_processor(self, prompt: str) -> None:
|
|
200
|
+
"""Simulate external input and send it back to the IOStream."""
|
|
201
|
+
def external_input_simulation():
|
|
202
|
+
with self.lock: # Ensure thread-safe access
|
|
203
|
+
time.sleep(2) # Simulate delay for network input
|
|
204
|
+
if self.stream:
|
|
205
|
+
self.stream.set_input("Simulated external input")
|
|
206
|
+
else:
|
|
207
|
+
raise RuntimeError("Stream reference not set!")
|
|
186
208
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
209
|
+
threading.Thread(target=external_input_simulation, daemon=True).start()
|
|
210
|
+
|
|
211
|
+
def set_stream(self, stream: "WaldiezIOStream"):
|
|
212
|
+
"""Set the WaldiezIOStream instance."""
|
|
213
|
+
with self.lock: # Ensure thread-safe setting of the stream
|
|
214
|
+
self.stream = stream
|
|
215
|
+
|
|
216
|
+
processor_wrapper = InputProcessorWrapper()
|
|
217
|
+
|
|
218
|
+
stream = WaldiezIOStream(
|
|
190
219
|
input_timeout=30,
|
|
220
|
+
print_function=
|
|
221
|
+
on_prompt_input=processor_wrapper.custom_input_processor,
|
|
191
222
|
)
|
|
223
|
+
|
|
224
|
+
# Link the processor wrapper to the WaldiezIOStream instance
|
|
225
|
+
processor_wrapper.set_stream(custom_stream)
|
|
226
|
+
|
|
192
227
|
with WaldiezIOStream.set_default(io_stream):
|
|
193
228
|
runner = WaldiezRunner.load(flow_path)
|
|
194
229
|
runner.run(stream=io_stream, output_path=output_path)
|
|
195
230
|
|
|
196
|
-
io_stream.close()
|
|
197
|
-
|
|
198
231
|
```
|
|
199
232
|
|
|
200
233
|
### Tools
|
|
201
234
|
|
|
202
|
-
- [
|
|
235
|
+
- [ag2 (formerly AutoGen)](https://github.com/ag2ai/ag2)
|
|
203
236
|
- [juptytext](https://github.com/mwouts/jupytext)
|
|
204
|
-
- [twisted](https://github.com/twisted/twisted)
|
|
205
237
|
- [pydantic](https://github.com/pydantic/pydantic)
|
|
206
238
|
|
|
207
239
|
## License
|
|
208
240
|
|
|
209
|
-
This project is licensed under the MIT License - see the [LICENSE](https://github.com/waldiez/
|
|
241
|
+
This project is licensed under the MIT License - see the [LICENSE](https://github.com/waldiez/waldiez/blob/main/LICENSE) file for details.
|