+
    „WÝjl*  ã                  ó2  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIHt ^ RI	H
t
Ht ^ RIHt ]P                  ! ]4      t. R OtR]R&   . R!OtR]R	&   R
 R ltR R ltR R ltR R ltR R ltR R ltR R ltR"R R lltR R ltR R ltR#R R lltR# )$z8Codex model discovery from API, local cache, and config.)ÚannotationsN)ÚPath)ÚListÚOptional)Únormalize_route_base_urlú	list[str]ÚDEFAULT_CODEX_MODELSz!list[tuple[str, tuple[str, ...]]]Ú_FORWARD_COMPAT_TEMPLATE_MODELSc               ó   € V ^8„  d   QhRR/# )é   Úreturnr   © )Úformats   "ÚKC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\codex_models.pyÚ__annotate__r   9   s   € ÷ *ñ *˜)ñ *ó    c                ó>   € \        \        P                  V 4      4      # )zOrder-preserving dedupe.)ÚlistÚdictÚfromkeys©Ú	model_idss   &r   Ú_deduper   9   s   € ä”—‘˜iÓ(Ó)Ð)r   c               ó    € V ^8„  d   QhRRRR/# ©r   r   r   r   r   )r   s   "r   r   r   >   s   € ÷ 	ñ 	¨)ð 	¸	ñ 	r   c                ó,  a€ \        V 4      p\        V4      o\         Fr  w  r#VS9  g   K  \        ;QJ d    V3R lV 4       F  '       g   K   RM	  RM! V3R lV 4       4      '       g   KP  VP	                  V4       SP                  V4       Kt  	  V# )z•Surface newer Codex slugs missing from live discovery when an older compatible template is
present (Clawdbot-style synthetic forward-compat catalog).c              3  ó,   <"  € T F	  qS9   x € K  	  R # 5i©Nr   )Ú.0ÚtemplateÚseens   & €r   Ú	<genexpr>Ú-_add_forward_compat_models.<locals>.<genexpr>D   s   øé € Ð.`ÑP_ÀH¸4Ö/?ÓP_ùs   ƒTF)r   Úsetr	   ÚanyÚappendÚadd)r   ÚorderedÚsynthetic_modelÚtemplate_modelsr    s   &   @r   Ú_add_forward_compat_modelsr*   >   so   ø€ ô �iÓ €GÜˆw‹<€Dß,KÑ(ˆØ $Ö&¯3«3Ô.`ÑP_Ó.`¯3¯3ª3Ô.`ÑP_Ó.`×+`Ô+`Ø�N‰N˜?Ô+Ø�H‰H�_Ö%ñ -Lð €Nr   c               ó    € V ^8„  d   QhRRRR/# r   r   )r   s   "r   r   r   J   s   € ÷ ñ  Yð °9ñ r   c                óÒ   € ^ RI HpHp . p\        V 4      pV  FK  pVP	                  V4       WQ,           pWd9   g   Wc9   d   K*  V! V4      '       g   K:  VP	                  V4       KM  	  V# )u,  Insert ``<slug>-900k`` large-context picker variants after eligible base slugs.

Base slugs keep the cheaper advertised 272K limit; the variant opts into the large window.
The suffix is Hermes-side only â€” stripped before the id hits the wire (agent/transports/codex.py,
agent/auxiliary_client.py).
)ÚCODEX_CONTEXT_VARIANT_SUFFIXÚhas_codex_context_variant)Úagent.model_metadatar-   r.   r#   r%   )r   r-   r.   ÚoutÚpresentÚmodel_idÚvariants   &      r   Ú_add_context_variantsr4   J   s_   € ÷ ]à€CÜ�)‹n€GÛˆØ�
‰
�8ÔØÕ9ˆØÔ ¤ÙÙ$ X×.Ô.Ø�J‰J�wÖñ ð €Jr   c               ó    € V ^8„  d   QhRRRR/# r   r   )r   s   "r   r   r   _   s   € ÷ Hñ H ið H°Iñ Hr   c                ó*   € \        \        V 4      4      # )z;Forward-compat synthesis + large-context variant synthesis.)r4   r*   r   s   &r   Ú_finalize_codex_modelsr7   _   s   € ä Ô!;¸IÓ!FÓGÐGr   c               ó    € V ^8„  d   QhRRRR/# r   r   )r   s   "r   r   r   d   s   € ÷ Gñ G¨	ð G°iñ Gr   c                óZ   € ^ RI Hp V  Uu. uF  q!! V4      '       d   K  VNK  	  up# u upi )z³Astra is account-gated: only the live account-scoped catalog may advertise it. A stale
``models_cache.json`` or a ``config.toml`` default is a compatibility hint, not entitlement.)Úis_astra_model)Úagent.reasoning_effortr:   )r   r:   Úmodels   &  r   Ú_drop_undiscovered_astrar=   d   s(   € õ 6á(ÓF™y�e°¸u×0E�EˆE™yÑFÐFùÒFs   ‹(Ÿ(c               ó   € V ^8„  d   QhRR/# )r   r   Ústrr   )r   s   "r   r   r   l   s   € ÷ Hñ H¨3ñ Hr   c                 ó¼  € ^ RI Hp Hp  V! RR7      p\        VP	                  R4      ;'       g    R4      p\        \        VP	                  R4      ;'       g    R4      P                  4       4      pV'       g   R# V ! V^ 4      '       d
   RX,           # ^ R	IH	p V! V4      pV'       d   R
P                  V4      MTR,           X,           #   \         d    Rp Lhi ; i)aY  Identity of the credential live discovery would use right now, for the catalog cache key.

Access/refresh tokens rotate in place while the account-scoped catalog stays authoritative for
the same ChatGPT principal and route, so the key includes the principal and resolved base URL,
not the rotating token. An expired token is its own state (per route): ``_codex_catalog`` serves
the static fallback for it, and that fallback must not outlive the refresh under the healthy
principal's key. Opaque non-JWT tokens
fall back to the token itself (the caller hashes every part before anything is persisted).
)Ú_codex_access_token_is_expiringÚ!resolve_codex_runtime_credentialsT)Ú	read_onlyÚapi_keyÚ Úbase_urlÚmissingzexpired
)Ú_codex_principal_identityÚ/Ú
)Úhermes_cli.authrA   rB   r?   Úgetr   ÚstripÚ	ExceptionÚagent.credential_poolrH   Újoin)rA   rB   ÚcredsÚtokenÚrouterH   Ú	principals          r   Ú!codex_catalog_credential_identityrU   l   s»   € ÷ cðÙ1¸DÔAˆÜ�E—I‘I˜iÓ(×.Ð.¨BÓ/ˆÜ(¬¨U¯Y©Y°zÓ-B×-HÐ-HÀbÓ)I×)OÑ)OÓ)QÓRˆ÷ ÙÙ& u¨a×0Ò0Ø˜UÕ"Ð"Ý?á)¨%Ó0€Iß#,ˆC�H‰H�YÔ°%¸4Õ?À%ÕGÐGøô ô ØŠðús   Š%C °(C ÁC ÃCÃCc               ó    € V ^8„  d   QhRRRR/# )r   ÚentriesÚobjectr   r   r   )r   s   "r   r   r   ˆ   s   € ÷ 1ñ 1˜6ð 1 iñ 1r   c                óZ  € . pV  EF  p\        V\        4      '       g   K  VP                  R4      p\        V\        4      '       d   VP	                  4       '       g   K[  VP                  R4      p\        V\        4      '       d&   VP	                  4       P                  4       R9   d   K§  VP                  R4      p\        V\        \        34      '       d   \        V4      MRpVP                  WcP	                  4       34       EK  	  VP                  4        \        R V 4       4      # )a  Visible slugs from a Codex catalog ``models`` list, sorted by (priority, slug), deduped.

Does not filter on ``supported_in_api``: that flag describes the public OpenAI API, while the
OAuth-backed Codex backend still accepts slugs marked false there (gpt-5.3-codex-spark).
ÚslugÚ
visibilityÚpriorityi'  c              3  ó*   "  € T F	  w  rVx € K  	  R # 5ir   r   )r   Ú_rZ   s   &  r   r!   Ú _ranked_slugs.<locals>.<genexpr>�   s   é € Ð0¡x™G˜A•4£xùs   ‚>   ÚhideÚhidden)Ú
isinstancer   rL   r?   rM   ÚlowerÚintÚfloatr%   Úsortr   )rW   ÚsortableÚitemrZ   r[   r\   Úranks   &      r   Ú_ranked_slugsrj   ˆ   sÝ   € ð €HÜˆÜ˜$¤×%Ò%ÙØ�x‰x˜ÓˆÜ˜$¤×$Ò$¨D¯J©J¯LªLÙØ—X‘X˜lÓ+ˆ
Ü�j¤#×&Ò&¨:×+;Ñ+;Ó+=×+CÑ+CÓ+EÐI[Ô+[ÙØ—8‘8˜JÓ'ˆÜ *¨8´c¼5°\× BÒ BŒs�8Œ}ÈˆØ�‰˜Ÿz™z›|Ð,×-ñ ð ‡M�M„OÜÑ0¡xÓ0Ó0Ð0r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úaccess_tokenr?   rF   úOptional[str]r   r   r   )r   s   "r   r   r       s"   € ÷ :ñ :¨ð :¸ð :ÐQZñ :r   c                ó˜  a
a€  ^ RI Hp ^ RIHp T;'       g    RP	                  4       P                  R4      ;'       g    V! 4       pV! W4      '       g   . # ^ RIo^ RIHp RRV  2/V! V 4      Co
^ R	I H	p V! V
V3R
 lVR7      w  rx\        \        T4      4      #   \         d#   p	\        P                  RT	4       . u Rp	?	# Rp	?	ii ; i)a  Fetch available models from the Codex API. Returns visible models sorted by priority.

``base_url`` is the host the credential is routed to (resolved together with it); the
catalog is fetched there, never from a host the credential does not belong to (#121486).
)Ú_codex_catalog_probe_allowed)Ú_codex_base_urlrE   rI   N)Úcodex_account_headersÚAuthorizationzBearer )Úfetch_codex_catalog_entriesc                ó,   <€ SP                  V S^
R7      # )é
   )ÚheadersÚtimeout)rL   )Úurlrv   Úhttpxs   &€€r   Ú<lambda>Ú(_fetch_models_from_api.<locals>.<lambda>³   s   ø€ ˜Ÿ	™	 #¨wÀ˜	ÔCr   ©rF   z)Failed to fetch Codex models from API: %s)r/   ro   Úhermes_cli.auth_codexrp   rM   Úrstripry   Úagent.codex_headersrq   rs   rN   ÚloggerÚdebugr7   rj   )rl   rF   ro   rp   Úcatalog_baserq   rs   rW   Ú_statusÚexcrv   ry   s   &&        @@r   Ú_fetch_models_from_apir…       s»   ù€ ðÝEÝ9Ø Ÿ˜ B×-Ñ-Ó/×6Ñ6°sÓ;×PÐP¹Ó?PˆÙ+¨L×GÒGØˆIÛõ 	>Ø" g¨l¨^Ð$<ÐdÑ@UÐVbÓ@cÐdˆÝDÙ6ÝCÈlô\Ñˆô "¤-°Ó"8Ó9Ð9øô	 ô Ü�‰Ð@À#ÔFØ�	ûðús.   „B ™&B Á B Á0B ÂC	Â'CÂ>C	ÃC	c               ó    € V ^8„  d   QhRRRR/# )r   Ú
codex_homer   r   rm   r   )r   s   "r   r   r   »   s   € ÷ Oñ O Dð O¨]ñ Or   c                óŠ  € V R ,          pVP                  4       '       g   R#  ^ RIp^ RIpVP                  VP                  RR7      4      p\        T\        4      '       d   TP                  R4      MRp\        T\        4      '       d'   TP                  4       '       d   TP                  4       # R#   \         d     R# i ; i)zconfig.tomlNú	utf-8-sig©Úencodingr<   )
ÚexistsÚtomllibÚloadsÚ	read_textrN   rb   r   rL   r?   rM   )r‡   Úconfig_pathr�   Úpayloadr<   s   &    r   Ú_read_default_modelr’   »   sž   € Ø˜}Õ,€KØ×Ñ×ÒÙðÛÛØ—-‘- × 5Ñ 5¸{Ð 5Ó KÓLˆô %/¨w¼×$=Ò$=ˆG�K‰K˜Ô À4€EÜ& u¬c×2Ò2°u·{±{·}²}ˆ5�;‰;‹=ÐNÈ$ÐNøô ô Úðús   £)B3 Â3CÃCc               ó    € V ^8„  d   QhRRRR/# )r   r‡   r   r   r   r   )r   s   "r   r   r   É   s   € ÷ 
Gñ 
G 4ð 
G¨Iñ 
Gr   c                óX  € V R ,          pVP                  4       '       g   . #  \        P                  ! VP                  RR7      4      p\        T\        4      '       d   TP                  R4      MRp\        \        T\        4      '       d   T4      # . 4      #   \         d    . u # i ; i)zmodels_cache.jsonr‰   rŠ   ÚmodelsN)
rŒ   ÚjsonrŽ   r�   rN   rb   r   rL   rj   r   )r‡   Ú
cache_pathÚrawrW   s   &   r   Ú_read_cache_modelsr™   É   s•   € ØÐ1Õ1€JØ×Ñ×ÒØˆ	ðÜ�jŠj˜×-Ñ-°{Ð-ÓCÓDˆô $.¨c´4×#8Ò#8ˆc�g‰g�hÔ¸d€GÜ¤J¨w¼×$=Ò$=˜ÓFÐFÀ2ÓFÐFøô	 ô ØŠ	ðús   £&B ÂB)Â(B)c               ó$   € V ^8„  d   QhRRRRRR/# )r   rl   rm   rF   r   r   r   )r   s   "r   r   r   Ö   s"   € ÷ #ñ # mð #Àmð #Ð_hñ #r   c                óÆ  € \        \        P                  ! RR4      P                  4       ;'       g&    \	        \         P
                  ! 4       R,          4      4      P                  4       pV '       d    \        WR7      pV'       d   \        V4      # ^ RI	H
p \        V4      pT! \        \        \        . V'       d   V.M. O\        V4      O\        O4      4      4      4      # )a©  Available Codex model IDs: live API (if token) > config.toml default > local cache > defaults.

Pass the ``base_url`` resolved together with ``access_token`` (runtime/pool route) so live
discovery asks the credential's own host. Without a live answer the result is
``CuratedFallbackModels``: a cache placeholder that never replaces a verified catalog, since
account-gated rows such as Astra are absent from the offline hints.Ú
CODEX_HOMErE   z.codexr|   )ÚCuratedFallbackModels)r   ÚosÚgetenvrM   r?   ÚhomeÚ
expanduserr…   r7   Ú hermes_cli.models_catalog_staticr�   r’   r=   r   r™   r   )rl   rF   r‡   Ú
api_modelsr�   Údefault_models   &&    r   Úget_codex_model_idsr¥   Ö   s½   € ô ”b—i’i ¨bÓ1×7Ñ7Ó9×XÐX¼SÄÇÂÃÈxÕAWÓ=XÓY×dÑdÓf€JßÜ+¨LÔLˆ
ßÜ)¨*Ó5Ð5åFä'¨
Ó3€MÙ Ô!7Ô8PÔQXð Zß*ˆ=‰/°ðZÜ6HÈÓ6TðZä	ðZó R ó 9!ó ""ó #ð #r   )	ú	gpt-6-solú
gpt-6-lunaúgpt-5.6-solúgpt-5.6-terraúgpt-5.6-lunaúgpt-5.5úgpt-5.4-miniúgpt-5.4úgpt-5.3-codex-spark))r¦   )r¨   r«   )r§   )rª   r«   )r¨   ©r«   r­   )r©   r¯   )rª   r¯   )r«   )r­   r¬   )r®   )r­   r«   r   )NN)Ú__conditional_annotations__Ú__doc__Ú
__future__r   r–   Úloggingrž   Úpathlibr   Útypingr   r   Úhermes_cli.route_identityr   Ú	getLoggerÚ__name__r€   r   Ú__annotations__r	   r   r*   r4   r7   r=   rU   rj   r…   r’   r™   r¥   )r°   s   @r   Ú<module>rº      s�   øðÜ >å "ã Û Û 	Ý ß !å >à	×	Ò	˜8Ó	$€ò#Ð �ió ò.	F5Ð Ð!Bó 	5õ*õ
	õõ*Hõ
GõHõ81÷0:õ6Oõ
G÷#ñ #r   