o
    پiN                     @   sz   d dl Z d dlZd dl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mZ eeZG dd deZdS )    N)AnyDictListTuple)Tool)BaseFormatDetector)StreamingParseResultToolCallItem_GetInfoFuncc                
       sv  e Zd ZdZ fddZdedefddZdedee	 de
fd	d
ZdededefddZdedee fddZdedee defddZdededee fddZdedee	 de
fddZdedee	 dee fddZd1d efd!d"Zdedee	 deeee f fd#d$Zd%edee	 dee fd&d'Zd(ed)ed*edee	 def
d+d,Zdefd-d.Zdefd/d0Z  ZS )2MinimaxM2Detectora  
    Detector for MiniMax M2 models.
    Assumes function call format:
        <minimax:tool_call>
        <invoke name="func1">
        <parameter name="param1">value1</parameter>
        <parameter name="param2">value2</parameter>
        </invoke>
        </minimax:tool_call>
    c                    sz   t    d| _d| _d| _d| _tdtj| _	tdtj| _
tdtj| _d| _d| _i | _i | _d	| _d	| _d S )
Nz<minimax:tool_call>z</minimax:tool_call>z<invoke name="z	</invoke>zF<minimax:tool_call>(.*?)</minimax:tool_call>|<minimax:tool_call>(.*?)$z2<invoke name=\"(.*?)</invoke>|<invoke name=\"(.*)$z<<parameter name=\"(.*?)</parameter>|<parameter name=\"(.*?)$ F)super__init__tool_call_start_tokentool_call_end_tokentool_call_prefixtool_call_function_end_tokenrecompileDOTALLtool_call_regextool_call_function_regextool_call_parameter_regex_buf_current_function_name_current_parameters_streamed_parameters_in_tool_call_function_name_sentself	__class__ W/home/ubuntu/.local/lib/python3.10/site-packages/sglang/srt/function_call/minimax_m2.pyr      s,   

zMinimaxM2Detector.__init__textreturnc                 C   s
   | j |v S N)r   )r    r%   r#   r#   r$   has_tool_call8   s   
zMinimaxM2Detector.has_tool_calltoolsc                 C   s   |  ||\}}t||dS )Nnormal_textcalls)_extractr   )r    r%   r)   normalr,   r#   r#   r$   detect_and_parse;   s   z"MinimaxM2Detector.detect_and_parsevalue
param_typec                 C   s   |  ||gS )zIConvert parameter value to the correct type (legacy single-type version).)_convert_param_value_with_types)r    r0   r1   r#   r#   r$   _convert_param_value?   s   z&MinimaxM2Detector._convert_param_valueschemac           	      C   s  |du rdgS t |tsdgS t }d|v r9|d }t |tr%|| nt |tr9|D ]}t |tr8|| q,d|v rt |d tr|d r|d D ]M}|du rX|d qLt |trc|d qLt |trn|d qLt |try|d qLt |tr|d qLt |tr|d	 qLt |tr|d
 qLdD ]}||v rt || tr|| D ]}| 	|}|
| qq|sdgS t|S )a5  
        Extract all possible types from a JSON schema definition.
        Handles anyOf, oneOf, allOf, type arrays, and enum fields.

        Args:
            schema: The JSON schema definition for a parameter

        Returns:
            List of type strings (e.g., ["string", "integer", "null"])
        Nstringtypeenumnullbooleanintegernumberarrayobject)anyOfoneOfallOf)
isinstancedictsetstraddlistboolintfloat_extract_types_from_schemaupdate)	r    r4   types
type_valuetr0   choice_fieldchoice	extractedr#   r#   r$   rJ   C   sP   












z,MinimaxM2Detector._extract_types_from_schemaparam_typesc              
   C   sb  |  dkrdS dd |D }d|v s|  dv rdS g d}|D ]|}||vr(q!|dv r0|  S |dv rGzt|W   S  ttfyF   Y q!w |d	v rmzt|}|t|kr[|W   S t|W   S  ttfyl   Y q!w |d
v r|   }|dv r~ dS |dv r dS q!|dv rzt|W   S  tjy   Y q!w q!zt|W S  tjy   | Y S w )a<  
        Convert parameter value to the correct type based on a list of possible types.
        Tries each type in order until one succeeds.

        Args:
            value: The string value to convert
            param_types: List of possible type strings

        Returns:
            The converted value
        r8   Nc                 S   s   g | ]}|  qS r#   )lower).0rN   r#   r#   r$   
<listcomp>   s    zEMinimaxM2Detector._convert_param_value_with_types.<locals>.<listcomp>)r8   nonenil)r:   rH   r;   rI   r9   rG   r=   r<   r5   rD   r%   )r5   rD   r%   )r:   rH   )r;   rI   )r9   rG   )true1yesonT)false0nooffF)r=   r<   )	rS   rH   
ValueError	TypeErrorrI   stripjsonloadsJSONDecodeError)r    r0   rR   normalized_typestype_priorityr1   val	lower_valr#   r#   r$   r2      sV   $z1MinimaxM2Detector._convert_param_value_with_types
param_nameparam_configc                 C   s0   ||vrdgS || }t |tsdgS | |S )a<  
        Get parameter types from parameter configuration.
        Handles anyOf, oneOf, allOf, and direct type definitions.

        Args:
            param_name: The name of the parameter
            param_config: The properties dict from the tool schema

        Returns:
            List of type strings
        r5   )rA   rB   rJ   )r    rj   rk   param_schemar#   r#   r$   _get_param_types_from_config   s   

z.MinimaxM2Detector._get_param_types_from_confignew_textc                 C   s  |  j |7  _ d}g }t| ds| || _	 | js*| j| j vr*|| j 7 }d| _ n0| jsn| j | j}|dkrB|| j 7 }d| _ n|| j d | 7 }| j |d  | _ d| _d| _d| _i | _	i | _
| j t| jd  | _ q| jstd| j }|r|d }|| jv r|| _d| _| jdkrd| _t| j| jkr| ji  t| j| jkst| j| jkr| jd t| j| jks|i d	| j| j< |t| j|dd
 | j | d  | _ qtd|  |   || j 7 }d| _ nfne| jrY| | j |}|| | j| j v rX| j | j}	| j| j }
|
r>|
d}|
d}||kr>|t| jd dd
 |
d | j| j< | j |	t| j d  | _ | d |  jd7  _qnqt||dS )Nr   _tool_indicesTFz<invoke name=\"([^>]+)\">   r   name	arguments
tool_indexrs   
parameterszInvalid function name: {}r*   )r   hasattr_get_tool_indicesro   r   r   findr   r   r   r   lenr   searchgrouprb   current_tool_idprev_tool_call_arrappendstreamed_args_for_toolr	   endloggerwarning_reset_streaming_state_parse_and_stream_parametersextendr   countr   )r    rn   r)   r.   r,   sfunction_matchfunction_nameparameter_callsend_poscurrent_streamedopen_bracesclose_bracesr#   r#   r$   parse_streaming_increment   s   




	






vz+MinimaxM2Detector.parse_streaming_incrementtext_to_parsec              	   C   s  g }t td|tj}i }|D ]}|d }|d}| | j|||||< q|| jkr| j	| j
 }	| jspg }
| D ]\}}|
tj|dd dtj|dd  q>dd|
 }|t| j
d	|d
 || j	| j
< nHt| t| j  }|rg }|D ]}|| }|tj|dd dtj|dd  qdd| }|t| j
d	|d
 |	| | j	| j
< || _|| j| j
 d< |S )a  
        Parse complete parameter blocks from text and return any tool call items to emit.

        This method:
        1. Finds all complete <parameter> blocks
        2. Parses them into a dictionary
        3. Compares with current parameters and generates diff if needed
        4. Updates internal state

        Args:
            text_to_parse: The text to search for parameter blocks

        Returns:
            List of ToolCallItem objects to emit (may be empty)
        z-<parameter name=\"([^>]+)\">(.*?)</parameter>rq      F)ensure_asciiz: rx   z, Nru   rt   )rF   r   finditerr   r   rb   _parse_parameterr   r   r   r   itemsr   rc   dumpsjoinr	   rC   keysr   )r    r   r)   r,   param_matches
new_paramsmatchrj   param_valueprevious_args_jsonr   keyr0   json_fragmentnew_keyscontinuation_partsr#   r#   r$   r   e  sj   	



  
z.MinimaxM2Detector._parse_and_stream_parametersFstill_in_tool_callc                 C   s(   || _ d| _d| _i | _i | _d| _dS )z,Reset streaming state for the next tool callFr   N)r   r   r   r   r   current_tool_name_sent)r    r   r#   r#   r$   r     s   
z(MinimaxM2Detector._reset_streaming_statec           	      C   s   g }g }d}	 | | j|}|dkr|||d   n:||||  | | j|}|dkr:|||d   n|||t| j  }|t| j }|| || qd||fS )Nr   Trp   r   )r|   r   r   r   r}   r   _parse_blockr   )	r    r%   r)   normal_partsr,   cursorr   eblockr#   r#   r$   r-     s$   zMinimaxM2Detector._extractr   c              	   C   s&  g }| j |D ]}|d r|d n|d }d|vrq|d}|d |  }||d d  }i }	| j|D ]8}
|
d rB|
d n|
d }d|vrKq8|d}|d |  }||d d  dd}| |||||	|< q8||	d}z|| 	|| W q t
y   td| Y qw |S )Nr   rq   z">r   
rr   z invalid tool call for %s dropped)r   findallindexrb   r   lstriprstripr   r   parse_base_json	Exceptionr   r   )r    r   r)   resmtxtidxfnamebodyparamspmptxtpidxpnamepvalrawr#   r#   r$   r     s0   


zMinimaxM2Detector._parse_blockr   r   r   c           	      C   sd   i }|D ]!}|j j|kr%|j jd ur%|j j}t|tr%d|v r%|d } nq| ||}| ||S )N
properties)functionrs   rw   rA   rB   rm   r2   )	r    r   r   r   r)   rk   toolrw   r1   r#   r#   r$   r     s   z"MinimaxM2Detector._parse_parameterc                 C   s   dS )NFr#   r   r#   r#   r$   supports_structural_tag     z)MinimaxM2Detector.supports_structural_tagc                 C   s   t r'   )NotImplementedErrorr   r#   r#   r$   structure_info	  r   z MinimaxM2Detector.structure_info)F)__name__
__module____qualname____doc__r   rD   rG   r(   r   r   r   r/   r   r3   rF   rJ   r2   rB   rm   r   r	   r   r   r   r-   r   r   r   r
   r   __classcell__r#   r#   r!   r$   r      sh    <
L

 
\&	
r   )rc   loggingr   typingr   r   r   r   &sglang.srt.entrypoints.openai.protocolr   -sglang.srt.function_call.base_format_detectorr   #sglang.srt.function_call.core_typesr   r	   r
   	getLoggerr   r   r   r#   r#   r#   r$   <module>   s    
