
    Rj<                        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 }t          j        d          }|st          d          t          j        d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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osgetenv
ValueErrordictlstriploggerinfopostraise_for_statusr   )r   r
   r   r   base_urlurlresponses          @/home/ubuntu/.hermes/hermes-agent/plugins/web/tavily/provider.py_tavily_requestr#   #   s     LLLi())G 
>
 
 	

 y*,DEEH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_resultsr6   >   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)r1   r2   
isinstancer	   )	r!   r7   	documentsr5   r    rawfailfail_urlurl_strs	            r"   _normalize_tavily_documentsrF   M   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TavilyrK   rL   s    r"   display_namez$TavilyWebSearchProvider.display_name   rO   r$   boolc                j    t          t          j        dd                                                    S )z@Return True when ``TAVILY_API_KEY`` is set to a non-empty value.r   r(   )rS   r   r   striprL   s    r"   is_availablez$TavilyWebSearchProvider.is_available   s)    BI.3399;;<<<r$   c                    dS NTrK   rL   s    r"   supports_searchz'TavilyWebSearchProvider.supports_search       tr$   c                    dS rX   rK   rL   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#   minr6   r   r	   	Exceptionwarning)rM   r^   r_   rc   rB   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   r8   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'   rK   ).0us     r"   
<listcomp>z3TavilyWebSearchProvider.extract.<locals>.<listcomp>   s/       HIACC  r$   zTavily extract: %d URL(s)extractF)ro   ri   r(   )r7   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   rK   rz   s     r"   rv   z3TavilyWebSearchProvider.extract.<locals>.<listcomp>   s?        B2@_Z]@_@_``  r$   )
rj   rc   r   r   lenr#   rF   r   rl   rm   )rM   ro   rq   rc   rB   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 )	NrQ   paidz!Search + extract in one provider.r   zTavily API keyzhttps://app.tavily.com/home)keypromptr    )rN   badgetagenv_varsrK   rL   s    r"   get_setup_schemaz(TavilyWebSearchProvider.get_setup_schema   s4    6 ,.8 	
 
 	
r$   N)r   r	   )r   rS   )r]   )r^   r	   r_   r`   r   r   )ro   rp   rq   r   r   r8   )r   r   )__name__
__module____qualname____doc__propertyrN   rR   rV   rY   r\   re   rw   r   rK   r$   r"   rH   rH      s        ++   X    X= = = =      O O O O O2       D
 
 
 
 
 
r$   rH   )r   r	   r
   r   r   r   )r!   r   r   r   )r(   )r!   r   r7   r	   r   r8   )r   
__future__r   loggingr   typingr   r   r   agent.web_search_providerr   	getLoggerr   r   r#   r6   rF   rH   rK   r$   r"   <module>r      s    . # " " " " "  				 " " " " " " " " " " 7 7 7 7 7 7		8	$	$   6; ; ; ;  350 0 0 0 0f\
 \
 \
 \
 \
/ \
 \
 \
 \
 \
r$   