+
    „WÝjU  ã                  óþ  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t^ RI
t^ RItRt]P                  ! R4      t]P                  ! R4      tRt^tR R ltR	 R
 ltR R ltR R ltRRRRR]R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" R# 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#R0 R1 lt$R2 R3 lt%R4 R5 lt&R6 R7 lt'R8]!R9]!R:]"R;]"R<]#R=]#R]#/t(R> R? lt)R@ RA lt*R# )Buz  ``hermes peer`` â€” bot-to-bot DMs across machines/gateways.

A *peer* is another Hermes gateway running the ``api_server`` platform; its stock
API is the transport (no new server surface). ``dm`` resolves the remote canonical
"Bot Chat" session (creating it when missing) and runs ONE synchronous turn â€” the
cross-machine twin of ``hermes -p <bot> chat --in ~ -c "Bot Chat"``. ``run``/``status``
/``stop`` do the same turn through the async Runs API. Peer labels/URLs live in
config.yaml (``bot_peers``); the key lives in ``~/.hermes/.env`` as
``HERMES_PEER_<NAME>_KEY``. ``<peer>/<profile>`` targets the ``/p/<profile>/`` mirror.
)ÚannotationsNzBot Chatz^[a-z0-9][a-z0-9_-]{0,63}$z ^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$iX  c               ó    € V ^8„  d   QhRRRR/# ©é   ÚnameÚstrÚreturn© )Úformats   "ÚOC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\subcommands\peer.pyÚ__annotate__r       s   € ÷ ?ñ ?˜ð ? ñ ?ó    c                óJ   € R V P                  4       P                  RR4       R2# )ÚHERMES_PEER_Ú-Ú_Ú_KEY)ÚupperÚreplace)r   s   &r   Ú_peer_key_envr       s%   € Ø˜$Ÿ*™*›,×.Ñ.¨s°CÓ8Ð9¸Ð>Ð>r   c               ó   € V ^8„  d   QhRR/# )r   r   Údictr	   )r
   s   "r   r   r   $   s   € ÷ 4ñ 4�Tñ 4r   c                 ó†   € ^ RI Hp  V ! 4       ;'       g    / pVP                  R4      p\        V\        4      '       d   V# / # )é    )Úload_configÚ	bot_peers)Úhermes_cli.configr   ÚgetÚ
isinstancer   )r   ÚcfgÚpeerss      r   Ú_load_peersr!   $   s9   € Ý-á
‹-×
Ð
˜2€CØ�G‰G�KÓ €EÜ˜u¤d×+Ò+ˆ5Ð3°Ð3r   c               ó    € V ^8„  d   QhRRRR/# )r   r    r   r   ÚNoner	   )r
   s   "r   r   r   ,   s   € ÷ ñ �tð  ñ r   c                óP   € ^ RI HpHp V! 4       ;'       g    / pWR&   V! V4       R# )r   )r   Úsave_configr   N)r   r   r%   )r    r   r%   r   s   &   r   Ú_save_peersr&   ,   s$   € ß:á
‹-×
Ð
˜2€CØˆÑÙ�Ör   c               ó    € V ^8„  d   QhRRRR/# r   r	   )r
   s   "r   r   r   4   s   € ÷ 
8ñ 
8�sð 
8˜sñ 
8r   c                óø   € \        V 4      p ^ RIHp V! VR4      ;'       g    RP                  4       #   \         d;    ^ RIpTP                  P                  T4      ;'       g    RP                  4       u # i ; i)zHThe peer's API key: profile-scoped secret store first, raw env fallback.)Ú
get_secretÚ N)r   Úagent.secret_scoper)   ÚstripÚ	ExceptionÚosÚenvironr   )r   Úenv_namer)   r.   s   &   r   Ú_peer_secretr1   4   sh   € ä˜TÓ"€Hð8Ý1á˜8 RÓ(×.Ð.¨B×5Ñ5Ó7Ð7øÜô 8Ûà—
‘
—‘˜xÓ(×.Ð.¨B×5Ñ5Ó7Ò7ð8ús   �4 £4 ´0A9Á%A9Á8A9ÚmethodÚGETÚbodyÚtimeoutÚheadersc               ó4   € V ^8„  d   QhRRRRRRRRRRR	R
RR/# )r   Úurlr   Úkeyr2   r4   zdict | Noner5   Úintr6   zdict[str, str] | Noner   r   r	   )r
   s   "r   r   r   A   sD   € ÷ ñ Ø	ðØðØ#&ðØ6Aðàðà,AðàMQñr   c               óN  € ^ RI Hp Ve&   \        P                  ! V4      P	                  R4      MRpRRV 2RRRR	/pV'       d   VP                  V4       \        P                  P                  WW(R
7      p	V! W”R7      ;_uu_ 4       p
V
P                  4       P                  RR4      pRRR4        \        P                  ! X4      p\        T\        4      '       g   \        R4      hT#   + '       g   i     LJ; i  \         d   p\        RXR,           24      ThRp?ii ; i)r   )Úopen_credentialed_urlNúutf-8ÚAuthorizationzBearer zContent-Typezapplication/jsonz
User-Agentzhermes-peer-dm)Údatar2   r6   )r5   r   z!Peer returned non-JSON response: ºNéÈ   Nz(Peer returned a non-object JSON response)Úhermes_cli.urllib_securityr<   ÚjsonÚdumpsÚencodeÚupdateÚurllibÚrequestÚRequestÚreadÚdecodeÚloadsÚ
ValueErrorÚRuntimeErrorr   r   )r8   r9   r2   r4   r5   r6   r<   r?   Úrequest_headersÚreqÚrespÚpayloadÚparsedÚexcs   &&$$$$        r   Ú_requestrU   A   s  € õ AØ/3Ò/?Œ4�:Š:�dÓ×"Ñ" 7Ô+ÀT€Dà˜7 3 %˜¨.Ð:LØÐ&ð(€O÷ Ø×Ñ˜wÔ'Ü
�.‰.×
 Ñ
  ¸Ð
 Ó
X€Cñ
 
˜s×	4Õ	4¸Ø—)‘)“+×$Ñ$ W¨iÓ8ˆ÷ 
5ðYÜ—’˜GÓ$ˆô �fœd×#Ò#ÜÐEÓFÐFØ€M÷ 
5×	4ûô ô YÜÐ>¸wÀt½}¸oÐNÓOÐUXÐXûðYús$   Â!C+Â2C> Ã+C;	Ã>D$Ä	DÄD$c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úpeerr   Úprofileú
str | Noner   r   r	   )r
   s   "r   r   r   [   s!   € ÷ ñ �Dð  :ð °#ñ r   c                óÈ   € \        V P                  R 4      ;'       g    R4      P                  R4      pV'       d'   V R\        P                  P                  VRR7       2# V# )r8   r*   Ú/z/p/©Úsafe)r   r   ÚrstriprG   ÚparseÚquote)rW   rX   r8   s   && r   Ú	_base_urlra   [   sU   € Ü
ˆd�h‰h�u‹o×#Ð# Ó
$×
+Ñ
+¨CÓ
0€Cßà��cœ&Ÿ,™,×,Ñ,¨W¸2Ð,Ó>Ð?Ð@Ð@Ø€Jr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úbaser   r9   r   rY   r	   )r
   s   "r   r   r   c   s!   € ÷ ñ ˜ð  3ð ¨:ñ r   c                ó²  € \         P                  P                  R^ÈR\        R^/4      p\	        V  RV 2V4      pVP                  R4      ;'       g    .  F}  p\        V\        4      '       g   K  VP                  R4      ;'       g    RP                  4       \        8X  g   KO  \        VP                  R4      ;'       g    R4      ;'       g    Ru # 	  R# )	a  The remote canonical Bot Chat's session id, or None.

Bot Mode always HIDES canonical chats, so the plain listing (which
excludes hidden sessions) misses an existing Bot Chat and the caller
would try to create a duplicate that the peer's UNIQUE(title) guard
rejects (issue #91583). Newer peers support an exact-title lookup with
``include_hidden=1``; older peers ignore the unknown query params and
return the ordinary visible listing, so this single request degrades
to exactly the previous behavior against them.
ÚlimitÚtitleÚinclude_hiddenz/api/sessions?r?   r*   ÚidN)
rG   r_   Ú	urlencodeÚBOT_CHAT_TITLErU   r   r   r   r,   r   )rc   r9   ÚqueryÚlistingÚsessions   &&   r   Ú_find_bot_chatrn   c   s´   € ô �L‰L×"Ñ" G¨S°'¼>ÐK[Ð]^Ð#_Ó`€EÜ˜$˜˜~¨e¨WÐ5°sÓ;€GØ—;‘;˜vÓ&×,Ð,¨"Ò,ˆÜ�gœt×$Ô$¨'¯+©+°gÓ*>×*DÐ*DÀ"×)KÑ)KÓ)MÔQ_Ö)_Ü�w—{‘{ 4Ó(×.Ð.¨BÓ/×7Ð7°4Ò7ñ -ñ r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   rc   r   r9   r   r	   )r
   s   "r   r   r   v   s!   € ÷ ñ ˜3ð  Sð ¨Sñ r   c           	     óV  € \        W4      pV'       d   V#  \        V  R 2VRR\        RR/R7      p\        TP                  R4      \        4      '       d   TP                  R4      MTp\        TP                  R4      ;'       g    TP                  R4      ;'       g    R4      pT'       g   \        R4      hT#   \        P                  P
                   dO   p\        T4      pTP                  R8X  d-   RTP                  4       9   d   \        R\         RT R	24      Thh R
p?ii ; i)z/api/sessionsÚPOSTrf   ÚsourceÚbot_peer_dm©r2   r4   i�  zPeer already has a 'zq' session but it is hidden and the peer's gateway is too old to expose hidden sessions to this lookup (HTTP 400: zk). Update the peer's hermes-agent, or unhide the session there: PATCH /api/sessions/<id> {"hidden": false}.Nrm   rh   Ú
session_idr*   z5Peer did not return a session id for the new Bot Chat)rn   rU   rj   rG   ÚerrorÚ	HTTPErrorÚ_http_error_detailÚcodeÚlowerrN   r   r   r   r   )rc   r9   ÚexistingÚcreatedrT   Údetailrm   ru   s   &&      r   Ú_ensure_bot_chatr~   v   s   € Ü˜dÓ(€HßØˆðÜØˆf�MÐ" C°Øœ>¨8°]ÐCôEˆô  )3°7·;±;¸yÓ3IÌ4×(PÒ(Pˆg�k‰k˜)Ô$ÐV]€GÜ�W—[‘[ Ó&×IÐI¨'¯+©+°lÓ*C×IÐIÀrÓJ€JßÜÐRÓSÐSØÐøô# �<‰<×!Ñ!ô Ü# CÓ(ˆØ�8‰8�sŒ?˜w¨&¯,©,«.Ô8ô Ø&¤~Ð&6ð 7à$˜Xð &QðRóSð Y\ð	\ð
 	ûðús   —B; Â;D(ÃA	D#Ä#D(c               ó    € V ^8„  d   QhRRRR/# )r   Útargetr   r   ztuple[str, str | None]r	   )r
   s   "r   r   r   ’   s   € ÷ 
ñ 
˜#ð 
Ð"8ñ 
r   c                óB  € T ;'       g    RP                  4       pVP                  R4      w  r#pVP                  4       pVP                  4       ;'       g    RpV'       g   \        R4      hV'       d+   \        P	                  V4      '       g   \        RV: 24      hW$3# )u<   ``<peer>`` or ``<peer>/<profile>`` â†’ (peer, profile|None).r*   r[   Nz8Peer name required (hermes peer dm <peer>[/<agent>] ...)zInvalid agent/profile name: )r,   Ú	partitionrM   Ú_PROFILE_REÚmatch)r€   ÚrawrW   r   rX   s   &    r   Ú_parse_targetr†   ’   s„   € à�<ˆ<�R×
Ñ
Ó
 €CØ—}‘} SÓ)Ñ€DˆWØ�:‰:‹<€DØ�m‰m‹o×%Ð% €GßÜÐSÓTÐTß”{×(Ñ(¨×1Ò1ÜÐ7¸±{ÐCÓDÐDØˆ=Ðr   c               ó    € V ^8„  d   QhRRRR/# )r   rT   zurllib.error.HTTPErrorr   r   r	   )r
   s   "r   r   r   Ÿ   s   € ÷ ñ Ð2ð °sñ r   c                ó@  €  V P                  4       P                  R R4      p\        P                  ! V4      p\	        V\
        4      '       d"   VP                  R/ 4      P                  R4      MRpT;'       g
    VR,          #   \         d    \        T 4      u # i ; i)r=   r   rv   ÚmessageNr@   )	rJ   rK   rC   rL   r   r   r   r-   r   )rT   r4   rS   r‰   s   &   r   rx   rx   Ÿ   s�   € ðØ�x‰x‹z× Ñ  ¨)Ó4ˆÜ—’˜DÓ!ˆÜ<FÀvÌt×<TÒ<T�&—*‘*˜W bÓ)×-Ñ-¨iÔ8ÐZ^ˆØ×$Ð$˜$˜t�*Ð$øÜô Ü�3‹xŠðús   ‚A7B Á:	B ÂBÂBc               ó    € V ^8„  d   QhRRRR/# )r   r€   r   r   z!tuple[str, str | None, dict, str]r	   )r
   s   "r   r   r   ©   s   € ÷ )ñ ) ð )Ð)Jñ )r   c           
     ó0  € \        V 4      w  r\        4       P                  V4      p\        V\        4      '       d   VP                  R4      '       g   \        RV R24      h\        V4      pV'       g   \        RV RV R\        V4       R24      hWW43# )z@Resolve a registered target to ``(name, profile, config, key)``.r8   úNo peer named 'z'. Run: hermes peer listzNo API key for peer 'z'. Set it: hermes peer add z! --url <url> --key <key> (or add ú=<key> to ~/.hermes/.env))	r†   r!   r   r   r   ÚLookupErrorr1   ÚPermissionErrorr   )r€   Ú	peer_namerX   rW   r9   s   &    r   Ú_resolve_peer_targetr‘   ©   s    € ä& vÓ.Ñ€IÜ‹=×Ñ˜YÓ'€DÜ�dœD×!Ò!¨¯©°%¯ªÜ˜O¨I¨;Ð6NÐOÓPÐPÜ
�yÓ
!€CßÜØ# I ;Ð.IÈ)Èð U/Ü/<¸YÓ/GÐ.HÐHaðcódð 	dð ˜tÐ(Ð(r   c               ó   € V ^8„  d   QhRR/# )r   r   r   r	   )r
   s   "r   r   r   ·   s   € ÷ ñ  ñ r   c                ó   € \        V R R4      ;'       g    RP                  4       pV'       gQ   \        P                  P	                  4       '       g-   \        P                  P                  4       P                  4       pV# )r‰   Nr*   )Úgetattrr,   ÚsysÚstdinÚisattyrJ   )Úargsr‰   s   & r   Ú_message_from_argsr™   ·   sT   € Ü�t˜Y¨Ó-×3Ð3°×:Ñ:Ó<€Gßœ3Ÿ9™9×+Ñ+×-Ò-Ü—)‘)—.‘.Ó"×(Ñ(Ó*ˆØ€Nr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   rc   r   r9   r   zbool | Noner	   )r
   s   "r   r   r   ¾   s!   € ÷ )ñ )˜sð )¨ð )°ñ )r   c                óL  €  \        V  R2V4      pTP                  R4      p\        T\        4      '       g   R# TP                  R4      p\        T\        4      '       d   TP                  R4      '       g   R# \        TP                  R4      4      #   \         d     R# i ; i)zGReturn durable support, or None when an older peer cannot advertise it.z/v1/capabilitiesNÚfeaturesÚruns_idempotencyÚ	supportedÚdurable)rU   r-   r   r   r   Úbool)rc   r9   Úcapabilitiesrœ   Úcontracts   &&   r   Ú_peer_run_durabilityr£   ¾   s’   € ðÜ 4 &Ð(8Ð 9¸3Ó?ˆð ×Ñ 
Ó+€HÜ�h¤×%Ò%ÙØ�|‰|Ð.Ó/€HÜ�h¤×%Ò%¨X¯\©\¸+×-FÒ-FÙÜ�—‘˜YÓ'Ó(Ð(øô ô Úðús   ‚B ÂB#Â"B#c               ó$   € V ^8„  d   QhRRRRRR/# )r   r�   r   rT   r-   r   r:   r	   )r
   s   "r   r   r   Í   s!   € ÷ ñ ˜Sð  yð °Sñ r   c                ó  € \        V\        P                  P                  4      '       d<   \	        V4      p\        RV  RVP                   RV 2\        P                  R7       ^# \        RV  RV 2\        P                  R7       ^# )zJPrint a peer HTTP rejection or transport failure to stderr; always exit 1.úPeer 'z' rejected the request (HTTP z): ©ÚfilezCould not reach peer 'ú': )	r   rG   rv   rw   rx   Úprintry   r•   Ústderr)r�   rT   r}   s   && r   Ú_peer_failurer¬   Í   sr   € ä�#”v—|‘|×-Ñ-×.Ò.Ü# CÓ(ˆÜ��y�kÐ!>¸s¿x¹x¸jÈÈFÈ8ÐTÜ—:‘:õ	ñ ô 	Ð& y k°°S°EÐ:ÄÇÁÕLÙr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   rR   r   Ú
text_linesz	list[str]r   r:   r	   )r
   s   "r   r   r   Ø   s!   € ÷ ñ ˜ð ¨9ð ¸ñ r   c                ó–   € \        V R R4      '       d"   \        \        P                  ! V4      4       ^ # V F  p\        V4       K  	  ^ # )rC   F)r”   rª   rC   rD   )r˜   rR   r®   Úlines   &&& r   Ú_emitr±   Ø   s=   € Üˆt�V˜U×#Ò#ÜŒd�jŠj˜Ó!Ô"ñ ó ˆDÜ�$ŽKñ ár   c               ó   € V ^8„  d   QhRR/# ©r   r   r:   r	   )r
   s   "r   r   r   á   s   € ÷ ñ �sñ r   c                óx  € V P                   ;'       g    R P                  4       P                  4       p\        P	                  V4      '       g#   \        RV: R2\        P                  R7       ^# V P                  ;'       g    R P                  4       pVP                  4       P                  R4      '       g   \        R\        P                  R7       ^# \        4       pRVP                  R4      /\        V RR 4      '       d   RV P                  P                  4       /M/ CW1&   \        V4       \        V RR 4      ;'       g    R P                  4       pV'       d9   ^ R	IHp V! \#        V4      V4       \        R
V RV R\#        V4       R24       ^ # \        R
V RV RV RV R\#        V4       R24       ^ # )r*   zInvalid peer name: z" (lowercase, digits, -, _; max 64)r§   zJPeer --url must be an http(s) gateway base URL, e.g. http://spark.lan:8377r8   r[   Únoter9   )Úsave_env_valuer¦   z	' saved (u   ) â€” key stored as z in ~/.hermes/.envuJ   ). No key given â€” set the peer's API_SERVER_KEY with:
  hermes peer add z --url z --key <key>
  (or add r�   )zhttp://zhttps://)r   r,   rz   Ú_PEER_NAME_REr„   rª   r•   r«   r8   Ú
startswithr!   r^   r”   rµ   r&   r   r¶   r   )r˜   r   r8   r    r9   r¶   s   &     r   Ú	_peer_addr¹   á   sˆ  € Ø�I‰I�OˆO˜×"Ñ"Ó$×*Ñ*Ó,€DÜ×Ñ˜t×$Ò$ÜÐ# D¡8Ð+MÐNÔUX×U_ÑU_Õ`ÙØ�8‰8�>ˆ>�r×
 Ñ
 Ó
"€CØ�9‰9‹;×!Ñ!Ð"9×:Ò:ÜÐZÔad×akÑakÕlÙÜ‹M€EØ˜#Ÿ*™* S›/ÐpÌWÐUYÐ[aÐce×MfÒMf¨v°t·y±y·±Ó7HÑ.IÐlnÐp€E�KÜ�ÔÜ�4˜ Ó#×)Ð) r×
0Ñ
0Ó
2€Cß
Ý4á”} TÓ*¨CÔ0Ü��t�f˜I c UÐ*>¼}ÈTÓ?RÐ>SÐSeÐfÔgñ ô	 	Ø�T�F˜) C 5ð )!Ø!%  g¨c¨Uð 3Ü& tÓ,Ð-Ð-FðHô	Iñ r   c               ó   € V ^8„  d   QhRR/# r³   r	   )r
   s   "r   r   r   û   s   € ÷ 	ñ 	˜#ñ 	r   c                ó:  € V P                   ;'       g    R P                  4       P                  4       p\        4       pW9  d"   \	        RV R2\
        P                  R7       ^# VP                  V4       \        V4       \	        RV R\        V4       R24       ^ # )r*   rŒ   z'.r§   r¦   z' removed (its z6 entry in .env is kept; delete it manually if unused).)
r   r,   rz   r!   rª   r•   r«   Úpopr&   r   )r˜   r   r    s   &  r   Ú_peer_remover½   û   s~   € Ø�I‰I�OˆO˜×"Ñ"Ó$×*Ñ*Ó,€DÜ‹M€EØÔÜ� ˜v RÐ(¬s¯z©zÕ:ÙØ	‡I�Iˆd„OÜ�ÔÜ	ˆF�4�&˜¬°dÓ(;Ð'<Ð<rÐ
sÔtÙr   c               ó   € V ^8„  d   QhRR/# r³   r	   )r
   s   "r   r   r     s   € ÷ 
ñ 
˜ñ 
r   c           
     óž  € \        4       pV'       g   \        R 4       ^ # \        V4       Fž  p\        W,          \        4      '       d	   W,          M/ p\        V4      '       d   RMR\        V4       R2pVP                  R4      '       d   RVP                  R4       2MRp\        V RVP                  RR	4       R
V RV 24       K   	  ^ # )zbNo peers registered. Add one: hermes peer add <name> --url http://host:port --key <API_SERVER_KEY>zkey setzNO KEY (z unset)rµ   u    â€” r*   Ú	r8   Ú?z	[Ú])r!   rª   Úsortedr   r   r1   r   r   )r˜   r    r   ÚentryÚhas_keyrµ   s   &     r   Ú
_peer_listrÆ     sµ   € Ü‹M€EßÜÐrÔsÙÜ�u–ˆÜ)¨%­+´t×<Ò<�–À"ˆÜ+¨D×1Ò1‘)¸Ä-ÐPTÓBUÐAVÐV]Ð7^ˆØ.3¯i©i¸×.?Ò.?��u—y‘y Ó(Ð)Ñ*ÀRˆÜ���b˜Ÿ™ 5¨#Ó.Ð/¨s°7°)¸1¸T¸FÐCÖDñ	 ñ
 r   c               ó0   € V ^8„  d   QhRRRRRRRRRRRR	/# )
r   Úactionr   r�   rX   rY   rc   r9   r   r:   r	   )r
   s   "r   r   r     s9   € ÷ ñ  ð °ð ¸jð ÐPSð ØðØ"ñr   c           	     ó~  € \        V RR4      ;'       g    RP                  4       pV'       g   \        R\        P                  R7       ^# VR8H  p \        V R\        P                  P                  VRR7       2V'       d   R	MR,           YW'       d   R
MRV'       d   / MRR7      p\        T RR4      '       d(   \        \        P                   ! RTRT/TC4      4       ^ # \        T RTP#                  RR4       24       T'       g,   TP#                  R4      '       d   \        TR,          4       ^ # T'       g:   TP#                  R4      '       d#   \        TR,          \        P                  R7       ^ #   \        P                  P                  \        \        \        3 d   p	\        Y)4      u Rp	?	# Rp	?	ii ; i)z-``status`` / ``stop`` on an asynchronous run.Úrun_idNr*   zRun ID required.r§   Ústopz	/v1/runs/r\   z/stoprq   r3   rt   rC   FrW   rX   ú: ÚstatusÚunknownÚoutputrv   )r”   r,   rª   r•   r«   rU   rG   r_   r`   rv   ÚURLErrorÚTimeoutErrorÚOSErrorrN   r¬   rC   rD   r   )
r˜   rÈ   r�   rX   rc   r9   rÊ   rË   ÚresultrT   s
   &&&&&&    r   Ú_peer_run_ctlrÔ     s\  € ô �d˜H dÓ+×1Ð1¨r×8Ñ8Ó:€FßÜÐ ¤s§z¡zÕ2ÙØ�VÑ€Dð-ÜØˆf�IœfŸl™l×0Ñ0°¸bÐ0ÓAÐBÐC×RVÁwÐ\^Õ_Ø¦$™¨E¿d¹ÈôNˆô
 ˆt�V˜U×#Ò#ÜŒd�jŠj˜& )¨Y¸ÐJÀ6ÐJÓKÔLÙÜ	ˆVˆH�B�v—z‘z (¨IÓ6Ð7Ð
8Ô9ß�F—J‘J˜x×(Ò(Üˆf�XÕÔñ ÷ �f—j‘j ×)Ò)Üˆf�W�o¤C§J¡JÕ/Ùøô �L‰L×!Ñ!¤<´¼,ÐGô -Ü˜YÓ,Õ,ûð-ús%   ÁAE8 Â	E8 Å8/F<Æ'
F7Æ1F<Æ7F<c               ó$   € V ^8„  d   QhRRRRRR/# )r   r‰   r   Úmessage_keyr   r   r	   )r
   s   "r   r   r   -  s!   € ÷ ñ ˜ð ¨Sð ¸dñ r   c               ó:   € ^ RI Hp W/VCpV! 4       pVe   WTR&   V# )z]Request body for one turn. ``author`` is added only when a dispatcher set HERMES_TURN_AUTHOR.)Úturn_author_from_envÚauthor)Úagent.turn_authorrØ   )r‰   rÖ   ÚextrarØ   r4   rÙ   s   &$,   r   Ú
_turn_bodyrÜ   -  s,   € å6àÐ* EÐ*€DÙ!Ó#€FØÒØˆX‰Ø€Kr   c               ó0   € V ^8„  d   QhRRRRRRRRRRRR	/# ©
r   r‰   r   r�   rX   rY   rc   r9   r   r:   r	   )r
   s   "r   r   r   8  s8   € ÷ 0ñ 0˜Sð 0¨Sð 0¸:ð 0ÈSð 0ÐWZð 0Ð_bñ 0r   c                óö  € \        V R R4      ;'       g#    R\        P                  ! 4       P                   2P	                  4       pV'       d.   \        V4      ^ÿ8”  g   \        P                  ! RV4      '       d   \        R\        P                  R7       ^#  \        WE4      RJd   \        R\        P                  R7       \        WE4      p\        V R2VR	\        VR
VR7      RV/R7      p\-        TP/                  R4      ;'       g    R4      p
T
'       g"   \        RT R2\        P                  R7       ^# RTRTRTRT
RTP/                  R4      ;'       g    RR TR\1        TP/                  RR4      4      /pTR,          '       d   RMRp\3        YT
 RTR,           T 2RT 2RT 2.4      #   \        P                   P"                  \$        \&        \(        3 d   p	\+        Y)4      u Rp	?	# Rp	?	ii ; i)Úidempotency_keyNzpeer-z
[\r\n\x00]zBIdempotency key must be 1-255 characters without control newlines.r§   Tz‚Warning: this peer does not advertise restart-durable run replay; keep the run ID and avoid blind retries after a gateway restart.z/v1/runsrq   Úinput)rÖ   ru   zIdempotency-Key)r2   r4   r6   rÊ   r*   r¦   z' did not return a run ID.rW   rX   ru   rÍ   ÚstartedÚreplayedFz (replayed)rÌ   zsession_id: zidempotency_key: )r”   ÚuuidÚuuid4Úhexr,   ÚlenÚreÚsearchrª   r•   r«   r£   r~   rU   rÜ   rG   rv   rÐ   rÑ   rÒ   rN   r¬   r   r   r    r±   )r˜   r‰   r�   rX   rc   r9   rà   ru   rÓ   rT   rÊ   rR   Úreplays   &&&&&&       r   Ú	_peer_runrë   8  sÐ  € Ü˜tÐ%6¸Ó=×[Ð[À5ÌÏÊË×IYÑIYÐHZÐA[×bÑbÓd€Oßœs ?Ó3°cÔ9Ü�yŠy˜¨×8Ò8ÜÐRÔY\×YcÑYcÕdÙð-Ü Ó*°$Ó6Üð+ä14·±õ=ô & dÓ0ˆ
ÜØˆf�HÐ˜s¨6Ü˜G°ÀZÔPØ&¨Ð8ô:ˆô �—‘˜HÓ%×+Ð+¨Ó,€FßÜ��y�kÐ!;Ð<Ä3Ç:Á:ÕNÙà�	˜9 g¨|¸ZÈÐSYØ�&—*‘*˜XÓ&×3Ð3¨)Ð5FÈØ”D˜Ÿ™ J°Ó6Ó7ð9€Gð & j×1Ô1‰]°r€FÜ�Øˆ(�"�W˜XÕ&Ð'¨ xÐ0°LÀÀÐ2MØ
˜OÐ,Ð-ð!/ó 0ð 0øô �L‰L×!Ñ!¤<´¼,ÐGô -Ü˜YÓ,Õ,ûð-ús   ÂAF4 Æ4/G8Ç#
G3Ç-G8Ç3G8c               ó0   € V ^8„  d   QhRRRRRRRRRRRR	/# rÞ   r	   )r
   s   "r   r   r   Y  s8   € ÷ ,9ñ ,9˜Cð ,9¨Cð ,9¸*ð ,9ÈCð ,9ÐVYð ,9Ð^añ ,9r   c                óX  € R p \        WE4      p\        V R\        P                  P	                  VR R7       R2VR\        VRR7      \        R7      pTP#                  R4      R8X  dc   TP#                  R4      ;'       g    Tp	\%        T RTRTRT	RTP#                  R4      ;'       g    RRTP#                  R4      /RT RT	 R2.4      # TP#                  R4      p
\        T
\&        4      '       d%   \)        T
P#                  R4      ;'       g    R 4      MR p^ RIHp T! T4      '       d   R pRTRTRTP#                  R4      ;'       g    TRT/p\%        YT;'       g    R.4      #   \         d-   p\        RT R	T 2\        P                  R
7        Rp?^# Rp?i\        P                  P                  \        \        3 dc   pT'       dF   \        T\        4      '       d0   \        RT R\         RT R2\        P                  R
7        Rp?^# \!        Y(4      u Rp?# Rp?ii ; i)r*   z/api/sessions/r\   z/chatrq   r‰   )rÖ   )r2   r4   r5   r¦   r©   r§   Nz;' accepted the message but its turn is still running after z3s: the message is already in its Bot Chat (session zU) and will be answered there. The reply cannot come back on this call. Do NOT resend.Úobjectzhermes.session.chat.queuedru   rW   rX   rÍ   ÚqueuedÚdelivery_idzE' has its Bot Chat open, so the message went into that chat (session zP) and is answered there. The reply cannot come back on this call. Do NOT resend.Úcontent)Úis_intentional_silence_responseÚreplyz
(no reply))r~   rU   rG   r_   r`   rÜ   ÚDM_TIMEOUT_SrN   rª   r•   r«   rv   rÐ   rÑ   rÒ   r   r¬   r   r±   r   r   Úgateway.response_filtersrò   )r˜   r‰   r�   rX   rc   r9   ru   rÓ   rT   Ú	queued_inÚmsgró   rò   rR   s   &&&&&&        r   Ú_peer_dmrø   Y  s   € Ø€Jð-Ü% dÓ0ˆ
ÜØˆf�N¤6§<¡<×#5Ñ#5°jÀrÐ#5Ó#JÐ"KÈ5ÐQÐSVØ¤
¨7À	Ô JÔT`ôbˆð& ‡z�z�(ÓÐ;Ô;ð —J‘J˜|Ó,×:Ð:°
ˆ	Ü�T˜F I¨y¸'À<ÐQZØ$ f§j¡j°Ó&:×&FÐ&F¸hÈÐW]×WaÑWaÐboÓWpðrà˜y˜kÐ)nØ"˜Ð#sðuð vówð 	wð �*‰*�YÓ
€CÜ-7¸¼T×-BÒ-BŒC�—‘˜	Ó"×(Ð( bÔ)È€Eõ IÙ& u×-Ò-ØˆØ�y )¨WØ˜VŸZ™Z¨Ó5×CÐC¸ÀWÈeðU€Gä� ×!6Ð!6¨,Ð 7Ó8Ð8øôK ô Ü��y�k  S EÐ*´·±Õ<ÝûÜ�L‰L×!Ñ!¤<´Ð9ô -÷ œ* S¬,×7Ò7Ü�F˜9˜+Ð%`Ü!�NÐ"UÐV`ÐUað bhðhô —z‘zõ#õ Ü˜YÓ,Õ,ûð-ús7   „AE( Å(H)Å3!FÆ+H)ÇH)ÇAH$È
H$ÈH)È$H)ÚaddÚsetÚremoveÚrmÚlistÚlsc               ó   € V ^8„  d   QhRR/# r³   r	   )r
   s   "r   r   r   �  s   € ÷ Añ A�cñ Ar   c                ó   € \        V R R4      pV\        9   d   \        V,          ! V 4      # VR9  d   \        R\        P                  R7       ^#  \        V P                  4      w  r#rE\        YC4      pTR9   d   \        YY#Yu4      # \        T 4      pT'       g   \        R\        P                  R7       ^# TR8X  d   \        M\        p	T	! YY#Yu4      #   \         d0   p\        \        T4      \        P                  R7        Rp?^# Rp?i\        \        3 d0   p\        \        T4      \        P                  R7        Rp?^# Rp?ii ; i)Úpeer_actionNÚrunz,Unknown peer action. See: hermes peer --helpr§   z%Message required (argument or stdin).>   Údmr  rË   rÍ   >   rË   rÍ   )r”   Ú_REGISTRY_ACTIONSrª   r•   r«   r‘   r€   rM   r   rŽ   r�   ra   rÔ   r™   rë   rø   )
r˜   rÈ   r�   rX   rW   r9   rT   rc   r‰   Úhandlers
   &         r   Úcmd_peerr  �  s  € Ü�T˜=¨$Ó/€FØÔ"Ô"Ü  Ö(¨Ó.Ð.ØÐ4Ô4ÜÐ<Ä3Ç:Á:ÕNÙðÜ(<¸T¿[¹[Ó(IÑ%ˆ	˜Dô �TÓ#€DØÐ#Ô#Ü˜T¨9¸tÓIÐIÜ  Ó&€GßÜÐ5¼C¿J¹JÕGÙØ! Uœ?�i´€GÙ�4 )°dÓ@Ð@øô ô ÜŒc�#‹hœSŸZ™ZÕ(ÝûÜœÐ)ô ÜŒc�#‹hœSŸZ™ZÕ(Ýûðús*   ÁC ÃEÃ $D
Ä
EÄEÄ$EÅEc               ó   € V ^8„  d   QhRR/# )r   r   r#   r	   )r
   s   "r   r   r   §  s   € ÷ 5'ñ 5' Tñ 5'r   c                óL  a€ V P                  RRRR\        P                  R7      pVP                  RR7      oSP                  RR	.R
R7      pVP	                  RRR7       VP	                  RRRR7       VP	                  RRRR7       VP	                  RRRR7       SP                  RR.RR7       SP                  RR.RR7      pVP	                  RRR7       R  V3R! llpV! R"R#R$R%7       V! R&R'R$R%7       V! R(R)RR%7       V! R*R+RR%7       VP                  \        R,7       R-# ).z1Attach the ``peer`` subcommand to ``subparsers``.rW   z5Bot-to-bot DMs across machines (peer Hermes gateways)uv  Register other Hermes gateways as peers and message their agents. 'hermes peer dm <peer>[/<agent>] "..."' delivers into the remote agent's canonical Bot Chat over the peer's API server and prints the reply â€” the cross-machine twin of 'hermes -p <bot> chat'. The peer must run the api_server platform; its API_SERVER_KEY is stored locally as a credential in ~/.hermes/.env.uâ  Examples:
  hermes peer add spark --url http://spark.lan:8377 --key <API_SERVER_KEY>
  hermes peer list
  hermes peer dm spark "Message from ðŸ¤– dixie (@dixie): disk status?"
  hermes peer dm spark/researcher "..."   # named profile on a multiplexed peer
  hermes peer run spark --idempotency-key ticket-123 < long-task.txt
  hermes peer status spark run_abc123
  hermes peer stop spark run_abc123
  hermes peer remove spark

Exit codes: 0 ok, 1 delivery/peer error, 2 usage error.)ÚhelpÚdescriptionÚepilogÚformatter_classr  )Údestrù   rú   z#Register (or update) a peer gateway)Úaliasesr	  r   z/Peer name (lowercase slug, e.g. spark, homelab)©r	  z--urlTz1Peer gateway base URL, e.g. http://spark.lan:8377)Úrequiredr	  z--keyr*   z4The peer's API_SERVER_KEY (stored in ~/.hermes/.env)©Údefaultr	  z--notezOptional descriptionrý   rþ   zList registered peersrû   rü   zRemove a peerz	Peer namec               ó$   € V ^8„  d   QhRRRRRR/# )r   r   r   r	  rÊ   r    r	   )r
   s   "r   r   Ú'build_peer_parser.<locals>.__annotate__Ë  s&   € ÷ 
añ 
a�cð 
a ð 
a°ñ 
ar   c               ó  <€ SP                  WR 7      pVP                  RRR 7       V'       d   VP                  RRR 7       M0VP                  RRRRR	7       V R
8X  d   VP                  RRRR7       VP                  RRRRR7       R# )r  r€   z><peer> or <peer>/<agent> (named profile on a multiplexed peer)rÊ   z$Run ID returned by 'hermes peer run'r‰   rÁ   NzMessage text (or stdin))Únargsr  r	  r  z--idempotency-keyz)Stable retry key (generated when omitted)r  z--jsonÚ
store_trueFzEmit a JSON result)rÈ   r  r	  )Ú
add_parserÚadd_argument)r   r	  rÊ   ÚspÚpeer_subs   &&$ €r   Ú_remoteÚ"build_peer_parser.<locals>._remoteË  s†   ø€ Ø× Ñ  Ð Ó1ˆØ
�‰˜Ð'gˆÔhßØ�O‰O˜HÐ+QˆOÕRà�O‰O˜I¨S¸$ÐE^ˆOÔ_Ø�uŒ}Ø—‘Ø'°Ð<gð  ô ià
�‰˜¨¸uÐK_ˆÖ`r   r  z6Message an agent on a peer gateway and print its replyF)rÊ   r  z;Start a long peer turn asynchronously and return its run IDrÍ   z<Read the status and final output of an asynchronous peer runrË   z=Stop one asynchronous peer run without affecting another turn)ÚfuncN)r  ÚargparseÚRawDescriptionHelpFormatterÚadd_subparsersr  Úset_defaultsr  )Ú
subparsersÚparserÚadd_pÚrm_pr  r  s   &    @r   Úbuild_peer_parserr'  §  sU  ø€ à×"Ñ"ØÐLð@ð
Fô !×<Ñ<ð) #ó >€Fð* ×$Ñ$¨-Ð$Ó8€Hà×Ñ °¨wÐ=bÐÓc€EØ	×Ñ�vÐ$UÐÔVØ	×Ñ�w¨Ð4gÐÔhØ	×Ñ�w¨Ð1gÐÔhØ	×Ñ�x¨Ð2HÐÔIà×Ñ˜¨¨Ð5LÐÔMà×Ñ˜x°$°¸oÐÓN€DØ×Ñ�f ;ÐÔ/÷
að 
añ ˆDÐJÐSXÕYÙˆEÐPÐY^Õ_ÙˆHÐTÐ]aÕbÙˆFÐSÐ\`Õaà
×ÑœXÐÖ&r   )+Ú__doc__Ú
__future__r   r  rC   rè   r•   Úurllib.errorrG   Úurllib.parseÚurllib.requesträ   rj   Úcompiler·   rƒ   rô   ÚLIST_TIMEOUT_Sr   r!   r&   r1   rU   ra   rn   r~   r†   rx   r‘   r™   r£   r¬   r±   r¹   r½   rÆ   rÔ   rÜ   rë   rø   r  r  r'  r	   r   r   Ú<module>r/     s  ðñ	õ #ã Û Û 	Û 
Û Û Û Û à€Ø—
’
Ð8Ó9€Ø�jŠjÐ<Ó=€ð €Ø€õ?õ4õõ
8ðØ).ðØDHðà!ðàDH÷õ4õõ&õ8
õõ)õõ)õõõõ4	õ
õõ2õ0õB,9ð` 
ˆ9�e˜Y¨°,ÀÀlØ
ˆJ˜˜j¨$°
ð<Ð õ
A÷45'r   