
    `gjQ!                    t   U d Z ddlmZ ddlZddlmZmZ ddlm	Z	 ddl
mZ ddlZddlmZ dZd	Zd
ZdZg dg ddZded<   d!dZddd"dZddd#dZd$dZd%dZdd	 	 	 	 	 	 	 	 	 d&dZd'dZ e       Zded<   d'dZddd(dZd)d*dZdddd	 	 	 	 	 	 	 	 	 d+dZ ddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d,d Z!y)-a  Human-friendly generic gateway status phrases.

These helpers deliberately avoid relaying raw model scratch text.  They turn
Hermes' long-running gateway status surface into short status lines suitable
for chat surfaces.

Built-in defaults live in ``gateway/assets/status_phrases.yaml``. Users can add
portable, profile-relative phrase catalogs under ``HERMES_HOME`` either by using
conventional paths::

    ~/.hermes/status_phrases.yaml
    ~/.hermes/status_phrases/*.yaml

or by pointing config at a relative file/directory::

    display:
      status_phrases:
        path: status_phrases/whatsapp.yaml  # relative to HERMES_HOME
        mode: append                        # append (default) or replace

Absolute paths and ``..`` escapes are ignored on purpose so config stays
profile-portable and does not accidentally read arbitrary files.

Only configured phrase strings are used; raw tool args, commands, previews, and
reasoning text are never interpolated into the returned phrase.
    )annotationsN)MappingMutableSequence)Path)Any)get_hermes_home)statusgenericP      )status_phrases.yamlstatus_phrases)zstill on itzstill working through itzwaiting for the result)zon itzone seczchecking that nowdict[str, list[str]]_FALLBACK_PHRASESc                   t        | t              sg S g }t               }| d t         D ]Z  }t	        |xs d      j                         }|rt        |      t        kD  s||v r9|j                  |       |j                  |       \ |S )N )

isinstancelistset_MAX_CUSTOM_PHRASES_PER_SURFACEstrstriplen_MAX_PHRASE_CHARSappendadd)valuecleanedseenitemphrases        I/root/.hermes/venv/lib/python3.12/site-packages/gateway/status_phrases.py_clean_phrase_listr#   5   s    eT"	GUD667 TZR&&(V'88FdNv N    inherited_modec                  t        |j                  d      xs |xs d      j                         j                         }|dk(  }t	        |j                  d      t
              r|j                  d      n|}t        D ]N  }t        t	        |t
              r|j                  |      nd       }|s2|r|ng | j                  |g       || |<   P y )Nmoder   replacephrases)r   getr   lowerr   r   _STATUS_SURFACESr#   )catalogsectionr&   r(   r)   
phrase_mapsurfacer*   s           r"   _merge_phrase_mappingr2   C   s    w{{6"@n@AGGIOOQDiG+5gkk)6Lg+VY'\cJ# Y$
:W^@_Z^^G%<eij&-73XW[["5M3XPW3X	Yr$   c                   	 t        j                  |j                  d            }t	        |t
              rt        | ||       y y # t        $ r Y y w xY w)Nzutf-8)encodingr%   )yaml	safe_load	read_text	Exceptionr   r   r2   )r.   pathr&   loadeds       r"   _merge_phrase_filer;   N   sQ     @A &'"gvnM #  s   %A 	AAc                >   t        |xs d      j                         }|sy t        |      j                         }|j	                         sd|j
                  v ry | j                         }||z  j                         }	 |j                  |       |S # t        $ r Y y w xY w)Nr   z..)	r   r   r   
expanduseris_absolutepartsresolverelative_to
ValueError)base_dirraw_pathraw	candidatebaseresolveds         r"   _relative_path_underrI   W   s    
hn"

#
#
%CS	$$&I$)//"9Dy ))+HT" O  s   =B 	BBc                    | j                         r| j                  j                         dv r| gS | j                         r t	        d | j                         D              S g S )N   .yml.yamlc              3  x   K   | ]2  }|j                         r |j                  j                         d v r| 4 yw)rK   N)is_filesuffixr,   ).0childs     r"   	<genexpr>z%_iter_phrase_files.<locals>.<genexpr>k   s6      
}}5<<#5#5#7;L#L 
s   8:)rO   rP   r,   is_dirsortediterdir)r9   s    r"   _iter_phrase_filesrW   g   sW    ||~$++++-1BBv{{} 
#||~
 
 	
 Ir$   c                   |y t        |t              r|n|g}|D ]/  }t        ||      }|t        |      D ]  }t	        | ||        1 y )Nr%   )r   r   rI   rW   r;   )r.   pathsrC   r&   	raw_pathsrD   rH   phrase_files           r"   _merge_phrase_pathsr\   r   sf     }#E40ugI T'(;-h7 	TKwNS	T	Tr$   c                     t         j                         D  ci c]  \  } }| t        |       }} }t        t              j                         j                  dz  dz  }t        ||d       |S c c}} w )Nassetsr   r)   r%   )r   itemsr   r   __file__r@   parentr;   )r1   r*   r.   catalog_paths       r"   _load_builtin_catalogrc      sf    >O>U>U>WX*:'7wW%XGX>))+22X=@UULwYGN Ys   A._DEFAULT_PHRASESc                 p    t         j                         D  ci c]  \  } }| t        |       c}} S c c}} w N)rd   r_   r   )r1   r*   s     r"   _copy_default_catalogrg      s-    ;K;Q;Q;ST'7wGT']"TTTs   2rC   c               .   t        |t              syt        |j                  d      xs d      j	                         j                         }|<t        | |j                  d      ||       t        | |j                  d      ||       t        | |       y)z@Merge one display.status_phrases-style section into ``catalog``.Nr(   r   r9   )rC   r&   rY   )r   r   r   r+   r   r,   r\   r2   )r.   r/   rC   r(   s       r"   _merge_phrase_configrj      sy    gw'w{{6".h/557==?DGW[[%88\`aGW[[%9H]ab'7+r$   c                F   t               }t               }t        |t        t              |       t        | t              r| xs i j                  d      nd}t        |t              s|S t        ||j                  d      |       t        ||j                  d      |       |j                  d      }|rkt        |t              r[|j                  |      }t        |t              r:t        ||j                  d      |       t        ||j                  d      |       |S )a>  Resolve built-in + user-configured generic status phrases.

    Resolution order mirrors gateway display settings: built-ins, conventional
    profile-relative user files, global ``display.status_phrases`` (or legacy
    alias ``generic_status_phrases``), then
    ``display.platforms.<platform>.status_phrases``.
    rh   displayNgeneric_status_phrasesr   	platforms)	rg   r   r\   r   _CONVENTIONAL_RELATIVE_PATHSr   r   r+   rj   )user_configplatform_keyr.   hermes_homerl   rn   platform_displays          r"   resolve_status_phrase_catalogrt      s     $%G!#K&B!CkZ4>{G4T{ b%%i0Z^Ggw''++.F"GR]^'++.>"?+VK(I
9g6$==6&0 *:*>*>?W*Xcno *:*>*>?O*P[fgNr$   	tool_namepreviewargsc               d    t        | xs d      j                         j                         }|dv ryy)zCClassify an internal gateway event into a Hermes UI-surface bucket.r   >   r	   waiting	heartbeatlong_runningr	   r
   )r   r   r,   )kindrv   rw   rx   
normalizeds        r"   classify_status_contextr      s2     TZR&&(..0JGGr$   )rv   rw   rx   recentrngr.   c               b   |xs t         }t        | |||      }t        |j                  |      xs |j                  d      xs	 t         d         }	|r#t	        |      }
|	D cg c]	  }||
vs| }}|r|}	|xs t
        }|j                  |	      }||j                  |       |dd= |S c c}w )zPick a short generic status phrase, avoiding recent repeats.

    ``preview`` and ``args`` are accepted for callback compatibility, but their
    raw contents are never embedded in the returned phrase.
    ru   r
   Ni)rd   r   r   r+   r   _randomchoicer   )r}   rv   rw   rx   r   r   r.   phrase_catalogcategory
candidates
recent_setr!   freshpickers                 r"   choose_status_phraser      s     0 0N&ty'X\]Hn((2rn6H6H6SrWghqWrsJ[
&0MFF*4LMMJ^GF]]:&Ff3B3KM Ns   #	B,-B,)r   r   returnz	list[str])r.   r   r/   zMapping[str, Any]r&   
str | Noner   None)r.   r   r9   r   r&   r   r   r   )rC   r   rD   r   r   Path | None)r9   r   r   z
list[Path])
r.   r   rY   r   rC   r   r&   r   r   r   )r   r   )r.   r   r/   r   rC   r   r   r   rf   )rp   zMapping[str, Any] | Nonerq   r   r   r   )
r}   r   rv   r   rw   r   rx   r   r   r   )r}   r   rv   r   rw   r   rx   r   r   zMutableSequence[str] | Noner   r   r.   zMapping[str, list[str]] | Noner   r   )"__doc__
__future__r   randomr   collections.abcr   r   pathlibr   typingr   r5   hermes_constantsr   r-   r   r   ro   r   __annotations__r#   r2   r;   rI   rW   r\   rc   rd   rg   rj   rt   r   r    r$   r"   <module>r      s  6 #  4    ,
 ) "$  H  T8+ '  vz Y cg N   "&T!TT 	T
 T 
T$ *?)@ & @U bf ,> !
  	
  	" !*..2
  	
  ( 
 , 	r$   