+
    lHàj‹#  ã                   ó  a € R t0 t R t^ RIt^ RIt^ RIt^ RIHtHt ^ RIH	t	 ^ RI
Ht R R lt/ t] ^ k ]P                  ! 4       tR R ltR	 R
 lt/ t] ^k RR R lltR R ltR R ltR R ltR R ltR R ltR R ltR# )u  User-supplied CDP endpoint resolution (browser.cdp_url / real-profile), dialog-policy config and the per-task CDP supervisor lifecycle.

Split out of ``tools/browser_tool.py``. Facade-owned state is read through ``_bt`` (``tools.browser_tool``, resolved per call) â€” no import cycle.N)ÚOptionalÚTuple)Úloopback_request_kwargs)Úorigin_modulec                ó0   € V ^8„  d   QhR\         R\         /# )é   Úcdp_urlÚreturn©Ústr)Úformats   "Ú;/home/ubuntu/.hermes/hermes-agent/tools/browser_tool_cdp.pyÚ__annotate__r      s   € ÷ #ñ #¤3ð #¬3ñ #ó    c           	     óÚ  € \        4       pT ;'       g    RP                  4       pV'       g   R# VP                  4       pRV9   d   V# TpVP                  R4      '       d¬   VP	                  R4      ^8X  d[   VP                  R4      P                  R^4      R,          P                  4       '       d   RVP                  R^4      R,          9  g   V# VP                  R4      '       d   RMRVP                  R^4      ^,          ,           pVP                  4       P                  R	4      '       d   TMVP                  R4      R	,           pVP                  p ^ R
IpVP                  ! V3R^
/\        V4      B pVP                  4        VP                  4       p	\'        T	P                  R4      ;'       g    R4      P                  4       pT'       d,   TP"                  P)                  RT! T4      T! T4      4       T# TP"                  P%                  RT! T4      4       T#   \          d=   p
TP"                  P%                  RT! T4      T! T4      T! T
4      4       Tu R
p
?
# R
p
?
ii ; i)u   Normalize a user-supplied CDP endpoint into a concrete websocket URL.

Full ``ws://.../devtools/browser/...`` endpoints pass through; HTTP discovery roots and bare ``ws://host:port``
resolve via ``/json/version`` â†’ ``webSocketDebuggerUrl`` (falls back to the raw value with a warning).
Ú z/devtools/browser/úws://Ú:Ú/zhttp://zhttps://z://z/json/versionNÚtimeoutz,Failed to resolve CDP endpoint %s via %s: %sÚwebSocketDebuggerUrlzResolved CDP endpoint %s -> %szKCDP discovery at %s did not return webSocketDebuggerUrl; using raw endpoint)r   zwss://éÿÿÿÿ)Ú_originÚstripÚlowerÚ
startswithÚcountÚrstripÚrsplitÚisdigitÚsplitÚendswithÚ_sanitize_url_for_logsÚrequestsÚgetr   Úraise_for_statusÚjsonÚ	ExceptionÚloggerÚwarningr   Úinfo)r   Ú_btÚrawÚloweredÚdiscovery_urlÚversion_urlÚsanr#   ÚresponseÚpayloadÚexcÚws_urls   &           r   Ú_resolve_cdp_overrider5      s  € ô ‹)€CØ�=ˆ=�b×
Ñ
Ó
!€CßÙØ�i‰i‹k€GØ˜wÔ&Øˆ
à€MØ×ÑÐ-×.Ò.Ø—	‘	˜#“ !Ô#¨¯
©
°3«×(>Ñ(>¸sÀAÓ(FÀrÕ(J×(RÑ(R×(TÒ(TÐY\Ðdg×dmÑdmÐnqÐstÓduÐvxÕdyÔYyØˆJØ&-×&8Ñ&8¸×&AÒ&A™ÀzÐUX×U^ÑU^Ð_dÐfgÓUhÐijÕUkÕkˆØ#0×#6Ñ#6Ó#8×#AÑ#AÀ/×#RÒ#R‘-ÐXe×XlÑXlÐmpÓXqð  uDõ  YD€Kà
×
$Ñ
$€CðÛØ—<’< Ñ`°RÐ`Ô;RÐS^Ó;_Ñ`ˆØ×!Ñ!Ô#Ø—-‘-“/ˆô �—‘Ð3Ó4×:Ð:¸Ó;×AÑAÓC€FßØ�
‰
�‰Ð8¹#¸c»(ÁCÈÃKÔPØˆØ‡J�J×ÑÐdÑfiÐjuÓfvÔwØ€Jøô ô Ø�
‰
×ÑÐIÉ3ÈsË8ÑUXÐYdÓUeÑgjÐknÓgoÔpØ�
ûðús   ÅAH# È#I*È.1I%ÉI*É%I*c                ó$   € V ^8„  d   QhR\         /# ©r   r	   r
   )r   s   "r   r   r   :   s   € ÷ :ñ :œ3ñ :r   c                 óÞ   € ^ RI Hp  ^ RIHpHp V! 4       f   V ! 4       '       d   R# \
        ;_uu_ 4        \        P                  V! 4       R4      uuRRR4       #   + '       g   i     R# ; i)aU  The current profile's live ``/browser connect`` endpoint, or "".

On a multiplexed gateway a context with no profile bound (a bare ``threading.Thread`` or stdlib
executor that did not copy the caller's context) answers "" rather than the launch profile's
endpoint, the way ``get_secret`` fails closed. Single-profile processes are unchanged.)Úis_multiplex_active)Úget_hermes_home_overrideÚhermes_home_keyNr   )Úagent.secret_scoper9   Úhermes_constantsr:   r;   Ú_live_overrides_lockÚ_live_overridesr$   )r9   r:   r;   s      r   Úlive_cdp_overrider@   :   sG   € õ 7ßJÙÓ!Ò)Ñ.A×.CÒ.CÙß	Ö	Ü×"Ñ"¡?Ó#4°bÓ9÷ 
×	×	Ó	ús   µAÁA,	c                ó>   € V ^8„  d   QhR\         \        ,          RR/# )r   Úurlr	   N)r   r   )r   s   "r   r   r   H   s"   € ÷ 	Cñ 	Cœx¬�}ð 	C°ñ 	Cr   c                ó  € ^ RI Hp V! 4       p\        ;_uu_ 4        V '       d   V \        V&   M\        P	                  VR4       \
        P                  V^ 4      ^,           \
        V&   RRR4       R#   + '       g   i     R# ; i)z`Set (or with a falsy ``url`` clear) the current profile's live endpoint and bump its generation.©r;   N)r=   r;   r>   r?   ÚpopÚ_live_generationsr$   )rB   r;   Úkeys   &  r   Úset_live_cdp_overriderH   H   s\   € å0Ù
Ó
€Cß	Ö	ßØ#&ŒO˜CÒ ä×Ñ  TÔ*Ü!2×!6Ñ!6°s¸AÓ!>ÀÕ!BÔ˜#Ñ÷ 
×	×	Ò	ús   œAA3Á3B	c                óF   € V ^8„  d   QhR\         \        ,          R\        /# )r   Úhome_keyr	   )r   r   Úint)r   s   "r   r   r   Z   s"   € ÷ Gñ G¤(¬3¥-ð G¼3ñ Gr   c                ó²   € ^ RI Hp \        ;_uu_ 4        \        P	                  T ;'       g    V! 4       ^ 4      uuRRR4       #   + '       g   i     R# ; i)zCThe current (or ``home_key``'s) profile's live-endpoint generation.rD   N)r=   r;   r>   rF   r$   )rJ   r;   s   & r   Úlive_cdp_generationrM   Z   s5   € å0ß	Ö	Ü ×$Ñ$ X×%BÐ%B±Ó1BÀAÓF÷ 
×	×	Ó	ús   •%AÁA	c                ó$   € V ^8„  d   QhR\         /# r7   r
   )r   s   "r   r   r   a   s   € ÷ 	!ñ 	!”Sñ 	!r   c                 ó¶   € ^ RI Hp HpHp V! 4       '       d"   V ! 4       ;'       g    / P	                  R4      pMV! R4      pT;'       g    RP                  4       # )a  ``BROWSER_CDP_URL`` from this profile's secret scope. A routed profile (multiplex, or a scope
bound for another home) reads only its own ``.env``: ``os.environ`` holds the launch profile's
value. Single-profile reads fall through to ``os.environ`` as before (``get_secret``).)Úcurrent_secret_scopeÚ
get_secretÚserves_routed_profileÚBROWSER_CDP_URLr   )r<   rP   rQ   rR   r$   r   )rP   rQ   rR   Úvalues       r   Úenv_cdp_urlrU   a   sP   € ÷ [ÑZÙ×ÒÙ%Ó'×-Ð-¨2×2Ñ2Ð3DÓE‰áÐ,Ó-ˆØ�KˆK�R×ÑÓ Ð r   c                ó$   € V ^8„  d   QhR\         /# r7   r
   )r   s   "r   r   r   m   s   € ÷ 
@ñ 
@œsñ 
@r   c                 óˆ   € \        4       ;'       g    \        4       p T ;'       g    \        4       P                  RRR R4      # )a¾  Return the *configured* CDP override without any network I/O.

Precedence: this profile's live ``/browser connect``, then its ``BROWSER_CDP_URL`` (:func:`env_cdp_url`),
then ``browser.cdp_url``. Is-it-configured
gates (check_fns, ``_is_local_mode`` / ``_is_local_backend``, ``hermes doctor``) MUST use this, not
:func:`_get_cdp_override`: its 10s HTTP discovery against a stale ``cdp_url`` would stall every startup's
schema build with no error.
r   r   c                 óH   € \        T ;'       g    R 4      P                  4       # )r   )r   r   )Úvs   &r   Ú<lambda>Ú'_get_cdp_override_raw.<locals>.<lambda>w   s   € Ì3ÈqÏwÈwÐTVË<×K]ÑK]ÔK_r   zbrowser.cdp_url from config)r@   rU   r   Ú_browser_cfg)Úenv_overrides    r   Ú_get_cdp_override_rawr^   m   s9   € ô %Ó&×7Ð7¬+«-€LØ×Ðœ7›9×1Ñ1°)¸RÑA_Ða~ÓÐr   c                ó$   € V ^8„  d   QhR\         /# r7   r
   )r   s   "r   r   r   z   s   € ÷ Rñ Rœ3ñ Rr   c                 óT   € \        4       p \        4       ;p'       d   \        V4      # R# )uÍ   Resolved CDP URL override, or "" (skips cloud AND local launch).

May perform HTTP ``/json/version`` discovery â€” only call on paths about to *connect*; pure gates must use
:func:`_get_cdp_override_raw`.
r   )r   r^   r5   )r+   r,   s     r   Ú_get_cdp_overridera   z   s)   € ô ‹)€CÜ1FÓ1HÐ*H¨#Ö*HÔ  Ó%ÐQÈrÐQr   c                óF   € V ^8„  d   QhR\         \        \        3,          /# r7   )Útupler   Úfloat)r   s   "r   r   r   „   s   € ÷ ?ñ ?¤5¬¬e¨Õ#4ñ ?r   c                 ó  € \        4       p ^ RIHpHpHp YrT ^ RIHp V! 4       p\        V\        4      '       d   VP                  R/ 4      M/ p\        V\        4      '       g   WE3# \        VP                  R4      ;'       g    T4      p	W“9   d   T	pMV P                  P                  RV	4       VP                  R4      p
 V
e   \        V
4      MTpV^ 8:  d   TpYE3#   \        \        3 d    Tp Li ; i  \          d    Y3u # i ; i)zgRead ``browser.dialog_policy`` + ``browser.dialog_timeout_s``; supervisor defaults when absent/invalid.)ÚDEFAULT_DIALOG_POLICYÚDEFAULT_DIALOG_TIMEOUT_SÚ_VALID_POLICIES)Úread_raw_configÚbrowserÚdialog_policyz/Invalid browser.dialog_policy=%r; using defaultÚdialog_timeout_s)r   Ú tools.browser_supervisor_dialogsrf   rg   rh   Úhermes_cli.configri   Ú
isinstanceÚdictr$   r   r(   Údebugrd   Ú	TypeErrorÚ
ValueErrorr'   )r+   rf   rg   rh   ÚpolicyÚ	timeout_sri   ÚcfgÚbrowser_cfgÚ	candidateÚtimeout_raws              r   Ú_get_dialog_policy_configrz   „   s  € ä
‹)€CçqÑqØ-ˆIð?Ý5ÙÓˆÜ0:¸3Ä×0EÒ0E�c—g‘g˜i¨Ô,È2ˆÜ˜+¤t×,Ò,ØÐ$Ð$Ü˜Ÿ™¨Ó8×QÐQÐ<QÓRˆ	ØÔ'Ø‰Fà�J‰J×ÑÐNÐPYÔZØ!—o‘oÐ&8Ó9ˆð	1Ø.9Ò.Eœ˜kÔ*ÐKcˆIØ˜AŒ~Ø4�	ð Ð Ð øô œ:Ð&ô 	1Ø0ŠIð	1ûô ô ?Ø$Ð>Ò>ð?úsB   ˜AC9 Á(C9 Â=C9 ÃC  ÃC9 Ã C6Ã3C9 Ã5C6Ã6C9 Ã9D
Ä	D
c                ó(   € V ^8„  d   QhR\         RR/# ©r   Útask_idr	   Nr
   )r   s   "r   r   r   ¡   s   € ÷ cñ c¤Cð c¨Dñ cr   c                ó  € \        4       p\        4       pV'       gq   VP                  ;_uu_ 4        VP                  P	                  V / 4      pRRR4       \        XP	                  R4      ;'       g    R4      pV'       d   \        V4      pV'       g   R#  ^ RIHp \        4       w  rgVP                  WWgR7       R#   + '       g   i     Ly; i  \         d(   pTP                  P                  RY4        Rp?R# Rp?ii ; i)uÂ  Start a CDP supervisor for ``task_id`` if an endpoint is reachable.

Idempotent (``get_or_start`` skips an existing ``(task_id, cdp_url)`` and restarts on URL change), so safe on
every navigate / ``/browser connect``. URL precedence: the CDP override, then the session's own ``cdp_url``
(cloud providers, e.g. Browserbase). Swallows all errors â€” a failed attach must not break the session;
snapshots just lack ``pending_dialogs`` / ``frame_tree``.
Nr   r   ©ÚSUPERVISOR_REGISTRY)r}   r   rk   rl   z8CDP supervisor attach for task=%s failed (non-fatal): %s)r   ra   Ú_cleanup_lockÚ_active_sessionsr$   r   r5   Útools.browser_supervisorr€   rz   Úget_or_startr'   r(   rq   )	r}   r+   r   Úsession_infoÚmayber€   rt   ru   r3   s	   &        r   Ú_ensure_cdp_supervisorr‡   ¡   sÌ   € ô ‹)€CÜÓ!€GßØ××ÓØ×/Ñ/×3Ñ3°G¸RÓ@ˆL÷ ä�L×$Ñ$ YÓ/×5Ð5°2Ó6ˆßÜ+¨EÓ2ˆGßÙðcÝ@Ü5Ó7ÑˆØ×(Ñ(°ÐY_Ð(Ö|÷ ×ûô ô cØ�
‰
×ÑÐSÐU\×bÒbûðcús#   ±B?Â%C Â?C	ÃDÃC?Ã?Dc                ó(   € V ^8„  d   QhR\         RR/# r|   r
   )r   s   "r   r   r   »   s   € ÷ gñ g¤#ð g¨$ñ gr   c                ó°   €  ^ RI Hp VP                  V 4       R#   \         d0   p\	        4       P
                  P                  RY4        Rp?R# Rp?ii ; i)zGStop the CDP supervisor for ``task_id`` if one exists. No-op otherwise.r   z6CDP supervisor stop for task=%s failed (non-fatal): %sN)rƒ   r€   Ústopr'   r   r(   rq   )r}   r€   r3   s   &  r   Ú_stop_cdp_supervisorr‹   »   sH   € ðgÝ@Ø× Ñ  Ö)øÜô gÜ‹	×Ñ×ÑÐWÐY`×fÒfûðgús   ‚ ›A¦$AÁAc                ó¬   € V ^8„  d   Qh/ ^ \         9   d   \        \        \        3,          ;R&   ^\         9   d   \        \        \        3,          ;R&   # )r   r?   rF   )Ú__conditional_annotations__rp   r   rK   )r   s   "r   r   r      sH   € ÷ Wñ W÷j %Ò $””cœ3�h•Ñ $ñkW÷l 'Ò &”4œœS˜•>Ñ &òmWr   )N)r�   Ú__doc__Ú
contextlibÚosÚ	threadingÚtypingr   r   Úagent.proxy_bypassr   Útools.browser_tool_originr   r   r5   r?   ÚLockr>   r@   rH   rF   rM   rU   r^   ra   rz   r‡   r‹   r   )r�   s   @r   Ú<module>r–      s{   øðöWó Û 	Û ß "å 6Ý >õ#ðP #%€Ó $Ø —~’~Ó'Ð õ:õ	Cð %'Ð Ó &÷Gõ	!õ
@õRõ?õ:c÷4gr   