+
    i             $         a  ERR t]0 t R t^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	H
t
 ^ RIHt ^ RIHtHtHtHtHt ^ RIHt ]P,                  ! 4       R8H  t]P0                  ! R4      t]! 0 RkR	kR
kRkRkRkRkRkRkRkRkRkRkRkRkRkRkRkRkRkRkRkRkRkR kR!kR"kR#kR$kR%kR&kR'kR(k4      t^ RIt^ R)IHtHt ^ R*I H!t! ERSt"R+R,R-R,R.R/R0R//t#R1 R2 lt$R3 R4 lt%R5 R6 lt&R7 R8 lt'ERTR9 R: llt(ERUR; R< llt)^ R=I*H+t+ R> R? lt,R@ RA lt-RB RC lt.RD t/RE t0RF RG lt1RH t2/ RIRJbRK/ bRL. bRM/ bRNRO.bRPRQ^ZRRRSRTRU/bRV/ RWRXbRYRUbRZR[bR\^bR]. bR^R_bR`. bRa/ bRbRcbRdR_bReR_bRf^bRgRhbRiRjbRkRlbRm. bRnRobRpRl/CbRqRr^xRs^RtRoRuRoRvRwRo//bRxRyRlRz^2/bR{R|bR}RyRlR~RRRR^RRJRRURR/bRRyRoR^R^R/ /bRRRRURIRJRRJRRJR\^R^/RRRURIRJRRJRRJR\R/R}RRURIRJRRJRRJR\^x/RRRURIRJRRJRRJR\^/RRRURIRJRRJRRJR\^/RRRURIRJRRJRRJR\^/RRRURIRJRRJRRJR\^/RRRURIRJRRJRRJR\^//bRRRoRRRRRRRRoRRoRRoRRlRRoRRRRoR^ /bRRRo/bRRRRRR/RRRRR/RRIRRR/RRRJRRJRIRRR//bRRyRlRRXRXRIR/RRIR//b/ RRRR^xRRoR^RR/bRRRRRRR/bRRRlRRlRRRRRRJ/bRRIRJRRJRRJRRJR^2/bRRJbRR. /bR/ bRRJbRRRlRRJRRlRRl/bR/ bRRRR\^</bR. bR/ bR/ bRRRlRRlRRR^RRlRRyRoR. R. //bRRRl/bRRRR^R^/bCR^/Ct3^. ERVO^RR.^. ERWO^
ER .^ER./t4] ^ k / t5/ ERERERERERERRERRoER	RER
Rl/bERERERERERERERERRlERERER.ER	RER
Rl/bERERERERERERERERRlER	RER
Rl/bERERERERERERERERRlER	RER
Rl/bERERERERERERRERRoER	RER
Rl/bERERERERERERERERRlER	RER
Rl/bER ERER!ERER"ERERERRlER	RER
Rl/bER#ERER!ERER"ERERERRlER	RER
Rl/bER$ERER%ERER&ERRERRoER	RER
Rl/bER'ERER(ERER)ERER*ERRlER	RER
Rl/bER+ERER,ERER-ERRERRoER	RER
Rl/bER.ERER/ERER0ERER1ERRlER	RER
Rl/bER2ERER3ERER4ERRERRoER	RER
Rl/bER5ERER6ERER7ERER8ERRlER	RER
Rl/bER9ERER:ERER;ERRERRoER	RER
Rl/bER<ERER=ERER>ERER?ERRlER	R/bER@ERERAERERBERRJERRoER	R/b/ ERCERERDEREREERERFERRlER	R/bERGERERHERERIERRJERRoER	RER
Rl/bERJERERKERERLERERMERRlER	RER
Rl/bERNEREROERERPERRERRoER	RER
Rl/bERQERERRERERSERERMERRlER	RER
Rl/bERTERERUERERVERRERRoER	RER
Rl/bERWERERXERERYERERZERRlER	R/bER[ERER\ERER]ERRERRoER	RER
Rl/bER^ERER_ERER`ERERaERERbR.ERRlER	ERc/bERdEREReERERfERERgERERbR.ERRlER	ERc/bRERERhERERiERERjERERbR.ERRlER	ERc/bERkERERlERERmERRERRoER	ERcER
Rl/bERnERERoERERpERRERRoER	ERcER
Rl/bERqERERrERERsERRERRoER	ERcER
Rl/bERtERERuERERvERRERRoER	ERcER
Rl/bERwERERxERERyERRERRlER	ERcER
Rl/bER ERERzERER{ERER|ER. ERXOERRlER	ERc/bC/ RERER}ERER~ERERERERER.ERRlER	ERc/bRERERERERERERERERER.ERRoER	ERc/bERERERERERERERERERER.ERRlER	ERc/bERERERERERERERER.ERRoER	ERc/bERERERERERERERERERER.ERRoER	ERc/bRERERERERERERERER.ERRlER	ERc/bERERERERERERERER. ERYOERRlER	ERc/bERERERERERERERERERER.ERRlER	ERc/bRERERERERERERERERER.ERRlER	ERc/bRERERERERERERERRlER	ERc/bERERERERERERERERRlER	ERc/bERERERERERERERERER.ERRlER	ERc/bERERERERERER	ERc/bERERERERERERERERRlER	ER/bERERERERERERERERRoER	ER/bERERERERERERERERRlER	ER/bERERERERERERRERRoER	ER/bC/ RERERERERERERERRlER	ER/bRERERERERERERERRlER	ER/bERERERERERERERERRoER	ER/bERERERERERERRERRlER	ER/bERERERERERERRERRoER	ER/bERERERERERERRERRoER	ER/bERERERERERERRERRoER	ER/bERERERERERERERERRoER	ER/bERERERERERERRERRlER	ER/bERERERERERERRERRoER	ER/bERERERERERERRERRoER	ER/bR&ERERERERERRERRoER	ERER
Rl/bR'ERERERERERRERRoER	ERER
Rl/bR(ERERERERERRERRoER	ERER
Rl/bR$ERERERERERRERRoER	ERER
Rl/bERERERERERERRERRoER	ERER
Rl/bERERERERERERRERRoER	ERER
Rl/bCERERERERERERRERRlER	ERER
Rl/ERERERERERERRERRoER	ERER
Rl/ERERERERERERRERRoER	ERER
Rl/ERERERERERERRERRoER	ER/ERERERERERERRERRoER	ER/ER ERERERERERRERRlER	ER/ERERERERERERRERRoER	ER/ERERERERER	ERRERRlER	ER/ER
ERERERERERRERRoER	ER/ERERERERERERRERRoER	ER/ERERERERERERRERRoER	ER/ERERERERERERRERRoER	ER/ERERERERERERRERRoER	ER//Ct6]! 4       '       g   ERZ F  t7]6Pq                  ]7R4       K  	  ER[ER ER llt9ER ER lt:ER ER lt;ER ER lt<ER  ER! lt=0 ER\mt>0 ER]mt?0 ER^mt@]
 ! ER" ER#4      4       tAER_ER$ ER% lltBER_ER& ER' lltCER`ER( ER) lltDER* ER+ ltEER, tFER- ER. ltGER/ ER0 ltHER1 ER2 ltIER3tJER4tKER5tLER6 ER7 ltMER8 ER9 ltNER: ER; ltOER< ER= ltPER> ER? ltQER@ ERA ltRER_ERB ERC lltSER_ERD ltTER_ERE ERF lltUERG ERH ltVERI ERJ ltWERK ERL ltXERM tYERN tZERO ERP lt[ERQ t\R# (a  a  
Configuration management for Hermes Agent.

Config files are stored in ~/.hermes/ for easy access:
- ~/.hermes/config.yaml  - All settings (model, toolsets, terminal, etc.)
- ~/.hermes/.env         - API keys and secrets

This module provides:
- hermes config          - Show current configuration
- hermes config edit     - Open config in editor
- hermes config set      - Set a specific value
- hermes config wizard   - Re-run setup wizard
N)	dataclassPath)DictAnyOptionalListTuple)managed_nous_tools_enabledWindowsz^[A-Za-z_][A-Za-z0-9_]*$OPENAI_API_KEYOPENAI_BASE_URLANTHROPIC_API_KEYANTHROPIC_TOKENAUXILIARY_VISION_MODELDISCORD_HOME_CHANNELTELEGRAM_HOME_CHANNELSIGNAL_ACCOUNTSIGNAL_HTTP_URLSIGNAL_ALLOWED_USERSSIGNAL_GROUP_ALLOWED_USERSDINGTALK_CLIENT_IDDINGTALK_CLIENT_SECRETFEISHU_APP_IDFEISHU_APP_SECRETFEISHU_ENCRYPT_KEYFEISHU_VERIFICATION_TOKENWECOM_BOT_IDWECOM_SECRETTERMINAL_ENVTERMINAL_SSH_KEYTERMINAL_SSH_PORTWHATSAPP_MODEWHATSAPP_ENABLEDMATTERMOST_HOME_CHANNELMATTERMOST_REPLY_MODEMATRIX_PASSWORDMATRIX_ENCRYPTIONMATRIX_DEVICE_IDMATRIX_HOME_ROOMMATRIX_REQUIRE_MENTIONMATRIX_FREE_RESPONSE_ROOMSMATRIX_AUTO_THREAD)Colorscolor)DEFAULT_SOUL_MDbrewHomebrewhomebrewnixNixOSnixosc                :    V ^8  d   QhR\         \        ,          /#    returnr   str)formats   "./home/ubuntu/hermes-agent/hermes_cli/config.py__annotate__r>   C   s      HSM     c                    \         P                  ! RR4      P                  4       p V '       d3   V P                  4       pV\        9   d   R# \
        P                  W4      # \        4       R,          pVP                  4       '       d   R# R# )z7Return the package manager owning this install, if any.HERMES_MANAGED r4   z.managedN)	osgetenvstriplower_MANAGED_TRUE_VALUES_MANAGED_SYSTEM_NAMESgetget_hermes_homeexists)raw
normalizedmanaged_markers      r=   get_managed_systemrO   C   si    
))$b
)
/
/
1C
YY[
--$((99$&3Nr?   c                $    V ^8  d   QhR\         /# r7   )bool)r<   s   "r=   r>   r>   R   s     , ,D ,r?   c                     \        4       RJ# )zCheck if Hermes is running in package-manager-managed mode.

Two signals: the HERMES_MANAGED env var (set by the systemd service),
or a .managed marker file in HERMES_HOME (set by the NixOS activation
script, so interactive shells also see it).
NrO    r?   r=   
is_managedrU   R   s     t++r?   c                :    V ^8  d   QhR\         \        ,          /# r7   r:   )r<   s   "r=   r>   r>   \   s      HSM r?   c                 >    \        4       p V R8X  d   R# V R8X  d   R# R# )z;Return the preferred upgrade command for a managed install.r1   zbrew upgrade hermes-agentr4   zsudo nixos-rebuild switchNrS   )managed_systems    r=   get_managed_update_commandrY   \   s#    ')N#* *r?   c                $    V ^8  d   QhR\         /# r7   r;   )r<   s   "r=   r>   r>   f   s     ; ;C ;r?   c                 *    \        4       ;'       g    R# )z<Return the best update command for the current installation.zhermes update)rY   rT   r?   r=   recommended_update_commandr]   f   s    %'::?:r?   c                0    V ^8  d   QhR\         R\         /# )r8   actionr9   r[   )r<   s   "r=   r>   r>   k   s      3 s r?   c                ,   \        4       ;'       g    Rp\        P                  ! RR4      P                  4       P	                  4       pVR8X  d#   V\
        9   d   RMT;'       g    RpRV  RV R2# VR	8X  d   T;'       g    R
pRV  RV R2# RV  RV R2# )z/Build a user-facing error for managed installs.za package managerrA   rB   r4   truezCannot z?: this Hermes installation is managed by NixOS (HERMES_MANAGED=ze).
Edit services.hermes-agent.settings in your configuration.nix and run:
  sudo nixos-rebuild switchr1   r2   zB: this Hermes installation is managed by Homebrew (HERMES_MANAGED=z#).
Use:
  brew upgrade hermes-agentz): this Hermes installation is managed by z:.
Use your package manager to upgrade or reinstall Hermes.)rO   rC   rD   rE   rF   rG   )r_   rX   rL   env_hints   &   r=   format_managed_messagerc   k   s    ')@@-@N
))$b
)
/
/
1
7
7
9C  $886cmmVfX 'j )**	
 #$$*fX 'j )**	
 &B>BR SC 	Cr?   c                $    V ^8  d   QhR\         /# )r8   r_   r[   )r<   s   "r=   r>   r>      s     ; ;# ;r?   c                N    \        \        V 4      \        P                  R7       R# )z+Print user-friendly error for managed mode.)fileN)printrc   sysstderr)r_   s   &r=   managed_errorrj      s    	
 
(szz:r?   rJ   c                $    V ^8  d   QhR\         /# r7   r   )r<   s   "r=   r>   r>      s     - - -r?   c                 $    \        4       R,          # )zGet the main config file path.zconfig.yamlrk   rT   r?   r=   get_config_pathrn      s    },,r?   c                $    V ^8  d   QhR\         /# r7   r   )r<   s   "r=   r>   r>      s     & &d &r?   c                 $    \        4       R,          # )z&Get the .env file path (for API keys).z.envrk   rT   r?   r=   get_env_pathrq      s    v%%r?   c                $    V ^8  d   QhR\         /# r7   r   )r<   s   "r=   r>   r>      s     2 2$ 2r?   c                 d    \        \        4      P                  P                  P                  4       # )z'Get the project installation directory.)r   __file__parentresolverT   r?   r=   get_project_rootrw      s!    >  ''//11r?   c                f     \         P                  ! V R4       R#   \        \        3 d     R# i ; i)z<Set directory to owner-only access (0700). No-op on Windows.i  N)rC   chmodOSErrorNotImplementedErrorpaths   &r=   _secure_dirr~      s-    
u() s    00c                     \         P                  P                  \        V 4      4      '       d   \         P                  ! V R4       R# R#   \
        \        3 d     R# i ; i)z;Set file to owner-only read/write (0600). No-op on Windows.i  N)rC   r}   rK   r;   ry   rz   r{   r|   s   &r=   _secure_filer      sI    77>>#d)$$HHT5! %() s   AA A A c                (    V ^8  d   QhR\         RR/# )r8   homer9   Nr   )r<   s   "r=   r>   r>      s      $ 4 r?   c                    V R,          pVP                  4       '       d   R# VP                  \        RR7       \        V4       R# )zISeed a default SOUL.md into HERMES_HOME if the user doesn't have one yet.zSOUL.mdNutf-8encoding)rK   
write_textr/   r   )r   	soul_paths   & r=   _ensure_default_soul_mdr      s9    y I7;r?   c                     \        4       p V P                  RRR7       \        V 4       R F)  pW,          pVP                  RRR7       \        V4       K+  	  \        V 4       R# )zDEnsure ~/.hermes directory structure exists with secure permissions.T)parentsexist_okN)cronsessionslogsmemories)rJ   mkdirr~   r   )r   subdirds      r=   ensure_hermes_homer      sT    DJJtdJ+:M	t,A ; D!r?   modelrB   	providersfallback_providerscredential_pool_strategiestoolsetsz
hermes-cliagent	max_turnsgateway_timeouti  tool_use_enforcementautoterminalbackendlocal
modal_modecwd.timeoutenv_passthroughdocker_image*nikolaik/python-nodejs:python3.11-nodejs20docker_forward_env
docker_envsingularity_image3docker://nikolaik/python-nodejs:python3.11-nodejs20modal_imagedaytona_imagecontainer_cpucontainer_memoryi   container_diski   container_persistentTdocker_volumesdocker_mount_cwd_to_workspaceFpersistent_shellbrowserinactivity_timeoutcommand_timeoutrecord_sessionsallow_private_urlscamofoxmanaged_persistencecheckpointsenabledmax_snapshotsfile_read_max_charsi compression	threshold      ?target_ratio皙?protect_last_nsummary_modelsummary_providersummary_base_urlsmart_model_routingmax_simple_charsmax_simple_wordscheap_model	auxiliaryvisionproviderbase_urlapi_keydownload_timeoutweb_extractih  session_search
skills_hubapprovalmcpflush_memoriesdisplaycompactpersonalitykawaiiresume_displayfullbusy_input_mode	interruptbell_on_completeshow_reasoning	streaminginline_diffs	show_costskindefaulttool_progress_commandtool_preview_lengthprivacy
redact_piittsedgevoicezen-US-AriaNeural
elevenlabsvoice_idpNInz6obpgDQGcFmaJgBmodel_ideleven_multilingual_v2openaizgpt-4o-mini-ttsalloyneutts	ref_audioref_textzneuphonic/neutts-air-q4-ggufdevicecpusttbasez	whisper-1
record_keyzctrl+bmax_recording_secondsauto_ttssilence_thresholdsilence_durationg      @human_delaymodeoffmin_msi   max_msi	  memorymemory_enableduser_profile_enabledmemory_char_limiti  user_char_limiti_  
delegationmax_iterationsprefill_messages_fileskillsexternal_dirshonchotimezonediscordrequire_mentionfree_response_channelsauto_thread	reactionswhatsapp	approvalsmanualcommand_allowlistquick_commandspersonalitiessecurityredact_secretstirith_enabledtirith_pathtirithtirith_timeouttirith_fail_openwebsite_blocklistdomainsshared_filesr   wrap_responselogginglevelINFOmax_size_mbbackup_count_config_versionFIRECRAWL_API_KEYBROWSERBASE_API_KEYBROWSERBASE_PROJECT_IDFAL_KEYVOICE_TOOLS_OPENAI_KEYELEVENLABS_API_KEYSLACK_BOT_TOKENSLACK_APP_TOKENTAVILY_API_KEYTERMINAL_MODAL_MODENOUS_BASE_URLdescriptionzNous Portal base URL overridepromptz.Nous Portal base URL (leave empty for default)urlpasswordcategoryadvancedOPENROUTER_API_KEYz>OpenRouter API key (for vision, web scraping helpers, and MoA)zOpenRouter API keyzhttps://openrouter.ai/keystoolsvision_analyzemixture_of_agentsGOOGLE_API_KEYz<Google AI Studio API key (also recognized as GEMINI_API_KEY)zGoogle AI Studio API keyz&https://aistudio.google.com/app/apikeyGEMINI_API_KEYz3Google AI Studio API key (alias for GOOGLE_API_KEY)zGemini API keyGEMINI_BASE_URLz"Google AI Studio base URL overridez)Gemini base URL (leave empty for default)GLM_API_KEYzBZ.AI / GLM API key (also recognized as ZAI_API_KEY / Z_AI_API_KEY)zZ.AI / GLM API keyzhttps://z.ai/ZAI_API_KEYz$Z.AI API key (alias for GLM_API_KEY)zZ.AI API keyZ_AI_API_KEYGLM_BASE_URLzZ.AI / GLM base URL overridez-Z.AI / GLM base URL (leave empty for default)KIMI_API_KEYzKimi / Moonshot API keyzKimi API keyzhttps://platform.moonshot.cn/KIMI_BASE_URLz!Kimi / Moonshot base URL overridez'Kimi base URL (leave empty for default)MINIMAX_API_KEYzMiniMax API key (international)zMiniMax API keyzhttps://www.minimax.io/MINIMAX_BASE_URLzMiniMax base URL overridez*MiniMax base URL (leave empty for default)MINIMAX_CN_API_KEYz MiniMax API key (China endpoint)zMiniMax (China) API keyzhttps://www.minimaxi.com/MINIMAX_CN_BASE_URLz!MiniMax (China) base URL overridez2MiniMax (China) base URL (leave empty for default)DEEPSEEK_API_KEYz+DeepSeek API key for direct DeepSeek accesszDeepSeek API Keyz&https://platform.deepseek.com/api_keysDEEPSEEK_BASE_URLz'Custom DeepSeek API base URL (advanced)zDeepSeek Base URLDASHSCOPE_API_KEYz>Alibaba Cloud DashScope API key (Qwen + multi-provider models)zDashScope API Keyz-https://modelstudio.console.alibabacloud.com/DASHSCOPE_BASE_URLzGCustom DashScope base URL (default: coding-intl OpenAI-compat endpoint)zDashScope Base URLOPENCODE_ZEN_API_KEYz=OpenCode Zen API key (pay-as-you-go access to curated models)zOpenCode Zen API keyzhttps://opencode.ai/authOPENCODE_ZEN_BASE_URLzOpenCode Zen base URL overridez/OpenCode Zen base URL (leave empty for default)OPENCODE_GO_API_KEYz<OpenCode Go API key ($10/month subscription for open models)zOpenCode Go API keyOPENCODE_GO_BASE_URLzOpenCode Go base URL overridez.OpenCode Go base URL (leave empty for default)HF_TOKENzVHugging Face token for Inference Providers (20+ open models via router.huggingface.co)zHugging Face Tokenz&https://huggingface.co/settings/tokensHF_BASE_URLz2Hugging Face Inference Providers base URL overridez%HF base URL (leave empty for default)EXA_API_KEYz1Exa API key for AI-native web search and contentszExa API keyzhttps://exa.ai/
web_searchtoolPARALLEL_API_KEYz5Parallel API key for AI-native web search and extractzParallel API keyzhttps://parallel.ai/z-Firecrawl API key for web search and scrapingzFirecrawl API keyzhttps://firecrawl.dev/FIRECRAWL_API_URLz6Firecrawl API URL for self-hosted instances (optional)z)Firecrawl API URL (leave empty for cloud)FIRECRAWL_GATEWAY_URLzQExact Firecrawl tool-gateway origin override for Nous Subscribers only (optional)z9Firecrawl gateway URL (leave empty to derive from domain)TOOL_GATEWAY_DOMAINzShared tool-gateway domain suffix for Nous Subscribers only, used to derive vendor hosts, e.g. nousresearch.com -> firecrawl-gateway.nousresearch.comzTool-gateway domain suffixTOOL_GATEWAY_SCHEMEzShared tool-gateway URL scheme for Nous Subscribers only, used to derive vendor hosts (`https` by default, set `http` for local gateway testing)zTool-gateway URL schemeTOOL_GATEWAY_USER_TOKENzuExplicit Nous Subscriber access token for tool-gateway requests (optional; otherwise read from the Hermes auth store)zTool-gateway user tokenz;Tavily API key for AI-native web search, extract, and crawlzTavily API keyzhttps://app.tavily.com/homeuU   Browserbase API key for cloud browser (optional — local browser works without this)zBrowserbase API keyzhttps://browserbase.com/browser_navigatebrowser_clickuC   Browserbase project ID (optional — only needed for cloud browser)zBrowserbase project IDBROWSER_USE_API_KEYuU   Browser Use API key for cloud browser (optional — local browser works without this)zBrowser Use API keyzhttps://browser-use.com/FIRECRAWL_BROWSER_TTLz@Firecrawl browser session TTL in seconds (optional, default 300)zBrowser session TTL (seconds)CAMOFOX_URLzYCamofox browser server URL for local anti-detection browsing (e.g. http://localhost:9377)zCamofox server URLz)https://github.com/jo-inc/camofox-browserz FAL API key for image generationzFAL API keyzhttps://fal.ai/image_generateTINKER_API_KEYzTinker API key for RL trainingzTinker API keyz/https://tinker-console.thinkingmachines.ai/keysrl_check_statusWANDB_API_KEYz0Weights & Biases API key for experiment trackingzWandB API keyzhttps://wandb.ai/authorizerl_get_resultsz?OpenAI API key for voice transcription (Whisper) and OpenAI TTSz&OpenAI API Key (for Whisper STT + TTS)z$https://platform.openai.com/api-keysvoice_transcription
openai_ttsz4ElevenLabs API key for premium text-to-speech voiceszElevenLabs API keyzhttps://elevenlabs.io/GITHUB_TOKENzCGitHub token for Skills Hub (higher API rate limits, skill publish)zGitHub Tokenz"https://github.com/settings/tokensHONCHO_API_KEYz.Honcho API key for AI-native persistent memoryzHoncho API keyzhttps://app.honcho.devhoncho_contextHONCHO_BASE_URLz=Base URL for self-hosted Honcho instances (no API key needed)z,Honcho base URL (e.g. http://localhost:8000)TELEGRAM_BOT_TOKENz"Telegram bot token from @BotFatherzTelegram bot tokenzhttps://t.me/BotFather	messagingTELEGRAM_ALLOWED_USERSzSComma-separated Telegram user IDs allowed to use the bot (get ID from @userinfobot)z+Allowed Telegram user IDs (comma-separated)zhttps://t.me/userinfobotDISCORD_BOT_TOKENz'Discord bot token from Developer PortalzDiscord bot tokenz+https://discord.com/developers/applicationsDISCORD_ALLOWED_USERSz7Comma-separated Discord user IDs allowed to use the botz*Allowed Discord user IDs (comma-separated)zSlack bot token (xoxb-). Get from OAuth & Permissions after installing your app. Required scopes: chat:write, app_mentions:read, channels:history, groups:history, im:history, im:read, im:write, users:read, files:writezSlack Bot Token (xoxb-...)zhttps://api.slack.com/appsu   Slack app-level token (xapp-) for Socket Mode. Get from Basic Information → App-Level Tokens. Also ensure Event Subscriptions include: message.im, message.channels, message.groups, app_mentionzSlack App Token (xapp-...)MATTERMOST_URLz3Mattermost server URL (e.g. https://mm.example.com)zMattermost server URLzhttps://mattermost.com/deploy/MATTERMOST_TOKENz-Mattermost bot token or personal access tokenzMattermost bot tokenMATTERMOST_ALLOWED_USERSz:Comma-separated Mattermost user IDs allowed to use the botz-Allowed Mattermost user IDs (comma-separated)MATTERMOST_REQUIRE_MENTIONzaRequire @mention in Mattermost channels (default: true). Set to false to respond to all messages.zRequire @mention in channels!MATTERMOST_FREE_RESPONSE_CHANNELSzJComma-separated Mattermost channel IDs where bot responds without @mentionz+Free-response channel IDs (comma-separated)MATRIX_HOMESERVERz7Matrix homeserver URL (e.g. https://matrix.example.org)zMatrix homeserver URLz%https://matrix.org/ecosystem/servers/MATRIX_ACCESS_TOKENz3Matrix access token (preferred over password login)zMatrix access tokenMATRIX_USER_IDz)Matrix user ID (e.g. @hermes:example.org)zMatrix user ID (@user:server)MATRIX_ALLOWED_USERSzLComma-separated Matrix user IDs allowed to use the bot (@user:server format)z)Allowed Matrix user IDs (comma-separated)zZRequire @mention in Matrix rooms (default: true). Set to false to respond to all messages.z&Require @mention in rooms (true/false)zCComma-separated Matrix room IDs where bot responds without @mentionz(Free-response room IDs (comma-separated)z@Auto-create threads for messages in Matrix rooms (default: true)z)Auto-create threads in rooms (true/false)zNStable Matrix device ID for E2EE persistence across restarts (e.g. HERMES_BOT)z)Matrix device ID (stable across restarts)GATEWAY_ALLOW_ALL_USERSzMAllow all users to interact with messaging bots (true/false). Default: false.zAllow all users (true/false)API_SERVER_ENABLEDzrEnable the OpenAI-compatible API server (true/false). Allows frontends like Open WebUI, LobeChat, etc. to connect.zEnable API server (true/false)API_SERVER_KEYz`Bearer token for API server authentication. If empty, all requests are allowed (local use only).zAPI server auth key (optional)API_SERVER_PORTz(Port for the API server (default: 8642).zAPI server portAPI_SERVER_HOSTu   Host/bind address for the API server (default: 127.0.0.1). Use 0.0.0.0 for network access — requires API_SERVER_KEY for security.zAPI server hostWEBHOOK_ENABLEDzREnable the webhook platform adapter for receiving events from GitHub, GitLab, etc.zEnable webhooks (true/false)WEBHOOK_PORTz1Port for the webhook HTTP server (default: 8644).zWebhook portWEBHOOK_SECRETz[Global HMAC secret for webhook signature validation (overridable per route in config.yaml).zWebhook secretMESSAGING_CWDz5Working directory for terminal commands via messagingz+Messaging working directory (default: home)settingSUDO_PASSWORDz9Sudo password for terminal commands requiring root accesszSudo passwordHERMES_MAX_ITERATIONSz>Maximum tool-calling iterations per conversation (default: 90)zMax iterationsHERMES_TOOL_PROGRESSz=(deprecated) Use display.tool_progress in config.yaml insteadu.   Tool progress (deprecated — use config.yaml)HERMES_TOOL_PROGRESS_MODEu.   Progress mode (deprecated — use config.yaml)HERMES_PREFILL_MESSAGES_FILEzFPath to JSON file with ephemeral prefill messages for few-shot primingzPrefill messages file pathHERMES_EPHEMERAL_SYSTEM_PROMPTzOEphemeral system prompt injected at API-call time (never persisted to sessions)zEphemeral system promptc                h    V ^8  d   QhR\         R\        \        \        \        3,          ,          /# )r8   required_onlyr9   )rQ   r   r   r;   r   )r<   s   "r=   r>   r>     s'       d38n9M r?   c                >   . p\         P                  4        F1  w  r#\        V4      '       d   K  VP                  RV/VCRR/C4       K3  	  V '       gJ   \        P                  4        F1  w  r#\        V4      '       d   K  VP                  RV/VCRR/C4       K3  	  V# )zl
Check which environment variables are missing.

Returns list of dicts with var info for missing variables.
nameis_requiredTF)REQUIRED_ENV_VARSitemsget_env_valueappendOPTIONAL_ENV_VARS)r  missingvar_nameinfos   &   r=   get_missing_env_varsr    s     G ,113X&&NNFHJJmTJK 4
 /557NH **ODO-OP 8 Nr?   c                0    V ^8  d   QhR\         R\        /# )r8   config
dotted_keydictr;   )r<   s   "r=   r>   r>     s       # r?   c                    VP                  R4      pT pVRR  F:  pWT9  g&   \        VP                  V4      \        4      '       g   / WE&   WE,          pK<  	  W$VR,          &   R# )zSet a value at an arbitrarily nested dotted key path.

Creates intermediate dicts as needed, e.g. ``_set_nested(c, "a.b.c", 1)``
ensures ``c["a"]["b"]["c"] == 1``.
r   N)split
isinstancerI   r  )r  r  valuepartscurrentparts   &&&   r=   _set_nestedr    s`     S!EGcr
jT1BD&I&IGM-  E"Ir?   c                \    V ^8  d   QhR\         \        \        \        3,          ,          /# r7   r   r   r;   r   )r<   s   "r=   r>   r>     s       4S#X#7 r?   c                 T   aa \        4       p . oRR VV3R llloS! \        V 4       S# )z
Check which config fields are missing or outdated (recursive).

Walks the DEFAULT_CONFIG tree at arbitrary depth and reports any keys
present in defaults but absent from the user's loaded config.
c                <    V ^8  d   QhR\         R\         R\        /# )r8   defaultsr  prefixr  )r<   s   "r=   r>   /get_missing_config_fields.<locals>.__annotate__  s!     > > > >c >r?   c           
      p  < V P                  4        F  w  r4VP                  R 4      '       d   K  V'       g   TMV RV 2pW19  d   SP                  RVRVRRV 2/4       KQ  \        V\        4      '       g   Ki  \        VP                  V4      \        4      '       g   K  S! WAV,          V4       K  	  R# )_r   keyr   r;  zNew config option: N)r  
startswithr  r  r  rI   )r  r  r  r  default_valuefull_key_checkr  s   &&&   r=   r  )get_missing_config_fields.<locals>._check  s    "*.."2C~~c"""(s#.?H!8}!%8
#C  
 M400ZC@PRV5W5W}clH= #3r?   )rB   )load_configDEFAULT_CONFIG)r  r  r  s    @@r=   get_missing_config_fieldsr    s,     ]FG> > >6"Nr?   c                \    V ^8  d   QhR\         \        \        \        3,          ,          /# r7   r  )r<   s   "r=   r>   r>     s      " "tDcN'; "r?   c                     ^ RI Hp Hp T ! 4       pT'       g   . # \	        4       p. pT F  pT RTR,           2pTP                  R4      pTpRp	T F-  p
\        T\        4      '       d   Y9   d   Y,          pTp	K+  Rp	 M	  T	e1   \        T	\        4      '       g   Ku  T	P                  4       '       d   K  TP                  T4       K  	  T#   \         d    . u # i ; i)a#  Return skill-declared config vars that are missing or empty in config.yaml.

Scans all enabled skills for ``metadata.hermes.config`` entries, then checks
which ones are absent or empty under ``skills.config.<key>`` in the user's
config.yaml.  Returns a list of dicts suitable for prompting.
)discover_all_skill_config_varsSKILL_CONFIG_PREFIXr   r  N)agent.skill_utilsr  r  	Exceptionr  r  r  r  r;   rE   r  )r  r  all_varsr  r  varstorage_keyr  r  r  r  s              r=   get_missing_skill_config_varsr    s    Y ./H	]F$&G,-Qs5zl;!!#&D'4((T_!-  =Zs33EKKMMNN3   N3  	s   C CCc                F    V ^8  d   QhR\         \        \        3,          /# r7   )r	   int)r<   s   "r=   r>   r>   '  s     	 	eCHo 	r?   c                 l    \        4       p V P                  R^ 4      p\        P                  R^4      pW3# )zC
Check config version.

Returns (current_version, latest_version).
r/  )r  rI   r  )r  r  latests      r=   check_config_versionr  '  s7     ]Fjj*A.G 115F?r?   c                   0   a  ] tR tRt o RtV 3R ltRtV tR# )ConfigIssueiI  z$A detected config structure problem.c                >   < V ^8  d   Qh/ S[ ;R&   S[ ;R&   S[ ;R&   # )r8   severitymessagehintr[   )r<   __classdict__s   "r=   r>   ConfigIssue.__annotate__I  s)      M	 
 L  I r?   rT   N)__name__
__module____qualname____firstlineno____doc____annotate_func____static_attributes____classdictcell__)r  s   @r=   r  r  I  s     .  r?   r  c                v    V ^8  d   QhR\         \        \        \        3,          ,          R\        R,          /# )r8   r  r9   r  )r   r   r;   r   r   )r<   s   "r=   r>   r>   R  s0     w whtCH~&> w$}J] wr?   c                   V f    \        4       p . pV P                  R4      pVEe   \	        V\
        4      '       d   VP                  \        RRR4      4       \	        V\
        4      '       d   \        VP                  4       4      M	\        4       pV\        ,          pV'       d*   VP                  \        RR\        V4       R	2R
4      4       M\	        V\        4      '       d   \        V4       F  w  rV\	        V\
        4      '       g9   VP                  \        RRV R\        V4      P                   R2R4      4       KS  VP                  R4      '       g!   VP                  \        RRV R2R4      4       VP                  R4      '       d   K  VP                  \        RRV R2R4      4       K  	  V P                  R4      pVe   \	        V\
        4      '       g4   VP                  \        RR\        V4      P                   2R4      4       MnV'       dg   VP                  R4      '       g   VP                  \        RRR4      4       VP                  R4      '       g   VP                  \        RRR4      4       \	        V\
        4      '       d5   RV 9  d.   RT;'       g    / 9   d   VP                  \        RRR4      4       V P                  R4      pV'       d%   V'       g   VP                  \        RR R!4      4       V  FZ  p	V	P                  R"4      '       d   K  V	\         9  g   K)  V	\        9   g   K6  VP                  \        RR#V	 R$2R%V	 R&24      4       K\  	  V#   \         d    \        RRR4      .u # i ; i)'a  Validate config.yaml structure and return a list of detected issues.

Catches common YAML formatting mistakes that produce confusing runtime
errors (like "Unknown provider") instead of clear diagnostics.

Can be called with a pre-loaded config dict, or will load from disk.
errorzCould not load config.yamlz+Run 'hermes setup' to create a valid configcustom_providersuO   custom_providers is a dict — it must be a YAML list (items prefixed with '-')zeChange to:
  custom_providers:
    - name: my-provider
      base_url: https://...
      api_key: ...warningzRoot-level keys z( look like custom_providers entry fieldszLThese should be indented under a '- name: ...' list entry, not at root levelzcustom_providers[z] is not a dict (got )z1Each entry should have at minimum: name, base_urlr  z] is missing 'name' fieldz#Add a name, e.g.: name: my-providerr   z] is missing 'base_url' fieldzDAdd the API endpoint URL, e.g.: base_url: https://api.example.com/v1fallback_modelzAfallback_model should be a dict with 'provider' and 'model', got zZChange to:
  fallback_model:
    provider: openrouter
    model: anthropic/claude-sonnet-4r   uH   fallback_model is missing 'provider' field — fallback will be disabledz/Add: provider: openrouter (or another provider)r   uE   fallback_model is missing 'model' field — fallback will be disabledz8Add: model: anthropic/claude-sonnet-4 (or another model)zGfallback_model appears inside custom_providers instead of at root levelzDMove fallback_model to the top level of config.yaml (no indentation)u[   custom_providers defined but no 'model' section — Hermes won't know which provider to useziAdd a model section:
  model:
    provider: custom
    default: your-model-name
    base_url: https://...r  zRoot-level key 'uW   ' looks misplaced — should it be under 'model:' or inside a 'custom_providers' entry?zMove 'z' under the appropriate section)r  r  r  rI   r  r  r  setkeys_CUSTOM_PROVIDER_LIKE_FIELDSsortedlist	enumeratetyper  r  _KNOWN_ROOT_KEYS)
r  issuescpcp_keys
suspiciousientryfb	model_cfgr  s
   &         r=   validate_config_structurer  R  sF    ~	w ]F !#F 
&	'B	~b$MM+a%  )32t(<(<c"'')n#%G #??Jk&vj'9&::bcb 
 D!!%bM!%..MM+!+A3.CDKDXDXCYYZ[K# 
 yy((MM+!+A3.GH=# 
 yy,,MM+!+A3.KL^#  *, 
$	%B	~"d##MM+STXY[T\TeTeSfg7  66*%%k^E 
 66'??k[N  "d 0 >CSXZX`X`^`CakUR
 	 

7#I	)ki(
 	 >>#&&32N+NMM+"3%'~<= 	  MY  	w)EGtuvv	ws   
M/ /N
Nc                `    V ^8  d   QhR\         \        \        \        3,          ,          RR/# )r8   r  r9   N)r   r   r;   r   )r<   s   "r=   r>   r>     s'     0 0(4S>": 0d 0r?   c                f    \        V 4      pT'       g   R# ^ RIpR.pT F9  pTP                  R8X  d   RMRpTP	                  RT RTP
                   24       K;  	  TP	                  R4       TP                  P                  R	P                  T4      R
,           4       R#   \         d     R# i ; i)zPrint config structure warnings to stderr at startup.

Called early in CLI and gateway init so users see problems before
they hit cryptic "Unknown provider" errors.  Prints nothing if
config is healthy.
Nu3   [33m⚠ Config issues detected in config.yaml:[0mr  u   [31m✗[0mu   [33m⚠[0m   z2  [2mRun 'hermes doctor' for fix suggestions.[0m
z

)	r  r  rh   r  r  r  ri   writejoin)r  r  rh   linescimarkers   &     r=   print_config_warningsr    s    *62 HIE)+)?%EYr&2::,/0  
LLKLJJTYYu%./  s   B! !B0/B0c                ^    V ^8  d   QhR\         R\         R\        \        \        3,          /# )r8   interactivequietr9   )rQ   r   r;   r   )r<   s   "r=   r>   r>     s.     _ _ _D _T#s(^ _r?   c           
        R. R. R. /p \        4       pV'       d   V'       g   \        RV R24       \        4       w  rET^8  Ed1   \	        4       pTP                  R/ 4      p\        T\        4      '       g   / pRT9  d   \        R4      p\        R	4      p	T'       d4   TP                  4       R]9   d   R
TR&   TR,          P                  R4       MxT	'       dT   T	P                  4       R^9   d?   T	P                  4       TR&   TR,          P                  RT	P                  4        R24       MRTR&   TR,          P                  R4       YvR&   \        T4       T'       g   \        RTR,           24       T^8  d   \	        4       pRT9  d   \        P                  ! RR4      p
T
'       dU   T
P                  4       '       d?   T
P                  4       TR&   TR,          P                  RT
P                  4        R24       MRTR&   TR,          P                  R4       \        T4       T'       g"   TR,          ;'       g    Rp\        RT 24       T^	8  d4    \        R4      pT'       d    \        RR4       T'       g   \        R4       T^8  Ed   \	        4       pTP                  R4      p\        T\         4      '       Edy   T'       Edp   TP                  R/ 4      p\        T\        4      '       g   / p^ pT EF  p\        T\        4      '       g   K  TP                  RR4      pTP                  RR4      ;'       g    TP                  RR4      ;'       g    RpTP                  R R4      pT'       g   K  TP                  4       P                  4       P#                  R!R"4      P#                  R#R4      P#                  R$R4      pR%T9   d   TP#                  R%R"4      pK  TP                  R"4      pT'       g6    ^ R&IHp T! T4      pTP(                  ;'       g    R'P#                  R(R"4      pTT9   d   T R"T 2pR*T/pT'       d   TTR&   T'       d   TR_9  d   TTR &   TP                  R+4      '       d   TR+,          TR,&   TP                  R-4      '       d   TR-,          TR.&   TTT&   T^,          pEK  	  T^ 8  dx   YR&   TR \        T4       T'       g^   \        R/T R024       \!        TP+                  4       4      T) R1  F-  pTT,          p\        R2T R3TP                  R*R4       24       K/  	  YE8  d   T'       g   \        R4T R5T 24       \-        R6R77      pT'       d<   T'       g4   \        R84       T F"  p\        R9TR,           R3TR:,           24       K$  	  T '       Ed%   T'       Ed   \        R;4       T EF	  pTP                  R4      '       d   \        R<TR,           24       TP                  R=4      '       d"   ^ R1IpTP/                  R>TR?,           R324      pM$\1        R>TR?,           R324      P                  4       pT'       dI   \        TR,          T4       TR,          P                  TR,          4       \        R@TR,           24       M#TR,          P                  RATR,           RB24       \        4        EK  	  \-        RCR77      pT'       d   T Uu0 uF  pTR,          kK  	  upM	\3        4       pT Uu. uF.  pTR,          T9  g   K  TP                  RD4      '       d   K,  TNK0  	  pp\3        4       p \5        T^,           T^,           4       F(  p!T P7                  \8        P                  T!. 4      4       K*  	  T '       Ed!   T '       Ed   T'       Eg   \;        T 4       U"u. uF2  p"\        T"4      '       d   K  T"\<        9   g   K#  T"\<        T",          3NK4  	  p#p"T#'       Ed   \        RE\?        T#4       RF24       T# F'  w  p"p$\        RGT" RHT$P                  R:R4       24       K)  	  \        4         \1        RI4      P                  4       P                  4       p%T%R`9   Ed5   \        4        T# EF"  w  p"p$T$P                  R4      '       d5   \        R>T$P                  R:T"4       24       \        R<T$R,           24       M\        R>T$P                  R:T"4       24       T$P                  R=4      '       d+   ^ R1IpTP/                  R>T$P                  R?T"4       RK24      pM-\1        R>T$P                  R?T"4       RK24      P                  4       pT'       d3   \        T"T4       TR,          P                  T"4       \        R@T" 24       \        4        EK%  	  M\        RL4       \E        4       p&T&'       dv   \	        4       pT& FU  p'T'RM,          pT'RN,          p(\G        TTT(4       TR,          P                  T4       T'       d   KD  \        ROT RPT( 24       KW  	  YVRQ&   \        T4       MYE8  d   \	        4       pYVRQ&   \        T4       \I        4       p)T)'       Ed   T '       Ed   T'       Eg   \        RE\?        T)4       RR24       T) F8  pTP                  RSRT4      p*\        RGTRM,           RHTR:,           RUT* R$24       K:  	  \        4         \1        RV4      P                  4       P                  4       p%T%R`9   Ed2   \        4        \	        4       p ^ RWI%H&p+ T) EF  pTP                  RNR4      p(T('       d   RYT( R$2MRp,\1        R>TR?,           T, R324      P                  4       pT'       g   T('       d   \O        T(4      pT'       dT   T+ R(TRM,           2p-\G        TT-T4       TR,          P                  TRM,          4       \        R@TRM,           RPT 24       M6TR,          P                  RATRM,           RZTP                  RSR[4       R\24       \        4        EK  	  \        T4       T# \        RL4       T#   \         d     EL8i ; i  \         d     E	Li ; i  \         d
    R)T 2p EL_i ; iu upi u upi u up"i   \@        \B        3 d    RJp% EL@i ; i  \@        \B        3 d    RJp% ELi ; i  \         d    RXp+ ELi ; i)aa  
Migrate config to latest version, prompting for new required fields.

Args:
    interactive: If True, prompt user for missing values
    quiet: If True, suppress output
    
Returns:
    Dict with migration results: {"env_added": [...], "config_added": [...], "warnings": [...]}
	env_addedconfig_addedwarningsu     ✓ Repaired .env file (z corrupted entries fixed)r   tool_progressr  r  r  z;display.tool_progress=off (from HERMES_TOOL_PROGRESS=false)allzdisplay.tool_progress=z! (from HERMES_TOOL_PROGRESS_MODE)z#display.tool_progress=all (default)u-     ✓ Migrated tool progress to config.yaml: r  HERMES_TIMEZONErB   z	timezone=z (from HERMES_TIMEZONE)z$timezone= (empty, uses server-local)(server-local)u%     ✓ Added timezone to config.yaml: r   u8     ✓ Cleared ANTHROPIC_TOKEN from .env (no longer used)r  r   r  r   r=  r   r  -(r  z--)urlparseendpointr   z	endpoint-apir   default_modelapi_mode	transportu     ✓ Migrated z) custom provider(s) to providers: sectionNu       → z: zConfig version:     → Tr  u0   
⚠️  Missing required environment variables:u      • r;  z
Let's configure them now:
z  Get your key at: r>  r  r<  u     ✓ Saved zSkipped z - some features may not workFr@  
  z$ new optional key(s) in this update:u       • u    — z  Configure new keys? [y/N]: nz (Enter to skip): z1  Set later with: hermes config set <key> <value>r  r   u     ✓ Added  = r/  z! skill setting(s) not configured:skillunknownz (from skill: z#  Configure skill settings? [y/N]: )r  zskills.configz (default: u    — skill '?z' may ask for it later)false0no)newr  )zno-keyzno-key-requiredrB   )yyes)(sanitize_env_filerg   r  r  r  rI   r  r  r  rF   r  save_configrC   rD   rE   save_env_valuer  replaceurllib.parser  hostnamer  r  getpassinputr  rangeupdateENV_VARS_BY_VERSIONr  r  lenEOFErrorKeyboardInterruptr  r  r  r  r  r;   ).r  r  resultsfixescurrent_ver
latest_verr  r   old_enabledold_modeold_tz
tz_display	old_tokencustom_listproviders_dictmigrated_countr  old_nameold_urlold_keyr  r  parsed	new_entryepmissing_envr  r*  r  missing_optionalvrequired_namesnew_var_namesverr  new_and_unsetr  answermissing_configfieldr   missing_skill_config
skill_namer  default_hintr  s.   &&                                            r=   migrate_configrQ    s    BJCG!#.ug5NOP
 34K Q**Y+'4((G')'(>?K$%@AH{0026JJ+0('../lmhnn..@+3>>+;('..1GHXGYYz/{|+0('../TU '9EgoF^E_`a QV#YY0"5F&,,..%+\\^z"'..6<<>:JJa/bc%'z"'../UV#J/CC3C
=j\JK Q	%&78I0"5TU
 Rjj!34k4(([[#ZZR8Nnd33!#N$!%.. 99VR0))J3QQuyy7KQQr))Ir2 nn&,,.66sC@HHbQYYZ]_abck++dC0Ciin;9!)'!2%<<*EEc3O
 .( E>"23C"G,	(0If%w.OO+2Ii( 99W%%16wIo.99Z((-2:->Ik*&/s#!#S %V !&4{#-.F#ON+;;def#N$7$7$9:N?;KL+C0Rub0A/BCD  M  U:,?@ 'T:K5ABCGCK=3}+=*>?@  {{{-.Cwwu~~+CJ<89wwz"""S]O2(>?3x=/45;;=s6{E2$++CK8S[M23
#**Xc&k]B_+`aG! ( ,%@9D5Aaii5#%N##aV9N* 	
34553D 	
#   EM[1_j1n5044S"=> 6 }UU }-
- & ,+/3D+D ,T$T*+- 	 

 =D]+,,PQR+
deDHH]B,G+HIJ ,G>?EEGMMO %"/JD$xx488M4#@"ABC 3DK=AB488M4#@"ABCxx
++& '"TXXh5M4NN`0a b %488Hd+C*DDV&W X ^ ^ `&tU3,33D9TF34G #0" IJ /0N#E,CI&GW-N#**3/5SEWI67 $ %/ !F		!$. !F 9:EES-.//PQR'C)4JHSZLc-.@-APZ|[\]^ ( 		@AGGIOOQF \!G ]F6A ,'')R0;BWIQ73x=/,rBCIIKLE%8$93u:,"GKU;N+223u:>LUCw?@J'.."3u:,l3777C;P:QQgh  ,   N EFN[  l  		B % ; ).)9:;F 6
 /0 z +, 	F	  6&5#6s   q q 2q/  r"r2rr*rrr"r"(r"'r' 0's 4s q,+q,/q>=q>rr'r>=r>sss,+s,c                <    V ^8  d   QhR\         R\         R\         /# )r8   r   overrider9   )r  )r<   s   "r=   r>   r>     s!      d d t r?   c                    V P                  4       pVP                  4        FW  w  r4W29   dI   \        W#,          \        4      '       d-   \        V\        4      '       d   \	        W#,          V4      W#&   KS  WBV&   KY  	  V# )a  Recursively merge *override* into *base*, preserving nested defaults.

Keys in *override* take precedence. If both values are dicts the merge
recurses, so a user who overrides only ``tts.elevenlabs.voice_id`` will
keep the default ``tts.elevenlabs.model_id`` intact.
)copyr  r  r  _deep_merge)r   rS  resultr  r  s   &&   r=   rV  rV    sa     YY[Fnn&
M6;--5$''%fk59FK3K ' Mr?   c                d   \        V \        4      '       d   \        P                  ! RR V 4      # \        V \        4      '       d/   V P                  4        UUu/ uF  w  rV\        V4      bK  	  upp# \        V \        4      '       d   V  Uu. uF  p\        V4      NK  	  up# V # u uppi u upi )zRecursively expand ``${VAR}`` references in config values.

Only string values are processed; dict keys, numbers, booleans, and
None are left untouched.  Unresolved references (variable not in
``os.environ``) are kept verbatim so callers can detect them.
z\${([^}]+)}c                 ~    \         P                  P                  V P                  ^4      V P                  ^ 4      4      # )   )rC   environrI   group)ms   &r=   <lambda>"_expand_env_vars.<locals>.<lambda>#  s#    bjjnnQWWQZ<r?   )r  r;   resubr  r  _expand_env_varsr  )objkrF  items   &   r=   rb  rb    s     #svv<
 	

 #t3699;?;41#A&&;??#t36734 &377J @7s   B'B-c                t    V ^8  d   QhR\         \        \        3,          R\         \        \        3,          /# r8   r  r9   r   r;   r   )r<   s   "r=   r>   r>   -  s*      tCH~ $sCx. r?   c                  a  \         ;QJ d    V 3R lR 4       F  '       g   K   RM	  RM! V 3R lR 4       4      pV'       g   S # \        S 4      o S P                  R4      p\        V\        4      '       g   V'       d   RV/M/ pVS R&   R FI  pS P                  V4      pV'       d   VP                  V4      '       g   WBV&   S P	                  VR4       KK  	  S # )u  Move stale root-level provider/base_url into model section.

Some users (or older code) placed ``provider:`` and ``base_url:`` at the
config root instead of inside ``model:``.  These root-level keys are only
used as a fallback when the corresponding ``model.*`` key is empty — they
never override an existing ``model.provider`` or ``model.base_url``.
After migration the root-level keys are removed so they can't cause
confusion on subsequent loads.
c              3   F   <"   T F  pSP                  V4      x  K  	  R # 5iNrI   ).0rd  r  s   & r=   	<genexpr>-_normalize_root_model_keys.<locals>.<genexpr>8  s     C*BQ6::a==*Bs   !TFr   r   N)r   r   )anyr  rI   r  pop)r  has_rootr   r  root_vals   f    r=   _normalize_root_model_keysrt  -  s     sC*BCsssC*BCCH&\FJJwEeT""&+E"w'::c?EIIcNN!#J

3	 ( Mr?   c                t    V ^8  d   QhR\         \        \        3,          R\         \        \        3,          /# rg  rh  )r<   s   "r=   r>   r>   K  s*      S#X 4S> r?   c                    \        V 4      p \        V P                  R4      ;'       g    / 4      pRV 9   d   RV9  d   V R,          VR&   RV9  d   \        R,          R,          VR&   WR&   V P                  RR4       V # )z;Normalize legacy root-level max_turns into agent.max_turns.r   r   N)r  rI   r  rq  )r  agent_configs   & r=   _normalize_max_turns_configrx  K  sz    &\F

7+11r2LfL!@$*;$7[!,&$27$;K$H[!"7O
JJ{D!Mr?   c                F    V ^8  d   QhR\         \        \        3,          /# r7   rh  )r<   s   "r=   r>   r>   \  s     ] ]T#s(^ ]r?   c                    ^ RI p \        4        \        4       pV P                  \        4      pVP                  4       '       d    \        VRR7      ;_uu_ 4       p\        P                  ! V4      ;'       g    / pRRR4       RX9   dZ   \        VP                  R4      ;'       g    / 4      pVP                  R4      f   VR,          VR&   WTR&   VP                  RR4       \        W$4      p\        \!        \#        V4      4      4      #   + '       g   i     L; i  \         d   p\        RT 24        Rp?LNRp?ii ; i)z.Load configuration from ~/.hermes/config.yaml.Nr   r   r   r   z Warning: Failed to load config: )rU  r   rn   deepcopyr  rK   openyaml	safe_loadr  rI   rq  rV  r  rg   rb  rt  rx  )rU  config_pathr  fuser_configagent_user_configes          r=   r  r  \  s   !#K]]>*F	:kG44"nnQ/552 5 k)$()A)G)GR$H!$((5=5@5M%k2'8G$T2 5F 67RSY7Z[\\ 54  	:4QC899	:s7   D !D;+D 'AD D	D E)D<<Eu  
# ── Security ──────────────────────────────────────────────────────────
# API keys, tokens, and passwords are redacted from tool output by default.
# Set to false to see full values (useful for debugging auth issues).
# tirith pre-exec scanning is enabled by default when the tirith binary
# is available. Configure via security.tirith_* keys or env vars
# (TIRITH_ENABLED, TIRITH_BIN, TIRITH_TIMEOUT, TIRITH_FAIL_OPEN).
#
# security:
#   redact_secrets: false
#   tirith_enabled: true
#   tirith_path: "tirith"
#   tirith_timeout: 5
#   tirith_fail_open: true
u  
# ── Fallback Model ────────────────────────────────────────────────────
# Automatic provider failover when primary is unavailable.
# Uncomment and configure to enable. Triggers on rate limits (429),
# overload (529), service errors (503), or connection failures.
#
# Supported providers:
#   openrouter   (OPENROUTER_API_KEY)  — routes to any model
#   openai-codex (OAuth — hermes auth) — OpenAI Codex
#   nous         (OAuth — hermes auth) — Nous Portal
#   zai          (ZAI_API_KEY)         — Z.AI / GLM
#   kimi-coding  (KIMI_API_KEY)        — Kimi / Moonshot
#   minimax      (MINIMAX_API_KEY)     — MiniMax
#   minimax-cn   (MINIMAX_CN_API_KEY)  — MiniMax (China)
#
# For custom OpenAI-compatible endpoints, add base_url and api_key_env.
#
# fallback_model:
#   provider: openrouter
#   model: anthropic/claude-sonnet-4
#
# ── Smart Model Routing ────────────────────────────────────────────────
# Optional cheap-vs-strong routing for simple turns.
# Keeps the primary model for complex work, but can route short/simple
# messages to a cheaper model across providers.
#
# smart_model_routing:
#   enabled: true
#   max_simple_chars: 160
#   max_simple_words: 28
#   cheap_model:
#     provider: openrouter
#     model: google/gemini-2.5-flash
uB  
# ── Security ──────────────────────────────────────────────────────────
# API keys, tokens, and passwords are redacted from tool output by default.
# Set to false to see full values (useful for debugging auth issues).
#
# security:
#   redact_secrets: false

# ── Fallback Model ────────────────────────────────────────────────────
# Automatic provider failover when primary is unavailable.
# Uncomment and configure to enable. Triggers on rate limits (429),
# overload (529), service errors (503), or connection failures.
#
# Supported providers:
#   openrouter   (OPENROUTER_API_KEY)  — routes to any model
#   openai-codex (OAuth — hermes auth) — OpenAI Codex
#   nous         (OAuth — hermes auth) — Nous Portal
#   zai          (ZAI_API_KEY)         — Z.AI / GLM
#   kimi-coding  (KIMI_API_KEY)        — Kimi / Moonshot
#   minimax      (MINIMAX_API_KEY)     — MiniMax
#   minimax-cn   (MINIMAX_CN_API_KEY)  — MiniMax (China)
#
# For custom OpenAI-compatible endpoints, add base_url and api_key_env.
#
# fallback_model:
#   provider: openrouter
#   model: anthropic/claude-sonnet-4
#
# ── Smart Model Routing ────────────────────────────────────────────────
# Optional cheap-vs-strong routing for simple turns.
# Keeps the primary model for complex work, but can route short/simple
# messages to a cheaper model across providers.
#
# smart_model_routing:
#   enabled: true
#   max_simple_chars: 160
#   max_simple_words: 28
#   cheap_model:
#     provider: openrouter
#     model: google/gemini-2.5-flash
c                F    V ^8  d   QhR\         \        \        3,          /# )r8   r  rh  )r<   s   "r=   r>   r>     s      S#X r?   c                <   \        4       '       d   \        R4       R# ^ RIHp \	        4        \        4       p\        \        V 4      4      p. pVP                  R/ 4      pV'       d   VP                  R4      f   VP                  \        4       VP                  R/ 4      pV'       d/   VP                  R4      '       d   VP                  R4      '       g   VP                  \        4       T! TTV'       d   R	P                  V4      MRR
7       \        V4       R# )z,Save configuration to ~/.hermes/config.yaml.zsave configurationN)atomic_yaml_writer  r   r  r   r   rB   )extra_content)rU   rj   utilsr  r   rn   rt  rx  rI   r  _SECURITY_COMMENT_FALLBACK_COMMENTr  r   )r  r  r  rM   r  secr  s   &      r=   r%  r%    s    ||*+'!#K+,G,OPJ E
..R
(C#''*+3&'	("	-BbffZ((RVVG__&'(-bggen4
 r?   c                F    V ^8  d   QhR\         \        \        3,          /# r7   )r   r;   )r<   s   "r=   r>   r>     s      $sCx. r?   c                    \        4       p / pV P                  4       '       d   \        '       d   RRRR/M/ p\        V 3/ VB ;_uu_ 4       pV F  pVP	                  4       pV'       g   K  VP                  R4      '       d   K6  RV9   g   K?  VP                  R4      w  rVpVP	                  4       P	                  R4      WP	                  4       &   K  	  RRR4       V# V#   + '       g   i     T# ; i)	z/Load environment variables from ~/.hermes/.env.r   r   errorsr'  #=z"'N)rq   rK   _IS_WINDOWSr|  rE   r  	partition)env_pathenv_varsopen_kwr  liner  r  r  s           r=   load_envr    s    ~HH AL:w)<QS(&g&&!zz|4 4 4$(NN3$7MCE,1KKM,?,?,FHYY[)	  ' O8O '& Os   C +C C AC  C1	c                0    V ^8  d   QhR\         R\         /# )r8   r  r9   )r  )r<   s   "r=   r>   r>     s     0 0t 0 0r?   c           	     t   \        \        P                  4       4      \        ,          p. pV  EF  pVP	                  R4      pVP                  4       pV'       d   VP                  R4      '       d   VP                  VR,           4       K^  . pV FX  pVR,           pVP                  V4      p	V	^ 8  g   K&  VP                  V	4       VP                  W\        V4      ,           4      p	K=  	  \        V4      ^8  d   VP                  4        \        \        V4      4      p\        V4       Fj  w  rV
^,           \        V4      8  d   Wj^,           ,          M
\        V4      pW[V P                  4       pV'       g   KR  VP                  VR,           4       Kl  	  EKn  VP                  VR,           4       EK  	  V# )a  Fix corrupted .env lines before writing.

Handles two known corruption patterns:
1. Concatenated KEY=VALUE pairs on a single line (missing newline between
   entries, e.g. ``ANTHROPIC_API_KEY=sk-...OPENAI_BASE_URL=https://...``).
2. Stale ``KEY=***`` placeholder entries left by incomplete setup runs.

Uses a known-keys set (OPTIONAL_ENV_VARS + _EXTRA_ENV_KEYS) so we only
split on real Hermes env var names, avoiding false positives from values
that happen to contain uppercase text with ``=``.
z
r  r  r  )r  r  r  _EXTRA_ENV_KEYSrstriprE   r  r  findr/  sortr  r  )r  
known_keys	sanitizedr  rL   strippedsplit_positionskey_nameneedleidxr  posendr  s   &             r=   _sanitize_env_linesr    si    &++-.@JIkk&!99; 8..s33S4Z( "H^F--'C(&&s+mmF#f+,=> # !#  "$S%9:O#O401AO8L0Lo!e,RUV^R_C(..04$$TD[1	 5 X_-; > r?   c                $    V ^8  d   QhR\         /# r7   )r  )r<   s   "r=   r>   r>   9  s     * *3 *r?   c                 2   \        4       p V P                  4       '       g   ^ # \        '       d   RRRR/M/ p\        '       d   RR/M/ p\        V 3/ VB ;_uu_ 4       pVP	                  4       pRRR4       \        X4      pWT8X  d   ^ # \        \        V4      \        V4      ,
          4      pV^ 8X  dG   \        R \        WE4       4       4      pV\        \        V4      \        V4      ,
          4      ,          p\        P                  ! \        V P                  4      RRR	7      w  rx \        P                  ! VR
3/ VB ;_uu_ 4       pVP!                  V4       VP#                  4        \        P$                  ! VP'                  4       4       RRR4       \        P(                  ! W4       \1        T 4       T#   + '       g   i     ELU; i  + '       g   i     LG; i  \*         d+     \        P,                  ! T4       h   \.         d     h i ; ii ; i)zRead, sanitize, and rewrite ~/.hermes/.env in place.

Returns the number of lines that were fixed (concatenation splits +
placeholder removals).  Returns 0 when no changes are needed.
r   r   r  r'  Nc              3   :   "   T F  w  rW8w  g   K  ^x  K  	  R# 5i)rZ  NrT   )rm  abs   &  r=   rn  $sanitize_env_file.<locals>.<genexpr>R  s     K"@$!AFAA"@s   

.tmp.env_dirsuffixr  w)rq   rK   r  r|  	readlinesr  absr/  sumziptempfilemkstempr;   ru   rC   fdopen
writelinesflushfsyncfilenor'  BaseExceptionunlinkrz   r   )	r  read_kwwrite_kwr  original_linesr  r3  fdtmp_paths	            r=   r$  r$  9  s    ~H??<GKz7Hi8RG(3
G$H	h	"'	"	"a 
# $N3I" I^!445EzK#n"@KKS^c.&99::##HOO(<VT[\LBYYr3+(++qLL#GGIHHQXXZ  , 	

8& L; 
#	"	"" ,+
  	IIh 	  		sU   F:) G! 	AGG! :G	G	G! !H-HHHHHHc                0    V ^8  d   QhR\         R\         /# r8   r  r  r[   )r<   s   "r=   r>   r>   f  s     ; ; ;C ;r?   c                T   \        4       '       d   \        RV  24       R# \        P                  V 4      '       g   \	        RV : 24      hVP                  RR4      P                  RR4      p\        4        \        4       p\        '       d   RRR	R
/M/ p\        '       d   RR/M/ p. pVP                  4       '       d9   \        V3/ VB ;_uu_ 4       pVP                  4       pRRR4       \        V4      pRp\        V4       F;  w  rV	P                  4       P                  V  R24      '       g   K/  V  RV R2WX&   Rp M	  V'       gS   V'       d4   VR,          P!                  R4      '       g   VR;;,          R,          uu&   VP#                  V  RV R24       \$        P&                  ! \)        VP*                  4      RRR7      w  r \,        P.                  ! V
R3/ VB ;_uu_ 4       pVP1                  V4       VP3                  4        \,        P4                  ! VP7                  4       4       RRR4       \,        P
                  ! W4       \?        T4       T\,        P@                  T &   \        '       g>    \,        PB                  ! T\D        PF                  \D        PH                  ,          4       R# R#   + '       g   i     EL; i  + '       g   i     L; i  \8         d+     \,        P:                  ! T4       h   \<         d     h i ; ii ; i  \<         d     R# i ; i)z)Save or update a value in ~/.hermes/.env.zset N#Invalid environment variable name: r  rB   r   r   r  r'  Fr  Tr  r  r  r  r  )%rU   rj   _ENV_VAR_NAME_REmatch
ValueErrorr'  r   rq   r  rK   r|  r  r  r  rE   r  endswithr  r  r  r;   ru   rC   r  r  r  r  r  r  r  rz   r   r[  ry   statS_IRUSRS_IWUSR)r  r  r  r  r  r  r  foundr  r  r  r  s   &&          r=   r&  r&  f  s   ||SEl#!!#&&>sgFGGMM$#++D"5E~H =HKz7Hi8RG(3
G$HE(&g&&!KKME ' $E* EU#::<""cU!9--awb)EHE	 $ r++D11"IIuAeWB'(##HOO(<VT[\LBYYr3+(++qLLGGIHHQXXZ  , 	

8& BJJsO ;	HHXt||dll:; K '&&* ,+
  	IIh 	  		  		sg   J9 K  ,AK2K  ;:L 9K
	K	K   L,LLLLLLL'&L'c                0    V ^8  d   QhR\         R\        /# r8   r  r9   )r;   rQ   )r<   s   "r=   r>   r>     s     * *# *$ *r?   c                   \        4       '       d   \        RV  24       R# \        P                  V 4      '       g   \	        RV : 24      h\        4       pVP                  4       '       g#   \        P                  P                  V R4       R# \        '       d   RRRR/M/ p\        '       d   RR/M/ p\        V3/ VB ;_uu_ 4       pVP                  4       pRRR4       \        X4      pV Uu. uF.  qfP                  4       P                  V  R	24      '       d   K,  VNK0  	  pp\!        V4      \!        V4      8  pV'       d   \"        P$                  ! \'        VP(                  4      R
RR7      w  r \        P*                  ! V	R3/ VB ;_uu_ 4       pVP-                  V4       VP/                  4        \        P0                  ! VP3                  4       4       RRR4       \        P4                  ! W4       \=        T4       \        P                  P                  V R4       V#   + '       g   i     ELU; iu upi   + '       g   i     Ll; i  \6         d+     \        P8                  ! T
4       h   \:         d     h i ; ii ; i)zrRemove a key from ~/.hermes/.env and os.environ.

Returns True if the key was found and removed, False otherwise.
zremove Fr  Nr   r   r  r'  r  r  r  r  r  )rU   rj   r  r  r  rq   rK   rC   r[  rq  r  r|  r  r  rE   r  r/  r  r  r;   ru   r  r  r  r  r  r'  r  r  rz   r   )r  r  r  r  r  r  r  	new_linesr  r  r  s   &          r=   remove_env_valuer    s   
 ||uo&!!#&&>sgFGG~H??


sD!<GKz7Hi8RG(3
G$H	h	"'	"	"a 
#&E"'R%$zz|/F/F#ay/Q%IR	NSZ'E''C,@X_`	2s/h//1Y'	$ 0 JJx* 	XJJNN3L1 
#	"	" S 0/
  			(#   	sa   H$/)H8H83 I AH=I $H5	=I	I JI32J3J>J JJc                $    V ^8  d   QhR\         /# r8   r  r[   )r<   s   "r=   r>   r>     s     $ $c $r?   c                J    T;'       g    \         pV! RV 4       V! RR4       R# )zBPersist an Anthropic OAuth/setup token and clear the API-key slot.r   r   rB   Nr&  r  save_fnwriters   && r=   save_anthropic_oauth_tokenr    s%    &&F
e$
#r?   c                J    T ;'       g    \         pV! RR4       V! RR4       R# )zHUse Claude Code's own credential files instead of persisting env tokens.r   rB   r   Nr  )r  r  s   & r=   %use_anthropic_claude_code_credentialsr    s%    &&F
b!
#r?   c                $    V ^8  d   QhR\         /# r  r[   )r<   s   "r=   r>   r>     s     " "# "r?   c                J    T;'       g    \         pV! RV 4       V! RR4       R# )zBPersist an Anthropic API key and clear the OAuth/setup-token slot.r   r   rB   Nr  r  s   && r=   save_anthropic_api_keyr    s%    &&F
&
b!r?   c                ^    V ^8  d   QhR\         R\         R\        \         \        3,          /# )r8   r  r  r9   )r;   r   r   )r<   s   "r=   r>   r>     s)      s 3 4S> r?   c                 (    \        W4       R RRV RR/# )successT	stored_as	validatedFr  )r  r  s   &&r=   save_env_value_securer    s#    34SU r?   c                F    V ^8  d   QhR\         R\        \         ,          /# r  )r;   r   )r<   s   "r=   r>   r>     s      s x} r?   c                    V \         P                  9   d   \         P                  V ,          # \        4       pVP                  V 4      # )z/Get a value from ~/.hermes/.env or environment.)rC   r[  r  rI   )r  r  s   & r=   r  r    s6     bjjzz# zH<<r?   c                0    V ^8  d   QhR\         R\         /# r  r[   )r<   s   "r=   r>   r>     s     & &C &C &r?   c                    V '       g   \        R\        P                  4      # \        V 4      ^8  d   R# V R,          R,           V RR ,           # )zRedact an API key for display.	(not set)z***:N   N...N)r.   r-   DIMr/  )r  s   &r=   
redact_keyr    s=    [&**--
3x"}r7U?SX%%r?   c                 2   \        4       p \        4        \        \        R\        P                  4      4       \        \        R\        P                  4      4       \        \        R\        P                  4      4       \        4        \        \        R\        P                  \        P
                  4      4       \        R\        4        24       \        R\        4        24       \        R\        4        24       \        4        \        \        R\        P                  \        P
                  4      4       . ROpV F+  w  r#\        V4      p\        R	VR
 R\        V4       24       K-  	  \        R4      ;'       g    \        R4      p\        R	RR
 R\        V4       24       \        4        \        \        R\        P                  \        P
                  4      4       \        RV P                  RR4       24       \        RV P                  R/ 4      P                  R\        R,          R,          4       24       \        4        \        \        R\        P                  \        P
                  4      4       V P                  R/ 4      p\        RVP                  RR4       24       \        RVP                  RR4      '       d   RMR 24       \        R VP                  R!R4      '       d   RMR 24       \        4        \        \        R"\        P                  \        P
                  4      4       V P                  R#/ 4      p\        R$VP                  R%R&4       24       \        R'VP                  R(R)4       24       \        R*VP                  R+^<4       R,24       VP                  R%4      R-8X  d!   \        R.VP                  R/R04       24       EMBVP                  R%4      R18X  d!   \        R2VP                  R3R44       24       EMVP                  R%4      R58X  dC   \        R6VP                  R7R04       24       \        R84      p\        R9V'       d   R:MR; 24       MVP                  R%4      R<8X  dC   \        R=VP                  R>R04       24       \        R?4      p	\        R@V	'       d   R:MR; 24       M\VP                  R%4      RA8X  dG   \        RB4      p
\        RC4      p\        RDT
;'       g    R; 24       \        RET;'       g    R; 24       \        4        \        \        RF\        P                  \        P
                  4      4       V P                  RGRH4      pV'       d   \        RIV 24       M&\        RI\        RJ\        P                  4       24       \        4        \        \        RK\        P                  \        P
                  4      4       V P                  RL/ 4      pVP                  RMRN4      p\        ROV'       d   RPMRQ 24       V'       d   \        RRVP                  RSRT4      ^d,          RU RV24       \        RWVP                  RXRY4      ^d,          RU RZ24       \        R[VP                  R\^4       R]24       VP                  R^RH4      ;'       g    R_p\        RV 24       VP                  R`Ra4      pVRa8w  d   \        RbV 24       V P                  Rc/ 4      pRdVP                  Re/ 4      RfVP                  Rg/ 4      /p\        ;QJ d*    Rh VP                  4        4       F  '       g   K   RNM	  RM! Rh VP                  4        4       4      pV'       d   \        4        \        \        Ri\        P                  \        P
                  4      4       VP!                  4        F~  w  ppVP                  RjRa4      pVP                  RRH4      pVRa8w  g   V'       g   K;  RkV 2.pV'       d   VP#                  RlV 24       \        R	VRm R	RnP%                  V4       24       K  	  \        4        \        \        Ro\        P                  \        P
                  4      4       \        Rp4      p\        Rq4      p\        RrV'       d   R:M\        Rs\        P                  4       24       \        RtV'       d   R:M\        Rs\        P                  4       24        ^ RuIHpHp V! 4       pV'       d   V! V4      p\        4        \        \        Rv\        P                  \        P
                  4      4       V F  pVRw,          p VP                  V RH4      pVP                  RxRH4      p!V'       d   \-        V4      M\        R;\        P                  4      p"\        R	V Ry RV" R	\        RzV! R{2\        P                  4       24       K  	  \        4        \        \        R\        P                  4      4       \        \        R|\        P                  4      4       \        \        R}\        P                  4      4       \        \        R~\        P                  4      4       \        4        R#   \.         d     Li ; i)zDisplay current configuration.u   ┌─────────────────────────────────────────────────────────┐u@   │              ⚕ Hermes Configuration                    │u   └─────────────────────────────────────────────────────────┘u	   ◆ Pathsz  Config:       z  Secrets:      z  Install:      u   ◆ API Keysr  z<14r  r   r   	Anthropicu	   ◆ Modelz  Model:        r   znot setz  Max turns:    r   r   u   ◆ Displayr   z  Personality:  r   r   z  Reasoning:    r   Fonr  z  Bell:         r   u   ◆ Terminalr   z  Backend:      r   r   z  Working dir:  r   r   z  Timeout:      r   sdockerz  Docker image: r   r   singularityz  Image:        r   r   modalz  Modal image:  r   MODAL_TOKEN_IDz  Modal token:  
configuredr  daytonaz  Daytona image: r   DAYTONA_API_KEYz  API key:      sshTERMINAL_SSH_HOSTTERMINAL_SSH_USERz  SSH host:     z  SSH user:     u   ◆ Timezoner  rB   z  Timezone:     r  u   ◆ Context Compressionr   r   Tz  Enabled:      r#  r   z  Threshold:    r   r   z.0f%z  Target ratio: r   r   z% of threshold preservedz  Protect last: r   z	 messagesr   z(main model)r   r   z  Provider:     r   Visionr   zWeb extractr   c              3      "   T F4  pVP                  R R4      R8g  ;'       g    VP                  RR4      x  K6  	  R# 5i)r   r   r   rB   Nrl  )rm  ts   & r=   rn  show_config.<locals>.<genexpr>u	  s=      #A 	
j&!V+AAquuWb/AA#s    >>u    ◆ Auxiliary Models (overrides)r   z	provider=zmodel=12s, u   ◆ Messaging Platformsru  rx  z  Telegram:     znot configuredz  Discord:      )r  resolve_skill_config_valuesu   ◆ Skill Settingsr  r  z<20s[]z+  hermes config edit     # Edit config filez!  hermes config set <key> <value>z+  hermes setup           # Run setup wizardN)	)rA  
OpenRouter)r4  zOpenAI (STT/TTS))r\  Exa)r_  Parallel)r0  	Firecrawl)r8  Tavily)r1  Browserbase)rg  zBrowser Use)r3  FALu   ────────────────────────────────────────────────────────────)r  rg   r.   r-   CYANBOLDrn   rq   rw   r  r  rI   r  r  rp  valuesr  r  r  r  r  r
  r;   r  )#r  r  env_keyr  r  anthropic_valuer   r   modal_tokendaytona_keyssh_hostssh_usertzr   r   _smcomp_providerr   	aux_taskshas_overrideslabeltask_cfgprovmdlr  telegram_tokendiscord_tokenr  r
  
skill_varsresolvedr  r  rO  display_vals#                                      r=   show_configr+  	  s   ]F	G	%  D  FL  FQ  FQ  R  S	%RTZT_T_
`a	%  D  FL  FQ  FQ  R  S 
G	%V[[&++
67	_./
01	\^,
-.	-/0
12 
G	%V[[
9:
D g&4*Aj/012  $$56\\-H[:\O	B{3qO!< =
>? 
G	%V[[&++
67	VZZ;<
=>	VZZ488nU\F]^iFjkl
mn 
G	%v{{FKK
89jjB'G	W[[AB
CD	W[[1A5%I%ITuU
VW	W[[1CU%K%KTQVW
XY 
G	%V[[
9:zz*b)H	X\\)W=>
?@	X\\%56
78	X\\)R89
;<||I(* n>j!k lmn	i	 M	1 .ACx!y z{|	i	 G	+ m=i!j klm#$45 + NOP	i	 I	-!(,,@l"m!nop#$56 + NOP	i	 E	) !45 !45 !8!8[ 9:; !8!8[ 9:; 
G	%V[[
9:	J	#B	 %& '7!D EFG 
G	%)6;;
DE**]B/Kooi.G	gU48
9: d!Cc!I# NaPQ !F!LS QQijk 1A2!F GyQRooor2DDn &'#(:FCF"$]O45 

;+Iy}}Xr2y}}]B7I C !!#CCC !!# M e6V[[QR(0OE8<<
F3D,,w+Cv~$TF+,LL6#05+R		%(8'9:;  1 
G	%)6;;
DE"#78N!"56M	^\GWY_YcYcAde
fg	]\FVX^XbXb@cd
efa35
2:>HG%,fkk6;;GH!%j S"- WWWb1
,1c%ju[&**7U3t*Ak]"UQzl!;Lfjj5Y4Z[\ " 
G	%
FJJ
'(	%=vzz
JK	%3VZZ
@A	%=vzz
JK	G  s   7j Cj jjc                 .   \        4       '       d   \        R4       R# \        4       p V P                  4       '       g   \	        \
        4       \        RV  24       \        P                  ! R4      ;'       g    \        P                  ! R4      pV'       g)   R F"  p^ RI	pVP                  V4      '       g   K   Tp M	  V'       g   \        R4       \        RV  24       R# \        RV  R	V R
24       \        P                  ! V\        V 4      .4       R# )z"Open config file in user's editor.zedit configurationNzCreated EDITORVISUALz#No editor found. Config file is at:r  zOpening  in r  )nanovimvicodenotepad)rU   rj   rn   rK   r%  r  rg   rC   rD   shutilwhich
subprocessrunr;   )r  editorcmdr5  s       r=   edit_configr;  	  s    ||*+!#K N#&' YYx 77BIIh$7F;C||C  	 < 34;- !	H[MfXS
12NNFC,-.r?   c                0    V ^8  d   QhR\         R\         /# r  r[   )r<   s   "r=   r>   r>   	  s     P7 P7# P7c P7r?   c                   \        4       '       d   \        R4       R# . R'OpV P                  4       V9   gp   V P                  4       P                  R4      '       gK   V P                  4       P                  R4      '       g&   V P                  4       P	                  R4      '       d6   \        V P                  4       V4       \        RV  R\        4        24       R# \        4       p/ pVP                  4       '       d@    \        VRR	7      ;_uu_ 4       p\        P                  ! V4      ;'       g    / pRRR4       V P                  R
4      pTpVRR(  F:  pW9  g&   \        VP!                  V4      \"        4      '       g   / Wx&   Wx,          pK<  	  VP%                  4       R)9   d   RpMlVP%                  4       R*9   d   RpMTVP'                  4       '       d   \)        V4      pM2VP+                  R
R^4      P'                  4       '       d   \-        V4      pWVR(,          &   \/        4        \        VRRR	7      ;_uu_ 4       p\        P0                  ! WERRR7       RRR4       RRRRRRRRRRRRRRRRR R!R"R#R$R%/p	W	9   d   \        W,          \3        V4      4       \        RV  R&V RV 24       R#   + '       g   i     EL; i  \         d    / p ELi ; i  + '       g   i     L; i)+zSet a configuration value.zset configuration valuesN_API_KEY_TOKENTERMINAL_SSHu   ✓ Set r/  r   r   r   TFrB   r  )default_flow_style	sort_keyszterminal.backendr   zterminal.modal_moder9  zterminal.docker_imageTERMINAL_DOCKER_IMAGEzterminal.singularity_imageTERMINAL_SINGULARITY_IMAGEzterminal.modal_imageTERMINAL_MODAL_IMAGEzterminal.daytona_imageTERMINAL_DAYTONA_IMAGEz&terminal.docker_mount_cwd_to_workspace&TERMINAL_DOCKER_MOUNT_CWD_TO_WORKSPACEzterminal.cwdTERMINAL_CWDzterminal.timeoutTERMINAL_TIMEOUTzterminal.sandbox_dirTERMINAL_SANDBOX_DIRzterminal.persistent_shellTERMINAL_PERSISTENT_SHELLr  )rA  r   r   r4  r\  r_  r0  r`  ra  rb  rc  rd  r8  r1  r2  rg  r3  ru  rx  r  r  r    r  r6  r7  rq  rr  rm  rk  r  )ra   r#  r  )r  r   r  )rU   rj   upperr  r  r&  rg   rq   rn   rK   r|  r}  r~  r  r  r  rI   r  rF   isdigitr  r'  floatr   dumpr;   )
r  r  api_keysr  r  r  r  r  r  _config_to_env_syncs
   &&        r=   set_config_valuerR  	  s   ||01H yy{h#))+"6"6z"B"BciikFZFZ[cFdFdhkhqhqhsh~h~  @N  iO  iOsyy{E*T,.!123
 "#KK	kG44"nnQ/552 5 IIcNEGcr
jT1BD&I&IGM-  {{}--	0	0	E
	sB	"	*	*	,	,eE"I 	k3	1	1Q		+UeL 
2 	N4!8$&B 6 ":02Z. 6#%@ !*/U<	HSEUG4}
56c 544 	K	4 
2	1s<   >K !J24K K2K	=K K KKK*	c           	     P   \        V RR4      pVe   VR8X  d   \        4        R# VR8X  d   \        4        R# VR8X  d   \        V RR4      p\        V RR4      pV'       d   VfX   \        R4       \        4        \        R	4       \        R
4       \        R4       \        R4       \        P
                  ! ^4       \        W#4       R# VR8X  d   \        \        4       4       R# VR8X  d   \        \        4       4       R# VR8X  Ed   \        4        \        \        R\        P                  \        P                  4      4       \        4        \        RR7      p\        4       p\        4       w  rgV'       g>   V'       g6   Wg8  d0   \        \        R\        P                   4      4       \        4        R# Wg8  d   \        RV RV 24       V'       d   \        R\#        V4       R24       V Uu. uF  qP%                  R4      '       g   K  VNK  	  p	pV Uu. uF7  pVP%                  R4      '       d   K  VP%                  R4      '       d   K5  VNK9  	  p
pV	'       d7   \        R\#        V	4       R24       V	 F  p\        RVR,           24       K  	  V
'       dq   \        R\#        V
4       R24       V
 FR  pVP%                  R . 4      pV'       d   R!R"P'                  VR#,          4       R$2MR%p\        RVR,           V 24       KT  	  \        4        \)        R&RR'7      p\        4        VR(,          '       g   VR),          '       d$   \        \        R*\        P                   4      4       VR+,          '       dA   \        4        VR+,           F)  p\        \        R,V 2\        P*                  4      4       K+  	  \        4        R# VR-8X  EdC   \        4        \        \        R.\        P                  \        P                  4      4       \        4        \        4       w  rgWg8  d   \        RV R/24       M*\        \        RV RV R02\        P*                  4      4       \        4        \        \        R1\        P                  4      4       \,         FK  p\/        V4      '       d   \        R2V 24       K$  \        \        R3V R42\        P0                  4      4       KM  	  \        4        \        \        R5\        P                  4      4       \2        P5                  4        F  w  pp\/        V4      '       d   \        R2V 24       K'  VP%                  R . 4      pV'       d   RR"P'                  VR#,          4       2MR%p\        \        R6V V 2\        P6                  4      4       K  	  \        4       pV'       dF   \        4        \        \        R7\#        V4       R82\        P*                  4      4       \        R94       \        4        R# \        R:V 24       \        4        \        R;4       \        R<4       \        R=4       \        R>4       \        R?4       \        R@4       \        RA4       \        RB4       \        P
                  ! ^4       R# u upi u upi )CzHandle config subcommands.config_commandNshoweditr  r  r  z&Usage: hermes config set <key> <value>z	Examples:z3  hermes config set model anthropic/claude-sonnet-4z+  hermes config set terminal.backend dockerz0  hermes config set OPENROUTER_API_KEY sk-or-...r}   zenv-pathmigrateu*   🔄 Checking configuration for updates...Fr  u    ✓ Configuration is up to date!z  Config version: r  r  z1 new config option(s) will be added with defaultsr  r@  u   
  ⚠️  z required API key(s) missing:u	        • r  u   
  ℹ️  z$ optional API key(s) not configured:rB  z (enables: r	  :Nr8   Nr  rB   T)r  r  r  r  u   ✓ Configuration updated!r	  u
     ⚠️  checku   📋 Configuration Statusu    ✓z (update available)z  Required:u       ✓ u       ✗ z
 (missing)z  Optional:u       ○ r  z new config option(s) availablez+    Run 'hermes config migrate' to add themzUnknown config command: zAvailable commands:z4  hermes config           Show current configurationz/  hermes config edit      Open config in editorz6  hermes config set <key> <value>   Set a config valuez;  hermes config check     Check for missing/outdated configz8  hermes config migrate   Update config with new optionsz/  hermes config path      Show config file pathz-  hermes config env-path  Show .env file path)getattrr+  r;  rg   rh   exitrR  rn   rq   r.   r-   r  r  r  r  r  GREENr/  rI   r  rQ  YELLOWr  r  REDr  r  r  )argssubcmdr  r  rD  rL  r4  r5  rF  required_missingoptional_missingr  rB  	tools_strr2  r  r  r  s   &                 r=   rT  rT  
  s   T+T2F~6)	6		5dE4(gt,em:;G+GH?@DEHHQK$	6	o 	:	ln	9	e@&++v{{[\ +?24"6"8>k6O%:FLLIJG #&{m5EFD^,--^_`'2K{!eeM6JAA{K"
"!55' 01j0A A{ 	 

 L%5!6 77TUV'	#f+/0 ( L%5!6 77[\]',EJk$))E"I*>)?qAPR		#f+yk:; (
 	 !T?;7>#:#:%4fllCD:G":..ej	2FMMBC / 		7	e/fkkJK"6"8$&{m489%,[MzlJ]^`f`m`mnoeM6;;/0)HX&&
+,ehxj
;VZZHI	 * 	eM6;;/0/557NHdX&&
+,"->CeDIIeBi$8#9:	ehxj<fjjIJ 8 34G%"S011PQSYS`S`ab?@ 	(12#$DE?@FGKLHI?@=>g L
s   1ZZZ#8Z#Z#c                x    V ^8  d   Qh/ ^ \         9   d&   \        \        \        \        ,          3,          ;R&   # )r8   r.  )__conditional_annotations__r   r  r   r;   )r<   s   "r=   r>   r>      s1      Z T#tCy.) [r?   )ra   1r#  )zmodify this Hermes installation)zmodify configuration)r0  r1  r2  r3  )r#   r"   WHATSAPP_ALLOWED_USERSr6  r7  SLACK_ALLOWED_USERS)r]  r   	web_crawl)rl_start_trainingrl  rl_stop_training)ra  rb  rc  rd  )F>   r   r   r  r   gatewayr   r   r   r   r  r   r  r/  r  r   r   >   r  modelsr   r  r   context_lengthrate_limit_delay>   r   r  r   rn  rk  )TF)^rd  r  rC   platformr`  r  r7  rh   r  dataclassesr   pathlibr   typingr   r   r   r   r	   tools.tool_backend_helpersr
   _managed_nous_tools_enabledsystemr  compiler  	frozensetr  r}  hermes_cli.colorsr-   r.   hermes_cli.default_soulr/   rG   rH   rO   rU   rY   r]   rc   rj   hermes_constantsrJ   rn   rq   rw   r~   r   r   r   r  r.  r  r  _hidden_varrq  r  r  r  r  r  r  _VALID_CUSTOM_PROVIDER_FIELDSr  r  r  r  rQ  rV  rb  rt  rx  r  r  r  _COMMENTED_SECTIONSr%  r  r  r$  r&  r  r  r  r  r  r  r  r+  r;  rR  rT  r>   )rd  s   @r=   <module>r~     s%   
  	   
  !  3 3 `oo9,::9:   '*  	 4	
 
 (  9  3  ) +? A\  #  ' )<  (   7  + -? AS  ; =Q    + 3 , 
J
	7W	 ,;
 8; ; --&2	" ]R]] "] !"	]
 ] R
 	4 	]*  %7%f% 	s% 	3	% 	2% 	D% 	b%  	b!%" 	R#%$ 	C%%& 	E'%* 	+%, 	D-%. 	%/%0 	1%8 	"9%> 	(?%H 	DI%+]x c25e
 "5
y]Z 4[]j 7k]n 4T"FDo]@ 5CBr	A]Z Rrr
 	Rrs
 	Rrs
 	Rrr
 	Rrr
 	Rrr
 	Rrr
 	Rrr
g:[]R 5x&;E%UU	qS]r es]| 
F'
 	.0
 	&W

 	3e	
}]j 
4GV
 	[
	k]@ hESCA]P #$Q]^ $T4
 	B
_]~ BB2"]V RW]` a]n bo]v w]| 4 "tT	}]L	  M	]b	 2c	]n	 o	]r	 bs	]z	 R{	]@
 $$x!DurB
A
]Z
  	[
]j
 qk
]x
 ry
]L X "67 E		-    w	6BtEJDw	 W&+D"$78JDw	& U,7DJD'w	6 L"7DJD7w	F ;=tEJDGw	V [&DJDWw	f =.DJDgw	v =.DJDww	F 5AtEJDGw	V 0..DJDWw	f :;tEJDgw	v 8#(DJDww	F 2>tEJDGw	V 9+*DJDWw	f :FtEJDgw	v D$7DJww	D @%rEJEw	R W%>DJSw	` `&rEJDaw	p V()DJDqw	@ 7CtEJDAw	P U')DJDQw	` 6BtEJDaw	p o&7DJqw	~ K9tEJDw	R J- ,.DFSw	b N$%,.DFcw	r F%',.DFsw	B O=tEFDCw	R jMtEFDSw	b   o.tEFDcw	r   j+tEFDsw	B   O+tDFD Cw	R T",;DFSw	b n')$o6DFcw	r \*)$o6EFsw	B	 n')$o6DFC	w	R	 Y1$o6EFS	w	`	 r&:$o6EFa	w	p	 9- "#DFq	w	@
 7"@MDFA
w	P
 I/+"$56DFQ
w	`
 X:5'6DFa
w	p
 M&'DFq
w	~
 \.3DF
w	P G"'"#DFQw	` V@Faw	n ;&'DKow	| l?)EK}w	J @%<DKKw	X P>tEKYw	f  P 	.+DKgw	x  G 	.+DKyw	J L)/EKKw	X F(tDKYw	f SAtEK!gw	t !z0tEK#uw	B (c?tEK*Cw	P P)6EKQw	^ L'tDK_w	l B1tEKmw	z e=tEK{w	H s:tEKDIw	X !\<tEKD#Yw	h Y=tEKDiw	x g=tEKDyw	H f0tEKD Iw	X   L2tEKDYw	h y2tDKD A#tEKD   ]#tEKD k0tEK J.tEK t"tDK N?tEI R/tDI W"tEI VBtEI  VBtEI" #_.tEI% %h+tEI'aw	 r #$$ 	k40 ,8"J	" !   W    w wt0 0._ _D	((<"]6  ! H( V:&0f*Z;|*Z$ $$" "&]@/@P7nFr?   