
    j#                    p   U d Z ddlmZ ddlmZ ddlmZmZmZm	Z	 dZ
dZdddd	dddd	dd
dd	dddd	dd
dd	dddd	dddd	dddd	dZded<    ed           G d d                      Zd-dZd.dZd/dZd0dZddlZdd lmZ ddlZ ed           G d! d"                      Zd1d'Z	 d2d3d,ZdS )4uO  Detect xAI models retired on May 15, 2026.

Source: https://docs.x.ai/developers/migration/may-15-retirement

Pure logic: walks a Hermes config dict, returns issues for any reference
to a retired xAI model. No I/O, no CLI dependencies — testable in isolation
and reusable from both `hermes doctor` and a future `hermes migrate xai`.
    )annotations)	dataclass)AnyDictListOptionalz8https://docs.x.ai/developers/migration/may-15-retirementzMay 15, 2026zgrok-4.3N)replacementreasoning_effortnotenonezgrok-imagine-image-quality)zgrok-4-0709zgrok-4-fast-reasoningzgrok-4-fast-non-reasoningzgrok-4-1-fast-reasoningzgrok-4-1-fast-non-reasoningzgrok-code-fast-1zgrok-3zgrok-imagine-image-proz#Dict[str, Dict[str, Optional[str]]]_RETIRED_MODELST)frozenc                  N    e Zd ZU dZded<   ded<   ded<   dZded<   dZded	<   dS )
RetirementIssuez<A reference to a retired xAI model found in a Hermes config.strconfig_pathcurrent_modelr	   NOptional[str]r
   r   )__name__
__module____qualname____doc____annotations__r
   r        8/usr/local/lib/hermes-agent/hermes_cli/xai_retirement.pyr   r   #   s_         FF&*****Dr   r   model_idr   returnc                    |                                                                  }dD ]0}|                    |          r|t          |          d         } n1|S )uE   Strip provider prefix (``x-ai/grok-4`` → ``grok-4``) and lowercase.)zx-ai/zxai/N)striplower
startswithlen)r   mprefixs      r   
_normalizer&   .   sd      A#  << 	#f++,,AE	 Hr   r   boolc                    t          | t                    r|                                 sdS t          |                               d          S )NFzgrok-)
isinstancer   r    r&   r"   )r   s    r   _looks_like_xair*   8   sF    h$$ HNN,<,< uh**7333r   configDict[str, Any]List[RetirementIssue]c                   g dfd}t          | t                    sS |                     d          }t          |t                    r |d	|                    d                     |                     d
          }t          |t                    rR|                                D ]=\  }}t          |t                    r# |d| d|                    d                     >|                     d          }t          |t                    r |d|                    d                     |                     d          }t          |t                    rI|                    d          }t          |t                    r |d|                    d                     |                     d          }	t          |	t                    rs|	                    d          }
t          |
t                    rI|
                    d          }t          |t                    r |d|                    d                     S )u'  Walk all model slots in a Hermes config and return retirement issues.

    Slots scanned:
      - ``principal.model``
      - ``auxiliary.<any>.model`` (introspective — covers future aux slots)
      - ``delegation.model``
      - ``tts.xai.model``
      - ``plugins.image_gen.xai.model``
    pathr   modelr   r   Nonec                *   t          |          sd S t          |          }t                              |          }|d S                     t          | ||d         |                    d          |                    d                               d S )Nr	   r
   r   )r   r   r	   r
   r   )r*   r&   r   getappendr   )r/   r0   normentryissuess       r   _checkz%find_retired_xai_refs.<locals>._checkJ   s    u%% 	F%  ##D))=Fom,"YY'9::6""
 
 
 	 	 	 	 	r   	principalzprincipal.model	auxiliaryz
auxiliary.z.model
delegationzdelegation.modelttsxaiztts.xai.modelplugins	image_genzplugins.image_gen.xai.model)r/   r   r0   r   r   r1   )r)   dictr3   items)r+   r8   r9   aux	slot_nameslot_cfgr;   r<   tts_xair>   r?   ig_xair7   s               @r   find_retired_xai_refsrG   >   s7    %'F      fd## 

;''I)T"" : )--"8"8999
**[
!
!C#t N#&99;; 	N 	NIx(D)) N5I555x||G7L7LMMML))J*d## <!:>>'#:#:;;;
**U

C#t :''%..gt$$ 	:F?GKK$8$8999jj##G'4   KKK,,	i&& 	K]]5))F&$'' K4fjj6I6IJJJMr   issuec                    | j          d| j        d| j        g}| j        r|                    d| j         d           | j        r|                    d| j         d           d                    |          S )z8One-line human-readable rendering of a retirement issue.z: u	    → use z(set reasoning_effort: "z")z[note: ] )r   r   r	   r
   r4   r   join)rH   partss     r   format_issuerN   {   s     UU 3UU@QUUE  LJ0FJJJKKKz .,uz,,,---88E??r   )Pathc                  <    e Zd ZU dZded<   ded<   ded<   ded	<   d
S )ApplyResultz#Outcome of an apply_migration call.rO   	file_pathzOptional[Path]backup_pathr-   issues_resolvedr'   config_changedN)r   r   r   r   r   r   r   r   rQ   rQ      sE         --OOO****r   rQ   yaml_docr   dotted_path'tuple[Any, str]'c                   |                     d          }t          |          dk     rt          d|          | }|dd         D ]8}t          |t                    r||vrt          d|d|          ||         }9||d         fS )zResolve a dotted slot path to (parent_mapping, leaf_key).

    Example: "auxiliary.vision.model" -> (yaml_doc["auxiliary"]["vision"], "model").
    Raises KeyError if any intermediate node is missing or not a mapping.
    .   z$Path must have at least one parent: NzPath segment z missing in )splitr#   
ValueErrorr)   r@   KeyError)rV   rW   rM   nodesegments        r   _walk_to_parentrb      s     c""E
5zzA~~OOOPPPD":  $%% 	S)<)<Q7QQ+QQRRRG}r?r   r   rO   r7   backupc                   ddl m} t          |           } |                                 st	          |           |st          | dg d          S  |d          }d|_        |                     d	d
          5 }|                    |          }ddd           n# 1 swxY w Y   |t          | dg d          S g }|D ]\}	 t          ||j
                  \  }	}
n# t          $ r Y (w xY w|j        |	|
<   |j        r
|j        |	d<   |                    |           ]|st          | dg d          S d}|ret          j                                                            d          }|                     | j         d|           }t+          j        | |           |                     dd
          5 }|                    ||           ddd           n# 1 swxY w Y   t          | ||d          S )aX  Rewrite ``config_path`` in-place so each issue is resolved.

    For every issue, the model name is replaced by ``issue.replacement``. If the
    issue has ``reasoning_effort`` set (i.e. the migration is from a
    ``*-non-reasoning`` variant), a sibling ``reasoning_effort`` key is added
    or updated alongside the model.

    Uses ``ruamel.yaml`` round-trip mode so comments, key order, indentation,
    and type literals (booleans, ints) are preserved.

    A backup copy is written to
    ``<config_path>.bak-pre-migrate-xai-YYYYMMDD-HHMMSS`` before rewriting,
    unless ``backup=False``.
    r   )YAMLNF)rR   rS   rT   rU   rt)typTrzutf-8)encodingr
   z%Y%m%d-%H%M%Sz.bak-pre-migrate-xai-w)ruamel.yamlre   rO   existsFileNotFoundErrorrQ   preserve_quotesopenloadrb   r   r_   r	   r
   r4   _dtdatetimenowstrftime	with_namenameshutilcopy2dump)r   r7   rc   re   yamlfhdocresolvedrH   parentleafrS   tss                r   apply_migrationr      s   & !     {##K -,,, 
! 	
 
 
 	
 4D>>>DD			#		0	0 Biimm               {! 	
 
 
 	
 ')H 	 		*30ABBLFDD 	 	 	H	 (t! 	@).)?F%& 
! 	
 
 
 	
 #'K /\((99!++::b::
 
 	[+...			#		0	0 B		#r                	   s6   8BB!BC
C'&C'0GGG)r   r   r   r   )r   r   r   r'   )r+   r,   r   r-   )rH   r   r   r   )rV   r   rW   r   r   rX   )T)r   rO   r7   r-   rc   r'   r   rQ   )r   
__future__r   dataclassesr   typingr   r   r   r   MIGRATION_GUIDE_URLRETIREMENT_DATEr   r   r   r&   r*   rG   rN   rr   rq   pathlibrO   rw   rQ   rb   r   r   r   r   <module>r      sG     # " " " " " ! ! ! ! ! ! , , , , , , , , , , , , Q   5?TXcg$h$h4>TXcg$h$h4>TZdh$i$i4>TXcg$h$h4>TZdh$i$i4>TXcg$h$h4>TXcg$h$h4Pfjtx$y$y	8 	8 	 	 	 	 $          4 4 4 4: : : :z	 	 	 	             $          ( R R R R R R Rr   