
    kKj                       d Z ddlmZ ddlZddlZddlmZ ddlmZ ddl	m
Z
 ddlZe
rddlmZ e G d d	             Ze G d
 d             Ze G d d             ZddZddZdd	 	 	 	 	 	 	 	 	 ddZdd	 	 	 	 	 	 	 ddZy)zIClient utilities for discovering and downloading skills from MCP servers.    )annotationsN)	dataclass)Path)TYPE_CHECKING)Clientc                  0    e Zd ZU dZded<   ded<   ded<   y)SkillSummaryz8Summary information about a skill available on a server.strnamedescriptionuriN__name__
__module____qualname____doc____annotations__     i/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/fastmcp/utilities/skills.pyr	   r	      s    B
I	Hr   r	   c                  0    e Zd ZU dZded<   ded<   ded<   y)	SkillFilez(Information about a file within a skill.r
   pathintsizehashNr   r   r   r   r   r      s    2
I
I
Ir   r   c                  &    e Zd ZU dZded<   ded<   y)SkillManifestz-Full manifest of a skill including all files.r
   r   zlist[SkillFile]filesNr   r   r   r   r   r   #   s    7
Ir   r   c                b  K   | j                          d{   }g }|D ]  }t        |j                        }|j                  d      s*|j	                  d      s<|t        d      d }|j                  dd      d   }|j                  t        ||j                  xs d|              |S 7 w)	ax  List all available skills from an MCP server.

    Discovers skills by finding resources with URIs matching the
    `skill://{name}/SKILL.md` pattern.

    Args:
        client: Connected FastMCP client

    Returns:
        List of SkillSummary objects with name, description, and URI

    Example:
        ```python
        from fastmcp import Client
        from fastmcp.utilities.skills import list_skills

        async with Client("http://skills-server/mcp") as client:
            skills = await list_skills(client)
            for skill in skills:
                print(f"{skill.name}: {skill.description}")
        ```
    Nskill://z	/SKILL.md/   r    )r   r   r   )
list_resourcesr
   r   
startswithendswithlenrsplitappendr	   r   )client	resourcesskillsresourcer   	path_partr   s          r   list_skillsr0   +   s     . ++--IF(,,>>*%#,,{*CC
O-.I##C+A.DMM ( 4 4 :  M% .s   B/B-1B/	B/AB/c                4  K   d| d}| j                  |       d{   }|st        d|       |d   }t        |t        j                  j
                        r!	 t        j                  |j                        }nt        d|       	 t        |d   |d	   D cg c]  }t        |d
   |d   |d          c}      S 7 # t        j                  $ r}t        d|       |d}~ww xY wc c}w # t        t        f$ r}t        d|       |d}~ww xY ww)a  Get the manifest for a specific skill.

    Args:
        client: Connected FastMCP client
        skill_name: Name of the skill

    Returns:
        SkillManifest with file listing

    Raises:
        ValueError: If manifest cannot be read or parsed
    r!   z
/_manifestNz#Could not read manifest for skill: r   z!Invalid manifest JSON for skill: z&Unexpected manifest format for skill: skillr   r   r   r   )r   r   r   )r   r   z#Invalid manifest format for skill: )read_resource
ValueError
isinstancemcptypesTextResourceContentsjsonloadstextJSONDecodeErrorr   r   KeyError	TypeError)r+   
skill_namemanifest_uriresultcontentmanifest_dataefs           r   get_skill_manifestrF   W   sB     j\4L''55F>zlKLLQiG'39999:	V JJw||4M A*NOO	Tw' 'w//A qyqyqyI/
 	
 6 ## 	V@MNTUU	V
 i  T>zlKLRSSTsi   DC=DC ;DC2 C-
9C2  DC*C%%C**D-C2 2DDDDF	overwritec                 K   t        |      j                         j                         }||z  j                         }|j                  |      st	        d|d      |j                         r|st        d| d      t        | |       d{   }|j                  dd       |j                  D ]:  }t        |j                        j                         r(||j                  z  j                         }|j                  |      sWd| d	|j                   }| j                  |       d{   }	|	s|	d
   }
|j                  j                  dd       t        |
t        j                   j"                        r|j%                  |
j&                         t        |
t        j                   j(                        r0|j+                  t-        j.                  |
j0                               ;= |S 7 d7 ŭw)a  Download a skill and all its files to a local directory.

    Creates a subdirectory named after the skill containing all files.

    Args:
        client: Connected FastMCP client
        skill_name: Name of the skill to download
        target_dir: Directory where skill folder will be created
        overwrite: If True, overwrite existing skill directory. If False
            (default), raise FileExistsError if directory exists.

    Returns:
        Path to the downloaded skill directory

    Raises:
        ValueError: If skill cannot be found or downloaded
        FileExistsError: If skill directory exists and overwrite=False

    Example:
        ```python
        from fastmcp import Client
        from fastmcp.utilities.skills import download_skill

        async with Client("http://skills-server/mcp") as client:
            skill_path = await download_skill(
                client,
                "pdf-processing",
                "~/.claude/skills"
            )
            print(f"Downloaded to: {skill_path}")
        ```
    zSkill name z" would escape the target directoryz Skill directory already exists: z . Use overwrite=True to replace.NT)parentsexist_okr!   r"   r   )r   
expanduserresolveis_relative_tor4   existsFileExistsErrorrF   mkdirr   r   is_absoluter3   parentr5   r6   r7   r8   
write_textr;   BlobResourceContentswrite_bytesbase64	b64decodeblob)r+   r?   
target_dirrH   	skill_dirmanifest	file_info	file_pathfile_urirA   rB   s              r   download_skillr`      s    N j!,,.668Jj(113I ##J/;zn4VWXX ).yk :- -
 	
 (
;;H OOD4O0 ^^		++-/88:	''	2j\9>>*:;++H55) 	td; gsyy==>  .!?!?@!!&"2"27<<"@A 5 $8 E < 6s&   BG6G1B G6.G4/CG64G6c                  K   t        |        d{   }g }|D ]5  }	 t        | |j                  ||       d{   }|j                  |       7 |S 7 B7 # t        $ r Y Iw xY ww)aa  Download all available skills from a server.

    Args:
        client: Connected FastMCP client
        target_dir: Directory where skill folders will be created
        overwrite: If True, overwrite existing files

    Returns:
        List of paths to downloaded skill directories

    Example:
        ```python
        from fastmcp import Client
        from fastmcp.utilities.skills import sync_skills

        async with Client("http://skills-server/mcp") as client:
            paths = await sync_skills(client, "~/.claude/skills")
            print(f"Downloaded {len(paths)} skills")
        ```
    NrG   )r0   r`   r   r*   rP   )r+   rZ   rH   r-   
downloadedr2   r   s          r   sync_skillsrc      s{     4 v&&FJ	'

J) D d#   '
  		sB   A'AA'AAAA'A	A$!A'#A$$A')r+   r   returnzlist[SkillSummary])r+   r   r?   r
   rd   r   )
r+   r   r?   r
   rZ   
str | PathrH   boolrd   r   )r+   r   rZ   re   rH   rf   rd   z
list[Path])r   
__future__r   rW   r9   dataclassesr   pathlibr   typingr   	mcp.typesr6   fastmcp.clientr   r	   r   r   r0   rF   r`   rc   r   r   r   <module>rm      s    O "   !    %         )X%TZ XXX X
 X 
X~ 	''' 	'
 'r   