
    iE                       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Z&d$dZ'd%dZ(d&dZ)d#dZ*d#dZ+	 	 	 	 	 	 d'dZ,	 d(	 	 	 	 	 d)dZ-d*d Z.d+d!Z/y"),    )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.
    c                    |d   dk(  r| j                  |      S |d   dk(  r| j                  |      S t        |   |      S )zEOverride to prevent ref generation for enums and handle list schemas.typeenumlist)enum_schemalist_schemasupergenerate_innerselfschema	__class__s     j/Users/bowang/.openclaw/workspace/ChatDev/.venv/lib/python3.12/site-packages/fastmcp/server/elicitation.pyr&   z$ElicitationJsonSchema.generate_inner,   sQ     &>V# ##F++&>V###F++w%f--    c                   |j                  d      }|r5|j                  d      dk(  r!| j                  |      }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)   r.   r3   items_resultr*   s        r+   r$   z!ElicitationJsonSchema.list_schema9   s    zz.1 L,,V4>$$\2E% %.1   71,?L <'\)l* l*$+\'-B#CL#)  w"6**r,   c                "    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     w"6**r,   )r)   zcore_schema.CoreSchemareturnr   )r)   zcore_schema.ListSchemar8   r   )r)   zcore_schema.EnumSchemar8   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<   y)r   z)Result when user accepts the elicitation.acceptzLiteral['accept']actionr   dataN)r9   r:   r;   r<   r@   __annotations__ r,   r+   r   r   i   s    3 (F(
Gr,   r   c                      e Zd ZU ded<   y)r   r   valueN)r9   r:   r;   rB   rC   r,   r+   r   r   p   s    Hr,   r   c                  0    e Zd ZU dZded<   ded<   ded<   y)	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)r9   r:   r;   r<   rB   rC   r,   r+   r   r   u   s     Lr,   r   c                &   | t        di ddd      S t        | t              rt        |       S t        | t              rt        |       S t        |       t        u rt        |       S t        |       rt        |       S t        t        |       | d      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
    Nobject)r    
propertiesFr)   rH   rJ   )r   
isinstancedict_parse_dict_syntaxr"   _parse_list_syntaxr
   _parse_generic_list_is_scalar_type_parse_scalar_typer   rH   s    r+   r   r      s     $B7
 	
 -&!-00-&!-00- D("=11}%!-00 %m4# r,   c                    | t         t        t        t        hv xs5 t	        |       t
        u xs" t        | t              xr t        | t              S )z<Check if response_type is a scalar type that needs wrapping.)
rI   intfloatstrr
   r   rO   r    
issubclassr   rV   s    r+   rT   rT      sI     	$UC00 	Qm$/	Q}d+O
=$0Or,   c                `    | 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_selectrL   rE   r    rM   requiredNTrN   )
ValueError_dict_to_enum_schemar   )dr#   s     r+   rQ   rQ      sG    >??&qu=K"K0 	

  r,   c                    t        |       dk(  rJt        | d   t              r7| d   r2t        d | d   D              rt	        dddd| d   ididgd	d
d      S t        |       dk(  r@t        | d   t
              r-| d   r(t        | d   d      }t	        ddd|didgd	d
d      S | rYt        d | D              rGt        t        t           t        t        |                }t        |   }t	        t        |      |d      S t        d|        )z0Parse list patterns: [[...]], [{...}], or [...].   r   c              3  <   K   | ]  }t        |t                y wNrO   rZ   .0items     r+   	<genexpr>z%_parse_list_syntax.<locals>.<genexpr>   s     9&$
4%&   rL   rE   r1   r!   r2   r_   NTrN   r]   c              3  <   K   | ]  }t        |t                y wrg   rh   ri   s     r+   rl   z%_parse_list_syntax.<locals>.<genexpr>   s     9ST:dC(Srm   Fz-Invalid list response_type format. Received: )lenrO   r"   allr   rP   rb   r	   r    r   r   tupler   r   ra   )lstr#   choice_literalwrappeds       r+   rR   rR      s5    	CAs1vt$F9#a&99 &FCPQFCS(TU$I
 
 	
 3x1}CFD1c!f*3q6E &;(OP$I
 
 	
 s9S99 %)cGE#J4G$H'7)'2!
 	
 DSEJ
KKr,   c                B    t         |    }t        t        |      |d      S )z.Parse list[X] type annotation -> multi-select.FrN   r   r   r   rH   rt   s     r+   rS   rS      '    #M2G%g. r,   c                B    t         |    }t        t        |      |d      S )z:Parse scalar types (bool, int, float, str, Literal, Enum).FrN   rv   rw   s     r+   rU   rU      rx   r,   c                   | j                   r5t        |t              rd|vrt        d      t	        t
           |d         S | j                  ft        | j                        }|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
    rE   z4Elicitation response missing required 'value' field.)rA   z6Elicitation expected an empty response, but received: )rJ   rO   rP   ra   r   r   rH   r   validate_pythonr   rE   rZ   )configcontenttype_adaptervalidated_datas       r+   r   r   	  s     }}'4(G7,BSTT"3'WW-=>> '-f.B.BC%55g>n&;<&s+1E1EFF"3'^<< DWIN
 	
 tCH~.B77r,   c                    |rdnd}g }| j                         D ]+  \  }}|j                  d|      }|j                  ||d       - ||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)
    r0   r/   title)r4   r   stringr    )r3   r5   append)	enum_dictr^   pattern_keypatternrE   metadatar   results           r+   rb   rb   +  se     *'wKG$??,xWe,78 - *73F!vMr,   c                p    t        |       j                  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)rH   r)   s     r+   r   r   D  s<     $M2>>. ? F V$F %V,Mr,   c                   h d}| j                  d      dk7  rt        d| j                  d       d      | j                  di       }|j                         D ]  \  }}|j                  d      }t        |t              r-d|v r<|D cg c]
  }|dk7  s	| }}t        |      dk(  r|d	   }n|j                  d
d      rhd|v rmd|v rrd|v rj|d   }|j                  d      rB|dd }| j                  di       j                  |i       }	d|	v r|	j                  d      }
|
|v rt        d| d| d      d|v sd|v ra|j                  dg       |j                  dg       z   }|D ]5  }d|v sd|v r|j                  d      }||vs"t        d| d| d| d       I|dk(  r|j                  di       }|j                  d      dk(  rt        d| d      d|v rd|v sd|v r;|j                  dg       |j                  dg       z   }|rt        d |D              rt        d| d      |dk(  rt        d| d       ||vst        d| d!| d| d       yc c}w )"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    rL   z7Elicitation schema must be an object schema, got type 'zR'. Elicitation schemas are limited to flat objects with primitive properties only.rM   nullre   r   nullableFr4   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.r/   r0   z' has union type 'z&' which is not a primitive type. Only z$ are allowed in elicitation schemas.r1   r3   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  
 yw)r4   NrC   )rj   ss     r+   rl   z3validate_elicitation_json_schema.<locals>.<genexpr>  s     (M}!A}s   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 ')r5   	TypeErrorr3   rO   r"   ro   
startswithrp   )r)   ALLOWED_TYPESrM   	prop_nameprop_schema	prop_typetref_pathdef_nameref_defref_typeunion_schemasunion_schema
union_typer.   s                  r+   r   r   W  sV     ?M zz&X%EfjjQWFXEY Z^ ^
 	

 L"-J","2"2"4	;OOF+	 i&"(1A	1Q&[Q		Ay>Q& )!I__Z/ k! [  [ "6*H"":.#AB< **Wb155hCW$";;v.},,YK7OPXz Zm m  k!W%;'OOGR8;??7TV;WWM -l*f.D)--f5
]2#4YK?QR\Q] ^22?@df  !.  &??7B7L'830 <_ _  % ,&'\*A , 0 0" =@P@PRA ! !S(M}(M%M ,YK 8r r   ,YK 8[ [  M),YK|I; O**78\^ w #5 Bs   	
I%I%N)rH   r   r8   r   )rH   r   r8   rI   )rc   rG   r8   r   )rr   z	list[Any]r8   r   )r|   r   r}   r   r8   zAcceptedElicitation[Any])F)r   zdict[str, dict[str, str]]r^   rI   r8   rG   )rH   ztype[T]r8   rG   )r)   rG   r8   None)0
__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__r9   loggerr   r   r   r   r   r   rT   rQ   rR   rS   rU   r   rb   r   r   rC   r,   r+   <module>r      s   " !  : :  D % % 9 0 :	 
H	CA+. A+J)WQZ  GAJ     &R ,L^88#&88F @E(8<2&yr,   