waldiez 0.2.2__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 +4 -3
  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.2.dist-info → waldiez-0.3.0.dist-info}/METADATA +32 -26
  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.2.dist-info/RECORD +0 -92
  136. waldiez-0.2.2.dist-info/licenses/LICENSE +0 -21
  137. {waldiez-0.2.2.dist-info → waldiez-0.3.0.dist-info}/WHEEL +0 -0
  138. {waldiez-0.2.2.dist-info → waldiez-0.3.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,192 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ """Export models (llm_configs)."""
4
+
5
+ from pathlib import Path
6
+ from typing import Dict, List, Optional, Tuple, Union
7
+
8
+ from waldiez.models import WaldiezAgent, WaldiezModel
9
+
10
+ from ..base import (
11
+ AgentPosition,
12
+ AgentPositions,
13
+ BaseExporter,
14
+ ExporterMixin,
15
+ ExporterReturnType,
16
+ ExportPosition,
17
+ ImportPosition,
18
+ )
19
+ from .utils import export_models, get_agent_llm_config_arg
20
+
21
+
22
+ class ModelsExporter(BaseExporter, ExporterMixin):
23
+ """Models exporter."""
24
+
25
+ _exported_string: Optional[str]
26
+
27
+ def __init__(
28
+ self,
29
+ flow_name: str,
30
+ agents: List[WaldiezAgent],
31
+ agent_names: Dict[str, str],
32
+ models: List[WaldiezModel],
33
+ model_names: Dict[str, str],
34
+ for_notebook: bool,
35
+ output_dir: Optional[Union[str, Path]] = None,
36
+ ) -> None:
37
+ """Initialize the models exporter.
38
+
39
+ Parameters
40
+ ----------
41
+ agents : List[WaldiezAgent]
42
+ The agents.
43
+ agent_names : Dict[str, str]
44
+ The agent names.
45
+ models : List[WaldiezModel]
46
+ The models.
47
+ model_names : Dict[str, str]
48
+ The model names.
49
+ output_dir : Optional[Union[str, Path]], optional
50
+ The output directory if any, by default None
51
+ """
52
+ self.for_notebook = for_notebook
53
+ self.flow_name = flow_name
54
+ self.agents = agents
55
+ self.agent_names = agent_names
56
+ self.models = models
57
+ self.model_names = model_names
58
+ if output_dir is not None and not isinstance(output_dir, Path):
59
+ output_dir = Path(output_dir)
60
+ self.output_dir = output_dir
61
+ self._exported_string = None
62
+
63
+ def get_imports(self) -> Optional[List[Tuple[str, ImportPosition]]]:
64
+ """Generate the imports string.
65
+
66
+ Returns
67
+ -------
68
+ Optional[Tuple[str, ImportPosition]]
69
+ The exported imports and the position of the imports.
70
+ """
71
+ if not self.output_dir:
72
+ return None
73
+ file_path = self.output_dir / f"{self.flow_name}_api_keys.py"
74
+ if not file_path.exists():
75
+ # might be because the models are not exported yet
76
+ if not self._exported_string:
77
+ self.generate()
78
+ # if still not exported, return None
79
+ if not file_path.exists(): # pragma: no cover
80
+ return None
81
+ import_string = f"from {self.flow_name}_api_keys import (" + "\n"
82
+ import_string += f" get_{self.flow_name}_model_api_key," + "\n"
83
+ import_string += ")\n"
84
+ return [(import_string, ImportPosition.LOCAL)]
85
+
86
+ def get_after_export(
87
+ self,
88
+ ) -> Optional[List[Tuple[str, Union[ExportPosition, AgentPosition]]]]:
89
+ # fmt: off
90
+ """Generate the after export strings.
91
+
92
+ The arguments for the agent's initialization.
93
+ example generated args:
94
+ >>> agent1 = ConversableAgent(
95
+ >>> ...
96
+ >>> llm_config=False,
97
+ >>> ...
98
+ >>> )
99
+
100
+ >>> agent2 = ConversableAgent(
101
+ >>> ...
102
+ >>> llm_config={
103
+ >>> "config_list": [
104
+ >>> model1_llm_config,
105
+ >>> model2_llm_config,
106
+ >>> ],
107
+ >>> },
108
+ >>> ...
109
+ >>> )
110
+
111
+ where `model1_llm_config` and `model2_llm_config`
112
+ are the exported models using `self.generate()`
113
+
114
+ Returns
115
+ -------
116
+ Optional[List[Tuple[str, Union[ExportPosition, AgentPosition]]]]
117
+ The exported after export strings and their positions.
118
+ """
119
+ # fmt: on
120
+ agent_llm_config_args: List[
121
+ Tuple[str, Union[ExportPosition, AgentPosition]]
122
+ ] = []
123
+ for agent in self.agents:
124
+ agent_llm_config_args.append(
125
+ (
126
+ get_agent_llm_config_arg(
127
+ agent,
128
+ all_models=self.models,
129
+ model_names=self.model_names,
130
+ ),
131
+ AgentPosition(
132
+ agent=agent, position=AgentPositions.AS_ARGUMENT
133
+ ),
134
+ )
135
+ )
136
+ return agent_llm_config_args
137
+
138
+ def generate(self) -> str:
139
+ """Export the models.
140
+
141
+ Returns
142
+ -------
143
+ str
144
+ The exported models.
145
+ """
146
+ if not self._exported_string: # pragma: no cover
147
+ self._exported_string = export_models(
148
+ flow_name=self.flow_name,
149
+ all_models=self.models,
150
+ model_names=self.model_names,
151
+ output_dir=self.output_dir,
152
+ serializer=self.serializer,
153
+ )
154
+ return self._exported_string
155
+
156
+ def get_environment_variables(self) -> Optional[List[Tuple[str, str]]]:
157
+ """Get the environment variables to set.
158
+
159
+ Returns
160
+ -------
161
+ Optional[List[Tuple[str, str]]
162
+ The environment variables to set.
163
+ """
164
+ env_vars = []
165
+ for model in self.models:
166
+ if model.api_key:
167
+ env_vars.append((model.api_key_env_key, model.api_key))
168
+ return env_vars
169
+
170
+ def export(self) -> ExporterReturnType:
171
+ """Export the models.
172
+
173
+ Returns
174
+ -------
175
+ ExporterReturnType
176
+ The exported models,
177
+ the imports,
178
+ the before export strings,
179
+ the after export strings,
180
+ and the environment variables.
181
+ """
182
+ exported_string = self.generate()
183
+ imports = self.get_imports()
184
+ after_export = self.get_after_export()
185
+ result: ExporterReturnType = {
186
+ "content": exported_string,
187
+ "imports": imports,
188
+ "before_export": None,
189
+ "after_export": after_export,
190
+ "environment_variables": None,
191
+ }
192
+ return result
@@ -0,0 +1,166 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ """Model/LLM related string generation functions.
4
+
5
+ Functions
6
+ ---------
7
+ export_models
8
+ Get the string representations of the LLM configs.
9
+ """
10
+
11
+ from pathlib import Path
12
+ from typing import Callable, Dict, List, Optional
13
+
14
+ from waldiez.models import WaldiezAgent, WaldiezModel
15
+
16
+
17
+ def export_models(
18
+ flow_name: str,
19
+ all_models: List[WaldiezModel],
20
+ model_names: Dict[str, str],
21
+ serializer: Callable[..., str],
22
+ output_dir: Optional[Path] = None,
23
+ ) -> str:
24
+ """Get the string representations of all the models in the flow.
25
+
26
+ Parameters
27
+ ----------
28
+ flow_name : str
29
+ The name of the flow.
30
+ all_models : List[WaldiezModel]
31
+ All the models in the flow.
32
+ model_names : Dict[str, str]
33
+ A mapping of model ids to model names.
34
+ serializer : Callable[..., str]
35
+ The serializer function.
36
+ output_dir : Optional[Path]
37
+ The output directory to write the api keys.
38
+
39
+ Returns
40
+ -------
41
+ str
42
+ The models' llm config string.
43
+ """
44
+ content = ""
45
+ for model in all_models:
46
+ model_name = model_names[model.id]
47
+ model_config = model.get_llm_config()
48
+ model_config["api_key"] = (
49
+ f'get_{flow_name}_model_api_key("{model_name}")'
50
+ )
51
+ model_dict_str = serializer(model_config, tabs=0)
52
+ model_dict_str = model_dict_str.replace(
53
+ f'"get_{flow_name}_model_api_key("{model_name}")"',
54
+ f'get_{flow_name}_model_api_key("{model_name}")',
55
+ )
56
+ content += "\n" + f"{model_name}_llm_config = {model_dict_str}" + "\n"
57
+ if output_dir:
58
+ write_api_keys(flow_name, all_models, model_names, output_dir)
59
+ return content
60
+
61
+
62
+ def get_agent_llm_config_arg(
63
+ agent: WaldiezAgent,
64
+ all_models: List[WaldiezModel],
65
+ model_names: Dict[str, str],
66
+ tabs: int = 1,
67
+ ) -> str:
68
+ """Get the string representation of the agent's llm config argument.
69
+
70
+ Parameters
71
+ ----------
72
+ agent : WaldiezAgent
73
+ The agent.
74
+ all_models : List[WaldiezModel]
75
+ All the models in the flow.
76
+ model_names : Dict[str, str]
77
+ A mapping of model ids to model names.
78
+ tabs : int, optional
79
+ The number of tabs for indentation, by default 1.
80
+
81
+ Returns
82
+ -------
83
+ str
84
+ The agent's llm config argument to use.
85
+ """
86
+ tab = " " * tabs if tabs > 0 else ""
87
+ if not agent.data.model_ids:
88
+ return f"{tab}llm_config=False," + "\n"
89
+ content = f"{tab}llm_config=" + "{\n"
90
+ content += f'{tab} "config_list": ['
91
+ got_at_least_one_model = False
92
+ for model_id in agent.data.model_ids:
93
+ model = next((m for m in all_models if m.id == model_id), None)
94
+ if model is not None:
95
+ model_name = model_names[model_id]
96
+ content += "\n" + f"{tab} {model_name}_llm_config,"
97
+ got_at_least_one_model = True
98
+ if not got_at_least_one_model: # pragma: no cover
99
+ return f"{tab}llm_config=False," + "\n"
100
+ content += "\n" + f"{tab} ]," + "\n"
101
+ content += tab + "},\n"
102
+ return content
103
+
104
+
105
+ def write_api_keys(
106
+ flow_name: str,
107
+ all_models: List[WaldiezModel],
108
+ model_names: Dict[str, str],
109
+ output_dir: Path,
110
+ ) -> None:
111
+ """Write the api keys to a separate file.
112
+
113
+ Parameters
114
+ ----------
115
+ flow_name : str
116
+ The name of the flow.
117
+ all_models : List[WaldiezModel]
118
+ All the models in the flow.
119
+ model_names : Dict[str, str]
120
+ A mapping of model ids to model names.
121
+ output_dir : Path
122
+ The output directory to write the api keys.
123
+ """
124
+ flow_name_upper = flow_name.upper()
125
+ api_keys_content = f'''
126
+ """API keys for the {flow_name} models."""
127
+
128
+ import os
129
+
130
+ __{flow_name_upper}_MODEL_API_KEYS__ = {{'''
131
+ for model in all_models:
132
+ model_name = model_names[model.id]
133
+ key_env = model.api_key_env_key
134
+ api_keys_content += (
135
+ "\n" + f' "{model_name}": '
136
+ f'{{"key": "{model.api_key}", "env_key": "{key_env}"}},'
137
+ )
138
+ api_keys_content += "\n}\n"
139
+ api_keys_content += f'''
140
+
141
+ def get_{flow_name}_model_api_key(model_name: str) -> str:
142
+ """Get the api key for the model.
143
+
144
+ Parameters
145
+ ----------
146
+ model_name : str
147
+ The name of the model.
148
+
149
+ Returns
150
+ -------
151
+ str
152
+ The api key for the model.
153
+ """
154
+ entry = __{flow_name_upper}_MODEL_API_KEYS__.get(model_name, {{}})
155
+ if not entry:
156
+ return ""
157
+ env_key = entry.get("env_key", "")
158
+ if env_key:
159
+ from_env = os.environ.get(env_key, "")
160
+ if from_env:
161
+ return from_env
162
+ return entry.get("key", "")
163
+ '''
164
+ file_name = f"{flow_name}_api_keys.py"
165
+ with open(output_dir / file_name, "w", encoding="utf-8", newline="\n") as f:
166
+ f.write(api_keys_content)
@@ -1,163 +1,9 @@
1
- """Skills/tools related string generation functions.
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ """Export skill."""
2
4
 
3
- Functions
4
- ---------
5
- get_agent_skill_registration
6
- Get an agent's skill registration string.
7
- export_skills
8
- Get the skills content and secrets.
9
- """
5
+ from .skills_exporter import SkillsExporter
10
6
 
11
- from pathlib import Path
12
- from typing import Dict, List, Optional, Set, Tuple, Union
13
-
14
- from waldiez.models import WaldiezSkill
15
-
16
- from ..utils import get_escaped_string
17
-
18
-
19
- def get_agent_skill_registration(
20
- caller_name: str,
21
- executor_name: str,
22
- skill_name: str,
23
- skill_description: str,
24
- ) -> str:
25
- """Get the agent skill string and secrets.
26
-
27
- Parameters
28
- ----------
29
- caller_name : str
30
- The name of the caller (agent).
31
- executor_name : str
32
- The name of the executor (agent).
33
- skill_name : str
34
- The name of the skill.
35
- skill_description : str
36
- The skill description.
37
-
38
- Returns
39
- -------
40
- str
41
- The agent skill string.
42
-
43
- Example
44
- -------
45
- ```python
46
- >>> get_agent_skill_registration(
47
- ... caller_name="agent1",
48
- ... executor_name="agent2",
49
- ... skill_name="skill1",
50
- ... skill_description="A skill that does something.",
51
- ... )
52
- register_function(
53
- skill1,
54
- caller=agent1,
55
- executor=agent2,
56
- name="skill1",
57
- description="A skill that does something.",
58
- )
59
- ```
60
- """
61
- skill_description = get_escaped_string(skill_description)
62
- content = f"""register_function(
63
- {skill_name},
64
- caller={caller_name},
65
- executor={executor_name},
66
- name="{skill_name}",
67
- description="{skill_description}",
68
- )"""
69
- return content
70
-
71
-
72
- def _write_skill_secrets(
73
- skill: WaldiezSkill,
74
- skill_name: str,
75
- output_dir: Path,
76
- ) -> None:
77
- """Write the skill secrets to a file.
78
-
79
- Parameters
80
- ----------
81
- skill : WaldiezSkill
82
- The skill.
83
- skill_name : str
84
- The name of the skill.
85
- output_dir : Path
86
- The output directory to save the secrets to.
87
- """
88
- if not skill.secrets:
89
- return
90
- secrets_file = output_dir / f"{skill_name}_secrets.py"
91
- with secrets_file.open("w", encoding="utf-8", newline="\n") as f:
92
- f.write('"""Secrets for the skill."""\n')
93
- f.write("from os import environ\n\n")
94
- for key, value in skill.secrets.items():
95
- f.write(f'environ["{key}"] = "{value}"\n')
96
-
97
-
98
- def export_skills(
99
- skills: List[WaldiezSkill],
100
- skill_names: Dict[str, str],
101
- output_dir: Optional[Union[str, Path]] = None,
102
- ) -> Tuple[Set[str], Set[Tuple[str, str]]]:
103
- """Get the skills' contents and secrets.
104
-
105
- If `output_dir` is provided, the contents are saved to that directory.
106
-
107
- Parameters
108
- ----------
109
- skills : List[WaldiezSkill]
110
- The skills.
111
- skill_names : Dict[str, str]
112
- The skill names.
113
- output_dir : Optional[Union[str, Path]]
114
- The output directory to save the skills to.
115
-
116
- Returns
117
- -------
118
- Tuple[Set[str], Set[Tuple[str, str]]]
119
- - The skill imports to use in the main file.
120
- - The skill secrets to set as environment variables.
121
-
122
- Example
123
- -------
124
- ```python
125
- >>> from waldiez.models import WaldiezSkill, WaldiezSkillData
126
- >>> skill1 = WaldiezSkill(
127
- ... id="ws-1",
128
- ... name="skill1",
129
- ... description="A skill that does something.",
130
- ... tags=["skill", "skill1"],
131
- ... requirements=[],
132
- ... data=WaldiezSkillData(
133
- ... content="def skill1():\\n pass",
134
- ... secrets={"API_KEY": "1234567890"},
135
- ... )
136
- >>> skill_names = {"ws-1": "skill1"}
137
- >>> export_skills([skill1], skill_names, None)
138
- ({'from skill1 import skill1'}, {('API_KEY', '1234567890')})
139
- ```
140
- """
141
- skill_imports: Set[str] = set()
142
- skill_secrets: Set[Tuple[str, str]] = set()
143
- for skill in skills:
144
- skill_name = skill_names[skill.id]
145
- skill_secrets.update(skill.secrets.items())
146
- if not output_dir:
147
- skill_imports.add(f"from {skill_name} import {skill_name}")
148
- continue
149
- if not isinstance(output_dir, Path):
150
- output_dir = Path(output_dir)
151
- if not skill.secrets:
152
- skill_imports.add(f"from {skill_name} import {skill_name}")
153
- else:
154
- # have the secrets before the skill
155
- skill_imports.add(
156
- f"import {skill_name}_secrets # noqa\n"
157
- f"from {skill_name} import {skill_name}"
158
- )
159
- _write_skill_secrets(skill, skill_name, output_dir)
160
- skill_file = output_dir / f"{skill_name}.py"
161
- with skill_file.open("w", encoding="utf-8", newline="\n") as f:
162
- f.write(skill.content)
163
- return skill_imports, skill_secrets
7
+ __all__ = [
8
+ "SkillsExporter",
9
+ ]
@@ -0,0 +1,169 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ """Skills/tools related string generation functions.
4
+
5
+ Functions
6
+ ---------
7
+ get_agent_skill_registration
8
+ Get an agent's skill registration string.
9
+ export_skills
10
+ Get the skills content and secrets.
11
+ """
12
+
13
+ from pathlib import Path
14
+ from typing import Dict, List, Optional, Tuple, Union
15
+
16
+ from waldiez.models import WaldiezAgent, WaldiezSkill
17
+
18
+ from ..base import (
19
+ AgentPosition,
20
+ AgentPositions,
21
+ BaseExporter,
22
+ ExporterMixin,
23
+ ExporterReturnType,
24
+ ExportPosition,
25
+ ImportPosition,
26
+ )
27
+ from .utils import export_skills, get_agent_skill_registrations
28
+
29
+
30
+ class SkillsExporter(BaseExporter, ExporterMixin):
31
+ """Skill exporter."""
32
+
33
+ def __init__(
34
+ self,
35
+ flow_name: str,
36
+ agents: List[WaldiezAgent],
37
+ agent_names: Dict[str, str],
38
+ skills: List[WaldiezSkill],
39
+ skill_names: Dict[str, str],
40
+ output_dir: Optional[Union[str, Path]] = None,
41
+ ) -> None:
42
+ """Initialize the skill exporter.
43
+
44
+ Parameters
45
+ ----------
46
+ flow_name : str
47
+ The name of the flow.
48
+ agents : List[WaldiezAgent]
49
+ The agents.
50
+ agent_names : Dict[str, str]
51
+ The agent names.
52
+ skills : List[WaldiezSkill]
53
+ The skills.
54
+ skill_names : Dict[str, str]
55
+ The skill names.
56
+ output_dir : Optional[Union[str, Path]], optional
57
+ The output directory if any, by default None
58
+ """
59
+ self.flow_name = flow_name
60
+ self.agents = agents
61
+ self.agent_names = agent_names
62
+ self.skills = skills
63
+ self.skill_names = skill_names
64
+ self.output_dir = output_dir
65
+ self.skill_imports, self.skill_secrets, self.skills_contents = (
66
+ export_skills(
67
+ flow_name=flow_name,
68
+ skills=skills,
69
+ skill_names=skill_names,
70
+ output_dir=output_dir,
71
+ )
72
+ )
73
+
74
+ def get_environment_variables(self) -> List[Tuple[str, str]]:
75
+ """Get the environment variables to set.
76
+
77
+ Returns
78
+ -------
79
+ List[Tuple[str, str]]
80
+ The environment variables to set.
81
+ """
82
+ return self.skill_secrets
83
+
84
+ def get_imports(self) -> List[Tuple[str, ImportPosition]]:
85
+ """ "Generate the imports string.
86
+
87
+ Returns
88
+ -------
89
+ Tuple[str, int]
90
+ The exported imports and the position of the imports.
91
+ """
92
+ if not self.skill_imports:
93
+ return []
94
+ imports: List[Tuple[str, ImportPosition]] = []
95
+ for skill_import in self.skill_imports:
96
+ if (skill_import, ImportPosition.LOCAL) not in imports:
97
+ imports.append((skill_import, ImportPosition.LOCAL))
98
+ return imports
99
+
100
+ def get_before_export(
101
+ self,
102
+ ) -> Optional[List[Tuple[str, Union[ExportPosition, AgentPosition]]]]:
103
+ """Generate the content before the main export.
104
+
105
+ Returns
106
+ -------
107
+ Optional[List[Tuple[str, Union[ExportPosition, AgentPosition]]]]
108
+ The exported content before the main export and its position.
109
+ """
110
+
111
+ def generate(self) -> Optional[str]:
112
+ """Generate the main export.
113
+
114
+ Returns
115
+ -------
116
+ Optional[str]
117
+ The exported content.
118
+ """
119
+ return self.skills_contents
120
+
121
+ def get_after_export(
122
+ self,
123
+ ) -> Optional[List[Tuple[str, Union[ExportPosition, AgentPosition]]]]:
124
+ """Generate the content after the main export.
125
+
126
+ Returns
127
+ -------
128
+ Optional[List[Tuple[str, Union[ExportPosition, AgentPosition]]]]
129
+ The exported content after the main export and its position.
130
+ """
131
+ agent_registrations: List[
132
+ Tuple[str, Union[ExportPosition, AgentPosition]]
133
+ ] = []
134
+ for agent in self.agents:
135
+ agent_registration = get_agent_skill_registrations(
136
+ agent=agent,
137
+ agent_names=self.agent_names,
138
+ all_skills=self.skills,
139
+ skill_names=self.skill_names,
140
+ string_escape=self.string_escape,
141
+ )
142
+ if agent_registration:
143
+ # after all agents since we use the executor
144
+ # (it might not yet be defined)
145
+ position = AgentPosition(None, AgentPositions.AFTER_ALL, 1)
146
+ agent_registrations.append((agent_registration, position))
147
+ return agent_registrations
148
+
149
+ def export(self) -> ExporterReturnType:
150
+ """Export the skills.
151
+
152
+ Returns
153
+ -------
154
+ ExporterReturnType
155
+ The exported skills content, the imports,
156
+ the before export strings, the after export strings,
157
+ and the environment variables.
158
+ """
159
+ imports = self.get_imports()
160
+ after_export = self.get_after_export()
161
+ environment_variables = self.get_environment_variables()
162
+ result: ExporterReturnType = {
163
+ "content": self.generate(),
164
+ "imports": imports,
165
+ "before_export": None,
166
+ "after_export": after_export,
167
+ "environment_variables": environment_variables,
168
+ }
169
+ return result