Ë
    ãß²jƒ:  ã                  ó  — d Z ddlmZ ddlZddlZddlZddlmZmZmZ ddl	m
Z
mZmZmZmZ ddlZddlmZmZ ddlmZmZmZ  ej.                  e«      ZdZd	Zd
ZdZdZd8d„Zd9d„Z d:d„Z!d;d„Z"d<d„Z#d=d„Z$d>d„Z%d?d„Z&d@d„Z'dAd„Z(dBd„Z)dCd„Z*dDd„Z+dEd„Z,	 	 	 	 	 	 	 	 	 	 dFd„Z-	 	 	 	 	 	 dG	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dHd„Z.dd d!d"d#d$œd%d&d"id'd(œd%d&d"id)d(œd"d*d$œd"d+d$œd,d-dd.œd,d/dd.œd0œdgd1œd2œZ/d3„ Z0 ejb                  dde/e0e#d4gd5d6¬7«       y)Iaw  X Search tool backed by xAI's built-in ``x_search`` Responses API tool.

Registers when either xAI credential path is available (``XAI_API_KEY`` or ``hermes auth add
xai-oauth``). At call time an explicit ``XAI_API_KEY`` wins (``prefer_api_key=True``): x_search
is API-metered and the subscription OAuth bearer answers ``/v1/responses`` without citations.
Date filters are validated client-side so malformed windows fail fast instead of burning a
billable call. Results carry ``degraded``: True when a narrowing filter was active AND xAI
returned no citations in either channel (answer came from model knowledge, not the X index).
é    )ÚannotationsN)ÚdateÚdatetimeÚtimezone)ÚAnyÚDictÚListÚOptionalÚTuple)ÚregistryÚ
tool_error)ÚDEFAULT_XAI_BASE_URLÚhermes_xai_user_agentÚresolve_xai_http_credentialszgrok-4.5é´   é   )ÚlowÚmediumÚhighÚxhighé
   c                 óh   — 	 ddl m}   | «       j                  di «      xs i S # t        $ r i cY S w xY w)Nr   ©Úload_configÚx_search)Úhermes_cli.configr   ÚgetÚ	Exceptionr   s    ú8/home/ubuntu/.hermes/hermes-agent/tools/x_search_tool.pyÚ_load_x_search_configr    "   s8   € ðÝ1Ù‹}× Ñ  ¨RÓ0Ò6°BÐ6øÜò ØŠ	ðús   ‚ # £1°1c                 óø   — t        «       j                  d«      } | �'t        | «      j                  «       j	                  «       nd}|r/|t
        vr'dj                  t
        «      }t        d|› d| ›d�«      ‚|xs d S )NÚreasoning_effortÚ ú, z*x_search.reasoning_effort must be one of: z (got ú))r    r   ÚstrÚstripÚlowerÚX_SEARCH_REASONING_EFFORTSÚjoinÚ
ValueError)Ú	raw_valueÚeffortÚalloweds      r   Ú_get_x_search_reasoning_effortr/   *   sz   € Ü%Ó'×+Ñ+Ð,>Ó?€IØ/8Ð/DŒS�‹^×!Ñ!Ó#×)Ñ)Ô+È"€FÙ�&Ô :Ñ:Ø—)‘)Ô6Ó7ˆÜÐEÀgÀYÈfÐU^ÐTaÐabÐcÓdÐdØŠ>�TÐó    c           	     ó€   — 	 t        |t        t        «       j                  | |«      «      «      S # t        $ r |cY S w xY w©N)ÚmaxÚintr    r   r   )ÚkeyÚdefaultÚfloors      r   Ú_get_x_search_intr8   3   s>   € ðÜ�5œ#Ô3Ó5×9Ñ9¸#¸wÓGÓHÓIÐIøÜò ØŠðús   ‚,/ ¯=¼=c                 óL  — t        d¬«      } t        | j                  d«      xs d«      j                  «       }|st	        d«      ‚t        | j                  d«      xs t
        «      j                  «       j                  d«      }||t        | j                  d«      xs d	«      fS )
uÈ  Return ``(api_key, base_url, source)``; ``source`` is ``"xai-oauth"`` or ``"xai"``. Raises RuntimeError
    when no credential is usable (expiry between registration and call -> clean tool error, not a 401).

    x_search is API-index access: when a subscription OAuth credential is configured alongside a paid
    ``XAI_API_KEY``, the OAuth path authorizes but answers ``/v1/responses`` in a degraded Grok explanatory
    mode with no citations, while the API key returns real posts (#88040). Pass ``prefer_api_key=True`` so
    the shared resolver checks the explicit API key first â€” same root cause as the TTS fix for #87045
    (#87081) â€” keeping OAuth as the fallback when no API key is configured.
    T)Úprefer_api_keyÚapi_keyr#   z~No xAI credentials available. Run `hermes auth add xai-oauth` to sign in with your SuperGrok subscription, or set XAI_API_KEY.Úbase_urlú/ÚproviderÚxai)r   r&   r   r'   ÚRuntimeErrorr   Úrstrip)Úcredsr;   r<   s      r   Ú_resolve_xai_bearerrC   :   s•   € ô )¸Ô=€EÜ�%—)‘)˜IÓ&Ò,¨"Ó-×3Ñ3Ó5€GÙÜðOó
ð 	
ô �5—9‘9˜ZÓ(Ò@Ô,@ÓA×GÑGÓI×PÑPÐQTÓU€HØ�Hœc %§)¡)¨JÓ"7Ò"@¸5ÓAÐAÐAr0   c                 ó|   — t        t        t        «       j                  d«      xs d«      j	                  «       «      S )zOTrue when xAI credentials resolve to a non-empty bearer (OAuth auto-refreshed).r;   r#   )Úboolr&   r   r   r'   © r0   r   Úcheck_x_search_requirementsrG   O   s/   € ä”Ô0Ó2×6Ñ6°yÓAÒGÀRÓH×NÑNÓPÓQÐQr0   c                ó˜   — d„ | xs g D «       D �cg c]  }|sŒ|‘Œ	 }}t        |«      t        kD  rt        |› dt        › d�«      ‚|S c c}w )Nc              3  ót   K  — | ]0  }t        |xs d «      j                  «       j                  d«      –— Œ2 y­w)r#   ú@N)r&   r'   Úlstrip)Ú.0Úhandles     r   ú	<genexpr>z%_normalize_handles.<locals>.<genexpr>U   s-   è ø€ Ò]ÀVœ3˜vš|¨Ó,×2Ñ2Ó4×;Ñ;¸C×@Ñ]ùó   ‚68z supports at most z handles)ÚlenÚMAX_HANDLESr+   )ÚhandlesÚ
field_nameÚhÚcleaneds       r   Ú_normalize_handlesrV   T   sR   € Ù]ÈwÊ}ÐZ\Ô]Öc�QÒabŠqÐc€GÐcÜ
ˆ7ƒ|”kÒ!Ü˜J˜<Ð'9¼+¸ÀhÐOÓPÐPØ€Nùò ds
   �A˜Ac                ó¸   — | j                  «       }|sy	 t        j                  |d«      j                  «       S # t        $ r}t	        |› d|›d�«      |‚d}~ww xY w)zdStrict YYYY-MM-DD or None for blank (xAI silently accepts malformed dates and returns no citations).Nz%Y-%m-%dz must be YYYY-MM-DD (got r%   )r'   r   Ústrptimer   r+   )ÚvaluerS   ÚrawÚexcs       r   Ú_parse_iso_dater\   [   sc   € à
�+‰+‹-€CÙØðTÜ× Ñ   jÓ1×6Ñ6Ó8Ð8øÜò TÜ˜J˜<Ð'@ÀÀÀqÐIÓJÐPSÐSûðTús   •#9 ¹	AÁAÁAc                óp  — t        | d«      t        |d«      }}|r5|r3||kD  r.t        d|j                  «       › d|j                  «       › d�«      ‚t        j                  t
        j                  «      j                  «       }|�4||kD  r.t        d|j                  «       › d|j                  «       › d�«      ‚yy)zYBoth parse as YYYY-MM-DD; from <= to; from not after today UTC (to may be in the future).Ú	from_dateÚto_datezfrom_date (z ) must be on or before to_date (r%   NzC) is in the future; X Search only indexes past posts (today UTC is )r\   r+   Ú	isoformatr   Únowr   Úutcr   )r^   r_   Úparsed_fromÚ	parsed_toÚ	today_utcs        r   Ú_validate_date_rangerf   f   sÊ   € ä,¨Y¸ÓDÄoÐV]Ð_hÓFi�€KÙ‘y [°9Ò%<ÜØ˜+×/Ñ/Ó1Ð2Ð2RÐS\×SfÑSfÓShÐRiÐijÐkó
ð 	
ô —‘œXŸ\™\Ó*×/Ñ/Ó1€IØÐ ;°Ò#:ÜØ˜+×/Ñ/Ó1Ð2ð 3>Ø>G×>QÑ>QÓ>SÐ=TÐTUðWó
ð 	
ð $;Ðr0   c              #  ó¬   K  — | j                  dg «      xs g D ]5  }|j                  d«      dk(  sŒ|j                  dg «      xs g E d {  –—†  Œ7 y 7 Œ­w)NÚoutputÚtypeÚmessageÚcontent©r   )ÚpayloadÚitems     r   Ú_message_contentsro   u   sR   è ø€ Ø—‘˜H bÓ)Ò/¨Rò 5ˆØ�8‰8�FÓ˜yÓ(Ø—x‘x 	¨2Ó.Ò4°"×4Ñ4ñ5à4ús   ‚.A±AÁ
AÁAc                óä   — t        | j                  d«      xs d«      j                  «       }|r|S d„ t        | «      D «       }d„ |D «       }dj	                  d„ |D «       «      j                  «       S )NÚoutput_textr#   c              3  óH   K  — | ]  }|j                  d «      dv sŒ|–— Œ y­w)ri   >   Útextrq   Nrl   ©rL   Úcs     r   rN   z)_extract_response_text.<locals>.<genexpr>   s    è ø€ Òb�a¸¿¹¸v»ÐJaÒ9a”Ñbùs   ‚"›"c              3  ót   K  — | ]0  }t        |j                  d «      xs d«      j                  «       –— Œ2 y­w)rs   r#   N)r&   r   r'   rt   s     r   rN   z)_extract_response_text.<locals>.<genexpr>€   s+   è ø€ Ò@°!ŒS�—‘�v“Ò$ "Ó%×+Ñ+×-Ñ@ùrO   z

c              3  ó&   K  — | ]	  }|sŒ|–— Œ y ­wr2   rF   )rL   Úps     r   rN   z)_extract_response_text.<locals>.<genexpr>�   s   è ø€ Ò-˜Qª1”qÑ-ùs   ‚Š)r&   r   r'   ro   r*   )rm   rq   ÚcontentsÚpartss       r   Ú_extract_response_textr{   {   sd   € Ü�g—k‘k -Ó0Ò6°BÓ7×=Ñ=Ó?€KÙØÐÙbÔ,¨WÓ5Ôb€HÙ@°xÔ@€EØ�;‰;Ñ- %Ô-Ó-×3Ñ3Ó5Ð5r0   c                ó(  — t        | «      D ��cg c]v  }|j                  dg «      xs g D ][  }|j                  d«      dk(  rE|j                  dd«      |j                  dd«      |j                  d«      |j                  d«      d	œ‘Œ] Œx c}}S c c}}w )
Nr   ri   Úurl_citationÚurlr#   ÚtitleÚstart_indexÚ	end_index)r~   r   r€   r�   )ro   r   )rm   rk   Úas      r   Ú_extract_inline_citationsrƒ   „   s–   € ô )¨Ó1÷ð
 Ø—‘˜]¨BÓ/Ò5°2òð Ø�5‰5�‹=˜NÒ*ð —5‘5˜ Ó#¨a¯e©e°G¸RÓ.@ØŸ5™5 Ó/¸a¿e¹eÀKÓ>Pó	
ðð	
óð ùó s   �A;Bc                ó  — t        | dd «      }|€t        | «      S 	 |j                  «       }t	        |t
        «      s:t        t        |dd«      xs d«      j                  «       }|r|d d S t        | «      S t        |j                  d«      xs d«      j                  «       }t        |j                  d«      xs d«      j                  «       xs t        |«      }|r||vr|› d|› �n|xs t        | «      S # t        $ r d }Y ŒØw xY w)NÚresponsers   r#   éô  ÚcodeÚerrorz: )Úgetattrr&   Újsonr   Ú
isinstanceÚdictr'   r   )r[   r…   rm   rs   r‡   rj   s         r   Ú_http_error_messager�   �   sü   € Ü�s˜J¨Ó-€HØÐÜ�3‹xˆðØ—-‘-“/ˆô �gœtÔ$Ü”7˜8 V¨RÓ0Ò6°BÓ7×=Ñ=Ó?ˆÙ!ˆt�D�SˆzÐ/¤s¨3£xÐ/Üˆw�{‰{˜6Ó"Ò( bÓ)×/Ñ/Ó1€DÜ�'—+‘+˜gÓ&Ò,¨"Ó-×3Ñ3Ó5ÒE¼¸W»€GÙ$(¨T¸Ñ-@ˆtˆf�B�w�iÑ ÀgÒZÔRUÐVYÓRZÐZøô ò ØŠðús   œC7 Ã7DÄDc                óp   — ddd| dœ}t        j                  i |¥dt        |«      j                  i¥d¬«      S )NFr?   r   )Úsuccessr>   Útoolrˆ   Ú
error_type©Úensure_ascii)rŠ   Údumpsri   Ú__name__)rˆ   r[   Úbodys      r   Ú_error_jsonr—       s8   € Ø¨%¸ÈeÑT€DÜ�:‰:Ð@˜Ð@˜|¬T°#«Y×-?Ñ-?Ñ@ÈuÔUÐUr0   c           	     óv  — t        dt        d«      }t        dt        d«      }t        |dz   «      D ]/  }	 t	        j
                  | |||¬«      }|j                  «        |c S  t#        d«      ‚# t        j                  $ r<}t        t        |dd«      d	d«      }|�
|d
k  s||k\  r‚ dt        |«      }
}	Y d}~n=d}~wt        j                  t        j                  f$ r}||k\  r‚ d|}
}	Y d}~nd}~ww xY wt        j                  d|	|dz   |dz   |
«       t        j                  t!        dd|dz   z  «      «       �Œ
)zSPOST with retries on 5xx / timeout / connection errors; re-raises the last failure.Útimeout_secondsé   Úretriesr   é   )ÚheadersrŠ   Útimeoutr…   NÚstatus_coder†   ÚupstreamÚ	transientz(x_search %s failure on attempt %s/%s: %sg      @g      ø?z*x_search request did not return a response)r8   Ú DEFAULT_X_SEARCH_TIMEOUT_SECONDSÚDEFAULT_X_SEARCH_RETRIESÚrangeÚrequestsÚpostÚraise_for_statusÚ	HTTPErrorr‰   r�   ÚReadTimeoutÚConnectionErrorÚloggerÚwarningÚtimeÚsleepÚminr@   )r~   r�   rm   r™   Úmax_retriesÚattemptr…   ÚerŸ   ÚkindÚdetails              r   Ú_post_with_retriesrµ   ¥   s6  € ä'Ð(9Ô;[Ð]_Ó`€OÜ# IÔ/GÈÓK€KÜ˜ q™Ó)ò 2ˆð	*Ü—}‘} S°'ÀÐQ`ÔaˆHØ×%Ñ%Ô'ØŠOð	2ô  ÐCÓ
DÐDøô ×!Ñ!ò 	>Ü!¤'¨!¨Z¸Ó">ÀÈtÓTˆKØÐ" k°CÒ&7¸7ÀkÒ;QØØ%Ô':¸1Ó'=�&�DûÜ×$Ñ$¤h×&>Ñ&>Ð?ò 	*Ø˜+Ò%ØØ&¨�&�Dûð	*úô 	�‰ÐAÀ4ÈÐSTÉÐVaÐdeÑVeÐgmÔnÜ�
‰
”3�s˜C 7¨Q¡;Ñ/Ó0Ö1s#   µ*A.Á.C2Â2B8Â8&C2Ã
C-Ã-C2c                ó2  — t        | d«      }t        |d«      }|r|rt        d«      ‚t        ||«       ddi}g }	d|fd|fd|j                  «       fd|j                  «       ff}
|
D ]  \  }}|sŒ	|||<   |	j	                  |«       Œ  |rd|d	<   |rd|d
<   ||	fS )zLReturn ``(tool_def, active_filters)``; raises ValueError on invalid filters.Úallowed_x_handlesÚexcluded_x_handlesz@allowed_x_handles and excluded_x_handles cannot be used togetherri   r   r^   r_   TÚenable_image_understandingÚenable_video_understanding)rV   r+   rf   r'   Úappend)r·   r¸   r^   r_   r¹   rº   r.   ÚexcludedÚtool_defÚactive_filtersÚfiltersr5   rY   s                r   Ú_build_x_search_tool_defrÀ   ¼   sÔ   € ô
 !Ð!2Ð4GÓH€GÜ!Ð"4Ð6JÓK€HÙ‘8ÜÐ[Ó\Ð\Ü˜ GÔ,à &¨
Ð3€HØ "€NØ# WÐ-Ð0DÀhÐ/OØ˜YŸ_™_Ó.Ð/°)¸W¿]¹]»_Ð1MðO€Gàò '‰
ˆˆUÚØ!ˆH�S‰MØ×!Ñ! #Õ&ð'ñ "Ø15ˆÐ-Ñ.Ù!Ø15ˆÐ-Ñ.Ø�^Ð#Ð#r0   FÚqueryc                ó<  — | r| j                  «       st        d«      S 	 t        «       \  }}}		 t        ||||||«      \  }}t        «       }	 t	        t        «       j                  d«      xs d«      j                  «       xs t        d| j                  «       dœg|gddœ}|rd|i|d	<   d
|› �dt        «       dœ}t        |› d�||«      j                  «       }t        |j                  d«      xs g «      }t        |«      }t!        |«      xr | xr | }dd|	d|d   | j                  «       t#        |«      ||||rddj%                  |«      › �nd dœ}t        j&                  |d¬«      S # t        $ r}
t        t	        |
«      «      cY d }
~
S d }
~
ww xY w# t        $ r}
t        t	        |
«      «      cY d }
~
S d }
~
ww xY w# t(        j*                  $ r7}t,        j/                  d|d¬«       t1        t3        |«      |«      cY d }~S d }~wt(        j4                  $ rC}t,        j/                  d|d¬«       t7        dt8        d«      }t1        d|› d�|«      cY d }~S d }~wt:        $ r7}t,        j/                  d|d¬«       t1        t	        |«      |«      cY d }~S d }~ww xY w)Nzquery is required for x_searchÚmodelr#   Úuser)Úrolerk   F)rÃ   ÚinputÚtoolsÚstorer-   Ú	reasoningzBearer zapplication/json)ÚAuthorizationzContent-Typez
User-Agentz
/responsesÚ	citationsTr?   r   z'no citations returned despite filters: r$   )r�   r>   Úcredential_sourcer�   rÃ   rÁ   ÚanswerrË   Úinline_citationsÚdegradedÚdegraded_reasonr’   zx_search failed: %s)Úexc_infozx_search timed out: %sr™   rš   zxAI x_search timed out after z seconds)r'   r   rC   r@   r&   rÀ   r/   r+   r    r   ÚDEFAULT_X_SEARCH_MODELr   rµ   rŠ   Úlistrƒ   rE   r{   r*   r”   r¥   r¨   r«   rˆ   r—   r�   r©   r8   r¢   r   )rÁ   r·   r¸   r^   r_   r¹   rº   r;   r<   Úsourcer[   r½   r¾   r"   rm   r�   ÚdatarË   rÎ   rÏ   Úresultr²   rž   s                          r   Úx_search_toolr×   Ö   s“  € ñ ˜Ÿ™œÜÐ:Ó;Ð;ð$Ü$7Ó$9Ñ!ˆ�˜6ð$Ü#;ØÐ1°9¸gØ&Ð(Bó$
Ñ ˆ�.ô :Ó;Ðð%&äÔ.Ó0×4Ñ4°WÓ=ÒCÀÓD×JÑJÓLÒfÔPfØ%°%·+±+³-Ñ@ÐAØ�ZØñ	
ˆñ Ø$,Ð.>Ð#?ˆG�KÑ à& w iÐ0ÐBTÜ/Ó1ñ
ˆô " X J¨jÐ"9¸7ÀGÓL×QÑQÓSˆÜ˜Ÿ™ +Ó.Ò4°"Ó5ˆ	Ü4°TÓ:Ðô ˜Ó'ÒR°	¨MÒRÐBRÐ>Rˆà¨ÀVÐU_Ø˜WÑ%°·±³ÔI_Ð`dÓIeØ"Ð8HÐV^áYaÐ9¸$¿)¹)ÀNÓ:SÐ9TÑUÐgkñ
ˆô �z‰z˜&¨uÔ5Ð5øôM ò $Üœ#˜c›(Ó#Õ#ûð$ûô ò $Üœ#˜c›(Ó#Õ#ûð$ûô> ×Ñò 6Ü�‰Ð*¨A¸ˆÔ=ÜÔ.¨qÓ1°1Ó5Õ5ûÜ×Ñò QÜ�‰Ð-¨q¸4ˆÔ@Ü#Ð$5Ô7WÐY[Ó\ˆÜÐ:¸7¸)À8ÐLÈaÓPÕPûÜò &Ü�‰Ð*¨A¸ˆÔ=Üœ3˜q›6 1Ó%Õ%ûð&ús}   ŸE+ ®F ÁDF? Å+	FÅ4FÆFÆFÆ	F<ÆF7Æ1F<Æ7F<Æ?JÇ,HÇ>JÈJÈ8IÉJÉJÉ$,JÊJÊJr   uÖ  Search X (Twitter) posts, profiles, and threads using xAI's built-in X Search tool. Read-only discovery only: use this for current discussion, reactions, or claims on public X rather than general web pages. Do not use it to post, reply, like, DM, upload media, delete, or inspect the user's authenticated X account â€” those require a separate authenticated X API surface outside this tool. Available when xAI credentials are configured (SuperGrok OAuth or XAI_API_KEY).ÚobjectÚstringzWhat to look up on X.)ri   ÚdescriptionÚarrayri   z;Optional list of X handles to include exclusively (max 10).)ri   ÚitemsrÚ   z/Optional list of X handles to exclude (max 10).z)Optional start date in YYYY-MM-DD format.z'Optional end date in YYYY-MM-DD format.Úbooleanz?Whether xAI should analyze images attached to matching X posts.)ri   rÚ   r6   z?Whether xAI should analyze videos attached to matching X posts.)rÁ   r·   r¸   r^   r_   r¹   rº   )ri   Ú
propertiesÚrequired)ÚnamerÚ   Ú
parametersc                ó$  — t        | j                  dd«      | j                  d«      | j                  d«      | j                  dd«      | j                  dd«      t        | j                  dd«      «      t        | j                  d	d«      «      «      S )
NrÁ   r#   r·   r¸   r^   r_   r¹   Frº   )r×   r   rE   )ÚargsÚkws     r   Ú_handle_x_searchrå   J  sx   € ÜØ�‰�˜"Ó˜tŸx™xÐ(;Ó<¸d¿h¹hÐG[Ó>\Ø�‰�˜bÓ! 4§8¡8¨I°rÓ#:ÜˆT�X‰XÐ2°EÓ:Ó;ÜˆT�X‰XÐ2°EÓ:Ó;ó	ð r0   ÚXAI_API_KEYu   ðŸ�¦i † )rà   ÚtoolsetÚschemaÚhandlerÚcheck_fnÚrequires_envÚemojiÚmax_result_size_chars)ÚreturnúDict[str, Any])rî   zOptional[str])r5   r&   r6   r4   r7   r4   rî   r4   )rî   zTuple[str, str, str])rî   rE   )rR   úOptional[List[str]]rS   r&   rî   z	List[str])rY   r&   rS   r&   rî   zOptional[date])r^   r&   r_   r&   rî   ÚNone)rm   rï   )rm   rï   rî   r&   )rm   rï   rî   zList[Dict[str, Any]])r[   zrequests.HTTPErrorrî   r&   )rˆ   r&   r[   ÚBaseExceptionrî   r&   )r~   r&   r�   zDict[str, str]rm   rï   rî   zrequests.Response)
r^   r&   r_   r&   r¹   rE   rº   rE   rî   z Tuple[Dict[str, Any], List[str]])NNr#   r#   FF)rÁ   r&   r·   rð   r¸   rð   r^   r&   r_   r&   r¹   rE   rº   rE   rî   r&   )2Ú__doc__Ú
__future__r   rŠ   Úloggingr­   r   r   r   Útypingr   r   r	   r
   r   r¥   Útools.registryr   r   Útools.xai_httpr   r   r   Ú	getLoggerr•   r«   rÒ   r¢   r£   r)   rQ   r    r/   r8   rC   rG   rV   r\   rf   ro   r{   rƒ   r�   r—   rµ   rÀ   r×   ÚX_SEARCH_SCHEMArå   ÚregisterrF   r0   r   ú<module>rü      s	  ðñõ #ã Û Û ß -Ñ -ß 3Õ 3ã ç /ß dÑ dà	ˆ×	Ñ	˜8Ó	$€à#Ð Ø#&Ð  ØÐ Ø?Ð Ø€óóóóBó*Ró
óTó
ó5ó6ó	ó[ó Vó
Eð.$Ø69ð$ØDGð$à $ð$àBFð$ð &ó$ð8 .2Ø.2ØØØ',Ø',ð=&Øð=&à*ð=&ð ,ð=&ð ð	=&ð
 ð=&ð !%ð=&ð !%ð=&ð 	ó=&ðB ð	Pð ð !Ø6ñð
  Ø  (Ð+Ø\ñ"ð  Ø  (Ð+ØPñ#ð !ØJñð
 !ØHñð
 "Ø`Ø ñ+ð "Ø`Ø ñ+ñ9!
ðD �IñI%ñ1€òhð €× Ñ Ø	˜Z°ÐIYØ(¸°ÈfØ!ör0   