
    iΚ                        U d Z ddlZddlmZmZ ddlmZ ddlmZm	Z	m
Z
mZmZ ddlmZ  ej        e          Ze G d d                      Zd	d
ddddddddddddddddi dddddddddd d!d"d#d$d%d&d$d#dddd&d"d#d#d'dg d(g d)g d*d+d,gd-d.gd/d0gd1d2ggd3d4d5d6d7d8d9dd:d;d<d=d>d?d@dAdBdCdDdBdEdEdFdGdDdCdBdEd@di ddddddHddddIdJdKdLdMdNdDdLdMdOdPdQdDdKdLdLdNdi ddddddddddRdSi dTdUdVdWdXdYdZd[d\d]d^dUd_d`dadbdcdddedfdgd]dhdidjdUdkdYdldmdndodpdodqdrdsdtdui ddddddHddvddwdxi dTdydVdzdXd{dZd|d\d}d^d{d_dzdad~dcddeddgd}dhdydjdydkdzdlddnddpddddddui dddddddddddddddddddddddddddg dg dg dddgddgddgddggd3ddddddddvddd=ddddddddddddddddddg dg dg dddgddgddgddggd3ddddddddvddd=ddddddddddddddddddg dĢg dŢg dƢddgd-d.gddgddggd3ddddddddvddd=dӜ	Ze	ee	eef         f         ed<   daee         ed<   d	aeed<   defd؄Zdedee	eef                  fdڄZde	eef         defd܄Zde
e	eef                  fd݄Zdedefd߄ZdefdZdedefdZdefdZde ddfdZ!ddedefdZ"ddedefdZ#ddedefdZ$de	eef         fdZ%dS )u  Hermes CLI skin/theme engine.

A data-driven skin system that lets users customize the CLI's visual appearance.
Skins are defined as YAML files in ~/.hermes/skins/ or as built-in presets.
No code changes are needed to add a new skin.

SKIN YAML SCHEMA
================

All fields are optional. Missing values inherit from the ``default`` skin.

.. code-block:: yaml

    # Required: skin identity
    name: mytheme                         # Unique skin name (lowercase, hyphens ok)
    description: Short description        # Shown in /skin listing

    # Colors: hex values for Rich markup (banner, UI, response box)
    colors:
      banner_border: "#CD7F32"            # Panel border color
      banner_title: "#FFD700"             # Panel title text color
      banner_accent: "#FFBF00"            # Section headers (Available Tools, etc.)
      banner_dim: "#B8860B"               # Dim/muted text (separators, labels)
      banner_text: "#FFF8DC"              # Body text (tool names, skill names)
      ui_accent: "#FFBF00"               # General UI accent
      ui_label: "#4dd0e1"                # UI labels
      ui_ok: "#4caf50"                   # Success indicators
      ui_error: "#ef5350"                # Error indicators
      ui_warn: "#ffa726"                 # Warning indicators
      prompt: "#FFF8DC"                  # Prompt text color
      input_rule: "#CD7F32"              # Input area horizontal rule
      response_border: "#FFD700"         # Response box border (ANSI)
      session_label: "#DAA520"           # Session label color
      session_border: "#8B8682"          # Session ID dim color
      status_bar_bg: "#1a1a2e"          # TUI status/usage bar background
      voice_status_bg: "#1a1a2e"        # TUI voice status background
      completion_menu_bg: "#1a1a2e"      # Completion menu background
      completion_menu_current_bg: "#333355"  # Active completion row background
      completion_menu_meta_bg: "#1a1a2e"     # Completion meta column background
      completion_menu_meta_current_bg: "#333355"  # Active completion meta background

    # Spinner: customize the animated spinner during API calls
    spinner:
      waiting_faces:                      # Faces shown while waiting for API
        - "(⚔)"
        - "(⛨)"
      thinking_faces:                     # Faces shown during reasoning
        - "(⌁)"
        - "(<>)"
      thinking_verbs:                     # Verbs for spinner messages
        - "forging"
        - "plotting"
      wings:                              # Optional left/right spinner decorations
        - ["⟪⚔", "⚔⟫"]                  # Each entry is [left, right] pair
        - ["⟪▲", "▲⟫"]

    # Branding: text strings used throughout the CLI
    branding:
      agent_name: "Hermes Agent"          # Banner title, status display
      welcome: "Welcome message"          # Shown at CLI startup
      goodbye: "Goodbye! ⚕"              # Shown on exit
      response_label: " ⚕ Hermes "       # Response box header label
      prompt_symbol: "❯ "                # Input prompt symbol
      help_header: "(^_^)? Commands"      # /help header text

    # Tool prefix: character for tool output lines (default: ┊)
    tool_prefix: "┊"

    # Tool emojis: override the default emoji for any tool (used in spinners & progress)
    tool_emojis:
      terminal: "⚔"           # Override terminal tool emoji
      web_search: "🔮"        # Override web_search tool emoji
      # Any tool not listed here uses its registry default

USAGE
=====

.. code-block:: python

    from hermes_cli.skin_engine import get_active_skin, list_skins, set_active_skin

    skin = get_active_skin()
    print(skin.colors["banner_title"])    # "#FFD700"
    print(skin.get_branding("agent_name"))  # "Hermes Agent"

    set_active_skin("ares")               # Switch to built-in ares skin
    set_active_skin("mytheme")            # Switch to user skin from ~/.hermes/skins/

BUILT-IN SKINS
==============

- ``default`` — Classic Hermes gold/kawaii (the current look)
- ``ares``    — Crimson/bronze war-god theme with custom spinner wings
- ``mono``    — Clean grayscale monochrome
- ``slate``   — Cool blue developer-focused theme
- ``daylight`` — Light background theme with dark text and blue accents
- ``warm-lightmode`` — Warm brown/gold text for light terminal backgrounds

USER SKINS
==========

Drop a YAML file in ``~/.hermes/skins/<name>.yaml`` following the schema above.
Activate with ``/skin <name>`` in the CLI or ``display.skin: <name>`` in config.yaml.
    N)	dataclassfield)Path)AnyDictListOptionalTupleget_hermes_homec                   r   e Zd ZU dZeed<   dZeed<    ee          Z	e
eef         ed<    ee          Ze
eef         ed<    ee          Ze
eef         ed<   d	Zeed
<    ee          Ze
eef         ed<   dZeed<   dZeed<   ddededefdZdeeeef                  fdZddededefdZdS )
SkinConfigzComplete skin configuration.name description)default_factorycolorsspinnerbranding   ┊tool_prefixtool_emojisbanner_logobanner_herokeyfallbackreturnc                 8    | j                             ||          S )z Get a color value with fallback.)r   getselfr   r   s      >/home/agentuser/.hermes/hermes-agent/hermes_cli/skin_engine.py	get_colorzSkinConfig.get_color   s    {sH---    c                 "   | j                             dg           }g }|D ]n}t          |t          t          f          rPt          |          dk    r=|                    t          |d                   t          |d                   f           o|S )z.Get spinner wing pairs, or empty list if none.wings   r      )r   r   
isinstancelisttuplelenappendstr)r!   rawresultpairs       r"   get_spinner_wingszSkinConfig.get_spinner_wings   s    lw++ 	< 	<D$u.. <3t99>>s47||Sa\\:;;;r$   c                 8    | j                             ||          S )z#Get a branding value with fallback.)r   r   r    s      r"   get_brandingzSkinConfig.get_branding   s    }  h///r$   N)r   )__name__
__module____qualname____doc__r.   __annotations__r   r   dictr   r   r   r   r   r   r   r   r   r#   r   r
   r2   r4    r$   r"   r   r   x   s}        &&
IIIK"U4888FDcN888#eD999GT#s(^999$uT:::Hd38n:::K"'%"="="=Kc3h===KK. .S .C . . . . .4c3h#8    0 0 0s 0C 0 0 0 0 0 0r$   r   defaultu"   Classic Hermes — gold and kawaii#CD7F32#FFD700z#FFBF00z#B8860B#FFF8DCz#4dd0e1z#4caf50z#ef5350z#ffa726z#DAA520z#8B8682)banner_borderbanner_titlebanner_accent
banner_dimbanner_text	ui_accentui_labelui_okui_errorui_warnprompt
input_ruleresponse_bordersession_labelsession_borderzHermes AgentzAWelcome to Hermes Agent! Type your message or /help for commands.   Goodbye! ⚕u    ⚕ Hermes    ❯ (^_^)? Available Commands)
agent_namewelcomegoodbyeresponse_labelprompt_symbolhelp_headerr   )r   r   r   r   r   r   aresu$   War-god theme — crimson and bronzez#9F1C1Cz#C7A96Bz#DD4A3Az#6B1717z#F1E6CFz#6E584B)   (⚔)   (⛨)   (▲)(<>)z(/))rY   rZ   r[      (⌁)r\   )forgingmarchingzsizing the fieldzholding the linezhammering plansztempering steelzplotting impactzraising the shieldu   ⟪⚔u   ⚔⟫u   ⟪▲u   ▲⟫u   ⟪╸u   ╺⟫u   ⟪⛨u   ⛨⟫)waiting_facesthinking_facesthinking_verbsr&   z
Ares Agentz?Welcome to Ares Agent! Type your message or /help for commands.u   Farewell, warrior! ⚔u
    ⚔ Ares u   ⚔ ❯ u   (⚔) Available Commandsu   ╎uW  [bold #A3261F] █████╗ ██████╗ ███████╗███████╗       █████╗  ██████╗ ███████╗███╗   ██╗████████╗[/]
[bold #B73122]██╔══██╗██╔══██╗██╔════╝██╔════╝      ██╔══██╗██╔════╝ ██╔════╝████╗  ██║╚══██╔══╝[/]
[#C93C24]███████║██████╔╝█████╗  ███████╗█████╗███████║██║  ███╗█████╗  ██╔██╗ ██║   ██║[/]
[#D84A28]██╔══██║██╔══██╗██╔══╝  ╚════██║╚════╝██╔══██║██║   ██║██╔══╝  ██║╚██╗██║   ██║[/]
[#E15A2D]██║  ██║██║  ██║███████╗███████║      ██║  ██║╚██████╔╝███████╗██║ ╚████║   ██║[/]
[#EB6C32]╚═╝  ╚═╝╚═╝  ╚═╝╚══════╝╚══════╝      ╚═╝  ╚═╝ ╚═════╝ ╚══════╝╚═╝  ╚═══╝   ╚═╝[/]u  [#9F1C1C]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣤⣤⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#9F1C1C]⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⠟⠻⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#C7A96B]⠀⠀⠀⠀⠀⠀⠀⣠⣾⡿⠋⠀⠀⠀⠙⢿⣷⣄⠀⠀⠀⠀⠀⠀⠀[/]
[#C7A96B]⠀⠀⠀⠀⠀⢀⣾⡿⠋⠀⠀⢠⡄⠀⠀⠙⢿⣷⡀⠀⠀⠀⠀⠀[/]
[#DD4A3A]⠀⠀⠀⠀⣰⣿⠟⠀⠀⠀⣰⣿⣿⣆⠀⠀⠀⠻⣿⣆⠀⠀⠀⠀[/]
[#DD4A3A]⠀⠀⠀⢰⣿⠏⠀⠀⢀⣾⡿⠉⢿⣷⡀⠀⠀⠹⣿⡆⠀⠀⠀[/]
[#9F1C1C]⠀⠀⠀⣿⡟⠀⠀⣠⣿⠟⠀⠀⠀⠻⣿⣄⠀⠀⢻⣿⠀⠀⠀[/]
[#9F1C1C]⠀⠀⠀⣿⡇⠀⠀⠙⠋⠀⠀⚔⠀⠀⠙⠋⠀⠀⢸⣿⠀⠀⠀[/]
[#6B1717]⠀⠀⠀⢿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⡿⠀⠀⠀[/]
[#6B1717]⠀⠀⠀⠘⢿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⡿⠃⠀⠀⠀[/]
[#C7A96B]⠀⠀⠀⠀⠈⠻⣿⣷⣦⣤⣀⣀⣤⣤⣶⣿⠿⠋⠀⠀⠀⠀[/]
[#C7A96B]⠀⠀⠀⠀⠀⠀⠀⠉⠛⠿⠿⠿⠿⠛⠉⠀⠀⠀⠀⠀⠀⠀[/]
[#DD4A3A]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⚔⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[dim #6B1717]⠀⠀⠀⠀⠀⠀⠀⠀war god online⠀⠀⠀⠀⠀⠀⠀⠀[/])r   r   r   r   r   r   r   r   monou   Monochrome — clean grayscale#555555z#e6edf3z#aaaaaaz#444444z#c9d1d9z#888888z#ccccccz#999999z[?] Available Commandsslateu   Cool blue — developer-focusedz#4169e1z#7eb8f6z#8EA8FFz#4b5563z#63D0A6z#F7A072z#e6a855daylightzELight theme for bright terminals with dark text and cool blue accentsr@   z#2563EBrA   z#0F172ArB   z#1D4ED8rC   z#475569rD   z#111827rE   rF   z#0F766ErG   z#15803DrH   z#B91C1CrI   z#B45309rJ   rK   z#93C5FDrL   rM   rN   z#64748Bstatus_bar_bgz#E5EDF8voice_status_bgz#F8FAFCz#DBEAFEz#EEF2FFz#BFDBFE)completion_menu_bgcompletion_menu_current_bgcompletion_menu_meta_bgcompletion_menu_meta_current_bgu   │warm-lightmodeuG   Warm light mode — dark brown/gold text for light terminal backgroundsz#8B6914z#5C3D11z#8B4513z#8B7355z#2C1810z#2E7D32z#C62828z#E65100z#A0845Cz#F5F0E8z#F5EFE0z#E8DCC8z#F0E8D8z#DFCFB0poseidonu)   Ocean-god theme — deep blue and seafoamz#2A6FB9z#A9DFFFz#5DB8F5z#153C73z#EAF7FFz#496884)   (≈)   (Ψ)   (∿)   (◌)u   (◠))rp   rq   ro   r]   rr   )zcharting currentszsounding the depthzreading foam lineszsteering the tridentztracking undertowzplotting sea laneszcalling the swellzmeasuring pressureu   ⟪≈u   ≈⟫u   ⟪Ψu   Ψ⟫u   ⟪∿u   ∿⟫u   ⟪◌u   ◌⟫zPoseidon AgentzCWelcome to Poseidon Agent! Type your message or /help for commands.u   Fair winds! Ψu    Ψ Poseidon u   Ψ ❯ u   (Ψ) Available Commandsu=  [bold #B8E8FF]██████╗  ██████╗ ███████╗███████╗██╗██████╗  ██████╗ ███╗   ██╗       █████╗  ██████╗ ███████╗███╗   ██╗████████╗[/]
[bold #97D6FF]██╔══██╗██╔═══██╗██╔════╝██╔════╝██║██╔══██╗██╔═══██╗████╗  ██║      ██╔══██╗██╔════╝ ██╔════╝████╗  ██║╚══██╔══╝[/]
[#75C1F6]██████╔╝██║   ██║███████╗█████╗  ██║██║  ██║██║   ██║██╔██╗ ██║█████╗███████║██║  ███╗█████╗  ██╔██╗ ██║   ██║[/]
[#4FA2E0]██╔═══╝ ██║   ██║╚════██║██╔══╝  ██║██║  ██║██║   ██║██║╚██╗██║╚════╝██╔══██║██║   ██║██╔══╝  ██║╚██╗██║   ██║[/]
[#2E7CC7]██║     ╚██████╔╝███████║███████╗██║██████╔╝╚██████╔╝██║ ╚████║      ██║  ██║╚██████╔╝███████╗██║ ╚████║   ██║[/]
[#1B4F95]╚═╝      ╚═════╝ ╚══════╝╚══════╝╚═╝╚═════╝  ╚═════╝ ╚═╝  ╚═══╝      ╚═╝  ╚═╝ ╚═════╝ ╚══════╝╚═╝  ╚═══╝   ╚═╝[/]u9  [#2A6FB9]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#5DB8F5]⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#5DB8F5]⠀⠀⠀⠀⠀⠀⠀⢠⣿⠏⠀Ψ⠀⠹⣿⡄⠀⠀⠀⠀⠀⠀⠀[/]
[#A9DFFF]⠀⠀⠀⠀⠀⠀⠀⣿⡟⠀⠀⠀⠀⠀⢻⣿⠀⠀⠀⠀⠀⠀⠀[/]
[#A9DFFF]⠀⠀⠀≈≈≈≈≈⣿⡇⠀⠀⠀⠀⠀⢸⣿≈≈≈≈≈⠀⠀⠀[/]
[#5DB8F5]⠀⠀⠀⠀⠀⠀⠀⣿⡇⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⠀[/]
[#2A6FB9]⠀⠀⠀⠀⠀⠀⠀⢿⣧⠀⠀⠀⠀⠀⣼⡿⠀⠀⠀⠀⠀⠀⠀[/]
[#2A6FB9]⠀⠀⠀⠀⠀⠀⠀⠘⢿⣷⣄⣀⣠⣾⡿⠃⠀⠀⠀⠀⠀⠀⠀[/]
[#153C73]⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⣿⡿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#153C73]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#5DB8F5]⠀⠀⠀⠀⠀≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈⠀⠀⠀⠀⠀[/]
[#A9DFFF]⠀⠀⠀⠀⠀⠀≈≈≈≈≈≈≈≈≈≈≈≈≈⠀⠀⠀⠀⠀⠀[/]
[dim #153C73]⠀⠀⠀⠀⠀⠀⠀deep waters hold⠀⠀⠀⠀⠀⠀⠀[/]sisyphusu6   Sisyphean theme — austere grayscale with persistencez#B7B7B7z#F5F5F5z#E7E7E7z#4A4A4Az#D3D3D3z#919191z#656565)   (◉)rr      (◬)u   (⬤)z(::))rt   ru   rr   u   (○)u   (●))zfinding tractionzmeasuring the gradezresetting the boulderzcounting the ascentztesting leveragezsetting the shoulderzpushing uphillzenduring the loopu   ⟪◉u   ◉⟫u   ⟪◬u   ◬⟫u   ⟪⬤u   ⬤⟫zSisyphus AgentzCWelcome to Sisyphus Agent! Type your message or /help for commands.u   The boulder waits. ◉u    ◉ Sisyphus u   ◉ ❯ u   (◉) Available Commandsu  [bold #F5F5F5]███████╗██╗███████╗██╗   ██╗██████╗ ██╗  ██╗██╗   ██╗███████╗       █████╗  ██████╗ ███████╗███╗   ██╗████████╗[/]
[bold #E7E7E7]██╔════╝██║██╔════╝╚██╗ ██╔╝██╔══██╗██║  ██║██║   ██║██╔════╝      ██╔══██╗██╔════╝ ██╔════╝████╗  ██║╚══██╔══╝[/]
[#D7D7D7]███████╗██║███████╗ ╚████╔╝ ██████╔╝███████║██║   ██║███████╗█████╗███████║██║  ███╗█████╗  ██╔██╗ ██║   ██║[/]
[#BFBFBF]╚════██║██║╚════██║  ╚██╔╝  ██╔═══╝ ██╔══██║██║   ██║╚════██║╚════╝██╔══██║██║   ██║██╔══╝  ██║╚██╗██║   ██║[/]
[#8F8F8F]███████║██║███████║   ██║   ██║     ██║  ██║╚██████╔╝███████║      ██║  ██║╚██████╔╝███████╗██║ ╚████║   ██║[/]
[#626262]╚══════╝╚═╝╚══════╝   ╚═╝   ╚═╝     ╚═╝  ╚═╝ ╚═════╝ ╚══════╝      ╚═╝  ╚═╝ ╚═════╝ ╚══════╝╚═╝  ╚═══╝   ╚═╝[/]ur  [#B7B7B7]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#D3D3D3]⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#E7E7E7]⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀[/]
[#F5F5F5]⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀[/]
[#E7E7E7]⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀[/]
[#D3D3D3]⠀⠀⠀⠀⠀⠀⠘⢿⣿⣿⣿⣿⣿⡿⠃⠀⠀⠀⠀⠀⠀⠀[/]
[#B7B7B7]⠀⠀⠀⠀⠀⠀⠀⠀⠙⠿⣿⠿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#919191]⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#656565]⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#656565]⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#4A4A4A]⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#4A4A4A]⠀⠀⠀⠀⠀⣀⣴⣿⣿⣿⣿⣿⣿⣦⣀⠀⠀⠀⠀⠀⠀[/]
[#656565]⠀⠀⠀━━━━━━━━━━━━━━━━━━━━━━━⠀⠀⠀[/]
[dim #4A4A4A]⠀⠀⠀⠀⠀⠀⠀⠀⠀the boulder⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]	charizardu)   Volcanic theme — burnt orange and emberz#C75B1Dz#FFD39Az#F29C38z#7A3511z#FFF0D4z#6C4724)   (✦)r[      (◇)r\      (🔥))rw   r[   rx   r]   ry   )zbanking into the draftzmeasuring burnzreading the updraftztracking ember fallzsetting wing anglezholding the flame corezplotting a hot landingzcoiling for liftu   ⟪✦u   ✦⟫u   ⟪◇u   ◇⟫zCharizard AgentzDWelcome to Charizard Agent! Type your message or /help for commands.u   Flame out! ✦u    ✦ Charizard u   ✦ ❯ u   (✦) Available Commandsu  [bold #FFF0D4] ██████╗██╗  ██╗ █████╗ ██████╗ ██╗███████╗ █████╗ ██████╗ ██████╗        █████╗  ██████╗ ███████╗███╗   ██╗████████╗[/]
[bold #FFD39A]██╔════╝██║  ██║██╔══██╗██╔══██╗██║╚══███╔╝██╔══██╗██╔══██╗██╔══██╗      ██╔══██╗██╔════╝ ██╔════╝████╗  ██║╚══██╔══╝[/]
[#F29C38]██║     ███████║███████║██████╔╝██║  ███╔╝ ███████║██████╔╝██║  ██║█████╗███████║██║  ███╗█████╗  ██╔██╗ ██║   ██║[/]
[#E2832B]██║     ██╔══██║██╔══██║██╔══██╗██║ ███╔╝  ██╔══██║██╔══██╗██║  ██║╚════╝██╔══██║██║   ██║██╔══╝  ██║╚██╗██║   ██║[/]
[#C75B1D]╚██████╗██║  ██║██║  ██║██║  ██║██║███████╗██║  ██║██║  ██║██████╔╝      ██║  ██║╚██████╔╝███████╗██║ ╚████║   ██║[/]
[#7A3511] ╚═════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═════╝       ╚═╝  ╚═╝ ╚═════╝ ╚══════╝╚═╝  ╚═══╝   ╚═╝[/]u  [#FFD39A]⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⠶⠶⠶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#F29C38]⠀⠀⠀⠀⠀⠀⣴⠟⠁⠀⠀⠀⠀⠈⠻⣦⠀⠀⠀⠀⠀⠀[/]
[#F29C38]⠀⠀⠀⠀⠀⣼⠏⠀⠀⠀✦⠀⠀⠀⠀⠹⣧⠀⠀⠀⠀⠀[/]
[#E2832B]⠀⠀⠀⠀⢰⡟⠀⠀⣀⣤⣤⣤⣀⠀⠀⠀⢻⡆⠀⠀⠀⠀[/]
[#E2832B]⠀⠀⣠⡾⠛⠁⣠⣾⠟⠉⠀⠉⠻⣷⣄⠀⠈⠛⢷⣄⠀⠀[/]
[#C75B1D]⠀⣼⠟⠀⢀⣾⠟⠁⠀⠀⠀⠀⠀⠈⠻⣷⡀⠀⠻⣧⠀[/]
[#C75B1D]⢸⡟⠀⠀⣿⡟⠀⠀⠀🔥⠀⠀⠀⠀⢻⣿⠀⠀⢻⡇[/]
[#7A3511]⠀⠻⣦⡀⠘⢿⣧⡀⠀⠀⠀⠀⠀⢀⣼⡿⠃⢀⣴⠟⠀[/]
[#7A3511]⠀⠀⠈⠻⣦⣀⠙⢿⣷⣤⣤⣤⣾⡿⠋⣀⣴⠟⠁⠀⠀[/]
[#C75B1D]⠀⠀⠀⠀⠈⠙⠛⠶⠤⠭⠭⠤⠶⠛⠋⠁⠀⠀⠀⠀[/]
[#F29C38]⠀⠀⠀⠀⠀⠀⠀⠀⣰⡿⢿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀[/]
[#F29C38]⠀⠀⠀⠀⠀⠀⠀⣼⡟⠀⠀⢻⣧⠀⠀⠀⠀⠀⠀⠀⠀[/]
[dim #7A3511]⠀⠀⠀⠀⠀⠀⠀tail flame lit⠀⠀⠀⠀⠀⠀⠀⠀[/])	r<   rX   rc   re   rf   rm   rn   rs   rv   _BUILTIN_SKINS_active_skin_active_skin_namer   c                  $    t                      dz  S )zUser skins directory.skinsr   r;   r$   r"   
_skins_dirr   Q  s    w&&r$   pathc                 ,   	 ddl }t          | dd          5 }|                    |          }ddd           n# 1 swxY w Y   t          |t                    rd|v r|S n3# t
          $ r&}t                              d| |           Y d}~nd}~ww xY wdS )z(Load a skin definition from a YAML file.r   Nrzutf-8)encodingr   zFailed to load skin from %s: %s)yamlopen	safe_loadr)   r:   	Exceptionloggerdebug)r   r   fdataes        r"   _load_skin_from_yamlr   V  s    A$g... 	%!>>!$$D	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	%dD!! 	fnnK A A A6a@@@@@@@@A4s4   A! :A! >A! >A! !
B+BBr   c                 ,   t           d         }t          |                    di                     }|                    |                     di                      t          |                    di                     }|                    |                     di                      t          |                    di                     }|                    |                     di                      t	          |                     dd          |                     dd          ||||                     d	|                    d	d
                    |                     di           |                     dd          |                     dd          	  	        S )zBBuild a SkinConfig from a raw dict (built-in or loaded from YAML).r<   r   r   r   r   unknownr   r   r   r   r   r   r   )	r   r   r   r   r   r   r   r   r   )rz   r:   r   updater   )r   r<   r   r   r   s        r"   _build_skin_configr   c  sS    Y'G'++h++,,F
MM$((8R(()))7;;y"--..GNN488Ir**+++GKK
B//00HOODHHZ,,---XXfi((HH]B//HH]GKKu,M,MNNHH]B//HH]B//HH]B//
 
 
 
r$   c                     g } t                                           D ]2\  }}|                     ||                    dd          dd           3t	                      }|                                rt          |                    d                    D ]w}t          |          }|rd|                    d|j	                  t          fd| D                       rJ|                     |                    dd          dd           x| S )	zList all available skins (built-in + user-installed).

    Returns list of {"name": ..., "description": ..., "source": "builtin"|"user"}.
    r   r   builtin)r   r   sourcez*.yamlr   c              3   0   K   | ]}|d          k    V  dS )r   Nr;   ).0s	skin_names     r"   	<genexpr>zlist_skins.<locals>.<genexpr>  s,      >>!qyI->>>>>>r$   user)rz   itemsr-   r   r   is_dirsortedglobr   stemany)r0   r   r   
skins_pathr   r   s        @r"   
list_skinsr   {  s8   
 F$**,,  
d88M266
 
 	 	 	 	 J 
1122 	 	A'**D 	 HHVQV44	>>>>v>>>>> %#'88M2#>#>$     Mr$   r   c                 F   t                      }||  dz  }|                                r t          |          }|rt          |          S | t          v rt          t          |                    S t
                              d|            t          t          d                   S )z<Load a skin by name. Checks user skins first, then built-in.z.yamlz"Skin '%s' not found, using defaultr<   )r   is_filer   r   rz   r   warning)r   r   	user_filer   s       r"   	load_skinr     s     J^^^+I ,#I.. 	,%d+++ ~!."6777 NN7>>>nY7888r$   c                  F    t           t          t                    a t           S )z.Get the currently active skin config (cached).)r{   r   r|   r;   r$   r"   get_active_skinr     s      !233r$   c                 2    | a t          |           at          S )z3Switch the active skin. Returns the new SkinConfig.)r|   r   r{   )r   s    r"   set_active_skinr     s     T??Lr$   c                      t           S )z*Get the name of the currently active skin.)r|   r;   r$   r"   get_active_skin_namer     s    r$   configc                 D   |                      d          pi }t          |t                    si }|                     dd          }t          |t                    r7|                                r#t          |                                           dS t          d           dS )z|Initialize the active skin from CLI config at startup.

    Call this once during CLI init with the loaded config dict.
    displayskinr<   N)r   r)   r:   r.   stripr   )r   r   r   s      r"   init_skin_from_configr     s    
 jj##)rGgt$$ FI..I)S!! #ioo&7&7 #	))*****	"""""r$   r   c                 l    	 t                                          d|           S # t          $ r | cY S w xY w)z7Get the interactive prompt symbol from the active skin.rV   r   r4   r   r   s    r"   get_active_prompt_symbolr     sG      --oxHHH      !$ 33c                 l    	 t                                          d|           S # t          $ r | cY S w xY w)z*Get the /help header from the active skin.rW   r   r   s    r"   get_active_help_headerr     sG      --mXFFF   r   c                 l    	 t                                          d|           S # t          $ r | cY S w xY w)z*Get the goodbye line from the active skin.rT   r   r   s    r"   get_active_goodbyer     sG      --iBBB   r   c            	         	 t                      } n# t          $ r i cY S w xY w|                     dd          }|                     dd          }|                     dd          }|                     d|          }|                     dd	          }|                     d
|          }|                     dd          }|                     dd          }|                     dd          }	|                     d|	          }
|                     dd          }|                     dd          }|                     d|          }|                     d|          }i d|d| dd|d| dd| ddd|	 d| dd|	 d| d d!d|	 d| d"d|	 d|                     d#d$           d d%d|	 d| d d&d|	 d|                     d'|           d d(d|	 d| d d)|d*| d d+d| d| d,d| d| d-d| d| i d.d| d| d/d| d| d0|d1| d d2| d d3|d4| d d5| dd6|d7| d d8|d9| d d:|d;|d<| d d=| d d>| d|| d d|
 d| d|
 d| d d?S )@zReturn prompt_toolkit style overrides derived from the active skin.

    These are layered on top of the CLI's base TUI style so /skin can refresh
    the live prompt_toolkit UI immediately without rebuilding the app.
    rJ   r?   rK   r=   rA   r>   rD   rC   rd   rF   rI   z#FF8C00rH   z#FF6B6Brg   z#1a1a2erh   ri   rj   z#333355rk   rl   z
input-areaplaceholderz italiczprompt-workinghintz
status-barzbg: zstatus-bar-strongz boldzstatus-bar-dimzstatus-bar-goodrG   z#8FBC8Fzstatus-bar-warnzstatus-bar-badrB   zstatus-bar-criticalz
input-rulezimage-badgezcompletion-menuzcompletion-menu.completionz"completion-menu.completion.currentzcompletion-menu.meta.completionz'completion-menu.meta.completion.currentzclarify-borderzclarify-titlezclarify-questionzclarify-choicezclarify-selectedzclarify-active-otherzclarify-countdownzsudo-promptzsudo-borderz
sudo-titlez	sudo-textzapproval-borderzapproval-titlezapproval-desczapproval-cmd)zapproval-choicezapproval-selectedzvoice-statuszvoice-status-recording)r   r   r#   )r   rJ   rK   titletextdimlabelwarnerror	status_bgvoice_bgmenu_bgmenu_current_bgmenu_meta_bgmenu_meta_current_bgs                  r"   "get_prompt_toolkit_style_overridesr     s        			 ^^Hi00Fi88JNN>955E>>-00D
..y
1
1CNN:u--E>>)Y//DNN:y11E	::I~~/;;Hnn19==Gnn%A9MMO>>";WEEL>>*K_]]'f'#' 	&' 	S///	'
 	3' 	.I....' 	;9;;u;;;' 	1	11C11' 	VVVT^^GY-O-OVVV' 	888T888' 	X	XXDNN?D,Q,QXXX' 	=Y=====' 	j' 	%' 	111411'  	%&<G&<&<d&<&<!'" 	-.MO.M.Me.M.M#' '$ 	*+E+E+E+E+E%'& 	23W9M3W3WPU3W3W''( 	*)'* 	E+', 	tNNN-'. 	#/'0 	uOOO1'2 	5 1 1 13'4 	Z5'6 	%7'8 	z9': 	ooo;'< 	T='> 	:?'@ 	T...A'B 	DC'D 	3E' 'F  %___0h0000"?"?"?5"?"?"?M' ' ' 's      )rP   )rQ   )rO   )&r8   loggingdataclassesr   r   pathlibr   typingr   r   r   r	   r
   hermes_constantsr   	getLoggerr5   r   r   rz   r.   r9   r{   r|   r   r   r   r   r   r   r   r   r:   r   r   r   r   r   r;   r$   r"   <module>r      s	  g g gR  ( ( ( ( ( ( ( (       3 3 3 3 3 3 3 3 3 3 3 3 3 3 , , , , , ,		8	$	$ 0 0 0 0 0 0 0 0H ;&%&#$"!! #(&'
 
"
 )Z%,#6
 
 ?   D =&%&#$"!! #(&'
 
$ HGGJJJ  
 8$8$8$8$	
 
 'X/*'5
 
 WRc? ?B 7&%&#$"!! #(&'
 
" (Z%,#3
 
 ; @ 8&%&#$"!! #(&'
 
" (Z%,#6
 
 ; @ ^
Y
I
 Y
 )	

 9
 
 	
 Y
 	
 y
 i
 )
 y
 Y
 i
  Y!
" y#
$ #,*3'0/8+
 
 
. (Z%,#3
 
 G$ $L !`
Y
I
 Y
 )	

 9
 
 	
 Y
 	
 y
 i
 )
 y
 Y
 i
  Y!
" y#
$ #,*3'0/8+
 
 
. (Z(/&6
 
  G$ $L B&%&#$"!! #(&'
 
$ JIIJJJ   8$'"8$8$	
 
  +\'-&4
 
 dNe? ?B O&%&#$"!! #(&'
 
$ JIIKKK   8$8$8$8$	
 
  +\/.'5
 
 XUe@ @D B&%&#$"!! #(&'
 
$ KJJLLL   8$8$8$8$	
 
  ,]'/'5
 
 pOe? ?Wk- k-S$sCx.() k k kd &*hz" ) ) )" 3 " " "'D ' ' ' '

t 
c3h(@ 
 
 
 
T#s(^ 
    0Dc3h(    >9C 9J 9 9 9 9&    # *    c    
#$ #4 # # # #( s      S 3      #    ADcN A A A A A Ar$   