Ë
    ãß²j<  ã                  óR  — d Z ddlm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mZmZmZ ddlmZmZ  ej$                  d«      Zdd„Zdd	„Z ed
dh«      Zdd„ZdZdZdZ eeeeh«      ZeZdZdZdZ de › d�Z!dZ"e	 G d„ d«      «       Z#e	 G d„ d«      «       Z$ G d„ d«      Z%y)uT  Dialog capture + response half of the CDP supervisor.

Two capture paths feed one ``PendingDialog`` queue: native ``Page.javascriptDialogOpening``
events (answered with ``Page.handleJavaScriptDialog``), and the injected *dialog bridge* â€”
a page script rewriting alert/confirm/prompt into a sync XHR to a magic host we intercept
via the CDP ``Fetch`` domain and answer with ``Fetch.fulfillRequest``. The bridge works on
Browserbase (whose CDP proxy auto-dismisses native dialogs) because the native dialog never fires.
``DialogSupervisionMixin`` relies on state ``CDPSupervisor.__init__`` sets.
é    )ÚannotationsN)Ú	dataclass)ÚAnyÚCallableÚDictÚOptional)Úparse_qsÚurlparseztools.browser_supervisorc                ó"   — ddl m}  || d¬«      S )zARedact page-originated text before exposing supervisor snapshots.r   )Úredact_sensitive_textT)Úforce)Úagent.redactr   )Úvaluer   s     úE/home/ubuntu/.hermes/hermes-agent/tools/browser_supervisor_dialogs.pyÚ_redact_supervisor_textr      s   € å2á  ¨dÔ3Ð3ó    c                ó4   — t        | «      |dz  kD  r| | d S | S )zTCap a ring buffer at ``keep`` entries once it overflows to 2x (slack reduces churn).é   N)Úlen)ÚeventsÚkeeps     r   Ú
_trim_ringr   !   s$   € ä  ›[¨4°!©8Ò3ˆ6�4�%�&ˆ>Ð?¸Ð?r   ÚmessageÚdefault_promptc           
     ó|   — |D �ci c],  }||t         v rt        t        | |«      «      nt        | |«      “Œ. c}S c c}w )zDSnapshot dict of ``keys`` with page-originated text fields redacted.)Ú_REDACTED_FIELDSr   Úgetattr)ÚobjÚkeysÚks      r   Ú_dialog_dictr!   )   s<   € àosÖtÐjkˆA¸1Ô@PÑ;PÔ&¤w¨s°A£Ô7ÔV]Ð^aÐcdÓVeÑeÒtÐtùÒts   …19Úmust_respondÚauto_dismissÚauto_acceptg     Àr@é   zhermes-dialog-bridge.invalidzhttp://z/*a¡  
(() => {
  if (window.__hermesDialogBridgeInstalled) return;
  window.__hermesDialogBridgeInstalled = true;
  const ENDPOINT = "http://hermes-dialog-bridge.invalid/";
  function ask(kind, message, defaultPrompt) {
    try {
      const xhr = new XMLHttpRequest();
      const params = new URLSearchParams({
        kind: String(kind || ""),
        message: String(message == null ? "" : message),
        default_prompt: String(defaultPrompt == null ? "" : defaultPrompt),
      });
      xhr.open("GET", ENDPOINT + "?" + params.toString(), false);  // sync
      xhr.send(null);
      if (xhr.status !== 200) return null;
      let parsed;
      try { parsed = JSON.parse(xhr.responseText || ""); } catch (e) { return null; }
      if (kind === "alert") return undefined;
      if (kind === "confirm") return Boolean(parsed && parsed.accept);
      if (kind === "prompt") {
        if (!parsed || !parsed.accept) return null;
        return parsed.prompt_text == null ? "" : String(parsed.prompt_text);
      }
      return null;
    } catch (e) {
      return null;
    }
  }
  window.alert   = function(message) { ask("alert",   message, ""); };
  window.confirm = function(message) {
    const r = ask("confirm", message, "");
    return r === null ? false : Boolean(r);
  };
  window.prompt  = function(message, def) {
    const r = ask("prompt", message, def == null ? "" : def);
    return r === null ? null : String(r);
  };
})();
c                  ór   — e Zd ZU dZded<   ded<   ded<   ded<   ded<   ded	<   d
Zded<   d
Zded<   dd„Zy
)ÚPendingDialogz3A JS dialog currently open on some frame's session.ÚstrÚidÚtyper   r   ÚfloatÚ	opened_atÚcdp_session_idNúOptional[str]Úframe_idÚbridge_request_idc                ó   — t        | d«      S )N)r)   r*   r   r   r,   r/   ©r!   ©Úselfs    r   Úto_dictzPendingDialog.to_dict|   s   € Ü˜DÐ"fÓgÐgr   ©ÚreturnúDict[str, Any])Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__r/   r0   r5   © r   r   r'   r'   n   sA   … á=àƒGØ
ƒIØƒLØÓØÓØÓØ"€HˆmÓ"à'+Ð�}Ó+ôhr   r'   c                  ód   — e Zd ZU dZded<   ded<   ded<   ded<   ded<   ded	<   d
Zded<   dd„Zy
)ÚDialogRecordzOA dialog that was opened and then handled (kept briefly in ``recent_dialogs``).r(   r)   r*   r   r+   r,   Ú	closed_atÚ	closed_byNr.   r/   c                ó   — t        | d«      S )N©r)   r*   r   r,   rA   rB   r/   r2   r3   s    r   r5   zDialogRecord.to_dictŒ   s   € Ü˜DÐ"nÓoÐor   r6   )r9   r:   r;   r<   r=   r/   r5   r>   r   r   r@   r@   €   s5   … áYàƒGØ
ƒIØƒLØÓØÓØƒNØ"€HˆmÓ"ôpr   r@   c                  ó¤   — e Zd ZU dZ	 	 	 	 	 	 dd„Zdd„Zdd„Zdd„Zddœ	 	 	 	 	 dd„Zdd	„Z	dd
„Z
dd„Zdd„Zdd„Zdd„Zdd„ZeeedœZded<   y)ÚDialogSupervisionMixinzJDialog event handling for ``CDPSupervisor`` (all methods run on its loop).c             ƒ  ó¨   K  — 	 | j                  ||||¬«      ƒ d{  –—†  y7 Œ# t        $ r"}t        j                  d|||«       Y d}~yd}~ww xY w­w)zABest-effort CDP call: failures are logged at debug and swallowed.©Ú
session_idÚtimeoutNz%s failed (%s): %s)Ú_cdpÚ	ExceptionÚloggerÚdebug)r4   ÚmethodÚparamsrI   rJ   ÚwhatÚes          r   Ú
_cdp_quietz!DialogSupervisionMixin._cdp_quiet“   sM   è ø€ ð	@Ø—)‘)˜F F°zÈ7�)ÓS×SÒSùÜò 	@Ü�L‰LÐ-¨v°t¸Q×?Ñ?ûð	@üs6   ‚A„$ œ"�$ ¡A¢$ ¤	A­A
ÁAÁ
AÁAc              ƒ  óÜ   K  — |xs ddd }dt         ddœdd|› �fd	t        d
dœgddœdd|› �fdt         ddœdd|› �ff}|D ]%  \  }}}}| j                  |||||¬«      ƒ d{  –—†  Œ' y7 Œ­w)aJ  Install the dialog-bridge init script + Fetch interceptor on a session. Idempotent at
        the CDP level (Chromium de-dupes identical add-script calls; Fetch.enable replaces prior
        patterns); the final Runtime.evaluate injects into the already-loaded document so
        existing pages pick up the override on reconnect.Ú Né   z%Page.addScriptToEvaluateOnNewDocumentT)ÚsourceÚrunImmediatelyç      @zdialog bridge sid=zFetch.enableÚRequest)Ú
urlPatternÚrequestStageF)ÚpatternsÚhandleAuthRequestszRuntime.evaluate)Ú
expressionÚreturnByValueç      @zdialog bridge inject sid=©rI   rJ   rQ   )Ú_DIALOG_BRIDGE_SCRIPTÚDIALOG_BRIDGE_URL_PATTERNrS   )r4   rI   ÚsidÚstepsrO   rP   rJ   rQ   s           r   Ú_install_dialog_bridgez-DialogSupervisionMixin._install_dialog_bridge›   sÅ   è ø€ ð
 Ò˜R  "Ð%ˆà4ÔAVÐjnÑ6oØÐ& s eÐ,ð.àÔ:SÐenÑ+oÐ*pØ49ñ;Ø<?ÐCUÐVYÐUZÐA[ð]àÔ0EÐX\Ñ!]ØÐ-¨c¨UÐ3ð5ð
ˆð .3ò 	eÑ)ˆF�F˜G TØ—/‘/ &¨&¸ZÐQXÐ_c�/Ód×dÑdñ	eØdús   ‚A A,Á"A*Á#A,c           	   ƒ  óþ   K  — | j                  t        |j                  d«      xs d«      t        |j                  d«      xs d«      t        |j                  d«      xs d«      ||j                  d«      ¬«       y ­w)Nr*   rU   r   ÚdefaultPromptÚframeId)r*   r   r   rI   r/   )Ú_admit_dialogr(   Úget)r4   rP   rI   s      r   Ú_on_dialog_openingz)DialogSupervisionMixin._on_dialog_opening®   sl   è ø€ Ø×ÑÜ�V—Z‘Z Ó'Ò-¨2Ó.¼¸F¿J¹JÀyÓ<QÒ<WÐUWÓ8XÜ˜vŸz™z¨/Ó:Ò@¸bÓAÈjÐci×cmÑcmÐnwÓcxð 	õ 	
ùs   ‚A;A=c           
   ƒ  ó:  K  — t        |j                  di «      j                  d«      xs d«      }|j                  d«      }|syt        |vr!| j                  dd|i|dd¬	«      ƒ d{  –—†  yt	        t        |«      j                  «      j                  «       D ��ci c]  \  }}||d
   “Œ }}}| j                  |j                  d«      xs d|j                  dd«      |j                  dd«      ||j                  d«      t        |«      ¬«       y7 Œªc c}}w ­w)uã   Bridge XHR captured mid-flight â€” materialize as a pending dialog. The page's JS
        thread is blocked on the XHR until we Fetch.fulfillRequest (agent or watchdog);
        requests for other hosts are forwarded unchanged.ÚrequestÚurlrU   Ú	requestIdNzFetch.continueRequestra   Úpassthroughrb   r   ÚkindÚalertr   r   rj   )r*   r   r   rI   r/   r0   )	r(   rl   ÚDIALOG_BRIDGE_HOSTrS   r	   r
   ÚqueryÚitemsrk   )r4   rP   rI   rp   Ú
request_idr    ÚvÚqs           r   Ú_on_fetch_pausedz'DialogSupervisionMixin._on_fetch_paused´   s  è ø€ ô �&—*‘*˜Y¨Ó+×/Ñ/°Ó6Ò<¸"Ó=ˆØ—Z‘Z Ó,ˆ
ÙØÜ SÑ(Ø—/‘/Ð"9¸KÈÐ;TØ-7ÀÈ=ð "ó Z÷ Zð ZàÜ!)¬(°3«-×*=Ñ*=Ó!>×!DÑ!DÓ!F×G™˜˜AˆQ��!‘‰WÐGˆÑGØ×ÑØ—‘�v“Ò) '°1·5±5¸ÀBÓ3GÐXY×X]ÑX]Ð^nÐprÓXsØ!¨F¯J©J°yÓ,AÔUXÐYcÓUdð 	õ 	
ð	Zúó Hùs%   ‚A&DÁ(DÁ)4DÂDÂ-A'DÄDN)r0   c          
     óØ  ‡ ‡— ‰ xj                   dz  c_         t        d‰ j                   › �|||t        j                  «       |xs ‰ j                  xs d||¬«      Št        dt
        d|fij                  ‰ j                  «      }|�U‰ j                  5  ‰ j                  ‰d«       ddd«       t        j                  ‰ j                  ‰|d	   |d   ¬
«      «       y‰ j                  5  ‰‰ j                  ‰j                  <   ddd«       t        j                  «       j!                  ‰ j"                  ˆˆ fd„«      ‰ j$                  ‰j                  <   y# 1 sw Y   Œ¯xY w# 1 sw Y   Œ_xY w)zîCreate the dialog and apply the policy: auto-respond, or queue + arm the watchdog.
        Auto policies archive FIRST (tagged ``auto_policy``) so the ``closed`` event that
        follows our own response isn't re-archived as ``remote``.é   zd-rU   )r)   r*   r   r   r,   r-   r/   r0   )FrU   TNÚauto_policyr   ©ÚacceptÚprompt_textc                 ó`   •— t        j                  ‰j                  ‰ j                  «      «      S ©N)ÚasyncioÚcreate_taskÚ_dialog_timeout_expiredr)   )Údialogr4   s   €€r   ú<lambda>z6DialogSupervisionMixin._admit_dialog.<locals>.<lambda>Ý   s!   ø€ ”G×'Ñ'¨×(DÑ(DÀVÇYÁYÓ(OÓP€ r   )Ú_dialog_seqr'   ÚtimeÚ_page_session_idÚDIALOG_POLICY_AUTO_DISMISSÚDIALOG_POLICY_AUTO_ACCEPTrl   Údialog_policyÚ_state_lockÚ_archive_dialog_lockedr„   r…   Ú_respond_quietÚ_pending_dialogsr)   Úget_running_loopÚ
call_laterÚdialog_timeout_sÚ_dialog_watchdogs)	r4   r*   r   r   rI   r/   r0   Úautor‡   s	   `       @r   rk   z$DialogSupervisionMixin._admit_dialogÆ   sT  ù€ ð
 	×Ò˜AÑÕÜØ�D×$Ñ$Ð%Ð&¨T¸7ÐSaÜ—i‘i“k°*Ò2[À×@UÑ@UÒ2[ÐY[ØÐ1Bô
ˆô
 +¨KÔ9RÐUYÐ[iÐTjÐk×oÑoØ×Ñó
ˆð ÐØ×!Ñ!ñ CØ×+Ñ+¨F°MÔB÷Cä×Ñ × 3Ñ 3°FÀ4ÈÁ7ÐX\Ð]^ÑX_Ð 3Ó `ÔaØØ×Ññ 	6Ø/5ˆD×!Ñ! &§)¡)Ñ,÷	6ä,3×,DÑ,DÓ,F×,QÑ,QØ×!Ñ!ÜPó-
ˆ×Ñ˜vŸy™yÒ)÷Cð Cú÷	6ð 	6ús   ÂEÃ(E ÅEÅ E)c          	   ƒ  ó   K  — |j                   xs d}|j                  r³t        j                  t	        |«      |j
                  |j                  dk(  r|xs dnddœ«      j                  «       }| j                  d|j                  dddd	œd
dd	œgt        j                  |«      j                  «       dœ|dd|j
                  › �¬«      ƒ d{  –—†  yd|i}|�|j                  dk(  r||d<   | j                  d||d¬«      ƒ d{  –—†  y7 Œ=7 Œ­w)u¿   Bridge-fulfill for XHR-captured dialogs (swallows failures so the page
        unblocks), else native CDP â€” ``promptText`` only for prompt dialogs when
        given; raises on CDP failure.NÚpromptrU   )r€   Ú	dialog_idr�   zFetch.fulfillRequestéÈ   zContent-Typezapplication/json)Únamer   zAccess-Control-Allow-OriginÚ*)rq   ÚresponseCodeÚresponseHeadersÚbodyrY   zbridge fulfill rb   r€   Ú
promptTextzPage.handleJavaScriptDialogrH   )r-   r0   ÚjsonÚdumpsÚboolr)   r*   ÚencoderS   Úbase64Ú	b64encodeÚdecoderK   )r4   r‡   r€   r�   rI   r    rP   s          r   Ú_respondzDialogSupervisionMixin._respondâ   s(  è ø€ ð ×*Ñ*Ò2¨dˆ
Ø×#Ò#Ü—:‘:¬¨f«ÀFÇIÁIØEKÇ[Á[ÐT\ÒE\¨{Ò/@¹bÐbdñfó gßgmÑgmÓgoð à—/‘/Ø&Ø$×6Ñ6ÈØ.<ÐGYÑ%ZØ.KÐVYÑ%Zð%\ä×)Ñ)¨$Ó/×6Ñ6Ó8ñ:ð &¨s¸?È6Ï9É9È+Ð9Vð "ó ÷ ð ð Ø"*¨FÐ!3ˆØÐ" v§{¡{°hÒ'>Ø#.ˆF�<Ñ Ø�i‰iÐ5°vÈ*Ð^aˆiÓb×bÑbðøð 	cús$   ‚C
DÃD
Ã7DÄDÄDÄDc             ƒ  ó¸   K  — 	 | j                  |||¬«      ƒ d{  –—†  y7 Œ# t        $ r+}t        j                  d|j                  |«       Y d}~yd}~ww xY w­w)zWAuto-policy / watchdog response (already archived by the caller); failures logged only.r   Nzauto response failed for %s: %s)r©   rL   rM   rN   r)   )r4   r‡   r€   r�   rR   s        r   r‘   z%DialogSupervisionMixin._respond_quietø   sM   è ø€ ð	JØ—-‘- ¨vÀ;�-ÓO×OÒOùÜò 	JÜ�L‰LÐ:¸F¿I¹IÀq×IÑIûð	Jüs6   ‚A„# ›!œ#  A¡# £	A¬!AÁAÁAÁAc             ƒ  óÄ   K  — 	 | j                  |||¬«      ƒ d{  –—†  | j                  |j                  d«       y7 Œ!# | j                  |j                  d«       w xY w­w)u£   Agent response path. The dialog is retired regardless of outcome â€” a CDP
        error usually means it already closed (browser auto-dismissed after navigation).r   NÚagent)r©   Ú_retire_dialogr)   )r4   r‡   r€   r�   s       r   Ú_handle_dialog_cdpz)DialogSupervisionMixin._handle_dialog_cdpÿ   sR   è ø€ ð	4Ø—-‘- ¨vÀ;�-ÓO×OÐOà×Ñ §	¡	¨7Õ3ð Pùà×Ñ §	¡	¨7Õ3üs%   ‚A „? ›=œ?  A ½? ¿AÁA c              ƒ  óX  K  — | j                   5  | j                  j                  |«      }d d d «       €y t        j	                  d| j
                  ||j                  | j                  «       | j                  |d«       | j                  |dd ¬«      ƒ d {  –—†  y # 1 sw Y   ŒrxY w7 Œ­w)NzBCDP supervisor %s: dialog %s (%s) auto-dismissed after %ss timeoutÚwatchdogFr   )
r�   r’   rl   rM   ÚwarningÚtask_idr*   r•   r­   r‘   )r4   rš   r‡   s      r   r†   z.DialogSupervisionMixin._dialog_timeout_expired  sœ   è ø€ Ø×Ññ 	:Ø×*Ñ*×.Ñ.¨yÓ9ˆF÷	:àˆ>ØÜ�‰Ð[Ø—|‘| Y°·±¸T×=RÑ=Rô	Tð 	×Ñ˜I zÔ2Ø×!Ñ! &°ÀDÐ!ÓI×IÑI÷	:ð 	:úð 	Jús(   ‚B*�B«A+B*ÂB(ÂB*ÂB%Â!B*c                ó  — | j                   5  | j                  j                  |d«      }|�| j                  ||«       ddd«       | j                  j                  |d«      }|�|j                  «        yy# 1 sw Y   Œ9xY w)zRRemove a pending dialog (archiving it with ``closed_by``) and cancel its watchdog.N)r�   r’   Úpopr�   r–   Úcancel)r4   rš   rB   r‡   Úhandles        r   r­   z%DialogSupervisionMixin._retire_dialog  s|   € à×Ññ 	?Ø×*Ñ*×.Ñ.¨y¸$Ó?ˆFØÐ!Ø×+Ñ+¨F°IÔ>÷	?ð ×'Ñ'×+Ñ+¨I°tÓ<ˆØÐØ�M‰M�Oð ÷	?ð 	?ús   �1A6Á6A?c           	     óö   — t        |j                  |j                  |j                  |j                  t        j
                  «       ||j                  ¬«      }t        g | j                  ¢|‘t        «      | _        y)zNMove a pending dialog to the recent_dialogs ring buffer. Must hold state_lock.rD   N)
r@   r)   r*   r   r,   rŠ   r/   r   Ú_recent_dialogsÚRECENT_DIALOGS_MAX)r4   r‡   rB   Úrecords       r   r�   z-DialogSupervisionMixin._archive_dialog_locked  s]   € ä §¡°·±ÀfÇnÁnÐ`f×`pÑ`pÜ(,¯	©	«¸yÐSY×SbÑSbôdˆä)Ð*I¨D×,@Ñ,@Ð*IÀ&Ð*IÔK]Ó^ˆÕr   c              ƒ  óÔ   ‡K  — | j                   5  t        ˆfd„| j                  j                  «       D «       d «      }d d d «       r| j	                  |d«       y y # 1 sw Y   ŒxY w­w)Nc              3  ól   •K  — | ]+  }|j                   ‰k(  r|j                  €|j                  –— Œ- y ­wrƒ   )r-   r0   r)   )Ú.0ÚdrI   s     €r   ú	<genexpr>z;DialogSupervisionMixin._on_dialog_closed.<locals>.<genexpr>)  s7   øè ø€ ò a qØ!"×!1Ñ!1°ZÒ!?ÀA×DWÑDWÐD_ð  Ÿd�dñ aùs   ƒ14Úremote)r�   Únextr’   Úvaluesr­   )r4   rP   rI   Ú	candidates     ` r   Ú_on_dialog_closedz(DialogSupervisionMixin._on_dialog_closed$  so   øè ø€ ð ×Ññ 	hÜó a¨D×,AÑ,A×,HÑ,HÓ,Jô aØbfóhˆI÷	hñ Ø×Ñ 	¨8Õ4ð ÷	hð 	hüs   ƒA(�.A¾A(ÁA%Á!A()zPage.javascriptDialogOpeningzPage.javascriptDialogClosedzFetch.requestPausedzDict[str, Callable[..., Any]]ÚEVENT_HANDLERS)rO   r(   rP   r8   rI   r.   rJ   r+   rQ   r(   r7   ÚNone)rI   r(   r7   rÆ   )rP   r8   rI   r.   r7   rÆ   )r*   r(   r   r(   r   r(   rI   r.   r/   r.   r0   r.   r7   rÆ   )r‡   r'   r€   r¤   r�   r.   r7   rÆ   )r‡   r'   r€   r¤   r�   r(   r7   rÆ   )rš   r(   r7   rÆ   )rš   r(   rB   r(   r7   rÆ   )r‡   r'   rB   r(   r7   rÆ   )r9   r:   r;   r<   rS   rg   rm   r{   rk   r©   r‘   r®   r†   r­   r�   rÄ   rÅ   r=   r>   r   r   rF   rF   �   s›   … ÙTð@Ø"'ð@Ø/2ð@Ø7;ó@óeó&
ó
ð& SWñ
Ø -ð
ØBOð
Ø[_ó
ó8có,Jó4ó	Jóó_ó5ð );Ø'8Ø/ñ5€NÐ1ô r   rF   )r   r(   r7   r(   )r   Úlistr   Úintr7   rÇ   )r   r   r   Útupler7   r8   )&r<   Ú
__future__r   r„   r¦   r¢   ÚloggingrŠ   Údataclassesr   Útypingr   r   r   r   Úurllib.parser	   r
   Ú	getLoggerrM   r   r   Ú	frozensetr   r!   ÚDIALOG_POLICY_MUST_RESPONDrŒ   r�   Ú_VALID_POLICIESÚDEFAULT_DIALOG_POLICYÚDEFAULT_DIALOG_TIMEOUT_Sr¹   ru   rd   rc   r'   r@   rF   r>   r   r   ú<module>rÕ      s	  ðñõ #ã Û Û Û Û Ý !ß 0Ó 0ß +ð 
ˆ×	Ñ	Ð5Ó	6€ó4ó@ñ
 ˜iÐ)9Ð:Ó;Ð óuð
 ,Ð Ø+Ð Ø)Ð ÙØÐ!;Ð=VÐWó€ð 3Ð Ø Ð ð Ð ð 4Ð Ø%Ð&8Ð%9¸Ð<Ð ð'Ð ðT ÷hð hó ðhð" ÷pð pó ðp÷cò cr   