autobyteus 1.0.5__py3-none-any.whl → 1.1.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.
Files changed (256) hide show
  1. autobyteus/agent/agent.py +97 -222
  2. autobyteus/agent/bootstrap_steps/__init__.py +19 -0
  3. autobyteus/agent/bootstrap_steps/agent_bootstrapper.py +88 -0
  4. autobyteus/agent/bootstrap_steps/agent_runtime_queue_initialization_step.py +57 -0
  5. autobyteus/agent/bootstrap_steps/base_bootstrap_step.py +38 -0
  6. autobyteus/agent/bootstrap_steps/system_prompt_processing_step.py +93 -0
  7. autobyteus/agent/bootstrap_steps/workspace_context_initialization_step.py +47 -0
  8. autobyteus/agent/context/__init__.py +18 -0
  9. autobyteus/agent/context/agent_config.py +80 -0
  10. autobyteus/agent/context/agent_context.py +132 -0
  11. autobyteus/agent/context/agent_phase_manager.py +164 -0
  12. autobyteus/agent/context/agent_runtime_state.py +89 -0
  13. autobyteus/agent/context/phases.py +47 -0
  14. autobyteus/agent/events/__init__.py +63 -0
  15. autobyteus/agent/events/agent_events.py +147 -0
  16. autobyteus/agent/events/agent_input_event_queue_manager.py +174 -0
  17. autobyteus/agent/events/notifiers.py +104 -0
  18. autobyteus/agent/events/worker_event_dispatcher.py +118 -0
  19. autobyteus/agent/factory/__init__.py +9 -0
  20. autobyteus/agent/factory/agent_factory.py +126 -79
  21. autobyteus/agent/group/agent_group.py +155 -0
  22. autobyteus/agent/group/agent_group_context.py +81 -0
  23. autobyteus/agent/handlers/__init__.py +36 -0
  24. autobyteus/agent/handlers/approved_tool_invocation_event_handler.py +134 -0
  25. autobyteus/agent/handlers/base_event_handler.py +36 -0
  26. autobyteus/agent/handlers/event_handler_registry.py +76 -0
  27. autobyteus/agent/handlers/generic_event_handler.py +46 -0
  28. autobyteus/agent/handlers/inter_agent_message_event_handler.py +76 -0
  29. autobyteus/agent/handlers/lifecycle_event_logger.py +64 -0
  30. autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +136 -0
  31. autobyteus/agent/handlers/llm_user_message_ready_event_handler.py +140 -0
  32. autobyteus/agent/handlers/tool_execution_approval_event_handler.py +85 -0
  33. autobyteus/agent/handlers/tool_invocation_request_event_handler.py +186 -0
  34. autobyteus/agent/handlers/tool_result_event_handler.py +96 -0
  35. autobyteus/agent/handlers/user_input_message_event_handler.py +77 -0
  36. autobyteus/agent/hooks/__init__.py +9 -0
  37. autobyteus/agent/hooks/base_phase_hook.py +52 -0
  38. autobyteus/agent/input_processor/__init__.py +18 -0
  39. autobyteus/agent/input_processor/base_user_input_processor.py +51 -0
  40. autobyteus/agent/input_processor/content_prefixing_input_processor.py +41 -0
  41. autobyteus/agent/input_processor/metadata_appending_input_processor.py +34 -0
  42. autobyteus/agent/input_processor/passthrough_input_processor.py +32 -0
  43. autobyteus/agent/input_processor/processor_definition.py +42 -0
  44. autobyteus/agent/input_processor/processor_meta.py +46 -0
  45. autobyteus/agent/input_processor/processor_registry.py +98 -0
  46. autobyteus/agent/llm_response_processor/__init__.py +16 -0
  47. autobyteus/agent/llm_response_processor/base_processor.py +50 -0
  48. autobyteus/agent/llm_response_processor/processor_definition.py +36 -0
  49. autobyteus/agent/llm_response_processor/processor_meta.py +37 -0
  50. autobyteus/agent/llm_response_processor/processor_registry.py +94 -0
  51. autobyteus/agent/llm_response_processor/provider_aware_tool_usage_processor.py +53 -0
  52. autobyteus/agent/message/__init__.py +20 -0
  53. autobyteus/agent/message/agent_input_user_message.py +96 -0
  54. autobyteus/agent/message/context_file.py +82 -0
  55. autobyteus/agent/message/context_file_type.py +64 -0
  56. autobyteus/agent/message/{message.py → inter_agent_message.py} +12 -12
  57. autobyteus/agent/message/{message_types.py → inter_agent_message_type.py} +8 -6
  58. autobyteus/agent/message/send_message_to.py +142 -36
  59. autobyteus/agent/remote_agent.py +240 -5
  60. autobyteus/agent/runtime/__init__.py +15 -0
  61. autobyteus/agent/runtime/agent_runtime.py +139 -0
  62. autobyteus/agent/runtime/agent_thread_pool_manager.py +88 -0
  63. autobyteus/agent/runtime/agent_worker.py +200 -0
  64. autobyteus/agent/streaming/__init__.py +15 -0
  65. autobyteus/agent/streaming/agent_event_stream.py +120 -0
  66. autobyteus/agent/streaming/queue_streamer.py +58 -0
  67. autobyteus/agent/streaming/stream_event_payloads.py +156 -0
  68. autobyteus/agent/streaming/stream_events.py +123 -0
  69. autobyteus/agent/system_prompt_processor/__init__.py +14 -0
  70. autobyteus/agent/system_prompt_processor/base_processor.py +45 -0
  71. autobyteus/agent/system_prompt_processor/processor_definition.py +40 -0
  72. autobyteus/agent/system_prompt_processor/processor_meta.py +47 -0
  73. autobyteus/agent/system_prompt_processor/processor_registry.py +119 -0
  74. autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +65 -0
  75. autobyteus/agent/tool_invocation.py +28 -5
  76. autobyteus/agent/utils/__init__.py +9 -0
  77. autobyteus/agent/utils/wait_for_idle.py +59 -0
  78. autobyteus/agent/workflow/__init__.py +11 -0
  79. autobyteus/agent/workflow/agentic_workflow.py +89 -0
  80. autobyteus/agent/workflow/base_agentic_workflow.py +98 -0
  81. autobyteus/agent/workspace/__init__.py +9 -0
  82. autobyteus/agent/workspace/base_workspace.py +55 -0
  83. autobyteus/cli/__init__.py +10 -0
  84. autobyteus/cli/agent_cli.py +299 -0
  85. autobyteus/events/event_emitter.py +33 -56
  86. autobyteus/events/event_manager.py +133 -66
  87. autobyteus/events/event_types.py +41 -14
  88. autobyteus/llm/api/autobyteus_llm.py +13 -15
  89. autobyteus/llm/api/bedrock_llm.py +9 -3
  90. autobyteus/llm/api/claude_llm.py +10 -5
  91. autobyteus/llm/api/deepseek_llm.py +53 -91
  92. autobyteus/llm/api/gemini_llm.py +10 -4
  93. autobyteus/llm/api/grok_llm.py +53 -77
  94. autobyteus/llm/api/groq_llm.py +10 -5
  95. autobyteus/llm/api/mistral_llm.py +10 -5
  96. autobyteus/llm/api/nvidia_llm.py +9 -4
  97. autobyteus/llm/api/ollama_llm.py +56 -48
  98. autobyteus/llm/api/openai_llm.py +20 -14
  99. autobyteus/llm/base_llm.py +95 -34
  100. autobyteus/llm/extensions/base_extension.py +3 -4
  101. autobyteus/llm/extensions/token_usage_tracking_extension.py +2 -3
  102. autobyteus/llm/llm_factory.py +12 -13
  103. autobyteus/llm/models.py +87 -8
  104. autobyteus/llm/user_message.py +73 -0
  105. autobyteus/llm/utils/llm_config.py +124 -27
  106. autobyteus/llm/utils/response_types.py +3 -2
  107. autobyteus/llm/utils/token_usage.py +7 -4
  108. autobyteus/rpc/__init__.py +73 -0
  109. autobyteus/rpc/client/__init__.py +17 -0
  110. autobyteus/rpc/client/abstract_client_connection.py +124 -0
  111. autobyteus/rpc/client/client_connection_manager.py +153 -0
  112. autobyteus/rpc/client/sse_client_connection.py +306 -0
  113. autobyteus/rpc/client/stdio_client_connection.py +280 -0
  114. autobyteus/rpc/config/__init__.py +13 -0
  115. autobyteus/rpc/config/agent_server_config.py +153 -0
  116. autobyteus/rpc/config/agent_server_registry.py +152 -0
  117. autobyteus/rpc/hosting.py +244 -0
  118. autobyteus/rpc/protocol.py +244 -0
  119. autobyteus/rpc/server/__init__.py +20 -0
  120. autobyteus/rpc/server/agent_server_endpoint.py +181 -0
  121. autobyteus/rpc/server/base_method_handler.py +40 -0
  122. autobyteus/rpc/server/method_handlers.py +259 -0
  123. autobyteus/rpc/server/sse_server_handler.py +182 -0
  124. autobyteus/rpc/server/stdio_server_handler.py +151 -0
  125. autobyteus/rpc/server_main.py +198 -0
  126. autobyteus/rpc/transport_type.py +13 -0
  127. autobyteus/tools/__init__.py +75 -0
  128. autobyteus/tools/ask_user_input.py +34 -77
  129. autobyteus/tools/base_tool.py +66 -37
  130. autobyteus/tools/bash/__init__.py +2 -0
  131. autobyteus/tools/bash/bash_executor.py +42 -79
  132. autobyteus/tools/browser/__init__.py +2 -0
  133. autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +50 -42
  134. autobyteus/tools/browser/session_aware/browser_session_aware_tool.py +7 -4
  135. autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +117 -125
  136. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +75 -22
  137. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +94 -28
  138. autobyteus/tools/browser/session_aware/factory/browser_session_aware_web_element_trigger_factory.py +10 -2
  139. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_reader_factory.py +18 -2
  140. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_screenshot_taker_factory.py +10 -2
  141. autobyteus/tools/browser/session_aware/shared_browser_session_manager.py +4 -3
  142. autobyteus/tools/browser/standalone/__init__.py +7 -0
  143. autobyteus/tools/browser/standalone/factory/google_search_factory.py +17 -2
  144. autobyteus/tools/browser/standalone/factory/webpage_reader_factory.py +17 -2
  145. autobyteus/tools/browser/standalone/factory/webpage_screenshot_taker_factory.py +10 -2
  146. autobyteus/tools/browser/standalone/google_search_ui.py +104 -67
  147. autobyteus/tools/browser/standalone/navigate_to.py +52 -28
  148. autobyteus/tools/browser/standalone/web_page_pdf_generator.py +94 -0
  149. autobyteus/tools/browser/standalone/webpage_image_downloader.py +146 -61
  150. autobyteus/tools/browser/standalone/webpage_reader.py +80 -61
  151. autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +91 -45
  152. autobyteus/tools/factory/__init__.py +9 -0
  153. autobyteus/tools/factory/tool_factory.py +25 -4
  154. autobyteus/tools/file/file_reader.py +22 -51
  155. autobyteus/tools/file/file_writer.py +25 -56
  156. autobyteus/tools/functional_tool.py +234 -0
  157. autobyteus/tools/image_downloader.py +49 -71
  158. autobyteus/tools/mcp/__init__.py +47 -0
  159. autobyteus/tools/mcp/call_handlers/__init__.py +18 -0
  160. autobyteus/tools/mcp/call_handlers/base_handler.py +40 -0
  161. autobyteus/tools/mcp/call_handlers/sse_handler.py +22 -0
  162. autobyteus/tools/mcp/call_handlers/stdio_handler.py +62 -0
  163. autobyteus/tools/mcp/call_handlers/streamable_http_handler.py +55 -0
  164. autobyteus/tools/mcp/config_service.py +258 -0
  165. autobyteus/tools/mcp/factory.py +70 -0
  166. autobyteus/tools/mcp/registrar.py +135 -0
  167. autobyteus/tools/mcp/schema_mapper.py +131 -0
  168. autobyteus/tools/mcp/tool.py +101 -0
  169. autobyteus/tools/mcp/types.py +96 -0
  170. autobyteus/tools/parameter_schema.py +268 -0
  171. autobyteus/tools/pdf_downloader.py +78 -79
  172. autobyteus/tools/registry/__init__.py +0 -2
  173. autobyteus/tools/registry/tool_definition.py +106 -34
  174. autobyteus/tools/registry/tool_registry.py +46 -22
  175. autobyteus/tools/timer.py +150 -102
  176. autobyteus/tools/tool_config.py +117 -0
  177. autobyteus/tools/tool_meta.py +48 -26
  178. autobyteus/tools/usage/__init__.py +6 -0
  179. autobyteus/tools/usage/formatters/__init__.py +31 -0
  180. autobyteus/tools/usage/formatters/anthropic_json_example_formatter.py +18 -0
  181. autobyteus/tools/usage/formatters/anthropic_json_schema_formatter.py +25 -0
  182. autobyteus/tools/usage/formatters/base_formatter.py +42 -0
  183. autobyteus/tools/usage/formatters/default_json_example_formatter.py +42 -0
  184. autobyteus/tools/usage/formatters/default_json_schema_formatter.py +28 -0
  185. autobyteus/tools/usage/formatters/default_xml_example_formatter.py +55 -0
  186. autobyteus/tools/usage/formatters/default_xml_schema_formatter.py +46 -0
  187. autobyteus/tools/usage/formatters/gemini_json_example_formatter.py +34 -0
  188. autobyteus/tools/usage/formatters/gemini_json_schema_formatter.py +25 -0
  189. autobyteus/tools/usage/formatters/google_json_example_formatter.py +34 -0
  190. autobyteus/tools/usage/formatters/google_json_schema_formatter.py +25 -0
  191. autobyteus/tools/usage/formatters/openai_json_example_formatter.py +49 -0
  192. autobyteus/tools/usage/formatters/openai_json_schema_formatter.py +28 -0
  193. autobyteus/tools/usage/parsers/__init__.py +22 -0
  194. autobyteus/tools/usage/parsers/anthropic_xml_tool_usage_parser.py +10 -0
  195. autobyteus/tools/usage/parsers/base_parser.py +41 -0
  196. autobyteus/tools/usage/parsers/default_json_tool_usage_parser.py +106 -0
  197. autobyteus/tools/usage/parsers/default_xml_tool_usage_parser.py +135 -0
  198. autobyteus/tools/usage/parsers/exceptions.py +13 -0
  199. autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +68 -0
  200. autobyteus/tools/usage/parsers/openai_json_tool_usage_parser.py +147 -0
  201. autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +67 -0
  202. autobyteus/tools/usage/providers/__init__.py +22 -0
  203. autobyteus/tools/usage/providers/json_example_provider.py +32 -0
  204. autobyteus/tools/usage/providers/json_schema_provider.py +35 -0
  205. autobyteus/tools/usage/providers/json_tool_usage_parser_provider.py +28 -0
  206. autobyteus/tools/usage/providers/tool_manifest_provider.py +68 -0
  207. autobyteus/tools/usage/providers/xml_example_provider.py +28 -0
  208. autobyteus/tools/usage/providers/xml_schema_provider.py +29 -0
  209. autobyteus/tools/usage/providers/xml_tool_usage_parser_provider.py +26 -0
  210. autobyteus/tools/usage/registries/__init__.py +20 -0
  211. autobyteus/tools/usage/registries/json_example_formatter_registry.py +51 -0
  212. autobyteus/tools/usage/registries/json_schema_formatter_registry.py +51 -0
  213. autobyteus/tools/usage/registries/json_tool_usage_parser_registry.py +42 -0
  214. autobyteus/tools/usage/registries/xml_example_formatter_registry.py +30 -0
  215. autobyteus/tools/usage/registries/xml_schema_formatter_registry.py +33 -0
  216. autobyteus/tools/usage/registries/xml_tool_usage_parser_registry.py +30 -0
  217. {autobyteus-1.0.5.dist-info → autobyteus-1.1.0.dist-info}/METADATA +21 -3
  218. autobyteus-1.1.0.dist-info/RECORD +279 -0
  219. {autobyteus-1.0.5.dist-info → autobyteus-1.1.0.dist-info}/WHEEL +1 -1
  220. autobyteus/agent/async_agent.py +0 -175
  221. autobyteus/agent/async_group_aware_agent.py +0 -136
  222. autobyteus/agent/group/async_group_aware_agent.py +0 -122
  223. autobyteus/agent/group/coordinator_agent.py +0 -36
  224. autobyteus/agent/group/group_aware_agent.py +0 -121
  225. autobyteus/agent/orchestrator/__init__.py +0 -0
  226. autobyteus/agent/orchestrator/base_agent_orchestrator.py +0 -82
  227. autobyteus/agent/orchestrator/multi_replica_agent_orchestrator.py +0 -72
  228. autobyteus/agent/orchestrator/single_replica_agent_orchestrator.py +0 -43
  229. autobyteus/agent/registry/__init__.py +0 -11
  230. autobyteus/agent/registry/agent_definition.py +0 -94
  231. autobyteus/agent/registry/agent_registry.py +0 -114
  232. autobyteus/agent/response_parser/__init__.py +0 -0
  233. autobyteus/agent/response_parser/tool_usage_command_parser.py +0 -100
  234. autobyteus/agent/status.py +0 -12
  235. autobyteus/conversation/__init__.py +0 -0
  236. autobyteus/conversation/conversation.py +0 -54
  237. autobyteus/conversation/user_message.py +0 -59
  238. autobyteus/events/decorators.py +0 -29
  239. autobyteus/prompt/prompt_version_manager.py +0 -58
  240. autobyteus/prompt/storage/__init__.py +0 -0
  241. autobyteus/prompt/storage/prompt_version_model.py +0 -29
  242. autobyteus/prompt/storage/prompt_version_repository.py +0 -83
  243. autobyteus/tools/bash/factory/__init__.py +0 -0
  244. autobyteus/tools/bash/factory/bash_executor_factory.py +0 -6
  245. autobyteus/tools/factory/ask_user_input_factory.py +0 -6
  246. autobyteus/tools/factory/image_downloader_factory.py +0 -9
  247. autobyteus/tools/factory/pdf_downloader_factory.py +0 -9
  248. autobyteus/tools/factory/webpage_image_downloader_factory.py +0 -6
  249. autobyteus/tools/file/factory/__init__.py +0 -0
  250. autobyteus/tools/file/factory/file_reader_factory.py +0 -6
  251. autobyteus/tools/file/factory/file_writer_factory.py +0 -6
  252. autobyteus/tools/mcp_remote_tool.py +0 -82
  253. autobyteus/tools/web_page_pdf_generator.py +0 -90
  254. autobyteus-1.0.5.dist-info/RECORD +0 -163
  255. {autobyteus-1.0.5.dist-info → autobyteus-1.1.0.dist-info}/licenses/LICENSE +0 -0
  256. {autobyteus-1.0.5.dist-info → autobyteus-1.1.0.dist-info}/top_level.txt +0 -0
@@ -1,159 +1,151 @@
1
1
  # File: autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py
2
2
 
3
- from datetime import datetime
4
- import os
5
3
  import xml.etree.ElementTree as ET
4
+ from typing import Optional, TYPE_CHECKING, Dict, Any
5
+ import logging
6
+
6
7
  from autobyteus.tools.browser.session_aware.browser_session_aware_tool import BrowserSessionAwareTool
7
8
  from autobyteus.tools.browser.session_aware.shared_browser_session import SharedBrowserSession
8
9
  from autobyteus.tools.browser.session_aware.web_element_action import WebElementAction
10
+ from autobyteus.tools.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
11
+ from autobyteus.tools.tool_config import ToolConfig
9
12
 
10
- class BrowserSessionAwareWebElementTrigger(BrowserSessionAwareTool):
11
- def __init__(self):
12
- super().__init__()
13
-
14
- def get_name(self) -> str:
15
- return "WebElementTrigger"
16
-
17
- @classmethod
18
- def tool_usage_xml(cls):
19
- """
20
- Return an XML string describing the usage of the WebElementTrigger tool.
21
-
22
- Returns:
23
- str: An XML description of how to use the WebElementTrigger tool.
24
- """
25
- return f'''WebElementTrigger: Triggers actions on web elements on web pages, takes a screenshot, and returns the absolute path of the screenshot.
26
- <command name="WebElementTrigger">
27
- <arg name="webpage_url">url</arg>
28
- <arg name="css_selector">selector</arg>
29
- <arg name="action">action</arg>
30
- <arg name="params">
31
- <param>
32
- <name>param_name</name>
33
- <value>param_value</value>
34
- </param>
35
- </arg>
36
- </command>
37
-
38
- Parameters:
39
- - webpage_url: String. URL of the webpage to interact with.
40
- - css_selector: String. CSS selector to find the target element.
41
- - action: String. Type of interaction to perform on the element. Must be one of:
42
- {', '.join(str(action) for action in WebElementAction)}
43
- - params: XML-formatted string containing additional parameters for specific actions.
44
-
45
- Common actions and their parameters:
46
- 1. click: No additional params required.
47
- 2. type: Requires 'text' param. Example: <param><name>text</name><value>Hello, World!</value></param>
48
- 3. select: Requires 'option' param. Example: <param><name>option</name><value>option1</value></param>
49
- 4. check: Optional 'state' param (default: true). Example: <param><name>state</name><value>false</value></param>
50
- 5. submit: No additional params required.
51
- 6. hover: No additional params required.
52
- 7. double_click: No additional params required.
13
+ if TYPE_CHECKING:
14
+ pass
53
15
 
54
- Return Value:
55
- - String: Absolute path to the screenshot taken after the action is performed.
56
- The screenshot is saved in the current working directory with the filename format:
57
- 'screenshot_<action>_<timestamp>.png'
16
+ logger = logging.getLogger(__name__)
58
17
 
59
- Examples:
60
- 1. Typing in a search box:
61
- <command name="WebElementTrigger">
62
- <arg name="webpage_url">https://example.com</arg>
63
- <arg name="css_selector">#search-input</arg>
64
- <arg name="action">type</arg>
65
- <arg name="params">
66
- <param>
67
- <name>text</name>
68
- <value>Python tutorial</value>
69
- </param>
70
- </arg>
71
- </command>
72
- Returns: '/path/to/screenshot_type_20230615_120530.png'
73
-
74
- 2. Selecting an option from a dropdown:
75
- <command name="WebElementTrigger">
76
- <arg name="webpage_url">https://example.com</arg>
77
- <arg name="css_selector">#country-select</arg>
78
- <arg name="action">select</arg>
79
- <arg name="params">
80
- <param>
81
- <name>option</name>
82
- <value>USA</value>
83
- </param>
84
- </arg>
85
- </command>
86
- Returns: '/path/to/screenshot_select_20230615_120545.png'
18
+ class BrowserSessionAwareWebElementTrigger(BrowserSessionAwareTool):
19
+ """
20
+ A session-aware tool to trigger actions on web elements identified by a CSS selector.
21
+ """
22
+ def __init__(self, config: Optional[ToolConfig] = None):
23
+ super().__init__(config=config)
24
+ logger.debug("BrowserSessionAwareWebElementTrigger tool initialized.")
87
25
 
88
- 3. Clicking a button:
89
- <command name="WebElementTrigger">
90
- <arg name="webpage_url">https://example.com</arg>
91
- <arg name="css_selector">.submit-button</arg>
92
- <arg name="action">click</arg>
93
- </command>
94
- Returns: '/path/to/screenshot_click_20230615_120600.png'
95
- '''
26
+ @classmethod
27
+ def get_name(cls) -> str:
28
+ return "WebElementTrigger"
96
29
 
97
- async def perform_action(self, shared_session: SharedBrowserSession, **kwargs):
98
- css_selector = kwargs.get("css_selector")
99
- action_str = kwargs.get("action")
100
- params_str = kwargs.get("params", "")
30
+ @classmethod
31
+ def get_description(cls) -> str:
32
+ action_names = ', '.join(str(action) for action in WebElementAction)
33
+ return (f"Triggers actions on web elements on the current page in a shared browser session. "
34
+ f"Supported actions: {action_names}. "
35
+ f"Returns a confirmation message upon successful execution.")
101
36
 
102
- if not css_selector:
103
- raise ValueError("CSS selector is required.")
37
+ @classmethod
38
+ def get_argument_schema(cls) -> Optional[ParameterSchema]:
39
+ schema = ParameterSchema()
40
+ schema.add_parameter(ParameterDefinition(
41
+ name="webpage_url",
42
+ param_type=ParameterType.STRING,
43
+ description="URL of the webpage. Required if no browser session is active or to ensure context.",
44
+ required=True
45
+ ))
46
+ schema.add_parameter(ParameterDefinition(
47
+ name="css_selector",
48
+ param_type=ParameterType.STRING,
49
+ description="CSS selector to find the target web element.",
50
+ required=True
51
+ ))
52
+ schema.add_parameter(ParameterDefinition(
53
+ name="action",
54
+ param_type=ParameterType.ENUM,
55
+ description=f"Type of interaction to perform. Must be one of: {', '.join(str(act) for act in WebElementAction)}.",
56
+ required=True,
57
+ enum_values=[str(act) for act in WebElementAction]
58
+ ))
59
+ schema.add_parameter(ParameterDefinition(
60
+ name="params",
61
+ param_type=ParameterType.STRING,
62
+ description="Optional XML-formatted string containing additional parameters for specific actions (e.g., text for 'type', option for 'select'). Example: <param><name>text</name><value>Hello</value></param>",
63
+ required=False
64
+ ))
65
+ return schema
66
+
67
+ async def perform_action(
68
+ self,
69
+ shared_session: SharedBrowserSession,
70
+ css_selector: str,
71
+ action: str,
72
+ webpage_url: str,
73
+ params: Optional[str] = ""
74
+ ) -> str:
75
+ logger.info(f"WebElementTrigger performing action '{action}' on selector '{css_selector}' for page related to URL '{webpage_url}'. Params: '{params[:50]}...'")
104
76
 
105
77
  try:
106
- action = WebElementAction.from_string(action_str)
78
+ action_enum = WebElementAction.from_string(action)
107
79
  except ValueError as e:
108
- raise ValueError(f"Invalid action: {action_str}. {str(e)}")
80
+ logger.error(f"Invalid action string '{action}' passed to perform_action despite schema validation: {e}")
81
+ raise
109
82
 
110
- params = self._parse_params(params_str)
83
+ parsed_params = self._parse_xml_params(params if params else "")
111
84
 
112
85
  element = shared_session.page.locator(css_selector)
113
86
 
114
- if action == WebElementAction.CLICK:
87
+ try:
88
+ await element.wait_for(state="visible", timeout=10000)
89
+ except Exception as e_wait:
90
+ error_msg = f"Element with selector '{css_selector}' not visible or found within timeout on page {shared_session.page.url}. Error: {e_wait}"
91
+ logger.warning(error_msg)
92
+ raise ValueError(error_msg) from e_wait
93
+
94
+ if action_enum == WebElementAction.CLICK:
115
95
  await element.click()
116
- elif action == WebElementAction.TYPE:
117
- text = params.get("text")
118
- if not text:
96
+ elif action_enum == WebElementAction.TYPE:
97
+ text_to_type = parsed_params.get("text")
98
+ if text_to_type is None:
119
99
  raise ValueError("'text' parameter is required for 'type' action.")
120
- await element.type(text)
121
- elif action == WebElementAction.SELECT:
122
- option = params.get("option")
123
- if not option:
100
+ await element.fill("")
101
+ await element.type(text_to_type)
102
+ elif action_enum == WebElementAction.SELECT:
103
+ option_value = parsed_params.get("option")
104
+ if option_value is None:
124
105
  raise ValueError("'option' parameter is required for 'select' action.")
125
- await element.select_option(option)
126
- elif action == WebElementAction.CHECK:
127
- state = params.get("state", "true").lower() == "true"
128
- if state:
106
+ await element.select_option(option_value)
107
+ elif action_enum == WebElementAction.CHECK:
108
+ state_str = parsed_params.get("state", "true")
109
+ is_checked_state = state_str.lower() == "true"
110
+ if is_checked_state:
129
111
  await element.check()
130
112
  else:
131
113
  await element.uncheck()
132
- elif action == WebElementAction.SUBMIT:
133
- await element.submit()
134
- elif action == WebElementAction.HOVER:
114
+ elif action_enum == WebElementAction.SUBMIT:
115
+ logger.warning("WebElementAction.SUBMIT is interpreted as a click. Ensure CSS selector targets a submit button or form element intended for click-based submission.")
116
+ await element.click()
117
+ elif action_enum == WebElementAction.HOVER:
135
118
  await element.hover()
136
- elif action == WebElementAction.DOUBLE_CLICK:
119
+ elif action_enum == WebElementAction.DOUBLE_CLICK:
137
120
  await element.dblclick()
138
121
  else:
139
- raise ValueError(f"Unsupported action: {action}")
122
+ raise ValueError(f"Unsupported action: {action_enum}")
140
123
 
141
- # Take screenshot after action
142
- return "The WebElementTrigger command is executed"
124
+ success_msg = f"The WebElementTrigger action '{action_enum}' on selector '{css_selector}' was executed."
125
+ logger.info(success_msg)
126
+ return success_msg
143
127
 
144
- def _parse_params(self, params_str):
145
- if not params_str:
128
+ def _parse_xml_params(self, params_xml_str: str) -> Dict[str, str]:
129
+ if not params_xml_str:
146
130
  return {}
147
131
 
148
132
  try:
149
- xml_string = f"<root>{params_str}</root>"
150
- root = ET.fromstring(xml_string)
151
- params = {}
152
- for param in root.findall('param'):
153
- name_elem = param.find('name')
154
- value_elem = param.find('value')
155
- if name_elem is not None and value_elem is not None:
156
- params[name_elem.text] = value_elem.text
157
- return params
158
- except ET.ParseError:
133
+ if not params_xml_str.strip().startswith("<root>"):
134
+ xml_string_to_parse = f"<root>{params_xml_str}</root>"
135
+ else:
136
+ xml_string_to_parse = params_xml_str
137
+
138
+ root = ET.fromstring(xml_string_to_parse)
139
+ parsed_params: Dict[str, str] = {}
140
+ for param_node in root.findall('param'):
141
+ name_elem = param_node.find('name')
142
+ value_elem = param_node.find('value')
143
+ if name_elem is not None and name_elem.text and value_elem is not None and value_elem.text is not None:
144
+ parsed_params[name_elem.text] = value_elem.text
145
+ elif name_elem is not None and name_elem.text and value_elem is not None and value_elem.text is None:
146
+ parsed_params[name_elem.text] = ""
147
+
148
+ return parsed_params
149
+ except ET.ParseError as e_parse:
150
+ logger.warning(f"Failed to parse params XML string: '{params_xml_str}'. Error: {e_parse}. Returning empty params.")
159
151
  return {}
@@ -1,33 +1,86 @@
1
1
  # File: autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py
2
2
 
3
+ import logging
4
+ from typing import Optional, TYPE_CHECKING, Any
3
5
  from autobyteus.tools.browser.session_aware.browser_session_aware_tool import BrowserSessionAwareTool
4
6
  from autobyteus.tools.browser.session_aware.shared_browser_session import SharedBrowserSession
7
+ from autobyteus.tools.tool_config import ToolConfig
8
+ from autobyteus.tools.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
5
9
  from autobyteus.utils.html_cleaner import clean, CleaningMode
6
10
 
11
+ if TYPE_CHECKING:
12
+ from autobyteus.agent.context import AgentContext
13
+
14
+ logger = logging.getLogger(__name__)
15
+
7
16
  class BrowserSessionAwareWebPageReader(BrowserSessionAwareTool):
8
- def __init__(self, cleaning_mode=CleaningMode.THOROUGH):
9
- super().__init__()
10
- self.cleaning_mode = cleaning_mode
17
+ """
18
+ A session-aware tool to read and clean HTML content from the current page
19
+ in a shared browser session.
20
+ """
21
+ def __init__(self, config: Optional[ToolConfig] = None):
22
+ super().__init__(config=config)
23
+
24
+ cleaning_mode_to_use = CleaningMode.THOROUGH
25
+ if config:
26
+ cleaning_mode_value = config.get('cleaning_mode')
27
+ if cleaning_mode_value:
28
+ if isinstance(cleaning_mode_value, str):
29
+ try:
30
+ cleaning_mode_to_use = CleaningMode(cleaning_mode_value.upper())
31
+ except ValueError:
32
+ cleaning_mode_to_use = CleaningMode.THOROUGH
33
+ elif isinstance(cleaning_mode_value, CleaningMode):
34
+ cleaning_mode_to_use = cleaning_mode_value
35
+
36
+ self.cleaning_mode = cleaning_mode_to_use
37
+ logger.debug(f"BrowserSessionAwareWebPageReader initialized with cleaning_mode: {self.cleaning_mode}")
11
38
 
12
- def get_name(self) -> str:
39
+ @classmethod
40
+ def get_name(cls) -> str:
13
41
  return "WebPageReader"
14
42
 
15
43
  @classmethod
16
- def tool_usage_xml(cls):
17
- """
18
- Return an XML string describing the usage of the WebPageReader tool.
19
-
20
- Returns:
21
- str: An XML description of how to use the WebPageReader tool.
22
- """
23
- return '''WebPageReader: Reads and cleans the HTML content from a given webpage. Usage:
24
- <command name="WebPageReader">
25
- <arg name="webpage_url">url_to_read</arg>
26
- </command>
27
- where "url_to_read" is a string containing the URL of the webpage to read the content from.
28
- '''
29
-
30
- async def perform_action(self, shared_session: SharedBrowserSession, **kwargs):
31
- page_content = await shared_session.page.content()
32
- cleaned_content = clean(page_content, self.cleaning_mode)
33
- return cleaned_content
44
+ def get_description(cls) -> str:
45
+ return ("Reads and cleans the HTML content from the current page in a shared browser session. "
46
+ "The level of HTML cleanup can be configured at tool instantiation.")
47
+
48
+ @classmethod
49
+ def get_argument_schema(cls) -> Optional[ParameterSchema]:
50
+ schema = ParameterSchema()
51
+ schema.add_parameter(ParameterDefinition(
52
+ name="webpage_url",
53
+ param_type=ParameterType.STRING,
54
+ description="URL of the webpage. Required if no browser session is active or to ensure context. Tool reads current page content after navigation if applicable.",
55
+ required=True
56
+ ))
57
+ return schema
58
+
59
+ @classmethod
60
+ def get_config_schema(cls) -> Optional[ParameterSchema]:
61
+ schema = ParameterSchema()
62
+ schema.add_parameter(ParameterDefinition(
63
+ name="cleaning_mode",
64
+ param_type=ParameterType.ENUM,
65
+ description="Level of HTML content cleanup (BASIC or THOROUGH). Applied to the read webpage content.",
66
+ required=False,
67
+ default_value="THOROUGH",
68
+ enum_values=[mode.name for mode in CleaningMode]
69
+ ))
70
+ return schema
71
+
72
+ async def perform_action(
73
+ self,
74
+ shared_session: SharedBrowserSession,
75
+ webpage_url: str
76
+ ) -> str:
77
+ logger.info(f"BrowserSessionAwareWebPageReader performing action. Current page URL: {shared_session.page.url}, cleaning_mode: {self.cleaning_mode}")
78
+
79
+ try:
80
+ page_content = await shared_session.page.content()
81
+ cleaned_content = clean(page_content, self.cleaning_mode)
82
+ logger.debug(f"Read and cleaned content from {shared_session.page.url}. Cleaned length: {len(cleaned_content)}")
83
+ return cleaned_content
84
+ except Exception as e:
85
+ logger.error(f"Error reading page content in shared session from {shared_session.page.url}: {e}", exc_info=True)
86
+ raise RuntimeError(f"Failed to read page content from shared session: {str(e)}")
@@ -1,38 +1,104 @@
1
1
  # File: autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py
2
2
 
3
3
  import os
4
+ import logging
5
+ from typing import Optional, TYPE_CHECKING, Any
4
6
  from autobyteus.tools.browser.session_aware.browser_session_aware_tool import BrowserSessionAwareTool
5
7
  from autobyteus.tools.browser.session_aware.shared_browser_session import SharedBrowserSession
8
+ from autobyteus.tools.tool_config import ToolConfig
9
+ from autobyteus.tools.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
10
+
11
+ if TYPE_CHECKING:
12
+ from autobyteus.agent.context import AgentContext
13
+
14
+ logger = logging.getLogger(__name__)
6
15
 
7
16
  class BrowserSessionAwareWebPageScreenshotTaker(BrowserSessionAwareTool):
8
- def __init__(self):
9
- super().__init__()
17
+ """
18
+ A session-aware tool to take a screenshot of the current page in a shared browser session.
19
+ """
20
+ def __init__(self, config: Optional[ToolConfig] = None):
21
+ super().__init__(config=config)
22
+
23
+ self.full_page: bool = True
24
+ self.image_format: str = "png"
25
+
26
+ if config:
27
+ self.full_page = config.get('full_page', True)
28
+ self.image_format = str(config.get('image_format', 'png')).lower()
29
+ if self.image_format not in ["png", "jpeg"]:
30
+ logger.warning(f"Invalid image_format '{self.image_format}' in config. Defaulting to 'png'.")
31
+ self.image_format = "png"
32
+ logger.debug(f"BrowserSessionAwareWebPageScreenshotTaker initialized. Full page: {self.full_page}, Format: {self.image_format}")
10
33
 
11
- def get_name(self) -> str:
12
- return "WebPageScreenshotTaker"
34
+ @classmethod
35
+ def get_name(cls) -> str:
36
+ return "WebPageScreenshotTaker"
37
+
38
+ @classmethod
39
+ def get_description(cls) -> str:
40
+ return ("Takes a screenshot of the current page in a shared browser session. "
41
+ "Saves it to the specified local file path and returns the absolute path of the saved screenshot. "
42
+ "Screenshot options (full page, image format) can be set at tool instantiation.")
13
43
 
14
44
  @classmethod
15
- def tool_usage_xml(cls):
16
- """
17
- Return an XML string describing the usage of the WebPageScreenshotTaker tool.
18
-
19
- Returns:
20
- str: An XML description of how to use the WebPageScreenshotTaker tool.
21
- """
22
- return '''WebPageScreenshotTaker: Takes a screenshot of a given webpage and saves it to the specified file. Usage:
23
- <command name="WebPageScreenshotTaker">
24
- <arg name="webpage_url">url_to_screenshot</arg>
25
- <arg name="file_name">screenshot_file_name</arg>
26
- </command>
27
- where "url_to_screenshot" is a string containing the URL of the webpage to take a screenshot of, and "screenshot_file_name" is the name of the file to save the screenshot (including extension, e.g., 'screenshot.png'). Optionally, "screenshot_file_name" can include a relative path (e.g., 'images/screenshot.png').
28
- Returns the absolute file path of the saved screenshot.
29
- '''
30
-
31
- async def perform_action(self, shared_session: SharedBrowserSession, **kwargs):
32
- file_name = kwargs.get('file_name')
33
- if not file_name:
34
- raise ValueError("The 'file_name' keyword argument must be specified.")
35
-
36
- await shared_session.page.screenshot(path=file_name, full_page=True)
37
- absolute_path = os.path.abspath(file_name)
38
- return absolute_path
45
+ def get_argument_schema(cls) -> Optional[ParameterSchema]:
46
+ schema = ParameterSchema()
47
+ schema.add_parameter(ParameterDefinition(
48
+ name="webpage_url",
49
+ param_type=ParameterType.STRING,
50
+ description="URL of the webpage. Required if no browser session is active or to ensure context. Screenshot is of current page.",
51
+ required=True
52
+ ))
53
+ schema.add_parameter(ParameterDefinition(
54
+ name="file_name",
55
+ param_type=ParameterType.STRING,
56
+ description="The local file path (including filename and extension, e.g., 'session_screenshots/page.png') where the screenshot will be saved.",
57
+ required=True
58
+ ))
59
+ return schema
60
+
61
+ @classmethod
62
+ def get_config_schema(cls) -> Optional[ParameterSchema]:
63
+ schema = ParameterSchema()
64
+ schema.add_parameter(ParameterDefinition(
65
+ name="full_page",
66
+ param_type=ParameterType.BOOLEAN,
67
+ description="Default for whether to capture the full scrollable page or just the viewport.",
68
+ required=False,
69
+ default_value=True
70
+ ))
71
+ schema.add_parameter(ParameterDefinition(
72
+ name="image_format",
73
+ param_type=ParameterType.ENUM,
74
+ description="Default image format for screenshots (png or jpeg).",
75
+ required=False,
76
+ default_value="png",
77
+ enum_values=["png", "jpeg"]
78
+ ))
79
+ return schema
80
+
81
+ async def perform_action(
82
+ self,
83
+ shared_session: SharedBrowserSession,
84
+ file_name: str,
85
+ webpage_url: str
86
+ ) -> str:
87
+ logger.info(f"BrowserSessionAwareWebPageScreenshotTaker performing action. Saving to '{file_name}'. Current page: {shared_session.page.url}")
88
+
89
+ output_dir = os.path.dirname(file_name)
90
+ if output_dir:
91
+ os.makedirs(output_dir, exist_ok=True)
92
+
93
+ try:
94
+ await shared_session.page.screenshot(
95
+ path=file_name,
96
+ full_page=self.full_page,
97
+ type=self.image_format # type: ignore
98
+ )
99
+ absolute_file_path = os.path.abspath(file_name)
100
+ logger.info(f"Screenshot of {shared_session.page.url} saved successfully to {absolute_file_path}")
101
+ return absolute_file_path
102
+ except Exception as e:
103
+ logger.error(f"Error taking screenshot in shared session for page {shared_session.page.url}, saving to '{file_name}': {e}", exc_info=True)
104
+ raise RuntimeError(f"Failed to take screenshot in shared session: {str(e)}")
@@ -1,6 +1,14 @@
1
1
  from autobyteus.tools.factory.tool_factory import ToolFactory
2
2
  from autobyteus.tools.browser.session_aware.browser_session_aware_web_element_trigger import BrowserSessionAwareWebElementTrigger
3
+ from typing import Optional, TYPE_CHECKING
4
+
5
+ if TYPE_CHECKING:
6
+ from autobyteus.tools.tool_config import ToolConfig
3
7
 
4
8
  class BrowserSessionAwareWebElementTriggerFactory(ToolFactory):
5
- def create_tool(self) -> BrowserSessionAwareWebElementTrigger:
6
- return BrowserSessionAwareWebElementTrigger()
9
+ def create_tool(self, config: Optional['ToolConfig'] = None) -> BrowserSessionAwareWebElementTrigger:
10
+ """
11
+ Creates an instance of BrowserSessionAwareWebElementTrigger.
12
+ The 'config' parameter is ignored by this factory.
13
+ """
14
+ return BrowserSessionAwareWebElementTrigger()
@@ -1,10 +1,26 @@
1
1
  from autobyteus.tools.factory.tool_factory import ToolFactory
2
2
  from autobyteus.tools.browser.session_aware.browser_session_aware_webpage_reader import BrowserSessionAwareWebPageReader
3
3
  from autobyteus.utils.html_cleaner import CleaningMode
4
+ from typing import Optional, TYPE_CHECKING
5
+
6
+ if TYPE_CHECKING:
7
+ from autobyteus.tools.tool_config import ToolConfig
8
+ from autobyteus.tools.base_tool import BaseTool
4
9
 
5
10
  class BrowserSessionAwareWebPageReaderFactory(ToolFactory):
6
11
  def __init__(self, content_cleanup_level: CleaningMode = CleaningMode.THOROUGH):
7
12
  self.content_cleanup_level = content_cleanup_level
8
13
 
9
- def create_tool(self) -> BrowserSessionAwareWebPageReader:
10
- return BrowserSessionAwareWebPageReader(cleaning_mode=self.content_cleanup_level)
14
+ def create_tool(self, config: Optional['ToolConfig'] = None) -> BrowserSessionAwareWebPageReader:
15
+ """
16
+ Creates an instance of BrowserSessionAwareWebPageReader.
17
+ The 'config' parameter is ignored; configuration is set during factory initialization.
18
+ """
19
+ # This factory passes its own configuration to the tool's constructor.
20
+ # The tool's constructor expects a ToolConfig object.
21
+ from autobyteus.tools.tool_config import ToolConfig as ConcreteToolConfig
22
+
23
+ tool_creation_config = ConcreteToolConfig(
24
+ params={"cleaning_mode": self.content_cleanup_level}
25
+ )
26
+ return BrowserSessionAwareWebPageReader(config=tool_creation_config)
@@ -1,6 +1,14 @@
1
1
  from autobyteus.tools.factory.tool_factory import ToolFactory
2
2
  from autobyteus.tools.browser.session_aware.browser_session_aware_webpage_screenshot_taker import BrowserSessionAwareWebPageScreenshotTaker
3
+ from typing import Optional, TYPE_CHECKING
4
+
5
+ if TYPE_CHECKING:
6
+ from autobyteus.tools.tool_config import ToolConfig
3
7
 
4
8
  class BrowserSessionAwareWebPageScreenshotTakerFactory(ToolFactory):
5
- def create_tool(self) -> BrowserSessionAwareWebPageScreenshotTaker:
6
- return BrowserSessionAwareWebPageScreenshotTaker()
9
+ def create_tool(self, config: Optional['ToolConfig'] = None) -> BrowserSessionAwareWebPageScreenshotTaker:
10
+ """
11
+ Creates an instance of BrowserSessionAwareWebPageScreenshotTaker.
12
+ The 'config' parameter is ignored by this factory.
13
+ """
14
+ return BrowserSessionAwareWebPageScreenshotTaker()
@@ -1,14 +1,15 @@
1
1
  from autobyteus.utils.singleton import SingletonMeta
2
2
  from autobyteus.tools.browser.session_aware.shared_browser_session import SharedBrowserSession
3
3
  from autobyteus.events.event_emitter import EventEmitter
4
+ from autobyteus.events.event_types import EventType
4
5
 
5
6
  class SharedBrowserSessionManager(metaclass=SingletonMeta):
6
7
  def __init__(self):
7
8
  self.shared_browser_session = None
8
9
  self.event_emitter = EventEmitter()
9
- self.event_emitter.subscribe("create_shared_session", self.create_shared_browser_session)
10
+ self.event_emitter.subscribe(EventType.CREATE_SHARED_SESSION, self.create_shared_browser_session)
10
11
 
11
- async def create_shared_browser_session(self):
12
+ async def create_shared_browser_session(self, **kwargs):
12
13
  self.shared_browser_session = SharedBrowserSession()
13
14
  await self.shared_browser_session.initialize()
14
15
 
@@ -21,4 +22,4 @@ class SharedBrowserSessionManager(metaclass=SingletonMeta):
21
22
  self.shared_browser_session = shared_session
22
23
 
23
24
  def get_shared_browser_session(self):
24
- return self.shared_browser_session
25
+ return self.shared_browser_session
@@ -0,0 +1,7 @@
1
+ # This file makes 'standalone' a package under 'browser'.
2
+ # from .google_search_ui import GoogleSearch
3
+ # from .webpage_reader import WebPageReader
4
+ # from .webpage_screenshot_taker import WebPageScreenshotTaker
5
+ # from .navigate_to import NavigateTo
6
+ # from .webpage_image_downloader import WebPageImageDownloader
7
+ # from .web_page_pdf_generator import WebPagePDFGenerator
@@ -1,10 +1,25 @@
1
1
  from autobyteus.tools.factory.tool_factory import ToolFactory
2
2
  from autobyteus.tools.browser.standalone.google_search_ui import GoogleSearch
3
3
  from autobyteus.utils.html_cleaner import CleaningMode
4
+ from typing import Optional, TYPE_CHECKING
5
+
6
+ if TYPE_CHECKING:
7
+ from autobyteus.tools.tool_config import ToolConfig
4
8
 
5
9
  class GoogleSearchFactory(ToolFactory):
6
10
  def __init__(self, cleaning_mode: CleaningMode = CleaningMode.THOROUGH):
7
11
  self.cleaning_mode = cleaning_mode
8
12
 
9
- def create_tool(self) -> GoogleSearch:
10
- return GoogleSearch(cleaning_mode=self.cleaning_mode)
13
+ def create_tool(self, config: Optional['ToolConfig'] = None) -> GoogleSearch:
14
+ """
15
+ Creates an instance of GoogleSearch.
16
+ The 'config' parameter is ignored; configuration is set during factory initialization.
17
+ """
18
+ # This factory passes its own configuration to the tool's constructor.
19
+ # The tool's constructor expects a ToolConfig object.
20
+ from autobyteus.tools.tool_config import ToolConfig as ConcreteToolConfig
21
+
22
+ tool_creation_config = ConcreteToolConfig(
23
+ params={"cleaning_mode": self.cleaning_mode}
24
+ )
25
+ return GoogleSearch(config=tool_creation_config)