waldiez 0.5.8__py3-none-any.whl → 0.5.10__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 (88) hide show
  1. waldiez/_version.py +1 -1
  2. waldiez/cli.py +112 -24
  3. waldiez/exporting/agent/exporter.py +3 -0
  4. waldiez/exporting/agent/extras/captain_agent_extras.py +44 -7
  5. waldiez/exporting/agent/extras/handoffs/condition.py +3 -1
  6. waldiez/exporting/chats/utils/common.py +25 -23
  7. waldiez/exporting/core/__init__.py +0 -2
  8. waldiez/exporting/core/context.py +13 -13
  9. waldiez/exporting/core/protocols.py +0 -141
  10. waldiez/exporting/core/result.py +5 -5
  11. waldiez/exporting/flow/merger.py +2 -2
  12. waldiez/exporting/flow/orchestrator.py +1 -0
  13. waldiez/exporting/flow/utils/common.py +2 -2
  14. waldiez/exporting/flow/utils/importing.py +1 -0
  15. waldiez/exporting/flow/utils/logging.py +6 -7
  16. waldiez/exporting/tools/exporter.py +5 -0
  17. waldiez/exporting/tools/factory.py +4 -0
  18. waldiez/exporting/tools/processor.py +5 -1
  19. waldiez/io/_ws.py +13 -5
  20. waldiez/io/models/content/image.py +1 -0
  21. waldiez/io/models/user_input.py +4 -4
  22. waldiez/io/models/user_response.py +1 -0
  23. waldiez/io/mqtt.py +1 -1
  24. waldiez/io/structured.py +17 -17
  25. waldiez/io/utils.py +1 -1
  26. waldiez/io/ws.py +9 -11
  27. waldiez/logger.py +180 -63
  28. waldiez/models/agents/agent/update_system_message.py +0 -2
  29. waldiez/models/agents/doc_agent/doc_agent.py +8 -1
  30. waldiez/models/common/dict_utils.py +169 -40
  31. waldiez/models/flow/flow.py +6 -6
  32. waldiez/models/flow/info.py +5 -1
  33. waldiez/models/model/_llm.py +28 -14
  34. waldiez/models/model/model.py +4 -1
  35. waldiez/models/model/model_data.py +18 -5
  36. waldiez/models/tool/predefined/_config.py +5 -1
  37. waldiez/models/tool/predefined/_duckduckgo.py +4 -0
  38. waldiez/models/tool/predefined/_email.py +474 -0
  39. waldiez/models/tool/predefined/_google.py +8 -6
  40. waldiez/models/tool/predefined/_perplexity.py +3 -0
  41. waldiez/models/tool/predefined/_searxng.py +3 -0
  42. waldiez/models/tool/predefined/_tavily.py +4 -1
  43. waldiez/models/tool/predefined/_wikipedia.py +4 -1
  44. waldiez/models/tool/predefined/_youtube.py +4 -1
  45. waldiez/models/tool/predefined/protocol.py +3 -0
  46. waldiez/models/tool/tool.py +22 -4
  47. waldiez/models/waldiez.py +12 -0
  48. waldiez/runner.py +37 -54
  49. waldiez/running/__init__.py +6 -0
  50. waldiez/running/base_runner.py +310 -353
  51. waldiez/running/environment.py +1 -0
  52. waldiez/running/exceptions.py +9 -0
  53. waldiez/running/post_run.py +4 -4
  54. waldiez/running/pre_run.py +51 -40
  55. waldiez/running/protocol.py +21 -101
  56. waldiez/running/run_results.py +1 -1
  57. waldiez/running/standard_runner.py +84 -277
  58. waldiez/running/step_by_step/__init__.py +46 -0
  59. waldiez/running/step_by_step/breakpoints_mixin.py +188 -0
  60. waldiez/running/step_by_step/step_by_step_models.py +224 -0
  61. waldiez/running/step_by_step/step_by_step_runner.py +745 -0
  62. waldiez/running/subprocess_runner/__base__.py +282 -0
  63. waldiez/running/subprocess_runner/__init__.py +16 -0
  64. waldiez/running/subprocess_runner/_async_runner.py +362 -0
  65. waldiez/running/subprocess_runner/_sync_runner.py +455 -0
  66. waldiez/running/subprocess_runner/runner.py +561 -0
  67. waldiez/running/timeline_processor.py +1 -1
  68. waldiez/running/utils.py +376 -1
  69. waldiez/utils/version.py +2 -6
  70. waldiez/ws/__init__.py +70 -0
  71. waldiez/ws/__main__.py +15 -0
  72. waldiez/ws/_file_handler.py +201 -0
  73. waldiez/ws/cli.py +211 -0
  74. waldiez/ws/client_manager.py +835 -0
  75. waldiez/ws/errors.py +416 -0
  76. waldiez/ws/models.py +971 -0
  77. waldiez/ws/reloader.py +342 -0
  78. waldiez/ws/server.py +469 -0
  79. waldiez/ws/session_manager.py +393 -0
  80. waldiez/ws/session_stats.py +83 -0
  81. waldiez/ws/utils.py +385 -0
  82. {waldiez-0.5.8.dist-info → waldiez-0.5.10.dist-info}/METADATA +74 -74
  83. {waldiez-0.5.8.dist-info → waldiez-0.5.10.dist-info}/RECORD +87 -65
  84. waldiez/running/patch_io_stream.py +0 -210
  85. {waldiez-0.5.8.dist-info → waldiez-0.5.10.dist-info}/WHEEL +0 -0
  86. {waldiez-0.5.8.dist-info → waldiez-0.5.10.dist-info}/entry_points.txt +0 -0
  87. {waldiez-0.5.8.dist-info → waldiez-0.5.10.dist-info}/licenses/LICENSE +0 -0
  88. {waldiez-0.5.8.dist-info → waldiez-0.5.10.dist-info}/licenses/NOTICE.md +0 -0
@@ -0,0 +1,474 @@
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 send email tool."""
6
+
7
+ from copy import deepcopy
8
+ from typing import Any
9
+
10
+ from ._config import PredefinedToolConfig
11
+ from .protocol import PredefinedTool
12
+
13
+
14
+ class SendEmailToolImpl(PredefinedTool):
15
+ """Predefined tool for sending emails."""
16
+
17
+ required_secrets: list[str] = [
18
+ "SMTP_HOST",
19
+ "SMTP_PORT",
20
+ "SMTP_USERNAME",
21
+ "SMTP_PASSWORD",
22
+ ]
23
+ required_kwargs: dict[str, type] = {}
24
+
25
+ DEFAULT_KWARGS: dict[str, Any] = {
26
+ "is_async": False, # controls whether the exported tool function is async or sync
27
+ "subject": "",
28
+ "body_text": "",
29
+ "body_html": "",
30
+ "to": [],
31
+ "attachments": [],
32
+ "cc": [],
33
+ "bcc": [],
34
+ "reply_to": [],
35
+ "sender": "",
36
+ "use_ssl": False,
37
+ "use_starttls": True,
38
+ "timeout": 30.0,
39
+ }
40
+
41
+ kwarg_types: dict[str, type] = {
42
+ "is_async": bool,
43
+ "subject": str,
44
+ "body_text": str,
45
+ "body_html": str,
46
+ "to": list,
47
+ "attachments": list,
48
+ "cc": list,
49
+ "bcc": list,
50
+ "reply_to": list,
51
+ "sender": str,
52
+ "use_ssl": bool,
53
+ "use_starttls": bool,
54
+ "timeout": float,
55
+ }
56
+
57
+ def __init__(self) -> None:
58
+ self._kwargs: dict[str, Any] = deepcopy(self.DEFAULT_KWARGS)
59
+
60
+ @property
61
+ def name(self) -> str:
62
+ return "send_email"
63
+
64
+ @property
65
+ def description(self) -> str:
66
+ return "A tool for sending emails with support for attachments, HTML/text content, and various SMTP configurations."
67
+
68
+ @property
69
+ def kwargs(self) -> dict[str, Any]:
70
+ """
71
+ Get the keyword arguments for the tool.
72
+
73
+ Returns
74
+ -------
75
+ dict[str, Any]
76
+ The keyword arguments for the tool.
77
+ """
78
+ return dict(self._kwargs)
79
+
80
+ @property
81
+ def tags(self) -> list[str]:
82
+ return ["email", "communication", "smtp"]
83
+
84
+ @property
85
+ def requirements(self) -> list[str]:
86
+ return []
87
+
88
+ @property
89
+ def tool_imports(self) -> list[str]:
90
+ return [
91
+ "import asyncio",
92
+ "import smtplib",
93
+ "import ssl",
94
+ "from email.message import EmailMessage",
95
+ "from email.utils import formatdate, make_msgid",
96
+ "from pathlib import Path",
97
+ ]
98
+
99
+ def validate_secrets(self, secrets: dict[str, str]) -> list[str]:
100
+ """
101
+ Validate the provided secrets against the tool's requirements.
102
+
103
+ Parameters
104
+ ----------
105
+ secrets: dict[str, str]
106
+ The secrets to validate.
107
+
108
+ Returns
109
+ -------
110
+ list[str]
111
+ A list of validation error messages, if any.
112
+ """
113
+ problems: list[str] = []
114
+ for key in self.required_secrets:
115
+ val = secrets.get(key)
116
+ if val is None or str(val).strip() == "":
117
+ problems.append(key)
118
+ # pylint: disable=broad-exception-caught
119
+ try:
120
+ port = int(secrets.get("SMTP_PORT", ""))
121
+ if not 1 <= port <= 65535:
122
+ problems.append("SMTP_PORT (invalid port range)")
123
+ except Exception:
124
+ problems.append("SMTP_PORT (not a valid integer)")
125
+ return problems
126
+
127
+ def validate_kwargs(self, kwargs: dict[str, Any]) -> list[str]:
128
+ """
129
+ Validate the provided keyword arguments against the tool's requirements.
130
+
131
+ Parameters
132
+ ----------
133
+ kwargs: dict[str, Any]
134
+ The keyword arguments to validate.
135
+
136
+ Returns
137
+ -------
138
+ list[str]
139
+ A list of validation error messages, if any.
140
+ """
141
+ updated = dict(self._kwargs)
142
+ for key, value in kwargs.items():
143
+ if key in self.kwarg_types:
144
+ typ = self.kwarg_types[key]
145
+ # pylint: disable=broad-exception-caught
146
+ try:
147
+ if typ is list and isinstance(value, str):
148
+ updated[key] = [
149
+ s.strip() for s in value.split(",") if s.strip()
150
+ ]
151
+ else:
152
+ updated[key] = typ(value)
153
+ except Exception:
154
+ pass
155
+ self._kwargs = updated
156
+ return []
157
+
158
+ def _get_effective_kwargs(
159
+ self,
160
+ runtime_kwargs: dict[str, Any] | None = None,
161
+ ) -> dict[str, Any]:
162
+ """Get effective keyword arguments."""
163
+ effective = dict(self._kwargs)
164
+ if runtime_kwargs:
165
+ # cast only known keys, same rules as validate_kwargs
166
+ for k, v in runtime_kwargs.items():
167
+ if k in self.kwarg_types:
168
+ typ = self.kwarg_types[k]
169
+ # pylint: disable=broad-exception-caught
170
+ try:
171
+ if typ is list and isinstance(v, str):
172
+ effective[k] = [
173
+ s.strip() for s in v.split(",") if s.strip()
174
+ ]
175
+ else:
176
+ effective[k] = typ(v)
177
+ except Exception:
178
+ pass
179
+ return effective
180
+
181
+ def get_content(
182
+ self,
183
+ secrets: dict[str, str],
184
+ runtime_kwargs: dict[str, Any] | None = None,
185
+ ) -> str:
186
+ """
187
+ Generate the email content based on the provided secrets and tool kwargs.
188
+
189
+ Parameters
190
+ ----------
191
+ secrets: dict[str, str]
192
+ The secrets required for SMTP authentication and configuration.
193
+ runtime_kwargs: dict[str, Any] | None, optional
194
+ Runtime keyword arguments to customize the content generation.
195
+
196
+ Returns
197
+ -------
198
+ str
199
+ The generated email content.
200
+ """
201
+ smtp_host = secrets.get("SMTP_HOST", "smtp.gmail.com")
202
+ try:
203
+ smtp_port = int(secrets.get("SMTP_PORT", "587"))
204
+ except (ValueError, TypeError):
205
+ smtp_port = 587
206
+ smtp_user = secrets.get("SMTP_USERNAME", "")
207
+ smtp_pass = secrets.get("SMTP_PASSWORD", "")
208
+
209
+ effective_kwargs = self._get_effective_kwargs(runtime_kwargs)
210
+
211
+ is_async = effective_kwargs.get("is_async", False)
212
+ use_ssl = effective_kwargs.get("use_ssl", False)
213
+ use_starttls = effective_kwargs.get("use_starttls", True)
214
+ timeout = effective_kwargs.get("timeout", 30.0)
215
+
216
+ base = f"""
217
+ def _collect_rcpts(to, cc, bcc):
218
+ rcpts = []
219
+ for part in (to, cc, bcc):
220
+ if not part:
221
+ continue
222
+ if isinstance(part, str):
223
+ rcpts.extend([s.strip() for s in part.split(",") if s.strip()])
224
+ else:
225
+ rcpts.extend(part)
226
+ seen, out = set(), []
227
+ for r in rcpts:
228
+ if r not in seen:
229
+ seen.add(r)
230
+ out.append(r)
231
+ return out
232
+
233
+
234
+ def _split_emails(value) -> list[str]:
235
+ if not value:
236
+ return []
237
+ if isinstance(value, str):
238
+ return [s.strip() for s in value.split(",") if s.strip()]
239
+ return list(value)
240
+
241
+ def _build_message(
242
+ subject: str,
243
+ sender: str,
244
+ recipients: str | list[str],
245
+ body_text: str | None = None,
246
+ body_html: str | None = None,
247
+ attachments: list | None = None,
248
+ cc: list[str] | None = None,
249
+ reply_to: list[str] | None = None,
250
+ ) -> EmailMessage:
251
+ recipients = _split_emails(recipients)
252
+ cc = _split_emails(cc)
253
+ reply_to = _split_emails(reply_to)
254
+ attachments = attachments or []
255
+
256
+ if not (body_text or body_html):
257
+ raise ValueError("Provide at least one of body_text or body_html.")
258
+
259
+ msg = EmailMessage()
260
+ msg["Subject"] = subject
261
+ msg["From"] = sender
262
+ msg["To"] = ", ".join(recipients)
263
+ msg["Date"] = formatdate(localtime=True)
264
+ msg["Message-ID"] = make_msgid()
265
+ if cc:
266
+ msg["Cc"] = ", ".join(cc)
267
+ if reply_to:
268
+ msg["Reply-To"] = ", ".join(reply_to)
269
+
270
+ if body_html and body_text:
271
+ msg.set_content(body_text)
272
+ msg.add_alternative(body_html, subtype="html")
273
+ elif body_html:
274
+ msg.add_alternative(body_html, subtype="html")
275
+ else:
276
+ msg.set_content(body_text or "")
277
+
278
+ for item in attachments:
279
+ if isinstance(item, Path):
280
+ data = item.read_bytes()
281
+ filename = item.name
282
+ mime = "application/octet-stream"
283
+ else:
284
+ filename, data, mime = item
285
+ maintype, _, subtype = mime.partition("/")
286
+ msg.add_attachment(data, maintype=maintype, subtype=subtype, filename=filename)
287
+
288
+ return msg
289
+
290
+
291
+ def _send_email_sync(
292
+ subject: str,
293
+ to: str | list[str],
294
+ body_text: str | None = None,
295
+ body_html: str | None = None,
296
+ attachments: list | None = None,
297
+ cc: list[str] | None = None,
298
+ bcc: list[str] | None = None,
299
+ reply_to: list[str] | None = None,
300
+ sender: str | None = None,
301
+ use_ssl: bool = {use_ssl},
302
+ use_starttls: bool = {use_starttls},
303
+ timeout: float = {timeout},
304
+ ) -> dict:
305
+ smtp_host = "{smtp_host}"
306
+ smtp_port = {smtp_port}
307
+ username = "{smtp_user}"
308
+ password = "{smtp_pass}"
309
+ sender = sender or username
310
+
311
+ context = ssl.create_default_context()
312
+ msg = _build_message(
313
+ subject=subject,
314
+ sender=sender,
315
+ recipients=to,
316
+ body_text=body_text,
317
+ body_html=body_html,
318
+ attachments=attachments,
319
+ cc=cc,
320
+ reply_to=reply_to,
321
+ )
322
+ rcpts = _collect_rcpts(to, cc, bcc)
323
+ if not rcpts:
324
+ raise ValueError("No recipients provided (to/cc/bcc are all empty).")
325
+ if use_ssl:
326
+ with smtplib.SMTP_SSL(smtp_host, smtp_port, context=context, timeout=timeout) as server:
327
+ if username and password:
328
+ server.login(username, password)
329
+ return server.send_message(msg, to_addrs=rcpts)
330
+ else:
331
+ with smtplib.SMTP(smtp_host, smtp_port, timeout=timeout) as server:
332
+ server.ehlo()
333
+ if use_starttls:
334
+ server.starttls(context=context)
335
+ server.ehlo()
336
+ if username and password:
337
+ server.login(username, password)
338
+ return server.send_message(msg, to_addrs=rcpts)
339
+
340
+
341
+ async def _send_email_async(
342
+ subject: str,
343
+ to: str | list[str],
344
+ body_text: str | None = None,
345
+ body_html: str | None = None,
346
+ attachments: list | None = None,
347
+ cc: list[str] | None = None,
348
+ bcc: list[str] | None = None,
349
+ reply_to: list[str] | None = None,
350
+ sender: str | None = None,
351
+ use_ssl: bool = {use_ssl},
352
+ use_starttls: bool = {use_starttls},
353
+ timeout: float = {timeout},
354
+ ) -> dict:
355
+ return await asyncio.to_thread(
356
+ _send_email_sync,
357
+ subject=subject,
358
+ to=to,
359
+ body_text=body_text,
360
+ body_html=body_html,
361
+ attachments=attachments,
362
+ cc=cc,
363
+ bcc=bcc,
364
+ reply_to=reply_to,
365
+ sender=sender,
366
+ use_ssl=use_ssl,
367
+ use_starttls=use_starttls,
368
+ timeout=timeout,
369
+ )
370
+ """
371
+
372
+ # exported callable is chosen by config: async or sync
373
+ if is_async:
374
+ exported = f'''
375
+ async def {self.name}(
376
+ subject: str,
377
+ to: str | list[str],
378
+ body_text: str | None = None,
379
+ body_html: str | None = None,
380
+ attachments: list | None = None,
381
+ cc: list[str] | None = None,
382
+ bcc: list[str] | None = None,
383
+ reply_to: list[str] | None = None,
384
+ sender: str | None = None,
385
+ ) -> dict:
386
+ """Send email asynchronously.
387
+
388
+ At least one recipient must be specified.
389
+ At least one of `body_text` or `body_html` must be provided.
390
+
391
+ Args:
392
+ subject: The email subject.
393
+ to: The recipient email address(es).
394
+ body_text: The plain text body of the email.
395
+ body_html: The HTML body of the email.
396
+ attachments: Any file attachments to include.
397
+ cc: The CC email address(es).
398
+ bcc: The BCC email address(es).
399
+ reply_to: The reply-to email address(es).
400
+ sender: The sender email address.
401
+
402
+ Returns:
403
+ A dictionary containing the result of the email sending operation.
404
+ """
405
+ return await _send_email_async(
406
+ subject=subject,
407
+ to=to,
408
+ body_text=body_text,
409
+ body_html=body_html,
410
+ attachments=attachments,
411
+ cc=cc,
412
+ bcc=bcc,
413
+ reply_to=reply_to,
414
+ sender=sender,
415
+ )
416
+ '''
417
+ else:
418
+ exported = f'''
419
+ def {self.name}(
420
+ subject: str,
421
+ to: str | list[str],
422
+ body_text: str | None = None,
423
+ body_html: str | None = None,
424
+ attachments: list | None = None,
425
+ cc: list[str] | None = None,
426
+ bcc: list[str] | None = None,
427
+ reply_to: list[str] | None = None,
428
+ sender: str | None = None,
429
+ ) -> dict:
430
+ """Send email synchronously.
431
+
432
+ At least one recipient must be specified.
433
+ At least one of `body_text` or `body_html` must be provided.
434
+
435
+ Args:
436
+ subject: The email subject.
437
+ to: The recipient email address(es).
438
+ body_text: The plain text body of the email.
439
+ body_html: The HTML body of the email.
440
+ attachments: Any file attachments to include.
441
+ cc: The CC email address(es).
442
+ bcc: The BCC email address(es).
443
+ reply_to: The reply-to email address(es).
444
+ sender: The sender email address.
445
+
446
+ Returns:
447
+ A dictionary containing the result of the email sending operation.
448
+ """
449
+ return _send_email_sync(
450
+ subject=subject,
451
+ to=to,
452
+ body_text=body_text,
453
+ body_html=body_html,
454
+ attachments=attachments,
455
+ cc=cc,
456
+ bcc=bcc,
457
+ reply_to=reply_to,
458
+ sender=sender,
459
+ )
460
+ '''
461
+
462
+ return base + exported
463
+
464
+
465
+ SendEmailTool = SendEmailToolImpl()
466
+ SendEmailConfig = PredefinedToolConfig(
467
+ name=SendEmailTool.name,
468
+ description=SendEmailTool.description,
469
+ tags=SendEmailTool.tags,
470
+ requirements=SendEmailTool.requirements,
471
+ required_secrets=SendEmailTool.required_secrets,
472
+ required_kwargs=SendEmailTool.required_kwargs,
473
+ implementation=SendEmailTool,
474
+ )
@@ -16,10 +16,9 @@ class GoogleSearchToolImpl(PredefinedTool):
16
16
 
17
17
  required_secrets: list[str] = [
18
18
  "GOOGLE_SEARCH_API_KEY",
19
+ "GOOGLE_SEARCH_ENGINE_ID",
19
20
  ]
20
- required_kwargs: dict[str, type] = {
21
- "google_search_engine_id": str,
22
- }
21
+ required_kwargs: dict[str, type] = {}
23
22
  _kwargs: dict[str, Any] = {}
24
23
 
25
24
  @property
@@ -40,7 +39,7 @@ class GoogleSearchToolImpl(PredefinedTool):
40
39
  @property
41
40
  def requirements(self) -> list[str]:
42
41
  """Python requirements for the tool."""
43
- return ["ag2[google-search,gemini,openai]"]
42
+ return ["ag2[google-search,gemini]"]
44
43
 
45
44
  @property
46
45
  def tags(self) -> list[str]:
@@ -125,6 +124,7 @@ class GoogleSearchToolImpl(PredefinedTool):
125
124
  def get_content(
126
125
  self,
127
126
  secrets: dict[str, str],
127
+ runtime_kwargs: dict[str, Any] | None = None,
128
128
  ) -> str:
129
129
  """Get content for the tool.
130
130
 
@@ -132,6 +132,8 @@ class GoogleSearchToolImpl(PredefinedTool):
132
132
  ----------
133
133
  secrets : dict[str, str]
134
134
  Dictionary of secrets/environment variables.
135
+ runtime_kwargs : dict[str, Any] | None, optional
136
+ Runtime keyword arguments to customize the content generation.
135
137
 
136
138
  Returns
137
139
  -------
@@ -163,8 +165,8 @@ def {self.name}(
163
165
  )
164
166
  return {self.name}_tool(
165
167
  query=query,
166
- search_api_key=search_api_key,
167
- search_engine_id=search_engine_id,
168
+ search_api_key=google_search_api_key,
169
+ search_engine_id=google_search_engine_id,
168
170
  num_results=num_results
169
171
  )
170
172
  '''
@@ -106,6 +106,7 @@ class PerplexitySearchToolImpl(PredefinedTool):
106
106
  def get_content(
107
107
  self,
108
108
  secrets: dict[str, str],
109
+ runtime_kwargs: dict[str, Any] | None = None,
109
110
  ) -> str:
110
111
  """Get content for the tool.
111
112
 
@@ -113,6 +114,8 @@ class PerplexitySearchToolImpl(PredefinedTool):
113
114
  ----------
114
115
  secrets : dict[str, str]
115
116
  Dictionary of secrets/environment variables.
117
+ runtime_kwargs : dict[str, Any] | None, optional
118
+ Runtime keyword arguments to customize the content generation.
116
119
 
117
120
  Returns
118
121
  -------
@@ -98,6 +98,7 @@ class SearxNGSearchToolImpl(PredefinedTool):
98
98
  def get_content(
99
99
  self,
100
100
  secrets: dict[str, str],
101
+ runtime_kwargs: dict[str, Any] | None = None,
101
102
  ) -> str:
102
103
  """Get content for the tool.
103
104
 
@@ -105,6 +106,8 @@ class SearxNGSearchToolImpl(PredefinedTool):
105
106
  ----------
106
107
  secrets : dict[str, str]
107
108
  Dictionary of secrets/environment variables.
109
+ runtime_kwargs : dict[str, Any] | None, optional
110
+ Runtime keyword arguments to customize the content generation.
108
111
 
109
112
  Returns
110
113
  -------
@@ -34,7 +34,7 @@ class TavilySearchToolImpl(PredefinedTool):
34
34
  @property
35
35
  def requirements(self) -> list[str]:
36
36
  """Python requirements for the tool."""
37
- return ["ag2[tavily, openai]"]
37
+ return ["ag2[tavily]"]
38
38
 
39
39
  @property
40
40
  def tags(self) -> list[str]:
@@ -84,6 +84,7 @@ class TavilySearchToolImpl(PredefinedTool):
84
84
  def get_content(
85
85
  self,
86
86
  secrets: dict[str, str],
87
+ runtime_kwargs: dict[str, Any] | None = None,
87
88
  ) -> str:
88
89
  """Get content for the tool.
89
90
 
@@ -91,6 +92,8 @@ class TavilySearchToolImpl(PredefinedTool):
91
92
  ----------
92
93
  secrets : dict[str, str]
93
94
  Dictionary of secrets/environment variables.
95
+ runtime_kwargs : dict[str, Any] | None, optional
96
+ Runtime keyword arguments to customize the content generation.
94
97
 
95
98
  Returns
96
99
  -------
@@ -43,7 +43,7 @@ class WikipediaSearchToolImpl(PredefinedTool):
43
43
  @property
44
44
  def requirements(self) -> list[str]:
45
45
  """Python requirements for the tool."""
46
- return ["ag2[wikipedia, openai]"]
46
+ return ["ag2[wikipedia]"]
47
47
 
48
48
  @property
49
49
  def tags(self) -> list[str]:
@@ -104,6 +104,7 @@ class WikipediaSearchToolImpl(PredefinedTool):
104
104
  def get_content(
105
105
  self,
106
106
  secrets: dict[str, str],
107
+ runtime_kwargs: dict[str, Any] | None = None,
107
108
  ) -> str:
108
109
  """Get the content of the tool.
109
110
 
@@ -111,6 +112,8 @@ class WikipediaSearchToolImpl(PredefinedTool):
111
112
  ----------
112
113
  secrets : dict[str, str]
113
114
  Dictionary of secrets/environment variables.
115
+ runtime_kwargs : dict[str, Any] | None, optional
116
+ Runtime keyword arguments to customize the content generation.
114
117
 
115
118
  Returns
116
119
  -------
@@ -36,7 +36,7 @@ class YouTubeSearchToolImpl(PredefinedTool):
36
36
  @property
37
37
  def requirements(self) -> list[str]:
38
38
  """Python requirements for the tool."""
39
- return ["ag2[google-search, openai]"]
39
+ return ["ag2[google-search]"]
40
40
 
41
41
  @property
42
42
  def tags(self) -> list[str]:
@@ -87,6 +87,7 @@ class YouTubeSearchToolImpl(PredefinedTool):
87
87
  def get_content(
88
88
  self,
89
89
  secrets: dict[str, str],
90
+ runtime_kwargs: dict[str, Any] | None = None,
90
91
  ) -> str:
91
92
  """Get content for the tool.
92
93
 
@@ -94,6 +95,8 @@ class YouTubeSearchToolImpl(PredefinedTool):
94
95
  ----------
95
96
  secrets : dict[str, str]
96
97
  Dictionary of secrets/environment variables.
98
+ runtime_kwargs : dict[str, Any] | None, optional
99
+ Runtime keyword arguments to customize the content generation.
97
100
 
98
101
  Returns
99
102
  -------
@@ -37,6 +37,7 @@ class PredefinedTool(Protocol):
37
37
  def get_content(
38
38
  self,
39
39
  secrets: dict[str, str],
40
+ runtime_kwargs: dict[str, Any] | None = None,
40
41
  ) -> str:
41
42
  """Get the content of the tool.
42
43
 
@@ -44,6 +45,8 @@ class PredefinedTool(Protocol):
44
45
  ----------
45
46
  secrets : dict[str, str]
46
47
  Dictionary of secrets/environment variables.
48
+ runtime_kwargs : dict[str, Any] | None, optional
49
+ Runtime keyword arguments to customize the content generation.
47
50
 
48
51
  Returns
49
52
  -------