Ë
    ãß²jG4  ã                  ó‚  — U d dl mZ d dlZd dlZd dlZd dlmZmZmZm	Z	m
Z
mZ d dlmZmZmZmZ d dlmZ d dlmZ d dlmZmZmZmZ d dlmZmZ d d	lmZmZm Z  d d
l!m"Z"  ejF                  e$«      Z%dZ&dZ'dZ(ejR                  ejT                  fejV                  ejT                  fejV                  ejT                  fejV                  ejT                  fejX                  ejZ                  fdœZ.de/d<   dZ0d„ Z1dd„Z2d d„Z3d!d„Z4d"d„Z5d#d„Z6d$d„Z7d%d„Z8d&d„Z9d'd„Z:d(d„Z;d)d„Z<ddddddœ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d*d„Z=y)+é    )ÚannotationsN)ÚAnyÚCallableÚDictÚListÚOptionalÚTuple)ÚActorÚSettleReasonÚTargetStateÚallowed)Úoperation_session_key)ÚRateLimited)ÚConnectionOperationÚDetachedOperationÚIllegalTransitionÚTarget)ÚKindÚrun_operation)Úcatalog_namesÚhosted_namesÚmisrouted_to_hosted_error)Ú
tool_errorg      ð?g      $@)ÚactiveÚfailedÚrevokedÚinactiveÚexpiredz$Dict[str, Tuple[TargetState, Actor]]Ú_ACCOUNT_OUTCOMEu  Settled once. connected â†’ use the app now; skipped â†’ the user chose Not now, do not connect it or route around it; not_connected â†’ ask the user what to do, never re-mint on your own. A later request from the USER for that same app is not a re-ask â€” run it.c                 ó   — ddl m}   | «       S )Nr   ©ÚConnectorClient)Útools.connectors.gateway.clientr"   r!   s    ú=/home/ubuntu/.hermes/hermes-agent/tools/connectors/managed.pyÚmanaged_clientr%   -   s   € Ý?áÓÐó    c                óD   ‡ — t        t        ‰ ||«      ˆ fd„t        ¬«      S )Nc                ó   •— t        ‰| «      S ©N)Ú_observe)Ú	operationÚclients    €r$   ú<lambda>zmanaged_kind.<locals>.<lambda>4   s   ø€ ÔS[Ð\bÐdmÓSn€ r&   )ÚprepareÚobserveÚnote)r   Ú_prepareÚNOTE)r,   ÚactionÚforces   `  r$   Úmanaged_kindr5   3   s   ø€ Üœ ¨°Ó7ÓAnÔuyÔzÐzr&   c           	     óº   — | j                  «       D �ci c]=  }t        |t        «      sŒt        |j	                  dd«      «      j                  «       |“Œ? c}S c c}w )z¦The toolkit list, by slug. Only the reconnect repair check reads it: it answers "is this app
    already connected" before any account exists for the watcher to read.Ú	connectorÚ )Úlist_connectorsÚ
isinstanceÚdictÚstrÚgetÚlower)r,   Úis     r$   Ú_status_by_slugr@   7   sL   € ð =C×<RÑ<RÓ<TÖl°qÔXbÐcdÔfjÕXkŒC�—‘�k 2Ó&Ó'×-Ñ-Ó/°Ñ2ÒlÐlùÒls
   “A©,Ac          	     óÖ  — ddl m} |sy | j                  |fd|i ||j                  ¬«      ¤Ž}|j	                  dg «      D �]$  }t        |j	                  d«      xs d«      j                  «       }|j                  |«      }	|	€ŒDt        |j	                  d	«      xs d«      }
t        |j	                  d
«      xs d«      }|j	                  d«      }|
dk(  rS|j                  |t        j                  |«       |j                  |t        j                  t        j                  |¬«       Œé|
dk(  rN|st        j                  d|«       |j                  |t        j                  ||j	                  d«      ||¬«       �Œ<|	j                   t        j"                  k(  r|j%                  |d|¬«       �Œo|	j                   t        j&                  k(  rh|j                  |t        j                  |«       |j                  |t        j"                  t        j                  |¬«       |j%                  |d|¬«       �Œô|j                  |t        j"                  t        j                  |¬«       �Œ' y)a  Mint links for ``names`` and apply the gateway's per-app answer to the operation. ``actor`` is
    the watcher on the first mint and the user on Try again. The operation id rides along so the
    vendor's done page can name it on the way back to the desktop.r   )Úreturn_to_argsNÚ
reinitiate)ÚopÚresultsr7   r8   ÚstatusÚstatus_reasonÚconnection_idr   )rH   Ú	initiatedzuconnector %s: the mint named no account, so the watcher cannot read it; only the card or the deadline can end the rowÚconnect_url)rJ   rH   Údetail)rJ   rK   ©rK   )r#   rB   ÚconnectionsÚop_idr=   r<   r>   ÚtargetÚ
transitionr   rI   Ú	connectedr
   Úbackend_watcherÚloggerÚwarningÚstater   Úrefreshr   )r,   r+   ÚnamesrC   ÚactorrB   ÚresponseÚentryÚnamerO   rF   rK   rH   s                r$   Úmintr\   =   s  € õ ?áØØ!ˆv×!Ñ! %Ñe°JÐeÁ.ÐT]×TcÑTcÔBdÑe€HØ—‘˜i¨Ó,ó aˆÜ�5—9‘9˜[Ó)Ò/¨RÓ0×6Ñ6Ó8ˆØ×!Ñ! $Ó'ˆØˆ>ØÜ�U—Y‘Y˜xÓ(Ò.¨BÓ/ˆÜ�U—Y‘Y˜Ó/Ò5°2Ó6ˆØŸ	™	 /Ó2ˆØ�XÒØ× Ñ  ¤{×'<Ñ'<¸eÔDØ× Ñ  ¤{×'<Ñ'<¼e×>SÑ>SÐcpÐ ÕqØ�{Ò"Ù Ü—‘ð  OØPTôVà× Ñ Ø”k×+Ñ+¨UØ!ŸI™I mÓ4ÀMØð !ö ð
 �\‰\œ[×/Ñ/Ò/à×Ñ˜d°¸VÐÖDØ�\‰\œ[×0Ñ0Ò0à× Ñ  ¤{×'<Ñ'<¸eÔDØ× Ñ  ¤{×'9Ñ'9¼5×;PÑ;PÐY_Ð Ô`Ø×Ñ˜d°¸VÐÖDð × Ñ  ¤{×'9Ñ'9¼5×;PÑ;PÐY_Ð Ö`ñ=ar&   c               ó  — |j                   r!t        j                  «       |j                  k  ry	 | j                  |j                   |¬«      S # t        $ r ‚ t
        $ r+}t        j                  d|j                  |«       Y d}~yd}~ww xY w)un  The one route the watcher reads: that target's own account row. ``None`` means "nothing to
    apply this tick" â€” no account to read, a rate-limit still in force, an account the gateway does
    not know yet (404 until the deadline), or a read that failed. A 429 is raised to the tick: its
    budget is the principal's, so it is not this one target's to wait out.N©Útimeoutz(connector account read failed for %s: %s)	rH   ÚtimeÚnext_read_atÚaccount_statusr   Ú	ExceptionrS   Údebugr[   )r,   rO   r_   Úexcs       r$   Ú_status_forrf   g   sw   € ð
 ×Ò¤4§9¡9£;°×1DÑ1DÒ#DØðØ×$Ñ$ V×%9Ñ%9À7Ð$ÓKÐKøÜò ØÜò Ü�‰Ð?ÀÇÁÈcÔRÜûðús   °A ÁB
Á!BÂB
c                ó  — t         j                  |«      }|€y|\  }}	 t        |j                  |j                  |«      €9| j                  |j                  t        j                  t        j                  «       | j                  |j                  |||xs |j                  ¬«       y# t        $ rQ | j                  st        |«      r‚ t        j!                  d|j                  ||j                  j"                  «       Y yw xY w)uŽ  Apply one account read to one target. The RPC thread can move the row while the read is in
    flight â€” a Skip resolves it, a Continue freezes the whole result â€” and the read then has no
    live row to move: it is dropped, not raised into the tool result (that would end the watch
    with the operation still open and no card to answer it). Any other refusal is a real
    contract violation.NrL   z,connector %s: %s read dropped, the row is %s)r   r=   r   ÚkindrU   rP   r[   r   rI   r
   rR   rK   r   ÚsettledÚ_liverS   rd   Úvalue)r+   rO   rF   ÚreasonÚoutcomeÚtorX   s          r$   Ú_apply_readro   w   sÐ   € ô ×"Ñ" 6Ó*€GØ€ØØ�I€BˆðnÜ�6—;‘; §¡¨bÓ1Ð9à× Ñ  §¡¬k×.CÑ.CÄU×EZÑEZÔ[Ø×Ñ˜VŸ[™[¨"¨e¸FÒ<SÀfÇmÁmÐÕTøÜò nØ× Ò ¤U¨6¤]ØÜ�‰ÐCÀVÇ[Á[ÐRXÐZ`×ZfÑZf×ZlÑZlÖmðnús   ŸBB' Â'ADÄ Dc                óZ   — | j                   t        j                  t        j                  fv S )z˜Only a live attempt (pending, initiated) can be advanced by a gateway read; a failed or
    expired link waits for the user, and a resolved row is done.)rU   r   ÚpendingrI   )rO   s    r$   rj   rj   Œ   s$   € ð �<‰<œK×/Ñ/´×1FÑ1FÐGÐGÐGr&   c                óL   — | j                   D ]  }t        |«      sŒ||_        Œ y)zZA 429 is per principal, not per account: every live target waits out the same Retry-After.N)Útargetsrj   ra   )r+   ÚuntilrO   s      r$   Ú_parkru   ’   s&   € à×#Ñ#ò (ˆÜ��=Ø"'ˆFÕñ(r&   c                óþ  — |j                   D ]¬  }|j                  st        |«      sŒt        t        t        t        |j                  «       «      «      }	 t        | ||¬«      }|€ŒYt        ||t        |j                  d«      xs d«      j!                  «       t        |j                  d«      xs d«      «       Œ® y# t        $ r6}t        |t        j                  «       |j                  z   «       Y d}~ yd}~ww xY w)z¨One account read per live target per tick, sequential: this is the only thread reading them.
    A 429 ends the tick: the next read would spend the same refused budget.r^   NrF   r8   ÚstatusReason)rs   ri   rj   ÚminÚ_MAX_READ_SECONDSÚmaxÚ_MIN_READ_SECONDSÚremaining_secondsrf   r   ru   r`   Úretry_afterro   r<   r=   r>   )r,   r+   rO   r_   Úrowre   s         r$   r*   r*   ™   sØ   € ð ×#Ñ#ò qˆà×Ò¤E¨&¤MØÜÔ'¬Ô->À	×@[Ñ@[Ó@]Ó)^Ó_ˆð	Ü˜f f°gÔ>ˆCð ˆ;ØÜ�I˜v¤s¨3¯7©7°8Ó+<Ò+BÀÓ'C×'IÑ'IÓ'KÌSÐQT×QXÑQXÐYgÓQhÒQnÐlnÓMoÕpñqøô ò 	Ü�)œTŸY™Y›[¨3¯?©?Ñ:Ô;Ýûð	ús   ÁB=Â=	C<Ã+C7Ã7C<c           	     ón  — | j                   D �cg c]-  }|j                  t        j                  k(  r|j                  s|‘Œ/ }}|sy t        «       }|D �cg c]  }|j                  |v sŒ|‘Œ }}|sy t        «       }|€y |D �cg c]  }|j                  |vsŒ|‘Œ }}|D ]B  }| j                  |j                  d t        j                  t        |j                  «      ¬«       ŒD |rBt        |«      t        | j                   «      k(  r | j                  t        j                  «       y y y c c}w c c}w c c}w )N)rJ   rX   rK   )rs   rU   r   r   rH   r   r[   r   rV   r
   rR   r   ÚlenÚsettler   Úall_resolved)r+   ÚtÚunmintedÚcatalogÚ
candidatesÚhostedÚ	misroutedrO   s           r$   Ú_mark_misroutedr‰   «   s%  € Ø$×,Ñ,ö J�aØ—7‘7œk×0Ñ0Ò0¸¿ºò ð J€Hð JáØÜ‹o€GØ%Ö;˜¨¯©°7Ò):’!Ð;€JÐ;ÙØÜ‹^€FØ€~ØØ&Ö?�q¨!¯&©&¸Ò*>’Ð?€IÐ?Øò IˆØ×Ñ˜&Ÿ+™+°4¼u×?TÑ?TÜ!:¸6¿;¹;Ó!Gð 	õ 	IðIñ ”S˜“^¤s¨9×+<Ñ+<Ó'=Ò=Ø×Ñœ×2Ñ2Õ3ð >€yùòJùò
 <ùò @s   �2D(ÁD-Á(D-ÂD2ÂD2c                ó   ‡ ‡‡— dˆˆ ˆfd„}|S )Nc                ó¨  •— | j                   D �cg c]  }|j                  ‘Œ }}‰dk(  r*t        ‰| |dt        j                  ¬«       t        | «       y ‰r*t        ‰| |dt        j                  ¬«       t        | «       y t        ‰«      }g }|D ]“  }|j                  |i «      j                  d«      r_| j                  |t        j                  t        j                  «       | j                  |t        j                  t        j                  «       Œƒ|j                  |«       Œ• t        ‰| |dt        j                  ¬«       t        | «       y c c}w )NÚconnectF)rC   rX   TrQ   )rs   r[   r\   r
   rR   r‰   r@   r=   rP   r   rI   rQ   Úappend)	r+   rƒ   rW   rF   Úrepairr[   r3   r,   r4   s	         €€€r$   r.   z_prepare.<locals>.prepareÀ   s  ø€ Ø!*×!2Ñ!2Ö3˜A�—“Ð3ˆÐ3Ø�YÒÜ�˜ E°eÄ5×CXÑCXÕYÜ˜IÔ&ØÙä�˜ E°dÄ%×BWÑBWÕXÜ˜IÔ&ØÜ  Ó(ˆØˆØò 	$ˆDØ�z‰z˜$ Ó#×'Ñ'¨Ô4Ø×$Ñ$ T¬;×+@Ñ+@Ä%×BWÑBWÔXØ×$Ñ$ T¬;×+@Ñ+@Ä%×BWÑBWÕXà—‘˜dÕ#ð	$ô 	ˆV�Y °4¼u×?TÑ?TÕUÜ˜	Õ"ùò' 4s   �E©r+   r   ÚreturnÚNone© )r,   r3   r4   r.   s   ``` r$   r1   r1   ¿   s   ú€ ÷#ð, €Nr&   c           
     ó   — t        |D �cg c]  }t        |d|«      ‘Œ c}|¬«      } t        | ||«      |«       |j                  d¬«      }t	        d„ |j
                  D «       «      rdnd|d<   d	|d
<   t        j                  |d¬«      S c c}w )Nr7   )Úsession_keyT)Ú	with_urlsc              3  óV   K  — | ]!  }|j                   t        j                  k(  –— Œ# y ­wr)   )rU   r   rI   )Ú.0rƒ   s     r$   ú	<genexpr>z"_no_card_result.<locals>.<genexpr>Ý   s    è ø€ Ò*gÐPQ¨1¯7©7´k×6KÑ6KÕ+KÑ*gùs   ‚')rI   ri   rF   zÀShow each connect_url to the user; they open it in a browser to authorize. Ask them to tell you when they are done, then check with action 'status'. Do not call connect again for the same app.r0   F©Úensure_ascii)r   r   r1   ÚresultÚanyrs   ÚjsonÚdumps)r,   r3   rW   r4   Ú
session_idÚnr+   Úpayloads           r$   Ú_no_card_resultr¢   Ù   s’   € Ü!È5Ö"QÀa¤6¨!¨[¸&Õ#AÒ"QÐ_iÔj€IØ#„HˆV�V˜UÓ# IÔ.Ø×Ñ¨ÐÓ.€GÜ'*Ñ*gÐU^×UfÑUfÔ*gÔ'g™Ðmv€GˆHÑð	kð ˆF�Oô �:‰:�g¨EÔ2Ð2ùò #Rs   ŠB)Úclient_factoryrŸ   Útool_call_idÚconnection_callbackÚconnectors_availablec          
     óÈ  — |� |«       st        d«      S 	  |xs t        «       }| dk(  rr|j                  «       }	|rFt        |«      }
|	D �cg c]0  }t	        |j                  dd«      «      j                  «       |
v sŒ/|‘Œ2 }	}t        j                  |	ddœd¬«      S |st        d	| › d
�«      S t        |j                  dd«      «      }t        |«      }|€t        || |||«      S t        |D �cg c]  }t        |d| «      ‘Œ c}t        || |«      ||t        |d¬«      S c c}w c c}w # t         $ r0}t"        j%                  d| |«       t        d|› d�«      cY d }~S d }~ww xY w)Nz-Connectors are not available in this session.rF   r7   r8   z~connected=false means calls to that connector will return CONNECTION_REQUIRED. Use action 'connect' to start an authorization.)Ú
connectorsÚhintFr™   ú'zm' requires 'connectors': the connector slugs to authorize (e.g. ["gmail"]). Use action 'status' to list them.r4   )r”   r¤   Útick_secondsr¥   Úwith_urls_in_resultz manage_connections %s failed: %sz&The connector gateway request failed: zG. If this persists, the user can manage connections in the Nous Portal.)r   r%   r9   Úsetr<   r=   r>   r�   rž   Úboolr   r¢   r   r   r5   ÚWATCH_TICK_SECONDSrc   rS   rd   )r3   r¨   Úargsr£   rŸ   r¤   r¥   r¦   r,   ÚitemsÚwantedr?   r4   r”   r    re   s                   r$   Úrun_managed_actionr³   å   s“  € ð Ð'Ñ0DÔ0FÜÐIÓJÐJð
Ø2�.Ò2¤NÓ5ˆØ�XÒØ×*Ñ*Ó,ˆEÙÜ˜Z›�Ø$)Ö[˜q¬S°·±°{ÀBÓ1GÓ-H×-NÑ-NÓ-PÐTZÒ-ZšÐ[�Ð[Ü—:‘:¨UðBñDàRWôYð Yñ ÜØ�F�8ð 4ð 4óð ô �T—X‘X˜g uÓ-Ó.ˆÜ+¨JÓ7ˆØÐ&Ü" 6¨6°:¸uÀkÓRÐRÜØ5?Ö@°ŒV�A�{ FÕ+Ò@Ü˜ ¨Ó/Ø#°,ÔM_Ø 3Èô	
ð 	
ùò \ùò Aøô
 ò 
Ü�‰Ð7¸ÀÔEÜØ4°S°Eð :Tð Tó
õ 	
ûð
úsS   –5D( Á0DÁ<DÂ D( ÂD( Â-6D( Ã$	D( Ã-D#ÄD( Ä
D( Ä(	E!Ä1%EÅE!ÅE!)r,   r   r3   r<   r4   r®   r�   r   )r,   r   r�   zDict[str, Dict[str, Any]])r,   r   r+   r   rW   ú	List[str]rC   r®   rX   r
   r�   r‘   )r,   r   rO   r   r_   Úfloatr�   zOptional[Dict[str, Any]])
r+   r   rO   r   rF   r<   rl   r<   r�   r‘   )rO   r   r�   r®   )r+   r   rt   rµ   r�   r‘   )r,   r   r+   r   r�   r‘   r�   )r,   r   r3   r<   r4   r®   r�   z%Callable[[ConnectionOperation], None])r,   r   r3   r<   rW   r´   r4   r®   rŸ   r<   r�   r<   )r3   r<   r¨   r´   r°   zDict[str, Any]r£   zOptional[Callable[[], Any]]rŸ   úOptional[str]r¤   r¶   r¥   z3Optional[Callable[[Dict[str, Any]], Optional[str]]]r¦   zOptional[Callable[[], bool]]r�   r<   )>Ú
__future__r   r�   Úloggingr`   Útypingr   r   r   r   r   r	   Útools.connectors.contractr
   r   r   r   Útools.connectors.gateway.configr   Útools.connectors.gateway.errorsr   Útools.connectors.operationr   r   r   r   Útools.connectors.runr   r   Útools.connectors.targetsr   r   r   Útools.registryr   Ú	getLoggerÚ__name__rS   r¯   r{   ry   rQ   rR   r   r   Úclockr   Ú__annotations__r2   r%   r5   r@   r\   rf   ro   rj   ru   r*   r‰   r1   r¢   r³   r’   r&   r$   ú<module>rÅ      sŒ  ðÞ "ã Û Û ß =× =ç OÓ OÝ AÝ 7ß hÓ hß 4ß [Ñ [Ý %à	ˆ×	Ñ	˜8Ó	$€ð Ð ð Ð ØÐ ð
 ×$Ñ$ e×&;Ñ&;Ð<Ø×!Ñ! 5×#8Ñ#8Ð9Ø×"Ñ" E×$9Ñ$9Ð:Ø×#Ñ# U×%:Ñ%:Ð;à×#Ñ# U§[¡[Ð1ñ:Ð Ð6ó ðRð òó{ómó'aóTó nó*Hó(óqó$4ó(ó4	3ð" 37Ø $Ø"&ØOSØ9=ñ+
Øð+
àð+
ð ð+
ð
 0ð+
ð ð+
ð  ð+
ð Mð+
ð 7ð+
ð 	ô+
r&   