Ë
    ãß²j0  ã                  ó  — d Z ddlmZ ddlZddlmZmZ ddlmZ	 ddl
mZ ddlmZmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ dd„Zdd„Zdd„Z d d„Z!dd„Z"dd„Z#d!d„Z$d!d„Z%d"d„Z&d!d„Z'd#d„Z(d!d„Z)d!d„Z*d!d„Z+d!d„Z,y)$u)  Cloud browser provider resolution (explicit browser.cloud_provider, auto-detect, per-profile cache), backend/engine selection and headed-mode flags.

Split out of ``tools/browser_tool.py``. Facade-owned state is read through ``_bt`` (``tools.browser_tool``, resolved per call) â€” no import cycle.é    )ÚannotationsN)ÚCallableÚOptional)ÚBrowserProvider)Úget_provider)Úget_hermes_home_overrideÚhermes_home_key)ÚBrowserUseBrowserProvider)ÚBrowserbaseBrowserProvider)Ú normalize_browser_cloud_provider©Úis_truthy_value)Úorigin_module)Úbrowser_tool_cdpc                ó’   — t        «       � |«       S t        | |«      st        | |d«       t        | | |«       «       t        | |«      S )a°  Process-lifetime cache on ``_bt``: the resolved flag is set BEFORE computing, then the final value is stored.

    Under a routed profile (HERMES_HOME override, multiplexed gateway) the slot is NOT consulted: every
    ``_memo`` here caches a ``browser.*`` config read, and one process-wide slot would hand the launch
    profile's engine/headed/private-URL policy to every other profile (same rule as ``_allow_private_urls``).
    T)r   ÚgetattrÚsetattr)Ú_btÚresolved_attrÚ
cache_attrÚcomputes       ú=/home/ubuntu/.hermes/hermes-agent/tools/browser_tool_cloud.pyÚ_memor      sF   € ô  Ó!Ð-Ù‹yÐÜ�3˜Ô&Ü��] DÔ)Ü��Z¡£Ô+Ü�3˜
Ó#Ð#ó    c                 ó”   — 	 ddl m}   | «        y# t        $ r.}t        «       j                  j                  d|«       Y d}~yd}~ww xY w)zbIdempotently trigger plugin discovery (standalone scripts/tests may never import ``model_tools``).r   )Ú_ensure_plugins_discoveredz/Browser plugin discovery failed (non-fatal): %sN)Úhermes_cli.pluginsr   Ú	ExceptionÚ_originÚloggerÚdebug)r   Úexcs     r   Ú_ensure_browser_plugins_loadedr#   $   s@   € ðWÝAÙ"Õ$øÜò WÜ‹	×Ñ×ÑÐPÐRU×VÑVûðWús   ‚ �	A™$AÁAc                 óº  — t        «       } t        «       }| j                  5  | j                  s!d| _        | j
                  j                  «        	 | j                  |¬«      }||f}|| j
                  v r7| j
                  |   | _        d| _        || _        | j                  cddd«       S d| _        d| _        t        «       }| j                  |¬«      }||k7  rŒŒ| j                  rZ|| _        | j
                  D �cg c]  }|d   |k(  sŒ|‘Œ c}D ]  }| j
                  j                  |d«       Œ  || j
                  |<   |cddd«       S c c}w # 1 sw Y   yxY w)z9Return the provider cached for the active Hermes profile.NT)ÚscopeFr   )r   r	   Ú_cloud_provider_cache_lockÚ_cloud_provider_resolvedÚ_cached_cloud_provider_scopeÚ_cached_cloud_providersÚclearÚ_browser_registry_generationÚ_cached_cloud_providerÚ _resolve_cloud_provider_uncachedÚpop)r   r%   Úbefore_generationÚ	cache_keyÚresolvedÚafter_generationÚkeyÚ	stale_keys           r   Ú_get_cloud_providerr5   -   sh  € ä
‹)€CÜÓ€EØ	×	'Ñ	'ñ à×+Ò+Ø/3ˆCÔ,Ø×'Ñ'×-Ñ-Ô/ØØ #× @Ñ @ÀuÐ @Ó MÐØÐ 1Ð2ˆIØ˜C×7Ñ7Ñ7Ø-0×-HÑ-HÈÑ-S�Ô*Ø/3�Ô,Ø38�Ô0Ø×1Ñ1÷ñ ð *.ˆCÔ&Ø+0ˆCÔ(Ü7Ó9ˆHØ"×?Ñ?ÀeÐ?ÓLÐØ Ð$4Ò4ØØ×+Ò+Ø38�Ô0Ø14×1LÑ1LÖ!`¨#ÐPSÐTUÑPVÐZ_ÓP_¢#Ò!`ò E�IØ×/Ñ/×3Ñ3°I¸tÕDðEà9A�×+Ñ+¨IÑ6Ø÷1ñ ùò* "a÷+ð ús+   ¡B EÂ+AEÃ<EÄ
EÄ4EÅEÅEc                óð   — t        «       }	 t        «        t        | «      }|€ddlm} t         |dd| › d�d«      «      ‚|S # t
        $ r ‚ t        $ r! |j                  j                  d| d¬	«       Y yw xY w)
zóBuild the provider named by ``browser.cloud_provider``.

    Strict: an unregistered name raises ``ValueError`` (never a silent reroute to auto-detect); any
    other instantiation error is logged and yields None so the next call retries.
    Nr   )Úselection_errorÚbrowserú'zlno registered browser plugin has that name (install the corresponding plugin or fix the config key spelling)zIFailed to instantiate explicit cloud_provider %r; will retry on next callT©Úexc_info)	r   r#   Ú_registry_get_browser_providerÚtools.tool_backend_helpersr7   Ú
ValueErrorr   r    Úwarning)Úprovider_keyr   r1   r7   s       r   Ú$_instantiate_explicit_cloud_providerrA   L   s•   € ô ‹)€CðÜ&Ô(Ü1°,Ó?ˆØÐÝBÜ™_Ø˜Q˜|˜n¨AÐ.Ø~óó ð ð ˆøÜò ØÜò Ø�
‰
×ÑÐfÐhtð  @DÐô  	EÙðús   Œ5A Á0A5Á4A5c                 óÌ   — t        «       } 	 t        t        fD ]  } |«       }|j                  «       sŒ|c S  	 y# t        $ r  | j
                  j                  dd¬«       Y yw xY w)z›Auto-detect: Browser Use, then Browserbase; never raises.

    Third-party plugins are only reachable via explicit ``browser.cloud_provider: <name>``.
    z!Cloud provider auto-detect failedTr:   N)r   r
   r   Úis_availabler   r    r!   )r   ÚclsÚfallback_providers      r   Ú_autodetect_cloud_providerrF   d   ss   € ô
 ‹)€CðMÜ-Ô/IÐJò 	)ˆCÙ #£ÐØ ×-Ñ-Õ/Ø(Ò(ñ	)ð øô ò MØ�
‰
×ÑÐ<ÀtÐÕLØðMús   Œ&: ³: ·: º&A#Á"A#c                 óÖ  — t        «       } d}d}	 ddlm}  |«       j                  di «      }t	        |t
        «      r8d|v r4t        |j                  d«      «      }|dv rd| _        d| _        y|dk(  rd	}|rt        |«      }|€y|€|€
t        «       }|€y|| _        d| _        | j                  S # t        $ r ‚ t        $ r&}| j                  j                  d
|«       Y d}~Œ^d}~ww xY w)aK  Return the configured cloud browser provider, or None for local mode.

    Pins the cache only when definitive (explicit ``local``/``camofox`` or a resolved provider); a transient None
    (unreadable config, missing credentials) is NOT cached so it can self-heal. Auto-detect runs only when no
    selection was ever written.
    Nr   )Úread_raw_configr8   Úcloud_provider)ÚlocalÚcamofoxTÚnouszbrowser-usez-Could not read cloud_provider from config: %s)r   Úhermes_cli.configrH   ÚgetÚ
isinstanceÚdictr   r,   r'   rA   r>   r   r    r!   rF   )r   r1   r@   rH   Úbrowser_cfgÚes         r   r-   r-   t   s	  € ô ‹)€CØ/3€HØ€LðMÝ5Ù%Ó'×+Ñ+¨I°rÓ:ˆÜ�k¤4Ô(Ð-=ÀÑ-LÜ;¸K¿O¹OÐL\Ó<]Ó^ˆLØÐ3Ñ3à-1�Ô*Ø/3�Ô,ØØ˜vÒ%à,�ÙÜ;¸LÓIˆHØÐØð Ð˜LÐ0Ü-Ó/ˆØÐØØ!)€CÔØ#'€CÔ Ø×%Ñ%Ð%øô ò ØÜò Mà�
‰
×ÑÐHÈ!×LÑLûðMús   �AB0 Á.B0 Â0C(ÃC#Ã#C(c                 ó\   — t        «       } t        j                  «        xr t        «       du S )zCReturn True when the browser tool will use a local browser backend.N)r   Ú_cdpÚ_get_cdp_override_rawr5   ©r   s    r   Ú_is_local_moderW   ž   s)   € ä
‹)€CÜ×)Ñ)Ó+Ð+ÒMÔ0CÓ0EÈÐ0MÐMr   c                 óÒ   — t        «       } t        j                  «       ry| j                  «       ryt	        «       �yddlm}  |dd«      j                  «       j                  «       dv S )u§  True when the browser runs locally AND the terminal is also local.

    SSRF protection only matters when the browser can reach networks the terminal cannot (cloud backends,
    containerized terminals). A CDP override is never trusted as local (that Chrome may live off-host) and MUST
    be checked before the Camofox short-circuit; ``_is_local_mode`` treats overrides the same way â€” keep the two
    in agreement.
    FTr   )Úterminal_envÚTERMINAL_ENVrJ   )rJ   Ú )	r   rT   rU   Ú_is_camofox_moder5   Útools.terminal_scoperY   ÚstripÚlower)r   rY   s     r   Ú_is_local_backendr`   ¤   s^   € ô ‹)€CÜ×!Ñ!Ô#ØØ
×ÑÔØÜÓÐ(Øõ 2Ù˜¨Ó0×6Ñ6Ó8×>Ñ>Ó@ÀMÐQÐQr   c                 ó@   ‡— t        «       Šdˆfd„} t        ‰dd| «      S )a
  Return the browser engine: ``auto`` (no ``--engine`` flag), ``lightpanda`` or ``chrome``.

    ``browser.engine`` first, then ``AGENT_BROWSER_ENGINE``, then ``auto``; cached. Lightpanda is faster on
    navigation but has no graphical renderer (no screenshots).
    c            	     ó:  •— ‰j                  ddd„ d«      } | dk(  r@t        j                  j                  dd«      j	                  «       j                  «       xs | } h d£}| |vr7‰j                  j                  d| d	j                  t        |«      «      «       d} | S )
NÚengineÚautoc                óŠ   — | r@t        | «      j                  «       r't        | «      j                  «       j                  «       S dS )Nrd   ©Ústrr^   r_   ©Úvs    r   ú<lambda>z6_get_browser_engine.<locals>.compute.<locals>.<lambda>Â   s3   € ÑXYÔ^aÐbcÓ^d×^jÑ^jÔ^l¼cÀ!»f¿l¹l»n×>RÑ>RÓ>T€ Ðrx€ r   zbrowser.engine from configÚAGENT_BROWSER_ENGINEr[   >   rd   ÚchromeÚ
lightpandaz=Unknown browser engine %r (valid: %s), falling back to 'auto'z, )
Ú_browser_cfgÚosÚenvironrN   r^   r_   r    r?   ÚjoinÚsorted)rc   Ú_VALID_ENGINESr   s     €r   r   z$_get_browser_engine.<locals>.computeÁ   s¨   ø€ Ø×!Ñ! (¨FÑ4xð  {Wó  XˆØ�VÒÜ—Z‘Z—^‘^Ð$:¸BÓ?×EÑEÓG×MÑMÓOÒYÐSYˆFâ9ˆØ˜Ñ'Ø�J‰J×ÑÐ^Ð`fÐhl×hqÑhqÔrxð  zHó  sIó  iJô  KØˆFØˆr   Ú_browser_engine_resolvedÚ_cached_browser_engine©Úreturnrg   ©r   r   ©r   r   s    @r   Ú_get_browser_enginerz   º   s&   ø€ ô ‹)€Cõ	ô �Ð0Ð2JÈGÓTÐTr   c                 ó@   ‡— t        «       Šdˆfd„} t        ‰dd| «      S )zfTrue when the browser should launch headed: ``browser.headed``, else ``AGENT_BROWSER_HEADED``; cached.c                 ó²   •— ‰j                  ddd„ d«      } | xs> t        j                  j                  dd«      j	                  «       j                  «       dv S )NÚheadedFc                ó\   — | €dS t        | «      j                  «       j                  «       dv S )NF©ÚtrueÚ1Úyesrf   rh   s    r   rj   z2_is_headed_mode.<locals>.compute.<locals>.<lambda>Ò   s5   € ÀaÀi¸U€ ÔUXÐYZÓU[×UaÑUaÓUc×UiÑUiÓUkð  pDð  VD€ r   zbrowser.headed from configÚAGENT_BROWSER_HEADEDr[   r   )rn   ro   rp   rN   r^   r_   )r}   r   s    €r   r   z _is_headed_mode.<locals>.computeÑ   sX   ø€ Ø×!Ñ! (¨Eñ  4Dð  Fbó  cˆØÒkœŸ™Ÿ™Ð(>ÀÓC×IÑIÓK×QÑQÓSÐWkÐkÐkr   Ú_headed_mode_resolvedÚ_cached_headed_mode©rw   Úboolrx   ry   s    @r   Ú_is_headed_moderˆ   Î   s%   ø€ ä
‹)€Cõlô �Ð-Ð/DÀgÓNÐNr   c                ó^   — t        «       }| dk7  xr |j                  «        xr
 t        «       S )zqTrue when ``--engine`` should be added: explicit (non-``auto``) engine on a non-cloud, non-camofox local session.rd   )r   r\   rW   )rc   r   s     r   Ú_should_inject_enginerŠ   ×   s-   € ä
‹)€CØ�VÑÒO C×$8Ñ$8Ó$:Ð :ÒO¼~Ó?OÐOr   c                 ó:   ‡ — t        «       Š t        ‰ ddˆ fd„«      S )z…``browser.auto_local_for_private_urls`` (default True), cached: route private/LAN URLs to a local sidecar even with a cloud provider.Ú%_auto_local_for_private_urls_resolvedÚ#_cached_auto_local_for_private_urlsc                 óH   •— ‰ j                  d‰ j                  t        d«      S )NÚauto_local_for_private_urlsz'auto_local_for_private_urls from config)rn   r�   r‡   rV   s   €r   rj   z._auto_local_for_private_urls.<locals>.<lambda>â   s(   ø€ �× Ñ Ð!>À×@gÑ@gÔimð  pYó  Z€ r   rx   rV   s   @r   Ú_auto_local_for_private_urlsr�   Ý   s&   ø€ ä
‹)€CÜØÐ4Ð6[ó 	Zóð r   c                 óB   — t        «       j                  ddt        d«      S )a  Whether the user consented to real-profile local browsing.

    Read on EVERY call: it is a consent switch (flipping it off must not need a restart) and each multiplexed
    profile must decide for itself. One YAML load per local session creation, so no hot-path cost.
    Úuse_real_profileFzuse_real_profile from config)r   rn   r‡   © r   r   Ú_use_real_profiler”   æ   s   € ô ‹9×!Ñ!Ð"4°e¼TÐCaÓbÐbr   c                 ób   — t        «       } t        «       �
t        «       S t        | ddt        «      S )a&  Whether the browser may navigate to private/internal addresses (default False: SSRF protection on).

    Single-profile calls cache for the process lifetime; multiplexed profile turns (ContextVar-scoped config)
    resolve on every call so one profile's opt-out is never reused by another.
    Ú_allow_private_urls_resolvedÚ_cached_allow_private_urls)r   r   Ú_resolve_allow_private_urlsr   rV   s    r   Ú_allow_private_urlsr™   ï   s1   € ô ‹)€CÜÓ!Ð-Ü*Ó,Ð,Ü�Ð4Ð6RÔToÓpÐpr   c                 ó@   — t        «       } | j                  ddd„ d«      S )zARead the browser private-URL toggle from the active config scope.Úallow_private_urlsFc                ó   — t        | d¬«      S )NF)Údefaultr   rh   s    r   rj   z-_resolve_allow_private_urls.<locals>.<lambda>þ   s   € Ä?ÐSTÐ^cÔCd€ r   zallow_private_urls from config)r   rn   rV   s    r   r˜   r˜   û   s-   € ä
‹)€CØ×ÑÐ0°%Ñ9dð  gGó  Hð  Hr   )r   rg   r   rg   r   zCallable[[], object])rw   ÚNone)rw   úOptional[CloudBrowserProvider])r@   rg   rw   rŸ   r†   rv   )rc   rg   rw   r‡   )-Ú__doc__Ú
__future__r   ro   Útypingr   r   Úagent.browser_providerr   ÚCloudBrowserProviderÚagent.browser_registryr   r<   Úhermes_constantsr   r	   Ú$plugins.browser.browser_use.providerr
   Ú$plugins.browser.browserbase.providerr   r=   r   Úutilsr   Útools.browser_tool_originr   r   Útoolsr   rT   r   r#   r5   rA   rF   r-   rW   r`   rz   rˆ   rŠ   r�   r”   r™   r˜   r“   r   r   ú<module>r¬      s†   ðñWõ #ã 	ß %å JÝ Qß FÝ JÝ KÝ GÝ !Ý >Ý *ó$óWóó>ó0ó '&óTNóRó,Uó(OóPóócó	qôHr   