o
    
۾i#                  
   @   s  d dl mZ d dlmZmZmZ d dlmZ d dl	m
Z
mZ d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dlmZ deee B de fddZ!dddddedB deee B dee dB dee dB fddZ"dedee dedB fddZ#dee dee fddZ$dedefd d!Z%d"ee de&e fd#d$Z'd%e(de(fd&d'Z)d"ee d(edee(eef  dB fd)d*Z*dS )+    )Any)#ChatCompletionAssistantMessageParam"ChatCompletionMessageToolCallParamChatCompletionToolMessageParam)Function)ResponseFunctionToolCallResponseOutputItem)
ToolChoice)"ResponseFunctionToolCallOutputItem)ResponseOutputMessage)ResponseReasoningItem)Tool)envs)
MCP_PREFIX)ChatCompletionMessageParam)ResponseInputOutputItemrequest_inputreturnc                 C   sv   t | trdS | sdS | d }t |tr|jdv S t |tr#|jdv S t |tr9|dddvr2dS |ddv S dS )a  
    Determine if the last input message is a partial assistant message
    that should be continued rather than starting a new generation.

    This enables partial message completion similar to Anthropic's Messages API,
    where users can provide an incomplete assistant message and have the model
    continue from where it left off.

    A message is considered partial if:
    1. It's a ResponseOutputMessage or ResponseReasoningItem
    2. Its status is "in_progress" or "incomplete"

    Args:
        request_input: The input to the Responses API request

    Returns:
        True if the final message should be continued, False otherwise
    F)in_progress
incompletetypemessage)r   	reasoningstatus)
isinstancestrr   r   r   dictget)r   	last_item r    [/home/ubuntu/.local/lib/python3.10/site-packages/vllm/entrypoints/openai/responses/utils.pyshould_continue_final_message   s   





r"   N)request_instructionsprev_msgprev_response_outputr#   r$   r%   c                 C   s   g }| r| d| d |d ur|| |d ur2|D ]}t|tr1|jD ]}| d|jd q%qt|trA| d|d |S t|}|| |S )Nsystemrolecontent	assistantuser)appendextendr   r   r)   textr   &construct_chat_messages_with_tool_call)r#   r   r$   r%   messagesoutput_itemr)   input_messagesr    r    r!   construct_input_messagesL   s2   



	
r3   itemr0   c                 C   s~   t | tr| jr| jtsdS t|dkrdS |d }|ddkr*|ddus,dS t| jt	| j
| jddd	g|d
< |S )zMany models treat MCP calls and reasoning as a single message.
    This function checks if the last message is a reasoning message and
    the current message is a tool callNr   r   r(   r*   r   name	argumentsfunctionidr8   r   
tool_calls)r   r   r:   
startswithr   lenr   r   call_idFunctionCallToolr6   r7   )r4   r0   last_messager    r    r!   &_maybe_combine_reasoning_and_tool_callw   s.   

rA   r2   c                 C   s<   g }| D ]}t ||}|dur||d< q|t| q|S )zThis function wraps _construct_single_message_from_response_item
    Because some chatMessages come from multiple response items
    for example a reasoning item and a MCP tool call are two response items
    but are one chat message
    Nr   )rA   r,   ,_construct_single_message_from_response_item)r2   r0   r4   maybe_combined_messager    r    r!   r/      s   

r/   c                 C   s   t | trtdt| jt| j| jdddgdS t | trId}| j	r&t
dt| jdkr4| jd	 j}n| jrDt| jdkrD| jd	 j}d|d
S t | trWd| jd	 jdS t | tretd| j| jdS t | tr~| ddkr~td| d| ddS | S )Nr*   r5   r8   r9   )r(   r;    z#Encrypted content is not supported.   r   )r(   r   r'   tool)r(   r)   tool_call_idr   function_call_outputoutputr>   )r   r   r   r   r>   r?   r6   r7   r   encrypted_content
ValueErrorr=   summaryr.   r)   r   r
   r   rI   r   r   )r4   reasoning_contentr    r    r!   rB      sR   




rB   toolsc                 C   sD   t  }| D ]}|jdkr|jtjv r||j q||j q|S )z7
    Extracts the tool types from the given tools.
    mcp)setr   server_labelr   #VLLM_GPT_OSS_SYSTEM_TOOL_MCP_LABELSadd)rN   
tool_typesrF   r    r    r!   extract_tool_types   s   
rU   rF   c                 C   s
   d| dS )z
    Convert a flat tool schema:
        {"type": "function", "name": "...", "description": "...", "parameters": {...}}
    into:
        {"type": "function", "function": {...}}
    r8   )r   r8   r    )rF   r    r    r!   ,convert_tool_responses_to_completions_format   s   rV   tool_choicec                 C   s*   | d u s|dkrd }|S dd | D }|S )Nnonec                 S   s   g | ]}t | qS r    )rV   
model_dump).0rF   r    r    r!   
<listcomp>  s    
z(construct_tool_dicts.<locals>.<listcomp>r    )rN   rW   
tool_dictsr    r    r!   construct_tool_dicts   s   r]   )+typingr   openai.types.chatr   r   r   9openai.types.chat.chat_completion_message_tool_call_paramr   r?   openai.types.responsesr   r   openai.types.responses.responser	   >openai.types.responses.response_function_tool_call_output_itemr
   .openai.types.responses.response_output_messager   .openai.types.responses.response_reasoning_itemr   openai.types.responses.toolr   vllmr   vllm.entrypoints.constantsr   0vllm.entrypoints.openai.chat_completion.protocolr   *vllm.entrypoints.openai.responses.protocolr   r   listboolr"   r3   rA   r/   rB   rP   rU   r   rV   r]   r    r    r    r!   <module>   sp   

1



+
"

3