
    `gj                        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	dZ G d de	      Zy)
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                     	 ddl m}   | d      }|t        j                  dd      }|xs dj                         S # t        $ r d}Y 9w xY w)zMReturn SEARXNG_URL from Hermes config-aware env, falling back to process env.r   )get_env_valueSEARXNG_URLN )hermes_cli.configr   	Exceptionosgetenvstrip)r   vals     O/root/.hermes/venv/lib/python3.12/site-packages/plugins/web/searxng/provider.py_searxng_urlr   "   sT    3M* {iir*I2	  s   < A
	A
c                  ^    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	)SearXNGWebSearchProviderz*Search via a user-hosted SearXNG instance.c                     y)Nsearxng selfs    r   namezSearXNGWebSearchProvider.name2           c                     y)NSearXNGr   r   s    r   display_namez%SearXNGWebSearchProvider.display_name6   r   r   c                (    t        t                     S )z(Return True when ``SEARXNG_URL`` is set.)boolr   r   s    r   is_availablez%SearXNGWebSearchProvider.is_available:   s    LN##r   c                     y)NTr   r   s    r   supports_searchz(SearXNGWebSearchProvider.supports_search>   s    r   c                     y)NFr   r   s    r   supports_extractz)SearXNGWebSearchProvider.supports_extractA   s    r   c                   ddl }t               j                  d      }|sdddS |ddd	}	 |j                  | d
|dddi      }|j	                          	 |j                         }|j                  dg       }	t        |	d d      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| 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 )"z9Execute a search against the configured SearXNG instance.r   N/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                8    t        | j                  dd            S )Nscorer   )floatget)rs    r   <lambda>z1SearXNGWebSearchProvider.search.<locals>.<lambda>u   s    %gq 12 r   T)keyreversetitler
   urlcontent)r>   r?   descriptionpositionz7SearXNG search '%s': %d results (from %d raw, limit %d)web)r)   data)httpxr   rstripr9   raise_for_statusHTTPStatusErrorloggerwarningresponsestatus_codeRequestErrorr+   r   sorted	enumeratestrinfolen)r   querylimitrE   base_urlr2   respexcrD   raw_resultssorted_resultsir:   web_resultss                 r   searchzSearXNGWebSearchProvider.searchD   s   >((-$/GHH "
	99*G$!#56	  D !!#	99;D hhy"-  2
 5	 ".1
 1 QUU7B/0155+,"155B#78E	
 
 	E	
  %)=>>c $$ 	NN3S9 1#,,2J2J1KL  !! 	NN6< 6xj3%H 	  	NN=sC C 	 
sT   *D- F3 AG$-F0<1E3-F03F0 F+%F0+F03	G!<GG!G!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<   promptr?   )r   badgetagenv_varsr   r   s    r   get_setup_schemaz)SearXNGWebSearchProvider.get_setup_schema   s*    *] )Q1	
 	
r   NreturnrP   )rd   r!   )   )rS   rP   rT   intrd   Dict[str, Any])rd   rg   )__name__
__module____qualname____doc__propertyr   r   r"   r$   r&   r\   rb   r   r   r   r   r   /   sF    4   $G?R
r   r   rc   )rk   
__future__r   loggingr   typingr   r   agent.web_search_providerr   	getLoggerrh   rI   r   r   r   r   r   <module>rr      sA   , #  	  7			8	$
j
0 j
r   