+
    kHàj‘7  ã                  ó  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIHtHtH	t	H
t
 ^ RIHtHtHtHtHt ^ RIHtHtHt ]P.                  ! ]4      tRt^Zt^t]P:                  ! R]P<                  4      tR R	 lt R
 R lt!R R lt" ! R R]4      t#R# )uå  xAI Web Search â€” search-only provider backed by Grok's server-side ``web_search`` tool on the
Responses API (https://docs.x.ai/developers/tools/web-search); Grok is asked for structured JSON
so rows match every other Hermes web provider. Config: ``web.backend: "xai"``; optional ``web.xai``:
``model`` (default grok-build-0.1), ``allowed_domains`` / ``excluded_domains`` (max 5, mutually
exclusive), ``timeout`` (default 90s). Auth: Grok OAuth via ``hermes auth``, else XAI_API_KEY.
)ÚannotationsN)ÚAnyÚDictÚListÚOptional)ÚBaseWebSearchProviderÚsearch_failÚ	search_okÚsetup_schemaÚ	title_hit)Úhas_xai_credentialsÚhermes_xai_user_agentÚresolve_xai_http_credentialszgrok-build-0.1z\{[\s\S]*\}c               ó   € V ^8„  d   QhRR/# ©é   Úreturnúdict[str, Any]© )Úformats   "Ú=/home/ubuntu/.hermes/hermes-agent/plugins/web/xai/provider.pyÚ__annotate__r      s   € ÷ 
ñ 
˜nñ 
ó    c                 ó  €  ^ RI Hp  V ! 4       pR F,  p\        V\        4      '       d   VP	                  V4      MRpK.  	  \        V\        4      '       d   V# / #   \
         d#   p\        P                  RT4       / u Rp?# Rp?ii ; i)z7Read ``web.xai`` from config.yaml (returns {} on miss).)Úload_configNz!Could not load web.xai config: %s)ÚwebÚxai)Úhermes_cli.configr   Ú
isinstanceÚdictÚgetÚ	ExceptionÚloggerÚdebug)r   ÚcfgÚkeyÚexcs       r   Ú_load_xai_web_configr'      sq   € ðÝ1Ù‹mˆÛ!ˆCÜ",¨S´$×"7Ò"7�#—'‘'˜#”,¸TŠCñ "ä  ¤d×+Ò+ˆsÐ3°Ð3øÜô Ü�‰Ð8¸#Ô>Ø�	ûðús$   ‚AA ÁA ÁBÁ&BÁ=BÂBc               ó    € V ^8„  d   QhRRRR/# )r   Úvaluer   r   z	list[str]r   )r   s   "r   r   r   )   s   € ÷ Oñ O˜sð O yñ Or   c                óê   € \        V \        4      '       dX   V  Uu. uFC  p\        V\        4      '       g   K  VP                  4       '       g   K3  VP                  4       NKE  	  upR \         # . # u upi ©N)r   ÚlistÚstrÚstripÚ_MAX_DOMAIN_FILTERS)r)   Úitems   & r   Ú_coerce_domain_listr1   )   sh   € ÜoyÐzô  BF÷  pGò  pG¡UÓU¡U˜T¬j¸¼s×.CŒLÈÏ
É
ÏŒLˆD�J‰JŽL¡UÑUÐVjÔWjÐkð  Oð  MOð  OùÒUs   ›A0¸A0ÁA0c               ó$   € V ^8„  d   QhRRRRRR/# )r   r)   r   Údefaultr   r   )r   s   "r   r   r   -   s!   € ÷ ñ ˜ð  sð ¨sñ r   c                óF   €  V ! V4      #   \         \        3 d    Tu # i ; ir+   )Ú	TypeErrorÚ
ValueError)Úcastr)   r3   s   &&&r   Ú_coercer8   -   s*   € ðÙ�E‹{ÐøÜ”zÐ"ô ØŠðús   ‚
 Š Ÿ c                  óä   € ] tR t^4tRtRtRtR R ltRR R llt]	R R	 l4       t
]	R
 R l4       t]	R R l4       t]R R l4       t]	R R l4       t]	R R l4       t]	R R l4       tR R ltRtR# )ÚXAIWebSearchProvideru  Sends a structured prompt with ``tools=[{"type": "web_search"}]`` and parses the JSON Grok
returns; falls back to message annotations, then ``citations``. Trust model: Grok *generates*
the URLs/titles/descriptions and is steerable by the query text â€” validate before fetching.r   úxAI Web Search (Grok)c               ó   € V ^8„  d   QhRR/# )r   r   Úboolr   )r   s   "r   r   Ú!XAIWebSearchProvider.__annotate__<   s   € ÷ %ñ %˜dñ %r   c                ó   € \        4       # )zÈCheap probe (env var OR auth-store tokens). Deliberately NOT
``resolve_xai_http_credentials``: must never refresh tokens or take the
auth-store lock, since this runs on every ``hermes tools`` repaint.)r   ©Úselfs   &r   Úis_availableÚ!XAIWebSearchProvider.is_available<   s   € ô #Ó$Ð$r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úqueryr-   ÚlimitÚintr   r   r   )r   s   "r   r   r>   B   s&   € ÷ )Cñ )C˜Cð )C¨ð )C°Nñ )Cr   c                	ó„  €  ^ RI Hp V! 4       '       d   \        R4      #  \	        4       p\        VP                  R4      ;'       g    R4      P                  4       p\        VP                  R4      ;'       g    R4      P                  4       P                  R4      pV'       g   \        R4      # \        ^\        \        \        V^4      ^d4      4      p\        4       p\        VP                  R	4      \
        4      '       d   VR	,          P                  4       MR;'       g    \        pV P!                  V4      p	V	f   \        R4      # R	VRRRRV P#                  W4      /.RV	.RR./p
 ^ R
Ip\(        P+                  RYaY(4       T P-                  YjT\        \.        TP                  R\0        4      \0        4      TP                  R4      R8H  R7      w  rÍT'       d   T# \        T\2        4      '       d   TP                  R4      MR
p\        T\2        4      '       dY   TP                  R4      ;'       g    TP                  R4      ;'       g    Rp\(        P5                  RT4       \        RT 24      # \7        T P9                  YÂR7      4      #   \         d     EL�i ; i  \&         d    \        R4      u # i ; i) é    )Úis_interruptedÚInterruptedÚapi_keyÚ Úbase_urlzhttps://api.x.ai/v1Ú/z_No xAI credentials found. Run `hermes auth` to sign in with xAI Grok OAuth, or set XAI_API_KEY.ÚmodelNzZweb.xai.allowed_domains and web.xai.excluded_domains cannot both be set (xAI restriction).ÚinputÚroleÚuserÚcontentÚtoolsÚincludeÚno_inline_citationsz4httpx is not installed (required for xAI web search)z0xAI web search via %s: '%s' (limit=%d, model=%s)ÚtimeoutÚproviderz	xai-oauth)Úis_oauth_pathÚerrorÚmessageÚcodezunknown errorz*xAI web search returned error envelope: %szxAI returned an error: ©rF   )Útools.interruptrJ   Ú_failr!   r   r-   r    r.   ÚrstripÚmaxÚminr8   rG   r'   r   ÚDEFAULT_MODELÚ_web_search_toolÚ_build_promptÚhttpxÚImportErrorr"   ÚinfoÚ_post_responsesÚfloatÚDEFAULT_TIMEOUTr   Úwarningr	   Ú_extract_results)rA   rE   rF   rJ   ÚcredsrL   rN   r$   rP   Úweb_search_toolÚpayloadrg   Údatar[   Ú	api_errorÚerr_msgs   &&&             r   ÚsearchÚXAIWebSearchProvider.searchB   s‰  € ð	Ý6Ù×ÒÜ˜]Ó+Ð+ð  ô -Ó.ˆÜ�e—i‘i 	Ó*×0Ð0¨bÓ1×7Ñ7Ó9ˆÜ�u—y‘y Ó,×EÐEÐ0EÓF×LÑLÓN×UÑUÐVYÓZˆßÜÐzÓ{Ð{ä�A”sœ7¤3¨¨qÓ1°3Ó7Ó8ˆÜ"Ó$ˆÜ)3°C·G±G¸GÓ4DÄc×)JÒ)J��W•×#Ñ#Ô%ÐPR×dÐdÔWdˆØ×/Ñ/°Ó4ˆØÒ"äÐuÓvÐvà#*¨E°7¸fÀfÈiÐY]×YkÑYkÐlqÓYyÐ=zÐ<{ð  ~Eð  HWð  GXð  Zcð  f{ð  e|ð  #}ˆð	QÛô 	�‰ÐFÈÐY^ÔfØ×*Ñ*Ø˜w¬´°s·w±w¸yÌ/Ó7ZÔ\kÓ(lØ Ÿ9™9 ZÓ0°KÑ?ð +ó 
‰ˆ÷ ØˆLô *4°D¼$×)?Ò)?�D—H‘H˜WÔ%ÀTˆ	Ü�i¤×&Ò&Ø—m‘m IÓ.×ZÐZ°)·-±-ÀÓ2G×ZÐZÈ?ˆGÜ�N‰NÐGÈÔQÜÐ2°7°)Ð<Ó=Ð=ä˜×.Ñ.¨tÐ.ÓAÓBÐBøôI ô 	Úð	ûô& ô 	QÜÐOÓPÒPð	Qús(   ‚J •
J Å-J& ÊJ#Ê"J#Ê&J?Ê>J?c               ó    € V ^8„  d   QhRRRR/# )r   r$   r   r   zOptional[dict[str, Any]]r   )r   s   "r   r   r>   n   s   € ÷ añ a˜nð aÐ1Iñ ar   c           	     ó  € R Uu/ uF  q\        V P                  V4      4      bK  	  ppVP                  4        UUu/ uF  w  rV'       g   K  WbK  	  ppp\        V4      ^8X  d   R# V'       d   RRRV/# RR/# u upi u uppi )z�``web_search`` tool spec with optional domain filters; None when both
allowed and excluded are set (xAI rejects the combination).NÚtypeÚ
web_searchÚfilters)Úallowed_domainsÚexcluded_domains)r1   r    ÚitemsÚlen)r$   Úkr{   Úvs   &   r   re   Ú%XAIWebSearchProvider._web_search_toolm   sƒ   € ñ @gÓgÑ?f¸!Ô)¨#¯'©'°!«*Ó5Ò5Ñ?fˆÐgØ$+§M¡M¤OÔ9¡O™D˜A´q”4�1’4¡OˆÑ9Üˆw‹<˜1ÔÙß=D�˜ i°Ð9Ð`È6ÐS_ÐJ`Ð`ùò	 hùÛ9s   …#A;½B ÁB c               ó0   € V ^8„  d   QhRRRRRRRRRR	R
R/# )r   rN   r-   rq   r   rL   rX   rk   rZ   r=   r   z$tuple[Any, Optional[dict[str, Any]]]r   )r   s   "r   r   r>   x   sE   € ÷ .Rñ .R #ð .R°ð .RÈð .RÐW\ð .RÐptð .Rð  z^ñ .Rr   c          	     ó  a€ ^ RI pRRS 2RRR\        4       /pR V3R llpRp\        ^4       F+  p	 VP                  V  R	2WaVR
7      pVP	                  4         M	  Vf   R\        R4      3#  VP!                  4       R3#   TP
                   d÷   p
T
P                  e   T
P                  P                  M^ pTR8X  dE   T	^ 8X  d>   T'       d6   \        P                  R4       T! 4       ;p'       d   TRT 2uoTR&    Rp
?
KÕ   T
P                  e   T
P                  P                  R,          MRpM  \         d    Rp Mi ; i\        P                  RY½4       R\        RT RT 2P                  4       4      3u Rp
?
u # Rp
?
iTP                   d3   p
\        P                  RT
4       R\        RT
 24      3u Rp
?
u # Rp
?
ii ; i  \         d.   p
\        P                  RT
4       R\        R4      3u Rp
?
# Rp
?
ii ; i)uF  POST ``/responses`` â†’ ``(parsed_json, None)`` or ``(None, failure_envelope)``.

Two attempts: on a first-call 401 with OAuth creds, force-refresh once and retry
(opaque tokens the resolver can't pre-check; mid-window revocation/rotation).
XAI_API_KEY creds can't be refreshed, so they skip the retry rather than burn quota.
NÚAuthorizationzBearer zContent-Typezapplication/jsonz
User-Agentc               ó   € V ^8„  d   QhRR/# )r   r   r-   r   )r   s   "r   r   Ú:XAIWebSearchProvider._post_responses.<locals>.__annotate__�   s   € ÷ 	ñ 	 ñ 	r   c                 óô   <€  \        \        RSR7      P                  R4      ;'       g    R4      P                  4       p V S8w  d   V # R#   \         d"   p\
        P                  RT4        Rp?R# Rp?ii ; i)zeNew bearer after a 401, or "" when refresh fails / returns the same token (retry would be pointless).T)Úforce_refreshÚapi_key_hintrL   rM   z1xAI web search OAuth refresh after 401 failed: %sN)r-   r   r    r.   r!   r"   rm   )r%   Úrefresh_excrL   s     €r   Ú_refreshed_keyÚ<XAIWebSearchProvider._post_responses.<locals>._refreshed_key�   sm   ø€ ðÜÔ6ÀTÐX_Ô`×dÑdÐenÓo×uÐuÐsuÓv×|Ñ|Ó~�Ø! Wœn�sÐ4°"Ð4øÜô Ü—‘ÐRÐT_Ô`Ýûðús"   ƒ'A «A Á	A ÁA7ÁA2Á2A7z
/responses)ÚheadersÚjsonrX   i‘  zQxAI web search got 401 on first attempt; forcing OAuth refresh and retrying once.:Ni,  NrM   zxAI web search HTTP %d: %szxAI web search returned HTTP z: z xAI web search request error: %szCould not reach xAI: z#xAI web search produced no responsezxAI web search bad JSON: %sz/Could not parse xAI Responses API reply as JSON)rg   r   ÚrangeÚpostÚraise_for_statusÚHTTPStatusErrorÚresponseÚstatus_coder"   ri   Útextr!   rm   r`   ra   ÚRequestErrorr�   )rN   rq   rL   rX   rZ   rg   rŽ   rŒ   ÚrespÚattemptr&   ÚstatusÚnew_keyÚbodys   &&f&$         r   rj   Ú$XAIWebSearchProvider._post_responsesw   s  ø€ ó 	Ø" g¨g¨YÐ$7¸ÐI[Ð]iô  lAó  lCð  Dˆ÷	ð 	ð ˆÜ˜Q–xˆGðBØ—z‘z X J¨jÐ"9À7Ðbi�zÓj�Ø×%Ñ%Ô'Ùñ	  ð* Š<ØœÐDÓEÐEÐEð	RØ—9‘9“; Ð$Ð$øð' ×(Ñ(ô ^Ø58·\±\Ò5M˜Ÿ™×1Ò1ÐST�Ø˜S”= W°¤\·mÜ—K‘KÐ sÔtÙ"0Ó"2Ð2�wÖ2Ø<CÀwÈwÈiÐEXÐ9˜ ¨Ñ!9Ý ðØ69·l±lÒ6N˜3Ÿ<™<×,Ñ,¨TÖ2ÐTV‘DøÜ ô Ø’Dðúä—‘Ð;¸VÔJØœUÐ%BÀ6À(È"ÈTÈFÐ#S×#ZÑ#ZÓ#\Ó]Ð]×]ûØ×%Ñ%ô BÜ—‘ÐAÀ3ÔGØœUÐ%:¸3¸%Ð#@ÓAÐA×AûðBûô ô 	RÜ�N‰NÐ8¸#Ô>ØœÐPÓQÐQÕQûð	Rúsƒ   ³'BÁ0G ÂG
Â;FÃ#FÃ3FÄ-D3Ä2FÄ3EÅ FÅEÅ9FÅ<G
ÆG
ÆG
Æ%GÆ=G
ÇG
ÇHÇ"H Ç:HÈ Hc               ó$   € V ^8„  d   QhRRRRRR/# )r   rE   r-   rF   rG   r   r   )r   s   "r   r   r>   ©   s!   € ÷ 

ñ 

˜Sð 

¨ð 

°ñ 

r   c                ó   € RV RV  2# )zˆAsk for a JSON *object* (cheap to match with ``_JSON_BLOCK_RE``) and forbid
prose/fences/inline citations to keep the payload parseable.u<  Use the web_search tool to find current information for the query below, then respond with ONLY a single JSON object â€” no prose, no markdown fences, no inline citation links â€” matching this exact schema:

{"results": [{"title": "string", "url": "string", "description": "1-2 sentence summary"}]}

Return at most zy results, ordered by relevance, with absolute https:// URLs. If no usable results exist, return {"results": []}.

Query: r   )rE   rF   s   &&r   rf   Ú"XAIWebSearchProvider._build_prompt¨   s"   € ð
ð $˜Wð %à�Wðð	
r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úresponse_datar   rF   rG   r   úlist[dict[str, Any]]r   )r   s   "r   r   r>   ¶   s'   € ÷ 
añ 
a¨^ð 
aÀsð 
aÐOcñ 
ar   c               ó0  a a€ S P                  V4      w  r4\        R V V3R lV 4        4       R4      pV'       g4   V'       d.   S P                  VRP                  V4      SR7      ;p'       d   V# VP	                  R4      ;'       g    . p\        V\        4      '       do   \        VRS 4       UUu. uFS  w  rx\        V\        4      '       g   K  VP                  4       '       g   K5  \        R\        V4      RV^,           4      NKU  	  upp# . # u uppi )a  Rows in order of preference: (1) the JSON object in ``output_text`` blocks,
(2) ``url_citation`` annotations paired with surrounding text, (3) the raw
``citations`` list. (2) only short-circuits when it yields rows, so future
annotation types don't mask real data in ``citations``.c              3  ó8   "  € T F  q'       g   K  Vx € K  	  R # 5ir+   r   )Ú.0Úps   & r   Ú	<genexpr>Ú8XAIWebSearchProvider._extract_results.<locals>.<genexpr>¼   s   é € ÐjÑ"d˜QÓhi—q’qÓ"dùs   ‚	�
c              3  óJ   <"  € T F  pSP                  VSR 7      x € K  	  R# 5i)r^   N)Ú_try_parse_json_results)r¦   ÚbÚclsrF   s   & €€r   r¨   r©   ¼   s'   øé € Ð"dÑXcÐST 3×#>Ñ#>¸qÈÐ#>×#NÐ#NÓXcùs   ƒ #NÚ
r^   Ú	citationsrM   )Ú_collect_output_textÚnextÚ_results_from_annotationsÚjoinr    r   r,   Ú	enumerater-   r.   Ú_row)	r­   r¢   rF   Útext_blocksr   Úparsedr¯   ÚiÚus	   f&d      r   rn   Ú%XAIWebSearchProvider._extract_resultsµ   s  ù€ ð $'×#;Ñ#;¸MÓ#JÑ ˆÜÑjÕ"dÑXcÔ"dÓjÐlpÓqˆß—k°×1NÑ1NÈ{Ð\`×\eÑ\eÐfqÓ\rÐzÐ1Nó  2Að  (A vö  (AØˆMØ!×%Ñ% kÓ2×8Ð8°bˆ	ô ~Hð  IRô  TX÷  ~Yò  ~Y¼	À)ÈFÈUÐBSÔ8TÔyÑ8T±°ÔXbÐcdÔfi×XjÔ+Ðop×ovÑov×oxÔ+”�Rœ˜Q›  Q¨¥UÖ+Ñ8TÒyð  	að  _að  	aùÓys   Â3DÃDÃ*"Dc               ó    € V ^8„  d   QhRRRR/# )r   r¢   r   r   z&tuple[list[str], list[dict[str, Any]]]r   )r   s   "r   r   r>   Ã   s   € ÷ (ñ (¨Nð (Ð?eñ (r   c           	     óP  € V P                  R4      p\        V\        4      '       d   TM.  UUu. uFœ  p\        V\        4      '       g   K  VP                  R4      R8X  g   K3  \        VP                  R4      \        4      '       g   KZ  VR,           F5  p\        V\        4      '       g   K  VP                  R4      R8X  g   K3  VNK7  	  Kž  	  pppV Uu. uFR  p\        VP                  R4      \        4      '       g   K*  VR,          P                  4       '       g   KI  VR,          NKT  	  ppV UUu. uFT  p\        VP                  R4      \        4      '       g   K*  VR,           F  p\        V\        4      '       g   K  VNK  	  KV  	  pppWh3# u uppi u upi u uppi )zC(text_blocks, annotations) from ``response.output`` message chunks.Úoutputry   r\   rT   Úoutput_textr–   r   )r    r   r,   r   r-   r.   )	r¢   r½   r0   ÚchunkÚchunksÚcr¶   Úar   s	   &        r   r°   Ú)XAIWebSearchProvider._collect_output_textÂ   sy  € ð ×"Ñ" 8Ó,ˆô $.¨f´d×#;Ò#;™ÀÐCô
áC�Ü˜$¤×%ô à*.¯(©(°6Ó*:¸iÑ*Gô äLVÐW[×W_ÑW_Ð`iÓWjÔlp×Lqô ð ˜iŸ˜�Ü˜%¤×&ô	 ð ,1¯9©9°VÓ+<ÀÑ+M÷	 ˆEñ )ñ ÙCð 	ñ 
ñ +1Ói©& Q´J¸q¿u¹uÀV»}Ìc×4R”yÐWXÐY_ÕW`×WfÑWf×Wh”y�q˜—y�y©&ˆÐiÙ"(ô  E¡&˜Q¬J°q·u±u¸]Ó7KÌT×,R”qÐ\]Ð^k×\lÐ\lÐWXÔpzÐ{|ô  C÷  qD—q�qÑ\l‘q¡&ˆñ  EØÐ'Ð'ùó
ùò jùó EsG   ¯FÁFÁ$"FÂFÂ/FÃ
FÃ'FÄFÄ#FÄ7'F"Å#F"Æ
F"c               ó$   € V ^8„  d   QhRRRRRR/# )r   r–   r-   rF   rG   r   zOptional[list[dict[str, Any]]]r   )r   s   "r   r   r>   Ò   s"   € ÷ ñ  cð °Sð Ð=[ñ r   c               ól  € \         P                  V 4      pV .V'       d)   VP                  ^ 4      V 8w  d   VP                  ^ 4      .M. ,            EF<  p \        P                  ! V4      p\        T\        4      '       d   TP                  R4      MRp\        T\        4      '       g   K\  . pTRT  FÉ  p\        T\        4      '       d*   \        TP                  RR4      4      P                  4       MRpT'       g   KN  TP                  \        \        TP                  RR4      4      P                  4       T\        TP                  RR4      4      P                  4       \        T4      ^,           4      4       KË  	  T'       g   EK;  Tu # 	  R#   \        P
                  \        3 d     EKb  i ; i)z¥Parse a JSON object with a ``results`` array out of ``text``; None when absent.
Whole string first, then the regex-matched block (reasoning models prefix narration).ÚresultsNÚurlrM   ÚtitleÚdescription)Ú_JSON_BLOCK_REru   Úgroupr�   ÚloadsÚJSONDecodeErrorr6   r   r   r    r,   r-   r.   Úappendrµ   r   )	r–   rF   ÚmatchÚ	candidater·   rÆ   Ú
normalizedÚrowrÇ   s	   &$       r   r«   Ú,XAIWebSearchProvider._try_parse_json_resultsÑ   sv  € ô ×%Ñ% dÓ+ˆØ˜·uÀÇÁÈQÃÐSWÔAW E§K¡K°£NÑ#3Ð]_×`Ñ`ˆIðÜŸš IÓ.�ô 0:¸&Ä$×/GÒ/G�f—j‘j Ô+ÈTˆGÜ˜g¤t×,Ò,ÙØ/1ˆJØ˜v “�Ü9CÀCÌ×9NÒ9N”c˜#Ÿ'™' %¨Ó,Ó-×3Ñ3Ô5ÐTV�ß‘3à×%Ñ%¤d¬3¨s¯w©w°wÀÓ/CÓ+D×+JÑ+JÓ+LÈcÔSVÐWZ×W^ÑW^Ð_lÐnpÓWqÓSr×SxÑSxÓSzÔ|ð  AKó  }Lð  OPõ  }Pó  'Qö  Rñ	 '÷
 ŠzØ!Ò!ñ añ  øô ×(Ñ(¬*Ð5ô Ûðús   ÁFÆF3Æ2F3c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r   r£   Újoined_textr-   rF   rG   r   r   )r   s   "r   r   r>   é   s,   € ÷ ñ Ð/Cð ÐRUð Ðadð Ði}ñ r   c               óè  € \        4       p. pV  EF^  pVP                  R4      R8X  d*   \        VP                  RR4      4      P                  4       MRpV'       d   Wc9   d   KU  VP	                  V4       RpVP                  R4      VP                  R4      r˜\        V\        4      '       d�   \        V	\        4      '       dk   ^ Tu;8:  d   T	u;8  d   \        V4      8:  dK   M MGV\        ^ V^È,
          4      V P                  4       p\        V4      ^È8”  d   VRR P                  4       pVP                  \        RWg\        V4      ^,           4      4       \        V4      V8¼  g   EK^   V# 	  V# )	z’Fallback rows from ``url_citation`` annotations: URL plus ~200 chars of
preceding text as the description (the annotation title is just a number).ry   Úurl_citationrÇ   rM   Ústart_indexÚ	end_indexNi8ÿÿÿ)Úsetr    r-   r.   Úaddr   rG   r   rb   rÎ   rµ   )
r   rÕ   rF   ÚseenrÆ   ÚannrÇ   rÉ   ÚstartÚends
   &&$       r   r²   Ú.XAIWebSearchProvider._results_from_annotationsè   s*  € ô ›ˆØ(*ˆÜˆCØ58·W±W¸V³_ÈÔ5V”#�c—g‘g˜e RÓ(Ó)×/Ñ/Ô1Ð\^ˆCß˜#œ+ÙØ�H‰H�SŒMØˆKØŸ™ Ó/°·±¸Ó1E�3Ü˜%¤×%Ò%¬*°S¼#×*>Ò*>À1ÈÖCgÐPSÖCgÔWZÐ[fÓWg×CgØ)¬#¨a°¸µÓ*=¸eÐD×JÑJÓL�Ü�{Ó# cÔ)Ø"-¨d¨eÐ"4×":Ñ":Ó"<�KØ�N‰Nœ4  C´c¸'³lÀQÕ6FÓGÔHÜ�7‹|˜u×$ØØˆñ ð ˆr   c               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r>   þ   s   € ÷ 
ñ 
 .ñ 
r   c                	ó    € \        R RRRR7      # )r;   ÚpaiduU   Agentic web search via Grok's web_search tool â€” uses xAI Grok OAuth or XAI_API_KEY.Úxai_grok)Ú
post_setup)r
   r@   s   &r   Úget_setup_schemaÚ%XAIWebSearchProvider.get_setup_schemaþ   s   € ô Ø# VØcÐpzô
ð 	
r   r   N)é   )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__ÚNAMEÚDISPLAY_NAMErB   ru   Ústaticmethodre   rj   rf   Úclassmethodrn   r°   r«   r²   ræ   Ú__static_attributes__r   r   r   r:   r:   4   s½   † ñeð €DØ*€Lõ%÷)CðV ôaó ðað ô.Ró ð.Rð` ô

ó ð

ð ô
aó ð
að ô(ó ð(ð ôó ðð, ôó ð÷*
ñ 
r   r:   )$rí   Ú
__future__r   r�   ÚloggingÚreÚtypingr   r   r   r   Úplugins.web._commonr   r   r`   r	   r
   r   rµ   Útools.xai_httpr   r   r   Ú	getLoggerré   r"   rd   rl   r/   ÚcompileÚ	MULTILINErÊ   r'   r1   r8   r:   r   r   r   Ú<module>rü      s   ðñõ #ã Û Û 	ß ,Ó ,ç wÕ wß cÑ cà	×	Ò	˜8Ó	$€à €Ø€ØÐ ð —’˜N¨B¯L©LÓ9€õ
õOõôP
Ð0ö P
r   