
    PL
j                    ~    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 G d de	          ZdS )u  SearXNG search — plugin form.

Subclasses :class:`agent.web_search_provider.WebSearchProvider`. Same JSON
API call (``/search?format=json``), same result normalization. The legacy
in-tree module ``tools.web_providers.searxng`` was removed in the same
commit that moved this code under ``plugins/``; this file is now the
canonical implementation.

Search-only — SearXNG aggregates results from upstream engines but does not
fetch/extract arbitrary URLs. ``supports_extract()`` returns False.

Config keys this provider responds to::

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

Env var::

    SEARXNG_URL=http://localhost:8080
    )annotationsN)AnyDict)WebSearchProviderc                  l    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dS )SearXNGWebSearchProviderz*Search via a user-hosted SearXNG instance.returnstrc                    dS )Nsearxng selfs    @/home/kuhnn/.hermes/hermes-agent/plugins/web/searxng/provider.pynamezSearXNGWebSearchProvider.name%       y    c                    dS )NSearXNGr   r   s    r   display_namez%SearXNGWebSearchProvider.display_name)   r   r   boolc                j    t          t          j        dd                                                    S )z(Return True when ``SEARXNG_URL`` is set.SEARXNG_URL )r   osgetenvstripr   s    r   is_availablez%SearXNGWebSearchProvider.is_available-   s(    BImR006688999r   c                    dS )NTr   r   s    r   supports_searchz(SearXNGWebSearchProvider.supports_search1   s    tr   c                    dS )NFr   r   s    r   supports_extractz)SearXNGWebSearchProvider.supports_extract4   s    ur      querylimitintDict[str, Any]c                   ddl }t          j        dd                                                              d          }|sdddS |d	d
d}	 |                    | d|dddi          }|                                 n|# |j        $ r7}t          	                    d|           dd|j
        j         dcY d}~S d}~w|j        $ r0}t          	                    d|           dd| d| dcY d}~S d}~ww xY w	 |                                }n7# t          $ r*}t          	                    d|           dddcY d}~S d}~ww xY w|                    dg           }	t          |	d d          d|         }
d t!          |
          D             }t                              d|t%          |          t%          |	          |           dd|idS ) z9Execute a search against the configured SearXNG instance.r   Nr   r   /FzSEARXNG_URL is not set)successerrorjson   )qformatpagenoz/search   Acceptzapplication/json)paramstimeoutheaderszSearXNG HTTP error: %szSearXNG returned HTTP zSearXNG request error: %szCould not reach SearXNG at z: z SearXNG response parse error: %sz(Could not parse SearXNG response as JSONresultsc                H    t          |                     dd                    S )Nscorer   )floatget)rs    r   <lambda>z1SearXNGWebSearchProvider.search.<locals>.<lambda>h   s    %gq 1 122 r   T)keyreversec           
         g | ]r\  }}t          |                    d d                    t          |                    dd                    t          |                    dd                    |dz   dsS )titler   urlcontentr-   )r@   rA   descriptionposition)r
   r:   ).0ir;   s      r   
<listcomp>z3SearXNGWebSearchProvider.search.<locals>.<listcomp>l   s     
 
 
 1 QUU7B//00155++,,"155B#7#788E	 
 
 
r   z7SearXNG search '%s': %d results (from %d raw, limit %d)web)r*   data)httpxr   r   r   rstripr:   raise_for_statusHTTPStatusErrorloggerwarningresponsestatus_codeRequestErrorr,   	Exceptionsorted	enumerateinfolen)r   r$   r%   rJ   base_urlr3   respexcrI   raw_resultssorted_resultsweb_resultss               r   searchzSearXNGWebSearchProvider.search7   s   9]B//5577>>sCC 	I$/GHHH "
 "
	99$$$!#56	   D !!####$ 	 	 	NN3S999 L#,2JLL        ! 	 	 	NN6<<< HxHH3HH       		99;;DD 	 	 	NN=sCCC C       	 hhy"--  22
 
 
 5&	
 
 ".11
 
 
 	E	
 	
 	
  %)=>>>sN   2B   
C9
,B<6C9<C9	%C4.C94C9=D 
EE;EEc                    dddddddgdS )	Nr   u   free · self-hostedzHFree, privacy-respecting metasearch. Point SEARXNG_URL at your instance.r   z1SearXNG instance URL (e.g. http://localhost:8080)zhttps://searx.space/)r=   promptrA   )r   badgetagenv_varsr   r   s    r   get_setup_schemaz)SearXNGWebSearchProvider.get_setup_schema   s4    *] )Q1 	
 
 	
r   N)r	   r
   )r	   r   )r#   )r$   r
   r%   r&   r	   r'   )r	   r'   )__name__
__module____qualname____doc__propertyr   r   r   r    r"   r^   rd   r   r   r   r   r   "   s        44   X    X: : : :      G? G? G? G? G?R
 
 
 
 
 
r   r   )rh   
__future__r   loggingr   typingr   r   agent.web_search_providerr   	getLoggerre   rN   r   r   r   r   <module>ro      s    , # " " " " "  				         7 7 7 7 7 7		8	$	$j
 j
 j
 j
 j
0 j
 j
 j
 j
 j
r   