
    $jM                       d dl mZ d dlmZ d dlmZ d dlmZmZm	Z	m
Z
mZ d dl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 g dZ ee          Z  ede          Z! G d de          Z" G d deee!                   Z#e G d dee!                               Z$e G d d                      Z%	 	 d;d<dZ&d=d%Z'd>d'Z(d?d)Z)d@d,Z*dAd-Z+dAd.Z,dBd2Z-	 dCdDd7Z.dEd9Z/dFd:Z0dS )G    )annotations)	dataclass)Enum)AnyGenericLiteralcast
get_origin)CancelledElicitationDeclinedElicitation)	BaseModel)GenerateJsonSchemaJsonSchemaValue)core_schema)TypeVar)compress_schema)
get_logger)get_cached_typeadapter)AcceptedElicitationr   r   ElicitConfigScalarElicitationTypeget_elicitation_schemahandle_elicit_acceptparse_elicit_response_typeT)defaultc                  <     e Zd ZdZd fdZd fdZd fd
Z xZS )ElicitationJsonSchemaa5  Custom JSON schema generator for MCP elicitation that always inlines enums.

    MCP elicitation requires inline enum schemas without $ref/$defs references.
    This generator ensures enums are always generated inline for compatibility.
    Optionally adds enumNames for better UI display when available.
    schemacore_schema.CoreSchemareturnr   c                    |d         dk    r|                      |          S |d         dk    r|                     |          S t                                          |          S )zEOverride to prevent ref generation for enums and handle list schemas.typeenumlist)enum_schemalist_schemasupergenerate_innerselfr   	__class__s     b/home/rurouni/.hermes/hermes-agent/venv/lib/python3.11/site-packages/fastmcp/server/elicitation.pyr)   z$ElicitationJsonSchema.generate_inner,   se     &>V## ##F+++&>V####F+++ww%%f---    core_schema.ListSchemac                z   |                     d          }|rA|                     d          dk    r(|                     |          }d|v r
d|d         i}d|dS |r@t                                          |          }d|v sd|v sd|v rd|v r
d|d         i}d|dS t                                          |          S )	zFGenerate schema for list types, detecting enum items for multi-select.items_schemar#   r$   oneOfanyOfarrayr#   itemsconst)getr&   r(   r)   r'   )r+   r   r1   r6   items_resultr,   s        r-   r'   z!ElicitationJsonSchema.list_schema9   s   zz.11  		L,,V44>>$$\22E% %.1    	 7711,??L <''\))l** l**$+\'-B#CL#)   ww""6***r.   core_schema.EnumSchemac                F    t                                          |          S )zGenerate inline enum schema.

        Always generates enum pattern: `{"enum": [value, ...]}`
        Titled enums are handled separately via dict-based syntax in ctx.elicit().
        )r(   r&   r*   s     r-   r&   z!ElicitationJsonSchema.enum_schema^   s     ww""6***r.   )r   r    r!   r   )r   r/   r!   r   )r   r:   r!   r   )__name__
__module____qualname____doc__r)   r'   r&   __classcell__)r,   s   @r-   r   r   $   s         . . . . . .#+ #+ #+ #+ #+ #+J+ + + + + + + + + +r.   r   c                  ,    e Zd ZU dZdZded<   ded<   dS )r   z)Result when user accepts the elicitation.acceptzLiteral['accept']actionr   dataN)r<   r=   r>   r?   rC   __annotations__ r.   r-   r   r   i   s0         33 (F((((GGGGGr.   r   c                      e Zd ZU ded<   dS )r   r   valueN)r<   r=   r>   rE   rF   r.   r-   r   r   p   s         HHHHHr.   r   c                  2    e Zd ZU dZded<   ded<   ded<   dS )	r   a  Configuration for an elicitation request.

    Attributes:
        schema: The JSON schema to send to the client
        response_type: The type to validate responses with (None for raw schemas)
        is_raw: True if schema was built directly (extract "value" from response)
    dict[str, Any]r   ztype | Noneresponse_typeboolis_rawN)r<   r=   r>   r?   rE   rF   r.   r-   r   r   u   s=           LLLLLr.   r   NrK   r   response_title
str | Noneresponse_descriptionr!   c                   |dup|du}| &|rt          d          t          di ddd          S t          | t                    rt	          |           }nt          | t
                    rt          |           }nut          |           t
          u rt          |           }nOt          |           rt          |           }n0|rt          d          t          t          |           | d          S |rt          |j        ||           |S )a  Parse response_type into schema and handling configuration.

    Supports multiple syntaxes:
    - None: Empty object schema, expect empty response
    - dict: `{"low": {"title": "..."}}` -> single-select titled enum
    - list patterns:
        - `[["a", "b"]]` -> multi-select untitled
        - `[{"low": {...}}]` -> multi-select titled
        - `["a", "b"]` -> single-select untitled
    - `list[X]` type annotation: multi-select with type
    - Scalar types (bool, int, float, str, Literal, Enum): single value
    - Other types (dataclass, BaseModel): use directly

    The ``response_title`` and ``response_description`` arguments customize the
    label and description of the wrapped ``value`` property for the scalar/dict/list
    shorthand forms. They are only valid when FastMCP is wrapping the response
    type; passing them with a full BaseModel/dataclass (or ``None``) raises
    ``TypeError``, because in those cases the user already controls field
    metadata via ``Field(title=..., description=...)``.
    Nzresponse_title and response_description are not supported when response_type is None, because the elicitation schema has no fields to label.object)r#   
propertiesFr   rK   rM   zresponse_title and response_description are only supported when response_type is a scalar, Literal, Enum, or the dict/list shorthand forms. For BaseModel or dataclass response types, use Field(title=..., description=...) on the individual fields.)	TypeErrorr   
isinstancedict_parse_dict_syntaxr%   _parse_list_syntaxr
   _parse_generic_list_is_scalar_type_parse_scalar_typer   _apply_value_metadatar   )rK   rN   rP   has_response_metadataconfigs        r-   r   r      sc   4 	d"F&:$&F    	#  
 $B77
 
 
 	
 -&& 
#M22	M4	(	( 
#M22	M	"	"d	*	*$]33		'	' 
#M22 ! 	N   )-88'
 
 
 	
  Sfm^=QRRRMr.   r   rJ   titledescriptionNonec                    |                      di                                d          }|dS |||d<   |||d<   dS dS )zFOverride title/description on the wrapped ``value`` property in-place.rS   rH   Nr`   ra   )r8   )r   r`   ra   value_schemas       r-   r]   r]      s^     ::lB//33G<<L %W&1]### r.   rL   c                    | t           t          t          t          hv p?t	          |           t
          u p)t          | t                    ot          | t                    S )z<Check if response_type is a scalar type that needs wrapping.)
rL   intfloatstrr
   r   rV   r#   
issubclassr   )rK   s    r-   r[   r[      sR     	$UC00 	Qm$$/	Q}d++O
=$0O0Or.   dc                x    | st          d          t          | d          }t          dd|idgddd	          S )
zEParse dict syntax: {"low": {"title": "..."}} -> single-select titled.z#Dict response_type cannot be empty.Fmulti_selectrR   rH   r#   rS   requiredNTrT   )
ValueError_dict_to_enum_schemar   )rj   r&   s     r-   rX   rX      se     @>???&qu===K"K0 	
 

    r.   lst	list[Any]c                   t          |           dk    rft          | d         t                    rK| d         rCt          d | d         D                       r$t	          dddd| d         ididgd	d
d          S t          |           dk    rVt          | d         t
                    r;| d         r3t          | d         d          }t	          ddd|didgd	d
d          S | r}t          d | D                       rdt          t          t                   t          t          |                              }t          |         }t	          t          |          |d          S t          d|            )z0Parse list patterns: [[...]], [{...}], or [...].   r   c              3  @   K   | ]}t          |t                    V  d S NrV   rh   .0items     r-   	<genexpr>z%_parse_list_syntax.<locals>.<genexpr>   s,      99$
4%%999999r.   rR   rH   r4   r$   r5   rn   NTrT   rl   c              3  @   K   | ]}t          |t                    V  d S rw   rx   ry   s     r-   r|   z%_parse_list_syntax.<locals>.<genexpr>  s,      99T:dC((999999r.   Fz-Invalid list response_type format. Received: )lenrV   r%   allr   rW   rq   r	   r#   r   r   tupler   r   rp   )rr   r&   choice_literalwrappeds       r-   rY   rY      s    	CAs1vt$$ 	F 	 99#a&99999 	
  &FCPQFCS(T(TU$I 
 
 
 
 	
 3xx1}}CFD11}c!f}*3q6EEE &;(O(OP$I 
 
 
 
 	
  	
s99S99999 	
 %)cGE#JJ4G$H$H'7)'22!
 
 
 	
 JSJJ
K
KKr.   c                Z    t           |          }t          t          |          |d          S )z.Parse list[X] type annotation -> multi-select.FrT   r   r   r   rK   r   s     r-   rZ   rZ   !  4    #M2G%g..   r.   c                Z    t           |          }t          t          |          |d          S )z:Parse scalar types (bool, int, float, str, Literal, Enum).FrT   r   r   s     r-   r\   r\   +  r   r.   r_   contentAcceptedElicitation[Any]c                $   | j         rIt          |t                    rd|vrt          d          t	          t
                   |d                   S | j        yt          | j                  }|                    |          }t          |t                    r t	          t
                   |j
                  S t	          t
                   |          S |rt          d|           t	          t          t          t
          f                  i           S )a  Handle an accepted elicitation response.

    Args:
        config: The elicitation configuration from parse_elicit_response_type
        content: The response content from the client

    Returns:
        AcceptedElicitation with the extracted/validated data
    rH   z4Elicitation response missing required 'value' field.)rD   Nz6Elicitation expected an empty response, but received: )rM   rV   rW   rp   r   r   rK   r   validate_pythonr   rH   rh   )r_   r   type_adaptervalidated_datas       r-   r   r   5  s    } ?'4(( 	UG7,B,BSTTT"3'WW-=>>>> '-f.BCC%55g>>n&;<< 	G&s+1EFFFF"3'^<<<<  
NWNN
 
 	
 tCH~.B7777r.   F	enum_dictdict[str, dict[str, str]]rm   c                    |rdnd}g }|                                  D ]3\  }}|                    d|          }|                    ||d           4||i}|sd|d<   |S )a~  Convert dict enum to SEP-1330 compliant schema pattern.

    Args:
        enum_dict: {"low": {"title": "Low Priority"}, "medium": {"title": "Medium Priority"}}
        multi_select: If True, use anyOf pattern; if False, use oneOf pattern

    Returns:
        {"type": "string", "oneOf": [...]} for single-select
        {"anyOf": [...]} for multi-select (used as array items)
    r3   r2   r`   )r7   r`   stringr#   )r6   r8   append)r   rm   pattern_keypatternrH   metadatar`   results           r-   rq   rq   W  s     *6''wKG$??,, 9 9xWe,,778888)73F "!vMr.   type[T]c                    t          |                               t                    }t          |          }t	          |           |S )zkGet the schema for an elicitation response.

    Args:
        response_type: The type of the response
    )schema_generator)r   json_schemar   r    validate_elicitation_json_schema)rK   r   s     r-   r   r   p  sM     $M22>>. ?  F V$$F %V,,,Mr.   c                   h d}|                      d          dk    r&t          d|                      d           d          |                      di           }|                                D ]g\  }}|                     d          }t          |t                    r,d|v r'd |D             }t          |          d	k    r|d
         }n|                     dd          rsd|v rxd|v r}d|v r|d         }|                    d          rS|dd         }|                      di                                |i           }d|v r|                     d          }	|	|v rt          d| d| d          d|v sd|v ro|                     dg           |                     dg           z   }
|
D ]=}d|v sd|v r|                     d          }||vrt          d| d| d| d          >~|dk    r|                     di           }|                     d          dk    rt          d| d          d|v rd|v sd|v rJ|                     dg           |                     dg           z   }
|
rt          d |
D                       rt          d| d           |dk    rt          d| d!          ||vrt          d| d"| d| d          idS )#aa  Validate that a JSON schema follows MCP elicitation requirements.

    This ensures the schema is compatible with MCP elicitation requirements:
    - Must be an object schema
    - Must only contain primitive field types (string, number, integer, boolean)
    - Must be flat (no nested objects or arrays of objects)
    - Allows const fields (for Literal types) and enum fields (for Enum types)
    - Only primitive types and their nullable variants are allowed

    Args:
        schema: The JSON schema to validate

    Raises:
        TypeError: If the schema doesn't meet MCP elicitation requirements
    >   numberr   booleanintegerr#   rR   z7Elicitation schema must be an object schema, got type 'zR'. Elicitation schemas are limited to flat objects with primitive properties only.rS   nullc                    g | ]
}|d k    |S )r   rF   )rz   ts     r-   
<listcomp>z4validate_elicitation_json_schema.<locals>.<listcomp>  s    AAA1Q&[[Q[[[r.   ru   r   nullableFr7   r$   z$refz#/$defs/   Nz$defszElicitation schema field 'z' contains a reference 'z\' that could not be validated. Only references to enum types or primitive types are allowed.r2   r3   z' has union type 'z&' which is not a primitive type. Only z$ are allowed in elicitation schemas.r4   r6   z' is an array of objects, but arrays of objects are not allowed. Elicitation schemas must be flat objects with primitive properties only.c              3     K   | ]}d |v V  	dS )r7   NrF   )rz   ss     r-   r|   z3validate_elicitation_json_schema.<locals>.<genexpr>  s&      (M(M!A(M(M(M(M(M(Mr.   z' is an array, but arrays are only allowed when items are enums (for multi-select). Only enum arrays are supported in elicitation schemas.z|' is an object, but nested objects are not allowed. Elicitation schemas must be flat objects with primitive properties only.z' has type ')r8   rU   r6   rV   r%   r~   
startswithr   )r   ALLOWED_TYPESrS   	prop_nameprop_schema	prop_typeref_pathdef_nameref_defref_typeunion_schemasunion_schema
union_typer1   s                 r-   r   r     s     ?>>M zz&X%%^fjjQWFXFX ^ ^ ^
 
 	

 L"--J","2"2"4"4 ^ ^	;OOF++	 i&& 	""AA	AAA	y>>Q&& )!I__Z// 	 k!! [   [  "6*H"":.. 	#ABB< **Wb1155hCCW$$";;v..},,mY m mPX m m m   k!!W%;%;'OOGR88;??7TV;W;WWM - 	 	l**f.D.D)--f55
]22#fY f fR\ f f2?f f f   3
  &??7B77L''833_ _ _ _   %% ,&&'\*A*A , 0 0" = =@P@PRA A ! ! S(M(M}(M(M(M%M%M  rY r r r     [Y [ [ [   M))^Y ^ ^I ^ ^*7^ ^ ^   *u^ ^r.   )NN)rK   r   rN   rO   rP   rO   r!   r   )r   rJ   r`   rO   ra   rO   r!   rb   )rK   r   r!   rL   )rj   rJ   r!   r   )rr   rs   r!   r   )rK   r   r!   r   )r_   r   r   r   r!   r   )F)r   r   rm   rL   r!   rJ   )rK   r   r!   rJ   )r   rJ   r!   rb   )1
__future__r   dataclassesr   r$   r   typingr   r   r   r	   r
   mcp.server.elicitationr   r   pydanticr   pydantic.json_schemar   r   pydantic_corer   typing_extensionsr   fastmcp.utilities.json_schemar   fastmcp.utilities.loggingr   fastmcp.utilities.typesr   __all__r<   loggerr   r   r   r   r   r   r]   r[   rX   rY   rZ   r\   r   rq   r   r   rF   r.   r-   <module>r      s,   " " " " " " ! ! ! ! ! !       : : : : : : : : : : : : : :              D D D D D D D D % % % % % % % % % % % % 9 9 9 9 9 9 0 0 0 0 0 0 : : : : : :	 	 	 
H		GCA+ A+ A+ A+ A+. A+ A+ A+J    )WQZ        GAJ             "&'+C C C C CL2 2 2 2       ,L ,L ,L ,L^      8 8 8 8F @E    2   &y y y y y yr.   