waldiez 0.3.10__py3-none-any.whl → 0.3.11__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 CHANGED
@@ -2,4 +2,4 @@
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
3
  """Version information for Waldiez."""
4
4
 
5
- __version__ = "0.3.10"
5
+ __version__ = "0.3.11"
waldiez/exporter.py CHANGED
@@ -6,21 +6,12 @@ to an autogen's flow with one or more chats.
6
6
 
7
7
  The resulting file(s): a `flow.py` file with one `main()` function
8
8
  to trigger the chat(s).
9
- If additional tools/skills are used,
10
- they are exported as their `skill_name` in the same directory with
11
- the `flow.py` file. So the `flow.py` could have entries like:
12
- `form {flow_name}_{skill1_name} import {skill1_name}`
13
- `form {flow_name}_{skill2_name} import {skill2_name}`
14
9
  """
15
10
 
16
- # pylint: disable=inconsistent-quotes
17
-
18
- import os
19
- import shutil
20
- import subprocess
21
- import sys
22
11
  from pathlib import Path
23
- from typing import List, Optional, Union
12
+ from typing import Union
13
+
14
+ import jupytext # type: ignore[import-untyped]
24
15
 
25
16
  from .exporting import FlowExporter
26
17
  from .models import Waldiez
@@ -125,25 +116,10 @@ class WaldiezExporter:
125
116
  py_path = path.with_suffix(".tmp.py")
126
117
  with open(py_path, "w", encoding="utf-8", newline="\n") as f:
127
118
  f.write(content)
128
- if not shutil.which("jupytext"): # pragma: no cover
129
- run_command(
130
- [sys.executable, "-m", "pip", "install", "jupytext"],
131
- allow_error=False,
132
- )
133
- run_command(
134
- [
135
- sys.executable,
136
- "-m",
137
- "jupytext",
138
- "--to",
139
- "notebook",
140
- str(py_path),
141
- ],
142
- allow_error=False,
143
- )
119
+ with open(py_path, "r", encoding="utf-8") as py_out:
120
+ content = jupytext.read(py_out, fmt="py:light")
144
121
  ipynb_path = str(py_path).replace(".tmp.py", ".tmp.ipynb")
145
- if not os.path.exists(ipynb_path): # pragma: no cover
146
- raise RuntimeError("Could not generate notebook")
122
+ jupytext.write(content, ipynb_path, fmt="ipynb")
147
123
  Path(ipynb_path).rename(ipynb_path.replace(".tmp.ipynb", ".ipynb"))
148
124
  py_path.unlink(missing_ok=True)
149
125
 
@@ -182,42 +158,3 @@ class WaldiezExporter:
182
158
  """
183
159
  with open(file_path, "w", encoding="utf-8", newline="\n") as file:
184
160
  file.write(self.waldiez.model_dump_json())
185
-
186
-
187
- def run_command(
188
- cmd: List[str],
189
- cwd: Optional[Path] = None,
190
- allow_error: bool = True,
191
- ) -> None:
192
- """Run a command.
193
-
194
- Parameters
195
- ----------
196
- cmd : List[str]
197
- The command to run.
198
- cwd : Path, optional
199
- The working directory, by default None (current working directory).
200
- allow_error : bool, optional
201
- Whether to allow errors, by default True.
202
-
203
- Raises
204
- ------
205
- RuntimeError
206
- If the command fails and allow_error is False.
207
- """
208
- if not cwd:
209
- cwd = Path.cwd()
210
- # pylint: disable=broad-except
211
- try:
212
- subprocess.run(
213
- cmd,
214
- check=True,
215
- cwd=cwd,
216
- env=os.environ,
217
- stdout=subprocess.PIPE,
218
- stderr=subprocess.PIPE,
219
- ) # nosemgrep # nosec
220
- except BaseException as error: # pragma: no cover
221
- if allow_error:
222
- return
223
- raise RuntimeError(f"Error running command: {error}") from error
@@ -97,7 +97,7 @@ class ChatsExporter(BaseExporter, ExporterMixin):
97
97
  recipient=recipient,
98
98
  serializer=self.serializer,
99
99
  string_escape=self.string_escape,
100
- tabs=0 if self.for_notebook else 1,
100
+ tabs=1 if self.for_notebook else 2,
101
101
  is_async=self.is_async,
102
102
  )
103
103
  return
@@ -109,7 +109,7 @@ class ChatsExporter(BaseExporter, ExporterMixin):
109
109
  chat_names=self.chat_names,
110
110
  serializer=self.serializer,
111
111
  string_escape=self.string_escape,
112
- tabs=0 if self.for_notebook else 1,
112
+ tabs=1 if self.for_notebook else 2,
113
113
  is_async=self.is_async,
114
114
  )
115
115
  return
@@ -119,7 +119,7 @@ class ChatsExporter(BaseExporter, ExporterMixin):
119
119
  chat_names=self.chat_names,
120
120
  serializer=self.serializer,
121
121
  string_escape=self.string_escape,
122
- tabs=0 if self.for_notebook else 1,
122
+ tabs=1 if self.for_notebook else 2,
123
123
  is_async=self.is_async,
124
124
  )
125
125
 
@@ -181,6 +181,7 @@ def _get_chat_dict_string(
181
181
  chat_string = "{"
182
182
  chat_string += "\n" + f'{tab} "sender": {agent_names[sender.id]},'
183
183
  chat_string += "\n" + f'{tab} "recipient": {agent_names[recipient.id]},'
184
+ chat_string += "\n" + f'{tab} "cache": cache,'
184
185
  additional_methods_string = ""
185
186
  for key, value in chat_args.items():
186
187
  if isinstance(value, str):
@@ -86,6 +86,7 @@ def export_single_chat(
86
86
  agent1.initiate_chat(
87
87
  agent2,
88
88
  message="Hello, how are you?",
89
+ cache=cache,
89
90
  )
90
91
  ```
91
92
  """
@@ -167,6 +168,7 @@ def get_simple_chat_string(
167
168
  recipient_name = agent_names[recipient.id]
168
169
  chat_string = "\n" + f"{tab}results = {sender_name}.{initiate}(" + "\n"
169
170
  chat_string += f"{tab} {recipient_name},"
171
+ chat_string += "\n" + f"{tab} cache=cache,"
170
172
  for key, value in chat_args.items():
171
173
  if isinstance(value, str):
172
174
  chat_string += "\n" + f'{tab} {key}="{value}",'
@@ -228,6 +230,7 @@ def get_empty_simple_chat_string(
228
230
  initiate = "a_initiate_chat" if is_async else "initiate_chat"
229
231
  content = "\n" + f"{tab}results = {sender_name}.{initiate}(" + "\n"
230
232
  content += f"{tab} {recipient_name}," + "\n"
233
+ content += f"{tab} cache=cache," + "\n"
231
234
  message_arg, _ = get_chat_message(
232
235
  tab=tab,
233
236
  chat=chat,
@@ -202,6 +202,7 @@ class FlowExporter(BaseExporter, ExporterMixin):
202
202
  The merged export contents.
203
203
  """
204
204
  is_async = self.waldiez.is_async
205
+ cache_seed = self.waldiez.cache_seed
205
206
  content = (
206
207
  get_py_content_start(self.waldiez)
207
208
  if not self.for_notebook
@@ -236,9 +237,18 @@ class FlowExporter(BaseExporter, ExporterMixin):
236
237
  chats_content,
237
238
  after_run=after_run,
238
239
  is_async=self.waldiez.is_async,
240
+ cache_seed=cache_seed,
239
241
  )
240
242
  else:
241
- content += "\n" + chats_content + "\n"
243
+ # content += f" with Cache.disk(cache_seed={cache_seed}" + "):\n"
244
+ # content += f"{flow_chats}" + "\n"
245
+ # content += "\n" + chats_content + "\n"
246
+ if chats_content.startswith("\n"):
247
+ chats_content = chats_content[1:]
248
+ content += (
249
+ "\n" + f"with Cache.disk(cache_seed={cache_seed}):"
250
+ "\n" + chats_content + "\n"
251
+ )
242
252
  if is_async:
243
253
  content += "await stop_logging()"
244
254
  else:
@@ -332,6 +342,7 @@ class FlowExporter(BaseExporter, ExporterMixin):
332
342
  model_names=self.model_names,
333
343
  for_notebook=self.for_notebook,
334
344
  output_dir=self.output_dir,
345
+ cache_seed=self.waldiez.cache_seed,
335
346
  )
336
347
  return exporter.export()
337
348
 
@@ -4,8 +4,12 @@
4
4
  # pylint: disable=inconsistent-quotes, line-too-long
5
5
  """Get the main function."""
6
6
 
7
+ from typing import Optional
7
8
 
8
- def get_def_main(flow_chats: str, after_run: str, is_async: bool) -> str:
9
+
10
+ def get_def_main(
11
+ flow_chats: str, after_run: str, is_async: bool, cache_seed: Optional[int]
12
+ ) -> str:
9
13
  """Get the main function.
10
14
 
11
15
  When exporting to python, waldiez_chats string will be the
@@ -22,17 +26,21 @@ def get_def_main(flow_chats: str, after_run: str, is_async: bool) -> str:
22
26
  The content after the run of the flow.
23
27
  is_async : bool
24
28
  Whether the main function is asynchronous.
29
+ cache_seed : Optional[int]
30
+ The seed for the cache. If None, cache should be disabled.
25
31
  Returns
26
32
  -------
27
33
  str
28
34
  The main function.
29
35
  """
36
+ if flow_chats.startswith("\n"):
37
+ flow_chats = flow_chats[1:]
30
38
  content = ""
31
39
  if is_async:
32
40
  content += "async "
33
- content += "def main():\n"
34
- content += " # type: () -> Union[ChatResult, List[ChatResult], Dict[int, ChatResult]]\n"
41
+ content += "def main() -> Union[ChatResult, List[ChatResult], Dict[int, ChatResult]]:\n"
35
42
  content += ' """Start chatting."""\n'
43
+ content += f" with Cache.disk(cache_seed={cache_seed}" + ") as cache:\n"
36
44
  content += f"{flow_chats}" + "\n"
37
45
  if is_async:
38
46
  content += " await stop_logging()"
@@ -45,7 +53,7 @@ def get_def_main(flow_chats: str, after_run: str, is_async: bool) -> str:
45
53
  else:
46
54
  content += "def call_main() -> None:\n"
47
55
  content += ' """Run the main function and print the results."""\n'
48
- content += " results: Union[ChatResult, List[ChatResult], Dict[int, ChatResult]] = "
56
+ content += " results = "
49
57
  if is_async:
50
58
  content += "await "
51
59
  content += "main()\n"
@@ -58,7 +66,7 @@ def get_def_main(flow_chats: str, after_run: str, is_async: bool) -> str:
58
66
  content += " for result in results:\n"
59
67
  content += " pprint(asdict(result))\n"
60
68
  content += " else:\n"
61
- content += " pprint(asdict(results))\n"
69
+ content += " pprint(asdict(results))\n\n\n"
62
70
  content += 'if __name__ == "__main__":\n'
63
71
  if is_async:
64
72
  content += " anyio.run(call_main)\n"
@@ -136,25 +136,26 @@ def get_after_run_content(
136
136
  # if th eflow has reasoning agents, we add
137
137
  # visualize_tree(agent._root) for each agent
138
138
  content = ""
139
- space = " " * tabs
139
+ tab = " "
140
+ space = tab * tabs
140
141
  for agent in waldiez.agents:
141
142
  if agent.agent_type == "reasoning":
142
143
  agent_name = agent_names[agent.id]
143
144
  content += f"""
144
145
  {space}# pylint: disable=broad-except,too-many-try-statements
145
146
  {space}try:
146
- {space}{space}visualize_tree({agent_name}._root) # pylint: disable=protected-access
147
- {space}{space}if os.path.exists("tree_of_thoughts.png"):
148
- {space}{space}{space}new_name = "{agent_name}_tree_of_thoughts.png"
149
- {space}{space}{space}os.rename("tree_of_thoughts.png", new_name)
147
+ {space}{tab}visualize_tree({agent_name}._root) # pylint: disable=protected-access
148
+ {space}{tab}if os.path.exists("tree_of_thoughts.png"):
149
+ {space}{tab}{tab}new_name = "{agent_name}_tree_of_thoughts.png"
150
+ {space}{tab}{tab}os.rename("tree_of_thoughts.png", new_name)
150
151
  {space}except BaseException:
151
- {space}{space}pass
152
+ {space}{tab}pass
152
153
  {space}# save the tree to json
153
154
  {space}try:
154
- {space}{space}data = {agent_name}._root.to_dict() # pylint: disable=protected-access
155
- {space}{space}with open("{agent_name}_reasoning_tree.json", "w", encoding="utf-8") as f:
156
- {space}{space}{space}json.dump(data, f)
155
+ {space}{tab}data = {agent_name}._root.to_dict() # pylint: disable=protected-access
156
+ {space}{tab}with open("{agent_name}_reasoning_tree.json", "w", encoding="utf-8") as f:
157
+ {space}{tab}{tab}json.dump(data, f)
157
158
  {space}except BaseException:
158
- {space}{space}pass
159
+ {space}{tab}pass
159
160
  """
160
161
  return content
@@ -28,6 +28,7 @@ TYPING_IMPORTS = [
28
28
  ]
29
29
  COMMON_AUTOGEN_IMPORTS = [
30
30
  "from autogen import Agent",
31
+ "from autogen import Cache",
31
32
  "from autogen import ConversableAgent",
32
33
  "from autogen import ChatResult",
33
34
  "from autogen import GroupChat",
@@ -32,6 +32,7 @@ class ModelsExporter(BaseExporter, ExporterMixin):
32
32
  models: List[WaldiezModel],
33
33
  model_names: Dict[str, str],
34
34
  for_notebook: bool,
35
+ cache_seed: Optional[int],
35
36
  output_dir: Optional[Union[str, Path]] = None,
36
37
  ) -> None:
37
38
  """Initialize the models exporter.
@@ -46,6 +47,10 @@ class ModelsExporter(BaseExporter, ExporterMixin):
46
47
  The models.
47
48
  model_names : Dict[str, str]
48
49
  The model names.
50
+ for_notebook : bool
51
+ Whether the export is for a notebook or not.
52
+ cache_seed : Optional[int]
53
+ The cache seed if any, by default None
49
54
  output_dir : Optional[Union[str, Path]], optional
50
55
  The output directory if any, by default None
51
56
  """
@@ -57,6 +62,7 @@ class ModelsExporter(BaseExporter, ExporterMixin):
57
62
  self.model_names = model_names
58
63
  if output_dir is not None and not isinstance(output_dir, Path):
59
64
  output_dir = Path(output_dir)
65
+ self.cache_seed = cache_seed
60
66
  self.output_dir = output_dir
61
67
  self._exported_string = None
62
68
 
@@ -127,6 +133,7 @@ class ModelsExporter(BaseExporter, ExporterMixin):
127
133
  agent,
128
134
  all_models=self.models,
129
135
  model_names=self.model_names,
136
+ cache_seed=self.cache_seed,
130
137
  ),
131
138
  AgentPosition(
132
139
  agent=agent, position=AgentPositions.AS_ARGUMENT
@@ -63,6 +63,7 @@ def get_agent_llm_config_arg(
63
63
  agent: WaldiezAgent,
64
64
  all_models: List[WaldiezModel],
65
65
  model_names: Dict[str, str],
66
+ cache_seed: Optional[int],
66
67
  tabs: int = 1,
67
68
  ) -> str:
68
69
  """Get the string representation of the agent's llm config argument.
@@ -75,6 +76,8 @@ def get_agent_llm_config_arg(
75
76
  All the models in the flow.
76
77
  model_names : Dict[str, str]
77
78
  A mapping of model ids to model names.
79
+ cache_seed : Optional[int]
80
+ The cache seed.
78
81
  tabs : int, optional
79
82
  The number of tabs for indentation, by default 1.
80
83
 
@@ -98,6 +101,7 @@ def get_agent_llm_config_arg(
98
101
  if not got_at_least_one_model: # pragma: no cover
99
102
  return f"{tab}llm_config=False," + "\n"
100
103
  content += "\n" + f"{tab} ]," + "\n"
104
+ content += f'{tab} "cache_seed": {cache_seed},' + "\n"
101
105
  content += tab + "},\n"
102
106
  return content
103
107
 
@@ -115,8 +115,8 @@ class WaldiezAgents(WaldiezBase):
115
115
  If the agents are invalid.
116
116
  """
117
117
  all_agent_ids = [agent.id for agent in self.members]
118
- if len(all_agent_ids) < 2:
119
- raise ValueError("At least two agents are required.")
118
+ if len(all_agent_ids) < 1:
119
+ raise ValueError("At least one agent is required.")
120
120
  if len(all_agent_ids) != len(set(all_agent_ids)):
121
121
  raise ValueError("Agent IDs must be unique.")
122
122
  return self
@@ -64,3 +64,7 @@ class WaldiezBase(BaseModel):
64
64
  if not isinstance(by_alias, bool):
65
65
  by_alias = True
66
66
  return super().model_dump_json(by_alias=by_alias, **kwargs)
67
+
68
+ def __hash__(self) -> int:
69
+ """Return the hash of the object."""
70
+ return id(self)
@@ -126,6 +126,7 @@ class WaldiezFlow(WaldiezBase):
126
126
  _ordered_flow: Optional[
127
127
  List[Tuple[WaldiezChat, WaldiezAgent, WaldiezAgent]]
128
128
  ] = None
129
+ _single_agent_mode: bool = False
129
130
 
130
131
  @property
131
132
  def is_async(self) -> bool:
@@ -139,15 +140,15 @@ class WaldiezFlow(WaldiezBase):
139
140
  return self.data.is_async
140
141
 
141
142
  @property
142
- def has_shared_skill(self) -> bool:
143
- """Check if the flow has a skill with shared variables (global).
143
+ def cache_seed(self) -> Optional[int]:
144
+ """Check if the flow has caching disabled.
144
145
 
145
146
  Returns
146
147
  -------
147
148
  bool
148
- True if the flow has shared skills, False otherwise.
149
+ True if the flow has caching disabled, False otherwise.
149
150
  """
150
- return any(skill.is_shared for skill in self.data.skills)
151
+ return self.data.cache_seed
151
152
 
152
153
  @property
153
154
  def is_swarm_flow(self) -> bool:
@@ -162,6 +163,17 @@ class WaldiezFlow(WaldiezBase):
162
163
  agent.agent_type == "swarm" for agent in self.data.agents.members
163
164
  )
164
165
 
166
+ @property
167
+ def is_single_agent_mode(self) -> bool:
168
+ """Check if the flow is in single agent mode.
169
+
170
+ Returns
171
+ -------
172
+ bool
173
+ True if the flow is in single agent mode, False otherwise.
174
+ """
175
+ return self._single_agent_mode
176
+
165
177
  @property
166
178
  def ordered_flow(
167
179
  self,
@@ -417,6 +429,7 @@ class WaldiezFlow(WaldiezBase):
417
429
 
418
430
  - unique node ids
419
431
  - there are at least two agents
432
+ - (or a single agent but not a group manager or a swarm agent)
420
433
  - all the agents connect to at least one other agent
421
434
  - all the linked agent skills are found in the flow
422
435
  - all the linked agent models are found in the flow
@@ -440,14 +453,13 @@ class WaldiezFlow(WaldiezBase):
440
453
  If the agents do not connect to any other node.
441
454
  If the manager's group chat has no members.
442
455
  """
456
+ all_members = list(self.data.agents.members)
457
+ if len(all_members) == 1:
458
+ return self.validate_single_agent_mode(all_members[0])
443
459
  if not self.ordered_flow:
444
460
  raise ValueError("The ordered flow is empty.")
445
- model_ids = [model.id for model in self.data.models]
446
- if len(model_ids) != len(set(model_ids)):
447
- raise ValueError("Model IDs must be unique.")
448
- skills_ids = [skill.id for skill in self.data.skills]
449
- if len(skills_ids) != len(set(skills_ids)):
450
- raise ValueError("Skill IDs must be unique.")
461
+ model_ids = self.validate_flow_models()
462
+ skills_ids = self.validate_flow_skills()
451
463
  self.data.agents.validate_flow(model_ids, skills_ids)
452
464
  self._validate_agent_connections()
453
465
  if self.is_swarm_flow:
@@ -458,3 +470,69 @@ class WaldiezFlow(WaldiezBase):
458
470
  all_chats=self.data.chats,
459
471
  )
460
472
  return self
473
+
474
+ def validate_flow_models(self) -> List[str]:
475
+ """Validate the flow models.
476
+
477
+ Returns
478
+ -------
479
+ List[str]
480
+ The list of model IDs.
481
+
482
+ Raises
483
+ ------
484
+ ValueError
485
+ If the model IDs are not unique.
486
+ """
487
+ model_ids = [model.id for model in self.data.models]
488
+ if len(model_ids) != len(set(model_ids)):
489
+ raise ValueError("Model IDs must be unique.")
490
+ return model_ids
491
+
492
+ def validate_flow_skills(self) -> List[str]:
493
+ """Validate the flow skills.
494
+
495
+ Returns
496
+ -------
497
+ List[str]
498
+ The list of skill IDs.
499
+
500
+ Raises
501
+ ------
502
+ ValueError
503
+ If the skill IDs are not unique.
504
+ """
505
+ skill_ids = [skill.id for skill in self.data.skills]
506
+ if len(skill_ids) != len(set(skill_ids)):
507
+ raise ValueError("Skill IDs must be unique.")
508
+ return skill_ids
509
+
510
+ def validate_single_agent_mode(self, member: WaldiezAgent) -> Self:
511
+ """Flow validation for single agent mode.
512
+
513
+ Parameters
514
+ ----------
515
+ member : WaldiezAgent
516
+ The only agent in the flow
517
+ Returns
518
+ -------
519
+ WaldiezFlow
520
+ The validated flow.
521
+
522
+ Raises
523
+ ------
524
+ ValueError
525
+ - If the only agent is a group manager or a swarm agent.
526
+ - If the model IDs are not unique.
527
+ - If the skill IDs are not unique.
528
+ """
529
+ if member.agent_type in ["manager", "swarm"]:
530
+ raise ValueError(
531
+ "In single agent mode, "
532
+ "the agent must not be a group manager or a swarm agent."
533
+ )
534
+ model_ids = self.validate_flow_models()
535
+ skills_ids = self.validate_flow_skills()
536
+ self.data.agents.validate_flow(model_ids, skills_ids)
537
+ self._single_agent_mode = True
538
+ return self
@@ -2,7 +2,7 @@
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
3
  """Waldiez flow data."""
4
4
 
5
- from typing import Any, Dict, List
5
+ from typing import Any, Dict, List, Optional
6
6
 
7
7
  from pydantic import Field, model_validator
8
8
  from typing_extensions import Annotated, Self
@@ -40,6 +40,8 @@ class WaldiezFlowData(WaldiezBase):
40
40
  The chats of the flow. See `WaldiezChat`.
41
41
  is_async : bool
42
42
  Whether the flow is asynchronous or not.
43
+ cache_seed : Optional[int]
44
+ The seed for the cache. If None, the seed is not set. Default is 41.
43
45
  """
44
46
 
45
47
  # the ones below (nodes,edges, viewport) we ignore
@@ -109,6 +111,18 @@ class WaldiezFlowData(WaldiezBase):
109
111
  title="Is Async",
110
112
  ),
111
113
  ]
114
+ cache_seed: Annotated[
115
+ Optional[int],
116
+ Field(
117
+ 41,
118
+ alias="cacheSeed",
119
+ description=(
120
+ "The seed for the cache. If None, the seed is not set."
121
+ "Default is 41."
122
+ ),
123
+ title="Cache Seed",
124
+ ),
125
+ ] = 41
112
126
 
113
127
  @model_validator(mode="after")
114
128
  def validate_flow_chats(self) -> Self:
@@ -145,11 +145,14 @@ class WaldiezModel(WaldiezBase):
145
145
  - other: 'OPENAI_API_KEY'
146
146
  """
147
147
  if self.data.api_key and self.data.api_key != "REPLACE_ME":
148
+ os.environ[self.api_key_env_key] = self.data.api_key
148
149
  return self.data.api_key
149
150
  env_key = self.api_key_env_key
150
151
  api_key = os.environ.get(
151
152
  env_key, getattr(self.data, "api_key", "REPLACE_ME")
152
153
  )
154
+ if api_key and api_key != "REPLACE_ME":
155
+ os.environ[env_key] = api_key
153
156
  return api_key or "REPLACE_ME"
154
157
 
155
158
  @property
waldiez/models/waldiez.py CHANGED
@@ -211,6 +211,16 @@ class Waldiez:
211
211
  """Check if the flow is asynchronous."""
212
212
  return self.flow.is_async
213
213
 
214
+ @property
215
+ def cache_seed(self) -> Optional[int]:
216
+ """Get the cache seed."""
217
+ return self.flow.cache_seed
218
+
219
+ @property
220
+ def is_single_agent_mode(self) -> bool:
221
+ """Check if the flow is single agent mode."""
222
+ return self.flow.is_single_agent_mode
223
+
214
224
  @property
215
225
  def requirements(self) -> List[str]:
216
226
  """Get the flow requirements."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: waldiez
3
- Version: 0.3.10
3
+ Version: 0.3.11
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
@@ -27,31 +27,31 @@ Requires-Dist: httpx<1
27
27
  Requires-Dist: jupytext
28
28
  Requires-Dist: pandas>=2
29
29
  Requires-Dist: parso==0.8.4
30
- Requires-Dist: pyautogen==0.7.2
30
+ Requires-Dist: pyautogen==0.7.3
31
31
  Requires-Dist: pydantic<3,>=2.6.1
32
32
  Requires-Dist: typer<0.16,>=0.9
33
33
  Provides-Extra: ag2-extras
34
- Requires-Dist: autogen[captainagent]==0.7.2; (platform_system == 'Linux') and extra == 'ag2-extras'
34
+ Requires-Dist: autogen[captainagent]==0.7.3; (platform_system == 'Linux') and extra == 'ag2-extras'
35
35
  Requires-Dist: chromadb; (platform_system != 'Linux') and extra == 'ag2-extras'
36
- Requires-Dist: huggingface-hub>=0.0.17; (platform_system != 'Linux') and extra == 'ag2-extras'
36
+ Requires-Dist: huggingface-hub; (platform_system != 'Linux') and extra == 'ag2-extras'
37
37
  Requires-Dist: pgvector>=0.3.6; extra == 'ag2-extras'
38
38
  Requires-Dist: psycopg[binary]>=3.2.3; extra == 'ag2-extras'
39
- Requires-Dist: pyautogen[anthropic]==0.7.2; extra == 'ag2-extras'
40
- Requires-Dist: pyautogen[bedrock]==0.7.2; extra == 'ag2-extras'
41
- Requires-Dist: pyautogen[gemini]==0.7.2; extra == 'ag2-extras'
42
- Requires-Dist: pyautogen[groq]==0.7.2; extra == 'ag2-extras'
43
- Requires-Dist: pyautogen[lmm]==0.7.2; extra == 'ag2-extras'
44
- Requires-Dist: pyautogen[mistral]==0.7.2; extra == 'ag2-extras'
45
- Requires-Dist: pyautogen[neo4j]==0.7.2; extra == 'ag2-extras'
46
- Requires-Dist: pyautogen[retrievechat-mongodb]==0.7.2; extra == 'ag2-extras'
47
- Requires-Dist: pyautogen[retrievechat-pgvector]==0.7.2; extra == 'ag2-extras'
48
- Requires-Dist: pyautogen[retrievechat-qdrant]==0.7.2; (python_version < '3.13') and extra == 'ag2-extras'
49
- Requires-Dist: pyautogen[retrievechat]==0.7.2; extra == 'ag2-extras'
50
- Requires-Dist: pyautogen[together]==0.7.2; extra == 'ag2-extras'
51
- Requires-Dist: pyautogen[websurfer]==0.7.2; extra == 'ag2-extras'
39
+ Requires-Dist: pyautogen[anthropic]==0.7.3; extra == 'ag2-extras'
40
+ Requires-Dist: pyautogen[bedrock]==0.7.3; extra == 'ag2-extras'
41
+ Requires-Dist: pyautogen[gemini]==0.7.3; extra == 'ag2-extras'
42
+ Requires-Dist: pyautogen[groq]==0.7.3; extra == 'ag2-extras'
43
+ Requires-Dist: pyautogen[lmm]==0.7.3; extra == 'ag2-extras'
44
+ Requires-Dist: pyautogen[mistral]==0.7.3; extra == 'ag2-extras'
45
+ Requires-Dist: pyautogen[neo4j]==0.7.3; extra == 'ag2-extras'
46
+ Requires-Dist: pyautogen[retrievechat-mongodb]==0.7.3; extra == 'ag2-extras'
47
+ Requires-Dist: pyautogen[retrievechat-pgvector]==0.7.3; extra == 'ag2-extras'
48
+ Requires-Dist: pyautogen[retrievechat-qdrant]==0.7.3; (python_version < '3.13') and extra == 'ag2-extras'
49
+ Requires-Dist: pyautogen[retrievechat]==0.7.3; extra == 'ag2-extras'
50
+ Requires-Dist: pyautogen[together]==0.7.3; extra == 'ag2-extras'
51
+ Requires-Dist: pyautogen[websurfer]==0.7.3; extra == 'ag2-extras'
52
52
  Requires-Dist: pymongo>=4.10.1; extra == 'ag2-extras'
53
53
  Requires-Dist: qdrant-client[fastembed]; (python_version >= '3.13') and extra == 'ag2-extras'
54
- Requires-Dist: sentence-transformers>=2.0.0; (platform_system != 'Linux') and extra == 'ag2-extras'
54
+ Requires-Dist: sentence-transformers; (platform_system != 'Linux') and extra == 'ag2-extras'
55
55
  Provides-Extra: dev
56
56
  Requires-Dist: autoflake==2.3.1; extra == 'dev'
57
57
  Requires-Dist: bandit==1.8.2; extra == 'dev'
@@ -64,7 +64,7 @@ Requires-Dist: pre-commit==4.1.0; extra == 'dev'
64
64
  Requires-Dist: pydocstyle==6.3.0; extra == 'dev'
65
65
  Requires-Dist: pylint==3.3.4; extra == 'dev'
66
66
  Requires-Dist: python-dotenv==1.0.1; extra == 'dev'
67
- Requires-Dist: ruff==0.9.3; extra == 'dev'
67
+ Requires-Dist: ruff==0.9.4; extra == 'dev'
68
68
  Requires-Dist: toml; (python_version <= '3.10') and extra == 'dev'
69
69
  Requires-Dist: types-pyyaml==6.0.12.20241230; extra == 'dev'
70
70
  Requires-Dist: types-toml==0.10.8.20240310; extra == 'dev'
@@ -74,16 +74,16 @@ Requires-Dist: mdx-include==1.4.2; extra == 'docs'
74
74
  Requires-Dist: mdx-truly-sane-lists==1.3; extra == 'docs'
75
75
  Requires-Dist: mkdocs-jupyter==0.25.1; extra == 'docs'
76
76
  Requires-Dist: mkdocs-macros-plugin==1.3.7; extra == 'docs'
77
- Requires-Dist: mkdocs-material==9.5.50; extra == 'docs'
77
+ Requires-Dist: mkdocs-material==9.6.1; extra == 'docs'
78
78
  Requires-Dist: mkdocs-minify-html-plugin==0.2.3; extra == 'docs'
79
79
  Requires-Dist: mkdocs==1.6.1; extra == 'docs'
80
80
  Requires-Dist: mkdocstrings-python==1.13.0; extra == 'docs'
81
81
  Requires-Dist: mkdocstrings[crystal,python]==0.27.0; extra == 'docs'
82
82
  Provides-Extra: jupyter
83
83
  Requires-Dist: jupyterlab>=4.3.0; extra == 'jupyter'
84
- Requires-Dist: waldiez-jupyter==0.3.10; extra == 'jupyter'
84
+ Requires-Dist: waldiez-jupyter==0.3.11; extra == 'jupyter'
85
85
  Provides-Extra: studio
86
- Requires-Dist: waldiez-studio==0.3.10; extra == 'studio'
86
+ Requires-Dist: waldiez-studio==0.3.11; extra == 'studio'
87
87
  Provides-Extra: test
88
88
  Requires-Dist: pytest-asyncio==0.25.3; extra == 'test'
89
89
  Requires-Dist: pytest-cov==6.0.0; extra == 'test'
@@ -1,8 +1,8 @@
1
1
  waldiez/__init__.py,sha256=cXWdy5P9i_x6fHwlL5DRaIhmpfnhabo5GjASStlcLWw,819
2
2
  waldiez/__main__.py,sha256=0dYzNrQbovRwQQvmZC6_1FDR1m71SUIOkTleO5tBnBw,203
3
- waldiez/_version.py,sha256=Dlx5WyLmhau88DdjdwOZD6NwqTOnOOMu9xNL-3soMP8,156
3
+ waldiez/_version.py,sha256=xakNljN5CllPqeJEkZbxbd1Lwzqsba0yrHbJfxNpzSU,156
4
4
  waldiez/cli.py,sha256=ZhcXOH5WtGVncQpoOix9yHXctQKBwckgiIdYLaRj40c,7108
5
- waldiez/exporter.py,sha256=8EqLya3UqCA_F2TwtfdeRCt7ILnWxBcQvkMyX8no0BU,6501
5
+ waldiez/exporter.py,sha256=ZuMF8cra0Shw4nkDiFuPqaQKFYrF0vPj_I3EhPyesPw,4788
6
6
  waldiez/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  waldiez/runner.py,sha256=rFuCPFSmdOxujEWdEtCrGv8FpZ0cZhPagIslPs-2DZU,11317
8
8
  waldiez/exporting/__init__.py,sha256=nlMWBnn_MViGBJmDhrTCYpPv19fEP_WixvmmY9jt5c8,399
@@ -36,33 +36,33 @@ waldiez/exporting/base/utils/naming.py,sha256=G4e9MPnbg9W8QLVblQj31sV46GKmAOqEA8
36
36
  waldiez/exporting/base/utils/path_check.py,sha256=5XGKmHA3oi9kf2gI4ZHB3K9gnjDP0NEfpn0tP8cme-8,1425
37
37
  waldiez/exporting/base/utils/to_string.py,sha256=fo8i6QaLZJsym3biN2IhVooTWlXiXVCzuU8FNFJVXME,2183
38
38
  waldiez/exporting/chats/__init__.py,sha256=BS8F-hgrzsKPtWEyEMPE-e0JL6q5478i76vR1bKjXXY,195
39
- waldiez/exporting/chats/chats_exporter.py,sha256=6nfLxvS3UWnhe0aq0l6FACJQIrdENCDZlyAl6qIAV84,8515
39
+ waldiez/exporting/chats/chats_exporter.py,sha256=xbVSa9HJ5X8tU197XqAeWfORdtSxcZf9V9scbO_6cNg,8515
40
40
  waldiez/exporting/chats/utils/__init__.py,sha256=FMS94ObfHIlH_Pg_5s5PR-QaXYzcpZErP1Vut2PYaTY,442
41
41
  waldiez/exporting/chats/utils/common.py,sha256=kZ9xO26Oo3tKSxZescFfB2laE9I8F5Hnq3c8oojEVGo,2410
42
42
  waldiez/exporting/chats/utils/nested.py,sha256=evjvJeWHATumNNffAPZUInlyQuzXLmBWnlHfYQaub0I,9227
43
- waldiez/exporting/chats/utils/sequential.py,sha256=kKdfxpt-ZCDeXqwbWRDydkp5BwCuk2BJdG_6DMnK8TM,7787
44
- waldiez/exporting/chats/utils/single_chat.py,sha256=DvB2ODOATHdJ1sw0QIuqoH-2jRim7Y22xWfCdMr6GCc,9416
43
+ waldiez/exporting/chats/utils/sequential.py,sha256=TYAte2hwpGkEENjCMer-6PcL2r8PE-o95hgoi_AX2eg,7841
44
+ waldiez/exporting/chats/utils/single_chat.py,sha256=FYz0jvtO0yFYPk5CBuXb7rOW8VxB0NJWvWY1PEHPIAQ,9535
45
45
  waldiez/exporting/chats/utils/swarm.py,sha256=KJTtgQFt8c_jR800vC8R14ArYVm6ZgpsUyGbiOykmMI,6929
46
46
  waldiez/exporting/flow/__init__.py,sha256=TAJ8lq9saP1IX0U-A6yGKCfvbQnEocmRAX4Hc60f3yY,183
47
- waldiez/exporting/flow/flow_exporter.py,sha256=vI0dKd2jNPGoDTaah_4zPbXKewvJtKB8vbyRRYXh36I,17769
47
+ waldiez/exporting/flow/flow_exporter.py,sha256=DIiplGZaUretIpp6z2inEiiKIxNVhPw8-DF6tC23gjg,18280
48
48
  waldiez/exporting/flow/utils/__init__.py,sha256=Fe0sg5i1K2Vu0ruWsIuPj7oTRHoJTW4KdKmktKRxyrc,1389
49
49
  waldiez/exporting/flow/utils/agent_utils.py,sha256=QL1nzlgYeh6Y-l9R3hmCsrxSzluvBVciuuEIFdBXXKM,6109
50
50
  waldiez/exporting/flow/utils/chat_utils.py,sha256=q6HS4JTNQJe15eh78H1BlN-wId9XzvVQziGhxsUIEFs,1882
51
- waldiez/exporting/flow/utils/def_main.py,sha256=7yrxYizssTBYvcsXj3p-LIP-29-KpCRAV7I3_bhWbXE,2440
52
- waldiez/exporting/flow/utils/flow_content.py,sha256=kAEXS5rWGw0Lvc4R5fosRZZ89SOlFbLsp7qk10pirPU,4515
51
+ waldiez/exporting/flow/utils/def_main.py,sha256=3sINpH9q5h4v14tsV5G1abUgm6-v5HdVwUyfsN8CRN4,2662
52
+ waldiez/exporting/flow/utils/flow_content.py,sha256=RIMtpBFZCJf2G67ipOa3Co5OQinaobYvthqisgir5sQ,4505
53
53
  waldiez/exporting/flow/utils/flow_names.py,sha256=GtfVRF8WYUP8Xx47AiyZ5FuuCUb22jhJn3diblbbBfM,3463
54
- waldiez/exporting/flow/utils/importing_utils.py,sha256=j0E6gyDl0-l1oQUoSd8tRb64TfAet9HEtnQrnGLIDmE,5519
54
+ waldiez/exporting/flow/utils/importing_utils.py,sha256=h8FqyAU0ApSFaie2lipxk69rNWNGwp_xAuhPpT991-M,5552
55
55
  waldiez/exporting/flow/utils/logging_utils.py,sha256=m3Ja00Qb_07rLVgwSOFSBaJk48SfCNsyPuQbRy5VMNU,10963
56
56
  waldiez/exporting/models/__init__.py,sha256=QbyYuS-Px-M9vMrdL-UKqnDzhYWRkNmRGBbc1IBuwpM,212
57
- waldiez/exporting/models/models_exporter.py,sha256=W4EDMY79RNSqZKBd2wYGFRQnt-OvbixXMXiAeTjNdU0,5994
58
- waldiez/exporting/models/utils.py,sha256=atxJ1OxjlSIxdyfBCmr_U7aXjHcZ82IQmjgw8QB4XLM,4849
57
+ waldiez/exporting/models/models_exporter.py,sha256=i9aSnL7JNU8iWJotfSxWbm1CRjUP6yqd9CtfXWiRbV4,6289
58
+ waldiez/exporting/models/utils.py,sha256=g15N_JA21Ly5nzCfburEbHf6fTWX7hG5rxyTvAwyXl0,4997
59
59
  waldiez/exporting/skills/__init__.py,sha256=sJm4ZnN3haldxRBgNlLK0qMK5YtydF2XnSaqnxu2hQo,195
60
60
  waldiez/exporting/skills/skills_exporter.py,sha256=o_16s0VjMoaDwe-JJdbqDP2BzQJV9SAM57k_4KxAix0,5290
61
61
  waldiez/exporting/skills/utils.py,sha256=SAJ55fpNlU9DmmAcSHafq1ddgg4A-bjBxbL3aaWps50,8120
62
62
  waldiez/models/__init__.py,sha256=R_1yLo1mSJHMyrxokXuO-24PVxE3sA0ep2Tj5EG-mTM,3816
63
- waldiez/models/waldiez.py,sha256=Db63-G-fcssUOtOB0ePVvZcLxMr2f6d_UJVrn7hgBwk,10450
63
+ waldiez/models/waldiez.py,sha256=Hc54e_aTzckmi8jsfgNP-an2ocx2HRQhTVhWaexNzBI,10737
64
64
  waldiez/models/agents/__init__.py,sha256=HOY3IG1WWNqepRkETjFZihHRZHgipxWO5cxeVWm1Rv0,4553
65
- waldiez/models/agents/agents.py,sha256=2eN0S9Zjm5pJgv-0JOl8HtcsurbTx01kbUprlMSGWq8,4324
65
+ waldiez/models/agents/agents.py,sha256=pSB3UjeUcYpmWqKoxKpT_CAp2YMzN6l2-ZEYh8Pdddc,4322
66
66
  waldiez/models/agents/agent/__init__.py,sha256=us1qPNCwKdUao9UUVXDHbcjuUUA5yexWEQkozvWLUDY,1044
67
67
  waldiez/models/agents/agent/agent.py,sha256=qZLvi3kAW13DiOzL6IqsjrgkA4q65gTJY9ymC0Pf044,5803
68
68
  waldiez/models/agents/agent/agent_data.py,sha256=rqRRMdqOzUF5jjdVoYika-tqe0YUWHQ4at5fNL9GAYM,5437
@@ -105,16 +105,16 @@ waldiez/models/chat/chat_message.py,sha256=FyQCIVFl6Z1nlyCpDYHZ5YySN6pHSNbMSp4e5
105
105
  waldiez/models/chat/chat_nested.py,sha256=C1ygS7TeB5emRIIIs_xFabKgXzze0HTEO4CIexedGKw,4132
106
106
  waldiez/models/chat/chat_summary.py,sha256=RDeRw7vTV4Niw5_v_UZTOWQkIZUI0q9vdQ01Ja1isM4,2916
107
107
  waldiez/models/common/__init__.py,sha256=I_j63y68FCpSVDz9YXW7aKQsA-X3MOWDvNokyrVpv4w,493
108
- waldiez/models/common/base.py,sha256=SwnnuFTJ0C3PfBoRilqE0uZv3j5aelw7-s-79KcxJNA,1840
108
+ waldiez/models/common/base.py,sha256=WTqElKnOIoDUN9tfaVR4q3-U-DyyrkyV8x7296eZ8jE,1941
109
109
  waldiez/models/common/date_utils.py,sha256=hdnxYU8GKQTnucOnAfs1DAqER0oe59A5G3UVDktl-ro,344
110
110
  waldiez/models/common/dict_utils.py,sha256=ydUP9Am9QxQveqnDB3Rdt62FvTHeFfD4kTmCLXyutGY,1050
111
111
  waldiez/models/common/method_utils.py,sha256=CyTwRppegHviN-J_oj5XsPvX0edMSmEbLVeTkrG2HVo,7010
112
112
  waldiez/models/flow/__init__.py,sha256=3UdwoUZdkLr6G78tNTyaijoiwvmHZ-N0tY3G7S_xbRs,255
113
- waldiez/models/flow/flow.py,sha256=kM8K7dl8wZIP0GEryELC2yZ0t0blEFFkNOvx7VEMW4o,14700
114
- waldiez/models/flow/flow_data.py,sha256=Mqa7NLZMfdiPknj-RhyDPgMZjkDTmcDFUpPKkXuYpTk,5034
113
+ waldiez/models/flow/flow.py,sha256=Shyg-XwzloSzqLLFPwY9g_MjZHxAGy2h_qfPmK58UZs,16876
114
+ waldiez/models/flow/flow_data.py,sha256=afD97Ff9Yd7QSXE4DphaENY7wqrq4QIl4EVgI8O4ZFk,5464
115
115
  waldiez/models/flow/utils.py,sha256=Bd8dWYlCenuU4VeusAL_qxkXzYSuxl9e3a7FhHs6UCY,5435
116
116
  waldiez/models/model/__init__.py,sha256=1cOyDThhZV8o7pZN1DaIhh12jWty_YMegoQ4Jg7uKyI,383
117
- waldiez/models/model/model.py,sha256=0EqHSMIBun_Owy-v0cbv39sRP8if1LlLKeMOD_XA3Ow,6984
117
+ waldiez/models/model/model.py,sha256=k31Tr5mjW4zmahBI52e0pBPnOSxXY0KgOgiNKvNVLQw,7139
118
118
  waldiez/models/model/model_data.py,sha256=EwObYtzPyxZqADdTeWjULNmb3dLgF91mzK3r1nxxJJk,3819
119
119
  waldiez/models/skill/__init__.py,sha256=kAyp9-LwBacI3ndQpU-dCGWjsjojRQy73zXsTddGAmg,306
120
120
  waldiez/models/skill/skill.py,sha256=6r8heHUgRYwfcBJbdsV5DywvTXcEeWPuJN4jzCh3-O4,4255
@@ -130,9 +130,9 @@ waldiez/utils/pysqlite3_checker.py,sha256=LypcHlCMbzdC0QUfrr68gzmrEbwzvKLUn-riYi
130
130
  waldiez/utils/cli_extras/__init__.py,sha256=FQ6biuz6Ig-U3xkmgac3WMUynH_7XWjeGI-DqWFTC8c,625
131
131
  waldiez/utils/cli_extras/jupyter.py,sha256=C4fOiS_PbU15X-6HUZBPHvfgEjOrY39e07mClKvswPI,2971
132
132
  waldiez/utils/cli_extras/studio.py,sha256=te6VmwYDeEEK6Jps-Ou84QPZmCYMsF-oE1hNu6ewFHg,887
133
- waldiez-0.3.10.dist-info/METADATA,sha256=oupQyYHDh2lDqTki8KTa5seNXAjOLCItAVc64lOB32Y,9438
134
- waldiez-0.3.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
135
- waldiez-0.3.10.dist-info/entry_points.txt,sha256=9MQ8Y1rD19CU7UwjNPwoyTRpQsPs2QimjrtwTD0bD6k,44
136
- waldiez-0.3.10.dist-info/licenses/LICENSE,sha256=bWinEG_ynCS8eSj1vhAmYDWwYODhBOF0AUEjOgZ3kmU,11355
137
- waldiez-0.3.10.dist-info/licenses/NOTICE.md,sha256=lrKsUNrpE18LPSLPJY_kt2ZJFZJEwH55wPv5Axcheyc,133
138
- waldiez-0.3.10.dist-info/RECORD,,
133
+ waldiez-0.3.11.dist-info/METADATA,sha256=olpy7txsUlYNHBlFo5-6fU9F1rRRk8_sgeNiw7hq0Hc,9422
134
+ waldiez-0.3.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
135
+ waldiez-0.3.11.dist-info/entry_points.txt,sha256=9MQ8Y1rD19CU7UwjNPwoyTRpQsPs2QimjrtwTD0bD6k,44
136
+ waldiez-0.3.11.dist-info/licenses/LICENSE,sha256=bWinEG_ynCS8eSj1vhAmYDWwYODhBOF0AUEjOgZ3kmU,11355
137
+ waldiez-0.3.11.dist-info/licenses/NOTICE.md,sha256=lrKsUNrpE18LPSLPJY_kt2ZJFZJEwH55wPv5Axcheyc,133
138
+ waldiez-0.3.11.dist-info/RECORD,,