
    [j]/                        d Z ddlmZ ddlZddl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mZmZ  ej        e          Zdddd	ZddZddZddZddZ G d de          ZddZdS )u  DeepInfra image generation backend.

Exposes DeepInfra's image-gen catalog (FLUX, Qwen-Image-Edit, …) through
the OpenAI-compatible ``/v1/openai/images/generations`` endpoint as an
:class:`ImageGenProvider` implementation.

**Fully dynamic model discovery.** Unlike the other image-gen plugins in
this tree (which ship a hardcoded ``_MODELS`` dict), DeepInfra publishes
a single tagged catalog at
``https://api.deepinfra.com/v1/openai/models?filter=true&sort_by=hermes``
where each entry's ``metadata.tags`` declares its surface (``image-gen``
here). ``list_models()`` filters that catalog via
:func:`hermes_cli.models._fetch_deepinfra_models_by_tag` so newly added
models show up in ``hermes tools`` automatically. No model ids are
hardcoded in this file — if a model is retired upstream, it disappears
from hermes the next time the catalog is fetched, no patch required.

Model selection (first hit wins):

1. ``DEEPINFRA_IMAGE_MODEL`` env var
2. ``image_gen.deepinfra.model`` in ``config.yaml``
3. First model from the live catalog

When all three are absent (catalog unreachable, nothing configured),
``generate()`` returns an :func:`error_response` rather than guessing.
    )annotationsN)AnyDictListOptional)DEFAULT_ASPECT_RATIOImageGenProvidererror_responseresolve_aspect_ratiosave_b64_imagesave_url_imagesuccess_response	1536x1024	1024x1024	1024x1536)	landscapesquareportraitreturnDict[str, Any]c                 n   	 ddl m}   |             }t          |t                    r|                    d          nd}t          |t                    r|                    d          nd}t          |t                    r|ni S # t
          $ r'}t                              d|           i cY d}~S d}~ww xY w)z.Read ``image_gen.deepinfra`` from config.yaml.r   )load_config	image_genN	deepinfraz-Could not load image_gen.deepinfra config: %s)hermes_cli.configr   
isinstancedictget	Exceptionloggerdebug)r   cfgsection
di_sectionexcs        F/home/ice/.hermes/hermes-agent/plugins/image_gen/deepinfra/__init__.py_load_deepinfra_image_configr'   9   s    	111111kmm*4S$*?*?I#''+&&&T1;GT1J1JTW[[---PT
'
D99AzzrA   DcJJJ						s   B B 
B4B/)B4/B4Optional[List[Dict[str, Any]]]c                     	 ddl m}  n3# t          $ r&}t                              d|           Y d}~dS d}~ww xY w | d          S )z=Fetch ``image-gen``-tagged models from the DeepInfra catalog.r   )_fetch_deepinfra_models_by_tagz0Cannot import _fetch_deepinfra_models_by_tag: %sNz	image-gen)hermes_cli.modelsr*   r   r    r!   )r*   r%   s     r&   _live_modelsr,   G   sp    DDDDDDD   GMMMttttt *)+666s   	 
949itemc                   |                      dd          }|                      d          pi }t          |t                    r|                     d          nd}d}t          |t                    rJ|                     d          5	 dt          |d                   dd	}n# t          t
          f$ r d}Y nw xY w|d
|v r|                    d
d          d         n|t          |t                    r|                     dd          ndd}|r||d<   t          |t                    r%dD ]"}|                     |          ||         ||<   #|S )z0Format a catalog item into the picker row shape.id metadatapricingNper_image_unit$z.4fz/image/   description)r/   display	strengthsprice)default_widthdefault_heightdefault_iterations)r   r   r   float	TypeError
ValueErrorsplit)r-   midr1   r2   r;   rowkeys          r&   _format_catalog_rowrF   Q   s}   
((4

Cxx
##)rH)3Hd)C)CMhll9%%%GE'4   W[[1A%B%B%N	Dg&6788DDDDEE:& 	 	 	EEE	 ,/3JJ399S!$$R((C8B8T8R8RZX\\-444XZ C
  G(D!! )L 	) 	)C||C  ,#C=CJs   B" "B87B8catalogList[Dict[str, Any]]r"   Optional[str]c                   t           j                            dd                                          }|r|S t	          |t
                    r|                    d          nd}t	          |t                    r(|                                r|                                S | r4| d                             d          }t	          |t                    r|r|S dS )zPick the model id (env > config > first live result, else None).

    Takes the already-loaded ``image_gen.deepinfra`` config so ``generate()``
    reads config once instead of via a second ``load_config`` deepcopy.
    DEEPINFRA_IMAGE_MODELr0   modelNr   r/   )osenvironr   stripr   r   str)rG   r"   env_override	cfg_modelfirsts        r&   _resolve_modelrT   j   s     :>>"92>>DDFFL $.sD$9$9C   tI)S!! !ioo&7&7 !    
t$$eS!! 	e 	L4    c                  v    e Zd ZdZedd            Zedd            ZddZdd	ZddZ	ddZ
ddZefddZdS )DeepInfraImageGenProviderzDeepInfra ``images.generations`` backend.

    Catalog is discovered live from the DeepInfra ``/models`` endpoint
    filtered by the ``image-gen`` surface tag.
    r   rP   c                    dS )Nr    selfs    r&   namezDeepInfraImageGenProvider.name       {rU   c                    dS )N	DeepInfrarY   rZ   s    r&   display_namez&DeepInfraImageGenProvider.display_name   r]   rU   boolc                    t          t          j                            dd                                                    S )NDEEPINFRA_API_KEYr0   )ra   rM   rN   r   rO   rZ   s    r&   is_availablez&DeepInfraImageGenProvider.is_available   s-    BJNN#6;;AACCDDDrU   rH   c                >    t                      }|sg S d |D             S )Nc                ,    g | ]}t          |          S rY   )rF   ).0r-   s     r&   
<listcomp>z9DeepInfraImageGenProvider.list_models.<locals>.<listcomp>   s!    ;;;d#D));;;rU   )r,   )r[   lives     r&   list_modelsz%DeepInfraImageGenProvider.list_models   s,    ~~ 	I;;d;;;;rU   rI   c                h    |                                  }|r|d                             d          S d S )Nr   r/   )rj   r   )r[   rowss     r&   default_modelz'DeepInfraImageGenProvider.default_model   s6    !! 	%7;;t$$$trU   r   c                    dgddS )z>DeepInfra's OpenAI-compatible generation surface is text-only.textr   )
modalitiesmax_reference_imagesrY   rZ   s    r&   capabilitiesz&DeepInfraImageGenProvider.capabilities   s    %hBBBrU   c                    dddddddgdS )	Nr_   paidu=   FLUX, Qwen-Image, … — live catalog from api.deepinfra.comrc   zDeepInfra API keyz#https://deepinfra.com/dash/api_keys)rE   prompturl)r\   badgetagenv_varsrY   rZ   s    r&   get_setup_schemaz*DeepInfraImageGenProvider.get_setup_schema   s4    R /1@ 	
 
 	
rU   ru   aspect_ratiokwargsr   c           	        |pd                                 }t          |          }|                    d          s|                    d          rt          ddd||          S |st          dd	d|
          S t          j                            dd                                           }|st          ddd|
          S t                      }t                      pg }t          ||          }|st          ddd||          S t                              |t          d                   }	ddl
m}
  |
|          }	 dd l}n## t          $ r t          ddd|
          cY S w xY w|                    ||          }	 |j                            |||	d          }nv# t"          $ ri}t$                              dd           t          d| dd|||          cY d }~t)          |dd           }t+          |          r |             S S d }~ww xY w	 t)          |dd           }t+          |          r
 |             n0# t)          |dd           }t+          |          r |             w w xY wt)          |dd           pg }|st          d d!d|||          S |d         }t)          |d"d           }t)          |d#d           }|                    d$d          d%                             d&d'          }|rU	 t1          |d(| )          }n/# t"          $ r"}t          d*| d+d|||          cY d }~S d }~ww xY wt3          |          }nn|rW	 t3          t5          |d(| )                    }nI# t"          $ r'}t$                              d,|           |}Y d }~nd }~ww xY wt          d-d!d|||          S t7          ||||dd.|	i/          S )0Nr0   	image_urlreference_image_urlszuDeepInfra image generation is text-to-image only in this backend; image_url and reference_image_urls are unsupported.modality_unsupportedr   )error
error_typeproviderru   r{   z1Prompt is required and must be a non-empty stringinvalid_argument)r   r   r   r{   rc   u   DEEPINFRA_API_KEY not set. Run `hermes tools` → Image Generation → DeepInfra to configure, or `hermes setup` to add the key.auth_requiredzNo DeepInfra image-gen model available. Pin one in config.yaml under image_gen.deepinfra.model, set DEEPINFRA_IMAGE_MODEL, or check connectivity to api.deepinfra.com so the live catalog can be fetched.no_model_availabler   r   )deepinfra_base_urlz8openai Python package not installed (pip install openai)missing_dependency)api_keybase_urlr6   )rL   ru   sizenz!DeepInfra image generation failedT)exc_infoz#DeepInfra image generation failed: 	api_error)r   r   r   rL   ru   r{   closedataz DeepInfra returned no image dataempty_responseb64_jsonrv   r5   r7   :_
deepinfra_)prefixzCould not save image to cache: io_errorz:DeepInfra: caching delivery URL failed (%s); returning URLz5DeepInfra response contained neither b64_json nor URLr   )imagerL   ru   r{   r   extra)rO   r   r   r
   rM   rN   r'   r,   rT   _SIZESr+   r   openaiImportErrorOpenAIimagesgenerater   r    r!   getattrcallablerB   replacer   rP   r   r   )r[   ru   r{   r|   aspectr   di_cfgrG   model_idr   r   r   r   clientresponser%   r   r   rS   b64rv   short
saved_path	image_refs                           r&   r   z"DeepInfraImageGenProvider.generate   s[    ,B%%''%l33::k"" 
	fjj1G&H&H 
	!S 2$#	 	 	 	  	!I-$#	    *..!4b99??AA 
	!& +$#	 	 	 	 .//..&B!'622 	!L
 0$#    zz&&"233888888%%f--
	MMMM 	 	 	!P/$#	     	 wBB	}--	 .  HH  		 		 		LL<tLLLL!ACAA&$#        FGT22E 		 " FGT22E  FGT22E  x..4" 	!8+$#    QeZ..eUD)) sA&&r*223<< 	
+C8LU8L8LMMM

   %ACAA)("!!'         JII 	
 s;O;O;O P P PQQ		      Y[^___						  "M+$#      4.
 
 
 	
s~   <E E! E!<F H= 
H%3H	HH= 	HH= =-I*4L	 	
L5L0*L50L5!M- -
N7NNN)r   rP   )r   ra   )r   rH   )r   rI   r   r   )ru   rP   r{   rP   r|   r   r   r   )__name__
__module____qualname____doc__propertyr\   r`   rd   rj   rm   rr   rz   r   r   rY   rU   r&   rW   rW   }   s             X    XE E E E< < < <   C C C C
 
 
 
" 1]
 ]
 ]
 ]
 ]
 ]
 ]
rU   rW   Nonec                H    |                      t                                 dS )uL   Plugin entry point — wire ``DeepInfraImageGenProvider`` into the registry.N)register_image_gen_providerrW   )ctxs    r&   registerr   M  s#    ##$=$?$?@@@@@rU   r   )r   r(   )r-   r   r   r   )rG   rH   r"   r   r   rI   )r   r   )r   
__future__r   loggingrM   typingr   r   r   r   agent.image_gen_providerr   r	   r
   r   r   r   r   	getLoggerr   r    r   r'   r,   rF   rT   rW   r   rY   rU   r&   <module>r      s   6 # " " " " "  				 , , , , , , , , , , , ,                  
	8	$	$ 
 
   7 7 7 7   2   &M
 M
 M
 M
 M
 0 M
 M
 M
`A A A A A ArU   