Ë
    ãß²jé ã                   óì  — 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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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mZ ddl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)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1 ddl2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZD  ejŠ                  eF«      ZGej�                  ej’                  ej”                  hZKdZLdeMfd„ZNdeOdeMdePeOeMeQf   fd„ZRdeSdeOdeMdeMdeOf
d„ZTdZU eVh d£«      ZWdZXdeQfd„ZY ej´                  dej¶                  «      Z\ ej´                  dej¶                  «      Z]deOd eSdeOfd!„Z^d"eOdeQfd#„Z_d­d$eOd%eOez  dz  deQfd&„Z`d"eOd'eOdeOfd(„Zad®d'eOdeMfd*„Zbd+ecdeQfd,„Zd ejÊ                  «       Zfi ZgeSehd-<   d.eOd'eOfd/„Zid®d'eOdefd0„Zjd­d'eOfd1„ZkejØ                  d2fejÚ                  d3fejÜ                  d4fejÞ                  d5ffZpdeOdz  fd6„Zqd"eOdeMd7eMd'eOdeOdz  f
d8„Zrd9eSd:ePd"eOdeOfd;„Zsd<ddddd=œd9eSd'eOd"eOd>eOdeMd7eMd:ePd?eQd@eQdAeMdz  deMfdB„ZtdCed)fd"eOdeMd7eMd'eOdeOf
dD„Zud$eOd'eOdeOdz  fdE„ZvdFeweO   dGeweO   d'eOdHeQdeOdz  f
dI„ZxdFeweO   d eSd'eOdeweO   fdJ„Zyd'eOdFeweO   d eSdKeOdz  ddf
dL„ZzdMZ{dNZ|dOZ}d'eOdPeOdz  dQeOdeOdz  fdR„Z~	 	 	 d¯d"eOdeOd'eOdHeQdKeOdz  deOfdS„ZdeOdePeweO   eweO   f   eOz  fdT„Z€	 	 	 	 d°dVeOd"eOdWeOdXeOdYeQdeOd'eOdHeQdKeOdz  deOfdZ„Z�	 	 	 	 	 d±d^eOd_eOd"eOd`eOd7eMdeMdaeOdbeMdceOd'eOdeOfdd„Z‚ddelƒm„Z„m…Z… df„ Z†dgdhdidjdkdlœdmdndCdCdoœdmdpedqdrœdsœd"gdtœduœZ‡dvdwdidjdxdlœdjdydlœdzœd"dgdtœduœZˆdd{didjd|dlœdjd}dlœdjd~dlœdd€d<d�œd‚œg dƒ¢dtœduœZ‰d„ZŠdjdUdgd…dUd†œdjd‡dlœdˆœZ‹deQfd‰„ZŒdŠd‹didjdŒdlœdjdd�gdŽdd†œdjd�d[d�œdjd�dlœdmd‘d\d�œdmd’dd�œdjd]d“gd”d]d†œdjg d•¢d–dd†œdmd—dd�œd˜œ	d^gdtœduœZ�d™„ ZŽdš„ Z�d›„ Z�dœ„ Z‘d�„ Z’ e„�j&                  dgdže‡eŽe†dŸde’¬ «        e„�j&                  dvdžeˆe�e†d¡d¬¢«       d£„ Z” e„�j&                  ddže‰e�e†d¤de”¬ «        e„�j&                  dŠdže�e‘e†d¥d¬¢«       dd¦lm•Z• ddl–Z–ddl—Z—d§d¨d©dªd«œZ˜d¬„ Z™y)²zõFile Tools Module - LLM agent file manipulation tools.

Companions: ``file_tools_paths`` (task-aware resolution), ``file_tools_write_guards``
(write-side guards), ``file_tools_read_tracking`` (per-task dedup / loop-detection /
staleness state).
é    N)Ú	ExitStack)ÚPath)Úget_nt_namespace_errorÚget_read_block_error)ÚGUARDRAIL_REFUSAL_KEY)Úhas_binary_extension)Úis_background_review)ÚShellFileOperationsÚnormalize_read_paginationÚnormalize_search_pagination)ÚDEFAULT_READ_LIMITÚcount_conflict_blocks)Ú
file_state)Ú_is_secret_file_argÚredact_sensitive_text)Ú_expand_tildeÚ_path_resolution_warningÚ_resolve_base_dirÚ_resolve_path_for_task)	Ú_READ_DEDUP_STATUS_MESSAGEÚ_check_approval_required_writeÚ_check_binary_document_writeÚ_check_cross_profile_pathÚ"_check_protected_instruction_writeÚ_check_sensitive_pathÚ_is_internal_file_tool_contentÚ_stale_overwrite_blockerÚ_stale_write_refusal)Ú_bump_consecutiveÚ_cap_read_tracker_dataÚ_check_file_stalenessÚ_check_not_found_cacheÚ_file_metadataÚ_file_versionÚ_mark_full_write_baselineÚ_mark_verification_staleÚ_note_read_coverageÚ_patch_failure_lockÚ_patch_failure_trackerÚ_read_trackerÚ_read_tracker_lockÚ_record_not_foundÚ_record_patch_failureÚ_reset_patch_failuresÚ
_task_dataÚ_update_read_timestampi † Úreturnc                  ó¾   — 	 ddl m}   | «       j                  d«      }t	        |t
        t        f«      xr |dkD  }|rt        |«      S t        S # t        $ r d}Y Œ=w xY w)zýReturn ``file_read_max_chars`` from config.yaml (default on missing/invalid). No module
    cache: ``load_config_readonly`` is already mtime+path cached, and a process-lifetime slot
    would pin the launch profile's value under the multiplexed gateway.r   )Úload_config_readonlyÚfile_read_max_charsN)Úhermes_cli.configr3   ÚgetÚ	ExceptionÚ
isinstanceÚintÚfloatÚ_DEFAULT_MAX_READ_CHARS)r3   ÚvalÚvalids      ú5/home/ubuntu/.hermes/hermes-agent/tools/file_tools.pyÚ_get_max_read_charsr?   3   sa   € ðÝ:Ù"Ó$×(Ñ(Ð)>Ó?ˆô �sœS¤%˜LÓ)Ò5¨c°A©g€EÙŒ3ˆs‹8Ð9Ô"9Ð9øô ò ØŠðús   ‚A ÁAÁAÚcontentÚ	max_charsc                 ó`  — t        | «      |k  r| | r| j                  d«      dz   dfS ddfS | j                  d«      }g }d}|D ]4  }t        |«      |rdndz   }||z   |kD  r n|j                  |«       ||z  }Œ6 |s|j                  |d   d| «       dj	                  |«      t        |«      dfS )aó  Trim line-numbered ``read_file`` content to the last COMPLETE line within *max_chars*.

    Returns ``(kept_text, lines_kept, truncated)`` so the caller can offer a
    ``next_offset`` instead of rejecting the read. If not even the first line
    fits it is clamped mid-line so the read is never empty and the cursor advances.

    Ported in spirit from nearai/ironclaw#5029 (dual line/byte cap on ``read_file``). Where hermes
    previously hard-rejected an oversized read (forcing the model to guess a smaller ``limit`` and burn a
    round-trip returning nothing), this trims the content to the last *complete line* that fits within
    ``max_chars`` and reports how many lines were kept so the caller can offer a ``next_offset``
    continuation.
    Ú
é   r   FNT)ÚlenÚcountÚsplitÚappendÚjoin)r@   rA   ÚlinesÚkeptÚrunningÚlineÚadditions          r>   Ú_truncate_to_char_budgetrO   @   sË   € ô ˆ7ƒ|�yÒ Ø±G˜Ÿ™ tÓ,¨qÑ0ÀUÐJÐJÀÀUÐJÐJà�M‰M˜$Ó€EØ€DØ€GØò ˆÜ�t“9¡T¡¨qÑ1ˆØ�XÑ 	Ò)ÙØ�‰�DÔØ�8Ñ‰ðñ Ø�‰�E˜!‘H˜Z˜iÐ(Ô)Ø�9‰9�T‹?œC ›I tÐ+Ð+ó    Úresult_dictÚoffsetc                 óö   — t        ||«      \  }}}||z   }|| d<   d| d<   d| d<   || d<   d|d›d	|› d
|› d|dz
  › d|› d|› d�| d<   t        |j                  dd«      d   «      |k\  rd| d<   | dxx   dz  cc<   |S )zvTrim *content* to the char budget, annotate *result_dict* with the
    continuation hint, and return the trimmed text.r@   TÚ	truncatedÚbytesÚtruncated_byÚnext_offsetzOutput truncated at the ú,z-char read budget after z line(s) (showing lines Ú-rD   ú of z). Use offset=z to continue.ÚhintrC   r   Útruncated_lineszv Note: the first line alone exceeded the budget and was clamped mid-line; its remainder is not retrievable via offset.)rO   rE   rG   )	rQ   r@   rR   Útotal_linesrA   ÚtrimmedÚ
lines_keptÚ_rW   s	            r>   Ú_apply_char_budgetra   ^   sÓ   € ô 6°g¸yÓIÑ€GˆZ˜Ø˜:Ñ%€KØ$€K�	ÑØ#€K�ÑØ")€K�ÑØ!,€K�Ñà
" 9¨Q -Ð/GØˆ,Ð.¨v¨h°a¸Àa¹Ð7HÈØˆ-�~ k ]°-ð	Að �Ñô ˆ7�=‰=˜˜qÓ! !Ñ$Ó%¨Ò2Ø)-ˆÐ%Ñ&Ø�FÓðMñ	NÓð €NrP   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)z/fd/0z/fd/1z/fd/2z/environz/cmdlinez/mapsz/smapsz/smaps_rollupz
/numa_mapsz/memz/auxvz/pagemapc                 óf   — t        | dd«      }|€y	 ddlm} t	        ||«      S # t        $ r Y yw xY w)z¥True when *file_ops* targets the host filesystem (only then may we stat paths
    or rewrite V4A headers to host-absolute paths; sandboxes have their own namespace).ÚenvNTr   )ÚLocalEnvironment)ÚgetattrÚtools.environments.localrp   ÚImportErrorr8   )Úfile_opsro   rp   s      r>   Ú_file_ops_uses_host_pathsru   …   sF   € ô �(˜E 4Ó
(€CØ
€{ØðÝ=ô �cÐ+Ó,Ð,øô ò Ùðús   ’$ ¤	0¯0z/^(\*\*\*\s*(Update|Add|Delete)\s+File:\s*)(.+)$z-^(\*\*\*\s*Move\s+File:\s*)(.+?)\s*->\s*(.+)$ÚpatchÚpath_to_resolvedc                 ó¨   ‡‡— t        |«      s| S dt        dt        fˆfd„Št        j                  ˆfd„| «      } t        j                  ˆfd„| «      S )u  Rewrite V4A file headers to the resolved host paths (host backends only).

    The shell layer must patch the SAME files ``patch_tool`` resolved for
    locking/staleness, not re-resolve a relative header against its own cwd
    (which can differ â€” the git-worktree cwd bug).
    Úrawr1   c                 óN   •— | j                  «       } ‰j                  | «      xs | S ©N)Ústripr6   )ry   rw   s    €r>   Ú_resz/_rewrite_v4a_patch_paths_for_host.<locals>._res£   s$   ø€ Ø�i‰i‹kˆØ×#Ñ# CÓ(Ò/¨CÐ/rP   c                 óX   •— | j                  d«      ›  ‰| j                  d«      «      › �S )NrD   é   ©Úgroup©Úmr}   s    €r>   ú<lambda>z3_rewrite_v4a_patch_paths_for_host.<locals>.<lambda>§   s&   ø€ °1·7±7¸1³:°,¹tÀAÇGÁGÈAÃJÓ?OÐ>PÐ0Q€ rP   c                 óˆ   •— | j                  d«      ›  ‰| j                  d«      «      › d ‰| j                  d«      «      › �S )NrD   é   z -> r   r€   r‚   s    €r>   r„   z3_rewrite_v4a_patch_paths_for_host.<locals>.<lambda>¨   s@   ø€ °·±¸³
¨|¹DÀÇÁÈÃÓ<LÐ;MÈTÑRVÐWX×W^ÑW^Ð_`ÓWaÓRbÐQcÐ-d€ rP   )ru   ÚstrÚ_V4A_SINGLE_HEADER_REÚsubÚ_V4A_MOVE_HEADER_RE)rv   rw   rt   r}   s    ` @r>   Ú!_rewrite_v4a_patch_paths_for_hostr‹   ™   sP   ù€ ô % XÔ.Øˆð0”#ð 0œ#õ 0ô "×%Ñ%Ó&QÐSXÓY€EÜ×"Ñ"Ó#dÐfkÓlÐlrP   Úpathc                 ó´   — t         j                  j                  t        | «      «      }|t        v ry|j                  d«      xr |j                  t        «      S )zXReturn True for concrete device/fd/proc paths that can hang reads or leak process state.Tz/proc/)ÚosrŒ   Únormpathr   Ú_BLOCKED_DEVICE_PATHSÚ
startswithÚendswithÚ_BLOCKED_PROC_SUFFIXES)rŒ   Ú
normalizeds     r>   Ú_is_blocked_device_pathr•   «   sI   € ä—‘×!Ñ!¤-°Ó"5Ó6€JØÔ*Ñ*ØØ× Ñ  Ó*ÒZ¨z×/BÑ/BÔCYÓ/ZÐZrP   ÚfilepathÚbase_dirc                 ó–  — t        | «      }|�Rt        j                  j                  |«      s3t        j                  j	                  t        j
                  |«      |«      }t        j                  j                  |«      }t        |«      ryt        «       }|}t        d«      D ]¹  }	 t        j                  |«      }t        j                  j                  |«      s=t        j                  j	                  t        j                  j                  |«      |«      }t        j                  j                  |«      }t        |«      r y||v r n|j                  |«       |}Œ» 	 t        j                  j                  t        j                  j                  |«      «      }t        |«      S # t        $ r Y  ŒTw xY w# t        t        f$ r Y yw xY w)zîTrue if the path (literal, any symlink hop, or final realpath) is a blocked device.

    Literal first so /dev/stdin is caught before resolving to a terminal path;
    every symlink hop is checked so an alias cannot bypass the guard.
    Té   F)r   rŽ   rŒ   ÚisabsrI   Úfspathr�   r•   ÚsetÚrangeÚreadlinkÚOSErrorÚdirnameÚaddÚrealpathÚ
ValueError)	r–   r—   Úexpandedr”   ÚseenÚcurrentr`   ÚtargetÚresolveds	            r>   Ú_is_blocked_devicer©   ³   s_  € ô ˜XÓ&€HØÐ¤B§G¡G§M¡M°(Ô$;Ü—7‘7—<‘<¤§	¡	¨(Ó 3°XÓ>ˆÜ—‘×!Ñ! (Ó+€JÜ˜zÔ*Øä“U€DØ€GÜ�2‹Yò ˆð	Ü—[‘[ Ó)ˆFô �w‰w�}‰}˜VÔ$Ü—W‘W—\‘\¤"§'¡'§/¡/°'Ó":¸FÓCˆFÜ—‘×!Ñ! &Ó)ˆÜ" 6Ô*ÙØ�T‰>ÙØ�‰�ÔØ‰ððÜ—7‘7×#Ñ#¤B§G¡G×$4Ñ$4°ZÓ$@ÓAˆô # 8Ó,Ð,øô! ò 	Úð	ûô ”ZÐ ò Ùðús$   Â&F&Å<F6 Æ&	F3Æ2F3Æ6GÇGÚtask_idc                 óf   — 	 t        t        | |«      «      S # t        t        t        f$ r | cY S w xY w)aB  Best-effort task-cwd resolution of a search hit's path.

    Search backends may return cwd-relative paths while the process cwd differs, so both the
    read-block filter and the redaction classifier must resolve against the task cwd. An
    unresolvable path is used as-is (the raw path is still worth classifying).
    )r‡   r   rŸ   r£   ÚRuntimeError)rŒ   rª   s     r>   Ú_resolved_match_pathr­   Ø   s5   € ðÜÔ)¨$°Ó8Ó9Ð9øÜ”Z¤Ð.ò ØŠðús   ‚ —0¯0Údefaultc                 óÎ  ‡‡— dŠdt         dt        fˆˆfd„}t        | dd«      r2| j                  D �cg c]  } ||j                  «      sŒ|‘Œ c}| _        t        | dd«      r(| j
                  D �cg c]  } ||«      sŒ|‘Œ c}| _        t        | dd«      r<| j                  j                  «       D ��ci c]  \  }} ||«      sŒ||“Œ c}}| _        ‰S c c}w c c}w c c}}w )	zåRemove credential/cache/env paths from a SearchResult in-place; return the omitted count.

    Each path is resolved against the task cwd first (search backends may
    return cwd-relative paths; the process cwd can differ).
    r   rŒ   r1   c                 ó<   •— t        t        | ‰«      «      r‰dz  Šyy)NrD   FT)r   r­   )rŒ   Úomittedrª   s    €€r>   Ú_allowedz5_filter_read_blocked_search_results.<locals>._allowedí   s"   ø€ äÔ 4°T¸7Ó CÔDØ�q‰LˆGØØrP   ÚmatchesNÚfilesÚcounts)r‡   Úboolrq   r³   rŒ   r´   rµ   Úitems)Úresultrª   r²   rƒ   ÚfÚcr±   s    `    @r>   Ú#_filter_read_blocked_search_resultsr»   å   s¾   ù€ ð €Gð”sð œtö ô ˆv�y $Ô'Ø%+§^¡^ÖH ±xÀÇÁÕ7Gš!ÒHˆŒÜˆv�w Ô%Ø#)§<¡<Ö?˜a±8¸Aµ;šÒ?ˆŒÜˆv�x Ô&Ø*0¯-©-×*=Ñ*=Ó*?×O¡$ ! QÁ8ÈAÅ;˜˜A™ÓOˆŒØ€Nùò Iùâ?ùãOs#   ³CÁCÁ2CÂ CÂ6C!ÃC!Úexcc                 ón   — t        | t        «      xs$ t        | t        «      xr | j                  t        v S )zFReturn True for expected write denials that should not hit error logs.)r8   ÚPermissionErrorrŸ   ÚerrnoÚ_EXPECTED_WRITE_ERRNOS)r¼   s    r>   Ú_is_expected_write_exceptionrÁ   ý   s1   € ä�cœ?Ó+ò JÜ�3œÓ ÒH S§Y¡YÔ2HÐ%HðJrP   Ú_file_ops_cacheÚraw_task_idc                 óè  — ddl m} ddlm}m}m}m}m}m}m	}	  |«       }
|
d   } |	| «      }	  || «      }|j                  d«      xs	 |xs |
d   } ||«      r0 ||«      r(||
d   k7  rt        j                  d|||
d   «       |
d   }t        j                  d||dd	 «        ||
| ||||
«      ||
d
   | ||
| «      |dk(  rd|
j                  dd«      ind¬«      }||fS # t        $ r d}Y Œºw xY w)z³Build the terminal environment for *task_id* via the shared ``_create_configured_env``,
    so a file tool that runs before any terminal command still gets the configured backend.r   )Ú_is_container_backend)Ú_create_configured_envÚ_get_env_configÚ_is_unusable_container_cwdÚ_resolve_task_host_cwdÚ_select_imageÚget_session_cwdÚresolve_task_overridesÚenv_typeNÚcwdzaIgnoring host/relative cwd override %r for %s backend (won't exist in sandbox). Using %r instead.z*Creating new %s environment for task %s...é   ÚtimeoutÚlocalÚ
persistentÚlocal_persistentF)ÚimagerÎ   rÐ   rª   Úhost_cwdÚlocal_config)Útools.terminal_tool_configrÅ   Útools.terminal_toolrÆ   rÇ   rÈ   rÉ   rÊ   rË   rÌ   r7   r6   ÚloggerÚinfo)rÃ   rª   rÅ   rÆ   rÇ   rÈ   rÉ   rÊ   rË   rÌ   ÚconfigrÍ   Ú	overridesÚrecorded_cwdrÎ   Úterminal_envs                   r>   Ú!_create_terminal_env_for_file_opsrß     s6  € õ A÷X÷ Xñ Xñ Ó€FØ�jÑ!€HÙ& {Ó3€IðÙ& {Ó3ˆð �-‰-˜Ó
Ò
? ,Ò
?°&¸±-€Cñ ˜XÔ&Ñ+EÀcÔ+JØ�&˜‘-ÒÜ�K‰Kð>à�X˜v e™}ô.ð �U‰mˆÜ
‡K�KÐ<¸hÈÐPRÐQRÈÔTÙ)Ø�¡¨h¸	À6Ó JÐPSØ�yÑ!¨7Ù'¨°Ó<ØNVÐZaÒNa�l F§J¡JÐ/AÀ5Ó$IÑJÐgkô	€Lð �\Ð!Ð!øô5 ò ØŠðús   ®C# Ã#C1Ã0C1c                 óF  — ddl m}m}m}m}m}m}m}m}m	}	 | xs d}
 ||
«      } t        5  t        j                  | «      }ddd«       �w|5  | |v r"t        j                  «       || <   |cddd«       S t        |dd«      }|r	  ||
«      €	 |	|
|«       t        5  t        j!                  | d«       ddd«       ddd«       |5  |j#                  | t%        j&                  «       «      }ddd«       5  |5  |j                  | «      }|�t        j                  «       || <   ddd«       €Wt)        |
| «      \  }}|5  ||| <   t        j                  «       || <   ddd«        |«        t*        j-                  d|| dd «       ddd«       t/        «      }t        5  |t        | <   ddd«       |S # 1 sw Y   �ŒpxY w# t        $ r Y �Œ3w xY w# 1 sw Y   �ŒxY w# 1 sw Y   �Œ!xY w# 1 sw Y   ŒþxY w# 1 sw Y   ŒÒxY w# 1 sw Y   Œ¦xY w# 1 sw Y   Œ‰xY w# 1 sw Y   |S xY w)ao  Get or create ShellFileOperations for the task's terminal environment.

    Uses terminal_tool's per-task creation locks (no duplicate sandboxes).
    Subagent task_ids collapse to "default" (``_resolve_container_task_id``) so
    delegate_task children share the parent's container; RL/benchmark task_ids
    with a registered env override keep their isolation.
    r   )	Ú_active_environmentsÚ	_env_lockÚ_last_activityÚ_start_cleanup_threadÚ_creation_locksÚ_creation_locks_lockÚ_resolve_container_task_idrË   Úrecord_session_cwdr®   NrÎ   z %s environment ready for task %srÏ   )rØ   rá   râ   rã   rä   rå   ræ   rç   rË   rè   Ú_file_ops_lockrÂ   r6   Útimerq   r7   ÚpopÚ
setdefaultÚ	threadingÚLockrß   rÙ   rÚ   r
   )rª   rá   râ   rã   rä   rå   ræ   rç   rË   rè   rÃ   ÚcachedÚold_cwdÚ	task_lockrÞ   rÍ   rt   s                    r>   Ú_get_file_opsrò   2  s2  € ÷-÷ -õ -ð
 Ò&˜Y€KÙ(¨Ó5€Gô 
ñ .Ü ×$Ñ$ WÓ-ˆ÷.àÐØñ 	3ØÐ.Ñ.Ü*.¯)©)«+�˜wÑ'Ø÷	3ñ 	3ô ˜f e¨TÓ2ˆGÙðÙ& {Ó3Ð;Ù*¨;¸Ô@ô  ñ 3Ü×#Ñ# G¨TÔ2÷3÷'	3ð, 
ñ JØ#×.Ñ.¨w¼	¿¹Ó8HÓIˆ	÷Jð 
ñ Sàñ 	6Ø/×3Ñ3°GÓ<ˆLØÐ'Ü*.¯)©)«+�˜wÑ'÷	6ð ÐÜ%FÀ{ÐT[Ó%\Ñ"ˆH�lØñ 6Ø0<Ð$ WÑ-Ü*.¯)©)«+�˜wÑ'÷6ñ "Ô#Ü�K‰KÐ:¸HÀgÈbÈqÀkÔR÷Sô # <Ó0€HÜ	ñ ,Ø#+Œ˜Ñ ÷,à€O÷[.ñ .ûô( !ò Úðú÷3ñ 3ú÷'	3ñ 	3ú÷,Jð Jú÷
	6ð 	6ú÷6ð 6ú÷Sð Sú÷,à€Oús­   «F/ÁGÁ4GÂF<ÂGÂGÂ2GÃ%G&Ã3H
Ã6+G2Ä!H
Ä<G>Å)H
Æ
HÆ/F9Æ<	G	ÇGÇG	Ç	GÇG	ÇGÇG#Ç&G/Ç2G;	Ç7H
Ç>H	ÈH
È
HÈH c                 óD  — t         5  | rt        j                  | d«       nt        j                  «        ddd«       t        5  | rt        j                  | d«       nt        j                  «        ddd«       t        5  | rt        j                  | d«       nt        j                  «        ddd«       | r$t        j                  «       j                  | «       yt        j                  «       j                  «        y# 1 sw Y   ŒÊxY w# 1 sw Y   ŒšxY w# 1 sw Y   ŒjxY w)z=Clear file-operation state for a finished task, or all tasks.N)ré   rÂ   rë   Úclearr+   r*   r(   r)   r   Úget_registryÚforget_task)rª   s    r>   Úclear_file_ops_cacher÷   s  sÜ   € ä	ñ $ÙÜ×Ñ ¨Õ.ä×!Ñ!Ô#÷	$ô 
ñ "ÙÜ×Ñ˜g tÕ,ä×ÑÔ!÷	"ô 
ñ +ÙÜ"×&Ñ& w°Õ5ä"×(Ñ(Ô*÷	+ñ Ü×ÑÓ!×-Ñ-¨gÕ6ä×ÑÓ!×'Ñ'Õ)÷+$ð $ú÷"ð "ú÷+ð +ús#   ‡.C>Á.D
Á?.DÃ>DÄ
DÄDza FIFO (named pipe)za socketza character deviceza block devicec                 ó  ‡— 	 t        j                  t        j                  | «      «      j                  Št        j
                  ‰«      st        j                  ‰«      ryt        ˆfd„t        D «       d«      S # t        $ r Y yw xY w)a4  Human name for a non-regular file type that would hang a read, else None.

    Stat-based sibling of ``_is_blocked_device``: a FIFO/socket in a workspace
    hangs like ``/dev/zero`` but has no recognizable name. Host filesystems
    only; unstattable paths return None and flow to the normal read path.
    Nc              3   ó:   •K  — | ]  \  }} |‰«      sŒ|–— Œ y ­wr{   © )Ú.0Ú	predicateÚlabelÚmodes      €r>   ú	<genexpr>z%_special_file_kind.<locals>.<genexpr>¡  s   øè ø€ ÒVÑ+˜9 eÁiÐPTÅo”ÑVùs   ƒ”za special (non-regular) file)	rŽ   Ústatr›   Úst_moderŸ   ÚS_ISREGÚS_ISDIRÚnextÚ_SPECIAL_FILE_KINDS)rŒ   rþ   s    @r>   Ú_special_file_kindr  ”  sm   ø€ ðÜ�w‰w”r—y‘y “Ó'×/Ñ/ˆô ‡|�|�DÔœTŸ\™\¨$Ô/ØÜÓVÔ/BÔVØ.ó0ð 0øô	 ò Ùðús   ƒ2A9 Á9	BÂBÚlimitc           
      óü  ‡— ddl m}m}m}m}m}	m}
  |
t        |«      «      syt        |«      }	 |j                  t        |«      |¬«      }|j                  s|j                  € ||j                  xs d«      ‚t        j                  |j                  d¬«      } |	|t        |«      «      }|j1                  «       }t3        |«      }||z   dz
  }dj5                  ||dz
  | «      }ddlm}  |«       Št;        ˆfd„|j=                  d«      D «       «      }|r|j?                  ||«      nd||j@                  ||kD  ddœ}|d   rd|dz   › d|› dtC        ||«      › d|› d�	|d<   tE        «       }t3        |d   «      |kD  rtG        ||d   |||«       |d   r1|d   }tI        |dtK        t        |«      «      ¬«      |d<   |d   |k7  }nd}|dk(  rc|d   s^|s\|sZ|jM                  d «      sItO        t        |«      |«       tQ        t        |«      |«       tS        jT                  |t        |«      «       tW        jX                  |d¬!«      S # |t        t        j                  j                   f$ r�}t"        j%                  d| d¬	«       |j&                  j)                  «       }||v xs ||v xr |d
k7  }|r@t+        ||«      r4t        |«      j-                  d«      st/        d| › d|› d|› d�«      cY d}~S Y d}~yd}~ww xY w)"a$  Render an extractable document (.docx/.xlsx/.pdf/...) as paginated text.

    Returns the JSON result, a tool_error for an actionable extraction failure
    (size cap, encrypted, malformed), or ``None`` to fall through to the normal
    read path. Runs BEFORE the binary-extension guard.
    r   )ÚANYDOC_EXTENSIONSÚEXTRACTABLE_EXTENSIONSÚMAX_DOCUMENT_BYTESÚExtractionErrorÚextract_document_bytesÚis_extractable_documentN)Ú	max_byteszDocument bytes unavailableT)Úvalidatez!document extraction failed for %s©Úexc_infoz.ipynbzUnsupported document typeúCannot read 'ú' (u"   ): document extraction failed â€” z8. Use terminal utilities to inspect or convert the file.rD   rC   )Úget_max_line_lengthc              3   ó:   •K  — | ]  }t        |«      ‰kD  –— Œ y ­wr{   )rE   )rû   rM   Úmax_line_lengths     €r>   rÿ   z+_read_extracted_document.<locals>.<genexpr>Î  s   øè ø€ ÒX¸$œ#˜d›) oÕ5ÑXùs   ƒÚ )r@   r]   Ú	file_sizerT   Úextracted_documentrT   zUse offset=z to continue reading (showing rY   rZ   z lines)r[   r@   ©Ú	file_readÚsecret_fileFr\   ©Úensure_ascii)-Útools.read_extractr	  r
  r  r  r  r  r‡   rò   Úread_file_bytesÚerrorÚbase64_contentÚbase64Ú	b64decoder£   ÚbinasciiÚErrorrÙ   ÚdebugÚsuffixÚlowerr8   r‘   Ú
tool_errorÚ
splitlinesrE   rI   Útools.tool_output_limitsr  ÚanyrG   Ú_add_line_numbersr  Úminr?   ra   r   r   r6   r%   r0   r   Úrecord_readÚjsonÚdumps)rŒ   Ú	_resolvedrR   r  rª   r	  r
  r  r  r  r  rt   ÚbinaryÚdocument_bytesÚextracted_textr¼   Ú_doc_extÚ_binary_docrJ   r]   Úend_lineÚ	page_textr  r\   rQ   rA   ÚrenderedÚredactedr  s                               @r>   Ú_read_extracted_documentr>  ¥  s  ø€ ÷9÷ 9ñ #¤3 y£>Ô2ØÜ˜WÓ%€HðØ×)Ñ)¬#¨i«.ÐDVÐ)ÓWˆØ�<Š<˜6×0Ñ0Ð8Ù! &§,¡,Ò"NÐ2NÓOÐOÜ×)Ñ)¨&×*?Ñ*?È$ÔOˆÙ/°ÄÀIÃÓOˆð  ×%Ñ%Ó'€EÜ�e“*€KØ˜‰~ Ñ!€HØ—	‘	˜% ¨¡
¨8Ð4Ó5€IÝ<Ù)Ó+€OÜÓXÀ)Ç/Á/ÐRVÓBWÔXÓX€OáDM�8×-Ñ-¨i¸Ô@ÐSUØ"Ø×%Ñ%Ø  8Ñ+Ø"ñ$€Kð �;Òà˜( Q™,˜ð (Ø�x˜q¤ X¨{Ó!;Ð <¸DÀÀÈWðVð 	�FÑô $Ó%€IÜ
ˆ;�yÑ!Ó" YÒ.Ü˜;¨°IÑ(>ÀÈÐU^Ô_Ø�9ÒØ˜yÑ)ˆÜ!6Ø Ü+¬C°	«NÓ;ô"=ˆ�IÑð ˜yÑ)¨XÑ5‰àˆØ�!Š˜K¨Ò4¹XÙ#¨K¯O©OÐ<MÔ,Nô 	"¤# i£.°'Ô:Üœs 9›~¨wÔ7Ü×Ñ˜w¬¨I«Ô7Ü�:‰:�k°Ô6Ð6øðg œZ¬¯©×)>Ñ)>Ð?ò Ü�‰Ð8¸$ÈˆÔNð ×#Ñ#×)Ñ)Ó+ˆØÐ"3Ð3ò IØÐ.Ð.ÒG°8¸xÑ3Gð 	áœJ s¨OÔ<Ü˜C›×+Ñ+Ð,GÔHÜØ ˜v S¨¨
ð 3)Ø),¨ð .2ð2ó3õ 3ô ûðús   °A=I É$K;É,A?K6Ë+K;Ë6K;Ú	task_dataÚ	dedup_keyc                 ó  — t         5  | d   j                  |d«      dz   }|| d   |<   t        | «       ddd«       dk\  rt        d|dz   › d�f||dz   dœt        d	i¤ŽS t        j                  d
t        |d	ddœd¬«      S # 1 sw Y   ŒNxY w)z’Return the "unchanged" stub for a repeated identical read, escalating to a
    hard BLOCK after 2 stubs so weak tool-followers don't loop forever.Ú
dedup_hitsr   rD   Nr†   z8BLOCKED: You have called read_file on this exact region uâ    times and the file has NOT changed. STOP calling read_file for this path â€” the content from your earlier read_file result in this conversation is still current. Proceed with your task using the information you already have.©rŒ   Úalready_readTÚ	unchangedF)ÚstatusÚmessagerŒ   ÚdedupÚcontent_returnedr  )r+   r6   r    r+  r   r2  r3  r   )r?  r@  rŒ   Úhitss       r>   Ú_dedup_stub_or_blockrK  ï  sÉ   € ô 
ñ *Ø˜Ñ&×*Ñ*¨9°aÓ8¸1Ñ<ˆØ-1ˆ	�,Ñ 	Ñ*Ü˜yÔ)÷*ð
 ˆq‚yÜðØ  1™H˜:ð &0ð0ð-ð Ø ™ñ-ô % dÐ+ñ-ð 	-ô �:‰:ØÜ-ØØØ!ñð ôð ÷+*ð *ús   ‡,B Â B	F)r=  r:  r]   Úversion_beforeÚsnapshotÚresolved_strÚpartialr=  r:  c          
      ó   — |�|xs t        |«      nd}|duxr |dd |cxk(  xr t        |«      k(  nc }d}t        5  | d   j                  |d«       | d   j	                  |«       | d   j	                  |||f«       t        | d|||f«      }	 t        j                  j                  |«      }|| j                  di «      |<   | d	   }|rN|�L|d
k  rG|| d   |<   |j                  |«      |k(  }|s"| }|r|	�t        | ||||	|
|«      \  }}|xr | }|r|||<   |s|j                  |d«       |r|d
k\  r)| d   j                  |d«       | d   j                  |«       t        | «       ddd«       	 t        j                   ||| ¬«       |r	 ddlm}  |t-        |«      «       S S # t        $ r Y Œïw xY w# 1 sw Y   ŒPxY w# t"        $ r t$        j'                  dd¬«       Y Œ[w xY w# t"        $ r t$        j'                  dd¬«       Y S w xY w)uø  Bookkeeping after a real (non-stub) read; returns the consecutive-read count.

    Per-task tracker under the lock (stub counter, history, consecutive count,
    mtime for dedup + staleness, page coverage, and the write_file baseline once
    the task has seen every line UNREDACTED â€” in one page or by paging
    contiguously through a file too big for one; a redacted page returned a
    non-round-trippable ``Â«redacted:â€¦Â»`` sentinel, so it must not bless an
    overwrite that would persist the sentinel into a credential file). Then
    OUTSIDE our lock (no nested locking): the cross-agent registry, and the
    background-review read-mark (a FULL read of a skill file counts like
    skill_view so a follow-up skill_manage(patch) is accepted).
    NéÿÿÿÿFrB  Údedup_generation_readsÚread_historyÚreadÚread_timestampsÚfull_write_baselinesé   rH  )rO  zfile_state.record_read failedTr  r   )Ú!mark_background_review_skill_readz"background-review read-mark failed)r$   r#   r+   rë   r¡   r   rŽ   rŒ   Úgetmtimerì   rŸ   r6   r'   Údiscardr    r   r1  r7   rÙ   r(  Útools.skill_manager_guardsrX  r   )r?  rª   rŒ   rN  rR   r  r@  rO  r=  r:  r]   rL  rM  ÚversionÚstableÚcompleterF   Ú
_mtime_nowÚ	baselinesrX  s                       r>   Ú_record_successful_readra    s`  € ð  <JÐ;UˆxÒ6œ=¨Ô6Ð[_€GØ˜DÐ Òc W¨S¨b \°^Ö%cÄ~ÐVbÓGcÔ%c€FØ€HÜ	ñ *Ø�,Ñ×#Ñ# I¨tÔ4ØÐ*Ñ+×/Ñ/°	Ô:Ø�.Ñ!×%Ñ% t¨V°UÐ&;Ô<Ü! )¨f°d¸FÀEÐ-JÓKˆð	ÜŸ™×)Ñ)¨,Ó7ˆJØHRˆI× Ñ Ð!2°BÓ7¸ÑEð Ð4Ñ5ˆ	Ù�gÐ)¨e°aªiØ,:ˆI�gÑ˜yÑ)ð !—}‘} \Ó2°gÑ=ˆHÙØ&˜;�Ù˜xÐ3Ü)<Ø! <°¸&À(ÈKÐYaó*cÑ&�H˜hà#Ò4¨H¨�ÙØ*1�	˜,Ñ'ÙØ�M‰M˜,¨Ô-Ù˜ !šØ�gÑ×"Ñ" 9¨dÔ3ØÐ.Ñ/×7Ñ7¸	ÔBÜ˜yÔ)÷;*ð>EÜ×Ñ˜w¨À(¸lÕKñ ð
	Nõ UÙ-¬d°<Ó.@ÔAð €Lˆ5€LøôQ ò 	Ùð	ú÷*ð *ûôB ò EÜ�‰Ð4¸tˆÖDðEûô ò 	NÜ�L‰LÐ=ÈˆLÕMØ€Lð	NúsU   ¾AF7Â4F(ÃB$F7Å1G ÆG) Æ(	F4Æ1F7Æ3F4Æ4F7Æ7G Ç G&Ç%G&Ç) HÈHrD   c                 óà	  — 	 t        ||«      \  }}t        | d¬«      }|rt        |«      S t        | «      j	                  «       j                  «       rdn
t        |«      }t        | |¬«      rt        d| › d�«      S t        | |«      }t        t        |«      «      r,t        |«      }|�t        j                  dd| › d	|› d
�dœ«      S t        t        |«      «      }|rt        |«      S t!        | ||||«      }	|	�|	S t#        t        |«      «      r*t        d| › d|j$                  j'                  «       › d�«      S t        |«      }
t)        d|
|«      }|�|S |
||f}t*        5  t-        |«      }|d   j/                  |«      }||d   v }ddd«       t        |«      }t        |«      rt1        |
«      nd}�t3        «       s||k(  rrt5        || «      S |j7                  t        |«      r|
n| ||«      }|j9                  «       }|j/                  d«      xs d}t;        |t        «      r4|j=                  d«      r#t?        d|
|t        j                  |d¬«      «       |s|j/                  d«      rt        j                  |d¬«      S |j/                  dd«      }tA        «       }tC        |jD                  xs d«      |kD  r2tG        ||jD                  xs d||j/                  dd«      |«      |_"        d}|jD                  rF|jD                  }tI        |dtK        |
«      ¬«      |_"        |jD                  |k7  }|jD                  |d<   |jD                  r$tM        |jD                  «      }|r||d<   |› d�|d <   |r6|tN        kD  r-|d!kD  r(|j/                  d"«      r|jQ                  d d#|d$›d%�«       |j/                  d«      }|j/                  d&«      d'k(  rtS        |j/                  d(|«      «      d)z
  }n)||z   d)z
  }t;        |tR        «      r|dkD  rtU        ||«      }tW        || |
||||d)kD  xs tY        |j/                  d"«      «      |xs tY        |j/                  d*«      «      |||t[        |d+d«      ¬,«      }|d-k\  rt        d.|› d/�f| |d0œt\        di¤ŽS |d1k\  r	d2|› d3�|d4<   t        j                  |d¬«      S # 1 sw Y   �Œ4xY w# t^        $ r}t        t        |«      «      cY d}~S d}~ww xY w)5u`  Read a file with pagination and line numbers.

    Guard order: NT/device-namespace prefix (raw string, no resolution) â†’
    device-path blocklist (no I/O) â†’ stat-based special-file guard (host only)
    â†’ Hermes internal denylist â†’ document extraction â†’ binary-extension guard
    â†’ negative-result cache â†’ dedup stub â†’ real read.
    ÚRead©ÚverbN)r—   r  zE': this is a device file that would block or produce infinite output.Fú'z' is u�   , not a regular file â€” reading it would block indefinitely, so no read was attempted. Use terminal utilities if you need to interact with it.)ÚsuccessÚnotezCannot read binary file 'r  zF). Use vision_analyze for images, or terminal to inspect binary files.rT  rH  rR  r"  r  zFile not found:r  Ú	is_binaryr  r   r]   ÚunknownTr  r@   Úconflict_blocksz¬ unresolved git merge-conflict block(s) (<<<<<<< / ======= / >>>>>>>) in this range. Resolve them (keep one side or combine, delete the markers) before editing around them.Ú_hintéÈ   rT   zThis file is large (rX   zj bytes). Consider reading only the section you need with offset and limit to keep context usage efficient.rV   rU   rW   rD   r\   Ú	_snapshot)rO  r=  r:  r]   rL  rM  rW  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.rC  r   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)0r   r   r+  r   Ú
expanduserÚis_absoluter   r©   r   ru   rò   r  r2  r3  r   r‡   r>  r   r)  r*  r"   r+   r/   r6   r#   r	   rK  Ú	read_fileÚto_dictr8   r‘   r,   r?   rE   r@   ra   r   r   r   Ú_LARGE_FILE_HINT_BYTESrì   r9   r0  ra  r¶   rq   r   r7   )rŒ   rR   r  rª   Únt_errÚdevice_baser4  ÚkindÚblock_errorÚ	extractedrN  Úcached_not_foundr@  r?  Úcached_versionÚcontent_served_in_generationrt   rL  r¸   rQ   Ú_errr  rA   r=  Ú
unredactedÚ	conflictsr]   r:  rF   Úes                                 r>   Úread_file_toolr�  V  sN  € ðN"Ü1°&¸%Ó@‰ˆ�ô (¨°6Ô:ˆÙÜ˜fÓ%Ð%ä" 4›j×3Ñ3Ó5×AÑAÔC‘dÔIZÐ[bÓIcˆÜ˜d¨[Õ9ÜØ ˜vð &4ð 4ó5ð 5ô +¨4°Ó9ˆ	ô %¤]°7Ó%;Ô<Ü% iÓ0ˆDØÐÜ—z‘zØ$à˜D˜6  t fð -,ð ,ñ#.ó /ð /ô +¬3¨y«>Ó:ˆÙÜ˜kÓ*Ð*ä,¨T°9¸fÀeÈWÓUˆ	ØÐ ØÐô  ¤ I£Ô/ÜØ+¨D¨6°°Y×5EÑ5E×5KÑ5KÓ5MÐ4Nð OVð VóWð Wô ˜9“~ˆÜ1°&¸,ÈÓPÐØÐ'Ø#Ð#ð " 6¨5Ð1ˆ	Üñ 	\Ü" 7Ó+ˆIØ& wÑ/×3Ñ3°IÓ>ˆNð ,5¸	ÐBZÑ8[Ð+[Ð(÷	\ô ! Ó)ˆÜ9RÐS[Ô9\œ¨Ô5ÐbfˆØÐ&Ô/CÔ/EØ" nÒ4Ñ9UÜ'¨	°9¸dÓCÐCà×#Ñ#Ô4MÈhÔ4W¡LÐ]aÐciÐkpÓqˆØ—n‘nÓ&ˆð �‰˜wÓ'Ò-¨2ˆÜ�dœCÔ  T§_¡_Ð5FÔ%GÜ˜f l°G¼T¿Z¹ZÈÐbgÔ=hÔiÙ�;—?‘? ;Ô/Ü—:‘:˜k¸Ô>Ð>ð
  —O‘O K°Ó3ˆ	Ü'Ó)ˆ	Üˆv�~‰~Ò# Ó$ yÒ0Ü/Ø˜VŸ^™^Ò1¨r°6Ø—‘ ¨yÓ9¸9óFˆFŒNð ˆØ�>Š>ØŸ™ˆJÜ2Ø dÔ8KÈLÓ8Yô[ˆFŒNà—~‘~¨Ñ3ˆHØ%+§^¡^ˆK˜	Ñ"à�>Š>Ü-¨f¯n©nÓ=ˆIÙØ1:�Ð-Ñ.à �kð "uð uð ˜GÑ$ñ ˜)Ô&<Ò<Ø˜C’K K§O¡O°KÔ$@Ø×"Ñ" 7Ø& y° mð 43ð 3ô5ð
 "—o‘o mÓ4ˆØ�?‰?˜>Ó*¨gÒ5Ü˜;Ÿ?™?¨=¸&ÓAÓBÀQÑF‰Hà ‘~¨Ñ)ˆHÜ˜+¤sÔ+°¸a²Ü˜x¨Ó5�Ü'¨	°7¸DÀ,ÐPVÐX]Ø(1¸FÀQ¹JÒ;mÌ4ÐP[×P_ÑP_Ð`kÓPlÓKmØ19Ò1e¼TÀ+Ç/Á/ÐRcÓBdÓ=eØ19À{Ø7EÜ18¸ÀÈdÓ1SôUˆð �AŠ:ÜØ@ÀÀð H>ð >ð1ð Ø"ñ1ô )¨$Ð/ñ1ð 1ð �AŠ:à7¸°wð ?cð cð ˜
Ñ#ô �z‰z˜+°EÔ:Ð:÷e	\ñ 	\ûôf ò "Üœ#˜a›&Ó!Õ!ûð"úsu   ‚(S «AS Á;AS Ã S Ã(S Ã;=S Ä9S ÅS Å 'R9ÆA
S ÇB2S ÊHS Ò$S Ò9SÒ>S Ó	S-ÓS(Ó"S-Ó(S-c                 óL   — 	 t        t        | |«      «      S # t        $ r Y yw xY w)zHTask-resolved path string, or None when resolution fails for any reason.N)r‡   r   r7   )r–   rª   s     r>   Ú_resolve_or_nonerƒ  ñ  s,   € ðÜÔ)¨(°GÓ<Ó=Ð=øÜò Ùðús   ‚ —	#¢#ÚpathsÚcontent_pathsÚcross_profilec                 ó¾   — | D ]&  }t        ||«      xs |rdnt        ||«      }|sŒ$|c S  |D ]  }t        ||«      }|sŒ|c S  t        | |«      xs t	        | |«      S )a  Run the shared write/patch guards in order; return the first error string.

    Order matters: hard denies (sensitive path, mirror) and the corruption
    guard run before anything that could prompt the user, and ONE approval
    prompt covers every path of a multi-file patch.
    N)r   r   r   r   r   )r„  r…  rª   r†  ÚpÚerrs         r>   Ú_write_precheck_errorrŠ  ù  s„   € ð ò ˆÜ# A wÓ/ò NÙ!‰DÔ'@ÀÀGÓ'Lð 	âØŠJð	ð
 ò ˆÜ*¨1¨gÓ6ˆÚØŠJðô /¨u°gÓ>ò >Ü-¨e°WÓ=ð?rP   c                 óæ   — g }| D ]i  }|j                  |«      }|rt        j                  ||«      ndxs t        ||«      }|s|rt	        |t        |«      |«      }|sŒY|j                  |«       Œk |S )uæ   One pre-edit warning per path, in priority order: cross-agent registry
    (names the sibling subagent) > per-task staleness > workspace divergence
    (relative path resolving outside the terminal's cwd â€” the worktree-cwd bug).N)r6   r   Úcheck_staler!   r   r   rH   )r„  rw   rª   Úwarningsrˆ  ÚrÚws          r>   Ú_edit_warningsr�    sz   € ð €HØò ˆØ× Ñ  Ó#ˆÙ34ŒZ×#Ñ# G¨QÔ/¸$ÒdÔCXÐYZÐ\cÓCdˆÙ‘QÜ(¨¬D°«G°WÓ=ˆAÚØ�O‰O˜AÕðð €OrP   Ú
session_idc           	      óè   — t        | |D �cg c]  }|j                  |«      xs |‘Œ c}|¬«       |D ]9  }t        || «       |j                  |«      sŒ!t        j                  | ||   «       Œ; yc c}w )z™Post-success bookkeeping: verification-stale marker, then per path refresh
    the read stamp (no false staleness on the next edit) and record the write.)r‘  N)r&   r6   r0   r   Ú
note_write)rª   r„  rw   r‘  rˆ  s        r>   Ú_note_editedr”    su   € ô ˜WÈUÖ&SÈÐ'7×';Ñ';¸AÓ'>Ò'CÀ!Ñ'CÒ&SÐ`jÕkØò @ˆÜ˜q 'Ô*Ø×Ñ Õ"Ü×!Ñ! 'Ð+;¸AÑ+>Õ?ñ@ùò 'Ts   ‹A/
i N  gš™™™™™é?i€ r¨   Únew_contentc                 ó¸  — |rt         t        |«      cxk  r	t        k  sy y	 t        | «      j	                  |«      }t        |dd«      }t        |dd«      st        |t        «      sy	 t         t        |«      cxk  r	t        k  sy y|j                  «       |j                  «       }}|syddl
m} t         ||«       ||«      z  j                  «       «      }|t        t        |«      t        |«      «      z  }	|	t        k  ryt        t        |«      t        |«      «      |z
  }
|d›dt        |«      d›d|	d	›d
|
d›dt        |«      d›d�
S # t        $ r Y yw xY w)aÙ  Return a hint when ``new_content`` mostly re-sends what is already at ``resolved``.

    Reads the OLD content through the task's own file ops (``read_file_raw``, the sandbox/remote
    backend the write targets), never the host path: on a remote backend the host file is a
    different file, and a host FIFO at that path would block the write lock forever. Bounded size
    and a line multiset comparison (linear) instead of a sequence diff (quadratic on repeated lines).Nr@   r"  r   )ÚCounterrX   rZ   z lines were already on disk (z.0%z unchanged); ~z( line(s) actually changed. Re-sending a z”-char file costs output tokens for every unchanged line; for edits like this use patch (old_string/new_string), which sends only the changed region.)Ú_REWRITE_HINT_MIN_CHARSrE   Ú_REWRITE_HINT_MAX_CHARSrò   Úread_file_rawrq   r8   r‡   r7   r,  Úcollectionsr—  ÚsumÚvaluesÚmaxÚ_REWRITE_HINT_MIN_UNCHANGED)rª   r¨   r•  r¸   ÚoldÚ	old_linesÚ	new_linesr—  rE  ÚratioÚchangeds              r>   Ú_whole_file_rewrite_hintr¥  3  sq  € ñ Ô3´s¸;Ó7GÔbÔKbÒbØð cØðÜ˜wÓ'×5Ñ5°hÓ?ˆÜ�f˜i¨Ó.ˆÜ�6˜7 DÔ)´¸CÄÔ1EØð 2Fô $¤s¨3£xÔJÔ3JÒJØð KØØŸ>™>Ó+¨[×-CÑ-CÓ-Eˆy€IÙØÝ#Ü‘W˜YÓ'©'°)Ó*<Ñ<×DÑDÓFÓG€IØœœC 	›N¬C°	«NÓ;Ñ;€EØÔ*Ò*ØÜ”#�i“.¤# i£.Ó1°IÑ=€Gà�Qˆ-�tœC 	›N¨1Ð-Ð-JÈ5ÐQTÈ+ÐUcÐdkÐlmÐcnð o2Ü25°kÓ2BÀ1Ð1Eð Fvð	vðøô ò Ùðús   £AE Å	EÅEc           
      ó´  — t        | |«      xs< t        | |«      xs. t        | g|«      xs t        | g|«      xs |rdnt	        | |«      }|st        |«      rd}|rt        |«      S 	 t        | |«      }| |i}t        «       5 }|r$|j                  t        j                  |«      «       t        | ||«      }	|	r+t        j                  t        | |	|«      d¬«      cddd«       S t!        | g||«      }
t#        |||«      }t%        |«      j'                  |xs | |«      }|j)                  «       }|
r|
d   |d<   |r|j+                  d«      s||d<   |r||d	<   |j+                  d«      rt-        | |«       n/|r|g|d
<   t/        ||t1        |dd«      «       t3        || g||«       ddd«       t        j                  d¬«      S # 1 sw Y   Œ xY w# t4        $ r€}t7        |«      r+t8        j;                  dt=        |«      j>                  |«       n,t8        jA                  dt=        |«      j>                  |d¬«       t        tC        |«      «      cY d}~S d}~ww xY w)uò   Write content to a file.

    ``cross_profile`` bypasses the sandbox-mirror lost-write guards only
    (unadvertised in the schema; the mirror rejection error teaches it â€” the
    cross-PROFILE guard it was named for no longer exists).
    Nz¡Refusing to write internal read_file display text as file content. Strip read_file line-number prefixes or reconstruct the intended file contents before writing.Fr  r   ro  r"  r[   Úresolved_pathÚfiles_modifiedÚ_content_sha256z"write_file expected denial: %s: %szwrite_file error: %s: %sTr  )"r   r   r   r   r   r   r+  rƒ  r   Úenter_contextr   Ú	lock_pathr   r2  r3  r   r�  r¥  rò   Ú
write_filers  r6   r0   r%   rq   r”  r7   rÁ   rÙ   r(  ÚtypeÚ__name__r"  r‡   )rŒ   r@   rª   r†  r‘  r‰  r4  rw   Ú_lockÚblockerr�  Úrewrite_hintr¸   rQ   r€  s                  r>   Úwrite_file_toolr²  U  sb  € ô !  wÓ/ò TÜ*¨4°Ó9òTä0°$°¸ÓAòTô -¨d¨V°WÓ=òTñ %‰tÔ*CÀDÈ'Ó*Rð	 ñ
 Ô1°'Ô:ð/ˆñ Ü˜#‹Ðð+"ô % T¨7Ó3ˆ	Ø  )Ð,ÐÜ‹[ð 	L˜EÙð ×#Ñ#¤J×$8Ñ$8¸Ó$CÔDô /¨t°YÀÓHˆGÙÜ—z‘zÔ"6°t¸WÀiÓ"PÐ_dÔe÷	Lñ 	Lô & t fÐ.>ÀÓHˆHÜ3°G¸YÈÓPˆLÜ" 7Ó+×6Ñ6°yÒ7HÀDÈ'ÓRˆFØ Ÿ.™.Ó*ˆKÙØ*2°1©+�˜JÑ'Ù K§O¡O°GÔ$<Ø&2�˜FÑ#Ùð 09�˜OÑ,Ø�‰˜wÔ'Ü& t¨WÕ5áØ5>°K�KÐ 0Ñ1ô .¨i¸Ä'È&ÐRcÐeiÓBjÔkÜ˜W t fÐ.>À
ÔK÷?	Lô@ �z‰z˜+°EÔ:Ð:÷A	Lð 	LûôB ò "Ü'¨Ô*Ü�L‰LÐ=¼tÀA»w×?OÑ?OÐQRÕSä�L‰LÐ3´T¸!³W×5EÑ5EÀqÐSWˆLÔXÜœ#˜a›&Ó!Õ!ûð"úsE   Á(G ÂAGÃ	G Ã#C GÆ#G ÇGÇG Ç	IÇA5IÉIÉIc           	      ó  — ddl m} t        j                  | «      D �cg c]&  }|j	                  d«      |j	                  d«      dv f‘Œ( }}|t
        j                  | «      D ��cg c]-  }|j	                  d«      |j	                  d«      fD ]  }|df‘Œ Œ/ c}}z  }g }g }|D ]S  \  }}|j                  «       }	 ||	«      rt        d|	›d�«      c S |j                  |	«       |sŒC|j                  |	«       ŒU ||fS c c}w c c}}w )	a{  Extract every path named in V4A headers, rejecting ``..`` traversal.

    Returns ``(all_paths, content_write_paths)`` or a tool_error string. Header
    paths come from patch CONTENT (more attacker-influenceable than ``path=``,
    which keeps its legitimate ``..`` use). Move headers check BOTH endpoints;
    only Update/Add write text and feed the binary-document guard.
    r   )Úhas_traversal_componentr   r†   )ÚUpdateÚAddFz*V4A patch header contains '..' traversal: zš. Use the agent's cwd-relative path (no '..') or an absolute path in '*** Update File:' / '*** Add File:' / '*** Delete File:' / '*** Move File:' headers.)	Útools.path_securityr´  rˆ   Úfinditerr�   rŠ   r|   r+  rH   )
rv   r´  rƒ   ÚheadersÚgr„  r…  ry   Úwrites_textÚv4a_paths
             r>   Ú_collect_v4a_header_pathsr½  ˜  s  € õ <äF[×FdÑFdÐejÓFkÖlÀ�—‘˜“
˜AŸG™G A›JÐ*;Ð;Ò<Ðl€GÐlØÔ$7×$@Ñ$@ÀÓ$G×j˜qÐRS×RYÑRYÐZ[ÓR\Ð^_×^eÑ^eÐfgÓ^hÐQiÒjÈA��E’
Ðj�
ÓjÑj€GØ€EØ!€MØ#ò 
+Ñˆˆ[Ø—9‘9“;ˆÙ" 8Ô,ÜØ<¸X¸Lð IAð AóBò Bð
 	�‰�XÔÚØ× Ñ  Õ*ð
+ð �-ÐÐùò mùÛjs   ž+C<Á$2DÚreplacerþ   Ú
old_stringÚ
new_stringÚreplace_allc	                 óJ  — |r|gng }	t        |	«      }
| dk(  r/|r-t        |«      }t        |t        «      r|S |	|d   z  }	|
|d   z  }
t	        |	|
||«      }|rt        |«      S 	 |	D �ci c]  }|t        ||«      “Œ }}t        «       5 }t        |j                  «       D �ch c]  }|sŒ|’Œ	 c}«      D ]&  }|j                  t        j                  |«      «       Œ( t        |	||«      }t        |«      }| dk(  rX|st        d«      cddd«       S |�|€t        d«      cddd«       S |j                  |«      xs |}|j!                  ||||«      }nO| dk(  r3|st        d«      cddd«       S |j#                  t%        |||«      «      }nt        d	| › �«      cddd«       S |j'                  «       }|rd
j)                  |«      |d<   |j                  d«      sv|	D �cg c]  }|j                  |«      xs |‘Œ }}||d<   t+        |«      dk(  r|d   |d<   t-        ||	||«       t/        ||j                  «       D �cg c]  }|sŒ|‘Œ	 c}«       ddd«       j                  d«      r_dt        |d   «      v rOd}| dk(  r!|rt1        ||j                  |«      xs |«      }|dk\  rd|› d|›d�|d<   ndt        |d   «      vrd|d<   t3        j4                  |d¬«      S c c}w c c}w c c}w c c}w # 1 sw Y   Œ¤xY w# t6        $ r}t        t        |«      «      cY d}~S d}~ww xY w)z§Patch a file using replace mode or V4A patch format.

    ``cross_profile``: same semantics as ``write_file``'s flag (mirror-guard
    bypass only; unadvertised).
    rv   r   rD   r¾  zpath requiredNz"old_string and new_string requiredzpatch content requiredzUnknown mode: z | ro  r"  r¨  r§  zCould not findr   zThis is failure #z
 patching a  . Stop retrying with variations of the same old_string. Either: (1) re-read the file fresh to verify current content, (2) use a longer / more unique old_string with surrounding context lines, or (3) use write_file to replace the entire file if the targeted region is hard to anchor.rl  z#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.Fr  )Úlistr½  r8   r‡   rŠ  r+  rƒ  r   Úsortedr�  rª  r   r«  r�  rò   r6   Úpatch_replaceÚ	patch_v4ar‹   rs  rI   rE   r”  r.   r-   r2  r3  r7   )rþ   rŒ   r¿  rÀ  rÁ  rv   rª   r†  r‘  Ú_paths_to_checkÚ_content_write_pathsÚ	collectedÚprecheck_errÚ_pÚ_path_to_resolvedÚ_locksÚ_rÚstale_warningsrt   Ú_replace_targetr¸   rQ   Ú_resolved_modifiedÚfailure_countr€  s                            r>   Ú
patch_toolrÓ  ´  s‹  € ñ !%�t‘f¨"€OÜ Ó0ÐØˆw‚™5Ü-¨eÓ4ˆ	Ü�i¤Ô%ØÐØ˜9 Q™<Ñ'ˆØ 	¨!¡Ñ,ÐÜ(¨Ð:NÐPWÐYfÓg€LÙÜ˜,Ó'Ð'ð>"ð ZiÖ,iÐSU¨RÔ1AÀ"ÀgÓ1NÑ-NÐ,iÐÐ,iÜ‹[ð "	`˜FÜÐ+<×+CÑ+CÓ+EÖL RÊšbÒLÓMò ?�Ø×$Ñ$¤Z×%9Ñ%9¸"Ó%=Õ>ð?ä+¨OÐ=NÐPWÓXˆNÜ$ WÓ-ˆHð �yÒ ÙÜ% oÓ6÷"	`ñ "	`ð Ð%¨Ð);Ü%Ð&JÓK÷"	`ñ "	`ð #4×"7Ñ"7¸Ó"=Ò"EÀ�Ø!×/Ñ/°ÀÈZÐYdÓe‘Ø˜’ÙÜ%Ð&>Ó?÷#"	`ñ "	`ð$ "×+Ñ+Ô,MÈeÐUfÐhpÓ,qÓr‘ä! N°4°&Ð"9Ó:÷)"	`ñ "	`ð, !Ÿ.™.Ó*ˆKÙØ*/¯*©*°^Ó*D�˜JÑ'Ø—?‘? 7Ô+ð Q`Ö%`È"Ð&7×&;Ñ&;¸BÓ&?Ò&EÀ2Ñ&EÐ%`Ð"Ð%`Ø0B�Ð,Ñ-ÜÐ)Ó*¨aÒ/Ø3EÀaÑ3H�K Ñ0Ü˜W oÐ7HÈ*ÔUä% gÐ=N×=UÑ=UÓ=WÖ/^°rÒ[]²Ò/^Ô_÷E"	`ðL �?‰?˜7Ô#Ð(8¼CÀÈGÑ@TÓ<UÑ(UØˆMØ�yÒ ¡TÜ 5°gÐ?P×?TÑ?TÐUYÓ?ZÒ?bÐ^bÓ c�Ø Ò!à'¨ °jÀÀð I!ð !ð ˜GÒ$ð 7¼cÀ+ÈgÑBVÓ>WÑWðCð ˜GÑ$ô �z‰z˜+°EÔ:Ð:ùòq -jùâLùò6 &aùò 0_÷E"	`ð "	`ûôp ò "Üœ#˜a›&Ó!Õ!ûð"ús±   Á#K; Á'KÁ;K; ÂK/ÂK 
Â'K 
Â+AK/Ä	K; ÄK/Ä	K; Ä&;K/Å!	K; Å+*K/Æ	K; Æ;K/ÇK%Ç6AK/È9K*ÉK*ÉK/ÉBK; ËK; Ë K/Ë/K8Ë4K; Ë;	L"ÌLÌL"ÌL"ú.é2   Ú	discoveryÚpatternr§   Ú	file_globÚoutput_modeÚcontextÚorderc
                 ó.  — 	 t        ||«      \  }}d| |t        |«      |xs d|||f}
t        5  t        j                  |	ddt        «       dœ«      }t        ||
«      }ddd«       dk\  rt        d|› d�f| |d	œt        d
i¤ŽS t        |d¬«      }|rt        |«      S 	 t        t        ||	«      «      }t        |«      }|rt        |«      S t!        d||	«      }|�|S t#        |	«      j%                  | ||||||||¬«	      }t'        ||	«      }t)        |dd«      xs dD ]J  }t)        |dd«      sŒt+        |j,                  d
t/        t1        |j2                  |	«      «      ¬«      |_        ŒL |j5                  d
¬«      }|r|› d�|d<   |j7                  d«      xs d}t        |t        «      r4|j9                  d«      r#t;        d||	t=        j>                  |d¬«      «       |dk\  r	d|› d�|d<   |j7                  d«      rd||z   › d�|d <   t=        j>                  |d¬«      S # 1 sw Y   �ŒÅxY w# t        t        t        f$ r)}|}t        |t        «      rt        |«      s‚ Y d}~�Œ²d}~ww xY w# t@        $ r}t        t        |«      «      cY d}~S d}~ww xY w)!zSearch for content or files.Úsearchr  Nr   )Úlast_keyÚconsecutiverS  rW  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×  Úalready_searchedTÚSearchrd  )	r×  rŒ   r§   rØ  r  rR   rÙ  rÚ  rÛ  r³   rú   r@   r  )Údensifyze result(s) omitted because they target credential, token, cache, or secret-bearing environment files.Ú_omittedr"  zPath not found:Fr  r   zYou have run this exact search zY times consecutively. The results have not changed. Use the information you already have.ro  rT   zResults truncated. Use offset=zB to see more, or narrow with a more specific pattern or file_glob.rl  )!r   r‡   r+   r*   rì   rœ   r   r+  r   r   r   rŸ   r£   r¬   r8   r   r"   rò   rÝ  r»   rq   r   r@   r   r­   rŒ   rs  r6   r‘   r,   r2  r3  r7   )r×  r§   rŒ   rØ  r  rR   rÙ  rÚ  rÛ  rª   Ú
search_keyr?  rF   ru  Úresolved_search_pathr¼   rx  Úcached_search_nfr¸   r±   rƒ   rQ   Ú_search_errr€  s                           r>   Úsearch_toolrè  	  s  € ðO"Ü3°F¸EÓB‰ˆ�ð  ¨´°T³¸IºOÈÈUÐTZÐ\aÐbˆ
Üñ 	=Ü%×0Ñ0°Ø °ÄCÃEñ;Kó LˆIä% i°Ó<ˆE÷	=ð
 �AŠ:ÜØ:¸5¸'ð B@ð @ð1ð  Ø!&ñ1ô )¨$Ð/ñ1ð 1ô (¨°8Ô<ˆÙÜ˜fÓ%Ð%ð	Ü#&Ô'=¸dÀGÓ'LÓ#MÐ ô +Ð+?Ó@ˆÙÜ˜kÓ*Ð*ô 2°(Ð<PÐRYÓZÐØÐ'Ø#Ð#ä˜wÓ'×.Ñ.Ø $¨vÀØ °KÈÐX]ð /ó _ˆô 6°f¸gÓFˆÜ˜ ¨DÓ1Ò7°Rò 	\ˆAÜ�q˜) TÕ*Ü1Ø—I‘I¨Ü 3Ô4HÈÏÉÐQXÓ4YÓ Zô\�•	ð	\ð
 —n‘n¨T�nÓ2ˆáà�)ð Eð Eð ˜
Ñ#ð
 "—o‘o gÓ.Ò4°"ˆÜ�k¤3Ô'¨K×,BÑ,BÐCTÔ,UÜ˜hÐ(<¸gÄtÇzÁzÐR]ÐlqÔGrÔsà�AŠ:à1°%°ð 9Vð Vð ˜
Ñ#ð �?‰?˜;Ô'à0°¸%±Ð0@ð AGð Gð ˜Ñ ô �z‰z˜+°EÔ:Ð:÷O	=ñ 	=ûô* œ¤\Ð2ò 	Ø#'Ð ô ˜#œ|Ô,Ô5IÈ$Ô5OØÿùð	ûôf ò "Üœ#˜a›&Ó!Õ!ûð"úsx   ‚,I- ®/H Á%I- ÂI- ÂH- Â3I- ÃI- ÃAI- Ä-C2I- È H*È%I- È-I*ÉI%ÉI- É%I*É*I- É-	JÉ6JÊ	JÊJ)Úregistryr+  c                  ó   — ddl m}   | «       S )z=Lazy wrapper to avoid circular import with tools/__init__.py.r   ©Úcheck_file_requirements)Útoolsrì  rë  s    r>   Ú_check_file_reqsrî  g  s   € å-Ù"Ó$Ð$rP   rr  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 truncated on a line boundary and return a next_offset; continue with offset to read the rest. Documents auto-extract to readable text: .ipynb, Office (.docx/.xlsx/.pptx and legacy .doc/.ppt/.xls), PDF (text layer), OpenDocument, RTF, EPUB, SQLite (.db/.sqlite: schema, row counts, first rows). Cannot read images/binary â€” 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®   Úminimumz–Maximum number of lines to read (default: 2000, max: 2000). Reads are additionally capped at a ~100K-character budget with a next_offset continuation.iÐ  )r­  rñ  r®   Úmaximum)rŒ   rR   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. For an EXISTING file, call read_file first: write_file refuses (file untouched) when this task has no current full read/write of the file or the file changed on disk since; on refusal, read_file, merge, then retry. Auto-runs syntax checks on .py/.json/.yaml/.toml and other linted languages; only NEW errors introduced by this write are surfaced (pre-existing errors are filtered out). The result's verified:true means the on-disk content hash was confirmed â€” do NOT re-read the file to check the write landed.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)rŒ   r@   a  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. Finds a unique string and replaces it.zFile path to edit.z‹Exact text to find and replace. Must be unique in the file unless replace_all=true. Include surrounding context lines to ensure uniqueness.zjChanged replacement text; it must differ from old_string. Pass empty string '' to delete the matched text.ÚbooleanzLReplace all occurrences instead of requiring a unique match (default: false))r­  rñ  r®   )rŒ   r¿  rÀ  rÁ  )rŒ   r¿  rÀ  aã  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 (mode='replace', default): find a unique string and replace it. REQUIRED PARAMETERS: mode, path, old_string, new_string.
PATCH MODE (mode='patch'): apply V4A multi-file patches for bulk changes. REQUIRED PARAMETERS: mode, patch.znEdit mode. 'replace' (default): requires path + old_string + new_string. 'patch': requires patch content only.)r­  Úenumrñ  r®   z´REQUIRED when mode='patch'. V4A format patch content. Format:
*** Begin Patch
*** Update File: path/to/file
@@ context hint @@
 context line
-removed line
+added line
*** End Patch)rþ   rv   c                  ó.  — 	 ddl m} m}  |«       xs dj                  «       j	                  «       } | «       xs dj                  «       j	                  «       }|dv ry|j                  dd«      d	   }|j                  d
«      ryd|v S # t
        $ r Y yw xY w)uœ  Whether the active main provider/model is the OpenAI/codex family â€”
    the population trained on the V4A apply_patch dialect.

    Provider-family-coarse on purpose (no per-model training-diet table to
    go stale): direct OpenAI providers always qualify; on aggregators
    (openrouter/nous/azure...) the MODEL slug decides (gpt-*/o-series/
    codex). Fail-closed to the universal replace-only schema.
    r   )Ú_read_main_modelÚ_read_main_providerr  F>   úopenai-chatúazure-openaiúopenai-codexÚcodexÚopenaiTú/rD   rQ  )zgpt-zgpt.Úchatgptr  Úo1Úo3Úo4Úo5zopenai/)Úagent.auxiliary_clientrý  rþ  r|   r*  r7   rG   r‘   )rý  rþ  ÚproviderÚmodelÚslugs        r>   Ú_is_openai_family_mainr  Ü  sš   € ðßPá'Ó)Ò/¨R×6Ñ6Ó8×>Ñ>Ó@ˆÙ!Ó#Ò) r×0Ñ0Ó2×8Ñ8Ó:ˆð ÐUÑUØà�;‰;�s˜AÓ˜rÑ"€DØ‡�ÐSÔTØØ˜ÐÐøô ò Ùðús   ‚AB Â	BÂBÚsearch_filesaÕ  Search file contents or find files by name. Use this instead of grep/rg/find/ls in terminal. Ripgrep-backed, faster than shell equivalents. On macOS, broad searches above the user home automatically skip TCC-protected folders (Desktop, Documents, Downloads, Library, Movies, Music, Pictures); target one directly when access is intentional.

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. Discovery order is the fast bounded default; exact global newest-first order is an explicit opt-in and may scan the full tree.zPRegex pattern for content search, or glob pattern (e.g., '*.py') for file searchr´   zK'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)Úmodifiedz—File-search order: 'discovery' is fast bounded traversal order; 'modified' is exact global newest-first and may scan the full tree; ignored for content)r@   Ú
files_onlyrF   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§   rŒ   rØ  r  rR   rÛ  rÙ  rÚ  c                 ó²   — |j                  d«      xs d}t        | j                  dd«      | j                  dd«      | j                  dt        «      |¬«      S )	Nrª   r®   rŒ   r  rR   rD   r  )rŒ   rR   r  rª   )r6   r�  r   ©ÚargsÚkwÚtids      r>   Ú_handle_read_filer  
  sW   € Ø
�&‰&�Ó
Ò
(˜y€CÜ˜tŸx™x¨°Ó3¸D¿H¹HÀXÈqÓ<QÐY]×YaÑYaÐbiÔk}ÓY~ð  ILô  Mð  MrP   c                 ó¬  — |j                  d«      xs d}| j                  d«      rt        | j                  d«      t        «      st        d«      S d| vrt        d«      S t        | d   t        «      s%t        dt	        | d   «      j
                  › d�«      S t        | d   | d   |t        | j                  d	d
«      «      |j                  d«      ¬«      S )Nrª   r®   rŒ   zdwrite_file: missing required field 'path'. Re-emit the tool call with both 'path' and 'content' set.r@   u%  write_file: missing required field 'content'. The tool call included a path but no content argument â€” this is almost always a dropped-arg bug under context pressure. Re-emit the tool call with the full content payload, or use execute_code with hermes_tools.write_file() for very large files.z,write_file: 'content' must be a string, got rÔ  r†  Fr‘  )rŒ   r@   rª   r†  r‘  )r6   r8   r‡   r+  r­  r®  r²  r¶   r  s      r>   Ú_handle_write_filer    sÚ   € Ø
�&‰&�Ó
Ò
(˜y€CØ�8‰8�FÔ¤:¨d¯h©h°vÓ.>ÄÔ#DÜð-ó
ð 	
ð ˜ÑÜðó
ð 	
ô �d˜9‘o¤sÔ+ÜØ:Ü�D˜‘OÓ$×-Ñ-Ð.¨að1ó
ð 	
ô Ø�&‰\ 4¨	¡?¸CÜ˜4Ÿ8™8 O°UÓ;Ó<Ø—6‘6˜,Ó'ôð rP   c                 ó\  — |j                  d«      xs d}t        | j                  dd«      | j                  d«      | j                  d«      | j                  d«      | j                  dd	«      | j                  d
«      |t        | j                  dd	«      «      |j                  d«      ¬«	      S )Nrª   r®   rþ   r¾  rŒ   r¿  rÀ  rÁ  Frv   r†  r‘  )	rþ   rŒ   r¿  rÀ  rÁ  rv   rª   r†  r‘  )r6   rÓ  r¶   r  s      r>   Ú_handle_patchr  *  s�   € Ø
�&‰&�Ó
Ò
(˜y€CÜØ�X‰X�f˜iÓ(¨t¯x©x¸Ó/?Ø—8‘8˜LÓ)°d·h±h¸|Ó6LØ—H‘H˜]¨EÓ2¸$¿(¹(À7Ó:KÐUXÜ˜4Ÿ8™8 O°UÓ;Ó<Ø—6‘6˜,Ó'ôð rP   c                 óò  — |j                  d«      xs d}dddœ}| j                  dd«      }|j                  ||«      }| j                  dd«      }|� t        |t        «      r|j                  «       sd}t	        | j                  d	d
«      ||| j                  d«      | j                  dd«      | j                  dd«      | j                  dd«      | j                  dd«      | j                  dd«      |¬«
      S )Nrª   r®   r@   r´   )ÚgrepÚfindr§   rŒ   rÔ  r×  r  rØ  r  rÕ  rR   r   rÙ  rÚ  rÛ  rÖ  )
r×  r§   rŒ   rØ  r  rR   rÙ  rÚ  rÛ  rª   )r6   r8   r‡   r|   rè  )r  r  r  Ú
target_mapÚ
raw_targetr§   rŒ   s          r>   Ú_handle_search_filesr!  5  sß   € Ø
�&‰&�Ó
Ò
(˜y€CØ#¨WÑ5€JØ—‘˜( IÓ.€JØ�^‰^˜J¨
Ó3€Fð �8‰8�F˜CÓ €DØ€|œ
 4¬Ô-°d·j±j´lØˆÜØ—‘˜ BÓ'°¸TØ—(‘(˜;Ó'¨t¯x©x¸ÀÓ/DÈTÏXÉXÐV^Ð`aÓMbØ—H‘H˜]¨IÓ6ÀÇÁÈÐTUÓ@VØ�h‰h�w Ó,°cô	;ð ;rP   c                  óz   — 	 ddl m}   | «       rdt        d   j                  dd«      iS 	 i S # t        $ r Y i S w xY w)u-  One-word capability upgrade: "PDF (text layer)" â†’ "PDF (scanned or
    text)" when hosted OCR has a trusted route (see
    read_extract.hosted_ocr_available). Config/env probe only â€” no
    network at schema-build time. Compaction's tool refresh (#97073)
    picks up a key added mid-session.
    r   ©Úhosted_ocr_availablerñ  zPDF (text layer)zPDF (scanned or text))r   r$  ÚREAD_FILE_SCHEMAr¾  r7   r#  s    r>   Ú_read_file_schema_overridesr&  F  s[   € ð
Ý;áÔ!àÔ/°Ñ>×FÑFØ&Ð(?ó ðð ð "ð €Iøô ò ØØ€Iðús   ‚'- ­	:¹:Úfileu   ðŸ“–)rø  ÚtoolsetÚschemaÚhandlerÚcheck_fnÚemojiÚmax_result_size_charsÚdynamic_schema_overridesu   âœ�ï¸�)rø  r(  r)  r*  r+  r,  r-  c                  óž   — 	 t        «       si S ddt        d   it        d   d   ¥dt        d   i¥dgdœ} t        | dœS # t        $ r i cY S w xY w)uø   Layer the V4A patch mode onto the base replace-only schema for
    OpenAI-family mains (see PATCH_SCHEMA comment). Config/context probe
    only â€” no I/O at schema-build time; compaction's tool refresh
    (#97073) re-evaluates on model switches.rï  rþ   rù  rö  rv   rõ  )rñ  rù  )r  Ú_PATCH_V4A_PARAMSÚPATCH_SCHEMAÚ_PATCH_V4A_DESCRIPTIONr7   )Úparamss    r>   Ú_patch_schema_overridesr4  ]  sx   € ð
Ü%Ô'ØˆIààÔ)¨&Ñ1ðä˜|Ñ,¨\Ñ:ðð Ô*¨7Ñ3ñð
  ˜ñ
ˆô  6ÀVÑLÐLøÜò ØŠ	ðús   ‚> Ž/> ¾AÁAu   ðŸ”§u   ðŸ”Ž)ÚPurePosixPath)útools.binary_extensionsÚhas_opaque_document_extension)r6  Úis_pdf_path)útools.file_tools_read_trackingÚnotify_other_tool_call)r9  Úreset_file_dedup)r7  r8  r:  r;  c                 óÌ   — t         j                  | «      }|€t        dt        ›d| ›�«      ‚dd l}ddlm}  |t        | g|¢­Ž  t        |j                  |d   «      |d   «      S )Nzmodule z has no attribute r   )Ú	warn_oncerD   )	Ú_PLUGIN_COMPAT_LAZYr6   ÚAttributeErrorr®  Ú	importlibÚhermes_cli.plugin_compatr=  rq   Úimport_module)rø  r§   r@  r=  s       r>   Ú__getattr__rC  ˆ  se   € Ü ×$Ñ$ TÓ*€FØ€~Ü˜w¤x lÐ2DÀTÀHÐMÓNÐNÛÝ2ÙŒh˜Ð&˜vÓ&Ü�9×*Ñ*¨6°!©9Ó5°v¸a±yÓAÐArP   r{   )r®   )r®   FN)	r¾  NNNFNr®   FN)	r@   rÔ  NrÕ  r   r@   r   rÖ  r®   )šÚ__doc__r$  r¿   r2  ÚloggingrŽ   Úrer   rí   rê   Ú
contextlibr   Úpathlibr   Úagent.file_safetyr   r   Ú agent.tool_result_classificationr   Útools.binary_extensionsr   Útools.skill_provenancer	   Útools.file_operationsr
   r   r   Útools.file_operations_commonr   r   rí  r   Úagent.redactr   r   Útools.file_tools_pathsr   r   r   r   Útools.file_tools_write_guardsr   r   r   r   r   r   r   r   r   Útools.file_tools_read_trackingr   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   Ú	getLoggerr®  rÙ   ÚEACCESÚEPERMÚEROFSrÀ   r;   r9   r?   r‡   Útupler¶   rO   Údictra   rt  Ú	frozensetr�   r“   ru   ÚcompileÚ	MULTILINErˆ   rŠ   r‹   r•   r©   r­   r»   r7   rÁ   rî   ré   rÂ   Ú__annotations__rß   rò   r÷   ÚS_ISFIFOÚS_ISSOCKÚS_ISCHRÚS_ISBLKr  r  r>  rK  ra  r�  rƒ  rÃ  rŠ  r�  r”  r˜  rŸ  r™  r¥  r²  r½  rÓ  rè  Útools.registryré  r+  rî  r%  ÚWRITE_FILE_SCHEMAr1  r2  r0  r  ÚSEARCH_FILES_SCHEMAr  r  r  r!  r&  Úregisterr4  r5  Ú	posixpathÚsysr>  rC  rú   rP   r>   ú<module>rg     s	  ðòó Û Û Û Û 	Û 	Û Û Û Ý  Ý ç JÝ BÝ 8Ý 7÷Qñ Qç RÝ ß C÷Xó X÷T÷ Tõ T÷V÷ V÷ V÷ V÷ Vð 
ˆ×	Ñ	˜8Ó	$€ð  Ÿ,™,¨¯©°U·[±[ÐAÐ ð "Ð ð
:˜Só 
:ð, cð ,°cð ,¸eÀCÈÈdÀNÑ>Só ,ð< Dð °3ð Àð Ð]`ð Ðehó ð, !Ð ñ "ò #ó Ð ð!Ð ð
-¨4ó 
-ð  #˜Ÿ
™
Ð#UÐWY×WcÑWcÓdÐ Ø �b—j‘jÐ!QÐSU×S_ÑS_Ó`Ð ðm¨Sð mÀDð mÐWZó mð$[ #ð [¨$ó [ñ"- ð "-°°d±
¸TÑ0Að "-ÈTó "-ðJ
˜sð 
¨Sð 
°Só 
ñ¸ð ÈSó ð0J ið J°Dó Jð  �—‘Ó!€Ø€�Ó ð'"°3ð '"Àó '"ñT>˜3ð >Ð/Bó >ñB* #ó *ð6 
‡]�]Ð)Ð*Ø	‡]�]�JÐØ	‡\�\Ð'Ð(Ø	‡\�\Ð#Ð$ð	&Ð ð0  d¡
ó 0ð"G7 3ð G7¸3ð G7Àsð G7ÐUXð G7Ð]`ÐcgÑ]gó G7ðT Dð °Uð À#ð È#ó ðF .3È4Ø(,¸TÈDòC tð C°cð CÀð CÐTWð CØ$'ðCØ03ðCØ@EðCØSWðCà&*ðCà>AÀD¹jðCð VYóCðL -.Ð<NÐ_hñ V"˜ð V" cð V"°cð V"ÐY\ð V"Ðmpó V"ðv˜sð ¨Sð °S¸4±Zó ð?  c¡ð ?¸4À¹9ð ?Èsð ?Ø)-ð?Ø25¸±*ó?ð*˜$˜s™)ð °tð Àcð ÈdÐSVÉió ð@˜#ð @ d¨3¡ið @À4ð @ÐUXÐ[_ÑU_ð @Ðdhó @ð !Ð Ø"Ð ð
 "Ð ð cð °S¸4±Zð Ècð ÐVYÐ\`ÑV`ó ðD =FØ*/Ø-1ñ@"˜#ð @"¨ð @"°cð @"Ø#'ð@"à # d¡
ð@"à69ó@"ðF  Sð  ¨U°4¸±9¸dÀ3¹iÐ3GÑ-HÈ3Ñ-Nó  ð8 KOØOSØ?DØ(,ñR"�Sð R"¨Cð R"ÀCð R"ØðR"Ø48ðR"ØILðR"àðR"à8<ðR"ð  ™:ðR"ð 25óR"ðj DGØFGØ=>Ø(Ø(ñ	U"˜ð U" cð U"¸Sð U"ØðU"Ø.1ðU"Ø@CðU"à ðU"à7:ðU"ð ðU"ð ð	U"ð .1ó	U"÷v 0ò%ð ð q	àà%Ð6pÑqØ(Ð9tð  BCð  PQñ  RØ'ð  9Qð  ^pð  }Añ  Bñ
ð
 �HññÐ ð. ð qàà%ð  7Pñ  QØ (Ð9`Ñañ
ð ˜YÐ'ññÐ ð& ð	1ð ð !Ø3ñð
 !ð  mñð
 !ð  Lñð
 "ØmØ ññ
ò. 9ñ3ñ!+€ðb(ð ð Ø˜GÐ$ð HØñ	ð ð UññÐ ð ó ð4 ð oàà (ð  :Lñ  MØ'°)¸WÐ1Eð  Wdð  qzñ  {Ø%Ð6{ð  ILñ  MØ"*ð  <Mñ  NØ'Ð8kÐxzÑ{Ø(Ð9kÐxyÑzØ&°¸jÐ0Ið  [tð  ALñ  MØ$,Ò6Xð  j}ð  JSñ  TØ )ð  ;Að  NOñ  Pñ

ð �KññÐ ò*Mò
ò6ò;ò"ð* €× Ò �{¨FÐ;KÐUfð  rBð  JPð  hoð  Jeõ  fØ €× Ò �|¨VÐ<MÐWið  uEð  MUð  mtõ  uòð, €× Ò �w¨°|È]Ðeuð  ~Dð  \cð  ~Uõ  VØ €× Ò �~¨vÐ>QÐ[oð  {Kð  SYð  qxõ  yõ "Û Û 
ð &bØ=ØZØNñ	Ð óBrP   