
    i                   	   d dl mZ d dlZd dlZd dlZd dlZd dlmZ d dlmZ d dl	m
Z
mZmZmZmZmZmZmZmZmZmZmZmZmZ ddlmZ d dlZd dlZd dlmZ d d	lmZ d d
l m!Z! d dl"m#Z# d dl$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+ ddlm,Z, ddl-m.Z. ddl/m0Z0m1Z1 ddl2m3Z3m4Z4  ej5        d          dk    Z6dZ7ddZ8g fddZ9ddZ:ddZ;dd#Z<ed$         Z=	 ed%         Z>	  G d& d'e#d()          Z? G d* d+e#d()          Z@ee?e@f         ZA	 i d,eBgd-eCgd.eDgd/eDgd0eBgd1eBgd2eBgd3eBgd4eBgd5eDgd6eDgd7e>eBgd8e=gd9eDgd:eEgd;eFeEgd<eDgeBgeFgd=ZGeBgeCgeDgeDgeBgeBgeBgeBgeDgeDgeEge=geDgeFeEgd>ZHed?         ZIeDgeFeEgeFeEgeFeEgeFeEgeFeEgeCgeIgeCgeEgeDgd@ZJeCgeBeDgeFgeDgdAZKddFZLdG ZMddJZNedK         ZO	 edL         ZP	  G dM dNe#d()          ZQ G dO dPe#d()          ZR G dQ dRe#d()          ZS G dS dTe#d()          ZT G dU dVe#d()          ZU G dW dXe#d()          ZV G dY dZe#d()          ZW G d[ d\e#d()          ZX G d] d^e#d()          ZYe G d_ d`                      ZZe G da db                      Z[e G dc dd                      Z\e G de df                      Z]e G dg dh                      Z^e G di dj                      Z_e G dk dl                      Z`e G dm dn                      Zae G do dp                      Zbe G dq dr                      Zce G ds dt                      Zde G du dv                      Zee G dw dx                      Zfeeeeff         Zge G dy dz                      Zhe G d{ d|eh                      Zie G d} d~eh                      Zje G d deh                      Zke G d deh                      Zle G d d                      Zme G d d                      Zne G d d                      Zo G d d          Zp G d d          Zq ed          Zre G d d                      Zse G d deer                               Zte G d d                      Zued         Zv	 e G d d                      Zwe G d d                      ZxddZyddZz G d d          Z{ G d de{          Z|dS )    )annotationsN)	dataclass)wraps)AnyCallableDictGenericIterableIteratorListLiteralOptionalTypeVarUnionget_args
get_originoverload   )AsyncWebsetsClient)OpenAI)ChatCompletionMessageParam)	ChatModel)	TypedDict)ExaOpenAICompletion_convert_schema_input_get_package_versionadd_message_to_messagesformat_exa_resultmaybe_get_queryJSONSchemaInput)WebsetsClient)ExaJSONEncoder)SearchMonitorsClientAsyncSearchMonitorsClient)ResearchClientAsyncResearchClientIS_BETATruei'  	snake_strstrreturnc                    | dk    rdS | dk    rdS |                      d          }|d         d                    d |d	d
         D                       z   S )zConvert snake_case string to camelCase.

    Args:
        snake_str (str): The string in snake_case format.

    Returns:
        str: The string converted to camelCase format.
    schema_z$schemanot_not_r    c              3  >   K   | ]}|                                 V  d S N)title).0xs     Q/home/ubuntu/.hermes/hermes-agent/venv/lib/python3.11/site-packages/exa_py/api.py	<genexpr>z!snake_to_camel.<locals>.<genexpr>G   s*      "E"E17799"E"E"E"E"E"E    r   N)splitjoin)r)   
componentss     r7   snake_to_camelr=   7   sg     IyFu%%Ja=277"E"Ejn"E"E"EEEEEr9   datadict	skip_keys	list[str]c                r    t          | t                    r fd|                                 D             S | S )z
    Convert keys in a dictionary from snake_case to camelCase recursively.

    Args:
        data (dict): The dictionary with keys in snake_case format.

    Returns:
        dict: The dictionary with keys converted to camelCase format.
    c                    i | ]@\  }}|t          |          t          |t                    r|vrt          |          n|AS r3   )r=   
isinstancer?   to_camel_case)r5   kvr@   s      r7   
<dictcomp>z!to_camel_case.<locals>.<dictcomp>U   sf     
 
 
 1}	 1!T"" '(	'9'9  -Q	:::}}r9   rD   r?   items)r>   r@   s    `r7   rE   rE   J   sS     $ 

 
 
 
 

	
 
 
 	
 Kr9   	camel_strc                ~    t          j        dd|           }t          j        dd|                                          S )zConvert camelCase string to snake_case.

    Args:
        camel_str (str): The string in camelCase format.

    Returns:
        str: The string converted to snake_case format.
    z(.)([A-Z][a-z]+)z\1_\2z([a-z0-9])([A-Z]))resublower)rK   r)   s     r7   camel_to_snakerP   _   s9     )8Y??I6%x;;AACCCr9   c                l    t          | t                    rd |                                 D             S | S )z
    Convert keys in a dictionary from camelCase to snake_case recursively.

    Args:
        data (dict): The dictionary with keys in camelCase format.

    Returns:
        dict: The dictionary with keys converted to snake_case format.
    c                |    i | ]9\  }}t          |          t          |t                    rt          |          n|:S  )rP   rD   r?   to_snake_caser5   rF   rG   s      r7   rH   z!to_snake_case.<locals>.<dictcomp>w   sR     
 
 
1 1:a3F3FM}Q///A
 
 
r9   rI   )r>   s    r7   rT   rT   l   sF     $ 

 



 
 
 	
 Kr9   entities_dataOptional[List[dict]]Optional[List]c                \  	
 | sdS ddl m}m}mmmmm	m
m	m
mm dfdd fd
d!fdd"
fdd#	fdd$fdd%fd}d&fd}g }| D ]}|                    d          }|dk    rL|                     ||d         d|d          ||                    di                                          i|dk    rK|                     ||d         d|d          ||                    di                                          |r|ndS )'z
    Parse entity data from API response into Entity dataclasses.

    Handles field mapping for reserved Python keywords:
    - 'from' -> 'from_date'
    - 'to' -> 'to_date'
    Nr   )CompanyEntityPersonEntityEntityCompanyPropertiesEntityPersonProperties EntityCompanyPropertiesWorkforce#EntityCompanyPropertiesHeadquarters!EntityCompanyPropertiesFinancials#EntityCompanyPropertiesFundingRound!EntityCompanyPropertiesWebTrafficEntityDateRange EntityPersonPropertiesCompanyRef&EntityPersonPropertiesWorkHistoryEntryr>   Optional[dict]r+   Optional[EntityDateRange]c                r    | sd S  |                      d          |                      d                    S )Nfromto)	from_dateto_dateget)r>   rc   s    r7   parse_date_rangez)_parse_entities.<locals>.parse_date_range   sE     	4hhv&&HHTNN
 
 
 	
r9   *Optional[EntityPersonPropertiesCompanyRef]c                r    | sd S  |                      d          |                      d                    S )Nidname)rr   rs   rm   )r>   rd   s    r7   parse_company_refz*_parse_entities.<locals>.parse_company_ref   sF     	4//xx~~&!!
 
 
 	
r9   r?   re   c           
          |                      d          |                      d           |                      d                     |                      d                              S )Nr4   locationdatescompany)r4   rv   rw   rx   rm   )r>   re   rt   ro   s    r7   parse_work_history_entryz1_parse_entities.<locals>.parse_work_history_entry   so    55((7##XXj))""488G#4#455%%dhhy&9&9::	
 
 
 	
r9   -Optional[EntityCompanyPropertiesFundingRound]c                    | sd S  |                      d          |                      d          |                      d                    S )Nrs   dateamount)rs   r|   r}   rm   )r>   ra   s    r7   parse_funding_roundz,_parse_entities.<locals>.parse_funding_round   sW     	422&!!&!!88H%%
 
 
 	
r9   +Optional[EntityCompanyPropertiesFinancials]c           	         | sd S  |                      d          |                      d           |                      d                              S )NrevenueAnnualfundingTotalfundingLatestRound)revenue_annualfunding_totalfunding_latest_roundrm   )r>   r`   r~   s    r7   parse_financialsz)_parse_entities.<locals>.parse_financials   sc     	40088O44((>22!4!4TXX>R5S5S!T!T
 
 
 	
r9   +Optional[EntityCompanyPropertiesWebTraffic]c                J    | sd S  |                      d                    S )NvisitsMonthly)visits_monthlyrm   )r>   rb   s    r7   parse_web_trafficz*_parse_entities.<locals>.parse_web_traffic   s9     	40088O44
 
 
 	
r9   r\   c                Z   |                      d          }|                      d          } |                      d          |                      d          |                      d          |r |                     d                    nd |r[ |                     d          |                     d	          |                     d
          |                     d                    nd  |                      d                     |                      d                              S )N	workforceheadquartersrs   foundedYeardescriptiontotalr   addresscity
postalCodecountry)r   r   postal_coder   
financials
webTraffic)rs   founded_yearr   r   r   r   web_trafficrm   )r>   workforce_dataheadquarters_datar\   r_   r^   r   r   s      r7   parse_company_propertiesz1_parse_entities.<locals>.parse_company_properties   s:   +.. HH^44&&&!!-00//]ku66^=O=OPW=X=XYYYYqu #-<<)--i88&**622-11,??)--i88	   
 )-''(>(>??))$((<*@*@AA
 
 
 	
r9   r]   c                    |                      d          } |                      d          |                      d          |rfd|D             nd           S )NworkHistoryrs   rv   c                &    g | ]} |          S rS   rS   )r5   whry   s     r7   
<listcomp>zD_parse_entities.<locals>.parse_person_properties.<locals>.<listcomp>   s%    NNN222266NNNr9   )rs   rv   work_historyrm   )r>   r   r]   ry   s     r7   parse_person_propertiesz0_parse_entities.<locals>.parse_person_properties   so    xx..%%&!!XXj))R^hNNNNNNNNdh
 
 
 	
r9   typerx   rr   version
properties)rr   r   r   r   person)r>   rf   r+   rg   )r>   rf   r+   rp   )r>   r?   r+   re   )r>   rf   r+   rz   )r>   rf   r+   r   )r>   rf   r+   r   )r>   r?   r+   r\   )r>   r?   r+   r]   )
exa_py.apirZ   r[   r\   r]   r^   r_   r`   ra   rb   rc   rd   re   rn   append)rV   rZ   r[   r   r   entitiesentity_dataentity_typer\   r`   ra   r_   rb   r^   rc   r]   rd   re   rt   ro   r   r~   r   ry   s           @@@@@@@@@@@@@@@@r7   _parse_entitiesr   ~   s     t                           
 
 
 
 
 

 
 
 
 
 

 
 
 
 
 
 
 

 
 
 
 
 

 
 
 
 
 
 

 
 
 
 
 

 
 
 
 
 
 
 
 
 
$
 
 
 
 
 
 
 H$  !oof--)##OOMMt$#I.33KOOLRT4U4UVV	       H$$OOLLt$#I.22;??<QS3T3TUU	       )88T)r9   )rx   zresearch papernewspdfzpersonal sitezfinancial reportpeople)autofastdeepzdeep-reasoningneuralinstantc                  (    e Zd ZU dZded<   ded<   dS )DeepTextOutputSchemaz0Deep search output schema for plain-text output.zLiteral['text']r   r*   r   N__name__
__module____qualname____doc____annotations__rS   r9   r7   r   r     s0         ::r9   r   Fr   c                  2    e Zd ZU dZded<   ded<   ded<   dS )	DeepObjectOutputSchemaz<Deep search output schema for structured JSON object output.zLiteral['object']r   zDict[str, Any]r   	List[str]requiredNr   rS   r9   r7   r   r     s<         FFr9   r   querynum_resultsinclude_domainsexclude_domainsstart_crawl_dateend_crawl_datestart_published_dateend_published_dateuser_locationinclude_textexclude_textr   categoryflags
moderationcontentsadditional_queries)system_promptoutput_schema)urlr   r   r   r   r   r   r   r   r   exclude_source_domainr   r   r   )alwaysfallbackneverr   	preferred)urlstextsummary
highlightscontextmetadatalivecrawl_timeout	livecrawlmax_age_hoursfilter_empty_resultsr   )subpagessubpage_targetextrasr   optionsDict[str, Optional[object]]expectedNonec           	         |                                  D ]Z\  }||vrt          d| d          ||         }t          fd|D                       st          d| d d|           [dS )a'  Validate an options dict against expected types and constraints.

    Args:
        options (Dict[str, Optional[object]]): The options to validate.
        expected (dict): The expected types for each option.

    Raises:
        ValueError: If an invalid option or option type is provided.
    zInvalid option: ''Nc              3  8   K   | ]}t          |          V  d S r3   )is_valid_type)r5   tvalues     r7   r8   z*validate_search_options.<locals>.<genexpr>  s-      CCq=**CCCCCCr9   zInvalid value for option 'z': z. Expected one of )rJ   
ValueErrorany)r   r   keyexpected_typesr   s       @r7   validate_search_optionsr   w  s     mmoo 	 	
Uh7777888=!#CCCCNCCCCC 	^S^^U^^n^^  		 	r9   c                    t          |          t          u r| t          |          v S t          |t                    rt          | |          S dS )NF)r   r   r   rD   r   )r   expected_types     r7   r   r     sO    -  G++////-&& 0%///5r9   rawOptional[CostDollars]c                    | sdS |                      d          }|dS |                      d          }|                      d          }t          |||          S )zb
    Parse the costDollars JSON into a CostDollars object, or return None if missing/invalid.
    Nr   searchr   )r   r   r   )rn   CostDollars)r   r   search_partcontents_parts       r7   parse_cost_dollarsr    se      tGGGE}t ''(##KGGJ''MU;OOOOr9   )compactstandardfull)unspecifiedheader
navigationbannerbodysidebarfooterr   c                  F    e Zd ZU dZded<   ded<   ded<   ded	<   ded
<   dS )TextContentsOptionsa7  A class representing the options that you can specify when requesting text

    Attributes:
        max_characters (int): The maximum number of characters to return. Default: None (no limit).
        include_html_tags (bool): If true, include HTML tags in the returned text. Default false.
        verbosity (VERBOSITY_OPTIONS): Controls verbosity level of returned content.
            "compact" (default): main content only; "standard": balanced; "full": all sections.
            Requires max_age_hours=0 to take effect.
        include_sections (List[SECTION_TAG]): Only include content from these semantic sections.
            Requires max_age_hours=0 to take effect.
        exclude_sections (List[SECTION_TAG]): Exclude content from these semantic sections.
            Requires max_age_hours=0 to take effect.
    intmax_charactersboolinclude_html_tagsVERBOSITY_OPTIONS	verbosityzList[SECTION_TAG]include_sectionsexclude_sectionsNr   rS   r9   r7   r  r    sZ               ''''''''''r9   r  c                      e Zd ZU dZded<   ded<   ded<   ded<   ded	<   d
ed<   ded<   ded<   ded<   ded<   ded<   ded<   ded<   ded<   d ed<   dS )
JSONSchemaa(  Represents a JSON Schema definition used for structured summary output.

    .. deprecated:: 1.15.0
        Use Pydantic models or dict[str, Any] directly instead.
        This will be removed in a future version.

    To learn more visit https://json-schema.org/overview/what-is-jsonschema.
    r*   r-   r4   r   zLLiteral['object', 'array', 'string', 'number', 'boolean', 'null', 'integer']r   zDict[str, JSONSchema]r   z#Union[JSONSchema, List[JSONSchema]]rJ   r   r   r   enumzUnion[bool, JSONSchema]additionalPropertiesdefinitionspatternPropertieszList[JSONSchema]allOfanyOfoneOfr.   Nr   rS   r9   r7   r  r    s           LLLJJJVVVV%%%%....JJJ1111&&&&,,,,r9   r  c                  (    e Zd ZU dZded<   ded<   dS )SummaryContentsOptionsa  A class representing the options that you can specify when requesting summary

    Attributes:
        query (str): The query string for the summary. Summary will bias towards answering the query.
        schema (Union[BaseModel, dict[str, Any]]): JSON schema for structured output from summary.
            Can be a Pydantic model (automatically converted) or a dict containing JSON Schema.
    r*   r   r    schemaNr   rS   r9   r7   r!  r!    s3           JJJr9   r!  c                  <    e Zd ZU dZded<   ded<   ded<   ded<   dS )	HighlightsContentsOptionsa0  A class representing the options that you can specify when requesting highlights.

    Attributes:
        query (str): The query string for highlight generation. Highlights will be biased towards this query.
        max_characters (int): The maximum number of characters to return for highlights. Default: None (server default).
        num_sentences (int): Deprecated. Use max_characters instead. The number of sentences per highlight.
        highlights_per_url (int): Deprecated. Use max_characters instead. The number of highlights to return per URL.
    r*   r   r  r  num_sentenceshighlights_per_urlNr   rS   r9   r7   r$  r$    sK           JJJr9   r$  c                      e Zd ZU dZded<   dS )ContextContentsOptionsaY  Options for retrieving aggregated context from a set of search results.

    .. deprecated::
        Use ``highlights`` or ``text`` instead. The ``context`` option is deprecated
        and will be removed in a future version.

    Attributes:
        max_characters (int): The maximum number of characters to include in the context string.
    r  r  Nr   rS   r9   r7   r(  r(    s*           r9   r(  c                  (    e Zd ZU dZded<   ded<   dS )ExtrasOptionszFA class representing additional extraction fields (e.g. links, images)r  linksimage_linksNr   rS   r9   r7   r*  r*    s-         PPJJJr9   r*  c                  x    e Zd ZU dZded<   ded<   ded<   ded	<   d
ed<   ded<   ded<   ded<   ded<   ded<   dS )ContentsOptionsa  Options for retrieving page contents in search and find_similar methods.

    All fields are optional. If no content options are specified, text with
    max_characters=10000 is returned by default.

    Attributes:
        text (TextContentsOptions | True): Options for text extraction, or True for defaults.
        highlights (HighlightsContentsOptions | True): Options for highlight extraction, or True for defaults.
        summary (SummaryContentsOptions | True): Options for summary generation, or True for defaults.
        context (ContextContentsOptions | True): Deprecated. Use ``highlights`` or ``text`` instead. Will be removed in a future version.
        max_age_hours (int): Maximum age of cached content in hours. If content is older, it will be
            fetched fresh. Special values: 0 = always fetch fresh content,
            -1 = never fetch fresh (use cached content only). Example: 168 = fetch fresh for pages older than 7 days.
        subpages (int): Number of subpages to crawl.
        subpage_target (str | List[str]): Target subpage path(s) to crawl.
        extras (ExtrasOptions): Additional extraction options (links, images).
    )Union[TextContentsOptions, Literal[True]]r   z/Union[HighlightsContentsOptions, Literal[True]]r   ,Union[SummaryContentsOptions, Literal[True]]r   z,Union[ContextContentsOptions, Literal[True]]r   LIVECRAWL_OPTIONSr   r  r   r   r   zUnion[str, List[str]]r   r*  r   Nr   rS   r9   r7   r.  r.    s          $ 4333????99999999    MMM))))r9   r.  c                  (    e Zd ZU dZded<   ded<   dS )CostDollarsSearchz)Represents the cost breakdown for search.floatr   keywordNr   rS   r9   r7   r3  r3  9  s(         33MMMNNNNNr9   r3  c                  (    e Zd ZU dZded<   ded<   dS )CostDollarsContentsz+Represents the cost breakdown for contents.r4  r   r   Nr   rS   r9   r7   r7  r7  @  s(         55KKKNNNNNr9   r7  c                  :    e Zd ZU dZded<   dZded<   dZded<   dS )	r   z1Represents costDollars field in the API response.r4  r   Nr3  r   r7  r   )r   r   r   r   r   r   r   rS   r9   r7   r   r   G  sC         ;;LLL $F$$$$$(H((((((r9   r   c                  "    e Zd ZU dZdZded<   dS )r^   zCompany workforce information.NOptional[int]r   )r   r   r   r   r   r   rS   r9   r7   r^   r^   T  s)         ((Er9   r^   c                  L    e Zd ZU dZdZded<   dZded<   dZded<   dZded<   dS )r_   z!Company headquarters information.NOptional[str]r   r   r   r   )	r   r   r   r   r   r   r   r   r   rS   r9   r7   r_   r_   [  s\         ++!G!!!!D!%K%%%%!G!!!!!!r9   r_   c                  >    e Zd ZU dZdZded<   dZded<   dZded<   dS )ra   zFunding round information.Nr<  rs   r|   r:  r}   )r   r   r   r   rs   r   r|   r}   rS   r9   r7   ra   ra   e  sK         $$DD F      r9   ra   c                  >    e Zd ZU dZdZded<   dZded<   dZded<   dS )r`   zCompany financial information.Nr:  r   r   rz   r   )r   r   r   r   r   r   r   r   rS   r9   r7   r`   r`   n  sL         (($(N((((#'M''''JNNNNNNNr9   r`   c                  "    e Zd ZU dZdZded<   dS )rb   z Company web traffic information.Nr:  r   )r   r   r   r   r   r   rS   r9   r7   rb   rb   w  s)         **$(N((((((r9   rb   c                  v    e Zd ZU dZdZded<   dZded<   dZded<   dZded	<   dZ	d
ed<   dZ
ded<   dZded<   dS )r\   z+Structured properties for a company entity.Nr<  rs   r:  r   r   z*Optional[EntityCompanyPropertiesWorkforce]r   z-Optional[EntityCompanyPropertiesHeadquarters]r   r   r   r   r   )r   r   r   r   rs   r   r   r   r   r   r   r   rS   r9   r7   r\   r\   ~  s         55D"&L&&&&!%K%%%%<@I@@@@BFLFFFF>BJBBBB?CKCCCCCCr9   r\   c                  0    e Zd ZU dZdZded<   dZded<   dS )rc   z$Date range for work history entries.Nr<  rk   rl   )r   r   r   r   rk   r   rl   rS   r9   r7   rc   rc     s:         ..#I####!G!!!!!!r9   rc   c                  0    e Zd ZU dZdZded<   dZded<   dS )rd   z'Reference to a company in work history.Nr<  rr   rs   )r   r   r   r   rr   r   rs   rS   r9   r7   rd   rd     s:         11BDr9   rd   c                  L    e Zd ZU dZdZded<   dZded<   dZded<   dZded	<   dS )
re   z)A single work history entry for a person.Nr<  r4   rv   rg   rw   rp   rx   )	r   r   r   r   r4   r   rv   rw   rx   rS   r9   r7   re   re     s\         33E"H""""'+E++++:>G>>>>>>r9   re   c                  >    e Zd ZU dZdZded<   dZded<   dZded<   dS )r]   z*Structured properties for a person entity.Nr<  rs   rv   z6Optional[List[EntityPersonPropertiesWorkHistoryEntry]]r   )r   r   r   r   rs   r   rv   r   rS   r9   r7   r]   r]     sK         44D"H""""KOLOOOOOOr9   r]   c                  <    e Zd ZU dZded<   ded<   ded<   ded	<   d
S )rZ   z%Structured entity data for a company.r*   rr   zLiteral['company']r   r  r   r\   r   Nr   rS   r9   r7   rZ   rZ     sB         //GGGLLL''''''r9   rZ   c                  <    e Zd ZU dZded<   ded<   ded<   ded	<   d
S )r[   z$Structured entity data for a person.r*   rr   zLiteral['person']r   r  r   r]   r   Nr   rS   r9   r7   r[   r[     sB         ..GGGLLL&&&&&&r9   r[   c                      e Zd ZU dZded<   ded<   dZded<   dZded	<   dZded
<   dZded<   dZ	ded<   dZ
ded<   dZded<   dZded<   dZded<   	 	 	 	 	 	 	 	 	 ddZd ZdS )_Resultax  A class representing the base fields of a search result.

    Attributes:
        title (str): The title of the search result.
        url (str): The URL of the search result.
        id (str): The temporary ID for the document.
        score (float, optional): A number from 0 to 1 representing similarity.
        published_date (str, optional): An estimate of the creation date, from parsing HTML content.
        author (str, optional): The author of the content (if available).
        image (str, optional): A URL to an image associated with the content (if available).
        favicon (str, optional): A URL to the favicon (if available).
        subpages (List[_Result], optional): Subpages of main page
        extras (Dict, optional): Additional metadata; e.g. links, images.
        entities (List[Entity], optional): Structured entity data for company or person searches.
    r*   r   rr   Nr<  r4   Optional[float]scorepublished_dateauthorimagefaviconzOptional[List[_Result]]r   zOptional[Dict]r   zOptional[List[Entity]]r   c                    || _         || _        || _        || _        || _        || _        || _        || _        |	| _        |
| _	        || _
        d S r3   )r   rr   r4   rJ  rK  rL  rM  rN  r   r   r   )selfr   rr   r4   rJ  rK  rL  rM  rN  r   r   r   s               r7   __init__z_Result.__init__  sV     

,
  r9   c                   d| j          d| j         d| j         d| j         d| j         d| j         d| j         d| j         d	| j         d
| j	         d}| j
        r-d                    d | j
        D                       }|d| dz  }|S )NTitle: 
URL: 
ID: z
Score: 
Published Date: 	
Author: z
Image: z

Favicon: z	
Extras: z
Subpages: 
c              3  H   K   | ]}d |j          d|j        j        pd V  dS )z  - [z] UnknownN)r   r   rs   )r5   es     r7   r8   z"_Result.__str__.<locals>.<genexpr>  sS       % % CBB!,"3"@yBB% % % % % %r9   z
Entities:
)r4   r   rr   rJ  rK  rL  rM  rN  r   r   r   r;   )rP  resultentities_strs      r7   __str__z_Result.__str__  s   	+dj 	+ 	+H	+ 	+7	+ 	+ j	+ 	+  $2		+ 	+
 {	+ 	+ j	+ 	+ 	+ 	+ {	+ 	+ 	+ 	+ 	+ 	 = 	599 % %% % %  L 4L4444Fr9   )	NNNNNNNNN)r   r   r   r   r   r4   rJ  rK  rL  rM  rN  r   r   r   rQ  r^  rS   r9   r7   rH  rH    s           HHHGGGE!E!!!!$(N(((( F    E!G!!!!(,H,,,,!F!!!!'+H++++ ! ! ! !4    r9   rH  c                       e Zd ZU dZdZded<   dZded<   dZded<   dZded	<   	 	 	 	 	 	 	 	 	 	 	 	 	 d fd
	Z	 fdZ
 xZS )Resulta  
    A class representing a search result with optional text, summary, and highlights.

    Attributes:
        text (str, optional): The text content of the page.
        summary (str, optional): A summary of the page content.
        highlights (List[str], optional): Relevant sentences from the page.
        highlight_scores (List[float], optional): Scores for each highlight.
    Nr<  r   r   Optional[List[str]]r   zOptional[List[float]]highlight_scoresc                    t                                          |||||||||	|
|           || _        || _        || _        || _        d S r3   )superrQ  r   r   r   rb  )rP  r   rr   r4   rJ  rK  rL  rM  rN  r   r   r   r   r   r   rb  	__class__s                   r7   rQ  zResult.__init__$  sg    $ 		
 	
 	
 	$ 0r9   c                    t                                                      }|d| j         d| j         dz   }| j        r|d| j         dz  }| j        r|d| j         dz  }|S )NText: z

Summary: rX  zHighlights: zHighlight Scores: )rd  r^  r   r   r   rb  )rP  base_strr\  re  s      r7   r^  zResult.__str__H  s    77??$$KTYKK4<KKKK? 	98T_8888F  	ED4+@DDDDFr9   )NNNNNNNNNNNNN)r   r   r   r   r   r   r   r   rb  rQ  r^  __classcell__re  s   @r7   r`  r`    s           D!G!!!!&*J****.22222 !"1 "1 "1 "1 "1 "1H        r9   r`  c                  p     e Zd ZU dZ ej        e          Zded<   	 	 	 	 	 	 	 	 	 	 d	 fd	Z	 fdZ
 xZS )
ResultWithTextz
    A class representing a search result with text present.

    Attributes:
        text (str): The text of the search result page.
    default_factoryr*   r   Nr1   c                l    t                                          |||||||||	|
|           || _        d S r3   )rd  rQ  r   )rP  r   rr   r4   rJ  rK  rL  rM  rN  r   r   r   r   re  s                r7   rQ  zResultWithText.__init__]  sO     		
 	
 	
 			r9   c                `    t                                                      }|d| j         dz   S )Nrg  rX  )rd  r^  r   rP  rh  re  s     r7   r^  zResultWithText.__str__{  s/    77??$$04900000r9   
NNNNNNNNNr1   )r   r   r   r   dataclassesfieldr*   r   r   rQ  r^  ri  rj  s   @r7   rl  rl  R  s           "!#666D6666      <1 1 1 1 1 1 1 1 1r9   rl  c                  p     e Zd ZU dZ ej        e          Zded<   	 	 	 	 	 	 	 	 	 	 d	 fd	Z	 fdZ
 xZS )
ResultWithSummaryzk
    A class representing a search result with summary present.

    Attributes:
        summary (str)
    rm  r*   r   Nr1   c                l    t                                          |||||||||	|
|           || _        d S r3   )rd  rQ  r   )rP  r   rr   r4   rJ  rK  rL  rM  rN  r   r   r   r   re  s                r7   rQ  zResultWithSummary.__init__  sO     		
 	
 	
 r9   c                `    t                                                      }|d| j         dz   S )N	Summary: rX  )rd  r^  r   rq  s     r7   r^  zResultWithSummary.__str__  s/    77??$$6dl66666r9   rr  )r   r   r   r   rs  rt  r*   r   r   rQ  r^  ri  rj  s   @r7   rv  rv    s           %;$S999G9999      <7 7 7 7 7 7 7 7 7r9   rv  c                       e Zd ZU dZ ej        e          Zded<    ej        e          Z	ded<   	 	 	 	 	 	 	 	 	 	 	 d
 fd	Z
 fd	Z xZS )ResultWithTextAndSummaryz
    A class representing a search result with text and summary present.

    Attributes:
        text (str)
        summary (str)
    rm  r*   r   r   Nr1   c                z    t                                          |||||||||	|
|           || _        || _        d S r3   )rd  rQ  r   r   )rP  r   rr   r4   rJ  rK  rL  rM  rN  r   r   r   r   r   re  s                 r7   rQ  z!ResultWithTextAndSummary.__init__  sV      		
 	
 	
 	r9   c                x    t                                                      }|d| j         dz   d| j         dz   S )Nrg  rX  ry  )rd  r^  r   r   rq  s     r7   r^  z ResultWithTextAndSummary.__str__  sB    77??$$04900003Ot|3O3O3OOOr9   )NNNNNNNNNr1   r1   )r   r   r   r   rs  rt  r*   r   r   r   rQ  r^  ri  rj  s   @r7   r{  r{    s           "!#666D6666$;$S999G9999      @P P P P P P P P Pr9   r{  c                  p    e Zd ZU dZded<   ded<   dZded<   dZded<   dZded	<   dZded
<   	 ddZ	d Z
dS )AnswerResulta  A class representing a result for an answer.

    Attributes:
        title (str): The title of the search result.
        url (str): The URL of the search result.
        id (str): The temporary ID for the document.
        published_date (str, optional): An estimate of the creation date, from parsing HTML content.
        author (str, optional): If available, the author of the content.
        text (str, optional): The full page text from each search result.
    r*   rr   r   Nr<  r4   rK  rL  r   c                Z    || _         || _        || _        || _        || _        || _        d S r3   rr   r   r4   rK  rL  r   )rP  rr   r   r4   rK  rL  r   s          r7   rQ  zAnswerResult.__init__  s3     
,			r9   c                h    d| j          d| j         d| j         d| j         d| j         d| j         dS )NrS  rT  rU  rV  rW  
Text: 

)r4   r   rr   rK  rL  r   rP  s    r7   r^  zAnswerResult.__str__  sq    %dj % %H% %7% %  $2% % {	% %
 Y% % %	
r9   )NNNN)r   r   r   r   r   r4   rK  rL  r   rQ  r^  rS   r9   r7   r  r    s         	 	 GGGHHHE$(N(((( F    D KO   
 
 
 
 
r9   r  c                  @    e Zd ZU dZdZded<   dZded<   dd	ZddZdS )StreamChunkzA class representing a single chunk of streaming data.

    Attributes:
        content (Optional[str]): The partial text content of the answer
        citations (Optional[List[AnswerResult]]): List of citations if provided in this chunk
    Nr<  contentzOptional[List[AnswerResult]]	citationsr+   r  c                &    | j         dup| j        duS )z&Check if this chunk contains any data.Nr  r  r  s    r7   has_datazStreamChunk.has_data  s    |4'E4>+EEr9   r*   c                h    d}| j         r
|| j         z  }| j        r|dz  }| j        D ]
}|d| z  }|S )z"Format the chunk data as a string.r1   z
Citations:rX  r  rP  outputsources      r7   r^  zStreamChunk.__str__  sY    < 	#dl"F> 	(n$F. ( (-v--'r9   )r+   r  )r+   r*   )	r   r   r   r   r  r   r  r  r^  rS   r9   r7   r  r  	  sp           "G!!!!.2I2222F F F F	 	 	 	 	 	r9   r  c                  <    e Zd ZU dZded<   ded<   dZded<   d	 ZdS )
AnswerResponsea(  A class representing the response for an answer operation.

    Attributes:
        answer (str): The generated answer.
        citations (List[AnswerResult]): A list of citations used to generate the answer.
        cost_dollars (CostDollars, optional): The cost breakdown for this request.
    Union[str, dict[str, Any]]answerzList[AnswerResult]r  Nr   cost_dollarsc                    d| j          d}| j        D ]U}|d|j         z  }|d|j         z  }|d|j         z  }|d|j         z  }|d|j         z  }|d|j         z  }|d	z  }V|S )
NzAnswer: z

Citations:z
Title: rU  rT  rV  rW  r  rX  )r  r  r4   rr   r   rK  rL  r   r  s      r7   r^  zAnswerResponse.__str__3  s    7DK777n 	 	F0&,000F*vy***F,
,,,FB6+@BBBF26=222F....FdNFFr9   )r   r   r   r   r   r  r^  rS   r9   r7   r  r  %  sZ           '&&&!!!!*.L....
 
 
 
 
r9   r  c                  0    e Zd ZdZddZd ZddZdd
ZdS )StreamAnswerResponse1A class representing a streaming answer response.raw_responserequests.Responsec                <    || _         |                                  d S r3   _raw_response_ensure_ok_statusrP  r  s     r7   rQ  zStreamAnswerResponse.__init__C  "    )     r9   c                x    | j         j        dk    r)t          d| j         j         d| j         j                   d S N    Request failed with status code : r  status_coder   r   r  s    r7   r  z&StreamAnswerResponse._ensure_ok_statusG  M    )S00n43E3QnnUYUgUlnn   10r9   r+   Iterator[StreamChunk]c              #  n  K   | j                                         D ]}|s|                    d                              d          }	 t	          j        |          }n# t          j        $ r Y Uw xY wd }d }d|v r?|d         r7d|d         d         v r'|d         d         d                             d          }d|v r|d         r|d         dk    rg }|d         D ]}t          |          }|	                    t          |                    d	          |                    d
          |                    d          |                    d          |                    d          |                    d                               t          ||          }|                                r|V  d S )Nzutf-8data: choicesdeltar   r  r  nullrr   r   r4   rK  rL  r   r  r  )r  
iter_linesdecoderemoveprefixjsonloadsJSONDecodeErrorrn   rT   r   r  r  r  )	rP  linedecoded_linechunkr  r  ssnake_sstream_chunks	            r7   __iter__zStreamAnswerResponse.__iter__M  s     &1133 %	# %	#D ;;w//<<XFFL
<00'    GIE!!eI&6!eI.q111#I.q1':>>yIIG u$$+& %+&&00	{+  A+A..G$$$&{{400 'E 2 2")++g"6"6+2;;7G+H+H#*;;x#8#8!(V!4!4  	 	 	 	 'w)LLLL$$&& #""""K%	# %	#s   A  A21A2r   c                8    | j                                          dS z@Close the underlying raw response to release the network socket.Nr  closer  s    r7   r  zStreamAnswerResponse.closeu        """""r9   N)r  r  )r+   r  r+   r   )r   r   r   r   rQ  r  r  r  rS   r9   r7   r  r  @  sf        ;;! ! ! !  &# &# &# &#P# # # # # #r9   r  c                  .    e Zd ZdZddZd Zd Zdd	Zd
S )AsyncStreamAnswerResponser  r  httpx.Responsec                <    || _         |                                  d S r3   r  r  s     r7   rQ  z"AsyncStreamAnswerResponse.__init__}  r  r9   c                x    | j         j        dk    r)t          d| j         j         d| j         j                   d S r  r  r  s    r7   r  z+AsyncStreamAnswerResponse._ensure_ok_status  r  r9   c                "      fd} |            S )Nc                V  K   j                                         2 3 d {V } | s
|                     d          }	 t          j        |          }n# t          j        $ r Y Fw xY wd }d }d|v r?|d         r7d|d         d         v r'|d         d         d                             d          }d|v r|d         r|d         dk    rg }|d         D ]}t          |          }|                    t          |                    d          |                    d	          |                    d
          |                    d          |                    d          |                    d                               t          ||          }|                                r|W V  6 d S )Nr  r  r  r   r  r  r  rr   r   r4   rK  rL  r   r  r  )r  aiter_linesr  r  r  r  rn   rT   r   r  r  r  )	r  r  r  r  r  r  r  r  rP  s	           r7   	generatorz6AsyncStreamAnswerResponse.__aiter__.<locals>.generator  s     "0<<>> %' %' %' %' %' %' %'d #00:: J|44EE+   H  	%%%	*:%%	"21"555"'	"21"5g">"B"B9"M"M  5((k* )k*f44 "I";/  "/"2"2!(((#*;;t#4#4$+KK$6$6&-kk'&:&:/6{{;K/L/L'.{{8'<'<%,[[%8%8  	 	 	 	  +7iPPP((** '&&&&&K ?>>s   F(AA$#A$rS   )rP  r  s   ` r7   	__aiter__z#AsyncStreamAnswerResponse.__aiter__  s+    &	' &	' &	' &	' &	'P y{{r9   r+   r   c                8    | j                                          dS r  r  r  s    r7   r  zAsyncStreamAnswerResponse.close  r  r9   N)r  r  r  )r   r   r   r   rQ  r  r  r  rS   r9   r7   r  r  z  sa        ;;! ! ! !  ) ) )V# # # # # #r9   r  Tc                  2    e Zd ZU dZded<   ded<   ded<   dS )ContentStatuszAA class representing the status of a content retrieval operation.r*   rr   statusr  Nr   rS   r9   r7   r  r    s1         KKGGGKKKKKKKKr9   r  c                  ~    e Zd ZU dZded<   ded<   ded<   dZded<   dZd	ed
<   dZded<   dZded<   dZ	ded<   d Z
dS )SearchResponsea  A class representing the response for a search operation.

    Attributes:
        results (List[Result]): A list of search results.
        resolved_search_type (str, optional): 'neural' or 'keyword' if auto.
        auto_date (str, optional): A date for filtering if autoprompt found one.
        context (str, optional): Deprecated. Combined context string when requested via contents.context. Use highlights or text instead.
        output (DeepSearchOutput, optional): Deep search synthesized output object containing content and field-level grounding.
        statuses (List[ContentStatus], optional): Status list from get_contents.
        cost_dollars (CostDollars, optional): Cost breakdown.
        search_time (float, optional): Time taken for the search in milliseconds.
    zList[T]resultsr<  resolved_search_type	auto_dateNr   zOptional['DeepSearchOutput']r  zOptional[List[ContentStatus]]statusesr   r  rI  search_timec                   d                     d | j        D                       }| j        r|d| j         z  }| j        |d| j         z  }| j        r|d| j         z  }| j        |d| j         dz  }| j        rN|d| j        j         z  }| j        j        r|d	| j        j         z  }| j        j	        r|d
| j        j	         z  }| j
        r|d| j
         z  }|S )Nr  c              3  4   K   | ]}t          |          V  d S r3   )r*   )r5   r\  s     r7   r8   z)SearchResponse.__str__.<locals>.<genexpr>  s(      DDVS[[DDDDDDr9   z

Context: z	
Output: z
Resolved Search Type: z
Search Time: msz
CostDollars: total=z
  - search: z
  - contents: z
Statuses: )r;   r  r   r  r  r  r  r   r   r   r  )rP  r  s     r7   r^  zSearchResponse.__str__  s=   DDt|DDDDD< 	32DL222F;"04;000F$ 	ML1JLLLF'<(8<<<<F 	JGd.?.EGGGF ' FE4+<+CEEE ) JIT->-GIII= 	54T]444Fr9   )r   r   r   r   r   r   r  r  r  r  r^  rS   r9   r7   r  r    s           ''''!G!!!!+/F////.2H2222*.L....#'K''''    r9   r  c                  (    e Zd ZU dZded<   ded<   dS )!DeepSearchOutputGroundingCitationz0Citation metadata for one grounded output field.r*   r   r4   Nr   rS   r9   r7   r  r    s(         ::HHHJJJJJr9   r  lowmediumhighc                  2    e Zd ZU dZded<   ded<   ded<   dS )	DeepSearchOutputGroundingzCGrounding metadata for one field in deep-search synthesized output.r*   rt  z'List[DeepSearchOutputGroundingCitation]r  #DeepSearchOutputGroundingConfidence
confidenceNr   rS   r9   r7   r  r    s9         MMJJJ6666333333r9   r  c                  (    e Zd ZU dZded<   ded<   dS )DeepSearchOutputz'Deep-search synthesized output payload.r  r  zList[DeepSearchOutputGrounding]	groundingNr   rS   r9   r7   r  r    s0         11''''......r9   r  r   Optional[DeepSearchOutput]c                   t          | t                    sdS |                     d          }t          |t                    r|}nt          |t                    r|}nd}g }|                     d          }t          |t                    rJ|D ]F}t          |t                    s|                    d          }t          |t                    sDg }|                    d          }t          |t                    r|D ]}	t          |	t                    s|	                    d          }
|	                    d          }t          |
t                    sX|                    t          |
t          |t                    r|nd	                     |                    d
          }|dvrd}|                    t          |||                     Ht          ||          S )zParse deep-search output into a typed object.

    Args:
        raw: Raw `output` field from API response.

    Returns:
        Parsed DeepSearchOutput when the payload is an object, otherwise None.
    Nr  r1   r  rt  r  r   r4   )r   r4   r  r  r  )rt  r  r  )r  r  )	rD   r?   rn   r*   listr   r  r  r  )r   raw_contentr  r  raw_groundinggrounding_rowrt  r  raw_citationscitationr   r4   r  s                r7   parse_deep_search_outputr    s    c4   t'')$$K+s## .9	K	&	& 13IGGK((M-&& $* #	 #	MmT22 !%%g..EeS)) ACI)--k::M-..  -  H%h55 ! ",,u--C$LL11E%c3// ! $$9 #+5eS+A+A"I%%r      '**<88J!:::%
)')      GyAAAAr9   original_dictr   fields_to_nestr   new_keyc                V    i }|D ]}|| v r|                      |          ||<   || |<   | S r3   )pop)r  r  r  nested_dictrt  s        r7   nest_fieldsr  M  sN    K   : :M!!!.!2!25!9!9K )M'r9   c                     e Zd ZdZ	 	 dndod	Z	 	 	 	 dpdqdZddddddddddddddddddddrd2Zdsd3Ze	 	 	 	 	 	 	 	 dtdudA            Z	edddddddddBdvdE            Z	edddddddddBdwdI            Z	edddddddddBdxdK            Z	dydLZ	ddddddddddddddMdzdPZ
eddddddddddddddddddddQd{dR            ZeddddddddddddddddddddQd|dS            ZeddddddddddddddddddddQd|dT            ZeddddddddddddddddddddQd}dU            ZeddddddddddddddddddddQd~dV            ZddWZddZZdd`Zedadadddddbddh            ZdadadddddbddiZdadddddjddmZdS )Exaz&A client for interacting with Exa API.https://api.exa.aiNapi_keyr<  base_urlr*   
user_agentc                *   |/ddl }|j                            d          }|t          d          |dt	                       }|| _        ||dd| _        t          |           | _        t          |           | _
        t          |           | _        dS )a~  Initialize the Exa client with the provided API key and optional base URL and user agent.

        Args:
            api_key (str): The API key for authenticating with the Exa API.
            base_url (str, optional): The base URL for the Exa API. Defaults to "https://api.exa.ai".
            user_agent (str, optional): Custom user agent. Defaults to "exa-py {version}".
        Nr   EXA_API_KEYzNAPI key must be provided as an argument or in EXA_API_KEY environment variablezexa-py/zapplication/json)z	x-api-keyz
User-AgentzContent-Type)osenvironrn   r   r   r  headersr!   websetsr%   researchr#   monitors)rP  r  r  r  r  s        r7   rQ  zExa.__init__a  s     ?IIIjnn]33G d  
 ;#7#9#9;;J  $.
 

 %T**&t,,,T22r9   POSTendpointr>   $Optional[Union[Dict[str, Any], str]]methodparamsOptional[Dict[str, Any]]r  Optional[Dict[str, str]]r+   (Union[Dict[str, Any], requests.Response]c                ,   t          |t                    r|}n|rt          j        |t                    nd}|r*t          |t
                    r|                    d          p|o|                    d          dk    }i | j        }|r|                    |           |	                                dk    rD|r"t          j        | j        |z   ||d          }	|	S t          j        | j        |z   ||          }	n|	                                d	k    rD|r"t          j        | j        |z   ||d
          }	|	S t          j        | j        |z   ||          }	n|	                                dk    r t          j        | j        |z   ||          }	nI|	                                dk    rt          j        | j        |z   |          }	nt          d|           |	j        dk    rt          d|	j         d|	j                   |	                                S )a
  Send a request to the Exa API, optionally streaming if data['stream'] is True.

        Args:
            endpoint (str): The API endpoint (path).
            data (dict, optional): The JSON payload to send. Defaults to None.
            method (str, optional): The HTTP method to use. Defaults to "POST".
            params (Dict[str, Any], optional): Query parameters to include. Defaults to None.
            headers (Dict[str, str], optional): Additional headers to include in the request. Defaults to None.

        Returns:
            Union[dict, requests.Response]: If streaming, returns the Response object.
            Otherwise, returns the JSON-decoded response as a dict.

        Raises:
            ValueError: If the request fails (non-200 status code).
        )clsNstreamtrueGETT)r  r  r  )r  r  r  )r>   r  r  )r>   r  PATCHDELETEr  Unsupported HTTP method: i  r  r  )rD   r*   r  dumpsr"   r?   rn   r  updateupperrequestsr  postpatchdeleter   r  r   )
rP  r  r>   r
  r  r  	json_dataneeds_streamingrequest_headersress
             r7   requestzExa.request  s`   2 dC   	OII AEN
4^<<<<$I  QJtT$:$:Qtxx?Q?Q 
5vzz(++v5 	
 +T\* 	,""7+++<<>>U"" lMH,+!	   
lMH,of   \\^^v%% mMH,"+	   
mMH,9o   \\^^w&&.(y/  CC \\^^x''/$-(":OTTTCCAAABBB?c!!P3?PPchPP   xxzzr9   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   0Optional[Union[ContentsOptions, Literal[False]]]r   r:  r   ra  r   r   r   r   r   r   r   r    Optional[Union[SearchType, str]]r   Optional[Category]r   r   Optional[bool]r   r   r   r   Optional[DeepOutputSchema]SearchResponse[Result]c               \   d t                                                      D             }|du r|                    dd           n|d|vrddt          ii|d<   n|||d<   t	          |t
                     t          |dg          }|                     d	|          }t          |	                    d
                    }g }|d         D ]m}t          |          }|                    t          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          t          |	                    d                                         ot          |d|v r|d         ndd|v r|d         nd|	                    d          t          |	                    d                    ||	                    d                     S )!a  Perform a search.

        By default, returns text contents with 10,000 max characters. Use contents=False to opt-out.

        Args:
            query (str): The query string.
            contents (ContentsOptions | False, optional): Options for retrieving page contents.
                Defaults to {"text": {"maxCharacters": 10000}}. Use False to disable contents.
                See ContentsOptions for available options (text, highlights, summary, etc.).
                Note: The ``context`` option is deprecated; use ``highlights`` or ``text`` instead.
            num_results (int, optional): Number of search results to return. Default 10.
            include_domains (List[str], optional): Domains to include in the search.
            exclude_domains (List[str], optional): Domains to exclude from the search.
            start_crawl_date (str, optional): Only links crawled after this date.
            end_crawl_date (str, optional): Only links crawled before this date.
            start_published_date (str, optional): Only links published after this date.
            end_published_date (str, optional): Only links published before this date.
            include_text (List[str], optional): Strings that must appear in the page text.
            exclude_text (List[str], optional): Strings that must not appear in the page text.
            type (SearchType, optional): Search type - 'auto' (default), 'fast', 'deep', 'deep-reasoning', 'neural', or 'instant'.
            category (Category, optional): Data category to focus on (e.g. 'company', 'news', 'research paper').
            flags (List[str], optional): Experimental flags for Exa usage.
            moderation (bool, optional): If True, the search results will be moderated for safety.
            user_location (str, optional): Two-letter ISO country code of the user (e.g. US).
            additional_queries (List[str], optional): Alternative query formulations for deep search to skip
                automatic LLM-based query expansion. Max 5 queries. Only applicable when type is
                'deep' or 'deep-reasoning'.
                Example: ["machine learning", "ML algorithms", "neural networks"]
            system_prompt (str, optional): Deep-search-only instructions that guide both the
                search process and the final returned result. Use this to prefer certain sources,
                emphasize novelty, avoid duplicates, or constrain the response style.
                Only applicable when type is 'deep' or 'deep-reasoning'.
            output_schema (DeepOutputSchema, optional): Deep output schema for deep search.
                Use ``{"type": "text", "description": ...}`` for plain text output or
                ``{"type": "object", "properties": ..., "required": ...}`` for structured JSON.
                For object schemas, max nesting depth is 2 and max total properties is 10.
                Only applicable when type is 'deep' or 'deep-reasoning'.

        Returns:
            SearchResponse: The response containing search results, etc.

        Examples:
            # Basic search
            result = exa.search(
              "hottest AI startups",
              num_results=2,
              contents={"highlights": True}
            )

            # Deep search with query variations
            deep_result = exa.search(
              "blog post about AI",
              type="deep",
              additional_queries=["AI blogpost", "machine learning blogs"],
              num_results=5
            )
        c                *    i | ]\  }}|d k    |||S r  rS   rU   s      r7   rH   zExa.search.<locals>.<dictcomp>*  '    VVVDAqV1ar9   Fr   Nr   r  r   r@   /searchcostDollarsr  r   rr   r4   rJ  rK  rL  rM  rN  r   r   r   r   rb  r   r   rr   r4   rJ  rK  rL  rM  rN  r   r   r   r   r   rb  r   resolvedSearchTypeautoDater   r  
searchTimer   r  r  r  )localsrJ   r  DEFAULT_MAX_CHARACTERSr   SEARCH_OPTIONS_TYPESrE   r#  r  rn   rT   r   r`  r   r  r  rP  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r>   r  r  r\  snake_results                             r7   r   z
Exa.search  s   ` WVFHHNN$4$4VVV uKK
D))))*G";";#),<>T+U"VGJ!"*GJ)=>>>O3DEEE||Iw//)$((=*A*ABB9o 	 	F(00LNN$((//#''--&**733&**733#/#3#34D#E#E'++H55&**733(,,Y77)--j99'++H55%))&11(,,Y77+//==%1%5%56H%I%I,VZZ
-C-CDD     & *>$*F*FD%&&D *d 2 2DHHY''+DHHX,>,>??%..
 
 
 	
r9   c                r   d|i}|                                 D ]\  }}||||<   d|vrd|vrd|vrdt          i|d<   i }|                    t                     |                    t                     |                    t
                     t          ||           d|v r?t          |d         t                    r$|d         }d|v rt          |d                   |d<   t          |g dd	          }t          |dg
          }|                     d|          }t          |                    d                    }	g }
|d         D ]m}t          |          }|
                    t#          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          t%          |                    d                                         ot'          |
|                    d          |                    d          |                    d          t)          |                    d                    |	|                    d                     S )!t  
        DEPRECATED: Use search() instead. The search() method now returns text contents by default.

        Migration:
        - search_and_contents(query) → search(query)
        - search_and_contents(query, text=True) → search(query, contents={"text": True})
        - search_and_contents(query, summary=True) → search(query, contents={"summary": True})
        r   Nr   r   r   r  r"  
r   r   r   r   r   r   r   r   r   r   r   r.  r/  r0  r  r   rr   r4   rJ  rK  rL  rM  rN  r   r   rb  r   r1  r2  r3  r   r  r4  r5  )rJ   r7  r  r8  CONTENTS_OPTIONS_TYPESCONTENTS_ENDPOINT_OPTIONS_TYPESr   rD   r?   r   r  rE   r#  r  rn   rT   r   r`  r   r  r  rP  r   kwargsr   rF   rG   merged_optionssummary_optsr>   r  r  r\  r:  s                r7   search_and_contentszExa.search_and_contents[  sA    E"LLNN 	 	DAq}
 '!!((''/1GHGFO23334555=>>>888 Jwy/A4$H$H"9-L<'')>|H?U)V)VX&    
 
   H:>>>||Iw//)$((=*A*ABB9o 	 	F(00LNN$((//#''--&**733&**733#/#3#34D#E#E'++H55&**733(,,Y77)--j99'++H55%))&11(,,Y77+//==%1%5%56H%I%I,VZZ
-C-CDD     & HH)**HHZ  HHY''+DHHX,>,>??%..
 
 
 	
r9   r   $Union[str, List[str], List[_Result]]r   r   Optional[LIVECRAWL_OPTIONS]r   r   r   r   Optional[Union[str, List[str]]]r   Optional[ExtrasOptions]SearchResponse[ResultWithText]c
                    d S r3   rS   )
rP  r   r   r   r   r   r   r   r   r   s
             r7   get_contentszExa.get_contents  s	     *-r9   )r   r   r   r   r   r   r   r   r   r/  c       	            d S r3   rS   )rP  r   r   r   r   r   r   r   r   r   r   s              r7   rK  zExa.get_contents  s	     *-r9   r   r0  !SearchResponse[ResultWithSummary]c       	            d S r3   rS   )rP  r   r   r   r   r   r   r   r   r   r   s              r7   rK  zExa.get_contents  s	     -0Cr9   (SearchResponse[ResultWithTextAndSummary]c       
            d S r3   rS   )rP  r   r   r   r   r   r   r   r   r   r   r   s               r7   rK  zExa.get_contents  s	     473r9   c                   t          |t                    r|g}nOt          |t                    r:t          |          dk    r't          |d         t                    rd |D             }d|i}|                                D ]\  }}|dk    r||||<   d|vrd|vrd|vrd	t          i|d<   i }|                    t                     |                    t                     t          ||           d|v r?t          |d         t                    r$|d         }d
|v rt          |d
                   |d
<   t          |d
g          }|                     d|          }t          |                    d                    }	g }
|                    dg           D ]`}|
                    t%          |                    d          |                    d          |                    d                               ag }|d         D ]m}t'          |          }|                    t)          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          t+          |                    d                                         ot-          ||                    d          |                    d           |                    d!          |	|
|                    d"          #          S )$a  Retrieve contents for a list of URLs.

        Args:
            urls (str | List[str] | List[Result]): A single URL, list of URLs, or list of Result objects.
            text (TextContentsOptions | True, optional): Options for text extraction.
            summary (SummaryContentsOptions | True, optional): Options for summary generation.
            max_age_hours (int, optional): Maximum age of cached content in hours. If content is older,
                it will be fetched fresh. Special values: 0 = always fetch fresh content,
                -1 = never fetch fresh (cache only). Example: 168 = fetch fresh for pages older than 7 days.
            filter_empty_results (bool, optional): Whether to filter out empty results.
            subpages (int, optional): Number of subpages to retrieve.
            subpage_target (str | List[str], optional): Target subpages to retrieve.
            extras (ExtrasOptions, optional): Options for extra content (links, image_links).
            flags (List[str], optional): Experimental flags.

        Returns:
            SearchResponse[Result]: The response containing the contents of the URLs.

        Examples:
            # Get contents for a single URL
            contents = exa.get_contents("https://example.com/article")

            # Get contents for multiple URLs
            contents = exa.get_contents([
                "https://example.com/article1",
                "https://example.com/article2"
            ])
        r   c                    g | ]	}|j         
S rS   r   r5   rs     r7   r   z$Exa.get_contents.<locals>.<listcomp>      (((aAE(((r9   r   rP  Nr   r   r   r  r"  	/contentsr0  r  rr   r  r  rr   r  r  r  r   r4   rJ  rK  rL  rM  rN  r   r   rb  r   r1  r2  r3  r   r4  r   r  r  r  )rD   r*   r  lenrH  rJ   r7  r  r>  r?  r   r?   r   rE   r#  r  rn   r   r  rT   r`  r   r  rP  r   rA  r   rF   rG   rB  rC  r>   r  r  r  r  r\  r:  s                  r7   rK  zExa.get_contents  s   < dC   	)6DDd## 	)D		A*T!Wg:V:V((4(((D4.LLNN 	 	DAqF{{q}
 '!!((''/1GHGFO4555=>>>888 Jwy/A4$H$H"9-L<'')>|H?U)V)VX&(44||K11)$((=*A*ABBhhz2.. 	 	FOOzz$''!::h//!::h//      9o 	 	F(00LNN$((//#''--&**733&**733#/#3#34D#E#E'++H55&**733(,,Y77)--j99'++H55%))&11(,,Y77+//==%1%5%56H%I%I,VZZ
-C-CDD     & HH)**HHZ  HHY''%..
 
 
 	
r9   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   c                  d t                                                      D             }|du r|                    dd           n|d|vrddt          ii|d<   n|||d<   t	          |t
                     t          |          }|                     d|          }t          |	                    d                    }g }|d	         D ]m}t          |          }|                    t          |	                    d
          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          t          |	                    d                                         ot          ||	                    d          |	                    d          ||	                    d                    S )aA  Finds similar pages to a given URL, potentially with domain filters and date filters.

        By default, returns text contents with 10,000 max characters. Use contents=False to opt-out.

        Args:
            url (str): The URL to find similar pages for.
            contents (ContentsOptions | False, optional): Options for retrieving page contents.
                Defaults to {"text": {"maxCharacters": 10000}}. Use False to disable contents.
                See ContentsOptions for available options (text, highlights, summary, etc.).
            num_results (int, optional): Number of results to return. Default is None (server default).
            include_domains (List[str], optional): Domains to include in the search.
            exclude_domains (List[str], optional): Domains to exclude from the search.
            start_crawl_date (str, optional): Only links crawled after this date.
            end_crawl_date (str, optional): Only links crawled before this date.
            start_published_date (str, optional): Only links published after this date.
            end_published_date (str, optional): Only links published before this date.
            include_text (List[str], optional): Strings that must appear in the page text.
            exclude_text (List[str], optional): Strings that must not appear in the page text.
            exclude_source_domain (bool, optional): Whether to exclude the source domain.
            category (Category, optional): Data category to focus on (e.g. 'company', 'news', 'research paper').
            flags (List[str], optional): Experimental flags.

        Returns:
            SearchResponse[Result]

        Examples:
            similar_results = exa.find_similar(
                "miniclip.com",
                num_results=2,
                exclude_source_domain=True
            )
        c                *    i | ]\  }}|d k    |||S r  rS   rU   s      r7   rH   z$Exa.find_similar.<locals>.<dictcomp>  r-  r9   Fr   Nr   r  /findSimilarr0  r  r   rr   r4   rJ  rK  rL  rM  rN  r   r   r   r   rb  r   r1  r2  r3  r4  r  r  )r6  rJ   r  r7  r   FIND_SIMILAR_OPTIONS_TYPESrE   r#  r  rn   rT   r   r`  r   r  rP  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r>   r  r  r\  r:  s                        r7   find_similarzExa.find_similarW  st   d WVFHHNN$4$4VVV uKK
D))))*G";";#),<>T+U"VGJ!"*GJ)CDDD((||NG44)$((=*A*ABB9o 	 	F(00LNN$((//#''--&**733&**733#/#3#34D#E#E'++H55&**733(,,Y77)--j99'++H55%))&11(,,Y77+//==%1%5%56H%I%I,VZZ
-C-CDD     & HH)**HHZ  %..
 
 
 	
r9   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   c                   d S r3   rS   )rP  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   s                        r7   find_similar_and_contentszExa.find_similar_and_contents  s	    0 *-r9   c                   d S r3   rS   rP  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   s                         r7   re  zExa.find_similar_and_contents  	    2 *-r9   c                   d S r3   rS   rg  s                         r7   re  zExa.find_similar_and_contents  rh  r9   c                   d S r3   rS   )rP  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   s                         r7   re  zExa.find_similar_and_contents  s	    2 -0Cr9   c                   d S r3   rS   )rP  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   s                          r7   re  zExa.find_similar_and_contents#  s	    4 473r9   c                (   d|i}|                                 D ]\  }}||||<   d|vrd|vrdt          i|d<   i }|                    t                     |                    t                     |                    t
                     t          ||           d|v r?t          |d         t                    r$|d         }d|v rt          |d                   |d<   t          |g dd          }t          |dg	          }|                     d
|          }t          |                    d                    }	g }
|d         D ]m}t          |          }|
                    t#          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          t%          |                    d                                         ot'          |
|                    d          |                    d          |                    d          |	|                    d                    S u  
        DEPRECATED: Use find_similar() instead. The find_similar() method now returns text contents by default.

        Migration:
        - find_similar_and_contents(url) → find_similar(url)
        - find_similar_and_contents(url, text=True) → find_similar(url, contents={"text": True})
        - find_similar_and_contents(url, summary=True) → find_similar(url, contents={"summary": True})
        r   Nr   r   r  r"  r=  r   r.  r_  r0  r  rr   r4   rJ  rK  rL  rM  rN  r   r   r   rb  r   r1  r2  r3  r   r4  r   r  r  )rJ   r7  r  ra  r>  r?  r   rD   r?   r   r  rE   r#  r  rn   rT   r   r`  r   r  rP  r   rA  r   rF   rG   rB  rC  r>   r  r  r\  r:  s                r7   re  zExa.find_similar_and_contents?  s    #,LLNN 	 	DAq}
  Yg%=%=/1GHGFO89994555=>>>888 Jwy/A4$H$H"9-L<'')>|H?U)V)VX&    
 
   H:>>>||NG44)$((=*A*ABB9o 	 	F(00LNN$((//#''--&**733&**733#/#3#34D#E#E'++H55&**733(,,Y77)--j99'++H55%))&11(,,Y77+//==%1%5%56H%I%I,VZZ
-C-CDD     & HH)**HHZ  HHY''%..
 
 
 	
r9   clientr   c                     |j         j        j        t                    	 	 	 	 	 	 	 	 	 	 	 	 	 	 d d! fd            }t	          d           ||j         j        _        |S )"a  Wrap an OpenAI client with Exa functionality.

        After wrapping, any call to `client.chat.completions.create` will be intercepted
        and enhanced with Exa RAG functionality. To disable Exa for a specific call,
        set `use_exa="none"` in the `create` method.

        Args:
            client (OpenAI): The OpenAI client to wrap.

        Returns:
            OpenAI: The wrapped OpenAI client.
        r      N   messages$Iterable[ChatCompletionMessageParam]modelUnion[str, ChatModel]use_exa-Optional[Literal['required', 'none', 'auto']]r   r:  r   ra  r   r   r<  r   r   r   r   r   r   r&  r   r'  result_max_lenr  r   c                    |||||||	|
||||d}d|i}|                     |                               t          |           |||          S )N)r   r   r   r   r   r   r   r   r   r   r   r   rv  )	create_fnrt  max_lencreate_kwargs
exa_kwargs)r  _create_with_toolr  )rt  rv  rx  r   r   r   r   r   r   r   r   r   r   r   rz  r   openai_kwargsr  r~  funcrP  s                      r7   create_with_ragz!Exa.wrap.<locals>.create_with_rag  s    0  +#2#2$4"0(<&8 , ,$ J %e,M  ///))h&+% *   r9   z.Wrapping OpenAI client with Exa functionality.)r   rr  NNNNNNNNNNrs  N) rt  ru  rv  rw  rx  ry  r   r:  r   ra  r   ra  r   r<  r   r<  r   r<  r   r<  r   ra  r   ra  r   r&  r   r'  rz  r  r   ra  )chatcompletionscreater   print)rP  rp  r  r  s   `  @r7   wrapzExa.wrap  s     {&-	t FL)*3737.2,02604040459+/"&)-%.	 .	 .	 .	 .	 .	 .	 
.	` 	>???)8&r9   r|  r   rt   List[ChatCompletionMessageParam]r   c                *   ddddddddidgd	d
dg}||d<    |dd|i|}t          |          }|st          j        |d           S |                     ||                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d                    }	t          |	|          }
t          |||
          } |dd|i|}t          j        ||	          }|S )Nfunctionr   z(Search the web for relevant information.objectr   stringzThe query to search for.)r   r   )r   r   r   )rs   r   
parameters)r   r  toolsrt  )
completion
exa_resultr   r   r   r   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   )r}  rS   )r   r   from_completionrD  rn   r   r   )rP  r|  rt  r}  r~  r  r  r  r   r  exa_strnew_messagesexa_completions                r7   r  zExa._create_with_tool  s    #$#M (#(0/I& &' &-I	# 	#  
( "'gYBBBMBB

++ 	&6%$   
 --"}55&NN+<==&NN+<=='^^,>??%>>*:;;!+0F!G!G)~~.BCC#77#77''^^J//..)) . 
 

 $J@@@.z8WMMYFFFFF
,<!j
 
 
 r9   Fr  r   r   rv  r   r   r  rv  #Optional[Literal['exa', 'exa-pro']]Optional[JSONSchemaInput]+Union[AnswerResponse, StreamAnswerResponse]c                   d S r3   rS   )rP  r   r  r   r   rv  r   r   s           r7   r  z
Exa.answer	  s	     7:cr9   c                  |rt          d          d t                                                      D             }d|v r |d         t          |d                   |d<   t	          |dg          }|                     d|          }	g }
|	d         D ]}t          |          }|
                    t          |	                    d          |	                    d          |	                    d	          |	                    d
          |	                    d          |	                    d                               t          |		                    d                    }t          |	d         |
|          S )a  Generate an answer to a query using Exa's search and LLM capabilities.

        Args:
            query (str): The query to answer.
            text (bool, optional): Whether to include full text in the results. Defaults to False.
            system_prompt (str, optional): A system prompt to guide the LLM's behavior when generating the answer.
            model (str, optional): The model to use for answering. Defaults to None.
            output_schema (dict[str, Any], optional): JSON schema describing the desired answer structure.

        Returns:
            AnswerResponse: An object containing the answer and citations.

        Raises:
            ValueError: If stream=True is provided. Use stream_answer() instead for streaming responses.

        Examples:
            response = exa.answer("What is the capital of France?")

            print(response.answer)       # e.g. "Paris"
            print(response.citations)    # list of citations used

            # If you want the full text of the citations in the response:
            response_with_text = exa.answer(
                "What is the capital of France?",
                text=True
            )
            print(response_with_text.citations[0].text)  # Full page text
        Zstream=True is not supported in `answer()`. Please use `stream_answer(...)` for streaming.c                *    i | ]\  }}|d k    |||S r  rS   rU   s      r7   rH   zExa.answer.<locals>.<dictcomp>P	  r-  r9   r   N/answerr  rr   r   r4   rK  rL  r   r  r0  r  )r   r6  rJ   r   rE   r#  rT   r   r  rn   r  r  rP  r   r  r   r   rv  r   r   r   responser  r\  r:  r  s                 r7   r  z
Exa.answer#	  s   N  	A  
 WVFHHNN$4$4VVV g%%'/*B*N'<W_=U'V'VGO$/):;;<<	733	{+ 	 	F(00L#''--$((//&**733#/#3#34D#E#E'++H55%))&11  	 	 	 	 *(,,}*E*EFFhx0)\JJJr9   r   r   rv  r   r   r  r  c                  d t                                                      D             }d|v r |d         t          |d                   |d<   t          |dg          }d|d<   |                     d|          }t          |          S )a]  Generate a streaming answer response.

        Args:
            query (str): The query to answer.
            text (bool): Whether to include full text in the results. Defaults to False.
            system_prompt (str, optional): A system prompt to guide the LLM's behavior when generating the answer.
            model (str, optional): The model to use for answering. Defaults to None.
            output_schema (dict[str, Any], optional): JSON schema describing the desired answer structure.

        Returns:
            StreamAnswerResponse: An object that can be iterated over to retrieve (partial text, partial citations).
                Each iteration yields a tuple of (Optional[str], Optional[List[AnswerResult]]).

        Examples:
            stream = exa.stream_answer("What is the capital of France?", text=True)

            for chunk in stream:
                if chunk.content:
                    print("Partial answer:", chunk.content)
                if chunk.citations:
                    for citation in chunk.citations:
                        print("Citation found:", citation.url)
        c                *    i | ]\  }}|d k    |||S r  rS   rU   s      r7   rH   z%Exa.stream_answer.<locals>.<dictcomp>	  r-  r9   r   Nr.  Tr  r  )r6  rJ   r   rE   r#  r  	rP  r   r   r   rv  r   r   r   r  s	            r7   stream_answerzExa.stream_answeri	  s    B WVFHHNN$4$4VVV g%%'/*B*N'<W_=U'V'VGO$O3DEEE ||Iw77#L111r9   )r  N)r  r<  r  r*   r  r<  Nr  NN)r  r*   r>   r	  r
  r*   r  r  r  r  r+   r  (r   r*   r   r%  r   r:  r   ra  r   ra  r   r<  r   r<  r   r<  r   r<  r   ra  r   ra  r   r&  r   r'  r   ra  r   r(  r   r<  r   ra  r   r<  r   r)  r+   r*  r   r*   )NNNNNNNN)r   rE  r   r:  r   rF  r   r:  r   r(  r   r:  r   rG  r   rH  r   ra  r+   rI  )r   rE  r   r/  r   r:  r   rF  r   r:  r   r(  r   r:  r   rG  r   rH  r   ra  r+   rI  )r   rE  r   r0  r   r:  r   rF  r   r:  r   r(  r   r:  r   rG  r   rH  r   ra  r+   rM  )r   rE  r   r/  r   r0  r   r:  r   rF  r   r:  r   r(  r   r:  r   rG  r   rH  r   ra  r+   rO  r   rE  r   r*   r   r%  r   r:  r   ra  r   ra  r   r<  r   r<  r   r<  r   r<  r   ra  r   ra  r   r(  r   r'  r   ra  r+   r*  )*r   r*   r   r:  r   ra  r   ra  r   r<  r   r<  r   r<  r   r<  r   ra  r   ra  r   r(  r   r'  r   ra  r   r:  r   rF  r   r:  r   r(  r   r:  r   rG  r   rH  r+   rI  ),r   r*   r   r/  r   r:  r   ra  r   ra  r   r<  r   r<  r   r<  r   r<  r   ra  r   ra  r   r(  r   r'  r   ra  r   r:  r   rF  r   r:  r   r(  r   r:  r   rG  r   rH  r+   rI  ),r   r*   r   r0  r   r:  r   ra  r   ra  r   r<  r   r<  r   r<  r   r<  r   ra  r   ra  r   r(  r   r'  r   ra  r   r:  r   rF  r   r:  r   r(  r   r:  r   rG  r   rH  r+   rM  ).r   r*   r   r/  r   r0  r   r:  r   ra  r   ra  r   r<  r   r<  r   r<  r   r<  r   ra  r   ra  r   r(  r   r'  r   ra  r   r:  r   rF  r   r:  r   r(  r   r:  r   rG  r   rH  r+   rO  r   r*   )rp  r   )r|  r   rt  r  r+   r   r   r*   r  r(  r   r(  r   r<  rv  r  r   r  r   r<  r+   r  )r   r*   r   r  r   r<  rv  r  r   r  r   r<  r+   r  )r   r   r   r   rQ  r#  r   rD  r   rK  rc  re  r  r  r  r  rS   r9   r7   r  r  ^  sA       00
 -$(	$3 $3 $3 $3 $3R 6:+/,0Q Q Q Q Qn FJ%)/3/3*.(,.2,0,0,015'+%)%)'+26'+48+
 
 
 
 
 
BT
 T
 T
 T
l  ,015'+/3"&:>*.%)- - - - X-  ,015'+/3"&:>*.%)- - - - - X-  ,015'+/3"&:>*.%)0 0 0 0 0 X0  ,015'+/3"&:>*.%)7 7 7 7 7 X7 e
 e
 e
 e
V FJ%)/3/3*.(,.2,0,0,004'+%)!_
 _
 _
 _
 _
 _
B 
 &*/3/3*.(,.2,0,0,004'+%)+/15'+/3"&:>*.-- - - - - X-2  &*/3/3*.(,.2,0,0,004'+%)+/15'+/3"&:>*./- - - - - X-4  &*/3/3*.(,.2,0,0,004'+%)+/15'+/3"&:>*./- - - - - X-4  &*/3/3*.(,.2,0,0,004'+%)+/15'+/3"&:>*./0 0 0 0 0 X04  &*/3/3*.(,.2,0,0,004'+%)+/15'+/3"&:>*.17 7 7 7 7 X76O
 O
 O
 O
bD D D DL> > > >@ 
 "'$'+5937'+
: 
: 
: 
: 
: X
:  "'$'+5937'+DK DK DK DK DK DKT '+5937'+*2 *2 *2 *2 *2 *2 *2 *2r9   r  c                       e Zd ZdDdE fdZedFd            Z	 	 	 	 dGdHdZd	d	d	d	d	d	d	d	d	d	d	d	d	d	d	d	d	d	ddId-ZdJd.ZdKd1Z	d	d	d	d	d	d	d	d	d	d	d	d	d	d2dLd5Z
dMd6Zd7d7d	d	d	d	d8dNd?Zd7d	d	d	d	d@dOdCZ xZS )PAsyncExar  r  r*   api_basec                    t                                          ||           t          |           | _        t	          |           | _        t          |           | _        d | _        d S r3   )	rd  rQ  r&   r  r   r  r$   r  _client)rP  r  r  re  s      r7   rQ  zAsyncExa.__init__	  sU    (++++D11)$//1$77r9   r+   httpx.AsyncClientc                j    | j         &t          j        | j        | j        d          | _         | j         S )NiX  )r  r  timeout)r  httpxAsyncClientr  r  r  s    r7   rp  zAsyncExa.client	  s:     < ,c  DL |r9   Nr  r  r
  r  r  c                  K   |r*t          |t                    r|                    d          p|o|                    d          dk    }i | j        }|r|                    |           |                                dk    rs|rDt          j        d| j        |z   ||          }| j	        
                    |d           d{V }	|	S | j	                            | j        |z   ||           d{V }	n#|                                dk    rr|rDt          j        d| j        |z   ||	          }| j	        
                    |d           d{V }	|	S | j	                            | j        |z   ||	           d{V }	n|                                d
k    r,| j	                            | j        |z   ||	           d{V }	nU|                                dk    r+| j	                            | j        |z   |           d{V }	nt          d|           |	j        dk    r*|	j        dk    rt          d|	j         d|	j                   |	                                S )a  Send a request to the Exa API, optionally streaming if data['stream'] is True.

        Args:
            endpoint (str): The API endpoint (path).
            data (dict, optional): The JSON payload to send.
            method (str, optional): The HTTP method to use. Defaults to "POST".
            params (dict, optional): Query parameters.
            headers (Dict[str, str], optional): Additional headers to include in the request. Defaults to None.

        Returns:
            Union[dict, httpx.Response]: If streaming, returns the Response object.
            Otherwise, returns the JSON-decoded response as a dict.

        Raises:
            ValueError: If the request fails (non-200 status code).
        r  r  r  )r  r  T)r  Nr  )r  r  r  r  r  r  r     r  r  )rD   r?   rn   r  r  r  r  Requestr  rp  sendr  r  r  r   r  r   r  )
rP  r  r>   r
  r  r  r   r!  r#  r"  s
             r7   async_requestzAsyncExa.async_request	  s     2  QJtT$:$:Qtxx?Q?Q 
5vzz(++v5 	
 +T\* 	,""7+++<<>>U"" -MH,!+	   !K,,WT,BBBBBBBB
 KOOMH,V_ ,         \\^^v%% 	-DMH44   !K,,WT,BBBBBBBB
 K,,MH,4 -         \\^^w&&))(t_ *        CC \\^^x''**(/ +        CC AAABBB?c!!co&<&<P3?PPchPP   xxzzr9   r$  r   r   r%  r   r:  r   ra  r   r   r<  r   r   r   r   r   r   r&  r   r'  r   r   r(  r   r   r   r   r)  r*  c                 K   d t                                                      D             }|du r|                    dd           n|d|vrddt          ii|d<   n|||d<   t	          |t
                     t          |dg          }|                     d	|           d{V }t          |	                    d
                    }g }|d         D ]m}t          |          }|                    t          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          t          |	                    d                                         ot          ||	                    d          |	                    d          |	                    d          t          |	                    d                    ||	                    d                     S )!aD  Perform a search with a prompt-engineered query to retrieve relevant results.

        By default, returns text contents with 10,000 max characters. Use contents=False to opt-out.

        Args:
            query (str): The query string.
            contents (ContentsOptions | False, optional): Options for retrieving page contents.
                Defaults to {"text": {"maxCharacters": 10000}}. Use False to disable contents.
                See ContentsOptions for available options (text, highlights, summary, etc.).
                Note: The ``context`` option is deprecated; use ``highlights`` or ``text`` instead.
            num_results (int, optional): Number of search results to return. Default 10.
            include_domains (List[str], optional): Domains to include in the search.
            exclude_domains (List[str], optional): Domains to exclude from the search.
            start_crawl_date (str, optional): Only links crawled after this date.
            end_crawl_date (str, optional): Only links crawled before this date.
            start_published_date (str, optional): Only links published after this date.
            end_published_date (str, optional): Only links published before this date.
            include_text (List[str], optional): Strings that must appear in the page text.
            exclude_text (List[str], optional): Strings that must not appear in the page text.
            type (SearchType, optional): Search type - 'auto' (default), 'fast', 'deep', 'deep-reasoning', 'neural', or 'instant'.
            category (Category, optional): Data category to focus on (e.g. 'company', 'news', 'research paper').
            flags (List[str], optional): Experimental flags for Exa usage.
            moderation (bool, optional): If True, the search results will be moderated for safety.
            user_location (str, optional): Two-letter ISO country code of the user (e.g. US).
            additional_queries (List[str], optional): Alternative query formulations for deep search to skip
                automatic LLM-based query expansion. Max 5 queries. Only applicable when type is
                'deep' or 'deep-reasoning'.
                Example: ["machine learning", "ML algorithms", "neural networks"]
            system_prompt (str, optional): Deep-search-only instructions that guide both the
                search process and the final returned result. Use this to prefer certain sources,
                emphasize novelty, avoid duplicates, or constrain the response style.
                Only applicable when type is 'deep' or 'deep-reasoning'.
            output_schema (DeepOutputSchema, optional): Deep output schema for deep search.
                Use ``{"type": "text", "description": ...}`` for plain text output or
                ``{"type": "object", "properties": ..., "required": ...}`` for structured JSON.
                For object schemas, max nesting depth is 2 and max total properties is 10.
                Only applicable when type is 'deep' or 'deep-reasoning'.

        Returns:
            SearchResponse: The response containing search results, etc.

        Examples:
            Basic async search:
            >>> async_exa = AsyncExa(api_key="your-api-key")
            >>> results = await async_exa.search("latest AI research papers")
            >>> print(results.results[0].title)

            Async search with filters:
            >>> results = await async_exa.search(
            ...     "climate change research",
            ...     include_domains=["nature.com", "science.org"],
            ...     start_published_date="2024-01-01"
            ... )
        c                *    i | ]\  }}|d k    |||S r  rS   rU   s      r7   rH   z#AsyncExa.search.<locals>.<dictcomp>B
  r-  r9   Fr   Nr   r  r   r.  r/  r0  r  r   rr   r4   rJ  rK  rL  rM  rN  r   r   r   r   rb  r   r1  r2  r3  r   r  r4  r5  )r6  rJ   r  r7  r   r8  rE   r  r  rn   rT   r   r`  r   r  r  r9  s                             r7   r   zAsyncExa.search	  s     Z WVFHHNN$4$4VVV uKK
D))))*G";";#),<>T+U"VGJ!"*GJ)=>>>O3DEEE''	7;;;;;;;;)$((=*A*ABB9o 	 	F(00LNN$((//#''--&**733&**733#/#3#34D#E#E'++H55&**733(,,Y77)--j99'++H55%))&11(,,Y77+//==%1%5%56H%I%I,VZZ
-C-CDD     & HH)**HHZ  HHY''+DHHX,>,>??%..
 
 
 	
r9   c                @  K   d|i}|                                 D ]\  }}||||<   d|vrd|vrd|vrdt          i|d<   i }|                    t                     |                    t                     |                    t
                     t          ||           d|v r?t          |d         t                    r$|d         }d|v rt          |d                   |d<   t          |g dd	          }t          |dg
          }|                     d|           d{V }t          |                    d                    }	g }
|d         D ]m}t          |          }|
                    t#          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          t%          |                    d                                         ot'          |
|                    d          |                    d          |                    d          |	|                    d                    S ) r<  r   Nr   r   r   r  r"  r=  r   r.  r/  r0  r  r   rr   r4   rJ  rK  rL  rM  rN  r   r   rb  r   r1  r2  r3  r   r4  rn  )rJ   r7  r  r8  r>  r?  r   rD   r?   r   r  rE   r  r  rn   rT   r   r`  r   r  r@  s                r7   rD  zAsyncExa.search_and_contentss
  sB      E"LLNN 	 	DAq}
 '!!((''/1GHGFO23334555=>>>888 Jwy/A4$H$H"9-L<'')>|H?U)V)VX&    
 
   H:>>>''	7;;;;;;;;)$((=*A*ABB9o 	 	F(00LNN$((//#''--&**733&**733#/#3#34D#E#E'++H55&**733(,,Y77)--j99'++H55%))&11(,,Y77+//==%1%5%56H%I%I,VZZ
-C-CDD     & HH)**HHZ  HHY''%..
 
 
 	
r9   r   rE  c                  K   t          |t                    r|g}nOt          |t                    r:t          |          dk    r't          |d         t                    rd |D             }d|i}|                                D ]\  }}|dk    r||||<   d|vrd|vrd|vrd	t          i|d<   i }|                    t                     |                    t                     t          ||           d|v r?t          |d         t                    r$|d         }d
|v rt          |d
                   |d
<   t          |d
g          }|                     d|           d{V }t          |                    d                    }	g }
|                    dg           D ]`}|
                    t%          |                    d          |                    d          |                    d                               ag }|d         D ]m}t'          |          }|                    t)          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          t+          |                    d                                         ot-          ||                    d          |                    d           |                    d!          |	|
|                    d"          #          S )$as  Retrieve contents for a list of URLs asynchronously.

        Args:
            urls (str | List[str] | List[Result]): A single URL, list of URLs, or list of Result objects.
            text (TextContentsOptions | True, optional): Options for text extraction.
            summary (SummaryContentsOptions | True, optional): Options for summary generation.
            max_age_hours (int, optional): Maximum age of cached content in hours. If content is older,
                it will be fetched fresh. Special values: 0 = always fetch fresh content,
                -1 = never fetch fresh (cache only). Example: 168 = fetch fresh for pages older than 7 days.
            filter_empty_results (bool, optional): Whether to filter out empty results.
            subpages (int, optional): Number of subpages to retrieve.
            subpage_target (str | List[str], optional): Target subpages to retrieve.
            extras (ExtrasOptions, optional): Options for extra content (links, image_links).
            flags (List[str], optional): Experimental flags.

        Returns:
            SearchResponse[Result]: The response containing the contents of the URLs.

        Examples:
            Get contents for URLs asynchronously:
            >>> async_exa = AsyncExa(api_key="your-api-key")
            >>> results = await async_exa.get_contents("https://example.com/article")
            >>> print(results.results[0].text)

            Get contents from async search results:
            >>> search_results = await async_exa.search("AI news", contents=False)
            >>> contents = await async_exa.get_contents(search_results.results[:5])
        r   c                    g | ]	}|j         
S rS   rS  rT  s     r7   r   z)AsyncExa.get_contents.<locals>.<listcomp>
  rV  r9   r   rP  Nr   r   r   r  r"  rW  r0  r  rr   r  r  rX  r  r   r4   rJ  rK  rL  rM  rN  r   r   rb  r   r1  r2  r3  r   r4  rY  )rD   r*   r  rZ  rH  rJ   r7  r  r>  r?  r   r?   r   rE   r  r  rn   r   r  rT   r`  r   r  r[  s                  r7   rK  zAsyncExa.get_contents
  s     < dC   	)6DDd## 	)D		A*T!Wg:V:V((4(((D4.LLNN 	 	DAqF{{q}
 '!!((''/1GHGFO4555=>>>888 Jwy/A4$H$H"9-L<'')>|H?U)V)VX&(44''W========)$((=*A*ABBhhz2.. 	 	FOOzz$''!::h//!::h//      9o 	 	F(00LNN$((//#''--&**733&**733#/#3#34D#E#E'++H55&**733(,,Y77)--j99'++H55%))&11(,,Y77+//==%1%5%56H%I%I,VZZ
-C-CDD     & HH)**HHZ  HHY''%..
 
 
 	
r9   r\  r   r   c                 K   d t                                                      D             }|du r|                    dd           n|d|vrddt          ii|d<   n|||d<   t	          |t
                     t          |          }|                     d|           d{V }t          |	                    d                    }g }|d	         D ]m}t          |          }|                    t          |	                    d
          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          t          |	                    d                                         ot          ||	                    d          |	                    d          ||	                    d                    S )a  Finds similar pages to a given URL, potentially with domain filters and date filters.

        By default, returns text contents with 10,000 max characters. Use contents=False to opt-out.

        Args:
            url (str): The URL to find similar pages for.
            contents (ContentsOptions | False, optional): Options for retrieving page contents.
                Defaults to {"text": {"maxCharacters": 10000}}. Use False to disable contents.
                See ContentsOptions for available options (text, highlights, summary, etc.).
            num_results (int, optional): Number of results to return. Default is None (server default).
            include_domains (List[str], optional): Domains to include in the search.
            exclude_domains (List[str], optional): Domains to exclude from the search.
            start_crawl_date (str, optional): Only links crawled after this date.
            end_crawl_date (str, optional): Only links crawled before this date.
            start_published_date (str, optional): Only links published after this date.
            end_published_date (str, optional): Only links published before this date.
            include_text (List[str], optional): Strings that must appear in the page text.
            exclude_text (List[str], optional): Strings that must not appear in the page text.
            exclude_source_domain (bool, optional): Whether to exclude the source domain.
            category (Category, optional): Data category to focus on (e.g. 'company', 'news', 'research paper').
            flags (List[str], optional): Experimental flags.

        Returns:
            SearchResponse[Result]

        Examples:
            Find similar pages asynchronously:
            >>> async_exa = AsyncExa(api_key="your-api-key")
            >>> results = await async_exa.find_similar("https://www.nature.com/articles/s41586-021-03819-2")
            >>> print(results.results[0].title)

            Find similar with domain filters:
            >>> results = await async_exa.find_similar(
            ...     "https://arxiv.org/abs/2301.00001",
            ...     include_domains=["arxiv.org", "openreview.net"],
            ...     exclude_source_domain=True
            ... )
        c                *    i | ]\  }}|d k    |||S r  rS   rU   s      r7   rH   z)AsyncExa.find_similar.<locals>.<dictcomp>g  r-  r9   Fr   Nr   r  r_  r0  r  r   rr   r4   rJ  rK  rL  rM  rN  r   r   r   r   rb  r   r1  r2  r3  r4  r`  )r6  rJ   r  r7  r   ra  rE   r  r  rn   rT   r   r`  r   r  rb  s                        r7   rc  zAsyncExa.find_similar/  s     p WVFHHNN$4$4VVV uKK
D))))*G";";#),<>T+U"VGJ!"*GJ)CDDD((''@@@@@@@@)$((=*A*ABB9o 	 	F(00LNN$((//#''--&**733&**733#/#3#34D#E#E'++H55&**733(,,Y77)--j99'++H55%))&11(,,Y77+//==%1%5%56H%I%I,VZZ
-C-CDD     & HH)**HHZ  %..
 
 
 	
r9   c                8  K   d|i}|                                 D ]\  }}||||<   d|vrd|vrdt          i|d<   i }|                    t                     |                    t                     |                    t
                     t          ||           d|v r?t          |d         t                    r$|d         }d|v rt          |d                   |d<   t          |g dd          }t          |dg	          }|                     d
|           d{V }t          |                    d                    }	g }
|d         D ]m}t          |          }|
                    t#          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          t%          |                    d                                         ot'          |
|                    d          |                    d          |                    d          |	|                    d                    S rm  )rJ   r7  r  ra  r>  r?  r   rD   r?   r   r  rE   r  r  rn   rT   r   r`  r   r  ro  s                r7   re  z"AsyncExa.find_similar_and_contents  s3      #,LLNN 	 	DAq}
  Yg%=%=/1GHGFO89994555=>>>888 Jwy/A4$H$H"9-L<'')>|H?U)V)VX&    
 
   H:>>>''@@@@@@@@)$((=*A*ABB9o 	 	F(00LNN$((//#''--&**733&**733#/#3#34D#E#E'++H55&**733(,,Y77)--j99'++H55%))&11(,,Y77+//==%1%5%56H%I%I,VZZ
-C-CDD     & HH)**HHZ  HHY''%..
 
 
 	
r9   Fr  r  r   rv  r  r  r  c                 K   |rt          d          d t                                                      D             }d|v r |d         t          |d                   |d<   t	          |dg          }|                     d|           d{V }	g }
|	d         D ]}t          |          }|
                    t          |	                    d          |	                    d	          |	                    d
          |	                    d          |	                    d          |	                    d                               t          |		                    d                    }t          |	d         |
|          S )a  Generate an answer to a query using Exa's search and LLM capabilities.

        Args:
            query (str): The query to answer.
            text (bool, optional): Whether to include full text in the results. Defaults to False.
            system_prompt (str, optional): A system prompt to guide the LLM's behavior when generating the answer.
            model (str, optional): The model to use for answering. Defaults to None.
            output_schema (dict[str, Any], optional): JSON schema describing the desired answer structure.

        Returns:
            AnswerResponse: An object containing the answer and citations.

        Raises:
            ValueError: If stream=True is provided. Use stream_answer() instead for streaming responses.

        Examples:
            Basic async question answering:
            >>> async_exa = AsyncExa(api_key="your-api-key")
            >>> response = await async_exa.answer("What are the latest developments in quantum computing?")
            >>> print(response.answer)

            Async answer with citations:
            >>> response = await async_exa.answer("Explain renewable energy benefits", text=True)
            >>> for citation in response.citations:
            ...     print(f"{citation.title}: {citation.url}")
        r  c                *    i | ]\  }}|d k    |||S r  rS   rU   s      r7   rH   z#AsyncExa.answer.<locals>.<dictcomp>  r-  r9   r   Nr.  r  r  rr   r   r4   rK  rL  r   r  r0  r  )r   r6  rJ   r   rE   r  rT   r   r  rn   r  r  r  s                 r7   r  zAsyncExa.answer  s     J  	A  
 WVFHHNN$4$4VVV g%%'/*B*N'<W_=U'V'VGO$O3DEEE++Iw????????	{+ 	 	F(00L#''--$((//&**733#/#3#34D#E#E'++H55%))&11  	 	 	 	 *(,,}*E*EFFhx0)\JJJr9   r  r  r  c               &  K   d t                                                      D             }d|v r |d         t          |d                   |d<   t          |dg          }d|d<   |                     d|           d{V }t          |          S )a  Generate a streaming answer response.

        Args:
            query (str): The query to answer.
            text (bool): Whether to include full text in the results. Defaults to False.
            system_prompt (str, optional): A system prompt to guide the LLM's behavior when generating the answer.
            model (str, optional): The model to use for answering. Defaults to None.
            output_schema (dict[str, Any], optional): JSON schema describing the desired answer structure.
            user_location (str, optional): The user's location for location-aware answers.

        Returns:
            AsyncStreamAnswerResponse: An object that can be iterated over to retrieve (partial text, partial citations).
                Each iteration yields a tuple of (Optional[str], Optional[List[AnswerResult]]).

        Examples:
            Stream an answer asynchronously:
            >>> async_exa = AsyncExa(api_key="your-api-key")
            >>> async for chunk in async_exa.stream_answer("What is quantum computing?"):
            ...     if chunk.text:
            ...         print(chunk.text, end="", flush=True)

            Async stream with citations:
            >>> async for chunk in async_exa.stream_answer("Explain climate change", text=True):
            ...     if chunk.text:
            ...         print(chunk.text, end="")
            ...     if chunk.citations:
            ...         print(f"\nCitations: {[c.url for c in chunk.citations]}")
        c                *    i | ]\  }}|d k    |||S r  rS   rU   s      r7   rH   z*AsyncExa.stream_answer.<locals>.<dictcomp>P  r-  r9   r   Nr.  Tr  r  )r6  rJ   r   rE   r  r  r  s	            r7   r  zAsyncExa.stream_answer*  s      L WVFHHNN$4$4VVV g%%'/*B*N'<W_=U'V'VGO$O3DEEE !//	7CCCCCCCC(666r9   )r  )r  r*   r  r*   )r+   r  r  )r  r*   r
  r*   r  r  r  r  r  r  r  r  )r   r*   r   r  r   r<  rv  r  r   r  r   r<  r+   r  )r   r   r   rQ  propertyrp  r  r   rD  rK  rc  re  r  r  ri  rj  s   @r7   r  r  	  s                 X ,0I I I I I^ FJ%)/3/3*.(,.2,0,0,015'+%)%)'+26'+48+|
 |
 |
 |
 |
 |
|S
 S
 S
 S
je
 e
 e
 e
V FJ%)/3/3*.(,.2,0,0,004'+%)!e
 e
 e
 e
 e
 e
NN
 N
 N
 N
h "'$'+5937'+BK BK BK BK BK BKP '+5937'+/7 /7 /7 /7 /7 /7 /7 /7 /7 /7r9   r  )r)   r*   r+   r*   )r>   r?   r@   rA   r+   r?   )rK   r*   r+   r*   )r>   r?   r+   r?   )rV   rW   r+   rX   )r   r   r   r?   r+   r   )r   r?   r+   r   )r   r   r+   r  )r  r   r  r   r  r*   )}
__future__r   rs  r  r  rM   r   	functoolsr   typingr   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r  r   r  r  openair   /openai.types.chat.chat_completion_message_paramr   openai.types.chat_modelr   typing_extensionsr   exa_py.utilsr   r   r   r   r   r   r    r!   websets.core.baser"   r  r#   r$   r  r%   r&   getenvis_betar7  r=   rE   rP   rT   r   Category
SearchTyper   r   DeepOutputSchemar*   r  r  r  r?   r8  ra  r1  r>  r?  r   r   r  r  SECTION_TAGr  r  r!  r$  r(  r*  r.  r3  r7  r   r^   r_   ra   r`   rb   r\   rc   rd   re   r]   rZ   r[   EntityrH  r`  rl  rv  r{  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rS   r9   r7   <module>r     s/   " " " " " "      				 				 ! ! ! ! ! !                                     " ( ' ' ' ' '         V V V V V V - - - - - - ' ' ' ' ' '                  # " " " " " - - - - - - E E E E E E E E 9 9 9 9 9 9 9 9 ")I

&
(   F F F F& 68     *
D 
D 
D 
D   $w* w* w* w*v  q 
 l    9E        Ye     -/EEF #cU#C5# # v# # se# # # cU#  !#& '#, -#4 
5#6 dV7#8 4&9#: t;#< =#B UVE# # # L 55vve E%FF"V
Vt  $ NO  F4Ld|,d|t#$U!FV   DkfV	# #    0  P P P P& 9:  \ 3( ( ( ( ()5 ( ( ( (,    %    6
 
 
 
 
Ye 
 
 
 
    	         Ye        IU        iu    >    	        )5     ) ) ) ) ) ) ) )                 " " " " " " " " ! ! ! ! ! ! ! ! O O O O O O O O ) ) ) ) ) ) ) ) 	D 	D 	D 	D 	D 	D 	D 	D " " " " " " " "         ? ? ? ? ? ? ? ? P P P P P P P P ( ( ( ( ( ( ( ( ' ' ' ' ' ' ' ' 
}l*	+ J J J J J J J JZ ; ; ; ; ;W ; ; ;| *1 *1 *1 *1 *1W *1 *1 *1Z *7 *7 *7 *7 *7 *7 *7 *7Z .P .P .P .P .Pw .P .P .Pb %
 %
 %
 %
 %
 %
 %
 %
P        6        47# 7# 7# 7# 7# 7# 7# 7#t:# :# :# :# :# :# :# :#z GCLL         ) ) ) ) )WQZ ) ) )X         '..E&F # 4 4 4 4 4 4 4 4 4 / / / / / / / /=B =B =B =B@   "u2 u2 u2 u2 u2 u2 u2 u2p!C7 C7 C7 C7 C7s C7 C7 C7 C7 C7r9   