§
    ÚŽ’j¤2  ã                   óÂ   — d 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	m
Z
 ddlmZmZ dd	lmZmZ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  G d„ de	¦  «        ZdS )zThe write tool in agentscope.é    N)ÚPath)ÚAnyÚListé   )ÚToolBaseÚToolMiddlewareBase)ÚDEFAULT_DANGEROUS_FILESÚDEFAULT_DANGEROUS_DIRECTORIESé   )ÚPermissionContextÚPermissionDecisionÚPermissionBehaviorÚPermissionModeÚPermissionRule)Ú	ToolChunk)Ú	TextBlockÚToolResultState)Ú
AgentStateé   )ÚBackendBasec                   ó²  ‡ — e Zd ZU dZd Zeed<   	 dZeed<   	 ddddœdd	dœd
œddgdœZe	ee
f         ed<   dZeed<   dZeed<   dZeed<   dZeed<   dZeed<   eeddfdee         dee         dee         dz  dedz  ddf
ˆ fd„Zde	ee
f         dedefd„Zd edz  de	ee
f         defd!„Zde	ee
f         dee         fd"„Z	 d%deded#edz  defd$„Z ˆ xZ!S )&ÚWritezThe write tool.Únamean  Writes a file to the local filesystem.

Usage:
- This tool will overwrite the existing file if there is one at the provided path.
- If this is an existing file, you MUST use the Read tool first to read the file's contents. This tool will fail if you did not read the file first.
- ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.
- NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.
- Only use emojis if the user explicitly requests it. Avoid writing emojis to files unless asked.ÚdescriptionÚobjectÚstringzGThe absolute path to the file to write (must be absolute, not relative))Útyper   z The content to write to the file)Ú	file_pathÚcontentr   r   )r   Ú
propertiesÚrequiredÚinput_schemaFÚis_mcpÚis_read_onlyÚis_concurrency_safeÚis_external_toolTÚis_state_injectedNÚdangerous_filesÚdangerous_directoriesÚmiddlewaresÚbackendÚreturnc                 óÊ   •— ddl m} t          ¦   «                              |¬¦  «         t	          |¦  «        | _        t	          |¦  «        | _        |p	 |¦   «         | _         dS )a‡  Initialize the write tool.

        Args:
            dangerous_files (`list[str]`, optional):
                Sensitive files that require explicit user confirmation,
                even in BYPASS mode. Matched by basename
                (case-insensitive). Defaults to `DEFAULT_DANGEROUS_FILES`.
                Pass a custom list to fully replace the defaults, or `[]`
                to disable the filename check.
            dangerous_directories (`list[str]`, optional):
                Sensitive directories that require explicit user
                confirmation. Matched when any path segment equals an
                entry (case-insensitive). Defaults to
                `DEFAULT_DANGEROUS_DIRECTORIES`. Pass a custom list to
                fully replace the defaults, or `[]` to disable the
                directory check.
            middlewares (`List[ToolMiddlewareBase] | None`, optional):
                Tool middlewares wrapping the tool execution.
            backend (`BackendBase | None`, optional):
                The sandbox backend to use for file I/O. When ``None``,
                a :class:`LocalBackend` is created.
        r   )ÚLocalBackend)r*   N)Ú_backendr.   ÚsuperÚ__init__Úlistr(   r)   )Úselfr(   r)   r*   r+   r.   Ú	__class__s         €úMC:\Projects\DSCons\.venv\Lib\site-packages\agentscope\tool\_builtin\_write.pyr1   zWrite.__init__A   si   ø€ ð: 	+Ð*Ð*Ð*Ð*Ð*å‰Œ×Ò [ÐÑ1Ô1Ð1Ý# OÑ4Ô4ˆÔÝ%)Ð*?Ñ%@Ô%@ˆÔ"àÐ1 < <¡>¤>ˆŒˆˆó    Ú
tool_inputÚcontextc              ƒ   ó´  K  — |                      d¦  «        }|st          t          j        d¬¦  «        S |                      |¦  «        r t          t          j        d|› �dd¬¦  «        S |j        t          j        t          j	        fv r6|  
                    ||¦  «        r t          t          j        d|› d	�d
¬¦  «        S t          t          j        d¬¦  «        S )a}  Check permissions for file writing.

        This method implements Write-specific permission checks:
        1. Dangerous path check (safety check, bypass-immune)
        2. ACCEPT_EDITS mode check for files in working directories

        Args:
            tool_input (`dict[str, Any]`):
                The tool input containing "file_path" key
            context (`PermissionContext`):
                The permission context with mode and rules

        Returns:
            `PermissionDecision`:
                ASK for dangerous paths, ALLOW for safe operations in
                ACCEPT_EDITS mode, PASSTHROUGH otherwise
        r   zNo file path provided)ÚbehaviorÚmessagez7Permission required: Write operation on sensitive file z)Safety check: dangerous file or directoryT)r:   r;   Údecision_reasonÚbypass_immunezPermission granted for writing z (in working directory)z5File is in working directory and not a dangerous path)r:   r;   r<   Ú )Úgetr   r   ÚPASSTHROUGHÚ_is_dangerous_pathÚASKÚmoder   ÚACCEPT_EDITSÚDONT_ASKÚ_path_in_allowed_working_pathÚALLOW)r3   r7   r8   r   s       r5   Úcheck_permissionszWrite.check_permissionsf   s$  è è € ð. —N’N ;Ñ/Ô/ˆ	Øð 	Ý%Ý+Ô7Ø/ðñ ô ð ð ×"Ò" 9Ñ-Ô-ð 	Ý%Ý+Ô/ð.Ø"+ð.ð .à KØ"ðñ ô ð ð Œ<ÝÔ'ÝÔ#ð
ð 
ð 
ð ×1Ò1°)¸WÑEÔEð Ý)Ý/Ô5ð.¸ið .ð .ð .ð%'ð	ñ ô ð õ "Ý'Ô3Øð
ñ 
ô 
ð 	
r6   Úrule_contentc              ƒ   ól   K  — |€dS |                      dd¦  «        }|sdS t          j        ||¦  «        S )a‹  Check if a permission rule matches the file path.

        Matches rule_content as a glob pattern against the "file_path"
        parameter using fnmatch. If rule_content is None, matches all
        invocations (tool-name-level rule).

        Args:
            rule_content (`str | None`):
                Glob pattern to match against the file path (e.g., "src/**"),
                or None to match all invocations
            tool_input (`dict[str, Any]`):
                The tool input data containing "file_path" key

        Returns:
            `bool`:
                True if the glob pattern matches the file path, False otherwise
        NTr   r>   F)r?   Úfnmatch)r3   rI   r7   r   s       r5   Ú
match_rulezWrite.match_rule¦   sE   è è € ð, ÐØ�4à—N’N ;°Ñ3Ô3ˆ	Øð 	Ø�5ÝŒ˜y¨,Ñ7Ô7Ð7r6   c              ƒ   óì   K  — |                      dd¦  «        }|sg S | j                             |¦  «        }|r|                     d¦  «        dz   nd}t	          | j        |t          j        d¬¦  «        gS )a  Generate suggested permission rules for the file path.

        Suggests a glob pattern covering the parent directory of the file,
        allowing the user to grant permission for the entire directory at once.

        Args:
            tool_input (`dict[str, Any]`):
                The tool input data containing "file_path" key

        Returns:
            `List[PermissionRule]`:
                A single suggested rule covering the parent directory
                (e.g., file "/src/main.py" -> rule "src/**")
        r   r>   z/\z/**z**Ú	suggested)Ú	tool_namerI   r:   Úsource)r?   r/   ÚdirnameÚrstripr   r   r   rG   )r3   r7   r   ÚparentÚpatterns        r5   Úgenerate_suggestionszWrite.generate_suggestionsÄ   sŽ   è è € ð$ —N’N ;°Ñ3Ô3ˆ	Øð 	ØˆIà”×&Ò& yÑ1Ô1ˆð 5;ÐD�6—=’= Ñ'Ô'¨%Ñ/Ð/Àˆõ Øœ)Ø$Ý+Ô1Ø"ð	ñ ô ð
ð 	
r6   Ú_agent_statec           	   ƒ   ó°  K  — | j                              |¦  «        s.t          t          d|› �¬¦  «        gt          j        d¬¦  «        S | j                              |¦  «        ƒ d{V —†rS|�Q|j                             |¦  «        ƒ d{V —†}|€/t          t          d|› d�¬¦  «        gt          j        d¬¦  «        S | j                              |¦  «        ƒ d{V —†}d}|rG	 | j          	                    |¦  «        ƒ d{V —† 
                    d	¦  «        }n# t          $ r d}Y nw xY wt          |¦  «        j        }| j                              d
dt          |¦  «        g¦  «        ƒ d{V —† | j                              ||                     d	¦  «        ¦  «        ƒ d{V —† t%          |                     d¦  «        ¦  «        }d                     t+          j        |                     d¬¦  «        |                     d¬¦  «        |sdnd|› �d|› �d¬¦  «        ¦  «        }	t          t          d|› d|› d�¬¦  «        gt          j        d|	|ddœ¬¦  «        S )z.Write content to a file and return the result.z0Error: file_path must be an absolute path, got: )ÚtextT)r   ÚstateÚis_lastNzError: File zU exists but has not been read yet. You must read the file first before writing to it.r>   zutf-8Úmkdirz-pú
)Úkeependsz	/dev/nullza/zb/r   )ÚfromfileÚtofileÚnz	The file z  has been written successfully (z lines).r   )Údiffr   Úoccurrences)r   rY   rZ   Úmetadata)r/   Úisabsr   r   r   ÚERRORÚfile_existsÚtool_contextÚ	get_cacheÚ	read_fileÚdecodeÚ	Exceptionr   rS   Ú
exec_shellÚstrÚ
write_fileÚencodeÚlenÚsplitÚjoinÚdifflibÚunified_diffÚ
splitlinesÚRUNNING)
r3   r   r   rV   ÚcacheÚfile_existedÚprevious_contentÚ
parent_dirÚ
line_countÚ	diff_texts
             r5   Úcallz
Write.callè   s]  è è € ð Œ}×"Ò" 9Ñ-Ô-ð 
	Ýåð,Ø )ð,ð ,ðñ ô ðõ &Ô+Øð	ñ 	ô 	ð 	ð ”-×+Ò+¨IÑ6Ô6Ð6Ð6Ð6Ð6Ð6Ð6ð	àÐ(à&Ô3×=Ò=¸iÑHÔHÐHÐHÐHÐHÐHÐHˆEØˆ}Ý å!ð"5°	ð "5ð "5ð "5ðñ ô ðõ *Ô/Ø ð
ñ 
ô 
ð 
ð$ "œ]×6Ò6°yÑAÔAÐAÐAÐAÐAÐAÐAˆØÐØð 	&ð&àœ-×1Ò1°)Ñ<Ô<Ð<Ð<Ð<Ð<Ð<Ð<ß’&˜‘/”/ð !Ð øõ ð &ð &ð &ð $&Ð Ð Ð ð&øøøõ ˜)‘_”_Ô+ˆ
ØŒm×&Ò&Ø�d�C 
™OœOÐ,ñ
ô 
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð
 Œm×&Ò&ØØ�NŠN˜7Ñ#Ô#ñ
ô 
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
õ ˜Ÿš tÑ,Ô,Ñ-Ô-ˆ
ð
 —G’GÝÔ Ø ×+Ò+°TÐ+Ñ:Ô:Ø×"Ò"¨DÐ"Ñ1Ô1à'3ÐI�K�KÐ9I¸iÐ9IÐ9Ià'˜IÐ'Ð'Øðñ ô ñ

ô 

ˆ	õ åð- Yð -ð -Ø"ð-ð -ð -ðñ ô ðõ "Ô)Øà!Ø&Ø ðð ð
ñ 
ô 
ð 	
s   Ã#3D ÄD&Ä%D&)N)"Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   rm   Ú__annotations__r   r"   Údictr   r#   Úboolr$   r%   r&   r'   r	   r
   r2   r   r   r   r1   r   r   rH   rL   r   rU   r   r   r}   Ú__classcell__)r4   s   @r5   r   r      s�  ø€ € € € € € ØÐà€Dˆ#ÐÐÑØ/ðe€K�ð eð eñ eð 2ð ð !ð 3ðð ð !ØAðð ð

ð 

ð ! )Ð,ð$ð $€L�$�s˜C�x”.ð ð ñ ð  €FˆDÐÐÑØ€L�$ÐÐÑØ %Ð˜Ð%Ð%Ñ%Ø"Ð�dÐ"Ð"Ñ"Ø"Ð�tÐ"Ð"Ñ"ð &=Ø+HØ7;Ø&*ð#2ð #2à˜cœð#2ð  $ Cœyð#2ð Ð,Ô-°Ñ4ð	#2ð
 ˜tÑ#ð#2ð 
ð#2ð #2ð #2ð #2ð #2ð #2ðJ>
à˜˜c˜”Nð>
ð #ð>
ð 
ð	>
ð >
ð >
ð >
ð@8à˜D‘jð8ð ˜˜c˜”Nð8ð 
ð	8ð 8ð 8ð 8ð<"
à˜˜c˜”Nð"
ð 
ˆnÔ	ð"
ð "
ð "
ð "
ðP +/ð	f
ð f
àðf
ð ðf
ð ! 4Ñ'ð	f
ð
 
ðf
ð f
ð f
ð f
ð f
ð f
ð f
ð f
r6   r   )r�   rs   rK   Úpathlibr   Útypingr   r   Ú_baser   r   Ú
_constantsr	   r
   Ú
permissionr   r   r   r   r   Ú	_responser   r;   r   r   rY   r   r/   r   r   © r6   r5   ú<module>r�      s[  ðà #Ð #Ø €€€Ø €€€Ø Ð Ð Ð Ð Ð Ø Ð Ð Ð Ð Ð Ð Ð à 0Ð 0Ð 0Ð 0Ð 0Ð 0Ð 0Ð 0ðð ð ð ð ð ð ð ðð ð ð ð ð ð ð ð ð ð ð ð ð ð "Ð !Ð !Ð !Ð !Ð !Ø 1Ð 1Ð 1Ð 1Ð 1Ð 1Ð 1Ð 1Ø Ð Ð Ð Ð Ð Ø !Ð !Ð !Ð !Ð !Ð !ðt
ð t
ð t
ð t
ð t
ˆHñ t
ô t
ð t
ð t
ð t
r6   