
    _j                        S r SSKJrJrJrJr  SSKJrJr  S\	S\	4S jr
S\S\4S	 jrS\S\4S
 jrSrS S\S\	S\\	\4   S\\   S\4
S jjrS\\	\4   S\4S jrS!S\S\\	\4   S\\   S\S\4
S jjrS\S\4S jrS S\S\\	\	4   4S jjrS\S\\\	\4      4S jrS\S\\	\4   4S jrS\S\\	\4   4S jrS\S\\	\4   4S jrS\S\\	\4   4S jrS\\   S\\   4S jrS\\   S\\\	\4      4S jrg)"z3
Shared validation functions for Firecrawl v2 API.
    )OptionalDictAnyList   )ScrapeOptionsScrapeFormats
format_strreturnc                 0    SSSS.nUR                  X 5      $ )z
Convert format string from snake_case to camelCase.

Args:
    format_str: Format string in snake_case
    
Returns:
    Format string in camelCase
rawHtmlchangeTrackingzscreenshot@fullPage)raw_htmlchange_trackingscreenshot_full_page)get)r
   format_mappings     R/home/rurouni/.local/lib/python3.13/site-packages/firecrawl/v2/utils/validation.py_convert_format_stringr   	   s'     + 5N
 j55    schemac                    ^^ U (       a  [        U [        5      (       d  U $ [        5       mS[        S[        4UU4S jjmT" U 5      $ )z
Normalize a schema for OpenAI compatibility by handling recursive references.

Args:
    schema: Schema to normalize
    
Returns:
    Normalized schema
objr   c                 *  > [        U [        5      (       d0  [        U [        5      (       a  U  Vs/ s H  nT" U5      PM     sn$ U $ [        U 5      nUT;   a  U $ TR	                  U5        [        U 5      nSU;   a  TR                  U5        U$ SU;   a  UR                  S5      n0 nUR                  5        H0  u  pg[        U[        5      (       a  SU;  a  T" U5      XV'   M,  XuU'   M2     0 nUR                  5        H  u  pgT" U5      X'   M     0 UESU0En	TR                  U5        U	$ UR                  S5      S:X  a  SU;   a  UR                  S5      SL a  US	 UR                  S5      S:X  an  SU;   ah  SU;   ab  [        US   [        5      (       aG  [        US   [        5      (       a/  US    V
s/ s H  n
XS   ;   d  M  U
PM     nn
U(       a  XS'   OUS	 OUS	 [        UR                  5       5       Hu  u  pg[        U[        5      (       a  SU;  a  T" U5      X6'   M,  [        U[        5      (       d  MC  U Vs/ s H"  n[        U[        5      (       a  T" U5      OUPM$     snX6'   Mw     TR                  U5        U$ s  snf s  sn
f s  snf )	N$ref$defstypeobject
propertiesadditionalPropertiesTrequired)	
isinstancedictlistidadddiscardpopitemsr   )r   itemobj_id
normalizeddefsprocessed_restkeyvaluenormalized_defsresultfieldvalid_requirednormalize_objectvisiteds               r   r5   5normalize_schema_for_openai.<locals>.normalize_object*   s   #t$$#t$$;>?34(.3??JCWJF#Y
 ZOOF#j >>'*DN(..0
eT**vU/B*:5*AN'*/3'	 1 !O"jjl
'7'>$ + BAAFOOF#MNN6"h.J&NN12d:12NN6"h.*$J&:j1488:l3T::5?
5K "E5KE"'l+C"C #(5K "E!-;z*":.z*z//12JC%&&6+>"25"9
E4((jo"pjobfZd=S=S#3D#9Y]#]jo"p
	 3 	w @V"E #qs   J6JJ)J)r"   r#   setr   )r   r5   r6   s    @@r   normalize_schema_for_openair9      sF     FD11eG>c >c > >@ F##r   c                    ^^ U (       a  [        U [        5      (       d  g[        5       mS[        S[        4UU4S jjmT" U 5      (       + $ )z
Validate schema for OpenAI compatibility.

Args:
    schema: Schema to validate
    
Returns:
    True if schema is valid, False otherwise
Tr   r   c                   > [        U [        5      (       d  g[        U 5      nUT;   a  gTR                  U5        SU ;   a  TR	                  U5        gU R                  S5      S:X  a2  SU ;  a,  SU ;  a&  U R                  S5      SL a  TR	                  U5        gU R                  5        H  n[        U[        5      (       a(  SU;  a"  T" U5      (       a  TR	                  U5          gM@  [        U[        5      (       d  MW  U HC  n[        U[        5      (       d  M  SU;  d  M"  T" U5      (       d  M1  TR	                  U5            g   M     TR	                  U5        g)	NFr   r   r   r   patternPropertiesr    T)r"   r#   r%   r&   r'   r   valuesr$   )r   r+   r0   r*   has_invalid_structurer6   s       r   r>   9validate_schema_for_openai.<locals>.has_invalid_structure|   s%   #t$$CWFS=OOF#GGFOx'#s*GG*+t3OOF#ZZ\E%&&6+>(//OOF+ 0 E4((!D!$--&2D066#OOF3#'	 " " 	r   )r"   r#   r8   r   bool)r   r>   r6   s    @@r   validate_schema_for_openairA   m   sG     FD11eG!3 !4 ! !F %V,,,r   a  Schema contains invalid structure for OpenAI: object type with no 'properties' defined but 'additionalProperties: true' (schema-less dictionary not supported by OpenAI). Please define specific properties for your object. Note: Recursive schemas using '$ref' are supported.Nr   target_def_namer-   r6   c                 d   U (       a  [        U [        [        45      (       d  gUc
  [        5       nSSKnUR                  U S[        S9nXS;   a  gUR                  U5         [        U [        5      (       a  SU ;   a  [        U S   [        5      (       aw  U S   R                  S5      n[        U5      S:  aT  US   S	:X  aK  US
   S:X  aB  US   nXq:X  a   UR                  U5        gXr;   a   [        X'   XU5      UR                  U5        $ U R                  5        H'  n[        XX#5      (       d  M    UR                  U5        g   OB[        U [        5      (       a-  U  H'  n	[        XX#5      (       d  M    UR                  U5        g   UR                  U5        g! UR                  U5        f = f)aU  
Check if an object contains a recursive reference to a specific definition.

Args:
    obj: Object to check
    target_def_name: Name of the definition to check for recursion
    defs: Dictionary of definitions
    visited: Set of visited object keys to detect cycles
    
Returns:
    True if recursive reference is found, False otherwise
FNr   T)	sort_keysdefaultr   /   #   r   )r"   r#   r$   r8   jsondumpsstrr&   splitlenr'   _contains_recursive_refr=   )
r   rB   r-   r6   rK   obj_keyref_pathdef_namer0   r*   s
             r   rP   rP      s    jtTl33%jjcj:GKK!c4  }CK!=!=v;,,S1x=A%(1+*<!PWAW'|H2# 	   '6t~^ef 	  *54QQ 	  & T""*4$PP 	  
 	  	 s1   "A2F 'F "F 2F ,F 5F F F/c                 l    U (       d  gU R                  5        H  u  p[        X!U 5      (       d  M    g   g)z
Check if $defs contain circular references.

Args:
    defs: Dictionary of definitions to check
    
Returns:
    True if circular references are found, False otherwise
FT)r)   rP   )r-   rS   	def_values      r   _check_for_circular_defsrV      s2     #zz|"9==  , r   depthc           
         U (       a!  [        U [        [        45      (       a  US:  a  U $ Uc
  [        5       n[	        U 5      nXB;   a  U $ UR                  U5         [        U [        5      (       a  SU ;   a  [        U S   [        5      (       a~  U S   R                  S5      n[        U5      S:  aH  US   S:X  a?  US   S:X  a6  US	   nXa;   a,  [        [        X   5      XUS-   5      UR                  U5        $ U UR                  U5        $ 0 nU R                  5        H  u  pUS:X  a  M  [        XX#S-   5      Xx'   M      UUR                  U5        $ [        U [        5      (       a1  U  V
s/ s H  n
[        XX#S-   5      PM     sn
UR                  U5        $  UR                  U5        U $ s  sn
f ! UR                  U5        f = f)
a$  
Resolve $ref references in a JSON schema object.

Args:
    obj: Object to resolve references in
    defs: Dictionary of definitions
    visited: Set to track visited objects and prevent infinite recursion
    depth: Current recursion depth
    
Returns:
    Object with resolved references

   r   rF   rG   r   rH   rI   r   rJ   )r"   r#   r$   r8   r%   r&   rM   rN   rO   resolve_refsr'   r)   )r   r-   r6   rW   r+   rR   rS   resolvedr/   r0   r*   s              r   rZ   rZ      s    jtTl33urz
%WF
KK c4  }CK!=!=v;,,S1x=A%(1+*<!PWAW'|H'+D,@$QVYZQZ[ 	  	 H!iik
'> ,U'19 M *  		 T""MPQSTLWai@SQ 		 # 	J R 	s1   BF3 :F3 5F3 F3 -F.F3 .F3 3Gc                    U (       a  [        U [        5      (       d  gSSKnUR                  U 5      nSU;   =(       d    SU;   =(       d    SU;   n[	        U R                  S5      =(       d    U R                  S5      5      nU=(       d    U$ )	z
Detect if a schema contains recursive references.

Args:
    schema: Schema to analyze
    
Returns:
    True if schema has recursive patterns, False otherwise
Fr   N"$ref"#/$defs/z#/definitions/r   definitions)r"   r#   rK   rL   r@   r   )r   rK   schema_stringhas_refshas_defss        r   detect_recursive_schemarc   #  s|     FD11JJv&MM! 	*m#	*M) 
 FJJw'D6::m+DEHxr   c                 N    U (       d  SSS.$ [        U 5      (       a  SSS.$ SSS.$ )z
Select appropriate model based on schema complexity.

Args:
    schema: Schema to analyze
    
Returns:
    Dict with modelName and reason
zgpt-4o-mini	no_schema)	modelNamereasonzgpt-4orecursive_schema_detectedsimple_schema)rc   )r   s    r   select_model_for_schemarj   <  s4     *kBBv&&%1LMM&/BBr   c                 2    [        U S5      (       a*  [        U R                  5      (       a  U R                  5       $ [        U S5      (       ak  [        U R                  5      (       aQ  [	        U R
                  SS5      n[        U5      (       a  U R
                  R                  5       $ U R                  5       $ [        U S5      (       a*  [        U R                  5      (       a  U R                  5       $ [        U S5      (       ak  [        U R                  5      (       aQ  [	        U R
                  SS5      n[        U5      (       a  U R
                  R                  5       $ U R                  5       $ [        U [        5      (       a  U $ S$ ! [         a     N%f = f)z}
Normalize a schema object which may be a dict, Pydantic BaseModel subclass,
or a Pydantic model instance into a plain dict.
model_json_schema
model_dumpNr   r#   )
hasattrcallablerl   rm   getattr	__class__r   r#   	Exceptionr"   )r   mjsschs      r   _normalize_schemaru   O  s@   
6.//HV=U=U4V4V++--6<((Xf6G6G-H-H&**,?FC}}''99;;$$&&68$$&--)@)@==?"66""x'<'<&**Hd;C}}''..00;;=   --6747  s0   :F	 A+F	 )F	 9:F	 4A+F	  F	 	
FF
format_objc                 X   [        U [        5      (       d  [        S5      eU R                  S5      S:w  a  [        S5      eU R                  S5      n[        U 5      nUGb)  [	        U5      nUGb  [        U[        5      (       a  UR                  S0 5      nSSKnUR                  U5      nUR                  S5      =(       d    S	U;   =(       d    S
U;   nU(       aV   [        X45      nUR                  U5      n	S	U	;   =(       d    S
U	;   n
U
(       d   Un[        U[        5      (       a	  SU;   a  US	 O* [        X45      n[        U[        5      (       a	  SU;   a  US	 [        U5      n[        U5      (       d  [        [        5      eXS'   U$ ! [         a     N<f = f! [         a     NLf = f)z
Validate and prepare json format object.

Args:
    format_obj: Format object that should be json type
    
Returns:
    Validated json format dict
    
Raises:
    ValueError: If json format is missing required fields
Hjson format must be an object with 'type', 'prompt', and 'schema' fieldsr   rK   z!json format must have type='json'r   Nr   r   r]   r^   )r"   r#   
ValueErrorr   ru   rK   rL   rZ   rr   r9   rA   OPENAI_SCHEMA_ERROR_MESSAGE)rv   r   r,   normalized_schemar-   rK   r`   has_any_refsresolved_schemaresolved_stringhas_remaining_refsopenai_normalized_schemas               r   _validate_json_formatr   p  s    j$''cdd~~f'<== ^^H%Fj!J-f5(+T22(,,Wb9 $

+< =%))'2 0-0-/   *67H*O*.**_*E-5-H-iJZiLi*10?-)*;TBBwRcGc$5g$>,89J,Q)%&7>>7N_C_ 1' :
 (CCT'U$-.FGG !<==#;x % %  % s%   AF 3)F 
FF
F)(F)c                 @   [        U [        5      (       d  [        S5      e[        U R                  S5      [        5      (       a  U S   R                  5       (       d  [        S5      eSU ;   a  [        S5      eU R                  S5      nUb  US;  a  [        S5      eU $ )	z
Validate and prepare query format object.

Args:
    format_obj: Format object that should be query type

Returns:
    Validated query format dict

Raises:
    ValueError: If query format is missing required 'prompt' field
>query format must be an object with 'type' and 'prompt' fieldspromptz1query format requires a non-empty 'prompt' stringdirectQuotez1query format uses 'mode' instead of 'directQuote'mode)freeformr   z5query format mode must be 'freeform' or 'directQuote'r"   r#   ry   r   rM   strip)rv   r   s     r   _validate_query_formatr     s     j$''YZZjnnX.44Jx<P<V<V<X<XLMM
"LMM>>&!DD(CCPQQr   c                     [        U [        5      (       d  [        S5      e[        U R                  S5      [        5      (       a  U S   R                  5       (       d  [        S5      eU $ )z,Validate and prepare question format object.Cquestion format must be an object with 'type' and 'question' fieldsquestionz6question format requires a non-empty 'question' stringr   rv   s    r   _validate_question_formatr     sV    j$''^__jnnZ0#66j>T>Z>Z>\>\QRRr   c                     [        U [        5      (       d  [        S5      e[        U R                  S5      [        5      (       a  U S   R                  5       (       d  [        S5      eU $ )z.Validate and prepare highlights format object.Bhighlights format must be an object with 'type' and 'query' fieldsqueryz5highlights format requires a non-empty 'query' stringr   r   s    r   _validate_highlights_formatr     sV    j$'']^^jnnW-s33:g;N;T;T;V;VPQQr   optionsc                     U c  gU R                   b  U R                   S::  a  [        S5      eU R                  b  U R                  S:  a  [        S5      eU $ )z
Validate and normalize scrape options.

Args:
    options: Scraping options to validate
    
Returns:
    Validated options or None
    
Raises:
    ValueError: If options are invalid
Nr   zTimeout must be positivezwait_for must be non-negative)timeoutry   wait_for)r   s    r   validate_scrape_optionsr     s[      "w!';344 #(8(81(<899Nr   c                    U c  g[        U 5      nUc  gSSSSSSSSS.nUR                  SS9nUR                  5        H  u  pEXC;  d  M  XSU'   M     0 nSSS	S
SSSSSSSS.nUR                  5        H  u  pX;   d  M  UR                  U5      Xi'   M!     UR                  5        G
H  u  pUc  M  U
S:X  a'  [	        U5      R                  5       =(       d    SUS'   M8  U
S:X  Ga]  / n[        U SS5      n[        U[        5      (       Ga5  UR                  (       Ga3  UR                   GH"  n[        U[        5      (       a`  US:X  a  [        S5      eUS:X  a  [        S5      eUS:X  a  [        S5      eUS:X  a  [        S5      eUR                  [        U5      5        My  [        U[        5      (       Ga`  UR                  S5      (       a  [        UR                  S5      5      OSnUS:X  a$  [        0 UESS0E5      nUR                  U5        M  US:X  a  UR                  [!        U5      5        GM  US:X  a  UR                  [#        U5      5        GM1  US:X  a  UR                  [%        U5      5        GMT  US:X  aj  0 UESS0EnSU;   a  UR                  S5      US '   UR                  S!5      n['        US"5      (       a  UR                  SS9US!'   UR                  U5        GM  SU;   a  U=(       d    US   US'   UR                  U5        GM  ['        US5      (       Ga  UR(                  S:X  a+  UR                  [        UR                  5       5      5        GM<  UR(                  S:X  a*  UR                  [!        UR                  SS95      5        GMv  UR(                  S:X  a*  UR                  [#        UR                  SS95      5        GM  UR(                  S:X  a*  UR                  [%        UR                  SS95      5        GM  UR                  [        UR(                  5      5        GM  UR                  U5        GM%     UR*                  (       a  UR                  S#5        UR,                  (       a  UR                  S$5        UR.                  (       a  UR                  S%5        UR0                  (       a  UR                  S&5        UR2                  (       a  UR                  S'5        UR4                  (       a  UR                  S5        UR6                  (       a  UR                  S(5        GO[        U[8        5      (       Ga  U GH  n[        U[        5      (       a`  US:X  a  [        S5      eUS:X  a  [        S5      eUS:X  a  [        S5      eUS:X  a  [        S5      eUR                  [        U5      5        My  [        U[        5      (       Ga`  UR                  S5      (       a  [        UR                  S5      5      OSnUS:X  a$  [        0 UESS0E5      nUR                  U5        M  US:X  a  UR                  [!        U5      5        GM  US:X  a  UR                  [#        U5      5        GM1  US:X  a  UR                  [%        U5      5        GMT  US:X  aj  0 UESS0EnSU;   a  UR                  S5      US '   UR                  S!5      n['        US"5      (       a  UR                  SS9US!'   UR                  U5        GM  SU;   a  U=(       d    US   US'   UR                  U5        GM  ['        US5      (       Ga  UR(                  S:X  a+  UR                  [        UR                  5       5      5        GM<  UR(                  S:X  a*  UR                  [!        UR                  SS95      5        GMv  UR(                  S:X  a*  UR                  [#        UR                  SS95      5        GM  UR(                  S:X  a  SS0n[        USS5      b  UR:                  US '   [        US)S5      b  UR<                  US)'   [        US!S5      nUb%  ['        US"5      (       a  UR                  SS9OUUS!'   UR                  U5        GMG  UR(                  S:X  a*  UR                  [%        UR                  SS95      5        GM  UR                  [        UR(                  5      5        GM  UR                  U5        GM     O U H  nUR                  U5        M     U(       a  XS'   GM  GM  U
S*:X  a  / nU H  n[        U[        5      (       aA  0 nUR                  5        H  u  nnUS:X  a  UUS '   M  UUU'   M     UR                  U5        MY  UR                  SS9n0 nUR                  5        H  u  nnUS:X  a  UUS '   M  UUU'   M     UR                  U5        M     UUS*'   G	MY  U
S+:X  a  / nU H  n[        U[        5      (       a  UR                  U5        M+  [        U[        5      (       a8  [        U5      nS,U;   a  UR                  S,5      US-'   UR                  U5        Mx  UR                  SS9nS,U;   a  UR                  S,5      US-'   UR                  U5        M     UUS+'   G
M!  U
S.:X  a1  [        U[        5      (       a  XS.'   G
MC  UR                  SS9US.'   G
MX  U
S/:X  ak  [        U[        5      (       a)  US0   UR                  S1UR                  S2S5      5      S3.nO%UR@                  [        US1[        US2S5      5      S3.nUUS/'   G
M  XU
'   G
M     U$ ! [>         a     GNVf = f)4z
Prepare ScrapeOptions for API submission with manual snake_case to camelCase conversion.

Args:
    options: ScrapeOptions to prepare
    
Returns:
    Dictionary ready for API submission or None if options is None
NTFi  )only_main_contentmobileskip_tls_verificationremove_base64_images	fast_mode	block_adsmax_agestore_in_cache)exclude_noneincludeTagsexcludeTagsonlyMainContentwaitForskipTlsVerificationremoveBase64ImagesfastModeuseMockblockAdsstoreInCachemaxAge)include_tagsexclude_tagsr   r   r   r   r   use_mockr   r   r   integrationformatsrK   rx   r   r   r   r   
highlightsr   r   
screenshot	full_pagefullPageviewportrm   markdownhtmlr   summarylinksr   qualityactionsparsers	max_pagesmaxPageslocationprofilenamesave_changessaveChanges)r   r   )!r   rm   r)   r(   rM   r   rp   r"   r	   r   ry   appendr   r#   r   r   r   r   r   rn   r   r   r   r   r   r   r   r   r$   r   r   	TypeErrorr   )r   validated_optionsdefault_valuesoptions_datar3   default_valuescrape_datafield_mappings
snake_case
camel_caser/   r0   converted_formatsoriginal_formatsfmtfmt_typevalidated_jsonr,   vpconverted_actionsactionconverted_action
action_keyaction_valueaction_dataconverted_parsersparserparser_dataprofile_datas                                r   prepare_scrape_optionsr     s
     08  "!% $	N %//T/BL !/ 4 4 6$"/ !7 K &%.!6 4(N #1"6"6"8
%&2&6&6z&BK# #9
 #((*
m#.1%j.>.>.@.HDM*i/1! $+7It#D .>>'///#3#;#;C)#s33#&&=*45  +A  %A#&'>*45u*v$v#&*#4*45z*{${#&,#6*45y*z$z 1 8 89OPS9T U!+C!6!6VYV]V]^dVeVe+A#''&/+Rko#+v#55JKbcKbSY[aKb5cN$5$<$<^$L%-%;$5$<$<=VWZ=[$\%-%=$5$<$<=XY\=]$^%-%8$5$<$<=STW=X$Y%-%=1NC1N1NJ'2j'@AKP[A\
:(>)3
)CB'.r<'@'@AC\`Aa
:(>$5$<$<Z$H'-}6>6M#f+F$5$<$<S$A!(f!5!5#&88v#5$5$<$<=RSVSaSaSc=d$e%(XX%;$5$<$<=VWZWeWeswWeWx=y$z%(XX%=$5$<$<=XY\YgYguyYgYz={$|%(XX%8$5$<$<=STWTbTbptTbTu=v$w$5$<$<=STWT\T\=]$^ 1 8 8 =a $<f (00)00<',,)008'00)00;'//)00;'--)009'22)00>'77)001AB   0$77/%c3//"f}&01{&| |"g~&01q&r r"j0&01v&w w"l2&01u&v v-445KC5PQ'T22RURYRYZ`RaRa'=cggfo'NgkH'611FG^#G^vW]G^1_ 1 8 8 H!)Z!7 1 8 89RSV9W X!)\!9 1 8 89TUX9Y Z!)W!4 1 8 89OPS9T U!)\!9-J-JV\-J
#.*#<=G^^K=XJz$:%/^^J%?#*2|#<#<=?]]X\]=]Jz$: 1 8 8 D#)S=2:2Ic&kCK 1 8 8 =$S&11"xx61 1 8 89Ns~~O_9` a!$Z!7 1 8 89RSVSaSaosSaSt9u v!$\!9 1 8 89TUXUcUcquUcUv9w x!$\!9.4l-C
#*3T#B#N=@]]Jz$:#*3	4#@#L<?KKJy$9%,S*d%C#%>ahikmyazazR]]X\]=]  ACJz$: 1 8 8 D!$W!4 1 8 89OPSP^P^lpP^Pq9r s 1 8 89OPSPXPX9Y Z-44S9q  0v#(C-44S9 $)
 %->	* %	!$&!#F!&$//+-(8>4J)[8?K 0 <?K 0 <	 9G
 *001AB '-&7&7T&7&J+-(8C8I8I8K4J)[8?K 0 <?K 0 <	 9L
 *001AB' $( *;I&	!$&!#F!&#..)008#FD11&*6l&+56Aook6RK
3)00=&,&7&7T&7&J&+56Aook6RK
3)00= $ *;I&
"eT**.3
+.3.>.>D.>.QK
+	!eT** %f',yy=Z^A_'`$L !&

'.ungeUbdhFi'j$L *6I& $)C g +j G % s   m99
nn)N)Nr   )__doc__typingr   r   r   r   typesr   r	   rM   r   r9   r@   rA   rz   r8   rP   rV   intrZ   rc   rj   ru   r   r   r   r   r   r    r   r   <module>r      s   - , 06s 6s 6$O$ O$ O$d2-s 2-t 2-lm 0 0s 0$sCx. 0[cdg[h 0tx 0f4S> d (0c 0c3h 0(3- 0WZ 0cf 0f C  D  2CC C4S> C&8c 8htCH~&> 8BCc Cd38n CLs tCH~ :# $sCx. C DcN Xm%< -AX 6RH]$; RcSVh@X Rr   