
    sj^e                       d Z ddlmZ ddlmZmZ ddlmZmZm	Z	m
Z
mZmZ eee	eef         ge	eef         f         Zeegef         Zd#d	Zd$dZd%dZd&dZd'dZd&dZddd(dZe G d d                      Z G d  d!          Zd"S ))a  Session-scoped typed-browser routing for cua-driver.

The public model surface remains the single ``computer_use`` tool.  This
module owns the stateful adapter between its namespaced ``cua_browser_*``
actions and cua-driver's raw ``get_browser_state`` / ``browser_*`` tools.

The adapter is deliberately stricter than the transport:

* native binding must be exact before mutation;
* the driver session id is injected by the adapter, never accepted from the
  model;
* refs are usable only from the latest snapshot in this Hermes session;
* every mutation invalidates refs and requires a fresh state read; and
* changing from trusted input to ``dom_event`` is always explicit.

Browser preparation remains a separate approved action. Existing-profile
attachment is delegated to cua-driver's daemon authorization coordinator;
ordinary Hermes tool approval never substitutes for protected consent.
    )annotations)	dataclassfield)AnyCallableDictIterableOptionalSetvaluer   returnOptional[int]c                    t          | t                    rd S 	 t          |           }n# t          t          f$ r Y d S w xY w|dk    r|nd S )Nr   )
isinstanceboolint	TypeError
ValueError)r   parseds     D/home/agent/.hermes/hermes-agent/tools/computer_use/browser_route.py_positive_intr      sd    % tUz"   ttaZZ66T)s   ) >>outDict[str, Any]c                N   |                      d          }|                      d          }i }t          |t                    r|                    |           nt          |t                    r|r||d<   t          |t                    r|                    |           |                      d          }|                      d          }t          |t
                    rg }t          |          D ]\  }}t          |t                    r|sd}	t          |t
                    r6|t          |          k     r#t          ||         t                    r||         }	|                    ||	d           |r||d<   |                      d	          d
u r|	                    d	d
           |S )zAReturn structured data without discarding refusals or MCP images.structuredContentdatamessageimagesimage_mime_types )r   	mime_type_mcp_imagesisErrorT)
getr   dictupdatestrlist	enumeratelenappend
setdefault)
r   
structuredr   payloadr   
mime_typespreserved_imagesindeximager!   s
             r   _tool_payloadr3   )   s   ,--J776??D G$ "t	D#		 "4 "!	*d## #z"""WWXF+,,J&$ 6%f-- 
	M 
	MLE5eS))  I:t,,.C
OO++z%0#66 , 'u-	##U$K$KLLLL 	6%5GM"
wwyT!!9d+++N    r.   Dict[str, Set[str]]c                    i d	fd} ||                      d                      ||                      d                     |                      d          }t          |t                    r ||                     d                     S )
a6  Normalize semantic-v2 action refs to ``ref -> actions``.

    cua-driver has emitted both mapping and list representations while the
    semantic snapshot contract evolved.  Accept both without weakening the
    capability rule: a ref with no declared action remains readable only.

    cua-driver >= 0.17 splits the semantic_v2 payload: action-bearing refs
    live in the ``refs`` array while ``content_refs`` carries every node
    with empty action lists.  Merge both sources (plus the legacy
    snapshot.refs forms) so click/pointer/type refs stay usable.
    rawr   r   Nonec                   t          | t                    r|                                 }n$t          | t                    rd | D             }nd S |D ]\  }}t          |t                    r-|                    d          p|}|                    d          }n|}d }t          |t
                    r|scd |pg D             }                    |t                                |z  |<   d S )Nc              3     K   | ]}d |fV  	d S N ).0items     r   	<genexpr>z+_ref_map.<locals>.absorb.<locals>.<genexpr>\   s&      44d|444444r4   refactionsc                <    h | ]}t          |t                    |S r<   )r   r'   )r=   actions     r   	<setcomp>z+_ref_map.<locals>.absorb.<locals>.<setcomp>h   s7       !
638O8O  r4   )r   r%   itemsr(   r$   r'   set)r7   entrieskeyr   r@   rA   
action_set
normalizeds          r   absorbz_ref_map.<locals>.absorbX   s   c4   	;>99;;GGT"" 	44444GGF! 	F 	FJC%&& ii&&-#))I..c3'' s  &-m  J
 )nnS#%%88:EJsOO	F 	Fr4   refscontent_refssnapshot)r7   r   r   r8   )r$   r   r%   )r.   rK   rN   rJ   s      @r   _ref_maprO   J   s     ')JF F F F F F2 F7;;v
F7;;~&&'''{{:&&H(D!! %x||F##$$$r4   Optional[str]c                   |                      d          }t          |t                    r|r|S |                      d          }t          |t                    r.|                     d          }t          |t                    r|r|S d S )NcontinuationrN   r$   r   r'   r%   )r.   directrN   nesteds       r   _continuationrV   y   s    [[((F&# 6 {{:&&H(D!! n--fc"" 	v 	M4r4   Set[str]c                .   t                      }|                     d          pg D ]n}t          |t                    s|                    d          p|                    d          }t          |t                    r|r|                    |           o|S )Ntabstab_idid)rF   r$   r   r%   r'   add)r.   resulttabrZ   s       r   _tab_idsr_      s    uuF{{6""(b  #t$$ 	""3cggdmmfc"" 	v 	JJvMr4   c                   |                      d          }t          |t                    r|S |                      d          }t          |t                    r0t          |                     d          t                    r|d         S d S )NcoderefusalrS   )r.   ra   rb   s      r   _refusal_coderc      sy    ;;vD$ kk)$$G'4   ZF0C0CS%I%I v4r4   Fnative_fallbackra   r'   r   re   r   extrac               L    dd| |d}|rd|d<   |                     |           |S )NFrefused)okstatusra   r   Tnative_fallback_required)r&   )ra   r   re   rf   r.   s        r   _refusalrl      sH     	 G  3.2*+NN5Nr4   c                      e Zd ZU dZdZded<   dZded<   dZded<    ee	          Z
d	ed
<   dZded<   dZded<   dZded<    ee          Zded<   dZded<   dZded<   ddZddZdS )BrowserRouteStatez8Capabilities minted for one explicit cua-driver session.Nr   pid	window_idrP   	target_id)default_factoryrW   tab_idsrZ   binding_qualityFr   mutation_allowedr5   rL   rR   verification_requiredr   r8   c                F    | j                                          d | _        d S r;   )rL   clearrR   selfs    r   
clear_refszBrowserRouteState.clear_refs   s"    	 r4   c                    d | _         d | _        d | _        | j                                         d | _        d | _        d| _        |                                  d| _	        d S )NF)
ro   rp   rq   rs   rx   rZ   rt   ru   r{   rv   ry   s    r   rx   zBrowserRouteState.clear   s`    # %%*"""r4   )r   r8   )__name__
__module____qualname____doc__ro   __annotations__rp   rq   r   rF   rs   rZ   rt   ru   r%   rL   rR   rv   r{   rx   r<   r4   r   rn   rn      s
        BBC#I#####I####c222G2222 F    %)O))))""""" %d ; ; ;D;;;;"&L&&&&"'''''! ! ! !	+ 	+ 	+ 	+ 	+ 	+r4   rn   c            	          e Zd ZdZd4d
Zd5dZd6dZdddddddddd7d Zddddd!d"d8d(Zdd)d9d-Z	d:d1Z
ddd2d;d3ZdS )<CuaTypedBrowserRoutez=Exact-bind typed-browser adapter for a single driver session.
session_idr'   	call_tool
ToolCallerhas_tool	ToolProber   r8   c               V    || _         || _        || _        t                      | _        d S r;   )_session_id
_call_tool	_has_toolrn   state)rz   r   r   r   s       r   __init__zCuaTypedBrowserRoute.__init__   s+     &#!&((


r4   nameargsr   c                z    t          |          }| j        |d<   t          |                     ||                    S )Nsession)r%   r   r3   r   )rz   r   r   r.   s       r   _callzCuaTypedBrowserRoute._call   s8    t** "-	T__T7;;<<<r4   Optional[Dict[str, Any]]c                \    |                      |          rd S t          dd| dd          S )Ntyped_browser_unavailablez,The connected cua-driver does not advertise z); use the native AX/PX/foreground ladder.Trd   )r   rl   )rz   r   s     r   _require_toolz"CuaTypedBrowserRoute._require_tool   sF    >>$ 	4'j4jjj 
 
 
 	
r4   Nsemantic_v2F)ro   rp   rZ   snapshot_formatquery	scope_refrR   include_screenshotro   r   rp   rZ   rP   r   r   r   rR   r   r   c               B   |                      d          }	|	|	S |dup|du}
|
rt          |          }t          |          }| j                                         ||t	          ddd          S ||d}|rd|d<   |                     d|          }|                    d	          d
k    r7t          |          }|                    d
d           d|d<   |dk    rd|d<   |S |                    d          }|                    d          }|                    d          du }t          |t                    r|st	          ddd          S || j        _        || j        _        || j        _        t          |          | j        _        t          |t                    r|nd| j        _        || j        _        d| j        _        d|d<   d|d<   d|d<   |r|                    d          sd|d<   |dk    |d<   |dk    s|sd|d<   |S | j        j        }|r| j        j        dk    rt	          ddd          S |p| j        j        }t          |t                    r|st	          d d!          S || j        j        vrt	          d"d#          S | || j        j        k    rt	          d$d%          S ||| j        j        vrt	          d&d'          S |||d(}|r||d)<   |r||d*<   |r||d+<   |rd|d<   |du}|s| j                                         |                     d|          }|                    d	          d,vs|                    d-          du r=| j                                         d| j        _        |                    d
d           |S t/          |          }|r | j        j                            |           n|| j        _        t3          |          | j        _        || j        _        d| j        _        d|d.<   t5          | j        j                  |d/<   |S )0z4Bind an exact native window or snapshot a bound tab.get_browser_stateNbrowser_exact_target_requiredzHTyped browser binding requires an exact positive pid and window_id pair.Trd   )ro   rp   r   rj   ri   Fnative_fallback_availablebrowser_requires_setupsetup_requiredrq   rt   ru   browser_binding_unprovenzFBrowser bind returned no opaque target capability; use native control.snapshot_requiredfresh_browser_state	next_stepzBinding only, no page content. Call cua_browser_state again WITHOUT pid or window_id (optionally with tab_id, query, snapshot_format, include_screenshot) to take the snapshot this binding requires before any mutation.hintr"   screenshot_deferredexactexact_bindingrk   browser_exact_binding_requiredzABind the exact native pid/window_id before reading a browser tab.browser_tab_requiredz3Choose an opaque tab_id returned by the exact bind.browser_tab_unboundAThe requested tab_id was not minted by this session's exact bind.browser_continuation_stalezLThe continuation is not current for this session/tab; take a fresh snapshot.browser_ref_stalez@scope_ref must come from this session's latest browser snapshot.)rq   rZ   r   r   r   rR   Nri   r#   fresh_staterefs_current)r   r   r   rx   rl   r   r$   rc   r,   r   r'   ro   rp   rq   r_   rs   rt   ru   rv   rZ   rR   rL   r{   rO   r&   rV   r*   )rz   ro   rp   rZ   r   r   r   rR   r   missingbinding_request	exact_pidexact_window	bind_argsr.   ra   rq   qualityru   selected_tabr   
continuing
discovereds                          r   observezCuaTypedBrowserRoute.observe   s     $$%899NT/BYd-B C	%c**I(33LJ L$83^$(    !)) )I " 726	./jj!4i@@G{{8$$,,$W--""4///7;3433304G,-K00Ikk"344G&{{+=>>$Fi-- Y .\$(    'DJN#/DJ #,DJ !)'!2!2DJ4>w4L4L)VRVDJ&*:DJ' 04DJ, ,0G'(#8GK = FO " 6'++m*D*D 6 26-.'.''9GO$'!!)9!6:23NJ(	 	DJ6'AA0S $   
 2!2,,, 	L 	&E   tz111%S   #
8O(O(O,^    Ydjo%E%E#R   #". 
  

  	"!DM 	* )D 	0#/D  	.)-D%&!-
 	$ J!!###**0$77;;x  44I8N8NRV8V8VJ!!###/3DJ,tU+++Ng&&
 	)JO"":....(DJO"/"8"8
(
+0
(!%"%djo"6"6r4   standard)rp   profile_nameallow_launchgrant_existing_profilepermission_modeprofile_moder   r   r   r   c                  |                      d          }||S t          |          }	|	t          dd          S |dk    rpt          |          }
|
t          dd          S |dk    r|st          d	d
          S | j                                         |	|
ddid}|                     d|          S |dvrt          dd          S |st          dd          S d|i}|dk    r,t          |t                    r|st          dd          S ||d<   |	d|d}t          |          }
|
|
|d<   | j                                         |                     d|          S )z@Run explicit setup through the driver's authoritative mode gate.browser_prepareNbrowser_pid_requiredz(browser_prepare requires a positive pid.existing_profiler   zNExisting-profile attachment requires an exact positive pid and window_id pair.bounded$browser_existing_profile_not_granteda  Attaching to an existing browser profile requires the one-time opt-in `computer_use.grant_existing_profile: true` in config.yaml. Hermes cannot grant this at runtime, and an approval bypass does not substitute for it. Use profile_mode=isolated_new to browse without it.kind)ro   rp   strategy>   isolated_newisolated_namedbrowser_profile_mode_invalidz6Use isolated_new, isolated_named, or existing_profile.browser_launch_not_approvedz@Driver-owned isolated setup requires explicit allow_launch=true.moder   browser_profile_name_requiredz1isolated_named requires a non-empty profile name.r   T)ro   r   profilerp   )r   r   rl   r   rx   r   r   r'   )rz   ro   rp   r   r   r   r   r   r   r   r   r   r   s                r   preparezCuaTypedBrowserRoute.prepare  s    $$%677N!#&&	&(R   ---(33L#3d   )++4J+:N   J )#%78$ $D
 ::/666AAA.H    	-R   $*<"8+++lC00  3G   +GFO  
  

 %Y//# ,D 	
zz+T222r4   )allow_without_snapshottoolr   .tuple[Optional[str], Optional[Dict[str, Any]]]c                  |                      |          }|d |fS | j        j        r| j        j        dk    s| j        j        sd t          ddd          fS |p| j        j        }t          |t                    r|sd t          dd          fS || j        j	        vrd t          dd	          fS | j        j
        r|sd t          d
d          fS |d fS )Nr   browser_mutation_unprovenzzTyped browser mutation requires status=ok, binding_quality=exact, and mutation_allowed=true; use native control otherwise.Trd   r   zChoose a bound tab_id first.r   r   browser_verification_requiredzTake a fresh cua_browser_state snapshot before another browser mutation: call cua_browser_state WITHOUT pid or window_id. Re-sending pid/window_id re-binds instead of snapshotting, which mints new tab_ids and leaves this mutation refused.)r   r   rq   rt   ru   rl   rZ   r   r'   rs   rv   )rz   r   rZ   r   r   r   s         r   _require_mutationz&CuaTypedBrowserRoute._require_mutation  s<    $$T**= 
$		z)W44:. 5 + M $    
 2!2,,, 	L 	&(F    tz111%S    :+ 	4J 	/$    T!!r4   r@   rA   rW   c                   t          |t                    r|| j        j        vrt	          dd          S | j        j        |         }|r%|                    |          st	          dd          S d S )Nr   z=Use a current ref from the latest cua_browser_state snapshot.browser_action_unavailablez>The current ref does not declare the requested browser action.)r   r'   r   rL   rl   intersection)rz   r@   rA   declareds       r   _require_refz!CuaTypedBrowserRoute._require_ref  s     #s## 	s$*/'A'A#O   :?3' 	80099 	,P   tr4   )rZ   r   c               *   t          |pi           }|dk    o|                    d          dk    }|                     |||          \  }}||S || j        j        J |                    d          }|dv }	|                    d          }
|
|	st          d	| d
          S |
pd}|dvrt          dd          S |dk    r|st          dd          S t                      }|dk    r|rddh}nK|dk    rh d}n@|dk    r%|r#|                    d          }|dk    rddhndh}n|dk    rh d}n
|dk    rddh}|r|                     ||          }||S |                    d          }||                     |h d          }||S | j        j        |d <   ||d!<   |s1|| j        _        | j        	                                 d"| j        _
        |                     ||          }t          |          }|                    d#          d"u p|                    d$          d%vp|du}|	r||d&<   |dk    rd"|d'<   |rBd"|d(<   |r)|d)v r%| j        	                                 d"| j        _
        |d*k    r
d"|d+<   d"|d(<   |S |rd"|d,<   |S d"|d-<   d.|d/<   |S )0z;Invoke one typed browser tool against current capabilities.browser_dialogrC   inspect)r   rZ   r   Nr@   >   browser_clickbrowser_pointerinput_routebrowser_input_route_unsupportedz= does not expose a trust-route choice in the live 0.9 schema.trusted>   r   	dom_eventbrowser_input_route_invalidz8Use input_route=trusted or explicitly request dom_event.r   browser_dom_event_ref_requiredz:The dom_event trust class requires a current semantic ref.r   clickpointerbrowser_type>   edittypeinputr   scrollbrowser_set_input_files>   filesuploadset_input_filesbrowser_downloaddownload)rA   destination_ref>   dragdropr   rq   rZ   Tr#   rj   r   input_trusttrust_downgrade_explicitr   >   r   browser_binding_ambiguousbrowser_input_trust_unavailable%trust_change_requires_explicit_choicefresh_dialog_staterv   r   r   )r%   r$   r   r   rq   rl   rF   r   rZ   r{   rv   r   rc   )rz   r   rZ   r   	call_argsdialog_inspectr   rb   r@   supports_trust_choicerequested_routerouterequired_actionspointer_actioninvalid_refr   invalid_destinationr.   ra   rh   s                       r   mutatezCuaTypedBrowserRoute.mutate  s    $$	$$Mx)@)@I)M 	 !% 6 6#1 !7 !
 !
g
 N'DJ,@,L,LLmmE"" $(L L#--66&/D&1VVV    ,9000-J   K0L  
 &)UU?""s" '3^##888&&&3&&]]844N)78)C)C9%%)  ...EEE''' *G4 	#++C9I+JJK&""#--(9::&"&"3"3)D)D)D #4 # # #.**!%!5	+*	( 	4 !-DJJ!!###/3DJ,**T9--W%%KK	""d*  {{8$$L8 4 	
 ! 	;%*GM"##6:23 	37G/0 8$ + # # 
%%'''37
0888CG?@7;34N 	,0G()N
 ,0'(4r4   )r   r'   r   r   r   r   r   r8   )r   r'   r   r   r   r   )r   r'   r   r   )ro   r   rp   r   rZ   rP   r   r'   r   rP   r   rP   rR   rP   r   r   r   r   )ro   r   rp   r   r   r'   r   rP   r   r   r   r   r   r'   r   r   )r   r'   rZ   rP   r   r   r   r   )r@   r   rA   rW   r   r   )r   r'   rZ   rP   r   r   r   r   )r}   r~   r   r   r   r   r   r   r   r   r   r
  r<   r4   r   r   r      s1       GG
) 
) 
) 
)= = = =
 
 
 
  $,##'&*#(X X X X X X| &*"',)R3 R3 R3 R3 R3 R3r (-'" '" '" '" '" '"R   . !%)-o o o o o o o or4   r   N)r   r   r   r   )r   r   r   r   )r.   r   r   r5   )r.   r   r   rP   )r.   r   r   rW   )
ra   r'   r   r'   re   r   rf   r   r   r   )r   
__future__r   dataclassesr   r   typingr   r   r   r	   r
   r   r'   r   r   r   r   r3   rO   rV   r_   rc   rl   rn   r   r<   r4   r   <module>r     s   ( # " " " " " ( ( ( ( ( ( ( ( ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? sDcN+T#s(^;<
cUD[!	* * * *   B, , , ,^	 	 	 	       "	     & + + + + + + + +<x x x x x x x x x xr4   