
    i's                        d Z ddlmZmZmZmZ ddlmZmZ de	de	fdZ
dedefd	Zdedefd
ZdZddede	dee	ef         dee         def
dZdee	ef         defdZddedee	ef         dee         dedef
dZdedefdZddedee	e	f         fdZdedeee	ef                  fdZdedee	ef         fdZdedee	ef         fdZdee         dee         fdZdee         deee	ef                  fdZdS ) z3
Shared validation functions for Firecrawl v2 API.
    )OptionalDictAnyList   )ScrapeOptionsScrapeFormats
format_strreturnc                 :    dddd}|                     | |           S )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     g/home/agentuser/.hermes/hermes-agent/venv/lib/python3.11/site-packages/firecrawl/v2/utils/validation.py_convert_format_stringr   	   s1     + 5 N
 j*555    schemac                     | rt          | t                    s| S t                      dt          dt          ffd |           S )z
    Normalize a schema for OpenAI compatibility by handling recursive references.
    
    Args:
        schema: Schema to normalize
        
    Returns:
        Normalized schema
    objr   c                   	 t          | t                    s%t          | t                    r
fd| D             S | S t          |           }|v r| S                     |           t          |           	d	v r                    |           	S d	v r	                    d          }i }	                                D ]2\  }}t          |t                    rd|vr 
|          ||<   -|||<   3i }|                                D ]\  }} 
|          ||<   i |d|i}                    |           |S 	                    d          dk    rd	v r	                    d          du r	d= 	                    d          dk    rad		v r]d	v rYt          	d	         t                    r;t          	d         t                    r 	fd
	d	         D             }|r|	d	<   n	d	= n	d	= t          	                                          D ]S\  }}t          |t                    rd|vr 
|          	|<   -t          |t                    r
fd|D             	|<   T                    |           	S )Nc                 &    g | ]} |          S  r   .0itemnormalize_objects     r   
<listcomp>zInormalize_schema_for_openai.<locals>.normalize_object.<locals>.<listcomp>-   s%    ???4((..???r   $ref$defstypeobject
propertiesadditionalPropertiesTrequiredc                 (    g | ]}|d          v |S )r&   r   )r   field
normalizeds     r   r!   zInormalize_schema_for_openai.<locals>.normalize_object.<locals>.<listcomp>X   s5     "E "E "EE"':l+C"C"C #("C"C"Cr   c                 T    g | ]$}t          |t                    r |          n|%S r   )
isinstancedictr   s     r   r!   zInormalize_schema_for_openai.<locals>.normalize_object.<locals>.<listcomp>e   s;    "p"p"pbfZd=S=S#]#3#3D#9#9#9Y]"p"p"pr   )	r-   r.   listidadddiscardpopitemsr   )r   obj_iddefsprocessed_restkeyvaluenormalized_defsresultvalid_requiredr+   r    visiteds            @r   r    z5normalize_schema_for_openai.<locals>.normalize_object*   s(   #t$$ 	#t$$ @????3????JCWJF#YY
 ZOOF###j  >>'**DN(..00 0 0
UeT** 0vU/B/B*:*:5*A*AN3''*/N3'' O"jjll ? ?
U'7'7'>'>$$AAAAFOOF###MNN6""h..J&&NN122d::12NN6""h..*$$J&&:j1488 	+:l3T::	+"E "E "E "EZ
5K "E "E "E! /-;Jz**":..z*z//1122 	q 	qJC%&& q6+>+>"2"25"9"9
3E4(( q"p"p"p"pjo"p"p"p
3r   )r-   r.   setr   )r   r    r=   s    @@r   normalize_schema_for_openair?      sr      FD11 eeG>c >c > > > > > > >@ F###r   c                     | rt          | t                    sdS t                      dt          dt          ffd |            S )z
    Validate schema for OpenAI compatibility.
    
    Args:
        schema: Schema to validate
        
    Returns:
        True if schema is valid, False otherwise
    Tr   r   c                    t          | t                    sdS t          |           }|v rdS                     |           d| v r                    |           dS |                     d          dk    r6d| vr2d| vr.|                     d          du r                    |           dS |                                 D ]}t          |t                    r(d|vr$ |          r                    |            dS ?t          |t                    rB|D ]?}t          |t                    r(d|vr$ |          r                    |             dS @                    |           dS )	NFr"   r$   r%   r&   patternPropertiesr'   T)r-   r.   r0   r1   r2   r   valuesr/   )r   r5   r9   r   has_invalid_structurer=   s       r   rD   z9validate_schema_for_openai.<locals>.has_invalid_structure|   s   #t$$ 	5CW5FS==OOF###5GGFOOx''##s**GG*++t33OOF###4ZZ\\ 
	( 
	(E%&& 	(6+>+>((//  OOF+++44  E4(( (! ( (D!$-- (&2D2D0066 (#OOF333#'444ur   )r-   r.   r>   r   bool)r   rD   r=   s    @@r   validate_schema_for_openairF   m   su      FD11 teeG!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_namer6   r=   c                    | rt          | t          t          f          sdS |t                      }ddl}|                    | dt                    }||v rdS |                    |           	 t          | t                    rd| v rt          | d         t                    r| d                             d          }t          |          dk    ro|d         d	k    rc|d
         dk    rW|d         }||k    r	 |
                    |           dS ||v r-t          ||         |||          |
                    |           S |                                 D ],}t          ||||          r |
                    |           dS -nDt          | t                    r/| D ],}	t          |	|||          r |
                    |           dS -|
                    |           n# |
                    |           w xY wdS )a  
    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/   r>   jsondumpsstrr1   splitlenr2   _contains_recursive_refrC   )
r   rG   r6   r=   rP   obj_keyref_pathdef_namer9   r   s
             r   rU   rU      s>     jtTl33 u%%KKKjjcj::G'uKK!c4   	 }}CK!=!=}v;,,S11x==A%%(1+*<*<!PWAWAW'|H?22# 	       4''6tH~X\^eff 	         *5/4QQ   	        T"" 	     *4$PP   	     	  	        5s%   .BG G ?)G ?.G G G2c                 j    | sdS |                                  D ]\  }}t          |||           r dS dS )z
    Check if $defs contain circular references.
    
    Args:
        defs: Dictionary of definitions to check
        
    Returns:
        True if circular references are found, False otherwise
    FT)r4   rU   )r6   rX   	def_values      r   _check_for_circular_defsr[      sT      u#zz||  )"9h== 	44	 5r   depthc                    | r"t          | t          t          f          rdk    r| S t                      t	          |           }|v r| S                     |           	 t          | t                    rd| v rt          | d         t                    r| d                             d          }t          |          dk    ra|d         dk    rU|d         d	k    rI|d
         }|v r=t          t          |                   dz             
                    |           S | 
                    |           S i }|                                 D ]$\  }}	|d	k    rt          |	dz             ||<   %|
                    |           S t          | t                    r%fd| D             
                    |           S 	 
                    |           n# 
                    |           w xY w| S )aP  
    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
    
   Nr"   rK   rL   r   rM   rN   r#   rO   c           	      :    g | ]}t          |d z             S )rN   )resolve_refs)r   r   r6   r\   r=   s     r   r!   z resolve_refs.<locals>.<listcomp>  s+    QQQTLtWeai@@QQQr   )r-   r.   r/   r>   r0   r1   rR   rS   rT   r`   r2   r4   )
r   r6   r=   r\   r5   rW   rX   resolvedr8   r9   s
    ```      r   r`   r`      s9     jtTl33 urzz
%%WWF
KK c4   	R}}CK!=!=}v;,,S11x==A%%(1+*<*<!PWAWAW'|H4''+Dh,@,@$QVYZQZ[[ 	  	 H!iikk N N
U'>> ,UD'519 M M 		 T"" 	RQQQQQQSQQQ 			R 	Js   %B.G# )G#  <G# $G# #G:c                     | rt          | t                    sdS ddl}|                    |           }d|v pd|v pd|v }t	          |                     d          p|                     d                    }|p|S )	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.   rP   rQ   rE   r   )r   rP   schema_stringhas_refshas_defss        r   detect_recursive_schemari   #  s      FD11 uKKKJJv&&MM! 	*m#	*M) 
 FJJw''D6::m+D+DEEHxr   c                 B    | sdddS t          |           rdddS ddd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)ri   )r   s    r   select_model_for_schemarp   <  sI      C*kBBBv&& N%1LMMM&/BBBr   c                    	 t          | d          r(t          | j                  r|                                 S t          | d          rft          | j                  rRt	          | j        dd          }t          |          r| j                                        S |                                 S t          | d          r(t          | j                  r|                                 S t          | d          rft          | j                  rRt	          | j        dd          }t          |          r| j                                        S |                                 S n# t          $ r Y nw xY wt          | t                    r| ndS )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callablerr   rs   getattr	__class__r   r.   	Exceptionr-   )r   mjsschs      r   _normalize_schemar{   O  s   
6.// 	.HV=U4V4V 	.++---6<(( 	'Xf6G-H-H 	'&*,?FFC}} <'99;;;$$&&&68$$ 	#&-)@)@ 	#==??"66"" 	!x'<'< 	!&*Hd;;C}} 1'..000;;==      --76647s0   7E A!E E 07E (A!E 
E 
E,+E,
format_objc                 ~   t          | t                    st          d          |                     d          dk    rt          d          |                     d          }t          |           }|It	          |          }|7t          |t                    r|                    di           }ddl}|                    |          }|                    d          pd	|v pd
|v }|r_	 t          ||          }|                    |          }	d	|	v pd
|	v }
|
s|}t          |t                    rd|v r|d= nN# t          $ r Y nBw xY w	 t          ||          }t          |t                    rd|v r|d= n# t          $ r Y nw xY wt          |          }t          |          st          t                    ||d<   |S )a  
    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$   rP   z!json format must have type='json'r   Nr#   r   rc   rd   )r-   r.   
ValueErrorr   r{   rP   rQ   r`   rx   r?   rF   OPENAI_SCHEMA_ERROR_MESSAGE)r|   r   r+   normalized_schemar6   rP   rf   has_any_refsresolved_schemaresolved_stringhas_remaining_refsopenai_normalized_schemas               r   _validate_json_formatr   p  s3    j$'' ecddd~~f''<=== ^^H%%Fj!!J-f55(+T22  (,,Wb99 $

+< = =%))'22 0-0-/    *67H$*O*O*.**_*E*E-5-H-iJZiLi*1 ?0?-)*;TBB ?wRcGcGc$5g$>$   
,89JD,Q,Q)%&7>> ;7N_C_C_ 1' :$    (CCT'U'U$-.FGG > !<===#;Jx s%   *AD8 8
EE	,E6 6
FFc                     t          | t                    st          d          t          |                     d          t                    r| d                                         st          d          | S )a   
    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)r-   r.   r   r   rR   strip)r|   s    r   _validate_query_formatr     ss     j$'' [YZZZjnnX..44 NJx<P<V<V<X<X NLMMMr   optionsc                     | dS | j         | j         dk    rt          d          | j        | j        dk     rt          d          | S )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)timeoutr   wait_for)r   s    r   validate_scrape_optionsr     s_     t "w!';';3444 #(81(<(<8999Nr   c                    | dS t          |           }|dS ddddddddd}|                    d          }|                                D ]\  }}||vr|||<   i }ddd	d
dddddddd}|                                D ]!\  }}	||v r|                    |          ||	<   "|                                D 	]\  }
}|	|
dk    r't	          |                                          pd|d<   6|
dk    rg }t          | dd          }t          |t                    r_|j	        r|j	        D ]}t          |t                    rM|dk    rt          d          |dk    rt          d          |                    t          |                     et          |t                    r;|                    d          r"t          |                    d                    nd}|dk    r+t          i |ddi          }|                    |           |dk    r$|                    t!          |                     |dk    ryi |ddi}d|v r|                    d          |d<   |                    d          }t#          |d          r|                    d          |d<   |                    |           d|v r|p|d         |d<   |                    |           t#          |d          r|j        dk    r6|                    t          |                                                     |j        dk    r8|                    t!          |                    d                               J|                    t          |j                             s|                    |           |j        r|                    d           |j        r|                    d            |j        r|                    d!           |j        r|                    d"           |j        r|                    d#           |j        r|                    d           |j        r|                    d$           njt          |t4                    r(|D ]#}t          |t                    rM|dk    rt          d          |dk    rt          d          |                    t          |                     et          |t                    r;|                    d          r"t          |                    d                    nd}|dk    r+t          i |ddi          }|                    |           |dk    r$|                    t!          |                     |dk    ryi |ddi}d|v r|                    d          |d<   |                    d          }t#          |d          r|                    d          |d<   |                    |           d|v r|p|d         |d<   |                    |           t#          |d          rG|j        dk    r6|                    t          |                                                     |j        dk    rddi}t          |dd          
|j        |d<   t          |d%d          
|j        |d%<   t          |dd          }|+t#          |d          r|                    d          n||d<   |                    |           |j        dk    r8|                    t!          |                    d                               |                    t          |j                             |                    |           %n,	 |D ]}|                    |           n# t:          $ r Y nw xY w|r||d<   8|
d&k    rg }|D ]}t          |t                    rCi }|                                D ]\  }}|dk    r||d<   |||<   |                    |           Z|                    d          }i }|                                D ]\  }}|dk    r||d<   |||<   |                    |           ||d&<   |
d'k    rg }|D ]}t          |t                    r|                    |           -t          |t                    rAt          |          }d(|v r|                    d(          |d)<   |                    |           |                    d          }d(|v r|                    d(          |d)<   |                    |           ||d'<   |
d*k    r7t          |t                    r||d*<   |                    d          |d*<   	|
d+k    rxt          |t                    r4|d,         |                    d-|                    d.d                    d/}n(|j        t          |d-t          |d.d                    d/}||d+<   	|||
<   	|S )0z
    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formatsrP   r~   queryr   r$   
screenshot	full_pagefullPageviewportrs   markdownhtmlr   summarylinksr   qualityactionsparsers	max_pagesmaxPageslocationprofilenamesave_changessaveChanges)r   r   )r   rs   r4   r3   rR   r   rv   r-   r	   r   r   appendr   r.   r   r   r   rt   r$   r   r   r   r   r   r   r   r/   r   r   	TypeErrorr   )r   validated_optionsdefault_valuesoptions_datar*   default_valuescrape_datafield_mappings
snake_case
camel_caser8   r9   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?    t 088 t "!% $	 	N %//T/BBL !/ 4 4 6 6 0 0}$$"/LK &%.!6 4( N #1"6"6"8"8 C C
J%%&2&6&6z&B&BK
# #((** {) {)
Um##.1%jj.>.>.@.@.HDM*i/1! $+7It#D#D .>> o'/ %>#3#; $> $>C)#s33 #>#&&==*45  +A  +A  %A#&'>>*45u*v*v$v 1 8 89OPS9T9T U U U U!+C!6!6 >VYV]V]^dVeVe+o+A#''&//+R+R+Rko#+v#5#55JKbcKbSY[aKbKb5c5cN$5$<$<^$L$L$L$L%-%8%8$5$<$<=STW=X=X$Y$Y$Y$Y%-%=%=1NC1N1N1NJ'2j'@'@AKP[A\A\
:(>)3
)C)CB'.r<'@'@ %bAC\`AaAa
:(>$5$<$<Z$H$H$H$H'-}}6>6M#f+F$5$<$<S$A$A$A$A!(f!5!5 >#&8v#5#5$5$<$<=RSVSaSaScSc=d=d$e$e$e$e%(X%8%8$5$<$<=STWTbTbptTbTuTu=v=v$w$w$w$w$5$<$<=STWT\=]=]$^$^$^$^ 1 8 8 = = = = (0 =)00<<<', 9)00888'0 <)00;;;'/ <)00;;;'- :)00999'2 ?)00>>>'7 C)001ABBB   0$77 4/ ,: ,:%c3// +:"f}}&01{&|&| |"g~~&01q&r&r r-445KC5P5PQQQQ'T22 %:RURYRYZ`RaRa'k'=cggfoo'N'N'NgkH'6111FG^#G^vW]G^G^1_1_ 1 8 8 H H H H!)W!4!4 1 8 89OPS9T9T U U U U!)\!9!9-J-JV\-J-J
#.*#<#<=G^^K=X=XJz$:%/^^J%?%?#*2|#<#< !^=?]]X\]=]=]Jz$: 1 8 8 D D D D#)S==2:2Ic&kCK 1 8 8 = = = =$S&11 :"x611 1 8 89Ns~~O_O_9`9` a a a a!$\!9!9.4l-C
#*3T#B#B#N=@]Jz$:#*3	4#@#@#L<?KJy$9%,S*d%C%C#%>ahikmyazaz  >CR]]X\]=]=]=]  ACJz$: 1 8 8 D D D D!$W!4!4 1 8 89OPSP^P^lpP^PqPq9r9r s s s s 1 8 89OPSPX9Y9Y Z Z Z Z-44S9999Y,:^#( : :C-44S9999:$    % ?->K	*	!!$&!# C CF!&$// C+-(8> L L4J)[88?K 0 < <?K 0 < <)001ABBBB '-&7&7T&7&J&J+-(8C8I8I8K8K L L4J)[88?K 0 < <?K 0 < <)001ABBBB):I&&	!!$&!# > >F!&#.. >)008888#FD11 
>&*6ll&+556Aook6R6RK
3)00====&,&7&7T&7&J&J&+556Aook6R6RK
3)00====):I&&
""eT** R.3K
++.3.>.>D.>.Q.QK
++	!!eT** 	 %f',yy=Z^A_A_'`'`$ $LL !&
'.ungeUbdhFiFi'j'j$ $L *6I&& $)C s   :_
_"!_")N)Nr   )__doc__typingr   r   r   r   typesr   r	   rR   r   r?   rE   rF   r   r>   rU   r[   intr`   ri   rp   r{   r   r   r   r   r   r   r   <module>r      s    - , , , , , , , , , , , 0 0 0 0 0 0 0 06s 6s 6 6 6 6$O$ O$ O$ O$ O$ O$d2-s 2-t 2- 2- 2- 2-lm 0 0 0s 0$sCx. 0[cdg[h 0tx 0 0 0 0f4S> d    (0 0c 0c3h 0(3- 0WZ 0cf 0 0 0 0f C  D        2C CC C4S> C C C C&8c 8htCH~&> 8 8 8 8BCc Cd38n C C C CLs tCH~    ,Xm%< -AX    6zH]$; zcSVh@X z z z z z zr   