From b9f28705c892b21eb826a96a2bf0360922263d2b Mon Sep 17 00:00:00 2001 From: Pavel Date: Thu, 6 Mar 2025 18:46:50 +0300 Subject: [PATCH 1/2] brave-tool --- application/agents/tools/brave.py | 217 +++++++++++++++++++++++ frontend/public/toolIcons/tool_brave.svg | 1 + 2 files changed, 218 insertions(+) create mode 100644 application/agents/tools/brave.py create mode 100644 frontend/public/toolIcons/tool_brave.svg diff --git a/application/agents/tools/brave.py b/application/agents/tools/brave.py new file mode 100644 index 00000000..f2213c8b --- /dev/null +++ b/application/agents/tools/brave.py @@ -0,0 +1,217 @@ +import requests +from application.tools.base import Tool + + +class BraveSearchTool(Tool): + """ + Brave Search + A tool for performing web and image searches using the Brave Search API. + Requires an API key for authentication. + """ + + def __init__(self, config): + self.config = config + self.token = config.get("token", "") + self.base_url = "https://api.search.brave.com/res/v1" + + def execute_action(self, action_name, **kwargs): + actions = { + "brave_web_search": self._web_search, + "brave_image_search": self._image_search, + } + + if action_name in actions: + return actions[action_name](**kwargs) + else: + raise ValueError(f"Unknown action: {action_name}") + + def _web_search(self, query, country="ALL", search_lang="en", count=10, + offset=0, safesearch="off", freshness=None, + result_filter=None, extra_snippets=False, summary=False): + """ + Performs a web search using the Brave Search API. + """ + print(f"Performing Brave web search for: {query}") + + url = f"{self.base_url}/web/search" + + # Build query parameters + params = { + "q": query, + "country": country, + "search_lang": search_lang, + "count": min(count, 20), + "offset": min(offset, 9), + "safesearch": safesearch + } + + # Add optional parameters only if they have values + if freshness: + params["freshness"] = freshness + if result_filter: + params["result_filter"] = result_filter + if extra_snippets: + params["extra_snippets"] = 1 + if summary: + params["summary"] = 1 + + # Set up headers + headers = { + "Accept": "application/json", + "Accept-Encoding": "gzip", + "X-Subscription-Token": self.token + } + + # Make the request + response = requests.get(url, params=params, headers=headers) + + if response.status_code == 200: + return { + "status_code": response.status_code, + "results": response.json(), + "message": "Search completed successfully." + } + else: + return { + "status_code": response.status_code, + "message": f"Search failed with status code: {response.status_code}." + } + + def _image_search(self, query, country="ALL", search_lang="en", count=5, + safesearch="off", spellcheck=False): + """ + Performs an image search using the Brave Search API. + """ + print(f"Performing Brave image search for: {query}") + + url = f"{self.base_url}/images/search" + + # Build query parameters + params = { + "q": query, + "country": country, + "search_lang": search_lang, + "count": min(count, 100), # API max is 100 + "safesearch": safesearch, + "spellcheck": 1 if spellcheck else 0 + } + + # Set up headers + headers = { + "Accept": "application/json", + "Accept-Encoding": "gzip", + "X-Subscription-Token": self.token + } + + # Make the request + response = requests.get(url, params=params, headers=headers) + + if response.status_code == 200: + return { + "status_code": response.status_code, + "results": response.json(), + "message": "Image search completed successfully." + } + else: + return { + "status_code": response.status_code, + "message": f"Image search failed with status code: {response.status_code}." + } + + def get_actions_metadata(self): + return [ + { + "name": "brave_web_search", + "description": "Perform a web search using Brave Search", + "parameters": { + "type": "object", + "properties": { + "query": { + "type": "string", + "description": "The search query (max 400 characters, 50 words)", + }, + # "country": { + # "type": "string", + # "description": "The 2-character country code (default: US)", + # }, + "search_lang": { + "type": "string", + "description": "The search language preference (default: en)", + }, + # "count": { + # "type": "integer", + # "description": "Number of results to return (max 20, default: 10)", + # }, + # "offset": { + # "type": "integer", + # "description": "Pagination offset (max 9, default: 0)", + # }, + # "safesearch": { + # "type": "string", + # "description": "Filter level for adult content (off, moderate, strict)", + # }, + "freshness": { + "type": "string", + "description": "Time filter for results (pd: last 24h, pw: last week, pm: last month, py: last year)", + }, + # "result_filter": { + # "type": "string", + # "description": "Comma-delimited list of result types to include", + # }, + # "extra_snippets": { + # "type": "boolean", + # "description": "Get additional excerpts from result pages", + # }, + # "summary": { + # "type": "boolean", + # "description": "Enable summary generation in search results", + # } + }, + "required": ["query"], + "additionalProperties": False, + }, + }, + { + "name": "brave_image_search", + "description": "Perform an image search using Brave Search", + "parameters": { + "type": "object", + "properties": { + "query": { + "type": "string", + "description": "The search query (max 400 characters, 50 words)", + }, + # "country": { + # "type": "string", + # "description": "The 2-character country code (default: US)", + # }, + # "search_lang": { + # "type": "string", + # "description": "The search language preference (default: en)", + # }, + "count": { + "type": "integer", + "description": "Number of results to return (max 100, default: 5)", + }, + # "safesearch": { + # "type": "string", + # "description": "Filter level for adult content (off, strict). Default: strict", + # }, + # "spellcheck": { + # "type": "boolean", + # "description": "Whether to spellcheck provided query (default: true)", + # } + }, + "required": ["query"], + "additionalProperties": False, + }, + } + ] + + def get_config_requirements(self): + return { + "token": { + "type": "string", + "description": "Brave Search API key for authentication" + }, + } \ No newline at end of file diff --git a/frontend/public/toolIcons/tool_brave.svg b/frontend/public/toolIcons/tool_brave.svg new file mode 100644 index 00000000..380c19ed --- /dev/null +++ b/frontend/public/toolIcons/tool_brave.svg @@ -0,0 +1 @@ + \ No newline at end of file From 1e3c8cb7b17754687b73e337d0c6bd1b3bd09e8a Mon Sep 17 00:00:00 2001 From: Pavel Date: Thu, 6 Mar 2025 19:13:19 +0300 Subject: [PATCH 2/2] fix imports --- application/agents/tools/brave.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/agents/tools/brave.py b/application/agents/tools/brave.py index f2213c8b..1428bea4 100644 --- a/application/agents/tools/brave.py +++ b/application/agents/tools/brave.py @@ -1,5 +1,5 @@ import requests -from application.tools.base import Tool +from application.agents.tools.base import Tool class BraveSearchTool(Tool):