§
    ÷žyj8  ã                  ó¼   — U d Z ddlmZ ddlZddlZddlmZmZmZ ddl	m
Z
  ej        e¦  «        Zi Zded<    ej        ¦   «         Zdd„Zdd„Zdd„Zdd„Zdd„ZdS )uÚ  
Image Generation Provider Registry
==================================

Central map of registered providers. Populated by plugins at import-time via
``PluginContext.register_image_gen_provider()``; consumed by the
``image_generate`` tool to dispatch each call to the active backend.

Active selection
----------------
The active provider is chosen by ``image_gen.provider`` in ``config.yaml``.
If unset, :func:`get_active_provider` applies fallback logic:

1. If exactly one provider is registered, use it.
2. Otherwise if a provider named ``fal`` is registered, use it (legacy
   default â€” matches pre-plugin behavior).
3. Otherwise return ``None`` (the tool surfaces a helpful error pointing
   the user at ``hermes tools``).
é    )ÚannotationsN)ÚDictÚListÚOptional)ÚImageGenProviderzDict[str, ImageGenProvider]Ú
_providersÚproviderr   ÚreturnÚNonec                ó<  — t          | t          ¦  «        s$t          dt          | ¦  «        j        › �¦  «        ‚| j        }t          |t          ¦  «        r|                     ¦   «         st          d¦  «        ‚t          5  t                               |¦  «        }| t          |<   ddd¦  «         n# 1 swxY w Y   |�0t                               d|t          |¦  «        j        ¦  «         dS t                               d|t          | ¦  «        j        ¦  «         dS )uÚ   Register an image generation provider.

    Re-registration (same ``name``) overwrites the previous entry and logs
    a debug message â€” this makes hot-reload scenarios (tests, dev loops)
    behave predictably.
    z>register_provider() expects an ImageGenProvider instance, got z3Image gen provider .name must be a non-empty stringNz.Image gen provider '%s' re-registered (was %r)z'Registered image gen provider '%s' (%s))Ú
isinstancer   Ú	TypeErrorÚtypeÚ__name__ÚnameÚstrÚstripÚ
ValueErrorÚ_lockr   ÚgetÚloggerÚdebug)r	   r   Úexistings      ú>/home/ragecks/.hermes/hermes-agent/agent/image_gen_registry.pyÚregister_providerr   $   sJ  € õ �hÕ 0Ñ1Ô1ð 
Ýð-Ý˜‘>”>Ô*ð-ð -ñ
ô 
ð 	
ð Œ=€DÝ�d�CÑ Ô ð P¨¯
ª
©¬ð PÝÐNÑOÔOÐOÝ	ð $ð $Ý—>’> $Ñ'Ô'ˆØ#�
�4Ñð$ð $ð $ñ $ô $ð $ð $ð $ð $ð $ð $øøøð $ð $ð $ð $ð ÐÝ�ŠÐEÀtÍTÐRZÉ^Ì^ÔMdÑeÔeÐeÐeÐeå�ŠÐ>ÀÅdÈ8ÁnÄnÔF]Ñ^Ô^Ð^Ð^Ð^s   Â %B1Â1B5Â8B5úList[ImageGenProvider]c                 ó°   — t           5  t          t                               ¦   «         ¦  «        } ddd¦  «         n# 1 swxY w Y   t	          | d„ ¬¦  «        S )z0Return all registered providers, sorted by name.Nc                ó   — | j         S )N©r   )Úps    r   ú<lambda>z list_providers.<locals>.<lambda>@   s   €  q¤v€ ó    )Úkey)r   Úlistr   ÚvaluesÚsorted)Úitemss    r   Úlist_providersr(   <   s�   € å	ð *ð *Ý•Z×&Ò&Ñ(Ô(Ñ)Ô)ˆð*ð *ð *ñ *ô *ð *ð *ð *ð *ð *ð *øøøð *ð *ð *ð *å�%Ð-Ð-Ð.Ñ.Ô.Ð.s   ˆ';»?Á?r   r   úOptional[ImageGenProvider]c                óÊ   — t          | t          ¦  «        sdS t          5  t                               |                      ¦   «         ¦  «        cddd¦  «         S # 1 swxY w Y   dS )z5Return the provider registered under *name*, or None.N)r   r   r   r   r   r   r   s    r   Úget_providerr+   C   sš   € å�d�CÑ Ô ð ØˆtÝ	ð ,ð ,Ý�~Š~˜dŸjšj™lœlÑ+Ô+ð,ð ,ð ,ð ,ñ ,ô ,ð ,ð ,ð ,ð ,ð ,ð ,øøøð ,ð ,ð ,ð ,ð ,ð ,s   Ÿ,AÁAÁAc                 óR  ‡
— d} 	 ddl m}  |¦   «         }t          |t          ¦  «        r|                     d¦  «        nd}t          |t          ¦  «        rR|                     d¦  «        }t          |t
          ¦  «        r(|                     ¦   «         r|                     ¦   «         } n2# t          $ r%}t           	                    d|¦  «         Y d}~nd}~ww xY wt          5  t          t          ¦  «        }ddd¦  «         n# 1 swxY w Y   dd„Š
| r4|                     | ¦  «        }|�|S t           	                    d| ¦  «         ˆ
fd„|                     ¦   «         D ¦   «         }t          |¦  «        dk    r|d         S |                     d¦  «        }	|	� ‰
|	¦  «        r|	S dS )uÑ  Resolve the currently-active provider.

    Reads ``image_gen.provider`` from config.yaml; falls back per the
    module docstring.

    **Availability semantics** (mirrors :mod:`agent.web_search_registry`):

    - When ``image_gen.provider`` is explicitly set, the configured
      provider is returned even if :meth:`ImageGenProvider.is_available`
      reports False â€” the dispatcher surfaces a precise "X_API_KEY is not
      set" error rather than silently switching backends.
    - When ``image_gen.provider`` is unset, the fallback path (single-
      provider shortcut and the FAL legacy preference) is filtered by
      ``is_available()`` so we don't pick a provider the user has no
      credentials for.
    Nr   )Úload_config_readonlyÚ	image_genr	   z1Could not read image_gen.provider from config: %sr    r   r
   Úboolc                ó¸   — 	 t          |                      ¦   «         ¦  «        S # t          $ r,}t                               d| j        |¦  «         Y d}~dS d}~ww xY w)zDWrap ``is_available()`` so a buggy provider doesn't kill resolution.z.image_gen provider %s.is_available() raised %sNF)r/   Úis_availableÚ	Exceptionr   r   r   )r    Úexcs     r   Ú_is_available_safez/get_active_provider.<locals>._is_available_safel   se   € ð	Ý˜ŸšÑ(Ô(Ñ)Ô)Ð)øÝð 	ð 	ð 	Ý�LŠLÐIÈ1Ì6ÐSVÑWÔWÐWØ�5�5�5�5�5øøøøð	øøøs   ‚ # £
A­!AÁAzCimage_gen.provider='%s' configured but not registered; falling backc                ó*   •— g | ]} ‰|¦  «        ¯|‘ŒS © r6   )Ú.0r    r4   s     €r   ú
<listcomp>z'get_active_provider.<locals>.<listcomp>‚   s*   ø€ ÐGÐGÐG�qÐ1CÐ1CÀAÑ1FÔ1FÐG�ÐGÐGÐGr"   é   Úfal)r    r   r
   r/   )Úhermes_cli.configr-   r   Údictr   r   r   r2   r   r   r   r   r%   Úlen)Ú
configuredr-   ÚcfgÚsectionÚrawr3   Úsnapshotr	   Ú	availabler:   r4   s             @r   Úget_active_providerrD   K   s!  ø€ ð" !%€Jð
OØ:Ð:Ð:Ð:Ð:Ð:à"Ð"Ñ$Ô$ˆÝ*4°S½$Ñ*?Ô*?ÐI�#—'’'˜+Ñ&Ô&Ð&ÀTˆÝ�g�tÑ$Ô$ð 	)Ø—+’+˜jÑ)Ô)ˆCÝ˜#�sÑ#Ô#ð )¨¯	ª	©¬ð )Ø ŸYšY™[œ[�
øøÝð Oð Oð OÝ�ŠÐHÈ#ÑNÔNÐNÐNÐNÐNÐNÐNøøøøðOøøøõ 
ð $ð $Ý�
Ñ#Ô#ˆð$ð $ð $ñ $ô $ð $ð $ð $ð $ð $ð $øøøð $ð $ð $ð $ðð ð ð ð ð 
Ø—<’< 
Ñ+Ô+ˆØÐØˆOÝ�ŠØQØñ	
ô 	
ð 	
ð HÐGÐGÐG˜HŸOšOÑ-Ô-ÐGÑGÔG€IÝ
ˆ9�~„~˜ÒÐØ˜Œ|Ðð �,Š,�uÑ
Ô
€CØ
€Ð-Ð-¨cÑ2Ô2€Øˆ
àˆ4s*   …B#B) Â)
CÂ3CÃCÃ"DÄDÄ
Dc                 óx   — t           5  t                               ¦   «          ddd¦  «         dS # 1 swxY w Y   dS )z"Clear the registry. **Test-only.**N)r   r   Úclearr6   r"   r   Ú_reset_for_testsrG   Ž   s~   € å	ð ð Ý×ÒÑÔÐðð ð ñ ô ð ð ð ð ð ð ð øøøð ð ð ð ð ð s   ˆ/¯3¶3)r	   r   r
   r   )r
   r   )r   r   r
   r)   )r
   r)   )r
   r   )Ú__doc__Ú
__future__r   ÚloggingÚ	threadingÚtypingr   r   r   Úagent.image_gen_providerr   Ú	getLoggerr   r   r   Ú__annotations__ÚLockr   r   r(   r+   rD   rG   r6   r"   r   ú<module>rQ      s  ððð ð ð( #Ð "Ð "Ð "Ð "Ð "à €€€Ø Ð Ð Ð Ø 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'à 5Ð 5Ð 5Ð 5Ð 5Ð 5à	ˆÔ	˜8Ñ	$Ô	$€ð +-€
Ð ,Ð ,Ð ,Ñ ,Øˆ	ŒÑÔ€ð_ð _ð _ð _ð0/ð /ð /ð /ð,ð ,ð ,ð ,ð@ð @ð @ð @ðFð ð ð ð ð r"   