§
    ‰eîi³  ã                   óB  — U d 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	 ddl
mZ ddlmZ ddlmZmZmZ ddlmZ dd	lmZ  ej        e¦  «        Zej        ej        ej        hZd
Zdaedz  e d<   defd„Z!dZ" e#h d£¦  «        Z$dyde%de%defd„Z&dyde%de%dz  fd„Z'dyde%de%defd„Z(de%de)fd„Z*dZ+ddhZ,dyde%de%de%dz  fd„Z-de.de)fd„Z/ ej0        ¦   «         Z1i Z2e3e d<    ej0        ¦   «         Z4i Z5e3e d<   dZ6d Z7d Z8d!e3ddfd"„Z9dyde%defd#„Z:dzde%fd$„Z;d{d&e%d'ed(ede%de%f
d)„Z<dzde%fd*„Z=dyde%fd+„Z>de%de%ddfd,„Z?de%de%de%dz  fd-„Z@dyd&e%d.e%de%de%fd/„ZA	 	 	 d|d2e%d&e%d3e%d4e%d5e)d6e%de%de%fd7„ZB	 	 	 	 d}d:e%d;e%d&e%d<e%d(ed'ed=e%d>ede%de%fd?„ZCdd@lDmEZEmFZF dA„ ZGdBdCdDdEdFdGœdHdId%d%dJœdHdKddLdMœdNœd&gdOœdPœZHdQdRdDdEdSdGœdEdTdGœdUœd&d.gdOœdPœZId6dVdDdEd0d6gdWd0dXœdEdYdGœdEdZdGœdEd[dGœd\d]d1d^œdEd_dGœd`œd2gdOœdPœZJdadbdDdEdcdGœdEd.ddgded.dXœdEdfd8d^œdEdgdGœdHdhd9d^œdHdidd^œdEg dj¢dkd.dXœdHdldd^œdmœd:gdOœdPœZKdn„ ZLdo„ ZMdp„ ZNdq„ ZO eEjP        dBdreHeLeGds eQdt¦  «        ¬u¦  «          eEjP        dQdreIeMeGdvd
¬u¦  «          eEjP        d6dreJeNeGdwd
¬u¦  «          eEjP        dadreKeOeGdxd
¬u¦  «         dS )~z6File Tools Module - LLM agent file manipulation tools.é    N)ÚPath)ÚOptional)Úget_read_block_error)Úhas_binary_extension)ÚShellFileOperationsÚnormalize_read_paginationÚnormalize_search_pagination)Ú
file_state)Úredact_sensitive_texti † Ú_max_read_chars_cachedÚreturnc                  ó  — t           �t           S 	 ddlm}   | ¦   «         }|                     d¦  «        }t	          |t
          t          f¦  «        r|dk    rt          |¦  «        a t           S n# t          $ r Y nw xY wt          a t           S )zÿReturn the configured max characters per file read.

    Reads ``file_read_max_chars`` from config.yaml on first call, caches
    the result for the lifetime of the process.  Falls back to the
    built-in default if the config is missing or invalid.
    Nr   )Úload_configÚfile_read_max_chars)	r   Úhermes_cli.configr   ÚgetÚ
isinstanceÚintÚfloatÚ	ExceptionÚ_DEFAULT_MAX_READ_CHARS)r   ÚcfgÚvals      ú2/home/div/.hermes/hermes-agent/tools/file_tools.pyÚ_get_max_read_charsr   (   s¡   € õ Ð)Ý%Ð%ðØ1Ð1Ð1Ð1Ð1Ð1Øˆk‰mŒmˆØ�gŠgÐ+Ñ,Ô,ˆÝ�c�C¥˜<Ñ(Ô(ð 	*¨S°1ªW¨WÝ%(¨¡X¤XÐ"Ý)Ð)øøÝð ð ð Øˆðøøøå4ÐÝ!Ð!s   �AA. Á.
A;Á:A;i Ð >   ú/dev/ttyú	/dev/fd/0ú	/dev/fd/1ú	/dev/fd/2ú	/dev/fullú	/dev/zeroú
/dev/stdinú/dev/randomú/dev/stderrú/dev/stdoutú/dev/consoleú/dev/urandomÚdefaultÚfilepathÚtask_idc                 ó"   — t          | |¦  «        S )zsResolve a path relative to TERMINAL_CWD (the worktree base directory)
    instead of the main repository root.
    )Ú_resolve_path_for_task)r)   r*   s     r   Ú_resolve_pathr-   R   s   € õ " (¨GÑ4Ô4Ð4ó    c                 óR  — 	 ddl m}  || ¦  «        }n# t          $ r | }Y nw xY wt          5  t                               |¦  «        pt                               | ¦  «        }ddd¦  «         n# 1 swxY w Y   |�5t          t          |dd¦  «        dd¦  «        pt          |dd¦  «        }|r|S 	 ddl m}m} |5  |                     |¦  «        p|                     | ¦  «        }|�t          |dd¦  «        nd}ddd¦  «         n# 1 swxY w Y   |r|S n# t          $ r Y nw xY wdS )zCReturn the task's live terminal cwd for bookkeeping when available.r   )Ú_resolve_container_task_idNÚenvÚcwd)Ú_active_environmentsÚ	_env_lock)	Útools.terminal_toolr0   r   Ú_file_ops_lockÚ_file_ops_cacher   Úgetattrr3   r4   )r*   r0   Úcontainer_keyÚcachedÚlive_cwdr3   r4   r1   s           r   Ú_get_live_tracking_cwdr<   Y   s5  € ð ØBÐBÐBÐBÐBÐBØ2Ð2°7Ñ;Ô;ˆˆøÝð  ð  ð  Øˆˆˆð øøøõ 
ð Tð TÝ ×$Ò$ ]Ñ3Ô3ÐSµ×7JÒ7JÈ7Ñ7SÔ7SˆðTð Tð Tñ Tô Tð Tð Tð Tð Tð Tð Tøøøð Tð Tð Tð TàÐÝ�7 6¨5°$Ñ7Ô7¸ÀÑEÔEð 
ÍØ�E˜4ñJ
ô J
ˆð ð 	ØˆOð	ØGÐGÐGÐGÐGÐGÐGÐGàð 	Nð 	NØ&×*Ò*¨=Ñ9Ô9Ð^Ð=Q×=UÒ=UÐV]Ñ=^Ô=^ˆCØ47°O•w˜s E¨4Ñ0Ô0Ð0ÈˆHð	Nð 	Nð 	Nñ 	Nô 	Nð 	Nð 	Nð 	Nð 	Nð 	Nð 	Nøøøð 	Nð 	Nð 	Nð 	Nð ð 	ØˆOð	øåð ð ð Øˆðøøøð ˆ4sT   ‚ ”#¢#­5A.Á.A2Á5A2Â1
D Â;A DÃ;D ÄDÄD ÄDÄD Ä
D$Ä#D$c                 ó8  — t          | ¦  «                             ¦   «         }|                     ¦   «         sRt          |¦  «        p0t          j                             dt	          j        ¦   «         ¦  «        }t          |¦  «        |z  }|                     ¦   «         S )zFResolve *filepath* against the task's live terminal cwd when possible.ÚTERMINAL_CWD)	r   Ú
expanduserÚis_absoluter<   ÚosÚenvironr   ÚgetcwdÚresolve)r)   r*   ÚpÚbases       r   r,   r,   x   sw   € åˆX‰Œ×!Ò!Ñ#Ô#€AØ�=Š=‰?Œ?ð Ý% gÑ.Ô.ð 
µ"´*·.².Ø�BœI™KœKñ3
ô 3
ˆõ �‰JŒJ˜‰NˆØ�9Š9‰;Œ;Ðr.   c                 ó²   — t           j                             | ¦  «        }|t          v rdS |                     d¦  «        r|                     d¦  «        rdS dS )uG  Return True if the path would hang the process (infinite output or blocking input).

    Uses the *literal* path â€” no symlink resolution â€” because the model
    specifies paths directly and realpath follows symlinks all the way
    through (e.g. /dev/stdin â†’ /proc/self/fd/0 â†’ /dev/pts/0), defeating
    the check.
    Tz/proc/)z/fd/0z/fd/1z/fd/2F)rA   Úpathr?   Ú_BLOCKED_DEVICE_PATHSÚ
startswithÚendswith)r)   Ú
normalizeds     r   Ú_is_blocked_devicerM   ƒ   sf   € õ ”×#Ò# HÑ-Ô-€JØÕ*Ð*Ð*Øˆtà×Ò˜XÑ&Ô&ð ¨:×+>Ò+>Ø#ñ,ô ,ð ð ˆtØˆ5r.   )z/etc/z/boot/z/usr/lib/systemd/z/private/etc/z/private/var/z/var/run/docker.sockz/run/docker.sockc                 ó’  — 	 t          t          | |¦  «        ¦  «        }n# t          t          f$ r | }Y nw xY wt          j                             t          j                             | ¦  «        ¦  «        }d| › d�}t          D ]0}| 	                    |¦  «        s| 	                    |¦  «        r|c S Œ1|t          v s	|t          v r|S dS )zHReturn an error message if the path targets a sensitive system location.z,Refusing to write to sensitive system path: zD
Use the terminal tool with sudo if you need to modify system files.N)Ústrr,   ÚOSErrorÚ
ValueErrorrA   rH   Únormpathr?   Ú_SENSITIVE_PATH_PREFIXESrJ   Ú_SENSITIVE_EXACT_PATHS)r)   r*   ÚresolvedrL   Ú_errÚprefixs         r   Ú_check_sensitive_pathrX   Ÿ   sù   € ðÝÕ-¨h¸Ñ@Ô@ÑAÔAˆˆøÝ•ZÐ ð ð ð Øˆˆˆðøøøå”×!Ò!¥"¤'×"4Ò"4°XÑ">Ô">Ñ?Ô?€Jð	N°xð 	Nð 	Nð 	Nð 	õ +ð ð ˆØ×Ò˜vÑ&Ô&ð 	¨*×*?Ò*?ÀÑ*GÔ*Gð 	ØˆKˆKˆKð	àÕ)Ð)Ð)¨ZÕ;QÐ-QÐ-QØˆØˆ4s   ‚   6µ6Úexcc                 ó~   — t          | t          ¦  «        rdS t          | t          ¦  «        r| j        t          v rdS dS )zFReturn True for expected write denials that should not hit error logs.TF)r   ÚPermissionErrorrP   ÚerrnoÚ_EXPECTED_WRITE_ERRNOS)rY   s    r   Ú_is_expected_write_exceptionr^   ²   sB   € å�#•Ñ'Ô'ð ØˆtÝ�#•wÑÔð  C¤IÕ1GÐ$GÐ$GØˆtØˆ5r.   r7   Ú_read_trackeréô  iè  Ú	task_datac                 óŒ  — |                       d¦  «        }|�gt          |¦  «        t          k    rOt          |¦  «        t          z
  }t          |¦  «        D ](}	 |                     ¦   «          Œ# t
          $ r Y  nw xY w|                       d¦  «        }|�‰t          |¦  «        t          k    rqt          |¦  «        t          z
  }t          |¦  «        D ]J}	 |                     t          t          |¦  «        ¦  «        ¦  «         Œ3# t          t
          f$ r Y  nw xY w|                       d¦  «        }|�Št          |¦  «        t          k    rtt          |¦  «        t          z
  }t          |¦  «        D ]O}	 |                     t          t          |¦  «        ¦  «        ¦  «         Œ3# t          t
          f$ r Y  dS w xY wdS dS dS )a¬  Enforce size caps on the per-task read-tracker sub-containers.

    Must be called with ``_read_tracker_lock`` held.  Eviction policy:

      * ``read_history`` (set): pop arbitrary entries on overflow.  This
        is fine because the set only feeds diagnostic summaries; losing
        old entries just trims the summary's tail.
      * ``dedup`` / ``read_timestamps`` (dict): pop oldest by insertion
        order (Python 3.7+ dicts).  Evicted entries lose their dedup
        skip on a future re-read (the file gets re-sent once) and
        external-edit mtime comparison (the write/patch falls back to
        a non-mtime check).  Both are graceful degradations, not bugs.
    Úread_historyNÚdedupÚread_timestamps)r   ÚlenÚ_READ_HISTORY_CAPÚrangeÚpopÚKeyErrorÚ
_DEDUP_CAPÚnextÚiterÚStopIterationÚ_READ_TIMESTAMPS_CAP)ra   ÚrhÚexcessÚ_rd   Útss         r   Ú_cap_read_tracker_datart   Û   sÚ  € ð 
�Š�~Ñ	&Ô	&€BØ	€~�#˜b™'œ'Õ$5Ò5Ð5Ý�R‘”Õ,Ñ,ˆÝ�v‘”ð 	ð 	ˆAðØ—’‘”��øÝð ð ð Ø��ðøøøð �MŠM˜'Ñ"Ô"€EØÐ�S ™ZœZ­*Ò4Ð4Ý�U‘”�jÑ(ˆÝ�v‘”ð 	ð 	ˆAðØ—	’	�$�t E™{œ{Ñ+Ô+Ñ,Ô,Ð,Ð,øÝ!¥8Ð,ð ð ð Ø��ðøøøð 
�ŠÐ(Ñ	)Ô	)€BØ	€~�#˜b™'œ'Õ$8Ò8Ð8Ý�R‘”Õ/Ñ/ˆÝ�v‘”ð 	ð 	ˆAðØ—’•t�D ™HœH‘~”~Ñ&Ô&Ð&Ð&øÝ!¥8Ð,ð ð ð Ø���ðøøøð €~Ð8Ð8ð	ð 	s6   ÁA.Á.
A<Á;A<Ã/DÄDÄDÅ7/F'Æ'F=Æ<F=c                 óæ  — ddl m}m}m}m}m}m}m}m}m	}	 ddl
}
 |	| ¦  «        } t          5  t                               | ¦  «        }ddd¦  «         n# 1 swxY w Y   |�}|5  | |v r%|
 
                    ¦   «         || <   |cddd¦  «         S t          5  t                               | d¦  «         ddd¦  «         n# 1 swxY w Y   ddd¦  «         n# 1 swxY w Y   |5  | |vrt          j        ¦   «         || <   ||          }ddd¦  «         n# 1 swxY w Y   |5  |5  | |v r |
 
                    ¦   «         || <   ||          }nd}ddd¦  «         n# 1 swxY w Y   |�€Âddl m}  |¦   «         }|d         }|                     | i ¦  «        }|dk    r|                     d¦  «        p|d         }nn|dk    r|                     d	¦  «        p|d	         }nJ|d
k    r|                     d¦  «        p|d         }n&|dk    r|                     d¦  «        p|d         }nd}|                     d¦  «        p|d         }t$                               d|| dd…         ¦  «         d}|dv r–|                     dd¦  «        |                     dd¦  «        |                     dd¦  «        |                     dd¦  «        |                     dg ¦  «        |                     dd¦  «        |                     dg ¦  «        dœ}d}|d k    rl|                     d!d¦  «        |                     d"d¦  «        |                     d#d$¦  «        |                     d%d¦  «        |                     d&d¦  «        d'œ}d}|d(k    rd)|                     d*d¦  «        i} |||||d+         |||| |                     d,¦  «        ¬-¦	  «	        }|5  ||| <   |
 
                    ¦   «         || <   ddd¦  «         n# 1 swxY w Y    |¦   «          t$                               d.|| dd…         ¦  «         ddd¦  «         n# 1 swxY w Y   t)          |¦  «        }t          5  |t          | <   ddd¦  «         n# 1 swxY w Y   |S )/a£  Get or create ShellFileOperations for a terminal environment.

    Respects the TERMINAL_ENV setting -- if the task_id doesn't have an
    environment yet, creates one using the configured backend (local, docker,
    modal, etc.) rather than always defaulting to local.

    Thread-safe: uses the same per-task creation locks as terminal_tool to
    prevent duplicate sandbox creation from concurrent tool calls.

    Note: subagent task_ids are collapsed to "default" via
    ``_resolve_container_task_id`` so delegate_task children share the
    parent's container and its cached file_ops. RL/benchmark task_ids with
    a registered env override keep their isolation.
    r   )	r3   r4   Ú_create_environmentÚ_get_env_configÚ_last_activityÚ_start_cleanup_threadÚ_creation_locksÚ_creation_locks_lockr0   N)Ú_task_env_overridesÚenv_typeÚdockerÚdocker_imageÚsingularityÚsingularity_imageÚmodalÚmodal_imageÚdaytonaÚdaytona_imageÚ r2   z*Creating new %s environment for task %s...é   )r~   r€   r‚   r„   Úcontainer_cpué   Úcontainer_memoryi   Úcontainer_diski È  Úcontainer_persistentTÚdocker_volumesÚdocker_mount_cwd_to_workspaceFÚdocker_forward_env)rˆ   rŠ   r‹   rŒ   r�   rŽ   r�   ÚsshÚssh_hostÚssh_userÚssh_porté   Ússh_keyÚssh_persistent)ÚhostÚuserÚportÚkeyÚ
persistentÚlocalr›   Úlocal_persistentÚtimeoutÚhost_cwd)	r}   Úimager2   rž   Ú
ssh_configÚcontainer_configÚlocal_configr*   rŸ   z %s environment ready for task %s)r5   r3   r4   rv   rw   rx   ry   rz   r{   r0   Útimer6   r7   r   ri   Ú	threadingÚLockr|   ÚloggerÚinfor   )r*   r3   r4   rv   rw   rx   ry   rz   r{   r0   r¤   r:   Ú	task_lockÚterminal_envr|   Úconfigr}   Ú	overridesr    r2   r¢   r¡   r£   Úfile_opss                           r   Ú_get_file_opsr®     sx  € ðð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð €K€K€Kà(Ð(¨Ñ1Ô1€Gõ 
ð .ð .Ý ×$Ò$ WÑ-Ô-ˆð.ð .ð .ñ .ô .ð .ð .ð .ð .ð .ð .øøøð .ð .ð .ð .àÐØð 	7ð 	7ØÐ.Ð.Ð.Ø*.¯)ª)©+¬+�˜wÑ'Øð	7ð 	7ð 	7ð 	7ñ 	7ô 	7ð 	7ð 	7õ $ð 7ð 7Ý#×'Ò'¨°Ñ6Ô6Ð6ð7ð 7ð 7ñ 7ô 7ð 7ð 7ð 7ð 7ð 7ð 7øøøð 7ð 7ð 7ð 7ð	7ð 	7ð 	7ñ 	7ô 	7ð 	7ð 	7ð 	7ð 	7ð 	7ð 	7øøøð 	7ð 	7ð 	7ð 	7ð 
ð -ð -Ø˜/Ð)Ð)Ý'0¤~Ñ'7Ô'7ˆO˜GÑ$Ø# GÔ,ˆ	ð-ð -ð -ñ -ô -ð -ð -ð -ð -ð -ð -øøøð -ð -ð -ð -ð
 
ð KSð KSàð 	$ð 	$ØÐ.Ð.Ð.Ø*.¯)ª)©+¬+�˜wÑ'Ø3°GÔ<��à#�ð	$ð 	$ð 	$ñ 	$ô 	$ð 	$ð 	$ð 	$ð 	$ð 	$ð 	$øøøð 	$ð 	$ð 	$ð 	$ð ÑØ?Ð?Ð?Ð?Ð?Ð?à$�_Ñ&Ô&ˆFØ˜jÔ)ˆHØ+×/Ò/°¸Ñ<Ô<ˆIà˜8Ò#Ð#Ø!Ÿš nÑ5Ô5ÐO¸ÀÔ9O��Ø˜]Ò*Ð*Ø!ŸšÐ&9Ñ:Ô:ÐY¸fÐEXÔ>Y��Ø˜WÒ$Ð$Ø!Ÿš mÑ4Ô4ÐM¸¸}Ô8M��Ø˜YÒ&Ð&Ø!Ÿš oÑ6Ô6ÐQ¸&ÀÔ:Q��à�à—-’- Ñ&Ô&Ð7¨&°¬-ˆCÝ�KŠKÐDÀhÐPWÐXZÐYZÐXZÔP[Ñ\Ô\Ð\à#ÐØÐHÐHÐHà%+§Z¢Z°ÀÑ%CÔ%CØ(.¯
ª
Ð3EÀtÑ(LÔ(LØ&,§j¢jÐ1AÀ5Ñ&IÔ&IØ,2¯JªJÐ7MÈtÑ,TÔ,TØ&,§j¢jÐ1AÀ2Ñ&FÔ&FØ5;·Z²ZÐ@_ÐafÑ5gÔ5gØ*0¯*ª*Ð5IÈ2Ñ*NÔ*Nð$ð $Ð ð ˆJØ˜5Ò Ð à"ŸJšJ z°2Ñ6Ô6Ø"ŸJšJ z°2Ñ6Ô6Ø"ŸJšJ z°2Ñ6Ô6Ø!Ÿ:š: i°Ñ4Ô4Ø"(§*¢*Ð-=¸uÑ"EÔ"Eðð �
ð  ˆLØ˜7Ò"Ð"à  &§*¢*Ð-?ÀÑ"GÔ"Gð �ð /Ð.Ø!ØØØ˜yÔ)Ø%Ø!1Ø)ØØŸš JÑ/Ô/ð
ñ 
ô 
ˆLð ð 6ð 6Ø0<Ð$ WÑ-Ø*.¯)ª)©+¬+�˜wÑ'ð6ð 6ð 6ñ 6ô 6ð 6ð 6ð 6ð 6ð 6ð 6øøøð 6ð 6ð 6ð 6ð "Ð!Ñ#Ô#Ð#Ý�KŠKÐ:¸HÀgÈbÈqÈbÄkÑRÔRÐRðWKSð KSð KSñ KSô KSð KSð KSð KSð KSð KSð KSøøøð KSð KSð KSð KSõ\ # <Ñ0Ô0€HÝ	ð ,ð ,Ø#+�˜Ñ ð,ð ,ð ,ñ ,ô ,ð ,ð ,ð ,ð ,ð ,ð ,øøøð ,ð ,ð ,ð ,à€OsÌ   ­AÁAÁAÁ#CÂCÂB<Â0CÂ<C 	Ã CÃC 	ÃCÃCÃCÃ #DÄDÄDÄP.Ä'EÅP.ÅE	ÅP.ÅE	ÅI&P.Ï O)ÏP.Ï)O-	Ï-P.Ï0O-	Ï11P.Ð.P2Ð5P2ÑQ&Ñ&Q*Ñ-Q*c                 ó´   — t           5  | rt                               | d¦  «         nt                               ¦   «          ddd¦  «         dS # 1 swxY w Y   dS )z Clear the file operations cache.N)r6   r7   ri   Úclear)r*   s    r   Úclear_file_ops_cacher±   ˆ  sŸ   € å	ð $ð $Øð 	$Ý×Ò ¨Ñ.Ô.Ð.Ð.å×!Ò!Ñ#Ô#Ð#ð	$ð $ð $ñ $ô $ð $ð $ð $ð $ð $ð $ð $øøøð $ð $ð $ð $ð $ð $s   ˆ8AÁAÁAr‰   rH   ÚoffsetÚlimitc           	      ó	  — 	 t          ||¦  «        \  }}t          | ¦  «        rt          j        dd| › d�i¦  «        S t	          | |¦  «        }t          t          |¦  «        ¦  «        r6|j                             ¦   «         }t          j        dd| › d|› d�i¦  «        S t          | ¦  «        }|rt          j        d|i¦  «        S t          |¦  «        }|||f}t          5  t                               |ddt          ¦   «         i d	œ¦  «        }	|	                     d
i ¦  «                             |¦  «        }
ddd¦  «         n# 1 swxY w Y   |
�Q	 t          j                             |¦  «        }||
k    rt          j        d| ddœd¬¦  «        S n# t$          $ r Y nw xY wt'          |¦  «        }|                     | ||¦  «        }|                     ¦   «         }t-          |j        pd¦  «        }|                     dd¦  «        }t1          ¦   «         }||k    r=|                     dd¦  «        }t          j        d|d›d|d›d|› d�| ||dœd¬¦  «        S |j        r#t3          |j        ¦  «        |_        |j        |d<   |rA|t4          k    r6|dk    r0|                     d¦  «        r|                     dd|d›d�¦  «         d | ||f}t          5  d
|	vri |	d
<   |	d!                              | ||f¦  «         |	d"         |k    r|	d#xx         d$z  cc<   n
||	d"<   d$|	d#<   |	d#         }	 t          j                             |¦  «        }||	d
         |<   ||	                     d%i ¦  «        |<   n# t$          $ r Y nw xY wt9          |	¦  «         ddd¦  «         n# 1 swxY w Y   	 |d$k    p!t;          |                     d¦  «        ¦  «        }t=          j        |||¬&¦  «         n,# t@          $ r tB           "                    d'd¬(¦  «         Y nw xY w|d)k    rt          j        d*|› d+�| |d,œd¬¦  «        S |d-k    r	d.|› d/�|d0<   t          j        |d¬¦  «        S # t@          $ r&}tG          t          |¦  «        ¦  «        cY d}~S d}~ww xY w)1z-Read a file with pagination and line numbers.ÚerrorzCannot read 'zE': this is a device file that would block or produce infinite output.zCannot read binary file 'z' (zF). Use vision_analyze for images, or terminal to inspect binary files.Nr   )Úlast_keyÚconsecutiverc   rd   rd   uœ   File unchanged since last read. The content from the earlier read_file result in this conversation is still current â€” refer to that instead of re-reading.T)ÚcontentrH   rd   F©Úensure_asciir†   Ú	file_sizeÚtotal_linesÚunknownzRead produced Ú,z, characters which exceeds the safety limit (zD chars). Use offset and limit to read a smaller range. The file has z lines total.)rµ   rH   r¼   r»   r¸   éÈ   Ú	truncatedÚ_hintzThis file is large (zj bytes). Consider reading only the section you need with offset and limit to keep context usage efficient.Úreadrc   r¶   r·   r‰   re   )Úpartialzfile_state.record_read failed©Úexc_infoé   z.BLOCKED: You have read this exact file region z| times in a row. The content has NOT changed. You already have this information. STOP re-reading and proceed with your task.)rµ   rH   Úalready_readé   z%You have read this exact file region z¾ times consecutively. The content has not changed since your last read. Use the information you already have. If you are stuck in a loop, stop reading and proceed with writing or responding.Ú_warning)$r   rM   ÚjsonÚdumpsr,   r   rO   ÚsuffixÚlowerr   Ú_read_tracker_lockr_   Ú
setdefaultÚsetr   rA   rH   ÚgetmtimerP   r®   Ú	read_fileÚto_dictrf   r¸   r   r   Ú_LARGE_FILE_HINT_BYTESÚaddrt   Úboolr
   Úrecord_readr   r§   ÚdebugÚ
tool_error)rH   r²   r³   r*   Ú	_resolvedÚ_extÚblock_errorÚresolved_strÚ	dedup_keyra   Úcached_mtimeÚcurrent_mtimer­   ÚresultÚresult_dictÚcontent_lenr»   Ú	max_charsr¼   Úread_keyÚcountÚ
_mtime_nowÚ_partialÚes                           r   Úread_file_toolrê   ‘  s®  € ði"Ý1°&¸%Ñ@Ô@‰ˆ�õ
 ˜dÑ#Ô#ð 	Ý”:Øð8 Dð 8ð 8ð 8ðñ ô ð õ +¨4°Ñ9Ô9ˆ	õ  ¥ I¡¤Ñ/Ô/ð 	ØÔ#×)Ò)Ñ+Ô+ˆDÝ”:ØðZ°ð Zð Z¸ð Zð Zð Zðñ ô ð õ +¨4Ñ0Ô0ˆØð 	6Ý”:˜w¨Ð4Ñ5Ô5Ð5õ ˜9‘~”~ˆØ! 6¨5Ð1ˆ	Ýð 	Eð 	EÝ%×0Ò0°Ø °Ý #¡¤°ð;ð ;ñ ô ˆIð %Ÿ=š=¨°"Ñ5Ô5×9Ò9¸)ÑDÔDˆLð	Eð 	Eð 	Eñ 	Eô 	Eð 	Eð 	Eð 	Eð 	Eð 	Eð 	Eøøøð 	Eð 	Eð 	Eð 	Eð Ð#ðÝ "¤× 0Ò 0°Ñ >Ô >�Ø  LÒ0Ð0Ýœ:ðUð !%Ø!%ð'ð 'ð %*ð+ñ +ô +ð +ð 1øõ ð ð ð Ø�ðøøøõ ! Ñ)Ô)ˆØ×#Ò# D¨&°%Ñ8Ô8ˆØ—n’nÑ&Ô&ˆõ ˜&œ.Ð.¨BÑ/Ô/ˆØ—O’O K°Ñ3Ô3ˆ	Ý'Ñ)Ô)ˆ	Ø˜Ò"Ð"Ø%Ÿ/š/¨-¸ÑCÔCˆKÝ”:ð? [ÐNð ?ð ?Ø)2Ð?ð?ð ?ð %0ð?ð ?ð ?ð
 Ø*Ø&ð
ð 
ð "ð
#ñ 
#ô 
#ð 
#ð Œ>ð 	4Ý2°6´>ÑBÔBˆFŒNØ%+¤^ˆK˜	Ñ"ð ð 	˜)Õ&<Ò<Ð<Ø˜C’K�KØ—O’O KÑ0Ô0ð  à×"Ò" 7ð3 yÐ=ð 3ð 3ð 3ñô ð ð ˜D &¨%Ð0ˆÝð 	.ð 	.à˜iÐ'Ð'Ø%'�	˜'Ñ"Ø�nÔ%×)Ò)¨4°¸Ð*?Ñ@Ô@Ð@Ø˜Ô$¨Ò0Ð0Ø˜-Ð(Ð(Ô(¨AÑ-Ð(Ð(Ñ(Ð(à(0�	˜*Ñ%Ø+,�	˜-Ñ(Ø˜mÔ,ˆEðÝœW×-Ò-¨lÑ;Ô;�
Ø0:�	˜'Ô" 9Ñ-ØLV�	×$Ò$Ð%6¸Ñ;Ô;¸LÑIÐIøÝð ð ð Ø�ðøøøõ
 # 9Ñ-Ô-Ð-ð3	.ð 	.ð 	.ñ 	.ô 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.øøøð 	.ð 	.ð 	.ð 	.ðD	IØ š
ÐI¥t¨K¯OªO¸KÑ,HÔ,HÑ'IÔ'IˆHÝÔ" 7¨LÀ(ÐKÑKÔKÐKÐKøÝð 	Ið 	Ið 	IÝ�LŠLÐ8À4ˆLÑHÔHÐHÐHÐHð	Iøøøð �AŠ:ˆ:å”:ðBÀUð Bð Bð Bð Ø %ðð ð "ð#ñ #ô #ð #ð �aŠZˆZðc¸ð cð cð cð ˜
Ñ#õ Œz˜+°EÐ:Ñ:Ô:Ð:øÝð "ð "ð "Ý�#˜a™&œ&Ñ!Ô!Ð!Ð!Ð!Ð!Ð!Ð!øøøøð"øøøsô   ‚;Q ¾A!Q Â &Q ÃQ Ã"AEÄ8Q ÅEÅQ ÅEÅQ Å>F ÆQ Æ
FÆQ ÆFÆB9Q ÉA:Q ËANÌ+AM/Í.NÍ/
M<Í9NÍ;M<Í<NÎQ ÎNÎQ Î!NÎ"Q Î&?O& Ï%Q Ï&&PÐQ ÐPÐ&Q Ð6$Q Ñ
RÑ%RÒ RÒRc                 ó4  — t           5  | r;t                               | ¦  «        }|rd|v r|d                              ¦   «          n:t                               ¦   «         D ] }d|v r|d                              ¦   «          Œ!ddd¦  «         dS # 1 swxY w Y   dS )u²  Clear the deduplication cache for file reads.

    Called after context compression â€” the original read content has been
    summarised away, so the model needs the full content if it reads the
    same file again.  Without this, reads after compression would return
    a "file unchanged" stub pointing at content that no longer exists in
    context.

    Call with a task_id to clear just that task, or without to clear all.
    rd   N)rÎ   r_   r   r°   Úvalues©r*   ra   s     r   Úreset_file_deduprî   A  sñ   € õ 
ð /ð /Øð 	/Ý%×)Ò)¨'Ñ2Ô2ˆIØð +˜W¨	Ð1Ð1Ø˜'Ô"×(Ò(Ñ*Ô*Ð*øå*×1Ò1Ñ3Ô3ð /ð /�	Ø˜iÐ'Ð'Ø˜gÔ&×,Ò,Ñ.Ô.Ð.øð/ð /ð /ñ /ô /ð /ð /ð /ð /ð /ð /ð /øøøð /ð /ð /ð /ð /ð /s   ˆA8BÂBÂBc                 ó’   — t           5  t                               | ¦  «        }|r
d|d<   d|d<   ddd¦  «         dS # 1 swxY w Y   dS )u�  Reset consecutive read/search counter for a task.

    Called by the tool dispatcher (model_tools.py) whenever a tool OTHER
    than read_file / search_files is executed.  This ensures we only warn
    or block on *truly consecutive* repeated reads â€” if the agent does
    anything else in between (write, patch, terminal, etc.) the counter
    resets and the next read is treated as fresh.
    Nr¶   r   r·   )rÎ   r_   r   rí   s     r   Únotify_other_tool_callrð   W  s�   € õ 
ð )ð )Ý!×%Ò% gÑ.Ô.ˆ	Øð 	)Ø$(ˆI�jÑ!Ø'(ˆI�mÑ$ð	)ð )ð )ñ )ô )ð )ð )ð )ð )ð )ð )ð )øøøð )ð )ð )ð )ð )ð )s   ˆ'<¼A ÁA c                 óz  — 	 t          t          | |¦  «        ¦  «        }t          j                             |¦  «        }n# t
          t          f$ r Y dS w xY wt          5  t           	                    |¦  «        }|�(|| 
                    di ¦  «        |<   t          |¦  «         ddd¦  «         dS # 1 swxY w Y   dS )u  Record the file's current modification time after a successful write.

    Called after write_file and patch so that consecutive edits by the
    same task don't trigger false staleness warnings â€” each write
    refreshes the stored timestamp to match the file's new state.
    Nre   )rO   r,   rA   rH   rÑ   rP   rQ   rÎ   r_   r   rÏ   rt   )r)   r*   rU   rà   ra   s        r   Ú_update_read_timestamprò   g  s	  € ðÝÕ-¨h¸Ñ@Ô@ÑAÔAˆÝœ×(Ò(¨Ñ2Ô2ˆˆøÝ•ZÐ ð ð ð Øˆˆðøøøå	ð .ð .Ý!×%Ò% gÑ.Ô.ˆ	ØÐ ØDQˆI× Ò Ð!2°BÑ7Ô7¸ÑAÝ" 9Ñ-Ô-Ð-ð	.ð .ð .ñ .ô .ð .ð .ð .ð .ð .ð .ð .øøøð .ð .ð .ð .ð .ð .s"   ‚<? ¿AÁAÁAB0Â0B4Â7B4c                 óÜ  — 	 t          t          | |¦  «        ¦  «        }n# t          t          f$ r Y dS w xY wt          5  t
                               |¦  «        }|s	 ddd¦  «         dS |                     di ¦  «                             |¦  «        }ddd¦  «         n# 1 swxY w Y   |€dS 	 t          j         	                    |¦  «        }n# t          $ r Y dS w xY w||k    rd| › d�S dS )u  Check whether a file was modified since the agent last read it.

    Returns a warning string if the file is stale (mtime changed since
    the last read_file call for this task), or None if the file is fresh
    or was never read.  Does not block â€” the write still proceeds.
    Nre   z	Warning: z£ was modified since you last read it (external edit or concurrent agent). The content you read may be stale. Consider re-reading the file to verify before writing.)
rO   r,   rP   rQ   rÎ   r_   r   rA   rH   rÑ   )r)   r*   rU   ra   Ú
read_mtimerà   s         r   Ú_check_file_stalenessrõ   z  s¢  € ðÝÕ-¨h¸Ñ@Ô@ÑAÔAˆˆøÝ•ZÐ ð ð ð Øˆtˆtðøøøå	ð Hð HÝ!×%Ò% gÑ.Ô.ˆ	Øð 	ØðHð Hð Hñ Hô Hð Hð Hð Hð —]’]Ð#4°bÑ9Ô9×=Ò=¸hÑGÔGˆ
ð	Hð Hð Hñ Hô Hð Hð Hð Hð Hð Hð Høøøð Hð Hð Hð Hð
 ÐØˆtðÝœ×(Ò(¨Ñ2Ô2ˆˆøÝð ð ð Øˆtˆtðøøøà˜
Ò"Ð"ðL˜ð Lð Lð Lð	
ð
 ˆ4s5   ‚   5´5¿BÁ*)BÂB#Â&B#Â/C Ã
CÃCr¸   c                 ó¤  — t          | |¦  «        }|rt          |¦  «        S 	 	 t          t          | |¦  «        ¦  «        }n# t          $ r d}Y nw xY w|€vt          | |¦  «        }t          |¦  «        }|                     | |¦  «        }|                     ¦   «         }|r||d<   t          | |¦  «         t          j        |d¬¦  «        S t          j        |¦  «        5  t          j        ||¦  «        }	t          | |¦  «        }t          |¦  «        }|                     | |¦  «        }|                     ¦   «         }|	p|}
|
r|
|d<   t          | |¦  «         |                     d¦  «        st          j        ||¦  «         ddd¦  «         n# 1 swxY w Y   t          j        |d¬¦  «        S # t          $ r”}t#          |¦  «        r/t$                               dt)          |¦  «        j        |¦  «         n0t$                               dt)          |¦  «        j        |d¬	¦  «         t          t          |¦  «        ¦  «        cY d}~S d}~ww xY w)
zWrite content to a file.NrÉ   Fr¹   rµ   z"write_file expected denial: %s: %szwrite_file error: %s: %sTrÄ   )rX   rÙ   rO   r,   r   rõ   r®   Ú
write_filerÓ   rò   rÊ   rË   r
   Ú	lock_pathÚcheck_staler   Ú
note_writer^   r§   rØ   ÚtypeÚ__name__rµ   )rH   r¸   r*   Úsensitive_errrÚ   Ústale_warningr­   rá   râ   Úcross_warningÚeffective_warningré   s               r   Úwrite_file_toolr  ™  s³  € å)¨$°Ñ8Ô8€MØð )Ý˜-Ñ(Ô(Ð(ð,"ð	ÝÕ2°4¸ÑAÔAÑBÔBˆIˆIøÝð 	ð 	ð 	ØˆIˆIˆIð	øøøð ÐÝ1°$¸Ñ@Ô@ˆMÝ$ WÑ-Ô-ˆHØ×(Ò(¨¨wÑ7Ô7ˆFØ Ÿ.š.Ñ*Ô*ˆKØð 8Ø*7�˜JÑ'Ý" 4¨Ñ1Ô1Ð1Ý”:˜k¸Ð>Ñ>Ô>Ð>õ
 Ô! )Ñ,Ô,ð 	:ð 	:õ 'Ô2°7¸IÑFÔFˆMÝ1°$¸Ñ@Ô@ˆMÝ$ WÑ-Ô-ˆHØ×(Ò(¨¨wÑ7Ô7ˆFØ Ÿ.š.Ñ*Ô*ˆKØ -Ð >°ÐØ ð <Ø*;�˜JÑ'õ # 4¨Ñ1Ô1Ð1Ø—?’? 7Ñ+Ô+ð :ÝÔ% g¨yÑ9Ô9Ð9ð	:ð 	:ð 	:ñ 	:ô 	:ð 	:ð 	:ð 	:ð 	:ð 	:ð 	:øøøð 	:ð 	:ð 	:ð 	:õ  Œz˜+°EÐ:Ñ:Ô:Ð:øÝð "ð "ð "Ý'¨Ñ*Ô*ð 	YÝ�LŠLÐ=½tÀA¹w¼wÔ?OÐQRÑSÔSÐSÐSå�LŠLÐ3µT¸!±W´WÔ5EÀqÐSWˆLÑXÔXÐXÝ�#˜a™&œ&Ñ!Ô!Ð!Ð!Ð!Ð!Ð!Ð!øøøøð"øøøsh   ¤A ÁF1 ÁAÁF1 ÁAÁA:F1 ÃF1 Ã B$FÆF1 ÆFÆF1 ÆFÆF1 Æ1
IÆ;B	I
ÉIÉ
IÚreplaceFÚmodeÚ
old_stringÚ
new_stringÚreplace_allÚpatchc                 óð  — g }|r|                      |¦  «         | dk    r_|r]ddl}|                     d||j        ¦  «        D ]<}	|                      |	                     d¦  «                             ¦   «         ¦  «         Œ=|D ]%}
t          |
|¦  «        }|rt          |¦  «        c S Œ&	 g }t          ¦   «         }|D ]c}
	 t          t          |
|¦  «        ¦  «        }n# t          $ r d}Y nw xY w|r.||vr*|                      |¦  «         |                     |¦  «         Œd|                     ¦   «          ddlm}  |¦   «         5 }|D ])}|                     t#          j        |¦  «        ¦  «         Œ*g }i }|D ]z}
	 t          t          |
|¦  «        ¦  «        }n# t          $ r d}Y nw xY w|||
<   |rt#          j        ||¦  «        nd}|pt)          |
|¦  «        }|r|                      |¦  «         Œ{t+          |¦  «        }| dk    rU|st          d¦  «        cddd¦  «         S |�|€t          d	¦  «        cddd¦  «         S |                     ||||¦  «        }nW| dk    r3|st          d
¦  «        cddd¦  «         S |                     |¦  «        }nt          d| › �¦  «        cddd¦  «         S |                     ¦   «         }|r3t3          |¦  «        dk    r|d         nd                     |¦  «        |d<   |                     d¦  «        sA|D ]>}
t9          |
|¦  «         |                     |
¦  «        }|rt#          j        ||¦  «         Œ?ddd¦  «         n# 1 swxY w Y   |                     d¦  «        r3dt          |d         ¦  «        v rdt          |d         ¦  «        vrd|d<   t=          j        |d¬¦  «        S # t          $ r&}t          t          |¦  «        ¦  «        cY d}~S d}~ww xY w)z4Patch a file using replace mode or V4A patch format.r  r   Nz/^\*\*\*\s+(?:Update|Add|Delete)\s+File:\s*(.+)$r‰   )Ú	ExitStackr  zpath requiredz"old_string and new_string requiredzpatch content requiredzUnknown mode: z | rÉ   rµ   zCould not findz#Did you mean one of these sections?zfold_string not found. Use read_file to verify the current content, or search_files to locate the text.rÁ   Fr¹   ) ÚappendÚreÚfinditerÚ	MULTILINEÚgroupÚstriprX   rÙ   rÐ   rO   r,   r   rÕ   ÚsortÚ
contextlibr	  Úenter_contextr
   rø   rù   rõ   r®   Úpatch_replaceÚ	patch_v4arÓ   rf   Újoinr   rò   rú   rÊ   rË   )r  rH   r  r  r  r  r*   Ú_paths_to_checkÚ_reÚ_mÚ_prý   Ú_resolved_pathsÚ_seenÚ_rr	  Ú_locksÚstale_warningsÚ_path_to_resolvedÚ_crossÚ_swr­   rá   râ   ré   s                            r   Ú
patch_toolr"  Í  sŠ  € ð
 €OØð %Ø×Ò˜tÑ$Ô$Ð$Øˆw‚€˜5€ØÐÐÐØ—,’,ÐQÐSXÐZ]ÔZgÑhÔhð 	8ð 	8ˆBØ×"Ò" 2§8¢8¨A¡;¤;×#4Ò#4Ñ#6Ô#6Ñ7Ô7Ð7Ð7Øð -ð -ˆÝ-¨b°'Ñ:Ô:ˆØð 	-Ý˜mÑ,Ô,Ð,Ð,Ð,ð	-ðM"ð &(ˆÝ™%œ%ˆØ!ð 	ð 	ˆBðÝÕ/°°GÑ<Ô<Ñ=Ô=��øÝð ð ð Ø���ðøøøàð �b �o�oØ×&Ò& rÑ*Ô*Ð*Ø—	’	˜"‘”�øØ×ÒÑÔÐð
 	)Ð(Ð(Ð(Ð(Ð(ØˆY‰[Œ[ð ,	;˜FØ%ð ?ð ?�Ø×$Ò$¥ZÔ%9¸"Ñ%=Ô%=Ñ>Ô>Ð>Ð>ð )+ˆNØ02ÐØ%ð 	/ð 	/�ðÝÕ3°B¸Ñ@Ô@ÑAÔA�B�BøÝ ð ð ð Ø�B�B�Bðøøøà(*Ð! "Ñ%Ø@BÐL�Ô/°¸Ñ<Ô<Ð<È�ØÐBÕ 5°b¸'Ñ BÔ B�Øð /Ø"×)Ò)¨#Ñ.Ô.Ð.øå$ WÑ-Ô-ˆHà�yÒ Ð Øð 7Ý% oÑ6Ô6ð/,	;ð ,	;ð ,	;ð ,	;ñ ,	;ô ,	;ð ,	;ð ,	;ð0 Ð%¨Ð);Ý%Ð&JÑKÔKð3,	;ð ,	;ð ,	;ð ,	;ñ ,	;ô ,	;ð ,	;ð ,	;ð4 "×/Ò/°°jÀ*ÈkÑZÔZ��Ø˜’�Øð @Ý%Ð&>Ñ?Ô?ð;,	;ð ,	;ð ,	;ð ,	;ñ ,	;ô ,	;ð ,	;ð ,	;ð< "×+Ò+¨EÑ2Ô2��å!Ð"9°4Ð"9Ð"9Ñ:Ô:ðA,	;ð ,	;ð ,	;ð ,	;ñ ,	;ô ,	;ð ,	;ð ,	;ðD !Ÿ.š.Ñ*Ô*ˆKØð xÝ?BÀ>Ñ?RÔ?RÐVWÒ?WÐ?W¨.¸Ô*;Ð*;Ð]b×]gÒ]gÐhvÑ]wÔ]w�˜JÑ'ð —?’? 7Ñ+Ô+ð ;Ø)ð ;ð ;�BÝ*¨2¨wÑ7Ô7Ð7Ø*×.Ò.¨rÑ2Ô2�BØð ;Ý"Ô-¨g°rÑ:Ô:Ð:øðY,	;ð ,	;ð ,	;ñ ,	;ô ,	;ð ,	;ð ,	;ð ,	;ð ,	;ð ,	;ð ,	;øøøð ,	;ð ,	;ð ,	;ð ,	;ðb �?Š?˜7Ñ#Ô#ð 	Ð(8½CÀÈGÔ@TÑ<UÔ<UÐ(UÐ(UØ4½CÀÈGÔ@TÑ<UÔ<UÐUÐUðCð ˜GÑ$õ Œz˜+°EÐ:Ñ:Ô:Ð:øÝð "ð "ð "Ý�#˜a™&œ&Ñ!Ô!Ð!Ð!Ð!Ð!Ð!Ð!øøøøð"øøøs¾   Â(O Â=CÃO ÃC*Ã'O Ã)C*Ã*AO Å5MÅ8FÆMÆF%Æ"MÆ$F%Æ%A0MÈO È"MÈ4O É/MÉ0O É='MÊ$O Ê1BMÍO ÍM Í O Í#M Í$A O Ï
O5ÏO0Ï*O5Ï0O5ú.é2   ÚpatternÚtargetÚ	file_globÚoutput_modeÚcontextc	           
      ó¢  — 	 t          ||¦  «        \  }}d| |t          |¦  «        |pd||f}	t          5  t                               |ddt          ¦   «         dœ¦  «        }
|
d         |	k    r|
dxx         dz  cc<   n
|	|
d<   d|
d<   |
d         }ddd¦  «         n# 1 swxY w Y   |d	k    rt          j        d
|› d�| |dœd¬¦  «        S t          |¦  «        }| 	                    | |||||||¬¦  «        }t          |d¦  «        r:|j        D ]2}t          |d¦  «        r |j        rt          |j        ¦  «        |_        Œ3|                     ¦   «         }|dk    r	d|› d�|d<   t          j        |d¬¦  «        }|                     d¦  «        r||z   }|d|› d�z  }|S # t           $ r&}t#          t          |¦  «        ¦  «        cY d}~S d}~ww xY w)zSearch for content or files.Úsearchr†   Nr   )r¶   r·   rc   r¶   r·   r‰   rÆ   z(BLOCKED: You have run this exact search z times in a row. The results have NOT changed. You already have this information. STOP re-searching and proceed with your task.)rµ   r%  Úalready_searchedFr¹   )r%  rH   r&  r'  r³   r²   r(  r)  Úmatchesr¸   rÈ   zYou have run this exact search zY times consecutively. The results have not changed. Use the information you already have.rÉ   rÀ   z'

[Hint: Results truncated. Use offset=zC to see more, or narrow with a more specific pattern or file_glob.])r	   rO   rÎ   r_   rÏ   rÐ   rÊ   rË   r®   r+  Úhasattrr-  r¸   r   rÓ   r   r   rÙ   )r%  r&  rH   r'  r³   r²   r(  r)  r*   Ú
search_keyra   ræ   r­   rá   Úmrâ   Úresult_jsonÚnext_offsetré   s                      r   Úsearch_toolr3  -  sÞ  € ð
>"Ý3°F¸EÑBÔB‰ˆ�ð ØØÝ�‰IŒIØˆO˜ØØð
ˆ
õ  ð 		-ð 		-Ý%×0Ò0°Ø °ÅCÁEÄEð;ð ;ñ ô ˆIð ˜Ô$¨
Ò2Ð2Ø˜-Ð(Ð(Ô(¨AÑ-Ð(Ð(Ñ(Ð(à(2�	˜*Ñ%Ø+,�	˜-Ñ(Ø˜mÔ,ˆEð		-ð 		-ð 		-ñ 		-ô 		-ð 		-ð 		-ð 		-ð 		-ð 		-ð 		-øøøð 		-ð 		-ð 		-ð 		-ð �AŠ:ˆ:Ý”:ðD¸uð Dð Dð Dð #Ø$)ðð ð "ð#ñ #ô #ð #õ ! Ñ)Ô)ˆØ—’Ø $¨vÀØ °KÈð !ñ 
ô 
ˆõ �6˜9Ñ%Ô%ð 	AØ”^ð Að A�Ý˜1˜iÑ(Ô(ð A¨Q¬Yð AÝ 5°a´iÑ @Ô @�A”IøØ—n’nÑ&Ô&ˆà�AŠ:ˆ:ðV°%ð Vð Vð Vð ˜
Ñ#õ
 ”j ¸5ÐAÑAÔAˆð �?Š?˜;Ñ'Ô'ð 	XØ  5™.ˆKØð  XÀ{ð  Xð  Xð  Xñ  XˆKØÐøÝð "ð "ð "Ý�#˜a™&œ&Ñ!Ô!Ð!Ð!Ð!Ð!Ð!Ð!øøøøð"øøøsH   ‚2F ´ABÂF ÂBÂF Â"BÂ#&F Ã
CF Æ
GÆ(G	ÇGÇ	G)ÚregistryrÙ   c                  ó"   — ddl m}   | ¦   «         S )z=Lazy wrapper to avoid circular import with tools/__init__.py.r   ©Úcheck_file_requirements)Útoolsr7  r6  s    r   Ú_check_file_reqsr9  {  s#   € à-Ð-Ð-Ð-Ð-Ð-Ø"Ð"Ñ$Ô$Ð$r.   rÒ   u�  Read a text file with line numbers and pagination. Use this instead of cat/head/tail in terminal. Output format: 'LINE_NUM|CONTENT'. Suggests similar filenames if not found. Use offset and limit for large files. Reads exceeding ~100K characters are rejected; use offset and limit to read specific sections of large files. NOTE: Cannot read images or binary files â€” use vision_analyze for images.ÚobjectÚstringz8Path to the file to read (absolute, relative, or ~/path))rû   ÚdescriptionÚintegerz9Line number to start reading from (1-indexed, default: 1))rû   r<  r(   Úminimumz9Maximum number of lines to read (default: 500, max: 2000)iÐ  )rû   r<  r(   Úmaximum)rH   r²   r³   )rû   Ú
propertiesÚrequired)Únamer<  Ú
parametersr÷   uÚ   Write content to a file, completely replacing existing content. Use this instead of echo/cat heredoc in terminal. Creates parent directories automatically. OVERWRITES the entire file â€” use 'patch' for targeted edits.zWPath to the file to write (will be created if it doesn't exist, overwritten if it does)z%Complete content to write to the file)rH   r¸   ai  Targeted find-and-replace edits in files. Use this instead of sed/awk in terminal. Uses fuzzy matching (9 strategies) so minor whitespace/indentation differences won't break it. Returns a unified diff. Auto-runs syntax checks after editing.

Replace mode (default): find a unique string and replace it.
Patch mode: apply V4A multi-file patches for bulk changes.zVEdit mode: 'replace' for targeted find-and-replace, 'patch' for V4A multi-file patches)rû   Úenumr<  r(   z/File path to edit (required for 'replace' mode)z¤Text to find in the file (required for 'replace' mode). Must be unique in the file unless replace_all=true. Include enough surrounding context to ensure uniqueness.z_Replacement text (required for 'replace' mode). Can be empty string to delete the matched text.ÚbooleanzLReplace all occurrences instead of requiring a unique match (default: false))rû   r<  r(   z´V4A format patch content (required for 'patch' mode). Format:
*** Begin Patch
*** Update File: path/to/file
@@ context hint @@
 context line
-removed line
+added line
*** End Patch)r  rH   r  r  r  r  Úsearch_filesuµ  Search file contents or find files by name. Use this instead of grep/rg/find/ls in terminal. Ripgrep-backed, faster than shell equivalents.

Content search (target='content'): Regex search inside files. Output modes: full matches with line numbers, file paths only, or match counts.

File search (target='files'): Find files by glob pattern (e.g., '*.py', '*config*'). Also use this instead of ls â€” results sorted by modification time.zPRegex pattern for content search, or glob pattern (e.g., '*.py') for file searchÚfileszK'content' searches inside file contents, 'files' searches for files by namezCDirectory or file to search in (default: current working directory)zOFilter files by pattern in grep mode (e.g., '*.py' to only search Python files)z1Maximum number of results to return (default: 50)z0Skip first N results for pagination (default: 0))r¸   Ú
files_onlyræ   z‘Output format for grep mode: 'content' shows matching lines with line numbers, 'files_only' lists file paths, 'count' shows match counts per filezDNumber of context lines before and after each match (grep mode only))r%  r&  rH   r'  r³   r²   r(  r)  c                 óÎ   — |                      d¦  «        pd}t          |                       dd¦  «        |                       dd¦  «        |                       dd¦  «        |¬	¦  «        S )
Nr*   r(   rH   r†   r²   r‰   r³   r`   )rH   r²   r³   r*   )r   rê   ©ÚargsÚkwÚtids      r   Ú_handle_read_filerN  À  s_   € Ø
�&Š&�Ñ
Ô
Ð
(˜y€CÝ˜tŸxšx¨°Ñ3Ô3¸D¿HºHÀXÈqÑ<QÔ<QÐY]×YaÒYaÐbiÐknÑYoÔYoÐy|Ð}Ñ}Ô}Ð}r.   c                 ó¤   — |                      d¦  «        pd}t          |                       dd¦  «        |                       dd¦  «        |¬¦  «        S )Nr*   r(   rH   r†   r¸   )rH   r¸   r*   )r   r  rJ  s      r   Ú_handle_write_filerP  Å  sK   € Ø
�&Š&�Ñ
Ô
Ð
(˜y€CÝ §¢¨°Ñ 4Ô 4¸d¿hºhÀyÐRTÑ>UÔ>UÐ_bÐcÑcÔcÐcr.   c           
      óD  — |                      d¦  «        pd}t          |                       dd¦  «        |                       d¦  «        |                       d¦  «        |                       d¦  «        |                       dd	¦  «        |                       d
¦  «        |¬¦  «        S )Nr*   r(   r  r  rH   r  r  r  Fr  )r  rH   r  r  r  r  r*   )r   r"  rJ  s      r   Ú_handle_patchrR  Ê  s‘   € Ø
�&Š&�Ñ
Ô
Ð
(˜y€CÝØ�XŠX�f˜iÑ(Ô(¨t¯xªx¸Ñ/?Ô/?Ø—8’8˜LÑ)Ô)°d·h²h¸|Ñ6LÔ6LØ—H’H˜]¨EÑ2Ô2¸$¿(º(À7Ñ:KÔ:KÐUXðZñ Zô Zð Zr.   c                 óØ  — |                      d¦  «        pd}dddœ}|                       dd¦  «        }|                      ||¦  «        }t          |                       dd¦  «        ||                       d	d
¦  «        |                       d¦  «        |                       dd¦  «        |                       dd¦  «        |                       dd¦  «        |                       dd¦  «        |¬¦	  «	        S )Nr*   r(   r¸   rG  )ÚgrepÚfindr&  r%  r†   rH   r#  r'  r³   r$  r²   r   r(  r)  )	r%  r&  rH   r'  r³   r²   r(  r)  r*   )r   r3  )rK  rL  rM  Ú
target_mapÚ
raw_targetr&  s         r   Ú_handle_search_filesrX  Ò  sß   € Ø
�&Š&�Ñ
Ô
Ð
(˜y€CØ#¨WÐ5Ð5€JØ—’˜( IÑ.Ô.€JØ�^Š^˜J¨
Ñ3Ô3€FÝØ—’˜ BÑ'Ô'°¸T¿XºXÀfÈcÑ=RÔ=RØ—(’(˜;Ñ'Ô'¨t¯xªx¸ÀÑ/DÔ/DÈTÏXÊXÐV^Ð`aÑMbÔMbØ—H’H˜]¨IÑ6Ô6ÀÇÂÈÐTUÑ@VÔ@VÐ`cðeñ eô eð er.   Úfileu   ðŸ“–Úinf)rB  ÚtoolsetÚschemaÚhandlerÚcheck_fnÚemojiÚmax_result_size_charsu   âœ�ï¸�u   ðŸ”§u   ðŸ”Ž)r(   )N)r‰   r`   r(   )r  NNNFNr(   )r¸   r#  Nr$  r   r¸   r   r(   )RÚ__doc__r\   rÊ   ÚloggingrA   r¥   Úpathlibr   Útypingr   Úagent.file_safetyr   Útools.binary_extensionsr   Útools.file_operationsr   r   r	   r8  r
   Úagent.redactr   Ú	getLoggerrü   r§   ÚEACCESÚEPERMÚEROFSr]   r   r   r   Ú__annotations__r   rÔ   Ú	frozensetrI   rO   r-   r<   r,   rÖ   rM   rS   rT   rX   r   r^   r¦   r6   r7   ÚdictrÎ   r_   rg   rk   ro   rt   r®   r±   rê   rî   rð   rò   rõ   r  r"  r3  Útools.registryr4  rÙ   r9  ÚREAD_FILE_SCHEMAÚWRITE_FILE_SCHEMAÚPATCH_SCHEMAÚSEARCH_FILES_SCHEMArN  rP  rR  rX  Úregisterr   © r.   r   ú<module>rw     s}	  ðà <Ð <Ð <à €€€Ø €€€Ø €€€Ø 	€	€	€	Ø Ð Ð Ð Ø Ð Ð Ð Ð Ð Ø Ð Ð Ð Ð Ð à 2Ð 2Ð 2Ð 2Ð 2Ð 2Ø 8Ð 8Ð 8Ð 8Ð 8Ð 8ðð ð ð ð ð ð ð ð ð ð
 Ð Ð Ð Ð Ð Ø .Ð .Ð .Ð .Ð .Ð .à	ˆÔ	˜8Ñ	$Ô	$€ð  œ,¨¬°U´[ÐAÐ ð "Ð Ø%)Ð ˜˜d™
Ð )Ð )Ñ )ð"˜Sð "ð "ð "ð "ð0 !Ð ð "˜	ð 	#ð 	#ð 	#ñ 	ô 	Ð ð5ð 5˜Cð 5¨#ð 5¸dð 5ð 5ð 5ð 5ðð  Cð ¸¸d¹
ð ð ð ð ð>ð  Sð °3ð Àtð ð ð ð ð ð ¨ð ð ð ð ð*Ð ð 1Ð2DÐEÐ ðð  Cð °#ð ÀcÈDÁjð ð ð ð ð& ið °Dð ð ð ð ð  �”Ñ!Ô!€Ø€�Ð Ð Ñ ð" $�Y”^Ñ%Ô%Ð Ø€ˆtÐ Ð Ñ ð Ð Ø€
ØÐ ð' dð '¨tð 'ð 'ð 'ð 'ðT@ð @˜3ð @Ð/Bð @ð @ð @ð @ðF$ð $ #ð $ð $ð $ð $ðk"ð k"˜ð k" cð k"°cð k"È#ð k"Ð^að k"ð k"ð k"ð k"ð`/ð /˜cð /ð /ð /ð /ð,)ð ) Cð )ð )ð )ð )ð . Sð .°3ð .¸4ð .ð .ð .ð .ð& Cð °#ð ¸#À¹*ð ð ð ð ð>1"ð 1"˜#ð 1"¨ð 1"°cð 1"È#ð 1"ð 1"ð 1"ð 1"ðh KOØOSØ'ð]"ð ]"�Sð ]"¨Cð ]"ÀCð ]"Øð]"Ø48ð]"ØILð]"àð]"à,/ð]"ð ]"ð ]"ð ]"ð@ DGØFGØ=>Ø(ðC"ð C"˜ð C" cð C"¸Sð C"ØðC"Ø.1ðC"Ø@CðC"à ðC"à7:ðC"ð ðC"ð .1ðC"ð C"ð C"ð C"ðV 0Ð /Ð /Ð /Ð /Ð /Ð /Ð /ð%ð %ð %ð ð càà%Ð6pÐqÐqØ(Ð9tð  BCð  PQð  Rð  RØ'Ð8sð  ADð  QUð  Vð  Vð
ð 
ð
 �Hðð ðð Ð ð ð pàà%ð  7Pð  Qð  QØ (Ð9`ÐaÐað
ð 
ð ˜YÐ'ðð ðð Ð ð ð Bàà%°	¸7Ð/Cð  Umð  zCð  Dð  DØ%Ð6gÐhÐhØ#+ð  =cð  dð  dØ#+ð  =^ð  _ð  _Ø$-ð  ?Mð  Z_ð  `ð  `Ø&ð  8uð  vð  vð
ð 
ð �Hðð ðð €ð$ ð Oàà (ð  :Lð  Mð  MØ'°)¸WÐ1Eð  Wdð  qzð  {ð  {Ø%Ð6{ð  ILð  Mð  MØ"*ð  <Mð  Nð  NØ'Ð8kÐxzÐ{Ð{Ø(Ð9kÐxyÐzÐzØ$,Ð6XÐ6XÐ6Xð  j}ð  JSð  Tð  TØ )ð  ;Að  NOð  Pð  Pð	
ð 	
ð �Kðð ðð Ð ð(~ð ~ð ~ð
dð dð dð
Zð Zð Zðeð eð eð €Ô �{¨FÐ;KÐUfð  rBð  JPð  hmð  hmð  nsñ  htô  htð  uñ  uô  uð  uØ €Ô �|¨VÐ<MÐWið  uEð  MUð  mtð  uñ  uô  uð  uØ €Ô �w¨°|È]Ðeuð  ~Dð  \cð  dñ  dô  dð  dØ €Ô �~¨vÐ>QÐ[oð  {Kð  SYð  qxð  yñ  yô  yð  yð  yð  yr.   