waldiez 0.2.1__py3-none-any.whl → 0.3.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.

Files changed (138) hide show
  1. waldiez/__init__.py +2 -0
  2. waldiez/__main__.py +2 -0
  3. waldiez/_version.py +3 -1
  4. waldiez/cli.py +13 -3
  5. waldiez/cli_extras.py +25 -27
  6. waldiez/conflict_checker.py +4 -3
  7. waldiez/exporter.py +28 -105
  8. waldiez/exporting/__init__.py +8 -9
  9. waldiez/exporting/agent/__init__.py +7 -0
  10. waldiez/exporting/agent/agent_exporter.py +279 -0
  11. waldiez/exporting/agent/utils/__init__.py +23 -0
  12. waldiez/exporting/agent/utils/agent_class_name.py +34 -0
  13. waldiez/exporting/agent/utils/agent_imports.py +50 -0
  14. waldiez/exporting/{agents → agent/utils}/code_execution.py +9 -11
  15. waldiez/exporting/{agents → agent/utils}/group_manager.py +47 -35
  16. waldiez/exporting/{agents → agent/utils}/rag_user/__init__.py +2 -0
  17. waldiez/exporting/{agents → agent/utils}/rag_user/chroma_utils.py +22 -17
  18. waldiez/exporting/{agents → agent/utils}/rag_user/mongo_utils.py +14 -10
  19. waldiez/exporting/{agents → agent/utils}/rag_user/pgvector_utils.py +12 -8
  20. waldiez/exporting/{agents → agent/utils}/rag_user/qdrant_utils.py +11 -8
  21. waldiez/exporting/{agents → agent/utils}/rag_user/rag_user.py +78 -55
  22. waldiez/exporting/{agents → agent/utils}/rag_user/vector_db.py +10 -8
  23. waldiez/exporting/agent/utils/swarm_agent.py +463 -0
  24. waldiez/exporting/{agents → agent/utils}/teachability.py +10 -6
  25. waldiez/exporting/{agents → agent/utils}/termination_message.py +7 -8
  26. waldiez/exporting/base/__init__.py +25 -0
  27. waldiez/exporting/base/agent_position.py +75 -0
  28. waldiez/exporting/base/base_exporter.py +118 -0
  29. waldiez/exporting/base/export_position.py +48 -0
  30. waldiez/exporting/base/import_position.py +23 -0
  31. waldiez/exporting/base/mixin.py +134 -0
  32. waldiez/exporting/base/utils/__init__.py +18 -0
  33. waldiez/exporting/{utils → base/utils}/comments.py +12 -55
  34. waldiez/exporting/{utils → base/utils}/naming.py +14 -4
  35. waldiez/exporting/base/utils/path_check.py +68 -0
  36. waldiez/exporting/{utils/object_string.py → base/utils/to_string.py} +21 -20
  37. waldiez/exporting/chats/__init__.py +5 -12
  38. waldiez/exporting/chats/chats_exporter.py +240 -0
  39. waldiez/exporting/chats/utils/__init__.py +15 -0
  40. waldiez/exporting/chats/utils/common.py +81 -0
  41. waldiez/exporting/chats/{nested.py → utils/nested.py} +125 -86
  42. waldiez/exporting/chats/utils/sequential.py +244 -0
  43. waldiez/exporting/chats/utils/single_chat.py +313 -0
  44. waldiez/exporting/chats/utils/swarm.py +207 -0
  45. waldiez/exporting/flow/__init__.py +5 -3
  46. waldiez/exporting/flow/flow_exporter.py +503 -0
  47. waldiez/exporting/flow/utils/__init__.py +47 -0
  48. waldiez/exporting/flow/utils/agent_utils.py +204 -0
  49. waldiez/exporting/flow/utils/chat_utils.py +71 -0
  50. waldiez/exporting/flow/utils/def_main.py +62 -0
  51. waldiez/exporting/flow/utils/flow_content.py +112 -0
  52. waldiez/exporting/flow/utils/flow_names.py +115 -0
  53. waldiez/exporting/flow/utils/importing_utils.py +179 -0
  54. waldiez/exporting/{utils → flow/utils}/logging_utils.py +34 -31
  55. waldiez/exporting/models/__init__.py +7 -242
  56. waldiez/exporting/models/models_exporter.py +192 -0
  57. waldiez/exporting/models/utils.py +166 -0
  58. waldiez/exporting/skills/__init__.py +7 -161
  59. waldiez/exporting/skills/skills_exporter.py +169 -0
  60. waldiez/exporting/skills/utils.py +281 -0
  61. waldiez/models/__init__.py +25 -7
  62. waldiez/models/agents/__init__.py +70 -0
  63. waldiez/models/agents/agent/__init__.py +11 -1
  64. waldiez/models/agents/agent/agent.py +9 -4
  65. waldiez/models/agents/agent/agent_data.py +3 -1
  66. waldiez/models/agents/agent/code_execution.py +2 -0
  67. waldiez/models/agents/agent/linked_skill.py +2 -0
  68. waldiez/models/agents/agent/nested_chat.py +2 -0
  69. waldiez/models/agents/agent/teachability.py +2 -0
  70. waldiez/models/agents/agent/termination_message.py +49 -13
  71. waldiez/models/agents/agents.py +15 -3
  72. waldiez/models/agents/assistant/__init__.py +2 -0
  73. waldiez/models/agents/assistant/assistant.py +2 -0
  74. waldiez/models/agents/assistant/assistant_data.py +2 -0
  75. waldiez/models/agents/group_manager/__init__.py +9 -1
  76. waldiez/models/agents/group_manager/group_manager.py +2 -0
  77. waldiez/models/agents/group_manager/group_manager_data.py +2 -0
  78. waldiez/models/agents/group_manager/speakers.py +49 -13
  79. waldiez/models/agents/rag_user/__init__.py +21 -4
  80. waldiez/models/agents/rag_user/rag_user.py +3 -1
  81. waldiez/models/agents/rag_user/rag_user_data.py +2 -0
  82. waldiez/models/agents/rag_user/retrieve_config.py +268 -17
  83. waldiez/models/agents/rag_user/vector_db_config.py +5 -3
  84. waldiez/models/agents/swarm_agent/__init__.py +49 -0
  85. waldiez/models/agents/swarm_agent/after_work.py +178 -0
  86. waldiez/models/agents/swarm_agent/on_condition.py +103 -0
  87. waldiez/models/agents/swarm_agent/on_condition_available.py +140 -0
  88. waldiez/models/agents/swarm_agent/on_condition_target.py +40 -0
  89. waldiez/models/agents/swarm_agent/swarm_agent.py +107 -0
  90. waldiez/models/agents/swarm_agent/swarm_agent_data.py +125 -0
  91. waldiez/models/agents/swarm_agent/update_system_message.py +144 -0
  92. waldiez/models/agents/user_proxy/__init__.py +2 -0
  93. waldiez/models/agents/user_proxy/user_proxy.py +2 -0
  94. waldiez/models/agents/user_proxy/user_proxy_data.py +2 -0
  95. waldiez/models/chat/__init__.py +21 -3
  96. waldiez/models/chat/chat.py +241 -7
  97. waldiez/models/chat/chat_data.py +192 -48
  98. waldiez/models/chat/chat_message.py +153 -144
  99. waldiez/models/chat/chat_nested.py +33 -53
  100. waldiez/models/chat/chat_summary.py +2 -0
  101. waldiez/models/common/__init__.py +6 -6
  102. waldiez/models/common/base.py +4 -1
  103. waldiez/models/common/method_utils.py +163 -83
  104. waldiez/models/flow/__init__.py +2 -0
  105. waldiez/models/flow/flow.py +176 -40
  106. waldiez/models/flow/flow_data.py +63 -2
  107. waldiez/models/flow/utils.py +172 -0
  108. waldiez/models/model/__init__.py +2 -0
  109. waldiez/models/model/model.py +25 -6
  110. waldiez/models/model/model_data.py +3 -1
  111. waldiez/models/skill/__init__.py +4 -1
  112. waldiez/models/skill/skill.py +30 -2
  113. waldiez/models/skill/skill_data.py +2 -0
  114. waldiez/models/waldiez.py +28 -4
  115. waldiez/runner.py +142 -228
  116. waldiez/running/__init__.py +33 -0
  117. waldiez/running/environment.py +83 -0
  118. waldiez/running/gen_seq_diagram.py +185 -0
  119. waldiez/running/running.py +300 -0
  120. {waldiez-0.2.1.dist-info → waldiez-0.3.0.dist-info}/METADATA +36 -30
  121. waldiez-0.3.0.dist-info/RECORD +125 -0
  122. waldiez-0.3.0.dist-info/licenses/LICENSE +201 -0
  123. waldiez/exporting/agents/__init__.py +0 -5
  124. waldiez/exporting/agents/agent.py +0 -236
  125. waldiez/exporting/agents/agent_skills.py +0 -67
  126. waldiez/exporting/agents/llm_config.py +0 -53
  127. waldiez/exporting/chats/chats.py +0 -46
  128. waldiez/exporting/chats/helpers.py +0 -420
  129. waldiez/exporting/flow/def_main.py +0 -32
  130. waldiez/exporting/flow/flow.py +0 -189
  131. waldiez/exporting/utils/__init__.py +0 -36
  132. waldiez/exporting/utils/importing.py +0 -265
  133. waldiez/exporting/utils/method_utils.py +0 -35
  134. waldiez/exporting/utils/path_check.py +0 -51
  135. waldiez-0.2.1.dist-info/RECORD +0 -92
  136. waldiez-0.2.1.dist-info/licenses/LICENSE +0 -21
  137. {waldiez-0.2.1.dist-info → waldiez-0.3.0.dist-info}/WHEEL +0 -0
  138. {waldiez-0.2.1.dist-info → waldiez-0.3.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,185 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ """Generate a Mermaid sequence diagram from a file containing event data."""
4
+
5
+ import json
6
+ import re
7
+ from pathlib import Path
8
+ from typing import Any, Dict, Set, Union
9
+
10
+ import pandas as pd
11
+
12
+ MAX_LEN = 100
13
+ SEQ_TXT = """
14
+ %%{init: {'sequence': {'actorSpacing': 10, 'width': 150}}}%%
15
+ sequenceDiagram
16
+ """
17
+
18
+
19
+ def escape_mermaid_text(text: str) -> str:
20
+ """Replace newline characters with <br/> for Mermaid compatibility.
21
+
22
+ Parameters
23
+ ----------
24
+ text : str
25
+ The text to escape.
26
+
27
+ Returns
28
+ -------
29
+ str
30
+ The escaped text with newline characters replaced by <br/>.
31
+ """
32
+ if len(text) > MAX_LEN:
33
+ limited_text = text[:MAX_LEN] + "..."
34
+ else:
35
+ limited_text = text
36
+ output = limited_text.replace("\n", "<br/>")
37
+ output = re.sub(r"<br/>\s*<br/>", "<br/><br/>", output)
38
+ return output
39
+
40
+
41
+ def get_json_state(json_state: Any) -> Dict[str, Any]:
42
+ """Get the JSON state of the event.
43
+
44
+ Parameters
45
+ ----------
46
+ json_state : Union[str, dict]
47
+ The JSON state of the event.
48
+
49
+ Returns
50
+ -------
51
+ dict
52
+ The JSON state of the event.
53
+ """
54
+ if isinstance(json_state, dict):
55
+ return json_state
56
+ if isinstance(json_state, str):
57
+ try:
58
+ return json.loads(json_state)
59
+ except json.JSONDecodeError:
60
+ return {}
61
+ return {}
62
+
63
+
64
+ # pylint: disable=too-many-locals
65
+ def process_events(df_events: pd.DataFrame) -> str:
66
+ """Process the events DataFrame and generate a Mermaid sequence diagram.
67
+
68
+ Parameters
69
+ ----------
70
+ df_events : pd.DataFrame
71
+ The DataFrame containing the events data.
72
+ Returns
73
+ -------
74
+ str
75
+ The Mermaid sequence diagram text.
76
+ """
77
+
78
+ # Set to store participants (senders and recipients)
79
+ participants: Set[str] = set()
80
+ recipient: str
81
+
82
+ # Initialize the sequence diagram text
83
+ seq_text = SEQ_TXT
84
+
85
+ # Loop through each event in the DataFrame
86
+ for i in range(len(df_events["json_state"])):
87
+ # Parse the JSON state of the event
88
+ df_j = get_json_state(df_events["json_state"][i])
89
+ # Skip events that are not relevant (e.g., replies or missing messages)
90
+ if ("message" in df_j.keys()) and (
91
+ df_events["event_name"][i] != "reply_func_executed"
92
+ ):
93
+ sender = df_j["sender"]
94
+ recipient = df_events["source_name"][i]
95
+
96
+ # Extract message content if available
97
+ if (
98
+ isinstance(df_j["message"], dict)
99
+ and "content" in df_j["message"]
100
+ ):
101
+ message = "Content: " + str(df_j["message"]["content"])
102
+ else:
103
+ message = str(df_j["message"])
104
+
105
+ # Escape the message for Mermaid compatibility and
106
+ # truncate long messages
107
+ message = escape_mermaid_text(message)
108
+
109
+ # Add sender and recipient to participants set
110
+ participants.add(recipient)
111
+ participants.add(sender)
112
+
113
+ # Split message into main message and context
114
+ # if "Content" is present
115
+ if "Content: " in message:
116
+ message_parts = message.split("Content: ")
117
+ main_message = message_parts[0].strip()
118
+ context = "Content: " + message_parts[1].strip()
119
+ seq_text += f" {sender}->>{recipient}: {main_message}\n"
120
+ seq_text += f" note over {recipient}: {context}\n"
121
+ else:
122
+ seq_text += f" {sender}->>{recipient}: {message}\n"
123
+
124
+ # Add participants to the Mermaid diagram
125
+ participants_text = ""
126
+ for participant in participants:
127
+ participant_title = participant.replace("_", " ").title()
128
+ participants_text += (
129
+ f" participant {participant} as {participant_title}" + "\n"
130
+ )
131
+ # Prepend the participants to the sequence diagram text
132
+ mermaid_text = SEQ_TXT + participants_text + seq_text[len(SEQ_TXT) :]
133
+ return mermaid_text
134
+
135
+
136
+ def save_diagram(mermaid_text: str, output_path: Union[str, Path]) -> None:
137
+ """Save the Mermaid diagram to a .mmd file.
138
+
139
+ Parameters
140
+ ----------
141
+ mermaid_text : str
142
+ The Mermaid sequence diagram text.
143
+ output_path : Union[str, Path]
144
+ The path to save the Mermaid diagram.
145
+ """
146
+ with open(output_path, "w", encoding="utf-8", newline="\n") as file:
147
+ file.write(mermaid_text)
148
+
149
+
150
+ def generate_sequence_diagram(
151
+ file_path: Union[str, Path], output_path: Union[str, Path]
152
+ ) -> None:
153
+ """Main function to generate the Mermaid diagram.
154
+
155
+ Parameters
156
+ ----------
157
+ file_path : Union[str, Path]
158
+ The path to the JSON or CSV file containing the events data.
159
+ output_path : Union[str, Path]
160
+ The path to save the Mermaid diagram.
161
+
162
+ Raises
163
+ ------
164
+ FileNotFoundError
165
+ If the input file is not found.
166
+ ValueError
167
+ If the input file is not a JSON or CSV file.
168
+ """
169
+ if isinstance(file_path, str):
170
+ file_path = Path(file_path)
171
+ if not file_path.exists():
172
+ raise FileNotFoundError(f"File not found: {file_path}")
173
+ if file_path.suffix not in [".json", ".csv"]:
174
+ raise ValueError("Input file must be a JSON or CSV file.")
175
+ is_csv = file_path.suffix == ".csv"
176
+ if is_csv:
177
+ df_events = pd.read_csv(file_path)
178
+ else:
179
+ df_events = pd.read_json(file_path)
180
+
181
+ # Generate the Mermaid sequence diagram text
182
+ mermaid_text = process_events(df_events)
183
+
184
+ # Save the Mermaid diagram to a file
185
+ save_diagram(mermaid_text, output_path)
@@ -0,0 +1,300 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ """Utilities for running code."""
4
+
5
+ import asyncio
6
+ import datetime
7
+ import io
8
+ import os
9
+ import shutil
10
+ import subprocess
11
+ import sys
12
+ import tempfile
13
+ from contextlib import asynccontextmanager, contextmanager
14
+ from pathlib import Path
15
+ from typing import (
16
+ AsyncIterator,
17
+ Callable,
18
+ Iterator,
19
+ Optional,
20
+ Set,
21
+ Tuple,
22
+ Union,
23
+ )
24
+
25
+ from .environment import in_virtualenv
26
+ from .gen_seq_diagram import generate_sequence_diagram
27
+
28
+ # pylint: disable=import-outside-toplevel
29
+
30
+
31
+ @contextmanager
32
+ def chdir(to: Union[str, Path]) -> Iterator[None]:
33
+ """Change the current working directory in a context.
34
+
35
+ Parameters
36
+ ----------
37
+ to : Union[str, Path]
38
+ The directory to change to.
39
+
40
+ Yields
41
+ ------
42
+ Iterator[None]
43
+ The context manager.
44
+ """
45
+ old_cwd = str(os.getcwd())
46
+ os.chdir(to)
47
+ try:
48
+ yield
49
+ finally:
50
+ os.chdir(old_cwd)
51
+
52
+
53
+ @asynccontextmanager
54
+ async def a_chdir(to: Union[str, Path]) -> AsyncIterator[None]:
55
+ """Asynchronously change the current working directory in a context.
56
+
57
+ Parameters
58
+ ----------
59
+ to : Union[str, Path]
60
+ The directory to change to.
61
+
62
+ Yields
63
+ ------
64
+ AsyncIterator[None]
65
+ The async context manager.
66
+ """
67
+ old_cwd = str(os.getcwd())
68
+ os.chdir(to)
69
+ try:
70
+ yield
71
+ finally:
72
+ os.chdir(old_cwd)
73
+
74
+
75
+ def before_run(
76
+ output_path: Optional[Union[str, Path]],
77
+ uploads_root: Optional[Union[str, Path]],
78
+ ) -> str:
79
+ """Actions to perform before running the flow.
80
+
81
+ Parameters
82
+ ----------
83
+ output_path : Optional[Union[str, Path]]
84
+ The output path.
85
+ uploads_root : Optional[Union[str, Path]]
86
+ The runtime uploads root.
87
+
88
+ Returns
89
+ -------
90
+ str
91
+ The file name.
92
+ """
93
+ printer = get_printer()
94
+ printer(
95
+ "Requirements installed.\n"
96
+ "NOTE: If new packages were added and you are using Jupyter, "
97
+ "you might need to restart the kernel."
98
+ )
99
+ if not uploads_root:
100
+ uploads_root = Path(tempfile.mkdtemp())
101
+ else:
102
+ uploads_root = Path(uploads_root)
103
+ if not uploads_root.exists():
104
+ uploads_root.mkdir(parents=True)
105
+ file_name = "waldiez_flow.py" if not output_path else Path(output_path).name
106
+ if file_name.endswith((".json", ".waldiez")):
107
+ file_name = file_name.replace(".json", ".py").replace(".waldiez", ".py")
108
+ if not file_name.endswith(".py"):
109
+ file_name += ".py"
110
+ return file_name
111
+
112
+
113
+ def install_requirements(
114
+ extra_requirements: Set[str], printer: Callable[..., None]
115
+ ) -> None:
116
+ """Install the requirements.
117
+
118
+ Parameters
119
+ ----------
120
+ extra_requirements : Set[str]
121
+ The extra requirements.
122
+ printer : Callable[..., None]
123
+ The printer function.
124
+ """
125
+ requirements_string = ", ".join(extra_requirements)
126
+ printer(f"Installing requirements: {requirements_string}")
127
+ pip_install = [sys.executable, "-m", "pip", "install"]
128
+ if not in_virtualenv():
129
+ pip_install.append("--user")
130
+ pip_install.extend(extra_requirements)
131
+ with subprocess.Popen(
132
+ pip_install,
133
+ stdout=subprocess.PIPE,
134
+ stderr=subprocess.PIPE,
135
+ ) as proc:
136
+ if proc.stdout:
137
+ for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
138
+ printer(line.strip())
139
+ if proc.stderr:
140
+ for line in io.TextIOWrapper(proc.stderr, encoding="utf-8"):
141
+ printer(line.strip())
142
+
143
+
144
+ async def a_install_requirements(
145
+ extra_requirements: Set[str], printer: Callable[..., None]
146
+ ) -> None:
147
+ """Install the requirements asynchronously.
148
+
149
+ Parameters
150
+ ----------
151
+ extra_requirements : Set[str]
152
+ The extra requirements.
153
+ printer : Callable[..., None]
154
+ The printer function.
155
+ """
156
+ requirements_string = ", ".join(extra_requirements)
157
+ printer(f"Installing requirements: {requirements_string}")
158
+ pip_install = [sys.executable, "-m", "pip", "install"]
159
+ if not in_virtualenv():
160
+ pip_install.append("--user")
161
+ pip_install.extend(extra_requirements)
162
+ proc = await asyncio.create_subprocess_exec(
163
+ *pip_install,
164
+ stdout=asyncio.subprocess.PIPE,
165
+ stderr=asyncio.subprocess.PIPE,
166
+ )
167
+ if proc.stdout:
168
+ async for line in proc.stdout:
169
+ printer(line.decode().strip())
170
+ if proc.stderr:
171
+ async for line in proc.stderr:
172
+ printer(line.decode().strip())
173
+
174
+
175
+ def after_run(
176
+ temp_dir: Path,
177
+ output_path: Optional[Union[str, Path]],
178
+ printer: Callable[..., None],
179
+ flow_name: str,
180
+ skip_mmd: bool = False,
181
+ ) -> None:
182
+ """Actions to perform after running the flow.
183
+
184
+ Parameters
185
+ ----------
186
+ temp_dir : Path
187
+ The temporary directory.
188
+ output_path : Optional[Union[str, Path]]
189
+ The output path.
190
+ printer : Callable[..., None]
191
+ The printer function.
192
+ flow_name : str
193
+ The flow name.
194
+ skip_mmd : bool, optional
195
+ Whether to skip the mermaid sequence diagram generation,
196
+ by default False
197
+ """
198
+ if isinstance(output_path, str):
199
+ output_path = Path(output_path)
200
+ output_dir = output_path.parent if output_path else Path.cwd()
201
+ if output_dir.is_file():
202
+ output_dir = output_dir.parent
203
+ if skip_mmd is False:
204
+ events_csv_path = temp_dir / "logs" / "events.csv"
205
+ if events_csv_path.exists():
206
+ printer("Generating mermaid sequence diagram...")
207
+ mmd_path = temp_dir / f"{flow_name}.mmd"
208
+ generate_sequence_diagram(events_csv_path, mmd_path)
209
+ shutil.copyfile(mmd_path, output_dir / f"{flow_name}.mmd")
210
+ if output_path:
211
+ destination_dir = output_path.parent
212
+ destination_dir = (
213
+ destination_dir
214
+ / "waldiez_out"
215
+ / datetime.datetime.now().strftime("%Y%m%d%H%M%S")
216
+ )
217
+ destination_dir.mkdir(parents=True, exist_ok=True)
218
+ # copy the contents of the temp dir to the destination dir
219
+ printer(f"Copying the results to {destination_dir}")
220
+ for item in temp_dir.iterdir():
221
+ # skip cache files
222
+ if (
223
+ item.name.startswith("__pycache__")
224
+ or item.name.endswith(".pyc")
225
+ or item.name.endswith(".pyo")
226
+ or item.name.endswith(".pyd")
227
+ or item.name == ".cache"
228
+ ):
229
+ continue
230
+ if item.is_file():
231
+ shutil.copy(item, destination_dir)
232
+ else:
233
+ shutil.copytree(item, destination_dir / item.name)
234
+ shutil.rmtree(temp_dir)
235
+
236
+
237
+ def get_printer() -> Callable[..., None]:
238
+ """Get the printer function.
239
+
240
+ Returns
241
+ -------
242
+ Callable[..., None]
243
+ The printer function.
244
+ """
245
+ from autogen.io import IOStream # type: ignore
246
+
247
+ printer = IOStream.get_default().print
248
+
249
+ def safe_printer(*args: object, **kwargs: object) -> None:
250
+ try:
251
+ printer(*args, **kwargs)
252
+ except UnicodeEncodeError:
253
+ # pylint: disable=too-many-try-statements
254
+ try:
255
+ msg, flush = get_what_to_print(*args, **kwargs)
256
+ printer(msg, end="", flush=flush)
257
+ except UnicodeEncodeError:
258
+ sys.stdout = io.TextIOWrapper(
259
+ sys.stdout.buffer, encoding="utf-8"
260
+ )
261
+ sys.stderr = io.TextIOWrapper(
262
+ sys.stderr.buffer, encoding="utf-8"
263
+ )
264
+ try:
265
+ printer(*args, **kwargs)
266
+ except UnicodeEncodeError:
267
+ sys.stderr.write(
268
+ "Could not print the message due to encoding issues.\n"
269
+ )
270
+
271
+ return safe_printer
272
+
273
+
274
+ def get_what_to_print(*args: object, **kwargs: object) -> Tuple[str, bool]:
275
+ """Get what to print.
276
+
277
+ Parameters
278
+ ----------
279
+ args : object
280
+ The arguments.
281
+ kwargs : object
282
+ The keyword arguments.
283
+
284
+ Returns
285
+ -------
286
+ Tuple[str, bool]
287
+ The message and whether to flush.
288
+ """
289
+ sep = kwargs.get("sep", " ")
290
+ if not isinstance(sep, str):
291
+ sep = " "
292
+ end = kwargs.get("end", "\n")
293
+ if not isinstance(end, str):
294
+ end = "\n"
295
+ flush = kwargs.get("flush", False)
296
+ if not isinstance(flush, bool):
297
+ flush = False
298
+ msg = sep.join(str(arg) for arg in args) + end
299
+ utf8_msg = msg.encode("utf-8", errors="replace").decode("utf-8")
300
+ return utf8_msg, flush
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: waldiez
3
- Version: 0.2.1
3
+ Version: 0.3.0
4
4
  Summary: waldiez
5
5
  Project-URL: homepage, https://waldiez.github.io/waldiez/python
6
6
  Project-URL: repository, https://github.com/waldiez/python.git
@@ -9,7 +9,7 @@ License-File: LICENSE
9
9
  Classifier: Development Status :: 3 - Alpha
10
10
  Classifier: Intended Audience :: Developers
11
11
  Classifier: Intended Audience :: Science/Research
12
- Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
13
  Classifier: Operating System :: OS Independent
14
14
  Classifier: Programming Language :: Python
15
15
  Classifier: Programming Language :: Python :: 3
@@ -17,43 +17,47 @@ Classifier: Programming Language :: Python :: 3.10
17
17
  Classifier: Programming Language :: Python :: 3.11
18
18
  Classifier: Programming Language :: Python :: 3.12
19
19
  Requires-Python: <3.13,>=3.10
20
+ Requires-Dist: asyncer==0.0.8
20
21
  Requires-Dist: jupytext
21
- Requires-Dist: pyautogen==0.6.0
22
+ Requires-Dist: pandas>=2
23
+ Requires-Dist: parso==0.8.4
24
+ Requires-Dist: pyautogen==0.7.1
22
25
  Requires-Dist: pydantic>=2.0
23
26
  Requires-Dist: typer<0.13,>=0.9
24
27
  Provides-Extra: ag2-extras
25
- Requires-Dist: autogen[captainagent]==0.6.0; (platform_system == 'Linux') and extra == 'ag2-extras'
28
+ Requires-Dist: autogen[captainagent]==0.7.1; (platform_system == 'Linux') and extra == 'ag2-extras'
26
29
  Requires-Dist: pgvector>=0.3.6; extra == 'ag2-extras'
27
30
  Requires-Dist: psycopg[binary]>=3.2.3; extra == 'ag2-extras'
28
- Requires-Dist: pyautogen[anthropic]==0.6.0; extra == 'ag2-extras'
29
- Requires-Dist: pyautogen[bedrock]==0.6.0; extra == 'ag2-extras'
30
- Requires-Dist: pyautogen[gemini]==0.6.0; extra == 'ag2-extras'
31
- Requires-Dist: pyautogen[groq]==0.6.0; extra == 'ag2-extras'
32
- Requires-Dist: pyautogen[lmm]==0.6.0; extra == 'ag2-extras'
33
- Requires-Dist: pyautogen[mistral]==0.6.0; extra == 'ag2-extras'
34
- Requires-Dist: pyautogen[neo4j]==0.6.0; extra == 'ag2-extras'
35
- Requires-Dist: pyautogen[retrievechat-mongodb]==0.6.0; extra == 'ag2-extras'
36
- Requires-Dist: pyautogen[retrievechat-pgvector]==0.6.0; extra == 'ag2-extras'
37
- Requires-Dist: pyautogen[retrievechat-qdrant]==0.6.0; (python_version < '3.13') and extra == 'ag2-extras'
38
- Requires-Dist: pyautogen[retrievechat]==0.6.0; extra == 'ag2-extras'
39
- Requires-Dist: pyautogen[together]==0.6.0; extra == 'ag2-extras'
40
- Requires-Dist: pyautogen[websurfer]==0.6.0; extra == 'ag2-extras'
31
+ Requires-Dist: pyautogen[anthropic]==0.7.1; extra == 'ag2-extras'
32
+ Requires-Dist: pyautogen[bedrock]==0.7.1; extra == 'ag2-extras'
33
+ Requires-Dist: pyautogen[gemini]==0.7.1; extra == 'ag2-extras'
34
+ Requires-Dist: pyautogen[groq]==0.7.1; extra == 'ag2-extras'
35
+ Requires-Dist: pyautogen[lmm]==0.7.1; extra == 'ag2-extras'
36
+ Requires-Dist: pyautogen[mistral]==0.7.1; extra == 'ag2-extras'
37
+ Requires-Dist: pyautogen[neo4j]==0.7.1; extra == 'ag2-extras'
38
+ Requires-Dist: pyautogen[retrievechat-mongodb]==0.7.1; extra == 'ag2-extras'
39
+ Requires-Dist: pyautogen[retrievechat-pgvector]==0.7.1; extra == 'ag2-extras'
40
+ Requires-Dist: pyautogen[retrievechat-qdrant]==0.7.1; (python_version < '3.13') and extra == 'ag2-extras'
41
+ Requires-Dist: pyautogen[retrievechat]==0.7.1; extra == 'ag2-extras'
42
+ Requires-Dist: pyautogen[together]==0.7.1; extra == 'ag2-extras'
43
+ Requires-Dist: pyautogen[websurfer]==0.7.1; extra == 'ag2-extras'
41
44
  Requires-Dist: pymongo==4.10.1; extra == 'ag2-extras'
42
45
  Requires-Dist: qdrant-client[fastembed]; (python_version >= '3.13') and extra == 'ag2-extras'
43
46
  Provides-Extra: dev
44
47
  Requires-Dist: autoflake==2.3.1; extra == 'dev'
45
- Requires-Dist: bandit==1.8.0; extra == 'dev'
48
+ Requires-Dist: bandit==1.8.2; extra == 'dev'
46
49
  Requires-Dist: black[jupyter]==24.10.0; extra == 'dev'
47
50
  Requires-Dist: flake8==7.1.1; extra == 'dev'
48
51
  Requires-Dist: isort==5.13.2; extra == 'dev'
49
- Requires-Dist: mypy==1.14.0; extra == 'dev'
52
+ Requires-Dist: mypy==1.14.1; extra == 'dev'
53
+ Requires-Dist: pandas-stubs; extra == 'dev'
50
54
  Requires-Dist: pre-commit==4.0.1; extra == 'dev'
51
55
  Requires-Dist: pydocstyle==6.3.0; extra == 'dev'
52
56
  Requires-Dist: pylint==3.3.3; extra == 'dev'
53
57
  Requires-Dist: python-dotenv==1.0.1; extra == 'dev'
54
- Requires-Dist: ruff==0.8.4; extra == 'dev'
58
+ Requires-Dist: ruff==0.9.2; extra == 'dev'
55
59
  Requires-Dist: toml; (python_version <= '3.10') and extra == 'dev'
56
- Requires-Dist: types-pyyaml==6.0.12.20240917; extra == 'dev'
60
+ Requires-Dist: types-pyyaml==6.0.12.20241230; extra == 'dev'
57
61
  Requires-Dist: types-toml==0.10.8.20240310; extra == 'dev'
58
62
  Requires-Dist: yamllint==1.35.1; extra == 'dev'
59
63
  Provides-Extra: docs
@@ -61,17 +65,18 @@ Requires-Dist: mdx-include==1.4.2; extra == 'docs'
61
65
  Requires-Dist: mdx-truly-sane-lists==1.3; extra == 'docs'
62
66
  Requires-Dist: mkdocs-jupyter==0.25.1; extra == 'docs'
63
67
  Requires-Dist: mkdocs-macros-plugin==1.3.7; extra == 'docs'
64
- Requires-Dist: mkdocs-material==9.5.49; extra == 'docs'
68
+ Requires-Dist: mkdocs-material==9.5.50; extra == 'docs'
65
69
  Requires-Dist: mkdocs-minify-html-plugin==0.2.3; extra == 'docs'
66
70
  Requires-Dist: mkdocs==1.6.1; extra == 'docs'
67
- Requires-Dist: mkdocstrings-python==1.12.2; extra == 'docs'
71
+ Requires-Dist: mkdocstrings-python==1.13.0; extra == 'docs'
68
72
  Requires-Dist: mkdocstrings[crystal,python]==0.27.0; extra == 'docs'
69
73
  Provides-Extra: jupyter
70
74
  Requires-Dist: jupyterlab>=4.3.0; extra == 'jupyter'
71
- Requires-Dist: waldiez-jupyter==0.2.1; extra == 'jupyter'
75
+ Requires-Dist: waldiez-jupyter==0.3.0; extra == 'jupyter'
72
76
  Provides-Extra: studio
73
- Requires-Dist: waldiez-studio==0.2.1; extra == 'studio'
77
+ Requires-Dist: waldiez-studio==0.3.0; extra == 'studio'
74
78
  Provides-Extra: test
79
+ Requires-Dist: pytest-asyncio==0.25.2; extra == 'test'
75
80
  Requires-Dist: pytest-cov==6.0.0; extra == 'test'
76
81
  Requires-Dist: pytest-html==4.1.1; extra == 'test'
77
82
  Requires-Dist: pytest-sugar==1.0.0; extra == 'test'
@@ -120,17 +125,17 @@ The repo for the js library is [here](https://github.com/waldiez/react).
120
125
  - You also can use the vscode extension:
121
126
  - [repo](https://github.com/waldiez/vscode)
122
127
  - [marketplace](https://marketplace.visualstudio.com/items?itemName=Waldiez.waldiez-vscode)
123
- - Finally, you can use [waldiez-studio](https://github.com/waldiez/studio)
128
+ - Finally, you can use [waldiez-studio](https://github.com/waldiez/studio), which includes a FastAPI app to handle the conversion and running of waldiez flows.
124
129
 
125
- <!--
126
- The jupyterlab extension and studio also provided as extras in the main package.
130
+ The jupyterlab extension and waldiez studio are also provided as extras in the main package.
127
131
 
128
132
  ```shell
129
133
  pip install waldiez[studio] # or pip install waldiez_studio
130
134
  pip install waldiez[jupyter] # or pip install waldiez_jupyter
131
135
  # or both
132
136
  pip install waldiez[studio,jupyter]
133
- ``` -->
137
+ ```
138
+
134
139
  ### CLI
135
140
 
136
141
  ```bash
@@ -202,6 +207,7 @@ runner.run(output_path=output_path)
202
207
  - [juptytext](https://github.com/mwouts/jupytext)
203
208
  - [pydantic](https://github.com/pydantic/pydantic)
204
209
  - [typer](https://github.com/fastapi/typer)
210
+ - [asyncer](https://github.com/fastapi/asyncer)
205
211
 
206
212
  ## Known Conflicts
207
213
 
@@ -219,4 +225,4 @@ runner.run(output_path=output_path)
219
225
 
220
226
  ## License
221
227
 
222
- This project is licensed under the MIT License - see the [LICENSE](https://github.com/waldiez/python/blob/main/LICENSE) file for details.
228
+ This project is licensed under the [Apache License, Version 2.0 (Apache-2.0)](https://github.com/waldiez/python/blob/main/LICENSE).