
    epj/                        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 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)
get_secret)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        J/home/thesage/.hermes/hermes-agent/plugins/image_gen/deepinfra/__init__.py_load_deepinfra_image_configr(   :   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-   H   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)r0   display	strengthsprice)default_widthdefault_heightdefault_iterations)r   r   r   float	TypeError
ValueErrorsplit)r.   midr2   r3   r<   rowkeys          r'   _format_catalog_rowrG   R   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_MODELr1   modelNr   r0   )osenvironr   stripr   r   str)rH   r#   env_override	cfg_modelfirsts        r'   _resolve_modelrU   k   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   rQ   c                    dS )Nr    selfs    r'   namezDeepInfraImageGenProvider.name       {rV   c                    dS )N	DeepInfrarZ   r[   s    r'   display_namez&DeepInfraImageGenProvider.display_name   r^   rV   boolc                d    t          t          dd          pd                                          S )NDEEPINFRA_API_KEYr1   )rb   r   rP   r[   s    r'   is_availablez&DeepInfraImageGenProvider.is_available   s,    Z 3R88>BEEGGHHHrV   rI   c                >    t                      }|sg S d |D             S )Nc                ,    g | ]}t          |          S rZ   )rG   ).0r.   s     r'   
<listcomp>z9DeepInfraImageGenProvider.list_models.<locals>.<listcomp>   s!    ;;;d#D));;;rV   )r-   )r\   lives     r'   list_modelsz%DeepInfraImageGenProvider.list_models   s,    ~~ 	I;;d;;;;rV   rJ   c                h    |                                  }|r|d                             d          S d S )Nr   r0   )rk   r   )r\   rowss     r'   default_modelz'DeepInfraImageGenProvider.default_model   s6    !! 	%7;;t$$$trV   r   c                    dgddS )z>DeepInfra's OpenAI-compatible generation surface is text-only.textr   )
modalitiesmax_reference_imagesrZ   r[   s    r'   capabilitiesz&DeepInfraImageGenProvider.capabilities   s    %hBBBrV   c                    dddddddgdS )	Nr`   paidu=   FLUX, Qwen-Image, … — live catalog from api.deepinfra.comrd   zDeepInfra API keyz#https://deepinfra.com/dash/api_keys)rF   prompturl)r]   badgetagenv_varsrZ   r[   s    r'   get_setup_schemaz*DeepInfraImageGenProvider.get_setup_schema   s4    R /1@ 	
 
 	
rV   rv   aspect_ratiokwargsr   c           	     ~   |pd                                 }t          |          }|                    d          s|                    d          rt          ddd||          S |st          dd	d|
          S t	          dd          p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	 t/          |d(| )          }n/# t           $ r"}t          d*| d+d|||          cY d }~S d }~ww xY wt1          |          }nn|rW	 t1          t3          |d(| )                    }nI# t           $ r'}t"                              d,|           |}Y d }~nd }~ww xY wt          d-d!d|||          S t5          ||||dd.|	i/          S )0Nr1   	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providerrv   r|   z1Prompt is required and must be a non-empty stringinvalid_argument)r   r   r   r|   rd   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_urlr7   )rM   rv   sizenz!DeepInfra image generation failedT)exc_infoz#DeepInfra image generation failed: 	api_error)r   r   r   rM   rv   r|   closedataz DeepInfra returned no image dataempty_responseb64_jsonrw   r6   r8   :_
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   )imagerM   rv   r|   r   extra)rP   r   r   r   r   r(   r-   rU   _SIZESr,   r   openaiImportErrorOpenAIimagesgenerater    r!   r"   getattrcallablerC   replacer   rQ   r   r   )r\   rv   r|   r}   aspectr   di_cfgrH   model_idr   r   r   r   clientresponser&   r   r   rT   b64rw   short
saved_path	image_refs                           r'   r   z"DeepInfraImageGenProvider.generate   sZ    ,B%%''%l33::k"" 
	fjj1G&H&H 
	!S 2$#	 	 	 	  	!I-$#	    1266<"CCEE 
	!& +$#	 	 	 	 .//..&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~   .D3 3EE.F H/ 
H 3G;
H H/ ;H  H/ /-I&K; ;
L'L"L'"L'=!M 
N)NNN)r   rQ   )r   rb   )r   rI   )r   rJ   r   r   )rv   rQ   r|   rQ   r}   r   r   r   )__name__
__module____qualname____doc__propertyr]   ra   re   rk   rn   rs   r{   r	   r   rZ   rV   r'   rX   rX   ~   s             X    XI I I I< < < <   C C C C
 
 
 
" 1]
 ]
 ]
 ]
 ]
 ]
 ]
rV   rX   Nonec                H    |                      t                                 dS )uL   Plugin entry point — wire ``DeepInfraImageGenProvider`` into the registry.N)register_image_gen_providerrX   )ctxs    r'   registerr   N  s#    ##$=$?$?@@@@@rV   r   )r   r)   )r.   r   r   r   )rH   rI   r#   r   r   rJ   )r   r   )r   
__future__r   loggingrN   typingr   r   r   r   agent.secret_scoper   agent.image_gen_providerr	   r
   r   r   r   r   r   	getLoggerr   r!   r   r(   r-   rG   rU   rX   r   rZ   rV   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rV   