§
    ‰eîi=1  ã                  ó  — U d Z ddlmZ ddlZddlmZmZmZmZm	Z	 ddl
mZmZmZmZmZmZ  ej        e¦  «        ZdZddd	d
dœdddddœdddddœdœZded<   dZddddœZdZdZdZd2d!„Zd3d#„Zd4d%„Zd&„ Zd5d-„Z  G d.„ d/e¦  «        Z!d6d1„Z"dS )7u3  OpenAI image generation backend â€” ChatGPT/Codex OAuth variant.

Identical model catalog and tier semantics to the ``openai`` image-gen plugin
(``gpt-image-2`` at low/medium/high quality), but routes the request through
the Codex Responses API ``image_generation`` tool instead of the
``images.generate`` REST endpoint. This lets users who are already
authenticated with Codex/ChatGPT generate images without configuring a
separate ``OPENAI_API_KEY``.

Selection precedence for the tier (first hit wins):

1. ``OPENAI_IMAGE_MODEL`` env var (escape hatch for scripts / tests)
2. ``image_gen.openai-codex.model`` in ``config.yaml``
3. ``image_gen.model`` in ``config.yaml`` (when it's one of our tier IDs)
4. :data:`DEFAULT_MODEL` â€” ``gpt-image-2-medium``

Output is saved as PNG under ``$HERMES_HOME/cache/images/``.
é    )ÚannotationsN)ÚAnyÚDictÚListÚOptionalÚTuple)ÚDEFAULT_ASPECT_RATIOÚImageGenProviderÚerror_responseÚresolve_aspect_ratioÚsave_b64_imageÚsuccess_responsezgpt-image-2zGPT Image 2 (Low)z~15szFast iteration, lowest costÚlow)ÚdisplayÚspeedÚ	strengthsÚqualityzGPT Image 2 (Medium)z~40su   Balanced â€” defaultÚmediumzGPT Image 2 (High)z~2minz,Highest fidelity, strongest prompt adherenceÚhigh)zgpt-image-2-lowúgpt-image-2-mediumzgpt-image-2-highzDict[str, Dict[str, Any]]Ú_MODELSr   Ú	1536x1024Ú	1024x1024Ú	1024x1536)Ú	landscapeÚsquareÚportraitzgpt-5.4z%https://chatgpt.com/backend-api/codexzrYou are an assistant that must fulfill image generation requests by using the image_generation tool when provided.ÚreturnúDict[str, Any]c                 ó  — 	 ddl m}   | ¦   «         }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`` from config.yaml (returns {} on any failure).r   )Úload_configÚ	image_genNz#Could not load image_gen config: %s)Úhermes_cli.configr!   Ú
isinstanceÚdictÚgetÚ	ExceptionÚloggerÚdebug)r!   ÚcfgÚsectionÚexcs       úI/home/div/.hermes/hermes-agent/plugins/image_gen/openai-codex/__init__.pyÚ_load_image_gen_configr.   X   s¥   € ðØ1Ð1Ð1Ð1Ð1Ð1àˆk‰mŒmˆÝ*4°S½$Ñ*?Ô*?ÐI�#—'’'˜+Ñ&Ô&Ð&ÀTˆÝ$ W­dÑ3Ô3Ð;ˆwˆw¸Ð;øÝð ð ð Ý�ŠÐ:¸CÑ@Ô@Ð@Øˆ	ˆ	ˆ	ˆ	ˆ	ˆ	øøøøðøøøs   ‚AA Á
BÁ!BÁ=BÂBúTuple[str, Dict[str, Any]]c                 óf  — ddl } | j                             d¦  «        }|r|t          v r|t          |         fS t	          ¦   «         }t          |                     d¦  «        t          ¦  «        r|                     d¦  «        ni }d}t          |t          ¦  «        r5|                     d¦  «        }t          |t          ¦  «        r|t          v r|}|€5|                     d¦  «        }t          |t          ¦  «        r|t          v r|}|�|t          |         fS t          t          t                   fS )z9Decide which tier to use and return ``(model_id, meta)``.r   NÚOPENAI_IMAGE_MODELúopenai-codexÚmodel)	ÚosÚenvironr&   r   r.   r$   r%   ÚstrÚDEFAULT_MODEL)r4   Úenv_overrider*   ÚsubÚ	candidateÚvalueÚtops          r-   Ú_resolve_modelr=   e   s#  € à€I€I€Ià”:—>’>Ð"6Ñ7Ô7€LØð 3˜­Ð/Ð/Ø�W \Ô2Ð2Ð2å
 Ñ
"Ô
"€CÝ%/°·²¸Ñ0GÔ0GÍÑ%NÔ%NÐ
Vˆ#�'Š'�.Ñ
!Ô
!Ð
!ÐTV€CØ#€IÝ�#•tÑÔð Ø—’˜Ñ Ô ˆÝ�e�SÑ!Ô!ð 	 e­wÐ&6Ð&6ØˆIØÐØ�gŠg�gÑÔˆÝ�c�3ÑÔð 	 C­7 N NØˆIàÐØ�' )Ô,Ð,Ð,å�'¥-Ô0Ð0Ð0ó    úOptional[str]c                 ó  — 	 ddl m}   | ¦   «         }t          |t          ¦  «        r(|                     ¦   «         r|                     ¦   «         S dS # t
          $ r&}t                               d|¦  «         Y d}~dS d}~ww xY w)zÉReturn a usable Codex OAuth token, or None.

    Delegates to the canonical reader in ``agent.auxiliary_client`` so token
    expiry, credential pool selection, and JWT decoding stay in one place.
    r   )Ú_read_codex_access_tokenNz(Could not resolve Codex access token: %s)Úagent.auxiliary_clientrA   r$   r6   Ústripr'   r(   r)   )Ú_readerÚtokenr,   s      r-   rA   rA      s™   € ð	ØNÐNÐNÐNÐNÐNà�‘	”	ˆÝ�e�SÑ!Ô!ð 	! e§k¢k¡m¤mð 	!Ø—;’;‘=”=Ð ØˆtøÝð ð ð Ý�ŠÐ?ÀÑEÔEÐEØˆtˆtˆtˆtˆtøøøøðøøøs   ‚AA Á
BÁA<Á<Bc                 óî   — t          ¦   «         } | sdS 	 ddl}ddlm} |                     | t
           || ¦  «        ¬¦  «        S # t          $ r&}t                               d|¦  «         Y d}~dS d}~ww xY w)zFReturn an OpenAI client pointed at the ChatGPT/Codex backend, or None.Nr   )Ú_codex_cloudflare_headers)Úapi_keyÚbase_urlÚdefault_headersz&Could not build Codex image client: %s)	rA   ÚopenairB   rG   ÚOpenAIÚ_CODEX_BASE_URLr'   r(   r)   )rE   rK   rG   r,   s       r-   Ú_build_codex_clientrN   ‘   s¬   € å$Ñ&Ô&€EØð ØˆtðØˆˆˆØDÐDÐDÐDÐDÐDà�}Š}ØÝ$Ø5Ð5°eÑ<Ô<ð ñ 
ô 
ð 	
øõ
 ð ð ð Ý�ŠÐ=¸sÑCÔCÐCØˆtˆtˆtˆtˆtøøøøðøøøs   ”/A Á
A4ÁA/Á/A4Úclientr   Úpromptr6   Úsizer   c               óÖ  — d}| j                              t          dt          ddd|dœgdœgdt          ||d	d
ddœgddddigdœ¬¦  «        5 }|D ]š}t          |dd¦  «        }|dk    rQt          |dd¦  «        }t          |dd¦  «        dk    r*t          |dd¦  «        }	t          |	t          ¦  «        r|	r|	}Œj|dk    r*t          |dd¦  «        }
t          |
t          ¦  «        r|
r|
}Œ›|                     ¦   «         }ddd¦  «         n# 1 swxY w Y   t          |dd¦  «        pg D ]A}t          |dd¦  «        dk    r*t          |dd¦  «        }	t          |	t          ¦  «        r|	r|	}ŒB|S )zHStream a Codex Responses image_generation call and return the b64 image.NFÚmessageÚuserÚ
input_text)ÚtypeÚtext)rV   ÚroleÚcontentÚimage_generationÚpngÚopaqueé   )rV   r3   rQ   r   Úoutput_formatÚ
backgroundÚpartial_imagesÚallowed_toolsÚrequiredrV   )rV   ÚmodeÚtools)r3   ÚstoreÚinstructionsÚinputrd   Útool_choiceÚ zresponse.output_item.doneÚitemÚimage_generation_callÚresultz,response.image_generation_call.partial_imageÚpartial_image_b64Úoutput)	Ú	responsesÚstreamÚ_CODEX_CHAT_MODELÚ_CODEX_INSTRUCTIONSÚ	API_MODELÚgetattrr$   r6   Úget_final_response)rO   rP   rQ   r   Ú	image_b64rp   ÚeventÚ
event_typerj   rl   ÚpartialÚfinals               r-   Ú_collect_image_b64r{   ¤   s/  € à#€Ià	Ô	×	 Ò	 ÝØÝ(àØØ!-°vÐ>Ð>Ð?ð
ð 
ð ð 'ÝØØØ"Ø"Øð
ð 
ð ð $ØØÐ1Ð2Ð3ð
ð 
ð% 
!ñ 
ô 
ð $,ð. 
Øð 	(ð 	(ˆEÝ  ¨°Ñ3Ô3ˆJØÐ8Ò8Ð8Ý˜u f¨dÑ3Ô3�Ý˜4 ¨Ñ.Ô.Ð2IÒIÐIÝ$ T¨8°TÑ:Ô:�FÝ! &­#Ñ.Ô.ð +°6ð +Ø$*˜	øØÐMÒMÐMÝ! %Ð)<¸dÑCÔC�Ý˜g¥sÑ+Ô+ð (°ð (Ø '�IøØ×)Ò)Ñ+Ô+ˆðI$,ð $,ð $,ñ $,ô $,ð $,ð $,ð $,ð $,ð $,ð $,øøøð $,ð $,ð $,ð $,õP ˜˜x¨Ñ.Ô.Ð4°"ð #ð #ˆÝ�4˜ Ñ&Ô&Ð*AÒAÐAÝ˜T 8¨TÑ2Ô2ˆFÝ˜&¥#Ñ&Ô&ð #¨6ð #Ø"�	øàÐs   ÁB2D	Ä	DÄDc                  ón   — 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
efdd„ZdS )ÚOpenAICodexImageGenProviderzEgpt-image-2 routed through ChatGPT/Codex OAuth instead of an API key.r   r6   c                ó   — dS )Nr2   © ©Úselfs    r-   Únamez OpenAICodexImageGenProvider.nameá   s   € àˆ~r>   c                ó   — dS )NúOpenAI (Codex auth)r   r€   s    r-   Údisplay_namez(OpenAICodexImageGenProvider.display_nameå   s   € à$Ð$r>   Úboolc                óT   — t          ¦   «         sdS 	 dd l}n# t          $ r Y dS w xY wdS )NFr   T)rA   rK   ÚImportError)r�   rK   s     r-   Úis_availablez(OpenAICodexImageGenProvider.is_availableé   sL   € Ý'Ñ)Ô)ð 	Ø�5ð	ØˆMˆMˆMˆMøÝð 	ð 	ð 	Ø�5�5ð	øøøàˆts   ’ —
%¤%úList[Dict[str, Any]]c                óH   — d„ t                                ¦   «         D ¦   «         S )Nc                óH   — g | ]\  }}||d          |d         |d         ddœ‘Œ S )r   r   r   Úvaries)Úidr   r   r   Úpricer   )Ú.0Úmodel_idÚmetas      r-   ú
<listcomp>z;OpenAICodexImageGenProvider.list_models.<locals>.<listcomp>ó   sQ   € ð 	
ð 	
ð 	
ñ �˜$ð Ø 	œ?Ø˜gœØ! +Ô.Ø!ðð ð	
ð 	
ð 	
r>   )r   Úitemsr€   s    r-   Úlist_modelsz'OpenAICodexImageGenProvider.list_modelsò   s-   € ð	
ð 	
õ #*§-¢-¡/¤/ð	
ñ 	
ô 	
ð 		
r>   r?   c                ó   — t           S )N)r7   r€   s    r-   Údefault_modelz)OpenAICodexImageGenProvider.default_modelþ   s   € ÝÐr>   r   c                ó   — dddg ddœS )Nr„   Úfreeu;   gpt-image-2 via ChatGPT/Codex OAuth â€” no API key requiredui   Sign in with `hermes auth codex` (or `hermes setup` â†’ Codex) if you haven't already. No API key needed.)r‚   ÚbadgeÚtagÚenv_varsÚpost_setup_hintr   r€   s    r-   Úget_setup_schemaz,OpenAICodexImageGenProvider.get_setup_schema  s"   € à)ØØPØð=ð	
ð 	
ð 		
r>   rP   Úaspect_ratioÚkwargsr   c           
     óœ  — |pd                      ¦   «         }t          |¦  «        }|st          ddd|¬¦  «        S t          ¦   «         st          ddd|¬¦  «        S 	 dd l}n## t
          $ r t          d	d
d|¬¦  «        cY S w xY wt          ¦   «         \  }}t                               |t          d         ¦  «        }t          ¦   «         }	|	€t          ddd|||¬¦  «        S 	 t          |	|||d         ¬¦  «        }
nK# t          $ r>}t                               dd¬¦  «         t          d|› �dd|||¬¦  «        cY d }~S d }~ww xY w|
st          ddd|||¬¦  «        S 	 t          |
d|› �¬¦  «        }n/# t          $ r"}t          d|› �dd|||¬¦  «        cY d }~S d }~ww xY wt          t!          |¦  «        |||d||d         dœ¬¦  «        S )Nri   z1Prompt is required and must be a non-empty stringÚinvalid_argumentr2   )ÚerrorÚ
error_typeÚproviderrŸ   uo   No Codex/ChatGPT OAuth credentials available. Run `hermes auth codex` (or `hermes setup` â†’ Codex) to sign in.Úauth_requiredr   z8openai Python package not installed (pip install openai)Úmissing_dependencyr   z'Could not initialize Codex image client)r£   r¤   r¥   r3   rP   rŸ   r   )rP   rQ   r   zCodex image generation failedT)Úexc_infoz/OpenAI image generation via Codex auth failed: Ú	api_errorz8Codex response contained no image_generation_call resultÚempty_responseÚopenai_codex_)ÚprefixzCould not save image to cache: Úio_error)rQ   r   )Úimager3   rP   rŸ   r¥   Úextra)rC   r   r   rA   rK   rˆ   r=   Ú_SIZESr&   rN   r{   r'   r(   r)   r   r   r6   )r�   rP   rŸ   r    ÚaspectrK   Útier_idr’   rQ   rO   Úb64r,   Ú
saved_paths                r-   Úgeneratez$OpenAICodexImageGenProvider.generate  së  € ð �,˜B×%Ò%Ñ'Ô'ˆÝ% lÑ3Ô3ˆàð 	Ý!ØIØ-Ø'Ø#ð	ñ ô ð õ (Ñ)Ô)ð 		Ý!ðTð +Ø'Ø#ðñ ô ð ð	ØˆMˆMˆMˆMøÝð 	ð 	ð 	Ý!ØPØ/Ø'Ø#ð	ñ ô ð ð ð ð	øøøõ 'Ñ(Ô(‰ˆ�Ý�zŠz˜&¥&¨Ô"2Ñ3Ô3ˆå$Ñ&Ô&ˆØˆ>Ý!Ø?Ø*Ø'ØØØ#ðñ ô ð ð	Ý$ØØØØ˜Yœð	ñ ô ˆCˆCøõ ð 		ð 		ð 		Ý�LŠLÐ8À4ˆLÑHÔHÐHÝ!ØMÈÐMÐMØ&Ø'ØØØ#ðñ ô ð ð ð ð ð ð øøøøð		øøøð ð 	Ý!ØPØ+Ø'ØØØ#ðñ ô ð ð
	Ý'¨Ð4MÀGÐ4MÐ4MÐNÑNÔNˆJˆJøÝð 	ð 	ð 	Ý!Ø=¸Ð=Ð=Ø%Ø'ØØØ#ðñ ô ð ð ð ð ð ð øøøøð	øøøõ  Ý�j‘/”/ØØØØ#Ø¨D°¬OÐ<Ð<ð
ñ 
ô 
ð 	
sN   ÁA" Á"BÂBÃ"C< Ã<
EÄ3D?Ä9EÄ?EÅE4 Å4
F Å>FÆF ÆF N)r   r6   )r   r†   )r   rŠ   ©r   r?   ©r   r   )rP   r6   rŸ   r6   r    r   r   r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Úpropertyr‚   r…   r‰   r•   r—   rž   r	   rµ   r   r>   r-   r}   r}   Þ   sÍ   € € € € € ØOÐOàðð ð ñ „Xðð ð%ð %ð %ñ „Xð%ðð ð ð ð

ð 

ð 

ð 

ðð ð ð ð

ð 

ð 

ð 

ð 1ðc
ð c
ð c
ð c
ð c
ð c
ð c
r>   r}   ÚNonec                óH   — |                       t          ¦   «         ¦  «         dS )uD   Plugin entry point â€” register the Codex-backed image-gen provider.N)Úregister_image_gen_providerr}   )Úctxs    r-   ÚregisterrÁ   x  s#   € à×#Ò#Õ$?Ñ$AÔ$AÑBÔBÐBÐBÐBr>   r·   )r   r/   r¶   )
rO   r   rP   r6   rQ   r6   r   r6   r   r?   )r   r½   )#r»   Ú
__future__r   ÚloggingÚtypingr   r   r   r   r   Úagent.image_gen_providerr	   r
   r   r   r   r   Ú	getLoggerr¸   r(   rs   r   Ú__annotations__r7   r°   rq   rM   rr   r.   r=   rA   rN   r{   r}   rÁ   r   r>   r-   ú<module>rÈ      s  ððð ð ð& #Ð "Ð "Ð "Ð "Ð "à €€€Ø 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3ðð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð 
ˆÔ	˜8Ñ	$Ô	$€ð €	ð 'ØØ2Øð	ð ð *ØØ+Øð	ð ð (ØØCØð	ð ð&ð &€ð ð ð ñ ð* %€ð ØØð
ð 
€ð Ð Ø9€ð5ð ð
ð 
ð 
ð 
ð1ð 1ð 1ð 1ð4ð ð ð ð$ð ð ð&2ð 2ð 2ð 2ðtR
ð R
ð R
ð R
ð R
Ð"2ñ R
ô R
ð R
ðtCð Cð Cð Cð Cð Cr>   