+
    „WÝj�  ã                   óÔ  € R 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I	H	t	H
t
Ht ^ RIHt ^ RIHtHtHtHt ^ RIHtHtHtHtHt ^ RIHt ^ RIHt ^ RIHt ^ R	IH t  ^ R
I!H"t" ^ RI#H$t$H%t% ^ RI&H't'H(t(H)t)H*t*H+t+H,t,H-t-H.t.H/t/H0t0H1t1 ^ RI2H3t3H4t4H5t5H6t6H7t7 ^ RI8H9t9 ]Pt                  ! R4      t;]! 4       t<]! RR4      t=]! RR4      t>]! RR4      t?]! RR4      t@]! RR4      tA]! RR4      tB]! RR4      tC]! RR4      tD]! RR4      tERR/R R  lltFRƒR! R" lltG]<P‘                  R#4      RƒR$ R% ll4       tI]<P•                  R&4      R' R( l4       tK]<P•                  R)4      R* R+ l4       tL]<P•                  R,4      RƒR- R. ll4       tMR/ R0 ltN]<P‘                  R14      RƒR2 R3 ll4       tO]<P•                  R44      RƒR5 R6 ll4       tP]<P•                  R14      RƒR7 R8 ll4       tQR9 R: ltR]<P§                  R;4      RƒR< R= ll4       tT]<P«                  R>4      RƒR? R@ ll4       tV]<P•                  RA4      RƒRB RC ll4       tW]<P•                  RD4      R„RF RG ll4       tXRH RI ltY]<P‘                  RJ4      RƒRK RL ll4       tZ]<P•                  RJ4      RƒRM RN ll4       t[]<P§                  RO4      RƒRP RQ ll4       t\R…t]]<P‘                  RR4      RƒRS RT ll4       t^]<P«                  RU4      RƒRV RW ll4       t_]<P•                  RX4      RƒRY RZ ll4       t`]<P•                  R[4      RƒR\ R] ll4       ta]<P•                  R^4      RƒR_ R` ll4       tbRƒRa Rb lltc]<P•                  Rc4      RƒRd Re ll4       td]<P‘                  Rf4      RƒRg Rh ll4       teRƒRi Rj lltf]<P•                  Rk4      RƒRl Rm ll4       tgRn Ro lth]<P•                  Rp4      ]! Rq4      ]! RE4      R3Rr Rs ll4       ti]<P‘                  Rt4      RƒRu Rv ll4       tjRw Rx ltk]<P•                  Rt4      RƒRy Rz ll4       tl]<P§                  Rt4      RƒR{ R| ll4       tm]<P‘                  R}4      RƒR~ R ll4       tn]<P•                  R€4      RƒR� R‚ ll4       toR# )†a  Pairing, webhooks, gateway lifecycle, credential pool, memory provider and
operations (doctor/backup/import/hooks/checkpoints) dashboard routes.

Helpers/state that tests monkeypatch on ``web_server`` stay there and are
reached through the late-binding seam (cycle-safe).
N)ÚdatetimeÚtimezoneÚUTC)ÚPath)ÚAnyÚDictÚListÚOptional)Ú	APIRouterÚFileÚFormÚHTTPExceptionÚ
UploadFile)ÚFileResponse)Ú
redact_key)Úlate)Ú_path_is_under)Ú_restart_gateway_after)Ú_normalize_memory_provider_nameÚ_require_memory_provider_ready)ÚBackupRequestÚCredentialPoolAddÚ
HookCreateÚ
HookDeleteÚImportRequestÚMemoryProviderSelectÚMemoryResetÚPairingApproveÚPairingRevokeÚWebhookCreateÚWebhookEnabledToggle)Úconfig_scoped_to_threadÚconfig_write_scopeÚdestructive_profileÚhttp_failureÚspawn_profile_action)Ústream_upload_to_pathzhermes_cli.web_serverÚ"_discover_memory_provider_statuseszhermes_cli.web_server_memoryÚ_gateway_subcommandzhermes_cli.web_server_gatewayÚ_config_profile_scopezhermes_cli.web_server_profilesÚ_resolve_profile_dirÚ_spawn_hermes_actionÚ_write_platform_enabledzhermes_cli.web_server_messagingÚget_hermes_homezhermes_cli.configÚload_configÚsave_configÚprofilec                óŒ   € V ^8„  d   QhR\         \        ,          R\        R\        R\        R\        \        ,          R\        /# )é   ÚargvÚnameÚlog_msgÚprefixr0   Úreturn)ÚlistÚstrr	   Údict)Úformats   "ÚNC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\web_routers\ops.pyÚ__annotate__r=   5   sH   € ÷ Uñ UœœS�	ð U¬ð U¼#ð UÄsð UÜ#¤C�=ðUÜ48ñUó    c               ó   € \        W@WVR7      # )u×   Spawn a ``hermes -p <profile> <argv>`` action; spawn failure -> 500.

The profile reaches the child as argv (``_profile_cli_args``) â€” the only mechanism
that retargets a fresh process's import-time home bindings.
)r5   r6   )r%   )r3   r4   r5   r6   r0   s   &&$$$r<   Ú_spawn_actionr@   5   s   € ô   ¨tÈVÔTÐTr>   c                ó:   € V ^8„  d   QhR\         \        ,          /# ©r2   r0   ©r	   r9   )r;   s   "r<   r=   r=   B   s   € ÷ +ñ +œH¤S�Mñ +r>   c                ó²   € ^ RI Hp T ;'       g    RP                  4       pV'       d   VP                  4       R8X  d   V! 4       # \	        V4       V! VR7      # )u§  Pairing store for ``profile`` â€” the dashboard's own when unspecified.

The gateway keeps one store per served profile, so without scoping an
operator on a named profile would approve into a whitelist their gateway
never consults. ``PairingStore`` resolves the profile home itself
(``default`` maps to the global store); only the name is validated here,
so nothing process-global is swapped across the ``await`` boundary.
)ÚPairingStoreÚ Úcurrent©r0   )Úgateway.pairingrE   ÚstripÚlowerr*   )r0   rE   Ú	requesteds   &  r<   Ú_pairing_storerM   B   sG   € õ -à—�˜B×%Ñ%Ó'€Iß˜	Ÿ™Ó)¨YÔ6Ù‹~ÐÜ˜Ô#Ù 	Ô*Ð*r>   z/api/pairingc                ó:   € V ^8„  d   QhR\         \        ,          /# rB   rC   )r;   s   "r<   r=   r=   U   s   € ÷ gñ g¤¬¥ñ gr>   c              ƒ   ó˜   "  € \        V 4      pR \        P                  ! VP                  4      G Rj  x€L
 RVP	                  4       /#  L5i)ÚpendingNÚapproved)rM   ÚasyncioÚ	to_threadÚlist_pendingÚlist_approved)r0   Ústores   & r<   Úlist_pairingrW   T   s?   é € ä˜7Ó#€EàœW×.Ò.¨u×/AÑ/AÓB×BÀJÐPU×PcÑPcÓPeÐfÐfÑBùs   ‚0A
²A³A
z/api/pairing/approvec                ó$   € V ^8„  d   QhR\         /# ©r2   Úbody)r   )r;   s   "r<   r=   r=   \   s   € ÷ ñ ¤ñ r>   c              ƒ   ó  "  € \        V P                  4      pV P                  ;'       g    R P                  4       P	                  4       pV P
                  ;'       g    V P                  ;'       g    R P	                  4       pV'       d	   V'       g   \        RRR7      h\        V P
                  4      ;'       g    VP                  V4      pV'       d+   \        P                  ! VP                  W#4      G Rj  x€L
 pM7\        P                  ! VP                  W#P                  4       4      G Rj  x€L
 pV'       d   RRRV/# V'       g)   VP                  V4      '       d   \        RR	V R
2R7      h\        RRV R2R7      h L‹ LU5i)rF   é�  z,platform and request_id or code are required©Ústatus_codeÚdetailNÚokTÚuseri­  z
Platform 'z0' is locked out after too many failed approvals.é”  z;Pairing request or code not found or expired for platform 'z'.)rM   r0   ÚplatformrK   rJ   Ú
request_idÚcoder   ÚboolÚlooks_like_request_idrR   rS   Úapprove_requestÚapprove_codeÚupperÚ_is_locked_out)rZ   rV   rc   ÚtargetÚby_request_idÚresults   &     r<   Úapprove_pairingro   [   s>  é € ä˜4Ÿ<™<Ó(€EØ—‘×#Ð# ×*Ñ*Ó,×2Ñ2Ó4€Hð �o‰o×0Ð0 §¡×0Ð0¨b×7Ñ7Ó9€FßŸ6Ü¨Ð4bÔcÐcä˜Ÿ™Ó)×PÐP¨U×-HÑ-HÈÓ-P€MßÜ×(Ò(¨×)>Ñ)>ÀÓQ×Q‰ä×(Ò(¨×);Ñ);¸XÇ|Á|Ã~ÓV×VˆßØ�d˜F FÐ+Ð+÷ ˜U×1Ñ1°(×;Ò;ÜØ j°°
Ð:jÐ$kô
ð 	
ô ØÐ"]Ð^fÐ]gÐgiÐ jôð ñ RáVùsZ   ‚AF	ÁF	Á1F	Â
F	Â(F	Â;F	Ã$F	Ã9FÃ:7F	Ä1FÄ2F	Ä>F	ÅF	Å##F	ÆF	z/api/pairing/revokec                ó$   € V ^8„  d   QhR\         /# rY   )r   )r;   s   "r<   r=   r=   y   s   € ÷ sñ sœ}ñ sr>   c              ƒ   ó   "  € \        V P                  4      pV P                  ;'       g    R P                  4       P	                  4       pV'       d   V P
                  '       g   \        RRR7      h\        P                  ! VP                  W P
                  4      G Rj  x€L
 '       d   RR/# \        RRV P
                   R	V R
2R7      h L,5i)rF   r\   z!platform and user_id are requiredr]   Nr`   Trb   zUser z  not found in approved list for Ú.)
rM   r0   rc   rK   rJ   Úuser_idr   rR   rS   Úrevoke)rZ   rV   rc   s   &  r<   Úrevoke_pairingru   x   s¡   é € ä˜4Ÿ<™<Ó(€EØ—‘×#Ð# ×*Ñ*Ó,×2Ñ2Ó4€Hß˜4Ÿ<Ÿ<˜<Ü¨Ð4WÔXÐXÜ×Ò˜uŸ|™|¨X·|±|ÓD×DÖDØ�dˆ|ÐÜ
 C°%¸¿¹°~ÐEeÐfnÐeoÐopÐ0qÔ
rÐrñ Eùs$   ‚ACÁCÁ$;CÂCÂ 	CÂ*#Cz/api/pairing/clear-pendingc                ó:   € V ^8„  d   QhR\         \        ,          /# rB   rC   )r;   s   "r<   r=   r=   „   s   € ÷ cñ c¬´#­ñ cr>   c              ƒ   óx   "  € R RR\         P                  ! \        V 4      P                  4      G Rj  x€L
 /#  L5i)r`   TÚclearedN)rR   rS   rM   Úclear_pendingrH   s   &r<   Úclear_pending_pairingrz   ƒ   s0   é € à�$˜	¬×):Ò):¼>È'Ó;R×;`Ñ;`Ó)a×#aÐbÐbÑ#aùs   ‚0:²8
³:c          
      óŒ   € V ^8„  d   QhR\         R\        \         \        3,          R\         R\        \         \        3,          /# )r2   r4   ÚrouteÚbase_urlr7   )r9   r:   r   )r;   s   "r<   r=   r=   Œ   s;   € ÷ ñ ¤ð ¬T´#´s°(­^ð Äsð ÌtÔTWÔY\ÐT\Í~ñ r>   c                 óê  € R T RVP                  RR4      R\        VP                  R4      ;'       g    . 4      RVP                  RR4      R\        VP                  R4      4      RVP                  RR4      RVP                  RR4      R	\        VP                  R	4      ;'       g    . 4      R
VP                  R
4      RV RV  2R\        VP                  R4      4      RVP                  RR4      RJ/# )r4   ÚdescriptionrF   ÚeventsÚdeliverÚlogÚdeliver_onlyÚpromptÚscriptÚskillsÚ
created_atÚurlz
/webhooks/Ú
secret_setÚsecretÚenabledTF)Úgetr8   rf   )r4   r|   r}   s   &&&r<   Ú_webhook_route_summaryr�   Œ   sà   € à�Ø�u—y‘y °Ó3Ø”$�u—y‘y Ó*×0Ð0¨bÓ1Ø�5—9‘9˜Y¨Ó.Øœ˜UŸY™Y ~Ó6Ó7Ø�%—)‘)˜H bÓ)Ø�%—)‘)˜H bÓ)Ø”$�u—y‘y Ó*×0Ð0¨bÓ1Ø�e—i‘i Ó-Ø�(�˜: d VÐ,Ø”d˜5Ÿ9™9 XÓ.Ó/à�5—9‘9˜Y¨Ó-°UÐ:ðð r>   z/api/webhooksc                ó:   € V ^8„  d   QhR\         \        ,          /# rB   rC   )r;   s   "r<   r=   r=   Ÿ   s   € ÷ 8ñ 8¤¬#¥ñ 8r>   c              ƒ   ó:   "  € R  p\        W4      G Rj  x€L
 #  L5i)c                  óÚ   € ^ RI Hp  V P                  4       pRV P                  4       RTRV P	                  4       P                  4        UUu. uF  w  r#\        W#V4      NK  	  upp/# u uppi )é    Nr‹   r}   Úsubscriptions)Úhermes_cli.webhookÚwebhookÚ_get_webhook_base_urlÚ_is_webhook_enabledÚ_load_subscriptionsÚitemsr�   )Úwhr}   r4   r|   s       r<   Ú_runÚlist_webhooks.<locals>._run    sn   € Ý'à×+Ñ+Ó-ˆà�r×-Ñ-Ó/Ø˜Øà#%×#9Ñ#9Ó#;×#AÑ#AÔ#Côá#C‘K�Dô ' t°HÖ=Ù#Còð
ð 	
ùós   ÁA'N©r!   ©r0   rš   s   & r<   Úlist_webhooksrž   ž   s   é € ò
ô )¨Ó7×7Ð7Ñ7ùó   ‚”•z/api/webhooks/enablec                ó:   € V ^8„  d   QhR\         \        ,          /# rB   rC   )r;   s   "r<   r=   r=   ±   s   € ÷ ñ ¤8¬C¥=ñ r>   c           	   ƒ   ó  a "  € V 3R  lp\        RRRR7      ;_uu_ 4        \        P                  ! V4      G Rj  x€L
  RRR4       \        S RRR7      pR	R
RRRR
RVR,          '       * /VC#  L2  + '       g   i     L8; i5i)c                  ó€   <€ \        S 4      ;_uu_ 4        \        R R4       RRR4       R#   + '       g   i     R# ; i)r”   TN)r"   r,   rH   s   €r<   rš   Úenable_webhooks.<locals>._run²   s'   ø€ Ü ×(Õ(Ü# I¨tÔ4÷ )×(×(Ò(ús   •,¬=	z0Failed to enable webhook platform from dashboardéô  z"Failed to enable webhook platform.)r_   Nzenabling webhookszWebhook enable)ÚwhatÚlabelr`   Trc   r”   r‹   Úneeds_restartÚrestart_started)r$   rR   rS   r   )r0   rš   Úrestart_results   f  r<   Úenable_webhooksrª   °   s‡   øé € õ5ô 
ÐHÈ#ÐVz×	{Ö	{Ü×Ò Ó%×%Ð%÷ 
|ä+¨GÐ:MÐUeÔf€NàˆdØ�IØ�4Ø˜^Ð,=Õ>Ô>ð	ð
 ðð ñ 	&÷ 
|×	{üs+   ƒB A/ºA-»A/¿.BÁ-A/Á/A?	Á:Bc                óF   € V ^8„  d   QhR\         R\        \        ,          /# ©r2   rZ   r0   )r   r	   r9   )r;   s   "r<   r=   r=   Ã   s   € ÷ 4ñ 4œ}ð 4´xÄµ}ñ 4r>   c              ƒ   óš  a	a
aa"  € ^ RI Ho V3R lp\        W4      G Rj  x€L
 '       g   \        RRR7      hV P                  ;'       g    RP                  4       P                  4       P                  RR4      o
\        P                  ! R	S
4      '       g   \        RR
R7      hV P                  '       d   V P                  R8X  d   \        RRR7      hV
V3R lp\        W4      G Rj  x€L
 o	V P                  ;'       g    \        P                  ! ^ 4      pRV P                  ;'       g    RS
 2RV P                    Uu. uF*  qUP                  4       '       g   K  VP                  4       NK,  	  upRTRV P"                  ;'       g    RRV P$                   Uu. uF*  qfP                  4       '       g   K  VP                  4       NK,  	  upRV P                  ;'       g    RR\&        P(                  ! R\&        P*                  ! 4       4      /oV P,                  '       d>   V P,                  P                  4       '       d   V P,                  P                  4       SR&   V P                  '       d   RSR&   V P.                  '       d   RV P.                  /SR&   V	V
VV3R lp\        W4      G Rj  x€L
 pWHR&   V#  EL˜ ELÒu upi u upi  L5i)r‘   Nc                  ó$   <€ S P                  4       # ©N)r–   )r™   s   €r<   Ú_enabledÚ create_webhook.<locals>._enabledÆ   s   ø€ Ø×%Ñ%Ó'Ð'r>   r\   zHWebhook platform is not enabled. Enable it from the Webhooks page first.r]   rF   Ú Ú-z^[a-z0-9][a-z0-9_-]*$zBInvalid name. Use lowercase alphanumeric with hyphens/underscores.r‚   uK   Direct delivery requires a real target (telegram, discord, â€¦), not 'log'.c                  ó\   <€ SP                  4       p V P                  SSP                  4      # r¯   )r—   rŒ   Ú_MISSING_SUBSCRIPTION)r’   r4   r™   s    €€r<   Ú	_snapshotÚ!create_webhook.<locals>._snapshot×   s*   ø€ Ø×.Ñ.Ó0ˆØ× Ñ   r×'?Ñ'?Ó@Ð@r>   r   z Dashboard-created subscription: r€   rŠ   r„   r†   r�   r‡   z%Y-%m-%dT%H:%M:%SZr…   Trƒ   Úchat_idÚdeliver_extrac                  óÂ   <€  SP                  SSS4      p \	        ST SP                  4       4      #   SP                   d   p\        R \        T4      R7      ThRp?ii ; i)é™  r]   N)Ú_replace_subscriptionÚSubscriptionMutationConflictr   r9   r�   r•   )Ú	publishedÚexcÚexpectedr4   r|   r™   s     €€€€r<   Ú_saveÚcreate_webhook.<locals>._saveî   sd   ø€ ð	KØ×0Ñ0°°u¸hÓGˆIô & d¨I°r×7OÑ7OÓ7QÓRÐRøð ×.Ñ.ô 	KÜ¨C¼¸C»ÔAÀsÐJûð	Kús   ƒ1 ±AÁAÁA)r“   r”   r!   r   r4   rJ   rK   ÚreplaceÚreÚmatchrƒ   r�   rŠ   ÚsecretsÚtoken_urlsafer   r€   r„   r†   ÚtimeÚstrftimeÚgmtimer…   Údeliver_chat_id)rZ   r0   r°   r¶   rŠ   ÚeÚsrÁ   ÚsummaryrÀ   r4   r|   r™   s   &&       @@@@r<   Úcreate_webhookrÏ   Â   s>  ûé € å#õ(ô )¨Ó;×;Ö;ÜØÐ$nô
ð 	
ð �I‰I�OˆO˜×"Ñ"Ó$×*Ñ*Ó,×4Ñ4°S¸#Ó>€DÜ�8Š8Ð,¨d×3Ò3ÜØÐ$hô
ð 	
ð ××Ð˜TŸ\™\¨UÔ2ÜØÐ$qô
ð 	
öAô -¨WÓ@×@€Hà�[‰[×5Ð5œG×1Ò1°"Ó5€Fà�t×'Ñ'×TÐTÐ-MÈdÈVÐ+TØ d§k¢kÓ?¡k ·W±W·Y”9�1—7‘7–9¡kÑ?Ø�&Ø�$—+‘+×#Ð# Ø d§k¢kÓ?¡k ·W±W·Y”9�1—7‘7–9¡kÑ?Ø�4—<‘<×(Ð( 5Ø”d—m’mÐ$8¼$¿+º+»-ÓHð€Eð ‡{‡{€{�t—{‘{×(Ñ(×*Ò*ØŸ+™+×+Ñ+Ó-ˆˆh‰Ø××ÐØ $ˆˆnÑØ××ÐØ"+¨T×-AÑ-AÐ!BˆˆoÑ÷Sð Sô ,¨GÓ;×;€GØˆHÑØ€Nò] <ò$ Aùò
 @ùò @ñ$ <ùsŸ   †K¡J9¢	K¬KÁAKÂKÂ73KÃ*J<Ã+KÄ*KÄ-KÅJ?
ÅJ?
Å1KÆ	KÆKÆ6KÇ
KÇ ?KÈ KÉ .KÉ/KÊ(KÊ.K	Ê/KÊ<KÊ?Kc                ó^   € V ^8„  d   QhR\         \        \         3,          R\        R\        /# )r2   r’   r4   r7   )r:   r9   )r;   s   "r<   r=   r=   ú   s)   € ÷ ñ ¤4¬¬T¨	¥?ð ¼#ð Ä#ñ r>   c                ó„   € T;'       g    RP                  4       P                  4       pW 9  d   \        RRV R2R7      hV# )zJNormalized key for an existing route in a lock-held subscription snapshot.rF   rb   zNo subscription named 'Ú'r]   )rJ   rK   r   )r’   r4   Úkeys   && r<   Ú_webhook_key_inrÔ   ú   sB   € à�:ˆ:�2×
Ñ
Ó
×
$Ñ
$Ó
&€CØ
ÔÜ¨Ð6MÈcÈUÐRSÐ4TÔUÐUØ€Jr>   z/api/webhooks/{name}c                óF   € V ^8„  d   QhR\         R\        \         ,          /# )r2   r4   r0   ©r9   r	   )r;   s   "r<   r=   r=     s   € ÷ ñ œsð ¬X´c­]ñ r>   c              ƒ   ób   a "  € \        VR 4      pV 3R lp\        W4      G Rj  x€L
  RR/#  L5i)zDELETE /api/webhooks/{name}c                  óB   <€ ^ RI Hp  V3R lpV P                  V4       R# )r‘   Nc                 ó"   <€ V \        V S4       R # r¯   )rÔ   )r’   r4   s   &€r<   ÚremoveÚ,delete_webhook.<locals>._run.<locals>.remove	  s   ø€ Øœo¨m¸TÓBÒCr>   ©r“   r”   Ú_mutate_subscriptions)r™   rÚ   r4   s     €r<   rš   Údelete_webhook.<locals>._run  s   ø€ Ý'õ	Dð 	× Ñ  Ö(r>   Nr`   T)r#   r!   )r4   r0   rš   s   f& r<   Údelete_webhookrß     s7   øé € ä! 'Ð+HÓI€Gõ)ô " 'Ó
0×0Ð0Ø�$ˆ<Ðñ 1ùs   ƒ!/¤-¥	/z/api/webhooks/{name}/enabledc                óR   € V ^8„  d   QhR\         R\        R\        \         ,          /# )r2   r4   rZ   r0   )r9   r    r	   )r;   s   "r<   r=   r=     s,   € ÷ Dñ D¤Cð DÔ/Cð DÌhÔWZÍmñ Dr>   c              ƒ  ó|   a a"  € VV 3R lp\        W#4      G Rj  x€L
 pRRRVR\        SP                  4      /#  L5i)z�Disabled routes stay on disk (re-enable later) but the gateway rejects
their events with 403; it hot-reloads the file, so no restart is needed.c                  ó@   <€ ^ RI Hp  VV3R lpV P                  V4      # )r‘   Nc                 ó\   <€ \        V S4      p\        SP                  4      W,          R &   V# )r‹   )rÔ   rf   r‹   )r’   rÓ   rZ   r4   s   & €€r<   ÚtoggleÚ1set_webhook_enabled.<locals>._run.<locals>.toggle  s*   ø€ Ü! -°Ó6ˆCÜ,0°·±Ó,>ˆMÕ˜yÑ)ØˆJr>   rÜ   )r™   rä   rZ   r4   s     €€r<   rš   Ú!set_webhook_enabled.<locals>._run  s   ø€ Ý'ö	ð
 ×'Ñ'¨Ó/Ð/r>   Nr`   Tr4   r‹   )r!   rf   r‹   )r4   rZ   r0   rš   rÓ   s   ff&  r<   Úset_webhook_enabledrç     s;   ùé € ö0ô (¨Ó6×
6€CØ�$˜  Y´°T·\±\Ó0BÐCÐCñ 7ùs   „<š:› <z/api/gateway/startc                ó:   € V ^8„  d   QhR\         \        ,          /# rB   rC   )r;   s   "r<   r=   r=   )  s   € ÷ 	Bñ 	B¤¬#¥ñ 	Br>   c              ƒ   ó4  "  € ^ RI Hp \        P                  ! WR4      G Rj  x€L
 pV'       d   \	        RVR7      h\        RRR4      ;_uu_ 4        \        \        V R4      R	4      pRRR4       R
RRXP                  RR	/#  L_  + '       g   i     L$; i5i)r‘   )Úmultiplexed_profile_refusalÚstartNr»   r]   zFailed to spawn gateway startr¤   zFailed to start gatewayzgateway-startr`   TÚpidr4   )	Úhermes_cli.web_server_gatewayrê   rR   rS   r   r$   r+   r(   rì   )r0   rê   ÚrefusalÚprocs   &   r<   Ústart_gatewayrð   (  s�   é € åIô ×%Ò%Ð&AÈGÓT×T€GßÜ¨°GÔ<Ð<Ü	Ð5°sÐ<U×	VÕ	VÜ#Ô$7¸ÀÓ$IÈ?Ó[ˆ÷ 
Wà�$˜˜tŸx™x¨°ÐAÐAñ U÷ 
W×	Vüs,   ‚!B£B¤B°"BÁBÁ)BÂB	ÂBz/api/gateway/stopFc                óF   € V ^8„  d   QhR\         \        ,          R\        /# )r2   r0   Ú	interrupt)r	   r9   rf   )r;   s   "r<   r=   r=   6  s"   € ÷ Añ A¤¬¥ð AÄñ Ar>   c              ƒ   óÒ  "  € ^ RI HpHp \        P                  ! W0R4      G Rj  x€L
 pV'       d   \        RVR7      hV'       g5   \        P                  ! W R4      G Rj  x€L
 ;p'       d   \        RVR7      h\        RRR4      ;_uu_ 4        \        \        V R4      R	.V,          ,           R
4      pRRR4       RRRXP                  RR
/#  Lª Lp  + '       g   i     L&; i5i)r‘   )Úlive_session_refusalrê   ÚstopNr»   r]   zFailed to spawn gateway stopr¤   zFailed to stop gatewayz--interruptzgateway-stopr`   Trì   r4   )
rí   rô   rê   rR   rS   r   r$   r+   r(   rì   )r0   rò   rô   rê   rî   rï   s   &&    r<   Ústop_gatewayrö   5  s¾   é € ç_ô ×%Ò%Ð&AÈFÓS×S€GßÜ¨°GÔ<Ð<ç¬7×+<Ò+<Ð=QÐ\bÓ+c×%cÐc˜'ÖcÜ¨°GÔ<Ð<Ü	Ð4°cÐ;S×	TÕ	TÜ#Ô$7¸ÀÓ$HÈMÈ?Ð]fÕKfÕ$fÐhvÓwˆ÷ 
Uà�$˜˜tŸx™x¨°Ð@Ð@ñ Tñ &dç	T×	TüsJ   ‚#C'¥C¦C'²C'ÁC'Á!CÁ"C'Á."C'Â&CÂ6C'ÃC'ÃC$	ÃC'c                ó^   € V ^8„  d   QhR\         R\        R\        \        \         3,          /# )r2   ÚentryÚindexr7   )r   Úintr:   r9   )r;   s   "r<   r=   r=   M  s)   € ÷ ñ œsð ¬3ð ´4¼¼S¸µ>ñ r>   c                ó2  € V P                   ;'       g    RpRTRV P                  RV P                  RV P                  RV P                  RV P
                  RV P                  R	V P                  R
V'       d   \        V4      MRR\        V P                  4      /
# )zcRedacted view of one PooledCredential; ``index`` is 1-based to match
CredentialPool.remove_index().rF   rù   Úidr¦   Ú	auth_typeÚsourceÚpriorityÚlast_statusÚrequest_countÚtoken_previewÚhas_refresh)Úaccess_tokenrü   r¦   rý   rþ   rÿ   r   r  r   rf   Úrefresh_token)rø   rù   Útokens   && r<   Ú_pool_entry_summaryr  M  s‡   € ð ×Ñ×$Ð$ "€Eà�Øˆe�h‰hØ�—‘Ø�U—_‘_Ø�%—,‘,Ø�E—N‘NØ�u×(Ñ(Ø˜×,Ñ,Ø¯eœ EÔ*¸Ø”t˜E×/Ñ/Ó0ðð r>   z/api/credentials/poolc                ó:   € V ^8„  d   QhR\         \        ,          /# rB   rC   )r;   s   "r<   r=   r=   `  s   € ÷ 8ñ 8¬´­ñ 8r>   c              ƒ   ó^   aa"  € ^ RI Ho ^ RIHo VV3R lp\	        W4      G Rj  x€L
 #  L5i)r‘   ©Ú	load_pool)Úread_credential_poolc                  óv  <€ . p \        S! 4       P                  4       4       Fc  p S! V4      pTP                  4       pT'       g   K&  T P                  RTR\        T^R7       UUu. uF  w  rE\        YT4      NK  	  upp/4       Ke  	  RV /#   \         d    \        P	                  R T4        K�  i ; iu uppi )zload_pool(%s) failedÚproviderÚentries)rë   Ú	providers)	ÚsortedÚkeysÚ	ExceptionÚ_logÚ	exceptionr  ÚappendÚ	enumerater  )r  Úprovider_idÚpoolr  ÚirÌ   r  r  s         €€r<   rš   Ú"list_credential_pool.<locals>._rund  s¼   ø€ Øˆ	ô "Ñ"6Ó"8×"=Ñ"=Ó"?Ö@ˆKðÙ  Ó-�ð —l‘l“nˆGß‰wØ× Ñ Ø ØÄiÐPWÐ_`ÕFaÔbÑFa¹d¸aÔ 3°AÖ 9ÑFaÒbð"ö ñ Að ˜YÐ'Ð'øô ô Ü—‘Ð5°{ÔCÚðüó  cs   ¦BÁ&B5Â!B2Â1B2N)Úagent.credential_poolr  Úhermes_cli.authr  r!   )r0   rš   r  r  s   & @@r<   Úlist_credential_poolr  _  s$   ùé € å/Ý4ö(ô* )¨Ó7×7Ð7Ñ7ùs   „"-¦+§-c                óF   € V ^8„  d   QhR\         R\        \        ,          /# r¬   )r   r	   r9   )r;   s   "r<   r=   r=   }  s   € ÷ 68ñ 68Ô*;ð 68ÄhÌsÅmñ 68r>   c           	   ƒ   ól  a aaaaaaa	a
"  € ^ RI o
^ RIHoHoHoHoHo S P                  ;'       g    RP                  4       P                  4       o	S P                  ;'       g    RP                  4       oS	'       d	   S'       g   \        RRR7      hVVVVVV VV	V
3	R lp\        W4      G Rj  x€L
 #  L5i)r‘   N)ÚAUTH_TYPE_API_KEYÚCUSTOM_POOL_PREFIXÚSOURCE_MANUALÚPooledCredentialr  rF   r\   z!provider and api_key are requiredr]   c                  ó$  <	€  S! S4      p SP                   ;'       g    R P                  4       ;'       g$    R\        V P                  4       4      ^,            2pV P	                  S	! SSP                  4       P                  R,          VS^ S
SR7      4       SP                  S4      '       gV    ^ RIH	pH
p V! 4       P                  R/ 4      p\        VP                  S. 4      ;'       g    . 4       F  pV! SV4       K  	  RRR	SR
\        V P                  4       4      /#   \         d    \        P                  R4        LAi ; i  \          d    h \         d2   p\        P                  R4       \!        R\#        T4      R7      ThRp?ii ; i)rF   zkey #:Né   N)r  rü   r¦   rý   rÿ   rþ   r  )Ú_load_auth_storeÚunsuppress_credential_sourceÚsuppressed_sourcesz,unsuppress after pool add failed (non-fatal)r`   Tr  Úcountz!POST /api/credentials/pool failedr\   r]   N)r¦   rJ   Úlenr  Ú	add_entryÚuuid4ÚhexÚ
startswithr  r'  r(  rŒ   r8   r  r  r  r   r9   )r  r¦   r'  r(  Ú
suppressedÚsrcr¿   r!  r"  r$  r#  Úapi_keyrZ   r  r  Úuuids          €€€€€€€€€r<   rš   Ú'add_credential_pool_entry.<locals>._runŒ  sh  ø€ ð$	KÙ˜XÓ&ˆDØ—Z‘Z×%Ð% 2×,Ñ,Ó.×SÐS°E¼#¸d¿l¹l»nÓ:MÐPQÕ:QÐ9RÐ2SˆEØ�N‰NÑ+Ø!ð —:‘:“<×#Ñ# BÕ'ØØ+ØØ$Ø$ôô ð& ×&Ñ&Ð'9×:Ò:ðSß^á!1Ó!3×!7Ñ!7Ð8LÈbÓ!Q�JÜ# J§N¡N°8¸RÓ$@×$FÐ$FÀBÖG˜Ù4°X¸sÖCñ  Hð ˜$ 
¨H°g¼sÀ4Ç<Á<Ã>Ó?RÐSÐSøô !ô SÜ—N‘NÐ#QÖRðSûô ô 	ØÜô 	KÜ�N‰NÐ>Ô?Ü¨C¼¸C»ÔAÀsÐJûð	KúsR   ƒE žE ¶A7E Â/<D" Ã,D" ÄE Ä" EÅE ÅEÅE ÅFÅFÅ,F
Æ
F)r3  r  r!  r"  r#  r$  r  r  rJ   rK   r2  r   r!   )rZ   r0   rš   r!  r"  r$  r#  r2  r  r  r3  s   f& @@@@@@@@r<   Úadd_credential_pool_entryr5  |  s†   ÿøé € ã÷õ ð —‘×#Ð# ×*Ñ*Ó,×2Ñ2Ó4€HØ�|‰|×!Ð!˜r×(Ñ(Ó*€GßŸ7Ü¨Ð4WÔXÐX÷%Kõ %KôN )¨Ó7×7Ð7Ñ7ùs$   ‹AB4Á#B4Á<B4Â)B4Â-B2Â.B4z(/api/credentials/pool/{provider}/{index}c                óR   € V ^8„  d   QhR\         R\        R\        \         ,          /# )r2   r  rù   r0   )r9   rú   r	   )r;   s   "r<   r=   r=   ·  s+   € ÷ 1_ñ 1_´ð 1_¼Sð 1_Ì8ÔTWÍ=ñ 1_r>   c              ƒ  óÜ   a aaaa"  € ^ RI Ho ^ RIHo ^ RIHo S ;'       g    RP                  4       P                  4       o VVVV V3R lp\        \        VR4      V4      G Rj  x€L
 #  L5i)u  Remove a pool entry (``index`` is 1-based, as listed).

Removal must be sticky: ``load_pool()`` re-seeds entries from their backing
source (.env var, OAuth file, custom-provider config) on every call, so
deleting only the row silently reverts on the next refresh. Dispatch through
the same RemovalStep registry as ``hermes auth remove``: each source cleans
its external state and suppresses ``(provider, source)`` so seeders skip it.
Manual entries have no step â€” nothing external, and they aren't re-seeded.

See #55217.
r
  )Úfind_removal_step)Úsuppress_credential_sourcerF   c            
      ó  <€  S	! S
4      p V P                  S4      pTf   \	        RRR7      h. p. pS! S
TP                  ;'       g    R4      pTec    TP                  S
T4      p\        TP                  4      p\        TP                  4      pTP                  '       d   S! S
TP                  4       R	R
RS
R\        T P                  4       4      RTRT/#   \         d2   p\        P                  R 4       \	        R\        T4      R7      ThRp?ii ; i  \         d`    \        P                  RS
TP                  4        S! S
TP                  4        L¤  \         d    \        P                  R4         LÇi ; ii ; i)z#DELETE /api/credentials/pool failedr\   r]   Nrb   zNo pool entry at that indexrF   z>credential source cleanup failed for %s/%s; suppressing anywayz!suppress_credential_source failedr`   Tr  r*  ÚcleanedÚhints)Úremove_indexr  r  r  r   r9   rþ   Ú	remove_fnr8   r;  r<  Úsuppressr+  r  )r  Úremovedr¿   r;  r<  Ústeprn   r8  rù   r  r  r9  s          €€€€€r<   rš   Ú*remove_credential_pool_entry.<locals>._runÉ  sh  ø€ ð	KÙ˜XÓ&ˆDØ×'Ñ'¨Ó.ˆGð Š?Ü¨CÐ8UÔVÐVàˆØˆÙ  ¨7¯>©>×+?Ð+?¸RÓ@ˆØÒðHØŸ™¨°'Ó:�Ü˜vŸ~™~Ó.�Ü˜VŸ\™\Ó*�Ø—?—?�?Ù.¨x¸¿¹ÔHð �d˜J¨°'¼3¸t¿|¹|»~Ó;NÐPYÐ[bÐdkÐmrÐsÐsøô1 ô 	KÜ�N‰NÐ@ÔAÜ¨C¼¸C»ÔAÀsÐJûð	Kûô  ô Hô —‘Ð_ÐaiÐkr×kyÑkyÔzðHÙ.¨x¸¿¹ÖHøÜ ô HÜ—N‘NÐ#F×GðHúðHúsB   ƒC ÁA!D ÃDÃ",DÄDÄ,F ÅEÅ E<Å8F Å;E<Å<F z/DELETE /api/credentials/pool/{provider}/{index}N)
r  r  Úagent.credential_sourcesr8  r  r9  rJ   rK   r!   r#   )r  rù   r0   rš   r8  r  r9  s   ff& @@@r<   Úremove_credential_pool_entryrD  ¶  se   üé € õ 0Ý:Ý:à—�˜B×%Ñ%Ó'×-Ñ-Ó/€H÷tñ tô< )Ü˜GÐ%VÓWÐY]ó_÷ _ð _ñ _ùs   ‡AA,Á%A*Á&A,z/api/memoryc                ó:   € V ^8„  d   QhR\         \        ,          /# rB   rC   )r;   s   "r<   r=   r=   ó  s   € ÷ 8ñ 8¤X¬c¥]ñ 8r>   c              ƒ   ó:   "  € R  p\        W4      G Rj  x€L
 #  L5i)c                  óx  € \        4       p V P                  R 4      p\        V\        4      '       d   \	        VP                  R4      4      MRp\        4       R,          p/ p\         FA  w  rVW5,          pVP                  4       '       d   VP                  4       P                  M^ WF&   KC  	  RVR\        4       RV/# )Úmemoryr  rF   ÚmemoriesÚactiver  Úbuiltin_files)r.   rŒ   Ú
isinstancer:   r   r-   Ú_MEMORY_FILESÚexistsÚstatÚst_sizer'   )ÚcfgÚmemrJ  Úmem_dirÚfilesÚfnamerÓ   Úpaths           r<   rš   Úget_memory_status.<locals>._runô  s›   € Ü‹mˆØ�g‰g�hÓˆÜISÐTWÔY]×I^ÒI^Ô0°·±¸Ó1DÔEÐdfˆÜ!Ó# jÕ0ˆØˆß'‰JˆEØ•?ˆDØ04·±·²˜Ÿ™›×,Ò,À1ˆE‹Jñ (ð ˜& +Ô/QÓ/SÐUdÐfkÐlÐlr>   Nrœ   r�   s   & r<   Úget_memory_statusrX  ò  s   é € ò	mô )¨Ó7×7Ð7Ñ7ùrŸ   z/api/memory/providerc                óF   € V ^8„  d   QhR\         R\        \        ,          /# r¬   )r   r	   r9   )r;   s   "r<   r=   r=     s   € ÷ )ñ )Ô$8ð )Ä8ÌCÅ=ñ )r>   c              ƒ   ó†   aa"  € \        V P                  4      oVV3R  lp\        P                  ! V4      G Rj  x€L
 #  L5i)c                  ó  <€ \        S4      ;_uu_ 4        \        S4       \        4       p \        V P	                  R 4      \
        4      '       g   / V R &   SV R ,          R&   \        V 4       RRR4       RRRS/#   + '       g   i     L; i)rH  r  Nr`   TrJ  )r"   r   r.   rL  rŒ   r:   r/   )rQ  r0   r  s    €€r<   rš   Ú!set_memory_provider.<locals>._run  ss   ø€ ô
   ×(Õ(Ü*¨8Ô4Ü“-ˆCÜ˜cŸg™g hÓ/´×6Ò6Ø "��H‘Ø(0ˆC��M˜*Ñ%Ü˜Ô÷ )ð �d˜H hÐ/Ð/÷ )×(ús   •AA:Á:B
	N)r   r  rR   rS   )rZ   r0   rš   r  s   &f @r<   Úset_memory_providerr]    s2   ùé € ä.¨t¯}©}Ó=€Hö0ô ×"Ò" 4Ó(×(Ð(Ñ(ùs   „6Aº?»Az/api/memory/resetc                óF   € V ^8„  d   QhR\         R\        \        ,          /# r¬   )r   r	   r9   )r;   s   "r<   r=   r=     s   € ÷ 8ñ 8œ[ð 8´8¼Cµ=ñ 8r>   c              ƒ   óæ   a"  € V P                   ;'       g    R P                  4       P                  4       oSR9  d   \        RRR7      h\	        VR4      pV3R lp\        W4      G Rj  x€L
 #  L5i)Úallr\   z#target must be all, memory, or userr]   zPOST /api/memory/resetc            	      ó:  <€ \        4       R ,          p . p\         FR  w  r#W,          pSRV09   g   K  VP                  4       '       g   K0   VP                  4        VP	                  V4       KT  	  RRR	V/#   \
         d   p\        RRT RT 2R7      hRp?ii ; i)
rI  r`  r¤   zCould not delete z: r]   Nr`   TÚdeleted)r-   rM  rN  Úunlinkr  ÚOSErrorr   )rS  rb  rU  rÓ   rV  r¿   rl   s         €r<   rš   Úreset_memory.<locals>._run  sž   ø€ Ü!Ó# jÕ0ˆØˆß'‰JˆEØ•?ˆDØ˜% ˜Ö%¨$¯+©+¯-¬-ðdØ—K‘K”MØ—N‘N 5Ö)ñ (ð �d˜I wÐ/Ð/øô ô dÜ'°CÐBSÐTYÐSZÐZ\Ð]`Ð\aÐ@bÔcÐcûðdús   Á!A7Á7BÂBÂBN>   r`  ra   rH  )rl   rJ   rK   r   r#   r!   )rZ   r0   rš   rl   s   && @r<   Úreset_memoryrf    se   øé € à�k‰k×"Ð"˜U×)Ñ)Ó+×1Ñ1Ó3€FØÐ.Ô.Ü¨Ð4YÔZÐZÜ! 'Ð+CÓD€Gõ0ô )¨Ó7×7Ð7Ñ7ùs   ƒA'A1Á*A/Á+A1z/api/ops/doctorc                ó:   € V ^8„  d   QhR\         \        ,          /# rB   rC   )r;   s   "r<   r=   r=   4  s   € ÷ Iñ Iœh¤s�mñ Ir>   c              ƒ   ó,   "  € \        R .R RRV R7      # 5i)ÚdoctorzFailed to spawn doctorzFailed to run doctor©r5   r6   r0   ©r@   rH   s   &r<   Ú
run_doctorrl  3  s"   é € ä˜(˜ XÐ7OØ 6ÀôIð Iùs   ‚z/api/ops/security-auditc                ó:   € V ^8„  d   QhR\         \        ,          /# rB   rC   )r;   s   "r<   r=   r=   :  s   € ÷ ñ ¤h¬s¥mñ r>   c              ƒ   ó.   "  € \        R R.RRRV R7      # 5i)ÚsecurityÚauditzsecurity-auditzFailed to spawn security auditzFailed to run security auditrj  rk  rH   s   &r<   Úrun_security_auditrq  9  s&   é € äØ	�WÐÐ/Ø0Ð9WÐahôð ùs   ‚c                óF   € V ^8„  d   QhR\         \        ,          R\        /# )r2   r0   r7   )r	   r9   r   )r;   s   "r<   r=   r=   A  s   € ÷ -ñ -¤8¬C¥=ð -¼Dñ -r>   c                óˆ   € \        V 4      ;_uu_ 4        \        4       R,          uuRRR4       #   + '       g   i     R# ; i)uN   ``<profile home>/backups`` â€” the archive belongs to the profile it backs up.ÚbackupsN)r)   r-   rH   s   &r<   Ú_dashboard_backup_dirru  A  s'   € ä	˜w×	'Õ	'ÜÓ  9Õ,÷ 
(×	'×	'Ó	'ús	   ”0°A	z/api/ops/backupc                óF   € V ^8„  d   QhR\         R\        \        ,          /# r¬   )r   r	   r9   )r;   s   "r<   r=   r=   H  s   € ÷ ñ œ=ð ´8¼Cµ=ñ r>   c              ƒ   óî  "  € R pV P                   ;'       g    RP                  4       pV'       g{   \        P                  ! 4       P	                  R4      p\        V4      RV R\        P                  ! ^4       R2,          p VP                  P                  RRR7       \        T4      p\        RRV.RRRVR7      pVe   \        V4      VR&   V#   \         d   p\        RR	T 2R
7      hR p?ii ; i5i)NrF   z%Y-%m-%d-%H%M%Szhermes-backup-r³   ú.zipT©ÚparentsÚexist_okr¤   z#Could not create backup directory: r]   Úbackupz-ozFailed to spawn backupzFailed to run backuprj  Úarchive)ÚoutputrJ   r   ÚnowrÉ   ru  rÆ   Ú	token_hexÚparentÚmkdirrd  r   r9   r@   )rZ   r0   r}  r~  Ústampr¿   Úresponses   &&     r<   Ú
run_backupr…  G  só   é € à"€GØ�k‰k×Ð˜R×&Ñ&Ó(€FßÜ—’“×'Ñ'Ð(9Ó:ˆÜ'¨Ó0°^ÀEÀ7È!ÌG×L]ÒL]Ð^_ÓL`ÐKaÐaeÐ3fÕfˆð	eØ�N‰N× Ñ ¨¸Ð Ô=ô �W“ˆÜ˜h¨¨fÐ5°xÐIaØ$:ÀGôM€HàÒÜ! '›lˆ�ÑØ€Oøô ô 	eÜ¨CÐ:]Ð^aÐ]bÐ8cÔdÐdûð	eüs/   ‚.C5±AC5ÂC Â 2C5ÃC2ÃC-Ã-C2Ã2C5z/api/ops/backup/downloadc                óF   € V ^8„  d   QhR\         R\        \         ,          /# )r2   r}  r0   rÖ   )r;   s   "r<   r=   r=   [  s   € ÷ ñ ¬Sð ¼8ÄC½=ñ r>   c              ƒ   óè  "  €  \        V4      P                  4       P                  R R7      p\        V 4      P                  4       P                  RR7      p\        Y#4      '       g   \        RR	R7      hTP                  4       '       g   \        RRR7      h\        \        T4      R
TP                  RR7      #   \         d    \        RRR7      h\        \        3 d    \        RRR7      hi ; i5i)F)ÚstrictTrb   zBackup not foundr]   r\   zInvalid backup pathi“  z0Backup is outside the dashboard backup directoryzapplication/zipÚ
attachment)rV  Ú
media_typeÚfilenameÚcontent_disposition_type)ru  Ú
expanduserÚresolver   ÚFileNotFoundErrorr   rd  ÚRuntimeErrorr   Úis_filer   r9   r4   )r}  r0   Ú
backup_dirrl   s   &&  r<   Údownload_dashboard_backupr“  Z  sß   é € ðKÜ*¨7Ó3×>Ñ>Ó@×HÑHÐPUÐHÓVˆ
Ü�g“×)Ñ)Ó+×3Ñ3¸4Ð3Ó@ˆô ˜*×-Ò-Ü¨Ð4fÔgÐgØ�>‰>×ÒÜ¨Ð4FÔGÐGÜÜ�‹[Ð%6ÀÇÁÐgsôð øô ô HÜ¨Ð4FÔGÐGÜ”\Ð"ô KÜ¨Ð4IÔJÐJðKüs)   ‚C2„AB9 Á3C2Â
/C2Â9&C/Ã C/Ã/C2c                ó^   € V ^8„  d   QhR\         R\        R\        \         ,          R\        /# )r2   r}  Úforcer0   r7   )r9   rf   r	   r:   )r;   s   "r<   r=   r=   m  s2   € ÷ Iñ Iœ3ð I¤tð I´h¼sµmð IÌtñ Ir>   c                 ó\   € R V .pV'       d   VP                  R4       \        VR RRVR7      # )Úimportz--forcezFailed to spawn importzFailed to run importrj  )r  r@   )r}  r•  r0   Úargss   &&& r<   Ú_spawn_importr™  m  s6   € Ø�gÐ€DßØ�‰�IÔÜ˜˜xÐ1IØ 6ÀôIð Ir>   z/api/ops/importc                óF   € V ^8„  d   QhR\         R\        \        ,          /# r¬   )r   r	   r9   )r;   s   "r<   r=   r=   v  s   € ÷ 7ñ 7œ=ð 7´8¼Cµ=ñ 7r>   c              ƒ   ó*  "  € \        VR 4      pV P                  ;'       g    RP                  4       pV'       g   \        RRR7      h\        P
                  P                  V4      '       g   \        RRV 2R7      h\        W P                  V4      # 5i)zPOST /api/ops/importrF   r\   zarchive path is requiredr]   rb   zArchive not found: )	r#   r}  rJ   r   ÚosrV  Úisfiler™  r•  )rZ   r0   r}  s   && r<   Ú
run_importrž  u  sv   é € ä! 'Ð+AÓB€GØ�|‰|×!Ð!˜r×(Ñ(Ó*€GßÜ¨Ð4NÔOÐOÜ�7‰7�>‰>˜'×"Ò"Ü¨Ð6IÈ'ÈÐ4SÔTÐTÜ˜§*¡*¨gÓ6Ð6ùs   ‚8B»1BÁ-&Bc                ó>   € V ^8„  d   QhR\         R,          R\         /# )r2   r‹  Nr7   )r9   )r;   s   "r<   r=   r=   €  s   € ÷ ñ ¤s¨T¥zð ´cñ r>   c                 ó  € \        T ;'       g    R 4      P                  P                  4       p\        P                  ! RRV4      P                  R4      ;'       g    R pVP                  4       P                  R4      '       g   V R2pV# )z
backup.zipz[^A-Za-z0-9._-]+r³   z.-rx  )r   r4   rJ   rÄ   ÚsubrK   Úendswith)r‹  r4   s   & r<   Ú_safe_backup_upload_namer£  €  sp   € Ü�×(Ð(˜LÓ)×.Ñ.×4Ñ4Ó6€DÜ�6Š6Ð% s¨DÓ1×7Ñ7¸Ó=×MÐMÀ€DØ�:‰:‹<× Ñ  ×(Ò(Ø��tˆ}ˆØ€Kr>   z/api/ops/import-upload.c                óR   € V ^8„  d   QhR\         R\        R\        \        ,          /# )r2   Úfiler•  r0   )r   rf   r	   r9   )r;   s   "r<   r=   r=   ‰  s/   € ÷ kñ kÜ
ðkäðkô ”c�]ñkr>   c           	   ƒ   ó^  "  € \        VR 4      p\        V4      p VP                  RRR7       \
        P                  ! \        4      P                  R4      pTRT R	\        P                  ! ^4       R	\        T P                  4       2,          p\        YR
RRR7      G Rj  x€L
 p\        P                  ! T4      '       g    TP!                  RR7       \	        RRR7      h/ \#        \%        T4      Y4      CR\%        T4      RT/C#   \         d   p\	        RRT 2R7      hRp?ii ; i Lˆ5i)zPOST /api/ops/import-uploadTry  r¤   z+Could not create import staging directory: r]   Nz%Y%m%d-%H%M%Szdashboard-import-r³   zArchive is too largez(Import staging directory is not writablez Could not write uploaded archive)Ú	too_largeÚnot_writableÚwrite_failed)Ú
missing_okr\   z(Uploaded archive is not a valid zip filer}  Úuploaded_bytes)r#   ru  r‚  rd  r   r   r  r   rÉ   rÆ   r€  r£  r‹  r&   ÚzipfileÚ
is_zipfilerc  r™  r9   )r¥  r•  r0   Ústaging_dirr¿   rƒ  rl   Útotals   &&&     r<   Úrun_import_uploadr°  ˆ  s+  é € ô " 'Ð+HÓI€GÜ'¨Ó0€KðiØ×Ñ $°ÐÔ6ô �LŠLœÓ×&Ñ& Ó7€EØÐ.¨u¨g°Q´w×7HÒ7HÈÓ7KÐ6LÈAÔNfÐgk×gtÑgtÓNuÐMvÐwÕw€FÜ'ØÐ 6Ø?ÐNpô÷ €Eô ×Ò˜f×%Ò%Ø�‰ ˆÔ&Ü¨Ð4^Ô_Ð_ØjŒmœC ›K¨Ó8Ðj¸)ÄSÈÃ[ÐRbÐdiÑjÐjøô ô iÜ¨Ð6aÐbeÐafÐ4gÔhÐhûðiúñ
ùs;   ‚D-›D ®A4D-Â"D+Â#D-ÃAD-ÄD(ÄD#Ä#D(Ä(D-z/api/ops/hooksc                ó:   € V ^8„  d   QhR\         \        ,          /# rB   rC   )r;   s   "r<   r=   r=   ¢  s   € ÷ %8ñ %8œh¤s�mñ %8r>   c              ƒ  ó:   "  € R p\        W4      G Rj  x€L
 #  L5i)z‹Configured shell hooks with consent (allowlist) status, whether the
script is currently executable, and the valid hook events for the form.c                  óª  € ^ RI Hp  ^ RIHp . p\        P
                  ! \        4      ;_uu_ 4        ^ RIHp \        V4      pRRR4       . p VP                  V ! 4       4      p. pV EF  pRpRp\        P
                  ! \        4      ;_uu_ 4        VP                  VP                  VP                  4      pRRR4       \        P
                  ! \        4      ;_uu_ 4        VP!                  VP                  4      pRRR4       TP#                  RVP                  RVP$                  R	VP                  R
VP&                  RVRJRT;'       g    / P)                  R4      RV/4       EK  	  RVRV/#   + '       g   i     EL:; i  \         d    \        P                  R4        ELGi ; i  + '       g   i     Lþ; i  + '       g   i     LË; i)r‘   )r.   ©Úshell_hooks©ÚVALID_HOOKSNziter_configured_hooks failedFÚeventÚmatcherÚcommandÚtimeoutÚallowedÚapproved_atÚ
executableÚhooksÚvalid_events)Úhermes_cli.configr.   Úagentrµ  Ú
contextlibr?  r  Úhermes_cli.pluginsr·  r  Úiter_configured_hooksr  r  Úallowlist_entry_forr¸  rº  Úscript_is_executabler  r¹  r»  rŒ   )	Ú_load_configrµ  rÀ  r·  ÚspecsÚoutÚspecrø   r¾  s	            r<   rš   Úlist_hooks.<locals>._run¥  sg  € ÝAÝ%àˆÜ× Ò ¤×+Õ+Ý6Ü! +Ó.ˆL÷ ,ð ˆð	;Ø×5Ñ5±l³nÓEˆEð ˆÜˆDØˆEØˆJÜ×$Ò$¤Y×/Õ/Ø#×7Ñ7¸¿
¹
ÀDÇLÁLÓQ�÷ 0ä×$Ò$¤Y×/Õ/Ø(×=Ñ=¸d¿l¹lÓK�
÷ 0à�J‰JØ˜Ÿ™Ø˜4Ÿ<™<Ø˜4Ÿ<™<Ø˜4Ÿ<™<Ø˜5¨Ð,Ø § ¨×0Ñ0°Ó?Ø˜jð÷ ñ ð  ˜˜n¨lÐ;Ð;÷7 ,×+Ð+ûô ô 	;Ü�N‰NÐ9×:ð	;ú÷ 0×/úç/×/ús5   ±E4ÁF Â'F/Ã#GÅ4F	Æ F,Æ+F,Æ/F?ÇGNrœ   r�   s   & r<   Ú
list_hooksrÍ  ¡  s   é € ò <ôD )¨Ó7×7Ð7Ñ7ùrŸ   c                óF   € V ^8„  d   QhR\         \        \        3,          /# )r2   r7   )Útupler9   )r;   s   "r<   r=   r=   Ê  s   € ÷ ñ œu¤S¬# X�ñ r>   c                 óÒ   € V P                   ;'       g    R P                  4       pV P                  ;'       g    R P                  4       pV'       d	   V'       g   \        RRR7      hW3# )rF   r\   zevent and command are requiredr]   )r¸  rJ   rº  r   )rZ   r¸  rº  s   &  r<   Ú_hook_body_fieldsrÑ  Ê  sQ   € Ø�Z‰Z×Ð˜2×$Ñ$Ó&€EØ�|‰|×!Ð!˜r×(Ñ(Ó*€GßŸÜ¨Ð4TÔUÐUØˆ>Ðr>   c                óF   € V ^8„  d   QhR\         R\        \        ,          /# r¬   )r   r	   r9   )r;   s   "r<   r=   r=   Ó  s   € ÷ /8ñ /8œJð /8´¼#µñ /8r>   c              ƒ  óŒ  a aaaa"  € ^ RI Ho \        SR4      o\        S 4      w  ooRp\        P
                  ! \        4      ;_uu_ 4        ^ RIHp RRR4       Ve3   SV9  d,   \        RRS RRP                  \        V4      4       2R	7      hV VVVV3R
 lp\        SV4      G Rj  x€L
 #   + '       g   i     Ld; i L5i)a  Add a shell hook to config.yaml and optionally record consent.

Shell hooks run arbitrary commands, so this is privileged: it writes the
``hooks:`` block and, with ``approve``, records the allowlist entry so the
hook actually fires. Takes effect on the next session / gateway restart.
r´  zPOST /api/ops/hooksNr¶  r\   zUnknown event 'z
'. Valid: z, r]   c                  óª  <€ \        S4      ;_uu_ 4        \        4       p V P                  R 4      p\        V\        4      '       g   / ;qR &   VP                  S4      p\        V\
        4      '       g   . ;q!S&   RS/pSP                  '       d   SP                  VR&   SP                  e   \        SP                  4      VR&   VP                  V4       \        V 4       RRR4       RpSP                  '       d    S	P                  SS4       RpRRR	SRSR
V/#   + '       g   i     LC; i  \         d    \        P                  R4        L?i ; i)r¿  rº  r¹  Nr»  FTzhook consent record failedr`   r¸  rQ   )r"   r.   rŒ   rL  r:   r8   r¹  r»  rú   r  r/   ÚapproveÚ_record_approvalr  r  r  )
rQ  Ú	hooks_cfgr  Ú	new_entryrQ   rZ   rº  r¸  r0   rµ  s
        €€€€€r<   rš   Úcreate_hook.<locals>._runè  s$  ø€ Ü ×(Õ(Ü“-ˆCØŸ™ Ó(ˆIÜ˜i¬×.Ò.Ø+-Ð-�	 ™LØ—m‘m EÓ*ˆGÜ˜g¤t×,Ò,Ø-/Ð/� EÑ*Ø)2°GÐ(<ˆIØ�|�|ˆ|Ø'+§|¡|�	˜)Ñ$Ø�|‰|Ò'Ü'*¨4¯<©<Ó'8�	˜)Ñ$Ø�N‰N˜9Ô%Ü˜Ô÷ )ð  ˆØ�<�<ˆ<ð=Ø×,Ñ,¨U°GÔ<Ø�ð �d˜G U¨I°wÀ
ÈHÐUÐU÷/ )×(ûô* ô =Ü—‘Ð;Ö<ð=ús%   •A:DÂADÃ>D/ ÄD,	Ä/ EÅE)rÂ  rµ  r#   rÑ  rÃ  r?  r  rÄ  r·  r   Újoinr  r!   )rZ   r0   Úvalid_hooksrš   rº  r¸  rµ  s   ff  @@@r<   Úcreate_hookrÜ  Ò  s­   üé € õ "ô " 'Ð+@ÓA€GÜ& tÓ,�N€Eˆ7Ø€KÜ	×	Ò	œY×	'Õ	'ÝA÷ 
(àÒ 5°Ô#;Ü¨°oÀeÀWÈJÐW[×W`ÑW`ÔagÐhsÓatÓWuÐVvÐ4wÔxÐx÷Vñ Vô4 )¨°$Ó7×7Ð7÷? 
(×	'úñ> 8ùs+   ‡ACÁB/ÁACÂ*CÂ+CÂ/B?	Â:	Cc                óF   € V ^8„  d   QhR\         R\        \        ,          /# r¬   )r   r	   r9   )r;   s   "r<   r=   r=     s   € ÷ ñ œJð ´¼#µñ r>   c              ƒ  ó¾   aaaa"  € ^ RI Ho \        SR4      o\        V 4      w  ooVVVV3R lp\	        SV4      G Rj  x€L
 '       g   \        RRR7      hRR	/#  L5i)
zFRemove a hook from config.yaml and revoke its consent allowlist entry.r´  zDELETE /api/ops/hooksc            	      ó  <€ R p \        S4      ;_uu_ 4        \        4       pVP                  R4      p\        V\        4      '       dÎ   \        VP                  S4      \
        4      '       d©   \        VS,          4      pVS,           Uu. uF3  p\        V\        4      '       d   VP                  R4      S8X  d   K1  VNK5  	  upVS&   \        VS,          4      V8  p VS,          '       g   VS V'       g   VP                  RR4       \        V4       RRR4       \        P                  ! \        4      ;_uu_ 4        SP                  S4       RRR4       V # u upi   + '       g   i     LS; i  + '       g   i     T # ; i)Fr¿  rº  N)r"   r.   rŒ   rL  r:   r8   r+  Úpopr/   rÃ  r?  r  rt   )	r@  rQ  r×  ÚbeforerÌ   rº  r¸  r0   rµ  s	        €€€€r<   rš   Údelete_hook.<locals>._run  s.  ø€ ØˆÜ ×(Õ(Ü“-ˆCØŸ™ Ó(ˆIÜ˜)¤T×*Ò*¬z¸)¿-¹-ÈÓ:NÔPT×/UÒ/UÜ˜Y uÕ-Ó.�à(¨Ö/ó$Ù/˜!Ü& q¬$×/Ò/°A·E±E¸)Ó4DÈÑ4O÷ �AÑ/ñ$�	˜%Ñ ô ˜i¨Õ.Ó/°&Ñ8�Ø  ×'Ô'Ø! %Ð(ß Ø—G‘G˜G TÔ*Ü˜CÔ ÷ )ô  × Ò ¤×+Õ+Ø×Ñ˜wÔ'÷ ,àˆùò$÷ )×(ú÷  ,Ö+àˆús6   —A4E!Â.EÂ>EÃ4E!Ã9E!Å E4ÅE!Å!E1	Å4F	Nrb   zNo matching hook foundr]   r`   T)rÂ  rµ  r#   rÑ  r!   r   )rZ   r0   rš   rº  r¸  rµ  s   &f @@@r<   Údelete_hookrã    s_   ûé € õ "ä! 'Ð+BÓC€GÜ& tÓ,�N€Eˆ7÷ð ô, )¨°$Ó7×7Ö7Ü¨Ð4LÔMÐMØ�$ˆ<Ðñ 8ùs   †9A¿AÁ 	AÁ
Az/api/ops/checkpointsc                ó:   € V ^8„  d   QhR\         \        ,          /# rB   rC   )r;   s   "r<   r=   r=   )  s   € ÷ 8ñ 8¤H¬S¥Mñ 8r>   c              ƒ  ó:   "  € R p\        W4      G Rj  x€L
 #  L5i)zÇ/rollback shadow-store checkpoints (read-only): count + size per session
so the UI can show what a prune reclaims; pruning itself is a spawned CLI
action so the confirmation logic stays in one place.c            	      ót  € \        4       R ,          p . p^ pV P                  4       '       dä   \        P                  ! V 4      ;_uu_ 4       p\	        R V 4       R R7      pRRR4       X F¡  pVP                  4       '       g   K  ^ ;rgVP                  R4       FE  pVP                  4       '       g   K   WhP                  4       P                  ,          pV^,          pKG  	  W&,          pVP                  RVP                  RVRV/4       K£  	  R	VR
V/#   + '       g   i     L½; i  \         d     K�  i ; i)Úcheckpointsc              3   óL   "  € T F  p\        VP                  4      x € K  	  R # 5ir¯   )r   rV  )Ú.0rÌ   s   & r<   Ú	<genexpr>Ú1list_checkpoints.<locals>._run.<locals>.<genexpr>3  s   é € Ð">¹°A¤4¨¯©§< <»ùs   ‚"$c                 ó   € V P                   # r¯   )r4   )Úps   &r<   Ú<lambda>Ú0list_checkpoints.<locals>._run.<locals>.<lambda>3  s   € ÈaÏfÊfr>   )rÓ   NÚ*ÚsessionrT  ÚbytesÚsessionsÚtotal_bytes)r-   Úis_dirrœ  Úscandirr  Úrglobr‘  rO  rP  rd  r  r4   )	Úcp_dirró  rô  ÚscanÚchildrenÚchildÚsizer*  Úfs	            r<   rš   Úlist_checkpoints.<locals>._run-  s  € Ü Ó" ]Õ2ˆØˆØˆØ�=‰=�?Š?Ü—’˜F×#Ô# tÜ!Ñ">¹Ó">ÑDTÔU�÷ $ã!�Ø—|‘|—~’~ÙØ Ð �ØŸ™ SÖ)�AØ—y‘y—{”{ð!Ø §F¡F£H×$4Ñ$4Õ4˜DØ! Q�JšEñ	 *ð Õ#�Ø—‘ ¨E¯J©J¸ÀÈÐQUÐ VÖWñ "ð ˜H m°[ÐAÐA÷ $×#ûô  'ô !Ú ð!ús   Á
DÂ5)D(ÄD%	Ä(D7Ä6D7Nrœ   r�   s   & r<   Úlist_checkpointsrÿ  (  s   é € ò
Bô, )¨Ó7×7Ð7Ñ7ùrŸ   z/api/ops/checkpoints/prunec                ó:   € V ^8„  d   QhR\         \        ,          /# rB   rC   )r;   s   "r<   r=   r=   G  s   € ÷ ñ ¤X¬c¥]ñ r>   c           
   ƒ   óB   "  € \        R R.RRR\        V R4      R7      # 5i)rç  Úprunezcheckpoints-prunez!Failed to spawn checkpoints prunezFailed to prune checkpointszPOST /api/ops/checkpoints/prunerj  )r@   r#   rH   s   &r<   Úprune_checkpointsr  F  s.   é € äØ	˜Ð Ð"5Ø3Ð<YÜ# GÐ-NÓOôð ùs   ‚r¯   )NF))z	MEMORY.mdrH  )zUSER.mdra   )pÚ__doc__rR   rÃ  Úloggingrœ  rÄ   rÆ   rÈ   r¬  r   r   r   Úpathlibr   Útypingr   r   r   r	   Úfastapir
   r   r   r   r   Úfastapi.responsesr   rÁ  r   Úhermes_cli.web_depsr   Úhermes_cli.web_server_filesr   rí   r   Úhermes_cli.web_server_memoryr   r   Úhermes_cli.web_modelsr   r   r   r   r   r   r   r   r   r   r    Úhermes_cli.web_routers._commonr!   r"   r#   r$   r%   Úhermes_cli.web_routers.filesr&   Ú	getLoggerr  Úrouterr'   r(   r)   r*   r+   r,   r-   r.   r/   r@   rM   rŒ   rW   Úpostro   ru   rz   r�   rž   rª   rÏ   rÔ   Údeleterß   Úputrç   rð   rö   r  r  r5  rD  rM  rX  r]  rf  rl  rq  ru  r…  r“  r™  rž  r£  r°  rÍ  rÑ  rÜ  rã  rÿ  r  © r>   r<   Ú<module>r     s¶  ðñó Û Û Û 	Û 	Û Û Û ß ,Ñ ,Ý ß ,Ó ,ç DÕ DÝ *å (Ý $Ý 6Ý @ß h÷÷ ÷ ñ ÷õ õ ?à×ÒÐ0Ó1€Ù	‹€ñ &*Ð*NÐPnÓ%oÐ "ÙÐ0Ð2QÓRÐ ÙÐ4Ð6VÓWÐ ÙÐ2Ð4TÓUÐ ÙÐ2Ð4SÓTÐ ÙÐ8Ð:[Ó\Ð ÙÐ(Ð*=Ó>€Ù�=Ð"5Ó6€Ù�=Ð"5Ó6€ðUØ+/÷U÷+ð$ ‡�ˆNÓögó ðgð ‡�Ð#Ó$ôó %ðð8 ‡�Ð"Ó#ôsó $ðsð ‡�Ð)Ó*öcó +ðcõð$ ‡�ˆOÓö8ó ð8ð" ‡�Ð#Ó$öó %ðð" ‡�ˆ_Óö4ó ð4õnð ‡�Ð%Ó&öó 'ðð ‡�Ð*Ó+öDó ,ðDð* ‡�Ð!Ó"ö	Bó #ð	Bð ‡�Ð Ó!öAó "ðAõ.ð$ ‡�Ð#Ó$ö8ó %ð8ð8 ‡�Ð$Ó%ö68ó &ð68ðr ‡�Ð9Ó:ö1_ó ;ð1_ðp ?€ð ‡�ˆMÓö8ó ð8ð ‡�Ð"Ó#ö)ó $ð)ð( ‡�Ð Ó!ö8ó "ð8ð6 ‡�ÐÓöIó  ðIð
 ‡�Ð&Ó'öó (ð÷-ð ‡�ÐÓöó  ðð$ ‡�Ð&Ó'öó (ð÷$Ið ‡�ÐÓö7ó  ð7õð ‡�Ð%Ó&á˜C“yÙ�u“+Ø!ökó 'ðkð0 ‡�ÐÓö%8ó ð%8õPð ‡�ÐÓö/8ó ð/8ðd ‡�ÐÓ öó !ððD ‡�Ð"Ó#ö8ó $ð8ð: ‡�Ð)Ó*öó +òr>   