
    iT                        U d Z ddlZddlZddlZddlZddlZddlZddlmZ ddl	m
Z
 ddlmZmZmZ ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ  ej        e          ZdZdZdZ dZ!de"fdZ#de"de"de"fdZ$de"de"de"fdZ%ddl&m'Z(m)Z* dZ+dZ,dee"ee"         f         fdZ-dZ.dee/         fdZ0dee         fdZ1dede"dee"         fdZ2d3dee         dee3         fd Z4de"fd!Z5da6ee/         e7d"<    ej8                    Z9d# Z:d4d%e;dee/         fd&Z<d'e/de"fd(Z=d)e"de"fd*Z>	 	 	 	 	 d5d+ed,e"d-e"d.ee3         d/ee"         d0e"d1e/fd2Z?dS )6zWelcome banner, ASCII art, skills summary, and update check for the CLI.

Pure display functions with no HermesCLI state dependency.
    N)Path)get_hermes_home)DictListOptional)Console)Panel)Table)print_formatted_text)ANSIz[1;38;2;255;215;0mz[1mz[2mz[0mtextc                 >    t          t          |                      dS )z:Print ANSI-colored text through prompt_toolkit's renderer.N)	_pt_print_PT_ANSI)r   s    9/home/agentuser/.hermes/hermes-agent/hermes_cli/banner.pycprintr   $   s    htnn    keyfallbackreturnc                 p    	 ddl m}  |                                | |          S # t          $ r |cY S w xY w)z5Get a color from the active skin, or return fallback.r   get_active_skin)hermes_cli.skin_enginer   	get_color	Exceptionr   r   r   s      r   _skin_colorr   -   s[    ::::::  **3999      #& 55c                 p    	 ddl m}  |                                | |          S # t          $ r |cY S w xY w)z?Get a branding string from the active skin, or return fallback.r   r   )r   r   get_brandingr   r   s      r   _skin_brandingr"   6   s[    ::::::  --c8<<<   r   )__version____release_date__u  [bold #FFD700]██╗  ██╗███████╗██████╗ ███╗   ███╗███████╗███████╗       █████╗  ██████╗ ███████╗███╗   ██╗████████╗[/]
[bold #FFD700]██║  ██║██╔════╝██╔══██╗████╗ ████║██╔════╝██╔════╝      ██╔══██╗██╔════╝ ██╔════╝████╗  ██║╚══██╔══╝[/]
[#FFBF00]███████║█████╗  ██████╔╝██╔████╔██║█████╗  ███████╗█████╗███████║██║  ███╗█████╗  ██╔██╗ ██║   ██║[/]
[#FFBF00]██╔══██║██╔══╝  ██╔══██╗██║╚██╔╝██║██╔══╝  ╚════██║╚════╝██╔══██║██║   ██║██╔══╝  ██║╚██╗██║   ██║[/]
[#CD7F32]██║  ██║███████╗██║  ██║██║ ╚═╝ ██║███████╗███████║      ██║  ██║╚██████╔╝███████╗██║ ╚████║   ██║[/]
[#CD7F32]╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝╚═╝     ╚═╝╚══════╝╚══════╝      ╚═╝  ╚═╝ ╚═════╝ ╚══════╝╚═╝  ╚═══╝   ╚═╝[/]u  [#CD7F32]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⡀⠀⣀⣀⠀⢀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#CD7F32]⠀⠀⠀⠀⠀⠀⢀⣠⣴⣾⣿⣿⣇⠸⣿⣿⠇⣸⣿⣿⣷⣦⣄⡀⠀⠀⠀⠀⠀⠀[/]
[#FFBF00]⠀⢀⣠⣴⣶⠿⠋⣩⡿⣿⡿⠻⣿⡇⢠⡄⢸⣿⠟⢿⣿⢿⣍⠙⠿⣶⣦⣄⡀⠀[/]
[#FFBF00]⠀⠀⠉⠉⠁⠶⠟⠋⠀⠉⠀⢀⣈⣁⡈⢁⣈⣁⡀⠀⠉⠀⠙⠻⠶⠈⠉⠉⠀⠀[/]
[#FFD700]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⡿⠛⢁⡈⠛⢿⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#FFD700]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠿⣿⣦⣤⣈⠁⢠⣴⣿⠿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#FFBF00]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠻⢿⣿⣦⡉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#FFBF00]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢷⣦⣈⠛⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#CD7F32]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣴⠦⠈⠙⠿⣦⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#CD7F32]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣿⣤⡈⠁⢤⣿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#B8860B]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠷⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#B8860B]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⠑⢶⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#B8860B]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⠁⢰⡆⠈⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#B8860B]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠳⠈⣡⠞⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#B8860B]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]c                      	 ddl m}   |             }n# t          $ r i cY S w xY wi }|D ]H}|                    d          pd}|                    |g                               |d                    I|S )a  Return skills grouped by category, filtered by platform and disabled state.

    Delegates to ``_find_all_skills()`` from ``tools/skills_tool`` which already
    handles platform gating (``platforms:`` frontmatter) and respects the
    user's ``skills.disabled`` config list.
    r   )_find_all_skillscategorygeneralname)tools.skills_toolr&   r   get
setdefaultappend)r&   
all_skillsskills_by_categoryskillr'   s        r   get_available_skillsr1   b   s    666666%%''

   			 02 J J99Z((5I%%h33::5=IIIIs    ""i`T  c            	         t                      } | dz  }| dz  }|dz                                  s0t          t                    j        j                                        }|dz                                  sdS t          j                    }	 |                                r]t          j        |	                                          }||
                    dd          z
  t          k     r|
                    d          S n# t          $ r Y nw xY w	 t          j        g dd	d
t          |                     n# t          $ r Y nw xY w	 t          j        g dd	d	dt          |                    }|j        dk    r't#          |j                                                  }nd}n# t          $ r d}Y nw xY w	 |                    t          j        ||d                     n# t          $ r Y nw xY w|S )a  Check how many commits behind origin/main the local repo is.

    Does a ``git fetch`` at most once every 6 hours (cached to
    ``~/.hermes/.update_check``).  Returns the number of commits behind,
    or ``None`` if the check fails or isn't applicable.
    hermes-agentz.update_check.gitNtsr   behind)gitfetchoriginz--quietT
   )capture_outputtimeoutcwd)r7   rev-list--countzHEAD..origin/main   r;   r   r<   r=   )r5   r6   )r   existsr   __file__parentresolvetimejsonloads	read_textr+   _UPDATE_CHECK_CACHE_SECONDSr   
subprocessrunstr
returncodeintstdoutstrip
write_textdumps)hermes_homerepo_dir
cache_filenowcachedresultr6   s          r   check_for_updatesrZ   ~   sH    "##K^+H.J v%%'' :>>(/7799v%%'' t )++C 	,Z
 4 4 6 677FVZZa(((+FFFzz(+++   111H	
 	
 	
 	
 	

    ???dAH
 
 

 !!,,..//FFF   djv)F)FGGHHHH    MsJ   A0C? ?
DD'D8 8
EE	AF& &F54F59*G$ $
G10G1c                      t                      } | dz  }|dz                                  s0t          t                    j        j                                        }|dz                                  r|ndS )zKReturn the active Hermes git checkout, or None if this isn't a git install.r3   r4   N)r   rB   r   rC   rD   rE   )rT   rU   s     r   _resolve_repo_dirr\      sm    !##K^+Hv%%'' :>>(/7799 6)1133=88=r   rU   revc           	          	 t          j        ddd|gdddt          |                     }n# t          $ r Y dS w xY w|j        dk    rdS |j        pd	                                }|pdS )
z4Resolve a git revision to an 8-character short hash.r7   z	rev-parsez	--short=8Tr@   rA   Nr    )rK   rL   rM   r   rN   rP   rQ   )rU   r]   rY   values       r   _git_short_hashra      s    	Kc2H
 
 
    ttAt] b''))E=Ds   *- 
;;c           	         | pt                      } | dS t          | d          }t          | d          }|r|sdS d}	 t          j        g ddddt	          |                     }|j        dk    r*t          |j        pd	                                pd	          }n# t          $ r d}Y nw xY w||t          |d          d
S )z8Return upstream/local git hashes for the startup banner.Nzorigin/mainHEADr   )r7   r>   r?   zorigin/main..HEADTr@   rA   0)upstreamlocalahead)r\   ra   rK   rL   rM   rN   rO   rP   rQ   r   max)rU   re   rf   rg   rY   s        r   get_git_banner_stateri      s    .,..Htx77HHf--E 5 tE???H
 
 
 !!-#4466=#>>E    !53ua==IIIs   AB B+*B+c            
         dt            dt           d} t                      }|s| S |d         }|d         }t          |                    d          pd          }|dk    s||k    r|  d| S |d	k    rd
nd}|  d| d| d| d| d
S )z;Return the version label shown in the startup banner title.zHermes Agent vz ()re   rf   rg   r   u    · upstream    commitcommitsu
    · local z (+z	 carried )VERSIONRELEASE_DATEri   rO   r+   )basestatere   rf   rg   carried_words         r   format_banner_version_labelrt      s    6G66|666D ""E Z H'NE		'""'a((EzzX&&//X///$zz88yL^^^^U^^u^^|^^^^r   _update_resultc                  `    d } t          j        | d          }|                                 dS )z4Kick off update check in a background daemon thread.c                  T    t                      at                                           d S N)rZ   ru   _update_check_doneset r   r   _runz#prefetch_update_check.<locals>._run  s%    *,,     r   T)targetdaemonN)	threadingThreadstart)r|   ts     r   prefetch_update_checkr     s9    ! ! ! 	T222AGGIIIIIr         ?r<   c                 F    t                               |            t          S )z:Get result of prefetched check. Returns None if not ready.r<   )ry   waitru   r   s    r   get_update_resultr     s    G,,,r   tokensc                    | dk    r5| dz  }t          |          }t          ||z
            dk     r| dS |ddS | dk    r5| dz  }t          |          }t          ||z
            dk     r| dS |ddS t          |           S )uL   Format a token count for display (e.g. 128000 → '128K', 1048576 → '1M').i@B g?Mz.1fi  K)roundabsrM   )r   valroundeds      r   _format_context_lengthr     s    y **sW}$$=== }}}}	5un**sW}$$=== }}}}v;;r   toolset_namec                 L    | sdS |                      d          r
| dd         n| S )zANormalize internal/legacy toolset identifiers for banner display.unknown_toolsNi)endswith)r   s    r   _display_toolset_namer   0  s=     y   **	SbSr   consolemodelr=   toolsenabled_toolsets
session_idcontext_lengthc                    ddl m}m}	 |ddl m} |pg }|pg } |d          \  }
}t	                      }t	                      }|D ]}|                    dd          }|	                    |i           }|                    d	g           }|                    d
          r|                    |           o|                    |           t          j        d          }|	                    dd           |	                    dd           t          dd          }t          dd          }t          dd          }t          dd          }	 ddlm}  |            }t          |d          r|j        r|j        nt          }n# t           $ r d}t          }Y nw xY wd|dg}d|v r|                    d          d         n|}|                    d          r
|dd         }t'          |          dk    r|dd          d!z   }|rd"| d#| d$t)          |           d%nd}|                    d&| d$| d'| d"| d#| d(           |                    d)| d$| d'           |r|                    d)| d*| d'           d+                    |          }d,| d-g}i }|D ]S} | d.         d         }!t/           ||!          pd/          }"|                    |"g                               |!           T|D ]}|                    d0|                    dd1                    }#t/          |#          }$|$|vrg ||$<   |                    d	g           D ]'}!|!||$         vr||$                             |!           (t3          |                                          }%|%dd2         }&t'          |%          d2z
  }'|&D ]}"||"         }(g })t3          |(          D ]Z}*|*|v r|)                    d3|* d'            |*|v r|)                    d4|* d'           >|)                    d&| d$|* d'           [d5                    |)          }+t'          d5                    t3          |(                              d6k    r g },d}-t3          |(          D ]\}*|-t'          |*          z   d7z   d8k    r|,                    d!            n+|,                    |*           |-t'          |*          d7z   z  }-]g })|,D ]v}*|*d!k    r|)                    d9           |*|v r|)                    d3|* d'           <|*|v r|)                    d4|* d'           Z|)                    d&| d$|* d'           wd5                    |)          }+|                    d)| d$|" d:|+            |'dk    r|                    d)| d;|' d<           	 dd=lm}.  |.            }/n# t           $ r g }/Y nw xY w|/r|                    d           |                    d,| d>           |/D ]p}0|0d?         r>|                    d)| d$|0d          d@| dA|0dB          dC| dD| d$|0d	          dE           H|                    d3|0d          dF|0dB          dG           q|                    d           |                    d,| dH           t;                      }1t=          dI |1                                D                       }2|1rt3          |1                                          D ]}3t3          |1|3                   }4t'          |4          d2k    r7|4dd2         }5d5                    |5          dJt'          |4          d2z
   dKz   }6nd5                    |4          }6t'          |6          dLk    r|6ddM         d!z   }6|                    d)| d$|3 dN| d$|6 d'	           n|                    d)| dO           |                    d           |/rt=          dP |/D                       nd}7t'          |           dQ|2 dRg}8|7r|8                    |7 dS           |8                    dT           	 ddUl m!}9  |9            }:|:r%|:dVk    r|                    d,| dW| d$|: d'           n# t           $ r Y nw xY w|                    d)| d$dX                    |8           d'           	 tE          dYZ          };|;r=|;dk    r7dd[l#m$}< |;d\k    rd]nd^}=|                    d_|; d`|= da |<             db           n# t           $ r Y nw xY wd+                    |          }>|%                    ||>           tM          dcdd          }?t          dedf          }@t          dgdh          }AtO          |d,|@ d$tQ                       d'|Adi          }B| )                                 tU          j+                    j,        }C|Cdjk    rP|rt          |dk          r|j-        r|j-        nt\          }D| )                    |D           | )                                 | )                    |B           dS )la  Build and print a welcome banner with caduceus on left and info on right.

    Args:
        console: Rich Console instance.
        model: Current model name.
        cwd: Current working directory.
        tools: List of tool definitions.
        enabled_toolsets: List of enabled toolset names.
        session_id: Session identifier.
        get_toolset_for_tool: Callable to map tool name -> toolset name.
        context_length: Model's context window size in tokens.
    r   )check_tool_availabilityTOOLSET_REQUIREMENTSN)get_toolset_for_toolT)quietr)   r_   r   check_fn)r      )paddingleftcenter)justifyrightbanner_accentz#FFBF00
banner_dimz#B8860Bbanner_textz#FFF8DCsession_borderz#8B8682r   banner_hero/z.gguf      z...z [dim u   ]·[/] [dim ]z context[/][z[/]z]Nous Research[/]z[dim z
]Session: 
z[bold z]Available Tools[/]functionotheridr      z[red]z[yellow]z, -   r   *   z[dim]...[/]z:[/] z](and z more toolsets...)[/])get_mcp_statusz]MCP Servers[/]	connectedz[/] [z](	transportz
)[/] [dim u	   ]—[/] [z tool(s)[/]z
[/] [dim](u   )[/] [red]— failed[/]z]Available Skills[/]c              3   4   K   | ]}t          |          V  d S rx   )len.0ss     r   	<genexpr>z'build_welcome_banner.<locals>.<genexpr>  s(      CC!s1vvCCCCCCr   z +z more2   /   z:[/] [z]No skills installed[/]c              3   *   K   | ]}|d          
dV  dS )r   rl   Nr{   r   s     r   r   z'build_welcome_banner.<locals>.<genexpr>  s+      @@a;@@@@@@@r   z toolsz skillsz MCP serversz/help for commands)get_active_profile_namedefaultz]Profile:[/] [u    · r   r   )recommended_update_commandrl   rm   rn   u   [bold yellow]⚠  u%    behind[/][dim yellow] — run [bold]z[/bold] to update[/]
agent_namezHermes Agentbanner_titlez#FFD700banner_borderz#CD7F32)titleborder_styler   _   banner_logo)/model_toolsr   r   r   rz   r+   updater
   grid
add_columnr   r   r   hasattrr   HERMES_CADUCEUSr   splitr   r   r   r-   joinr   r,   sortedkeystools.mcp_toolr   r1   sumvalueshermes_cli.profilesr   r   hermes_cli.configr   add_rowr"   r	   rt   printshutilget_terminal_sizecolumnsr   HERMES_AGENT_LOGO)Er   r   r=   r   r   r   r   r   r   r   _unavailable_toolsetsdisabled_tools
lazy_toolsitemr   ts_reqtools_in_tslayout_tableaccentdimr   session_colorr   _bskin_hero
left_linesmodel_shortctx_strleft_contentright_linestoolsets_dicttool	tool_nametoolset
toolset_iddisplay_namesorted_toolsetsdisplay_toolsetsremaining_toolsets
tool_namescolored_namesr)   	tools_strshort_nameslengthr   
mcp_statussrvr/   total_skillsr'   skill_namesdisplay_names
skills_strmcp_connectedsummary_partsr   _profile_namer6   r   commits_wordright_contentr   title_colorborder_colorouter_panel
term_width_logosE                                                                        r   build_welcome_bannerr  ;  s   $ JIIIIIII#444444KRE'-255DAAAAUUN J$ / /xx++%)),;;hhw++::j!! 	/k****!!+....:f---LFH555GV444 )44F
lI
.
.C}i00D 0)<<M :::::: ""&-fm&D&DpI[p""ap        eRJ*-,,%++c""2&&EKG$$ '!#2#&
;"!#2#&.es{asaaaa.D^.T.Taaaay{Gi&ii;ii7ii#iiSViiijjj,c,,C,,,--- LJ-JJ:JJJKKK99Z((L7F7778K%'M @ @$V,	'(<(<Y(G(G(R7SS  "--44Y????$ > >XXdDHHVY$?$?@@
,Z88},,*,M,''2.. 	> 	>Il ;;;l+229===	> ]//1122O&rr*_--1# !D !D"7+
:&& 	; 	;D~%%$$%6T%6%6%67777##$$%9%9%9%9::::$$%9%9%9%9%9%9::::IIm,,	tyy
++,,--22KFz** ( (CII%)B..&&u---E""4(((#d))a-'M# ? ?5==!((7777^++!(():):):):;;;;Z''!(()=D)=)=)=>>>>!(()=T)=)=D)=)=)=>>>>		-00IB3BBBByBBCCCCAW3WW.@WWWXXX111111#^%%

   


  2;F;;;<<< 
	 
	C; 	""KC K K#f+ K KD K KC<L K KK K*.K K14WK K K   
 ""*CK * *3{3C * * *   
 r<<<<===-//CC'9'@'@'B'BCCCCCL A1668899 		U 		UH !3H!=>>K;!## +BQB!YY}558XS=M=MPQ=Q8X8X8XX

!YY{33
:##'_u4
SsSSXSSTSSJSSSTTTT		U 	?3???@@@rDNUC@@:@@@@@@TUME

***|,D,D,DEM =;;;<<<-...??????//11 	Y]i77WWWdWW]WWWXXX    DsDDV[[%?%?DDDEEE
"3/// 	fqjjDDDDDD'-{{88	LaF a a\ a a.H.H.J.Ja a a       IIk**M}555n==Jni88K	::LG{GG%@%B%BGGG!	  K MMOOO)++3JR&,}1O1O}TZTf}""l}eMM+sI   5F FF:W WW7b 
bbAd 
d+*d+rx   )r   )NNNNN)@__doc__rG   loggingr   rK   r   rF   pathlibr   hermes_constantsr   typingr   r   r   rich.consoler   
rich.panelr	   
rich.tabler
   prompt_toolkitr   r   prompt_toolkit.formatted_textr   r   	getLogger__name__logger_GOLD_BOLD_DIM_RSTrM   r   r   r"   
hermes_clir#   ro   r$   rp   r   r   r1   rJ   rO   rZ   r\   ra   dictri   rt   ru   __annotations__Eventry   r   floatr   r   r   r  r{   r   r   <module>r0     s    
                   , , , , , , ' ' ' ' ' ' ' ' ' '                         < < < < < < : : : : : :		8	$	$ 	!    S C C     s s     P O O O O O O OF j,d3S	>2    2 ' 98C= 9 9 9 9x>8D> > > > >d  #    $J J8D> JXd^ J J J J8_S _ _ _ _, !% $ $ $$Y_&&    u x}    3 3    "      .27;+/.2/3\ \' \# \C \ $T
\+/9\ &)\
 *-\ \ \ \ \ \r   