o
    Ղi>                     @   s  d Z ddlZddlmZmZ ddlmZmZmZm	Z	 ddl
mZ ddlmZ ddlmZmZ ddlmZ eeZe Zd	efd
dZG dd deZded	dfddZded	dfddZejdddedddfdedefddZdedee d	dfd d!ZdS )"z
Internal endpoint: POST /internal/switch_mode
Switches the LLM service between inference and training modes.
Requires the X-Internal-Token header.
    N)LiteralOptional)	APIRouterHeaderHTTPExceptionstatus)	BaseModel)settings)get_status_managerServiceMode)
get_loggerreturnc                   C   s   t jS )N)r	   SWITCH_MODE_SCRIPT r   r   D/lsinfo/ai/hellotax_ai/base_platform/app/api/internal/switch_mode.py_get_script_path   s   r   c                   @   s*   e Zd ZU ed ed< dZee ed< dS )SwitchModeRequest)	inferencetrainingmedia_processingmodeNtraining_info)__name__
__module____qualname__r   __annotations__r   r   dictr   r   r   r   r      s   
 r   tokenc                 C   s8   t tdd}|sttjdd| |krttjdddS )zMRaise 403 if the provided token does not match the configured internal token.INTERNAL_API_TOKENNz4INTERNAL_API_TOKEN is not configured on this server.)status_codedetailzInvalid internal token.)getattrr	   r   r   HTTP_500_INTERNAL_SERVER_ERRORHTTP_403_FORBIDDEN)r   expectedr   r   r   _verify_internal_token   s   r%   r   c              
      s   t  }zJtjd|| tjjtjjdI dH }| I dH \}}|r'|jddnd}|jdkr=t	
d|j d	|  W dS t	d
|  d	|dd   W dS  tyi } zt	
d|  W Y d}~dS d}~ww )zHRun switch_mode.sh in the background without blocking the HTTP response.bash)stdoutstderrNreplace)errors r   zswitch_mode.sh exited z: z"switch_mode.sh completed for mode=   zFailed to run switch_mode.sh: )r   asynciocreate_subprocess_exec
subprocessPIPESTDOUTcommunicatedecode
returncodeloggererrorinfo	Exception)r   script_pathprocr'   _outputer   r   r   _run_switch_script+   s"   
$r>   z/switch_modez"Switch LLM service mode (internal))summary.zX-Internal-Token)aliasbodyx_internal_tokenc                    s   t | t }t| j}|tj td| j  |tjkr9| j	r9ddl
m} ddl}|j||| j	 tt||| j	 d| jd| j ddS )	aO  
    Switch the LLM service to **inference** or **training** mode.

    - Immediately marks Redis status as ``switching``.
    - Fires ``switch_mode.sh <mode>`` in the background.
    - On script start the Redis key is set to the requested mode.

    Requires: ``X-Internal-Token`` header matching ``settings.INTERNAL_API_TOKEN``.
    zMode switch initiated: target=r   )REDIS_KEY_TRAINING_INFON	switchingzMode switch to 'z?' initiated. Service will be in switching state until complete.)r   target_modemessage)r%   r
   r   r   set_mode	SWITCHINGr5   r7   TRAININGr   'app.services.llm.service_status_managerrC   json_redissetdumpsr-   create_task_background_switch)rA   rB   managerrE   rC   rK   r   r   r   switch_mode>   s   
rR   rE   r   c              
      st   zt |jI dH  | j||d td|j d W dS  ty9 } ztd| d | tj  d}~ww )z9Run the shell script then update Redis to the final mode.N)r   zMode switch complete: now in z modezBackground switch failed: z. Reverting to inference mode.)	r>   valuerG   r5   r7   r8   r6   r   	INFERENCE)rQ   rE   r   r=   r   r   r   rP   e   s   rP   )__doc__r-   typingr   r   fastapir   r   r   r   pydanticr   
app.configr	   rJ   r
   r   app.core.loggingr   r   r5   routerstrr   r   r%   r>   postrR   r   rP   r   r   r   r   <module>   s8    
&