
    o;iB                       U d Z ddlZddlZddlZddlZddlmZ ddlm	Z	m
Z
mZmZ ddlmZmZmZmZmZ ddlmZmZ ddlmZmZ ddlmZmZ dd	lmZmZ  ej        e           Z! ee"          j#        j#        $                                Z%dd
l&m'Z(m)Z*m+Z,m-Z.m/Z0 g dZ1h dZ2dhdhdZ3e	e4ee4         f         e5d<   de4de4de6fdZ7d Z8de9fdZ:ddl;m<Z= d  e=j>                    D             Z<dddddg dddd d!gd"d#d$d%g d&d'd(d)d*d d+d,d-gdd'd.d/d0d1d2d-gd3d4d5d)d6d7d8d9d-gd:d'd;d)d<d=d>d?d-gd@d'dAdBdCdDdEdFd-gdGd'dHdIdJg dKdKdLdMdIdNg dOdOdLg	dPdQdRdSdTdddUdVg ddWdXdYgdZd[d\d]dVdXd^d_d-gd`dad)dbdcdddedfd-gd`dgd)dhdidjdkdld-gd`dmdndodpdqdrdsd-gd`dtdudvdVdYdwdxgd`gdydzd{ddd|g dd}d~gdddd)dd~ddd-gddgdPdddddg ddddgdd	dd$dg ddddd)ddddd-dddxgddddd)ddddd-gddddd)ddXd^d_d-gdVddddddddddgdddgdPdddddddxddddgdgdPddddg ddgdPddddddddd-dddd-gddgdƜdddddddd-dddd-gdddddddxdddxddddgddgdPd֜Z?dgdgd؜Z@de4fdڄZAde
e4         fdۄZBddeCdee
e4                  de	e4ee4         f         fdބZDdde6de6fdZEdddeCde4de6dee4         fdZFdeCde4dee4         fdZGdde4deCde6fdZHdde4deIdeJdeJfdZKdaLee	e4eJf                  e5d<   de	e4eJf         fdZMdde4dee4         de4dee4         fdZNde4deCfdZOdeIeC         fdZPdeCdeCdeIeC         fdZQde4deCde6fdZRde4deCdeCfdZSdeCdeCde6fdZTdeIdeCdeJfdZUd ZVddd}eVdiZWde4deCdeCde4fdZXd e4deCddfdZYde4fdZZde4deCddfdZ[de4deCddfdZ\deCdeCfdZ]de4fdZ^deCfdZ_de4deCde6fd	Z`de4deCdeCfd
ZadeCdeCfdZbde4fdZcdde6deCfdZddeCfdZedeCde4de
e4         de4fdZfdeCde
e4         de4dee4         fdZgdde9deCde4fdZhd ZidS (  uY  
Unified tool configuration for Hermes Agent.

`hermes tools` and `hermes setup tools` both enter this module.
Select a platform → toggle toolsets on/off → for newly enabled tools
that need API keys, run through provider-aware configuration.

Saves per-platform tool configuration to ~/.hermes/config.yaml under
the `platform_toolsets` key.
    N)Path)DictListOptionalSet)cfg_getload_configsave_configget_env_valuesave_env_value)Colorscolor)apply_nous_managed_defaultsget_nous_subscription_features)fal_key_is_configuredmanaged_nous_tools_enabled)base_url_hostnameis_truthy_value)print_error
print_infoprint_successprint_warningprompt))webu   🔍 Web Search & Scrapingzweb_search, web_extract)browseru   🌐 Browser Automationznavigate, click, type, scroll)terminalu   💻 Terminal & Processeszterminal, process)fileu   📁 File Operationszread, write, patch, search)code_executionu   ⚡ Code Executionexecute_code)visionu    👁️  Vision / Image Analysisvision_analyze)	image_genu   🎨 Image Generationimage_generate)moau   🧠 Mixture of Agentsmixture_of_agents)ttsu   🔊 Text-to-Speechtext_to_speech)skillsu   📚 Skillszlist, view, manage)todou   📋 Task Planningr)   )memoryu   💾 Memoryz!persistent memory across sessions)session_searchu   🔎 Session Searchzsearch past conversations)clarifyu   ❓ Clarifying Questionsr,   )
delegationu   👥 Task Delegationdelegate_task)cronjobu   ⏰ Cron JobszBcreate/list/update/pause/resume/run, with optional attached skills)	messagingu   📨 Cross-Platform Messagingsend_message)rlu   🧪 RL TrainingzTinker-Atropos training tools)homeassistantu   🏠 Home Assistantzsmart home device control)spotifyu   🎵 Spotifyz$playback, search, playlists, library)discordu   💬 Discord (read/participate)z-fetch messages, search members, create thread)discord_adminu   🛡️  Discord Server Adminz&list channels/roles, pin, assign roles)yuanbaou   🤖 Yuanbaozgroup info, member queries, DM>   r2   r$   r5   r4   r6   r3   r5   )r5   r6   _TOOLSET_PLATFORM_RESTRICTIONSts_keyplatformreturnc                 F    t                               |           }|du p||v S )zReturn True if ``ts_key`` is configurable on ``platform``.

    Toolsets without a restriction entry are allowed everywhere (the default).
    N)r8   get)r9   r:   alloweds      </home/ubuntu/.hermes/hermes-agent/hermes_cli/tools_config.py_toolset_allowed_for_platformr@   `   s+    
 -0088Gd?1h'11    c                     t          t                    } d | D             }	 ddlm}m}  |              |            D ]=}|d         |v r|                    |d                    |                     |           >n# t          $ r Y nw xY w| S )u  Return CONFIGURABLE_TOOLSETS + any plugin-provided toolsets.

    Plugin toolsets are appended at the end so they appear after the
    built-in toolsets in the TUI checklist. A plugin whose toolset key
    already appears in ``CONFIGURABLE_TOOLSETS`` is skipped — bundled
    plugins (e.g. ``plugins/spotify``) share their toolset key with the
    built-in entry, and we want the built-in label/description to win.
    Without the dedupe, ``hermes tools`` → "reconfigure existing" would
    list the same toolset twice.
    c                     h | ]\  }}}|	S  rD   .0r9   _s      r?   	<setcomp>z7_get_effective_configurable_toolsets.<locals>.<setcomp>u   s    ...|vq!F...rA   r   discover_pluginsget_plugin_toolsets)listCONFIGURABLE_TOOLSETShermes_cli.pluginsrJ   rK   addappend	Exception)resultseenrJ   rK   entrys        r?   $_get_effective_configurable_toolsetsrU   i   s     '((F..v...D	LLLLLLLL((** 	! 	!EQx4HHU1XMM%    		!
    Ms   AA= =
B
	B
c                      	 ddl m} m}  |              d  |            D             S # t          $ r t	                      cY S w xY w)z3Return the set of toolset keys provided by plugins.r   rI   c                     h | ]\  }}}|	S rD   rD   rE   s      r?   rH   z+_get_plugin_toolset_keys.<locals>.<setcomp>   s    AAA<61aAAArA   )rN   rJ   rK   rQ   setrI   s     r?   _get_plugin_toolset_keysrY      st    LLLLLLLLAA+>+>+@+@AAAA   uus   %( AA)	PLATFORMSc                 4    i | ]\  }}||j         |j        d S )labeldefault_toolsetr\   )rF   kinfos      r?   
<dictcomp>ra      s;       4 0DEE  rA   zText-to-Speechu   🔊zNous Subscriptionsubscriptionz.Managed OpenAI TTS billed to your subscriptionopenaiTr&   VOICE_TOOLS_OPENAI_KEYOPENAI_API_KEY)namebadgetagenv_varstts_providerrequires_nous_authmanaged_nous_featureoverride_env_varszMicrosoft Edge TTSu   ★ recommended · freezGood quality, no API key needededge)rf   rg   rh   ri   rj   z
OpenAI TTSpaidzHigh quality voiceszOpenAI API keyz$https://platform.openai.com/api-keys)keyr   urlzxAI TTSz"Grok voices - requires xAI API keyXAI_API_KEYzxAI API keyzhttps://console.x.ai/xai)rf   rh   ri   rj   
ElevenLabszMost natural voicesELEVENLABS_API_KEYzElevenLabs API keyz+https://elevenlabs.io/app/settings/api-keys
elevenlabszMistral (Voxtral TTS)zMultilingual, native OpusMISTRAL_API_KEYzMistral API keyzhttps://console.mistral.ai/mistralzGoogle Gemini TTSpreviewz,30 prebuilt voices, controllable via promptsGEMINI_API_KEYzGemini API keyz&https://aistudio.google.com/app/apikeygemini	KittenTTSu   local · freez.Lightweight local ONNX TTS (~25MB), no API key	kittentts)rf   rg   rh   ri   rj   
post_setupPiperz0Local neural TTS, 44 languages (voices ~20-90MB)piper)rf   icon	providerszWeb Search & ExtractzSelect Search Provideruc   A free DuckDuckGo search skill is also included — skip this if you don't need a premium provider.u   🔍z-Managed Firecrawl billed to your subscription	firecrawlr   FIRECRAWL_API_KEYFIRECRAWL_API_URL)rf   rg   rh   web_backendri   rk   rl   rm   zFirecrawl Cloudu   ★ recommendedz(Full-featured search, extract, and crawlzFirecrawl API keyzhttps://firecrawl.dev)rf   rg   rh   r   ri   Exaz)Neural search with semantic understandingexaEXA_API_KEYzExa API keyzhttps://exa.aiParallelzAI-powered search and extractparallelPARALLEL_API_KEYzParallel API keyzhttps://parallel.aiTavilyz	free tieru4   Search, extract, and crawl — 1000 free searches/motavilyTAVILY_API_KEYzTavily API keyzhttps://app.tavily.com/homezFirecrawl Self-Hostedu   free · self-hostedz(Run your own Firecrawl instance (Docker)z9Your Firecrawl instance URL (e.g., http://localhost:3002))rp   r   )rf   setup_title
setup_noter   r   Image Generationu   🎨z8Managed FAL image generation billed to your subscriptionr"   FAL_KEYfal)rf   rg   rh   ri   rk   rl   rm   imagegen_backendzFAL.aiz@Pick from flux-2-klein, flux-2-pro, gpt-image, nano-banana, etc.zFAL API keyzhttps://fal.ai/dashboard/keys)rf   rg   rh   ri   r   zBrowser Automationu   🌐z%Nous Subscription (Browser Use cloud)z/Managed Browser Use billed to your subscriptionzbrowser-user   BROWSER_USE_API_KEYagent_browser)	rf   rg   rh   ri   browser_providerrk   rl   rm   r~   zLocal Browserz$Headless Chromium, no API key neededlocal)rf   rg   rh   ri   r   r~   Browserbasez&Cloud browser with stealth and proxiesBROWSERBASE_API_KEYzBrowserbase API keyzhttps://browserbase.comBROWSERBASE_PROJECT_IDzBrowserbase project IDbrowserbasezBrowser Usez#Cloud browser with remote executionzBrowser Use API keyzhttps://browser-use.com	FirecrawlCamofoxu   free · localz)Anti-detection browser (Firefox/Camoufox)CAMOFOX_URLzCamofox server URLzhttp://localhost:9377z)https://github.com/jo-inc/camofox-browser)rp   r   defaultrq   camofoxz
Smart Homeu   🏠zHome AssistantzREST API integration
HASS_TOKENz&Home Assistant Long-Lived Access TokenHASS_URLzHome Assistant URLzhttp://homeassistant.local:8123)rp   r   r   )rf   rh   ri   Spotifyu   🎵zSpotify Web APIu%   PKCE OAuth — opens the setup wizardr4   )rf   rh   ri   r~   zRL Trainingu   🧪)      zTinker / AtroposzRL training platformTINKER_API_KEYzTinker API keyz/https://tinker-console.thinkingmachines.ai/keysWANDB_API_KEYzWandB API keyzhttps://wandb.ai/authorizerl_training)rf   r   requires_pythonr   zLangfuse Observabilityu   📊zLangfuse Cloudz$Hosted Langfuse (cloud.langfuse.com)HERMES_LANGFUSE_PUBLIC_KEYzLangfuse public key (pk-lf-...)zhttps://cloud.langfuse.comHERMES_LANGFUSE_SECRET_KEYzLangfuse secret key (sk-lf-...)langfusezLangfuse Self-HostedzSelf-hosted Langfuse instanceHERMES_LANGFUSE_BASE_URLz0Langfuse server URL (e.g. http://localhost:3000)zhttp://localhost:3000)r&   r   r"   r   r3   r4   r2   r   )OPENROUTER_API_KEYzhttps://openrouter.ai/keys)r    r$   post_setup_keyc                    ddl }| dv rt          dz  dz  }|                    d          }|                    d          }|                                s|rt	          d           ddl}|                    g d	d
d
t          t                              }|j        dk    rt          d           nddl
m} t          d |             d           |j        r1t	          d|j                                        dd                     n%|                                st          d           dS | dk    rdS 	 ddlm}m}	 n*# t$          $ r}
t          d|
            Y d}
~
dS d}
~
ww xY w |            rt          d           dS  |	            r/t          d           t	          d           t	          d           dS |st          d           dS t	          d           ddl}t          dz  dz  dz  }t&          j        dk    r+|                    d          }|                                r|}|                                rt          |          dd gn|d!ddd g}	 |                    |d
d
t          t                    d"#          }|j        dk    rt          d$           ddlm} d|_        n{t          d%           |j        p|j        pd&                                                                d'd         }|D ]}t	          d|dd                     t	          d(           dS dS # |j        $ r" t          d)           t	          d(           Y dS t$          $ r,}
t          d*|
            t	          d(           Y d}
~
dS d}
~
ww xY w| d+k    r,t          dz  d,z  d-z  }|                                s|                    d          rjt	          d.           ddl}|                    g d	d
d
t          t                              }|j        dk    rt          d/           nt          d0           |                                r>t	          d1           t	          d2           t	          d3           t	          d4           dS |                    d          s t          d5           t	          d6           dS dS | d7k    r5	 t7          d7           t          d8           dS # t8          $ r Y nw xY wddl}t	          d9           d:}	 |                    t&          j        d;d<dd=|d>d?gd
d
d@A          }|j        dk    r.t          dB           t	          dC           t	          dD           nUt          dE           t	          d|j                                        dd@                     t	          dF| dG           dS dS # |j        $ r& t          dH           t	          dF| dG           Y dS w xY w| dIk    r;	 t7          dI           t          dJ           n# t8          $ r ddl}t	          dK           	 |                    t&          j        d;d<dd=dLd?gd
d
d@A          }|j        dk    rt          dM           nRt          dN           t	          d|j                                        dd@                     t	          dO           Y dS n0# |j        $ r# t          dP           t	          dO           Y Y dS w xY wY nw xY wt	          dQ           t	          dR           t	          dS           dS | dTk    rddUlm} 	 ddVl m!} n9# t$          $ r,}
t          dW|
            t	          dX           Y d}
~
dS d}
~
ww xY wt	          dY           	  | |ddddZd[                     t          d\           dS # tD          $ r,}
t          d]|
            t	          d^           Y d}
~
dS d}
~
wt$          $ r,}
t          d_|
            t	          dX           Y d}
~
dS d}
~
ww xY w| d`k    r\	 t7          da           dS # t8          $ r< t          dbz  }|                                r|dcz                                  rt	          dd           ddl}|                    de          }|r7|                    |d<ddft&          j        dgt          |          gd
d
h          }n5|                    t&          j        d;d<ddgt          |          gd
d
h          }|j        dk    rt          di           nRt          dj           t	          dk           n0t          dl           t	          dm           t	          dk           Y dS Y dS Y dS w xY w| dnk    rI	 t7          dn           t          do           nv# t8          $ ri ddl}t	          dp           |                    t&          j        d;d<ddnd?gd
d
dqA          }|j        dk    rt          dr           nt          ds           Y nw xY w	 ddtl#m$}m%}  |            }du|v sdn|v rt          dv           n/|&                    du            ||           t          dw           n8# t$          $ r+}
t          dx|
            t	          dy           Y d}
~
nd}
~
ww xY wt	          dz           t	          d{           dS dS )|zBRun post-setup hooks for tools that need extra installation steps.r   N)r   r   node_moduleszagent-browsernpmnpxz8    Installing Node.js dependencies for browser tools...)r   installz--silentT)capture_outputtextcwdz"    Node.js dependencies installeddisplay_hermes_homez*    npm install failed - run manually: cd z/hermes-agent && npm installz         zV    Node.js not found - browser tools require: npm install (in hermes-agent directory)r   )_chromium_installed_running_in_dockerz%    Could not check Chromium status: z&    Chromium browser already installedz5    Chromium is missing but you're running in Docker.z6    Pull the latest image to get the bundled Chromium:z:      docker pull ghcr.io/nousresearch/hermes-agent:latestzT    npx not found - install Chromium manually: npx agent-browser install --with-depsz5    Installing Chromium (~170MB one-time download)...z.binwin32z.cmdr   z--with-depsz-yiX  )r   r   r   timeoutz    Chromium installedz    Chromium install failed: z7    Run manually: npx agent-browser install --with-depsz'    Chromium install timed out (>10min)z    Chromium install failed: r   z@askjozcamofox-browserz(    Installing Camofox browser server...z    Camofox installedz2    npm install failed - run manually: npm installz    Start the Camofox server:z       npx @askjo/camofox-browserz4    First run downloads the Camoufox engine (~300MB)zV    Or use Docker: docker run -p 9377:9377 -e CAMOFOX_PORT=9377 jo-inc/camofox-browserz2    Node.js not found. Install Camofox via Docker:zI      docker run -p 9377:9377 -e CAMOFOX_PORT=9377 jo-inc/camofox-browserr}   z"    kittentts is already installedz6    Installing kittentts (~25-80MB model, CPU-only)...z^https://github.com/KittenML/KittenTTS/releases/download/0.8.1/kittentts-0.8.1-py3-none-any.whlz-mpipz-U	soundfilez--quieti,  )r   r   r   z    kittentts installedz>    Voices: Jasper, Bella, Luna, Bruno, Rosie, Hugo, Kiki, LeozO    Models: KittenML/kitten-tts-nano-0.8-int8 (25MB), micro (41MB), mini (80MB)z    kittentts install failed:z,    Run manually: python -m pip install -U 'z' soundfilez'    kittentts install timed out (>5min)r   z"    piper-tts is already installedzI    Installing piper-tts (~14MB wheel, voices downloaded on first use)...z	piper-ttsz    piper-tts installedz    piper-tts install failed:z4    Run manually: python -m pip install -U piper-ttsz'    piper-tts install timed out (>5min)zE    Default voice: en_US-lessac-medium (downloaded on first TTS call)zU    Full voice list: https://github.com/OHF-Voice/piper1-gpl/blob/main/docs/VOICES.mdzE    Switch voices by setting tts.piper.voice in ~/.hermes/config.yamlr4   )SimpleNamespace)login_spotify_commandz!    Could not load Spotify auth: z%    Run manually: hermes auth spotifyz    Starting Spotify login...F)	client_idredirect_uriscope
no_browserr   z    Spotify authenticatedz$    Spotify login did not complete: z"    Run later: hermes auth spotifyz    Spotify login failed: r   tinker_atroposztinker-atroposzpyproject.tomlz*    Installing tinker-atropos submodule...uvz--pythonz-e)r   r   z    tinker-atropos installedz1    tinker-atropos install failed - run manually:z*      uv pip install -e "./tinker-atropos"z-    tinker-atropos submodule not found - run:z-      git submodule update --init --recursiver   z"    langfuse SDK already installedz    Installing langfuse SDK...x   z    langfuse SDK installeduF       langfuse SDK install failed — run manually: pip install langfuse)_get_enabled_set_save_enabled_setzobservability/langfusez1    Plugin observability/langfuse already enabledz)    Plugin observability/langfuse enabledz+    Could not enable plugin automatically: z>    Run manually: hermes plugins enable observability/langfusez.    Restart Hermes for tracing to take effect.z    Verify: hermes plugins list)'shutilPROJECT_ROOTwhichexists_print_info
subprocessrunstr
returncode_print_successhermes_constantsr   _print_warningstderrstriptools.browser_toolr   r   rQ   sysr:   with_suffixbrowser_tool_cached_chromium_installedstdout
splitlinesTimeoutExpired
__import__ImportError
executabletypesr   hermes_cli.authr   
SystemExithermes_cli.plugins_cmdr   r   rO   )r   r   r   npm_binnpx_binr   rR   r   r   r   exclocal_ablocal_ab_wininstall_cmd_bttaillinecamofox_dir	wheel_urlr   r   
tinker_diruv_binr   r   enableds                             r?   _run_post_setupr     s   MMM999#n4F,,u%%,,u%%""$$ 	 	RSSS^^...#$C4E4E $  F  A%%CDDDD@@@@@@L_L_LaLa  A  A  A= H F)<)<)>)>tt)D F FGGG$$&& 	stttF
 _,,F		          	 	 	H3HHIIIFFFFF	    	CDDDF 
	G   H   L   F 	f   FKLLL  .069OK<7""#//77L""$$ ('   LS]]I}554)]K 	
	S^^#$C4E4Es $  F  A%%7888 10000015..=>>><<"CCEEPPRRSUSVSVW  7 7D 5dsd 5 56666UVVVVV /. ( 	S 	S 	SDEEEQRRRRRR 	S 	S 	S@3@@AAAQRRRRRRRRR	S 
9	$	$"^3h>ARR!!## 
	UU(;(; 
	UBCCC^^...#$C4E4E $  F  A%%67777STTT 	e7888:;;;NOOOpqqqqqe$$ 	eOPPPcddddd	e 	e 
;	&	&	{###?@@@F 	 	 	D	LMMM5 		_^^uiy+W`a#$ $  F  A%%8999\]]]mnnnn>???BV]%8%8%:%:4C4%@BBCCCa9aaabbbbb	 on
 ( 	_ 	_ 	_DEEE]y]]]^^^^^^	_ 
7	"	"	w?@@@@ 	 	 	cddd#^T5)T;PYZ#'dC (   $))"#<===="#BCCC F)<)<)>)>tt)D F FGGG VWWWFF > ,   HIIIRSSS >=	& 	[\\\klll[\\\\\	9	$	$ 	*)))))	======= 	 	 	DsDDEEE?@@@FFFFF	 	3444	A!!//T $# # #    677777 	> 	> 	> G#GGHHH<========= 	A 	A 	A===>>>?@@@@@@@@@	A 
=	(	(	J'((((( 	J 	J 	J%(88J  "" J
5E(E'M'M'O'O JHIII!!!!d++ 	'^^	:s~tUXYcUdUde'+$ ,  FF
 (^^uis:W'+$ ,  F $))"#ABBBB"#VWWW LMMMMNOOOKLLLHIIIIII	 NMM CBB#	J4 
:	%	%	iz"""?@@@@ 
	i 
	i 
	i8999^^uiYO#$ $  F  A%%;<<<<ghhh
	i	ZRRRRRRRR&&((G'722jG6K6KRSSSS4555!!'***JKKK 	Z 	Z 	ZNNNOOOXYYYYYYYY	Z 	DEEE566666A 
&	%s  :E 
E*E%%E* CL1 1(N	N%!NNS/ /
S<;S<B7W ,X ?X X* *\B[ \ (\\\\\] 
^#!^

^"(_ 
`6!_==`6
!`11`6a D=ff$g A0h65h6:Aj 
k	!kk	c                  t   dg} t          d          r|                     d           t          d          r|                     d           t          d          r|                     d           t          d          r|                     d	           t          d
          r|                     d           | S )zBReturn platform keys that are configured (have tokens or are CLI).cliTELEGRAM_BOT_TOKENtelegramDISCORD_BOT_TOKENr5   SLACK_BOT_TOKENslackWHATSAPP_ENABLEDwhatsapp	QQ_APP_IDqqbot)r   rP   )r   s    r?   _get_enabled_platformsr    s    gG)** #z"""()) "y!!!&''  w'(( #z"""[!!  wNrA   config	platformsc                 Z    |t                      }i }|D ]}t          | |          ||<   |S )zReturn a summary of enabled toolsets per platform.

    When ``platforms`` is None, this uses ``_get_enabled_platforms`` to
    auto-detect platforms. Tests can pass an explicit list to avoid relying
    on environment variables.
    )r  _get_platform_tools)r  r	  summarypkeys       r?   _platform_toolset_summaryr    sC     *,,	#%G : :+FD99NrA   r   c                     | |S t          | t                    r| S t          | t                    r| dk    S t          | t                    r2|                                                                 }|dv rdS |dv rdS |S )z=Parse bool-like config values used by tool/platform settings.Nr   >   1onyestrueT>   0noofffalseF)
isinstanceboolintr   r   lower)valuer   lowereds      r?   _parse_enabled_flagr    s    }% % z% ++--%%''00041115NrA   include_default_mcp_serversr   c                X
  #$% ddl m}m} |                     d          pi }|                              }|t	          |t
                    s-t                                        }|r	|d         }nd }|g}d |D             }d t          D             #t                      %d	 t          	                                D             $t          #fd
|D                       }	|	r#fd|D             }
n
t                      }|D ] }|                     ||                     !t                      }
t          D ][\  }}}t          |          st           ||                    }|r*|                    |          r|
                    |           \t          t                     }|v rt"          vr|                               d|v r)t'          j        d          r|                    d           |
|z  }
t                                        }|r|d         nd }t           ||                    }t                      }#D ] }|                     ||                     !t                      }|
D ] }|                     ||                     !#%z  $z  }|d |D             z  }|t          t                     hz
  z  }|                                D ]\  }}||v r
|                    d          r t           ||                    }|r|                    |          sP|                    |          rf|                    |          s*|
                    |           |                    |           %r{|                     di           }t          |                    g                     }%D ]?}||v r|
                    |           |t           v r&||vr|
                    |           @#$%fd|D             }|                     d          pi }d |                                D             }d|v r+t                      }|
                    ||z
  dhz
             n||z  }|
                    ||z
             |r2|sd|v r|
                    |           n+|
                    |           n|
                    |           |                     d          pi } |                     d          pg }!|!rd |!D             }"|
|"z  }
|
S )zBResolve which individual toolset names are enabled for a platform.r   )resolve_toolsetTOOLSETSplatform_toolsetsNr^   hermes-c                 ,    g | ]}t          |          S rD   r   rF   tss     r?   
<listcomp>z'_get_platform_tools.<locals>.<listcomp>=  s    555SWW555rA   c                     h | ]\  }}}|	S rD   rD   rE   s      r?   rH   z&_get_platform_tools.<locals>.<setcomp>?      JJJLFAqJJJrA   c                     h | ]
}|d          S r^   rD   rF   ps     r?   rH   z&_get_platform_tools.<locals>.<setcomp>A      NNNaQ01NNNrA   c              3       K   | ]}|v V  	d S NrD   )rF   r)  configurable_keyss     r?   	<genexpr>z&_get_platform_tools.<locals>.<genexpr>H  s)      NN"b$55NNNNNNrA   c                 <    h | ]}|v t          |          |S rD   r@   )rF   r)  r4  r:   s     r?   rH   z&_get_platform_tools.<locals>.<setcomp>K  s?     
 
 
&&&+HX+V+V& &&&rA   r3   r   c                 <    h | ]}|                     d           |S )r%  )
startswith)rF   r_   s     r?   rH   z&_get_platform_tools.<locals>.<setcomp>  s)    <<<1ALL$;$;<Q<<<rA   includesknown_plugin_toolsetsc                 ,    h | ]}|vr
|vr|v|S rD   rD   )rF   r)  r4  platform_default_keysplugin_ts_keyss     r?   rH   z&_get_platform_tools.<locals>.<setcomp>  sH       &&&n$$+++	 	 ,++rA   mcp_serversc                     h | ]N\  }}t          |t                    t          |                    d d          d          ?t	          |          OS )r   Tr   )r  dictr  r=   r   )rF   rf   
server_cfgs      r?   rH   z&_get_platform_tools.<locals>.<setcomp>  sg       D*j$''  
y$ ? ?NNN	D		  rA   no_mcpagentdisabled_toolsetsc                 ,    h | ]}t          |          S rD   r'  r(  s     r?   rH   z&_get_platform_tools.<locals>.<setcomp>  s    <<<BB<<<rA   )toolsetsr"  r#  r=   r  rL   rZ   rM   rY   valuesanyrX   updater@   issubsetrO   _DEFAULT_OFF_TOOLSETSr8   removeosgetenvitems)&r  r:   r   r"  r#  r$  toolset_names	plat_info
default_tshas_explicit_configenabled_toolsetsall_tool_namests_namer9   rG   ts_toolsdefault_off
_plat_info_default_tsplatform_tool_universeconfigurable_tool_universeckclaimedskipts_def	known_mapknown_for_platformptsexplicit_passthroughr?  enabled_mcp_serversexplicit_mcp_servers	agent_cfgrF  disabled_setr4  r=  r>  s&    `                                 @@@r?   r  r  &  sx    32222222

#677=2%))(33MJ}d$C$CMM(++	 	."#45JJ .8--J# 65}555MJJ4IJJJ-//NNN9;K;K;M;MNNN NNNNNNNNN %(
 
 
 
 
&
 
 
 $ 	< 	<G!!//'":":;;;;551 	- 	-LFAq0BB ??62233H -H--n== - $$V,,,/00 {""x7U'U'Ux((( k))bi.E.E)///K' x((J3=W*.//CWXCWCWK !=!=>>!$ ? ?"))//"*=*=>>>>eeG" 0 0v..////~-0EED<<<<<<DC%&&(33D"..** % %T>>::j!! 	v..// 	x001GHH 	788 	  )) 	%  (((NN8$$$  *JJ6;;	 x!<!<==! 		* 		*Cm## $$S))))---... $$S)))
        **]++1rK  + 1 1 3 3   =  "uu 47J JhZ WXXXX36II 47J JKKK" 6 	98}#<#<##$89999##$78888 4555 

7##)rI!&9::@b )<<*;<<<L(rA   enabled_toolset_keysc                 J   |                      di            fd|D             }d t          D             t                      }|z  d t                                          D             t          | dg           }t          |t                    sg }d |D             }fd|D             }|                    d           t          ||z            | d         <   |r.|                      d	i            t          |          | d	         <   t          |            d
S )zSave the selected toolset keys for a platform to config.

    Preserves any non-configurable toolset entries (like MCP server names)
    that were already in the config for this platform.
    r$  c                 4    h | ]}t          |          |S rD   r7  )rF   r)  r:   s     r?   rH   z'_save_platform_tools.<locals>.<setcomp>  s9       (X66
  rA   c                     h | ]\  }}}|	S rD   rD   rE   s      r?   rH   z'_save_platform_tools.<locals>.<setcomp>  r,  rA   c                     h | ]
}|d          S r.  rD   r/  s     r?   rH   z'_save_platform_tools.<locals>.<setcomp>  r1  rA   rA  c                 ,    g | ]}t          |          S rD   r'  r(  s     r?   r*  z(_save_platform_tools.<locals>.<listcomp>  s    ===RR===rA   c                 $    h | ]}|v|v
|S rD   rD   )rF   rT   r4  r=  s     r?   rH   z'_save_platform_tools.<locals>.<setcomp>  s:       )))e;P.P.P 	.P.P.PrA   rD  r;  N)
setdefaultrM   rY   rZ   rI  r   r  rL   discardsortedr
   )r  r:   rk  plugin_keysexisting_toolsetspreserved_entriesr4  r=  s    `    @@r?   _save_platform_toolsrx    s    )2...
   )   KJ4IJJJ*,,K$
 ON9;K;K;M;MNNN  (;XrRRR'.. ==+<===    ,   h''' -33GJ[3[,\,\F)  H126664:;4G4G&'1rA   c                 @   |t                      }| dk    r*	 ddlm}  |            \  }}}|duS # t          $ r Y dS w xY w| dv r;t	          |          }|j                            |           }|r|j        s|j        rdS t                              |           }|rLt          ||          D ]9}	|	                    dg           }
|
s dS t          d	 |
D                       r dS :dS t                              | g           }|sdS t          d
 |D                       S )z6Check if a toolset's required API keys are configured.Nr    r   )resolve_vision_provider_clientF>   r&   r   r   r"   Tri   c              3   @   K   | ]}t          |d                    V  dS rp   Nr   )rF   es     r?   r5  z$_toolset_has_keys.<locals>.<genexpr>+  s.      ==q=5**======rA   c              3   :   K   | ]\  }}t          |          V  d S r3  r}  )rF   varrG   s      r?   r5  z$_toolset_has_keys.<locals>.<genexpr>3  s.      ==fc1}S!!======rA   )r	   agent.auxiliary_clientrz  rQ   r   featuresr=   	availablemanaged_by_nousTOOL_CATEGORIES_visible_providersallTOOLSET_ENV_REQUIREMENTS)r9   r  rz  	_providerclient_modelr  featurecatproviderri   requirementss               r?   _toolset_has_keysr    s   ~	MMMMMM(F(F(H(H%Ivv%% 	 	 	55	 7771&99#''// 	) 	W-D 	4 

f
%
%C
 *377 	 	H||J33H tt==H===== ttu ,//;;L t========s   0 
>>questionchoicesc                 ,    ddl m}  || |||          S )z?Single-select menu (arrow keys). Delegates to curses_radiolist.r   )curses_radiolist)selectedcancel_returns)hermes_cli.curses_uir  )r  r  r   r  s       r?   _prompt_choicer  8  s/    555555HgPWXXXXrA   _tool_token_cachec                  "   t           t           S 	 ddl} |                     d          }n3# t          $ r& t                              d           i a t           cY S w xY w	 ddl}ddlm} n3# t          $ r& t                              d           i a t           cY S w xY wi }|	                                D ]U}|
                    |          }|r<t          j        d|d          }t          |                    |                    ||<   V|a t           S )	aL  Return estimated token counts per individual tool name.

    Uses tiktoken (cl100k_base) to count tokens in the JSON-serialised
    OpenAI-format tool schema.  Triggers tool discovery on first call,
    then caches the result for the rest of the process.

    Returns an empty dict when tiktoken or the registry is unavailable.
    Nr   cl100k_basez4tiktoken unavailable; skipping tool token estimation)registryz4Tool registry unavailable; skipping token estimationfunction)typer  )r  tiktokenget_encodingrQ   loggerdebugmodel_toolstools.registryr  get_all_tool_names
get_schema_jsondumpslenencode)r  encr  r  countsrf   schemar   s           r?   _estimate_tool_tokensr  D  sY    $  !##M22 ! ! !KLLL    !
!+++++++ ! ! !KLLL    !
  F++-- 1 1$$T** 	1 ;
GGHHDszz$//00F4Ls!   * -AA
A) )-BBr   platform_labelr   c                    ddl m} ddlm t	                      t                      }fd|D             g }D ]j\  }}}d}	t          |          s6t                              |          st                              |          rd}	|
                    | d| d|	            kfd	t                    D             }
d
}r"d D             dt          dt          ffd} |d|  ||
|
|          }fd|D             S )zIMulti-select checklist of toolsets. Returns set of selected toolset keys.r   curses_checklist)r"  c                 B    g | ]\  }}}t          |          |||fS rD   r7  rF   r_   ldr:   s       r?   r*  z-_prompt_toolset_checklist.<locals>.<listcomp>x  E       q!Q(H55	
Aq	  rA   r   z  [no API key]  ()c                 *    h | ]\  }\  }}}|v |S rD   rD   )rF   ir9   rG   r   s       r?   rH   z,_prompt_toolset_checklist.<locals>.<setcomp>  s8       a&!QW 	
rA   Nc                     g | ]\  }}}|	S rD   rD   rE   s      r?   r*  z-_prompt_toolset_checklist.<locals>.<listcomp>  s    888lfa6888rA   chosenr;   c                     t                      }| D ]&}|                     |                              't          fd|D                       }|dk    r
d|dz  ddS d| dS )Nc              3   D   K   | ]}                     |d           V  dS )r   Nr=   )rF   rf   tool_tokenss     r?   r5  z?_prompt_toolset_checklist.<locals>.status_fn.<locals>.<genexpr>  s1      GGTa00GGGGGGrA   i  zEst. tool context: ~z.1fzk tokensz tokens)rX   rK  sum)r  	all_toolsidxtotalr"  r  ts_keyss       r?   	status_fnz,_prompt_toolset_checklist.<locals>.status_fn  s     UUI @ @  !>!>????GGGGYGGGGGE}}HedlHHHHH8%8888rA   z
Tools for )r  r  c                 ,    h | ]}|         d          S r   rD   )rF   r  	effectives     r?   rH   z,_prompt_toolset_checklist.<locals>.<setcomp>  s!    ,,,IaLO,,,rA   )r  r  rH  r"  r  rU   r  r  r=   r  rP   	enumeraterX   r   )r  r   r:   r  effective_alllabelsr9   ts_labelts_descsuffixpre_selectedr  r  r  r"  r  r  s    ``          @@@@r?   _prompt_toolset_checklistr  n  s   555555(((((( ())K8::M   #0  I
 F%. : :!' (( 	&o.A.A&.I.I 	&MeMiMijpMqMq 	&%F88g88889999   #,Y#7#7  L I 988i888	9c 	9c 	9 	9 	9 	9 	9 	9 	9 	9 %^%%#  F -,,,V,,,,rA   c                     t                               |           }|rt          | ||           dS t          |            dS )zConfigure a toolset - provider selection + API keys.
    
    Uses TOOL_CATEGORIES for provider-aware config, falls back to simple
    env var prompts for toolsets not in TOOL_CATEGORIES.
    N)r  r=   _configure_tool_category_configure_simple_requirements)r9   r  r  s      r?   _configure_toolsetr    sM     

f
%
%C
 / f55555 	'v.....rA   c            
      
   	 ddl m}  ddlm}  |              |             }n# t          $ r g cY S w xY wg }|D ]}t          |dd          dk    r	 |                                }n# t          $ r Y :w xY wt          |t                    sT|	                    |
                    d|j                  |
                    dd          |
                    d	d          |
                    d
g           |j        d           |S )uV  Build picker-row dicts from plugin-registered image gen providers.

    Each returned dict looks like a regular ``TOOL_CATEGORIES`` provider
    row but carries an ``image_gen_plugin_name`` marker so downstream
    code (config writing, model picker) knows to route through the
    plugin registry instead of the in-tree FAL backend.

    FAL is skipped — it's already exposed by the hardcoded
    ``TOOL_CATEGORIES["image_gen"]`` entries. When FAL gets ported to
    a plugin in a follow-up PR, the hardcoded entries go away and this
    function surfaces it alongside OpenAI automatically.
    r   list_providers_ensure_plugins_discoveredrf   Nr   rg   r   rh   ri   )rf   rg   rh   ri   image_gen_plugin_name)agent.image_gen_registryr  rN   r  rQ   getattrget_setup_schemar  rB  rP   r=   display_namerf   )r  r  r   rowsr  r  s         r?   _plugin_image_gen_providersr    sb   ;;;;;;AAAAAA""$$$"N$$		   			 D 
 
8VT**e33	..00FF 	 	 	H	&$'' 	

68+@AAGR00zz%,,"JJz266)1 	
 	
 	
 	
 Ks    # 22A''
A43A4r  c                 z   t          |          }g }|                     dg           D ]X}|                    d          rt                      s&|                    d          r|j        sC|                    |           Y|                     d          dk    r!|                    t                                 |S )zBReturn provider entries visible for the current auth/config state.r   rl   rk   rf   r   )r   r=   r   nous_auth_presentrP   extendr  )r  r  r  visibler  s        r?   r  r    s    -f55HGGGK,, ! !<<.// 	8R8T8T 	<<,-- 	h6P 	x     wwv,,,244555NrA   c                    t                               |           }|st          | |           S | dk    r0|                    di           }t          |t                     pd|vS | dk    r0|                    di           }t          |t                     pd|vS | dk    r0|                    di           }t          |t                     pd|vS | dk    rot                      rdS 	 d	d
lm} d	dlm	}  |              |            D ]*}	 |
                                r dS # t          $ r Y 'w xY wn# t          $ r Y nw xY wdS t          | |           S )zBReturn True when enabling this toolset should open provider setup.r&   r  r   backendr   cloud_providerr"   Fr   r  r  T)r  r=   r  r  rB  r   r  r  rN   r  is_availablerQ   )	r9   r  r  tts_cfgweb_cfgbrowser_cfgr  r  r  s	            r?   #_toolset_needs_configuration_promptr    s   


f
%
%C 5$VV4444**UB''gt,,,I
'0II**UB''gt,,,H	0HHjjB//k4000W4DK4WW !"" 	5	??????EEEEEE&&(((*N,,  ,,.. %$uu%    H	  	 	 	D	t 0000s<   '"D3 
D"D3 !D3 "
D/,D3 .D//D3 3
E ?E c                    |                     dd          }|d         }t          ||          }|                     d          r|d         }t          j        |k     rht	                       t          d| d|d          d|d	          d
t          j        j         dt          j        j         d           t          d           dS t          |          d	k    r|d         }t	                       t	          t          d| d| d|d          dt          j                             |                     d          rt          d|d                     |                     d          rt          d|d                     t          ||           dS t	                       |                     dd          }t	          t          d| d| d| dt          j                             |                     d          rt          d|d                     t	                       g }	|D ]}
|
                     d          rd|
d          dnd}|
                     d          rd|
d          nd}d}|
                     dg           }|rt          d |D                       rt          |
|          rd}n|sd}nd}|	                    |
d          | | |            |	                    d            t#          ||          }t%          d| d!|	|          }|t          |          k    rt          d"|            dS t          ||         |           dS )#z2Configure a tool category with provider selection.r   r   rf   r     z requires Python r   .   z+ (current: r  z3  Upgrade Python and reinstall to enable this tool.N  ---   () ---rh   r   r   zChoose a providerz - z ---rg    []    — ri   c              3   @   K   | ]}t          |d                    V  dS r|  r}  rF   vs     r?   r5  z+_configure_tool_category.<locals>.<genexpr>D  .      "M"Mq=5#:#:"M"M"M"M"M"MrA   	 [active] [configured]u(   Skip — keep defaults / configure later:z
  Skipped )r=   r  r   version_infoprint_print_errormajorminorr   r  r   r   CYAN_configure_providerr  _is_provider_activerP   _detect_active_provider_indexr  )r9   r  r  r   rf   r   reqr  titleprovider_choicesr0  rg   rh   
configuredri   default_idxprovider_idxs                    r?   r  r    s   7762Dv;D"3//I ww !! #$c!!GGG  Ed  E  ESV  E  Ec!f  E  ERURbRh  E  Eknk{  lB  E  E  E  F  F  FMNNNF
9~~Q<eCTCCDCCHV,<CCCV[QQRRR<< 	0.Xe_..///77<   	20S.00111Hf----- 	':;;e8T88D88U888&+FFGGG77<   	20S.00111  	L 	LA*+%%..@&7&&&&bE()e<$!E($$$"CJuuZ,,H 1s"M"MH"M"M"MMM 1&q&11 1!,JJ! 1!#JJ!0J##qy$J%$J$Jj$J$JKKKK 	 JKKK 4IvFF%m5mmm5E{SS 3y>>))+T++,,,FIl3V<<<<<rA   r  c                    |                      d          }|rD|                     di           }t          |t                    o|                     d          |k    S |                      d          }|rZt          |          }|j                             |          }|dS |dk    r|                     di           }t          |t                    rV|                     d          }|dvrdS |                     d          &t          |                     d          d	          sdS |j        S |                      d
          r"|j        ot          |dd          | d
         k    S d| v r$t          |dd          }|j        o| d         |k    S |                      d          r$t          |dd          }|j        o|| d         k    S |j        S |                      d
          rt          |dd          | d
         k    S d| v rt          |dd          }| d         |k    S |                      d          rt          |dd          }|| d         k    S |                      d          rw|                     di           }t          |t                    sdS |                     d          }| d         dk    o(|dv o$t          |                     d          d	           S dS )z>Check if a provider entry matches the currently active config.r  r"   r  rl   NFNr   r   use_gatewayrA  rj   r&   r   r   r  r   r   r  r   r   )r=   r  rB  r   r  r   r  r   )	r  r  plugin_name	image_cfgmanaged_featurer  r  configured_providercurrents	            r?   r  r  ]  s/   ,,677K XJJ{B//	)T**Wy}}Z/H/HK/WWll#9::O '1&99#''88?5k))

;33I)T** !&/mmJ&?&?#&.??? 5==//;OT]TaTaboTpTpz  EA  EA  EA; 5**<<'' 	' SFE:66(>:RR ))fi1ABBG*Vx8J/Kw/VV<<&& 	RfeY77G*Qw(=:Q/QQ&&||N## Nvuj11Xn5MMMX%%&)-=>>*+w66||M"" 2&%33(=111||&'' 	
JJ{B//	)T** 	5'mmJ77'(E1 Q#'88Q#IMM-$@$@%PPPP	

 5rA   r   c                     t          |           D ]N\  }}t          ||          r|c S |                    dg           }|rt          d |D                       r|c S OdS )z8Return the index of the currently active provider, or 0.ri   c              3   @   K   | ]}t          |d                    V  dS r|  r}  r  s     r?   r5  z0_detect_active_provider_index.<locals>.<genexpr>  s.      FFM!E(33FFFFFFrA   r   )r  r  r=   r  )r   r  r  r0  ri   s        r?   r	  r	    s    )$$  1q&)) 	HHH55R(( 	FFXFFFFF 	HHH1rA   c                      ddl m} m} | |fS )z5Lazy-load the FAL model catalog from the tool module.r   
FAL_MODELSDEFAULT_MODEL)tools.image_generation_toolr  r  r  s     r?   _fal_model_catalogr    s%    EEEEEEEE}$$rA   )display
config_key
catalog_fnmodel_idmetawidthsc           
          | d|d          d|                     dd          d|d          d|                     dd          d|d          d|                     dd           S )zIFormat a single picker row with column-aligned speed / strengths / price.<modelr  speedr   	strengthspricer  )r#  r$  r%  s      r?   _format_imagegen_model_rowr,    s      	#fWo 	#* 	# 	#88GR  	##)'?	#7	# 	#88K$$	#'-k':	#?	# 	# 88GR  	# 	#rA   backend_namec           	         t                               |           }|sdS  |d                     \  }sdS |d         }|                    |i           }t          |t                    si }|||<   |                    d          p|vr|t                                                    }gfd|D             z   }t          d |D                       t          fd|D             d	          t          fd
|D             d	          d}t                       ddd|d          ddd|d          ddd|d          d}	t          t          |	t          j                             g }
|D ]9}t          ||         |          }|k    r|dz  }|
                    |           :t          d|d          d|
d	          }||         }||d<   t          d|            dS )u   Prompt the user to pick a model for the given imagegen backend.

    Writes selection to ``config[backend_config_key]["model"]``. Safe to
    call even when stdin is not a TTY — curses_radiolist falls back to
    keeping the current selection.
    Nr"  r!  r(  c                      g | ]
}|k    |S rD   rD   rF   mcurrent_models     r?   r*  z-_configure_imagegen_model.<locals>.<listcomp>  #     L L Lqm9K9K9K9K9KrA   c              3   4   K   | ]}t          |          V  d S r3  r  rF   r1  s     r?   r5  z,_configure_imagegen_model.<locals>.<genexpr>  (      //SVV//////rA   c              3   j   K   | ]-}t          |                             d d                    V  .dS r)  r   Nr  r=   rF   r1  catalogs     r?   r5  z,_configure_imagegen_model.<locals>.<genexpr>  =      JJ1c'!*.."5566JJJJJJrA      rA  c              3   j   K   | ]-}t          |                             d d                    V  .dS r*  r   Nr:  r;  s     r?   r5  z,_configure_imagegen_model.<locals>.<genexpr>  =      RR1#gajnn["==>>RRRRRRrA   r   r(  r)  r*  r  Modelr'  Speedr)  	Strengthsr*    Price     ← currently in use	  Choose r    model:  Model set to: )IMAGEGEN_BACKENDSr=   rr  r  rB  rL   keysmaxr  r   r   r  r,  rP   r  r   )r-  r  r  default_modelcfg_keycur_cfg	model_idsorderedr%  headerr  midrowr  r  r<  r2  s                  @@r?   _configure_imagegen_modelrV    s     ##L11G 2W\244G] l#G,,Ggt$$ "!wKK((9MMG##%W\\^^$$Io L L L LI L L LLG //Y/////JJJJ	JJJTUVVVRRRR	RRR\]^^^ F 
GGG	W 	vg 	+ 	 		G_	)	 		,	1	 	 	  
%
$
$%%%D  (gclFCC-++CC
/GI&///  C S\FGG.f../////rA   r  c                    	 ddl m} ddlm}  |              ||           }n# t          $ r i dfcY S w xY w|i dfS 	 |                                pg }|                                }n# t          $ r i dfcY S w xY wd |D             }||fS )ua  Return ``(catalog_dict, default_model_id)`` for a plugin provider.

    ``catalog_dict`` is shaped like the legacy ``FAL_MODELS`` table —
    ``{model_id: {"display", "speed", "strengths", "price", ...}}`` —
    so the existing picker code paths work without change. Returns
    ``({}, None)`` if the provider isn't registered or has no models.
    r   )get_providerr  Nc                 R    i | ]$}t          |t                    d |v |d          |%S )id)r  rB  r6  s     r?   ra   z-_plugin_image_gen_catalog.<locals>.<dictcomp>  s2    OOOaZ4-@-@OTQYYqwYYYrA   )r  rX  rN   r  rQ   list_modelsrN  )r  rX  r  r  modelsr   r<  s          r?   _plugin_image_gen_catalogr]    s    999999AAAAAA""$$$<,,   4x4x%%''-2((**   4xOO6OOOGGs   !$ 55*A* *A;:A;c           	         t          |           \  }sdS |                    di           }t          |t                    si }||d<   |                    d          p|vr|t                                                    }gfd|D             z   }t          d |D                       t          fd|D             d          t          fd	|D             d
          d}t                       ddd|d          ddd|d          ddd|d          d}t          t          |t          j                             g }|D ]9}	t          |	|	         |          }
|	k    r|
dz  }
|                    |
           :t          d|  d|d
          }||         }||d<   t          d|            dS )zPrompt the user to pick a model for a plugin-registered backend.

    Writes selection to ``image_gen.model``. Mirrors
    :func:`_configure_imagegen_model` but sources its catalog from the
    plugin registry instead of :data:`IMAGEGEN_BACKENDS`.
    Nr"   r(  c                      g | ]
}|k    |S rD   rD   r0  s     r?   r*  z8_configure_imagegen_model_for_plugin.<locals>.<listcomp>4  r3  rA   c              3   4   K   | ]}t          |          V  d S r3  r5  r6  s     r?   r5  z7_configure_imagegen_model_for_plugin.<locals>.<genexpr>7  r7  rA   c              3   j   K   | ]-}t          |                             d d                    V  .dS r9  r:  r;  s     r?   r5  z7_configure_imagegen_model_for_plugin.<locals>.<genexpr>8  r=  rA   r>  rA  c              3   j   K   | ]-}t          |                             d d                    V  .dS r@  r:  r;  s     r?   r5  z7_configure_imagegen_model_for_plugin.<locals>.<genexpr>9  rA  rA   r   rB  r  rC  r'  rD  r)  rE  r*  rF  rG  rH  rI  rJ  )r]  rr  r  rB  r=   rL   rL  rM  r  r   r   r  r,  rP   r  r   )r  r  rN  rP  rQ  rR  r%  rS  r  rT  rU  r  r  r<  r2  s                @@r?   $_configure_imagegen_model_for_pluginrc     sq    7{CCG] R00Ggt$$ &%{KK((9MMG##%W\\^^$$Io L L L LI L L LLG //Y/////JJJJ	JJJTUVVVRRRR	RRR\]^^^ F 
GGG	W 	vg 	+ 	 		G_	)	 		,	1	 	 	  
%
$
$%%%D  (gclFCC-++CC
(K(((  C S\FGG.f../////rA   c                     |                     di           }t          |t                    si }||d<   | |d<   d|d<   t          d|             t	          | |           dS )z<Persist a plugin-backed image generation provider selection.r"   r  Fr  z  image_gen.provider set to: N)rr  r  rB  r   rc  )r  r  img_cfgs      r?   !_select_plugin_image_gen_providerrf  W  sy    R00Ggt$$ &%{%GJ"GM@;@@AAA(f=====rA   c           	      	   |                      dg           }|                      d          }|                      d          r't          |          }|j        st          d           dS |                      d          r3|                    di           }| d         |d<   t          |          |d	<   d
| v rd| d
         }|                    di           }|dk    rd|d<   t          d           n|r||d<   t          d|            t          |          |d	<   |                      d          rK|                    di           }| d         |d<   t          |          |d	<   t          d| d                     |r|dvrd|                    |i           d	<   n|s}t                                          D ]c\  }	}
| |
                     dg           v rF|                     |	          }t          |t                    r|                     d	          rd|d	<    nd|s|                      d          rt          | d                    t          d| d          d           |rt          d           |                      d          }|rt          ||           dS |                      d          }|rWt          ||           |                    di           }t          |t                    r|                     d          d vrd!|d<   dS d}|D ]}t          |d"                   }|rt          d|d"          d#           4|                     d$d%          }|rt          d&|            |                     d'd%          }|r.t!          d(|                     d)|d"                    |          }n.t!          d(|                     d)|d"                    d*          }|r&t#          |d"         |           t          d+           t          d,           d}|                      d          r|rt          | d                    |rt          d| d          d-           |                      d          }|rt          ||           dS |                      d          }|r[t          ||           |                    di           }t          |t                    r"|                     d          d vrd!|d<   dS dS dS dS dS ).zAConfigure a single provider - prompt for API keys and set config.ri   rl   rk   E  Nous Subscription is only available after logging into Nous Portal.Nrj   r&   r  r  r   r   r   r    Browser set to local mode!  Browser cloud provider set to: r   r   r    Web backend set to: r   r&   r   Tr   Fr~   r  rf    - no configuration needed!B  Requests for this tool will be billed to your Nous subscription.r  r   r"   r  r   rp   z: already configuredrq   r     Get yours at: r       r   password	    Saved    Skippedz configured!)r=   r   r  r   rr  r  r   r  rQ  r  rB  r   r   rf  rV  r   _promptr   )r  r  ri   r  r  r  bpr  r  cat_keyr  sectionr  r  re  all_configuredr  existingrq   default_valr  s                        r?   r  r  c  s   ||J++Hll#9::O||()) 1&99) 	bcccF ||N## 7##E2..&~6
!%o!6!6 X%%()''	266==,3K()89999 	E,.K()CrCCDDD%)/%:%:M" ||M"" K##E2..%m4	!%o!6!6I0GIIJJJ  
?2KKK@D/2..}==  ,1133 	 	LGS377;3333 **W--gt,, 3]1K1K 3-2GM*	 4  <<%% 	4H\2333IHV,IIIJJJ 	^\]]] ll#:;; 	-k6BBBF,,122 	,%gv666 ''R88G'4(( ,W[[-D-DL]-]-]&+
# N ' ' U,, 	'@E
@@@AAAA ''%$$C 64s44555'')R00K W FswwxU'D'D F FTT FswwxU'D'D F FQUVVV 's5z5111{++++}---!& ||L!! 0n 0./// ,:HV,:::;;;ll#:;; 	-k6BBBF,,122 	,%gv666''R88G'4(( ,W[[-D-DL]-]-]&+
###, ,	, 	,, ,-]-]rA   c                      dk    rt          d          rdS t                       t          t          dt          j                             g d}t          d|d          }|dk    rzt          d           t          d	d
          }|rG|                                r3t          d|                                           t          d           nt          d           n	|dk    rt          d                                          pd}t          |          dk    }|rdnd}t          |d
          }|r|                                rt          d|                                           t                      }|                    di                               di           }	||	d<   t          |           |rt          dd           t          d           nt          d           dS t                                g           }
|
sdS d |
D             }|sdS t%           fdt'                      D                        }t                       t          t          d| dt          j                             |D ]\  }}|rt          d|            t          d| d
          }|rF|                                r2t          ||                                           t          d           ut          d           dS ) zMSimple fallback for toolsets that just need env vars (no provider selection).r    Nz8  Vision / Image Analysis requires a multimodal backend:)u   OpenRouter — uses GeminiuB   OpenAI-compatible endpoint — base URL, API key, and vision modelSkipz  Configure vision backend   r   z(  Get key at: https://openrouter.ai/keysz    OPENROUTER_API_KEYTrq  r   rs  rt  r  z&    OPENAI_BASE_URL (blank for OpenAI)zhttps://api.openai.com/v1zapi.openai.comz    OPENAI_API_KEYz    API keyre   	auxiliarybase_urlAUXILIARY_VISION_MODELzgpt-4o-minic                 :    g | ]\  }}t          |          ||fS rD   r}  )rF   r  rq   s      r?   r*  z2_configure_simple_requirements.<locals>.<listcomp>  s-    QQQhc3mC>P>PQSzQQQrA   c              3   0   K   | ]\  }}}|k    |V  d S r3  rD   rF   r_   r  rG   r9   s       r?   r5  z1_configure_simple_requirements.<locals>.<genexpr>
  5      \\71aPQU[P[P[QP[P[P[P[\\rA   r  z requires configuration:  Get key at: rp  )r  r  r   r   YELLOWr  r   ru  r   r   r   r   r   r	   rr  r
   r  r=   nextrU   )r9   r  r  r  r  is_native_openai	key_labelapi_key_cfg_auxr  missingr  r  rq   s   `              r?   r  r    s>   X&& 	FeNPVP]^^___
 
 

 97AFF!88BCCC4tDDDE . .3U[[]]CCC{++++}----AXXGHHNNPPoToH0::>NN0@S,,mIi$777G .7==?? ./AAA"}}{B77BB8RPP#+Z D!!!# L"#;]KKK{++++}---+//;;L QQ,QQQG \\\\&J&L&L\\\^deeH	GGG	%7X777
G
GHHH * *S 	0...///st444 	*U[[]] 	*3...;''''=))))* *rA   c                    g }t                      D ]u\  }}}t                              |          }t                              |          }|s|r7t	          ||           st          ||           r|                    ||f           v|st          d           dS d |D             }|                    d           t          d|t          |          dz
            }|t          |          k    rdS ||         \  }}t                              |          }|rt          |||            nt          |           t          |            dS )z<Let user reconfigure an existing tool's provider or API key.z#No configured tools to reconfigure.Nc                     g | ]\  }}|S rD   rD   )rF   rG   r]   s      r?   r*  z%_reconfigure_tool.<locals>.<listcomp>(  s    222Eu222rA   Cancelz+  Which tool would you like to reconfigure?r  )rU   r  r=   r  r   _toolset_enabled_for_reconfigurerP   r   r  r  %_configure_tool_category_for_reconfig _reconfigure_simple_requirementsr
   )	r  configurabler9   r  rG   r  reqsr  r  s	            r?   _reconfigure_toolr    sv    LCEE 8 8!!!&))'++F33 	8$ 	8 00 84TU[]c4d4d 8##VX$6777 9:::22\222GNN8
FQTU\Q]Q]`aQa
b
bC
c,#C(FH


f
%
%C
 1-fc6BBBB(000rA   c                     t           D ]>}t          | |          s	 t          ||d          }n# t          $ r Y 3w xY w| |v r dS ?dS )zReturn True if a configurable toolset is enabled anywhere.

    Reconfigure must include enabled-but-unconfigured categories so users can
    finish provider/API-key setup without disabling and re-enabling the toolset.
    Fr  T)rZ   r@   r  rQ   )r9   r  r:   r   s       r?   r  r  ;  s       ,VX>> 		),1  GG
  	 	 	H	W44 5s   /
<<c                    |                     dd          }|d         }t          ||          }t          |          dk    r_|d         }t                       t          t	          d| d| d|d          d	t
          j                             t          ||           dS t                       t          t	          d| d| d
t
          j                             t                       g }|D ]}|                     d          rd|d          dnd}	|                     d          rd|d          nd}
d}|                     dg           }|rt          d |D                       rt          ||          rd}n|sd}nd}|
                    |d          |	 |
 |            t          ||          }t          d||          }t          ||         |           dS )zBReconfigure a tool category - provider selection + API key update.r   r   rf   r  r   r  r  r  r  z - Choose a provider ---rg   r  r  rh   r  ri   c              3   @   K   | ]}t          |d                    V  dS r|  r}  r  s     r?   r5  z8_configure_tool_category_for_reconfig.<locals>.<genexpr>g  r  rA   r  r  z  Select provider:N)r=   r  r  r  r   r   r  _reconfigure_providerr  r  rP   r	  r  )r9   r  r  r   rf   r   r  r  r0  rg   rh   r  ri   r  r  s                  r?   r  r  Q  s   7762Dv;D"3//I
9~~Q<eCTCCDCCHV,<CCCV[QQRRRh/////eBTBBDBBBFKPPQQQ 	L 	LA*+%%..@&7&&&&bE()e<$!E($$$"CJuuZ,,H 1s"M"MH"M"M"MMM 1&q&11 1!,JJ! 1!#JJ!0J##qy$J%$J$Jj$J$JKKKK3IvFF%&:<LkZZi5v>>>>>rA   c           	      T	   |                      dg           }|                      d          }|                      d          r't          |          }|j        st          d           dS |                      d          r7| d         |                    di           d<   t          d	| d                     d
| v rd| d
         }|dk    r)d|                    di           d<   t          d           n-|r+||                    di           d<   t          d|            |                      d          r7| d         |                    di           d<   t          d| d                     |r<|dvr8|                    |i           }t          |t                    si }|||<   d|d<   n|s}t          	                                D ]c\  }}| |                     dg           v rF|                     |          }t          |t                    r|                     d          rd|d<    nd|s|                      d          rt          | d                    t          d| d          d           |rt          d           |                      d          }	|	rt          |	|           dS |                      d          }
|
rKt          |
|           |
d k    r5|                    d!i           }t          |t                    r
d |d<   d|d<   dS |D ]}t          |d"                   }|r$t          d|d"          d#|dd$          d%           |                     d&d'          }|rt          d(|            |                     d)d'          }t          d*|                     d+|d"                    d,| -          }|rL|                                r8t#          |d"         |                                           t          d.           t          d/           |                      d          }	|	rt          |	|           dS |                      d          }
|
rMt          |
|           |
d k    r9|                    d!i           }t          |t                    rd |d<   d|d<   dS dS dS dS )0z)Reconfigure a provider - update API keys.ri   rl   rk   rh  Nrj   r&   r  z  TTS provider set to: r   r   r   r  ri  rj  r   r   r  rk  rl  Tr  r   Fr~   r  rf   rm  rn  r  r   r   r"   rp   : configured (   ...)rq   r   ro  r   rp  r    (Enter to keep current)rq      Updated    Kept current)r=   r   r  r   rr  r   r  rB  r  rQ  r   r   rf  rV  r   ru  r   r   )r  r  ri   r  r  rv  rx  rw  r  r  r  re  r  rz  rq   r{  r  s                    r?   r  r  v  sd   ||J++Hll#9::O||()) 1&99) 	bcccF||N## M3;N3K%$$Z0K.1IKKLLLX%%()==AHFi,,-=>89999 	EACFi,,-=>CrCCDDD ||M"" K2:=2I%$$Y/I0GIIJJJ ?2KKK##OR88'4(( 	.G&-F?#!% +1133 	 	LGS377;3333 **W--gt,, 3]1K1K 3-2GM*	 4  <<%% 	4H\2333IHV,IIIJJJ 	^\]]]ll#:;; 	-k6BBBF,,122 	3%gv666% ++K<<gt,, 3*/GJ'-2GM* , , U,, 	KISZIIx|IIIJJJggeR   	20300111ggi,,VswwxU<<VVVepapqqq 	,U[[]] 	,3u:u{{}}555=))))*++++ ,,677K )+v>>>ll-..G /!'6222e''R88G'4(( /&+
#).&&&/ // /rA   c           	      v    t                                g           }|sdS t           fdt                      D                        }t	                       t	          t          d| dt          j                             |D ]\  }}t          |          }|rt          d| d|dd          d           |rt          d|            t          d	| d
d          }|rF|                                r2t          ||                                           t          d           t          d           dS )z(Reconfigure simple env var requirements.Nc              3   0   K   | ]\  }}}|k    |V  d S r3  rD   r  s       r?   r5  z3_reconfigure_simple_requirements.<locals>.<genexpr>  r  rA   r  r   r  r  r  r  rp  r  Trq  r  r  )r  r=   r  rU   r  r   r   r  r   r   ru  r   r   r   )r9   r  r  r  rq   rz  r  s   `      r?   r  r    sl   +//;;L \\\\&J&L&L\\\^deeH	GGG	% X   &+
.
.///  , ,S %% 	DBSBB!BBBCCC 	0...///<s<<<tLLL 	,U[[]] 	,3...=))))*++++, ,rA   Ffirst_installc                 ,  !"# |t                      }t                      }t                       t          | dd          rt	          t                                }t          t          dt          j        t          j	                             t                       t          ||          }|D ]!}t          |         }|                    |t                                }t	          |          }	t          t          d|d          t          j	                  t          d|	 d| d	t          j                  z              |ret          |          D ]T#t!          #fd
t                      D             #          }
t          t          d|
 t          j                             Ut          t          dt          j                             #t                       dS t          t          dt          j        t          j	                             t          t          dt          j                             t          t          dt          j                             t          t          dt          j                             t                       |r|D ]}t          |         }t%          ||d          }|t&          z
  }t)          |d         ||          }||z
  }||z
  }|rdt          |          D ]T"t!          "fdt                      D             "          }
t          t          d|
 t          j                             U|rdt          |          D ]T"t!          "fdt                      D             "          }
t          t          d|
 t          j                             Ut-          ||          !t/                      r^t          !          D ]N#t!          #fdt0          D             #          }
t          t          d|
 dt          j                             O!fdt          |          D             }|rt                       t          t          dt	          |           dt          j                             |D ]T#t!          #fdt                      D             #          }
t          t          d|
 t          j                             Ut          t          dt          j                             t                       |D ]#t5          #|           t7          |||           t9          |           t          t          d |d          d!t          j                             t                       dS g }g }|D ]}t          |         }t%          ||d          }t	          |          }	t	          t                                }|                    d"|d          d|	 d| d#           |                    |           t	          |          d$k    r|                    d%           |                    d&           t=          |                    d'                    }|r|                    d(           |                    d)           t	          |          d$k    rt	          |          nd*}t	          |          t	          |          d$k    rd$nd+z   }|r|d$z   nd*}||rd,nd$z   }	 t?          d.|d+/          }||k    rnp||k    rtA          |           t                       ?||k    rtC          |           t                       c||k    rt                      }|D ]}|t%          ||d          z  }t)          d0|          }||k    rJ|D ]}t%          ||d          }||z
  }||z
  }t          |         }|s|rt          t          d|d          d1t          j                             t          |          D ]T"t!          "fd2t                      D             "          }
t          t          d3|
 t          j                             Ut          |          D ]T"t!          "fd4t                      D             "          }
t          t          d5|
 t          j                             Ut          |          D ]V#tD                              #          stF                              #          r tI          #|          rt5          #|           Wt7          |||           t9          |           t          t          d6t          j                             tK          |          D ]_\  }}t	          t%          ||d                    }t	          t                                }d"t          |         d          d| d| d#||<   `n't          t          d7t          j                             t                       *||         }t          |         }t%          ||d          }t)          |d         |          }||k    r||z
  }||z
  }|rdt          |          D ]T"t!          "fd8t                      D             "          }
t          t          d|
 t          j                             U|rdt          |          D ]T"t!          "fd9t                      D             "          }
t          t          d|
 t          j                             Ut          |          D ]V#tD                              #          stF                              #          r tI          #|          rt5          #|           Wt7          |||           t9          |           t          t          d |d          d:t          j                             n0t          t          d;|d          t          j                             t                       t	          t%          ||d                    }t	          t                                }d"|d          d| d| d#||<   t                       d+d<l&m'}  t          t          d= |              d>t          j                             t          t          d?t          j                             t                       dS )@a	  Entry point for `hermes tools` and `hermes setup tools`.

    Args:
        first_install: When True (set by the setup wizard on fresh installs),
            skip the platform menu, go straight to the CLI checklist, and
            prompt for API keys on all enabled tools that need them.
        config: Optional config dict to use.  When called from the setup
            wizard, the wizard passes its own dict so that platform_toolsets
            are written into it and survive the wizard's final save_config().
    Nr  Fu   ⚕ Tool Summaryr  r]   r  /r  c              3   0   K   | ]\  }}}|k    |V  d S r3  rD   r  s       r?   r5  z tools_command.<locals>.<genexpr>  5      !i!i1a]^bh]h]h!]h]h]h]h!i!irA   u       ✓ z    (none enabled)u   ⚕ Hermes Tool Configurationz'  Enable or disable tools per platform.z;  Tools that need API keys will be configured when enabled.zM  Guide: https://hermes-agent.nousresearch.com/docs/user-guide/features/toolsr  c              3   0   K   | ]\  }}}|k    |V  d S r3  rD   rF   r_   r  rG   r)  s       r?   r5  z tools_command.<locals>.<genexpr>)  5      !e!e1a]^bd]d]d!]d]d]d]d!e!erA   z  + c              3   0   K   | ]\  }}}|k    |V  d S r3  rD   r  s       r?   r5  z tools_command.<locals>.<genexpr>-  r  rA   z  - )rV  c              3   0   K   | ]\  }}}|k    |V  d S r3  rD   r  s       r?   r5  z tools_command.<locals>.<genexpr>6  s.      !X!X1aAQWKK!KKKK!X!XrA   u     ✓ z': using your Nous subscription defaultsc                     g | ]<}t                               |          st                              |          r|v:|=S rD   )r  r=   r  )rF   r9   auto_configureds     r?   r*  z!tools_command.<locals>.<listcomp>=  s]       !#''//3K3O3OPV3W3W /11 111rA   z  Configuring z	 tool(s):c              3   0   K   | ]\  }}}|k    |V  d S r3  rD   r  s       r?   r5  z tools_command.<locals>.<genexpr>G  r  rA   u       • z1  You can skip any tool you don't need right now.u     ✓ Saved z tool configurationz
Configure z	 enabled)r  z Configure all platforms (global)z2Reconfigure an existing tool's provider or API keyr?  zConfigure MCP server toolsDoner   r~  TzSelect an option:rA  zAll platformsr   c              3   0   K   | ]\  }}}|k    |V  d S r3  rD   r  s       r?   r5  z tools_command.<locals>.<genexpr>  5      )m)m1aefjlelel!elelelel)m)mrA   z    + c              3   0   K   | ]\  }}}|k    |V  d S r3  rD   r  s       r?   r5  z tools_command.<locals>.<genexpr>  r  rA   z    - u+     ✓ Saved configuration for all platformsz  No changesc              3   0   K   | ]\  }}}|k    |V  d S r3  rD   r  s       r?   r5  z tools_command.<locals>.<genexpr>  r  rA   c              3   0   K   | ]\  }}}|k    |V  d S r3  rD   r  s       r?   r5  z tools_command.<locals>.<genexpr>  r  rA   z configurationz  No changes to r   z  Tool configuration saved to z/config.yamlz:  Changes take effect on next 'hermes' or gateway restart.)(r	   r  r  r  r  rU   r   r   r  BOLDr  rZ   r=   rX   DIMrt  r  GREENr  rM  r  REDr   r   rM   r  r  rx  r
   rP   r  r  r   _configure_mcp_tools_interactiver  r  r  r  r   r   )$argsr  r  enabled_platformsr  r  r  pinfor   countr]   current_enabledchecklist_preselectednew_enabledaddedremovedto_configureplatform_choicesplatform_keysr  _has_mcp_global_idx_reconfig_idx_mcp_idx	_done_idxr  all_currentpkprevpinfo_innerci	new_countr   r  r)  r9   s$                                    @@@r?   tools_commandr    s    ~.00	GGG tY&& 8::;;e&V[AABBB+F4EFF% 
	? 
	?DdOEkk$..GLLE%-U7^--v{;;eDZ%DZDZRWDZDZDZ\b\f>g>gghhh ?$Woo C CF !i!i!i!i3W3Y3Y!i!i!ikqrrE% 25 2 2FLAABBBBC e0&*==>>>>	%/fk
J
JKKK	%96:
F
FGGG	%Mvz
Z
Z[[[	%_agak
l
lmmm	GGG  9% 6	 6	DdOE1&$\abbbO %46K$K! 4E'NDY[_``K/1E%3G ? -- ? ?B !e!e!e!e3W3Y3Y!e!e!egijjE%u==>>>> = // = =B !e!e!e!e3W3Y3Y!e!e!egijjE%u
;;<<<<9!,  O *++ h$_55 h hF !X!X!X!X3H!X!X!XZ`aaE% W W W WY_Yeffgggg   %+K%8%8  L  	7eIS->->III6=YYZZZ* A AF !i!i!i!i3W3Y3Y!i!i!ikqrrE% 25 2 2FJ??@@@@eOQWQ[\\]]]* 7 7F&vv6666 {;;;%JuW~JJJFLYYZZZGGGG M! # #$%fdPUVVVG8::;; XU7^ X X X X X X XYYYT""""
=A BCCCPQQQ FJJ}--..H > <===F### ),M(:(:Q(>(>#m$$$BK&&s=/A/AA/E/E!!1MM&.6!!BHh!5A6Ia]02BANNN ) -f%%%GGG (??,V444GGG +%%K# b b262[`aaaa3O[QQKk))' B BB.vrW\]]]D'$.E"[0G"+B-K G Ge$@W)=$@$@$@&*MMNNN"(-- I IB$()m)m)m)m;_;a;a)m)m)moq$r$rE!%(8(8(8&,"G"GHHHH"(// G GB$()m)m)m)m;_;a;a)m)m)moq$r$rE!%(8(8(8&*"E"EFFFF"(-- C C+//77 C;S;W;WX^;_;_ CB66RR C 266 B B B([AAAAF###eI6<XXYYY'66 p pFB #$7`e$f$f$f g gI D F FGGE+o	"g8N+o+oS\+o+o_d+o+o+o$R((p
 eNFJ77888GGGS!$ .fdX]^^^ 0gPP/))/1E%3G ? -- ? ?B !e!e!e!e3W3Y3Y!e!e!egijjE%u==>>>> = // = =B !e!e!e!e3W3Y3Y!e!e!egijjE%u
;;<<<< !-- ; ;#''// ;3K3O3OPV3W3W ;:66JJ ;*66::: {;;;%EuW~EEEv|TTUUUU%;5>;;VZHHIII +FDV[\\\]]	8::;; \U7^ \ \	 \ \E \ \ \Ca]F 
GGG444444	%T1D1D1F1FTTTV\V`
a
abbb	%Lfj
Y
YZZZ	GGGGGrA   c           
      	   ddl m} |                     d          pi }|st          d           dS d |                                D             }|st          d           dS t                       t          t          dt          j                             t          t          d	t          |           d
d
                    |           t          j                             	 ddlm}  |            n*# t          $ r}t          d|            Y d}~dS d}~ww xY ws t!          d           t          d           dS fd|D             }|r|D ]}t!          d| d           t#          d                                 D                       }t          t          d| dt                     dt          j                             t                       d}	                                D ]k\  }
}|st          d|
 d           |                    |
i           }|                    d          pi }|                    d          pg }|                    d          pg }g }|D ]Z\  }}t          |          dk    r|dd         dz   n|}|r|                    | d| d            E|                    |           [t+                      }d! |D             t-                    D ]R\  }}|r||v r|                    |           !|r||vr|                    |           =|                    |           S |d"|
 dt          |           d#|||$          |k    rt          d|
 d%           fd&t1          t                              D             }|                    |
i           }|                    di           }|r||d<   |                    dd           n,|                    dd           |                    dd           t                    }t          |          |z
  }t7          d|
 d'| d(| d)           d*}	m|	rFt9          |            t                       t          t          d+t          j                             dS t          t          d,t          j                             dS )-zProbe MCP servers for available tools and let user toggle them on/off.

    Connects to each configured MCP server, discovers tools, then shows
    a per-server curses checklist.  Writes changes back as ``tools.exclude``
    entries in config.yaml.
    r   r  r?  zNo MCP servers configured.Nc                 H    g | ]\  }}|                     d d          dv| S )r   T)Fr  r  r  r  r  )rF   r_   r  s      r?   r*  z4_configure_mcp_tools_interactive.<locals>.<listcomp>  s@       a55D!!)KKK 	
KKKrA   zAll MCP servers are disabled.z'  Discovering tools from MCP servers...z  Connecting to z server(s): , )probe_mcp_server_toolszFailed to probe MCP servers: z-Could not discover tools from any MCP server.zKCheck that server commands/URLs are correct and dependencies are installed.c                     g | ]}|v|	S rD   rD   )rF   nserver_toolss     r?   r*  z4_configure_mcp_tools_interactive.<locals>.<listcomp>	  s#    @@@A!<*?*?a*?*?*?rA   z  Could not connect to ''c              3   4   K   | ]}t          |          V  d S r3  r5  )rF   toolss     r?   r5  z3_configure_mcp_tools_interactive.<locals>.<genexpr>	  s(      DDUc%jjDDDDDDrA   z  Found z tool(s) across z
 server(s)Fr  z: no tools foundr  includeexcludeF   z...r  r  c                     g | ]
}|d          S r  rD   rF   ts     r?   r*  z4_configure_mcp_tools_interactive.<locals>.<listcomp>'	  s    ***qad***rA   zMCP Server: z tools))r  z: no changesc                 (    g | ]}|v|         S rD   rD   )rF   r  r  
tool_namess     r?   r*  z4_configure_mcp_tools_interactive.<locals>.<listcomp>A	  s#    XXXQWz!}rA   : z
 enabled, z	 disabledTu"     ✓ MCP tool configuration savedz  No changes to MCP tools)r  r  r=   r   rQ  r  r   r   r  r  joinr  tools.mcp_toolr  rQ   r  r   r  rI  r  rP   rX   r  rO   rangerr  popr   r
   )r  r  r?  enabled_namesr  r   failedrf   total_toolsany_changesserver_namer  srv_cfg	tools_cfginclude_listexclude_listr  	tool_namedescription
desc_shortr  r  new_excludeenabled_countdisabled_countr  r  r  s                            @@@r?   r  r    s    655555**]++1rK 0111 !''))  M  3444	GGG	%96=
I
IJJJ	%]3}#5#5]]499]C[C[]]_e_i
j
jkkk999999--//   :S::;;;  FGGGabbb A@@@@@@F ? 	? 	?D=d===>>>>DDl.A.A.C.CDDDDDK	%U;UUL8I8IUUUW]Wc
d
deee	GGGK*0022 C CU 	:[:::;;;//+r22KK((.B	 }}Y//52 }}Y//52 &+ 	) 	)"I{585E5E5J5JSbS)E11P[J )<<z<<<====i(((( "%**E***
%j11 	$ 	$LAy 
$,, $$Q''' $L00 $$Q'''   ####!!>;>>3u::>>>'	
 
 
 \!!6[666777 YXXXXeC
OO.D.DXXX ((b99&&w33	 	+#.Ii MM)T**** MM)T***MM)T***FUm3RRRRRRRR	
 	
 	
  >Fe8&,GGHHHHHe/<<=====s   (C9 9
D DD rR  actionc                     t          | |d          }|dk    r|t          |          z
  }n|t          |          z  }t          | ||           dS )z/Add or remove built-in toolsets for a platform.Fr  disableN)r  rX   rx  )r  r:   rR  r  r   updateds         r?   _apply_toolset_changer   b	  s`    !&(PUVVVGC...C...733333rA   targetsc                   	 t                      }|                     d          pi }|D ]}|                    dd          \  }	||vr|                    |           5||                             di           }t          |                    d          pg           }|dk    r	|vr|                    	           n	fd|D             }||d<   |S )zAdd or remove specific MCP tools from a server's exclude list.

    Returns the set of server names that were not found in config.
    r?  r   r  r  r  r  c                      g | ]
}|k    |S rD   rD   )rF   r  r  s     r?   r*  z%_apply_mcp_change.<locals>.<listcomp>	  s    <<<QQ)^^q^^^rA   )rX   r=   splitrO   rr  rL   rP   )
r  r  r  failed_serversr?  targetr  r  r  r  s
            @r?   _apply_mcp_changer  l	  s    
  #uuN**]++1rK ' '!'c1!5!5Yk)){+++,77DD	y}}Y//5266Y''y)))<<<<'<<<G&	)rA   rV  r?  c                    t                      }fd|D             }d t          D             t          d d           |D ]s\  }}}|vr|| v rt          dt          j                  nt          dt          j                  }t          d| d| dt          |t          j                              tfd|D             }	|	rt                       t          d	 d           |	D ]m\  }}|| v rt          dt          j                  nt          dt          j                  }t          d| d| dt          |t          j                              n|rt                       t          d
           |                                D ]\  }
}|	                    d          pi }|	                    d          pg }|	                    d          pg }|r)t          |
 dd                    |           d           u|rAt          |
 dt          d                    |          t          j                   d           t          |
 dt          dt          j                              dS dS )zBPrint a summary of enabled/disabled toolsets and MCP tool filters.c                 B    g | ]\  }}}t          |          |||fS rD   r7  r  s       r?   r*  z%_print_tools_list.<locals>.<listcomp>	  r  rA   c                     h | ]\  }}}|	S rD   rD   rE   s      r?   rH   z$_print_tools_list.<locals>.<setcomp>	  s    EEE|vq!FEEErA   zBuilt-in toolsets (z):u   ✓ enabledu   ✗ disabledr  c                 (    g | ]\  }}}|v
||fS rD   rD   )rF   r_   r  rG   builtin_keyss       r?   r*  z%_print_tools_list.<locals>.<listcomp>	  s-    OOOAq,9N9Nq!f9N9N9NrA   zPlugin toolsets (zMCP servers:r  r  r  z  [include only: r  r  z  [excluded: zall tools enabledN)rU   rM   r  r   r   r  r  r  rQ  r=   r   r  r  )rV  r?  r:   r  r  r9   r]   rG   statusplugin_entriessrv_namer  r  r  r  r  s     `            @r?   _print_tools_listr  	  s   8::M   #0  I FE/DEEEL	
,
,
,
,---% C Cq%%8>BR8R8R%v|444^VZ88 	A6AAVAAuUFJ'?'?AABBBB POOOIOOON G.(...///+ 	G 	GMFE<BFV<V<VeM6<888 << EvEEEE5
+C+CEEFFFF Un!,!2!2!4!4 		U 		UHgG,,2ImmI..4"GmmI..4"G UxOO$))G:L:LOOOPPPP UxaaeDIIg<N<NPVP]6^6^aaabbbbxSS51Dfj+Q+QSSTTTTU U		U 		UrA   c                 z   | j         }t          | dd          t                      }t          vr/t	          d dd                    t                                dS |dk    r8t          t          |d	          |                    d
          pi            dS | j	        }d |D             }d |D             }d t          D             t                      z  fd|D             r&D ]}t	          d| d           fd|D             }fd|D             rtD ]c}t          t                              |          pt                                }t	          d| d dd                    |           d           dfd|D             }|rt          |||           t                      |r)t!          |||          D ]}t	          d| d           t#          |           fd|D             }	|	r3|dk    rdnd}
t%          |
 dd                    |	                      dS dS )zEnable, disable, or list tools for a platform.

    Built-in toolsets use plain names (e.g. ``web``, ``memory``).
    MCP tools use ``server:tool`` notation (e.g. ``github:create_issue``).
    r:   r   zUnknown platform 'z
'. Valid: r  NrL   Fr  r?  c                     g | ]}d |v|	S r   rD   r  s     r?   r*  z0tools_disable_enable_command.<locals>.<listcomp>	  s    :::QS\\q\\\rA   c                     g | ]}d |v |	S r  rD   r  s     r?   r*  z0tools_disable_enable_command.<locals>.<listcomp>	  s    2221rA   c                     h | ]\  }}}|	S rD   rD   rE   s      r?   rH   z/tools_disable_enable_command.<locals>.<setcomp>	  s    GGGAfGGGrA   c                     g | ]}|v|	S rD   rD   rF   r  valid_toolsetss     r?   r*  z0tools_disable_enable_command.<locals>.<listcomp>	  s#    NNNaa~6M6M6M6M6MrA   zUnknown toolset 'r  c                     g | ]}|v |	S rD   rD   r  s     r?   r*  z0tools_disable_enable_command.<locals>.<listcomp>	  s#    MMMn9L9L19L9L9LrA   c                 4    g | ]}t          |          |S rD   r7  )rF   r  r:   s     r?   r*  z0tools_disable_enable_command.<locals>.<listcomp>	  s9       ,Q99	  rA   z	Toolset 'z ' is not available on platform 'z	' (only: r  c                     g | ]}|v|	S rD   rD   )rF   r  restricted_targetss     r?   r*  z0tools_disable_enable_command.<locals>.<listcomp>	  s$    UUUBT9T9T19T9T9TrA   zMCP server 'z' not found in configc                 ^    g | ])}|vd |vs|                     d           d         v'|*S )r   r   )r  )rF   r  r  unknown_toolsetss     r?   r*  z0tools_disable_enable_command.<locals>.<listcomp>	  sP       $$$#Q,,!''#,,q/Q_:_:_ 	
:_:_:_rA   r  DisabledEnabledr  )tools_actionr  r	   rZ   r  r  r  r  r=   namesrM   rY   rt  r8   rX   r   r  r
   r   )r  r  r  r  toolset_targetsmcp_targetsrf   r>   srv
successfulverbr  r:   r  r  r  s              @@@@@r?   tools_disable_enable_commandr(  	  s=    FtZ//H]]Fy  T(TTdii	>R>RTTUUU-fh\abbb **]339r8	E 	E 	EG::':::O22g222KGG1FGGGJbJdJddNNNNN?NNN N$ 	6 	6D4T4445555MMMMoMMM   "    V& 	 	D;??EENOOG0D 0 0( 0 0))G,,0 0 0    VUUUoUUU IfhHHH"uuN D*6;GG! 	D 	DCBBBBCCCC      J  ;#y00zzi$99$))J"7"799:::::; ;rA   r3  )Tr  )r   )NFN)j__doc__jsonr  loggingrO  r   pathlibr   typingr   r   r   r   hermes_cli.configr   r	   r
   r   r   hermes_cli.colorsr   r   hermes_cli.nous_subscriptionr   r   tools.tool_backend_helpersr   r   utilsr   r   	getLogger__name__r  __file__parentresolver   hermes_cli.cli_outputr   r  r   r   r   r   r   r   r   ru  rM   rM  r8   r   __annotations__r  r@   rU   rX   rY   hermes_cli.platformsrZ   _PLATFORMS_REGISTRYrQ  r  r  r   r  rB  r  r  r  rx  r  rL   r  r  r  r  r  r  r  r  r  r  r  r	  r  rK  r,  rV  r]  rc  rf  r  r  r  r  r  r  r  r  r  r   r  r  r(  rD   rA   r?   <module>r<     s  	 	 	      				 



       , , , , , , , , , , , ,              , + + + + + + +        Y X X X X X X X 4 4 4 4 4 4 4 4		8	$	$tH~~$+3355
                : ^]]  {[7 7 S#c(] 3   2# 2 2 2 2 2 2  4#     B A A A A A ,&,..  	 ! ,'G (&*(-&>@P%Q	 	 -28 &  %,4@PY  A  A !)  ";)]Kbcc !&  %,0<P  ZG  H  H !-  02-9JSpqq !*  ,"E,8HQyzz !)  $(G +)   (I '% MN
R Rh '/{ ,'F*&*(-&9;N%O	 	 **A*/;NWnoo  B$)]K[\\  #6).:LUjkk  !$M',8HQnoo  0.A*/;vww _8
> >@ # ,'Q&*(3&/[$)	 	 !Y%Gfgg %* 
 4 % @'H$1&*(1&;%<-
 
 (2=$+-  &?1=R[tuu4@XYY %2-
 
 &<1=R[tuu %2-	 	 $</;NWnoo %0-	 	 "(B)5IVmGI I %.'
 
g>
B BH  )-(4\]]&2FStuu 	
   *>'	 
  " +-,8H  RC  D  D+Okll , 

	 " ) )=8De  oK  L  L8De  oK  L  L )  /68Deff8Deff6Bt  BY  Z  Z
 )	 	
 sr rn	 JJIJ  V7C V7 V7 V7 V7vS	      d xS	7J VZ[^`cdg`h[hVi           * )-	o o ooo "&	o
 	Xo o o od5 5 5CPSH 5 5 5 5p#> #>c #>4 #>4 #> #> #> #>PY YS Y4 Y# Yc Y Y Y Y /3 8DcN+ 2 2 2'tCH~ ' ' ' 'T1- 1-c 1-CH 1-PS 1-`cdg`h 1- 1- 1- 1-l/s /D / / / /*T$Z * * * *ZD $ 4:    &#1 #1T #1d #1 #1 #1 #1LA=S A=t A=T A= A= A= A=H5$ 5 5 5 5 5 5p	T 	4 	C 	 	 	 	2% % % 
!(   D $ 3    ;0C ;0 ;0$ ;0 ;0 ;0 ;0|3    640c 404 40D 40 40 40 40n	>3 	> 	> 	> 	> 	> 	>t,$ t, t, t, t, t,n<*3 <* <* <* <*~d    DS $ 4    ,"?# "?D "?$ "? "? "? "?J\/D \/$ \/ \/ \/ \/~,S , , , ,4j jD j$ j j j j`}>T }> }> }> }>F4$ 4# 4d3i 4Y\ 4 4 4 4d T#Y  C    2'U 'U 'U$ 'U# 'U 'U 'U 'UT=; =; =; =; =;rA   