
    .cj'                        U d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	m
Z
 ddlZ ej        e          Zg dZded<   g d	Zd
ed<   ddZddZddZddZddZdddZdS ) z8Codex model discovery from API, local cache, and config.    )annotationsN)Path)ListOptional)gpt-5.6-solgpt-5.6-sol-progpt-5.6-terragpt-5.6-terra-progpt-5.6-lunagpt-5.6-luna-progpt-5.5gpt-5.4-minigpt-5.4gpt-5.3-codexgpt-5.3-codex-spark	List[str]DEFAULT_CODEX_MODELS)
)r   r   r   )r   r   )r	   r   )r
   r   )r   r   )r   r   )r   )r   r   r   )r   r   )r   r   )r   r   z!List[tuple[str, tuple[str, ...]]]_FORWARD_COMPAT_TEMPLATE_MODELS	model_idsreturnc                <   g }t                      | D ]0}|vr*|                    |                               |           1t          D ]O\  }}|v r
t	          fd|D                       r*|                    |                               |           P|S )a   Add Clawdbot-style synthetic forward-compat Codex models.

    If a newer Codex slug isn't returned by live discovery, surface it when an
    older compatible template model is present. This mirrors Clawdbot's
    synthetic catalog / forward-compat behavior for GPT-5 Codex variants.
    c              3      K   | ]}|v V  	d S N ).0templateseens     9/home/ice/.hermes/hermes-agent/hermes_cli/codex_models.py	<genexpr>z-_add_forward_compat_models.<locals>.<genexpr>Z   s(      @@Hx4@@@@@@    )setappendaddr   any)r   orderedmodel_idsynthetic_modeltemplate_modelsr   s        @r    _add_forward_compat_modelsr+   I   s     GUUD  4NN8$$$HHX,K & &(d""@@@@@@@@@ 	&NN?+++HH_%%%Nr"   access_tokenstrOptional[str]c                   	 |                      d          }t          |          dk     rdS |d         dt          |d                    dz  z  z   }t          j        t	          j        |                    }t          |t                    r)|                    di                               d          nd}t          |t                    r|r|ndS # t          $ r Y dS w xY w)	u  Best-effort extraction of ``chatgpt_account_id`` from the OAuth JWT.

    The Codex backend requires the ``ChatGPT-Account-Id`` header for the
    per-account catalog. Without it, ``GET /backend-api/codex/models``
    returns ``{"models":[]}`` (HTTP 200) — which masquerades as "no
    models available" and silently degrades the picker to the curated
    fallback list. The request-side path in ``auxiliary_client.py``
    already extracts the same claim; this mirrors that logic here so the
    probe sees the same catalog the request path will actually use.

    Returns ``None`` on any parse error — the probe then degrades
    gracefully to the unauthenticated fallback list instead of crashing.
    .   N   =   zhttps://api.openai.com/authchatgpt_account_id)splitlenjsonloadsbase64urlsafe_b64decode
isinstancedictgetr-   	Exception)r,   partspayload_b64claimsacct_ids        r    _extract_chatgpt_account_idrD   a   s    ""3''u::>>4AhU1X(:!;;F4[AABB &$''FJJ4b99==>RSSS 	
 %Wc22HwHwwDH   tts   (C B%C 
C C c                   	 ddl }dd|  i}t          |           }|r||d<   |                    d|d          }|j        d	k    rg S |                                }t          |t                    r|                    d
g           ng }n4# t          $ r'}t          	                    d|           g cY d}~S d}~ww xY wg }|D ]}	t          |	t                    s|	                    d          }
t          |
t                    r|
                                sX|
                                }
|	                    dd          }t          |t                    r)|                                                                dv r|	                    d          }t          |t          t          f          rt          |          nd}|                    ||
f           |                    d            t#          d |D                       S )zUFetch available models from the Codex API. Returns visible models sorted by priority.r   NAuthorizationzBearer zChatGPT-Account-IdzAhttps://chatgpt.com/backend-api/codex/models?client_version=1.0.0
   )headerstimeout   modelsz)Failed to fetch Codex models from API: %sslug
visibility >   hidehiddenpriority'  c                "    | d         | d         fS Nr   r2   r   )xs    r    <lambda>z(_fetch_models_from_api.<locals>.<lambda>   s    1qt r"   keyc                    g | ]\  }}|S r   r   )r   _rL   s      r    
<listcomp>z*_fetch_models_from_api.<locals>.<listcomp>   s    &D&D&D4t&D&D&Dr"   )httpxrD   r>   status_coder8   r<   r=   r?   loggerdebugr-   striplowerintfloatr$   sortr+   )r,   r\   rH   rC   respdataentriesexcsortableitemrL   rM   rQ   ranks                 r    _fetch_models_from_apirl      s-   "$<l$<$<=-l;; 	4,3G()yyO  
 

 s""Iyy{{,6tT,B,BJ$((8R(((   @#FFF						 H & &$%% 	xx$$$ 	DJJLL 	zz||
 XXlB//
j#&& 	:+;+;+=+=+C+C+E+EI[+[+[88J'' *8c5\ B BNs8}}}t%%%%MM,,M---%&D&D8&D&D&DEEEs%   AB
 AB
 

B;B60B;6B;
codex_homer   c                   | dz  }|                                 sd S 	 dd l}n# t          $ r Y d S w xY w	 |                    |                    d                    }n# t          $ r Y d S w xY wt          |t                    r|                    d          nd }t          |t                    r(|	                                r|	                                S d S )Nzconfig.tomlr   utf-8encodingmodel)
existstomllibr?   r9   	read_textr<   r=   r>   r-   r`   )rm   config_pathrt   payloadrr   s        r    _read_default_modelrx      s    },K t   tt-- 5 5w 5 G GHH   tt$.w$=$=GGKK   4E% %++-- {{}}4s   " 
00)A 
A,+A,c                   | dz  }|                                 sg S 	 t          j        |                    d                    }n# t          $ r g cY S w xY wt          |t                    r|                    d          nd }g }t          |t                    r|D ]}t          |t                    s|                    d          }t          |t                    r|
                                sX|
                                }|                    d          }t          |t                    r)|
                                                                dv r|                    d          }t          |t          t          f          rt          |          nd	}	|                    |	|f           |                    d
            g }
|D ]\  }}||
vr|
                    |           |
S )Nzmodels_cache.jsonro   rp   rK   rL   rM   >   rO   rP   rQ   rR   c                "    | d         | d         fS rT   r   )rj   s    r    rV   z$_read_cache_models.<locals>.<lambda>   s    DGT!W#5 r"   rW   )rs   r8   r9   ru   r?   r<   r=   r>   listr-   r`   ra   rb   rc   r$   rd   )rm   
cache_pathrawrg   ri   rj   rL   rM   rQ   rk   dedupedrZ   s               r    _read_cache_modelsr      s   11J 	j--w-??@@   			 $.c4#8#8BcgghdGH'4   * 	* 	*DdD)) 88F##DdC(( 

 ::<<D ,//J*c** z/?/?/A/A/G/G/I/IM_/_/_xx
++H$.x#u$F$FR3x===FDOOT4L))))MM55M666G ! !4wNN4   Ns   (A AAc                &   t          j        dd                                          p"t          t	          j                    dz            }t	          |                                          }g }| r t          |           }|rt          |          S t          |          }|r|
                    |           t          |          D ]}||vr|
                    |           t          D ]}||vr|
                    |           t          |          S )zReturn available Codex model IDs, trying API first, then local sources.
    
    Resolution order: API (live, if token provided) > config.toml default >
    local cache > hardcoded defaults.
    
CODEX_HOMErN   z.codex)osgetenvr`   r-   r   home
expanduserrl   r+   rx   r$   r   r   )r,   codex_home_strrm   r'   
api_modelsdefault_modelr(   s          r    get_codex_model_idsr      s    Y|R006688WC	h@V<W<WNn%%0022JG  :+L99
 	:-j999 (
33M &}%%%&z22 % %7""NN8$$$( % %7""NN8$$$%g...r"   )r   r   r   r   )r,   r-   r   r.   )r,   r-   r   r   )rm   r   r   r.   )rm   r   r   r   r   )r,   r.   r   r   )__doc__
__future__r   r:   r8   loggingpathlibr   typingr   r   r   	getLogger__name__r^   r   __annotations__r   r+   rD   rl   rx   r   r   r   r"   r    <module>r      s]   > > > " " " " " "          ! ! ! ! ! ! ! ! 						8	$	$&# &# &#  & & & &PF F F     $   0   <)F )F )F )FX   $" " " "J/ / / / / / /r"   