waldiez 0.5.3__py3-none-any.whl → 0.5.5__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 (76) hide show
  1. waldiez/_version.py +1 -1
  2. waldiez/cli.py +3 -27
  3. waldiez/exporter.py +0 -13
  4. waldiez/exporting/agent/exporter.py +38 -0
  5. waldiez/exporting/agent/extras/__init__.py +2 -0
  6. waldiez/exporting/agent/extras/doc_agent_extras.py +366 -0
  7. waldiez/exporting/agent/extras/group_member_extras.py +3 -2
  8. waldiez/exporting/agent/processor.py +113 -15
  9. waldiez/exporting/chats/processor.py +2 -21
  10. waldiez/exporting/chats/utils/common.py +66 -1
  11. waldiez/exporting/chats/utils/group.py +6 -3
  12. waldiez/exporting/chats/utils/nested.py +1 -1
  13. waldiez/exporting/chats/utils/sequential.py +25 -9
  14. waldiez/exporting/chats/utils/single.py +8 -6
  15. waldiez/exporting/core/context.py +0 -12
  16. waldiez/exporting/core/extras/agent_extras/standard_extras.py +3 -1
  17. waldiez/exporting/core/extras/base.py +20 -17
  18. waldiez/exporting/core/extras/path_resolver.py +39 -41
  19. waldiez/exporting/core/extras/serializer.py +16 -1
  20. waldiez/exporting/core/protocols.py +17 -0
  21. waldiez/exporting/core/types.py +6 -9
  22. waldiez/exporting/flow/execution_generator.py +56 -21
  23. waldiez/exporting/flow/exporter.py +1 -4
  24. waldiez/exporting/flow/factory.py +0 -9
  25. waldiez/exporting/flow/file_generator.py +6 -0
  26. waldiez/exporting/flow/orchestrator.py +27 -21
  27. waldiez/exporting/flow/utils/__init__.py +0 -2
  28. waldiez/exporting/flow/utils/common.py +15 -96
  29. waldiez/exporting/flow/utils/importing.py +4 -0
  30. waldiez/io/mqtt.py +33 -14
  31. waldiez/io/redis.py +18 -13
  32. waldiez/io/structured.py +9 -4
  33. waldiez/io/utils.py +32 -0
  34. waldiez/io/ws.py +8 -2
  35. waldiez/models/__init__.py +6 -0
  36. waldiez/models/agents/__init__.py +8 -0
  37. waldiez/models/agents/agent/agent.py +136 -38
  38. waldiez/models/agents/agent/agent_type.py +3 -2
  39. waldiez/models/agents/agents.py +10 -0
  40. waldiez/models/agents/doc_agent/__init__.py +13 -0
  41. waldiez/models/agents/doc_agent/doc_agent.py +126 -0
  42. waldiez/models/agents/doc_agent/doc_agent_data.py +149 -0
  43. waldiez/models/agents/doc_agent/rag_query_engine.py +127 -0
  44. waldiez/models/flow/flow.py +13 -2
  45. waldiez/models/model/__init__.py +2 -2
  46. waldiez/models/model/_aws.py +75 -0
  47. waldiez/models/model/_llm.py +516 -0
  48. waldiez/models/model/_price.py +30 -0
  49. waldiez/models/model/model.py +45 -2
  50. waldiez/models/model/model_data.py +2 -83
  51. waldiez/models/tool/predefined/_duckduckgo.py +123 -0
  52. waldiez/models/tool/predefined/_google.py +31 -9
  53. waldiez/models/tool/predefined/_perplexity.py +161 -0
  54. waldiez/models/tool/predefined/_searxng.py +152 -0
  55. waldiez/models/tool/predefined/_tavily.py +46 -9
  56. waldiez/models/tool/predefined/_wikipedia.py +26 -6
  57. waldiez/models/tool/predefined/_youtube.py +36 -8
  58. waldiez/models/tool/predefined/registry.py +6 -0
  59. waldiez/models/waldiez.py +12 -0
  60. waldiez/runner.py +177 -408
  61. waldiez/running/__init__.py +2 -4
  62. waldiez/running/base_runner.py +100 -112
  63. waldiez/running/environment.py +29 -4
  64. waldiez/running/post_run.py +0 -1
  65. waldiez/running/protocol.py +36 -48
  66. waldiez/running/run_results.py +5 -5
  67. waldiez/running/standard_runner.py +429 -0
  68. waldiez/running/timeline_processor.py +0 -82
  69. {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/METADATA +59 -62
  70. {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/RECORD +74 -64
  71. waldiez/running/import_runner.py +0 -437
  72. waldiez/running/subprocess_runner.py +0 -104
  73. {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/WHEEL +0 -0
  74. {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/entry_points.txt +0 -0
  75. {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/licenses/LICENSE +0 -0
  76. {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/licenses/NOTICE.md +0 -0
@@ -9,7 +9,9 @@ from pydantic import Field
9
9
  from typing_extensions import Annotated, Literal
10
10
 
11
11
  from ..common import WaldiezBase, now
12
- from .model_data import WaldiezModelAPIType, WaldiezModelAWS, WaldiezModelData
12
+ from ._aws import WaldiezModelAWS
13
+ from ._llm import get_llm_arg, get_llm_imports, get_llm_requirements
14
+ from .model_data import WaldiezModelAPIType, WaldiezModelData
13
15
 
14
16
  DEFAULT_BASE_URLS: dict[WaldiezModelAPIType, str] = {
15
17
  "deepseek": "https://api.deepseek.com/v1",
@@ -26,7 +28,7 @@ DEFAULT_BASE_URLS: dict[WaldiezModelAPIType, str] = {
26
28
  # we can omit the base_url for these models
27
29
  MODEL_NEEDS_BASE_URL: dict[WaldiezModelAPIType, bool] = {
28
30
  "openai": False,
29
- "azure": False,
31
+ "azure": True,
30
32
  "google": False,
31
33
  "anthropic": False,
32
34
  "cohere": False,
@@ -172,6 +174,10 @@ class WaldiezModel(WaldiezBase):
172
174
  )
173
175
  if api_key and api_key != "REPLACE_ME":
174
176
  os.environ[env_key] = api_key
177
+ if api_key == "GOOGLE_GEMINI_API_KEY":
178
+ # llama-index expects GOOGLE_API_KEY
179
+ # https://docs.llamaindex.ai/en/stable/examples/llm/gemini/
180
+ os.environ["GOOGLE_API_KEY"] = api_key
175
181
  return api_key or "REPLACE_ME"
176
182
 
177
183
  @property
@@ -228,6 +234,43 @@ class WaldiezModel(WaldiezBase):
228
234
  return set_bedrock_aws_config(_llm_config, self.data.aws)
229
235
  return set_default_base_url(_llm_config, self.data.api_type)
230
236
 
237
+ def get_llm_requirements(self, ag2_version: str) -> set[str]:
238
+ """Get the LLM requirements for the model.
239
+
240
+ Parameters
241
+ ----------
242
+ ag2_version : str
243
+ The version of AG2 to use for the requirements.
244
+
245
+ Returns
246
+ -------
247
+ set[str]
248
+ The set of LLM requirements for the model.
249
+ """
250
+ return get_llm_requirements(self, ag2_version=ag2_version)
251
+
252
+ def get_llm_imports(self) -> set[str]:
253
+ """Get the LLM import statements for the model.
254
+
255
+ Returns
256
+ -------
257
+ set[str]
258
+ The set of LLM import statements for the model.
259
+ """
260
+ return get_llm_imports(self)
261
+
262
+ def get_llm_arg(
263
+ self,
264
+ ) -> tuple[str, str]:
265
+ """Get the LLM argument and any content before it.
266
+
267
+ Returns
268
+ -------
269
+ tuple[str, str]
270
+ The LLM argument string for the model and any content before it.
271
+ """
272
+ return get_llm_arg(self)
273
+
231
274
 
232
275
  def set_default_base_url(
233
276
  llm_config: dict[str, Any], api_type: WaldiezModelAPIType
@@ -9,6 +9,8 @@ from pydantic import Field
9
9
  from typing_extensions import Annotated, Literal
10
10
 
11
11
  from ..common import WaldiezBase
12
+ from ._aws import WaldiezModelAWS
13
+ from ._price import WaldiezModelPrice
12
14
 
13
15
  WaldiezModelAPIType = Literal[
14
16
  "openai",
@@ -27,89 +29,6 @@ WaldiezModelAPIType = Literal[
27
29
  """Possible API types for the model."""
28
30
 
29
31
 
30
- class WaldiezModelAWS(WaldiezBase):
31
- """AWS related parameters.
32
-
33
- Attributes
34
- ----------
35
- region : Optional[str]
36
- The AWS region, by default None.
37
- access_key : Optional[str]
38
- The AWS access key, by default None.
39
- secret_key : Optional[str]
40
- The AWS secret access key, by default None.
41
- session_token : Optional[str]
42
- The AWS session token, by default None.
43
- profile_name : Optional[str]
44
- The AWS profile name, by default Nonde.
45
- """
46
-
47
- region: Annotated[
48
- Optional[str],
49
- Field(
50
- None,
51
- alias="region",
52
- title="Region",
53
- description="The AWS region",
54
- ),
55
- ] = None
56
- access_key: Annotated[
57
- Optional[str],
58
- Field(
59
- None,
60
- alias="accessKey",
61
- title="Access Ke",
62
- description="The AWS access key",
63
- ),
64
- ] = None
65
- secret_key: Annotated[
66
- Optional[str],
67
- Field(
68
- None,
69
- alias="secretKey",
70
- title="Secret Key",
71
- description="The AWS secret key",
72
- ),
73
- ] = None
74
- session_token: Annotated[
75
- Optional[str],
76
- Field(
77
- None,
78
- alias="sessionToken",
79
- title="Session Token",
80
- description="The AWS session token",
81
- ),
82
- ] = None
83
- profile_name: Annotated[
84
- Optional[str],
85
- Field(
86
- None,
87
- alias="profileName",
88
- title="Profile Name",
89
- description="The AWS Profile name to use",
90
- ),
91
- ] = None
92
-
93
-
94
- class WaldiezModelPrice(WaldiezBase):
95
- """Model Price.
96
-
97
- Attributes
98
- ----------
99
- prompt_price_per_1k : float
100
- The prompt price per 1k tokens.
101
- completion_token_price_per_1k : float
102
- The completion token price per 1k tokens.
103
- """
104
-
105
- prompt_price_per_1k: Annotated[
106
- Optional[float], Field(None, alias="promptPricePer1k")
107
- ]
108
- completion_token_price_per_1k: Annotated[
109
- Optional[float], Field(None, alias="completionTokenPricePer1k")
110
- ]
111
-
112
-
113
32
  # pylint: disable=line-too-long
114
33
  class WaldiezModelData(WaldiezBase):
115
34
  """Waldiez Model Data.
@@ -0,0 +1,123 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ """Predefined DuckDuckGo search tool for Waldiez."""
4
+
5
+ from typing import Any
6
+
7
+ from ._config import PredefinedToolConfig
8
+ from .protocol import PredefinedTool
9
+
10
+
11
+ class DuckDuckGoSearchToolImpl(PredefinedTool):
12
+ """DuckDuckGo search tool for Waldiez."""
13
+
14
+ required_secrets: list[str] = []
15
+ required_kwargs: dict[str, type] = {}
16
+
17
+ @property
18
+ def name(self) -> str:
19
+ """Tool name."""
20
+ return "duckduckgo_search"
21
+
22
+ @property
23
+ def description(self) -> str:
24
+ """Tool description."""
25
+ return "Search DuckDuckGo for a given query."
26
+
27
+ @property
28
+ def kwargs(self) -> dict[str, Any]:
29
+ """Keyword arguments for the tool, used for initialization."""
30
+ return {}
31
+
32
+ @property
33
+ def requirements(self) -> list[str]:
34
+ """Python requirements for the tool."""
35
+ return ["ag2[duckduckgo]", "ddgs"]
36
+
37
+ @property
38
+ def tags(self) -> list[str]:
39
+ """Tags for the tool, used for categorization."""
40
+ return ["duckduckgo", "search", "web"]
41
+
42
+ @property
43
+ def tool_imports(self) -> list[str]:
44
+ """Imports required for the tool implementation."""
45
+ return [
46
+ "from autogen.tools.experimental import DuckDuckGoSearchTool",
47
+ ]
48
+
49
+ def validate_secrets(self, secrets: dict[str, str]) -> list[str]:
50
+ """Validate secrets and return list of missing required ones.
51
+
52
+ Parameters
53
+ ----------
54
+ secrets : dict[str, str]
55
+ Dictionary of secrets/environment variables.
56
+
57
+ Returns
58
+ -------
59
+ list[str]
60
+ List of missing required secrets.
61
+ """
62
+ # no secrets required for DuckDuckGo search tool
63
+ return []
64
+
65
+ def validate_kwargs(self, kwargs: dict[str, str]) -> list[str]:
66
+ """Validate keyword arguments and return list of missing required ones.
67
+
68
+ Parameters
69
+ ----------
70
+ kwargs : dict[str, str]
71
+ Dictionary of keyword arguments.
72
+
73
+ Returns
74
+ -------
75
+ list[str]
76
+ List of missing required keyword arguments.
77
+ """
78
+ # no keyword arguments required for DuckDuckGo search tool
79
+ return []
80
+
81
+ def get_content(
82
+ self,
83
+ secrets: dict[str, str],
84
+ ) -> str:
85
+ """Get content for the tool.
86
+
87
+ Parameters
88
+ ----------
89
+ secrets : dict[str, str]
90
+ Dictionary of secrets/environment variables.
91
+
92
+ Returns
93
+ -------
94
+ str
95
+ The content for the tool.
96
+ """
97
+ content = f'''
98
+ def {self.name}(query: str, num_results: int = 5) -> list[dict[str, Any]]:
99
+ """Perform a DuckDuckGo search and return formatted results.
100
+
101
+ Args:
102
+ query: The search query string.
103
+ num_results: The maximum number of results to return. Defaults to 5.
104
+
105
+ Returns:
106
+ A list of dictionaries of the search results.
107
+ """
108
+ tool = DuckDuckGoSearchTool()
109
+ return tool(query=query, num_results=num_results)
110
+ '''
111
+ return content
112
+
113
+
114
+ DuckDuckGoSearchTool = DuckDuckGoSearchToolImpl()
115
+ DuckDuckGoSearchConfig = PredefinedToolConfig(
116
+ name=DuckDuckGoSearchTool.name,
117
+ description=DuckDuckGoSearchTool.description,
118
+ required_secrets=DuckDuckGoSearchTool.required_secrets,
119
+ required_kwargs=DuckDuckGoSearchTool.required_kwargs,
120
+ requirements=DuckDuckGoSearchTool.requirements,
121
+ tags=DuckDuckGoSearchTool.tags,
122
+ implementation=DuckDuckGoSearchTool,
123
+ )
@@ -142,15 +142,37 @@ class GoogleSearchToolImpl(PredefinedTool):
142
142
  google_search_engine_id = self.google_search_engine_id
143
143
  if not google_search_engine_id:
144
144
  google_search_engine_id = secrets.get("GOOGLE_SEARCH_ENGINE_ID", "")
145
- content = f"""
146
- google_search_api_key = os.environ.get("GOOGLE_SEARCH_API_KEY", "")
147
- if not google_search_api_key:
148
- raise ValueError("GOOGLE_SEARCH_API_KEY is required for Google search tool.")
149
- {self.name} = GoogleSearchTool(
150
- search_api_key=google_search_api_key,
151
- search_engine_id="{google_search_engine_id}",
152
- )
153
- """
145
+ content = f'''
146
+ def {self.name}(
147
+ query: str,
148
+ search_api_key: str,
149
+ search_engine_id: str,
150
+ num_results: int = 10,
151
+ ) -> list[dict[str, Any]]:
152
+ """Perform a Google search and return formatted results.
153
+
154
+ Args:
155
+ query: The search query string.
156
+ search_api_key: The API key for the Google Search API.
157
+ search_engine_id: The search engine ID for the Google Search API.
158
+ num_results: The maximum number of results to return. Defaults to 10.
159
+ Returns:
160
+ A list of dictionaries of the search results.
161
+ """
162
+ google_search_api_key = os.environ.get("GOOGLE_SEARCH_API_KEY", "")
163
+ if not google_search_api_key:
164
+ raise ValueError("GOOGLE_SEARCH_API_KEY is required for Google search tool.")
165
+ {self.name}_tool = GoogleSearchTool(
166
+ search_api_key=google_search_api_key,
167
+ search_engine_id="{google_search_engine_id}",
168
+ )
169
+ return {self.name}_tool(
170
+ query=query,
171
+ search_api_key=search_api_key,
172
+ search_engine_id=search_engine_id,
173
+ num_results=num_results
174
+ )
175
+ '''
154
176
  return content
155
177
 
156
178
 
@@ -0,0 +1,161 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ # pylint: disable=line-too-long
4
+ # flake8: noqa: E501
5
+ """Predefined Perplexity AI search tool for Waldiez."""
6
+
7
+ import os
8
+ from typing import Any
9
+
10
+ from ._config import PredefinedToolConfig
11
+ from .protocol import PredefinedTool
12
+
13
+
14
+ class PerplexitySearchToolImpl(PredefinedTool):
15
+ """Perplexity AI search tool for Waldiez."""
16
+
17
+ required_secrets: list[str] = ["PERPLEXITY_API_KEY"]
18
+ required_kwargs: dict[str, type] = {}
19
+ kwarg_types: dict[str, type] = {
20
+ "model": str,
21
+ "max_tokens": int,
22
+ "search_domain_filters": list,
23
+ }
24
+
25
+ @property
26
+ def name(self) -> str:
27
+ """Tool name."""
28
+ return "perplexity_search"
29
+
30
+ @property
31
+ def description(self) -> str:
32
+ """Tool description."""
33
+ return "Search Perplexity AI for a given query."
34
+
35
+ @property
36
+ def kwargs(self) -> dict[str, Any]:
37
+ """Keyword arguments for the tool, used for initialization."""
38
+ return {
39
+ "model": "sonar",
40
+ "max_tokens": 1000,
41
+ "search_domain_filter": None,
42
+ }
43
+
44
+ @property
45
+ def requirements(self) -> list[str]:
46
+ """Python requirements for the tool."""
47
+ return []
48
+
49
+ @property
50
+ def tags(self) -> list[str]:
51
+ """Tags for the tool, used for categorization."""
52
+ return ["perplexity", "search", "web"]
53
+
54
+ @property
55
+ def tool_imports(self) -> list[str]:
56
+ """Imports required for the tool implementation."""
57
+ return [
58
+ "from autogen.tools.experimental import PerplexitySearchTool",
59
+ "from autogen.tools.experimental.perplexity.perplexity_search import SearchResponse",
60
+ ]
61
+
62
+ def validate_secrets(self, secrets: dict[str, str]) -> list[str]:
63
+ """Validate secrets and return list of missing required ones.
64
+
65
+ Parameters
66
+ ----------
67
+ secrets : dict[str, str]
68
+ Dictionary of secrets/environment variables.
69
+
70
+ Returns
71
+ -------
72
+ list[str]
73
+ List of missing required secrets.
74
+ """
75
+ missing_secrets: list[str] = []
76
+ if not secrets.get("PERPLEXITY_API_KEY"):
77
+ missing_secrets.append("PERPLEXITY_API_KEY")
78
+ return missing_secrets
79
+
80
+ def validate_kwargs(self, kwargs: dict[str, Any]) -> list[str]:
81
+ """Validate keyword arguments and return list of missing required ones.
82
+
83
+ Parameters
84
+ ----------
85
+ kwargs : dict[str, Any]
86
+ Dictionary of keyword arguments.
87
+
88
+ Returns
89
+ -------
90
+ list[str]
91
+ List of missing required keyword arguments.
92
+ """
93
+ for key, value in self.kwargs.items():
94
+ if key in kwargs: # pragma: no branch
95
+ type_of = self.kwarg_types.get(key, str)
96
+ try:
97
+ casted = type_of(value)
98
+ if key in self.kwargs: # pragma: no branch
99
+ self.kwargs[key] = casted
100
+ except Exception: # pylint: disable=broad-except
101
+ pass
102
+ return []
103
+
104
+ def get_content(
105
+ self,
106
+ secrets: dict[str, str],
107
+ ) -> str:
108
+ """Get content for the tool.
109
+
110
+ Parameters
111
+ ----------
112
+ secrets : dict[str, str]
113
+ Dictionary of secrets/environment variables.
114
+
115
+ Returns
116
+ -------
117
+ str
118
+ Content retrieved by the tool.
119
+ """
120
+ os.environ["PERPLEXITY_API_KEY"] = secrets.get("PERPLEXITY_API_KEY", "")
121
+ content = f'''
122
+ def {self.name}(
123
+ query: str,
124
+ model: str = "{self.kwargs["model"]}",
125
+ max_tokens: int = {self.kwargs["max_tokens"]},
126
+ search_domain_filter: Optional[list[str]] = {self.kwargs["search_domain_filter"]},
127
+ ) -> "SearchResponse":
128
+ """Perform a Perplexity AI search and return formatted results.
129
+
130
+ Args:
131
+ query: The search query string.
132
+ model: The model to use for the search. Defaults to "{self.kwargs["model"]}".
133
+ max_tokens: The maximum number of tokens to return. Defaults to {self.kwargs["max_tokens"]}.
134
+ search_domain_filter: List of domain filters for the search. Defaults to {self.kwargs["search_domain_filter"]}.
135
+ Returns:
136
+ A list of dictionaries of the search results.
137
+ """
138
+ perplexity_api_key = os.environ.get("PERPLEXITY_API_KEY", "")
139
+ if not perplexity_api_key:
140
+ raise ValueError("PERPLEXITY_API_KEY is required for Perplexity search tool.")
141
+ perplexity_search_tool = PerplexitySearchTool(
142
+ api_key=perplexity_api_key,
143
+ model=model,
144
+ max_tokens=max_tokens,
145
+ search_domain_filter=search_domain_filter,
146
+ )
147
+ return perplexity_search_tool(query=query)
148
+ '''
149
+ return content
150
+
151
+
152
+ PerplexitySearchTool = PerplexitySearchToolImpl()
153
+ PerplexitySearchConfig = PredefinedToolConfig(
154
+ name=PerplexitySearchTool.name,
155
+ description=PerplexitySearchTool.description,
156
+ required_secrets=PerplexitySearchTool.required_secrets,
157
+ required_kwargs=PerplexitySearchTool.required_kwargs,
158
+ requirements=PerplexitySearchTool.requirements,
159
+ tags=PerplexitySearchTool.tags,
160
+ implementation=PerplexitySearchTool,
161
+ )
@@ -0,0 +1,152 @@
1
+ # SPDX-License-Identifier: Apache-2.0.
2
+ # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
+ # pylint: disable=line-too-long
4
+ # flake8: noqa: E501
5
+ """Predefined SearxNG search tool for Waldiez."""
6
+
7
+ from typing import Any
8
+
9
+ from ._config import PredefinedToolConfig
10
+ from .protocol import PredefinedTool
11
+
12
+
13
+ class SearxNGSearchToolImpl(PredefinedTool):
14
+ """SearxNG search tool for Waldiez."""
15
+
16
+ required_secrets: list[str] = []
17
+ required_kwargs: dict[str, type] = {}
18
+ kwarg_types: dict[str, type] = {
19
+ "base_url": str,
20
+ }
21
+
22
+ @property
23
+ def name(self) -> str:
24
+ """Tool name."""
25
+ return "searxng_search"
26
+
27
+ @property
28
+ def description(self) -> str:
29
+ """Tool description."""
30
+ return "Search SearxNG for a given query."
31
+
32
+ @property
33
+ def kwargs(self) -> dict[str, Any]:
34
+ """Keyword arguments for the tool, used for initialization."""
35
+ return {
36
+ "base_url": "https://searxng.site/search",
37
+ }
38
+
39
+ @property
40
+ def requirements(self) -> list[str]:
41
+ """Python requirements for the tool."""
42
+ return []
43
+
44
+ @property
45
+ def tags(self) -> list[str]:
46
+ """Tags for the tool, used for categorization."""
47
+ return ["searxng", "search", "web"]
48
+
49
+ @property
50
+ def tool_imports(self) -> list[str]:
51
+ """Imports required for the tool implementation."""
52
+ return [
53
+ "from autogen.tools.experimental import SearxngSearchTool",
54
+ ]
55
+
56
+ def validate_secrets(self, secrets: dict[str, str]) -> list[str]:
57
+ """Validate secrets and return list of missing required ones.
58
+
59
+ Parameters
60
+ ----------
61
+ secrets : dict[str, str]
62
+ Dictionary of secrets to validate.
63
+
64
+ Returns
65
+ -------
66
+ list[str]
67
+ List of missing required secrets.
68
+ """
69
+ return [] # No secrets required for this tool.
70
+
71
+ def validate_kwargs(self, kwargs: dict[str, Any]) -> list[str]:
72
+ """Validate keyword arguments and return list of missing required ones.
73
+
74
+ Parameters
75
+ ----------
76
+ kwargs : dict[str, Any]
77
+ Dictionary of keyword arguments to validate.
78
+
79
+ Returns
80
+ -------
81
+ list[str]
82
+ List of missing required keyword arguments.
83
+ """
84
+ for key, value in self.kwargs.items():
85
+ if key in kwargs: # pragma: no branch
86
+ type_of = self.kwarg_types.get(key, str)
87
+ try:
88
+ casted = type_of(value)
89
+ if key in self.kwargs: # pragma: no branch
90
+ self.kwargs[key] = casted
91
+ except Exception: # pylint: disable=broad-except
92
+ pass
93
+ return []
94
+
95
+ def get_content(
96
+ self,
97
+ secrets: dict[str, str],
98
+ ) -> str:
99
+ """Get content for the tool.
100
+
101
+ Parameters
102
+ ----------
103
+ secrets : dict[str, str]
104
+ Dictionary of secrets/environment variables.
105
+
106
+ Returns
107
+ -------
108
+ str
109
+ Content retrieved by the tool.
110
+ """
111
+ content = f'''
112
+ def {self.name}(
113
+ query: str,
114
+ max_results: int = 5,
115
+ categories: list[str] | None = None,
116
+ language: str | None = None,
117
+ ) -> list[dict[str, Any]]:
118
+ """Perform a SearxNG search and return formatted results.
119
+
120
+ Args:
121
+ query: The search query string.
122
+ max_results: The maximum number of results to return. Defaults to 5.
123
+ categories: List of categories to search in.
124
+ language: Language code (e.g., 'en-US').
125
+ base_url: SearxNG instance URL.
126
+
127
+ Returns:
128
+ A list of dictionaries, each containing 'title', 'link', and 'snippet' of a search result.
129
+ """
130
+ tool = SearxngSearchTool(
131
+ base_url="{self.kwargs["base_url"]}",
132
+ )
133
+ return tool(
134
+ query=query,
135
+ max_results=max_results,
136
+ categories=categories,
137
+ language=language,
138
+ )
139
+ '''
140
+ return content
141
+
142
+
143
+ SearxNGSearchTool = SearxNGSearchToolImpl()
144
+ SearxNGSearchConfig = PredefinedToolConfig(
145
+ name=SearxNGSearchTool.name,
146
+ description=SearxNGSearchTool.description,
147
+ tags=SearxNGSearchTool.tags,
148
+ requirements=SearxNGSearchTool.requirements,
149
+ required_kwargs=SearxNGSearchTool.required_kwargs,
150
+ required_secrets=SearxNGSearchTool.required_secrets,
151
+ implementation=SearxNGSearchTool,
152
+ )