
    `gj                        d Z ddlmZ ddlmZ ddlZddlmZm	Z	 ddl
mZ  ej                  e      ZdZd
dZ G d d	e      Zy)u  DuckDuckGo search — plugin form (via the ``ddgs`` package).

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

The ``ddgs`` package is an optional dependency. ``is_available()`` reflects
whether the package is importable; the plugin still registers either way so
``hermes tools`` can prompt the user to install it.
    )annotationsN)AnyDict)WebSearchProvider   c                   ddl m} g } |d      5 }t        |j                  | |            D ]  \  }}||k\  r n~t	        |j                  d      xs |j                  d      xs d      }|j                  t	        |j                  d	d            |t	        |j                  d
d            |dz   d        ddd       |S # 1 sw Y   |S xY w)aC  Run the blocking ddgs query and return normalized hits.

    Module-level (not a closure) so tests can patch it directly without
    spawning a real multi-second worker thread. ``DDGS(timeout=...)`` bounds
    each individual HTTP request; the overall wall-clock cap is enforced by
    the caller via a future timeout.
    r   )DDGS
   timeout)max_resultshrefurl titlebody   )r   r   descriptionpositionN)ddgsr	   	enumeratetextstrgetappend)query
safe_limitr	   resultsclientihitr   s           L/root/.hermes/venv/lib/python3.12/site-packages/plugins/web/ddgs/provider.py_run_ddgs_searchr#      s     $&G	b	 VEz JK 	FAsJcggfo==2>CNN "!56#&swwvr':#; !A			 N Ns   B(CC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	)DDGSWebSearchProvidera  DuckDuckGo HTML-scrape search provider.

    No API key needed. Rate limits are enforced server-side by DuckDuckGo;
    the provider surfaces ``DuckDuckGoSearchException`` and other ddgs errors
    as ``{"success": False, "error": ...}`` rather than raising.
    c                     y)Nr    selfs    r"   namezDDGSWebSearchProvider.nameB   s        c                     y)NDuckDuckGo (ddgs)r'   r(   s    r"   display_namez"DDGSWebSearchProvider.display_nameF   s    "r+   c                ,    	 ddl }y# t        $ r Y yw xY w)u   Return True when the ``ddgs`` package is importable.

        Probes the import once; cheap because Python caches the import. Must
        NOT perform network I/O — runs at tool-registration time and on every
        ``hermes tools`` paint.
        r   NTF)r   ImportError)r)   r   s     r"   is_availablez"DDGSWebSearchProvider.is_availableJ   s    	 		s    	c                     y)NTr'   r(   s    r"   supports_searchz%DDGSWebSearchProvider.supports_searchX   s    r+   c                     y)NFr'   r(   s    r"   supports_extractz&DDGSWebSearchProvider.supports_extract[   s    r+   c                   	 ddl }t        dt        |            }t	        j
                  d      }	 |j                  t        ||      }	 |j                  t              }	 |j                  dd       t        j                  d|t!        |      |       dd|idS # t        $ r dddcY S w xY w# t        j                  $ r> t        j                  d	t        |       dd
t         ddcY |j                  dd       S w xY w# t        $ r;}t        j                  d|       dd| dcY d}~|j                  dd       S d}~ww xY w# |j                  dd       w xY w)a  Execute a DuckDuckGo search and return normalized results.

        The synchronous ``ddgs`` call is run in a worker thread with a hard
        wall-clock timeout (``_SEARCH_TIMEOUT_SECS``) so a hung search cannot
        block the shared agent loop indefinitely (#36776).
        r   NFu8   ddgs package is not installed — run `pip install ddgs`)successerrorr   )max_workersr   z-DDGS search timed out after %ds for query: %rz"DuckDuckGo search timed out after uh   s — DuckDuckGo may be rate-limiting or slow. Try again later or switch to a different search provider.T)waitcancel_futureszDDGS search error: %szDuckDuckGo search failed: z'DDGS search '%s': %d results (limit %d)web)r7   data)r   r0   maxint_cfThreadPoolExecutorsubmitr#   result_SEARCH_TIMEOUT_SECSTimeoutErrorloggerwarningshutdown	Exceptioninfolen)	r)   r   limitr   r   poolfutureweb_resultsexcs	            r"   searchzDDGSWebSearchProvider.search^   st   	 CJ'
 %%!4	;[[!15*EF$mm4HmI, MMuTM:=uc+FVX]^%)=>>Y  	 S 	( ## C(%
  %<=Q<R SD D   MMuTM:+  	SNN2C8$1KC5/QRR MMuTM:	S MMuTM:s^   B D 
B0 B-,B-0;D+D  DD 	EE*E+E EE E c                    dddg ddS )Nr-   u   free · no key · search onlyuR   Search via the ddgs Python package — no API key (pair with any extract provider)r   )r*   badgetagenv_vars
post_setupr'   r(   s    r"   get_setup_schemaz&DDGSWebSearchProvider.get_setup_schema   s    '4g !
 	
r+   N)returnr   )rX   bool)   )r   r   rL   r?   rX   Dict[str, Any])rX   r[   )__name__
__module____qualname____doc__propertyr*   r.   r1   r3   r5   rQ   rW   r'   r+   r"   r%   r%   :   sI       # #5?n	
r+   r%   )r   r   r   r?   rX   zlist[dict[str, Any]])r_   
__future__r   concurrent.futuresfuturesr@   loggingtypingr   r   agent.web_search_providerr   	getLoggerr\   rF   rD   r#   r%   r'   r+   r"   <module>rh      sI   
 #     7			8	$  6d
- d
r+   