
    PL
j4                       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Zddl	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  ej        e          Z ee          j        j                                        Zd	Zd
ee ef         dee ef         fdZ!d
ee ef         dee e f         fdZ"d
ee ef         de de ddfdZ#de de$fdZ%dgg dg dg dg dg dddgg dg dg dg dg dg dg dg dd Z&d
ee ef         de fd!Z'd
ee ef         d"e ddfd#Z(dd$l)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4 dd%l5m6Z6m7Z7 d&e fd'Z8dd(l9m:Z:m;Z;m<Z<m=Z= de$fd)Z>dd*e dz  ddfd+Z?dd-e d.e d/e$de fd0Z@ ejA        d1          ZBd2e de fd3ZCdd-e d4eDd.eEd5e dz  deEf
d6ZFdd-e d4eDd.eEd5e dz  deEf
d7ZGdd-e d.e$de$fd9ZHdd&e d:eDd;eDdeDfd<ZId=eJfd>ZKd
eJfd?ZLd
eJfd@ZMd
eJfdAZNddBedz  deJe e f         fdCZOd,dDd
eJdEe$fdFZPde$fdGZQde$fdHZRde$fdIZSde$fdJZTde$fdKZUd
eJfdLZVd
eJfdMZWd
eJfdNZXd
eJfdOZYd
eJfdPZZdQ Z[dR Z\dSe deDfdTZ]dU Z^dV Z_dW Z`dX ZadY ZbdZ Zcd[ Zdd
eJfd\Zedd
eJd]e$fd^Zfd
eJde$fd_Zgd`e de fdaZhd
eJdbe dee          fdcZid
eJdbe d`e de$fddZj eedez            dfz  dgz  dhz  diz  Zkdj Zldkdldmdndodpdqdrdsdt	ZmdueJfdvZndwede$fdxZodydzePfd{d|eWfd}d~eXfddeefddeffddeZfgZpd Zqd
eJde$fdZrd
eJfdZsdS )u  
Interactive setup wizard for Hermes Agent.

Modular wizard with independently-runnable sections:
  1. Model & Provider — choose your AI provider and model
  2. Terminal Backend — where your agent runs commands
  3. Agent Settings — iterations, compression, session reset
  4. Messaging Platforms — connect Telegram, Discord, etc.
  5. Tools — configure TTS, web search, image generation, etc.

Config files are stored in ~/.hermes/ for easy access.
    N)Path)OptionalDictAny)get_nous_subscription_features)managed_nous_tools_enabled)base_url_hostname)get_optional_skills_dirz*https://hermes-agent.nousresearch.com/docsconfigreturnc                     |                      d          }t          |t                    rt          |          S t          |t                    r*|                                rd|                                iS i S )Nmodeldefault)get
isinstancedictstrstrip)r   current_models     4/home/kuhnn/.hermes/hermes-agent/hermes_cli/setup.py_model_config_dictr   %   st    JJw''M-&& #M"""-%% 2-*=*=*?*? 2=..0011I    c                 x    |                      d          }t          |t                    rt          |          ni S Ncredential_pool_strategiesr   r   r   )r   
strategiess     r   _get_credential_pool_strategiesr   .   s6    899J)*d;;C4
Cr   providerstrategyc                 @    |sd S t          |           }|||<   || d<   d S r   )r   )r   r   r    r   s       r   _set_credential_pool_strategyr"   3   s7     088J#Jx+5F'(((r   c                 v    | r| dk    rdS | dk    rdS ddl m} |                    |           }|sdS |j        dv S )NcustomF
openrouterTr   PROVIDER_REGISTRY>   api_keyoauth_device_code)hermes_cli.authr'   r   	auth_type)r   r'   pconfigs      r   "_supports_same_provider_pool_setupr-   ;   sj     x8++u<t111111##H--G u @@@r   copilot-acp)gpt-5.4zgpt-5.4-miniz
gpt-5-minigpt-5.3-codexzgpt-5.2-codexgpt-4.1gpt-4ogpt-4o-minizclaude-opus-4.6zclaude-sonnet-4.6zclaude-sonnet-4.5zclaude-haiku-4.5zgemini-2.5-pro)zgemini-3.1-pro-previewzgemini-3-pro-previewzgemini-3-flash-previewzgemini-3.1-flash-lite-preview)glm-5.1glm-5zglm-4.7zglm-4.5zglm-4.5-flash)	kimi-k2.6	kimi-k2.5zkimi-k2-thinkingzkimi-k2-turbo-previewzstep-3.5-flashzstep-3.5-flash-2603)ztrinity-large-thinkingztrinity-large-previewztrinity-mini)zMiniMax-M2.7zMiniMax-M2.5zMiniMax-M2.1z
MiniMax-M2)anthropic/claude-opus-4.6anthropic/claude-sonnet-4.6zopenai/gpt-5zgoogle/gemini-3-flash)r8   r9   zopenai/gpt-5.4zgoogle/gemini-3-pro-previewzgoogle/gemini-3-flash-preview)r/   r0   zclaude-sonnet-4-6zgemini-3-flashr5   r7   minimax-m2.7)r6   r7   r4   r5   zmimo-v2.5-proz	mimo-v2.5zmimo-v2-prozmimo-v2-omnir:   zminimax-m2.5zqwen3.6-pluszqwen3.5-plus)zQwen/Qwen3.5-397B-A17Bz"Qwen/Qwen3-235B-A22B-Thinking-2507z#Qwen/Qwen3-Coder-480B-A35B-Instructzdeepseek-ai/DeepSeek-R1-0528zdeepseek-ai/DeepSeek-V3.2zmoonshotai/Kimi-K2.5)r.   copilotgeminizaikimi-codingkimi-coding-cnstepfunarceeminimax
minimax-cn
ai-gatewaykilocodezopencode-zenzopencode-gohuggingfacec                     |                      d          }t          |t                    rHt          |                     d          pd                                                                          S dS )Nagentreasoning_effort )r   r   r   r   r   lower)r   	agent_cfgs     r   _current_reasoning_effortrM   t   sc    

7##I)T"" L9==!344:;;AACCIIKKK2r   effortc                 r    |                      d          }t          |t                    si }|| d<   ||d<   d S )NrH   rI   r   )r   rN   rL   s      r   _set_reasoning_effortrP   {   sD    

7##Ii&& $	#w$*I !!!r   )cfg_getDEFAULT_CONFIGget_hermes_homeget_config_pathget_env_pathload_configsave_configsave_env_valueremove_env_valueget_env_valueensure_hermes_home)Colorscolortitlec                     t                       t          t          d|  t          j        t          j                             dS )zPrint a section header.u   ◆ N)printr]   r\   CYANBOLD)r^   s    r   print_headerrc      s5    	GGG	%uV[
9
9:::::r   )print_error
print_infoprint_successprint_warningc                      t          t          dd          } | dS 	 t          |                                           S # t          $ r Y dS w xY w)z;Return True when stdin looks like a usable interactive TTY.stdinNF)getattrsysboolisatty	Exception)ri   s    r   is_interactive_stdinro      sZ    C$''E}uELLNN###   uus    = 
A
Areasonc                    t                       t          t          dt          j        t          j                             t                       | rt          |            t          d           t                       t          d           t          d           t          d           t          d           t                       t          d           t          d           t                       d	S )
z8Print guidance for headless/non-interactive setup flows.u)   ⚕ Hermes Setup — Non-interactive modez+The interactive wizard cannot be used here.z@Configure Hermes using environment variables or config commands:z)  hermes config set model.provider customz;  hermes config set model.base_url http://localhost:8080/v1z1  hermes config set model.default your-model-namez?Or set OPENROUTER_API_KEY / OPENAI_API_KEY in your environment.zERun 'hermes setup' in an interactive terminal to use the full wizard.N)r`   r]   r\   ra   rb   re   )rp   s    r   #print_noninteractive_setup_guidancerr      s    	GGG	%;V[&+
V
VWWW	GGG 6<===	GGGQRRR:;;;LMMMBCCC	GGGPQQQVWWW	GGGGGr   Fquestionr   passwordc                    |r	|  d| d}n|  d}	 |r2ddl }|                     t          |t          j                            }n't	          t          |t          j                            }t          |          }|                                p|pdS # t          t          f$ r& t                       t          j        d           Y dS w xY w)z'Prompt for input with optional default. []: : r   NrJ      )getpassr]   r\   YELLOWinput_sanitize_pasted_inputr   KeyboardInterruptEOFErrorr`   rk   exit)rs   r   rt   displayrz   valuecleaneds          r   promptr      s     "-----/// 	9NNNOOE'6=$A$ABBEE%7788E(//}}/'/R/x(   s   BB 3C
Cz\x1b\[\s*200~|\x1b\[\s*201~r   c                 j    t          | t                    r| s| S t                              d|           S )z@Strip terminal bracketed-paste control markers from pasted text.rJ   )r   r   _BRACKETED_PASTE_PATTERNsub)r   s    r   r}   r}      s6    eS!!  #''E222r   choicesdescriptionc                 .    ddl m}  || ||d|          S )z?Single-select menu using curses. Delegates to curses_radiolist.r   )curses_radiolist)selectedcancel_returnsr   )hermes_cli.curses_uir   )rs   r   r   r   r   s        r   _curses_prompt_choicer      s2    555555HgPR`kllllr   c           	         t          | |||          }|dk    r5||k    rt          d           t                       |S t                       |S t          t          | t          j                             t          |          D ]X\  }}||k    rdnd}||k    r.t          t          d| d| t          j                             Ct          d| d|            Yt          d|d	z    d
           	 	 t          t          dt          |           d|d	z    dt          j
                            }|s|S t          |          d	z
  }d|cxk    rt          |          k     rn n|S t          dt          |                      nS# t          $ r t          d           Y n8t          t          f$ r% t                       t!          j        d	           Y nw xY w)zPrompt for a choice from a list with arrow key navigation.

    Escape keeps the current default (skips the question).
    Ctrl+C exits the wizard.
    )r   r   z  Skipped (keeping current)u   ●u   ○   z  Enter for default (ry   z)  Ctrl+C to exitTz  Select [1-z] (z): z$Please enter a number between 1 and zPlease enter a number)r   re   r`   r]   r\   r{   	enumerateGREENr|   lenDIMintrd   
ValueErrorr~   r   rk   r   )	rs   r   r   r   idxichoicemarkerr   s	            r   prompt_choicer      s+     '7
T
T
TC
axx'>>4555GGGN
	%&-
(
()))w'' * *	6w,,E<<%.V..f..==>>>>(v(((())))Ew{EEEFFF	FS\\FFgkFFF
SS E  e**q.CC&&&&#g,,&&&&&
Ms7||MMNNNN 	1 	1 	1/00000!8, 	 	 	GGGHQKKKKK	s%   6AF	 80F	 )F	 	G$2GGTc                 h   |rdnd}	 	 t          t          |  d| dt          j                                                                                            }n9# t          t          f$ r% t                       t          j
        d           Y nw xY w|s|S |dv rdS |dv rd	S t          d
           )z=Prompt for yes/no. Ctrl+C exits, empty input returns default.zY/nzy/NTrv   rw   ry   >   yyes>   nnoFzPlease enter 'y' or 'n')r|   r]   r\   r{   r   rK   r~   r   r`   rk   r   rd   )rs   r   default_strr   s       r   prompt_yes_nor     s    "-%%K/	ex;;;;;;V]KKLL E
 "8, 	 	 	GGGHQKKKKK	  	NL  4K5-...#/s   AA 3BBitemspre_selectedc                     |g }ddl m}  || |t          |          t          |                    }t          |          S )u  
    Display a multi-select checklist and return the indices of selected items.

    Each item in `items` is a display string. `pre_selected` is a list of
    indices that should be checked by default. A "Continue →" option is
    appended at the end — the user toggles items with Space and confirms
    with Enter on "Continue →".

    Falls back to a numbered toggle interface when simple_term_menu is
    unavailable.

    Returns:
        List of selected indices (not including the Continue option).
    Nr   )curses_checklist)r   )r   r   setsorted)r^   r   r   r   chosens        r   prompt_checklistr   .  sb     555555L<((	  F &>>r   varc           
      t   |                      dg           }d                    |dd                   }t          |          dk    r|dt          |          dz
   dz  }t                       t          t	          d|                      d| d	                    d
t
          j                             t                       |rt          d|            |                      d          rt          d| d                     t                       |                      d          r/t          d|                      d| d	                    d          }n,t          d|                      d| d	                              }|r't          | d	         |           t          d           dS t          d           dS )zEDisplay a nicely formatted API key input screen for a single env var.tools, N   z, +z more     ─── r   name
    ───z  Enables: urlz  Get your key at: rt   r   r   Trt        ✓ Savedz/  Skipped (configure later with 'hermes setup'))r   joinr   r`   r]   r\   ra   re   r   rX   rf   rg   )r   r   	tools_strr   s       r   _prompt_api_keyr   K  s   GGGR  E		%)$$I
5zzA~~03u::>0000		GGG	%Nsww}c&kBBNNNPVP[
\
\]]]	GGG .,,,---
wwu~~ 75U55666	GGG
wwz ><CGGHc&k::<<tLLL<CGGHc&k::<<== Is6{E***m$$$$$GHHHHHr   c                 Z   t                       t          d           g }t          |           }	 ddlm}  |            }n# t
          $ r g }Y nw xY w|r|                    d           n|                    d           t          d          r|                    d           n|                    d           |j        j	        r|                    d	           nX|j        j
        r7d
}|j        j        rd|j        j         d}|                    |ddf           n|                    d           |j        j        }|j        j	        r|                    d           nl|j        j
        r#d}|rd| d}|                    |ddf           n=d}|dk    rd}n|dk    rd}n|dk    rd}n|dk    rd}|                    dd|f           |j        j	        r|                    d           n|j        j
        r|                    d           nd}		 ddlm}
 dd lm}  |              |
            D ]<}|j        d!k    r	 |                                r	|j        }	 n-# t
          $ r Y 9w xY wn# t
          $ r Y nw xY w|	r|                    d"|	 dddf           n|                    d#           	 ddlm} dd lm}  |             d} |            D ]0}	 |                                r	|j        } n!# t
          $ r Y -w xY wn# t
          $ r d}Y nw xY w|r|                    d$| dddf           t-          | d%d&d'(          }|j        j	        r|                    d)           n|d*k    r&t          d+          r|                    d,           n|d-k    r5t          d.          st          d/          r|                    d0           ns|d1k    r&t          d2          r|                    d3           nG|d4k    r&t          d5          r|                    d6           n|d7k    r4t          d8          st          d9          r|                    d:           n|d;k    r^	 |j                            d;          du}n# t
          $ r d}Y nw xY w|r|                    d<           n|                    d=           n}|d>k    rb	 ddl}|j                            d>          du}n# t
          $ r d}Y nw xY w|r|                    d?           n+|                    d@           n|                    dA           |j        j	        r|                    dB           nwt-          | dCdD          dEk    r8|j        j        r|                    dF           n@|                    dG           n*t;                      r|j        r|                    dH           t          dI          r|                    dJ           	 ddKlm }  |dL          pi }|!                    dM          s|!                    dN          r|                    dO           n# t
          $ r Y nw xY wt          dP          r|                    dQ           n|                    dR           |                    dS           |                    dT           |                    dU           tE          dV |D                       }tG          |          }tI          | dW| dX           t                       |D ]\  }}}|r.t          dYtK          dZtL          j'                   d[|            6t          dYtK          d\tL          j(                   d[| d[tK          d]| dtL          j)                              t                       d^ |D             }|r>tU          d_           dd`l+m,} tU          da |             db           t                       t                       t          tK          dctL          j'                             t          tK          ddtL          j'                             t          tK          detL          j'                             t                       dd`l+m,} t          tK          df |             dgtL          j-        tL          j.                             t                       t          dYtK          dhtL          j/                   dita                                  t          dYtK          djtL          j/                   ditc                                  t          dYtK          dktL          j/                   dl| dm           t                       t          tK          dntL          j)                             t                       t          tK          dotL          j-        tL          j.                             t                       t          dYtK          dptL          j'                   dq           t          dYtK          drtL          j'                   ds           t          dYtK          dttL          j'                   du           t          dYtK          dvtL          j'                   dw           t          dYtK          dxtL          j'                   dy           t                       t          dYtK          dztL          j'                   d{           t          dYtK          d|tL          j'                   d}           t          dYtK          d~tL          j'                              t          d           t                       t          d           t          dYtK          dta                       tL          j)                              t          dYtK          dtc                       tL          j)                              t                       t          tK          dntL          j)                             t                       t          tK          dtL          j-        tL          j.                             t                       t          dYtK          dtL          j'                   d           t          dYtK          dtL          j'                   d           t          dYtK          dtL          j'                   d           t                       dS )z#Print the setup completion summary.zTool Availability Summaryr   get_available_vision_backends)Vision (image analysis)TN)r   Fzrun 'hermes setup' to configureOPENROUTER_API_KEY)Mixture of AgentsTN)r   Fr   )z(Web Search & Extract (Nous subscription)TNWeb Search & ExtractzWeb Search & Extract ()TN)r   FzbEXA_API_KEY, PARALLEL_API_KEY, FIRECRAWL_API_KEY/FIRECRAWL_API_URL, TAVILY_API_KEY, or SEARXNG_URL)z%Browser Automation (Nous Browser Use)TNzBrowser AutomationzBrowser Automation (zVnpm install -g agent-browser, set CAMOFOX_URL, or configure Browser Use or BrowserbaseBrowserbasezOnpm install -g agent-browser and set BROWSERBASE_API_KEY/BROWSERBASE_PROJECT_IDzBrowser Usez8npm install -g agent-browser and set BROWSER_USE_API_KEYCamofoxCAMOFOX_URLzLocal browserznpm install -g agent-browserF)z$Image Generation (Nous subscription)TN)Image GenerationTN)list_providers)_ensure_plugins_discoveredfalzImage Generation ()r   FzFAL_KEY or OPENAI_API_KEYzVideo Generation (ttsr   edger   )z-Text-to-Speech (OpenAI via Nous subscription)TN
elevenlabsELEVENLABS_API_KEY)zText-to-Speech (ElevenLabs)TNopenaiVOICE_TOOLS_OPENAI_KEYOPENAI_API_KEY)zText-to-Speech (OpenAI)TNrB   MINIMAX_API_KEY)zText-to-Speech (MiniMax)TNmistralMISTRAL_API_KEY)z Text-to-Speech (Mistral Voxtral)TNr<   GEMINI_API_KEYGOOGLE_API_KEY)zText-to-Speech (Google Gemini)TNneutts)zText-to-Speech (NeuTTS local)TN)u)   Text-to-Speech (NeuTTS — not installed)Frun 'hermes setup tts'	kittentts)z Text-to-Speech (KittenTTS local)TN)u,   Text-to-Speech (KittenTTS — not installed)Fr   )zText-to-Speech (Edge TTS)TN)z#Modal Execution (Nous subscription)TNterminalbackendmodal)zModal Execution (direct Modal)TN)zModal ExecutionFzrun 'hermes setup terminal')z0Modal Execution (optional via Nous subscription)TN
HASS_TOKEN)zSmart Home (Home Assistant)TN)get_provider_auth_statespotifyaccess_tokenrefresh_token)zSpotify (PKCE OAuth)TNGITHUB_TOKEN)Skills Hub (GitHub)TN)r   Fr   )zTerminal/CommandsTN)zTask Planning (todo)TN)zSkills (view, create, edit)TNc              3   &   K   | ]\  }}}|d V  dS )ry   N ).0_avails      r   	<genexpr>z'_print_setup_summary.<locals>.<genexpr>*  s-      DD5!eD!DDDDDDr   /z tool categories available:z   u   ✓r   u   ✗z	(missing c                 "    g | ]\  }}}|||fS r   r   )r   r   r   r   s       r   
<listcomp>z(_print_setup_summary.<locals>.<listcomp>:  s(    SSS&6dE3UStSkSSSr   zDSome tools are disabled. Run 'hermes setup tools' to configure them,display_hermes_homezor edit z+/.env directly to add the missing API keys.   ┌─────────────────────────────────────────────────────────┐uA   │              ✓ Setup Complete!                          │   └─────────────────────────────────────────────────────────┘u   📁 All your files are in z/:z	Settings:r   z	API Keys:zData:      z/cron/, sessions/, logs/u   ────────────────────────────────────────────────────────────u    📝 To edit your configuration:zhermes setupz           Re-run the full wizardzhermes setup modelz    Change model/providerzhermes setup terminalz Change terminal backendzhermes setup gatewayz  Configure messagingzhermes setup toolsz    Configure tool providerszhermes configz         View current settingszhermes config editz    Open config in your editorzhermes config set <key> <value>z.                          Set a specific valuez   Or edit the files directly:znano u   🚀 Ready to go!hermesz              Start chattingzhermes gatewayz      Start messaging gatewayzhermes doctorz       Check for issues)2r`   rc   r   agent.auxiliary_clientr   rn   appendrZ   webmanaged_by_nous	availablecurrent_providerbrowser	image_genagent.image_gen_registryr   hermes_cli.pluginsr   r   is_availabledisplay_nameagent.video_gen_registryrQ   r   util	find_specimportlib.utilr   direct_overrider   nous_auth_presentr*   r   r   sumr   re   r]   r\   r   REDr   rg   hermes_constantsr   ra   rb   r{   rT   rU   )r   hermes_hometool_statussubscription_featuresr   _vision_backendslabelbrowser_providermissing_browser_hint_img_backendr   r   _p_list_video_providers_ensure_plugins_video_backend_vptts_provider	importlib	neutts_okkittentts_okr   _spotify_stateavailable_counttotal_countr   r   missing_vardisabled_tools_dhhs                                 r   _print_setup_summaryr   g  s[    
GGG,---K:6BBHHHHHH88::     bBCCCC`aaa )** O<====MNNN  0 bSTTTT		"	, b& $5 	[Z-B-F-WZZZEE4.////  a  	b  	b  	b -4E$4 
PQQQQ		&	0 
$ 	?>+;>>>EE4.////w},,= !  ..J !  **#0  00#A !5*>?	
 	
 	
 &6 YOPPPP		(	2 Y;<<<< 	??????EEEEEE&&((($n&&  7e##(( ') !   H 	 	 	D	 	Y D\ D D DdDQRRRRWXXX
TTTTTTTTTTTT((** 	 	C##%% %(%5NE        QBBBBD$OPPP 65*fEEEL 0 "FXYYYY		%	%-8L*M*M	%FGGGG		!	!.// 
"3@AQ3R3R 
" 	BCCCC		"	"}5F'G'G	"CDDDD		"	"}5F'G'G	"KLLLL		!	!}5E'F'F	!-XhJiJi	!IJJJJ		!	!	!00::$FII 	 	 	III	 	oLMMMMmnnnn		$	$	!!!!!$>33K@@LLL 	! 	! 	! LLL	! 	rOPPPPpqqqqDEEE"2 ]NOOOO	Y	/	/7	:	: &6 	ZMNNNNXYYYY	#	%	% ]*?*Q ][\\\ \"" HFGGG;;;;;;00;;Arn-- 	E1C1CO1T1T 	ECDDD    ^$$ K>????IJJJ 8999 ;<<< BCCC DD{DDDDDOk""K/LLKLLLMMM	GGG(3  $i 	;eV\22;;T;;<<<<geE6:..gggg>X+>X>X>XZ`Zd8e8egg    
GGGSS+SSSN R	
 	
 	
 	A@@@@@TTTTUUU 
GGG	 @  BH  BN	
 	
  
 
OQWQ]	
 	
  
 
 @  BH  BN	
 	
  
 
GGG =<<<<<	%8ddff888&+v{
S
STTT	GGG	
Hk6=11
H
H_5F5F
H
HIII	
Ek6=11
E
E\^^
E
EFFF	XeGV]++XX;XXX   
GGG	%
FJ
'
'(((	GGG	%2FK
M
MNNN	GGG	
Unfl33
U
U
UVVV	
T*FL99
T
T
TUUU	
V-v|<<
V
V
VWWW	
R,fl;;
R
R
RSSS	
W*FL99
W
W
WXXX	GGG	
Tov|44
T
T
TUUU	We(&,77WWW   

H7FF
H
HIII	
:;;;	GGG	
*+++	
@1o//116:>>
@
@AAA	
=.lnn..
;;
=
=>>>	GGG	%
FJ
'
'(((	GGG	%#V[&+
>
>???	GGG	
Kh--
K
K
KLLL	
T&55
T
T
TUUU	
Mov|44
M
M
MNNN	GGGGGs   A AA.I3 I"I3 "
I/,I3 .I//I3 3
J ?J 8$L K;8L ;
LL LL LL2R RR S7 7TT
AY 
Y*)Y*c                 <   |                      di           }t                       t          d           |                    dd          }|rdnd}t          d           t          d           t	          d	|          }|                                d
v |d<   |                    dd          }t	          dt          |                    }	 t          |          |d<   n# t          $ r Y nw xY w|                    dd          }t	          dt          |                    }	 t          |          |d<   n# t          $ r Y nw xY w|                    dd          }	t	          dt          |	                    }
	 t          |
          |d<   dS # t          $ r Y dS w xY w)zMPrompt for container resource settings (Docker, Singularity, Modal, Daytona).r   zContainer Resource Settings:container_persistentTr   r   z5  Persistent filesystem keeps files between sessions.z;  Set to 'no' for ephemeral sandboxes that reset each time.z.  Persist filesystem across sessions? (yes/no)>   1r   r   truecontainer_cpury     CPU corescontainer_memory     Memory in MB (5120 = 5GB)container_disk   z  Disk in MB (51200 = 50GB)N)

setdefaultr`   re   r   r   rK   r   floatr   r   )r   r   current_persistpersist_labelpersist_strcurrent_cpucpu_strcurrent_memmem_strcurrent_diskdisk_strs              r   _prompt_container_resourcesr7    s     R00H	GGG-... ll#94@@O,6EE$MFGGGLMMM8- K (3'8'8':':>W'WH#$ ,,22K]C$4$455G$)'NN!!    ,,1488K2C4D4DEEG'*7||#$$    << 0%88L3S5F5FGGH%(]]!"""   s6   C 
C+*C+"D5 5
EE9F 
FFc                 6   |                      di           }t                       t          d           t          d           t          d           ddlm} |                    d          pd}d	                    |          }t          d
| d|                                          p|}||vrt          d| d| d           ||v r|nd}||d<   t          d|           |                    dd          }|rdnd}t          d|                                          dv |d<   |                    dd          }t          dt          |                    }		 t          |	          |d<   n# t          $ r Y nw xY w|                    dd          }
t          dt          |
                    }	 t          |          |d<   n# t          $ r Y nw xY w|                    dd          dvrt          d           d|d<   t                       t          d            t          d!           t!                      }|rt          d"           t#          d#           t          d$t%          d%          pd&d'          }t          d(t%          d)          p|                    d*d&                    }t          d+t%          d,          p|                    d-d&                    }|rt          d%|           |rt          d)|           |rt          d,|           d.S d.S )/zLPrompt for Vercel Sandbox settings without exposing unsupported disk sizing.r   zVercel Sandbox settings:z/  Filesystem persistence uses Vercel snapshots.zX  Snapshots restore files only; live processes do not continue after sandbox recreation.r   )_SUPPORTED_VERCEL_RUNTIMESvercel_runtimenode24r   z  Runtime (r   zUnsupported Vercel runtime 'z', keeping .TERMINAL_VERCEL_RUNTIMEr"  Tr   r   z-  Persist filesystem with snapshots? (yes/no)>   r#  r   r   r$  r%  ry   r&  r'  r(  r)  r*  r+  >   r   r+  zVVercel Sandbox does not support custom disk sizing; resetting container_disk to 51200.zVercel authentication:z=  Use a long-lived Vercel access token plus project/team IDs.z1  Found defaults in nearest .vercel/project.json.VERCEL_OIDC_TOKENz    Vercel access tokenVERCEL_TOKENrJ   r   z    Vercel project IDVERCEL_PROJECT_ID	projectIdz    Vercel team IDVERCEL_TEAM_IDorgIdN)r,  r`   re   tools.terminal_toolr9  r   r   r   r   rg   rX   rK   r   r-  r   r   _read_nearest_vercel_projectrY   rZ   )r   r   r9  current_runtimesupported_labelruntimer.  r/  r1  r2  r3  r4  linked_projecttokenprojectteams                   r   _prompt_vercel_sandbox_settingsrM    s     R00H	GGG)***@AAAijjj>>>>>>ll#344@Oii :;;O5?555GGMMOObSbG000[W[[[[[\\\%48R%R%R//X`!(H,g666ll#94@@O,6EE$M'-7( (egg*(+H#$ ,,22K]C$4$455G$)'NN!!    ,,1488K2C4D4DEEG'*7||#$$    ||$e,,J>>nooo!&H	GGG'(((NOOO133N HFGGG())),mN.K.K.Qr\`aaaE)**Qn.@.@b.Q.Q G &''J>+=+=gr+J+J D  .~u--- 5*G444 /'...../ /s$   E- -
E:9E:1G 
GGstartc                 6   | pt          j                                                    }|                                r|j        }|g|j        R D ]}|dz  dz  }|                                s	 t          j        |	                    d                    }n # t          t          j        f$ r i cY c S w xY wt          |t                    si c S d |                    d          |                    d          d                                D             c S i S )	z=Read project/team defaults from the nearest Vercel link file.z.vercelzproject.jsonutf-8encodingc                 l    i | ]1\  }}t          |t                    |                                .||2S r   )r   r   r   )r   keyr   s      r   
<dictcomp>z0_read_nearest_vercel_project.<locals>.<dictcomp>   sR     
 
 
U %%%
 +0++--

 
 
r   rA  rC  )rA  rC  )r   cwdresolveis_fileparentparentsexistsjsonloads	read_textOSErrorJSONDecodeErrorr   r   r   r   )rN  current	directoryproject_filedatas        r   rE  rE    sO   "

++--G !.000 
 
	 9,~=""$$ 		:l44g4FFGGDD-. 	 	 	IIIII	$%% 	III
 
 "XXk22'**  egg
 
 
 	
 	
 	
 Is   .(BB43B4quickrf  c                   ddl m}m} t          d           t	          d           t	          dt
           d           t                       ddlm} 	  |             n# t          t          f$ r  t                       t	          d           Y nRt          $ rF}t                              d	|           t          d
|            t	          d           Y d}~nd}~ww xY w |            }|                    d|                     d                    | d<   d|v r|d         | d<   n|                     dd           d}|                     d          }t#          |t$                    r|                    d          }|s:t'          |          r*	 ddlm}	 ddlm}
 ddlm}  |
|          }|                                }t7          |          }t9          d |D                       }||z
  }t                       t          d           t	          d           t	          d           t	          d           t                       |dk    rt	          d| d| d| d| d	           nt	          d| d|            t;          dd          rp | |	|ddddddddd ddd!"                      |
|          }t7          |                                          }t	          d#| d$           t;          dd          p|d%k    rg d&}t=          |                               |d'          }dd%d(d)                    |d          }t?          d*||          }g d)|         }tA          | ||           tC          d+| d,|            n2# t          $ r%}t                              d-|           Y d}~nd}~ww xY w|rd}nS	 dd.l"m#} tI           |                      }n# t          $ r tI                      }Y nw xY wtK          |           }||v rd}|rFd/d0d1d2d3d4d5d6d7d8d9d:d;}|                    ||pd<          }t                       t          d=           t	          d>|            t	          d?           t	          d@           t                       g dA}t?          dB|d(          }|dk    rWtM          dCdDE          '                                }|r!tQ          dF|           tC          dG           nct	          dH           nR|d%k    r<tM          dI          '                                pdJ}dK}tS          |          dLk    } | rdM}tM          |dDE          '                                }!|!rtQ          dN|!           | *                    dOi           *                    dPi           }"||"dQ<   | r9g dR}#|#dSgz   }$t?          dT|$d          }%|%t7          |#          k     r|#|%         ndU}&n!tM          dV          '                                }&|&rtQ          dW|&           tC          dX| |&rd|& dYndz              nt	          dH           nt	          dZ            ||            |s|d[k    rtW          |            dS dS dS )\u  Configure the inference provider and default model.

    Delegates to ``cmd_model()`` (the same flow used by ``hermes model``)
    for provider selection, credential prompting, and model picking.
    This ensures a single code path for all provider setup — any new
    provider added to ``hermes model`` is automatically available here.

    When *quick* is True, skips credential rotation, vision, and TTS
    configuration — used by the streamlined first-time quick setup.
    r   )rV   rW   zInference Providerz.Choose how to connect to your main chat model.
   Guide: z/integrations/providers)select_provider_and_modelzProvider setup skipped.z0select_provider_and_model error during setup: %sz%Provider setup encountered an error: z*You can try again later with: hermes modelNr   custom_providersr   )SimpleNamespace)	load_pool)auth_add_commandc              3   |   K   | ]7}t          t          |d d                                        d          3dV  8dS )sourcerJ   manualry   N)r   rj   
startswith)r   entrys     r   r   z'setup_model_provider.<locals>.<genexpr>O  sK      ppUWUHVX=Y=Y9Z9Z9e9efn9o9opqppppppr   z!Same-Provider Fallback & RotationzHHermes can keep multiple credentials for one provider and rotate betweenzCthem when a credential is exhausted or rate-limited. This preserveszEyour primary provider while reducing interruptions from quota issues.zCurrent pooled credentials for rx   z (z	 manual, z$ auto-detected from env/shared auth)z2Add another credential for same-provider fallback?FrJ   g      .@,  )r   r+   r  r(   
portal_urlinference_url	client_idscope
no_browsertimeoutinsecure	ca_bundlemin_key_ttl_secondszProvider pool now has z credential(s).ry   )uU   Fill-first / sticky — keep using the first healthy credential until it is exhausteduJ   Round robin — rotate to the next healthy credential after each selectionu5   Random — pick a random healthy credential each time
fill_first   )r}  round_robinrandomz'Select same-provider rotation strategy:zSaved z rotation strategy: z7Could not configure same-provider fallback in setup: %sr   zNous Portal API keyzGitHub CopilotzGitHub Copilot ACPz
Z.AI / GLMzKimi / MoonshotzKimi / Moonshot (China)zStepFun Step PlanMiniMaxz
MiniMax CN	AnthropiczVercel AI Gatewayzyour custom endpoint)znous-apir;   r.   r=   r>   r?   r@   rB   rC   	anthropicrD   r$   zyour providerz"Vision & Image Analysis (optional)z+Vision uses a separate multimodal backend. z=doesn't currently provide one Hermes can auto-use for vision,z4so choose a backend now or skip and configure later.)u<   OpenRouter — uses Gemini (free tier at openrouter.ai/keys)uB   OpenAI-compatible endpoint — base URL, API key, and vision modelzSkip for nowzConfigure vision:z  OpenRouter API keyTr   r   u/   OpenRouter key saved — vision will use Geminiu%   Skipped — vision won't be availablez  Base URL (blank for OpenAI)zhttps://api.openai.com/v1z	  API keyzapi.openai.comz  OpenAI API keyr   	auxiliaryvisionbase_url)r2   r3   r1   zgpt-4.1-minizgpt-4.1-nanozUse default (gpt-4o-mini)zSelect vision model:r3   z0  Vision model (blank = use main/custom default)AUXILIARY_VISION_MODELzVision configured with r   uR   Skipped — add later with 'hermes setup' or configure AUXILIARY_VISION_* settingsnous),hermes_cli.configrV   rW   rc   re   
_DOCS_BASEr`   hermes_cli.mainri  
SystemExitr~   rn   loggerdebugrg   r   popr   r   r-   typesrk  agent.credential_poolrl  hermes_cli.auth_commandsrm  entriesr   r  r   r   r   r"   rf   r   r   r   rl   r   r   rX   r	   r,  _setup_tts_provider)'r   rf  rV   rW   ri  exc
_refreshedselected_provider_mrk  rl  rm  poolr  entry_countmanual_count
auto_countstrategy_labelscurrent_strategydefault_strategy_idxstrategy_idxstrategy_value_vision_needs_setupr   r  _prov_names_prov_display_vision_choices_vision_idx_or_key	_base_url_api_key_label_is_native_openai_oai_key_vaux_oai_vision_models_vm_choices_vm_idx_selected_vision_models'                                          r   setup_model_providerr    s
	    ;:::::::%&&&?@@@?J???@@@	GGG :99999A!!####)* . . .,----- A A AGMMMCcCCDDD?@@@@@@@@A J nnWfjj.A.ABBF7OZ''%/0B%C!""

%t,,, 	G		B"d /FF:..  JY78IJJ JYI	Y------777777AAAAAA9.//DllnnGg,,KppgpppppL$|3JGGG<===Z   U   W   GGGA~~`6G ` `; ` `$` `/9` ` `   
 _=N__R]__``` TV[\\ R  #O!2"$" $#'&*"&"#( $!&"&,2    " !y!233!$,,..11PKPPPQQQ)   TV[\\ R, Q# # #
 $C6#J#J#N#NO`bn#o#o "##$( ( #&**	 %
  -=#(   
 "I!H!H!V-f6GXXX^'8^^n^^___ 	Y 	Y 	YLLRTWXXXXXXXX	Y  (#	%LLLLLL"#@#@#B#BCC 	% 	% 	%"uu	% #''7"8"88 000"' Fm-'/,7* &$-,
 
 $(9;L;_P_``9:::PPPQQQRSSSIJJJ
 
 

 $$7!LL!3dCCCIIKKG D3W===OPPPPBCCCCA>??EEGGfKfI(N 1) < <@P P  4!3nt<<<BBDDH D/:::))+r::EEhPRSS$-j!$ 
p)m)m)m&"48S7T"TK+,BKQRSSG #S);%<%<<< +733* +* .44f-g-g-m-m-o-o*) U"#;=STTT9i999OW525555UWY   
 BCCCCklll K $&&00F#####$ $00sI   
A .C	C<CCG6N	 	
N8N33N8O O:9O:c                  Z    t          j        d          dupt          j        d          duS )z Check if espeak-ng is installed.	espeak-ngNespeak)shutilwhichr   r   r   _check_espeak_ngr    s,    <$$D0VFL4J4JRV4VVr   c            	         ddl } ddl}t                      sCt                       t	          d           |j        dk    rt          d           n*|j        dk    rt          d           nt          d           t                       t          d	d
          r	 |j        dk    r|                     g dd
           n>|j        dk    r|                     g dd
           n|                     g dd
           t          d           nO# | j
        t          f$ r,}t	          d|            t          d           Y d}~dS d}~ww xY wt	          d           t                       t          d           t          d           t                       	 |                     |j        ddddddgd
d           t          d           d
S # | j
        | j        f$ r,}t          d|            t          d            Y d}~dS d}~ww xY w)!zHInstall NeuTTS dependencies with user approval. Returns True on success.r   Nz,NeuTTS requires espeak-ng for phonemization.darwinz$Install with: brew install espeak-ngwin32z%Install with: choco install espeak-ngz(Install with: sudo apt install espeak-ngzInstall espeak-ng now?T)brewinstallr  )check)chocor  r  -y)sudoaptr  r  r  zespeak-ng installedz+Could not install espeak-ng automatically: z,Please install it manually and re-run setup.FzJespeak-ng is required for NeuTTS. Install it manually before using NeuTTS.z#Installing neutts Python package...z<This will also download the TTS model (~300MB) on first use.-mpipr  -Uzneutts[all]--quietrs  r  ry  zneutts installed successfullyzFailed to install neutts: z2Try manually: python -m pip install -U neutts[all])
subprocessrk   r  r`   rg   platformre   r   runrf   CalledProcessErrorFileNotFoundError
executableTimeoutExpiredrd   )r  rk   es      r   _install_neutts_depsr    s   JJJ  hDEEE<8##=>>>>\W$$>????ABBB1488 	h<8++NN#C#C#C4NPPPP\W,,NN#J#J#JRVNWWWWNN#P#P#PX\N]]]3444413DE   OAOOPPPIJJJuuuuu
 fggg 
GGG4555MNNN	GGG
^T5)T=)T 	 	
 	
 	
 	5666t):+DE   444555GHHHuuuuus1   A2D E	!EE	3G H!HHc            
      b   ddl } ddl}d}t                       t          d           t                       	 |                     |j        dddd|d	d
gdd           t          d           dS # | j        | j        f$ r0}t          d|            t          d| d           Y d}~dS d}~ww xY w)zKInstall KittenTTS dependencies with user approval. Returns True on success.r   Nz^https://github.com/KittenML/KittenTTS/releases/download/0.8.1/kittentts-0.8.1-py3-none-any.whlzOInstalling kittentts Python package (~25-80MB model downloaded on first use)...r  r  r  r  	soundfiler  Trs  r  z kittentts installed successfullyzFailed to install kittentts: z(Try manually: python -m pip install -U 'z' soundfileF)
r  rk   r`   re   r  r  rf   r  r  rd   )r  rk   	wheel_urlr  s       r   _install_kittentts_depsr  -  s    JJJ	1  
GGG`aaa	GGG
^T5)T9kS\] 	 	
 	
 	
 	8999t):+DE   7A77888TiTTTUUUuuuuus   4A- -B.>%B))B.c                      	 ddl m}  t           |                                 d                    S # t          $ r Y dS w xY w)zTrue iff xAI Grok OAuth credentials are already stored locally.

    Lets TTS / STT setup skip the API-key prompt for users who logged in
    through ``hermes model`` -> xAI Grok OAuth (SuperGrok Subscription).
    r   get_xai_oauth_auth_status	logged_inF)r*   r  rl   r   rn   r  s    r   _xai_oauth_logged_in_for_setupr  F  sa    ======--//33K@@AAA   uus   /2 
A A c                     	 ddl m} m}m}m}m} n*# t          $ r}t          d|            Y d}~dS d}~ww xY w |             }t                       t          d           	  ||          } ||d         |
                    d	          |
                    d
d          |
                    d                      |d|
                    d|                      dS # t          $ r}t          d|            Y d}~dS d}~ww xY w)zRun the xAI Grok OAuth loopback login from inside the setup wizard.

    Returns True on success, False on any failure (the caller falls back
    to whatever the user picked next, e.g. Edge TTS).
    r   )DEFAULT_XAI_OAUTH_BASE_URL_is_remote_session_save_xai_oauth_tokens_update_config_for_provider_xai_oauth_loopback_loginz$xAI Grok OAuth helpers unavailable: NFz8Signing in to xAI Grok OAuth (SuperGrok Subscription)...)open_browsertokens	discoveryredirect_urirJ   last_refresh)r  r  r  z	xai-oauthr  TzxAI Grok OAuth login failed: )r*   r  r  r  r  r  rn   rg   r`   re   r   )r  r  r  r  r  r  r  credss           r   _run_xai_oauth_login_from_setupr  T  s   
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
    BSBBCCCuuuuu *)+++L	GGGIJJJ))|DDD(Oii,,>266>22		
 	
 	
 	
 	$#:/IJJ	
 	
 	
 t   ;c;;<<<uuuuus)    
838$A;C! !
D+DDc           
         |                      di           }|                     dd          }t          |           }dddddd	d
ddd	}|                     ||          }t                       t          d           t	          d|            t                       g }g }t                      r1|j        r*|                    d           |                    d           |                    g d           |                    g d           |                    d| d           t          |          dz
  }t          d||          }	|	|k    rdS ||	         }
|
dk    }|
dk    r>d}
t	          d           t          d          st          d          rt          d           |
dk    r	 |j                            d          du}n# t          $ r d}Y nw xY w|rt!          d           nIt                       t	          d            t	          d!           t	          d"           t                       t#          d#d$          r!t%                      st          d%           d}
nt	          d&           d}
n|
d'k    rft          d(          }|sSt                       t'          d)d$*          }|r!t)          d(|           t!          d+           nct          d,           d}
nP|
dk    rw|sut          d          pt          d          }|sSt                       t'          d-d$*          }|r!t)          d|           t!          d.           nt          d,           d}
n|
d/k    rt+                      }t          d0          }|rt!          d1           n|rt!          d2           nt                       t          d3g d4d56          }|d5k    r0t-                      rt!          d7           nt          d8           d}
nn|dk    rWt'          d9d$*          }|r t)          d0|           t!          d:           n5d5d;lm} t          d< |             d=           d}
nt          d>           d}
|
d/k    rt                       t'          d?          }|rw|                                rc|                                |                     di                               d/i           d@<   t!          dA|                                            n'|
dBk    rft          dC          }|sSt                       t'          dDd$*          }|r!t)          dC|           t!          dE           nt          d,           d}
n|
dFk    rft          dG          }|sSt                       t'          dHd$*          }|r!t)          dG|           t!          dI           nbt          d,           d}
nO|
dJk    rt          dK          pt          dL          }|sat                       t	          dM           t'          dNd$*          }|r t)          dK|           t!          dO           nt          d,           d}
n|
dPk    r	 d5dl}|j                            dP          du}n# t          $ r d}Y nw xY w|rt!          dQ           n{t                       t	          dR           t	          dS           t                       t#          dTd$          r t9                      st          dU           d}
nt	          dV           d}
d| vri | d<   |
| d         d<   t;          |            t!          dW|                     |
|
                      dS )Xz@Interactive TTS provider selection with install flow for NeuTTS.r   r   r   zEdge TTS
ElevenLabsz
OpenAI TTSzxAI TTSzMiniMax TTSzMistral Voxtral TTSzGoogle Gemini TTSNeuTTS	KittenTTS)	r   r   r   xairB   r   r<   r   r   z"Text-to-Speech Provider (optional)z	Current: zCNous Subscription (managed OpenAI TTS, billed to your subscription)znous-openai)	z-Edge TTS (free, cloud-based, no setup needed)z+ElevenLabs (premium quality, needs API key)z(OpenAI TTS (good quality, needs API key)u0   xAI TTS (Grok voices — OAuth login or API key)z<MiniMax TTS (high quality with voice cloning, needs API key)z>Mistral Voxtral TTS (multilingual, native Opus, needs API key)zJGoogle Gemini TTS (30 prebuilt voices, prompt-controllable, needs API key)z5NeuTTS (local on-device, free, ~300MB model download)z<KittenTTS (local on-device, free, lightweight ~25-80MB ONNX)Keep current (r   ry   zSelect TTS provider:Nr   zKOpenAI TTS will use the managed Nous gateway and bill to your subscription.r   r   ziDirect OpenAI credentials are still configured and may take precedence until removed from ~/.hermes/.env.r   FzNeuTTS is already installedzNeuTTS requires:uH     • Python package: neutts (~50MB install + ~300MB model on first use)u,     • System package: espeak-ng (phonemizer)z Install NeuTTS dependencies now?Tz9NeuTTS installation incomplete. Falling back to Edge TTS.zISkipping install. Set tts.provider to 'neutts' after installing manually.r   r   zElevenLabs API keyr   zElevenLabs API key savedz.No API key provided. Falling back to Edge TTS.zOpenAI API key for TTSzOpenAI TTS API key savedr  XAI_API_KEYzIxAI TTS will use your xAI Grok OAuth (SuperGrok Subscription) credentialsz*xAI TTS will use your existing XAI_API_KEYz(How do you want xAI TTS to authenticate?)uF   Sign in with xAI Grok OAuth (SuperGrok Subscription) — browser loginz#Paste an xAI API key (console.x.ai)u   Skip → fallback to Edge TTSr   )r   r   u6   Logged in — xAI TTS will use these OAuth credentialsz@xAI Grok OAuth login did not complete. Falling back to Edge TTS.zxAI API key for TTSzxAI TTS API key savedr   zQNo xAI API key provided for TTS. Configure XAI_API_KEY via hermes setup model or z//.env to use xAI TTS. Falling back to Edge TTS.z*xAI TTS skipped. Falling back to Edge TTS.z:xAI voice_id (Enter for 'eve', or paste a custom voice ID)voice_idzxAI voice_id set to: rB   r   zMiniMax API key for TTSzMiniMax TTS API key savedr   r   zMistral API key for TTSzMistral TTS API key savedr<   r   r   z<Get a free API key at https://aistudio.google.com/app/apikeyzGemini API key for TTSzGemini TTS API key savedr   zKittenTTS is already installedzCKittenTTS is lightweight (~25-80MB, CPU-only, no API key required).z:Voices: Jasper, Bella, Luna, Bruno, Rosie, Hugo, Kiki, LeozInstall KittenTTS now?z<KittenTTS installation incomplete. Falling back to Edge TTS.zLSkipping install. Set tts.provider to 'kittentts' after installing manually.zTTS provider set to: )r   r   r`   rc   re   r   r  r   extendr   r   rZ   rg   r  r  rn   rf   r   r  r   rX   r  r  r  r   r   r,  r  r  rW   )r   
tts_configr   r  provider_labelscurrent_labelr   	providerskeep_current_idxr   r   selected_via_nousr  already_installedexistingr(   oauth_logged_inexisting_api_key
choice_idxr  r  s                        r   r  r  z  s	   E2&&J!~~j&99:6BB " (% 
 
O $''(8:JKKM	GGG5666*=**+++	GGGGI!## ((=(O (\]]]'''NN
	
 
	
 
	
   ssstttNN4M4445557||a'
.9I
J
JC
~H M1=  `aaa122 	mDT6U6U 	{   8	& ) 8 8 B B$ N 	& 	& 	& %	&  	"78888GGG)***abbbEFFFGGG?FF "+-- &!"]^^^%Hfggg!	\	!	! !566 	"GGG1DAAAG "3W===89999NOOO!	X		&7	 !9::]mL\>]>] 	"GGG5EEEG "7AAA89999NOOO!	U		
 9::(77 ,	"     '	"FGGGGGGG&:  
   J Q244 	&!P    "4    &HHq !6FFF 
&"=':::!"9::::LLLLLL!459TVV4 4 4  
  &HHJKKK!uGGGZ[[H JHNN,, JQYQ_Q_QaQa!!%,,77rBB:NHhnn6F6FHHIII 
Y		 !233 	"GGG6FFFG "0':::9::::NOOO!	Y		 !233 	"GGG6FFFG "0':::9::::NOOO!	X		 !122UmDT6U6U 		"GGGUVVV5EEEG "/99989999NOOO!	[	 	 	&!!!! ) 8 8 E ET Q 	& 	& 	& %	&  	":;;;;GGG\]]]STTTGGG5t<< ".00 &!"`aaa%Hijjj! Fu (F5M*S/*=*=h*Q*QSSTTTTTs$   )G GG4 Z Z$#Z$c                 $    t          |            dS )z.Standalone TTS setup (for 'hermes setup tts').N)r  r   s    r   	setup_ttsr  g  s    r   c           	      6   ddl }t          d           t          d           t          d           t          dt           d           t	                       t          | dd	d
          }|                                dk    }g d}d
dddddd}ddddddd}d}|r$|                    d           d||<   ||d<   |dz  }|}|                    d| d           |||<   t          d||          }	|	                    |	          }
|	|k    rt          d |            dS |
| 
                    di           d	<   |
d
k    rt          d!           t          d"           t	                       t          d#           t          d$           t          d%           t          | dd&d'          }t          d(|pt          t          j                                        }|r|| d         d&<   t	                       t!          d)          }|rt          d*           
n`t#          d+d,          r2t          d-d./          }|rt%          d)|           t          d0           
n|
dk    rt          d1           t'          j        d          }|st+          d2           t          d3           nt          d4|            t          | dd5d6          }t          d7|          }|| d         d5<   t%          d8|           t-          |            	nq|
dk    rt          d9           t'          j        d:          pt'          j        d          }|st+          d;           t          d<           nt          d=|            t          | dd>d?          }t          d@|          }|| d         d><   t%          dA|           t-          |            n|
dk    rt          dB           t          dC           ddDlm} ddElm} t7          t9                      ot;          |           j        o
 |d                    } |t          | ddF                    }d,}|r@dGdHg}|dIk    rd}n|dJk    rd}nt!          dK          rdnd}t          dL||          }|dk    }|rIdI| d         dF<   t          dM           t!          dK          st!          dN          rt          dO           ndJ| d         dF<   t          dP           	 t?          d           n# t@          $ r t          dQ           ddl!}t'          j        dR          }|r)|"                    |dSdTdUtF          j$        dgd.d.V          }n'|"                    tF          j$        dWdSdTdgd.d.V          }|j%        dk    rt          dX           nt+          dY           Y nw xY wt	                       t          dZ           t          d[           t!          dK          }|rft          d\           t#          d]d,          rFt          d^d./          }t          d_d./          } |rt%          dK|           | rt%          dN|            nFt          d^d./          }t          d_d./          } |rt%          dK|           | rt%          dN|            t-          |            n|
dk    r:t          d`           t          da           t          db           t          dc           	 t?          d           n# t@          $ r t          dd           ddl!}t'          j        dR          }|r)|"                    |dSdTdUtF          j$        dgd.d.V          }n'|"                    tF          j$        dWdSdTdgd.d.V          }|j%        dk    rt          de           nWt+          df           |j&        rAt          dg|j&        '                                (                                dh                     Y nw xY wt	                       t!          di          }!|!rRt          dj           t#          dkd,          r2t          dld./          }"|"rt%          di|"           t          dm           n2t          dld./          }"|"rt%          di|"           t          dn           t          | ddod6          }t          dp|          }|| d         do<   t%          dq|           t-          |            n|
dk    rJt          dr           t          ds           t          dt           	 t?          du           n# t@          $ r t          dv           ddl!}t'          j        dR          }|r)|"                    |dSdTdUtF          j$        dugd.d.V          }n'|"                    tF          j$        dWdSdTdugd.d.V          }|j%        dk    rt          dw           nWt+          dx           |j&        rAt          dg|j&        '                                (                                dh                     Y nw xY wtS          |            n4|
dk    r-t          dy           t          dz           t!          d{          pd'}#t          d||#          }$|$rt%          d{|$           t!          d}          pd'}%t          d~|%ptU          j+        dd'                    }&|&rt%          d}|&           t!          d          pd}'t          d|'          }(|(r|(dk    rt%          d|(           t!          d          pd'})t          t          j                    dz  dz            }*t          d|)p|*          }+|+rt%          d|+           |$rt#          dd.          rt          d           ddl!}g d},|+r|,,                    d|+g           |(r|(dk    r|,,                    d|(g           |,                    |&r|& d|$ n|$           |,                    d           |"                    |,d.d.d          }|j%        dk    rt          d           n8t+          d|j&        '                                            t          d           t%          d|
           |
dk    r*t%          d| d         	                    dFd                     |
dk    r*t%          d| d         	                    dd                     t[          |            t	                       t          d|
            dS )z)Configure the terminal execution backend.r   NTerminal Backendz1Choose where Hermes runs shell commands and code.z8This affects tool execution, file access, and isolation.rh  z/developer-guide/environmentsr   r   localr   Linux)z.Local - run directly on this machine (default)z7Docker - isolated container with configurable resourcesz Modal - serverless cloud sandboxzSSH - run on a remote machinez2Daytona - persistent cloud development environmentzCVercel Sandbox - cloud microVM with snapshot filesystem persistencedockerr   sshdaytonavercel_sandbox)r   ry   r~  r         ry   r~  r   r  r  )r  r  r   r  r  r     z.Singularity/Apptainer - HPC-friendly containersingularityr  r   zSelect terminal backend:zKeeping current backend: zTerminal backend: Localz&Commands run directly on this machine.zGateway working directory:z)  Used by Telegram/Discord/cron sessions.z4  CLI/TUI always uses your launch directory instead.rV  rJ   z  Gateway working directorySUDO_PASSWORDzSudo password: configuredz<Enable sudo support? (stores password for apt install, etc.)Fz  Sudo passwordTr   zSudo password savedzTerminal backend: DockerzDocker not found in PATH!z3Install Docker: https://docs.docker.com/get-docker/zDocker found: docker_imagez*nikolaik/python-nodejs:python3.11-nodejs20z  Docker imageTERMINAL_DOCKER_IMAGEz'Terminal backend: Singularity/Apptainer	apptainerz(Singularity/Apptainer not found in PATH!z@Install: https://apptainer.org/docs/admin/main/installation.htmlzFound: singularity_imagez3docker://nikolaik/python-nodejs:python3.11-nodejs20z  Container imageTERMINAL_SINGULARITY_IMAGEzTerminal backend: Modalz@Serverless cloud sandboxes. Each session gets its own container.)is_managed_tool_gateway_ready)normalize_modal_mode
modal_modezUse my Nous subscriptionzUse my own Modal accountmanageddirectMODAL_TOKEN_IDz,Select how Modal execution should be billed:zPModal execution will use the managed Nous gateway and bill to your subscription.MODAL_TOKEN_SECRETzZDirect Modal credentials are still configured, but this backend is pinned to managed mode.z+Requires a Modal account: https://modal.comzInstalling modal SDK...uvr  r  --pythoncapture_outputtextr  zmodal SDK installedu2   Install failed — run manually: pip install modalzModal authentication:z/  Get your token at: https://modal.com/settingsz!  Modal token: already configuredz  Update Modal credentials?z    Modal Token IDz    Modal Token SecretzTerminal backend: Daytonaz*Persistent cloud development environments.zBEach session gets a dedicated sandbox with filesystem persistence.zSign up at: https://daytona.iozInstalling daytona SDK...zdaytona SDK installedu4   Install failed — run manually: pip install daytona	  Error: r   DAYTONA_API_KEYz%  Daytona API key: already configuredz  Update API key?z    Daytona API keyz    Updatedz    Configureddaytona_imagez  Sandbox imageTERMINAL_DAYTONA_IMAGEz Terminal backend: Vercel SandboxzDCloud microVM sandboxes with snapshot-backed filesystem persistence.z=Requires the optional SDK: pip install 'hermes-agent[vercel]'vercelzInstalling vercel SDK...zvercel SDK installeduC   Install failed — run manually: pip install 'hermes-agent[vercel]'zTerminal backend: SSHz)Run commands on a remote machine via SSH.TERMINAL_SSH_HOSTz  SSH host (hostname or IP)TERMINAL_SSH_USERz
  SSH userUSERTERMINAL_SSH_PORT22z
  SSH portTERMINAL_SSH_KEYz.sshid_rsaz  SSH private key pathz  Test SSH connection?z  Testing connection...)r  -ozBatchMode=yesr'  zConnectTimeout=5z-iz-p@zecho ok
   )r  r  ry  z  SSH connection successful!z  SSH connection failed: z'  Check your SSH key and host settings.TERMINAL_ENVTERMINAL_MODAL_MODEautor=  r:  r;  zTerminal backend set to: ).r  rc   re   r  r`   rQ   systemr   r   r   r,  rf   r   r   r   homerZ   r   rX   r  r  rg   r7  tools.managed_tool_gatewayr  tools.tool_backend_helpersr  rl   r   r   r  
__import__ImportErrorr  r  rk   r  
returncodestderrr   
splitlinesrM  osgetenvr  rW   )-r   	_platformcurrent_backendis_linuxterminal_choicesidx_to_backendbackend_to_idxnext_idxr  terminal_idxselected_backendcurrent_cwdrV  existing_sudo	sudo_pass
docker_bincurrent_imageimagesing_binr  r  managed_modal_availabler  use_managed_modalmodal_choicesdefault_modal_idxmodal_mode_idxr  uv_binresultexisting_tokentoken_idtoken_secretexisting_keyr(   current_hosthostcurrent_userusercurrent_portportcurrent_keydefault_keyssh_keyssh_cmds-                                                r   setup_terminal_backendr]  q  s       #$$$BCCCIJJJEJEEEFFF	GGGfj)WMMMO!!W,H   !X'e	VfggN A!PQefggNH  PQQQ#0x (0}%A  ?_???@@@'6N#$ "$46F L &)),77'''@@@AAA3CFj"%%i07""/000;<<< 	/000>???IJJJfj%DDD2K4S3ty{{CSCSTT 	,(+F:u% 	%o66 	523333JE
 
 	5 04@@@I 5	:::3444	X	%	%0111 \(++
 	65666LMMMM4
44555  
NLxyyy'77-2z>*.666#F++++	]	*	*?@@@ <,,K]0K0K 	-DEEER    +++,,,
4G  RG  H  H  H*M::27z./3U;;;#F++++	W	$	$/000UVVVLLLLLLCCCCCC"&&(( 7*622D7 .-g66	#
 #
 *)'&*l*S*STT
!" 	4**M Y&&$%!!x''$%!!)67G)H)H$OAAa!*>! N
 !/! 3 ?	G/8F:|,ijjj-.. -@T2U2U p   08F:|,DEEEX7#### X X X4555!!!!d++ '^^"!%&N# (,! ,  FF (^^uiI'+! ,  F
 $))!"78888!"VWWW7X< GGG.///HIII*+;<<N G>??? !>FF K%&:TJJJH#)*BT#R#R#RL C&'7BBB# K&';\JJJ!"6FFF%&>NNN ?"#3X>>> G"#7FFF#F++++	Y	&	&1222?@@@WXXX3444	Uy!!!! 	U 	U 	U2333\$''F #UIz3>9U#' (   $^T5)YG#' (  
  A%%56666TUUU= US6=+>+>+@+@+K+K+M+Mb+QSSTTT-	U2 	$%677 	0>???0%88 1 !6FFF 1"#4g>>>!-0002TBBBG 00':::.///  
OMyzzz(-88.3z?+/777#F++++	-	-	-8999YZZZRSSS	Ux     	U 	U 	U1222\$''F #UIz3>8T#' (   $^T5)XF#' (  
  A%%45555cddd= US6=+>+>+@+@+K+K+M+Mb+QSSTTT-	U0 	(////	U	"	"-...>??? %%899?R3\BB 	6.555 %%899?RlL$IBIfb4I4IJJ 	6.555 %%899ATlL11 	6DDLL.555 $$677=2$)++.9::1;3M+NN 	8-w777  	FM":DAA 	F0111NNNG 0g/// -d|,,,NNt=d++T+++>>>NN9%%%^^GDtUW^XXF A%%<====Q&-:M:M:O:OQQRRRDEEE >#34447"",fZ.@.D.D\SY.Z.Z[[[+++0&2D2H2HIY[c2d2deee	GGG@.>@@AAAAAs9   7T B-V76V78\ C5` ?` *d: :C5h21h2c                    d|                      di           d<   t          d           d|                      di           d<   d|                      d	i           d
<   d| d	         d<   |                      di                               dddd           t          |            t	          d           t          d           t          d           t          d           t          d           t          d           dS )zDApply recommended defaults for all agent settings without prompting.Z   rH   	max_turnsHERMES_MAX_ITERATIONSallr   tool_progressTcompressionenabled      ?	thresholdsession_resetboth  r  )modeidle_minutesat_hourzApplied recommended defaults:z  Max iterations: 90z  Tool progress: allz  Compression threshold: 0.50z5  Session reset: inactivity (1440 min) + daily (4:00)z.  Run `hermes setup agent` later to customize.N)r,  rY   updaterW   rf   re   r  s    r   _apply_default_agent_settingsro    s   24Fgr"";/
 ,---8=Fi$$_56:FmR((3)-F=+&
or**113 3    1222%&&&%&&&.///FGGG?@@@@@r   c           	      X   t          d           t          dt           d           t                       t	          t          | ddd                    }t          d           t          d	           t          d
| d           t          d|          }	 t          |          }|dk    rP||                     di           d<   | 	                    dd           t          d           t          d|            n# t          $ r t          d           Y nw xY wt          d           t          d           t          d           t          d           t          d           t          d           t          d           t          | ddd          }t          d|          }|                                dv rZd| vri | d<   |                                | d         d<   t          |            t          d|                                            nt          d| d | d!           t          d"           t          d#           t          d$           d%|                     d&i           d'<   t          | d&d(d)          }t          d*t	          |                    }	 t!          |          }d)|cxk    rd+k    rn n|| d&         d(<   n# t          $ r Y nw xY wt          d,| d&                             d(d)                      t          d-           t          d.           t          d/           t          d           t          d0           t          d1           t          d2           t          d           t          d3           t          d           g d4}	|                     d5i           }
|
                    d6d7          }|
                    d8d9          }|
                    d:d;          }dd<d=d>d?                    |d          }t%          d@|	|          }|                     d5i            |dk    rd7| d5         d6<   t          dAt	          |                    }	 t          |          }|dk    r|| d5         d8<   n# t          $ r Y nw xY wt          dBt	          |                    }	 t          |          }d|cxk    rdCk    rn n|| d5         d:<   n# t          $ r Y nw xY wt          dD| d5                             d8d9           dE| d5                             d:d;           dF           nU|d<k    rdG| d5         d6<   t          dAt	          |                    }	 t          |          }|dk    r|| d5         d8<   n# t          $ r Y nw xY wt          dD| d5                             d8d9           dH           n|d=k    rdI| d5         d6<   t          dBt	          |                    }	 t          |          }d|cxk    rdCk    rn n|| d5         d:<   n# t          $ r Y nw xY wt          dJ| d5                             d:d;           dF           n/|d>k    r)dK| d5         d6<   t          dL           t          dM           t          |            dS )NzSConfigure agent behavior: iterations, progress display, compression, session reset.Agent Settingsrh  z/user-guide/configurationrH   r`  r_  r   z1Maximum tool-calling iterations per conversation.z3Higher = more complex tasks, but costs more tokens.zPress Enter to keep z5. Use 90 for most tasks or 150+ for open exploration.zMax iterationsr   Nra  zMax iterations set to z%Invalid number, keeping current valuerJ   zTool Progress Displayz=Controls how much tool activity is shown (CLI and messaging).u-     off     — Silent, just the final responseu>     new     — Show tool name only when it changes (less noise)u7     all     — Show every tool call with a short previewu0     verbose — Full args, results, and debug logsr   rc  rb  zTool progress mode>   rb  newoffverbosezTool progress set to: zUnknown mode 'z', keeping ''zContext CompressionzAAutomatically summarizes old messages when context gets too long.zNHigher threshold = compress later (use more context). Lower = compress sooner.Trd  re  rg  rf  z Compression threshold (0.5-0.95)gffffff?z%Context compression threshold set to zSession Reset PolicyzJMessaging sessions (Telegram, Discord, etc.) accumulate context over time.zMEach message adds to the conversation history, which means growing API costs.zMTo manage this, sessions can automatically reset after a period of inactivityzLor at a fixed time each day. When a reset happens, the agent saves importantuR   things to its persistent memory first — but the conversation context is cleared.z=You can also manually reset anytime by typing /reset in chat.)zDInactivity + daily reset (recommended - reset whichever comes first)z6Inactivity only (reset after N minutes of no messages)z+Daily only (reset at a fixed hour each day)zDNever auto-reset (context lives until /reset or context compression)zKeep current settingsrh  rk  ri  rl  rj  rm  r  ry   r~  r   )ri  idledailynonezSession reset mode:z  Inactivity timeout (minutes)z%  Daily reset hour (0-23, local time)   zSessions reset after z min idle or daily at z:00rv  z min of inactivityrw  zSessions reset daily at rx  zGSessions will never auto-reset. Context is managed only by compression.zFLong conversations will grow in cost. Use /reset manually when needed.)rc   re   r  r`   r   rQ   r   r   r,  r  rY   rf   r   rg   rK   rW   r-  r   r   )r   current_maxmax_iter_strmax_itercurrent_moderk  current_thresholdthreshold_strrg  reset_choicescurrent_policycurrent_idlecurrent_hourdefault_reset	reset_idxidle_stridle_valhour_strhour_vals                      r   setup_agent_settingsr    sF    !"""AJAAABBB	GGG gfg{BGGGHHKBCCCDEEEa{aaa   *K88L?|$$a<<
 ;CFgr**;7JJ{D)))4555=8==>>> ? ? ?=>>>>>? rNNN&'''NOOO>???OPPPHIIIABBB69ouMMML&55Dzz||777F"" "F9-1ZZ\\y/*F=tzz||==>>>>HtHHHHHIII &'''RSSSX   7;FmR((3{DQQQ=sCT?U?UVVM-((	)####t#####1:F=!+.    ^}0E0I0I+W[0\0\^^  
 '(((T   W   rNNNW   V   \   rNNNNOOOrNNN  M ZZ44N!%%ff55L!%%nd;;L!%%i33LAqAAEElTUVVM3]MRRI
or***A~~*0':C<M<MNN	8}}H!||:B'7 	 	 	D	A3|CTCTUU	8}}HH"""""""""5='	2 	 	 	D	 \F?$;$?$?PT$U$U  \  \ms  uD  nE  nI  nI  JS  UV  nW  nW  \  \  \	
 	
 	
 	
 
a*0':C<M<MNN	8}}H!||:B'7 	 	 	D	iF?$;$?$?PT$U$Uiii	
 	
 	
 	
 
a*1'A3|CTCTUU	8}}HH"""""""""5='	2 	 	 	D	Uvo'>'B'B9a'P'PUUU	
 	
 	
 	
 
a*0'U	
 	
 	
 	T	
 	
 	

 sm   A%C> >DD&*K 
KK0 R 
RR?*S* *
S76S75 V 
V#"V#*X. .
X;:X;c                     t          d           t          d          } | rt          d           t          dd          st          d          srt          d           t          dd	          rSt          d
           t	          d          }|r3t          d|                    dd                     t          d           dS t          d           ddl}	 t	          dd	          }|sdS  |j	        d|          st          d           7	 t          d|           t          d           t                       t          d           t          d           t          d           t          d           t                       t	          d          }|r4t          d|                    dd                     t          d           nt          d           t                       t          d           t          d           t          d            |r-|                    d!          d                                         nd}|r]t          d"| d#d	          r$t          d$|           t          d%|            dS t	          d&          }|rt          d$|           dS dS t          d'           t	          d(          }|rt          d$|           dS dS ))z1Configure Telegram bot credentials and allowlist.TelegramTELEGRAM_BOT_TOKENzTelegram: already configuredzReconfigure Telegram?FTELEGRAM_ALLOWED_USERSuA   ⚠️  Telegram has no user allowlist - anyone can use your bot!Add allowed users now?Tz6   To find your Telegram user ID: message @userinfobot"Allowed user IDs (comma-separated)r   rJ   zTelegram allowlist configuredNz'Create a bot via @BotFather on Telegramr   zTelegram bot tokenr   z^\d+:[A-Za-z0-9_-]{30,}$znInvalid token format. Expected: <numeric_id>:<alphanumeric_hash> (e.g., 123456789:ABCdefGHI-jklMNOpqrSTUvwxYZ)zTelegram token saved,   🔒 Security: Restrict who can use your botz!   To find your Telegram user ID:z&   1. Message @userinfobot on Telegramz:   2. It will reply with your numeric ID (e.g., 123456789)?Allowed user IDs (comma-separated, leave empty for open access)zATelegram allowlist configured - only listed users can use the botu@   ⚠️  No allowlist set - anyone who finds your bot can use it!:   📬 Home Channel: where Hermes delivers cron job results,.   cross-platform messages, and notifications.z:   For Telegram DMs, this is your user ID (same as above).,zUse your user ID (z) as the home channel?TELEGRAM_HOME_CHANNELzTelegram home channel set to zHHome channel ID (or leave empty to set later with /set-home in Telegram)zI   You can also set this later by typing /set-home in your Telegram chat.z*Home channel ID (leave empty to set later))rc   rZ   re   r   r   rX   replacerf   rematchrd   r`   splitr   )r  allowed_usersr  rJ  first_user_idhome_channels         r   _setup_telegramr    s[   122H 12224e<< 
	 !9:: G^___ !94@@ GWXXX$*+O$P$PM$ G&'?AVAVWZ\^A_A_```%&EFFFF8999III
+d;;; 	Frx3U;; 	@   '///()))	GGG=>>>23337888KLLL	GGGI M  W/1F1FsB1O1OPPPYZZZZUVVV	GGGKLLL?@@@KLLL;HPM'',,Q/55777bM BSmSSSUYZZ 	F2MBBBI-IIJJJJJ!"lmmL F6EEEEEF F 	^___JKK 	B2LAAAAA	B 	Br   c                     t          d           t          d          } | rt          d           t          dd          st          d          st          d           t          dd	          rat          d
           t	          d          }|rAt          |          }t          dd                    |                     t          d           dS t          d           t	          dd	          }|sdS t          d|           t          d           t                       t          d           t          d           t          d           t          d           t                       t          d           t                       t	          d          }|rBt          |          }t          dd                    |                     t          d           nt          d           t                       t          d           t          d           t          d           t          d           t          d           t	          d          }|rt          d |           dS dS )!z0Configure Discord bot credentials and allowlist.DiscordDISCORD_BOT_TOKENzDiscord: already configuredzReconfigure Discord?FDISCORD_ALLOWED_USERSu@   ⚠️  Discord has no user allowlist - anyone can use your bot!r  TuJ      To find Discord ID: Enable Developer Mode, right-click name → Copy IDr  r  zDiscord allowlist configuredNz;Create a bot at https://discord.com/developers/applicationszDiscord bot tokenr   zDiscord token savedr  z    To find your Discord user ID:z/   1. Enable Developer Mode in Discord settingsu'      2. Right-click your name → Copy IDzB   You can also use Discord usernames (resolved on gateway start).zLAllowed user IDs or usernames (comma-separated, leave empty for open access)uF   ⚠️  No allowlist set - anyone in servers with your bot can use it!r  r  uA      To get a channel ID: right-click a channel → Copy Channel IDz0   (requires Developer Mode in Discord settings)zH   You can also set this later by typing /set-home in a Discord channel.9Home channel ID (leave empty to set later with /set-home)DISCORD_HOME_CHANNEL)
rc   rZ   re   r   r   _clean_discord_user_idsrX   r   rf   r`   )r  r  cleaned_idsrJ  r  s        r   _setup_discordr    s   011H 01113U;; 
	 !899 F]^^^ !94@@ Fklll$*+O$P$PM$ F&=m&L&L&'>@U@UVVV%&DEEEFLMMM&666E &...'(((	GGG=>>>1222@AAA8999	GGGSTTT	GGGV M  ]-m<<.0E0EFFF45555[\\\	GGGKLLL?@@@RSSSABBBYZZZUVVL =-|<<<<<= =r   rawc                    g }|                      dd                              d          D ]}|                                }|                    d          r=|                    d          r(|                    d                              d          }|                                                    d          r
|dd	         }|r|                    |           |S )
zGStrip common Discord mention prefixes from a comma-separated ID string.r   rJ   r  z<@>z<@!zuser:r  N)	r  r  r   rq  endswithlstriprstriprK   r   )r  r   uids      r   r  r  ,  s    G{{3##))#..    iikk>>$ 	0CLL$5$5 	0**U##**3//C99;;!!'** 	abb'C 	 NN3Nr   c                  (   t          d           t          d          } | r?t          d           t          dd          s t          dd          rt	                       dS t          d	           t          d
           t          d           t          d           t          d           t          d           t          d           t                       t          d           t                       t	                       t                       t          dd          }|sdS t          d|           t          dd          }|rt          d|           t          d           t                       t          d           t          d           t                       t          d          }|r4t          d|	                    dd                     t          d           nt          d           t          d           t                       t          d           t          d            t          d!           t          d"           t          d#           t          d$          }|r$t          d%|                                           dS dS )&z Configure Slack bot credentials.SlackSLACK_BOT_TOKENzSlack: already configuredzReconfigure Slack?FzcRegenerate the Slack app manifest with the latest command list? (recommended after `hermes update`)TNzSteps to create a Slack app:u9      1. Go to https://api.slack.com/apps → Create New AppuG         Pick 'From an app manifest' — we'll generate one for you below.u=      2. Enable Socket Mode: Settings → Socket Mode → EnableuB         • Create an App-Level Token with 'connections:write' scopeu4      3. Install to Workspace: Settings → Install AppzD   4. After installing, invite the bot to channels: /invite @YourBotzU   Full guide: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/slack/zSlack Bot Token (xoxb-...)r   zSlack App Token (xapp-...)SLACK_APP_TOKENzSlack tokens savedr  u\      To find a Member ID: click a user's name → View full profile → ⋮ → Copy member IDzTAllowed user IDs (comma-separated, leave empty to deny everyone except paired users)SLACK_ALLOWED_USERSr   rJ   zSlack allowlist configureduJ   ⚠️  No Slack allowlist set - unpaired users will be denied by default.zw   Set SLACK_ALLOW_ALL_USERS=true or GATEWAY_ALLOW_ALL_USERS=true only if you intentionally want open workspace access.r  r  zC   To get a channel ID: open the channel in Slack, then right-clickuN      the channel name → Copy link — the ID starts with C (e.g. C01ABC2DE3F).zF   You can also set this later by typing /set-home in a Slack channel.r  SLACK_HOME_CHANNEL)rc   rZ   re   r   "_write_slack_manifest_and_instructr`   r   rX   rf   r  rg   r   )r  	bot_token	app_tokenr  r  s        r   _setup_slackr  :  s   .//H .///1599 		 <  5
 3444F-...JKKKXYYYNOOOSTTTEFFFUVVV	GGGfggg	GGG
 '(((	GGG3dCCCI $i0003dCCCI 5()444&'''	GGG=>>>mnnn	GGG^ M  N,m.C.CC.L.LMMM23333bccc  M  	N  	N  	N	GGGKLLL?@@@TUUU_```WXXXUVVL C+\-?-?-A-ABBBBBC Cr   c                     	 ddl m}  ddlm}  | dd          }t	           |                      dz  }|j                            dd	           dd
l}|                    |	                    |dd          dz   d           t          d|            t          d           t          d           d
S # t          $ r,}t          d|            t          d           Y d
}~d
S d
}~ww xY w)u  Generate the Slack manifest, write it under HERMES_HOME, and print
    paste-into-Slack instructions.

    Exposed as its own helper so both the initial setup flow and the
    "reconfigure? → no" branch can refresh the manifest without the user
    re-entering tokens. Failures are non-fatal — if the manifest write
    fails for any reason, we print a warning and skip rather than abort
    the whole Slack setup.
    r   )_build_full_manifest)rS   HermeszYour Hermes agent on Slack)bot_namebot_descriptionzslack-manifest.jsonT)rZ  exist_okNr~  F)indentensure_ascii
rP  rQ  zSlack app manifest written to: u      Paste it into https://api.slack.com/apps → your app → Features → App Manifest → Edit, then Save.  Slack will prompt to reinstall if scopes or slash commands changed.z\   Re-run `hermes slack manifest --write` anytime to refresh after Hermes adds new commands.zCouldn't write Slack manifest: zI   You can generate it manually later with: hermes slack manifest --write)hermes_cli.slack_clir  r  rS   r   rY  mkdirr\  
write_textdumpsrf   re   rn   rg   )r  rS   manifesttarget_jsonr  s         r   r  r  ~  s   
======444444''8
 
 
 oo''((+@@D4888KKK??$F 	 	
 	
 	
 	@@@AAA=	
 	
 	

 	(	
 	
 	
 	
 	
  
 
 
===>>>,	
 	
 	
 	
 	
 	
 	
 	
 	

s   B3B7 7
C-!C((C-c            	         t          d           t          d          pt          d          } | r!t          d           t          dd          sdS t          d           t          d	           t          d
           t	                       t          d          }|r#t          d|                    d                     t	                       t          d           t          dd          }|rAt          d|           t          d          }|rt          d|           t          d           nSt          d          }|rt          d|           t          dd          }|rt          d|           t          d           |st          d          rIt	                       t          dd          }|rt          dd           t          d           |rdnd}	 t          d           n# t          $ r t          d| d           d dl}t          j        d!          }|r)|                    |d"d#d$t          j        |gdd%          }	n'|                    t          j        d&d"d#|gdd%          }	|	j        d k    rt          | d'           n[t%          d(| d)           |	j        rAt          d*|	j                                                                        d+                     Y nw xY wt	                       t          d,           t          d-           t	                       t          d.          }
|
r4t          d/|
                    d0d1                     t          d2           nt          d3           t	                       t          d4           t          d5           t          d6           t          d7          }|rt          d8|           dS dS dS )9zConfigure Matrix credentials.MatrixMATRIX_ACCESS_TOKENMATRIX_PASSWORDzMatrix: already configuredzReconfigure Matrix?FNzMWorks with any Matrix homeserver (Synapse, Conduit, Dendrite, or matrix.org).zC   1. Create a bot user on your homeserver, or use your own accountzE   2. Get an access token from Element, or provide user ID + passwordz0Homeserver URL (e.g. https://matrix.example.org)MATRIX_HOMESERVERr   zCAuth: provide an access token (recommended), or user ID + password.z-Access token (leave empty for password login)Tr   u9   User ID (@bot:server — optional, will be auto-detected)MATRIX_USER_IDzMatrix access token savedzUser ID (@bot:server)PasswordzMatrix credentials savedz$Enable end-to-end encryption (E2EE)?MATRIX_ENCRYPTIONr$  zE2EE enabledzmautrix[encryption]mautrixzInstalling z...r   r  r  r  r  r  r  z
 installedu.   Install failed — run manually: pip install 'ru  r  r   r  z-   Matrix user IDs look like @username:serverr  MATRIX_ALLOWED_USERSr   rJ   zMatrix allowlist configuredE   ⚠️  No allowlist set - anyone who can message the bot can use it!uI   📬 Home Room: where Hermes delivers cron job results and notifications.zE   Room IDs look like !abc123:server (shown in Element room settings)zD   You can also set this later by typing /set-home in a Matrix room.z6Home room ID (leave empty to set later with /set-home)MATRIX_HOME_ROOM)rc   rZ   re   r   r`   r   rX   r  rf   r1  r2  r  r  r  r  rk   r  r3  rg   r4  r   r5  r  )r  
homeserverrJ  user_idrt   	want_e2ee
matrix_pkgr  rM  rN  r  	home_rooms               r   _setup_matrixr    sk   233W}EV7W7WH /0002E:: 	F^___TUUUVWWW	GGGJKKJ D*J,=,=c,B,BCCC	GGGTUUUBTRRRE 6,e444TUU 	6+W55512222011 	6+W555*t444 	6,h7774555 0:/00 0:!"H%PP	 	*.777.))).7F**Y
	Uy!!!! 	U 	U 	U4Z444555\$''F 	#UIz3>:V#'d (  
 $^T5)ZH#'d (    A%%7778888\z\\\]]]= US6=+>+>+@+@+K+K+M+Mb+QSSTTT'	U* 	ABBBBCCC`aa 	`1=3H3Hb3Q3QRRR78888^___^___Z[[[YZZZSTT	 	:-y99999a0: 0:^	: 	:s   G- -D K0/K0c                     t          d           t          d          } | r!t          d           t          dd          sdS t          d           t          d           t          d	           t	                       t          d
          }|r#t          d|                    d                     t          dd          }|sdS t          d|           t          d           t	                       t          d           t          d           t          d           t	                       t          d          }|r4t          d|	                    dd                     t          d           nt          d           t	                       t          d           t          d           t          d           t          d          }|rt          d|           t          d           dS ) z%Configure Mattermost bot credentials.
MattermostMATTERMOST_TOKENzMattermost: already configuredzReconfigure Mattermost?FNz/Works with any self-hosted Mattermost instance.uF      1. In Mattermost: Integrations → Bot Accounts → Add Bot Accountz   2. Copy the bot tokenz3Mattermost server URL (e.g. https://mm.example.com)MATTERMOST_URLr   z	Bot tokenTr   zMattermost token savedr  u6      To find your user ID: click your avatar → Profilez'   or use the API: GET /api/v4/users/mer  MATTERMOST_ALLOWED_USERSr   rJ   zMattermost allowlist configuredr  uL   📬 Home Channel: where Hermes delivers cron job results and notifications.uH      To get a channel ID: click channel name → View Info → copy the IDzK   You can also set this later by typing /set-home in a Mattermost channel.r  MATTERMOST_HOME_CHANNEL2   Open config in your editor:  hermes config edit)
rc   rZ   re   r   r`   r   rX   r  rf   r  )r  mm_urlrJ  r  r  s        r   _setup_mattermostr    s    /00H 34446>> 	F@AAAWXXX)***	GGGIJJF ='s););<<<;...E %u---*+++	GGG=>>>GHHH8999	GGG\]]M \1=3H3Hb3Q3QRRR78888Z[[[	GGG]^^^YZZZ\]]]UVVL @0,???CDDDDDr   c                     t          d           t          d          } | r!t          d           t          dd          sdS t          d           t          d           t          d	           t          d
           t	                       t          d           t	                       t          d          }|st          d           dS t          d|                    d                     t          dd          }|st          d           dS t          d|           t          d           t	                       t          d           t          d           t	                       t          d          }|r4t          d|
                    dd                     t          d           nt          d           t	                       t          d           t          d           t          d          }|rt          d |           t	                       t          d!           t          d"d          rnt          d#          }|r]	 t          d$t          t          |                               t          d%|            n# t          $ r t          d&           Y nw xY wt	                       t          d'           t          d(           t          d)           dS )*z'Configure BlueBubbles iMessage gateway.zBlueBubbles (iMessage)BLUEBUBBLES_SERVER_URLzBlueBubbles: already configuredzReconfigure BlueBubbles?FNuC   Connects Hermes to iMessage via BlueBubbles — a free, open-sourcez1macOS server that bridges iMessage to any device.z4   Requires a Mac running BlueBubbles Server v1.0.0+z%   Download: https://bluebubbles.app/uN   In BlueBubbles Server → Settings → API, note your Server URL and Password.z6BlueBubbles server URL (e.g. http://192.168.1.10:1234)u5   Server URL is required — skipping BlueBubbles setupr   zBlueBubbles server passwordTr   u3   Password is required — skipping BlueBubbles setupBLUEBUBBLES_PASSWORDzBlueBubbles credentials savedu0   🔒 Security: Restrict who can message your botzJ   Use iMessage addresses: email (user@icloud.com) or phone (+15551234567)zIAllowed iMessage addresses (comma-separated, leave empty for open access)BLUEBUBBLES_ALLOWED_USERSr   rJ   z BlueBubbles allowlist configureduI   ⚠️  No allowlist set — anyone who can iMessage you can use the bot!uJ   📬 Home Channel: phone or email for cron job delivery and notifications.zD   You can also set this later with /set-home in your iMessage chat.z/Home channel address (leave empty to set later)BLUEBUBBLES_HOME_CHANNELz6Advanced settings (defaults are fine for most setups):z$Configure webhook listener settings?z%Webhook listener port (default: 8645)BLUEBUBBLES_WEBHOOK_PORTWebhook port set to z'Invalid port number, using default 8645zBRequires the BlueBubbles Private API helper for typing indicators,zGread receipts, and tapback reactions. Basic messaging works without it.zC   Install: https://docs.bluebubbles.app/helper-bundle/installation)rc   rZ   re   r   r`   r   rg   rX   r  rf   r  r   r   r   )r  
server_urlrt   r  r  webhook_ports         r   _setup_bluebubblesr  +	  s   )***566H 45557?? 	FTUUUBCCCEFFF6777	GGG_```	GGGPQQJ MNNN+Z->->s-C-CDDD3dCCCH KLLL)84441222	GGGABBB[\\\	GGGfggM `2M4I4I#r4R4RSSS89999^___	GGG[\\\UVVVKLLL A1<@@@	GGGGHHH;UCC IEFF 	II93s<?P?P;Q;QRRRC\CCDDDD I I IGHHHHHI 
GGGSTTTXYYYTUUUUUs   <J J$#J$c                  &    ddl m}   |              dS )z5Configure QQ Bot (Official API v2) via gateway setup.r   )_setup_qqbotN)hermes_cli.gatewayr  )_gateway_setup_qqbots    r   r  r  l	  s)    GGGGGGr   c                  <   t          d           t          d          } | r!t          d           t          dd          sdS t	                       t          d           t          d           t          d	           t	                       t          d
           t	                       t          d          }|r]	 t          dt          t          |                               t          d|            n# t          $ r t          d           Y nw xY wt          dd          }|r t          d|           t          d           nt          d           t          dd           t	                       t          d           ddlm} t          d |             d           t          d           t          d           t	                       t          d           t          d           t	                       t          d           t          d           dS ) zConfigure webhook integration.WebhooksWEBHOOK_ENABLEDzWebhooks: already configuredzReconfigure webhooks?FNuD   ⚠  Webhook and SMS platforms require exposing gateway ports to thezE   internet. For security, run the gateway in a sandboxed environmentzB   (Docker, VM, etc.) to limit blast radius from prompt injection.zX   Full guide: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/webhooks/zWebhook port (default 8644)WEBHOOK_PORTr  z'Invalid port number, using default 8644z-Global HMAC secret (shared across all routes)Tr   WEBHOOK_SECRETzWebhook secret saveduE   No secret set — you must configure per-route secrets in config.yamlr$  zWebhooks enabled! Next steps:r   r   z   1. Define webhook routes in z/config.yamlz3   2. Point your service (GitHub, GitLab, etc.) at:z3      http://your-server:8644/webhooks/<route-name>z   Route configuration guide:z_   https://hermes-agent.nousresearch.com/docs/user-guide/messaging/webhooks/#configuring-routesr  )rc   rZ   re   r   r`   rg   r   rX   r   r   rf   r   r  r   )r  rX  secretr  s       r   _setup_webhooksr  r	  sH   .//H 12224e<< 	F	GGGXYYYYZZZVWWW	GGGijjj	GGG/00D E	E>3s4yy>>:::7778888 	E 	E 	ECDDDDD	E CdSSSF _'000,----]^^^$f---	GGG1222<<<<<<EEEEFFFDEEEDEEE	GGG.///pqqq	GGGCDDDCDDDDDs   :<C7 7DDc           	        ./ ddl m}m/m} t	          d           t          d           t          d           t                        |            }g }g }t          |          D ]U\  }} /|          }|                    |d          d|d          d	| d
           |dk    r|                    |           Vt          d||          }	|	st          d           dS |	D ]}
 |||
                    dt          dt          fd.t          ./fd |            D                       }|r+t                       t          d           t          d           g }t          d          r$t          d          s|                    d           t          d          r$t          d          s|                    d           t          d          r$t          d          s|                    d           t          d          r$t          d          s|                    d            t          d!          r3t          d"          s$t          d#          s|                    d$           |rt                       t          d%d&                    |                      t          d'           t          d(           t          d)           |D ]'}t          d*|                                 d+           (ddl}|                                d,k    }|                                d-k    }|                                d.k    }dd/l m}m}m}m}m}m}m}m}m}m}m}m}m }m!}m"}m#} m$}!  |            }" |            }# |            }$|$p|p|}%t                       |$r" |            r |             t                       |$r" |            r |             t                       |#r|$r |             r |!d0           nJtK          d1d2          r	 |$r |             n)|r |             n|rdd3l&m'}& |&(                                 n# |$ rP}'tS          d4           t          |'          *                                D ]}(t          d5|(            Y d}'~'nd}'~'w|$ r(}'tS          d6|'             |!d0           Y d}'~'nd}'~'wtV          $ r}'tS          d6|'            Y d}'~'nad}'~'ww xY wnW|"r|$r |             r |!d7           n;tK          d8d2          r	 |$r |             n)|r |             n|rdd3l&m'}& |&,                                 n# |$ rP}'tS          d9           t          |'          *                                D ]}(t          d5|(            Y d}'~'nd}'~'w|$ r(}'tS          d:|'             |!d7           Y d}'~'nwd}'~'wtV          $ r}'tS          d:|'            Y d}'~'nRd}'~'ww xY wnH|%r|$rd;})n|rd<})nd=})tK          d>|) d?d2          rk	 d}*d@}+d@},|$r |d@A          \  }*}+n1|r |d@A           d2}+n dd3l&m'}& |&-                    d@A           d2}+d2},t                       |+r|,stK          dBd2          r	 |$r ||*dCk    D           n|r
 |             n# |$ rO}'tS          d9           t          |'          *                                D ]}(t          d5|(            Y d}'~'nVd}'~'w|$ r'}'tS          d:|'             |!d7           Y d}'~'n,d}'~'wtV          $ r}'tS          d:|'            Y d}'~'nd}'~'ww xY wn# tV          $ r+}'tS          dE|'            t          dF           Y d}'~'nd}'~'ww xY wt          dG           |$rt          dH           t          dI           nddJl.m/}-  |-            r[t          dK           t          dL           t          dM           t          dN           t          dO           t          dP           nt          dK           t          dQ           t          d           dS dS )Rz*Configure messaging platform integrations.r   )_all_platforms_platform_status_configure_platformMessaging PlatformszAConnect to messaging platforms to chat with Hermes from anywhere.z&Toggle with Space, confirm with Enter.emojir   r  z  (r   
configuredzSelect platforms to configure:zENo platforms selected. Run 'hermes setup gateway' later to configure.Nstatusr   c                     |                                  }|dk    p)|                    d          p|                    d           S )Nnot configured	partiallyzplugin disabled)rK   rq  )r   ss     r   _is_progressz#setup_gateway.<locals>._is_progress	  sK    LLNN!! /||K((/||-..
 	
r   c              3   @   K   | ]}  |                    V  d S Nr   )r   pr  r  s     r   r   z setup_gateway.<locals>.<genexpr>	  sJ        ./%%a(())     r   u   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━zMessaging platforms configured!r  r  r  r  r  r  r  r  r  r  r  BlueBubbles	QQ_APP_IDQQBOT_HOME_CHANNELQQ_HOME_CHANNELQQBotzNo home channel set for: r   z7   Without a home channel, cron jobs and cross-platformz2   messages can't be delivered to those platforms.z1   Set one later with /set-home in your chat, or:z     hermes config set z_HOME_CHANNEL <channel_id>r   DarwinWindows)_is_service_installed_is_service_runningsupports_systemd_serviceshas_conflicting_systemd_unitshas_legacy_hermes_units install_linux_gateway_from_setup$print_systemd_scope_conflict_warningprint_legacy_unit_warningsystemd_startsystemd_restartlaunchd_installlaunchd_startlaunchd_restartUserSystemdUnavailableErrorSystemScopeRequiresRootError$_system_scope_wizard_would_need_root_print_system_scope_remediationrestartz)  Restart the gateway to pick up changes?T)gateway_windowsu0     Restart failed — user systemd not reachable:r   z  Restart failed: rN  z  Start the gateway service?u.     Start failed — user systemd not reachable:z  Start failed: systemdlaunchdzScheduled Taskz  Install the gateway as a z. service? (runs in background, starts on boot)F)forcez  Start the service now?r-  )r-  z  Install failed: z.  You can try manually: hermes gateway installz/  You can install later: hermes gateway installzA  Or as a boot-time service: sudo hermes gateway install --systemz'  Or run in foreground:  hermes gateway)is_containerz,Start the gateway to bring your bots online:z>   hermes gateway run          # Run as container main processrJ   z4For automatic restarts, use a Docker restart policy:z*   docker run --restart unless-stopped ...z/   docker restart <container>  # Manual restartz2   hermes gateway              # Run in foreground)0r  r  r  r  rc   re   r`   r   r   r   r   rl   anyrf   rZ   rg   r   upperr  r-  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r   
hermes_clir"  r!  rd   r5  rn   rN  r  r  r&  )0r   r  r  	platformsr   r   r   platr   r   r   any_messagingmissing_homer8  	_is_linux	_is_macos_is_windowsr  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   service_installedservice_runningsupports_systemdsupports_service_managerr"  r  linesvc_nameinstalled_scopedid_installstarted_inliner&  r  r  s0                                                 @@r   setup_gatewayr:  	  sy   XXXXXXXXXX&'''RSSS7888	GGG  I ELY'' # #4!!$''WCCWCC&CCCDDD\!!""" @%VVH Z[[[ , ,IcN++++
S 
T 
 
 
 
      3A>3C3C    M  |:7888 -.. 	,}#8
 8
 	, 
+++,-- 	+m"7
 7
 	+ 	****++ 	)MBV4W4W 	)(((122 	/=Ic;d;d 	/...%% 	).//	)3@AR3S3S	) ((( 		GGGOdii6M6MOOPPPPQQQKLLLJKKK$  VdjjllVVV   
 	%$$$$$&&'1	$$&&(2	&&((I5	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
( 2133--//4466#3#Oy#OK  	 = = ? ? 	00222GGG 	 7 7 9 9 	%%'''GGG n	Q :$H$H$J$J ://	::::JDQQ ::' 2'))))" 2'))))$ 2>>>>>>'//1112 + + + RSSS #A 1 1 3 3 + +k4kk****+ + + + +3 ? ? ?
   8Q 8 899933I>>>>>>>>  : : : 8Q 8 899999999:):,  U	Q 8$H$H$J$J 8//8888=tDD 88' 0%" 0%$ 0>>>>>>'--///2 + + + PQQQ #A 1 1 3 3 + +k4kk****+ + + + +3 = = = 61 6 677733G<<<<<<<<  8 8 8 61 6 6777777778!8$ & @	Q ,$ ,$+fhfff  -F$Q&*O"'K%*N' .7W7W^c7d7d7d4" .'e4444&* ?>>>>>'//e/<<<&*)-GGG" @> @mLfhl>m>m @@/ 0 -_5P Q Q Q Q Q!* 0 -: 3 3 3'(XYYY(+A(9(9(;(; 3 3 %k4kk 2 2 2 23 3 3 3 3; E E E'(>1(>(>???;;GDDDDDDDD( @ @ @'(>1(>(>????????@  Q Q Q 8Q 8 8999OPPPPPPPPQ LMMM# dbcccDEEEE555555|~~ 	QIJJJ[\\\2QRRRGHHHLMMMMIJJJOPPP:y| |s   6Q S,ARS,SS,S''S,6U W;AV&&W;.WW;W66W;%A+] Z1 0] 1]6A\ ;]  ]\*%] *]7]	] ]] 
^!!^^first_installc                 ,    ddl m}  |||            dS )u  Configure tools — delegates to the unified tools_command() in tools_config.py.

    Both `hermes setup tools` and `hermes tools` use the same flow:
    platform selection → toolset toggles → provider/API key configuration.

    Args:
        first_install: When True, uses the simplified first-install flow
            (no platform menu, prompts for all unconfigured API keys).
    r   )tools_command)r;  r   N)hermes_cli.tools_configr=  )r   r;  r=  s      r   setup_toolsr?  
  s1     655555Mf======r   c                    	 ddl m}  |            rdS n# t          $ r Y nw xY w	 ddl m} n# t          $ r i }Y nw xY wdt          fd}t          | t                    r|                     d          nd}t          |t                    ro|                    d	          pd
                                	                                }||v r |||                   rdS |dk    rdD ]}t          |          r dS dD ]}t          |          r dS |                                D ]\  }}|dk    r ||          r dS dS )u  Return True when any known inference provider has usable credentials.

    Sources of truth:
      * ``PROVIDER_REGISTRY`` in ``hermes_cli.auth`` — lists every supported
        provider along with its ``api_key_env_vars``.
      * ``active_provider`` in the auth store — covers OAuth device-code /
        external-OAuth providers (Nous, Codex, Qwen, Gemini CLI, ...).
      * The legacy OpenRouter aggregator env vars, which route generic
        ``OPENAI_API_KEY`` / ``OPENROUTER_API_KEY`` values through OpenRouter.
    r   get_active_providerTr&   r   c                 L    | j         D ]}|dk    r	t          |          r dS dS )NCLAUDE_CODE_OAUTH_TOKENTF)api_key_env_varsrZ   )r,   env_vars     r   _has_keyz0_model_section_has_credentials.<locals>._has_key
  sF    / 	 	G 333W%% ttur   r   Nr   rJ   r%   )r   r   r;   F)r*   rB  rn   r'   rl   r   r   r   r   rK   rZ   r   )	r   rB  r'   rG  	model_cfgprovider_idrF  pidr,   s	            r   _model_section_has_credentialsrK  
  s   777777   	4	   5555555   T     (2&$'?'?I

7###TI)T""   }}Z006B==??EEGG+++x)+677 t,&&C     ))  44  <  !! 	44	 *//11  W )8G 	44	5s    
""- <<r  c                 f    |                      dd          d                                         }|p| S )zFStrip trailing parenthetical qualifiers from a gateway platform label.(ry   r   )r  r   )r  bases     r   _gateway_platform_short_labelrO  
  s0    ;;sAq!''))D=5r   section_keyc                    |dk    rt          |           sdS |                     d          }t          |t                    r(|                                r|                                S t          |t
                    r9t          |                    d          p|                    d          pd          S dS |dk    rt          | ddd          }d	| S |d
k    rt          | d
dd          }d| S |dk    r7ddlm}m	 fd |            D             }|rd
                    |          S dS |dk    rg }t          d          r|                    d           t          d          r|                    d           t          d          r|                    d           |rd
                    |          S dS dS )a)  Return a short summary if a setup section is already configured, else None.

    Used after OpenClaw migration to detect which sections can be skipped.
    ``get_env_value`` is the module-level import from hermes_cli.config
    so that test patches on ``setup_mod.get_env_value`` take effect.
    r   Nr   r  r   r   r  r   z	backend: rH   r`  r_  zmax turns: gatewayr   )r  r  c                 n    g | ]1} |          r$ |          d k    t          |d                   2S )r  r  )rO  )r   r+  r  s     r   r   z/_get_section_config_summary.<locals>.<listcomp>  s[     
 
 
%%
 +;*:4*@*@DT*T*T *$w-88*T*T*Tr   r   r   r   zTTS/ElevenLabsBROWSERBASE_API_KEYBrowserFIRECRAWL_API_KEY	Firecrawl)rK  r   r   r   r   r   rQ   r  r  r  r   rZ   r   )	r   rP  r   r   r`  r  r  r   r  s	           @r   _get_section_config_summaryrX  
  s    g-f55 	4

7##eS!! 	!ekkmm 	!;;== eT"" 	Suyy++Quyy/A/AQ\RRR|	
	"	"&*iIII$7$$$			FG["EEE	(Y(((			!	!GGGGGGGG

 
 
 
&((
 
 


  	)99Z(((t			-.. 	+LL)***.// 	$LL###,-- 	&LL%%% 	$99U###t4r   c                     t          | |          }|sdS t                       t          d| d|            t          d|                                 dd           S )zShow an already-configured section summary and offer to skip.

    Returns True if the user chose to skip, False if the section should run.
    Fr   rx   z  Reconfigure ?r   )rX  r`   rf   r   rK   )r   rP  r  summarys       r   _skip_configured_sectionr\     sr     *&+>>G u	GGG)u))))***>ekkmm>>>NNNNNr   zoptional-skills	migrationzopenclaw-migrationscriptszopenclaw_to_hermes.pyc                     t                                           sdS t          j                            dt                     } | | j        dS t          j                            |           }ddl}||j        | j	        <   	 | j        
                    |           n/# t          $ r" |j                            | j	        d            w xY w|S )zLoad the openclaw_to_hermes migration script as a module.

    Returns the loaded module, or None if the script can't be loaded.
    Nopenclaw_to_hermesr   )_OPENCLAW_SCRIPTr[  r  r  spec_from_file_locationloadermodule_from_specrk   modulesr   exec_modulern   r  )specmod_syss      r   _load_openclaw_migration_modulerj  =  s    
 ""$$ t>11. D |t{*t
.
)
)$
/
/C !DL$$$$   D))) Js   ?B ,Cu\   ⚠ Gateway/messaging — this will configure Hermes to use your OpenClaw messaging channelsuE   ⚠ Telegram — this will point Hermes at your OpenClaw Telegram botuE   ⚠ Slack — this will point Hermes at your OpenClaw Slack workspaceuC   ⚠ Discord — this will point Hermes at your OpenClaw Discord botuL   ⚠ WhatsApp — this will point Hermes at your OpenClaw WhatsApp connectionuM   ⚠ Config values — OpenClaw settings may not map 1:1 to Hermes equivalentsuO   ⚠ Instruction file — may contain OpenClaw-specific setup/restart proceduresuJ   ⚠ Memory/context file — may reference OpenClaw-specific infrastructureu?   ⚠ Context file — may contain OpenClaw-specific instructions)	rR  telegramslackdiscordwhatsappr   soulmemorycontextreportc                 4   |                      dg           }|st          d           dS d |D             }d |D             }d |D             }t                      }|rEt          t	          dt
          j                             |D ]}|                     dd	          }|                     d
d          }|rXt          |                              t          t          j
                              d          }	t          d|dd|	            nt          d|            |                                }
t          |                                          }t                                          D ]"\  }}||
v s||v r|                    |           #t                       |r|t          t	          dt
          j                             |D ]D}|                     dd	          }|                     dd          }t          d|dd|            Et                       |r|t          t	          dt
          j                             |D ]D}|                     dd	          }|                     dd          }t          d|dd|            Et                       |rt          t	          dt
          j                             t#          |          D ],}t          t	          d| t
          j                             -t                       t          t	          dt
          j                             t          t	          dt
          j                             t          t	          dt
          j                             t                       dS dS )zPrint a detailed dry-run preview of what migration would do.

    Groups items by category and adds explicit warnings for high-impact
    changes like gateway token takeover and config value differences.
    r   zNothing to migrate.Nc                 D    g | ]}|                     d           dk    |S )r   migratedr   r   r   s     r   r   z,_print_migration_preview.<locals>.<listcomp>t  ,    HHHA!%%//Z*G*Ga*G*G*Gr   c                 D    g | ]}|                     d           dk    |S )r   conflictrv  rw  s     r   r   z,_print_migration_preview.<locals>.<listcomp>u  rx  r   c                 D    g | ]}|                     d           dk    |S )r   skippedrv  rw  s     r   r   z,_print_migration_preview.<locals>.<listcomp>v  s,    FFF1xI)E)EQ)E)E)Er   z  Would import:kindunknowndestinationrJ   ~r   z<22s    → z:  Would overwrite (conflicts with existing Hermes config):rp   zalready existsr   z  Would skip:u     ── Warnings ──z    zF  Note: OpenClaw config values may have different semantics in Hermes.uM     For example, OpenClaw's tool_call_execution: "auto" ≠ Hermes's yolo mode.zL  Instruction files (.md) from OpenClaw may contain incompatible procedures.)r   re   r   r`   r]   r\   r   r   r  r   r.  rK   _HIGH_IMPACT_KIND_KEYWORDSr   addr{   r   r   )rr  r   migrated_itemsconflict_itemsskipped_itemswarnings_shownitemr}  dest
dest_short
kind_lower
dest_lowerkeywordwarningrp   s                  r   _print_migration_previewr  i  s    JJw##E ()))HHHHHNHHHHHNFFFFFMUUN e%v|44555" 	0 	0D88FI..D88M2..D ' YY..s49;;/?/?EE
;t;;;z;;<<<<otoo&&& JT**J$>$D$D$F$F 0 0 j((Gz,A,A"&&w///0 	 ePRXR_``aaa" 	2 	2D88FI..DXXh(899F04000001111 eOVZ00111! 	2 	2D88FI..DXXh++F04000001111  e.>>???n-- 	: 	:G%(w((&-889999e\^d^kllmmmeegmgtuuvvvebdjdqrrsss r   r	  c                 	   t          j                    dz  }|                                sdS t                                          sdS t                       t          d           t          d|            t          d           t                       t          dd          st          d	           dS t                      }|                                st          t                                 	 t                      }|t          d           dS nF# t          $ r9}t          d|            t                              dd           Y d
}~dS d
}~ww xY w	 |                    d
d
d          }|                    |                                |                                 dd
ddd
|d	  	        }|                                }nF# t          $ r9}t          d|            t                              dd           Y d
}~dS d
}~ww xY w|                    di           }|                    dd          }	|	dk    rt                       t          d           dS t                       t          d|	 d           t          d           t                       t-          |           t          dd          s t          d           t          d           dS 	 |                    |                                |                                 dd
ddd
|d	  	        }
|
                                }nF# t          $ r9}t          d|            t                              dd           Y d
}~dS d
}~ww xY w|                    di           }|                    dd          }|                    d d          }|                    d!d          }|                    d"d          }t                       |rt/          d#| d$           |rt          d%| d&           |rt          d%| d'           |rt          | d(           |                    d)          }|rt          d*|            t/          d+           dS ),a  Detect ~/.openclaw and offer to migrate during first-time setup.

    Runs a dry-run first to show the user exactly what would be imported,
    overwritten, or taken over. Only executes after explicit confirmation.

    Returns True if migration ran successfully, False otherwise.
    z	.openclawFzOpenClaw Installation DetectedzFound OpenClaw data at zDHermes can preview what would be imported before making any changes.z+Would you like to see what can be imported?Tr   zLSkipping migration. You can run it later with: hermes claw migrate --dry-runNz Could not load migration script.z!Could not load migration script: z$OpenClaw migration module load error)exc_infofull)preset)	source_roottarget_rootexecuteworkspace_target	overwritemigrate_secrets
output_dirselected_optionspreset_namezMigration preview failed: z OpenClaw migration preview errorr[  ru  r   z Nothing to import from OpenClaw.u   Migration Preview — z item(s) would be importedz5No changes have been made yet. Review the list below:zProceed with migration?zCMigration cancelled. You can run it later with: hermes claw migratezIUse --dry-run to preview again, or --preset minimal for a lighter import.zMigration failed: zOpenClaw migration errorr|  rz  errorz	Imported z item(s) from OpenClaw.zSkipped zU item(s) that already exist in Hermes (use hermes claw migrate --overwrite to force).z" item(s) (not found or unchanged).u3    item(s) had errors — check the migration report.r  zFull report saved to: z,Migration complete! Continuing with setup...)r   r.  is_dirra  r[  r`   rc   re   r   rT   rW   rV   rj  rg   rn   r  r  resolve_selected_optionsMigratorrW  migrater   r  rf   )r	  openclaw_dirconfig_pathrh  r  r   dry_migratorpreview_reportpreview_summarypreview_countmigratorrr  r[  ru  r|  	conflictserrorsr  s                     r   _offer_openclaw_migrationr    s4    9;;,L   u""$$ u	GGG1222777888UVVV	GGGFPTUUU Z	
 	
 	
 u "##K #KMM"""-//;<===5     =!==>>>;dKKKuuuuu//d6/JJ||$,,..#++--! % $ 

 

 &--//   61667777$GGGuuuuu %((B77O#''
A66M5666u	GGGS-SSSTTTFGGG	GGG^,,, 2EBBB Q	
 	
 	
 	W	
 	
 	
 u<<$,,..#++--! %   

 

 !!##   .1..////$???uuuuu jjB''G{{:q))Hkk)Q''GJ**I[[!$$F	GGG EC(CCCDDD @~i~~~ KIgIIIJJJ VTTTUUUL))J :8J88999@AAA4sJ   4D 
E .EEA.G 
H.H

H"AL9 9
M<.M77M<r   Model & Providerr   zText-to-Speechr   r  rR  zMessaging Platforms (Gateway)r   ToolsrH   rq  c                    ddl m}m}  |            r |d           dS t                       t	          t          | dd                    }|r5t          t          j        t                               t          d           t	          t          | dd                    }t	          t          | d	d                    }t                      }t                      }t                      }|                                rldd
lm}	 |                    d|	                                                    d                     }
	 ddl} |j        ||
           n# t*          $ r d}
Y nw xY wd}
t          | dd          }|st-                      sd}|rt/          d           dS t          | dd          }|r!t0          D ]\  }}}||k    rt3                       t3          t5          dt6          j                             t3          t5          d|ddt6          j                             t3          t5          dt6          j                              ||           t          |           t3                       t          | d            dS t;          d|            t=          dd                    d t0          D                                   dS ddl m!}  |            }t	          tE          d                    pt	          tE          d                    p|du}t3                       t3          t5          dt6          j                             t3          t5          dt6          j                             t3          t5          dt6          j                             t3          t5          d t6          j                             t3          t5          d!t6          j                             t3          t5          dt6          j                             d}|r|rtG          ||           dS t3                       tI          d"           t          d#           t=          d$           t=          d%           t=          d&           t=          d'           t=          d(           nzt3                       |s|rt=          d)           t3                       tK          |          }|rt                      }tM          d*d+d,gd          }|dk    rtO          |||           dS tI          d-           t=          d.t                                  t=          d/tQ                                  t=          d0|            t=          d1tR                      t3                       t=          d2           |r;t3                       t=          d3           t=          d4           t=          d5           |rtU          |d6d7          stW          |           |rtU          |d8d9          stY          |           |rtU          |d:d;          st[          |           |rtU          |d<d=          st]          |           |rtU          |d>d?          st_          || @           t          |           |
rJ|
                                r6t=          dA|
            t=          dB           t=          dC|
 dD|            ta          ||           dS )Eu  Run the interactive setup wizard.

    Supports full, quick, and section-specific setup:
      hermes setup           — full or quick (auto-detected)
      hermes setup model     — just model/provider
      hermes setup tts       — just text-to-speech
      hermes setup terminal  — just terminal backend
      hermes setup gateway   — just messaging platforms
      hermes setup tools     — just tool configuration
      hermes setup agent     — just agent settings
    r   )
is_managedmanaged_errorzrun setup wizardNresetFz Configuration reset to defaults.reconfigurerf  )datetimez
.yaml.bak.z%Y%m%d_%H%M%Snon_interactiveTz;Running in a non-interactive environment (no TTY detected).sectionr   u   │     ⚕ Hermes Setup — z<34su    │r   z configuration complete!zUnknown setup section: zAvailable sections: r   c              3   "   K   | ]
\  }}}|V  d S r  r   )r   kr   s      r   r   z#run_setup_wizard.<locals>.<genexpr>  s(      3T3T'!QA3T3T3T3T3T3Tr   rA  r   OPENAI_BASE_URLu@   │             ⚕ Hermes Agent Setup Wizard                │u   ├─────────────────────────────────────────────────────────┤u>   │  Let's configure your Hermes Agent installation.       │u>   │  Press Ctrl+C at any time to exit.                     │Reconfigurez#You already have Hermes configured.uA   Running the full wizard — each prompt shows your current value.z9Press Enter to keep it, or type a new value to change it.rJ   zBTip: jump straight to a section with 'hermes setup model|terminal|zC     gateway|tools|agent', or fill only missing items with --quick.u=   No existing configuration found — running first-time setup.z$How would you like to set up Hermes?u9   Quick setup — provider, model & messaging (recommended)u#   Full setup — configure everythingzConfiguration LocationzConfig file:  zSecrets file: zData folder:  zInstall dir:  z=You can edit these files directly or use 'hermes config edit'z%Settings were imported from OpenClaw.uG   Each section below will show what was imported — press Enter to keep,z#or choose to reconfigure if needed.r   r  r   r  rH   rq  rR  r  r   r  )r;  zPrevious config backed up to: z9If setup changed a value you customized, restore it with:z  cp r   )1r  r  r  r[   rl   rj   rW   copydeepcopyrR   rf   rV   rS   rT   r[  r  with_suffixnowstrftimer  copy2rn   ro   rr   SETUP_SECTIONSr`   r]   r\   MAGENTArd   re   r   r*   rB  rZ   _run_quick_setuprc   r  r   _run_first_time_quick_setuprU   PROJECT_ROOTr\  r  r]  r  r:  r?  r   )argsr  r  reset_requestedreconfigure_requestedquick_requestedr   r	  r  _dt_backup_pathr  r  r  rT  r  funcrB  active_provideris_existingmigration_ran
setup_modes                         r   run_setup_wizardr  <  s    <;;;;;;;z|| ()))74%8899O :DM.112228999 }e!D!DEE74%8899O]]F!##K "##K ,,,,,,"..>++O<<>>
 
	 MMMFLl3333 	  	  	 LLL	   d$5u==O #7#9#9  +I	
 	
 	
 	 dIt,,G  . 	 	Cg~~ L    eLELLLLfn]]^^^ L    VF###@@@AAA' * 	7g77888V$))3T3T^3T3T3T*T*TVVWWW 433333))++O]/0011 	'/0011	'$&  
GGG	 @N	
 	
   
NPVP^	
 	
  
 
 @N	
 	
   
Lfn	
 	
  
 
Lfn	
 	
  
 
 @N	
 	
   M +  	V[111F]###;<<<VWWWNOOO2WXXXXYYYY 	 ! 	O 	VWWWGGG 2+>> 	# ]]F"#IG1L
  

 ??'[IIIF )***3 1 133444000111---......///	GGGNOOO ::;;;\]]]8999  %6vwHZ[[ %V$$$  '6vzK]^^ 'v&&&  %6vwHXYY %V$$$  6vyJ_`` f  ;6vwPP ;Fk/::::  9++-- 9BLBBCCCNOOO7<77+77888-----s   E E&%E&r  c                    t          | d           t          |            t          |            t          |            t	                       t          dddgd          }|dk    rt          |            t          |            t	                       t          d           t	                       t          d           |dk    rt          d	           t	                       t          | |           d
S )u   Streamlined first-time setup: provider, model, terminal & messaging.

    Applies sensible defaults for TTS (Edge), agent settings, and tools —
    the user can customize later via ``hermes setup <section>``.
    Tre  z7Connect a messaging platform? (Telegram, Discord, etc.)z"Set up messaging now (recommended)u1   Skip — set up later with 'hermes setup gateway'r   z#Setup complete! You're ready to go.z)  Configure all settings:    hermes setupz1  Connect Telegram/Discord:  hermes setup gatewayN)
r  r]  ro  rW   r`   r   r:  rf   re   r   )r   r	  r  gateway_choices       r   r  r    s    t,,,, 6""" "&))) 
GGG"A0?	
 	
 N fF	GGG7888	GGG:;;;FGGG	GGG-----r   c           
         ddl m}m}m} t	                       t          d           d  |d          D             }d  |d          D             } |            } |            \  }}	|p	|p|p||	k     }
|
s=t          d           t	                       t          d	           t          d
           dS |rt	                       t          t          |           d           |D ]}t	          d|d                     t	                       |D ]N}t	                       t	          t          d|d          t          j                             t          d|                    dd                      |                    d          rt          d|d                     |                    d          r/t          d|                    d|d                    d          }n,t          d|                    d|d                              }|r0t          |d         |           t          d|d                     6t          d|d                     Pd |D             }d |D             }|rt	                       t          d           g }|D ]o}|                    dg           }|r dd                    |dd                     nd}|                    |                    d|d                    |            pt%          d!|          }|D ]}||         }t'          |           |rJt	                       t          d"           t          d#           t          d$           g }i }|D ]b}|d         }d%|v rd&}nd'|v rd(}nd)|v rd*}n ||vr|                    |           |                    |g                               |           cd+ |D             }t%          d,|          }|D ]}||         }||         }d-d.d/d0                    |d          }t	                       t	          t          d1| d2| d3t          j                             t	                       |D ]}t          d|                    dd                      |                    d          rt          d|d                     |                    d          r/t          d|                    d|d                    d          }n,t          d|                    d|d                              }|r&t          |d         |           t          d4           nt          d5           t	                       |rht	                       t          d6t          |           d7           |D ]#}t          d8|d9          d:|d;                     $|	| d<<   t+          |            t-          | |           dS )=u6   Quick setup — only configure items that are missing.r   )get_missing_env_varsget_missing_config_fieldscheck_config_versionu"   Quick Setup — Missing Items Onlyc                 <    g | ]}|                     d           |S is_requiredrv  r   vs     r   r   z$_run_quick_setup.<locals>.<listcomp>O  s9       m@T@T	  r   F)required_onlyc                 <    g | ]}|                     d           |S r  rv  r  s     r   r   z$_run_quick_setup.<locals>.<listcomp>R  s9       AEE-DXDX	  r   z(Everything is configured! Nothing to do.z:Run 'hermes setup' and choose 'Full Setup' to reconfigure,z)or pick a specific section from the menu.Nz required setting(s) missing:u	        • r   r   r   rJ   r   z  Get key at: rt   r   Tr   z  Saved z
  Skipped c                 D    g | ]}|                     d           dk    |S )categorytoolrv  r  s     r   r   z$_run_quick_setup.<locals>.<listcomp>  s.    PPP1AEE*4E4E4O4OQ4O4O4Or   c                 n    g | ]2}|                     d           dk    |                     d          0|3S )r  	messagingadvancedrv  r  s     r   r   z$_run_quick_setup.<locals>.<listcomp>  sJ       55++AEE*4E4E+ 	
+++r   zTool API Keysr   r  r   r~  z(Which tools would you like to configure?r  z7Connect Hermes to messaging apps to chat from anywhere.z:You can configure these later with 'hermes setup gateway'.TELEGRAMr  DISCORDr  SLACKr  c                 B    g | ]}d ddd                     ||          S )u   📱 Telegramu   💬 Discordu
   💼 Slackr  r  r  rv  )r   r  s     r   r   z$_run_quick_setup.<locals>.<listcomp>  sI     
 
 
 	 ,)%  c!Qii
 
 
r   z)Which platforms would you like to set up?u   📱u   💬u   💼r  r   r   r   r   z	  SkippedzAdding z& new config option(s) with defaults...z  Added rT  z = r   _config_version)r  r  r  r  r`   rc   rf   re   r   r]   r\   ra   r   r   rX   rg   r   r   r   r   r,  rW   r   )r   r	  r  r  r  missing_requiredmissing_optionalmissing_configcurrent_ver
latest_verhas_anything_missingr   r   missing_toolsmissing_messagingchecklist_labelsr   r   selected_indicesr   platform_orderr*  r   r+  platform_labels	vars_listr  fields                               r   r  r  C  s}             
GGG5666 ''e<<<   ''e<<<   /.00N2244K 	 	$	$	$ #	    @AAAOPPP>???  :c*++JJJKKK# 	- 	-C+c&k++,,,,# 	: 	:CGGG%*S[**FK889998CGGM26688999wwu~~ :8CJ88999wwz"" FDCGGHc&k$B$BDDtTTTDCGGHc&k$B$BDDEE :s6{E2226V66777783v;889999 QP 0PPPM !    !_%%%  	Y 	YCGGGR((E:?G6		%) 4 4666RI##sww}c&k'J'J$WI$W$WXXXX+6
 

 $ 	! 	!C$CC      9*+++LMMMOPPP 	$ 	7 	7Cv;DT!!!d"" D9$$%%d+++  r**11#6666
 
 $
 
 
 ,7
 

 $ 	 	C!#&D!$I!'FVLLPPQUWYZZEGGG%?u??t???MMNNNGGG   <r : :<<===775>> 20CJ0011177:&& J"#H#f+(F(F#H#HSWXXXEE"#H#f+(F(F#H#HIIE /"3v;666!-0000!+...   
Qc.))QQQ	
 	
 	
 $ 	J 	JEHU5\HHeI6FHHIIII %/ !F -----r   r  )NF)r   N)T)F)t__doc__r  r  r\  loggingr6  r  r  rk   r  pathlibr   typingr   r   r   hermes_cli.nous_subscriptionr   r0  r   utilsr	   r  r
   	getLogger__name__r  __file__rY  rW  r  r  r   r   r   r"   rl   r-   _DEFAULT_PROVIDER_MODELSrM   rP   r  rQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   r[   hermes_cli.colorsr\   r]   rc   hermes_cli.cli_outputrd   re   rf   rg   ro   rr   r   compiler   r}   listr   r   r   r   r   r   r   r   r7  rM  rE  r  r  r  r  r  r  r  r  r]  ro  r  r  r  r  r  r  r  r  r  r  r  r:  r?  rK  rO  rX  r\  ra  rj  r  r  r  r  r  r  r  r   r   r   <module>r     s
          				 				  



        & & & & & & & & & & G G G G G G A A A A A A # # # # # # 4 4 4 4 4 4		8	$	$tH~~$+33559
tCH~ $sCx.    DDcN DtCH~ D D D D
6$sCx. 6C 6SV 6[_ 6 6 6 6
A 
A 
A 
A 
A 
A" 	     GFFZZZ]]] "78PPPMMMPPPwww _  _  _}}}       E' ' Td38n     +$sCx. +# +$ + + + +                          , + + + + + + +; ; ; ; ;           d     d
 d    & S 3  #    , &2:&DEE 3# 3# 3 3 3 3m mC m$ m mWZ]aWa mmp m m m m( (C ($ ( (sUYz (eh ( ( ( (V/ /C /$ /$ / / / /0 C  D D    :I I I I I8W W W W Wt' ' ' ' 'TB/D B/ B/ B/ B/J t tCH~    J 9> Y$ Y$ Y$ Y$ Y$ Y$ Y$ Y$BW$ W W W W
/d / / / /d    2    # # # # #LjU jU jU jU jUZ d        hB4 hB hB hB hB`A$ A A A A:i i i i ibDB DB DBN3= 3= 3=l     AC AC ACH(
 (
 (
VS: S: S:l)E )E )EX>V >V >VB  ,E ,E ,E^h$ h h h h`> > >T > > > >(;4 ;D ; ; ; ;|     4 43 48C= 4 4 4 4nOO"O+.O	O O O O* L+<<==  	   @ nWTT^]]ZP
 
 =T = = = =@B4 BD B B B BT  "67
i(#%;</?g{# 45Y. Y. Y.x(. (. (. (. (. (.Vc.T c. c. c. c. c. c.r   