
    `gj                        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y)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)WebSearchProviderc                :   ddl }ddlm}  |d      }|st        d       |d      xs d}t	        |      }||d<   | d	| j                  d	       }t        j                  d
| |       |j                  ||d      }|j                          |j                         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   )endpointpayloadr   r
   r   base_urlurlresponses           N/root/.hermes/venv/lib/python3.12/site-packages/plugins/web/tavily/provider.py_tavily_requestr!   #   s     :/0G>
 	

   12N6NH7mG GIJa,-
.C
KK)8S9zz#GRz8H==?    c           	         g }t        | j                  dg             D ]N  \  }}|j                  |j                  dd      |j                  dd      |j                  dd      |dz   d       P 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_resultsr4   @   s    Kx||Ir:; 
	6GR0zz%,%zz)R8E		

 e[%9::r"   c                z   g }| j                  dg       D ]t  }|j                  d|      }|j                  dd      xs |j                  dd      }|j                  ||j                  dd      ||||j                  dd      dd       v | j                  d	g       D ]L  }|j                  |j                  d|      ddd|j                  d
d      d|j                  d|      id       N | j                  dg       D ]9  }t        |t              r|n
t        |      }|j                  |ddddd|id       ; |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'   r6   metadatafailed_resultserrorzextraction failedr7   )r   r%   r'   r6   r:   r8   failed_urls)r/   r0   
isinstancestr)	r   fallback_url	documentsr3   r   rawfailfail_urlurl_strs	            r    _normalize_tavily_documentsrD   O   s[    ')I,,y"- 
jj-jj+Hvzz)R/HGR0"*-

7B8OP	

 -r2 

xx|4!'+>?($((5,*GH		


 LL3 
(37(S]!,('2		

 r"   c                  f    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y
)TavilyWebSearchProviderz!Tavily search + extract provider.c                     y)Ntavily selfs    r    namezTavilyWebSearchProvider.name       r"   c                     y)NTavilyrI   rJ   s    r    display_namez$TavilyWebSearchProvider.display_name   rM   r"   c                0    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
   bool)rK   r
   s     r    is_availablez$TavilyWebSearchProvider.is_available   s    >$%5677r"   c                     yNTrI   rJ   s    r    supports_searchz'TavilyWebSearchProvider.supports_search       r"   c                     yrU   rI   rJ   s    r    supports_extractz(TavilyWebSearchProvider.supports_extract   rW   r"   c                H   	 ddl m}  |       rdddS t        j                  d||       t	        d|t        |d      ddd	      }t        |      S # t        $ r}dt        |      dcY d
}~S d
}~wt        $ r(}t        j                  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   )querymax_resultsinclude_raw_contentinclude_imagesNzTavily search error: %szTavily search failed: )tools.interruptr\   r   r   r!   minr4   r   r=   	Exceptionwarning)rK   r`   limitr\   r@   excs         r    r^   zTavilyWebSearchProvider.search   s    	O6#(=AAKK8%G!"#&ub>+0&+	C 4C88 	9$s3x88 	ONN4c:$1Gu/MNN	Os4   A <A 	B!A-'B!-B!9BB!B!c           
        	 ddl m}  |       r|D cg c]  }|ddd
 c}S t        j                  dt	        |             t        d|dd	      }t        ||r
|d   
      S d
      S c c}w # t        $ r.}|D cg c]  }|ddt        |      d nc c}w c}cY d}~S d}~wt        $ r>}t        j                  d|       |D cg c]  }|ddd| d nc c}w c}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   r[   r]   r&   )r   r:   r%   zTavily extract: %d URL(s)extractF)urlsrc   )r>   )r   r%   r'   r:   NzTavily extract error: %szTavily extract failed: )rd   r\   r   r   lenr!   rD   r   r=   rf   rg   )rK   rl   kwargsr\   ur@   ri   s          r    rk   zTavilyWebSearchProvider.extract   s
   	6MQHIAC  KK3SY?! &+C /T$q' 79   	]W[\RSArCHM\\\ 	NN5s;  B2BYZ]Y^@_`  	sb   A/ A*A/ ?A/ #A/ *A/ /	C+8B!<BB!C+!C+-C&CC& C+&C+c                    dddddddgdS )	NrO   paidz!Search + extract in one provider.r   zTavily API keyzhttps://app.tavily.com/home)keypromptr   )rL   badgetagenv_varsrI   rJ   s    r    get_setup_schemaz(TavilyWebSearchProvider.get_setup_schema   s*    6 ,.8	
 	
r"   N)returnr=   )rx   rR   )   )r`   r=   rh   intrx   Dict[str, Any])rl   z	List[str]rn   r   rx   List[Dict[str, Any]])rx   r{   )__name__
__module____qualname____doc__propertyrL   rP   rS   rV   rY   r^   rk   rw   rI   r"   r    rF   rF      sK    +   8O2 D
r"   rF   )r   r=   r   r{   rx   r{   )r   r{   rx   r{   )r&   )r   r{   r>   r=   rx   r|   )r   
__future__r   loggingostypingr   r   r   r   r   	getLoggerr}   r   r!   r4   rD   rF   rI   r"   r    <module>r      sl   . #  	 " " 7			8	$:;  3500,/00f^
/ ^
r"   