
    $*j                    
   U d Z ddlZddlZddlZddlZddlZddlZddl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 dd	l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/m0Z1m2Z3 g dZ4de5de5fdZ6h dZ7de8fdZ9dhdhdZ:ee5ee5         f         e;d<   de5de5de8fdZ<d Z=de>fdZ?de5dee5         fdZ@ddlAmBZC d  eCjD                    D             ZBdddd d!g d"d#d$d%d&g d'd(d)d*d+gd,d-d.d/d*d0d1d2gd'd#d3d4g d5d6d7d8d.d9d:d;d<d2gd=d#d>d.d?d@dAdBd2gdCd#dDdEdFdGdHdId2gdJd#dKdLdMg dNdNdOdPdLdQg dRdRdOg	dSdTdUdVdWd$d%dXdYg d(dZd[d\gd]d^d_d`dYd\dadbgdcgdddedfd$d%dgg d(dhdigdjdkgdSdldmd$d%dng d(dodigdjdpgdSdqdrdsdtdud%dvg d6dwdxd.dydzdxd{d2gd|gddd}d~dd dg ddddd%dg dd(ddgdd	ddddddddgdddgdSdddddddbddddgdgdSddddg ddgdSddddddg ddwgddddddddd2dddd2gdddddddbdddbddddgddgdSd
ZEdgdgdZFde5fdZGdd(ddee5         deHde8fdĄZIde8fdńZJd"de8de8fdȄZKd#de5de8de8fd˄ZLde5fd̈́ZMdee5         fd΄ZNdeHfdτZOdee5         fdЄZPd$deQdeee5                  dee5ee5         f         fdӄZRd%de8de8fdՄZSd(d֜deQde5de8dee5         fd؄ZTdeQde5dee5         fdڄZU	 d$ddۜde5deQde8de8fd݄ZVd&de5deWdeHdeHfdZXdaYeee5eHf                  e;d<   dee5eHf         fdZZ	 d'd(dۜde5dee5         de5de8dee5         f
dZ[d(dۜde5deQde8fdZ\deWeQ         fdZ]deWeQ         fdZ^deWeQ         fdZ_deWeQ         fdZ`deWeQ         fdZaddۜdeQdeQde8deWeQ         fdZbddۜdeQdeQde5de8de5f
dZcdd iZdeQe;d<   de5de8fdZeddۜde5deQde8de8fdZfd(dۜde5deQdeQde8fdZgddۜdeQdeQde8de8fdZhddۜdeWdeQde8deHfdZid ZjdjddhejdiZkde5deQdeQde5fd Zlde5deQddfdZmde5fdZnde5deQddfdZode5deQddfdZpde5fdZqde5deQddfdZrdƐd	de5deQd
e8ddfdZsdeQdeQddfdZtde5de5deQddfdZud(dۜdeQdeQde8fdZvde5fdZwd(dۜdeQde8fdZxde5deQde8fdZyd(dۜde5deQdeQde8fdZzd(dۜdeQdeQde8fdZ{de5fdZ|d(de8deQfdZ}deQfdZ~deQde5dee5         de5fdZdeQdee5         de5dee5         fdZd'de>deQde5fd Zd! Zd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)&format_nous_portal_entitlement_message)fal_key_is_configured)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)videou   🎬 Video Analysisz,video_analyze (requires video-capable model))	image_genu   🎨 Image Generationimage_generate)	video_genu   🎬 Video Generationz/video_generate (text-to-video + image-to-video))x_searchu   🐦 X (Twitter) Searchz,x_search (requires xAI OAuth or XAI_API_KEY))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)context_engineu   🧩 Context Enginez,runtime tools from the active context engine)session_searchu   🔎 Session Searchzsearch past conversations)clarifyu   ❓ Clarifying Questionsr0   )
delegationu   👥 Task Delegationdelegate_task)cronjobu   ⏰ Cron JobszBcreate/list/update/pause/resume/run, with optional attached skills)	messagingu   📨 Cross-Platform Messagingsend_message)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)computer_useu   🖱️  Computer Use (macOS)z)background desktop control via cua-driverlabelreturnc                    | pd                                 }|s|S |                    dd          }t          |          dk    rA|d         r9t          d |d         D                       s|d                                          S |S )u   Strip leading emoji/icons from toolset titles for GUI surfaces.

    Registry labels use ``<emoji> <title>``; plugin toolsets prefix with ``🔌``.
    CLI/TUI keeps the raw ``label`` — only HTTP APIs call this helper.
     N      r   c              3   f   K   | ],}|                                 o|                                V  -d S N)isasciiisalnum).0chs     </home/ubuntu/.hermes/hermes-agent/hermes_cli/tools_config.py	<genexpr>z$gui_toolset_label.<locals>.<genexpr>`   s8      /a/aRT

0M/a/a/a/a/a/a    )stripsplitlenany)r<   textpartss      rH   gui_toolset_labelrQ   V   s     KR  D JJtQE
5zzQ58C/a/aX]^_X`/a/a/a,a,aQx~~KrJ   >   r'   r"   r8   r7   r&   r%   r9   r6   c                  n   	 ddl m}   |              dS # t          $ r Y nw xY w	 ddlm} t           |d          pd                                          rdS n# t          $ r Y nw xY wt          t          t          j	        
                    d          pd                                                    S )u  Cheap, side-effect-free check for usable xAI credentials.

    Used to auto-enable the ``x_search`` toolset when the user has either
    completed xAI Grok OAuth (SuperGrok / Premium+) or set
    ``XAI_API_KEY``. Does NOT hit the network — only inspects the local
    auth store and environment. The tool's runtime ``check_fn`` still
    gates schema registration if creds later expire or get revoked.
    r   )_read_xai_oauth_tokensTr   XAI_API_KEYr?   )hermes_cli.authrS   	Exceptiontools.xai_httpr   strrK   boolosenvironget)rS   _xai_get_env_values     rH   _xai_credentials_presentr_   v   s    ::::::   t   FFFFFF!!-006B77==?? 	4	   BJNN=117R88>>@@AAAs    
!!2A 
A'&A'r8   )r8   r9   _TOOLSET_PLATFORM_RESTRICTIONSts_keyplatformc                 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)r`   r]   )ra   rb   alloweds      rH   _toolset_allowed_for_platformre      s+    
 -0088Gd?1h'11rJ   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  rh   rF   ra   _s      rH   	<setcomp>z7_get_effective_configurable_toolsets.<locals>.<setcomp>   s    ...|vq!F...rJ   r   discover_pluginsget_plugin_toolsets)listCONFIGURABLE_TOOLSETShermes_cli.pluginsrm   rn   addappendrW   )resultseenrm   rn   entrys        rH   $_get_effective_configurable_toolsetsrw      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   rl   c                     h | ]\  }}}|	S rh   rh   ri   s      rH   rk   z+_get_plugin_toolset_keys.<locals>.<setcomp>   s    AAA<61aAAArJ   )rq   rm   rn   rW   setrl   s     rH   _get_plugin_toolset_keysr{      st    LLLLLLLLAA+>+>+@+@AAAA   uus   %( AAc                 8      fdt                      D             S )u  Return the toolset keys the ``hermes tools`` checklist actually offers
    for ``platform``.

    This mirrors exactly what ``_prompt_toolset_checklist`` renders:
    ``_get_effective_configurable_toolsets()`` (built-in + plugin toolsets),
    filtered by ``_toolset_allowed_for_platform``. The checklist's returned
    selection can therefore only ever be a subset of this universe.

    Non-configurable toolsets that ``_get_platform_tools`` resolves at read
    time — ``kanban`` and other check_fn-gated toolsets, recovered platform
    composites, MCP server names — are NOT in this set because the checklist
    never shows them. Use this to scope the added/removed diff the UI prints,
    so ``hermes tools`` never claims to add or remove a toolset the user was
    never given a checkbox for. The underlying config is unaffected — those
    entries are preserved by ``_save_platform_tools`` regardless.
    c                 <    h | ]\  }}}t          |          |S rh   re   )rF   ra   rj   rb   s      rH   rk   z*_checklist_toolset_keys.<locals>.<setcomp>   s?       FAq(::  rJ   )rw   )rb   s   `rH   _checklist_toolset_keysr      s4    "   @BB   rJ   )	PLATFORMSc                 4    i | ]\  }}||j         |j        d S )r<   default_toolsetr   )rF   kinfos      rH   
<dictcomp>r      s;       4 0DEE  rJ   Text-to-Speechu   🔊zMicrosoft Edge TTSu   ★ recommended · freezGood quality, no API key needededge)namebadgetagenv_varstts_providerNous Subscriptionsubscriptionz.Managed OpenAI TTS billed to your subscriptionopenaiTr)   VOICE_TOOLS_OPENAI_KEYOPENAI_API_KEY)r   r   r   r   r   requires_nous_authmanaged_nous_featureoverride_env_varsz
OpenAI TTSpaidzHigh quality voiceszOpenAI API keyz$https://platform.openai.com/api-keys)keyr   urlzxAI TTSu2   Grok voices — uses xAI Grok OAuth or XAI_API_KEYxaixai_grok)r   r   r   r   
post_setup
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)r   r   r   r   r   r   Piperz0Local neural TTS, 44 languages (voices ~20-90MB)piper)r   icon	providers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)r   r   r   web_backendr   r   r   r   zFirecrawl Self-Hostedu   free · self-hostedz(Run your own Firecrawl instance (Docker)z9Your Firecrawl instance URL (e.g., http://localhost:3002))r   r   )r   r   r   r   r   )r   setup_title
setup_noter   r   Image Generationu   🎨z8Managed FAL image generation billed to your subscriptionr#   FAL_KEYfal)r   r   r   r   r   r   r   imagegen_backendVideo Generationu   🎬z8Managed FAL video generation billed to your subscriptionr%   )r   r   r   r   r   r   r   video_gen_plugin_namezX (Twitter) SearchzSelect xAI Credential Sourceu  Hermes routes X searches through xAI's built-in x_search Responses tool. Both credential sources hit the same https://api.x.ai/v1/responses endpoint — pick whichever you already have. SuperGrok OAuth is preferred when both are set (uses your subscription quota instead of API spend).u   🐦z%xAI Grok OAuth (SuperGrok / Premium+)u6   Browser login at accounts.x.ai — no API key required)r   r   r   r   r   zxAI API keyz&Direct xAI API billing via XAI_API_KEYrU   zhttps://console.x.ai/)r   r   r   r   Browser Automationu   🌐zLocal Browserz$Headless Chromium, no API key neededlocalagent_browser)r   r   r   r   browser_providerr   z%Nous Subscription (Browser Use cloud)z/Managed Browser Use billed to your subscriptionzbrowser-user   BROWSER_USE_API_KEY)	r   r   r   r   r   r   r   r   r   Camofoxu   free · localz)Anti-detection browser (Firefox/Camoufox)CAMOFOX_URLzCamofox server URLzhttp://localhost:9377z)https://github.com/jo-inc/camofox-browser)r   r   defaultr   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)r   r   r   )r   r   r   Spotifyu   🎵zSpotify Web APIu%   PKCE OAuth — opens the setup wizardr7   )r   r   r   r   zComputer Use (macOS)u   🖱️darwinzcua-driver (background)u    ★ recommended · free · localun   macOS background computer-use via SkyLight SPIs — does NOT steal your cursor or focus. Works with any model.
cua_driver)r   r   platform_gater   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%   r&   r   r6   r7   r;   r   )OPENROUTER_API_KEYzhttps://openrouter.ai/keys)r    r'   c                  j    t           j                            dd                                          pdS )zIReturn the cua-driver executable name/path, honoring non-empty overrides.HERMES_CUA_DRIVER_CMDr?   z
cua-driver)r[   r\   r]   rK   rh   rJ   rH   _cua_driver_cmdr   B  s*    :>>1266<<>>N,NrJ   ,  )timeoutcapture_outputargsr   r   c          	      $   t          t          j                  j        j        }i t          j        dt          |          i}t          j        d          }|rI	 t          j
        |ddg| |d||          }|j        dk    r|S n# t          j        t          f$ r Y nw xY wt          j        ddg}	 t          j
        |d	gz   ddd
          }|j        dk    rt          d          n# t          j        t          f$ rr 	 t          j
        t          j        ddddgdddd           nE# t          j        t          j        f$ r'}	t          j        |ddd|	           cY d}	~	cY S d}	~	ww xY wY nw xY wt          j
        |dg| z   |d|          S )u  Install Python packages from a post-setup hook.

    Strategy (in order):
    1. ``uv pip install`` if uv is on PATH — fast, doesn't need pip in the venv.
    2. ``python -m pip install`` — works on stdlib venvs.
    3. ``python -m ensurepip --upgrade`` then retry pip — covers ``uv venv``
       which creates a venv WITHOUT pip.

    Why this exists: the Windows installer creates the venv via ``uv venv``,
    which doesn't seed pip. Post-setup hooks that shelled out to
    ``[sys.executable, '-m', 'pip', 'install', ...]`` failed with
    ``No module named pip`` on every fresh install. uv-first sidesteps that.

    Returns the ``subprocess.CompletedProcess`` from whichever tier succeeded
    (or the last failure for the caller to inspect).
    VIRTUAL_ENVuvpipinstallT)r   rO   r   envr   z-m	--version   r   rO   r   zpip not in venv	ensurepipz	--upgradez--default-pipx   )r   rO   r   checkr@   r?   z(pip not available and ensurepip failed: )
returncodestdoutstderrN)r   sys
executableparentr[   r\   rY   shutilwhich
subprocessrunr   TimeoutExpiredFileNotFoundErrorCalledProcessErrorCompletedProcess)
r   r   r   	venv_rootuv_envuv_binrt   pip_cmdprobees
             rH   _pip_installr   G  s<   , S^$$+2I:
:M3y>>::F\$F 	^	1D1-D'  F
  A%% & )+<= 	 	 	D	 ~tU+G{m#dB
 
 
 q  #$5666 !%'89   
	N{KQ#$4     -z/HI 	 	 	.AbE!EE          		  >9$t$$%D'   sT   *B BB26C) )E1 (D)(E1)E+E&E+E1&E++E10E1c                    
 ddl } ddl}|                                 }|dk    rdS d}	 |j                            |ddi          }|j                            |d	
          5 }t          j        |                                	                                          }ddd           n# 1 swxY w Y   |
                    dd          }|
                    dg           }ddh
t          
fd|D                       }	|	s3t          d| d           t          d           t          d           dS n# t          $ r Y nw xY wdS )a)  Check whether the latest CUA release ships an asset for this architecture.

    Returns True if the asset likely exists (or if we cannot determine it).
    Returns False and prints a warning when the asset is confirmed missing,
    so callers can skip the install attempt and avoid a raw 404.
    r   Narm64Tz7https://api.github.com/repos/trycua/cua/releases/latestAcceptzapplication/vnd.github+json)headers
   r   tag_namer?   assetsx86_64amd64c              3   P   K   | ]t          fd D                       V   dS )c              3   l   K   | ].}|                     d d                                          v V  /dS )r   r?   N)r]   lower)rF   aa_infos     rH   rI   z=_check_cua_driver_asset_for_arch.<locals>.<genexpr>.<genexpr>  sB      HHVZZ++11333HHHHHHrJ   N)rN   )rF   r  
arch_namess    @rH   rI   z3_check_cua_driver_asset_for_arch.<locals>.<genexpr>  sU       
 
 HHHHZHHHHH
 
 
 
 
 
rJ   z    Latest CUA release (z) has no Intel (x86_64) asset.z9    CUA Driver currently only ships Apple Silicon builds.z2    See: https://github.com/trycua/cua/issues/1493F)rb   urllib.requestmachinerequestRequesturlopen_jsonloadsreaddecoder]   rN   _print_warning_print_inforW   )_platurllibr  api_urlreqrespreleaser   r   	has_assetr  s             @rH    _check_cua_driver_asset_for_archr    s    mmooG't
 	B n$$WxA^6_$``^##C#44 	8k$))++"4"4"6"677G	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8kk*b))Xr**(
 
 
 
 
 
 
 
 
 
	  
	N3NNN   K   D   5
	     4s6   :D4 #9B(D4 (B,,D4 /B,0BD4 4
E EFupgradec                    ddl }ddl}ddl}|                                dk    r| rdS t	          d           dS t                      } |j        |          }|sR| sP |j        d          s t	          d           t          d           dS t                      sdS t          d	
          S |r| s	  |j
        |dgddd          j                                        }t          d| d|pd            n## t          $ r t          d| d           Y nw xY wt          d           t          d           t          d           dS  |j        d          st	          d           t          |          S t                      st          |          S |rA	  |j
        |dgddd          j                                        }n# t          $ r d}Y nw xY wd}t          dd          }|ry|rw	  |j
        |dgddd          j                                        }	|	r|	|k    rt          d| d| d|	            n|	rt          d| d|	            n# t          $ r Y nw xY w|S )u  Install or refresh the cua-driver binary used by Computer Use.

    The upstream installer always pulls the latest release tag, so re-running
    it is the canonical way to upgrade. We expose two modes:

    * ``upgrade=False`` — original post-setup behaviour: skip if already
      installed, install otherwise. Used by the toolset enable flow where
      we don't want to surprise the user with a network fetch.
    * ``upgrade=True`` — always re-run the installer (or call ``cua-driver
      update`` if the binary supports it). Used by ``hermes update`` and
      by ``hermes computer-use install --upgrade``.

    Returns True iff cua-driver is installed (or successfully refreshed)
    when the function returns. macOS-only — silently returns False on
    other platforms.
    r   NDarwinFz6    Computer Use (cua-driver) is macOS-only; skipping.curlu(       curl not found — install manually:zG      https://github.com/trycua/cua/blob/main/libs/cua-driver/README.md
Installing)r<   r   T   r       z already installed: zunknown versionz already installed.z,    Grant macOS permissions if not done yet::      System Settings > Privacy & Security > Accessibility=      System Settings > Privacy & Security > Screen Recordingu1       curl not found — cannot refresh cua-driver.r?   
Refreshing)r<   verbosez upgraded: u    → z up to date: )rb   r   r   systemr  r   r   r  r  _run_cua_driver_installerr   r   rK   _print_successrW   rZ   )
r  r  r   r   
driver_cmdbinaryversionbeforeokafters
             rH   install_cua_driverr*    sr   " MMM||~~!! 	 5OPPPu ""JV\*%%F  =' =v|F## 	EFFFabbb5/11 	5(|<<<<  g 	C$jn[)#$   UUWW  `*``'B^M^``aaaa 	C 	C 	CA*AAABBBBB	CBCCCPQQQSTTTt 6< JKKKF||+-- F|| 
	#Z^[)#$   UUWW F  	 	 	FFF	 	"u	E	E	EB	 f 
	"JN[)#$   UUWW   E&QjQQVQQ%QQRRRR EC:CCECCDDD 	 	 	D	Is8   1AC6 6DD-G GG.A%I 
I! I!r  r   c                    ddl }ddl}d}|rt          d|  d           nt          d|  d           t                      }	  |j        |dd	          }|j        dk    rc |j        |          rS|rOt          d| d
           t          d           t          d           t          d           t          d           dS t          d| 	                                 d           t          d|            dS # |j
        $ r) t          d| 	                                 d           Y dS t          $ r2}t          d| 	                                 d|            Y d}~dS d}~ww xY w)zRun the upstream cua-driver install.sh. Returns True on success.

    The script is idempotent: it always downloads the latest release, so
    re-running it on an already-installed system performs an upgrade.
    r   Nzq/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/trycua/cua/main/libs/cua-driver/scripts/install.sh)"r  z. cua-driver (macOS background computer-use)...z cua-driver...Tr   )shellr   z installed.u.       IMPORTANT — grant macOS permissions now:r  r  z2    Both must allow the terminal / Hermes process.z    cua-driver z# did not complete. Re-run manually:      Fz timed out. Re-run manually.z	 failed: )r   r   r  r   r   r   r   r#  r  r   r   rW   )r<   r   r   r   install_cmdr$  rt   r   s           rH   r"  r"    s    MMM	0 
  2P5PPPQQQQ05000111 ""J4EEE!!lfl:&>&>! R=j===>>>LMMMXYYY[\\\PQQQ4[[[[\\\*[**+++u$   TTTTUUUuu   DDDDDEEEuuuuus%   A?C= 7C= =/E*/	E*8'E%%E*post_setup_keyc           	         ddl }| dv rxt          dz  dz  } |j        d          } |j        d          }|                                s|rt	          d           ddl} |j        |d	d
dg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}	  |j        |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  } |j        d          }|                                si|rgt	          d/           ddl} |j        |d	d
dgddt          t                              }|j        dk    rt          d0           nt          d1           |                                r>t	          d2           t	          d3           t	          d4           t	          d5           dS  |j        d          s t          d6           t	          d7           dS dS | d8k    rt7          d9:           dS | d;k    r	 t9          d;           t          d<           dS # t:          $ r Y nw xY wt	          d=           d>}	 t=          d?|d@dAgdBC          }|j        dk    r.t          dD           t	          dE           t	          dF           nWt          dG           t	          d|j        pd'                                ddB                     t	          dH| dI           dS dS # |j        $ r& t          dJ           t	          dH| dI           Y dS w xY w| dKk    r"	 t9          dK           t          dL           n# t:          $ r t	          dM           	 t=          g dNdBC          }|j        dk    rt          dO           nTt          dP           t	          d|j        pd'                                ddB                     t	          dQ           Y dS n0# |j        $ r# t          dR           t	          dQ           Y Y dS w xY wY nw xY wt	          dS           t	          dT           t	          dU           dS | dVk    r	 t9          dV           t          dW           n# t:          $ r t	          dX           	 t=          g dYdBC          }|j        dk    rt          dZ           nTt          d[           t	          d|j        pd'                                ddB                     t	          d\           Y dS n0# |j        $ r# t          d]           t	          d\           Y Y dS w xY wY nw xY wt	          d^           t	          d_           dS | d`k    rddalm } 	 ddbl!m"} n9# t$          $ r,}
t          dc|
            t	          dd           Y d}
~
dS d}
~
ww xY wt	          de           	  | |dddd9df                     t          dg           dS # tF          $ r,}
t          dh|
            t	          di           Y d}
~
dS d}
~
wt$          $ r,}
t          dj|
            t	          dd           Y d}
~
dS d}
~
ww xY w| dkk    r/	 t9          dk           t          dl           n\# t:          $ rO t	          dm           t=          dkdAgdnC          }|j        dk    rt          do           nt          dp           Y nw xY w	 ddql$m%}m&}  |            }dr|v sdk|v rt          ds           n/|'                    dr            ||           t          dt           n8# t$          $ r+}
t          du|
            t	          dv           Y d}
~
nd}
~
ww xY wt	          dw           t	          dx           dS | dyk    ri	 ddzl!m(} tS           |            *                    d{                    }n# t$          $ r d9}Y nw xY wtW          d|          }|rt          d}           dS |rt          d~           dS t	          d           	 ddl,m-}m.}m/} ddl0m1} n9# t$          $ r,}
t          d|
            t	          d           Y d}
~
dS d}
~
ww xY w |dg dd          } | dk    r, |            rt          d           dS t          d           dS | dk    r= |dd          }!|!r |d||!           t          d           dS t          d           dS t	          d           dS dS )zBRun post-setup hooks for tools that need extra installation steps.r   N>   browserbaser   node_moduleszagent-browsernpmnpxz8    Installing Node.js dependencies for browser tools...r   z--silentz--workspaces=falseT)r   rO   cwdz"    Node.js dependencies installeddisplay_hermes_homez*    npm install failed - run manually: cd z//hermes-agent && npm install --workspaces=falser-     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.cmdz--with-depsz-yiX  )r   rO   r5  r   z    Chromium installedz    Chromium install failed:r?   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 installedzE    npm install failed - run manually: npm install --workspaces=falsez    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   F)r  r   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.whl-U	soundfile--quietr   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: uv 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)...)r=  z	piper-ttsr?  z    piper-tts installedz    piper-tts install failed:z-    Run manually: uv 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.yamlddgsz    ddgs is already installedz2    Installing ddgs (DuckDuckGo search package)...)r=  r@  r?  z    ddgs installedz    ddgs install failed:z(    Run manually: uv pip install -U ddgsz"    ddgs install timed out (>5min)zE    No API key required. DuckDuckGo enforces server-side rate limits.z?    Pair with an extract provider if you also need web_extract.r7   )SimpleNamespace)login_spotify_commandz!    Could not load Spotify auth: z%    Run manually: hermes auth spotifyz    Starting Spotify login...)	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   z"    langfuse SDK already installedz    Installing langfuse SDK...r   z    langfuse SDK installeduI       langfuse SDK install failed — run manually: uv 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 listr   )get_xai_oauth_auth_status	logged_inrU   zG    xAI will use your xAI Grok OAuth (SuperGrok / Premium+) credentialsz*    xAI will use your existing XAI_API_KEYz&    xAI needs credentials. Choose one:)_run_xai_oauth_login_from_setupprompt_choicer   )r   z"    Could not load setup helpers: z?    Run later: hermes auth add xai-oauth   (or set XAI_API_KEY)z(    How do you want xAI to authenticate?)uD   Sign in with xAI Grok OAuth (SuperGrok / Premium+) — browser loginz#Paste an xAI API key (console.x.ai)u8   Skip — configure later via `hermes auth add xai-oauth`)choicesr   u6       Logged in — xAI will use these OAuth credentialszO    xAI Grok OAuth login did not complete. Run later: hermes auth add xai-oauthr@   z    xAI API keypasswordz    XAI_API_KEY savedz=    No API key provided. Run later: hermes auth add xai-oauthz>    xAI will remain inactive until credentials are configured.)2r   PROJECT_ROOTr   existsr  r   r   rY   r   r#  hermes_constantsr7  r  r   rK   tools.browser_toolr9  r:  rW   r   rb   with_suffixbrowser_tool_cached_chromium_installedr   
splitlinesr   r*  
__import__ImportErrorr   typesrA  rV   rB  
SystemExithermes_cli.plugins_cmdrG  rH  rr   rI  rZ   r]   r   hermes_cli.setuprK  rL  r   hermes_cli.configr   )"r/  r   r2  npm_binnpx_binr   rt   r7  r9  r:  exclocal_ablocal_ab_winr.  _bttaillinecamofox_dir_npm_bin	wheel_urlrA  rB  rG  rH  enabledrI  oauth_logged_inexisting_api_keyrK  rL  _setup_promptr   idxapi_keys"                                     rH   _run_post_setuprp  A  s   MMM999#n4F&,u%%&,u%%""$$ 	 	RSSS
 $Z^ )Z1EF#$C4E4E  F  A%%CDDDD@@@@@@   SL_L_LaLa   S   S   S  T  T  T= 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#Z^#$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6<&&!!## 	h 	hBCCC#Z^9j2FG#$C4E4E  F
  A%%67777fggg 	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 
<	'	'5))))))	;	&	&	{###?@@@F 	 	 	D	LMMM5 		X!4K"KUXYYYF A%%8999\]]]mnnnn>???Jfm&9r%@%@%B%B4C4%HJJKKKZIZZZ[[[[[	 on
 ( 	X 	X 	XDEEEV	VVVWWWWWW	X 
7	"	"	w?@@@@ 	 	 	cddd%&D&D&DcRRR$))"#<===="#BCCC N&-*=2)D)D)F)Ftt)L N NOOO OPPPFF > ,   HIIIKLLL >=	 	[\\\klll[\\\\\	6	!	!	v:;;;; 	 	 	LMMM%&?&?&?MMM$))"#78888"#=>>> N&-*=2)D)D)F)Ftt)L N NOOO JKKKFF 9 ,   CDDDFGGG 98	 	[\\\UVVVVV	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 
:	%	%		lz"""?@@@@ 	l 	l 	l8999!:y"93GGGF A%%;<<<<jkkk	l	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6	:	%	%	$AAAAAA"#<#<#>#>#B#B;#O#OPPOO 	$ 	$ 	$#OOO	$(77 	Y   F 	GHHHF<===
	         
 9888888 	 	 	EEEFFFYZZZFFFFF	
 m6  
 
 
 
 !88..00 L     ;     AXX#m$5EEEG }g666677777S     XYYYYYC 
&	%s\  -D6 6
E EECL (M?
	M?!M::M?
S* *
S76S7B#V3 3,W#"W#.X ['A?Z*)[*([[[[[\6 6`A?_`(` ;`?`  ``6`= =
a3!a..a3(b0 0
d:!c!!d.!dd%e Aff!Ag; ;
h0!h++h00j jj#k4 4
l*>!l%%l*c                     t                      } t                                          D ]G}|                    dg           D ].}|                    d          }|r|                     |           /Ht
          t          t          t          fD ]L}	  |            D ].}|                    d          }|r|                     |           /=# t          $ r Y Iw xY w| S )a  Return the set of post-setup keys declared by any visible provider.

    Collected from ``TOOL_CATEGORIES`` plus the plugin-registered web /
    image-gen / video-gen / browser providers (which can also carry a
    ``post_setup``). This is the allowlist the ``hermes tools post-setup``
    command and the dashboard post-setup endpoint validate against, so a
    caller can't drive ``_run_post_setup`` with an arbitrary key.
    r   r   )
rz   TOOL_CATEGORIESvaluesr]   rr   _plugin_web_search_providers_plugin_image_gen_providers_plugin_video_gen_providers_plugin_browser_providersrW   )keyscatprovpsbuilders        rH   valid_post_setup_keysr}    s    UUD%%''  GGK,, 	 	D,''B 	 	%##!	  			 ! !XXl++ !HHRLLL!  	 	 	H	Ks   9C
CCc           
         t          | dd          }|st          d           dS t                      }||vr9t          d|dd                    t	          |                    pd            dS t          d	|            	 t          |           n*# t          $ r}t          d
|            Y d}~dS d}~ww xY wt          d| d           dS )u  ``hermes tools post-setup <key>`` — non-interactive post-setup runner.

    Runs the install/bootstrap hook a provider declares (npm install for
    browser/Camofox, pip install for kittentts/piper/ddgs, cua-driver fetch,
    etc.). This is the stable, scriptable target the dashboard spawns so the
    GUI can drive backend setup without re-implementing the install logic.
    Returns a process exit code (0 ok, 2 unknown key).
    r/  Nz$Usage: hermes tools post-setup <key>rA   zUnknown post-setup key: z. Valid keys: , z(none)zRunning post-setup hook: zPost-setup failed: r@   zPost-setup 'z
' completer   )	getattr_print_errorr}  joinsortedr  rp  rW   r#  )r   r   validra  s       rH   run_post_setup_commandr    s,    $($
/
/C ;<<<q!##E
%Bs B B99VE]]33?xB B	
 	
 	
 q1C11222   0300111qqqqq 1#1112221s   B 
B:B55B: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_TOKENr8   SLACK_BOT_TOKENslackWHATSAPP_ENABLEDwhatsapp	QQ_APP_IDqqbot)r   rs   )rj  s    rH   _get_enabled_platformsr    s    gG)** #z"""()) "y!!!&''  w'(( #z"""[!!  wNrJ   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       rH   _platform_toolset_summaryr    sC     *,,	#%G : :+FD99NrJ   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)
isinstancerZ   intrY   rK   r   )valuer   lowereds      rH   _parse_enabled_flagr    s    }% % z% ++--%%''00041115NrJ   include_default_mcp_serversr  c                  )*+ 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                       }	|	r0)fd|D             }
t                      }|D ].}|)v s|+v r||vr|                     ||                     /|rt                      }t          D ][\  }}}t          |          st           ||                    }|r*|                    |          r|                    |           \t          t                     }|v rt"          vr|                               d|v r)t'          j        d          r|                    d           ||z  }|
|z  }
nZt                      }|D ] }|                     ||                     !t                      }
t          D ][\  }}}t          |          st           ||                    }|r*|                    |          r|
                    |           \t          d          ot+                      }|r|
                    d           t          t                     }|v rt"          vr|                               d|v r)t'          j        d          r|                    d           |rd|v 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 |                    d          r6t           ||                    }|r|                    |          sf|                    |          r||                    |          s*|
                    |           |                    |           +r{|                     di           }t          |                    g                     }+D ]?}||v r|
                    |           |t           v r&||vr|
                    |           @|                     d          pi }t	          |t.                    si }t1          |                    d          pd                                                                          } |v o*t	          |                              t
                    o| }!| r| dk    r|!s|
                    d           )*+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 rh   rY   rF   tss     rH   
<listcomp>z'_get_platform_tools.<locals>.<listcomp>  s    555SWW555rJ   c                     h | ]\  }}}|	S rh   rh   ri   s      rH   rk   z&_get_platform_tools.<locals>.<setcomp>!      JJJLFAqJJJrJ   c                     h | ]
}|d          S r   rh   rF   ps     rH   rk   z&_get_platform_tools.<locals>.<setcomp>#      NNNaQ01NNNrJ   c              3       K   | ]}|v V  	d S rC   rh   )rF   r  configurable_keyss     rH   rI   z&_get_platform_tools.<locals>.<genexpr>*  s)      NN"b$55NNNNNNrJ   c                 <    h | ]}|v t          |          |S rh   r~   )rF   r  r  rb   s     rH   rk   z&_get_platform_tools.<locals>.<setcomp>-  s?     
 
 
&&&+HX+V+V& &&&rJ   r6   r   r&   c                 <    h | ]}|                     d           |S )r  )
startswith)rF   r   s     rH   rk   z&_get_platform_tools.<locals>.<setcomp>  s)    <<<1ALL$;$;<Q<<<rJ   includespostureknown_plugin_toolsetscontextengine
compressorr.   c                 ,    h | ]}|vr
|vr|v|S rh   rh   )rF   r  r  platform_default_keysplugin_ts_keyss     rH   rk   z&_get_platform_tools.<locals>.<setcomp>  sH       &&&n$$+++	 	 ,++rJ   mcp_serversc                     h | ]N\  }}t          |t                    t          |                    d d          d          ?t	          |          OS )rj  Tr   )r  dictr  r]   rY   )rF   r   
server_cfgs      rH   rk   z&_get_platform_tools.<locals>.<setcomp>  sg       D*j$''  
y$ ? ?NNN	D		  rJ   no_mcpagentdisabled_toolsetsc                 ,    h | ]}t          |          S rh   r  r  s     rH   rk   z&_get_platform_tools.<locals>.<setcomp>   s    <<<BB<<<rJ   )toolsetsr  r  r]   r  ro   r   rp   r{   rs  rN   rz   updatere   issubsetrr   _DEFAULT_OFF_TOOLSETSr`   remover[   getenvr_   itemsr  rY   rK   r   ),r  rb   r  r  r  r  toolset_names	plat_info
default_tshas_explicit_configenabled_toolsetscomposite_toolsts_nameexpandedra   rj   ts_toolsdefault_offall_tool_namesx_search_auto_enabled
_plat_info_default_tsplatform_tool_universeconfigurable_tool_universeckclaimedskipts_def	known_mapknown_for_platformptscontext_cfgcontext_engine_nameexplicit_empty_selectionexplicit_passthroughr  enabled_mcp_serversexplicit_mcp_servers	agent_cfgr  disabled_setr  r  r  s,    `                                       @@@rH   r  r    s'	    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+++w./H/Hh&&""??7#;#;<<<< 	)uuH 5 ) )14VXFF v6677 ) 1 1/ B B )LL(((344K;&&8;Y+Y+Y""8,,,+--")L2I2I-""?333#H( $ 	< 	<G!!//'":":;;;;551 	- 	-LFAq0BB ??62233H -H--n== - $$V,,, **h?? +(** 	 ! 	-  ,,,/00 {""x7U'U'Ux((( k))bi.E.E)/// ! 	+Z;%>%>z***K' x((J3=W*.//CWXCWCWK !=!=>>!$ ? ?"))//"*=*=>>>>eeG" 0 0v..////~-0EED<<<<<<DC%&&(33D"..** % %T>>::j!! 	 ::i   	v..// 	x001GHH 	788 	  )) 	%  (((NN8$$$  *JJ6;;	 x!<!<==! 		* 		*Cm## $$S))))---... $$S))) **Y''-2Kk4(( kooh77G<HHNNPPVVXX%% 	(,,X66==	 
  /2lBBKcB-...        **]++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(rJ   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 rh   r~   )rF   r  rb   s     rH   rk   z'_save_platform_tools.<locals>.<setcomp>  s9       (X66
  rJ   c                     h | ]\  }}}|	S rh   rh   ri   s      rH   rk   z'_save_platform_tools.<locals>.<setcomp>  r  rJ   c                     h | ]
}|d          S r  rh   r  s     rH   rk   z'_save_platform_tools.<locals>.<setcomp>  r  rJ   r  c                 ,    g | ]}t          |          S rh   r  r  s     rH   r  z(_save_platform_tools.<locals>.<listcomp>$  s    ===RR===rJ   c                 $    h | ]}|v|v
|S rh   rh   )rF   rv   r  r  s     rH   rk   z'_save_platform_tools.<locals>.<setcomp>(  s:       )))e;P.P.P 	.P.P.PrJ   r  r  N)
setdefaultrp   r{   r   rs  r   r  ro   discardr  r
   )r  rb   r  plugin_keysexisting_toolsetspreserved_entriesr  r  s    `    @@rH   _save_platform_toolsr    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rJ   force_freshr  c                H   |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                              |           }	|	rNt          |	||          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#   r%   r  Tr   c              3   @   K   | ]}t          |d                    V  dS r   NrT   )rF   r   s     rH   rI   z$_toolset_has_keys.<locals>.<genexpr>^  s.      ==q=5**======rJ   c              3   :   K   | ]\  }}t          |          V  d S rC   rT   )rF   varrj   s      rH   rI   z$_toolset_has_keys.<locals>.<genexpr>f  s.      ==fc1}S!!======rJ   )r	   agent.auxiliary_clientr  rW   r   featuresr]   	availablemanaged_by_nousrr  _visible_providersallTOOLSET_ENV_REQUIREMENTS)ra   r  r  r  	_providerclient_modelr  featurery  providerr   requirementss                rH   _toolset_has_keysr  >  s    ~	MMMMMM(F(F(H(H%Ivv%% 	 	 	55	 DDD1&kRRR#''// 	) 	W-D 	4 

f
%
%C
 *3KPPP 	 	H||J33H tt==H===== ttu ,//;;L t========s   0 
>>questionrM  c                 ,    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  rM  r   r  s       rH   _prompt_choicer   k  s/    555555HgPWXXXXrJ   _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_encodingrW   loggerdebugmodel_toolstools.registryr$  get_all_tool_names
get_schemar  dumpsrM   encode)r'  encr+  r$  countsr   schemarO   s           rH   _estimate_tool_tokensr4  w  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_labelrj  c                    ddl m} ddlm t	                      t                      }fd|D             g }D ]l\  }}}	d}
t          ||          s6t                              |          st                              |          rd}
|
                    | d|	 d	|
            m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 rh   r~   rF   r   ldrb   s       rH   r  z-_prompt_toolset_checklist.<locals>.<listcomp>  E       q!Q(H55	
Aq	  rJ   r?   r  z  [no API key]  ()c                 *    h | ]\  }\  }}}|v |S rh   rh   )rF   ira   rj   rj  s       rH   rk   z,_prompt_toolset_checklist.<locals>.<setcomp>  s8       a&!QW 	
rJ   Nc                     g | ]\  }}}|	S rh   rh   ri   s      rH   r  z-_prompt_toolset_checklist.<locals>.<listcomp>  s    888lfa6888rJ   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   r   tool_tokenss     rH   rI   z?_prompt_toolset_checklist.<locals>.status_fn.<locals>.<genexpr>  s1      GGTa00GGGGGGrJ   i  zEst. tool context: ~z.1fzk tokensz tokens)rz   r  sum)rC  	all_toolsrn  totalr  rG  ts_keyss       rH   	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8rJ   z
Tools for )r  rL  c                 ,    h | ]}|         d          S r   rh   )rF   rA  	effectives     rH   rk   z,_prompt_toolset_checklist.<locals>.<setcomp>  s!    ,,,IaLO,,,rJ   )r  r8  r  r  r4  rw   r  rr  r]   r  rs   	enumeraterz   rY   )r5  rj  rb   r  r8  effective_alllabelsra   ts_labelts_descsuffixpre_selectedrL  rC  rO  r  rG  rK  s    ``           @@@@rH   _prompt_toolset_checklistrW    s    655555(((((( ())K8::M   #0  I
 F%. : :!'!&kBBB	& $$V,,	&0H0L0LV0T0T	& &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,,,,rJ   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.
    r  N)rr  r]   _configure_tool_category_configure_simple_requirements)ra   r  r  ry  s       rH   _configure_toolsetr[    sR     

f
%
%C
 / f+NNNNNN 	'v.....rJ   c                  "   	 ddl m}  ddlm}  |              |             }n# t          $ r g cY S w xY wg }|D ]}	 |                                }n# t          $ r Y $w xY wt          |t                    s>|                    d|j	                  |                    dd          |                    dd          |                    dg           |j
        d	}|                    d
          r|d
         |d
<   |                    |           |S )u  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. Every image-gen backend is a plugin now — there
    are no hardcoded rows left in ``TOOL_CATEGORIES["image_gen"]`` for
    this function to dedupe against (see issue #26241).
    r   list_providers_ensure_plugins_discoveredr   r   r?   r   r   )r   r   r   r   image_gen_plugin_namer   )agent.image_gen_registryr^  rq   r`  rW   get_setup_schemar  r  r]   display_namer   rs   r^  r`  r   rowsr  r3  rows          rH   ru  ru    sg   ;;;;;;AAAAAA""$$$"N$$		   			 D  	..00FF 	 	 	H	&$'' 	JJvx'<==ZZ,,::eR((

:r22%-]
 
 ::l## 	5 &| 4CCK    # 22A
AAc                  "   	 ddl m}  ddlm}  |              |             }n# t          $ r g cY S w xY wg }|D ]}	 |                                }n# t          $ r Y $w xY wt          |t                    s>|                    d|j	                  |                    dd          |                    dd          |                    dg           |j
        d	}|                    d
          r|d
         |d
<   |                    |           |S )u`  Build picker-row dicts from plugin-registered video gen providers.

    Mirrors ``_plugin_image_gen_providers`` exactly — every video backend
    is a plugin, so this function is the *only* source of provider rows
    for the Video Generation category. The hardcoded ``TOOL_CATEGORIES``
    entry for ``video_gen`` keeps an empty providers list.
    r   r]  r_  r   r   r?   r   r   )r   r   r   r   r   r   )agent.video_gen_registryr^  rq   r`  rW   rc  r  r  r]   rd  r   rs   re  s          rH   rv  rv    sg   ;;;;;;AAAAAA""$$$"N$$		   			 D  	..00FF 	 	 	H	&$'' 	JJvx'<==ZZ,,::eR((

:r22%-]
 
 ::l## 	5 &| 4CCKrh  c                  B   	 ddl m}  ddlm}  |              |             }n# t          $ r g cY S w xY wg }|D ]}t          |dd          }|s	 |                                }n# t          $ r Y 8w xY wt          |t                    sR|	                    d|j
                  |	                    dd          |	                    dd          |	                    d	g           ||d
}|	                    d          r|d         |d<   |                    |           |S )a\  Build picker-row dicts from plugin-registered web search providers.

    Each returned dict is a regular ``TOOL_CATEGORIES`` provider row. It
    populates both ``web_backend`` (legacy field consumed by setup +
    selection helpers) and ``web_search_plugin_name`` (informational
    marker) so the picker behaves identically whether a provider is
    hardcoded or plugin-registered.

    After PR #25182, all seven web providers (brave-free, ddgs, searxng,
    exa, parallel, tavily, firecrawl) are plugins; this helper is the sole
    source of provider rows for the Web Search & Extract category.
    r   r]  r_  r   Nr   r?   r   r   )r   r   r   r   r   web_search_plugin_namer   )agent.web_search_registryr^  rq   r`  rW   r  rc  r  r  r]   rd  rs   )_list_web_providersr`  r   rf  r  r   r3  rg  s           rH   rt  rt  L  s   SSSSSSAAAAAA""$$$''))		   			 D  x.. 		..00FF 	 	 	H	&$'' 	JJvx'<==ZZ,,::eR((

:r22&*
 
 ::l## 	5 &| 4CCK    # 22A%%
A21A2c                  B   	 ddl m}  ddlm}  |              |             }n# t          $ r g cY S w xY wg }|D ]}t          |dd          }|s	 |                                }n# t          $ r Y 8w xY wt          |t                    sR|	                    d|j
                  |	                    dd          |	                    dd          |	                    d	g           ||d
}|	                    d          r|d         |d<   |                    |           |S )a1  Build picker-row dicts from plugin-registered cloud browser providers.

    Each returned dict mirrors the legacy ``TOOL_CATEGORIES["browser"]``
    schema (``name`` / ``badge`` / ``tag`` / ``env_vars`` /
    ``browser_provider`` / ``post_setup``) so the picker behaves identically
    whether a provider was hardcoded or plugin-registered.

    Populates ``browser_provider`` (the legacy config key written to
    ``browser.cloud_provider``) and a ``browser_plugin_name`` marker so
    setup / write paths can route through the registry when they want to.
    r   r]  r_  r   Nr   r?   r   r   )r   r   r   r   r   browser_plugin_namer   )agent.browser_registryr^  rq   r`  rW   r  rc  r  r  r]   rd  rs   )_list_browser_providersr`  r   rf  r  r   r3  rg  s           rH   rw  rw    s   TTTTTTAAAAAA""$$$++--		   			 D  x.. 		..00FF 	 	 	H	&$'' 	JJvx'<==ZZ,,::eR((

:r22 $#'
 
 ::l## 	5 &| 4CCKro  c                     	 ddl m} m} ddlm}  |              |            }n# t
          $ r g cY S w xY wg }|D ]}t          |dd          }|s|                                                                | v r@	 |	                                }n# t
          $ r Y bw xY wt          |t                    s||                    d|j                  |                    dd          |                    dd          |                    d	g           ||d
}|                    d          r|d         |d<   |                    |           |S )u  Build picker-row dicts from plugin-registered TTS providers.

    Issue #30398 — the ``register_tts_provider()`` plugin hook
    coexists alongside the 10 built-in TTS providers
    (``edge``/``openai``/``elevenlabs``/…) and the
    ``tts.providers.<name>: type: command`` registry from PR #17843.
    Built-in rows stay hardcoded in ``TOOL_CATEGORIES["tts"]``; this
    function only injects PLUGIN-registered providers.

    Defensive: plugins whose name collides with a built-in TTS provider
    are filtered out — even though the registry already rejects them
    at registration time, a future code path that registers directly
    via :func:`agent.tts_registry.register_provider` could slip
    through. Filtering here keeps the picker invariant.
    r   )_BUILTIN_NAMESr^  r_  r   Nr   r?   r   r   )r   r   r   r   r   tts_plugin_namer   )agent.tts_registryru  r^  rq   r`  rW   r  r   rK   rc  r  r  r]   rd  rs   )	ru  r^  r`  r   rf  r  r   r3  rg  s	            rH   _plugin_tts_providersrx    s    EEEEEEEEAAAAAA""$$$"N$$		   			 D  x.. 	::<<>11	..00FF 	 	 	H	&$'' 	JJvx'<==ZZ,,::eR((

:r22 !#

 

 ::l## 	5 &| 4CCKs   "% 44<B
BBry  c                   t          ||          }|j        }t          |o|j        o|j        duo|j                  }g }|                     dg           D ]|}|                    d          r|                    d          s|j        s4|r1|                    d          dk    r|r|                    d          sg|	                    |           }|                     d          d	k    r!|
                    t                                 |                     d          d
k    r!|
                    t                                 |                     d          dk    r!|
                    t                                 |                     d          dk    r!|
                    t                                 |                     d          dk    r!|
                    t                                 |S )u  Return provider entries visible for the current auth/config state.

    Nous-managed Tool Gateway rows (``managed_nous_feature``) are always
    shown — even to logged-out / unentitled users — so the picker advertises
    that the capability exists.  Selecting one drives an inline Nous Portal
    login + entitlement check (see ``_configure_provider``); the row only
    *activates* the gateway once paid access is confirmed.
    r  Tr   r   r   r%   z	fal-videor   r   r   r   r   r   )r   account_inforZ   rJ  paid_service_accesstool_gateway_entitledr]   nous_auth_presenttool_gateway_entitled_forrs   extendru  rv  rt  rw  rx  )ry  r  r  r  acct	pool_onlyvisibler  s           rH   r  r    s    .f+NNNH D  	'N	'$D0	' &	 I GGGK,, ! ! LL-..	LL!788	 .	
  	344CC D"<<[II D x     wwv,,,244555 wwv,,,244555 wwv000355666 wwv...022333
 wwv***,..///NrJ   
capabilityc                    dS )a  Deprecated: Nous Tool Gateway rows are no longer hidden.

    Previously this returned a "log in / upgrade" banner shown above a
    category when its Nous-managed rows were filtered out for unentitled
    users. Those rows are now always listed (see ``_visible_providers``), and
    the login + entitlement guidance happens inline when the user selects one
    (``ensure_nous_portal_access``). Kept as a no-op so call sites stay simple;
    always returns an empty string.
    r?   rh   )ry  r  r  r  s       rH   _hidden_nous_gateway_messager  ?  s	      2rJ   c                  \    t          t          j        t                                          S rC   )rZ   r   r   r   rh   rJ   rH   <lambda>r  `  s    $v|O,=,=>>?? rJ   _POST_SETUP_INSTALLEDc                     t                               |           }|dS 	 t           |                      S # t          $ r Y dS w xY w)zAReturn True when the post_setup install side-effect is satisfied.NT)r  r]   rZ   rW   )r/  	predicates     rH   _post_setup_already_installedr  d  s]    %)).99I tIIKK      tts   7 
AAc                   t                               |           }|st          | ||           S t          |||          D ]+}|                    d          }|rt	          |          s dS ,| dk    r0|                    di           }t          |t                     pd|vS | dk    rddlm}  |             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 | dk    r_	 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   Tr)   r  r   r   )check_web_api_keyr   cloud_providerr#   Fr]  r_  r%   )rr  r]   r  r  r  r  r  tools.web_toolsr  r   rb  r^  rq   r`  is_availablerW   rj  )ra   r  r  ry  r  r   tts_cfgr  browser_cfgr^  r`  s              rH   #_toolset_needs_configuration_promptr  q  s    

f
%
%C N$VVMMMMM 'sFLLL  \\,//
 	;JGG 	44**UB''gt,,,I
'0II 	655555$$&&&&jjB//k4000W4DK4WW !"" 	5	??????EEEEEE&&(((*N,,  ,,.. %$uu%    H	  	 	 	D	t	??????EEEEEE&&(((*N,,  ,,.. %$uu%    H	  	 	 	D	t [IIIIIsx   "E +E?E E 
EE EE 
E! E!-"F9 F($F9 'F9 (
F52F9 4F55F9 9
GGc                D   |                     dd          }|d         }t          |||          }t          ||d| |          }|                     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                     |r)|                                D ]}
t          d|
            t!          |	||           dS t                       |                     dd          }t          t          d| d| d| dt          j                             |                     d          rt          d|d                     |r)|                                D ]}
t          d|
            t                       	 t#          t%          ||          j                  }n# t(          $ r d}Y nw xY w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#          r|rd$}nd%}|                    |d          | | | |            |                    d&           t1          |||          }t3          d| d'||          }|t          |          k    rt          d(|            dS t!          ||         ||           dS ))z2Configure a tool category with provider selection.r   r?   r   r  #the Nous Subscription provider for requires_python  z requires Python r   .r@   z+ (current: r?  z3  Upgrade Python and reinstall to enable this tool.N  ---   () ---r   r   r   zChoose a providerz - z ---Fr    []    — r   c              3   @   K   | ]}t          |d                    V  dS r	  rT   rF   vs     rH   rI   z+_configure_tool_category.<locals>.<genexpr>	  .      "M"Mq=5#:#:"M"M"M"M"M"MrJ   	 [active] [configured]r   u*     ★ Included with your Nous subscriptionu'     ★ via Nous Portal (login on select)u(   Skip — keep defaults / configure later:z
  Skipped )r]   r  r  r   version_infoprintr  majorminorr  rM   r   r   CYANrW  r  _configure_providerrZ   r   r}  rW   r  _is_provider_activers   _detect_active_provider_indexr   )ra   ry  r  r  r   r   r   hidden_nous_messager  r  rf  title_nous_logged_inprovider_choicesr  r   r   
configuredr   
sub_markerdefault_idxprovider_idxs                         rH   rY  rY    s>    7762Dv;D"3KHHHI64d44	   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 	,+6688 , ,{D{{++++Hf+FFFFFF 	':;;e8T88D88U888&+FFGGG77<   	20S.00111 	,+6688 , ,{D{{++++	$". +   $	 OO  	$ 	$ 	$#OOO	$  	X 	XA*+%%..@&7&&&&bE()e<$!E($$$"CJuuZ,,H 1s"M"MH"M"M"MMM 1&q&kJJJ 1!,JJ! 1!#JJ!0J Juu+,, K" K!MJJ!JJ##qy$V%$V$Vj$V*$V$VWWWW 	 JKKK 4#
 
 
 &m5mmm5E{SS 3y>>))+T++,,,FIl3VUUUUUUs   #J5 5KKr  c                   |                      d          }|rD|                     di           }t          |t                    o|                     d          |k    S |                      d          }|rY|                      d          sD|                     di           }t          |t                    o|                     d          |k    S |                      d          }|rt          ||          }|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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.ra  r#   r  r   r   r%   r  NF>   Nr?   r   use_gatewayr  r   r)   r   r   r  r   r   backendr   r   )r]   r  r  r   r  r   r  r   )r  r  r  plugin_name	image_cfgvideo_plugin_name	video_cfgmanaged_featurer  r  configured_providercurrents               rH   r  r  -	  sC    ,,677K XJJ{B//	)T**Wy}}Z/H/HK/WW %<== ^.D!E!E ^JJ{B//	)T**]y}}Z/H/HL]/]]ll#9::O "'1&kRRR#''88?5k))

;33I)T** !&/mmJ&?&?#&.??? 5==//;OT]TaTaboTpTpz  EA  EA  EA; 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	

 5rJ   r   c                    t          |           D ]P\  }}t          |||          r|c S |                    dg           }|rt          d |D                       r|c S QdS )z8Return the index of the currently active provider, or 0.r  r   c              3   @   K   | ]}t          |d                    V  dS r	  rT   r  s     rH   rI   z0_detect_active_provider_index.<locals>.<genexpr>	  s.      FFM!E(33FFFFFFrJ   r   )rP  r  r]   r  )r   r  r  rA  r  r   s         rH   r  r  x	  s     )$$  1q&kBBB 	HHH55R(( 	FFXFFFFF 	HHH1rJ   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     rH   _fal_model_catalogr  	  s%    EEEEEEEE}$$rJ   zFAL.ai)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pricerF  )r  r  r  s      rH   _format_imagegen_model_rowr  	  s      	#fWo 	#* 	# 	#88GR  	##)'?	#7	# 	#88K$$	#'-k':	#?	# 	# 88GR  	# 	#rJ   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 rh   rh   rF   mcurrent_models     rH   r  z-_configure_imagegen_model.<locals>.<listcomp>	  #     L L Lqm9K9K9K9K9KrJ   c              3   4   K   | ]}t          |          V  d S rC   rM   rF   r  s     rH   rI   z,_configure_imagegen_model.<locals>.<genexpr>	  (      //SVV//////rJ   c              3   j   K   | ]-}t          |                             d d                    V  .dS r  r?   NrM   r]   rF   r  catalogs     rH   rI   z,_configure_imagegen_model.<locals>.<genexpr>	  =      JJ1c'!*.."5566JJJJJJrJ      r  c              3   j   K   | ]-}t          |                             d d                    V  .dS r  r?   Nr  r  s     rH   rI   z,_configure_imagegen_model.<locals>.<genexpr>	  =      RR1#gajnn["==>>RRRRRRrJ   r   r  r  r  r  Modelr  Speedr  	Strengthsr    Price     ← currently in use	  Choose r   model:  Model set to: )IMAGEGEN_BACKENDSr]   r  r  r  ro   rx  maxr  r   r   r  r  rs   r   r#  )r  r  r  default_modelcfg_keycur_cfg	model_idsorderedr  headerrf  midrg  rn  rC  r  r  s                  @@rH   _configure_imagegen_modelr  	  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../////rJ   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  r  r  s     rH   r   z-_plugin_image_gen_catalog.<locals>.<dictcomp>
  2    OOOaZ4-@-@OTQYYqwYYYrJ   )rb  r   rq   r`  rW   list_modelsr  r  r   r`  r  modelsr   r  s          rH   _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   !$ 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 rh   rh   r  s     rH   r  z8_configure_imagegen_model_for_plugin.<locals>.<listcomp>
  r  rJ   c              3   4   K   | ]}t          |          V  d S rC   r  r  s     rH   rI   z7_configure_imagegen_model_for_plugin.<locals>.<genexpr>
  r  rJ   c              3   j   K   | ]-}t          |                             d d                    V  .dS r  r  r  s     rH   rI   z7_configure_imagegen_model_for_plugin.<locals>.<genexpr> 
  r  rJ   r  r  c              3   j   K   | ]-}t          |                             d d                    V  .dS r  r  r  s     rH   rI   z7_configure_imagegen_model_for_plugin.<locals>.<genexpr>!
  r  rJ   r   r  r  r  r  r  r  r  r  r  r  r  r  r  )r	  r  r  r  r]   ro   rx  r  r  r   r   r  r  rs   r   r#  )r  r  r  r  r  r  r  r  rf  r  rg  rn  rC  r  r  s                @@rH   $_configure_imagegen_model_for_pluginr  
  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../////rJ   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)r  r  r  r#  r  )r  r  img_cfgs      rH   !_select_plugin_image_gen_providerr  ?
  sy    R00Ggt$$ &%{%GJ"GM@;@@AAA(f=====rJ   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 )zReturn ``(catalog_dict, default_model_id)`` for a video gen plugin.

    Mirrors :func:`_plugin_image_gen_catalog`. Returns ``({}, None)`` when
    the plugin isn't registered or has no models.
    r   r  r_  Nc                 R    i | ]$}t          |t                    d |v |d          |%S r  r  r  s     rH   r   z-_plugin_video_gen_catalog.<locals>.<dictcomp>c
  r  rJ   )rj  r   rq   r`  rW   r  r  r  s          rH   _plugin_video_gen_catalogr  N
  s    999999AAAAAA""$$$<,,   4x4x%%''-2((**   4xOO6OOOGGr
  c                 6   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 ]}	|	         }
d|	d|d          d|
                    dd          d|d          d|
                    dd          d|d          d|
                    dd           }|	k    r|dz  }|                    |           t          d|  d|d
          }||         }||d<   t          d|            dS )zPrompt for a video gen model from a plugin's catalog.

    Mirrors :func:`_configure_imagegen_model_for_plugin`. Writes the
    selection to ``video_gen.model``.
    Nr%   r  c                      g | ]
}|k    |S rh   rh   r  s     rH   r  z8_configure_videogen_model_for_plugin.<locals>.<listcomp>z
  r  rJ   c              3   4   K   | ]}t          |          V  d S rC   r  r  s     rH   rI   z7_configure_videogen_model_for_plugin.<locals>.<genexpr>}
  r  rJ   c              3   j   K   | ]-}t          |                             d d                    V  .dS r  r  r  s     rH   rI   z7_configure_videogen_model_for_plugin.<locals>.<genexpr>~
  r  rJ   r  r  c              3   j   K   | ]-}t          |                             d d                    V  .dS r  r  r  s     rH   rI   z7_configure_videogen_model_for_plugin.<locals>.<genexpr>
  r  rJ   r   r  r  r  r  r  r  r  r  r  r?   r  r  r  r  r  )r  r  r  r  r]   ro   rx  r  r  r   r   r  rs   r   r#  )r  r  r  r  r  r  r  r  rf  r  r  rg  rn  rC  r  r  s                 @@rH   $_configure_videogen_model_for_pluginr  g
  s    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 
 
s|' 'vg '+ ' 'xx$$''-g';' 'xxR(('+1++>'C' ' xx$$' ' 	 -++CC
(K(((  C S\FGG.f../////rJ   r  r  c                    |                     di           }t          |t                    si }||d<   | |d<   ||d<   t          d|             t	          | |           dS )z<Persist a plugin-backed video generation provider selection.r%   r  r  z  video_gen.provider set to: N)r  r  r  r#  r  )r  r  r  vid_cfgs       rH   !_select_plugin_video_gen_providerr   
  sy    R00Ggt$$ &%{%GJ(GM@;@@AAA(f=====rJ   c                   |                      d          r3|                    di           }| d         |d<   t          |          |d<   d| v r7| d         }|                    di           }|r||d<   t          |          |d<   |                      d          r3|                    d	i           }| d         |d
<   t          |          |d<   |r|dvrd|                    |i           d<   dS |s~t                                          D ]f\  }}| |                     dg           v rG|                     |          }	t          |	t                    r|	                     d          rd|	d<    dS edS dS )u  Persist the provider/backend config keys for a selected provider.

    This is the pure, non-interactive core of :func:`_configure_provider` —
    it writes ``tts.provider`` / ``browser.cloud_provider`` / ``web.backend``
    and the ``use_gateway`` flags based on the provider's markers, but does
    NOT prompt for env vars, run post-setup hooks, gate on Nous auth, or run
    interactive model pickers. Both the CLI configurator and the desktop GUI
    ``PUT .../provider`` endpoint call through here so there is one code path.
    r   r)   r  r  r   r   r  r   r   r  >   r)   r   r   Tr   FN)r]   r  rZ   rr  r  r  r  )
r  r  r  r  bpr  web_cfgcat_keyry  sections
             rH   _write_provider_configr&  
  s    ||N## 7##E2..&~6
!%o!6!6 X%%()''	266 	/,.K()%)/%:%:M" ||M"" 7##E2..%m4	!%o!6!6  
?2KKK@D/2..}===  ,1133 	 	LGS377;3333 **W--gt,, 3]1K1K 3-2GM*	 4	 	 	rJ   provider_namec                    t                               |           }|t          d|            t          ||d          }t	          fd|D             d          }|t          dd|           |                    d          }t          |||	           |                    d
          }|rI|                    di           }t          |t                    si }||d<   ||d<   t          |          |d<   |                    d          }	|	rI|                    di           }
t          |
t                    si }
|
|d<   |	|
d<   t          |          |
d<   |                    d          rI|                    di           }t          |t                    r |                    d          dvrd|d<   dS dS dS dS )u  Non-interactively persist a provider selection for a toolset.

    Resolves ``provider_name`` within ``ts_key``'s category (matching the
    rows the GUI/CLI picker shows via :func:`_visible_providers`) and writes
    the corresponding backend/provider config keys. Unlike
    :func:`_configure_provider`, this does NOT prompt for API keys, run
    post-setup hooks, gate on Nous Portal auth, or run interactive model
    pickers — those are handled separately (env endpoints, post-setup
    endpoints, the model picker) in the desktop GUI.

    Raises ``KeyError`` if the toolset has no category or the provider name
    is not found among the visible providers.
    Nz&Toolset has no configurable category: Tr  c              3   N   K   | ]}|                     d           k    |V   dS )r   NrF  )rF   r  r'  s     rH   rI   z+apply_provider_selection.<locals>.<genexpr>
  s7      LL1QUU6]]m-K-KQ-K-K-K-KLLrJ   zUnknown provider z for toolset r   r  ra  r#   r  r  r   r%   r   >   Nr?   r   r   )
rr  r]   KeyErrorr  nextr&  r  r  r  rZ   )ra   r'  r  ry  r   r  r  r  r  video_pluginr  s    `         rH   apply_provider_selectionr.  
  s    

f
%
%C
{HHHIII"3DAAAILLLL	LLLdSSHS=SSSSTTTll#9::O8V_MMMM ,,677K 7##K44'4(( 	*G")F;)
!%o!6!6<< 788L 7##K44'4(( 	*G")F;*
!%o!6!6 ||&'' (##K44gt$$ 	(Z)@)@HY)Y)Y"'GJ( (	( 	()Y)YrJ   c          	         |                      dg           }|                      d          }|rNddlm}m}  ||                      dd           |                     |                    st	          d           d	S |                      d
          r|s}t          ||          }t          |j        o|j        j        du           }|j	        r|sAt          |j        |                      dd                     }	t	          d|	pd            d	S |                      d          r3|                    di           }
| d         |
d<   t          |          |
d<   d| v r2| d         }|dk    rt          d           n|rt          d|            |                      d          rt          d| d                     t          | ||           |s%|                      d          rt          | d                    t          d| d          d           |rt          d           |                      d          }|rt!          ||           d	S |                      d           }|r!t#          ||t          |          !           d	S |                      d"          }|rWt%          ||           |                    d#i           }t'          |t(                    r|                     d          d$vrd%|d<   d	S d}d&}|r|s|                      d
          s	 d&}t*                                          D ]<\  }}|                     d'g           }| |v rt/          d( |D                       rd} n=|rt          ||          }|j	         }n# t0          $ r d&}Y nw xY w|rt          d)           |D ]}t3          |d*                   }|rt          d|d*          d+           4|                     d,d-          }|rt          d.|            |                     d/d-          }|r.t5          d0|                     d1|d*                    |          }n.t5          d0|                     d1|d*                    d2          }|r&t7          |d*         |           t          d3           t	          d4           d&}|                      d          r|rt          | d                    |rt          d| d          d5           |                      d          }|rt!          ||           d	S |                      d           }|r!t#          ||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 )6zAConfigure a single provider - prompt for API keys and set config.r   r   r   !MANAGED_FEATURE_COVERAGE_CATEGORYensure_nous_portal_accessr   the Nous Tool Gatewayr  coverage_categoryB     Not enabled — Nous Portal access is required for this backend.Nr   r  Tr   r  r  CNous Subscription is only available after logging into Nous Portal.r   r)   r  r  r   r     Browser set to local mode!  Browser cloud provider set to: r     Web backend set to: r*  r    - no configuration needed!B  Requests for this tool will be billed to your Nous subscription.ra  r   r  r   r#   >   Nr?   r   r   Fr   c              3   @   K   | ]}|                     d           V  dS )r   NrF  )rF   sibs     rH   rI   z&_configure_provider.<locals>.<genexpr>  s@       2 28;CGG2332 2 2 2 2 2rJ   z-  Available through Nous Portal subscription.r   z: already configuredr   r?     Get yours at: r   r  r   rN  	    Saved    Skippedz configured!)r]   hermes_cli.nous_subscriptionr1  r2  r  r   rZ   rz  r{  r}  r   r  r#  r&  rp  r  r  r   r  r  r  rr  r  rN   rW   r   _promptr   )r  r  r  r   r  r1  r2  r  entitledmessager  r"  r  r-  r  r  all_configured_show_portal_hint_has_managed_sibling_cat_key_cat
_providers	_featuresr  existingr   default_valr  s                               rH   r  r    st    ||J++Hll#9::O  	
 	
 	
 	
 	
 	
 	
 	

 )(",,v/FGGI?CCOTT
 
 
 	 T   F
 ||()) / 1&kRRR!Wh&;&OSW&W
 
 ) 	 	<%&ll63FGGI  G gWe egg   F ||N## 7##E2..&~6
!%o!6!6 X%%()==89999 	ECrCCDDD ||M"" KI0GIIJJJ
 8V_MMMM <<%% 	4H\2333IHV,IIIJJJ 	^\]]] ll#:;; 	-k6BBBF  ||$;<< 	-lFPTUdPePeffffF,,122 	,%gv666 ''R88G'4(( ,W[[-D-DL]-]-]&+
# N
  & &=Q0R0R &	&#( "1"7"7"9"9  $!XXk266
z))c 2 2?I2 2 2 / /) ,0(E# D: +  	 )2(C$C! 	& 	& 	& %	&  ECDDD ' ' 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||$;<< 	-lFPTUdPePeffffF,,122 	,%gv666''R88G'4(( ,W[[-D-DL]-]-]&+
###!, ,	, 	,, ,-]-]s   A3N NN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 backendrA   r   z(  Get key at: https://openrouter.ai/keysz    OPENROUTER_API_KEYTrN  r   rA  rB  r@   z&    OPENAI_BASE_URL (blank for OpenAI)zhttps://api.openai.com/v1zapi.openai.comz    OPENAI_API_KEYz    API keyr   	auxiliarybase_urlAUXILIARY_VISION_MODELzgpt-4o-minic                 :    g | ]\  }}t          |          ||fS rh   rT   )rF   r  r   s      rH   r  z2_configure_simple_requirements.<locals>.<listcomp>  s-    QQQhc3mC>P>PQSzQQQrJ   c              3   0   K   | ]\  }}}|k    |V  d S rC   rh   rF   r   r;  rj   ra   s       rH   rI   z1_configure_simple_requirements.<locals>.<genexpr>  5      \\71aPQU[P[P[QP[P[P[P[\\rJ   r  z requires configuration:  Get key at: r  )r  r  r   r   YELLOWr   r  rD  rK   r   r#  r  r   r	   r  r
   r  r]   r,  rw   )ra   rM  rn  r  rS  is_native_openai	key_labelro  _cfg_auxr  missingrS  r  r   s   `              rH   rZ  rZ    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...;''''=))))* *rJ   c                   g }t                      D ]w\  }}}t                              |          }t                              |          }|s|r9t	          || |          st          ||           r|                    ||f           x|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.r  z#No configured tools to reconfigure.Nc                     g | ]\  }}|S rh   rh   )rF   rj   r<   s      rH   r  z%_reconfigure_tool.<locals>.<listcomp>  s    222Eu222rJ   Cancelz+  Which tool would you like to reconfigure?r@   )rw   rr  r]   r  r   _toolset_enabled_for_reconfigurers   r  r   rM   %_configure_tool_category_for_reconfig _reconfigure_simple_requirementsr
   )
r  r  configurablera   rS  rj   ry  reqsrM  rn  s
             rH   _reconfigure_toolrh    s    LCEE 8 8!!!&))'++F33 	8$ 	8!&&kJJJ83FFCC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-#		
 	
 	
 	
 	
 	)000rJ   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)r   re   r  rW   )ra   r  rb   rj  s       rH   rc  rc  2  s       ,VX>> 		),1  GG
  	 	 	H	W44 5s   /
<<c                   |                     dd          }|d         }t          |||          }t          ||d| |          }t          |          dk    r|d         }t	                       t	          t          d| d	| d
|d          dt          j                             |r)|                                D ]}	t          d|	            t          |||           dS t	                       t	          t          d| d	| dt          j                             |r)|                                D ]}	t          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          | | |            t          |||          }t          d|
|          }t          ||         ||           dS )zBReconfigure a tool category - provider selection + API key update.r   r?   r   r  r  r@   r   r  r  r  r  r  z - Choose a provider ---r   r  r  r   r  r   c              3   @   K   | ]}t          |d                    V  dS r	  rT   r  s     rH   rI   z8_configure_tool_category_for_reconfig.<locals>.<genexpr>p  r  rJ   r  r  z  Select provider:N)r]   r  r  rM   r  r   r   r  rW  r  _reconfigure_providerr  r  rs   r  r   )ra   ry  r  r  r   r   r   r  r  rf  r  r  r   r   r  r   r  r  s                     rH   rd  rd  H  s    7762Dv;D"3KHHHI64d44	   9~~Q<eCTCCDCCHV,<CCCV[QQRRR 	,+6688 , ,{D{{++++hKHHHHHHeBTBBDBBBFKPPQQQ 	,+6688 , ,{D{{++++ 	L 	LA*+%%..@&7&&&&bE()e<$!E($$$"CJuuZ,,H 1s"M"MH"M"M"MMM 1&q&kJJJ 1!,JJ! 1!#JJ!0J##qy$J%$J$Jj$J$JKKKK3#
 
 
 &&:<LkZZl##	
 	
 	
 	
 	
 	
rJ   c          	      *   |                      dg           }|                      d          }|rNddlm}m}  ||                      dd           |                     |                    st	          d           d	S |                      d
          r|s}t          ||          }t          |j        o|j        j        du           }|j	        r|sAt          |j        |                      dd                     }	t	          d|	pd            d	S |                      d          rK|                    di           }
| d         |
d<   t          |          |
d<   t          d| 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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'          }|r!t)          ||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/           |                     d0d1          }|rt%          d2|            |                     d3d1          }t/          d4|                     d5|d,                    d6| 7          }|rL|                                r8t3          |d,         |                                           t          d8           t%          d9           |                      d#          rt#          | d#                    |                      d&          }|rt'          ||           d	S |                      d'          }|r!t)          ||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 ):z)Reconfigure a provider - update API keys.r   r   r   r0  r   r3  r4  r6  Nr   r  Tr   r7  r  r8  r   r)   r  r  z  TTS provider set to: r   r   r   r  r9  r:  r   r   r  r;  >   r)   r   r   r   Fr   r<  r=  ra  r   r  r   r   r#   r   : configured (   ...)r   r?   r@  r   r  r    (Enter to keep current)rN      Updated    Kept current)r]   rC  r1  r2  r  r   rZ   rz  r{  r}  r   r  r#  r  r  rr  r  rp  r  r  r   r  r   rD  rK   r   )r  r  r  r   r  r1  r2  r  rE  rF  r  r"  r  r#  r%  r$  ry  r  r-  r  r  r  rN  r   rO  r  s                             rH   rl  rl    sU    ||J++Hll#9::O  	
 	
 	
 	
 	
 	
 	
 	

 )(",,v/FGGI?CCOTT
 
 
 	 T   F ||()) / 1&kRRR!Wh&;&OSW&W
 
 ) 	 	<%&ll63FGGI  G gWe egg   F||N## M##E2..&~6
!%o!6!6K.1IKKLLL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##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||$;<< 	-lFPTUdPePeffff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=))))*++++||L!! 0./// ,,677K )+v>>> << 788L ),DQ`LaLabbbbll-..G /!'6222e''R88G'4(( /&+
#).&&&/ // /rJ   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 rC   rh   rW  s       rH   rI   z3_reconfigure_simple_requirements.<locals>.<genexpr>!  rX  rJ   r  r  rn  ro  rp  rY  r  rq  TrN  rr  rs  )r  r]   r,  rw   r  r   r   r  r   r  rD  rK   r   r#  )ra   r  rS  r  r   rN  r  s   `      rH   re  re    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...=))))*++++, ,rJ   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         ||          }t+          |          }||z
  |z  }||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/          ||d          "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n||k    r tA          |d0           t                       A||k    rtC          |           t                       e||k    rt                      }|D ]}|t%          ||d          z  }t)          d1|d0          }||k    ra|D ]}t%          ||d          }t+          |          }||z
  |z  }||z
  |z  }t          |         }|s|rt          t          d|d          d2t          j                             t          |          D ]T#t!          #fd3t                      D             #          }
t          t          d4|
 t          j                             Ut          |          D ]T#t!          #fd5t                      D             #          }
t          t          d6|
 t          j                             Ut          |          D ]X$tD                              $          stF                              $          r"tI          $|d0          rt5          $|           Yt7          |||           t9          |           t          t          d7t          j                             tK          |          D ]_\  }}t	          t%          ||d                    } t	          t                                }d#t          |         d          d|  d| d$||<   `n't          t          d8t          j                             t                       E||         }t          |         }t%          ||d          }t)          |d         |d0          }||k    rt+          |          }||z
  |z  }||z
  |z  }|rdt          |          D ]T#t!          #fd9t                      D             #          }
t          t          d|
 t          j                             U|rdt          |          D ]T#t!          #fd:t                      D             #          }
t          t          d|
 t          j                             Ut          |          D ]X$tD                              $          stF                              $          r"tI          $|d0          rt5          $|           Yt7          |||           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 )Aa	  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 rC   rh   rW  s       rH   rI   z tools_command.<locals>.<genexpr>S  5      !i!i1a]^bh]h]h!]h]h]h]h!i!irJ   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 rC   rh   rF   r   r;  rj   r  s       rH   rI   z tools_command.<locals>.<genexpr>v  5      !e!e1a]^bd]d]d!]d]d]d]d!e!erJ   z  + c              3   0   K   | ]\  }}}|k    |V  d S rC   rh   r|  s       rH   rI   z tools_command.<locals>.<genexpr>z  r}  rJ   z  - T)r  r  c              3   0   K   | ]\  }}}|k    |V  d S rC   rh   rW  s       rH   rI   z tools_command.<locals>.<genexpr>  s-      TTGAq!VaTTrJ   u     ✓ z': using your Nous subscription defaultsc                     g | ]<}t                               |          st                              |          r|v:|=S rh   )rr  r]   r  )rF   ra   auto_configureds     rH   r  z!tools_command.<locals>.<listcomp>  s]       !#''//3K3O3OPV3W3W /11 111rJ   z  Configuring z	 tool(s):c              3   0   K   | ]\  }}}|k    |V  d S rC   rh   rW  s       rH   rI   z tools_command.<locals>.<genexpr>  rz  rJ   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   rA   zSelect an option:r  r  zAll platformsr  c              3   0   K   | ]\  }}}|k    |V  d S rC   rh   r|  s       rH   rI   z tools_command.<locals>.<genexpr>  5      )m)m1aefjlelel!elelelel)m)mrJ   z    + c              3   0   K   | ]\  }}}|k    |V  d S rC   rh   r|  s       rH   rI   z tools_command.<locals>.<genexpr>  r  rJ   z    - u+     ✓ Saved configuration for all platformsz  No changesc              3   0   K   | ]\  }}}|k    |V  d S rC   rh   r|  s       rH   rI   z tools_command.<locals>.<genexpr>  r}  rJ   c              3   0   K   | ]\  }}}|k    |V  d S rC   rh   r|  s       rH   rI   z tools_command.<locals>.<genexpr>   r}  rJ   z configurationz  No changes to r6  z  Tool configuration saved to z/config.yamlz:  Changes take effect on next 'hermes' or gateway restart.)(r	   r  r  r  rM   rw   r   r   r  BOLDr  r   r]   rz   DIMr  r,  GREENr  r  rW  r   REDr   rp   rZ  r[  r  r
   rs   rZ   r   rh   _configure_mcp_tools_interactiverr  r  r  rP  rR  r7  )%r   rv  r  enabled_platformsrJ  r  r  pinforj  countr<   current_enabledchecklist_preselectednew_enabled_diff_universeaddedremovedto_configureplatform_choicesplatform_keysr  _has_mcp_global_idx_reconfig_idx_mcp_idx	_done_idxrn  all_currentpkprevpinfo_innerci	new_countr7  r  r  ra   s%                                     @@@rH   tools_commandr  5  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  @% =	 =	DdOE1&$\abbbO %46K$K! 4E'NDY[_``K 5T::N ?2nDE&4FG ? -- ? ?B !e!e!e!e3W3Y3Y!e!e!egijjE%u==>>>> = // = =B !e!e!e!e3W3Y3Y!e!e!egijjE%u
;;<<<<9!,   O
 !11 d dTTTT/DTTTV\]]eSUSSSU[Uabbcccc   %+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y]02BANNN ) -f$7777GGG (??,V444GGG +%%K# b b262[`aaaa3   K
 k))' B BB.vrW\]]]D &=R%@%@N(4/>AE#k1^CG"+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B & &,0      C
 !366 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'N
 
 
 /)) 5T::N ?2nDE&4FG ? -- ? ?B !e!e!e!e3W3Y3Y!e!e!egijjE%u==>>>> = // = =B !e!e!e!e3W3Y3Y!e!e!egijjE%u
;;<<<< !-- ; ;#''// ;3K3O3OPV3W3W ;:$(   ;
 +66::: {;;;%EuW~EEEv|TTUUUU%;5>;;VZHHIII +FDV[\\\]]	8::;; \U7^ \ \	 \ \E \ \ \sy]v 
GGG444444	%T1D1D1F1FTTTV\V`
a
abbb	%Lfj
Y
YZZZ	GGGGGrJ   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 ]{\  }
}|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          |          D             }|                    |
i           }|                    di           }t          |          t          |          k    r-|                    dd           |                    dd           n||d<   |                    dd           t          |          }t          |          |z
  }t7          d|
 d'| d(| d)           d*}	}|	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   r7  r  zNo MCP servers configured.Nc                 H    g | ]\  }}|                     d d          dv| S )rj  T>   Fr  r  r  r  rF  )rF   r   r  s      rH   r  z4_configure_mcp_tools_interactive.<locals>.<listcomp>S  s@       a55D!!)KKK 	
KKKrJ   zAll MCP servers are disabled.z'  Discovering tools from MCP servers...z  Connecting to z server(s): r  )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 rh   rh   )rF   nserver_toolss     rH   r  z4_configure_mcp_tools_interactive.<locals>.<listcomp>l  s#    @@@A!<*?*?a*?*?*?rJ   z  Could not connect to ''c              3   4   K   | ]}t          |          V  d S rC   r  )rF   toolss     rH   rI   z3_configure_mcp_tools_interactive.<locals>.<genexpr>q  s(      DDUc%jjDDDDDDrJ   z  Found z tool(s) across z
 server(s)Fr  z: no tools foundr  includeexcludeF   z...r>  r?  c                     g | ]
}|d          S rN  rh   rF   ts     rH   r  z4_configure_mcp_tools_interactive.<locals>.<listcomp>  s    ***qad***rJ   zMCP Server: z tools))r  z: no changesc                      g | ]
}|         S rh   rh   )rF   rA  
tool_namess     rH   r  z4_configure_mcp_tools_interactive.<locals>.<listcomp>  s    >>>!
1>>>rJ   : z
 enabled, z	 disabledTu"     ✓ MCP tool configuration savedz  No changes to MCP tools)r  r8  r]   r  r  r  r   r   rZ  rM   r  r  tools.mcp_toolr  rW   r  r  rH  rs  r  rs   rz   rP  rr   r  r  popr#  r
   )r  r8  r  enabled_namesr  ra  failedr   total_toolsany_changesserver_namer  srv_cfg	tools_cfginclude_listexclude_listrR  	tool_namedescription
desc_shortrV  rA  rC  chosen_namesenabled_countdisabled_countr  r  s                             @@rH   r  r  D  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 H H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 ?>>>vf~~>>> ((b99&&w33	v;;#e**$$ MM)T***MM)T****#/Ii 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   'C8 8
DDDr  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  rz   r  )r  rb   r  r  rj  updateds         rH   _apply_toolset_changer    s`    !&(PUVVVGC...C...733333rJ   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 rh   rh   )rF   r  r  s     rH   r  z%_apply_mcp_change.<locals>.<listcomp>  s    <<<QQ)^^q^^^rJ   )rz   r]   rL   rr   r  ro   rs   )
r  r  r  failed_serversr  targetr  r  r  r  s
            @rH   _apply_mcp_changer    s    
  #uuN**]++1rK ' '!'c1!5!5Yk)){+++,77DD	y}}Y//5266Y''y)))<<<<'<<<G&	)rJ   r  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 rh   r~   r:  s       rH   r  z%_print_tools_list.<locals>.<listcomp>  r=  rJ   c                     h | ]\  }}}|	S rh   rh   ri   s      rH   rk   z$_print_tools_list.<locals>.<setcomp>  s    EEE|vq!FEEErJ   zBuilt-in toolsets (z):u   ✓ enabledu   ✗ disabledr  c                 (    g | ]\  }}}|v
||fS rh   rh   )rF   r   r;  rj   builtin_keyss       rH   r  z%_print_tools_list.<locals>.<listcomp>  s-    OOOAq,9N9Nq!f9N9N9NrJ   zPlugin toolsets (zMCP servers:r  r  r  z  [include only: r  r  z  [excluded: zall tools enabledN)rw   rp   r  r   r   r  r  r  r  r]   r  r  rZ  )r  r  rb   rQ  rO  ra   r<   rj   statusplugin_entriessrv_namer  r  r  r  r  s     `            @rH   _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rJ   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``).
    rb   r  zUnknown platform 'z
'. Valid: r  Nro   Fr  r  c                     g | ]}d |v|	S r  rh   r  s     rH   r  z0tools_disable_enable_command.<locals>.<listcomp>-  s    :::QS\\q\\\rJ   c                     g | ]}d |v |	S r  rh   r  s     rH   r  z0tools_disable_enable_command.<locals>.<listcomp>.  s    2221rJ   c                     h | ]\  }}}|	S rh   rh   ri   s      rH   rk   z/tools_disable_enable_command.<locals>.<setcomp>0  s    GGGAfGGGrJ   c                     g | ]}|v|	S rh   rh   rF   r  valid_toolsetss     rH   r  z0tools_disable_enable_command.<locals>.<listcomp>1  s#    NNNaa~6M6M6M6M6MrJ   zUnknown toolset 'r  c                     g | ]}|v |	S rh   rh   r  s     rH   r  z0tools_disable_enable_command.<locals>.<listcomp>5  s#    MMMn9L9L19L9L9LrJ   c                 4    g | ]}t          |          |S rh   r~   )rF   r  rb   s     rH   r  z0tools_disable_enable_command.<locals>.<listcomp>8  s9       ,Q99	  rJ   z	Toolset 'z ' is not available on platform 'z	' (only: r?  c                     g | ]}|v|	S rh   rh   )rF   r  restricted_targetss     rH   r  z0tools_disable_enable_command.<locals>.<listcomp>C  s$    UUUBT9T9T19T9T9TrJ   zMCP server 'z' not found in configc                 ^    g | ])}|vd |vs|                     d           d         v'|*S )r  r   )rL   )rF   r  r  unknown_toolsetss     rH   r  z0tools_disable_enable_command.<locals>.<listcomp>P  sP       $$$#Q,,!''#,,q/Q_:_:_ 	
:_:_:_rJ   r  DisabledEnabledr  )tools_actionr  r	   r   r  r  r  r  r]   namesrp   r{   r  r`   rz   r  r  r
   r#  )r   r  r  r  toolset_targetsmcp_targetsr   rd   srv
successfulverbr  rb   r  r  r  s              @@@@@rH   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:::::; ;rJ   )F)r  TrC   )TrN  )r  )NFN)__doc__jsonr  loggingr[   r   r   r   pathlibr   typingr   r   r   r   r^  r   r	   r
   r   r   hermes_cli.colorsr   r   rC  r   r   hermes_cli.nous_accountr   tools.tool_backend_helpersr   utilsr   r   	getLogger__name__r)  __file__r   resolverP  hermes_cli.cli_outputr   r  r   r  r   r#  r   r  r   rD  rp   rY   rQ   r  rZ   r_   r`   __annotations__re   rw   rz   r{   r   hermes_cli.platformsr   _PLATFORMS_REGISTRYr  rr  r  r   r  r   r  r*  r"  rp  r}  r  r  r  r  r  r  r  r  ro   r   r!  r4  rW  r[  ru  rv  rt  rw  rx  r  r  r  r  r  rY  r  r  r  r  r  r  r	  r  r  r  r  r   r&  r.  r  rZ  rh  rc  rd  rl  re  r  r  r  r  r  r  rh   rJ   rH   <module>r     s+  	 	 	      				      



       , , , , , , , , , , , ,              , + + + + + + +        K J J J J J < < < < < < 4 4 4 4 4 4 4 4		8	$	$tH~~$+3355
                >S S    : zyy B$ B B B BB {[7 7 S#c(] 3   2# 2 2 2 2 2 2  4#    c c#h    4 B A A A A A ,&,..  	 ! -28 &  ,'G (&*(-&>@P%Q	 	 %,4@PY  A  A !)  "K %(  %,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	 	 0.A*/;vww 
# #J # ,'Q&*(3&/[$)	 	
 6 # ,'Q&*(3&/[
 */ 
 2 %5C  @'O(  &?  -"/6 	 
   D %" (2=$+-  @'H$1&*(1&;%<-
 
 "(B)5IVmGI I %.'
 
)
#1 1f  )-(4\]]&2FStuu 	
   *>'	 
  '! 2;L
 + 
	 , ) )=8De  oK  L  L8De  oK  L  L )  /68Deff8Deff6Bt  BY  Z  Z
 )	 	
 Y	E ET
 JJIJ  O O O O O 	A A A
s)A A 	A A A AJ-$ - - - -`Z Z Z Z Z Z Zz% %S %$ %RV % % % %PSZC SZ SZ SZ SZl
s3x    @C    @S	      d xS	7J VZ[^`cdg`h[hVi           * )-	{ { {{{ "&	{
 	X{ { { {|5 5 5CPSH 5 5 5 5t (> 	(> (> (>(>(> 	(>
 
(> (> (> (>ZY YS Y4 Y# Yc Y Y Y Y /3 8DcN+ 2 2 2'tCH~ ' ' ' 'Z :-
 :- :- :-:-X:- :-
 :- 	X:- :- :- :-F 	/ / /// 	/ / / /(%T$Z % % % %P#T$Z # # # #`-d4j - - - -p,4: , , , ,^5tDz 5 5 5 5x 	Q Q Q	QQ 	Q
 
$ZQ Q Q Qr   	 
  	   B ?? t   $
# 
$ 
 
 
 
" 	GJ GJ GJGJGJ 	GJ
 
GJ GJ GJ GJ^ oV oV oVoV	oV oV
 oV oV oV oVl 	H H HHH 	H
 
H H H H^ 	   	
 	   <% % % 
!(   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 	> 	> 	> 	> 	> 	>3    290c 904 90D 90 90 90 90x ^c 	> 	> 	>3 	> 	>VZ 	>gk 	> 	> 	> 	>*T *4 *PT * * * *Z5(S 5( 5(d 5(t 5( 5( 5( 5(x 	n, n, n,n,n, 	n, n, n, n,b<*3 <* <* <* <*D + + ++ + + + +\S $ 4    6 <
 <
 <
<
	<
 <

 <
 <
 <
 <
F 	Q/ Q/ Q/Q/Q/ 	Q/ Q/ Q/ Q/h,S , , , ,4I ID I$ I I I I^B>T B> B> B> B>P4$ 4# 4d3i 4Y\ 4 4 4 4d T#Y  C    2'U 'U 'U$ 'U# 'U 'U 'U 'UT=; =; =; =; =;rJ   