
    `gj]/                        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y)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portraitc                 .   	 ddl m}   |        }t        |t              r|j	                  d      nd}t        |t              r|j	                  d      nd}t        |t              r|S i S # t
        $ r"}t        j                  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        W/root/.hermes/venv/lib/python3.12/site-packages/plugins/image_gen/deepinfra/__init__.py_load_deepinfra_image_configr%   9   s|    	1m*4S$*?#''+&T1;GT1JW[[-PT
'
D9zArA DcJ	s$   A$A) 'A) )	B2B	BBc                 x    	 ddl m}   | d      S # t        $ r }t        j	                  d|       Y d}~yd}~ww xY w)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   s;    D *+66  GMs    	949c                (   | j                  dd      }| j                  d      xs i }t        |t              r|j                  d      nd}d}t        |t              r%|j                  d      	 dt        |d         dd	}|d
|v r|j                  d
d      d   n|t        |t              r|j                  dd      ndd}|r||d<   t        |t              r!dD ]  }|j                  |      ||   ||<    |S # t        t
        f$ r d}Y w xY w)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)itemmidr-   r.   r7   rowkeys          r$   _format_catalog_rowrC   Q   s#   
((4
Cxx
#)rH)3Hd)Chll9%GE'4 W[[1A%B%N	g&678=VDE ,/3J399S!$R(C8B8T8RX\\-4XZC
 G(D!L 	)C||C ,#C=C	) J :& 	E	s   /C= =DDc                b   t         j                  j                  dd      j                         }|r|S t	        |t
              r|j                  d      nd}t	        |t              r |j                         r|j                         S | r(| d   j                  d      }t	        |t              r|r|S y)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_MODELr,   modelNr   r+   )osenvironr   stripr   r   str)catalogr    env_override	cfg_modelfirsts        r$   _resolve_modelrO   j   s     ::>>"92>DDFL$.sD$9 tI)S!ioo&7  
t$eS!eL    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y
)DeepInfraImageGenProviderzDeepInfra ``images.generations`` backend.

    Catalog is discovered live from the DeepInfra ``/models`` endpoint
    filtered by the ``image-gen`` surface tag.
    c                     y)Nr    selfs    r$   namezDeepInfraImageGenProvider.name       rP   c                     y)N	DeepInfrarT   rU   s    r$   display_namez&DeepInfraImageGenProvider.display_name   rX   rP   c                p    t        t        j                  j                  dd      j	                               S )NDEEPINFRA_API_KEYr,   )boolrG   rH   r   rI   rU   s    r$   is_availablez&DeepInfraImageGenProvider.is_available   s&    BJJNN#6;AACDDrP   c                Z    t               }|sg S |D cg c]  }t        |       c}S c c}w )N)r)   rC   )rV   liver?   s      r$   list_modelsz%DeepInfraImageGenProvider.list_models   s+    ~I6:;d#D);;;s   (c                P    | j                         }|r|d   j                  d      S y )Nr   r+   )rb   r   )rV   rowss     r$   default_modelz'DeepInfraImageGenProvider.default_model   s)    !7;;t$$rP   c                    dgddS )z>DeepInfra's OpenAI-compatible generation surface is text-only.textr   )
modalitiesmax_reference_imagesrT   rU   s    r$   capabilitiesz&DeepInfraImageGenProvider.capabilities   s    %hBBrP   c                    dddddddgdS )	NrZ   paidu=   FLUX, Qwen-Image, … — live catalog from api.deepinfra.comr]   zDeepInfra API keyz#https://deepinfra.com/dash/api_keys)rB   prompturl)rW   badgetagenv_varsrT   rU   s    r$   get_setup_schemaz*DeepInfraImageGenProvider.get_setup_schema   s*    R /1@	
 	
rP   c           	     B   |xs dj                         }t        |      }|j                  d      s|j                  d      rt        ddd||      S |st        dd	d|
      S t        j
                  j                  dd      j                         }|st        ddd|
      S t               }t               xs g }t        ||      }|st        ddd||      S t        j                  |t        d         }	ddl
m}
  |
|      }	 dd l}|j                  ||      }	 |j                  j!                  |||	d      }	 t)        |dd       }t+        |      r |        	 t)        |dd       xs g }|st        d d!d|||      S |d   }t)        |d"d       }t)        |d#d       }|j-                  d$d      d%   j/                  d&d'      }|r	 t1        |d(| )      }t3        |      }n.|r	 t3        t5        |d(| )            }nt        d-d!d|||      S t7        ||||dd.|	i/      S # t        $ r t        ddd|
      cY S w xY w# t"        $ rU}t$        j'                  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 |        w w xY w# t"        $ r}t        d*| d+d|||      cY d }~S d }~ww xY w# t"        $ r#}t$        j'                  d,|       |}Y d }~d }~ww xY w)0Nr,   	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providerrm   aspect_ratioz1Prompt is required and must be a non-empty stringinvalid_argument)rw   rx   ry   rz   r]   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_urlr2   )rF   rm   sizenz!DeepInfra image generation failedT)exc_infoz#DeepInfra image generation failed: 	api_error)rw   rx   ry   rF   rm   rz   closedataz DeepInfra returned no image dataempty_responseb64_jsonrn   r1   r3   :_
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   )imagerF   rm   rz   ry   extra)rI   r   r   r
   rG   rH   r%   r)   rO   _SIZESr(   r~   openaiImportErrorOpenAIimagesgenerater   r   r   getattrcallabler>   replacer   rJ   r   r   )rV   rm   rz   kwargsaspectr   di_cfgrK   model_idr   r~   r   r   clientresponser#   r   r   rN   b64rn   short
saved_path	image_refs                           r$   r   z"DeepInfraImageGenProvider.generate   s    ,B%%'%l3::k"fjj1G&H!S 2$#	 	 !I-$#	  **..!4b9??A!& +$#	 	 ./.&B!'62!L
 0$#  zz&&"238%f-
	 wB	}}--	 . H" FGT2Ex.4"!8+$#  QeZ.eUD) sA&r*223<
+C*UG8LM
 JI
 sZw;O PQ	
 "M+$#    4.
 	
g  	!P/$#	 	   		LL<tLL!;C5A&$#  FGT2E 		 FGT2E 2  %;C5A)("!!' "   Y[^_	 sx   H$ I K &K2 $H?>H?	J *J5J 6J# J  J# #"K	K/K*$K/*K/2	L;LLN)returnrJ   )r   r^   )r   List[Dict[str, Any]])r   Optional[str]r   Dict[str, Any])rm   rJ   rz   rJ   r   r   r   r   )__name__
__module____qualname____doc__propertyrW   r[   r_   rb   re   rj   rr   r   r   rT   rP   r$   rR   rR   }   s        E<C
" 1]
]
 ]
 	]

 
]
rP   rR   c                6    | j                  t                      y)uL   Plugin entry point — wire ``DeepInfraImageGenProvider`` into the registry.N)register_image_gen_providerrR   )ctxs    r$   registerr   M  s    ##$=$?@rP   r   )r   zOptional[List[Dict[str, Any]]])r?   r   r   r   )rK   r   r    r   r   r   )r   None)r   
__future__r   loggingrG   typingr   r   r   r   agent.image_gen_providerr   r	   r
   r   r   r   r   	getLoggerr   r   r   r%   r)   rC   rO   rR   r   rT   rP   r$   <module>r      sz   6 #  	 , ,   
		8	$ 
72&M
 0 M
`ArP   