
    nSj                        d Z ddlmZ ddlZddlZddlmZmZmZ ddl	m
Z
  ej        e          ZddZddZ	 dddZ G d de
          ZdS )u  Tavily web search + content extraction — plugin form.

Subclasses :class:`agent.web_search_provider.WebSearchProvider`. Two
capabilities advertised:

- ``supports_search()``  -> True (Tavily ``/search``)
- ``supports_extract()`` -> True (Tavily ``/extract``)

Both are sync — the underlying call is ``httpx.post(...)``.

Config keys this provider responds to::

    web:
      search_backend: "tavily"     # explicit per-capability
      extract_backend: "tavily"    # explicit per-capability
      backend: "tavily"            # shared fallback for both

Env vars::

    TAVILY_API_KEY=...           # https://app.tavily.com/home (required)
    TAVILY_BASE_URL=...          # optional override of https://api.tavily.com
    )annotationsN)AnyDictList)WebSearchProviderendpointstrpayloadDict[str, Any]returnc                |   ddl }ddlm}  |d          }|st          d           |d          pd}t	          |          }||d<   | d	|                     d	           }t                              d
| |           |                    ||d          }|	                                 |
                                S )zPOST to the Tavily API and return the parsed JSON response.

    Mirrors :func:`tools.web_tools._tavily_request`. Raises ``ValueError``
    when ``TAVILY_API_KEY`` is unset; the caller catches and surfaces as
    a typed error response.
    r   Nget_provider_envTAVILY_API_KEYz\TAVILY_API_KEY environment variable not set. Get your API key at https://app.tavily.com/homeTAVILY_BASE_URLzhttps://api.tavily.comapi_key/zTavily %s request to %s<   )jsontimeout)httpxagent.web_search_providerr   
ValueErrordictlstriploggerinfopostraise_for_statusr   )r   r
   r   r   r   base_urlurlresponses           =/home/ice/.hermes/hermes-agent/plugins/web/tavily/provider.py_tavily_requestr$   #   s     LLL::::::/00G 
>
 
 	

   122N6NH7mmG GI
.
.,,
.
.C
KK)8S999zz#GRz88H==??    r"   c           	        g }t          |                     dg                     D ]^\  }}|                    |                    dd          |                    dd          |                    dd          |dz   d           _dd	|id
S )zEMap Tavily ``/search`` response to ``{success, data: {web: [...]}}``.resultstitle r!   content   )r(   r!   descriptionpositionTweb)successdata)	enumerategetappend)r"   web_resultsiresults       r#    _normalize_tavily_search_resultsr7   @   s    Kx||Ir::;; 
 
	6GR00zz%,,%zz)R88E	 	
 	
 	
 	
 e[%9:::r%   r)   fallback_urlList[Dict[str, Any]]c                   g }|                      dg           D ]}|                     d|          }|                     dd          p|                     dd          }|                    ||                     dd          ||||                     dd          dd           |                      d	g           D ]\}|                    |                     d|          ddd|                     d
d          d|                     d|          id           ]|                      dg           D ]F}t          |t                    r|nt          |          }|                    |ddddd|id           G|S )a4  Map Tavily ``/extract`` response to standard documents.

    Documents follow the legacy LLM post-processing shape::

        {"url", "title", "content", "raw_content", "metadata"}

    Failures (``failed_results``, ``failed_urls``) become result entries
    with an ``error`` field rather than raising.
    r'   r!   raw_contentr)   r*   r(   )	sourceURLr(   )r!   r(   r*   r;   metadatafailed_resultserrorzextraction failedr<   )r!   r(   r*   r;   r?   r=   failed_urls)r2   r3   
isinstancer	   )	r"   r8   	documentsr6   r!   rawfailfail_urlurl_strs	            r#   _normalize_tavily_documentsrG   O   s    ')I,,y"-- 
 
jj--jj++Hvzz)R/H/HGR00"*-

7B8O8OPP 	
 	
 	
 	
 -r22 

 

xx|44!'+>??($((5,*G*GH 		
 		
 		
 		
 LL33 
 
(377J((S]]!,('2 		
 		
 		
 		
 r%   c                  t    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dZdS )TavilyWebSearchProviderz!Tavily search + extract provider.r   r	   c                    dS )Ntavily selfs    r#   namezTavilyWebSearchProvider.name       xr%   c                    dS )NTavilyrL   rM   s    r#   display_namez$TavilyWebSearchProvider.display_name   rP   r%   boolc                >    ddl m} t           |d                    S )z@Return True when ``TAVILY_API_KEY`` is set to a non-empty value.r   r   r   )r   r   rT   )rN   r   s     r#   is_availablez$TavilyWebSearchProvider.is_available   s/    >>>>>>$$%566777r%   c                    dS NTrL   rM   s    r#   supports_searchz'TavilyWebSearchProvider.supports_search       tr%   c                    dS rX   rL   rM   s    r#   supports_extractz(TavilyWebSearchProvider.supports_extract   rZ   r%      querylimitintr   c                   	 ddl m}  |            rdddS t                              d||           t	          d|t          |d          ddd	          }t          |          S # t          $ r}dt          |          dcY d
}~S d
}~wt          $ r-}t          
                    d|           dd| dcY d
}~S d
}~ww xY w)zExecute a Tavily search.r   is_interruptedFInterrupted)r/   r?   zTavily search: '%s' (limit=%d)search   )r^   max_resultsinclude_raw_contentinclude_imagesNzTavily search error: %szTavily search failed: )tools.interruptrc   r   r   r$   minr7   r   r	   	Exceptionwarning)rN   r^   r_   rc   rC   excs         r#   re   zTavilyWebSearchProvider.search   s'   	O666666~ B#(=AAAKK8%GGG!"#&ub>>+0&+	  C 4C888 	9 	9 	9$s3xx88888888 	O 	O 	ONN4c:::$/M/M/MNNNNNNNN	Os5   A% AA% %
C /B C C "B;5C ;C urls	List[str]kwargsr   r9   c                   	 ddl m}  |            rd |D             S t                              dt	          |                     t          d|dd          }t          ||r|d         nd	          S # t          $ rfd
|D             cY dS dwt          $ r3t          	                    d           fd|D             cY dS dww xY w)u   Extract content from one or more URLs via Tavily.

        Sync — the underlying call is httpx.post(...). Returns the legacy
        list-of-results shape; per-URL failures become items with ``error``.
        r   rb   c                    g | ]}|d dd	S )rd   r)   )r!   r?   r(   rL   ).0us     r#   
<listcomp>z3TavilyWebSearchProvider.extract.<locals>.<listcomp>   s/       HIACC  r%   zTavily extract: %d URL(s)extractF)ro   ri   r)   )r8   c                8    g | ]}|d d t                    dS )r)   r!   r(   r*   r?   )r	   rt   ru   rn   s     r#   rv   z3TavilyWebSearchProvider.extract.<locals>.<listcomp>   s,    \\\RSArCHHMM\\\r%   NzTavily extract error: %sc                $    g | ]}|d d d dS )r)   zTavily extract failed: ry   rL   rz   s     r#   rv   z3TavilyWebSearchProvider.extract.<locals>.<listcomp>   s?        B2@_Z]@_@_``  r%   )
rj   rc   r   r   lenr$   rG   r   rl   rm   )rN   ro   rq   rc   rC   rn   s        @r#   rw   zTavilyWebSearchProvider.extract   sr   	666666~  MQ    KK3SYY???! &+  C /T"9$q''r     	] 	] 	]\\\\W[\\\\\\\\\ 	 	 	NN5s;;;           	s5   A5 AA5 5
C?BCC(CCCc                    dddddddgdS )	NrR   paidz!Search + extract in one provider.r   zTavily API keyzhttps://app.tavily.com/home)keypromptr!   )rO   badgetagenv_varsrL   rM   s    r#   get_setup_schemaz(TavilyWebSearchProvider.get_setup_schema   s4    6 ,.8 	
 
 	
r%   N)r   r	   )r   rT   )r]   )r^   r	   r_   r`   r   r   )ro   rp   rq   r   r   r9   )r   r   )__name__
__module____qualname____doc__propertyrO   rS   rV   rY   r\   re   rw   r   rL   r%   r#   rI   rI      s        ++   X    X8 8 8 8      O O O O O2       D
 
 
 
 
 
r%   rI   )r   r	   r
   r   r   r   )r"   r   r   r   )r)   )r"   r   r8   r	   r   r9   )r   
__future__r   loggingostypingr   r   r   r   r   	getLoggerr   r   r$   r7   rG   rI   rL   r%   r#   <module>r      s    . # " " " " "  				 " " " " " " " " " " 7 7 7 7 7 7		8	$	$   :; ; ; ;  350 0 0 0 0f^
 ^
 ^
 ^
 ^
/ ^
 ^
 ^
 ^
 ^
r%   