
    Sjj                        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e   dee   fdZdee   deee	ef      fdZy)z3
Shared validation functions for Firecrawl v2 API.
    )OptionalDictAnyList   )ScrapeOptionsScrapeFormats
format_strreturnc                 2    dddd}|j                  | |       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     P/root/.hermes/venv/lib/python3.12/site-packages/firecrawl/v2/utils/validation.py_convert_format_stringr   	   s)     + 5N
 j*55    schemac                 x    | 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| D cg c]
  } |       c}S | S t        |       }|v r| S j	                  |       t        |       }d|v rj                  |       |S d|v r|j                  d      }i }|j                         D ]*  \  }}t        |t              rd|vr |      ||<   &|||<   , i }|j                         D ]  \  }} |      ||<    i |d|i}	j                  |       |	S |j                  d      dk(  rd|v r|j                  d      du r|d= |j                  d      dk(  rVd|v rRd|v rNt        |d   t              r8t        |d   t              r%|d   D 
cg c]  }
|
|d   v r|
 }}
|r||d<   n|d= n|d= t        |j                               D ]a  \  }}t        |t              rd|vr |      ||<   &t        |t              s7|D cg c]  }t        |t              r |      n| c}||<   c j                  |       |S c c}w c c}
w c c}w )	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   z5normalize_schema_for_openai.<locals>.normalize_object*   s   #t$#t$;>?4(.??JCWJF#Y
 ZOOF#j >>'*DN(..0 0
UeT*vU/B*:5*AN3'*/N3'	0 !O"jjl ?
U'7'>$? BAAFOOF#MNN6"h.J&NN12d:12NN6"h.*$J&:j148:l3T:5?
5K "EE"':l+C"C #( "E "E!-;Jz*":.z*z//12 	qJC%&6+>"25"9
3E4(jo"pbfZd=S#3D#9Y]#]"p
3		q 	w @V"E #qs   H:	H?>!I)r"   r#   setr   )r   r5   r6   s    @@r   normalize_schema_for_openair8      s>     FD1eG>c >c >@ F##r   c                 x    | rt        | t              sy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                 X   t        | t              syt        |       }|v ryj                  |       d| v rj	                  |       y| j                  d      dk(  r-d| vr)d| vr%| j                  d      du rj	                  |       y| j                         D ]|  }t        |t              r d|vr |      s j	                  |        yt        |t              sD|D ]4  }t        |t              sd|vs |      s"j	                  |         y ~ j	                  |       y)	NFr   r   r   r   patternPropertiesr    T)r"   r#   r%   r&   r'   r   valuesr$   )r   r+   r0   r*   has_invalid_structurer6   s       r   r=   z9validate_schema_for_openai.<locals>.has_invalid_structure|   s   #t$CWFS=OOF#GGFOx'#s*GG*+t3OOF#ZZ\ 
	(E%&6+>(/OOF+E4(! (D!$-&2D06#OOF3#'	(
	( 	r   )r"   r#   r7   r   bool)r   r=   r6   s    @@r   validate_schema_for_openair?   m   s?     FD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                    | rt        | t        t        f      sy|
t               }ddl}|j                  | dt              }||v ry|j                  |       	 t        | t              rd| v rt        | d   t              ru| d   j                  d      }t        |      dk\  rS|d   d	k(  rK|d
   dk(  rC|d   }||k(  r	 |j                  |       y||v r"t        ||   |||      |j                  |       S | j                         D ]#  }t        ||||      s |j                  |       y n8t        | t              r(| D ]#  }	t        |	|||      s |j                  |       y |j                  |       y# |j                  |       w xY w)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$   r7   jsondumpsstrr&   splitlenr'   _contains_recursive_refr<   )
r   r@   r-   r6   rI   obj_keyref_pathdef_namer0   r*   s
             r   rN   rN      s    jtTl3%jjcj:G'KK!c4 }CK!=v;,,S1x=A%(1+*<!PWAW'|H?2# 	   4'6tH~X\^ef 	    *5/4Q 	   T"  *4$P 	  
 	  	 s1   A#E6 E6 5!E6 E6 *%E6 E6 #E6 6F	c                 X    | sy| j                         D ]  \  }}t        |||       s y y)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)   rN   )r-   rQ   	def_values      r   _check_for_circular_defsrT      s8     #zz| )"9h= r   depthc           
      P   | rt        | t        t        f      r|dkD  r| S |
t               }t	        |       }||v r| S |j                  |       	 t        | t              rd| v rt        | d   t              r|| d   j                  d      }t        |      dk\  rG|d   dk(  r?|d   dk(  r7|d	   }||v r.t        t        ||         |||dz         |j                  |       S | |j                  |       S i }| j                         D ]  \  }}	|dk(  rt        |	|||dz         ||<   ! ||j                  |       S t        | t              r0| D 
cg c]  }
t        |
|||dz          c}
|j                  |       S 	 |j                  |       | S c c}
w # |j                  |       w xY w)
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
    
   r   rD   rE   r   rF   rG   r   rH   )r"   r#   r$   r7   r%   r&   rK   rL   rM   resolve_refsr'   r)   )r   r-   r6   rU   r+   rP   rQ   resolvedr/   r0   r*   s              r   rX   rX      s    jtTl3urz
%WF
KK c4 }CK!=v;,,S1x=A%(1+*<!PWAW'|H4'+Dh,@$QVYZQZ[ 	  	 H!iik N
U'> ,UD'519 MN  		 T"MPQTLtWeai@Q 		 # 	J R 	s1   A>F F 25F 9F F%F F F%c                     | rt        | t              syddl}|j                  |       }d|v xs
 d|v xs d|v }t	        | j                  d      xs | j                  d            }|xs |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#   rI   rJ   r>   r   )r   rI   schema_stringhas_refshas_defss        r   detect_recursive_schemara   #  sy     FD1JJv&MM! 	*m#	*M) 
 FJJw'D6::m+DEHxr   c                 :    | 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)ra   )r   s    r   select_model_for_schemarh   <  s1     *kBBv&%1LMM&/BBr   c                    	 t        | d      r%t        | j                        r| j                         S t        | d      rat        | j                        rLt	        | j
                  dd      }t        |      r| j
                  j                         S | j                         S t        | d      r%t        | j                        r| j                         S t        | d      rat        | j                        rLt	        | j
                  dd      }t        |      r| j
                  j                         S | j                         S t        | t              r| S dS # t        $ r Y w xY w)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callablerj   rk   getattr	__class__r   r#   	Exceptionr"   )r   mjsschs      r   _normalize_schemars   O  s!   
6./HV=U=U4V++--6<(Xf6G6G-H&**,?FC}''99;;$$&&68$&--)@==?"66"x'<&**Hd;C}''..00;;=   -6747  s0   0E AE E  0E AE .E 	EE
format_objc                    t        | t              st        d      | j                  d      dk7  rt        d      | j                  d      }t        |       }|t	        |      }|t        |t              r|j                  di       }ddl}|j                  |      }|j                  d      xs
 d	|v xs d
|v }|rD	 t        ||      }|j                  |      }	d	|	v xs d
|	v }
|
s|}t        |t              rd|v r|d= n$	 t        ||      }t        |t              rd|v r|d= t        |      }t        |      st        t              ||d<   |S # t        $ r Y 7w xY w# t        $ r Y Fw xY w)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   rI   z!json format must have type='json'r   Nr   r   r[   r\   )r"   r#   
ValueErrorr   rs   rI   rJ   rX   rp   r8   r?   OPENAI_SCHEMA_ERROR_MESSAGE)rt   r   r,   normalized_schemar-   rI   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(,,Wb9 $

+< =%))'2 0-0-/   *67H$*O*.**_*E-5-H-iJZiLi*10?-)*;TBwRcGc$5g$>,89JD,Q)%&7>7N_C_ 1' :
 (CCT'U$-.FG !<==#;Jx % %  % s%   =AE #E 	EE	E+*E+optionsc                     | y| 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)timeoutrw   wait_for)r   s    r   validate_scrape_optionsr     s[      "w!';344 #(8(81(<899Nr   c                 t   | yt        |       }|yddddddddd}|j                  d      }|j                         D ]  \  }}||vs|||<    i }ddd	d
dddddddd}|j                         D ]  \  }}	||v s|j                  |      ||	<     |j                         D ]  \  }
}|
|
dk(  r!t	        |      j                         xs d|d<   0|
dk(  r0g }t        | dd      }t        |t              r|j                  r|j                  D ]  }t        |t              r+|dk(  rt        d      |j                  t        |             ?t        |t              r|j                  d      rt        |j                  d            nd}|dk(  r#t        i |ddi      }|j                  |       |dk(  rei |ddi}d|v r|j                  d      |d<   |j                  d      }t!        |d      r|j                  d      |d<   |j                  |       d|v r|xs |d   |d<   |j                  |       1t!        |d      r_|j"                  dk(  r*|j                  t        |j                                      v|j                  t        |j"                               |j                  |        |j$                  r|j                  d       |j&                  r|j                  d       |j(                  r|j                  d       |j*                  r|j                  d        |j,                  r|j                  d!       |j.                  r|j                  d       |j0                  r|j                  d"       nnt        |t2              rC|D ]<  }t        |t              r+|dk(  rt        d      |j                  t        |             ?t        |t              r|j                  d      rt        |j                  d            nd}|dk(  r#t        i |ddi      }|j                  |       |dk(  rei |ddi}d|v r|j                  d      |d<   |j                  d      }t!        |d      r|j                  d      |d<   |j                  |       d|v r|xs |d   |d<   |j                  |       1t!        |d      r|j"                  dk(  r*|j                  t        |j                                      v|j"                  dk(  rddi}t        |dd      |j4                  |d<   t        |d#d      |j6                  |d#<   t        |dd      }|#t!        |d      r|j                  d      n||d<   |j                  |       |j                  t        |j"                               ,|j                  |       ? n	 |D ]  }|j                  |        	 |s_||d<   f|
d$k(  rg }|D ]  }t        |t              r<i }|j                         D ]  \  }}|dk(  r||d<   |||<    |j                  |       O|j                  d      }i }|j                         D ]  \  }}|dk(  r||d<   |||<    |j                  |        ||d$<   |
d%k(  rg }|D ]  }t        |t              r|j                  |       %t        |t              r5t        |      }d&|v r|j                  d&      |d'<   |j                  |       j|j                  d      }d&|v r|j                  d&      |d'<   |j                  |        ||d%<   |
d(k(  r.t        |t              r||d(<   |j                  d      |d(<   |||
<    |S # t8        $ r Y w xY w))z
    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formatsrI   rv   r   
screenshot	full_pagefullPageviewportrk   markdownhtmlr   summarylinksr   qualityactionsparsers	max_pagesmaxPageslocation)r   rk   r)   r(   rK   striprn   r"   r	   r   rw   appendr   r#   r   r   rl   r   r   r   r   r   r   r   r   r$   r   r   	TypeError)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_datas                               r   prepare_scrape_optionsr     s)     08  "!% $	N %//T/BL !/ 4 4 6 0}$"/L0 K &%.!6 4(N #1"6"6"8 C
J%&2&6&6z&BK
#C
 #((* d)
Um#.1%j.>.>.@.HDM*i/1! $+7It#D .>'//#3#;#; >C)#s3#&&=*45  +A  %A 1 8 89OPS9T U!+C!6VYV]V]^dVe+A#''&/+Rko#+v#55JKbcKbSY[aKb5cN$5$<$<^$L%-%=1NC1N1NJ'2j'@AKP[A\
:(>)3
)CB'.r<'@AC\`Aa
:(>$5$<$<Z$H'-}6>6M#f+F$5$<$<S$A!(f!5#&88v#5$5$<$<=RSVSaSaSc=d$e$5$<$<=STWT\T\=]$^ 1 8 8 ==>B (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/ &:%c3/"f}&01{&| |-445KC5PQ'T2RURYRYZ`Ra'=cggfo'NgkH'611FG^#G^vW]G^1_ 1 8 8 H!)\!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"xx61 1 8 89Ns~~O_9` a!$\!9.4l-C
#*3T#B#N=@]]Jz$:#*3	4#@#L<?KKJy$9%,S*d%C#%>ahikmyazR]]X\]=]  ACJz$: 1 8 8 D 1 8 89OPSPXPX9Y Z-44S9M&:R#( :C-44S9:
 %->K	*	!$&!# CF!&$/+-(8> L4J)[8?K 0 <?K 0 <	L
 *001AB '-&7&7T&7&J+-(8C8I8I8K L4J)[8?K 0 <?K 0 <	L
 *001AB'C( *;I&	!$&!# >F!&#.)008#FD1&*6l&+56Aook6RK
3)00=&,&7&7T&7&J&+56Aook6RK
3)00=> *;I&
"eT*.3K
+.3.>.>D.>.QK
+ $)C Id)L q % s   $^**	^76^7)N)Nr   )__doc__typingr   r   r   r   typesr   r	   rK   r   r8   r>   r?   rx   r7   rN   rT   intrX   ra   rh   rs   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Xm%< -AX 6cH]$; ccSVh@X cr   