+
    jHàj°  ã                   óP  € 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 ^ RIHt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 ^ RIH t  ^ R	I!H"t" ^ R
I#H$t$H%t% ^ RI&H't' ^ RI(H)t)H*t* ^ RI+H,t,H-t-H.t.H/t/ ^ RI0H1t1H2t2H3t3 ^ RI4H5t5 ^ RI6H7t7H8t8H9t9 ]Pt                  ! R4      t;]! 4       t<]! 4       t=]! RR4      t>]! RR4      t?]! RR4      t@]! RR4      tA]! RR4      tB]! R4      tC]! RR4      tD]! RR4      tE]! RR4      tF]! R4      tG]! R 4      tH]! R!R"4      tI]! R#R"4      tJ]! R$R4      tK]! R%4      tL]! R&R'4      tM]! R(R'4      tN]! R)R*4      tO]! R+R"4      tP]! R,R'4      tQ]! R-R.4      tRR/tSR0tT0 RŽmtUR1 R2 ltVR3 R4 ltWR5 R6 ltX]<P³                  R74      R8 R9 l4       tZ]<P³                  R:4      R; 4       t[]<P³                  R<4      R= R> l4       t\]<P³                  R?4      R@ RA l4       t]]<P½                  RB4      RC RD l4       t_]PÀ                  ! RE4      taRF RG ltbRH RI ltc]d! RJRK04      teRL RM ltfRN RO ltgRP thRQ RR ltiRS RT ltjRU RV ltkRW RX ltlRY RZ ltmR[ R\ ltn]<P³                  R]4      R�R^ R_ ll4       to]<P³                  R`4      Ra 4       tp]<P³                  Rb4      R�Rc Rd ll4       tq]<På                  Re4      R�Rf Rg ll4       tsR�Rh Ri lltt]<P½                  Rj4      R�Rk Rl ll4       tu]<P³                  Rm4      R�Rn Ro ll4       tvRp Rq ltw]<P³                  Rr4      R�Rs Rt ll4       tx]<Pó                  Rr4      R�Ru Rv ll4       tz]<På                  Rr4      R�Rw Rx ll4       t{]<P³                  Ry4      R�Rz R{ ll4       t|R| R} lt}R~ t~]<P½                  R4      R�R€ R� ll4       t]<P½                  R‚4      R�Rƒ R„ ll4       t€]<P½                  R…4      R�R† R‡ ll4       t�]<P½                  Rˆ4      R�R‰ RŠ ll4       t‚]=P³                  R‹4      R‘RŒ R� ll4       tƒR# )’a  Status dashboard routes: health, /api/status, system stats, curator, learning graph,
portal and diagnostics actions.

Extracted from ``hermes_cli.web_server``; app state and helpers are late-bound through
:mod:`hermes_cli.web_deps` (cycle-safe, monkeypatch-friendly).
N)Ú	APIRouter)Ú	LateStateÚlate)Ú_display_system_platform)Úrun_in_threadpool)ÚHTTPExceptionÚRequest)	Úderive_gateway_busyÚderive_gateway_drainableÚnormalize_updated_atÚparse_active_agentsÚ"profile_platforms_from_multiplexerÚresolve_gateway_livenessÚretained_gateway_stateÚruntime_status_heartbeat_age_sÚruntime_status_is_stale)Úlocal_liveness_pid)Ú__release_date__)Úget_config_pathÚget_env_path)Úget_version_info)Úget_process_hermes_homeÚprofile_name_for_home)ÚCuratorPauseÚLearningNodeRefÚLearningNodeEditÚDebugShareRequest)Úconfig_scoped_to_threadÚdestructive_profileÚscoped_to_thread)ÚPath)ÚAnyÚDictÚOptionalzhermes_cli.web_serverÚ(_collect_profile_gateway_topology_cachedzhermes_cli.web_server_gatewayÚ_config_profile_scopezhermes_cli.web_server_profilesÚ*_dashboard_local_update_managed_externallyzhermes_cli.web_server_filesÚ"_load_configured_gateway_platformsÚ_probe_gateway_healthÚ_require_tokenÚ_resolve_profile_dirÚ_resolve_restart_drain_timeoutzhermes_cli.web_server_lifecycleÚ_spawn_hermes_actionÚ_ssh_runtime_intactÚappÚcheck_config_versionzhermes_cli.configÚget_hermes_homeÚ_profile_cli_argsÚget_install_idÚget_running_pid_cachedzgateway.statusÚget_runtime_status_running_pidÚserved_profile_runtimezgateway.status_servedÚload_configÚread_runtime_statusÚ_open_session_db_for_profilezhermes_cli.web_server_sessionsg      è?g      ð?c                ó$   € V ^8„  d   QhR\         /# )é   Úfn_name©Ústr)Úformats   "ÚB/home/ubuntu/.hermes/hermes-agent/hermes_cli/web_routers/status.pyÚ__annotate__r@   F   s   € ÷ ñ œSñ ó    c                 óv   €  \        WR 4      p\        V4      '       d   V! 4       # T#   \         d    Tu # i ; i©N)ÚgetattrÚcallableÚ	Exception)Úmodr;   ÚdefaultÚfns   &&& r?   Ú
_safe_callrJ   F   s<   € ðÜ�S 4Ó(ˆÜ —|’|‰r‹tÐ0¨Ð0øÜô ØŠðús   ‚#( ¦( ¨8·8c                ó$   € V ^8„  d   QhR\         /# ©r:   Úreturn©Úint)r>   s   "r?   r@   r@   N   s   € ÷ ñ ¤sñ rA   c                 ó<  a€ ^ RI Hp  \        V ! 4       4      P                  4       '       g   ^ # \	        RRR7      p VP                  ^2RR7      p\        P                  ! 4       o\        V3R lV 4       4      VP                  4        #   TP                  4        i ; i)z¦Best-effort status garnish. Opens read-only (via the shared stale-schema heal) so
/api/status never routinely writes to state.db while another Hermes process uses it.)Ú_default_db_pathNT)Ú	read_only)ÚlimitÚcompact_rowsc           	   3   ó°   <"  € T FK  qP                  R 4      e   K  SVP                  RVP                  R^ 4      4      ,
          R8  g   KG  ^x € KM  	  R# 5i)Úended_atNÚlast_activeÚ
started_ati,  ©Úget)Ú.0ÚsÚnows   & €r?   Ú	<genexpr>Ú0_count_status_active_sessions.<locals>.<genexpr>Z   sG   øé € ð S™h˜¯%©%°
Ó*;”1Ø˜aŸe™e M°1·5±5¸ÀqÓ3IÓJÕJÈcÑQ÷ ’1›hùs   ƒAœ+AÁ
A)	Úhermes_staterQ   r    Úexistsr8   Úlist_sessions_richÚtimeÚsumÚclose)rQ   ÚdbÚsessionsr]   s      @r?   Ú_count_status_active_sessionsrh   N   s‚   ø€ õ .ô Ñ Ó"Ó#×*Ñ*×,Ò,ÙÜ	% d°dÔ	;€BðØ×(Ñ(¨rÀÐ(ÓEˆÜ�iŠi‹kˆÜô S™hó Só Sð 	�‰�
øˆ�‰�
ús   ¼<B	 Â	Bc                ó$   € V ^8„  d   QhR\         /# rL   rN   )r>   s   "r?   r@   r@   `   s   € ÷ 
ñ 
¤sñ 
rA   c               ƒ   ó  "  €  \         P                  ! \        \        4      \        R 7      G Rj  x€L
 #  L  \
         d    \        P                  R\        4        ^ # \         d"   p \        P                  RT 4        Rp ? ^ # Rp ? ii ; i5i)©ÚtimeoutNz</api/status active session count exceeded %.2fs; returning 0z0/api/status active session count unavailable: %s)	ÚasyncioÚwait_forr   rh   Ú_STATUS_ACTIVE_SESSIONS_TIMEOUTÚTimeoutErrorÚ_logÚdebugrF   )Úexcs    r?   Ú_status_active_sessionsrt   `   s}   é € ðLÜ×%Ò%ÜÔ;Ó<Ü3ô5÷ 5ð 	5ñ 5øô ô 4Ü�
‰
ÐQÜ2õ	4ñ ô ô LÜ�
‰
ÐEÀs×KÐKÙûðLüsI   ‚B„,7 °5±7 ´Bµ7 ·%B
ÁBÁB
Á(B
Á)BÁ?BÂB
Â
Bz/api/ssh/ownershipc                ó$   € V ^8„  d   QhR\         /# ©r:   Úrequest©r   )r>   s   "r?   r@   r@   n   s   € ÷ 4ñ 4¤Wñ 4rA   c           	   ƒ   óz   "  € ^ RI Hp \        V 4       V'       g   \        RRR7      hRRRVR^R	\	        4       /# 5i)
é    )Ú_SSH_OWNER_NONCEé”  zSSH ownership is not active©Ústatus_codeÚdetailÚokTÚsshOwnerNonceÚprotocolVersionÚruntimeIntact)Úhermes_cli.web_serverr{   r)   r   r-   )rw   r{   s   & r?   Úget_ssh_ownershipr…   m   sC   é € å6Ü�7ÔßÜ¨Ð4QÔRÐRØ�$˜Ð)9Ð;LÈaØÔ0Ó2ð4ð 4ùs   ‚9;z/api/healthc               ƒ  ó¶   "  € \        4       p RRRV P                  RV P                  RV P                  R\	        \        \        P                  RR4      4      /# 5i)a>  Lightweight process liveness for desktop/backend readiness probes.

``commit`` is the code this process BOOTED from (``get_version_info`` is cached at
``web_server`` import): Desktop refuses to attach to a backend whose commit differs from
its checkout, so a serve that outlived ``hermes update`` is never re-adopted.
r€   TÚversionÚdisplayVersionÚcommitÚauth_requiredF)r   Úbase_versionÚdisplay_versionr‰   ÚboolrD   r.   Ústate)Úinfos    r?   Ú
get_healthr�   w   sU   é € ô Ó€DØ�$˜	 4×#4Ñ#4Ð6FÈ×H\ÑH\Ø�d—k‘kØœT¤'¬#¯)©)°_ÀeÓ"LÓMðOð Oùs   ‚AAz/api/host/identityc                ó$   € V ^8„  d   QhR\         /# rv   rx   )r>   s   "r?   r@   r@   †   s   € ÷ Hñ H¤Wñ HrA   c              ƒ  óè   "  € \        V 4       RRR^R\        P                  ! 4       R\        \        P
                  RR4      ;'       g    RR	\        \        \        P
                  R
R4      4      /# 5i)a  Prove to an attaching `hermes serve`/`dashboard` WHO owns this port.

The host rendezvous record names a (pid, port) owner, but a record cannot say whether that
owner still holds the port: a graceful-shutdown window or an unrelated listener that
inherited the port both look identical on disk. The attaching side dials this endpoint with
the owner's 0600 token and attaches only when pid+role match. ``servesSpa`` is false for
headless ``serve``, so a `hermes dashboard` user is never routed to a backend with no UI.
r€   Tr‚   ÚpidÚroleÚ	host_roleNÚserveÚ	servesSpaÚ
serves_spaF)r)   ÚosÚgetpidrD   r.   rŽ   r�   )rw   s   &r?   Úget_host_identityr›   …   sb   é € ô �7Ôð �$Ð)¨1¨e´R·Y²Y³[Ø”GœCŸI™I {°DÓ9×DÐD¸WØœœg¤c§i¡i°¸uÓEÓFðHð Hùs   ‚A0A2z/api/health/idlec                ó$   € V ^8„  d   QhR\         /# rv   rx   )r>   s   "r?   r@   r@   ™   s   € ÷ (ñ (¤7ñ (rA   c              ƒ  óB   "  € ^ RI Hp \        V 4       RR/V! 4       C# 5i)zYToken-gated diagnostic snapshot; never a retirement permit. None means cannot prove idle.)Ú
idle_proofr€   T)Ú hermes_cli.web_server_idle_proofrž   r)   )rw   rž   s   & r?   Úget_health_idler    ˜   s$   é € õ <Ü�7ÔØ�$Ð'™*›,Ð'Ð'ùs   ‚z/api/health/retirementc                ó$   € V ^8„  d   QhR\         /# rv   rx   )r>   s   "r?   r@   r@   ¡   s   € ÷ .ñ .¬'ñ .rA   c              ƒ   ó  "  € ^ RI Hp \        V 4        V P                  4       G Rj  x€L
 p\        T\        4      '       d   TP                  R4      R9  d   \        RRR7      hTR,          pTR8X  d   \        TP                  4      G Rj  x€L
 # TP                  R	4      p\        T\        4      '       d	   T'       g   \        RR
R7      h\        Y4      ! T4      #  L·  \         d    \        RRR7      hi ; i Lo5i)rz   )Ú
retirementNé�  zJSON body requiredr}   ÚactionÚpreparez)action must be prepare, commit, or cancelÚtokenztoken required)r¦   r‰   Úcancel)Úhermes_cli.backend_retirementr£   r)   ÚjsonÚ
ValueErrorr   Ú
isinstanceÚdictrZ   r   r¦   r=   rD   )rw   r£   Úbodyr¥   r§   s   &    r?   Úpost_health_retirementr¯       sÛ   é € å8ä�7ÔðJØ—\‘\“^×#ˆô �dœD×!Ò! T§X¡X¨hÓ%7Ð?^Ô%^Ü¨Ð4_Ô`Ð`Ø�(�^€FØ�ÔÜ& z×'9Ñ'9Ó:×:Ð:Ø�H‰H�WÓ€EÜ�eœS×!Ò!¯Ü¨Ð4DÔEÐEÜ�:Ô& uÓ-Ð-ñ $øÜô JÜ¨Ð4HÔIÐIðJúñ ;ùs>   ‚D •C" ¨C ©C" ­A!D ÂC>Â2D ÃD Ã C" Ã"C;Ã;D z3^[a-z0-9][a-z0-9_-]{0,63}:[a-z0-9][a-z0-9_-]{0,63}$c                ó0   € V ^8„  d   QhR\         R\        /# )r:   ÚkeyrM   )Úobjectr�   )r>   s   "r?   r@   r@   º   s   € ÷ Yñ Y¬ð Y´Dñ YrA   c                ón   € \        V \        4      ;'       d    \        \        P	                  V 4      4      # )zEAccept only the runner's public ``<profile>:<platform>`` key grammar.)r¬   r=   r�   Ú_PROFILE_PLATFORM_STATUS_KEY_REÚ	fullmatch)r±   s   &r?   Ú_is_profile_platform_status_keyr¶   º   s)   € ä�cœ3Ó×XÐX¤DÔ)H×)RÑ)RÐSVÓ)WÓ$XÐXrA   c                ó`   € V ^8„  d   QhR\         R\        \        ,          R,          R\        /# )r:   r±   Ú
configuredNrM   )r²   Úsetr=   r�   )r>   s   "r?   r@   r@   ¿   s)   € ÷ 
3ñ 
3¤fð 
3¼#¼c½(ÀT½/ð 
3Ìdñ 
3rA   c                óv   € \        V \        4      '       g   R# RV 9   d   \        V 4      # VRJ ;'       g    W9   # )af  Whether a runtime-status platform key may appear publicly: namespaced
``<profile>:<platform>`` keys are validated against the grammar *unconditionally* (a
failed config-set load must not fail open into projecting arbitrary keys from a
process-local JSON file); plain keys are checked against the configured set when it
loaded, passed through when it did not.FÚ:N)r¬   r=   r¶   )r±   r¸   s   &&r?   Ú_status_platform_key_allowedr¼   ¿   s<   € ô �cœ3×ÒÙØ
ˆc„zÜ.¨sÓ3Ð3Ø˜Ð×2Ð2 Ñ!2Ð2rA   Ú
writer_pidÚwriter_start_timec                ó0   € V ^8„  d   QhR\         R\         /# )r:   ÚvaluerM   )r!   )r>   s   "r?   r@   r@   Ò   s   € ÷ Uñ U¤#ð U¬#ñ UrA   c                ó    € \        V \        4      '       g   V # V P                  4        UUu/ uF  w  rV\        9  g   K  WbK  	  upp# u uppi )zEStrip writer-identity stamps from a platform entry before projection.)r¬   r­   ÚitemsÚ_PRIVATE_PLATFORM_ENTRY_KEYS)rÀ   ÚkÚvs   &  r?   Ú_public_platform_entryrÆ   Ò   s@   € ä�eœT×"Ò"ØˆØ"Ÿ[™[œ]ÔT™]‘T�Q¨aÔ7SÑ.SŒDˆAŠD™]ÒTÐTùÓTs   ¬A
Á A
c                ó<   € V ^8„  d   QhR\         R\         R\         /# )r:   Úgateway_platformsÚprofile_platformsrM   )r­   )r>   s   "r?   r@   r@   Ù   s#   € ÷ ñ ¼ð ÔQUð ÔZ^ñ rA   c                óæ  €  ^ RI Hp V! 4       p\        V 4      pT;'       g    / P	                  4        F¦  w  rVWS8X  g   \        V\        4      '       g   K#  VP	                  4        Fo  w  rx\        V\        4      '       d   RV9   g   \        V\        4      '       g   K:  V RV 2p	\        V	4      '       g   KT  VP                  V	\        V4      4       Kq  	  K¨  	  V#   \         d    Rp Lài ; i)a­  Merge independent per-profile gateway platform states: hosts running separate gateway
services per profile (``gateway_mode == "multiple"``) persist each profile's platform
failures in its own ``gateway_state.json``, invisible to the machine-level probe NAS
reads unless folded in under the validated ``<profile>:<platform>`` grammar. The active
profile's own map is skipped (already present); existing keys are never overwritten.)Úget_active_profile_namerH   r»   )
Úhermes_cli.profilesrË   rF   r­   rÂ   r¬   r=   r¶   Ú
setdefaultrÆ   )
rÈ   rÉ   rË   ÚactiveÚmergedÚprofÚplatsr±   rÀ   Ú
namespaceds
   &&        r?   Ú _merge_profile_gateway_platformsrÓ   Ù   sÔ   € ðÝ?Ù(Ó*ˆô Ð#Ó$€FØ)×/Ð/¨R×6Ñ6Ö8‰ˆØŒ>¤¨E´4×!8Ò!8ÙØŸ+™+ž-‰JˆCÜ˜c¤3×'Ò'¨3°#¬:¼ZÈÌt×=TÒ=TÙØ ˜6  3 %˜ˆJÜ2°:×>Ò>ÙØ×Ñ˜jÔ*@ÀÓ*GÖHó (ñ 9ð €Møô ô ØŠðús   ‚C  Ã C0Ã/C0c                 ó®  € \         P                  P                  ^R7      ;_uu_ 4       p V P                  \        4      p VP                  \        R7      uuRRR4       #   \         P                  P                   d*    \        P                  R\        4       Ru uuRRR4       # \         d    Ru uuRRR4       # i ; i  + '       g   i     R# ; i)zíHealth probe with the route's blocking-call budget preserved. The resolver only
reaches this rung when the local PID probe came up empty, so the timeout is paid at
most once per request and only in the cross-container case that needs it.)Úmax_workersrk   NzC/api/status gateway health probe exceeded %.2fs; using local status)FN)Ú
concurrentÚfuturesÚThreadPoolExecutorÚsubmitr(   ÚresultÚ_GATEWAY_HEALTH_ROUTE_TIMEOUTrp   rq   ÚwarningrF   )ÚpoolÚfutures     r?   Ú_bounded_health_proberß   û   s¬   € ô 
×	Ñ	×	.Ñ	.¸1Ð	.×	=Ô	=ÀØ—‘Ô2Ó3ˆð	Ø—=‘=Ô)F�=ÓG÷ 
>Ò	=øô ×!Ñ!×.Ñ.ô 	Ü�L‰LÐ^Ü6ô8àÑ÷ 
>Ò	=ô ô 	ØÑ÷ 
>Ò	=ð	ú÷ 
>×	=Ð	=ús;   ©CÁ A Á ;C ÂCÂ'C Â0C Â3CÂ?C Ã CÃC	c                ól   € V ^8„  d   QhR\         R\        \        ,          R,          R\        R\         /# )r:   rÈ   r¸   NÚgateway_runningrM   )r­   r¹   r=   r�   )r>   s   "r?   r@   r@     s2   € ÷ ñ ´$ð ÄCÌÅHÈtÅOð Ü04ðÜHLñrA   c                óh  € V P                  4        UUu/ uF$  w  rE\        WA4      '       g   K  V\        V4      bK&  	  pppV'       d   V# VR8X  dU   VP                  4        UUu/ uF7  w  rE\        V\        4      '       g   K  VP                  R4      R8X  g   K5  WEbK9  	  upp# / # u uppi u uppi )uß  Public projection of a runtime's platform map (see ``_status_platform_key_allowed``
for the key rules). A cleanly stopped gateway's platform states are stale noise and are
cleared so a dead process can't report "connected"; a startup_failed gateway's FATAL
entries are the diagnosis (credential collisions, auth failures) that the single
exit_reason string can't express, so they are kept â€” upstream writer-identity/freshness
filtering already dropped other processes' entries.Ústartup_failedrŽ   Úfatal)rÂ   r¼   rÆ   r¬   r­   rZ   )rÈ   r¸   rá   Úgateway_stater±   rÀ   Ú	platformss   &&&&   r?   Ú_project_gateway_platformsrç     s¸   € ð GX×F]ÑF]ÔF_ô CÑF_¹
¸Ü0°×Aô 4�Ô,¨UÓ3Ò3ÑF_€Iñ CçØÐØÐ(Ô(Ø-6¯_©_Ô->ô NÑ->™z˜sÜ˜e¤T×*ô Ø/4¯y©y¸Ó/AÀWÑ/Lô �’
Ñ->ò Nð 	Nà€IùóCùó
Ns   ”B(®B(Á%B.ÂB.ÂB.c                óh   € V ^8„  d   QhR\         \        ,          R\        \        \        3,          /# )r:   Úprofile_dirrM   )r#   r    r­   r=   r!   )r>   s   "r?   r@   r@     s1   € ÷ _iñ _i¬x¼­~ð _iÌdÔSVÔX[ÐS[Ínñ _irA   c              ƒ  ó–  a aa"  € S '       d   \        S R,          R7      M	\        4       o\        VVV 3R l4      G Rj  x€L
 pVP                  pVP                  p \        \        4      G Rj  x€L
 pSpVf"   V'       d   VP                  R4      '       d   TpS ;'       g    \        4       pVP                  e=   \        V4      p/ VP                  CR\        VP                  T;'       g    R4      /CpM<\        V4      e0    \        \        VS\        V4      R7      G Rj  x€L
 ;'       g    TpRp	/ p
RpRpRpV'       d±   VP                  R4      p	V'       g   \        V4      p	M1Ve   V	R9   d   Rp	M#V	R9   d   \!        V4      '       d   \#        V4      p\%        VP                  R4      ;'       g    / WSV	4      p
V	R8X  d   RMVP                  R4      p\'        VP                  R4      4      pV'       d   V	f   Ve   Rp	V'       d   T;'       g    / P                  R4      MRpRTRTRVP(                  RT	RT
RTRTRTR\+        V\,        4      '       d   V Uu. uF  p\/        V4      NK  	  up/	# R/	#  EL? EL  \
         d    Rp EL i ; i ELr  \
         d    \        P                  R	R
R7        EL‹i ; iu upi 5i)aw  Liveness + runtime-state readout (running/pid/state/platforms/exit_reason/updated_at
plus the raw ``runtime`` document).

Liveness is delegated to the shared ladder in gateway.status so this endpoint and
/api/messaging/platforms can never disagree. With ``?profile=<name>`` PID/state reads are
scoped to that profile's directory (gateway identity files live in the per-profile
home); plain /api/status keeps the exact zero-arg call so its cache signature is
unchanged. The module-level probe references are handed to the resolver so the
``monkeypatch.setattr(gateway.status, "get_running_pid_cached", ...)`` seam still intercepts.
zgateway_state.json)Úpathc            	      óZ   <€ \        SSS '       d   \        MR \        \        \        R7      # )N)ré   ÚruntimeÚhealth_probeÚ	pid_probeÚruntime_readerÚruntime_pid_probe)r   rß   r3   r7   r4   )Ú
health_urlÚlocal_runtimeré   s   €€€r?   Ú<lambda>Ú)_resolve_gateway_status.<locals>.<lambda>*  s!   ø€ Ô/GØ¨ß.8Õ*¸dÜ(Ô9LÜ8õ	0:rA   Nrå   ræ   Ú )Úgateway_pidz,/api/status multiplexer record lookup failedT)Úexc_infoÚstoppedÚrunningÚexit_reasonÚ
updated_atÚserved_profilesrí   rá   r÷   rÈ   Úgateway_exit_reasonÚgateway_updated_atÚgateway_heartbeat_stale_sÚgateway_shared_with>   Nrù   >   rú   ÚdegradedÚstarting)r7   r   rú   Úhealth_bodyr'   rF   rZ   r   rí   r   r   r   r5   rq   rÜ   r   r   r   rç   r   r“   r¬   Úlistr=   )ré   rò   Úlivenessrá   Úremote_health_bodyr¸   rí   Úown_homeÚserved_namerå   rÈ   rþ   rÿ   r   Úshared_withÚpró   s   ff              @r?   Ú_resolve_gateway_statusr    sð  úé € ÷ $ô )¨kÐ<PÕ.PÕQÜ)<Ó)>ð ä&ö (:ó ;÷ ;€Hð
 ×&Ñ&€OØ&.×&:Ñ&:ÐðÜ,Ô-OÓP×Pˆ
ð €GØ‚×-Ð2D×2HÑ2HÈ×2YÒ2YØ$ˆà×7Ð7Ô5Ó7€HØ×ÑÒ#ô
 ,¨HÓ5ˆði�X×%Ñ%ð iØÔ BÀ8×CSÑCSÐU`×UfÐUfÐdfÓ gñi‰ä	˜HÓ	%Ò	1ð	XÜ-Ü&¨°-ÔM_Ð`hÓMiôk÷ k÷ vð vØnuð ð €MØ ÐØÐØÐØ $ÐßØŸ™ OÓ4ˆßô 3°7Ó;‰MØÒ+°ÐARÔ0Rð &‰MØÐAÔAÔF]Ð^e×FfÒFfô )GÀwÓ(OÐ%Ü6Ø�K‰K˜Ó$×*Ð*¨¨JÈóXÐà&3°yÔ&@™dÀgÇkÁkÐR_ÓF`Ðô 2°'·+±+¸lÓ2KÓLÐ÷ ˜=Ò0Ð5GÒ5SØ!ˆ÷ =L�7—=�=˜b×%Ñ%Ð&7Ô8ÐQU€Kà�7Ð-¨ÀÈxÏ|É|Ø˜Ð(;Ð=NØÐ2Ð4HÐJ\Ø#Ð%>ØÄ
È;ÔX\×@]Ò@]±Ó<±¨1¤ A¦±Ñ<ðið ið
 dhðið iò[;ò QøÜô Ø‹
ðúò2køäô 	Xä�L‰LÐGÐRVˆL×Wð	XüòZ  =ùsÎ   …:K	¿I>Á K	ÁJ Á/JÁ0J Á4K	ÂK	Â
K	Â$A
K	Ã/K	ÄJ Ä&JÄ'
J Ä2J Ä5K	ÅK	Å AK	Æ:AK	Ç?K	ÈK	ÈA	K	É#K&É7K	ÊJ ÊJÊK	ÊJÊK	ÊJ Ê"KÊ=K	Ë KËK	c                óF   € V ^8„  d   QhR\         \        \        3,          /# rL   ©r­   r=   r!   )r>   s   "r?   r@   r@     s   € ÷ &ñ &œ4¤¤S �>ñ &rA   c                 óL  € \        \        \        P                  RR4      4      p . p. p ^ RIHpHp V! 4        Uu. uF  qUP                  NK  	  ppV '       d0   VP                  R4       V! 4       '       d   VP                  R4       RT RTRT/# u upi   \         d     Li ; i)uè  Dashboard auth gate readout: gate engaged, registered providers, and the RFC 8252
native-app capability advertisement ``auth_flows`` the desktop reads to pick the
system-browser + loopback + PKCE flow over the embedded-webview cookie flow. "cookie" is
always available in gated mode; "native_pkce" when at least one interactive session
provider is registered (token-only credentials such as drain don't count). Missing
"native_pkce" â‡’ older gateway â‡’ desktop falls back automatically.rŠ   F)Úlist_providersÚlist_session_providersÚcookieÚnative_pkceÚauth_providersÚ
auth_flows)
r�   rD   r.   rŽ   Úhermes_cli.dashboard_authr  r  ÚnameÚappendrF   )rŠ   r  r  Ú_list_providersÚ_list_session_providersr  s         r?   Ú_auth_gate_statusr    s§   € ô œ¤§¡¨O¸UÓCÓD€MØ "€NØ€Jð
÷	bá*9Ô*;Ó<Ñ*; QŸ&œ&Ñ*;ˆÐ<ßØ×Ñ˜hÔ'Ù&×(Ò(Ø×!Ñ! -Ô0ð ˜]Ð,<¸nØ˜*ð&ð &ùò =øô
 ô áðús(   ªB »BÁ'B Á7B ÂB ÂB#Â"B#c                ó$   € V ^8„  d   QhR\         /# rL   r<   )r>   s   "r?   r@   r@   ˜  s   € ÷ 	ñ 	¤ñ 	rA   c                 óB   €  ^ RI Hp  V ! 4       #   \         d     R# i ; i)aB  Nous bootstrap-session validity for the NAS health sweep: a hosted agent whose Nous
auth dies terminally looks HEALTHY to every liveness probe yet every inference turn
fails, and this is the ONLY signal that surfaces it (local auth-store state, no token
needed). Best-effort: never let auth classification break the probe.©Úget_nous_session_validityÚunknown)Úhermes_cli.authr  rF   r  s    r?   Ú_nous_session_validityr"  ˜  s%   € ð
Ý=Ù(Ó*Ð*øÜô Úðús   ‚ ��c                ót   € V ^8„  d   QhR\         \        \        3,          R\         \        \        3,          /# )r:   ÚgatewayrM   r  )r>   s   "r?   r@   r@   ¤  s*   € ÷ ñ ¤T¬#¬s¨(¥^ð ¼¼SÄ#¸X½ñ rA   c              ƒ  ól  "  € ^ RI Hp V R,          V R,          r2V R,          pRRV'       d
   VR9   d   RMR	R
T;'       g    V'       d   RMR/RVP                  4       /p ^ RIHp \        V\        4       4      G Rj  x€L
 pRVP                  RR	4      /VR&   VP                  R4      R8X  d   RVR,          R&   TP                  4        Uu. uFf  p\        T\        4      '       g   K  \        TP                  R
4      ;'       g    TP                  R4      ;'       g    R4      P                  4       NKh  	  p	pT	 U
u. uF  qªR8w  g   K  T
NK  	  p	p
\        R T	 4       4      pRT\        T	4      8X  d   RMR	R\        T	4      RT/TR&   T#  EL  \         d    RR	/TR&    Lêi ; iu upi u up
i 5i)uí   Component-level health rollup: counts and status enums only (public payload â€” no
messages, paths or other detail that could carry secrets). The storage probe reuses the
gateway readiness state_db check (read-only, 1s-bounded) off-loop.)ÚDASHBOARD_HEALTHrá   rå   rÈ   r$  Ústatusrú   r€   r  rŽ   rù   Ú	dashboard)Ú_probe_state_dbNÚstorager   ÚcorruptÚreasonrö   Údisabledc              3   ó>   "  € T F  q\         9   g   K  ^x € K  	  R# 5i)é   N)Ú_HEALTHY_PLATFORM_STATES)r[   rŽ   s   & r?   r^   Ú$_component_health.<locals>.<genexpr>¾  s   é € ÐX¡?˜%Ô?WÑ6W—A’A£?ùs   ‚“
r¸   Ú	connectedræ   >   rú   Údraining)r„   r&  ÚsnapshotÚgateway.readinessr)  r   r0   rZ   rF   Úvaluesr¬   r­   r=   Úlowerrd   Úlen)r$  r&  rá   rå   rÈ   Ú
componentsr)  Ústorage_checkrÀ   Úplatform_statesrŽ   r2  s   &           r?   Ú_component_healthr<  ¤  s½  é € õ 7Ø%,Ð->Õ%?ÀÈÕAY�]ØÐ 3Õ4ÐàØŸo°-ÐCZÔ2Z‘dÐ`jØ�]×SÐS·O¡yÈðUð 	Ð%×.Ñ.Ó0ð	"2€Jð
7Ý5Ü/°ÄÓARÓS×SˆØ!)¨=×+<Ñ+<¸XÀzÓ+RÐ Sˆ
�9Ñà×Ñ˜XÓ&¨)Ô3Ø.7ˆJ�yÕ! (Ñ+ð %6×$<Ñ$<Ô$>ó[Ù$>˜5Ä*ÈUÔTX×BYô T”s˜5Ÿ9™9 WÓ-×JÐJ°·±¸8Ó1D×JÐJÈÓK×QÑQÖSÙ$>ð ð [á*9ÓQ©/ ÀjÑ=P—u�u©/€OÐQÜÑX¡?ÓXÓX€IØ'°¼cÀ/Ó>RÔ1R©ÐXbØ+¬S°Ó-AÀ;ÐPYð[€Jˆ{ÑàÐò Tøô
 ô 7Ø!)¨:Ð 6ˆ
�9Óð7üò[ùâQùsw   ‚>F4ÁF4Á
F4Á!F Á>FÁ?=F Â<F4ÃF*Ã+F*ÄF*Ä!F*Ä:F4Å F/ÅF/Å<F4ÆF ÆF'Æ$F4Æ&F'Æ'F4c                óV   € V ^8„  d   QhR\         \        \        3,          R\        RR/# )r:   r'  ÚhomerM   N)r­   r=   r!   r    )r>   s   "r?   r@   r@   Ä  s)   € ÷ ñ ¤T¬#¬s¨(¥^ð ¼4ð ÀDñ rA   c              ƒ  óä  "  € R
 F<  w  r#p \        \        P                  ! V4      V4      p\        WQ4      G Rj  x€L
 W&   K>  	   ^ RIHp ^ RIHp V! 4       R,          pVP                  4       '       d8   V! VRR7      p	 V	P                  4       p
V	P                  4        V
e   W R	&   R# R# R#  Lt  \         d    RR/Y&    KÀ  i ; i  T	P                  4        i ; i  \         d     R# i ; i5i)aU  Memory / disk pressure rollups + deferred FTS rebuild progress (coarse numbers/enums
only; public payload). Deliberately NOT folded into components/overall: pressure is
advisory, not a liveness verdict, and flipping ``overall`` on it would page NAS's
availability sweep for a condition the valve is already handling. Read-only, never raise.
NÚpressurer   )Ú	SessionDB)r0   zstate.dbT)Údb_pathrR   Úfts_rebuild))Úmemoryzgateway.memory_statusÚcollect_memory_status)Údiskzgateway.disk_statusÚcollect_disk_status)rD   Ú	importlibÚimport_moduler   rF   r`   rA  Úhermes_constantsr0   ra   Úfts_rebuild_statusre   )r'  r>  r±   Úmod_namer;   ÚcollectÚ_SDBÚ_ghhÚ_db_pathÚ_sdbÚ_rebuilds   &&         r?   Ú_advisory_pressurerS  Ä  sæ   é € ó#[Ñˆ�wð	2Üœi×5Ò5°hÓ?ÀÓIˆGÜ 1°'Ó @×@ˆF‹Kñ	#[ðÝ2Ý<Ù“6˜JÕ&ˆØ�?‰?×ÒÙ °DÔ9ˆDðØ×2Ñ2Ó4�à—
‘
”ØÒ#Ø(0�}Ó%ñ $ñ ñ AøÜô 	2Ø% yÐ1ˆFŒKð	2ûð —
‘
•ûô ô Úðüsz   ‚	C0Œ.B1ºB/»B1ÁC0Á/C Á6
C ÂC	 ÂC Â)C0Â/B1Â1CÃC0ÃCÃC0Ã	CÃC ÃC-Ã)C0Ã,C-Ã-C0z/api/statusc                ó:   € V ^8„  d   QhR\         \        ,          /# ©r:   Úprofile©r#   r=   )r>   s   "r?   r@   r@   ã  s   € ÷ c3ñ c3œh¤s�mñ c3rA   c              ƒ  óÎ  "  € ^ RI Hp RpT ;'       g    RP                  4       pRpV'       d<   VP                  4       R8w  d'   \	        V4      p\        V4      pVP                  4         \        4       w  rV\        WA4      G Rj  x€L
 pVR,          VR,          r˜\        \        4      G Rj  x€L
 p
V'       g0   \        VR,          V
P                  R4      ;'       g    / 4      VR&   \        4       G Rj  x€L
 p\        VR	,          ;'       g    / P                  R
^ 4      4      p\        \        4      G Rj  x€L
 p\!        4       p/ R\#        4       P$                  bR\&        bRVbRVbR\)        4       '       * bRVbRV	bRVR,          bRVR,          bRVR,          bRVR,          bRVR,          bR
VbR\+        W‰VR7      bR\-        W‰R7      bRVbRVbVCR\/        4       /Cp\        \0        4      G Rj  x€L
 pV'       d   VVR&   ^ RIHp \7        \        V4      G Rj  x€L
 4      VR&   \9        V4      G Rj  x€L
 pVVR&   \:        ;QJ d*    R VP=                  4        4       F  '       d   K   R M	  R!M! R VP=                  4        4       4      '       d   R"MR#VR$&   \?        Yô'       d   TM	\A        4       4      G Rj  x€L
  V
R%,          VR%&   V
P                  R&. 4      VR&&   V
R',          VR'&   V
P                  R(4      VR(&   VR),          '       g_   VPC                  R*\E        \A        4       4      R+\E        \G        4       4      R,\E        \I        4       4      R-VR-,          R.VR/V
R/,          /4       TVe%   VPJ                  ! \L        PN                  ! 4       !   # #  EL EL÷ EL± ELq ELµ EL� ELv Lñ  Te%   TPJ                  ! \L        PN                  ! 4       !   i i ; i5i)0u²  Public machine-level liveness probe (``PUBLIC_API_PATHS``): version, gateway state,
active session count and the auth-gate shape â€” no bodies, no session content, no secrets.

``?profile=`` (dashboard management switcher) uses the config-only contextvar scope, NOT
_profile_scope: this handler awaits the remote health probe, and _profile_scope swaps
process-global skills-module attributes a concurrent request would cross-restore.
)Ú_GATEWAY_HEALTH_URLNrö   Úcurrentrá   rå   rÈ   rÉ   rí   Úactive_agentsr‡   Úrelease_dateÚconfig_versionÚlatest_config_versionÚcan_update_hermesrþ   rÿ   r   r  Úgateway_busy)rá   rå   r[  Úgateway_drainable)rá   rå   Úrestart_drain_timeoutÚactive_sessionsÚnous_session_validÚ
install_id)Úshared_profile_warningrf  r9  c              3   óH   "  € T F  qP                  R 4      R8H  x € K  	  R# 5i)r'  r€   NrY   )r[   Úitems   & r?   r^   Úget_status.<locals>.<genexpr>.  s   é € Ð(dÑPcÈ¯©°(Ó);¸tÖ)CÓPcùs   ‚ "FTr€   r  ÚoverallÚprofilesÚparked_profilesÚgateway_modeÚmultiplex_standalone_reasonrŠ   Úhermes_homeÚconfig_pathÚenv_pathr÷   Úgateway_health_urlÚgateways)(r„   rY  Ústripr7  r*   r%   Ú	__enter__r/   r  r   r$   rÓ   rZ   rt   r   r+   r  r   r‹   r   r&   r	   r
   r"  r2   Ú!hermes_cli.shared_profile_warningrf  r�   r<  Úallr6  rS  r0   Úupdater=   r   r   Ú__exit__Úsysrø   )rV  rY  Ústatus_scopeÚrequested_profileré   Úcurrent_verÚ
latest_verr$  rá   rå   Útopologyrc  r[  rb  Úauthr'  re  rf  r9  s   &                  r?   Ú
get_statusr�  â  s*  é € õ :Ø€LØ Ÿ˜ B×-Ñ-Ó/ÐØ"&€KßÐ.×4Ñ4Ó6¸)ÔCÜ*Ð+<Ó=ˆÜ,Ð->Ó?ˆØ×ÑÔ ðR3Ü"6Ó"8ÑˆÜ/°ÓQ×QˆØ)0Ð1BÕ)CÀWÈ_ÕE]˜ô
 +Ô+SÓT×Tˆß Ü+KØÐ+Õ,¨h¯l©lÐ;NÓ.O×.UÐ.UÐSUó,WˆGÐ'Ñ(ô !8Ó 9×9ˆô
 ,¨W°YÕ-?×-EÐ-EÀ2×,JÑ,JÈ?Ð\]Ó,^Ó_ˆô '8Ô8VÓ&W× WÐÜ Ó"ˆðDØÔ'Ó)×6Ñ6ðDØ8FÔHXðDà˜kðDà+BÀJðDð  Ô%OÓ%QÔ!QðDð ˜ð	Dð 1@Àð	Dð
   Ð)<Õ!=ðDð " 7Ð+@Õ#AðDð ! 'Ð*>Õ"?ðDð (¨Ð1LÕ)MðDð " 7Ð+@Õ#AðDð ˜]ðDð Ô/Ø /Ø+ô-ðDð"  Ô!9Ø /ô"Nð#Dð& $Ð%:ð'Dð& =NÈð'Dð( ð)Dð( )Ô*@Ó*Bñ)Dˆô0 -¬^Ó<×<ˆ
ßØ#-ˆF�<Ñ õ 	MÜ+/Ô6GÐH^Ó6_×0_Ó+`ˆÐ'Ñ(ä,¨WÓ5×5ˆ
Ø)ˆˆ|Ñß%(£SÑ(dÐPZ×PaÑPaÔPcÓ(d§S§S¢SÑ(dÐPZ×PaÑPaÔPcÓ(d×%dÒ%d™TØ",ð 	ˆyÑä  ¾©ÌÓIZÓ[×[Ð[ð
 & jÕ1ˆˆzÑØ$,§L¡LÐ1BÀBÓ$GˆÐ Ñ!Ø!)¨.Õ!9ˆˆ~ÑØ08·±Ð=ZÓ0[ˆÐ,Ñ-ð
 �O×$Ô$Ø�M‰MØœs¤?Ó#4Ó5°}ÄcÌ/ÓJ[ÓF\ØœC¤£Ó/°ÀÈÕ@VØ$Ð&9¸:ÀxÐPZÕG[ð]ô ^ð
 àÒ#Ø×!Ò!¤3§<¢<£>Ó2ð $ò_ Rò Uò
 :ò !Xò6 =ò 1`â5ñ 	\øð* Ò#Ø×!Ò!¤3§<¢<£>Ó2ð $üså   ‚,O%¯;O%Á+N8 ÂN!Â'N8 Â-N$Â.N8 Â:$N8 ÃN8 Ã6N'Ã7N8 Ä)N8 Ä9N*Ä:B>N8 Ç8N-Ç9N8 ÈN8 È#N0È$N8 È=N3È>N8 ÉN8 É4(N8 Ê'N8 ËN6ËAN8 ÌAN8 Í8)O%Î!N8 Î$N8 Î'N8 Î*N8 Î-N8 Î0N8 Î3N8 Î6N8 Î8*O"Ï"O%z/api/system/statsc               ƒ  óF  aa"  € ^ RI p / \        V P                  4       V P                  4       V P	                  4       V P                  4       R7      CRV P                  4       RV P                  4       RV P                  4       RV P                  4       R\        4       P                  R\        P                  ! 4       /CoVV3R	 lpVV3R
 lpVV3R lpVV3R lp ^ RIoSP                  4       pRVP                  RVP                   RVP"                  RVP$                  /SR&   WW43 F  p V! 4        K  	  RSR&   S#   \&         d     K$  i ; i  \&         dE    RSR&    \)        \        P*                  ! 4       4      SR&    S#   \,        \.        3 d      S# i ; ii ; i5i)z¬Host + process system stats for the System page (stdlib identity; psutil CPU/memory/
disk/uptime when available). Non-sensitive: no env values, no paths beyond hermes home.N)ÚsystemÚreleaser‡   Úplatform_labelÚarchÚhostnameÚpython_versionÚpython_implÚhermes_versionÚ	cpu_countc                  ó¶   <€ SP                  \        \        4       4      4      p R V P                  RV P                  RV P
                  RV P                  /SR&   R# )ÚtotalÚusedÚfreeÚpercentrF  N)Ú
disk_usager=   r0   r�  rŽ  r�  r�  )Údur�   Úpsutils    €€r?   Ú_diskÚget_system_stats.<locals>._diskX  sH   ø€ Ø×Ñœs¤?Ó#4Ó5Ó6ˆØ §¡¨6°2·7±7¸FÀBÇGÁGÈYÐXZ×XbÑXbÐcˆˆV‹rA   c                  ó†   <€ SP                  R R7      SR&   \        SRR4      p V '       d   \        V ! 4       4      SR&   R# R# )gš™™™™™¹?)ÚintervalÚcpu_percentÚ
getloadavgNÚload_avg)r˜  rD   r  )Úlar�   r“  s    €€r?   Ú_cpuÚget_system_stats.<locals>._cpu\  sA   ø€ Ø$×0Ñ0¸#Ð0Ó>ˆˆ]ÑÜ�V˜\¨4Ó0ˆßÜ#¡B£D›zˆD�Óñ rA   c                  ót   <€ \        \        P                  ! 4       SP                  4       ,
          4      S R &   R# )Úuptime_secondsN)rO   rc   Ú	boot_time)r�   r“  s   €€r?   Ú_uptimeÚ!get_system_stats.<locals>._uptimeb  s'   ø€ Ü!$¤T§Y¢Y£[°6×3CÑ3CÓ3EÕ%EÓ!FˆÐÓrA   c            	      óÐ   <€ SP                  4       p R V P                  RV P                  4       P                  R\	        V P                  4       4      RV P                  4       /SR&   R# )r“   ÚrssÚcreate_timeÚnum_threadsÚprocessN)ÚProcessr“   Úmemory_infor¤  rO   r¥  r¦  )Úprocr�   r“  s    €€r?   Ú_processÚ"get_system_stats.<locals>._processe  sW   ø€ Ø�~‰~ÓˆØ  $§(¡(¨E°4×3CÑ3CÓ3E×3IÑ3IØ(¬#¨d×.>Ñ.>Ó.@Ó*AØ(¨$×*:Ñ*:Ó*<ð>ˆˆY‹rA   r�  Ú	availablerŽ  r�  rD  Tr“  Frš  )Úplatformr   rƒ  r„  r‡   ÚmachineÚnoderˆ  Úpython_implementationr   r‹   r™   r‹  r“  Úvirtual_memoryr�  r­  rŽ  r�  rF   r  r™  ÚOSErrorÚAttributeError)	Ú	_platformr”  rœ  r¡  r«  ÚvmÚfillr�   r“  s	          @@r?   Úget_system_statsr¸  I  s—  ùé € ó !ðXÜ
"Ø×#Ñ#Ó%¨y×/@Ñ/@Ó/BÈI×L]ÑL]ÓL_Ø$×-Ñ-Ó/ô1ðXð 	�	×!Ñ!Ó# Z°·±Ó1AØ˜)×2Ñ2Ó4Ø�y×6Ñ6Ó8ØÔ*Ó,×9Ñ9¸;ÌÏÊËñX€Dödö*öGö>ðÛØ×"Ñ"Ó$ˆØ! 2§8¡8¨[¸"¿,¹,ÈÐPR×PWÑPWØ# R§Z¡Zð1ˆˆX‰à 'Ó4ˆDðÙ–ñ 5ð
 ˆˆX‰ð €Køô ô Úðûô ô ØˆˆX‰ð	Ü#¤B§M¢M£OÓ4ˆD�Òð €Køô œÐ(ô 	Ùà€Kð	úðüsm   „CF!ÃAE Ä+D=Ä2	E Ä;F!Ä=EÅE ÅEÅE ÅFÅ !FÆF!ÆFÆFÆF!ÆFÆFÆF!z/api/curatorc                ó:   € V ^8„  d   QhR\         \        ,          /# rU  rW  )r>   s   "r?   r@   r@   †  s   € ÷ 8ñ 8¤h¬s¥mñ 8rA   c              ƒ   ó–   a"  €  ^ RI Ho T3R lp\	        Y4      G Rj  x€L
 #   \         d   p\        RRT 2R7      hRp?ii ; i L'5i)rz   ©Úcuratoréô  zCurator unavailable: r}   Nc            
      óÞ   <€ \        SR / 4      p R\        SRR4      R\        SRR4      R\        SRR	4      R
V P                  R
4      /R Uu/ uF  pV\        SRV 2R	4      bK  	  upC# u upi )Ú
load_stateÚenabledÚ
is_enabledTÚpausedÚ	is_pausedFÚinterval_hoursÚget_interval_hoursNÚlast_run_atÚget_)Úmin_idle_hoursÚstale_after_daysÚarchive_after_days)rJ   rZ   )rŽ   r±   r¼  s     €r?   Ú_runÚ get_curator_status.<locals>._runŒ  s–   ø€ Ü˜7 L°"Ó5ˆà”z '¨<¸Ó>Ø”j ¨+°uÓ=Øœj¨Ð2FÈÓMØ˜5Ÿ9™9 ]Ó3ð	Yñ WóXÙV�3ð ”J˜w¨$¨s¨e¨°dÓ;Ò;ÙVñXðYð 	Yùò
Xs   ÁA*)Úagentr¼  rF   r   r   )rV  rs   rË  r¼  s   &  @r?   Úget_curator_statusrÎ  …  sS   øé € ðSÝ!õYô )¨Ó7×7Ð7øô ô SÜ¨Ð6KÈCÈ5Ð4QÔRÐRûðSúñ 8ùs,   ƒA	…$ ‹A	ŸA A	¤A¯?¿AÁA	z/api/curator/pausedc                óF   € V ^8„  d   QhR\         R\        \        ,          /# ©r:   r®   rV  )r   r#   r=   )r>   s   "r?   r@   r@   š  s   € ÷ 5ñ 5¤<ð 5¼(Ä3½-ñ 5rA   c              ƒ   ó‚   a a"  € ^ RI Ho \        VV V3R l4      G Rj  x€L
  RRR\        S P                  4      /#  L5i)rz   r»  c                  óL   <€ SP                  \        S P                  4      4      # rC   )Ú
set_pausedr�   rÂ  )r®   r¼  s   €€r?   rô   Ú$set_curator_paused.<locals>.<lambda>ž  s   ø€ °7×3EÑ3EÄdÈ4Ï;É;ÓFWÔ3XrA   Nr€   TrÂ  )rÍ  r¼  r   r�   rÂ  )r®   rV  r¼  s   f&@r?   Úset_curator_pausedrÕ  ™  s:   ùé € åô " 'Õ+XÓ
Y×YÐYØ�$˜¤$ t§{¡{Ó"3Ð4Ð4ñ Zùs   „?Ÿ= ?c          
      ój   € V ^8„  d   QhR\         R\        R\        R\        \        ,          R\        /# )r:   Úargvr  ÚprefixrV  rM   )r  r=   r#   r­   )r>   s   "r?   r@   r@   ¢  s4   € ÷ 7ñ 7œð 7¤Cð 7´ð 7¼xÌ½}ð 7ÔX\ñ 7rA   c                óª   €  \        \        V4      V ,           V4      pRRRTP                  RT/#   \         d   p\        RT RT 2R7      hRp?ii ; i)	zgSpawn a background ``hermes -p <profile> <argv>`` action; a spawn failure is
``500 "<prefix>: <exc>"``.r½  z: r}   Nr€   Tr“   r  )r,   r1   rF   r   r“   )r×  r  rØ  rV  rª  rs   s   &&&&  r?   Ú_spawn_actionrÚ  ¢  sd   € ðHÜ#Ô$5°gÓ$>ÀÕ$EÀtÓLˆð �$˜˜tŸx™x¨°Ð6Ð6øô ô HÜ¨°v°h¸bÀÀÐ4FÔGÐGûðHús   ‚0 °A»AÁAz/api/curator/runc                ó:   € V ^8„  d   QhR\         \        ,          /# rU  rW  )r>   s   "r?   r@   r@   ­  s   € ÷ Pñ Pœx¬�}ñ PrA   c           	   ƒ  ó>   "  € \        RR.RR\        V R4      4      # 5i)zºTrigger a curator review now (backgrounded; tail via action status). The curator
archives and rewrites skills, so an unnamed target is refused while this backend
serves several profiles.r¼  Úrunzcurator-runzFailed to run curatorzPOST /api/curator/run)rÚ  r   ©rV  s   &r?   Úrun_curatorrß  ¬  s-   é € ô
 ˜) UÐ+¨]Ð<SÜ,¨WÐ6MÓNóPð Pùs   ‚z/api/learning/graphc                ó:   € V ^8„  d   QhR\         \        ,          /# rU  rW  )r>   s   "r?   r@   r@   ¶  s   € ÷ Vñ V¤h¬s¥mñ VrA   c              ƒ  ó´   "  € R p \        W4      G Rj  x€L
 #  L  \         d    h \         d$    \        P	                  R4       \        RRR7      hi ; i5i)zTLearning graph for the desktop panel: profile-scoped learned skills + memory chunks.c                  ó   € ^ RI Hp  V ! 4       # )rz   ©Úbuild_learning_graph)Úagent.learning_graphrä  rã  s    r?   rË  Ú get_learning_graph.<locals>._run¸  s   € Ý=Ù#Ó%Ð%rA   NzGET /api/learning/graph failedr½  zFailed to build learning graphr}   )r   r   rF   rq   Ú	exception)rV  rË  s   & r?   Úget_learning_graphrè  µ  sY   é € ò&ðVô & gÓ4×4Ð4Ñ4øÜô ØÜô VÜ�‰Ð7Ô8Ü¨Ð4TÔUÐUðVüs*   ‚A‡ •– ™Aš œA±$AÁAc                óR   € V ^8„  d   QhR\         \        ,          R\        R\        /# )r:   rV  r'  Úfallback)r#   r=   rO   )r>   s   "r?   r@   r@   Ç  s&   € ÷ ñ ¤h¬s¥mð Äð ÔPSñ rA   c              ƒ  óž   "  € \        W4      G Rj  x€L
 pVP                  R4      '       g   \        W$P                  RV4      R7      hV#  L95i)z|Run a learning_mutations call under ``_profile_scope`` off-loop; a non-ok result
becomes ``HTTPException(status, message)``.Nr€   Úmessager}   )r   rZ   r   )rV  rI   r'  rê  Úress   &&&& r?   Ú_learning_mutationrî  Ç  sA   é € ô ! Ó-×
-€CØ�7‰7�4�=Š=Ü¨·w±w¸yÈ(Ó7SÔTÐTØ€Jñ .ùs   ‚A‘A’A­Az/api/learning/nodec                óF   € V ^8„  d   QhR\         R\        \         ,          /# )r:   ÚidrV  )r=   r#   )r>   s   "r?   r@   r@   Ñ  s"   € ÷ Xñ X¤ð X¬h´s­mñ XrA   c              ƒ  óT   a a"  € ^ RI Ho \        VV V3R lRR4      G Rj  x€L
 #  L5i)zXCurrent content of a journey node (skill SKILL.md or memory chunk), for an edit prefill.)Únode_detailc                  ó   <€ S! S 4      # rC   © )rð  rò  s   €€r?   rô   Ú#get_learning_node.<locals>.<lambda>Ô  s	   ø€ ±[À´_rA   r|   z	not foundN)Úagent.learning_mutationsrò  rî  )rð  rV  rò  s   f&@r?   Úget_learning_noder÷  Ð  s#   ùé € õ 5Ü# GÕ-DÀcÈ;ÓW×WÐWÑWùs   „(¡&¢(c                óF   € V ^8„  d   QhR\         R\        \        ,          /# rÐ  )r   r#   r=   )r>   s   "r?   r@   r@   Ø  s"   € ÷ Uñ U¤_ð U¼xÌ½}ñ UrA   c              ƒ  ó|   a a"  € ^ RI Ho \        S P                  ;'       g    TV V3R lRR4      G Rj  x€L
 #  L5i)uó   Delete a journey node â€” skills are archived (restorable), memories removed.

``?profile=`` is honoured too: a shared-backend Desktop scopes this call by query only, and
ignoring it archived the same-named skill of the launch profile instead.)Údelete_nodec                  ó(   <€ S! S P                   4      # rC   )rð  )r®   rú  s   €€r?   rô   Ú&delete_learning_node.<locals>.<lambda>ß  s   ø€ ©°T·W±WÔ)=rA   r¤   zdelete failedN)rö  rú  rî  rV  )r®   rV  rú  s   f&@r?   Údelete_learning_noderý  ×  s<   ùé € õ 5Ü#Ø�‰×Ð˜Õ!=¸sÀOóU÷ Uð Uñ Uùó   „1<µ:¶<c                óF   € V ^8„  d   QhR\         R\        \        ,          /# rÐ  )r   r#   r=   )r>   s   "r?   r@   r@   ã  s#   € ÷ _ñ _Ô%5ð _ÄÌÅñ _rA   c              ƒ  ó|   a a"  € ^ RI Ho \        S P                  ;'       g    TV V3R lRR4      G Rj  x€L
 #  L5i)zSRewrite a journey node's content (SKILL.md or memory chunk); profile as for DELETE.)Ú	edit_nodec                  ó>   <€ S! S P                   S P                  4      # rC   )rð  Úcontent)r®   r  s   €€r?   rô   Ú&update_learning_node.<locals>.<lambda>ç  s   ø€ ©°4·7±7¸D¿L¹LÔ)IrA   r¤   zedit failedN)rö  r  rî  rV  )r®   rV  r  s   f&@r?   Úupdate_learning_noder  â  s=   ùé € õ 3Ü#Ø�‰×Ð˜Õ!IÈ3ÐP]ó_÷ _ð _ñ _ùrþ  z/api/portalc                ó:   € V ^8„  d   QhR\         \        ,          /# rU  rW  )r>   s   "r?   r@   r@   î  s   € ÷ Kñ K¤X¬c¥]ñ KrA   c              ƒ   ó>   "  € \        V \        4      G R j  x€L
 #  L5irC   )r   Ú_get_portal_status_syncrÞ  s   &r?   Úget_portal_statusr	  í  s   é € ô )¨Ô2IÓJ×JÐJÑJùs   ‚–—c                ó$   € V ^8„  d   QhR\         /# rL   r<   )r>   s   "r?   r@   r@   ô  s   € ÷ ñ œCñ rA   c                 ó„   € \        V R R4      '       d   R# \        V RR4      '       d   \        V RR4      ;'       g    R# R# )Úmanaged_by_nousFzvia Nous PortalrÎ   Úcurrent_providerNznot configured)rD   )Úfeats   &r?   Ú_feature_stater  ô  s?   € ÜˆtÐ&¨×.Ò.Ù Üˆt�X˜u×%Ò%Ü�tÐ/°Ó6×BÐB¸(ÐBÙrA   c                  ó  € \        4       ;'       g    / p / p ^ RIHp V! 4       ;'       g    / p. p ^ RIHp V! V 4      pVe8   VP                  4        Uu. uF  pR\        VRR4      R\        V4      /NK  	  pp\        T P                  R4      \        4      '       d   T P                  R4      M/ pR\        TP                  R4      4      R	TP                  R
4      RTP                  R4      R\        T;'       g    / P                  R4      ;'       g    R4      R\        TP                  R4      4      RTP                  R4      RRRT/#   \         d    / p EL/i ; iu upi   \         d    \        P                  R4        ELi ; i)rz   )Úget_nous_auth_status_local)Úget_nous_subscription_featuresÚlabelrö   rŽ   zportal features failedÚmodelÚ	logged_inÚ
portal_urlÚportal_base_urlÚinference_urlÚinference_base_urlÚproviderÚ	free_tierÚaccount_tierÚsubscription_urlz3https://portal.nousresearch.com/manage-subscriptionÚfeatures)r6   r!  r  rF   Úhermes_cli.nous_subscriptionr  rÂ   rD   r  rq   rç  r¬   rZ   r­   r�   r=   )Úcfgr€  r  r  r  Úfeatsr  Ú	model_cfgs           r?   r  r  ü  sr  € Ü
‹-×
Ð
˜2€CØ€DðÝ>á)Ó+×1Ð1¨rˆð €Hð1ÝOÙ.¨sÓ3ˆØÒà$)§K¡K¤Mó3Ù$1˜Dð !¤'¨$°¸Ó"<¸gÄ~ÐVZÓG[Ó\Ù$1ð ð 3ô
 %/¨s¯w©w°wÓ/?Ä×$FÒ$F�—‘˜Ô ÈB€Ià”T˜$Ÿ(™( ;Ó/Ó0°,ÀÇÁÐIZÓ@[Ø˜Ÿ™Ð"6Ó7Ø”C˜Ÿ˜ b×-Ñ-¨jÓ9×?Ð?¸RÓ@ð 	”T˜$Ÿ(™( ;Ó/Ó0°.À$Ç(Á(È>ÓBZØÐQØ�Hðð øô ô Ø‹ðüò3øäô 1Ü�‰Ð/×0ð1ús9   ˜E ¬E ²$E' Á#E"Á9E' ÅEÅEÅ"E' Å' FÆ
Fz/api/ops/prompt-sizec                ó:   € V ^8„  d   QhR\         \        ,          /# rU  rW  )r>   s   "r?   r@   r@      s   € ÷ Lñ L¤8¬C¥=ñ LrA   c              ƒ   ó(   "  € \        R .R RV 4      # 5i)zprompt-sizeÚFailed©rÚ  rÞ  s   &r?   Úrun_prompt_sizer'    s   é € ä˜-˜¨-¸À7ÓKÐKùó   ‚z/api/ops/dumpc                ó:   € V ^8„  d   QhR\         \        ,          /# rU  rW  )r>   s   "r?   r@   r@   %  s   € ÷ >ñ >œH¤S�Mñ >rA   c              ƒ   ó(   "  € \        R .R RV 4      # 5i)Údumpr%  r&  rÞ  s   &r?   Úrun_dumpr,  $  s   é € ä˜&˜ 6¨8°WÓ=Ð=ùr(  z/api/ops/config-migratec                ó:   € V ^8„  d   QhR\         \        ,          /# rU  rW  )r>   s   "r?   r@   r@   *  s   € ÷ Uñ U¤h¬s¥mñ UrA   c              ƒ   ó*   "  € \        R R.RRV 4      # 5i)ÚconfigÚmigratezconfig-migrater%  r&  rÞ  s   &r?   Úrun_config_migrater1  )  s   é € ä˜( IÐ.Ð0@À(ÈGÓTÐTùs   ‚z/api/ops/debug-sharec                óT   € V ^8„  d   QhR\         R,          R\        \        ,          /# )r:   r®   NrV  )r   r#   r=   )r>   s   "r?   r@   r@   /  s)   € ÷ \ñ \Ô):¸TÕ)Að \Ü,4´S­Mñ\rA   c           
   ƒ  óÐ  aa"  € ^ RI Ho ^ RIHp T ;'       g    \	        4       o \        VVV3R l4      G Rj  x€L
 pRRRTP                  RTP                  RTP                  RTP                  /#  L8  \         d    h \         d   pT! T4      p\        RRT 2R7      hRp?i\         d3   p\        P                  R4       T! T4      p\        R	R
T 2R7      hRp?ii ; i5i)zãUpload a redacted debug report + full logs and return the paste URLs. Synchronous,
unlike the other diagnostics actions: the point is the shareable URLs, returned as a
structured payload the dashboard renders as copyable links.)Úbuild_debug_share)Úredact_debug_support_textc            
      óŒ   <€ S ! \        ^\        \        SP                  4      R4      4      \	        SP
                  4      R7      # )r/  iˆ  )Ú	log_linesÚredact)ÚmaxÚminrO   Úlinesr�   r8  )r4  Úreqs   €€r?   rô   Ú*run_debug_share_endpoint.<locals>.<lambda>8  s1   ø€ Ñ@QÜ˜!œS¤ S§Y¡Y£°Ó6Ó7ÄÀSÇZÁZÓ@PõARrA   Niö  zUpload failed: r}   zdebug share failedr½  zFailed: r€   TÚurlsÚfailuresÚredactedÚauto_delete_seconds)Úhermes_cli.debugr4  Úhermes_cli.debug_redactionr5  r   r   r   ÚRuntimeErrorrF   rq   rç  r>  r?  r@  rA  )r®   rV  r5  rÚ   rs   Úerrorr4  r<  s   &&    @@r?   Úrun_debug_share_endpointrF  .  sê   ùé € õ 3ÝDØ
×
%Ð
%Ô#Ó%€CðHÜ.¨wõ 9Ró S÷ Sˆð �$˜ §¡¨Z¸¿¹Ø˜Ÿ™Ð)>À×@ZÑ@Zð\ð \ñSøäô ØÜô Oá)¨#Ó.ˆÜ¨°oÀeÀWÐ4MÔNÐNûÜô HÜ�‰Ð+Ô,Ù)¨#Ó.ˆÜ¨°h¸u¸gÐ4FÔGÐGûðHüsO   „!C&¦A5 ºA3»A5 ¿4C&Á3A5 Á5C#Â
C#ÂB#Â#C#Â0C#Â1-CÃC#Ã#C&z	/api/logsc                ó¸   € V ^8„  d   QhR\         R\        R\        \         ,          R\        \         ,          R\        \         ,          R\        \         ,          /# )r:   Úfiler;  ÚlevelÚ	componentÚsearchrV  )r=   rO   r#   )r>   s   "r?   r@   r@   J  sN   € ÷ '+ñ '+Ü
ð'+Ü #ð'+Ü2:¼3µ-ð'+äœ�}ð'+ä-5´c­]ð'+ô ”c�]ñ'+rA   c              ƒ   óÔ  aaaaaa"  € ^ RI HoHp VP                  V 4      pV'       g   \	        RRV  2R7      h\        V4      ;_uu_ 4        \        4       R,          V,          oRRR4       SP                  4       '       g   RV R. /#  ^ R	IH	p V'       d   VP                  4       R
8w  d   TMRoRoV'       dV   VP                  4       R8w  dA   VP                  V4      oSf,   \	        RRV RRP                  \        V4      4       2R7      hVVVVVV3R lp	\        P                   ! V	4      G Rj  x€L
 p
RV RV
/#   + '       g   i     Lâ; i  \         d    / p LÑi ; i L05i)rz   )Ú
_read_tailÚ	LOG_FILESr¤   zUnknown log file: r}   ÚlogsNrH  r;  )ÚCOMPONENT_PREFIXESÚALLrw  zUnknown component: z. Available: z, c                  ó*  <€ S! SS'       g   \        SR 4      MR\        S;'       g    S;'       g    S4      SSR7      p S'       dG   SP                  4       pV  Uu. uF  q!VP                  4       9   g   K  VNK  	  up\        SR 4      ) R p V # u upi )r½  iÐ  )Úhas_filtersÚ	min_levelÚcomponent_prefixesN)r:  r�   r7  )	rÚ   ÚneedleÚlinerM  Úcomp_prefixesr;  Úlog_pathrT  rK  s	      €€€€€€r?   Ú
_load_logsÚget_logs.<locals>._load_logsd  sˆ   ø€ ÙØ¯V”c˜% ”o¸Ü˜Y×AÐA¨-×AÐA¸6ÓBØ°MôCˆ÷ Ø—\‘\“^ˆFÙ'-ÓH¡v˜t¸4¿:¹:»<Ñ1G—d�d¡vÑHÌ#ÈeÐUXË/ÐIYÐIZÐ[ˆFØˆùò Is   ÁBÁ7B)Úhermes_cli.logsrM  rN  rZ   r   r%   r0   ra   Úhermes_loggingrP  ÚImportErrorÚupperr7  ÚjoinÚsortedrm   Ú	to_thread)rH  r;  rI  rJ  rK  rV  rN  Úlog_namerP  rZ  rÚ   rM  rX  rY  rT  s   &f&&f&     @@@@r?   Úget_logsrd  I  sF  ýé € ÷
 6Ø�}‰}˜TÓ"€HßÜ¨Ð6HÈÈÐ4OÔPÐPÜ	˜w×	'Õ	'Ü"Ó$ vÕ-°Õ8ˆ÷ 
(à�?‰?×ÒØ˜˜g rÐ*Ð*ð Ý5÷
  5§;¡;£=°EÔ#9‘¸t€IØ€Mß�Y—_‘_Ó&¨%Ô/Ø*×.Ñ.¨yÓ9ˆØÒ Ü¨CÐ:MÈiÈ[ð Y.Ø.2¯i©i¼Ð?QÓ8RÓ.SÐ-Tð9Vô Wð W÷
ò 
ô ×$Ò$ ZÓ0×0€FØ�D˜' 6Ð*Ð*÷? 
(×	'ûô ô  ØÒð úñ. 1ùsa   ˆAE(ÁE Á&E(ÂE(ÂE ÂE(Â"E(Â<A9E(Ä5E&Ä6
E(Å E	ÅE(ÅE#Å E(Å"E#Å#E(>   r€   rú   r2  rC   )NN)rÍ  éd   NNNN)„Ú__doc__Úconcurrent.futuresrÖ   rH  ÚloggingÚrerm   r™   rz  rc   Úfastapir   Úhermes_cli.web_depsr   r   Úhermes_cli.web_server_gatewayr   Ústarlette.concurrencyr   r   r   Úgateway.statusr	   r
   r   r   r   r   r   r   r   Úgateway.status_servedr   Ú
hermes_clir   Úhermes_cli.configr   r   Úhermes_cli.version_infor   rJ  r   r   Úhermes_cli.web_modelsr   r   r   r   Úhermes_cli.web_routers._commonr   r   r   Úpathlibr    Útypingr!   r"   r#   Ú	getLoggerrq   ÚrouterÚlogs_routerr$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   ro   rÛ   r0  rJ   rh   rt   rZ   r…   r�   r›   r    Úpostr¯   Úcompiler´   r¶   r¼   Ú	frozensetrÃ   rÆ   rÓ   rß   rç   r  r  r"  r<  rS  r�  r¸  rÎ  ÚputrÕ  rÚ  rß  rè  rî  r÷  Údeleterý  r  r	  r  r  r'  r,  r1  rF  rd  rô  rA   r?   Ú<module>r     s¸  ðñó Û Û Û 	Û Û 	Û 
Û Ý ß /Ý BÝ 3ß *÷=÷ =õ =õ
 5Ý 'ß ;Ý 4ß Kß dÓ dß iÑ iÝ ß &Ñ &à×ÒÐ0Ó1€Ù	‹€á‹k€ñ ,0Ð0ZÐ\{Ó+|Ð (ÙÐ4Ð6VÓWÐ Ù-1Ð2^Ð`}Ó-~Ð *Ù%)Ð*NÐPoÓ%pÐ "ÙÐ4Ð6UÓVÐ ÙÐ&Ó'€ÙÐ2Ð4TÓUÐ Ù!%Ð&FÐHiÓ!jÐ ÙÐ2Ð4SÓTÐ ÙÐ0Ó1Ð Ù�Ó€ÙÐ2Ð4GÓHÐ ÙÐ(Ð*=Ó>€ÙÐ,Ð.NÓOÐ ÙÐ&Ó'€ÙÐ6Ð8HÓIÐ Ù!%Ð&FÐHXÓ!YÐ ÙÐ6Ð8OÓPÐ Ù�=Ð"5Ó6€ÙÐ0Ð2BÓCÐ Ù#Ð$BÐDdÓeÐ ð #'Ð Ø #Ð Ú9Ð õõõ$
ð ‡�Ð Ó!ô4ó "ð4ð ‡�ˆMÓñ
Oó ð
Oð ‡�Ð Ó!ôHó "ðHð$ ‡�ÐÓô(ó  ð(ð ‡�Ð%Ó&ô.ó 'ð.ð, #%§*¢*Ð-cÓ"dÐ õYõ

3ñ   )¨,Ð8KÐ)LÓMÐ õUõòDõ õ$_iõD&õ2	õõ@ð< ‡�ˆMÓöc3ó ðc3ðL ‡�ÐÓ ñ5ó !ð5ðv ‡�ˆNÓö8ó ð8ð& ‡�Ð!Ó"ö5ó #ð5÷7ð ‡�ÐÓ öPó !ðPð ‡�Ð!Ó"öVó #ðVõ"ð ‡�Ð Ó!öXó "ðXð ‡�Ð#Ó$öUó %ðUð ‡�Ð Ó!ö_ó "ð_ð ‡�ˆMÓöKó ðKõòðF ‡�Ð#Ó$öLó %ðLð ‡�ˆ_Óö>ó ð>ð ‡�Ð&Ó'öUó (ðUð ‡�Ð#Ó$ö\ó %ð\ð4 ‡��Óö'+ó ò'+rA   