
    `gjH                    ~    d Z ddlmZ ddlZddlZddlmZmZ ddlm	Z	  ej                  e      ZdZ G d de	      Zy)	uB  Brave Search (free tier) — plugin form.

Subclasses :class:`agent.web_search_provider.WebSearchProvider` (the
plugin-facing ABC). The legacy in-tree module
``tools.web_providers.brave_free`` was removed in the same commit that
moved this code under ``plugins/``; this file is now the canonical
implementation.

Config keys this provider responds to::

    web:
      search_backend: "brave-free"     # explicit per-capability
      backend: "brave-free"            # shared fallback

Auth env var::

    BRAVE_SEARCH_API_KEY=...    # https://brave.com/search/api/ (free tier)
    )annotationsN)AnyDict)WebSearchProviderz.https://api.search.brave.com/res/v1/web/searchc                  ^    e Zd ZdZed
d       Zed
d       ZddZddZddZ	dddZ
ddZy	)BraveFreeWebSearchProvideru   Search-only Brave provider using the free-tier Data-for-Search API.

    Free tier is 2,000 queries/month (1 qps). No content-extraction capability —
    users pair this with Firecrawl/Tavily/Exa for ``web_extract``.
    c                     y)Nz
brave-free selfs    R/root/.hermes/venv/lib/python3.12/site-packages/plugins/web/brave_free/provider.pynamezBraveFreeWebSearchProvider.name(   s         c                     y)NBrave Search (Free)r
   r   s    r   display_namez'BraveFreeWebSearchProvider.display_name.   s    $r   c                0    ddl m} t         |d            S )zFReturn True when ``BRAVE_SEARCH_API_KEY`` is set to a non-empty value.r   get_provider_envBRAVE_SEARCH_API_KEY)agent.web_search_providerr   bool)r   r   s     r   is_availablez'BraveFreeWebSearchProvider.is_available2   s    >$%;<==r   c                     y)NTr
   r   s    r   supports_searchz*BraveFreeWebSearchProvider.supports_search8   s    r   c                     y)NFr
   r   s    r   supports_extractz+BraveFreeWebSearchProvider.supports_extract;   s    r   c                   ddl }ddlm}  |d      }|sdddS t        dt	        t        |      d	            }	 |j                  t        ||d
|ddd      }|j                          	 |j                         }	|	j                  d      xs i j                  dg       xs g }
|
d| }t#        |      D cg c]Z  \  }}t%        |j                  dd            t%        |j                  dd            t%        |j                  dd            |dz   d\ }}}t        j'                  d|t)        |      t)        |
      |       dd|idS # |j                  $ r<}t        j                  d|       dd|j                  j                   dcY d}~S d}~w|j                  $ r(}t        j                  d|       dd| dcY d}~S d}~ww xY w# t         $ r%}t        j                  d|       dddcY d}~S d}~ww xY wc c}}w )zExecute a search against the Brave Search API.

        Returns ``{"success": True, "data": {"web": [{"title", "url", "description", "position"}]}}``
        on success, or ``{"success": False, "error": str}`` on failure.
        r   Nr   r   FzBRAVE_SEARCH_API_KEY is not set)successerror      )qcountzapplication/json)zX-Subscription-TokenAccept   )paramsheaderstimeoutzBrave Search HTTP error: %szBrave Search returned HTTP zBrave Search request error: %szCould not reach Brave Search: z%Brave Search response parse error: %sz-Could not parse Brave Search response as JSONwebresultstitle urldescription)r,   r.   r/   positionz5Brave Search '%s': %d results (from %d raw, limit %d)T)r   data)httpxr   r   maxminintget_BRAVE_ENDPOINTraise_for_statusHTTPStatusErrorloggerwarningresponsestatus_codeRequestErrorjson	Exception	enumeratestrinfolen)r   querylimitr2   r   api_keyr$   respexcr1   raw_results	truncatedirweb_resultss                  r   searchz!BraveFreeWebSearchProvider.search>   s    	>"#9:$/PQQ As3u:r*+	W99"U3,30   D !!#	`99;D
 xx,"11)R@FB'	 "),
 1 QUU7B/0155+,"155#;<E	
 
 	C	
  %)=>>K $$ 	NN8#> 6s||7O7O6PQ  !! 	WNN;SA$1OPSu/UVV	W  	`NNBCH$/^__	`
sT   /E
 *G 6AG>
G
1F
G
G
"G?G
G
	G;G60G;6G;c                    dddddddgdS )	Nr   freeu1   Free-tier API key — 2k queries/mo, search only.r   z Brave Search API key (free tier)zhttps://brave.com/search/api/)keypromptr.   )r   badgetagenv_varsr
   r   s    r   get_setup_schemaz+BraveFreeWebSearchProvider.get_setup_schema   s*    )F 2@:	
 	
r   N)returnrB   )rX   r   )   )rE   rB   rF   r5   rX   Dict[str, Any])rX   rZ   )__name__
__module____qualname____doc__propertyr   r   r   r   r   rO   rW   r
   r   r   r   r   !   sJ      
 % %>A?F
r   r   )r^   
__future__r   loggingostypingr   r   r   r   	getLoggerr[   r:   r7   r   r
   r   r   <module>re      sA   & #  	  7			8	$Bl
!2 l
r   