Ë
    âß²jã-  ã                  ó@  — d Z ddlmZ ddlZddlZddlZddlmZmZm	Z	m
Z
mZ ddlmZ ddlmZmZmZ ddlmZmZmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z"  ejF                  e$«      Z%i  ejL                  «       D � �ci c]  \  } }| i |¥dei¥“Œ c}} ¥d	D �����ci c]8  \  }}}}d
D ],  }|dk(  r|n|› d|› �d|› d|jO                  «       › d�||||dœ“Œ. Œ: c}}}}}¥Z(d!d„Z)d"d„Z*d#d„Z+d$d„Z,d%d„Z-d&d„Z. G d„ de«      Z/d'd„Z0ddddddœZ1d „ Z2yc c}} w c c}}}}}w )(uè  OpenAI GPT Image 2 and 2.5 Flare/Sunburst quality tiers;
base64 output â†’ image cache. Selection: ``OPENAI_IMAGE_MODEL`` â†’ ``image_gen.openai.model`` â†’
``image_gen.model`` â†’ :data:`DEFAULT_MODEL`; an id outside the catalog is sent verbatim.
Endpoint: ``image_gen.openai.base_url`` â†’ the named endpoint ``image_gen.openai.provider`` â†’
``OPENAI_BASE_URL`` â†’ SDK default; key: env named by ``image_gen.openai.key_env`` â†’ the named
endpoint's credential â†’ ``OPENAI_API_KEY``.é    )ÚannotationsN)ÚAnyÚDictÚListÚOptionalÚTuple)Ú
get_secret)ÚDEFAULT_ASPECT_RATIOÚresolve_aspect_ratioÚsuccess_response)ÚGPT_IMAGE_2_API_MODELÚGPT_IMAGE_2_DEFAULTÚGPT_IMAGE_2_TIERSÚStaticImageGenProviderÚcollect_source_imagesÚerror_factoryÚimport_openaiÚload_image_gen_configÚmaterialize_imageÚopenai_importableÚprompt_required_errorÚrecord_token_usageÚresolve_static_modelÚsize_forÚ	api_model))zgpt-image-2.5-flareÚFlareÚFastz%Everyday image generation and editing)zgpt-image-2.5-sunburstÚSunburstÚSlowerz Precision generation and editing)ÚautoÚlowÚmediumÚhighÚxhighÚmaxr    Ú-zGPT Image 2.5 z (ú))ÚdisplayÚspeedÚ	strengthsr   Úqualityc                 ó2   — t        t        t        ddd¬«      S )NÚOPENAI_IMAGE_MODELÚopenaiT)Úenv_varÚ
config_keyÚpassthrough)r   ÚMODELSÚDEFAULT_MODEL© ó    úF/home/ubuntu/.hermes/hermes-agent/plugins/image_gen/openai/__init__.pyÚ_resolve_modelr7   -   s   € ÜÜ”Ð';ÈÐ^bôdð dr5   c                ó¤  — ddl m}  || «      }|st        j                  d| «       yt	        |j                  d«      xs d«      j                  «       }t	        |j                  d«      xs d«      j                  «       xs |rt        |«      ndxs d}t	        |j                  d	«      xs d«      j                  «       j                  d
«      |fS )u  ``(base_url, api_key)`` of the user-declared custom endpoint *name* (``providers:`` /
    ``custom_providers:``), so image generation reuses a chat endpoint's URL and credential without
    duplicating the key into OpenAI variables (#83080). Unknown name â†’ ``("", "")`` with a warning.r   )Ú_get_named_custom_providerzEimage_gen.openai.provider %r matches no custom endpoint in providers:©Ú r;   Úkey_envr;   Úapi_keyNÚbase_urlú/)	Úhermes_cli.runtime_providerr9   ÚloggerÚwarningÚstrÚgetÚstripr	   Úrstrip)Únamer9   Úentryr<   r=   s        r6   Ú_named_endpointrI   2   s²   € õ Gá& tÓ,€EÙÜ�‰Ð^Ð`dÔeØÜ�%—)‘)˜IÓ&Ò,¨"Ó-×3Ñ3Ó5€GÜ�%—)‘)˜IÓ&Ò,¨"Ó-×3Ñ3Ó5ÒiÑQX¼*ÀWÔ:MÐ^bÒiÐgi€GÜˆu�y‰y˜Ó$Ò*¨Ó+×1Ñ1Ó3×:Ñ:¸3Ó?ÀÐHÐHr5   c                 ó  — t        d«      } t        | j                  d«      xs d«      j                  «       }|rt	        |«      nd\  }}t        | j                  d«      xs d«      j                  «       j                  d«      xs2 |xs. t        j                  j                  dd«      j                  «       }t        | j                  d«      xs d«      j                  «       }|rt        |«      nd	xs |xs t        d
«      xs d}||fS )u8  ``(base_url, api_key)`` â€” ``image_gen.openai.base_url`` â†’ ``OPENAI_BASE_URL`` â†’ ``""`` (SDK default);
    the env var named by ``image_gen.openai.key_env`` â†’ ``OPENAI_API_KEY``. Only the var NAME lives in
    config.yaml; ``is_available()`` and ``generate()`` share this so they cannot disagree (#65309).r.   Úproviderr;   r:   r>   r?   ÚOPENAI_BASE_URLr<   NÚOPENAI_API_KEY)	r   rC   rD   rE   rI   rF   ÚosÚenvironr	   )ÚcfgÚnamedÚ
named_baseÚ	named_keyr>   r<   r=   s          r6   Ú_resolve_endpointrT   A   së   € ô   Ó
)€CÜ�—‘˜
Ó#Ò) rÓ*×0Ñ0Ó2€EÙ6;œO¨EÔ2ÀÑ€J�	Ü�C—G‘G˜JÓ'Ò-¨2Ó.×4Ñ4Ó6×=Ñ=¸cÓBò AÀjò AÜ—:‘:—>‘>Ð"3°RÓ8×>Ñ>Ó@ð ä�#—'‘'˜)Ó$Ò*¨Ó+×1Ñ1Ó3€GÙ&-Œz˜'Ô"°4Òk¸IÒkÌÐTdÓIeÒkÐik€GØ�WÐÐr5   c                ól   — ddl m} |ddidœ}|r||d<    ||«      }|�||d<    | j                  di |¤ŽS )	ax  ``openai.OpenAI`` on Hermes' env-only-proxy httpx client, so a local/custom endpoint never
    routes through a macOS system proxy whose ExceptionsList httpx cannot see (#64888). The project
    header is blanked: an ``OPENAI_PROJECT_ID`` set for chat makes ``/images/generations`` 403 on
    projects with a model allow-list, and the key already carries the project (#60748).r   )Úbuild_keepalive_http_clientzOpenAI-Projectr;   )r=   Údefault_headersr>   Úhttp_clientr4   )Úagent.process_bootstraprV   ÚOpenAI)r.   r>   r=   rV   ÚkwargsrX   s         r6   Ú_build_clientr\   O   sT   € õ
 Dà)0ÐFVÐXZÐE[Ñ\€FÙØ%ˆˆzÑÙ-¨hÓ7€KØÐØ +ˆˆ}ÑØˆ6�=‰=Ñ"˜6Ñ"Ð"r5   c                óB  — | j                  «       } | j                  «       }|j                  d«      rŒddlm}m}  || «      st        d| › �«      ‚ |dd¬«      5 }|j                  | «      }ddd«       j                  «        | j                  d	d
«      d   j                  dd
«      d   xs d}|j                  |fS |j                  d«      raddl}| j                  d«      \  }}	}
d|v r(|j                  dd
«      d
   j                  dd
«      d   ndxs d}|j                  |
«      d|› �fS ddlm}  || «       t#        | d«      5 }|j%                  «       }ddd«       t&        j(                  j+                  | «      xs dfS # 1 sw Y   �ŒxY w# 1 sw Y   Œ;xY w)zYLoad ``(data, filename)`` from a URL, data URI or local path; raises on IO/network error.)zhttp://zhttps://r   )Úcreate_ssrf_safe_clientÚis_safe_urlz2Image reference URL failed the SSRF safety check: é<   T)ÚtimeoutÚfollow_redirectsNú?é   r?   éÿÿÿÿz	image.pngzdata:ú,zimage/ú;r;   Úpngzimage.)Úraise_if_read_blockedÚrb)rE   ÚlowerÚ
startswithÚtools.url_safetyr^   r_   Ú
ValueErrorrD   Úraise_for_statusÚsplitÚrsplitÚcontentÚbase64Ú	partitionÚ	b64decodeÚagent.file_safetyri   ÚopenÚreadrN   ÚpathÚbasename)Úrefrk   r^   r_   ÚclientÚresprG   rs   ÚheaderÚ_Úb64Úextri   ÚfhÚdatas                  r6   Ú_load_image_bytesr„   _   s‰  € à
�)‰)‹+€CØ�I‰I‹K€EØ×ÑÐ/Ô0ßIá˜3ÔÜÐQÐRUÐQVÐWÓXÐXÙ$¨RÀ$ÔGð 	#È6Ø—:‘:˜c“?ˆD÷	#à×ÑÔØ�y‰y˜˜aÓ  Ñ#×*Ñ*¨3°Ó2°2Ñ6ÒE¸+ˆØ�|‰|˜TÐ!Ð!Ø×Ñ˜Ô ÛàŸ™ sÓ+‰ˆ��3Ø@HÈFÑ@Rˆv�|‰|˜H aÓ(¨Ñ+×1Ñ1°#°qÓ9¸!Ò<ÐXZÒdÐ_dˆØ×Ñ Ó$¨¨s¨e nÐ4Ð4Ý7á˜#ÔÜ	ˆc�4‹ð ˜BØ�w‰w‹yˆ÷à”—‘×!Ñ! #Ó&Ò5¨+Ð5Ð5÷!	#ñ 	#ú÷ð ús   ÁFÅ
FÆFÆFc                óZ   — t        | «      \  }}t        j                  |«      }||_        |S )zH``images.edit()`` expects named file-like objects for correct multipart.)r„   ÚioÚBytesIOrG   )r{   rƒ   ÚfnameÚbios       r6   Ú_named_bytes_iorŠ   {   s*   € ä# CÓ(�K€Dˆ%Ü
�*‰*�TÓ
€CØ€C„HØ€Jr5   c                  óz   — e Zd ZdZdZdZeZeZ	dZ
 edddddd	¬
«      Zdd„Zdd„Zefdddœ	 	 	 	 	 	 	 	 	 	 	 dd„Zy)ÚOpenAIImageGenProviderzPOpenAI ``images.generate`` / ``images.edit`` backend with selectable API models.r.   rZ   ÚvariesÚpaiduH   GPT Image 2 / 2.5 Flare / 2.5 Sunburst â€” text-to-image & image editingrM   zOpenAI API keyz$https://platform.openai.com/api-keys)rG   ÚbadgeÚtagÚkeyÚpromptÚurlc                óF   — t        t        «       d   «      xr
 t        «       S )Nrd   )ÚboolrT   r   ©Úselfs    r6   Úis_availablez#OpenAIImageGenProvider.is_available�   s   € ÜÔ%Ó'¨Ñ*Ó+ÒCÔ0AÓ0CÐCr5   c                ó   — ddgddœS )NÚtextÚimageé   )Ú
modalitiesÚmax_reference_imagesr4   r–   s    r6   Úcapabilitiesz#OpenAIImageGenProvider.capabilities“   s   € à% wÐ/ÈÑLÐLr5   N)Ú	image_urlÚreference_image_urlsc               óº  — |xs dj                  «       }t        |«      }|st        d|«      S t        «       \  }}|s t	        d|«      dd«      S t        d|«      \  }	}
|
r|
S t        «       \  }}t        |«      }t        ||d¬«      }t        |«      }t	        d|||¬«      }t        |	||«      }t        |d   ||d	¬
«      }|d   �|d   |d<   |r1	 |D �cg c]  }t        |«      ‘Œ }}t        |«      d	kD  r|n|d   |d<   |rd|j                  j                   fnd|j                  j"                  f\  }}	  |d'i |¤Ž}t)        t+        |dd «      |d   d¬«       t+        |dd «      xs g }|s	 |dd«      S |d   }t-        t+        |dd «      t+        |dd «      d |› �d!d|||t$        ¬"«	      \  }}
|
r|
S ||d   d#œ}t+        |d$d «      r|j.                  |d$<   t1        ||||d|rd|¬&«      S d%|¬&«      S c c}w # t        $ r} |d|› �d«      cY d }~S d }~ww xY w# t        $ r5}t$        j'                  d|d¬«        |d|rdnd› d|› �d«      cY d }~S d }~ww xY w)(Nr;   r.   u·   OPENAI_API_KEY not set (or the variable named by image_gen.openai.key_env is empty). Run `hermes tools` â†’ Image Generation â†’ OpenAI to configure, or `hermes setup` to add the key.Úauth_requiredrœ   )Úlimit)Úmodelr’   r   rd   )r¥   r’   ÚsizeÚnr+   z)Could not load source image for editing: Úio_errorr   r›   ÚeditÚ
generationzOpenAI image %s failedT)Úexc_infozOpenAI image Úeditingz	 failed: Ú	api_errorÚusage)r¥   rK   rƒ   zOpenAI returned no image dataÚempty_responseÚb64_jsonr“   Úopenai_rZ   )ÚprefixÚlabelrK   r¥   r’   ÚaspectÚlog)r¦   r+   Úrevised_promptrš   )r›   r¥   r’   Úaspect_ratiorK   ÚmodalityÚextrar4   )rE   r   r   rT   r   r   r7   r   r   r•   r\   ÚdictrŠ   Ú	ExceptionÚlenÚimagesr©   ÚgeneraterA   Údebugr   Úgetattrr   r¶   r   )r—   r’   r·   r    r¡   r[   r´   r>   r=   r.   ÚerrÚtier_idÚmetar¦   ÚsourcesÚis_editÚfailr|   Úrequestr{   ÚfilesÚexcÚverbÚcallÚresponserƒ   ÚfirstÚ	image_refr¹   s                                r6   r¾   zOpenAIImageGenProvider.generate—   sÙ  € ð
 ’,˜B×%Ñ%Ó'ˆÜ% lÓ3ˆÙÜ(¨°6Ó:Ð:Ü-Ó/Ñˆ�'ÙØ2”= ¨6Ó2ð"ð  ó	!ð !ô $ H¨fÓ5‰ˆ�ÙØˆJÜ&Ó(‰ˆ�Ü˜ÓˆÜ'¨	Ð3GÈrÔRˆÜ�w“-ˆÜ˜X v°WÀVÔLˆÜ˜v x°Ó9ˆô
 #'¨T°+Ñ->ÀvÐTXÐ\]Ô"^ˆØ�	‰?Ð&Ø!% i¡ˆG�IÑÙð[Ø9@ÖA°#œ¨Õ-ÐA�ÐAô ),¨E«
°Qª™u¸EÀ!¹HˆG�GÑÙ5<�f˜fŸm™m×0Ñ0Ñ1À<ÐQW×Q^ÑQ^×QgÑQgÐBh‰
ˆˆdð	mÙ‘˜g‘ˆHô 	œ7 8¨W°dÓ;À4ÈÑCTÐ_gÕhÜ�x ¨Ó.Ò4°"ˆÙÙÐ7Ð9IÓJÐJØ�Q‘ˆÜ*Ü�E˜: tÓ,¬g°e¸UÀDÓ.IØ˜W˜IÐ&¨hÀØ &°¼VôE‰ˆ	�3ñ ØˆJØ)-¸$¸y¹/Ñ JˆÜ�5Ð*¨DÔ1Ø&+×&:Ñ&:ˆEÐ"Ñ#ÜØ 7°6ÈÐYaÙ '�W¸5ôBð 	Bà-3¸5ôBð 	Bùò7 BøÜò [ÙÐGÈÀuÐMÈzÓZÕZûð[ûô ò 	mÜ�L‰LÐ1°4À$ˆLÔGÙ˜-±W©	À,Ð'OÈyÐY\ÐX]Ð^Ð`kÓlÕlûð	músN   ÃG: ÃG5Ã(G: Ä8H Ç5G: Ç:	HÈHÈHÈHÈ	IÈ%*IÉIÉI)Úreturnr•   )rÏ   úDict[str, Any])r’   rC   r·   rC   r    zOptional[str]r¡   zOptional[List[str]]r[   r   rÏ   rÐ   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Úprovider_idr³   r2   Úmodelsr3   Údefault_model_idÚpricerº   Úsetupr˜   rŸ   r
   r¾   r4   r5   r6   rŒ   rŒ   ƒ   s¡   „ ÙZà€KØ€EØ€FØ$ÐØ€EÙØ˜VØVØÐ%5Ð;aôc€Eó
DóMð
 0Dð@Bà#'ÐUYñ@BØð@BØ),ð@Bà ð@Bà?Rð@Bð ð@Bð 
ô	@Br5   rŒ   c                ó6   — | j                  t        «       «       y)uI   Plugin entry point â€” wire ``OpenAIImageGenProvider`` into the registry.N)Úregister_image_gen_providerrŒ   )Úctxs    r6   ÚregisterrÝ   Ú   s   € à×#Ñ#Ô$:Ó$<Õ=r5   )úagent.image_gen_providerÚImageGenProvider)rÞ   Úerror_response)rÞ   Únormalize_reference_images)rÞ   Úsave_b64_image)rÞ   Úsave_url_image)rß   rà   rá   râ   rã   c                óÌ   — t         j                  | «      }|€t        dt        ›d| ›�«      ‚dd l}ddlm}  |t        | g|¢­Ž  t        |j                  |d   «      |d   «      S )Nzmodule z has no attribute r   )Ú	warn_oncerd   )	Ú_PLUGIN_COMPAT_LAZYrD   ÚAttributeErrorrÑ   Ú	importlibÚhermes_cli.plugin_compatrå   rÀ   Úimport_module)rG   Útargetrè   rå   s       r6   Ú__getattr__rì   î   se   € Ü ×$Ñ$ TÓ*€FØ€~Ü˜w¤x lÐ2DÀTÀHÐMÓNÐNÛÝ2ÙŒh˜Ð&˜vÓ&Ü�9×*Ñ*¨6°!©9Ó5°v¸a±yÓAÐAr5   )rÏ   zTuple[str, Dict[str, Any]])rG   rC   rÏ   úTuple[str, str])rÏ   rí   )r.   r   r>   rC   r=   rC   rÏ   r   )r{   rC   rÏ   zTuple[bytes, str])r{   rC   rÏ   z
io.BytesIO)rÏ   ÚNone)3rÔ   Ú
__future__r   r†   ÚloggingrN   Útypingr   r   r   r   r   Úagent.secret_scoper	   Úagent.image_gen_providerr
   r   r   Úplugins.image_gen._commonr   Ú	API_MODELr   r3   r   r   r   r   r   r   r   r   r   r   r   r   Ú	getLoggerrÑ   rA   ÚitemsÚtitler2   r7   rI   rT   r\   r„   rŠ   rŒ   rÝ   ræ   rì   )r‘   rÃ   r¥   rG   r)   r*   r+   s   0000000r6   ú<module>rù      su  ðñ1õ #ã 	Û Û 	ß 3Õ 3å )ß aÑ a÷÷ ÷ ÷ ð 
ˆ×	Ñ	˜8Ó	$€ð
Ø>UÐ>O×>UÑ>UÓ>W×X±°°d€sÐ,ˆtÐ,�[ )Ñ,Ñ,ÓXð
ð.
÷ò ñ *ˆE�4˜ 	ð Iòð ð ˜FÒ"‰¨5¨'°°7°)Ð(<Ø'¨ v¨R°·±³Ð/@ÀÐBØØ"ØØñ?
ñ 	
ðØ<öð
€ó&dó
Ióó#ó 6ó8ôTBÐ3ô TBón>ð IØDØ"\ØDØDñÐ óBùóg Yùös   Á:DÂ=D