§
    ‰eîiyÆ  ã            	       ó  — d Z ddlZddlZddl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 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  e ej        ¦   «         ¦  «        Z ee¦  «        Z ee¦  «        Z d
ee         fd„Z!ded
e"fd„Z#e G d„ d¦  «        ¦   «         Z$e G d„ d¦  «        ¦   «         Z%e G d„ d¦  «        ¦   «         Z&e G d„ d¦  «        ¦   «         Z'e G d„ d¦  «        ¦   «         Z(e G d„ d¦  «        ¦   «         Z)e G d„ d¦  «        ¦   «         Z* G d„ de¦  «        Z+h d£Z,dd d!d"d#d$œZ-d%Z.d%Z/d&Z0d'Z1d(Z2dZ3d)Z4d*ed+e5d
e5fd,„Z6e1e2fd-ed.ed
e7e5e5f         fd/„Z8e3e4fd-ed.ed
e7e5e5f         fd0„Z9 G d1„ d2e+¦  «        Z:dS )3aL  
File Operations Module

Provides file manipulation capabilities (read, write, patch, search) that work
across all terminal backends (local, docker, singularity, ssh, modal, daytona).

The key insight is that all file operations can be expressed as shell commands,
so we wrap the terminal backend's execute() interface to provide a unified file API.

Usage:
    from tools.file_operations import ShellFileOperations
    from tools.terminal_tool import _active_environments
    
    # Get file operations for a terminal environment
    file_ops = ShellFileOperations(terminal_env)
    
    # Read a file
    result = file_ops.read_file("/path/to/file.py")
    
    # Write a file
    result = file_ops.write_file("/path/to/new.py", "print('hello')")
    
    # Search for content
    result = file_ops.search("TODO", path=".", file_glob="*.py")
é    N)ÚABCÚabstractmethod)Ú	dataclassÚfield)ÚOptionalÚListÚDictÚAny)ÚPath)Úget_hermes_home)ÚBINARY_EXTENSIONS)Úbuild_write_denied_pathsÚbuild_write_denied_prefixesÚget_safe_write_rootÚis_write_deniedÚreturnc                  ó   — t          ¦   «         S )a\  Return the resolved HERMES_WRITE_SAFE_ROOT path, or None if unset.

    When set, all write_file/patch operations are constrained to this
    directory tree.  Writes outside it are denied even if the target is
    not on the static deny list.  Opt-in hardening for gateway/messaging
    deployments that should only touch a workspace checkout.
    )Ú_shared_get_safe_write_root© ó    ú7/home/div/.hermes/hermes-agent/tools/file_operations.pyÚ_get_safe_write_rootr   9   s   € õ 'Ñ(Ô(Ð(r   Úpathc                 ó    — t          | ¦  «        S )z.Return True if path is on the write deny list.)Ú_shared_is_write_denied)r   s    r   Ú_is_write_deniedr   D   s   € å" 4Ñ(Ô(Ð(r   c                   ó$  — e Zd ZU dZdZeed<   dZeed<   dZ	eed<   dZ
eed<   d	Zee         ed
<   dZeed<   dZeed<   d	Zee         ed<   d	Zee         ed<   d	Zee         ed<   d	Zee         ed<    ee¬¦  «        Zee         ed<   defd„Zd	S )Ú
ReadResultzResult from reading a file.Ú Úcontentr   Útotal_linesÚ	file_sizeFÚ	truncatedNÚhintÚ	is_binaryÚis_imageÚbase64_contentÚ	mime_typeÚ
dimensionsÚerror©Údefault_factoryÚsimilar_filesr   c                 óH   — d„ | j                              ¦   «         D ¦   «         S )Nc                 ó*   — i | ]\  }}|®|g k    ¯||“ŒS ©Nr   ©Ú.0ÚkÚvs      r   ú
<dictcomp>z&ReadResult.to_dict.<locals>.<dictcomp>^   s(   € ÐTÐTÐT™˜˜A¸!¸-ÈAÐQSÊGÈG��1ÈGÈGÈGr   ©Ú__dict__Úitems©Úselfs    r   Úto_dictzReadResult.to_dict]   s$   € ØTÐT ¤×!4Ò!4Ñ!6Ô!6ÐTÑTÔTÐTr   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r    ÚstrÚ__annotations__r!   Úintr"   r#   Úboolr$   r   r%   r&   r'   r(   r)   r*   r   Úlistr-   r   Údictr;   r   r   r   r   r   M   s#  € € € € € € à%Ð%Ø€GˆSÐÐÑØ€K�ÐÐÑØ€IˆsÐÐÑØ€IˆtÐÐÑØ€Dˆ(�3Œ-ÐÐÑØ€IˆtÐÐÑØ€HˆdÐÐÑØ$(€N�H˜S”MÐ(Ð(Ñ(Ø#€Iˆx˜Œ}Ð#Ð#Ñ#Ø $€J�˜”Ð$Ð$Ñ$Ø€Eˆ8�CŒ=ÐÐÑØ$˜u°TÐ:Ñ:Ô:€M�4˜”9Ð:Ð:Ñ:ðU˜ð Uð Uð Uð Uð Uð Ur   r   c                   óp   — e Zd ZU dZdZeed<   dZeed<   dZ	e
e         ed<   dZe
e         ed<   d	efd
„ZdS )ÚWriteResultzResult from writing a file.r   Úbytes_writtenFÚdirs_createdNr*   Úwarningr   c                 óH   — d„ | j                              ¦   «         D ¦   «         S )Nc                 ó   — i | ]
\  }}|®||“ŒS r0   r   r1   s      r   r5   z'WriteResult.to_dict.<locals>.<dictcomp>j   s   € ÐHÐHÐH™˜˜A¸!¸-��1¸-¸-¸-r   r6   r9   s    r   r;   zWriteResult.to_dicti   s$   € ØHÐH ¤×!4Ò!4Ñ!6Ô!6ÐHÑHÔHÐHr   )r<   r=   r>   r?   rH   rB   rA   rI   rC   r*   r   r@   rJ   rE   r;   r   r   r   rG   rG   a   s†   € € € € € € à%Ð%Ø€M�3ÐÐÑØ€L�$ÐÐÑØ€Eˆ8�CŒ=ÐÐÑØ!€GˆX�cŒ]Ð!Ð!Ñ!ðI˜ð Ið Ið Ið Ið Ið Ir   rG   c                   ó
  — e Zd ZU dZdZeed<   dZeed<    e	e
¬¦  «        Zee         ed<    e	e
¬¦  «        Zee         ed<    e	e
¬¦  «        Zee         ed	<   d
Zeeeef                  ed<   d
Zee         ed<   defd„Zd
S )ÚPatchResultzResult from patching a file.FÚsuccessr   Údiffr+   Úfiles_modifiedÚfiles_createdÚfiles_deletedNÚlintr*   r   c                 óä   — d| j         i}| j        r
| j        |d<   | j        r
| j        |d<   | j        r
| j        |d<   | j        r
| j        |d<   | j        r
| j        |d<   | j        r
| j        |d<   |S )NrO   rP   rQ   rR   rS   rT   r*   )rO   rP   rQ   rR   rS   rT   r*   ©r:   Úresults     r   r;   zPatchResult.to_dictx   s›   € Ø˜Tœ\Ð*ˆØŒ9ð 	'Ø!œYˆF�6‰NØÔð 	;Ø'+Ô':ˆFÐ#Ñ$ØÔð 	9Ø&*Ô&8ˆF�?Ñ#ØÔð 	9Ø&*Ô&8ˆF�?Ñ#ØŒ9ð 	'Ø!œYˆF�6‰NØŒ:ð 	)Ø"œjˆF�7‰OØˆr   )r<   r=   r>   r?   rO   rC   rA   rP   r@   r   rD   rQ   r   rR   rS   rT   r   r	   r
   r*   rE   r;   r   r   r   rN   rN   m   sè   € € € € € € à&Ð&Ø€GˆTÐÐÑØ€Dˆ#€N€N�NØ % °dÐ ;Ñ ;Ô ;€N�D˜”IÐ;Ð;Ñ;Ø$˜u°TÐ:Ñ:Ô:€M�4˜”9Ð:Ð:Ñ:Ø$˜u°TÐ:Ñ:Ô:€M�4˜”9Ð:Ð:Ñ:Ø%)€Dˆ(�4˜˜S˜”>Ô
"Ð)Ð)Ñ)Ø€Eˆ8�CŒ=ÐÐÑð˜ð ð ð ð ð ð r   rN   c                   ó@   — e Zd ZU dZeed<   eed<   eed<   dZeed<   dS )ÚSearchMatchzA single search match.r   Úline_numberr    g        ÚmtimeN)	r<   r=   r>   r?   r@   rA   rB   r[   Úfloatr   r   r   rY   rY   ‰   sF   € € € € € € à Ð Ø
€I€I�IØÐÐÑØ€L€L�LØ€Eˆ5ÐÐÑÐÐr   rY   c                   óä   — e Zd ZU dZ ee¬¦  «        Zee         e	d<    ee¬¦  «        Z
ee         e	d<    ee¬¦  «        Zeeef         e	d<   dZee	d<   dZee	d	<   d
Zee         e	d<   defd„Zd
S )ÚSearchResultzResult from searching.r+   ÚmatchesÚfilesÚcountsr   Útotal_countFr#   Nr*   r   c                 óÌ   — d| j         i}| j        rd„ | j        D ¦   «         |d<   | j        r
| j        |d<   | j        r
| j        |d<   | j        rd|d<   | j        r
| j        |d<   |S )	Nrb   c                 ó8   — g | ]}|j         |j        |j        d œ‘ŒS ))r   Úliner    ©r   rZ   r    )r2   Úms     r   ú
<listcomp>z(SearchResult.to_dict.<locals>.<listcomp>Ÿ   s8   € ð !ð !ð !àð œ¨¬À1Ä9ÐMÐMð!ð !ð !r   r_   r`   ra   Tr#   r*   )rb   r_   r`   ra   r#   r*   rV   s     r   r;   zSearchResult.to_dictœ   s™   € Ø Ô!1Ð2ˆØŒ<ð 	ð!ð !àœð!ñ !ô !ˆF�9Ñð Œ:ð 	)Ø"œjˆF�7‰OØŒ;ð 	+Ø#œ{ˆF�8ÑØŒ>ð 	'Ø"&ˆF�;ÑØŒ:ð 	)Ø"œjˆF�7‰OØˆr   )r<   r=   r>   r?   r   rD   r_   r   rY   rA   r`   r@   rE   ra   r	   rB   rb   r#   rC   r*   r   r;   r   r   r   r^   r^   ’   sÓ   € € € € € € à Ð Ø!& °tÐ!<Ñ!<Ô!<€GˆT�+ÔÐ<Ð<Ñ<Ø�u¨TÐ2Ñ2Ô2€Eˆ4�Œ9Ð2Ð2Ñ2Ø"˜U°4Ð8Ñ8Ô8€FˆD��c�ŒNÐ8Ð8Ñ8Ø€K�ÐÐÑØ€IˆtÐÐÑØ€Eˆ8�CŒ=ÐÐÑð˜ð ð ð ð ð ð r   r^   c                   óX   — e Zd ZU dZdZeed<   dZeed<   dZe	ed<   dZ
e	ed<   d	efd
„ZdS )Ú
LintResultzResult from linting a file.TrO   FÚskippedr   ÚoutputÚmessager   c                 óJ   — | j         r
d| j        dœS | j        rdnd| j        dœS )Nrk   )Ústatusrm   Úokr*   )ro   rl   )rk   rm   rO   rl   r9   s    r   r;   zLintResult.to_dict¶   s?   € ØŒ<ð 	BØ'°D´LÐAÐAÐAà"œlÐ7�d�d°Ø”kð
ð 
ð 	
r   N)r<   r=   r>   r?   rO   rC   rA   rk   rl   r@   rm   rE   r;   r   r   r   rj   rj   ®   sw   € € € € € € à%Ð%Ø€GˆTÐÐÑØ€GˆTÐÐÑØ€FˆCÐÐÑØ€GˆSÐÐÑð
˜ð 
ð 
ð 
ð 
ð 
ð 
r   rj   c                   ó0   — e Zd ZU dZdZeed<   dZeed<   dS )ÚExecuteResultz&Result from executing a shell command.r   Ústdoutr   Ú	exit_codeN)	r<   r=   r>   r?   rs   r@   rA   rt   rB   r   r   r   rr   rr   ¿   s8   € € € € € € à0Ð0Ø€FˆCÐÐÑØ€IˆsÐÐÑÐÐr   rr   c                   ód  — e Zd ZdZed!dedededefd„¦   «         Zededefd	„¦   «         Z	eded
ede
fd„¦   «         Ze	 d"dededededef
d„¦   «         Zededefd„¦   «         Zedede
fd„¦   «         Zededede
fd„¦   «         Ze	 	 	 d#dedededee         dededededefd „¦   «         ZdS )$ÚFileOperationsz@Abstract interface for file operations across terminal backends.é   éô  r   ÚoffsetÚlimitr   c                 ó   — dS )z$Read a file with pagination support.Nr   )r:   r   ry   rz   s       r   Ú	read_filezFileOperations.read_fileÍ   ó	   € ð 	ˆr   c                 ó   — dS )a
  Read the complete file content as a plain string.

        No pagination, no line-number prefixes, no per-line truncation.
        Returns ReadResult with .content = full file text, .error set on
        failure. Always reads to EOF regardless of file size.
        Nr   ©r:   r   s     r   Úread_file_rawzFileOperations.read_file_rawÒ   s	   € ð 	ˆr   r    c                 ó   — dS )z8Write content to a file, creating directories as needed.Nr   )r:   r   r    s      r   Ú
write_filezFileOperations.write_fileÜ   r}   r   FÚ
old_stringÚ
new_stringÚreplace_allc                 ó   — dS )z,Replace text in a file using fuzzy matching.Nr   )r:   r   rƒ   r„   r…   s        r   Úpatch_replacezFileOperations.patch_replaceá   s	   € ð 	ˆr   Úpatch_contentc                 ó   — dS )zApply a V4A format patch.Nr   )r:   rˆ   s     r   Ú	patch_v4azFileOperations.patch_v4aç   r}   r   c                 ó   — dS )z>Delete a file. Returns WriteResult with .error set on failure.Nr   r   s     r   Údelete_filezFileOperations.delete_fileì   r}   r   ÚsrcÚdstc                 ó   — dS )zSMove/rename a file from src to dst. Returns WriteResult with .error set on failure.Nr   )r:   r�   rŽ   s      r   Ú	move_filezFileOperations.move_fileñ   r}   r   ú.Né2   r   ÚpatternÚtargetÚ	file_globÚoutput_modeÚcontextc	                 ó   — dS )zSearch for content or files.Nr   )	r:   r“   r   r”   r•   rz   ry   r–   r—   s	            r   ÚsearchzFileOperations.searchö   s	   € ð
 	ˆr   ©rw   rx   ©F©r‘   r    Nr’   r   r    r   )r<   r=   r>   r?   r   r@   rB   r   r|   r€   rG   r‚   rC   rN   r‡   rŠ   rŒ   r�   r   r^   r™   r   r   r   rv   rv   Ê   s  € € € € € ØJÐJàðð ˜cð ¨3ð ¸3ð Èð ð ð ñ „^ðð ð #ð ¨*ð ð ð ñ „^ðð ð˜sð ¨Sð °[ð ð ð ñ „^ðð à*/ðð  #ð °3ð ÀCð Ø#'ðØ4?ðð ð ñ „^ðð
 ð sð ¨{ð ð ð ñ „^ðð ð ð ¨ð ð ð ñ „^ðð ð˜Sð  sð ¨{ð ð ð ñ „^ðð ØBKØOPØ<=ðð ˜cð ¨ð ¸Cð Ø" 3œ-ðØ7:ðØILðàðà69ðàBNðð ð ñ „^ðð ð r   rv   >   ú.bmpú.gifú.icoú.jpgú.pngú.jpegú.webpz python -m py_compile {file} 2>&1znode --check {file} 2>&1znpx tsc --noEmit {file} 2>&1zgo vet {file} 2>&1zrustfmt --check {file} 2>&1)z.pyz.jsz.tsz.goz.rsiÐ  i È  rw   rx   r’   ÚvalueÚdefaultc                 óT   — 	 t          | ¦  «        S # t          t          f$ r |cY S w xY w)z8Best-effort integer coercion for tool pagination inputs.)rB   Ú	TypeErrorÚ
ValueError)r¤   r¥   s     r   Ú_coerce_intr©     s<   € ðÝ�5‰zŒzÐøÝ•zÐ"ð ð ð Øˆˆˆðøøøs   ‚ ‘'¦'ry   rz   c                 óÖ   — ddl m}  |¦   «         }t          dt          | t          ¦  «        ¦  «        }t          |t
          ¦  «        }t          dt          ||¦  «        ¦  «        }||fS )a„  Return safe read_file pagination bounds.

    Tool schemas declare minimum/maximum values, but not every caller or
    provider enforces schemas before dispatch. Clamp here so invalid values
    cannot leak into sed ranges like ``0,-1p``.

    The upper bound on ``limit`` comes from ``tool_output.max_lines`` in
    config.yaml (defaults to the module-level ``MAX_LINES`` constant).
    r   )Úget_max_linesrw   )Útools.tool_output_limitsr«   Úmaxr©   ÚDEFAULT_READ_OFFSETÚDEFAULT_READ_LIMITÚmin)ry   rz   r«   Ú	max_linesÚnormalized_offsetÚnormalized_limits         r   Únormalize_read_paginationr´      st   € ð 7Ð6Ð6Ð6Ð6Ð6Ø�‘”€IÝ˜A�{¨6Õ3FÑGÔGÑHÔHÐÝ" 5Õ*<Ñ=Ô=ÐÝ˜1�cÐ"2°IÑ>Ô>Ñ?Ô?ÐØÐ.Ð.Ð.r   c                 ó–   — t          dt          | t          ¦  «        ¦  «        }t          dt          |t          ¦  «        ¦  «        }||fS )zCReturn safe search pagination bounds for shell head/tail pipelines.r   rw   )r­   r©   ÚDEFAULT_SEARCH_OFFSETÚDEFAULT_SEARCH_LIMIT)ry   rz   r²   r³   s       r   Únormalize_search_paginationr¸   3  sF   € õ ˜A�{¨6Õ3HÑIÔIÑJÔJÐÝ˜1�k¨%Õ1EÑFÔFÑGÔGÐØÐ.Ð.Ð.r   c                   óŒ  — e Zd ZdZd<defd„Z	 	 d=dededededef
d	„Zd
ede	fd„Z
d<dedede	fd„Zdede	fd„Zd>dededefd„Zdedefd„Zdedefd„Zdedededefd„Zd?dedededefd„Zdedefd„Zdedefd „Zdedefd!„Zd"ed#edefd$„Zdededefd%„Z	 d@ded'ed(ed)e	def
d*„Zd+edefd,„Zdedefd-„Z	 	 	 dAd1eded2ed3ee         deded4ed5edefd6„Z d1ededededef
d7„Z!d1ededededef
d8„Z"d1eded3ee         deded4ed5edefd9„Z#d1eded3ee         deded4ed5edefd:„Z$d1eded3ee         deded4ed5edefd;„Z%dS )BÚShellFileOperationszÝ
    File operations implemented via shell commands.
    
    Works with ANY terminal backend that has execute(command, cwd) method.
    This includes local, docker, singularity, ssh, modal, and daytona environments.
    NÚcwdc                 ó–   — || _         |p2t          |dd¦  «        p!t          t          |dd¦  «        dd¦  «        pd| _        i | _        dS )u—  
        Initialize file operations with a terminal environment.

        Args:
            terminal_env: Any object with execute(command, cwd) method.
                         Returns {"output": str, "returncode": int}
            cwd: Optional explicit fallback cwd when the terminal env has
                 no cwd attribute (rare â€” most backends track cwd live).

        Note:
            Every _exec() call prefers the LIVE ``terminal_env.cwd`` over
            ``self.cwd`` so ``cd`` commands run via the terminal tool are
            picked up immediately.  ``self.cwd`` is only used as a fallback
            when the env has no cwd at all â€” it is NOT the authoritative
            cwd, despite being settable at init time.

            Historical bug (fixed): prior versions of this class used the
            init-time cwd for every _exec() call, which caused relative
            paths passed to patch/read/write to target the wrong directory
            after the user ran ``cd`` in the terminal.  Patches would
            claim success and return a plausible diff but land in the
            original directory, producing apparent silent failures.
        r»   NÚconfigú/)ÚenvÚgetattrr»   Ú_command_cache)r:   Úterminal_envr»   s      r   Ú__init__zShellFileOperations.__init__C  se   € ð0  ˆŒð
 ð V�' ,°°tÑ<Ô<ð VÝ�7 <°¸4Ñ@Ô@À%ÈÑNÔNðVØRUð 	Œð 02ˆÔÐÐr   ÚcommandÚtimeoutÚ
stdin_datar   c                 óü   — i }|r||d<   |�||d<   |pt          | j        dd¦  «        p| j        } | j        j        |fd|i|¤Ž}t	          |                     dd¦  «        |                     dd¦  «        ¬	¦  «        S )
u½  Execute command via terminal backend.

        Args:
            stdin_data: If provided, piped to the process's stdin instead of
                        embedding in the command string. Bypasses ARG_MAX.

        Cwd resolution order (critical â€” see class docstring):
          1. Explicit ``cwd`` arg (if provided)
          2. Live ``self.env.cwd`` (tracks ``cd`` commands run via terminal)
          3. Init-time ``self.cwd`` (fallback when env has no cwd attribute)

        This ordering ensures relative paths in file operations follow the
        terminal's current directory â€” not the directory this file_ops was
        originally created in.  See test_file_ops_cwd_tracking.py.
        rÅ   NrÆ   r»   rl   r   Ú
returncoder   )rs   rt   )rÀ   r¿   r»   Úexecuterr   Úget)r:   rÄ   r»   rÅ   rÆ   ÚkwargsÚeffective_cwdrW   s           r   Ú_execzShellFileOperations._execf  s¦   € ð" ˆØð 	(Ø 'ˆF�9ÑØÐ!Ø#-ˆF�<Ñ ð ÐI�w t¤x°¸Ñ=Ô=ÐIÀÄˆØ!�”Ô! 'ÐGÐG¨}ÐGÀÐGÐGˆÝØ—:’:˜h¨Ñ+Ô+Ø—j’j ¨qÑ1Ô1ð
ñ 
ô 
ð 	
r   Úcmdc                 óª   — || j         vr>|                      d|› d�¦  «        }|j                             ¦   «         dk    | j         |<   | j         |         S )z6Check if a command exists in the environment (cached).zcommand -v z >/dev/null 2>&1 && echo 'yes'Úyes)rÁ   rÍ   rs   Ústrip)r:   rÎ   rW   s      r   Ú_has_commandz ShellFileOperations._has_command†  s[   € à�dÔ)Ð)Ð)Ø—Z’ZÐ Q¨cÐ QÐ QÐ QÑRÔRˆFØ'-¤}×':Ò':Ñ'<Ô'<ÀÒ'EˆDÔ Ñ$ØÔ" 3Ô'Ð'r   r   Úcontent_samplec                 ó  — t           j                             |¦  «        d                              ¦   «         }|t          v rdS |rEt          d„ |dd…         D ¦   «         ¦  «        }|t          t          |¦  «        d¦  «        z  dk    S dS )z
        Check if a file is likely binary.
        
        Uses extension check (fast) + content analysis (fallback).
        rw   Tc              3   óH   K  — | ]}t          |¦  «        d k     ¯|dv¯dV — ŒdS )é    z
	rw   N)Úord)r2   Úcs     r   ú	<genexpr>z8ShellFileOperations._is_likely_binary.<locals>.<genexpr>™  sJ   è è € ð  Eð  E aÝ"% a¡&¤&¨2¢+ +°!¸8Ð2CÐ2Cð !"Ø2CÐ2CÐ2CÐ2Cð Eð  Er   Niè  g333333Ó?F)Úosr   ÚsplitextÚlowerr   Úsumr°   Úlen)r:   r   rÓ   ÚextÚnon_printables        r   Ú_is_likely_binaryz%ShellFileOperations._is_likely_binary�  s§   € õ Œg×Ò˜tÑ$Ô$ QÔ'×-Ò-Ñ/Ô/ˆØÕ#Ð#Ð#Ø�4ð ð 	IÝð  Eð  E¨>¸%¸4¸%Ô+@ð  Eñ  Eô  Eñ Eô EˆMà ¥3¥s¨>Ñ':Ô':¸DÑ#AÔ#AÑAÀDÒHÐHàˆur   c                 ó‚   — t           j                             |¦  «        d                              ¦   «         }|t          v S )z2Check if file is an image we can return as base64.rw   )rÚ   r   rÛ   rÜ   ÚIMAGE_EXTENSIONS)r:   r   rß   s      r   Ú	_is_imagezShellFileOperations._is_imageŸ  s4   € åŒg×Ò˜tÑ$Ô$ QÔ'×-Ò-Ñ/Ô/ˆØÕ&Ð&Ð&r   rw   r    Ú
start_linec                 ó  — ddl m}  |¦   «         }|                     d¦  «        }g }t          ||¬¦  «        D ]@\  }}t	          |¦  «        |k    r|d|…         dz   }|                     |d›d|› �¦  «         ŒAd                     |¦  «        S )	z7Add line numbers to content in LINE_NUM|CONTENT format.r   )Úget_max_line_lengthÚ
)ÚstartNz... [truncated]Ú6dÚ|)r¬   rç   ÚsplitÚ	enumeraterÞ   ÚappendÚjoin)	r:   r    rå   rç   Úmax_line_lengthÚlinesÚnumberedÚire   s	            r   Ú_add_line_numbersz%ShellFileOperations._add_line_numbers¤  s·   € à@Ð@Ð@Ð@Ð@Ð@Ø-Ð-Ñ/Ô/ˆØ—’˜dÑ#Ô#ˆØˆÝ  ¨jÐ9Ñ9Ô9ð 	.ð 	.‰GˆAˆtå�4‰yŒy˜?Ò*Ð*ØÐ,˜_Ð,Ô-Ð0AÑA�Ø�OŠO˜qÐ,Ð,Ð, dÐ,Ð,Ñ-Ô-Ð-Ð-Ø�yŠy˜Ñ"Ô"Ð"r   c                 ó¬  — |s|S |                      d¦  «        �r9|                      d¦  «        }|j        dk    �r|j                             ¦   «         rÿ|j                             ¦   «         }|dk    r|S |                      d¦  «        r||dd…         z   S |dd…         }|                     d¦  «        }|dk    r
|d|…         n|}|r‰t          j        d|¦  «        rt|                      d	|› �¦  «        }|j        dk    rQ|j                             ¦   «         r8|j                             ¦   «         }|dt          |¦  «        z   d…         }	||	z   S |S )
z½
        Expand shell-style paths like ~ and ~user to absolute paths.
        
        This must be done BEFORE shell escaping, since ~ doesn't expand
        inside single quotes.
        Ú~z
echo $HOMEr   z~/rw   Nr¾   z[a-zA-Z0-9._-]+zecho ~)	Ú
startswithrÍ   rt   rs   rÑ   ÚfindÚreÚ	fullmatchrÞ   )
r:   r   rW   ÚhomeÚrestÚ	slash_idxÚusernameÚexpand_resultÚ	user_homeÚsuffixs
             r   Ú_expand_pathz ShellFileOperations._expand_path±  sr  € ð ð 	ØˆKð �?Š?˜3ÑÔñ 	2à—Z’Z Ñ-Ô-ˆFØÔ 1Ò$Ñ$¨¬×)<Ò)<Ñ)>Ô)>Ð$Ø”}×*Ò*Ñ,Ô,�Ø˜3’;�;Ø�KØ—_’_ TÑ*Ô*ð +Ø $ q r r¤(™?Ð*ð ˜A˜B˜B”x�Ø ŸIšI c™NœN�	Ø/8¸Aª~¨~˜4 
  
Ô+Ð+À4�Øð 2¥¤Ð-?ÀÑ JÔ Jð 2ð %)§J¢JÐ/B¸Ð/BÐ/BÑ$CÔ$C�MØ$Ô.°!Ò3Ð3¸Ô8L×8RÒ8RÑ8TÔ8TÐ3Ø$1Ô$8×$>Ò$>Ñ$@Ô$@˜	Ø!% a­#¨h©-¬-Ñ&7Ð&8Ð&8Ô!9˜Ø(¨6Ñ1Ð1àˆr   Úargc                 ó:   — d|                      dd¦  «        z   dz   S )z/Escape a string for safe use in shell commands.ú'z'"'"')Úreplace)r:   r  s     r   Ú_escape_shell_argz%ShellFileOperations._escape_shell_argÖ  s"   € ð �S—[’[  iÑ0Ô0Ñ0°3Ñ6Ð6r   Úold_contentÚnew_contentÚfilenamec                 óÀ   — |                      d¬¦  «        }|                      d¬¦  «        }t          j        ||d|› �d|› �¬¦  «        }d                     |¦  «        S )z2Generate unified diff between old and new content.T)Úkeependsza/zb/)ÚfromfileÚtofiler   )Ú
splitlinesÚdifflibÚunified_diffrï   )r:   r  r	  r
  Ú	old_linesÚ	new_linesrP   s          r   Ú_unified_diffz!ShellFileOperations._unified_diffÛ  sn   € à×*Ò*°DÐ*Ñ9Ô9ˆ	Ø×*Ò*°DÐ*Ñ9Ô9ˆ	ÝÔ#Ø�yØ$˜(�_�_Ø"˜�?�?ð
ñ 
ô 
ˆð
 �wŠw�t‰}Œ}Ðr   rx   ry   rz   c           	      óœ  — |                       |¦  «        }t          ||¦  «        \  }}d|                      |¦  «        › d�}|                      |¦  «        }|j        dk    r|                      |¦  «        S 	 t          |j                             ¦   «         ¦  «        }n# t          $ r d}Y nw xY w|t          k    r	 |                      |¦  «        rt          dd|d¬¦  «        S d|                      |¦  «        › d�}|                      |¦  «        }|                      ||j        ¦  «        rt          d|d¬	¦  «        S ||z   d
z
  }	d|› d|	› d|                      |¦  «        › �}
|                      |
¦  «        }|j        dk    rt          d|j        › �¬¦  «        S d|                      |¦  «        › �}|                      |¦  «        }	 t          |j                             ¦   «         ¦  «        }n# t          $ r d}Y nw xY w||	k    }d}|rd|	d
z   › d|› d|	› d|› d�	}t          |                      |j        |¦  «        ||||¬¦  «        S )a‚  
        Read a file with pagination, binary detection, and line numbers.
        
        Args:
            path: File path (absolute or relative to cwd)
            offset: Line number to start from (1-indexed, default 1)
            limit: Maximum lines to return (default 500, max 2000)
        
        Returns:
            ReadResult with content, metadata, or error info
        úwc -c < ú 2>/dev/nullr   Tz‹Image file detected. Automatically redirected to vision_analyze tool. Use vision_analyze with this file path to inspect the image contents.)r&   r%   r"   r$   úhead -c 1000 zUBinary file - cannot display as text. Use appropriate tools to handle this file type.©r%   r"   r*   rw   zsed -n 'Ú,zp' úFailed to read file: ©r*   zwc -l < NzUse offset=z to continue reading (showing Ú-z of z lines))r    r!   r"   r#   r$   )r  r´   r  rÍ   rt   Ú_suggest_similar_filesrB   rs   rÑ   r¨   ÚMAX_FILE_SIZErä   r   rá   rô   )r:   r   ry   rz   Ústat_cmdÚstat_resultr"   Ú
sample_cmdÚsample_resultÚend_lineÚread_cmdÚread_resultÚwc_cmdÚ	wc_resultr!   r#   r$   s                    r   r|   zShellFileOperations.read_fileê  së  € ð × Ò  Ñ&Ô&ˆå1°&¸%Ñ@Ô@‰ˆ�ð I˜d×4Ò4°TÑ:Ô:ÐHÐHÐHˆØ—j’j Ñ*Ô*ˆàÔ  AÒ%Ð%à×.Ò.¨tÑ4Ô4Ð4ð	Ý˜KÔ.×4Ò4Ñ6Ô6Ñ7Ô7ˆIˆIøÝð 	ð 	ð 	ØˆIˆIˆIð	øøøð •}Ò$Ð$àð �>Š>˜$ÑÔð 		ÝØØØ#ð\ðñ ô ð ð P T×%;Ò%;¸DÑ%AÔ%AÐOÐOÐOˆ
ØŸ
š
 :Ñ.Ô.ˆà×!Ò! $¨Ô(<Ñ=Ô=ð 	ÝØØ#Ømðñ ô ð ð ˜E‘> AÑ%ˆØR˜fÐRÐR xÐRÐR°D×4JÒ4JÈ4Ñ4PÔ4PÐRÐRˆØ—j’j Ñ*Ô*ˆàÔ  AÒ%Ð%ÝÐ$P¸KÔ<NÐ$PÐ$PÐQÑQÔQÐQð ;˜D×2Ò2°4Ñ8Ô8Ð:Ð:ˆØ—J’J˜vÑ&Ô&ˆ	ð	Ý˜iÔ.×4Ò4Ñ6Ô6Ñ7Ô7ˆKˆKøÝð 	ð 	ð 	ØˆKˆKˆKð	øøøð   (Ò*ˆ	ØˆØð 	yØx ¨A¡ÐxÐxÈVÐxÐxÐV^ÐxÐxÐdoÐxÐxÐxˆDåØ×*Ò*¨;Ô+=¸vÑFÔFØ#ØØØð
ñ 
ô 
ð 	
s$   Á8&B ÂB.Â-B.Ç&G3 Ç3HÈHc                 ó  — t           j                             |¦  «        pd}t           j                             |¦  «        }t           j                             |¦  «        d         }t           j                             |¦  «        d                              ¦   «         }|                     ¦   «         }d|                      |¦  «        › d�}|                      |¦  «        }g }	|j        dk    �rã|j	         
                    ¦   «         �rÉ|j	         
                    ¦   «                              d¦  «        D �]›}
|
sŒ|
                     ¦   «         }d}||k    rd}�n:t           j                             |
¦  «        d                              ¦   «         |                     ¦   «         k    rd}nê|                     |¦  «        s|                     |¦  «        rd	}n½||v rd
}n¶||v rt          |¦  «        dk    rd}nœ|ršt           j                             |
¦  «        d                              ¦   «         |k    r_t          |¦  «        t          |¦  «        z  }t          |¦  «        t          t          |¦  «        t          |¦  «        ¦  «        dz  k    rd}|dk    r5|	                     |t           j                             ||
¦  «        f¦  «         �Œ�|	                     d„ ¬¦  «         d„ |	dd…         D ¦   «         }t'          d|› �|¬¦  «        S )z;Suggest similar files when the requested file is not found.r‘   r   rw   úls -1 z 2>/dev/null | head -50rè   éd   éZ   éF   é<   é   é(   gš™™™™™Ù?é   c                 ó   — | d          S )Nr   r   )Úxs    r   ú<lambda>z<ShellFileOperations._suggest_similar_files.<locals>.<lambda>n  s   €  1 Q¤4 %€ r   )Úkeyc                 ó   — g | ]\  }}|‘ŒS r   r   )r2   Ú_Úfps      r   rh   z>ShellFileOperations._suggest_similar_files.<locals>.<listcomp>o  s   € Ð.Ð.Ð.™%˜!˜R�2Ð.Ð.Ð.r   Né   zFile not found: )r*   r-   )rÚ   r   ÚdirnameÚbasenamerÛ   rÜ   r  rÍ   rt   rs   rÑ   rì   r÷   rÞ   Úsetr­   rî   rï   Úsortr   )r:   r   Údir_pathr
  Úbasename_no_extrß   Ú
lower_nameÚls_cmdÚ	ls_resultÚscoredÚfÚlfÚscoreÚcommonÚsimilars                  r   r  z*ShellFileOperations._suggest_similar_filesB  sØ  € å”7—?’? 4Ñ(Ô(Ð/¨CˆÝ”7×#Ò# DÑ)Ô)ˆÝœ'×*Ò*¨8Ñ4Ô4°QÔ7ˆÝŒg×Ò˜xÑ(Ô(¨Ô+×1Ò1Ñ3Ô3ˆØ—^’^Ñ%Ô%ˆ
ð T˜$×0Ò0°Ñ:Ô:ÐSÐSÐSˆØ—J’J˜vÑ&Ô&ˆ	àˆØÔ !Ò#Ñ#¨	Ô(8×(>Ò(>Ñ(@Ô(@Ñ#ØÔ%×+Ò+Ñ-Ô-×3Ò3°DÑ9Ô9ð Fñ F�Øð ØØ—W’W‘Y”Y�Ø�ð ˜Ò#Ð#Ø�E‘Eå”W×%Ò% aÑ(Ô(¨Ô+×1Ò1Ñ3Ô3°×7LÒ7LÑ7NÔ7NÒNÐNØ�E�Eà—]’] :Ñ.Ô.ð #°*×2GÒ2GÈÑ2KÔ2Kð #Ø�E�Eà 2Ð%Ð%Ø�E�Eà˜:Ð%Ð%­#¨b©'¬'°Aª+¨+Ø�E�Eàð #�RœW×-Ò-¨aÑ0Ô0°Ô3×9Ò9Ñ;Ô;¸sÒBÐBÝ  ™_œ_­s°2©w¬wÑ6�FÝ˜6‘{”{¥c­#¨j©/¬/½3¸r¹7¼7Ñ&CÔ&CÀcÑ&IÒIÐIØ "˜à˜1’9�9Ø—M’M 5­"¬'¯,ª,°xÀÑ*CÔ*CÐ"DÑEÔEÐEùà�Š˜˜ˆÑ(Ô(Ð(Ø.Ð. 6¨"¨1¨"¤:Ð.Ñ.Ô.ˆåØ+ TÐ+Ð+Ø!ð
ñ 
ô 
ð 	
r   c                 ó  — |                       |¦  «        }d|                      |¦  «        › d�}|                      |¦  «        }|j        dk    r|                      |¦  «        S 	 t          |j                             ¦   «         ¦  «        }n# t          $ r d}Y nw xY w|  	                    |¦  «        rt          dd|¬¦  «        S |                      d|                      |¦  «        › d�¦  «        }|                      ||j        ¦  «        rt          d|d¬¦  «        S |                      d	|                      |¦  «        › �¦  «        }|j        dk    rt          d
|j        › �¬¦  «        S t          |j        |¬¦  «        S )zÅRead the complete file content as a plain string.

        No pagination, no line-number prefixes, no per-line truncation.
        Uses cat so the full file is returned regardless of size.
        r  r  r   T)r&   r%   r"   r  u'   Binary file â€” cannot display as text.r  úcat r  r  )r    r"   )r  r  rÍ   rt   r  rB   rs   rÑ   r¨   rä   r   rá   )r:   r   r   r!  r"   r#  Ú
cat_results          r   r€   z!ShellFileOperations.read_file_rawv  s©  € ð × Ò  Ñ&Ô&ˆØH˜d×4Ò4°TÑ:Ô:ÐHÐHÐHˆØ—j’j Ñ*Ô*ˆØÔ  AÒ%Ð%Ø×.Ò.¨tÑ4Ô4Ð4ð	Ý˜KÔ.×4Ò4Ñ6Ô6Ñ7Ô7ˆIˆIøÝð 	ð 	ð 	ØˆIˆIˆIð	øøøà�>Š>˜$ÑÔð 	RÝ t°tÀyÐQÑQÔQÐQØŸ
š
Ð#]°4×3IÒ3IÈ$Ñ3OÔ3OÐ#]Ð#]Ð#]Ñ^Ô^ˆØ×!Ò! $¨Ô(<Ñ=Ô=ð 	ÝØ¨)Ø?ðñ ô ð ð —Z’ZÐ E t×'=Ò'=¸dÑ'CÔ'CÐ EÐ EÑFÔFˆ
ØÔ 1Ò$Ð$ÝÐ$O¸JÔ<MÐ$OÐ$OÐPÑPÔPÐPÝ *Ô"3¸yÐIÑIÔIÐIs   Á%&B ÂBÂBc                 ó0  — |                       |¦  «        }t          |¦  «        rt          d|› d�¬¦  «        S |                      d|                      |¦  «        › �¦  «        }|j        dk    rt          d|› d|j        › �¬¦  «        S t          ¦   «         S )zDelete a file via rm.zDelete denied: ú is a protected pathr  zrm -f r   zFailed to delete ú: ©r  r   rG   rÍ   r  rt   rs   )r:   r   rW   s      r   rŒ   zShellFileOperations.delete_file’  s§   € à× Ò  Ñ&Ô&ˆÝ˜DÑ!Ô!ð 	SÝÐ%Q°tÐ%QÐ%QÐ%QÐRÑRÔRÐRØ—’ÐC T×%;Ò%;¸DÑ%AÔ%AÐCÐCÑDÔDˆØÔ˜qÒ Ð ÝÐ%P¸Ð%PÐ%PÀÄÐ%PÐ%PÐQÑQÔQÐQÝ‰}Œ}Ðr   r�   rŽ   c                 óž  — |                       |¦  «        }|                       |¦  «        }||fD ]'}t          |¦  «        rt          d|› d�¬¦  «        c S Œ(|                      d|                      |¦  «        › d|                      |¦  «        › �¦  «        }|j        dk    rt          d|› d|› d	|j        › �¬¦  «        S t          ¦   «         S )
zMove a file via mv.zMove denied: rM  r  zmv Ú r   zFailed to move z -> rN  rO  )r:   r�   rŽ   ÚprW   s        r   r�   zShellFileOperations.move_fileœ  sÿ   € à×Ò Ñ$Ô$ˆØ×Ò Ñ$Ô$ˆØ�s�ð 	Rð 	RˆAÝ Ñ"Ô"ð RÝ"Ð)P¸Ð)PÐ)PÐ)PÐQÑQÔQÐQÐQÐQðRà—’ØM�$×(Ò(¨Ñ-Ô-ÐMÐM°×0FÒ0FÀsÑ0KÔ0KÐMÐMñ
ô 
ˆð Ô˜qÒ Ð ÝÐ%V°sÐ%VÐ%VÀÐ%VÐ%VÀvÄ}Ð%VÐ%VÐWÑWÔWÐWÝ‰}Œ}Ðr   c                 ó  — |                       |¦  «        }t          |¦  «        rt          d|› d�¬¦  «        S t          j                             |¦  «        }d}|r:d|                      |¦  «        › �}|                      |¦  «        }|j        dk    rd}d|                      |¦  «        › �}|                      ||¬	¦  «        }|j        dk    rt          d
|j	        › �¬¦  «        S d|                      |¦  «        › d�}	|                      |	¦  «        }
	 t          |
j	                             ¦   «         ¦  «        }n2# t          $ r% t          |                     d¦  «        ¦  «        }Y nw xY wt          ||¬¦  «        S )u¤  
        Write content to a file, creating parent directories as needed.

        Pipes content through stdin to avoid OS ARG_MAX limits on large
        files. The content never appears in the shell command string â€”
        only the file path does.

        Args:
            path: File path to write
            content: Content to write

        Returns:
            WriteResult with bytes written or error
        úWrite denied: 'ú(' is a protected system/credential file.r  Fz	mkdir -p r   Tzcat > )rÆ   zFailed to write file: r  r  zutf-8)rH   rI   )r  r   rG   rÚ   r   r:  r  rÍ   rt   rs   rB   rÑ   r¨   rÞ   Úencode)r:   r   r    ÚparentrI   Ú	mkdir_cmdÚmkdir_resultÚ	write_cmdÚwrite_resultr   r!  rH   s               r   r‚   zShellFileOperations.write_file®  s±  € ð  × Ò  Ñ&Ô&ˆõ ˜DÑ!Ô!ð 	gÝÐ%e°tÐ%eÐ%eÐ%eÐfÑfÔfÐfõ ”—’ Ñ&Ô&ˆØˆàð 	$ØD D×$:Ò$:¸6Ñ$BÔ$BÐDÐDˆIØŸ:š: iÑ0Ô0ˆLØÔ%¨Ò*Ð*Ø#�ð <˜T×3Ò3°DÑ9Ô9Ð;Ð;ˆ	Ø—z’z )¸�zÑ@Ô@ˆàÔ! QÒ&Ð&ÝÐ%S¸lÔ>QÐ%SÐ%SÐTÑTÔTÐTð I˜d×4Ò4°TÑ:Ô:ÐHÐHÐHˆØ—j’j Ñ*Ô*ˆð	9Ý Ô 2× 8Ò 8Ñ :Ô :Ñ;Ô;ˆMˆMøÝð 	9ð 	9ð 	9Ý §¢¨wÑ 7Ô 7Ñ8Ô8ˆMˆMˆMð	9øøøõ Ø'Ø%ð
ñ 
ô 
ð 	
s   Ä&D> Ä>,E-Å,E-Frƒ   r„   r…   c           
      ó  — |                       |¦  «        }t          |¦  «        rt          d|› d�¬¦  «        S d|                      |¦  «        › d�}|                      |¦  «        }|j        dk    rt          d|› �¬¦  «        S |j        }ddlm}  |||||¦  «        \  }	}
}}|s|
dk    r@|pd	|› �}	 dd
lm	} | |||
||¦  «        z  }n# t          $ r Y nw xY wt          |¬¦  «        S |                      ||	¦  «        }|j        rt          d|j        › �¬¦  «        S d|                      |¦  «        › d�}|                      |¦  «        }|j        dk    rt          d|› �¬¦  «        S |j        |	k    r9t          d|› dt          |	¦  «        › dt          |j        ¦  «        › d�¬¦  «        S |                      ||	|¦  «        }|                      |¦  «        }t          d||g|r|                     ¦   «         nd¬¦  «        S )ai  
        Replace text in a file using fuzzy matching.

        Args:
            path: File path to modify
            old_string: Text to find (must be unique unless replace_all=True)
            new_string: Replacement text
            replace_all: If True, replace all occurrences

        Returns:
            PatchResult with diff and lint results
        rT  rU  r  rJ  r  r   r  )Úfuzzy_find_and_replacez'Could not find match for old_string in )Úformat_no_match_hintzFailed to write changes: z2Post-write verification failed: could not re-read z#Post-write verification failed for z5: on-disk content differs from intended write (wrote z chars, read back z=). The patch did not persist. Re-read the file and try again.TN)rO   rP   rQ   rT   )r  r   rN   r  rÍ   rt   rs   Útools.fuzzy_matchr]  r^  Ú	Exceptionr‚   r*   rÞ   r  Ú_check_lintr;   )r:   r   rƒ   r„   r…   r%  r&  r    r]  r	  Úmatch_countÚ	_strategyr*   Úerr_msgr^  r[  Ú
verify_cmdÚverify_resultrP   Úlint_results                       r   r‡   z!ShellFileOperations.patch_replaceè  sß  € ð × Ò  Ñ&Ô&ˆõ ˜DÑ!Ô!ð 	gÝÐ%e°tÐ%eÐ%eÐ%eÐfÑfÔfÐfð E˜$×0Ò0°Ñ6Ô6ÐDÐDÐDˆØ—j’j Ñ*Ô*ˆàÔ  AÒ%Ð%ÝÐ%C¸TÐ%CÐ%CÐDÑDÔDÐDàÔ$ˆð 	=Ð<Ð<Ð<Ð<Ð<à5KÐ5KØ�Z ¨[ñ6
ô 6
Ñ2ˆ�[ )¨Uð ð 	.�K 1Ò$Ð$ØÐOÐOÈÐOÐOˆGðØBÐBÐBÐBÐBÐBØÐ/Ð/°¸ÀjÐRYÑZÔZÑZ��øÝð ð ð Ø�ðøøøå WÐ-Ñ-Ô-Ð-à—’ t¨[Ñ9Ô9ˆØÔð 	WÝÐ%UÀÔASÐ%UÐ%UÐVÑVÔVÐVð G˜D×2Ò2°4Ñ8Ô8ÐFÐFÐFˆ
ØŸ
š
 :Ñ.Ô.ˆØÔ" aÒ'Ð'ÝÐ%`ÐZ^Ð%`Ð%`ÐaÑaÔaÐaØÔ ;Ò.Ð.ÝðM°dð Mð Må˜kÑ*Ô*ðMð Må>AÀ-ÔBVÑ>WÔ>WðMð Mð Mðñ ô ð ð ×!Ò! '¨;¸Ñ=Ô=ˆð ×&Ò& tÑ,Ô,ˆåØØØ ˜6Ø*5Ð?�×$Ò$Ñ&Ô&Ð&¸4ð	
ñ 
ô 
ð 	
s   Â5C Ã
CÃCrˆ   c                 ót   — ddl m}m}  ||¦  «        \  }}|rt          d|› �¬¦  «        S  ||| ¦  «        }|S )a¤  
        Apply a V4A format patch.
        
        V4A format:
            *** Begin Patch
            *** Update File: path/to/file.py
            @@ context hint @@
             context line
            -removed line
            +added line
            *** End Patch
        
        Args:
            patch_content: V4A format patch string
        
        Returns:
            PatchResult with changes made
        r   )Úparse_v4a_patchÚapply_v4a_operationszFailed to parse patch: r  )Útools.patch_parserri  rj  rN   )r:   rˆ   ri  rj  Ú
operationsÚparse_errorrW   s          r   rŠ   zShellFileOperations.patch_v4a8  sm   € ð( 	MÐLÐLÐLÐLÐLÐLÐLà"1 /°-Ñ"@Ô"@Ñˆ
�KØð 	NÝÐ%L¸{Ð%LÐ%LÐMÑMÔMÐMð &Ð% j°$Ñ7Ô7ˆØˆr   c                 ód  — t           j                             |¦  «        d                              ¦   «         }|t          vrt          dd|› d�¬¦  «        S t          |         }|                     ¦   «         d         }|                      |¦  «        st          d|› d�¬¦  «        S |                     d|  	                    |¦  «        ¦  «        }|  
                    |d	¬
¦  «        }t          |j        dk    |j                             ¦   «         r|j                             ¦   «         nd¬¦  «        S )zÂ
        Run syntax check on a file after editing.
        
        Args:
            path: File path to lint
        
        Returns:
            LintResult with status and any errors
        rw   TzNo linter for z files)rk   rm   r   z not availablez{file}r1  ©rÅ   r   )rO   rl   )rÚ   r   rÛ   rÜ   ÚLINTERSrj   rì   rÒ   r  r  rÍ   rt   rs   rÑ   )r:   r   rß   Ú
linter_cmdÚbase_cmdrÎ   rW   s          r   ra  zShellFileOperations._check_lintV  s-  € õ Œg×Ò˜tÑ$Ô$ QÔ'×-Ò-Ñ/Ô/ˆà•gÐÐÝ dÐ4PÀSÐ4PÐ4PÐ4PÐQÑQÔQÐQõ ˜S”\ˆ
à×#Ò#Ñ%Ô% aÔ(ˆà× Ò  Ñ*Ô*ð 	QÝ d°xÐ4OÐ4OÐ4OÐPÑPÔPÐPð × Ò  ¨4×+AÒ+AÀ$Ñ+GÔ+GÑHÔHˆØ—’˜C¨�Ñ,Ô,ˆåØÔ$¨Ò)Ø,2¬M×,?Ò,?Ñ,AÔ,AÐI�6”=×&Ò&Ñ(Ô(Ð(Àrð
ñ 
ô 
ð 	
r   r‘   r’   r   r“   r”   r•   r–   r—   c	           	      óê  — t          ||¦  «        \  }}|                      |¦  «        }|                      d|                      |¦  «        › d�¦  «        }	d|	j        v �rÝt
          j                             |¦  «        pd}
t
          j                             |¦  «        }d|› �g}|                      d|                      |
¦  «        › d�¦  «        }d|j        v �r=|�r:|                      d	|                      |
¦  «        › d
�¦  «        }|j	        dk    �r|j         
                    ¦   «         ré|                     ¦   «         }g }|j         
                    ¦   «                              d¦  «        D ]q}|sŒ|                     ¦   «         }||v s!||v s|                     |dd…         ¦  «        r3|                     t
          j                             |
|¦  «        ¦  «         Œr|r3|                     dd                     |dd…         ¦  «        z   ¦  «         t!          d                     |¦  «        d¬¦  «        S |dk    r|                      ||||¦  «        S |                      |||||||¦  «        S )a\  
        Search for content or files.
        
        Args:
            pattern: Regex (for content) or glob pattern (for files)
            path: Directory/file to search (default: cwd)
            target: "content" (grep) or "files" (glob)
            file_glob: File pattern filter for content search (e.g., "*.py")
            limit: Max results (default 50)
            offset: Skip first N results
            output_mode: "content", "files_only", or "count"
            context: Lines of context around matches
        
        Returns:
            SearchResult with matches or file list
        ztest -e z! && echo exists || echo not_foundÚ	not_foundr‘   zPath not found: ztest -d z && echo yes || echo norÐ   r*  z 2>/dev/null | head -20r   rè   Né   zSimilar paths: z, r9  z. ©r*   rb   r`   )r¸   r  rÍ   r  rs   rÚ   r   r:  r;  rt   rÑ   rÜ   rì   r÷   rî   rï   r^   Ú_search_filesÚ_search_content)r:   r“   r   r”   r•   rz   ry   r–   r—   ÚcheckrW  Úbasename_queryÚ
hint_partsÚparent_checkrB  Úlower_qÚ
candidatesÚentryÚles                      r   r™   zShellFileOperations.searchz  sœ  € õ& 4°F¸EÑBÔB‰ˆ�ð × Ò  Ñ&Ô&ˆð —
’
Ðe d×&<Ò&<¸TÑ&BÔ&BÐeÐeÐeÑfÔfˆØ˜%œ,Ð&Ñ&å”W—_’_ TÑ*Ô*Ð1¨cˆFÝœW×-Ò-¨dÑ3Ô3ˆNØ3¨TÐ3Ð3Ð4ˆJàŸ:š:ØR˜4×1Ò1°&Ñ9Ô9ÐRÐRÐRñô ˆLð ˜Ô+Ð+Ñ+°Ñ+Ø ŸJšJØT˜T×3Ò3°FÑ;Ô;ÐTÐTÐTñô �	ð Ô&¨!Ò+Ñ+°	Ô0@×0FÒ0FÑ0HÔ0HÐ+Ø,×2Ò2Ñ4Ô4�GØ!#�JØ!*Ô!1×!7Ò!7Ñ!9Ô!9×!?Ò!?ÀÑ!EÔ!Eð Kð K˜Ø$ð %Ø$Ø"Ÿ[š[™]œ]˜Ø" b˜=˜=¨B°'¨M¨M¸R¿]º]È7ÐSUÐTUÐSUÌ;Ñ=WÔ=W¨MØ&×-Ò-­b¬g¯lªl¸6À5Ñ.IÔ.IÑJÔJÐJøØ!ð Ø"×)Ò)Ø-°·	²	¸*ÀRÀaÀR¼.Ñ0IÔ0IÑIñô ð õ  Ø—i’i 
Ñ+Ô+Øðñ ô ð ð
 �WÒÐØ×%Ò% g¨t°U¸FÑCÔCÐCà×'Ò'¨°°yÀ%ÈØ(3°Wñ>ô >ð >r   c                 óH  — |                      d¦  «        sd|vr|}n|                     d¦  «        d         }|                      d¦  «        r|                      ||||¦  «        S |                      d¦  «        st	          d¬¦  «        S d}d	|                      |¦  «        › d
|› d|                      |¦  «        › d|dz   › d|› �
}|                      |d¬¦  «        }|j                             ¦   «         sTd	|                      |¦  «        › d
|› d|                      |¦  «        › d||z   › d|dz   › �
}	|                      |	d¬¦  «        }g }
|j                             ¦   «                              d¦  «        D ]�}|sŒ|                     d
d¦  «        }t          |¦  «        dk    rJ|d          
                    dd¦  «                             ¦   «         r|
                     |d         ¦  «         Œx|
                     |¦  «         ŒŽt	          |
t          |
¦  «        ¬¦  «        S )z-Search for files by name pattern (glob-like).z**/r¾   éÿÿÿÿÚrgrø   zƒFile search requires 'rg' (ripgrep) or 'find'. Install ripgrep for best results: https://github.com/BurntSushi/ripgrep#installationr  z-not -path '*/.*'zfind rQ  z -type f -name z6 -printf '%T@ %p\n' 2>/dev/null | sort -rn | tail -n +rw   z | head -n r.  ro  ú 2>/dev/null | head -n z | tail -n +rè   r/  r   r‘   r   ©r`   rb   )r÷   rì   rÒ   Ú_search_files_rgr^   r  rÍ   rs   rÑ   rÞ   r  Úisdigitrî   )r:   r“   r   rz   ry   Úsearch_patternÚhidden_excluderÎ   rW   Ú
cmd_simpler`   re   Úpartss                r   rw  z!ShellFileOperations._search_files¹  sº  € ð ×!Ò! %Ñ(Ô(ð 	4¨S¸Ð-?Ð-?Ø$ˆNˆNà$Ÿ]š]¨3Ñ/Ô/°Ô3ˆNð
 ×Ò˜TÑ"Ô"ð 	NØ×(Ò(¨¸¸uÀfÑMÔMÐMð × Ò  Ñ(Ô(ð 	ÝðKðñ ô ð ð -ˆðf�d×,Ò,¨TÑ2Ô2ð fð f°^ð fð fÐTX×TjÒTjÐkyÑTzÔTzð fð fØGMÐPQÁzðfð fØ^cðfð fˆð —’˜C¨�Ñ,Ô,ˆàŒ}×"Ò"Ñ$Ô$ð 	8ðZ ×!7Ò!7¸Ñ!=Ô!=ð Zð ZÀð Zð ZÐ_c×_uÒ_uð  wEñ  `Fô  `Fð Zð ZØ16¸±ðZð ZØMSÐVWÉZðZð ZˆJà—Z’Z 
°B�ZÑ7Ô7ˆFàˆØ”M×'Ò'Ñ)Ô)×/Ò/°Ñ5Ô5ð 	#ð 	#ˆDØð ØØ—J’J˜s AÑ&Ô&ˆEÝ�5‰zŒz˜QŠˆ 5¨¤8×#3Ò#3°C¸Ñ#<Ô#<×#DÒ#DÑ#FÔ#FˆØ—’˜U 1œXÑ&Ô&Ð&Ð&à—’˜TÑ"Ô"Ð"Ð"åØÝ˜E™
œ
ð
ñ 
ô 
ð 	
r   c                 óÄ  — d|vr|                      d¦  «        sd|› �}n|}||z   }d|                      |¦  «        › d|                      |¦  «        › d|› �}|                      |d¬¦  «        }d„ |j                             ¦   «                              d	¦  «        D ¦   «         }	|	s~d
|                      |¦  «        › d|                      |¦  «        › d|› �}
|                      |
d¬¦  «        }d„ |j                             ¦   «                              d	¦  «        D ¦   «         }	|	|||z   …         }t          |t          |	¦  «        t          |	¦  «        |k    ¬¦  «        S )ad  Search for files by name using ripgrep's --files mode.

        rg --files respects .gitignore and excludes hidden directories by
        default, and uses parallel directory traversal for ~200x speedup
        over find on wide trees.  Results are sorted by modification time
        (most recently edited first) when rg >= 13.0 supports --sortr.
        r¾   Ú*zrg --files --sortr=modified -g rQ  r„  r.  ro  c                 ó   — g | ]}|¯|‘ŒS r   r   ©r2   rD  s     r   rh   z8ShellFileOperations._search_files_rg.<locals>.<listcomp>  s   € ÐGÐGÐG˜1ÀQÐG�QÐGÐGÐGr   rè   zrg --files -g c                 ó   — g | ]}|¯|‘ŒS r   r   r�  s     r   rh   z8ShellFileOperations._search_files_rg.<locals>.<listcomp>  ó   € ÐKÐKÐK˜qÈÐK˜ÐKÐKÐKr   )r`   rb   r#   )r÷   r  rÍ   rs   rÑ   rì   r^   rÞ   )r:   r“   r   rz   ry   Úglob_patternÚfetch_limitÚ
cmd_sortedrW   Ú	all_filesÚ	cmd_plainÚpages               r   r†  z$ShellFileOperations._search_files_rgì  s®  € ð �gÐÐ g×&8Ò&8¸Ñ&=Ô&=ÐØ(˜w˜=˜=ˆLˆLà"ˆLà˜f‘nˆð'¨d×.DÒ.DÀ\Ñ.RÔ.Rð 'ð 'Ø×%Ò% dÑ+Ô+ð'ð 'à$ð'ð 'ð 	ð
 —’˜J°�Ñ3Ô3ˆØGÐG ¤× 3Ò 3Ñ 5Ô 5× ;Ò ;¸DÑ AÔ AÐGÑGÔGˆ	àð 	Lð+ ×!7Ò!7¸Ñ!EÔ!Eð +ð +Ø×)Ò)¨$Ñ/Ô/ð+ð +à(ð+ð +ð ð
 —Z’Z 	°2�ZÑ6Ô6ˆFØKÐK F¤M×$7Ò$7Ñ$9Ô$9×$?Ò$?ÀÑ$EÔ$EÐKÑKÔKˆIà˜ ¨¡Ð.Ô/ˆåØÝ˜I™œÝ˜)‘n”n¨Ò3ð
ñ 
ô 
ð 	
r   c           	      óâ   — |                       d¦  «        r|                      |||||||¦  «        S |                       d¦  «        r|                      |||||||¦  «        S t          d¬¦  «        S )z,Search for content inside files (grep-like).rƒ  ÚgrepzqContent search requires ripgrep (rg) or grep. Install ripgrep: https://github.com/BurntSushi/ripgrep#installationr  )rÒ   Ú_search_with_rgÚ_search_with_grepr^   )r:   r“   r   r•   rz   ry   r–   r—   s           r   rx  z#ShellFileOperations._search_content  s    € ð ×Ò˜TÑ"Ô"ð 	Ø×'Ò'¨°°yÀ%ÈØ(3°Wñ>ô >ð >à×Ò˜vÑ&Ô&ð 	Ø×)Ò)¨'°4¸ÀEÈ6Ø*5°wñ@ô @ð @õ  ð\ðñ ô ð r   c                 ó„	  — g d¢}|dk    r$|                      dt          |¦  «        g¦  «         |r*|                      d|                      |¦  «        g¦  «         |dk    r|                     d¦  «         n|dk    r|                     d¦  «         |                     |                      |¦  «        ¦  «         |                     |                      |¦  «        ¦  «         |dk    r||z   d	z   n||z   }	|                      d
ddt          |	¦  «        g¦  «         d                     |¦  «        }
|                      |
d¬¦  «        }|j        dk    r_|j                             ¦   «         sFt          |d¦  «        r |j
        r|j
                             ¦   «         nd}t          d|› �d¬¦  «        S |dk    rcd„ |j                             ¦   «                              d¦  «        D ¦   «         }t          |¦  «        }||||z   …         }t          ||¬¦  «        S |dk    r¾i }|j                             ¦   «                              d¦  «        D ]_}d|v rY|                     dd¦  «        }t          |¦  «        dk    r0	 t          |d         ¦  «        ||d         <   ŒO# t           $ r Y Œ[w xY wŒ`t          |t#          |                     ¦   «         ¦  «        ¬¦  «        S t'          j        d¦  «        }t'          j        d¦  «        }g }|j                             ¦   «                              d¦  «        D �]W}|r|dk    rŒ|                     |¦  «        }|rŒ|                     t-          |                     d¦  «        pd|                     d¦  «        z   t          |                     d¦  «        ¦  «        |                     d ¦  «        d!d"…         ¬#¦  «        ¦  «         Œ¯|dk    r¢|                     |¦  «        }|r‹|                     t-          |                     d¦  «        pd|                     d¦  «        z   t          |                     d¦  «        ¦  «        |                     d ¦  «        d!d"…         ¬#¦  «        ¦  «         �ŒYt          |¦  «        }||||z   …         }t          |||||z   k    ¬$¦  «        S )%zSearch using ripgrep.)rƒ  z--line-numberz--no-headingz--with-filenamer   ú-Cz--globÚ
files_onlyú-lÚcountú-céÈ   rë   Úheadú-nrQ  r.  ro  r/  ÚstderrúSearch errorúSearch failed: rv  c                 ó   — g | ]}|¯|‘ŒS r   r   r�  s     r   rh   z7ShellFileOperations._search_with_rg.<locals>.<listcomp>O  r‘  r   rè   r…  ú:rw   ©ra   rb   ú^([A-Za-z]:)?(.*?):(\d+):(.*)$ú^([A-Za-z]:)?(.*?)-(\d+)-(.*)$ú--r   ru  é   Nrx   rf   ©r_   rb   r#   )Úextendr@   r  rî   rï   rÍ   rt   rs   rÑ   Úhasattrr¥  r^   rì   rÞ   ÚrsplitrB   r¨   rÝ   Úvaluesrù   ÚcompileÚmatchrY   Úgroup©r:   r“   r   r•   rz   ry   r–   r—   Ú	cmd_partsr“  rÎ   rW   Ú	error_msgr•  Útotalr—  ra   re   r‹  Ú	_match_reÚ_ctx_rer_   rg   s                          r   rš  z#ShellFileOperations._search_with_rg(  sÜ  € ð OÐNÐNˆ	ð �QŠ;ˆ;Ø×Ò˜d¥C¨¡L¤LÐ1Ñ2Ô2Ð2ð ð 	LØ×Ò˜h¨×(>Ò(>¸yÑ(IÔ(IÐJÑKÔKÐKð ˜,Ò&Ð&Ø×Ò˜TÑ"Ô"Ð"Ð"Ø˜GÒ#Ð#Ø×Ò˜TÑ"Ô"Ð"ð 	×Ò˜×/Ò/°Ñ8Ô8Ñ9Ô9Ð9Ø×Ò˜×/Ò/°Ñ5Ô5Ñ6Ô6Ð6ð
 /6¸ªk¨k�e˜f‘n sÑ*Ð*¸uÀv¹~ˆØ×Ò˜#˜v t­S°Ñ-=Ô-=Ð>Ñ?Ô?Ð?à�hŠh�yÑ!Ô!ˆØ—’˜C¨�Ñ,Ô,ˆð Ô˜qÒ Ð ¨¬×)<Ò)<Ñ)>Ô)>Ð Ý18¸ÀÑ1JÔ1JÐpÈvÌ}Ðp˜œ×+Ò+Ñ-Ô-Ð-ÐbpˆIÝÐ&C¸	Ð&CÐ&CÐQRÐSÑSÔSÐSð ˜,Ò&Ð&ØKÐK F¤M×$7Ò$7Ñ$9Ô$9×$?Ò$?ÀÑ$EÔ$EÐKÑKÔKˆIÝ˜	‘N”NˆEØ˜V F¨U¡NÐ2Ô3ˆDÝ d¸Ð>Ñ>Ô>Ð>à˜GÒ#Ð#ØˆFØœ×+Ò+Ñ-Ô-×3Ò3°DÑ9Ô9ð !ð !�Ø˜$�;�;Ø ŸKšK¨¨QÑ/Ô/�EÝ˜5‘z”z Q’�ð!Ý/2°5¸´8©}¬}˜F 5¨¤8Ñ,Ð,øÝ)ð !ð !ð !Ø ˜Dð!øøøøå v½3¸v¿}º}¹¼Ñ;OÔ;OÐPÑPÔPÐPõ œ
Ð#DÑEÔEˆIÝ”jÐ!BÑCÔCˆGØˆGØœ×+Ò+Ñ-Ô-×3Ò3°DÑ9Ô9ð ñ �Øð ˜t tš|˜|Øð —O’O DÑ)Ô)�Øð Ø—N’N¥;ØŸgšg a™jœjÐ.¨B°!·'²'¸!±*´*Ñ<Ý$'¨¯ª°©
¬
¡O¤OØ !§¢¨¡
¤
¨4¨C¨4Ô 0ð$ñ $ô $ñ ô ð ð
 ð ˜Q’;�;ØŸš dÑ+Ô+�AØð ØŸš¥{Ø"#§'¢'¨!¡*¤*Ð"2°°a·g²g¸a±j´jÑ!@Ý(+¨A¯GªG°A©J¬J©¬Ø$%§G¢G¨A¡J¤J¨t°¨tÔ$4ð(ñ (ô (ñ ô ð ùõ ˜‘L”LˆEØ˜6 &¨5¡.Ð0Ô1ˆDÝØØ!Ø &¨5¡.Ò0ðñ ô ð s   É>JÊ
J*Ê)J*c                 ó¨	  — ddg}|                      d¦  «         |dk    r$|                     dt          |¦  «        g¦  «         |r*|                     d|                      |¦  «        g¦  «         |dk    r|                      d¦  «         n|d	k    r|                      d
¦  «         |                      |                      |¦  «        ¦  «         |                      |                      |¦  «        ¦  «         ||z   |dk    rdndz   }	|                     dddt          |	¦  «        g¦  «         d                     |¦  «        }
|                      |
d¬¦  «        }|j        dk    r_|j                             ¦   «         sFt          |d¦  «        r |j
        r|j
                             ¦   «         nd}t          d|› �d¬¦  «        S |dk    rcd„ |j                             ¦   «                              d¦  «        D ¦   «         }t          |¦  «        }||||z   …         }t          ||¬¦  «        S |d	k    r¾i }|j                             ¦   «                              d¦  «        D ]_}d|v rY|                     dd¦  «        }t          |¦  «        dk    r0	 t          |d         ¦  «        ||d         <   ŒO# t           $ r Y Œ[w xY wŒ`t          |t#          |                     ¦   «         ¦  «        ¬¦  «        S t'          j        d¦  «        }t'          j        d¦  «        }g }|j                             ¦   «                              d¦  «        D �]W}|r|dk    rŒ|                     |¦  «        }|rŒ|                      t-          |                     d¦  «        pd |                     d¦  «        z   t          |                     d!¦  «        ¦  «        |                     d"¦  «        d#d$…         ¬%¦  «        ¦  «         Œ¯|dk    r¢|                     |¦  «        }|r‹|                      t-          |                     d¦  «        pd |                     d¦  «        z   t          |                     d!¦  «        ¦  «        |                     d"¦  «        d#d$…         ¬%¦  «        ¦  «         �ŒYt          |¦  «        }||||z   …         }t          |||||z   k    ¬&¦  «        S )'zFallback search using grep.r™  z-rnHz--exclude-dir='.*'r   r�  z	--includerž  rŸ  r   r¡  r¢  rë   r£  r¤  rQ  r.  ro  r/  r¥  r¦  r§  rv  c                 ó   — g | ]}|¯|‘ŒS r   r   r�  s     r   rh   z9ShellFileOperations._search_with_grep.<locals>.<listcomp>³  r‘  r   rè   r…  r©  rw   rª  r«  r¬  r­  r   ru  r®  Nrx   rf   r¯  )rî   r°  r@   r  rï   rÍ   rt   rs   rÑ   r±  r¥  r^   rì   rÞ   r²  rB   r¨   rÝ   r³  rù   r´  rµ  rY   r¶  r·  s                          r   r›  z%ShellFileOperations._search_with_grep‹  sæ  € ð ˜VÐ$ˆ	ð 	×ÒÐ-Ñ.Ô.Ð.ð �QŠ;ˆ;Ø×Ò˜d¥C¨¡L¤LÐ1Ñ2Ô2Ð2ð ð 	OØ×Ò˜k¨4×+AÒ+AÀ)Ñ+LÔ+LÐMÑNÔNÐNð ˜,Ò&Ð&Ø×Ò˜TÑ"Ô"Ð"Ð"Ø˜GÒ#Ð#Ø×Ò˜TÑ"Ô"Ð"ð 	×Ò˜×/Ò/°Ñ8Ô8Ñ9Ô9Ð9Ø×Ò˜×/Ò/°Ñ5Ô5Ñ6Ô6Ð6ð ˜f‘n¨w¸ª{¨{¨¨ÀÑBˆØ×Ò˜#˜v t­S°Ñ-=Ô-=Ð>Ñ?Ô?Ð?à�hŠh�yÑ!Ô!ˆØ—’˜C¨�Ñ,Ô,ˆð Ô˜qÒ Ð ¨¬×)<Ò)<Ñ)>Ô)>Ð Ý18¸ÀÑ1JÔ1JÐpÈvÌ}Ðp˜œ×+Ò+Ñ-Ô-Ð-ÐbpˆIÝÐ&C¸	Ð&CÐ&CÐQRÐSÑSÔSÐSà˜,Ò&Ð&ØKÐK F¤M×$7Ò$7Ñ$9Ô$9×$?Ò$?ÀÑ$EÔ$EÐKÑKÔKˆIÝ˜	‘N”NˆEØ˜V F¨U¡NÐ2Ô3ˆDÝ d¸Ð>Ñ>Ô>Ð>à˜GÒ#Ð#ØˆFØœ×+Ò+Ñ-Ô-×3Ò3°DÑ9Ô9ð !ð !�Ø˜$�;�;Ø ŸKšK¨¨QÑ/Ô/�EÝ˜5‘z”z Q’�ð!Ý/2°5¸´8©}¬}˜F 5¨¤8Ñ,Ð,øÝ)ð !ð !ð !Ø ˜Dð!øøøøå v½3¸v¿}º}¹¼Ñ;OÔ;OÐPÑPÔPÐPõ œ
Ð#DÑEÔEˆIÝ”jÐ!BÑCÔCˆGØˆGØœ×+Ò+Ñ-Ô-×3Ò3°DÑ9Ô9ð ñ �Øð ˜t tš|˜|Øà—O’O DÑ)Ô)�Øð Ø—N’N¥;ØŸgšg a™jœjÐ.¨B°!·'²'¸!±*´*Ñ<Ý$'¨¯ª°©
¬
¡O¤OØ !§¢¨¡
¤
¨4¨C¨4Ô 0ð$ñ $ô $ñ ô ð ð
 à˜Q’;�;ØŸš dÑ+Ô+�AØð ØŸš¥{Ø"#§'¢'¨!¡*¤*Ð"2°°a·g²g¸a±j´jÑ!@Ý(+¨A¯GªG°A©J¬J©¬Ø$%§G¢G¨A¡J¤J¨t°¨tÔ$4ð(ñ (ô (ñ ô ð ùõ ˜‘L”LˆEØ˜6 &¨5¡.Ð0Ô1ˆDÝØØ!Ø &¨5¡.Ò0ðñ ô ð s   ÊJ/Ê/
J<Ê;J<r0   )NNN)rw   rš   r›   rœ   )&r<   r=   r>   r?   r@   rÃ   rB   rr   rÍ   rC   rÒ   rá   rä   rô   r  r  r  r   r|   r  r€   rG   rŒ   r�   r‚   rN   r‡   rŠ   rj   ra  r   r^   r™   rw  r†  rx  rš  r›  r   r   r   rº   rº   ;  s,  € € € € € ðð ð!2ð !2¨#ð !2ð !2ð !2ð !2ðF CGØ $ð
ð 
˜Sð 
 sð 
¸Cð 
Øð
Ø)6ð
ð 
ð 
ð 
ð@( ð (¨ð (ð (ð (ð (ðð  cð ¸3ð È$ð ð ð ð ð$'˜cð ' dð 'ð 'ð 'ð 'ð
#ð #¨ð #¸#ð #Àcð #ð #ð #ð #ð# ð #¨ð #ð #ð #ð #ðJ7 Sð 7¨Sð 7ð 7ð 7ð 7ð
	¨ð 	¸3ð 	È#ð 	ÐRUð 	ð 	ð 	ð 	ðV
ð V
˜cð V
¨3ð V
¸3ð V
Èð V
ð V
ð V
ð V
ðp2
¨3ð 2
°:ð 2
ð 2
ð 2
ð 2
ðhJ #ð J¨*ð Jð Jð Jð Jð8 ð ¨ð ð ð ð ð˜Sð  sð ¨{ð ð ð ð ð$4
˜sð 4
¨Sð 4
°[ð 4
ð 4
ð 4
ð 4
ðv +0ðN
ð N
 #ð N
°3ð N
ÀCð N
Ø#'ðN
Ø4?ðN
ð N
ð N
ð N
ð` sð ¨{ð ð ð ð ð<
 ð 
¨
ð 
ð 
ð 
ð 
ðH CLØOPØ<=ð=>ð =>˜cð =>¨ð =>¸Cð =>Ø" 3œ-ð=>Ø7:ð=>ØILð=>àð=>à69ð=>àBNð=>ð =>ð =>ð =>ð~1
 Sð 1
°ð 1
¸Cð 1
Èð 1
ÐQ]ð 1
ð 1
ð 1
ð 1
ðf)
¨ð )
°3ð )
¸sð )
ÈCð )
ÐT`ð )
ð )
ð )
ð )
ðV sð °#ð À(È3Ä-ð Ø"ðØ,/ðØ>AðØLOðØT`ðð ð ð ð"a sð a°#ð aÀ(È3Ä-ð aØ"ðaØ,/ðaØ>AðaØLOðaØT`ðað að að aðF_¨ð _°Cð _ÀHÈSÄMð _Ø!$ð_Ø.1ð_Ø@Cð_ØNQð_ØVbð_ð _ð _ð _ð _ð _r   rº   );r?   rÚ   rù   r  Úabcr   r   Údataclassesr   r   Útypingr   r   r	   r
   Úpathlibr   Úhermes_constantsr   Útools.binary_extensionsr   Úagent.file_safetyr   r   r   r   r   r   r@   rû   Ú_HOMEÚWRITE_DENIED_PATHSÚWRITE_DENIED_PREFIXESr   rC   r   r   rG   rN   rY   r^   rj   rr   rv   rã   rp  Ú	MAX_LINESÚMAX_LINE_LENGTHr  r®   r¯   r¶   r·   rB   r©   Útupler´   r¸   rº   r   r   r   ú<module>rÌ     sT  ððð ð4 
€	€	€	Ø 	€	€	€	Ø €€€Ø #Ð #Ð #Ð #Ð #Ð #Ð #Ð #Ø (Ð (Ð (Ð (Ð (Ð (Ð (Ð (Ø ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ø Ð Ð Ð Ð Ð Ø ,Ð ,Ð ,Ð ,Ð ,Ð ,Ø 5Ð 5Ð 5Ð 5Ð 5Ð 5ðð ð ð ð ð ð ð ð ð ð ð ð 	ˆˆIˆDŒI‰KŒKÑÔ€à-Ð-¨eÑ4Ô4Ð à3Ð3°EÑ:Ô:Ð ð)˜h sœmð )ð )ð )ð )ð)˜3ð ) 4ð )ð )ð )ð )ð ðUð Uð Uð Uð Uñ Uô Uñ „ðUð& ðIð Ið Ið Ið Iñ Iô Iñ „ðIð ðð ð ð ð ñ ô ñ „ðð6 ðð ð ð ð ñ ô ñ „ðð ðð ð ð ð ñ ô ñ „ðð6 ð
ð 
ð 
ð 
ð 
ñ 
ô 
ñ „ð
ð  ðð ð ð ð ñ ô ñ „ðð1ð 1ð 1ð 1ð 1�Sñ 1ô 1ð 1ðr NÐMÐMÐ ð .Ø%Ø)ØØ(ðð €ð €	Ø€Ø€ØÐ ØÐ ØÐ ØÐ ð�sð  Sð ¨Sð ð ð ð ð -@Ø+=ð/ð / cð /Ø%(ð/ØBGÈÈSÈÄ/ð/ð /ð /ð /ð& /DØ-Að/ð /¨ð /Ø'*ð/ØFKÈCÐQTÈHÄoð/ð /ð /ð /ðoð oð oð oð o˜.ñ oô oð oð oð or   