Ë
    A²Xjm+  ã                  ó  — d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	m
Z
 ddlmZmZ ddlmZ ddlZddlmZ e
rdd	lmZ d
gZdZ ej.                  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„Z dd„Z!y)zýSkill download + archive extraction for the agent toolset.

Split out from ``agent_toolset`` because fetching a session agent's skills and
safely unpacking a (possibly third-party) archive is a distinct concern from the
tool implementations themselves.
é    )ÚannotationsN)ÚTYPE_CHECKING)ÚPathÚPurePosixPath)Úpartial)Úrun_syncé   )ÚAsyncAnthropicÚdownload_session_skillsiÀ  z!anthropic.lib.tools.agent_toolsetc                óF   — 	 | j                  |«       y# t        $ r Y yw xY w)zJTrue if ``child`` is ``root`` or a path inside it (both already resolved).FT)Úrelative_toÚ
ValueError)ÚchildÚroots     úa/var/www/html/content_generation/venv/lib/python3.12/site-packages/anthropic/lib/tools/_skills.pyÚ_withinr   #   s.   € ðØ×Ñ˜$Ôð øô ò Ùðús   ‚ ”	 Ÿ c                óZ  — | j                  dd«      }|j                  d«      st        |«      j                  «       rt	        d| ›�«      ‚t        |«      j
                  D �cg c]
  }|dk7  sŒ	|‘Œ }}t        d„ |D «       «      rt	        d| ›�«      ‚|rt        t        |Ž «      S dS c c}w )u@  Return ``name`` as a confined relative path, or raise on path-traversal.

    Strips ``.`` components; rejects absolute paths and any ``..`` component
    outright (those only appear in malicious archives). Returns ``""`` for
    entries that resolve to nothing (e.g. ``"./"``) â€” the caller should skip
    those.
    Ú\Ú/z+refusing archive member with absolute path Ú.c              3  ó&   K  — | ]	  }|d k(  –— Œ y­w)ú..N© )Ú.0Úps     r   Ú	<genexpr>z$_safe_member_name.<locals>.<genexpr>8   s   è ø€ Ð
$™e˜ˆ1��9™eùs   ‚z-refusing archive member with '..' component: Ú )ÚreplaceÚ
startswithr   Úis_absoluter   ÚpartsÚanyÚstr)ÚnameÚnormr   r!   s       r   Ú_safe_member_namer&   ,   s§   € ð �<‰<˜˜cÓ"€DØ‡��sÔœ}¨TÓ2×>Ñ>Ô@ÜÐFÀtÀhÐOÓPÐPÜ% dÓ+×1Ò1Ó>Ñ1�1°Q¸#³XŠQÐ1€EÐ>Ü
Ñ
$™eÓ
$Ô$ÜÐHÈÈÐQÓRÐRÙ).Œ3Œ}˜eÐ$Ó%Ð6°BÐ6ùò ?s   Á"
B(Á-B(c                óî   — t        «       }d}| D ]?  }t        |«      j                  }|sŒ|j                  |d   «       t	        |«      dkD  sŒ>d}ŒA t	        |«      dk(  r|rt        t        |«      «      S dS )a¹  Return the single top-level directory shared by every archive entry, or
    ``""`` if the entries don't all live under one common directory.

    Skill bundles are packaged wrapped in one directory named after the skill
    (e.g. ``pdf/SKILL.md``, ``pdf/scripts/...``). The extractor strips that
    wrapper so the contents land directly in the skill's destination directory
    instead of a redundant nested ``<skill>/<skill>/`` level.
    Fr   é   Tr   )Úsetr   r!   ÚaddÚlenÚnextÚiter)ÚnamesÚtopsÚ
has_nestedÚnr!   s        r   Ú_archive_top_dirr2   =   sr   € ô “U€DØ€JÛˆÜ˜aÓ ×&Ñ&ˆÙØØ�‰��q‘ÔÜˆu‹:˜‹>Ø‰Jð ô  # 4›y¨Aš~±*Œ4”�T“
ÓÐDÀ"ÐDó    c                ó€   — |s| S t        | «      j                  }|r"|d   |k(  r|dd }|rt        t        |Ž «      S dS | S )z‹Drop the leading ``top`` component from ``safe`` (an already-confined
    relative path). Returns ``""`` for the bare top-dir entry itself.r   r(   Nr   )r   r!   r#   )ÚsafeÚtopr!   Úrests       r   Ú
_strip_topr8   R   sP   € ñ ØˆÜ˜$Ó×%Ñ%€EÙ��q‘˜S’Ø�Q�RˆyˆÙ,0Œs”= $Ð'Ó(Ð8°bÐ8Ø€Kr3   c                ó   — | dz  rdS dS )a  Reduce an archive entry's Unix mode to ``0o755`` if it is executable,
    ``0o644`` otherwise.

    Skill bundles can ship executable scripts (e.g. ``scripts/foo.sh``), so the
    execute bit recorded in the archive must survive extraction or invoking the
    script directly fails with permission denied. The mode is deliberately
    collapsed to one of two values: this preserves "is it executable" while
    never propagating setuid/setgid/sticky or group/other-write bits from a
    (possibly third-party) archive.
    éI   ií  i¤  r   )Úsrc_modes    r   Ú_archive_file_moder<   ^   s   € ð ˜uÒ$ˆ5Ð/¨%Ð/r3   c           	     ó�  — |j                  ddt        ¬«       |j                  «       }t        j                  | «      �rvt        j
                  | «      5 }|j                  «       }|D �cg c]  }t        |j                  «      x}sŒ|‘Œ }}t        |«      }|D �]  }t        t        |j                  «      |«      }	|	sŒ&||	z  j                  «       }
t        |
|«      st        d|j                  ›�«      ‚|j                  «       r|
j                  dd¬«       Œ�|
j                  j                  dd¬«       |j                  |«      5 }t        |
d«      5 }t!        j"                  ||«       ddd«       ddd«       t%        j&                  |
t)        |j*                  dz	  «      «       �Œ 	 ddd«       yt-        j                  | d¬	«      5 }|j/                  «       D �cg c]7  }|j1                  «       rŒ|j3                  «       rŒ%|j5                  «       rŒ6|‘Œ9 }}|D �cg c]  }t        |j6                  «      x}sŒ|‘Œ }}t        |«      }|D �]  }t        t        |j6                  «      |«      }	|	sŒ&||	z  j                  «       }
t        |
|«      st        d
|j6                  ›�«      ‚|j9                  «       r|
j                  dd¬«       Œ�|
j                  j                  dd¬«       |j;                  |«      }|€Œ²|5 }t        |
d«      5 }t!        j"                  ||«       ddd«       ddd«       t%        j&                  |
t)        |j<                  «      «       �Œ 	 ddd«       yc c}w # 1 sw Y   �Œ
xY w# 1 sw Y   �ŒxY w# 1 sw Y   yxY wc c}w c c}w # 1 sw Y   Œ|xY w# 1 sw Y   Œ€xY w# 1 sw Y   yxY w)a½  Extract a skill download (a zip or tar.* archive) from disk into ``dest``.

    Skill bundles are wrapped in a single directory named after the skill; that
    wrapper is stripped so files land directly under ``dest`` rather than a
    redundant ``dest/<skill>/`` level. Skills can be third-party, so this
    refuses any member that would escape ``dest`` (zip-slip / tar-slip) and
    skips symlink/hardlink/device members in tar archives.
    T©ÚparentsÚexist_okÚmodez&refusing to extract unsafe zip member )r?   r@   ÚwbNé   zr:*)rA   z&refusing to extract unsafe tar member )ÚmkdirÚ_SKILL_DIR_MODEÚresolveÚzipfileÚ
is_zipfileÚZipFileÚinfolistr&   Úfilenamer2   r8   r   r   Úis_dirÚparentÚopenÚshutilÚcopyfileobjÚosÚchmodr<   Úexternal_attrÚtarfileÚ
getmembersÚissymÚislnkÚisdevr$   ÚisdirÚextractfilerA   )Úarchive_pathÚdestr   ÚzfÚinfosÚinfoÚsÚ
safe_namesr6   r5   ÚtargetÚsrcÚoutÚtfÚmÚmembersÚmemberÚ	extracteds                     r   Ú_extract_skill_archiverj   l   s  € ð 	‡J�J�t d´€JÔAØ�<‰<‹>€Dä×Ñ˜,Õ'Ü�_‰_˜\Ô*¨bØ—K‘K“MˆEñ ).ÓY© Ô7HÈÏÉÓ7WÐ2W°!Ñ2Wš!¨ˆJÐYÜ" :Ó.ˆCÜ�Ü!Ô"3°D·M±MÓ"BÀCÓH�ÙØØ ™+×.Ñ.Ó0�Ü˜v tÔ,Ü$Ð'MÈdÏmÉmÐM^Ð%_Ó`Ð`Ø—;‘;”=Ø—L‘L¨¸�LÔ=ØØ—‘×#Ñ#¨D¸4Ð#Ô@Ø—W‘W˜T”] c¬4°¸Ô+=ÀÜ×&Ñ& s¨CÔ0÷ ,>—]ô —‘˜Ô!3°D×4FÑ4FÈ"Ñ4LÓ!MÖNñ ÷ +ð, 	ô 
�‰�l¨Õ	/°2Ø Ÿm™mœoÓ[™o˜°a·g±gµiÀ1Ç7Á7Å9ÐPQ×PWÑPWÕPY’1˜oˆÐ[Ù!(ÓM¡˜AÔ2CÀAÇFÁFÓ2KÐ-K¨QÑ-K’a ˆ
ÐMÜ˜zÓ*ˆÜˆFÜÔ/°·±Ó<¸cÓBˆDÙØØ˜T‘k×*Ñ*Ó,ˆFÜ˜6 4Ô(Ü Ð#IÈ&Ï+É+ÈÐ!YÓZÐZØ�|‰|Œ~Ø—‘ T°D�Ô9ØØ�M‰M×Ñ¨°tÐÔ<ØŸ™ vÓ.ˆIØÐ ØÙ˜c¤4¨°Ô#5¸Ü×"Ñ" 3¨Ô,÷ $6—ä�H‰H�VÔ/°·±Ó<Ö=ñ! ÷	 
0Ð	/ùò+ Z÷ ,>Ñ+=ú—]‘]ú÷# +ð, 	üò \ùÚM÷  $6Ð#5ú—�ú÷% 
0Ð	/úsÈ   ÁNÁ)M/ÂM/Â
B>NÅNÅM4	Å,NÅ47NÇN<ÇNÇ5NÈNÈNÈN<È!NÈ>NÉCN<ÌN0ÌN$	Ì)N0Ì14N<Í/NÍ4M>Í9NÎNÎNÎNÎ
N<Î$N-Î)N0Î0N9Î5N<Î<Oc              ƒ  ól  K  — |j                  «       r|S d}| j                  j                  j                  j	                  |«      2 3 d{  –—† }|j
                  j                  «       sŒ$|�"t        |j
                  «      t        |«      kD  sŒH|j
                  }ŒU7 ŒP6 |€t        d|›d|›d�«      ‚|S ­w)uN  Resolve ``version`` to the concrete numeric timestamp the
    ``/v1/skills/{id}/versions/{version}`` endpoints require.

    ``session.agent.skills[].version`` may be an alias such as ``"latest"``,
    which those endpoints reject â€” so list the skill's versions and pick the
    newest. Numeric versions are returned unchanged.
    Nzskill z$ has no concrete version to resolve z against)ÚisdigitÚbetaÚskillsÚversionsÚlistÚversionÚintr   )ÚclientÚskill_idrq   ÚnewestÚvs        r   Ú_resolve_skill_versionrw   ©   s¤   è ø€ ð ‡�ÔØˆØ€FØ—;‘;×%Ñ%×.Ñ.×3Ñ3°HÔ=÷ ˆaØ�9‰9×ÑÕ F N´c¸!¿)¹)³nÄsÈ6Ã{Ó6RØ—Y‘Y‰FðøÐ=ð €~Ü˜6 ( Ð-QÐRYÐQ\Ð\dÐeÓfÐfØ€Mùs6   ‚AB4ÁBÁ
BÁBÁB4Á*#B4ÂB4ÂBÂB4c             ƒ  óŠ  K  — | j                   j                  j                  |«      ƒ d{  –—† }t        t	        j                  |«      dz  j                  «       ƒ d{  –—† «      }g }|j                  j                  D �]ï  }	 t        | |j                  |j                  «      ƒ d{  –—† }| j                   j                  j                  j                  ||j                  ¬«      ƒ d{  –—† }t        j                  j                  |j                  j!                  «       «      xs |j                  }	|	dv r|j                  }	t        t	        j                  |«      |	z  j                  «       ƒ d{  –—† «      }
t#        |
|«      s"t$        j'                  d|j                  «       �Œ+t	        j                  |
«      }|j)                  «       ƒ d{  –—† r|j+                  «       ƒ d{  –—†  t-        t/        t0        j2                  |
d¬«      «      ƒ d{  –—†  t5        | |j                  ||
«      ƒ d{  –—†  |j7                  |
«       t$        j9                  d|j                  ||
«       �Œò |S 7 �ŒI7 �Œ7 �ŒÒ7 �Œ’7 �Œ7 Œ°7 Œš7 Œo7 ŒQ# t:        $ r,}t$        j'                  d	|j                  |«       Y d}~�Œ<d}~ww xY w­w)
a'  Download the session agent's skills into ``{workdir}/skills/<name>/``.

    Looks up the session's resolved agent, and for each skill fetches its files
    via ``client.beta.skills.versions.download`` and extracts the archive under a
    directory named after the skill. The archive is streamed to a temp file
    rather than buffered whole in memory. A failure on one skill is logged and
    does not block the others.

    Returns the list of skill directories that were created, so the caller can
    remove them when the workdir is torn down.
    Nrn   ©rt   )r   r   r   z.skill name %r escapes the skills dir; skippingT)Úignore_errorsz-downloaded skill skill_id=%s version=%s -> %sz(failed to download skill skill_id=%s: %s)rm   ÚsessionsÚretriever   ÚanyiorF   Úagentrn   rw   rt   rq   ro   rQ   ÚpathÚbasenamer$   Ústripr   ÚlogÚwarningÚ
is_symlinkÚunlinkr   r   rO   ÚrmtreeÚ_download_and_extractÚappendr_   Ú	Exception)rs   Ú
session_idÚworkdirÚsessionÚskills_rootÚ
downloadedÚskillÚ
version_idrq   Údirnamer\   ÚadestÚes                r   r   r   ¼   s  è ø€ ð  —K‘K×(Ñ(×1Ñ1°*Ó=×=€GÜœeŸj™j¨Ó1°HÑ<×EÑEÓG×GÓH€Kð  €JØ—‘×%Õ%ˆð	WÜ5°f¸e¿n¹nÈeÏmÉmÓ\×\ˆJØ"ŸK™K×.Ñ.×7Ñ7×@Ñ@ÀÐV[×VdÑVdÐ@Óe×eˆGô —g‘g×&Ñ& w§|¡|×'9Ñ'9Ó';Ó<ÒNÀÇÁˆGØ˜/Ñ)ØŸ.™.�ÜœuŸz™z¨+Ó6¸Ñ@×IÑIÓK×KÓLˆDÜ˜4 Ô-Ü—‘ÐLÈgÏlÉlÔ[ÙÜ—J‘J˜tÓ$ˆEØ×%Ñ%Ó'×'Ð'Ø—l‘l“n×$Ð$äœ7¤6§=¡=°$ÀdÔKÓL×LÐLÜ'¨°·±À
ÈDÓQ×QÐQØ×Ñ˜dÔ#Ü�H‰HÐDÀeÇnÁnÐV`ÐbfÖgð) &ð. Ðð9 >ùØGùð ]ùØeùð Lùð
 (øØ$øàLøØQùô ò 	WÜ�K‰KÐBÀEÇNÁNÐTU×VÒVûð	Wüs×   ‚)K«I4¬2KÁI7Á$KÂ$JÂ(I:Â)AJÃ+I=Ã,BJÅ3J 
Å44JÆ(KÆ*(JÇJÇJÇ*JÇ+,JÈJÈJÈ7J	È87JÉ/KÉ7KÉ:JÉ=JÊ JÊJÊJÊJÊ	JÊ	K Ê!J;Ê5KÊ;K Ë Kc              ƒ  ó,  K  — t        j                  |j                  «      j                  ddt        ¬«      ƒ d{  –—†  t        t        t        j                  dd|j                  ¬«      «      ƒ d{  –—† \  }}t        j                  |«       t        j                  |«      }	 | j                  j                  j                  j                  j                  ||¬«      4 ƒd{  –—† }|j!                  |«      ƒ d{  –—†  ddd«      ƒd{  –—†  t        t"        t        |«      |«      ƒ d{  –—†  |j%                  d¬«      ƒ d{  –—†  y7 �Œ7 Œß7 Œo7 ŒX7 ŒJ# 1 ƒd{  –—†7  sw Y   ŒZxY w7 Œ?7 Œ'# |j%                  d¬«      ƒ d{  –—†7   w xY w­w)	zGStream the skill archive to a temp file, then extract it into ``dest``.Tr>   Nz.skill-z.archive)ÚprefixÚsuffixÚdirry   )Ú
missing_ok)r}   r   rM   rD   rE   r   r   ÚtempfileÚmkstemprQ   Úcloserm   rn   ro   Úwith_streaming_responseÚdownloadÚstream_to_filerj   r…   )rs   rt   r�   r\   ÚfdÚtmp_nameÚtmpÚarchives           r   r‡   r‡   ë   sC  è ø€ ä
�*‰*�T—[‘[Ó
!×
'Ñ
'°¸tÌ/Ð
'Ó
Z×ZÐZÜ!¤'¬(×*:Ñ*:À9ÐU_Ðei×epÑepÔ"qÓr×r�L€BˆÜ‡H�HˆR„LÜ
�*‰*�XÓ
€Cð*Ø—;‘;×%Ñ%×.Ñ.×FÑF×OÑOØ ð P÷ 
ô 
àØ×(Ñ(¨Ó2×2Ð2÷
÷ 
ô
 Ô-¬t°H«~¸tÓD×DÐDà�j‰j DˆjÓ)×)Ñ)ð [ùØrøð
øð 3øð
ø÷ 
÷ 
ñ 
úð
 	Eøà)ùˆc�j‰j DˆjÓ)×)Ò)üs½   ‚9F»E¼7FÁ3EÁ41FÂ&?E4 Ã%EÃ&E4 Ã)EÃ>EÃ?EÄE4 ÄEÄ!E4 Ä0E0Ä1E4 Ä5FÅ
E2ÅFÅFÅE4 ÅEÅE4 ÅE-Å!E$Å"E-Å)E4 Å2FÅ4FÆ
FÆFÆF)r   r   r   r   ÚreturnÚbool)r$   r#   r£   r#   )r.   z	list[str]r£   r#   )r5   r#   r6   r#   r£   r#   )r;   rr   r£   rr   )r[   r   r\   r   r£   ÚNone)rs   r
   rt   r#   rq   r#   r£   r#   )rs   r
   rŠ   r#   r‹   zstr | os.PathLike[str]r£   z
list[Path])
rs   r
   rt   r#   r�   r#   r\   r   r£   r¥   )"Ú__doc__Ú
__future__r   rQ   rO   ÚloggingrT   rG   r™   Útypingr   Úpathlibr   r   Ú	functoolsr   r}   Úanyio.to_threadr   Ú_clientr
   Ú__all__rE   Ú	getLoggerr‚   r   r&   r2   r8   r<   rj   rw   r   r‡   r   r3   r   Ú<module>r°      s¨   ðñõ #ã 	Û Û Û Û Û Ý  ß 'Ý ã Ý $áÝ)à$Ð
%€ð €à€g×ÑÐ;Ó<€óó7ó"Eó*	ó0ó:>ózð&,Øð,Ø+.ð,Ø9Oð,àó,ô^*r3   