
    i|                       U d Z ddlm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  ej        e          Zi Zded<   i Zded	<   d
a ee                                          j        j        dz  dz  ZddZd dZd!dZd"dZd#dZd$dZdS )%u  Provider module registry.

Provider profiles can live in two places:

1. Bundled plugins: ``plugins/model-providers/<name>/`` (shipped with hermes-agent)
2. User plugins: ``$HERMES_HOME/plugins/model-providers/<name>/``

Each plugin directory contains:
  - ``__init__.py`` — calls ``register_provider(profile)`` at import
  - ``plugin.yaml`` — manifest (name, kind: model-provider, version, description)

Discovery is lazy: the first call to ``get_provider_profile()`` or
``list_providers()`` scans both locations and imports every plugin. User
plugins override bundled plugins on name collision (last-writer-wins), so
third parties can monkey-patch or replace any built-in profile without
editing the repo.

For backward compatibility, ``providers/*.py`` files (other than ``base.py``
and ``__init__.py``) are still discovered via ``pkgutil.iter_modules``.
This lets out-of-tree users drop a single-file profile into an editable
install without the plugin dir structure. New profiles should prefer the
plugin layout.

Usage::

    from providers import get_provider_profile
    profile = get_provider_profile("nvidia")   # ProviderProfile or None
    profile = get_provider_profile("kimi")     # checks name + aliases
    )annotationsN)Path)OMIT_TEMPERATUREProviderProfilezdict[str, ProviderProfile]	_REGISTRYzdict[str, str]_ALIASESFpluginsmodel-providersprofiler   returnNonec                V    | t           | j        <   | j        D ]}| j        t          |<   dS )u   Register a provider profile by name and aliases.

    Later registrations with the same name replace earlier ones — so user
    plugins under ``$HERMES_HOME/plugins/model-providers/`` can override
    bundled profiles without editing repo code.
    N)r   namealiasesr   )r   aliass     7/home/piyush/.hermes/hermes-agent/providers/__init__.pyregister_providerr   5   s8     &Igl ' '!,' '    r   strProviderProfile | Nonec                    t           st                       t                              | |           }t                              |          S )z{Look up a provider profile by name or alias.

    Returns None if the provider has no profile (falls back to generic).
    )_discovered_discover_providersr   getr   )r   	canonicals     r   get_provider_profiler   A   s=    
  T4((I==###r   list[ProviderProfile]c                    t           st                       t                      } g }t                                          D ]?}t          |          }|| vr*|                     |           |                    |           @|S )zAReturn all registered provider profiles (one per canonical name).)r   r   setr   valuesidaddappend)seenresultr   pids       r   list_providersr'   L   sz     UUD$&F##%% # #kkd??HHSMMMMM'"""Mr   Path | Nonec                     	 ddl m}   |             dz  dz  }|                                r|ndS # t          $ r Y dS w xY w)z>Return ``$HERMES_HOME/plugins/model-providers/`` if it exists.r   )get_hermes_homer	   r
   N)hermes_constantsr*   is_dir	Exception)r*   ds     r   _user_plugins_dirr/   [   sj    444444O	),==HHJJ(qqD(   tts   -0 
>>
plugin_dirr   sourcec                p   | dz  }|                                 sdS | j                            dd          }|dk    rd| }nd| }|t          j        v rdS 	 t
          j                            ||t          |           g          }||j	        dS t
          j        
                    |          }|t          j        |<   |j	                            |           dS # t          $ rM}t                              d	|| j        |           t          j                            |d           Y d}~dS d}~ww xY w)
zImport a single plugin directory so it self-registers.

    ``source`` is "bundled" or "user", used only for log messages.
    z__init__.pyN-_bundledzplugins.model_providers._hermes_user_provider_)submodule_search_locationsz(Failed to load %s provider plugin %s: %s)existsr   replacesysmodules	importlibutilspec_from_file_locationr   loadermodule_from_specexec_moduler-   loggerwarningpop)r0   r1   	init_file	safe_namemodule_namespecmoduleexcs           r   _import_plugin_dirrK   f   se   
 ]*I  ''S11I<<<:y::ck!!+~55J?P 6 
 
 <4;.F0066#)K ''''' + + +6
QT	
 	
 	
 	T*********	+s    9C AC 
D5(AD00D5c                 H   t           rdS da t                                          rht          t                                                    D ]A} |                                 r| j                            d          r1t          | d           Bt                      }|ct          |                                          D ]A} |                                 r| j                            d          r1t          | d           B	 ddl	}ddl
}|                    |j                  D ]m\  }}}|                    d          s|dk    r"	 t          j        d	|            ;# t          $ r&}t                               d
||           Y d}~fd}~ww xY wdS # t$          $ r Y dS w xY w)a  Populate the registry by importing every provider plugin.

    Order:
      1. Bundled plugins at ``<repo>/plugins/model-providers/<name>/``
      2. User plugins at ``$HERMES_HOME/plugins/model-providers/<name>/``
      3. Legacy per-file modules at ``providers/<name>.py`` (back-compat)

    Each step imports its plugins, which call ``register_provider()`` at
    module-level. Later steps win on name collision.
    NT)r4   .r5   userr   r4   basez
providers.z.Failed to import legacy provider module %s: %s)r   _BUNDLED_PLUGINS_DIRr,   sortediterdirr   
startswithrK   r/   pkgutil	providersiter_modules__path__r<   import_moduleImportErrorrB   rC   r-   )childuser_dirrT   _pkg	_importermodname_ispkgrJ   s           r   r   r      s     K ""$$ 1088::;; 	1 	1E<<>> UZ%:%::%F%F ui0000
 !""HH,,..// 	. 	.E<<>> UZ%:%::%F%F uf----
    *1*>*>t}*M*M 	 	&Iw!!#&& 'V*;*;'(>W(>(>????   Dgs       	 	    s=   AF EF 
F(F	F 	FF 
F! F!)r   r   r   r   )r   r   r   r   )r   r   )r   r(   )r0   r   r1   r   r   r   )r   r   )__doc__
__future__r   r<   importlib.utilloggingr:   pathlibr   providers.baser   r   	getLogger__name__rB   r   __annotations__r   r   __file__resolveparentrP   r   r   r'   r/   rK   r    r   r   <module>rm      sg    < # " " " " "          



       < < < < < < < <		8	$	$(*	 * * * *     	DNN#*Y69JJ 
	' 	' 	' 	'$ $ $ $      #+ #+ #+ #+L3 3 3 3 3 3r   