
    iW                        d Z ddlZddl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ZddlmZ ddlmZ ddlmZ ddlmZmZ  ej*                  e      Z	 ddlZd	Z	 ddlZd	Z	 ddlm Z! d	Z"	 ddl#m$Z$ d	Z%	 ddl&m'Z' d	Z(	 ddl)m)Z) d	Z*de+de+fdZ, G d de-      Z.de+de+dz  dede/e0e+f   fdZ1de+dede
fdZ2	 	 	 	 	 d"dededz  dedz  dedz  de3e+   dz  de4e+e+e4e+e+f   z  f   dz  de4e+e
f   fdZ5d e4e+e
f   de+fd!Z6y# e$ r d
ZY w xY w# e$ r d
ZY w xY w# e$ r d
Z"Y w xY w# e$ r d
Z%Y w xY w# e$ r d
Z(Y w xY w# e$ r d
Z*Y w xY w)#zNamespace initialization for code-use mode.

This module creates a namespace with all browser tools available as functions,
similar to a Jupyter notebook environment.
    N)Path)Any)BrowserSession)
FileSystem)BaseChatModel)CodeAgentToolsToolsTF)BeautifulSoup)	PdfReader)tabulatejs_codereturnc                     t        j                  dd| t         j                        } t        j                  dd| t         j                        } | S )z
	Remove JavaScript comments before CDP evaluation.
	CDP's Runtime.evaluate doesn't handle comments in all contexts.

	Args:
		js_code: JavaScript code potentially containing comments

	Returns:
		JavaScript code with comments stripped
	z	/\*.*?\*/ )flagsz	^\s*//.*$)resubDOTALL	MULTILINE)r   s    h/mnt/e/genesis-system/.venvs/browser-army/lib/python3.12/site-packages/browser_use/code_use/namespace.py_strip_js_commentsr   E   s;     66,G299= 66,G2<<@    c                       e Zd ZdZy)EvaluateErrorzLSpecial exception raised by evaluate() to stop Python execution immediately.N)__name__
__module____qualname____doc__ r   r   r   r   Z   s    Sr   r   taskoutputllmc                 0  K   ddl m} d|  d|r|dd nd d}	 |j                   ||	      g       d{   }|j                  }d
}d}|j	                  d      }	|	D ]  }
|
j                         j                         j                  d      r$|
j	                  dd      d   j                         }T|
j                         j                         j                  d      s|
j	                  dd      d   j                         j                         }d|v rd}d|v sd} |s|}|dk(  }t        j                  d|        t        j                  d|        ||fS 7 (# t        $ r)}t        j                  d|        dd| fcY d}~S d}~ww xY ww)a  
	Validate if task is truly complete by asking LLM without system prompt or history.

	Args:
		task: The original task description
		output: The output from the done() call
		llm: The LLM to use for validation

	Returns:
		Tuple of (is_complete, reasoning)
	r   )UserMessagezsYou are a task completion validator. Analyze if the agent has truly completed the user's task.

**Original Task:**
z

**Agent's Output:**
Ni z(No output provided)a:  

**Your Task:**
Determine if the agent has successfully completed the user's task. Consider:
1. Has the agent delivered what the user requested?
2. If data extraction was requested, is there actual data?
3. If the task is impossible (e.g., localhost website, login required but no credentials), is it truly impossible?
4. Could the agent continue and make meaningful progress?

**Response Format:**
Reasoning: [Your analysis of whether the task is complete]
Verdict: [YES or NO]

YES = Task is complete OR truly impossible to complete
NO = Agent should continue working)contentr   NO
z
reasoning::   zverdict:YESzTask validation: zValidation reasoning: z$Failed to validate task completion: TzValidation failed: )browser_use.llm.messagesr$   ainvoke
completionsplitstriplower
startswithupperloggerinfodebug	Exceptionwarning)r    r!   r"   r$   validation_promptresponseresponse_text	reasoningverdictlineslineverdict_textis_completees                 r   validate_task_completionrB   `   s      2    6 7 8#&,#);;4E FGHH(%%- )' 

d
#% d
jjl%%l3

3"1%++-I

''
3::c1%a(..0668LW		W 
95 +++!'+,,,'	{34	i	9 I< 	 )..7s;<	$QC(	(()sR   FE! EB(E!  <E! A E! FE! !	F*FF	FFFcodebrowser_sessionc                 "  K   t        |       } |j                          d{   }	 |j                  j                  j                  j                  | ddd|j                         d{   }|j                  d      r|d   }|j                  dd      }g }d|v r?|d   }d	|v r|j                  |d	          n!d
|v r|j                  t        |d
                d| }|r|ddj                  |       z  }t        |      |j                  di       }	|	j                  d
      }
|
d
|	v rdS dS t        |
t        t        f      r|
S |
S 7 *7 # t        $ r  t        $ r*}t        dt!        |      j"                   d|       |d}~ww xY ww)a  
	Execute JavaScript code in the browser and return the result.

	Args:
		code: JavaScript code to execute (must be wrapped in IIFE)

	Returns:
		The result of the JavaScript execution

	Raises:
		EvaluateError: If JavaScript execution fails. This stops Python execution immediately.

	Example:
		result = await evaluate('''
		(function(){
			return Array.from(document.querySelectorAll('.product')).map(p => ({
				name: p.querySelector('.name').textContent,
				price: p.querySelector('.price').textContent
			}))
		})()
		''')
	NT)
expressionreturnByValueawaitPromise)params
session_idexceptionDetailstextzUnknown error	exceptiondescriptionvaluezJavaScript execution error: z

Details: z | result	undefinedzFailed to execute JavaScript: : )r   get_or_create_cdp_session
cdp_clientsendRuntimeevaluaterJ   getappendstrjoinr   
isinstancedictlistr6   typer   )rC   rD   cdp_sessionrP   rM   
error_texterror_detailsexc_obj	error_msgresult_datarO   rA   s               r   rW   rW      s    0 	4 $>>@@2W'',,44==d
K$$ >  & ZZ"#()9fo6: =Y$G'-01	G	#gg./0 .j\:9;uzz-89::I 
y	!! 

8R(+ //'
"% ][($9k9%$&
< <[ AV 	  W6tAw7G7G6H1#NOUVVWsj   FEFAE )E*CE .F/E 0F1E F	E 
FE F"%FFFtoolspage_extraction_llmfile_systemavailable_file_pathssensitive_datac                 2    |
t               }g  t        t        t        t        t
        t        t        d	t        rt        d<   t        d<   t        rt        d<   t        d<   t        rt        d<   t        d<   t        rt        d	<   t        d
<   t         rt"        d<   t"        d<   t$        r	t&        d<   dvrg d<   	 ddt(        dz  dt*        t(        t,        f   dz  dt,        dt,        dt,        f
 fd}|d<   dt.        dt(        f fd}|d<   |j0                  j0                  j2                  j5                         D ]B  \  }}	|dk(  r|	j6                  }
|	j8                  } fd}|dk(  rdn|} |||
|      |<   D S )a%  
	Create a namespace with all browser tools available as functions.

	This function creates a dictionary of functions that can be used to interact
	with the browser, similar to a Jupyter notebook environment.

	Args:
		browser_session: The browser session to use
		tools: Optional Tools instance (will create default if not provided)
		page_extraction_llm: Optional LLM for page extraction
		file_system: Optional file system for file operations
		available_file_paths: Optional list of available file paths
		sensitive_data: Optional sensitive data dictionary

	Returns:
		Dictionary containing all available functions and objects

	Example:
		namespace = create_namespace(browser_session)
		await namespace['navigate'](url='https://google.com')
		result = await namespace['evaluate']('document.title')
	N)	browserrh   jsonasyncior   csvr   datetimerequestsnpnumpypdpandasplt
matplotlibr
   bs4r   pypdfr   _evaluate_failuresrC   	variables_argskwargsr   c           
      ^	  K   | 2|j                  d|j                  d|j                  dd                  } ||j                  d      }| st        d      |rat        j                  |      }| j	                         }t        j                  d|      rd| d	| d
} n|j                  d      xr d|dd  v xsR |j                  d      xr d|dd  v xs6 |j                  d      xr d|dd  v xs |j                  d      xr d|dd  v }|rt        j                  d|      }|r*|j                  d      }|t        |      d  }	| d| d|	 } nit        j                  d|      }
|
r*|
j                  d      }|t        |      d  }	| d| d|	 } n'd| d	| d} nd| d|  d} t        |        d {   S |s| j	                         }|j                  d      xr d|dd  v xsR |j                  d      xr d|dd  v xs6 |j                  d      xr d|dd  v xs |j                  d      xr d|dd  v }|sd|  d} 	 t        |        d {   }t        |t              r|rt        |d   t              rdt        |       d}|d   }t        |j                               d d D ]O  \  }}t        |t        t         t"        t%        d       f      st'        |      d d n
t'        |      }|d| d| d z  }Q t        |      dkD  r|d!t        |      dz
   d"z  }t)        |       |S t        |t              rFt        |      dk(  rt)        d#       |S t'        |      d d$ }t)        d%t        |       d&| d'       |S t        |t              rd(t        |       d)}t        |j                               d d D ]O  \  }}t        |t        t         t"        t%        d       f      st'        |      d d n
t'        |      }|d| d| d z  }Q t        |      dkD  r|d!t        |      dz
   d"z  }t)        |       |S t)        d*t%        |      j*                   d+t-        |      d d,         |S 7 7 $# t.        $ r&}d-   j1                  t'        |      d.d/        d }~ww xY ww)0NrC   r   rF   r   r{   z)No JavaScript code provided to evaluate()z'\((?:async\s+)?function\s*\(\s*\w+\s*\)z(function(){ const params = z	; return z(params); })()z(function()z})()iz(async function()z(() =>z)()z(async () =>z((\((?:async\s+)?function\s*\(\s*\)\s*\{)r)   z const params = z; z"(\((?:async\s+)?\(\s*\)\s*=>\s*\{)z; })()z })()z(function(){r   zlist of dicts - len=z, example 1:

   z  rR   z...
z  ... z
 more keysztype=list, len=0d   ztype=list, len=z
, preview=z...ztype=dict, len=z, sample keys:
ztype=z, value=2   rz   rM   )errorr_   )rX   
ValueErrorrm   dumpsr/   r   matchr1   grouplenrW   r\   r^   r]   itemsintfloatboolr_   rZ   printr   reprr6   rY   )rC   r{   r|   r}   	vars_jsonstripped
is_wrappedr   prefixrestarrow_matchrP   result_previewsample_resultkeyrO   	value_strrA   rD   	namespaces                     r   evaluate_wrapperz*create_namespace.<locals>.evaluate_wrapperM  sG     
\
**VVZZ	6::lB3OP
Q4zz+&9		?	@@ zz)$9jjl8 	hh98D*9+YxjXD
 -(EVx~-E J			0	1	Nf6NJ			X	&	B5HSTN+BJ 
		^	,	H(34.1H	   XXA8LU{{1~fc&km$dx'	{"TF;d HHBHMk	!!!$vs6{}%t(2dV<t .i[	(7St ,I;bfET4111 
jjl8 'DFhstn,D I/0MVx~5MIH%A%8CD>*AI 	N+G#$0G	  4&&D$	4116 6jD.I+CK=GN1IM=..01#26 4
U(253tTRVZ:X(YUCR_bch_iYC59+U33^4 =BM 2R 78
CC^	.( =% 	64 
6{a
  = &k$3'^
_S[MN3C3GH = 	64 &s6{m3CDN6<<>*3B/ 4
U(253tTRVZ:X(YUCR_bch_iYC59+U33^4 6{RFb 01<<^	.
 = 
E$v,''(fcr1B0C
DE
=a 2" 2@ 
 	!"))CFK*PQ	s{   F4R-7Q58BR-Q; Q8CQ; /R-0*Q; R-*Q; R-B<Q; R-1Q; 4R-8Q; ;	R*!R%%R**R-rW   indexc                   K   ddl m} j                  |        d{   }|)d|  d}t        j	                  d|        t        |      g }|j                  }|r||j                  a|j                  j                         }|j                  r|j                  j                  dd      nd}|r| d	| n|}|j                  d|       |j                  }|r|d
}	|j                  }|r/|j                  j                         dk(  rd}	n|j                  }|r/ ||      }
|rudj                  |      }t        j                  d|  d|        t        j                  d|
        t        j                  d|d   j                  d	      d    d|
 d       |	rt        j                  d|  d       |
r|
S |j                  r|j                  j                         S t!        d|        7 ͭw)a%  
		Get the CSS selector for an element by its interactive index.

		This allows you to use the element's index from the browser state to get
		its CSS selector for use in JavaScript evaluate() calls.

		Args:
			index: The interactive index from the browser state (e.g., [123])

		Returns:
			str: CSS selector that can be used in JavaScript

		Example:
			selector = await get_selector_from_index(123)
			await evaluate(f'''
			(function(){{
				const el = document.querySelector({json.dumps(selector)});
				if (el) el.click();
			}})()
			''')
		r   )!generate_css_selector_for_elementNzElement index zE not available - page may have changed. Try refreshing browser state.u   ⚠️ idr   #FiframeTz > z	Element [z] is inside Shadow DOM. Path: z    Selector: z'    To access: document.querySelector("z").shadowRoot.querySelector("z")z8] is inside an iframe. Regular querySelector won't work.z.Could not generate selector for element index )browser_use.dom.utilsr   get_element_by_indexr3   r7   RuntimeErrorparent_nodeshadow_root_typetag_namer0   
attributesrX   insertr[   r4   r.   r   )r   r   nodemsgshadow_hostscurrenthost_taghost_id	host_desc	in_iframeselectorshadow_pathrD   s               r   get_selector_from_index_wrapperz9create_namespace.<locals>.get_selector_from_index_wrapper  s    , F 33E:	:$	\% e	f3	>>GC5/"	c	 ,'*%%'H292D2Dg  $$T2."G+28*AgY'I9%  7 	 )'(*I	  7	 	 /t4( L);	;;5'!?}MN	;;z*+	;;-l1o.C.CC.H.K-LLijrissuv 	;;5'!YZ[
? 
]]
--


CE7KLLa 
;s   G.G+B:G.>G.CG.get_selector_from_indexc                 &      fd}|S )Nc                    K   | rMt        j                  j                               }t        |       D ]  \  }}|t	        |      k  s||||   <    	  d i |}dk(  rj                  d      }|r|dkD  rnj                  di       }t        |j                               D 	cg c]  }	|	j                  d      s|	 }
}	t	        |
      dkD  rd	}t        |       j                  d
      }|rlt        |t              r[|j                         j                  d      D cg c]  }|j                          }}|D cg c]  }|s|j                  d      r| }}d}t        t        |            D ]   \  }}d|v sd|v st	        |      dz
  |z
  } n d}d}d}|dkD  r||dz
     }|j                         j                  d      xr |j                         j!                  d      }|j                         j                  d      }|j                         j                  d      }|s|s|r-d}t"        j%                  |       t        |       t'        |      dd} d d|i| d {   }t)        |d      rdk(  rSt)        |d      rG|j*                  r;dd<   |j,                  r|j,                  d<   t)        |d      r|j.                  d<   |j,                  r|j,                  S |j$                  rt'        |j$                        y |S # t
        $ r}t        d d|       |d }~ww xY wc c}	w c c}w c c}w 7 ֭w)!NzInvalid parameters for rR   done_consecutive_errors   _all_code_blockspython_r)   zdone() should be the ONLY code block in the response.
You have multiple Python blocks in this response. Consider calling done() in a separate response Now verify the last output and if it satisfies the task, call done(), else continue working._current_cell_coder'   r   zawait done()zawait done(Fr   zif r(   zelse:zelif zdone() should be called individually after verifying the result from any logic.
Consider validating your output first, THEN call done() in a final step without if/else/elif blocks only if the task is truly complete.)rD   rg   ri   has_sensitive_datarh   rI   extracted_contentis_doneT
_task_done_task_resultsuccess_task_successr   )r^   model_fieldskeys	enumerater   r6   r   rX   sortedr1   r   r\   rZ   r/   r.   reversedendswithr3   r   r   hasattrr   r   r   )argsr}   field_namesiargrI   rA   consecutive_failures
all_blockskpython_blocksr   current_coder>   r=   
code_linesdone_line_indexhas_if_abovehas_else_abovehas_elif_above
line_abovespecial_contextrP   act_funcact_nameri   rD   rh   r   rg   	par_models                          r   action_wrapperzEcreate_namespace.<locals>.make_action_wrapper.<locals>.action_wrapper  sg    	..3356[T? $C	
S	 #vk!n$
H!&!V
 6%MM*?@!5!9
 ==!3R8j"():";WQq||I?VqWmW	]	a		g 
 Sz ]]#78l	*\37)5););)=)C)CD)IJ

JuJ&+QdtDOOC<PTQzQ  45 71dT!]d%:z?Q.2	
 |~~
A
! 34
!'')44U;`
@P@P@R@[@[\_@`#))+66w?#))+66w?
.N
S 	 	Sc
3 (/1 O =6=_==F v*+Fwvy9fnn $i		!	!#)#;#;y 		#$*NNy! 	  %%%&&Mm  H/zA3?@aGH X KQH >s|   AM	
ML AM)L> L>A#M'M>MMMM"&M	C-M6M7B$M	L;$L66L;;Mr   )	r   r   r   r   ri   rD   rh   r   rg   s	   ``` r   make_action_wrapperz-create_namespace.<locals>.make_action_wrapper  s    b bH r   input
input_text)NN)r   rm   rn   r   ro   r   rp   rq   NUMPY_AVAILABLErr   PANDAS_AVAILABLErt   MATPLOTLIB_AVAILABLErv   BS4_AVAILABLEr
   PYPDF_AVAILABLEr   TABULATE_AVAILABLEr   rZ   r]   r   r   registryactionsr   param_modelfunction)rD   rf   rg   rh   ri   rj   r   r   action_nameactionr   action_functionr   namespace_action_namer   s   ` ```         @r   create_namespacer      s   < 
M 
%  

	
 )D/)G)D/)H)E)L,)O")E$)K )G")J 	)$&) ! ?Cm	d
m	&*38nt&;m	LOm	[^m		m	^ *:IM# IM# IMV )H$% "NN33;;AAC rd[&J""+OO/e eP +6*@,k &9kSb%c)!"erdh 	r   r   c                 B   dg}t        | j                               D ]p  \  }}t        |      s|j                  d      r$t	        |d      s1|j
                  s>|j                  d| d       |j                  |j
                   d       r dj                  |      S )z
	Generate documentation for all available functions in the namespace.

	Args:
		namespace: The namespace dictionary

	Returns:
		Markdown-formatted documentation string
	z# Available Functions
_r   z## r'   )r   r   callabler1   r   r   rY   r[   )r   docsnameobjs       r   get_namespace_documentationr     s     
## *+ $YT3c]4??3/c9#++KK#dV2KK3;;-r"#$ 			$r   )NNNNN)7r   rn   ro   rp   rm   loggingr   pathlibr   typingr   rq   browser_use.browserr   "browser_use.filesystem.file_systemr   browser_use.llm.baser   browser_use.tools.servicer   r	   	getLoggerr   r3   rs   rr   r   ImportErrorru   rt   r   matplotlib.pyplotpyplotrv   r   rx   r
   r   ry   r   r   r   r   rZ   r   r6   r   tupler   rB   rW   r^   r]   r   r   r   r   r   <module>r     sN    
    	    . 9 . ;			8	$ 
  *I L)
L)	tL) L) 49	L)^NW NW~ NW# NWf -1"&*.:>B BB $d*B 4	B
 Cy4'B c3c3h//047B 
#s(^BJ4S> c O            sl   D D &D /D+ 8D8 E DDDDD('D(+D54D58EEEE