+
    lHàjoo ã                   ó  a € R  tF0 t R t^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
t
^ RIt^ RIt^ RIt^ RIHtHt ^ RIHtHt ^ RIHt ^ RIHt ^ RIHt ^ RIHtHtHtHtHtH t H!t!H"t"H#t#H$t$H%t%H&t&H't' ^ RI(H)t)H*t*H+t+ ^ R	I,H-t- ^ R
I.H/t0 ]
Pb                  ! ]24      t3]4! ]Pj                  ! 4       4      t6R!t7] ^ k R R lt8R R lt9 ! R R]4      t:0 R"mt;Rt<Rt=Rt>Rt?Rt@R R ltAR R ltBR R ltCR R ltD ! R R]*]-]:4      tER# )#a�  File operations (read, write, patch, search) over any terminal backend.

Every operation is a shell command run through the backend's ``execute()``, so one
implementation serves every environment (local, docker, ssh, modal, ...). Companions:
``file_operations_common`` (result dataclasses, text helpers), ``file_operations_lint``
(LintMixin), ``file_operations_search`` (SearchMixin).
N)ÚABCÚabstractmethod)ÚOptionalÚDict)ÚPath)Úhas_binary_extension)Úget_write_denied_error)ÚExecuteResultÚPatchResultÚ
ReadResultÚSearchResultÚWriteResultÚ	_UTF8_BOMÚ_detect_line_endingÚ_has_bomÚ_normalize_line_endingsÚ
_strip_bomÚ_strip_terminal_fence_leaksÚnormalize_read_paginationÚnormalize_search_pagination)ÚLINTERS_INPROCÚ	LintMixinÚ_FAIL_CLOSED_INPROC_EXTS)ÚSearchMixin)Úfile_operations_nativec                ó0   € V ^8„  d   QhR\         R\        /# ©é   ÚsampleÚreturn)ÚbytesÚstr)Úformats   "Ú:/home/ubuntu/.hermes/hermes-agent/tools/file_operations.pyÚ__annotate__r$   I   s   € ÷ 	ñ 	¤%ð 	¬Cñ 	ó    c                ó¨   € \          FG  w  rV P                  V4      '       g   K  VP                  R4      '       d   V R,          R8w  d   KE  Vu # 	  R# )zÁBest-effort human name for binary content from its magic bytes; never raises.
The ISO-media entry additionally requires ``ftyp`` at offset 4 (three leading
NULs alone are too weak a signature).z	ISO media:é   é   Ns   ftypzunknown binary)Ú_MAGIC_SIGNATURESÚ
startswith)r   ÚprefixÚnames   &  r#   Úidentify_binary_bytesr-   I   sH   € ÷ *‰ˆØ×Ñ˜V×$Ô$Ø�‰˜{×+Ò+°°sµ¸wÔ0FÙØŠKñ	 *ñ
 r%   c                óR   € V ^8„  d   QhR\         \        ,          R\        R\        /# )r   r   Ú	file_sizer   )r   r    Úintr!   )r"   s   "r#   r$   r$   U   s*   € ÷ 
Gñ 
G¤¬%¥ð 
G¼Sð 
GÄSñ 
Gr%   c                óœ   € \        T ;'       g    R4      pVR
8¼  d   VR
,          R R2pMVR8¼  d   VR,          R R2pMV R2pRV RV R	2# )z�One-line binary-file refusal naming the TYPE ("PNG image data, 4.1 KB"), so the
model gets what-is-this in one read instead of hunting for tools it may lack.r%   i   z.1fz MBz KBz byteszBinary file (ú, u   ) â€” cannot display as text.é   )r-   )r   r/   ÚkindÚsizes   &&  r#   Údescribe_binary_filer6   U   sn   € ô ! § ¨3Ó/€DØ�KÔØ˜{Õ+¨CÐ0°Ð4‰Ø	�dÔ	Ø˜dÕ" 3Ð' sÐ+‰à�˜FÐ#ˆØ˜4˜&  4 &Ð(EÐFÐFr%   c                   ó  a € ] tR t^bt o Rt]RV 3R lR ll4       t]V 3R lR l4       t]RV 3R lR ll4       t]RV 3R	 lR
 ll4       t	]V 3R lR l4       t
]V 3R lR l4       t]V 3R lR l4       t]RV 3R lR ll4       tRtV tR# )ÚFileOperationsz@Abstract interface for file operations across terminal backends.c                ó2   <€ V ^8„  d   QhRS[ RS[RS[RS[/# ©r   ÚpathÚoffsetÚlimitr   ©r!   r0   r   )r"   Ú__classdict__s   "€r#   r$   ÚFileOperations.__annotate__f   s)   ø€ ÷ 3ñ 3™cð 3©3ð 3¹3ð 3É*ñ 3r%   c                ó   € R# )z$Read a file with pagination support.N© )Úselfr;   r<   r=   s   &&&&r#   Ú	read_fileÚFileOperations.read_filee   ó   ‚ r%   c                ó&   <€ V ^8„  d   QhRS[ RS[/# ©r   r;   r   ©r!   r   )r"   r?   s   "€r#   r$   r@   j   s   ø€ ÷ Uñ U¡#ð U©*ñ Ur%   c                ó   € R# )zFWhole file as a plain string: no pagination, line numbers or clamping.NrB   ©rC   r;   s   &&r#   Úread_file_rawÚFileOperations.read_file_rawi   rF   r%   Nc                óB   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[/# ©r   r;   ÚcontentÚpre_contentr   ©r!   r   r   )r"   r?   s   "€r#   r$   r@   n   s4   ø€ ÷ Gñ G™sð G©Sð G¹xÉ½}ð GÑXcñ Gr%   c                ó   € R# )z8Write content to a file, creating directories as needed.NrB   )rC   r;   rP   rQ   s   &&&&r#   Ú
write_fileÚFileOperations.write_filem   rF   r%   c          
      ó8   <€ V ^8„  d   QhRS[ RS[ RS[ RS[RS[/# ©r   r;   Ú
old_stringÚ
new_stringÚreplace_allr   ©r!   Úboolr
   )r"   r?   s   "€r#   r$   r@   r   s2   ø€ ÷ ;ñ ;¡#ð ;±3ð ;ÁCð ;Ù#'ð;Ù4?ñ;r%   c                ó   € R# )z,Replace text in a file using fuzzy matching.NrB   )rC   r;   rX   rY   rZ   s   &&&&&r#   Úpatch_replaceÚFileOperations.patch_replaceq   rF   r%   c                ó&   <€ V ^8„  d   QhRS[ RS[/# ©r   Úpatch_contentr   ©r!   r
   )r"   r?   s   "€r#   r$   r@   w   s   ø€ ÷ (ñ (¡sð (©{ñ (r%   c                ó   € R# )zApply a V4A format patch.NrB   )rC   rb   s   &&r#   Ú	patch_v4aÚFileOperations.patch_v4av   rF   r%   c                ó&   <€ V ^8„  d   QhRS[ RS[/# rH   ©r!   r   )r"   r?   s   "€r#   r$   r@   {   s   ø€ ÷ Mñ M¡ð M©ñ Mr%   c                ó   € R# )z>Delete a file. Returns WriteResult with .error set on failure.NrB   rK   s   &&r#   Údelete_fileÚFileOperations.delete_filez   rF   r%   c                ó,   <€ V ^8„  d   QhRS[ RS[ RS[/# ©r   ÚsrcÚdstr   rh   )r"   r?   s   "€r#   r$   r@      s'   ø€ ÷ Rñ R™Sð R¡sð R©{ñ Rr%   c                ó   € R# )zCMove/rename a file. Returns WriteResult with .error set on failure.NrB   )rC   rn   ro   s   &&&r#   Ú	move_fileÚFileOperations.move_file~   rF   r%   c                óf   <€ V ^8„  d   QhRS[ RS[ RS[ RS[S[ ,          RS[RS[RS[ RS[R	S[ R
S[/
# ©r   Úpatternr;   ÚtargetÚ	file_globr=   r<   Úoutput_modeÚcontextÚorderr   ©r!   r   r0   r   )r"   r?   s   "€r#   r$   r@   ƒ   sb   ø€ ÷ +ñ +™cð +©ð +¹Cð +Ù"¡3�-ð+Ù7:ð+ÙILð+áð+á69ð+ñ ð+ñ -9ñ+r%   c
                ó   € R# )zSearch for content or files.NrB   )
rC   ru   r;   rv   rw   r=   r<   rx   ry   rz   s
   &&&&&&&&&&r#   ÚsearchÚFileOperations.search‚   rF   r%   rB   ©é   iÐ  ©N©F©Ú.rP   Né2   é    rP   r†   Ú	discovery)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   rD   rL   rT   r^   re   rj   rq   r}   Ú__static_attributes__Ú__classdictcell__©r?   s   @r#   r8   r8   b   sÃ   ø‡ € ÙJà÷3ñ 3ó ð3ð ÷Uó ðUð ÷Gñ Gó ðGð ÷;ñ ;ó ð;ð ÷(ó ð(ð ÷Mó ðMð ÷Ró ðRð ÷+ñ +ó ö+r%   r8   Ú__hermes_not_regular__Ú__hermes_missing__Ú__HERMES_RF_Ú__HERMES_WF_Ú__HERMES_RB_c                ó0   € V ^8„  d   QhR\         R\         /# )r   r+   r   ©r!   )r"   s   "r#   r$   r$   �   s   € ÷ 0ñ 0œ#ð 0¤#ñ 0r%   c                ó8   € V  \         P                  ! ^4       R2# )a  Per-call separator line for a compound shell probe. 128 random bits make a
collision with file content negligible; the underscores keep the token outside
the base64 alphabet, so a sentinel leaking into a sample segment fails base64
validation instead of decoding into bytes.Ú__)ÚsecretsÚ	token_hex)r+   s   &r#   Ú_new_sentinelr›   �   s!   € ð
 ˆX”g×'Ò'¨Ó+Ð,¨BÐ/Ð/r%   c                óR   € V ^8„  d   QhR\         R\         R\        \         ,          /# )r   ÚoutputÚsentinelr   )r!   Úlist)r"   s   "r#   r$   r$   ¥   s%   € ÷ )ñ )œCð )¬3ð )´4¼µ9ñ )r%   c                ó2   € V P                  VR,           4      # )a	  Split compound-probe stdout on its sentinel lines. Every producer (``wc``,
    ``base64``, ``cut``) newline-terminates or prints nothing, so the separator is
    always ``sentinel + "
"`` on its own line; the text after the final sentinel
    is the status segment.Ú
©Úsplit)r�   rž   s   &&r#   Ú_split_segmentsr¤   ¥   s   € ð
 �<‰<˜ 4�Ó(Ð(r%   c                óF   € V ^8„  d   QhR\         R\        \         ,          /# ©r   Útextr   ©r!   r   )r"   s   "r#   r$   r$   ­   s   € ÷ 'ñ '¤Sð '¬X´c­]ñ 'r%   c                óâ   a€ RV 9  d
   RV 9  d   R# . oR V3R llp \         P                  ! \        V 4      ^ ,          VR7       S'       d
   S^ ,          # R#   \        \        3 d     R# i ; i)z“First NaN/Infinity/-Infinity in ``text`` when it is otherwise valid JSON,
else None. ``json.loads`` accepts these JavaScript extensions by default.ÚNaNÚInfinityNc                ó0   € V ^8„  d   QhR\         R\        /# )r   Úvaluer   )r!   Úfloat)r"   s   "r#   r$   Ú0_json_nonstandard_constant.<locals>.__annotate__´   s   € ÷ ñ œSð ¤Uñ r%   c                 ó<   <€ SP                  V 4       \        R 4      # )Únan)Úappendr®   )r­   Úfounds   &€r#   Únote_constantÚ1_json_nonstandard_constant.<locals>.note_constant´   s   ø€ Ø�‰�UÔÜ�U‹|Ðr%   )Úparse_constant)ÚjsonÚloadsr   Ú
ValueErrorÚRecursionError)r§   r´   r³   s   & @r#   Ú_json_nonstandard_constantr»   ­   so   ø€ ð �DÔ˜Z¨tÔ3ÙØ€E÷ð ðÜ�
Š
”:˜dÓ# AÕ&°}ÕE÷ ˆ5��8Ð& $Ð&øô œÐ'ô Úðús   ž(A ÁA.Á-A.c          	      ót   € V ^8„  d   QhR\         R\         R\        \         ,          R\        \        ,          /# rO   rR   )r"   s   "r#   r$   r$   ¿   s3   € ÷ &ñ &¬3ð &¼ð &Ü2:¼3µ-ð&ÜDLÌ[ÕDYñ&r%   c                óp   € \        V4      pVf   R# Ve   \        V4      e   R# \        RV  RV R2R7      # )zØRefuse a JSON write that INTRODUCES a nonstandard constant (strict JSON
consumers reject them). A file that already holds one keeps accepting
unrelated edits, which is why the lenient syntax gate can't do this check.NúRefusing to write 'z': candidate content uses zh, which is not valid JSON. The file was NOT created or modified. Use null or a string instead and retry.©Úerror)r»   r   )r;   rP   rQ   Úconstants   &&& r#   Ú _refuse_introduced_json_constantrÂ   ¿   sQ   € ô
 *¨'Ó2€HØÒÙØÒÔ#=¸kÓ#JÒ#VÙÜØ
˜d˜VÐ#=¸h¸Zð H$ð 	$ô&ð &r%   c                   óæ  a € ] tR t^Ït o RtRzV 3R lR lltR{V 3R lR lltV 3R lR ltV 3R	 lR
 ltV 3R lR lt	V 3R lR lt
V 3R lR lt]V 3R lR l4       tR|V 3R lR lltV 3R lR lt]V 3R lR l4       tV 3R lR lt]V 3R lR l4       t]V 3R lR l4       tRzV 3R lR  lltV 3R! lR" ltR}V 3R# lR$ lltV 3R% lR& ltR~V 3R' lR( lltV 3R) lR* ltV 3R+ lR, ltRzV 3R- lR. lltV 3R/ lR0 lt]V 3R1 lR2 l4       tV 3R3 lR4 ltRV 3R5 lR6 lltV 3R7 lR8 lt R€t!R9t"V 3R: lR; lt#RzV 3R< lR= llt$V 3R> lR? lt%R�V 3R@ lRA llt&V 3RB lRC lt'V 3RD lRE lt(V 3RF lRG lt)]V 3RH lRI l4       t*V 3RJ lRK lt+V 3RL lRM lt,V 3RN lRO lt-V 3RP lRQ lt.V 3RR lRS lt/R‚t0V 3RT lRU lt1V 3RV lRW lt2V 3RX lRY lt3RzV 3RZ lR[ llt4V 3R\ lR] lt5V 3R^ lR_ lt6]7Pp                  ! R`4      t9V 3Ra lRb lt:]V 3Rc lRd l4       t;V 3Re lRf lt<V 3Rg lRh lt=V 3Ri lRj lt>V 3Rk lRl lt?RzV 3Rm lRn llt@V 3Ro lRp ltAV 3Rq lRr ltBRƒV 3Rs lRt lltCV 3Ru lRv ltDR„V 3Rw lRx lltERytFV tGR# )…ÚShellFileOperationsaµ  File operations over any terminal backend exposing ``execute(command, cwd)``
returning ``{"output": str, "returncode": int}``.

cwd rule: every ``_exec`` prefers the LIVE ``env.cwd`` so a ``cd`` run via the
terminal tool is picked up immediately; the init-time ``self.cwd`` is only a
fallback for envs that don't track cwd (using it for every call once made
patches "succeed" with a plausible diff while landing in the wrong directory).
Nc                ó.   <€ V ^8„  d   QhRS[ R,          /# )r   ÚcwdNr–   )r"   r?   s   "€r#   r$   Ú ShellFileOperations.__annotate__Ù   s   ø€ ÷ 
Dñ 
D©#°­*ñ 
Dr%   c                óÈ   € Wn         T;'       g8    \        VR R4      ;'       g#    \        \        VRR4      R R4      ;'       g    RV n        / V n        / V n        / V n        R# )rÆ   NÚconfigÚ/)ÚenvÚgetattrrÆ   Ú_command_cacheÚ_rg_resolution_cacheÚ_rg_modified_capability)rC   Úterminal_envrÆ   s   &&&r#   Ú__init__ÚShellFileOperations.__init__Ù   sr   € ØŒà÷ Vð Vœ' ,°°tÓ<÷ Vð VÜœ7 <°¸4Ó@À%ÈÓN÷Vð VØRUð 	Œð
 02ˆÔØ46ˆÔ!ØACˆÖ$r%   c          
      ób   <€ V ^8„  d   QhRS[ RS[ R,          RS[R,          RS[ R,          RS[/# )r   ÚcommandrÆ   NÚtimeoutÚ
stdin_datar   ©r!   r0   r	   )r"   r?   s   "€r#   r$   rÇ   å   sE   ø€ ÷ Vñ V™Sð V¡s¨T¥zð VÁ3ÈÅ:ð VÙ �*ðVÙ0=ñVr%   c                ó<  € / pV'       d   W5R&   Ve   WER&   T;'       g,    \        V P                  RR4      ;'       g    V P                  pV P                  P                  ! V3RV/VB pVP	                  R^ 4      pVP	                  RR4      p	Rp
V^~8X  dZ   RV	9   dS   ^ R	IHp \        V P                  R
R4      pV'       d   V! V4      '       d   RMRpRV: RV RV	P                  4        2;r©VP	                  R4      '       d
   V^ 8X  d   ^p\        W˜V
R7      # )uŽ   Run ``command`` on the backend. cwd: explicit arg â†’ live ``env.cwd`` â†’
init-time ``self.cwd``. ``stdin_data`` is piped (bypasses ARG_MAX).rÕ   NrÖ   rÆ   Ú
returncoder�   Ú zcd: )Ú_is_container_backendÚenv_typezI; for container backends use a path inside the container, e.g. /workspacezworking directory zU does not exist on the active terminal backend (check terminal.cwd or the session cwdz). Ústdin_error)ÚstdoutÚ	exit_codeÚ	cwd_error)	rÌ   rË   rÆ   ÚexecuteÚgetÚtools.terminal_tool_configrÛ   Ústripr	   )rC   rÔ   rÆ   rÕ   rÖ   ÚkwargsÚeffective_cwdÚresultrß   r�   rà   rÛ   rÜ   Úhints   &&&&&         r#   Ú_execÚShellFileOperations._execå   s&  € ð ˆßØ '�9ÑØÒ!Ø#-�<Ñ Ø×IÐIœw t§x¡x°¸Ó=×IÐIÀÇÁˆØ—‘×!Ò! 'ÑG¨}ÐGÀÑGˆØ—J‘J˜|¨QÓ/ˆ	Ø—‘˜H bÓ)ˆð
 ˆ	Ø˜Ô ¨&Ô 0ÝHÜ˜tŸx™x¨°TÓ:ˆHçÑ$9¸(×$CÒ$Cñ `ØIKð ð % ]Ñ$5ð 6AØAEÀÀcÈ&Ï,É,Ë.ÐIYð[ð\ˆIð
 �:‰:�m×$Ò$¨°a¬ØˆIÜ FÈ9ÔUÐUr%   c                ó&   <€ V ^8„  d   QhRS[ RS[/# )r   Úcmdr   ©r!   r\   )r"   r?   s   "€r#   r$   rÇ     s   ø€ ÷ 
(ñ 
(¡ð 
(©ñ 
(r%   c                ó"  € VR8X  d   V P                  V4      RJ# WP                  9  dT   V P                  RV R24      pVP                  '       d   R# VP                  P                  4       R8H  V P                  V&   V P                  V,          # )z}Check if a command exists in the environment (cached); rg goes through
the resolver so a mid-session install becomes visible.ÚrgNzcommand -v z >/dev/null 2>&1 && echo 'yes'FÚyes)Ú_resolve_commandrÍ   ré   rà   rÞ   rä   )rC   rì   rç   s   && r#   Ú_has_commandÚ ShellFileOperations._has_command  s‡   € ð �$Œ;Ø×(Ñ(¨Ó-°TÐ9Ð9Ø×)Ñ)Ô)Ø—Z‘Z +¨c¨UÐ2PÐ QÓRˆFØ××ÐÙØ'-§}¡}×':Ñ':Ó'<ÀÑ'EˆD×Ñ Ñ$Ø×"Ñ" 3Õ'Ð'r%   c                ó&   <€ V ^8„  d   QhRS[ RS[/# rH   ©r!   r	   )r"   r?   s   "€r#   r$   rÇ     s   ø€ ÷ Mñ M™ð M¡ñ Mr%   c                óJ   € V P                  RV P                  V4       R24      # )uG   ``cat`` the file with stderr silenced (missing file â†’ non-zero exit).úcat ú 2>/dev/null©ré   Ú_escape_shell_argrK   s   &&r#   Ú_catÚShellFileOperations._cat  s&   € à�z‰z˜D ×!7Ñ!7¸Ó!=Ð >¸lÐKÓLÐLr%   c                ó,   <€ V ^8„  d   QhRS[ RS[RS[/# )r   r;   Únbytesr   r×   )r"   r?   s   "€r#   r$   rÇ     s'   ø€ ÷ Zñ Z™#ð Z¡sð Z©}ñ Zr%   c                óP   € V P                  R V RV P                  V4       R24      # )úhead -c Ú rø   rù   )rC   r;   rþ   s   &&&r#   Ú_headÚShellFileOperations._head  s,   € Ø�z‰z˜H V H¨A¨d×.DÑ.DÀTÓ.JÐ-KÈ<ÐXÓYÐYr%   c                ó&   <€ V ^8„  d   QhRS[ RS[/# )r   Úsnippetr   rõ   )r"   r?   s   "€r#   r$   rÇ     s   ø€ ÷ ñ ©3ð ±=ñ r%   c                óê   € V P                  RV P                  V4       24      pVP                  ^ 8w  d?   RVP                  ;'       g    R9   d$   V P                  RV P                  V4       24      pV# )z}Run ``snippet`` via the backend's ``python3``, retrying with ``python``
when only that name exists (Windows / older systems).zpython3 -c Úpython3rÚ   z
python -c )ré   rú   rß   rÞ   )rC   r  rç   s   && r#   Ú_run_python_snippetÚ'ShellFileOperations._run_python_snippet  sl   € ð —‘˜k¨$×*@Ñ*@ÀÓ*IÐ)JÐKÓLˆØ×Ñ˜qÔ  Y°6·=±=×3FÐ3FÀBÔ%GØ—Z‘Z *¨T×-CÑ-CÀGÓ-LÐ,MÐ NÓOˆFØˆr%   c          	      óv   <€ V ^8„  d   QhRS[ RS[ RS[S[S[S[ ,          ,          S[S[,          S[3,          /# )r   ÚbodyÚmorer   )r!   Útupler   rŸ   r0   r	   )r"   r?   s   "€r#   r$   rÇ      s?   ø€ ÷ 0ñ 0¡ð 0©Sð 0±U¹8ÁDÉÅIÕ;NÑPXÑY\ÕP]Ñ_lÐ;lÕ5mñ 0r%   c           
     óÒ  a€ \        \        4      pRV 2oRP                  V3R lV 4       4      pV P                  RS RV RV S R24      p\	        VP
                  ;'       g    RV4      p\        V4      \        V4      ^,           8w  d   RRV3#  V^R	 \        \        VR	,          4      P                  4       ^ ,          4      V3#   \        \        3 d    T^R	 RT3u # i ; i)
ua  Run BODY, then each of MORE, each in its own sentinel-delimited segment; return (those
segments, BODY's exit status, reply).

The transport merges the backend's own stdout with the command's, and every caller here
decodes a segment into file bytes, so the payload has to be delimited rather than taken to
be the whole reply: a remote shell announcing ``TERM`` is four base64 characters that would
otherwise join the payload and decode to ``b"LDL"`` at the head of it. The fence drops noise
OUTSIDE it only; output emitted while BODY runs (a ``BASH_ENV`` DEBUG hook) lands inside the
payload, so a caller that writes the bytes back must verify them independently (MORE). The
status rides in its own trailing segment so a failed BODY is still told apart from an empty
file. ``(None, None, reply)`` when no fenced reply came back â€” the command never ran as
written.
úecho rÚ   c              3   ó4   <"  € T F  pS R V R 2x € K  	  R# 5i)ú; NrB   )Ú.0rì   Úmarks   & €r#   Ú	<genexpr>Ú3ShellFileOperations._fenced_read.<locals>.<genexpr>0  s   øé € Ð:±T¨c˜$˜˜r #  bÕ)³Tùs   ƒz{ set +x; } 2>/dev/null; r  z; __hb=$?; z; echo $__hbNéÿÿÿÿ)r›   Ú_BYTES_SENTINEL_PREFIXÚjoinré   r¤   rÞ   Úlenr0   r   r£   Ú
IndexErrorr¹   )rC   r  r  rž   Úrestrç   Úsegmentsr  s   &&*    @r#   Ú_fenced_readÚ ShellFileOperations._fenced_read   sö   ø€ ô !Ô!7Ó8ˆØ�x�jÐ!ˆØ�w‰wÔ:±TÓ:Ó:ˆð —‘Ð9¸$¸¸rÀ$ÀÀ{ÐSWÐRXÐY]ÐX^Ð^jÐkÓlˆÜ" 6§=¡=×#6Ð#6°B¸ÓAˆÜˆx‹=œC ›I¨�MÔ)Ø˜˜vÐ%Ð%ð	0Ø˜A˜b�>¤3Ô'BÀ8ÈBÅ<Ó'P×'VÑ'VÓ'XÐYZÕ'[Ó#\Ð^dÐdÐdøÜœJÐ'ô 	0Ø˜A˜b�> 4¨Ð/Ò/ð	0ús   Â5C
 Ã
C&Ã%C&c                ó,   <€ V ^8„  d   QhRS[ RS[RS[/# )r   ÚdataÚsize_segmentr   )r    r!   r\   )r"   r?   s   "€r#   r$   rÇ   =  s'   ø€ ÷ Xñ X™Eð X±ð X¹ñ Xr%   c                óÚ   € \        V4      P                  4       p\        V4      ^8H  ;'       d>    V^ ,          P                  4       ;'       d    \	        V^ ,          4      \        V 4      8H  # )zûWhether DATA is exactly as long as the file's own ``wc -c``. Noise inside the payload
only ever ADDS text, and any addition that still decodes adds bytes, so equal length is
the check; noise in the size segment breaks its single-integer shape instead.)r   r£   r  Úisdigitr0   )r   r!  Útokenss   && r#   Ú_matches_sizeÚ!ShellFileOperations._matches_size<  sU   € ô
 -¨\Ó:×@Ñ@ÓBˆÜ�6‹{˜aÑ×WÐW F¨1¥I×$5Ñ$5Ó$7×WÐW¼CÀÀqÅ	»NÌcÐRVËiÑ<WÐWr%   c                ó&   <€ V ^8„  d   QhRS[ RS[/# )r   r;   Úlength©r!   r0   )r"   r?   s   "€r#   r$   rÇ   D  s   ø€ ÷ 7ñ 7¡sð 7±Cñ 7r%   c                ó    € V P                  RV RV P                  V4       R24      w  r4pVe   V^ 8w  d   R# V P                  V^ ,          4      # )a¹  First ``length`` raw bytes, base64-wrapped so they survive the terminal
transport (which decodes stdout with ``errors="replace"`` and manufactures
U+FFFD for every undecodable byte, including a multibyte char cut in half
by ``head -c``). None when no clean base64 came back (no ``base64`` binary);
callers then fall back to the text heuristic.

Wrapping the sample in base64 lets the original bytes survive the transport, so binary detection can
happen at the byte layer where it is well-defined (#80308 and friends). Fenced like the
byte-exact read below: this sample is the binary-admission gate in FRONT of that read, so
backend noise decoded into it decides whether a file is editable at all.
r   r  z 2>/dev/null | base64N)r  rú   Ú_decode_base64_sample)rC   r;   r(  r  Úread_rcÚ_s   &&&   r#   Ú_sample_file_bytesÚ&ShellFileOperations._sample_file_bytesD  s]   € ð  $×0Ñ0Ø�v�h˜a × 6Ñ 6°tÓ <Ð=Ð=RÐSó UÑˆ˜1àÒ˜w¨!œ|ÙØ×)Ñ)¨(°1­+Ó6Ð6r%   c                ó\   <€ V ^8„  d   QhRS[ RS[S[S[,          S[S[,          3,          /# rH   ©r!   r  r   r    r	   )r"   r?   s   "€r#   r$   rÇ   V  s.   ø€ ÷ 2ñ 2¡cð 2©e±H¹UµOÁXÉmÕE\Ð4\Õ.]ñ 2r%   c           	     óÐ  € V P                  4       '       EdF   ^ RIp\        P                  P	                  V4      '       d   TMH\        P                  P                  \        V P                  RR4      ;'       g    V P                  V4      p \        P                  ! V\        P                  \        \        R^ 4      ,          4      p VP                  \        P                  ! V4      P                  4      '       dJ   \        VRRR7      ;_uu_ 4       pVP                  4       R3uuRRR4       \        P                  ! V4       # \        P                  ! V4       V P#                  V4      pV P%                  RV 2RV 24      w  rxp	\'        V R	2^R
7      p
Vf   RV	P(                  ^ 8w  d   V	3# T
3# Vf   RV
3# V^8X  d   V P+                  V4      # Vw  r¼V^ 8w  d   RV P-                  WV4      3# V P/                  V4      pVe   V P1                  WÜ4      '       g   RV
3# VR3#   + '       g   i     Lñ; i  \        P                  ! T4       i ; i  \          d     ELi ; i)a  The file's bytes exactly, for the edit paths that write back every line they did not touch.

The text transport cannot carry them: it decodes with errors="replace", so a byte UTF-8 cannot
decode comes back as U+FFFD and the edit then persists it. A native read on the local POSIX host,
else base64 over the transport; ``(None, result)`` hands back the failed shell read for the
caller's message. Only a regular file gets a native open (a FIFO would block this thread); the
rest take the shell path and its timeout, as before.NrÆ   Ú
O_NONBLOCKÚrbF)Úclosefdú	base64 < úwc -c < ú0: the backend returned a garbled byte-exact read©rÞ   rß   )Ú_native_read_enabledÚstatÚosr;   Úisabsr  rÌ   rË   rÆ   ÚopenÚO_RDONLYÚS_ISREGÚfstatÚst_modeÚreadÚcloseÚOSErrorrú   r  r	   rß   Ú_read_exact_bytes_hexÚ_failed_readr+  r%  )rC   r;   Ú_statÚfullÚfdÚfhÚargr  r,  rç   ÚgarbledÚpayloadr5   r   s   &&            r#   Ú_read_exact_bytesÚ%ShellFileOperations._read_exact_bytesV  s	  € ð ×$Ñ$×&Ó&Û ÜŸ7™7Ÿ=™=¨×.Ò.‘4´B·G±G·L±LÜ˜Ÿ™ %¨Ó.×:Ð:°$·(±(¸Dó5BˆDðô
 —W’W˜T¤2§;¡;´¼¸\È1Ó1MÕ#MÓN�ð!Ø—}‘}¤R§X¢X¨b£\×%9Ñ%9×:Ò:Ü! " d°E×:Õ:¸bØ#%§7¡7£9¨d ?÷ ;Ñ:ô —H’H˜R•L”B—H’H˜R”Lð ×$Ñ$ TÓ*ˆØ$(×$5Ñ$5¸	À#ÀÐ6GÈ8ÐTWÐSXÐIYÓ$ZÑ!ˆ˜6Ü¨$¨Ð/_Ð'`ÐlmÔnˆØÒð  6×#3Ñ#3°qÔ#8˜ÐEÐE¸gÐEÐEØŠ?Ø˜�=Ð Ø�cŒ>Ø×-Ñ-¨dÓ3Ð3Ø ‰ˆØ�aŒ<ð ˜×*Ñ*¨4¸'ÓBÐBÐBØ×)Ñ)¨'Ó2ˆØŠ<˜t×1Ñ1°$×=Ò=Ø˜�=Ð Ø�TˆzÐ÷= ;×:ûô —H’H˜R•LûÜô ÚðúsI   Â;I Ã	AH; ÄH(Ä&
H; Ä0I ÅI È(H8	È3H; È;IÉI ÉI%É$I%c                ó2   <€ V ^8„  d   QhRS[ RS[ RS[RS[/# )r   r;   rN  r,  r   r×   )r"   r?   s   "€r#   r$   rÇ   ‹  s)   ø€ ÷ 0ñ 0™3ð 0©ð 0±sð 0¹}ñ 0r%   c                óh   € \        \        V4      P                  4       ;'       g    V  RV 2VR7      # )zUThe backend's own diagnostic for a read that ran and failed, else a bare exit status.z: exit r9  )r	   r   rä   )r;   rN  r,  s   &&&r#   rG  Ú ShellFileOperations._failed_readŠ  s=   € ô Ô$?ÀÓ$H×$NÑ$NÓ$P×$mÐ$mÐW[ÐV\Ð\cÐdkÐclÐTmØ'.ô0ð 	0r%   c                ó\   <€ V ^8„  d   QhRS[ RS[S[S[,          S[S[,          3,          /# rH   r1  )r"   r?   s   "€r#   r$   rÇ   �  s/   ø€ ÷ ñ ©#ð ±%¹Á½ÉÑR_ÕI`Ð8`Õ2añ r%   c                ó  € V P                  V4      pV P                  RV 2RV 24      w  r4p\        V R2^R7      pVf   RVP                  ^ 8w  d   V3# T3# Ve   V^8X  d   RV3# Vw  rxV^ 8w  d   RV P	                  WV4      3#  \
        P                  RP                  \        V4      P                  4       4      4      p	V	e   V P                  W˜4      '       g   R\        V R2^R7      3# V	R3#   \         d    Rp	 L@i ; i)u«  ``od`` fallback for a backend without ``base64``, fenced the same way.

``read_file_raw`` is the edit paths' source read AND, through ``_apply_add``, their
existence check, so a transport that simply is not installed must not read as "no such
file" â€” that clobbers the file the Add was refusing to overwrite. ``od`` is POSIX and
present in busybox; when it is missing too the caller gets a transport error, never a
not-found.zod -An -v -tx1 < r7  zM: this backend has neither base64 nor od, so a byte-exact read is unavailabler9  NrÚ   r8  )rú   r  r	   rß   rG  r    Úfromhexr  r   r£   r¹   r%  )
rC   r;   rL  r  r,  rç   ÚunavailablerN  r5   r   s
   &&        r#   rF  Ú)ShellFileOperations._read_exact_bytes_hex�  s<  € ð ×$Ñ$ TÓ*ˆØ$(×$5Ñ$5Ð8IÈ#ÈÐ6OÐS[Ð\_Ð[`ÐQaÓ$bÑ!ˆ˜6Ü#Ø�VÐhÐiØôˆð ÒØ 6×#3Ñ#3°qÔ#8˜ÐIÐI¸kÐIÐIØŠ?˜g¨œnØ˜Ð$Ð$Ø ‰ˆØ�aŒ<Ø˜×*Ñ*¨4¸'ÓBÐBÐBð	Ü—=‘= §¡Ô)DÀWÓ)M×)SÑ)SÓ)UÓ!VÓWˆDð Š<˜t×1Ñ1°$×=Ò=Øœ°°Ð6fÐ.gØ12ô4ð 4ð 4à�TˆzÐøô ô 	ØŠDð	ús   Â;C4 Ã4DÄDc                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# r¦   )r!   r   r    )r"   r?   s   "€r#   r$   rÇ   ®  s   ø€ ÷ ñ ¡Cð ©H±U­Oñ r%   c                ó  € RP                  \        V 4      P                  4       4      pV'       g   R# \        P                  ! RV4      '       g   R#  \
        P                  ! VRR7      #   \        P                  \        3 d     R# i ; i)uê   Decode one ``base64`` transport reply (a ``head -c N`` sample or a whole file). Whitespace-joins
the whole text first (``base64`` wraps at 76 columns), so callers hand over exactly one
segment; anything else fails validation â†’ None.rÚ   r%   z[A-Za-z0-9+/]+={0,2}NT©Úvalidate)
r  r   r£   ÚreÚ	fullmatchÚbase64Ú	b64decodeÚbinasciiÚErrorr¹   )r§   Úencodeds   & r#   r+  Ú)ShellFileOperations._decode_base64_sample­  so   € ð
 —'‘'Ô5°dÓ;×AÑAÓCÓDˆßÙÜ�|Š|Ð3°W×=Ò=Ùð	Ü×#Ò# G°dÔ;Ð;øÜ—‘¤
Ð+ô 	Úð	ús   ÁA+ Á+B
Â	B
c                ó&   <€ V ^8„  d   QhRS[ RS[/# r   )r    r\   )r"   r?   s   "€r#   r$   rÇ   ½  s   ø€ ÷ ñ ©ð ±$ñ r%   c                ó0  € V '       g   R# RV 9   d   R#  V P                  R4       R#   \         dc   pTP                  \        T 4      ^,
          8¼  d7    T RTP                   P                  R4        Rp?R#   \         d     Mi ; i Rp?R# Rp?ii ; i)up  Byte-layer binary detection: text iff valid UTF-8, allowing one incomplete
multibyte sequence at the very end (artifact of the byte-boundary cut).
NUL bytes or mid-stream invalid UTF-8 stay read-only so a readâ†’editâ†’write
round-trip never rewrites undecodable bytes as U+FFFD; a file that
legitimately CONTAINS U+FFFD is valid UTF-8 and reads as text.

See #80308.
Fó    Túutf-8N)ÚdecodeÚUnicodeDecodeErrorÚstartr  )r   Úexcs   & r#   Ú_is_likely_binary_bytesÚ+ShellFileOperations._is_likely_binary_bytes¼  s…   € ÷ ÙØ�fÔÙð	Ø�M‰M˜'Ô"ÙøÜ!ô 		ð �y‰yœC ›K¨!�OÔ+ðØ˜;˜SŸY™YÐ'×.Ñ.¨wÔ7Ý øÜ)ô Ùðúåûð		ús2   •( ¨B³!BÁA9Á9BÂBÂBÂBÂBc                ó:   <€ V ^8„  d   QhRS[ RS[ R,          RS[/# )r   r;   Úcontent_sampleNr   rí   )r"   r?   s   "€r#   r$   rÇ   Ø  s'   ø€ ÷ ñ ¡cð ¹3À½:ð ÑQUñ r%   c                óÌ   € \        V4      '       d   R# V'       dI   RVR,          9   d   R# \        R VR,           4       4      pV\        \        V4      R4      ,          R8„  # R# )zILegacy text-layer binary check: extension, else >30% non-printable chars.Tu   ï¿½:Niè  Nc              3   ó\   "  € T F"  p\        V4      ^ 8  g   K  VR9  g   K  ^x € K$  	  R# 5i)é    z
	N)Úord)r  Úcs   & r#   r  Ú8ShellFileOperations._is_likely_binary.<locals>.<genexpr>á  s)   é € ÐfÑ+@ aÄCÈÃFÈRÁK¤ÐTUÐ]eÑTe§¢Ó+@ùs   ‚,™,¢
,éè  g333333Ó?F)r   ÚsumÚminr  )rC   r;   rp  Únon_printables   &&& r#   Ú_is_likely_binaryÚ%ShellFileOperations._is_likely_binaryØ  sY   € ä ×%Ò%Ùßð ˜>¨%Õ0Ô0ÙÜÑf¨>¸%Ö+@ÓfÓfˆMØ ¤3¤s¨>Ó':¸DÓ#AÕAÀDÑHÐHÙr%   c                ó&   <€ V ^8„  d   QhRS[ RS[/# rH   rí   )r"   r?   s   "€r#   r$   rÇ   å  s   ø€ ÷ Eñ E™cð E¡dñ Er%   c                óx   € \         P                  P                  V4      ^,          P                  4       \        9   # ©r€   )r<  r;   ÚsplitextÚlowerÚIMAGE_EXTENSIONSrK   s   &&r#   Ú	_is_imageÚShellFileOperations._is_imageå  s+   € Ü�w‰w×Ñ Ó% aÕ(×.Ñ.Ó0Ô4DÑDÐDr%   c                ó,   <€ V ^8„  d   QhRS[ RS[RS[ /# )r   rP   Ú
start_liner   r)  )r"   r?   s   "€r#   r$   rÇ   è  s'   ø€ ÷ Mñ M©ð M¹#ð MÁcñ Mr%   c                óª   a€ ^ RI Hp V! 4       oVP                  R4      pRP                  V3R l\	        VP                  R4      VR7       4       4      # )zÍPrefix each line with a compact ``<n>|`` gutter, clamping long lines. Not
fixed-width: padding cost ~16% more tokens per line for no accuracy gain in
A/B, while dropping numbers regressed line-referencing.©Úget_max_line_lengthr¡   c              3   ón   <"  € T F*  w  rT R \        V4      S8:  d   TMVRS R,            2x € K,  	  R# 5i)Ú|Nz... [truncated]©r  )r  ÚiÚlineÚmax_line_lengths   &  €r#   r  Ú8ShellFileOperations._add_line_numbers.<locals>.<genexpr>ô  sB   øé € ð MáK‘�ð ˆc�œ3˜t›9¨Ô7‘4¸TÐBRÀ?Ð=SÐVgÕ=gÐhÕiÛKùs   ƒ25)rk  )Útools.tool_output_limitsr‰  Úremovesuffixr  Ú	enumerater£   )rC   rP   r†  r‰  r�  s   &&& @r#   Ú_add_line_numbersÚ%ShellFileOperations._add_line_numbersè  sU   ø€ õ 	AÙ-Ó/ˆð ×&Ñ& tÓ,ˆØ�y‰yô Mä$ W§]¡]°4Ó%8À
ÕKóMó Mð 	Mr%   c                ó&   <€ V ^8„  d   QhRS[ RS[ /# rH   r–   )r"   r?   s   "€r#   r$   rÇ   ø  s   ø€ ÷ ñ ¡ð ©ñ r%   c                ó¤  € ^ RI Hp \        V P                  RR4      p\        V P                  RR4      ;'       g    RpT! Y;'       g    RV4      pV'       d   V# V'       d   VP	                  R4      '       g   V# V P                  R4      pVP                  ^ 8X  Ed1   VP                  P                  4       '       Ed   VP                  P                  4       pVR8X  d   V# VP	                  R	4      '       d   WqR
,          ,           # VR
,          pVP                  R4      p	V	^ 8¼  d   VRV	 MTp
V
'       d—   \        P                  ! RV
4      '       dz   V P                  RV
 24      pVP                  ^ 8X  dU   VP                  P                  4       '       d5   VP                  P                  4       V^\        V
4      ,           R ,           # V# )u  Expand ``~`` / ``~user`` via the backend's shell (its HOME, not the
host's). A host path under the configured workspace mount is rewritten
to that container path first, so a Windows drive path is readable
inside Docker. Must run BEFORE shell escaping â€” ~ doesn't expand in quotes.)Útranslate_mounted_host_pathÚhost_cwdNÚhost_cwd_mountz
/workspacerÚ   Ú~z
echo $HOMEz~/:r€   NNrÊ   z[a-zA-Z0-9._-]+zecho ~)rã   r˜  rÌ   rË   r*   ré   rß   rÞ   rä   Úfindr]  r^  r  )rC   r;   r˜  Ú	host_rootÚcontainer_rootÚ
translatedrç   Úhomer  Ú	slash_idxÚusernameÚexpand_results   &&          r#   Ú_expand_pathÚ ShellFileOperations._expand_pathø  st  € õ
 	KÜ˜DŸH™H j°$Ó7ˆ	Ü  §¡Ð+;¸TÓB×RÐRÀlˆÙ0°·°ÀBÈÓWˆ
ßØÐß˜4Ÿ?™?¨3×/Ò/ØˆKØ—‘˜LÓ)ˆØ×Ñ˜qÕ  V§]¡]×%8Ñ%8×%:Ó%:Ø—=‘=×&Ñ&Ó(ˆDØ�sŒ{Ø�Ø�‰˜t×$Ò$Ø 2�h•Ð&ð ˜•8ˆDØŸ	™	 #›ˆIØ+4¸¬>�t˜J˜YÑ'¸tˆHßœBŸLšLÐ);¸X×FÒFØ $§
¡
¨V°H°:Ð+>Ó ?�Ø ×*Ñ*¨aÔ/°M×4HÑ4H×4NÑ4N×4PÒ4PØ(×/Ñ/×5Ñ5Ó7¸$¸qÄ3ÀxÃ=Õ?PÐ?QÐ:RÕRÐRØˆr%   c                ó,   <€ V ^8„  d   QhRS[ RS[RS[ /# )r   rL  Útranslate_pathr   rí   )r"   r?   s   "€r#   r$   rÇ     s"   ø€ ÷ 7ñ 7¡Sð 7¹$ð 7É#ñ 7r%   c                óâ   € ^ RI HpHp V'       d
   V! V4      pM7V'       d0   \        V P                  RR4      '       d   VP                  RR4      pRVP                  RR4      ,           R,           # )a¿  Escape a string for safe use in shell commands.

On Windows native drive paths (``C:\Users\x`` / ``C:/Users/x``)
and mixed MSYS leftovers (``/c/Users\x``) are rewritten to the
Git Bash ``/c/Users/x`` form via ``_bash_safe_path``: bash eats
backslashes and MSYS otherwise mangles drive paths into the
``Directory \drivers\etc does not exist`` failure class. Reuses
the env-layer translator so shell file ops and the terminal ``cd``
agree on the path form. No-op off Windows and for plain POSIX paths.

``translate_path=False`` skips that translation for non-path values
such as regex patterns. Backslash compensation applies only to the
local Windows argv transport. Serialized shell text stays literal.
)Ú_IS_WINDOWSÚ_bash_safe_pathÚis_localFÚ\z\\Ú'ú'"'"')Útools.environments.localr©  rª  rÌ   rË   Úreplace)rC   rL  r§  r©  rª  s   &&&  r#   rú   Ú%ShellFileOperations._escape_shell_arg  sU   € ÷ 	JçÙ! #Ó&‰CßœW T§X¡X¨z¸5×AÒAØ—+‘+˜d FÓ+ˆCà�S—[‘[  iÓ0Õ0°3Õ6Ð6r%   c                ó&   <€ V ^8„  d   QhRS[ RS[ /# )r   rL  r   r–   )r"   r?   s   "€r#   r$   rÇ   /  s   ø€ ÷ 7ñ 7©3ð 7±3ñ 7r%   c                ó¢   € ^ RI HpHp V'       d!   V'       d   V! V4      P                  RR4      pRVP                  RR4      ,           R,           # )u*  Quote a path for a NATIVE Windows binary (rg, node, git ...): those don't
understand the MSYS ``/c/...`` form and Hermes disables MSYS argument
conversion, so nothing translates it back (â†’ ``os error 3``). ``C:/Users/x``
is accepted by every layer. Identical to ``_escape_shell_arg`` off Windows.)r©  Ú_msys_to_windows_pathr¬  rÊ   r­  r®  )r¯  r©  r´  r°  )rC   rL  r©  r´  s   &&  r#   Ú_escape_native_tool_argÚ+ShellFileOperations._escape_native_tool_arg/  s?   € ÷
 	PßŸ3Ù'¨Ó,×4Ñ4°T¸3Ó?ˆCØ�S—[‘[  iÓ0Õ0°3Õ6Ð6r%   c                ó,   <€ V ^8„  d   QhRS[ RS[ RS[/# ©r   r;   rP   r   rõ   )r"   r?   s   "€r#   r$   rÇ   9  s"   ø€ ÷ :6ñ :6¡#ð :6±ð :6¹ñ :6r%   c                óì  € V P                  4       '       d]   \        P                  ! V P                  V4      VP	                  RR4      4      p\        T;'       g    RV'       d   ^R7      # ^ R7      # V P                  V4      pT P                  \        P                  P                  V4      ;'       g    R4      pV P                  R4      pRV RV R	2V,           R
,           pV P                  WrR7      # )u<  Write ``content`` atomically: stdin â†’ temp file in the SAME directory â†’
``mv -f`` (same-FS rename; cross-device ``mv`` is copy+unlink, NOT atomic).
``mkdir -p`` folded in. Exit 0 = swap happened; non-zero = original intact.

Symlink targets are resolved first (replacing the link would orphan the
target) and the temp dir recomputed from the RESOLVED target. Existing
target: mode copied via ``stat`` (GNU ``-c%a`` / BSD ``-f%Lp``) + ``chmod``
(``chmod --reference`` is GNU-only). New target: ``chmod "=rw"`` AFTER cat
gives umask-default perms instead of mktemp's 0600 â€” not ``$(umask)``
arithmetic (zsh parses leading-zero constants as decimal), quoted so zsh
doesn't =word-expand. ``trap ... EXIT`` removes the temp on every failure.
The local POSIX backend does the same in-process (``tools.file_operations_native``).
rh  ÚsurrogateescaperÚ   r9  r„   z.hermes-tmp.XXXXXXz
set -e; d=z; t=z¾; if [ -L "$t" ]; then rt="$(readlink -f "$t" 2>/dev/null || realpath "$t" 2>/dev/null || true)"; [ -n "$rt" ] && { t="$rt"; d="$(dirname "$t")"; }; fi; mkdir -p "$d"; tmp="$(mktemp -p "$d" aó   2>/dev/null || mktemp "$d/.hermes-tmp.$$.XXXXXX" 2>/dev/null || { tmp="$d/.hermes-tmp.$$"; : > "$tmp" && echo "$tmp"; })"; [ -n "$tmp" ] || { echo "atomic write: could not create temp file" >&2; exit 1; }; trap 'rm -f \"$tmp\"' EXIT; if [ -e "$t" ]; then m="$(stat -c%a "$t" 2>/dev/null || stat -f%Lp "$t" 2>/dev/null || true)"; [ -n "$m" ] && chmod "$m" "$tmp" 2>/dev/null || true; fi; cat > "$tmp"; if [ ! -e "$t" ]; then chmod "=rw" "$tmp" 2>/dev/null || true; fi; mv -f "$tmp" "$t"; trap - EXIT)rÖ   )r:  Ú
_native_ioÚatomic_writeÚ_native_pathÚencoder	   rú   r<  r;   Údirnameré   )rC   r;   rP   rÀ   Úq_pathÚq_parentÚtmplÚscripts   &&&     r#   Ú_atomic_writeÚ!ShellFileOperations._atomic_write9  sé   € ð ×$Ñ$×&Ò&Ü×+Ò+¨D×,=Ñ,=¸dÓ,CÀWÇ^Á^ÐT[Ð]nÓEoÓpˆEÜ ¨¯¨°ÇE¸qÔQÐQÈqÔQÐQØ×'Ñ'¨Ó-ˆØ×)Ñ)¬"¯'©'¯/©/¸$Ó*?×*FÐ*FÀ3ÓGˆØ×%Ñ%Ð&:Ó;ˆðð  �
˜$˜v˜hð '%ð!%ð, (,õ-,ð,/õ-$ð 	ðL �z‰z˜&ˆzÓ5Ð5r%   c                ó<   <€ V ^8„  d   QhRS[ RS[S[ ,          RS[/# )r   r;   rQ   r   )r!   r   r\   )r"   r?   s   "€r#   r$   rÇ   u  s+   ø€ ÷ Kñ K¡#ð K±H¹SµMð KÉTñ Kr%   c                ó~   € V P                  V^4      pVP                  ^ 8H  ;'       d    \        VP                  4      # )uÛ   Whether the on-disk file starts with a UTF-8 BOM. ALWAYS probes disk:
``pre_content`` usually comes from ``read_file_raw``, which strips BOMs, so
trusting it would silently drop the marker on rewrite. Missing â†’ False.)r  rß   r   rÞ   )rC   r;   rQ   Úhead_results   &&& r#   Ú_file_has_bomÚ!ShellFileOperations._file_has_bomu  s8   € ð —j‘j  qÓ)ˆØ×$Ñ$¨Ñ)×JÐJ¬h°{×7IÑ7IÓ.JÐJr%   c                ó2   <€ V ^8„  d   QhRS[ RS[ RS[ RS[ /# )r   Úold_contentÚnew_contentÚfilenamer   r–   )r"   r?   s   "€r#   r$   rÇ   |  s*   ø€ ÷ ?ñ ?©ð ?¹3ð ?É#ð ?ÑRUñ ?r%   c           	     ó    € R P                  \        P                  ! VP                  RR7      VP                  RR7      RV 2RV 2R7      4      # )rÚ   T)Úkeependsza/zb/)ÚfromfileÚtofile)r  ÚdifflibÚunified_diffÚ
splitlines)rC   rÌ  rÍ  rÎ  s   &&&&r#   Ú_unified_diffÚ!ShellFileOperations._unified_diff|  sS   € Ø�w‰w”w×+Ò+Ø×"Ñ"¨DÐ"Ó1°;×3IÑ3IÐSWÐ3IÓ3XØ˜(˜�_¨r°(°¨_ô>ó ?ð 	?r%   c                ó&   <€ V ^8„  d   QhRS[ RS[/# rH   rI   )r"   r?   s   "€r#   r$   rÇ   „  s   ø€ ÷ Oñ O¡ð O©ñ Or%   c                ó"   € \        RV  R2R7      # )z5Error for a path that exists but would block if read.zCannot read 'zr': not a regular file (directory, dangling symlink, FIFO, socket, or device). Reading it could block indefinitely.r¿   ©r   )r;   s   &r#   Ú_not_regular_errorÚ&ShellFileOperations._not_regular_errorƒ  s&   € ô Ø˜D˜6ð "Mð MôOð 	Or%   c                ó<   <€ V ^8„  d   QhRS[ RS[S[S[ 3,          /# rH   )r!   r  r0   )r"   r?   s   "€r#   r$   rÇ   Š  s#   ø€ ÷ !ñ !©ð !±±c¹3°hµñ !r%   c                óŠ  € V P                  V4      pV P                  RV RV RV RV R\         R\         R24      p\	        VP
                  4      P                  4       pV\        8X  d   R
# V\        8X  d   R# VP                  ^ 8w  d   ^ VP                  ;'       g    R3#  \        V4      R	3#   \         d    Ru # i ; i)aœ  Byte size of a REGULAR file: ``(file_size, status)`` with status ``"ok"``,
``"missing"``, ``"not_regular"``, ``"bad_size"`` (unparseable ``wc``),
``"env_unavailable"``, or the named working-directory error when the exec
wrapper itself failed (``_env_unavailable_error`` surfaces it verbatim).
``wc -c <`` on a writer-less FIFO/socket//dev/zero blocks forever and a
name-based blocklist can't cover a FIFO (a file TYPE at any path); ``[ -f ]``
is a stat (symlinks followed) so it answers without touching content. A dangling
symlink is ``not_regular``, never ``missing``: the entry exists, and a writer
told the path is free would follow the link and create its target.úif [ -f ú ]; then wc -c < z 2>/dev/null; elif [ -e ú ] || [ -L ú ]; then echo ú; else echo ú; fiÚenv_unavailableÚok)r†   Úmissing)r†   Únot_regular)r†   Úbad_size)rú   ré   ÚNOT_REGULAR_SENTINELÚMISSING_SENTINELr   rÞ   rä   rß   rà   r0   r¹   )rC   r;   rL  Ústat_resultÚstat_outputs   &&   r#   Ú_probe_regular_fileÚ'ShellFileOperations._probe_regular_fileŠ  sè   € ð ×$Ñ$ TÓ*ˆð —j‘jØ�s�eÐ,¨S¨Eð 2Ø˜˜[¨¨¨^Ô<PÐ;Qð RÜ)Ð*¨$ð0ó1ˆô 2°+×2DÑ2DÓE×KÑKÓMˆØÔ*Ô*ØÐØÔ.Ô.Ø#Ð#Ø× Ñ  AÔ%Ø�k×+Ñ+×@Ð@Ð/@Ð@Ð@ð	!Ü�{Ó# TÐ)Ð)øÜô 	!Ø Ò ð	!ús   Â%B2 Â2CÃCc                ó,   <€ V ^8„  d   QhRS[ RS[ RS[/# )r   r;   Ústatusr   rI   )r"   r?   s   "€r#   r$   rÇ   ¨  s(   ø€ ÷ hñ h©3ð h¹ð hÑT^ñ hr%   c                óH   € VR 8w  d   \        VR7      # \        RV R2R7      # )rå  r¿   ú1Terminal environment unavailable: could not stat úC (the sandbox may still be starting or was removed). Retry shortly.rÚ  )rC   r;   rñ  s   &&&r#   Ú_env_unavailable_errorÚ*ShellFileOperations._env_unavailable_error¨  s;   € ØÐ&Ô&Ü FÔ+Ð+ÜÐ#TÐUYÐTZð [fð "fô hð 	hr%   c                óL   <€ V ^8„  d   QhRS[ RS[S[S[S[,          3,          /# rH   )r!   r  r\   r   r    )r"   r?   s   "€r#   r$   rÇ   ®  s-   ø€ ÷ Añ A¡3ð A©5±±xÁµÐ1FÕ+Gñ Ar%   c                óì   € V P                  V4      pVe)   \        V4      pT;'       g    V P                  V4      V3# \        V P	                  VR4      P
                  4      pV P                  W4      R3# )u’   ``(is_binary, sample_bytes)`` â€” byte-layer detection when the transport
allows (base64 sample), else the legacy text heuristic (sample is None).Nrw  )r.  r   rm  r   r  rÞ   r{  )rC   r;   Úsample_bytesÚ
ext_binaryÚsample_outputs   &&   r#   Ú_detect_binaryÚ"ShellFileOperations._detect_binary®  ss   € ð ×.Ñ.¨tÓ4ˆØÒ#Ü-¨dÓ3ˆJØ×KÐK ×!=Ñ!=¸lÓ!KÈ\ÐYÐYÜ3°D·J±J¸tÀTÓ4J×4QÑ4QÓRˆØ×%Ñ% dÓ:¸DÐ@Ð@r%   i   c                ó    <€ V ^8„  d   QhRS[ /# ©r   r   r–   )r"   r?   s   "€r#   r$   rÇ   Ã  s   ø€ ÷ ñ ©ñ r%   c                óp   € V P                  4       '       d    V P                  \        P                  4      # R# )uÜ  Return a shell-safe Python interpreter for the terminal backend.

On the local backend ``sys.executable`` is always a working
interpreter â€” and on Windows it dodges the Microsoft Store
``python``/``python3`` alias stub (exit 49, "Python was not
found") that otherwise breaks inline ``-c`` snippets. Remote
backends (docker/ssh/...) don't have the agent's interpreter, so
they fall back to ``python3`` on their own PATH (the ``python``
fallback is handled at the call site).
r  )Ú_lsp_local_onlyrú   ÚsysÚ
executable)rC   s   &r#   Ú_python_interpreter_cmdÚ+ShellFileOperations._python_interpreter_cmdÃ  s+   € ð ×Ñ×!Ò!Ø×)Ñ)¬#¯.©.Ó9Ð9Ùr%   c                ó:   <€ V ^8„  d   QhRS[ RS[ R,          RS[/# )r   r  ÚpyNr   rõ   )r"   r?   s   "€r#   r$   rÇ   Ò  s&   ø€ ÷ 
ñ 
©Cð 
±S¸4µZð 
É=ñ 
r%   c                óÀ   € \         P                  ! VP                  R4      4      P                  R4      pVf   V P	                  4       pV P                  V RV R24      # )a™  Run a Python ``snippet`` in the terminal backend's interpreter.

Base64-encodes the snippet so it survives every shell/quoting layer
as pure ASCII: Windows ``subprocess`` list-arg quoting and ``bash``
double-quote processing both eat backslashes, which otherwise
corrupts Windows paths (``C:\Users\x``) and byte literals
(``b'\xfe\xff'``) embedded in a ``-c`` program. ``exec`` decodes
and runs it unchanged.
rh  Úasciiz+ -c "import base64; exec(base64.b64decode('z').decode())")r_  Ú	b64encoder¾  ri  r  ré   )rC   r  r  rc  s   &&& r#   Ú_exec_python_snippetÚ(ShellFileOperations._exec_python_snippetÒ  s]   € ô ×"Ò" 7§>¡>°'Ó#:Ó;×BÑBÀ7ÓKˆØŠ:Ø×-Ñ-Ó/ˆBØ�z‰zØˆdÐ>¸w¸iÀ~ÐVó
ð 	
r%   c                óH   <€ V ^8„  d   QhRS[ RS[RS[RS[RS[S[,          /# )r   r;   r<   r=   r/   r   )r!   r0   r   r   )r"   r?   s   "€r#   r$   rÇ   ã  s>   ø€ ÷ P?ñ P?¡Cð P?±ð P?¹Sð P?Ù#&ðP?Ù+3±JÕ+?ñP?r%   c                ó\  a€ \        V4      '       g   W@P                  8”  d   R# R\        P                  ! V4       R\	        V4       R\	        V4       RV P                   RV P
                   R2pV P                  V4      pVP                  ^ 8w  d/   RVP                  ;'       g    R	9   d   V P                  VR
R7      p\        VP                  ;'       g    R	4      pVP                  R4      pVP                  ^ 8w  g   V^ 8  d   R# Wx\        R4      ,           R P                  4       p	 \        P                  ! RV	9   d   V	P                  R^4      ^ ,          MT	4      p
V
R,          p\	        V
R,          4      p\        V
P!                  RR4      4      pY#,           ^,
          pYÎ8„  pRTP)                  4        R2.pT'       d&   TP+                  RT^,            RT RT RT R2	4       ^ RIHp T! 4       o\0        ;QJ d.    T3R lTP                  R4       4       F  '       g   K   RM#	  RM! T3R lTP                  R4       4       4      p\3        T P5                  Y²4      TYORP7                  T4      T'       d   RR7      # RR7      #   \"        \$        \&        3 d     R# i ; i)zºRead ``path`` as UTF-16 transcoded to UTF-8, or None (caller falls back
to the binary-file error). Skips known-binary extensions and files over
10 MiB. ``path`` must already be expanded.Nzimport sys, json, os
p = z

offset = z	
limit = z
MAX = z

SAMPLE = af  
try:
    size = os.path.getsize(p)
    if size > MAX:
        print('HERMES_UTF16:NO'); sys.exit(0)
    with open(p, 'rb') as f:
        data = f.read()
    sample = data[:SAMPLE]
    enc = None
    if sample[:2] == b'\xfe\xff':
        enc = 'utf-16-be'
    elif sample[:2] == b'\xff\xfe':
        enc = 'utf-16-le'
    else:
        odd = sum(1 for i in range(1, len(sample), 2) if sample[i] == 0)
        even = sum(1 for i in range(0, len(sample), 2) if sample[i] == 0)
        if even == 0 and odd >= 2:
            enc = 'utf-16-le'
        elif odd == 0 and even >= 2:
            enc = 'utf-16-be'
    if enc is None:
        print('HERMES_UTF16:NO'); sys.exit(0)
    text = data.decode(enc, 'replace')
    if text[:1] == '\ufeff':
        text = text[1:]
    text = text.replace('\r\n', '\n')
    lines = text.split('\n')
    total = len(lines)
    sel = lines[offset - 1: offset - 1 + limit]
    out = {'total_lines': total, 'encoding': enc,
           'content': '\n'.join(sel)}
    print('HERMES_UTF16:OK')
    print(json.dumps(out, ensure_ascii=True))
except Exception:
    print('HERMES_UTF16:NO'); sys.exit(0)
r  rÚ   Úpython©r  zHERMES_UTF16:OKr¡   rP   Útotal_linesÚencodingzutf-16zTranscoded from zP to UTF-8 for display. Text edits via patch/write_file would re-encode as UTF-8.úUse offset=ú to continue reading (showing Ú-ú of ú lines)rˆ  c              3   ó@   <"  € T F  p\        V4      S8„  x € K  	  R # 5ir�   rŒ  ©r  rŽ  r�  s   & €r#   r  Ú6ShellFileOperations._try_read_utf16.<locals>.<genexpr>/  s   øé € ÐZÑFY¸dœc $›i¨/Ö9ÓFYùó   ƒTFr  ©rP   r  r/   Ú	truncatedrè   Útruncated_lines)r   Ú_UTF16_MAX_BYTESr·   Údumpsr0   Ú_UTF16_SAMPLE_BYTESr  rß   rÞ   r   rœ  r  rä   r¸   r£   r!   râ   r¹   ÚKeyErrorÚ	TypeErrorÚupperr²   r‘  r‰  Úanyr   r”  r  )rC   r;   r<   r=   r/   r  rç   rÞ   ÚmarkerrN  r   rP   r  r  Úend_liner  Ú
hint_partsr‰  r  r�  s   &&&&&              @r#   Ú_try_read_utf16Ú#ShellFileOperations._try_read_utf16ã  sŒ  ø€ ô
   ×%Ò%¨×5JÑ5JÔ)JÙðÜ—:’:˜dÓ#Ð$ð %Ü˜F›�}ð %Ü˜5“z�lð #Ø×*Ñ*Ð+ð ,Ø×0Ñ0Ð1ð "2:ð':ð 	ðV ×*Ñ*¨7Ó3ˆØ×Ñ˜qÔ  Y°6·=±=×3FÐ3FÀBÔ%GØ×.Ñ.¨w¸8Ð.ÓDˆFä,¨V¯]©]×-@Ð-@¸bÓAˆØ—‘Ð.Ó/ˆØ×Ñ˜qÔ  F¨Q¤JÙØ¤#Ð&7Ó"8Õ8Ð9Ð:×@Ñ@ÓBˆð	Ü—:’:¸4À7¼?˜gŸm™m¨D°!Ó4°QÖ7ÐPWÓXˆDØ˜9•oˆGÜ˜d =Õ1Ó2ˆKÜ˜4Ÿ8™8 J°Ó9Ó:ˆHð •> AÕ%ˆØÑ*ˆ	Ø(¨¯©Ó)9Ð(:ð ;Rð Rð Sˆ
çØ×ÑØ˜h¨�l˜^ð ,Ø"˜8 1 X J¨d°;°-¸wðHôIõ 	AÙ-Ó/ˆß›#ÔZÀgÇmÁmÐTXÔFYÓZŸ#Ÿ#š#ÔZÀgÇmÁmÐTXÔFYÓZÓZˆÜØ×*Ñ*¨7Ó;ÈØ¸3¿8¹8ÀJÓ;Oß$3˜Dô?ð 	?ð :>ô?ð 	?øô œH¤iÐ0ô 	Úð	ús   Ä.A,J ÊJ+Ê*J+c                ó2   <€ V ^8„  d   QhRS[ RS[RS[RS[/# r:   r>   )r"   r?   s   "€r#   r$   rÇ   5  s5   ø€ ÷ YPñ YP™cð YP©3ð YP¹3ð YPÉ*ñ YPr%   c           	     óÈ  € V P                  V4      p\        W#4      w  r#V P                  4       '       d   V P                  WV4      # V P	                  V4      '       g   \        V4      '       d   V P                  WV4      # ^ RIHp ^V! 4       ,          ^,           pW#,           ^,
          p\        \        4      pV P                  V P                  WWeV4      4      pVP                  ;'       g    Rp	Wy9  d�   \        V	4      P                  4       p
V
\         8X  d   V P#                  WV4      # V
\$        8X  d   V P'                  V4      # \(        P+                  RWP,                  \/        V	4      4       V P                  WV4      # \1        W—4      pVP,                  ^ 8w  g   \/        V4      ^8w  d=   \(        P+                  RWP,                  \/        V4      4       V P                  WV4      # Vw  rÍrïpp\        V4      P3                  4       p \5        V^ ,          4      \5        V^,          4      pp \5        \        T4      P                  4       4      pT^ 8X  d   T P;                  T4      MRpTe   T P=                  T4      pMN\(        P+                  RTT4       \        T P?                  TR4      P                  4      pT PA                  TT4      pT'       d   T PC                  YTTT4      # T^ 8w  d   \E        R	\        T4       2R
7      # \        T4      p \5        \        T4      P                  4       4      p\        T4      P                  4       pTR9   d   TR8H  MRpT PG                  TY&TTTR7      #   \6        \8        3 d0    \(        P+                  RTTRR 4       T P                  YT4      u # i ; i  \8         d    ^ p ELwi ; i  \8         d    ^ p L£i ; i)a  Read a file with pagination, binary detection, and line numbers.

``offset`` is 1-indexed; ``limit`` is clamped by ``normalize_read_pagination``.
One shell round-trip answers every question the read needs (existence, size,
binary sample, page, line count, trailing newline; see ``_read_probe_cmd``).
An unparseable reply falls back to ``_read_file_sequential`` (one probe per
question), so an exotic shell can never do worse than before. On a local
POSIX environment the read never touches the shell (``_read_file_native``).
rˆ  rÚ   zmread_file: compound probe reply for %s has no sentinel (exit %s, %d chars); falling back to sequential probesznread_file: compound probe for %s returned exit %s with %d segments (want 6); falling back to sequential probesz]read_file: compound probe for %s has unparseable status %r; falling back to sequential probesNznread_file: no usable base64 sample for %s (base64 exit %s); paying one extra round-trip for the text heuristicrw  úFailed to read file: r¿   Ú1©r<   r'  r  r/   Úfile_ends_with_newlineiØÿÿÿ)Ú0r.  )$r¤  r   r:  Ú_read_file_nativerƒ  r   Ú_read_file_sequentialr‘  r‰  r›   Ú_READ_SENTINEL_PREFIXré   Ú_read_probe_cmdrÞ   r   rä   rë  Ú_read_file_missingrê  rÛ  ÚloggerÚdebugrß   r  r¤   r£   r0   r  r¹   r+  rm  r  r{  Ú_read_binary_filer   Ú_assemble_read_result)rC   r;   r<   r=   r‰  Úline_clamp_bytesr'  rž   Úprober�   r&  r  Úsize_segÚ
sample_segÚpage_segÚwc_segÚtail_segÚ
status_segrñ  Ú	sample_rcr,  r/   rù  Ú	is_binaryrû  Úread_outputr  Ú	tail_flagr0  s   &&&&                         r#   rD   ÚShellFileOperations.read_file5  s©  € ð × Ñ  Ó&ˆÜ1°&Ó@‰ˆà×$Ñ$×&Ò&Ø×)Ñ)¨$¸Ó>Ð>ð �>‰>˜$×ÒÔ#7¸×#=Ò#=Ø×-Ñ-¨d¸EÓBÐBå@ØÑ2Ó4Õ4°qÕ8ÐØ•> AÕ%ˆÜ Ô!6Ó7ˆØ—
‘
˜4×/Ñ/°¸hÐZbÓcÓdˆØ—‘×#Ð# ˆàÔ!ä0°Ó8×>Ñ>Ó@ˆFØÔ)Ô)Ø×.Ñ.¨t¸UÓCÐCØÔ-Ô-Ø×.Ñ.¨tÓ4Ð4Ü�L‰LðIà—o‘o¤s¨6£{ô4ð ×-Ñ-¨d¸EÓBÐBä" 6Ó4ˆØ�?‰?˜aÔ¤3 x£=°AÔ#5Ü�L‰LðGà—o‘o¤s¨8£}ô6ð ×-Ñ-¨d¸EÓBÐBØGOÑDˆ˜h°¸*ä,¨ZÓ8×>Ñ>Ó@ˆð	CÜ!$ V¨A¥Y£´°V¸AµY³�wˆIð	ÜÔ7¸ÓA×GÑGÓIÓJˆIð BKÈaÄ�t×1Ñ1°*Ô=ÐUYˆØÒ#Ø×4Ñ4°\ÓB‰Iä�L‰LðEØFJÈIôWô 8¸¿
¹
À4ÈÓ8N×8UÑ8UÓVˆMØ×.Ñ.¨t°]ÓCˆIßØ×)Ñ)¨$¸¸yÈ,ÓWÐWà�aŒ<ÜÐ&;Ô<WÐX`Ó<aÐ;bÐ$cÔdÐdÜ1°(Ó;ˆð	ÜÔ9¸&ÓA×GÑGÓIÓJˆKô 0°Ó9×?Ñ?ÓAˆ	Ø5>À*Ô5L ¨cÒ!1ÐRVÐØ×)Ñ)Ø À{ØÐ8Nð *ó Pð 	PøôE œJÐ'ô 	CÜ�L‰Lð4Ø59¸:ÀcÀdÐ;KôMð ×-Ñ-¨d¸EÓBÒBð		Cûô ô 	Ø‹Ið	ûô, ô 	ØŠKð	ús6   È$M: È4"N= Ì"O Í:=N:Î9N:Î=OÏOÏO!Ï O!c                ó    <€ V ^8„  d   QhRS[ /# rÿ  )r\   )r"   r?   s   "€r#   r$   rÇ   �  s   ø€ ÷ 
Bñ 
B¡dñ 
Br%   c                óâ   € \         P                  P                  RR4      P                  4       P	                  4       pVR9   d   R# \
        P                  R8g  ;'       d    V P                  4       # )a  Whether ``read_file`` and ``search_files`` may bypass the shell: only POSIX + ``LocalEnvironment``
(file is on this host, path already native; Windows keeps the shell path since
file_operations holds Git-Bash-style paths there). ``HERMES_NATIVE_FILE_READ=0``
turns the fast path off.ÚHERMES_NATIVE_FILE_READr.  FÚwin32)r1  ÚfalseÚnoÚoff)r<  Úenvironrâ   rä   r�  r  Úplatformr  )rC   Úflags   & r#   r:  Ú(ShellFileOperations._native_read_enabled�  sY   € ô
 �z‰z�~‰~Ð7¸Ó=×CÑCÓE×KÑKÓMˆØÐ.Ô.Ùô �|‰|˜wÑ&×AÐA¨4×+?Ñ+?Ó+AÐAr%   c                ó&   <€ V ^8„  d   QhRS[ RS[ /# rH   r–   )r"   r?   s   "€r#   r$   rÇ   œ  s   ø€ ÷ oñ o¡ð o©ñ or%   c                óâ   € \         P                  P                  V4      '       d   V# \         P                  P                  \	        V P
                  RR4      ;'       g    V P                  V4      # )zN``path`` resolved the way the shell resolves it: against the live backend cwd.rÆ   N)r<  r;   r=  r  rÌ   rË   rÆ   rK   s   &&r#   r½  Ú ShellFileOperations._native_pathœ  sL   € ä—w‘w—}‘} T×*Ò*ˆtÐn´·±·±¼WÀTÇXÁXÈuÐVZÓ=[×=gÐ=gÐ_c×_gÑ_gÐimÓ0nÐnr%   c                ó2   <€ V ^8„  d   QhRS[ RS[RS[RS[/# r:   r>   )r"   r?   s   "€r#   r$   rÇ      s/   ø€ ÷ Xñ X¡cð X±3ð X¹sð XÁzñ Xr%   c                óŒ	  € ^ RI p\        P                  P                  V4      '       d   TMH\        P                  P	                  \        V P                  RR4      ;'       g    V P                  V4      p \        P                   ! V4      pTP                  TP                   4      '       g   T P                  T4      # TP"                  pT P%                  T4      '       d   T P'                  T4      # ^ RIHp ^T! 4       ,          ^,           p	Y#,           ^,
          p
. p^ p^p\-        4       pRpRp\.        P0                  ! 4       p \3        TR4      ;_uu_ 4       pTP5                  R4      p\7        T4      pT'       g   T P9                  T4      '       d   T P;                  YY7T4      uuRRR4       # TP=                  ^ 4        TP5                  R4      pT'       g   EMQTP?                  T4       TRR pYÚ8”  d#   TTPA                  R	4      ,          pTRR R	8g  pKZ  ^ \C        T4      ppTT8  g   Kp  TPE                  R	T4      pY-u;8*  ;'       d    T
8*  Mu pT^ 8  d@   T'       d4   \C        T4      T	8  d$   TTTTT	\C        T4      ,
          ,            ,          pRpKÝ  T'       d_   \C        T4      T	8  d.   TTT\G        TTT	\C        T4      ,
          ,           4       ,          pTPI                  \K        T4      R	,           4       \-        4       pRpT^,          pT^,          pT^,           pEK  RRR4       T'       d3   Y-u;8:  d   T
8:  d%   M M!TPI                  \K        T4      R	,           4       \M        RP	                  T4      PO                  R
RR7      4      pT PQ                  TY*TTT'       d   TR	8H  MRR7      pTPR                  TPT                  TP"                  TPV                  TPX                  TP[                  4       3Tn.        T#   \        \        3 dN    \        P                  P                  T4      '       d   T P                  T4      u # T P                  YT4      u # \         d    T P                  YT4      u # i ; i  + '       g   i     ELg; i  \         d    T P                  YT4      u # i ; i)u‚  ``read_file`` without a shell â€” same contract as the shell path, byte for
byte. ``os.stat`` is the ``[ -f ]`` guard (a stat, never an open, so FIFOs and
devices are refused before anything touches them); the first 1000 bytes drive
the byte-layer binary check; the page is produced exactly as
``sed -n 'a,bp' | cut -b1-N`` prints it (each line clamped to N bytes and
newline-terminated) then decoded with errors="replace" like the transport.
One chunked pass counts lines and collects the page, so neither the file nor
a pathological line is ever held whole. ``path`` is already expanded; any
unexpected OSError hands over to the shell path.NrÆ   rˆ  Fr%   r4  rw  Tó   
rh  r°  )Úerrorsr/  r3   r  )/r;  r<  r;   r=  r  rÌ   rË   rÆ   ÚFileNotFoundErrorÚNotADirectoryErrorÚislinkrÛ  r6  rE  r3  r@  rB  Úst_sizerƒ  Ú_image_redirect_resultr‘  r‰  Ú	bytearrayÚhashlibÚsha256r>  rC  r   rm  r9  ÚseekÚupdateÚcountr  rœ  ry  r²   r    r   ri  r:  Úst_devÚst_inoÚst_mtime_nsÚst_ctime_nsÚdigestÚ	_snapshot)rC   r;   r<   r=   rH  rI  Ústr/   r‰  Úclampr'  Úpager  ÚlinenoÚkeptÚhave_partialÚ	last_byteri  rK  r   rú  ÚchunkÚposÚnÚnlÚin_pagerE  rç   s   &&&&                        r#   r2  Ú%ShellFileOperations._read_file_native   só  € ó 	ä—w‘w—}‘} T×*Ò*‰t´·±·±Ü�D—H‘H˜e TÓ*×6Ð6¨d¯h©h¸ó1>ˆð	CÜ—’˜“ˆBð �}‰}˜RŸZ™Z×(Ò(Ø×*Ñ*¨4Ó0Ð0Ø—J‘Jˆ	Ø�>‰>˜$×ÒØ×.Ñ.¨yÓ9Ð9å@ØÑ'Ó)Õ)¨AÕ-ˆØ•> AÕ%ˆàˆØˆØˆÜ‹{ˆØˆØˆ	Ü—’Ó!ˆð&	CÜ�d˜D×!Ô! RØŸ™ ›�Ü1°$Ó7�
ß ×!=Ñ!=¸f×!EÒ!EØ×1Ñ1°$ÀÐRXÓY÷	 "Ò!ð
 —‘˜”
ØØŸG™G GÓ,�Eß ÙØ—M‘M %Ô(Ø % b c 
�IØÔ(ð $ u§{¡{°5Ó'9Õ9˜Ø',¨R¨S z°UÑ':˜Ù Ø¤ E£
˜�CØ ž'Ø"ŸZ™Z¨¨sÓ3˜Ø"(×">Ô">°hÔ">˜Ø œ6ß&¬3¨t«9°uÔ+<Ø $¨¨c°#¸ÄÀTÃÕ9JÕ2KÐ(LÕ L Ø+/˜LÙ!ß"Ü" 4›y¨5Ô0Ø $¨¨c´#°b¸#ÀÌÈTËÕARÕ:SÓ2TÐ(UÕ U Ø ŸK™K¬¨d«°eÕ(;Ô<Ü(›{˜Ø',˜Ø# qÕ(˜Ø !�˜Ø  1�f›÷G "÷L ˜FÖ8°×8à�K‰Kœ˜d› eÕ+Ô,ä1°#·(±(¸4³.×2GÑ2GÈÐXaÐ2GÓ2bÓcˆØ×+Ñ+Ø À{Øß;D I°Ò$6È$ð ,ó Pˆð ŸI™I r§y¡y°"·*±*¸b¿n¹nÈbÏnÉnÐ^d×^kÑ^kÓ^mÐnˆÔØˆøôQ "Ô#5Ð6ô 	@Ü�w‰w�~‰~˜d×#Ò#Ø×.Ñ.¨tÓ4Ò4Ø×*Ñ*¨4¸Ó?Ò?Üô 	CØ×-Ñ-¨d¸EÓBÒBð	Cú÷( "×!Ð!ûôH ô 	CØ×-Ñ-¨d¸EÓBÒBð	Cús€   Á6P ÅR# Å;RÆRÆ(
R# Æ3A<RÈ45RÉ*>RÊ)BRÌ1R# Ð5RÑRÑRÑ-RÑ6RÒRÒR 	ÒR# Ò R# Ò#SÓSc                ó&   <€ V ^8„  d   QhRS[ RS[/# )r   r/   r   )r0   r   )r"   r?   s   "€r#   r$   rÇ   û  s   ø€ ÷ Zñ Z©#ð Z±*ñ Zr%   c                ó    € \        R R V RR7      # )Tz‹Image file detected. Automatically redirected to vision_analyze tool. Use vision_analyze with this file path to inspect the image contents.)Úis_imagerD  r/   rè   rÚ  )r/   s   &r#   r^  Ú*ShellFileOperations._image_redirect_resultú  s   € äØ T°YðXôZð 	Zr%   c                ó>   <€ V ^8„  d   QhRS[ RS[RS[RS[RS[ RS[ /# )r   r;   r<   r'  r;  rž   r   r)  )r"   r?   s   "€r#   r$   rÇ     s:   ø€ ÷ 1ñ 1¡Cð 1±ð 1Áð 1Ù*-ð1Ù9<ð1ÙADñ1r%   c                ó  € V P                  V4      pRV 2pRP                  . RNV NRNV NRNV NRNV NRNV NRNV NR	NV NR
NV NRNV NRNV NRNV NRNV NRNV NRNV NRNV NRNV NRN\         NRN\         NRN4      # )uº  One shell command answering every question ``read_file`` asks: six
segments each closed by a ``sentinel`` line â€” byte size, base64 of the first
1000 bytes, the ``sed | cut`` page, ``wc -l``, whether the last byte is a
newline, then the base64 and page pipeline statuses. Probes run only inside
``[ -f ]`` (stat-not-open, like ``_probe_regular_file``) so a FIFO/device never
reaches ``head``/``sed``. A missing path echoes ``MISSING_SENTINEL`` (a compound
command only reports its last status). Every stage silences stderr: the local
backend merges stderr into stdout and a stray diagnostic would land inside a
segment. The byte clamp is ``4 * max_line_length + 1``; see ``_read_file_sequential``.r  rÚ   rß  rà  z 2>/dev/null; z; head -c 1000 z, 2>/dev/null | base64 2>/dev/null; __hs=$?; z
; sed -n 'Ú,úp' z 2>/dev/null | cut -b1-z 2>/dev/null; __hr=$?; z
; wc -l < z; tail -c 1 z 2>/dev/null | wc -l; z ; echo "$__hs $__hr"; elif [ -e rá  râ  rã  rä  )rú   r  rê  rë  )rC   r;   r<   r'  r;  rž   rL  r  s   &&&&&&  r#   r5  Ú#ShellFileOperations._read_probe_cmd  s½  € ð ×$Ñ$ TÓ*ˆØ�x�jÐ!ˆ÷	0ó 	0ˆhð 	0�s�eð 	0ð ð 	0Ø�eð	0Ø)ð	0Ø*.¨ð	0ð0ð	0à˜5ð	0à Lð	0àMQÈFð	0ðSð	0ð �hð	0ð  ð	0ð !)˜zð	0ð *-ð	0ð .1¨Eð	0ð2ð	0ð +Ð+ð		0ð ,Cð		0ð DHÀ&ð		0ðIð		0ð
 �eð	0ð
 *ð	0ð
 +/¨ð	0ð
0ð	0ð ˜ð	0ð 4ð	0ð 59°6ð	0ð:ð	0ð ˜ð	0ð )ð	0ð *-¨ð	0ð .<ð	0ô =QÐ;Qð	0ðRð	0ô *Ð*ð	0ð +/ô	0ð
	1r%   c                ó2   <€ V ^8„  d   QhRS[ RS[RS[RS[/# r:   r>   )r"   r?   s   "€r#   r$   rÇ     s)   ø€ ÷ 1ñ 1¡sð 1±Cð 1Áð 1É
ñ 1r%   c                óì   € V P                  V4      pVeP   V P                  WBVR7      pRV RV R2pVP                  '       d   V RVP                   2Vn        V# TVn        V# V P                  V4      # )u  Not-found recovery shared by every read path. Unicode-equivalent spellings
(NFC/NFD, confusable spaces/quotes) render identically, so the model can never
discover the byte mismatch by retyping â€” retrying is the tool's job. No
equivalent spelling â†’ suggest similar files.)r<   r=   zNote: 'zD' not found byte-for-byte; resolved to the unicode-equivalent file 'zM' (invisible encoding difference: NFC/NFD or special space/quote characters).r  )Ú_unicode_variant_matchrD   rè   Ú_suggest_similar_files)rC   r;   r<   r=   Úvariantrç   Únotes   &&&&   r#   r6  Ú&ShellFileOperations._read_file_missing  s’   € ð
 ×-Ñ-¨dÓ3ˆØÒØ—^‘^ GÀ%�^ÓHˆFà˜$˜ð  0Ø07¨yð 9ðð ð
 6<·[·[°[˜T˜F ! F§K¡K =Ð1ˆFŒKØˆMð GKˆFŒKØˆMØ×*Ñ*¨4Ó0Ð0r%   c                óN   <€ V ^8„  d   QhRS[ RS[RS[RS[RS[S[,          RS[/# )r   r;   r<   r=   r/   rù  r   )r!   r0   r   r    r   )r"   r?   s   "€r#   r$   rÇ   ,  sF   ø€ ÷ Añ A¡cð A±3ð A¹sð AÙ%(ðAÙ8@Á½ðAÙLVñAr%   c                ó`   € V P                  WW44      pVe   V# \        RV\        WT4      R7      # )a  Binary branch shared by every read path: UTF-16 text (Notepad, PowerShell
``>``) trips the binary guard; transcode it, else refuse with the type name.

UTF-16 rescue (ported from MoonshotAI/kimi-code#2647): the terminal env decodes stdout as UTF-8 with
errors="replace", so a UTF-16 text file (Windows Notepad .txt, PowerShell `>` redirects) arrives
mangled with U+FFFD and trips the binary guard. Probe the raw bytes via the backend's Python and
transcode to UTF-8 when a BOM or the zero-byte parity heuristic identifies UTF-16.
T©rD  r/   rÀ   )r)  r   r6   )rC   r;   r<   r=   r/   rù  Úutf16_results   &&&&&& r#   r9  Ú%ShellFileOperations._read_binary_file,  s>   € ð ×+Ñ+¨D¸%ÓKˆØÒ#ØÐÜØ iÜ& |Ó?ôAð 	Ar%   c                ó2   <€ V ^8„  d   QhRS[ RS[RS[RS[/# r:   r>   )r"   r?   s   "€r#   r$   rÇ   =  s/   ø€ ÷ 0Pñ 0P©#ð 0P±sð 0PÁ3ð 0PÉ:ñ 0Pr%   c           
     ór  € V P                  V4      w  rEVR8X  d   V P                  WV4      # VR8X  d   V P                  V4      # VR9  d   V P                  W4      # V P	                  V4      '       d   V P                  V4      # V P                  V4      w  rgV'       d   V P                  WW4V4      # ^ RIH	p ^V! 4       ,          ^,           p	W#,           ^,
          p
V P                  RV RV
 RV P                  V4       RV	 24      pVP                  ^ 8w  d   \        RVP                   2R	7      # \        VP                  4      pV P                  R
V P                  V4       24      p \!        \        VP                  4      P#                  4       4      pRpWê8”  gs   VP'                  R4      '       d\   V P                  RV P                  V4       R24      pVP                  ^ 8X  d'   \        VP                  4      P#                  4       R8g  pV P)                  WÂW®WOR7      #   \$         d    ^ p L�i ; i)zÈOne-probe-per-call read: the pre-compound form, kept as fallback for
image / known-binary extensions and unparseable compound replies. ``path`` is
already expanded and ``offset``/``limit`` normalized.rç  rè  rˆ  zsed -n 'r~  r  z | cut -b1-r-  r¿   zwc -l < Nr¡   z
tail -c 1 z | wc -lr1  r/  ©ræ  ré  )rî  r6  rÛ  rõ  rƒ  r^  rü  r9  r‘  r‰  ré   rú   rß   r   rÞ   r   r0   rä   r¹   Úendswithr:  )rC   r;   r<   r=   r/   rñ  rD  rù  r‰  r;  r'  Úread_resultrE  Ú	wc_resultr  r0  Útail_results   &&&&             r#   r3  Ú)ShellFileOperations._read_file_sequential=  s7  € ð !×4Ñ4°TÓ:Ñˆ	Ø�YÔØ×*Ñ*¨4¸Ó?Ð?Ø�]Ô"Ø×*Ñ*¨4Ó0Ð0ØÐ+Ô+Ø×.Ñ.¨tÓ<Ð<Ø�>‰>˜$×ÒØ×.Ñ.¨yÓ9Ð9Ø"&×"5Ñ"5°dÓ";Ñˆ	ßØ×)Ñ)¨$¸È,ÓWÐWõ 	AØÑ2Ó4Õ4°qÕ8ÐØ•> AÕ%ˆØ—j‘jØ�v�h˜a ˜z¨¨T×-CÑ-CÀDÓ-IÐ,JØÐ*Ð+ð-ó.ˆð × Ñ  AÔ%ÜÐ&;¸K×<NÑ<NÐ;OÐ$PÔQÐQÜ1°+×2DÑ2DÓEˆà—J‘J ¨$×*@Ñ*@ÀÓ*FÐ)GÐHÓIˆ	ð	ÜÔ9¸)×:JÑ:JÓK×QÑQÓSÓTˆKð 26ÐØÔ%¨+×*>Ñ*>¸t×*DÒ*DØŸ*™* z°$×2HÑ2HÈÓ2NÐ1OÈxÐ%XÓYˆKØ×$Ñ$¨Ô)Ü)DÀ[×EWÑEWÓ)X×)^Ñ)^Ó)`ÐdgÑ)gÐ&Ø×)Ñ)Ø°Øð *ó Pð 	Pøô ô 	ØŠKð	ús   Å,,H& È&H6È5H6c                óT   <€ V ^8„  d   QhRS[ RS[RS[RS[RS[RS[S[,          RS[/# )r   rE  r<   r'  r  r/   r0  r   )r!   r0   r   r\   r   )r"   r?   s   "€r#   r$   rÇ   o  sG   ø€ ÷ )?ñ )?±ð )?Áð )?ÑPSð )?Ù+.ð)?Ù;>ð)?á6>¹tµnð)?áISñ)?r%   c               ó˜  a€ V^ 8”  d   VRJ d
   V^,          pV^8X  d   \        V4      w  rWC8„  pRp	V'       d   RV^,            RV RV RV R2	p	V'       g#   VP                  R4      '       d   VRJ d   VRR pV^ 8X  d   \        R	^ ^ R
R7      # Y$u;8”  d   ^ 8”  d   M M\        R	WERV RV RV R2R7      # ^ RIHp
 V
! 4       o\
        ;QJ d.    V3R lVP                  R4       4       F  '       g   K   RM#	  RM! V3R lVP                  R4       4       4      p\        V P                  W4      TYXT	V'       d   RR7      # RR7      # )a.  Turn a raw ``sed | cut`` page into the final ``ReadResult``. Shared by every
read path so the BOM strip, pagination hint, ``cut`` newline-artifact fix and
the ambiguous-silence guards never drift apart. ``file_ends_with_newline`` is
None when the caller could not tell (artifact left alone, as before).FNr  r  r  r  r  r¡   rÚ   zFile is empty (0 bytes).)rP   r  r/   rè   zNote: offset z  is beyond the end of the file (z$ lines total). Retry with offset <= r„   rˆ  c              3   ó@   <"  € T F  p\        V4      S8„  x € K  	  R # 5ir�   rŒ  r  s   & €r#   r  Ú<ShellFileOperations._assemble_read_result.<locals>.<genexpr>”  s   øé € Ð^ÑF]¸dœc $›i¨/Ö9ÓF]ùr  Tr  r  )r   r�  r   r‘  r‰  r%  r£   r”  )rC   rE  r<   r'  r  r/   r0  r-  r  rè   r‰  r  r�  s   &&$$$$$     @r#   r:  Ú)ShellFileOperations._assemble_read_resulto  sk  ø€ ð �qŒ=Ð3°uÓ<Ø˜1ÕˆKØ�QŒ;Ü'¨Ó4‰NˆKØÑ*ˆ	ØˆßØ  ¨A¥ Ð.LÈVÈHÐTUÐV^ÐU_Ð_cÐdoÐcpÐpwÐxˆD÷ ˜[×1Ñ1°$×7Ò7Ð<RÐV[Ó<[Ø% c rÐ*ˆKð ˜Œ>Ü b°aÀ1ÐKeÔfÐfØÖ# !×#ÜØ¨à# F 8ð ,Ø#�}Ð$HØ"�m 1ð&ô(ð (õ 	AÙ-Ó/ˆß›#Ô^Àk×FWÑFWÐX\ÔF]Ó^Ÿ#Ÿ#š#Ô^Àk×FWÑFWÐX\ÔF]Ó^Ó^ˆÜØ×*Ñ*¨;Ó?È[Ø¸4ß$3˜Dô?ð 	?ð :>ô?ð 	?r%   c                ó6   <€ V ^8„  d   QhRS[ RS[S[ ,          /# rH   r¨   )r"   r?   s   "€r#   r$   rÇ   ¢  s   ø€ ÷ ñ ©3ð ±8¹Cµ=ñ r%   c                óÆ  a € \         P                  P                  V4      ;'       g    Rp\         P                  P                  V4      pV'       g   R# R V 3R llpV! V4      pS P	                  RS P                  V4       R24      pVP                  ^ 8w  g!   VP                  P                  4       '       g   R# \        VP                  4      P                  4        Uu. uF&  pV'       g   K  Ws8w  g   K  V! V4      V8X  g   K$  VNK(  	  pp\        V4      ^8X  d>   VR8w  g   RV9   d'   \         P                  P                  W(^ ,          4      # V^ ,          # R# u upi )uî   On-disk spelling of a file whose name is unicode-equivalent to ``path``
(NFC/NFD, confusable spaces/quotes). Returns the entry only when EXACTLY one
matches â€” several candidates = homoglyph collision, guessing would read the
wrong file.r„   Nc                ó0   € V ^8„  d   QhR\         R\         /# )r   r,   r   r–   )r"   s   "r#   r$   Ú@ShellFileOperations._unicode_variant_match.<locals>.__annotate__¬  s   € ÷ 	ñ 	œð 	¤ñ 	r%   c                 ó‚   <€ \         P                  ! R V 4      pSP                   F  w  r#VP                  W#4      pK  	  V# )ÚNFC)ÚunicodedataÚ	normalizeÚ_CONFUSABLESr°  )r,   Úoutrn   ro   rC   s   &   €r#   Ú_canonÚ:ShellFileOperations._unicode_variant_match.<locals>._canon¬  s:   ø€ Ü×'Ò'¨¨tÓ4ˆCØ ×-Ô-‘�Ø—k‘k #Ó+’ñ .àˆJr%   úls -1 rø   rÊ   )r<  r;   r¿  Úbasenameré   rú   rß   rÞ   rä   r   rÕ  r  r  )	rC   r;   Údir_pathrÎ  r¤  rv   Ú	ls_resultÚentryÚ
candidatess	   f&       r#   rƒ  Ú*ShellFileOperations._unicode_variant_match¢  s5  ø€ ô
 —7‘7—?‘? 4Ó(×/Ð/¨CˆÜ—7‘7×#Ñ# DÓ)ˆßÙ÷	ð 	ñ ˜Ó!ˆØ—J‘J ¨×(>Ñ(>¸xÓ(HÐ'IÈÐVÓWˆ	Ø×Ñ !Ô#¨9×+;Ñ+;×+AÑ+A×+CÒ+CÙä:¸9×;KÑ;KÓL×WÑWÔYóHÙY�eÜô ØÑ*ô Ù/5°e«}ÀÑ/F÷ ˆEÑYð 	ð Hô ˆz‹?˜aÔØ<DÈ¼OÈsÐVZÌ{”2—7‘7—<‘< °Q­-Ó8ÐmÐ`jÐklÕ`mÐmÙùòHs   Ã!
EÃ0EÃ8
EÄEc                ó&   <€ V ^8„  d   QhRS[ RS[/# rH   rI   )r"   r?   s   "€r#   r$   rÇ   ½  s   ø€ ÷ $Fñ $F©3ð $F±:ñ $Fr%   c           
     óˆ  € \         P                  P                  V4      ;'       g    Rp\         P                  P                  V4      p\         P                  P	                  V4      ^ ,          P                  4       p\         P                  P	                  V4      ^,          P                  4       pVP                  4       pV P                  RV P                  V4       R24      p. pVP                  ^ 8X  Ed   VP                  P                  4       '       Edæ   VP                  P                  4       P                  R4       EF·  p	V	'       g   K  V	P                  4       p
^ pW¦8X  d   ^dpEM \         P                  P	                  V	4      ^ ,          P                  4       V8X  d   ^ZpMäV
P                  V4      '       g   VP                  V
4      '       d   ^FpM³Wj9   d   ^<pMªW¦9   d   \        V
4      ^8”  d   ^(pM‘V'       dŠ   \         P                  P	                  V	4      ^,          P                  4       V8X  dQ   \        V4      \        V
4      ,          p\        V4      \        \        V4      \        V
4      4      R,          8¼  d   ^pV^ 8X  d-   \         P"                  ! RWj4      P%                  4       R8¼  d   ^2pV^ 8”  g   EK‡  VP'                  V\         P                  P)                  W)4      34       EKº  	  VP+                  R R	7       \-        R
V 2RVR,           UUu. uF  w  rÞVNK	  	  uppR7      # u uppi )zN"File not found" result listing up to 5 similar names from the same directory.r„   r¦  z 2>/dev/null | head -50r¡   gš™™™™™Ù?Ngš™™™™™é?c                 ó   € V ^ ,          ) # )r†   rB   )Úxs   &r#   Ú<lambda>Ú<ShellFileOperations._suggest_similar_files.<locals>.<lambda>ß  s
   €  1 Q¥4¡%r%   )ÚkeyúFile not found: T:Né   N)rÀ   Ú	not_foundÚsimilar_files)r<  r;   r¿  r§  r€  r�  ré   rú   rß   rÞ   rä   r£   r*   r  ÚsetÚmaxrÓ  ÚSequenceMatcherÚratior²   r  Úsortr   )rC   r;   r¨  rÎ  Úbasename_no_extÚextÚ
lower_namer©  ÚscoredÚfÚlfÚscoreÚcommonr-  Úfps   &&             r#   r„  Ú*ShellFileOperations._suggest_similar_files½  sq  € ä—7‘7—?‘? 4Ó(×/Ð/¨CˆÜ—7‘7×#Ñ# DÓ)ˆÜŸ'™'×*Ñ*¨8Ó4°QÕ7×=Ñ=Ó?ˆÜ�g‰g×Ñ˜xÓ(¨Õ+×1Ñ1Ó3ˆØ—^‘^Ó%ˆ
Ø—J‘J ¨×(>Ñ(>¸xÓ(HÐ'IÐI`ÐaÓbˆ	ØˆØ×Ñ !Õ#¨	×(8Ñ(8×(>Ñ(>×(@Ó(@Ø×%Ñ%×+Ñ+Ó-×3Ñ3°D×9�ßÙØ—W‘W“Y�Ø�ØÔ#Ø’EÜ—W‘W×%Ñ% aÓ(¨Õ+×1Ñ1Ó3°ÔFØ‘EØ—]‘] :×.Ò.°*×2GÑ2GÈ×2KÒ2KØ‘EØÔ%Ø‘EØÔ%¬#¨b«'°A¬+Ø‘EßœRŸW™W×-Ñ-¨aÓ0°Õ3×9Ñ9Ó;¸sÔBÜ  ›_¬s°2«wÕ6�FÜ˜6“{¤c¬#¨j«/¼3¸r»7Ó&CÀcÕ&IÔIØ "˜à˜A”:¤'×"9Ò"9¸$À
Ó"O×"UÑ"UÓ"WÐ[^Ô"^Ø�EØ˜1—9Ø—M‘M 5¬"¯'©'¯,©,°xÓ*CÐ"D×Eñ/ :ð0 	�‰™ˆÔ(ÜÐ"2°4°&Ð 9ÀTØ9?À¾Ô(D¹±°«¹Ò(DôFð 	FùÛ(Ds   Ì(L>c                ó&   <€ V ^8„  d   QhRS[ RS[/# rH   rI   )r"   r?   s   "€r#   r$   rÇ   ã  s   ø€ ÷ Lñ L¡#ð L©*ñ Lr%   c                ó€  € V P                  V4      pV P                  V4      w  r#VR8X  d   V P                  V4      # VR8X  d   V P                  V4      # VR9  d   V P	                  W4      # V P                  V4      '       d   \        RRVR7      # V P                  V4      w  rEV'       d   \        RV\        WR4      R7      # V P                  V4      w  rgVf   \        RVP                   2R7      # \        VP                  RR	4      4      w  r‰\        W‚\        P                  ! V4      P                  4       R
7      # )zCWhole file as a plain string (no pagination/line numbers/clamping).rç  rè  T)rz  rD  r/   rŠ  r-  r¿   rh  rº  )rP   r/   Ú_content_sha256r�  )r¤  rî  r„  rÛ  rõ  rƒ  r   rü  r6   rO  rÞ   r   ri  r`  ra  Ú	hexdigest)
rC   r;   r/   rñ  rD  rù  r   ÚfailedÚraw_contentr-  s
   &&        r#   rL   Ú!ShellFileOperations.read_file_rawã  s)  € à× Ñ  Ó&ˆØ ×4Ñ4°TÓ:Ñˆ	Ø�YÔØ×.Ñ.¨tÓ4Ð4Ø�]Ô"Ø×*Ñ*¨4Ó0Ð0ØÐ+Ô+Ø×.Ñ.¨tÓ<Ð<Ø�>‰>˜$×ÒÜ t°tÀyÔQÐQØ"&×"5Ñ"5°dÓ";Ñˆ	ßÜ¨¸	ÔI]Ð^jÓIvÔwÐwØ×-Ñ-¨dÓ3‰ˆØŠ<ÜÐ&;¸F¿M¹M¸?Ð$KÔLÐLô $ D§K¡K°Ð9JÓ$KÓL‰ˆÜ +Ü*1¯.ª.¸Ó*>×*HÑ*HÓ*JôLð 	Lr%   c                ó<   <€ V ^8„  d   QhRS[ RS[S[,          RS[/# )r   r;   Ú	max_bytesr   )r!   r   r0   r   )r"   r?   s   "€r#   r$   rÇ   þ  s+   ø€ ÷ Wñ W¡Cð W±H¹SµMð WÉZñ Wr%   c                ó  € V P                  V4      pV P                  V4      w  r4VR8X  d   \        RV 2RR7      # VR8X  d   V P                  V4      # VR9  d   V P	                  W4      # VR8X  d   \        RV 2R7      # Ve   W28”  d   \        VR	VR
 RVR
 R2R7      # V P                  RV P                  V4       24      pVP                  ^ 8w  d   \        RVP                   2R7      # RP                  \        VP                  4      P                  4       4      p \        P                  ! VRR7       \        YcRR7      #   \        \        P                  P                   3 d    \        RT 2R7      u # i ; i)zERead binary-safe bytes (as base64) from any shell-backed environment.rç  r´  T)rÀ   r¶  rè  ré  zCould not determine file size: r¿   zFile is too large (r~  z bytes, limit is Ú))r/   rÀ   r6  zFailed to read binary file: rÚ   r[  z*Backend returned invalid binary data for: )Úbase64_contentr/   rD  r�  )r¤  rî  r   rÛ  rõ  ré   rú   rß   rÞ   r  r   r£   r_  r`  r¹   ra  rb  )rC   r;   rÏ  r/   rñ  rc  Úcompacts   &&&    r#   Úread_file_bytesÚ#ShellFileOperations.read_file_bytesþ  s�  € à× Ñ  Ó&ˆØ ×4Ñ4°TÓ:Ñˆ	Ø�YÔÜÐ&6°t°fÐ$=ÈÔNÐNØ�]Ô"Ø×*Ñ*¨4Ó0Ð0ØÐ+Ô+Ø×.Ñ.¨tÓ<Ð<Ø�ZÔÜÐ&EÀdÀVÐ$LÔMÐMØÒ  YÔ%:ÜØ#Ø+¨I°a¨=Ð8IÈ)ÐTUÈÐVWÐXôZð Zð —*‘*˜y¨×)?Ñ)?ÀÓ)EÐ(FÐGÓHˆØ×Ñ Ô!ÜÐ&BÀ7Ç>Á>ÐBRÐ$SÔTÐTØ—'‘'Ô5°g·n±nÓE×KÑKÓMÓNˆð	YÜ×Ò˜W¨tÕ4ô ¨ÐQUÔVÐVøô œFŸO™O×1Ñ1Ð2ô 	YÜÐ&PÐQUÐPVÐ$WÔXÒXð	Yús   Ä"E Å4E>Å=E>c                ó&   <€ V ^8„  d   QhRS[ RS[/# rH   rh   )r"   r?   s   "€r#   r$   rÇ     s   ø€ ÷ &ñ &¡ð &©ñ &r%   c                óî  € V P                  V4      p\        VRRR7      pV'       d   \        VR7      # R\        P                  ! V4       R2pV P                  V4      pVP                  ^ 8w  d/   RVP                  ;'       g    R9   d   V P                  VR	R
7      pVP                  ^ 8w  d?   \        RT RVP                  ;'       g    RP                  4       ;'       g    R 2R7      # \        4       # )z–Delete a single file (directories rejected) via the backend's ``python -c``
so one code path works on local/docker/ssh AND Windows shells (no ``rm``).ÚDeleteT©Úverbrª  r¿   z-import shutil, pathlib, sys
p = pathlib.Path(a\  )
recursive = False
try:
    if p.is_dir() and not p.is_symlink():
        if recursive:
            shutil.rmtree(p)
        else:
            print('is a directory: ' + str(p), file=sys.stderr); sys.exit(2)
    else:
        p.unlink()
except FileNotFoundError:
    pass
except Exception as exc:
    print(str(exc), file=sys.stderr); sys.exit(1)
r  rÚ   r  r  zFailed to delete ú: zunknown error)	r¤  r   r   r·   r   r  rß   rÞ   rä   )rC   r;   Údeniedr  rç   s   &&   r#   rj   ÚShellFileOperations.delete_file  sð   € ð × Ñ  Ó&ˆô (¨°8À4ÔHˆßÜ VÔ,Ð,ð Ü $§
¢
¨4Ó 0Ð1ð 2BðBð 	ð$ ×*Ñ*¨7Ó3ˆð ×Ñ˜qÔ  Y°6·=±=×3FÐ3FÀBÔ%GØ×.Ñ.¨w¸8Ð.ÓDˆFà×Ñ˜qÔ ÜÐ'8¸¸¸bÀ&Ç-Á-×BUÐBUÐSU×A\ÑA\ÓA^×AqÐAqÐbqÐ@rÐ%sÔtÐtÜ‹}Ðr%   c                ó,   <€ V ^8„  d   QhRS[ RS[ RS[/# rm   rh   )r"   r?   s   "€r#   r$   rÇ   @  s"   ø€ ÷ ñ ™Sð ¡sð ©{ñ r%   c                ó€  € V P                  V4      pV P                  V4      pW3 F'  p\        VR RR7      pV'       g   K  \        VR7      u # 	  V P                  RV P	                  V4       RV P	                  V4       24      pVP
                  ^ 8w  d    \        RV RV RVP                   2R7      # \        4       # )	ÚMoveTrÙ  r¿   zmv r  zFailed to move z -> rÛ  )r¤  r   r   ré   rú   rß   rÞ   )rC   rn   ro   ÚprÜ  rç   s   &&&   r#   rq   ÚShellFileOperations.move_file@  sº   € Ø×Ñ Ó$ˆØ×Ñ Ó$ˆà“ˆAÜ+¨A°FÀ$ÔGˆFß‰vÜ"¨Ô0Ò0ñ ð —‘˜c $×"8Ñ"8¸Ó"=Ð!>¸aÀ×@VÑ@VÐWZÓ@[Ð?\Ð]Ó^ˆØ×Ñ˜qÔ Ü °s°e¸4À¸uÀBÀvÇ}Á}ÀoÐ%VÔWÐWÜ‹}Ðr%   z[\ud800-\udc7f\udd00-\udfff]c                ó<   <€ V ^8„  d   QhRS[ RS[ RS[S[,          /# r¸  rR   )r"   r?   s   "€r#   r$   rÇ   S  s'   ø€ ÷ 
ñ 
©ð 
±cð 
¹hÁ{Õ>Sñ 
r%   c                ó’   € V P                   P                  V4      pV'       d$   \        RV RVP                  ^ 4      : R2R7      # R# )z¾Refuse content with a lone surrogate BEFORE any subprocess: letting it
reach the pipe spawns a child that hangs or truncates the target via
empty-stdin ``cat``. A regex scan needs no encode.r¾   z0': content contains a lone surrogate character (zH) that cannot be encoded as UTF-8. The file was NOT created or modified.r¿   N)Ú_LONE_SURROGATE_REr}   r   Úgroup)rC   r;   rP   Úms   &&& r#   Ú_reject_unencodableÚ'ShellFileOperations._reject_unencodableS  sV   € ð ×#Ñ#×*Ñ*¨7Ó3ˆßÜØ% d Vð ,(Ø()¯©°«
¡~ð 6JðJôLð Lñ r%   c          	      óB   <€ V ^8„  d   QhRS[ RS[ RS[ RS[S[,          /# )r   r;   r¾  rP   r   rR   )r"   r?   s   "€r#   r$   rÇ   `  s5   ø€ ÷ Dñ D©ð D±#ð DÁð DÉÑQ\ÕH]ñ Dr%   c           	     ó¶   € V\         9   d   \        P                  ! V4      MRpVf   R# V! V4      w  rEV'       g   VR8X  d   R# \        RV  RV RV R2R7      # )a/  Fail-closed pre-write gate for ``_FAIL_CLOSED_INPROC_EXTS`` (JSON/YAML/TOML):
a structured-format write that doesn't parse is a corrupt write, so refuse
before any bytes touch disk. Checked against the RAW content, before the
BOM/CRLF shims (post-shim linting would false-positive on a BOM-marked file).NÚ__SKIP__r¾   z': candidate content fails z syntax validation (zC). The file was NOT created or modified. Fix the content and retry.r¿   )r   r   râ   r   )r;   r¾  rP   Úlinterræ  Úerrs   &&&   r#   Ú_fail_closed_syntax_errorÚ-ShellFileOperations._fail_closed_syntax_error_  sp   € ð -0Ô3KÔ,K”×#Ò# CÔ(ÐQUˆØŠ>ÙÙ˜“/‰ˆß�˜
Ô"ÙÜØ! $ Ð'BØˆeÐ'¨ uð -BðBôDð 	Dr%   c                óB   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[ /# )r   r;   rž   r  r   r¨   )r"   r?   s   "€r#   r$   rÇ   p  s.   ø€ ÷ 1ñ 1¡Sð 1±Cð 1¹xÉ½}ð 1ÑQTñ 1r%   c                óŒ   € V P                  V4      pVR8X  d   RV R2pMVR8X  d   RV R2pMRpRV RV R	V R
V R\         R2# )aÓ  One shell command for the on-disk questions ``write_file`` asks. Two
segments closed by a ``sentinel`` line: base64 of the first three bytes (BOM
detection at the byte layer, same on-disk truth as ``_file_has_bom``), then
``body``: ``"cat"`` for the full text when pre-content is wanted, ``"sample"``
for the 4 KB line-ending sample, or None for nothing. Gated on ``[ -f ]`` so a
FIFO/device never reaches ``head``/``cat``; a missing path echoes ``MISSING_SENTINEL``.Úcatr÷   rø   r   zhead -c 4096 Ú:rß  z ]; then head -c 3 z( 2>/dev/null | base64 2>/dev/null; echo r  rã  rä  )rú   rë  )rC   r;   rž   r  rL  Úbody_cmds   &&&&  r#   Ú_write_probe_cmdÚ$ShellFileOperations._write_probe_cmdp  sz   € ð ×$Ñ$ TÓ*ˆØ�5Œ=Ø˜c˜U ,Ð/‰HØ�XÔØ& s e¨<Ð8‰HàˆHà�s�eð Ø˜ÐEÀhÀZÈrØˆjð Ü)Ð*¨$ð0ð	1r%   c                ó|   <€ V ^8„  d   QhRS[ RS[S[ ,          RS[RS[S[S[S[ ,          S[S[ ,          3,          /# ©r   r;   rQ   Úwant_prer   ©r!   r   r\   r  )r"   r?   s   "€r#   r$   rÇ   „  sI   ø€ ÷ A,ñ A,©ð A,¹(Á3½-ð A,ÑSWð A,Ù!&¡t©X±c­]¹HÁS½MÐ'IÕ!JñA,r%   c                ó.  € V'       d   Vf   RpMV'       g   RpMRpV P                  4       '       d*   \        P                  ! V P                  V4      VR8H  4      MRpVe_   Vw  rgV'       d   VP	                  RR4      MRpVR8X  d   V'       d   TpT;'       g    VR8X  d   TMRp	YbV	'       d   \        V	4      3# R3# \        \        4      p
V P                  V P                  WV4      4      pVP                  ;'       g    RpW¬9  dx   \        V4      P                  4       \        8X  d   V'       d   \        V4      MRpRW-3# \        P                  RWP                   \#        V4      4       V P%                  WV4      # \'        WÊ4      pVP                   ^ 8w  g   \#        V4      ^8w  d=   \        P                  R	WP                   \#        V4      4       V P%                  WV4      # Vw  røV P)                  V4      pVf)   \        P                  R
V4       V P+                  W4      pM%VP-                  \.        P0                  ! R4      4      pVR8X  d   V'       d   TpV'       d   \        V4      pMVR8X  d   V'       d   \        V4      pMRpWbV3# )a·  ``(has_bom, pre_content, original_line_ending)`` for ``path`` in ONE
round-trip (replaces ``cat`` when pre-content is wanted, a ``head -c 4096``
line-ending sample and a ``head -c 3`` BOM check). Semantics unchanged:
pre-content is read only when wanted and not supplied; the line ending comes
from pre-content when there is any, else from the sample; the BOM always comes
from disk. An unparseable reply falls back to the separate probes.Nró  r   rh  r°  rÚ   Fzowrite_file: pre-write probe reply for %s has no sentinel (exit %s, %d chars); falling back to sequential probeszpwrite_file: pre-write probe for %s returned exit %s with %d segments (want 2); falling back to sequential probeszWwrite_file: no usable base64 head for %s; paying one extra round-trip for the BOM probe)r:  r»  r<  r½  ri  r   r›   Ú_WRITE_SENTINEL_PREFIXré   rö  rÞ   r   rä   rë  r7  r8  rß   r  Ú_probe_write_target_sequentialr¤   r+  rÉ  r*   r   r¾  )rC   r;   rQ   rú  Ú	body_modeÚnativeÚhas_bomÚrawr  r   rž   r<  r�   Úendingr  Úhead_segÚ
head_bytess   &&&&             r#   Ú_probe_write_targetÚ'ShellFileOperations._probe_write_target„  sH  € ÷ ˜Ò+Ø',‰IßØ ‰IàˆIàRV×RkÑRk×RmÒRm”×!Ò! $×"3Ñ"3°DÓ"9¸9ÈÑ;MÔNÐswˆØÒØ!‰LˆGç58�3—:‘:˜g yÔ1¸bˆDØ˜EÔ!§dØ"�Ø ×KÐK¨Y¸(Ô-B¡TÈˆFØÏÔ)<¸VÓ)DÐXÐXÐTXÐXÐXä Ô!7Ó8ˆØ—
‘
˜4×0Ñ0°ÀÓKÓLˆØ—‘×#Ð# ˆØÔ!Ü*¨6Ó2×8Ñ8Ó:Ô>NÔNß=HÔ,¨[Ô9Èd�Ø˜kÐ1Ð1Ü�L‰LðIà—o‘o¤s¨6£{ô4ð ×6Ñ6°tÈ(ÓSÐSä" 6Ó4ˆØ�?‰?˜aÔ¤3 x£=°AÔ#5Ü�L‰LðGà—o‘o¤s¨8£}ô6ð ×6Ñ6°tÈ(ÓSÐSØ!‰ˆà×/Ñ/°Ó9ˆ
ØÒä�L‰Lð/Ø04ô6ð ×(Ñ(¨Ó;‰Gà ×+Ñ+¬I×,<Ò,<¸WÓ,EÓFˆGà˜Ô§$ØˆKßÜ(¨Ó5‰FØ˜(Ô"§tÜ(¨Ó.‰FàˆFØ VÐ+Ð+r%   c                ó|   <€ V ^8„  d   QhRS[ RS[S[ ,          RS[RS[S[S[S[ ,          S[S[ ,          3,          /# rù  rû  )r"   r?   s   "€r#   r$   rÇ   Ç  sJ   ø€ ÷ Jñ J±3ð JÁXÉcÅ]ð JÑ^bð JÙ,1±$¹Á½ÁxÑPSÅ}Ð2TÕ,UñJr%   c                ó€  € V'       dE   VfA   V P                  V4      pVP                  ^ 8X  d   VP                  '       d   VP                  pV'       d   \        V4      pMLV P	                  VR4      pVP                  ^ 8X  d(   VP                  '       d   \        VP                  4      MRpV P                  W4      W%3# )z¥Pre-compound form of ``_probe_write_target``: one exec per question. A
failed ``cat`` leaves pre_content None so the lint-delta and LSP consumers
degrade gracefully.Ni   )rû   rß   rÞ   r   r  rÉ  )rC   r;   rQ   rú  r‘  r  Úheads   &&&&   r#   rþ  Ú2ShellFileOperations._probe_write_target_sequentialÇ  s™   € ÷
 ˜Ò+ØŸ)™) D›/ˆKØ×$Ñ$¨Ô)¨k×.@×.@Ð.@Ø)×0Ñ0�ßÜ(¨Ó5‰Fà—:‘:˜d DÓ)ˆDØ9=¿¹È1Ô9LÐQU×Q\×Q\ÐQ\Ô(¨¯©Ô5ÐbfˆFØ×!Ñ! $Ó4°kÐIÐIr%   c          	      ób   <€ V ^8„  d   QhRS[ RS[RS[S[S[,          S[S[,          3,          /# )r   r;   Úcontent_bytesr   )r!   r    r  r   r\   r   )r"   r?   s   "€r#   r$   rÇ   ×  s8   ø€ ÷ ñ ©ð ¹Uð ÁuÉXÑVZÍ^Ñ]eÑfqÕ]rÐMrÕGsñ r%   c                óV  €  V P                  4       '       d&   \        P                  ! V P                  V4      4      MRpV'       d   RM#V P	                  RV P                  V4       R24      pVea   VP                  ^ 8X  dP   VP                  P                  4       '       d0   VP                  P                  4       P                  4       ^ ,          pV'       d>   V\        P                  ! V4      P                  4       8w  d   R\        RV R2R7      3# R#  R	#   \         d     R	# i ; i)
zÓCompare the on-disk sha256 to the intended bytes: ``(verified, error)``.
The explicit flag saves the model a confirming re-read; a mismatch is a hard
error. ``verified`` is None when the hash could not be taken.Nz
sha256sum rø   Fú#Post-write verification failed for u{   : on-disk content hash differs from the intended write. The write did not persist correctly â€” re-read the file and retry.r¿   )TN)NN)r:  r»  Ú	sha256_ofr½  ré   rú   rß   rÞ   rä   r£   r`  ra  rÊ  r   Ú	Exception)rC   r;   r  Údisk_shaÚhash_results   &&&  r#   Ú_verify_written_hashÚ(ShellFileOperations._verify_written_hash×  s  € ð	ØHL×HaÑHa×HcÒHc”z×+Ò+¨D×,=Ñ,=¸dÓ,CÔDÐimˆHß"*™$°·
±
¸ZÈ×H^ÑH^Ð_cÓHdÐGeÐeqÐ;rÓ0sˆKØÒ&¨;×+@Ñ+@ÀAÔ+EÈ+×J\ÑJ\×JbÑJb×JdÒJdØ&×-Ñ-×3Ñ3Ó5×;Ñ;Ó=¸aÕ@�ßØœwŸ~š~¨mÓ<×FÑFÓHÔHØ ¤+Ø=¸d¸Vð D%ð %ô#'ð 'ð 'ð
 "Ð!ð ð Ðøô ô 	ØØÐð	ús/   ‚D ˜.D ÁAD Â"6D Ã:D ÄD ÄD(Ä'D(c                óB   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[/# rO   rR   )r"   r?   s   "€r#   r$   rÇ   ì  s4   ø€ ÷ ?bñ ?b™sð ?b©Sð ?b¹xÉ½}ð ?bÑXcñ ?br%   c           	     óÞ  € \         P                  ! 4       pV P                  V4      p\        V4      pV'       d   \	        VR7      # V P                  W4      pVe   V# \        P                  P                  V4      ^,          P                  4       pV P                  WV4      pVe   V# V\        9   ;'       g    V P                  V4      pV P                  WV4      w  r“p
VR8X  d   \        WV4      pVe   V# V
R8X  d   \        VR4      pV	'       d   \!        V4      '       g   \"        V,           p\%        \        P                  P'                  V4      4      pVP)                  RR4      pV P+                  W4      pVP,                  ^ 8w  d   \	        RVP.                   2R7      # V P1                  W4      w  rïVe   V# V P3                  WVR7      pRpVP4                  '       g   VP6                  '       d   V P9                  WW$R	7      ;'       g    Rp\	        \;        V4      Y¾\<        P>                  ! V4      PA                  4       V'       d   VPC                  4       VR
7      # RVR
7      # )u±  Write content atomically, creating parent directories as needed.

Order: deny list â†’ lone-surrogate refusal â†’ fail-closed syntax gate on the
CANDIDATE content (JSON/YAML/TOML) â†’ one compound on-disk probe
(pre-content when wanted, CRLF, BOM; see ``_probe_write_target``) â†’
JSON NaN/Infinity refusal when the write introduces one â†’ CRLF/BOM
preservation â†’ atomic write (content rides stdin: no ARG_MAX limit) â†’
sha256 verification â†’ lint delta â†’ LSP check when syntax is clean
(non-blocking; the pre-edit content is its baseline, see ``_maybe_lsp_diagnostics``). ``pre_content``: pre-edit content the
caller already has (skips the read); BOM detection always probes disk.
r¿   Nz.jsonú
rh  rº  zFailed to write file: )rQ   Úpost_content)rQ   r  Ústarted)Úbytes_writtenÚdirs_createdÚverifiedrÉ  ÚlintÚlsp_diagnostics)"ÚtimeÚ	monotonicr¤  r   r   rè  r<  r;   r€  r�  rï  r   Ú_lsp_handles_extensionr  rÂ   r   r   r   r\   r¿  r¾  rÄ  rß   rÞ   r  Ú_check_lint_deltaÚsuccessÚskippedÚ_maybe_lsp_diagnosticsr  r`  ra  rÊ  Úto_dict)rC   r;   rP   rQ   r  rÜ  Úrefusedr¾  rú  r  Úoriginal_endingr  r  Úwrite_resultÚcontent_verifiedÚverify_errorÚlint_resultr  s   &&&&              r#   rT   ÚShellFileOperations.write_fileì  sM  € ô —.’.Ó"ˆØ× Ñ  Ó&ˆÜ'¨Ó-ˆßÜ VÔ,Ð,Ø×*Ñ*¨4Ó9ˆØÒØˆNÜ�g‰g×Ñ˜tÓ$ QÕ'×-Ñ-Ó/ˆØ×0Ñ0°¸GÓDˆØÒØˆNð œ.Ñ(×LÐL¨D×,GÑ,GÈÓ,LˆØ04×0HÑ0HÈÐ\dÓ0eÑ-ˆ˜oØ�'Œ>Ü6°tÀkÓRˆGØÒ"Ø�ð ˜fÔ$Ü-¨g°vÓ>ˆGßœ8 G×,Ò,Ü 'Õ)ˆGô œBŸG™GŸO™O¨DÓ1Ó2ˆð  Ÿ™ wÐ0AÓBˆØ×)Ñ)¨$Ó8ˆØ×!Ñ! QÔ&ÜÐ'=¸l×>QÑ>QÐ=RÐ%SÔTÐTØ)-×)BÑ)BÀ4Ó)WÑ&ÐØÒ#ØÐà×,Ñ,¨TÐY`Ð,Óaˆð *.ˆØ××Ð +×"5×"5Ð"5Ø"×9Ñ9Ø¸Gð :ó V÷ ^ð ^ØY]ð äÜ˜mÓ,¸<Ü#ŸNšN¨=Ó9×CÑCÓEß*5�×$Ñ$Ó&ÐQ`ôbð 	bð <@ÐQ`ôbð 	br%   c                óT   <€ V ^8„  d   QhRS[ RS[ RS[ RS[ RS[RS[S[ ,          RS[/# )r   r;   rP   rX   rY   Úmatch_countrÀ   r   )r!   r0   r   r
   )r"   r?   s   "€r#   r$   rÇ   /  sF   ø€ ÷ *ñ *¡Sð *±3ð *ÁCð *Ù%(ð*Ù7:ð*ÙCKÉCÅ=ð*ÙU`ñ*r%   c                óÌ   € ^ RI HpHp V! W#V4      '       d   \        RRRV R2R7      # T;'       g    RV 2p	 W—! W•W24      ,          p	\        V	R7      #   \         d     Li ; i)a!  PatchResult for a failed fuzzy match. Already-applied detection first: the
most common production failure is a re-send of an edit that already landed,
and a success-shaped no-op stops the model burning turns on re-reads.
Otherwise attach a best-effort "Did you mean?" snippet to the error.)Úformat_no_match_hintÚis_already_appliedTuT   File already contains the target text â€” the edit appears to be already applied to z0. No write performed; do not re-send this patch.)r$  Ú	no_changer†  z'Could not find match for old_string in r¿   )Útools.fuzzy_matchr2  r3  r
   r  )
rC   r;   rP   rX   rY   r0  rÀ   r2  r3  Úerr_msgs
   &&&&&&&   r#   Ú_no_match_resultÚ$ShellFileOperations._no_match_result/  sŠ   € ÷ 	OÙ˜g°:×>Ò>ÜØ¨ð8Ø8<°vð ><ð<ô>ð >ð ×KÐKÐDÀTÀFÐKˆð	ØÐ+¨GÀ*ÓVÕVˆGô  Ô)Ð)øô ô 	Ùð	ús   ºA ÁA#Á"A#c                ó<   <€ V ^8„  d   QhRS[ RS[ RS[S[,          /# )r   r;   rÍ  r   )r!   r   r
   )r"   r?   s   "€r#   r$   rÇ   D  s'   ø€ ÷ ñ ©Cð ¹cð ÁhÉ{ÕF[ñ r%   c           
     óp  € V P                  V4      w  r4Vf   \        RV 2R7      # \        VP                  RR4      4      w  rVVP	                  RR4      P	                  RR4      pVP	                  RR4      P	                  RR4      pWx8w  d)   \        R	V R
\        V4       R\        V4       R2R7      # R# )aF  Re-read ``path`` and confirm the intended bytes landed; error result or None.
Catches silent persistence failures (FS oddities, races, truncated pipe).
Line endings are normalized first (Windows text-mode ``open()`` writes LF as
CRLF) and the re-read's BOM stripped (``new_content`` is the BOM-less
string we matched against).Nz2Post-write verification failed: could not re-read r¿   rh  rº  r  r¡   Úr  z5: on-disk content differs from intended write (wrote z chars, read back zb chars after normalizing line endings). The patch did not persist. Re-read the file and try again.)rO  r
   r   ri  r°  r  )	rC   r;   rÍ  r   Ú_failedÚbomlessr-  Úon_diskÚintendeds	   &&&      r#   Ú_verify_patch_persistedÚ+ShellFileOperations._verify_patch_persistedD  sË   € ð ×.Ñ.¨tÓ4‰ˆØŠ<ÜÐ'YÐZ^ÐY_Ð%`ÔaÐaÜ §¡¨GÐ5FÓ GÓH‰
ˆØ—/‘/ &¨$Ó/×7Ñ7¸¸dÓCˆØ×&Ñ& v¨tÓ4×<Ñ<¸TÀ4ÓHˆØÔÜØ5°d°Vð <ä˜h›-˜Ð(:Ü�w“<�.ð !MðMôOð Oñ r%   c          
      ó8   <€ V ^8„  d   QhRS[ RS[ RS[ RS[RS[/# rW   r[   )r"   r?   s   "€r#   r$   rÇ   Y  s9   ø€ ÷ *^ñ *^¡#ð *^±3ð *^ÁCð *^Ù#'ð*^Ù4?ñ*^r%   c                ó˜  € V P                  V4      p\        V4      pV'       d   \        VR7      # V P                  V4      w  rgVf$   \        VP                  ;'       g    RV 2R7      # TP                  RR4      p\        V4      w  rš^ RIHpH	p . pV! W’W4VR7      w  rïppV'       g   V^ 8X  d   V P                  WW#VV4      # \        V	4      pV'       d   \        VV4      pV P                  WVR7      pVP                  '       d   \        R	VP                   2R7      # V P                  W4      pVe   V# \        R
V P!                  WžV4      V.VP"                  RP%                  R . VOV! V.4      N 4       4      ;'       g    RVP&                  V\(        P*                  ! V4      P-                  4       VP.                  3.R7      # )z‹Replace text in a file using fuzzy matching (``old_string`` must be
unique unless ``replace_all``). Returns a PatchResult with diff + lint.r¿   Nr-  rh  rº  )Úboundary_noteÚfuzzy_find_and_replace)Úcorrection_notes)rQ   zFailed to write changes: Tr¡   c              3   ó8   "  € T F  q'       g   K  Vx € K  	  R # 5ir�   rB   )r  rt  s   & r#   r  Ú4ShellFileOperations.patch_replace.<locals>.<genexpr>€  s   é € ÐZÑ&T ÓXYŸ1š1Ó&Tùs   ‚	�
)r$  ÚdiffÚfiles_modifiedr  r†  r  Ú_writes)r¤  r   r
   rO  rà   ri  r   r5  rD  rE  r7  r   r   rT   rÀ   r@  rÖ  r  r  r  r`  ra  rÊ  rÉ  )rC   r;   rX   rY   rZ   rÜ  r   rË  rÌ  rP   r-  rD  rE  rF  rÍ  r0  ÚstrategyrÀ   Úfile_endingr*  r,  s   &&&&&                r#   r^   Ú!ShellFileOperations.patch_replaceY  sÆ  € ð × Ñ  Ó&ˆÜ'¨Ó-ˆßÜ VÔ,Ð,Ø×-Ñ-¨dÓ3‰ˆØŠ<Ü V×%5Ñ%5×%WÐ%WÐ;PÐQUÐPVÐ9WÔXÐXð
 —k‘k 'Ð+<Ó=ˆÜ Ó,‰
ˆçKØÐÙ4JØ ÐK[ô5]Ñ1ˆ (¨Eç�K 1Ô$Ø×(Ñ(¨¸
ÐP[Ð]bÓcÐcô *¨'Ó2ˆßÜ1°+¸{ÓKˆKØ—‘ tÀk�ÓRˆØ××ÐÜÐ'@À×ASÑASÐ@TÐ%UÔVÐVØ×3Ñ3°DÓFˆØÒ#ØÐäØ˜t×1Ñ1°'ÈÓMÐ_cÐ^dØ×"Ñ"Ø—‘ÑZÐ&TÐ(8Ð&T¹-ÈÈ
Ó:SÑ&TÓZÓZ×bÐbÐ^bà(×8Ñ8ØœGŸNšN¨4Ó0×:Ñ:Ó<¸l×>ZÑ>ZÐ[Ð\ô^ð 	^r%   c                ó&   <€ V ^8„  d   QhRS[ RS[/# ra   rc   )r"   r?   s   "€r#   r$   rÇ   …  s   ø€ ÷ 6ñ 6¡sð 6©{ñ 6r%   c                ód   € ^ RI HpHp V! V4      w  rEV'       d   \        RV 2R7      # V! W@4      # )zqApply a V4A format patch (``*** Begin Patch`` / ``*** Update File:`` /
``@@ hint @@`` hunks / ``*** End Patch``).)Úparse_v4a_patchÚapply_v4a_operationszFailed to parse patch: r¿   )Útools.patch_parserrQ  rR  r
   )rC   rb   rQ  rR  Ú
operationsÚparse_errors   &&    r#   re   ÚShellFileOperations.patch_v4a…  s6   € ÷ 	MÙ"1°-Ó"@Ñˆ
ßÜÐ'>¸{¸mÐ%LÔMÐMÙ# JÓ5Ð5r%   c                óf   <€ V ^8„  d   QhRS[ RS[ RS[ RS[S[ ,          RS[RS[RS[ RS[R	S[ R
S[/
# rt   r{   )r"   r?   s   "€r#   r$   rÇ   �  sb   ø€ ÷ %ñ %™cð %©ð %¹Cð %Ù"¡3�-ð%Ù7:ð%ÙILð%áð%á69ð%ñ ð%ñ -9ñ%r%   c
                ór  € \        We4      w  reVR8X  d   V	R9  d   \        RV	: R2R7      # V P                  V4      pV P                  V4      p
V
P                  pV
P
                  '       d   \        V
P
                  R7      # RV9  d   RV9  d   \        RV R2R7      # RV9   d-   V P                  WW4WVWxV	4	      pVe   V# V P                  V4      # V P                  WW4WVWxV	4	      pV P                  V4      pV'       d6   VP                  '       g$   R	P                  R
 V 4       4      pRV R2Vn        V# )u  Search for content (regex, ``target="content"``) or files (glob,
``target="files"``). ``output_mode``: "content", "files_only" or "count";
``context``: lines of context around matches; ``order``: file-search
ordering â€” fast "discovery" or exact "modified" time.ÚfileszInvalid file search order z%; expected 'discovery' or 'modified'.r¿   Úexistsr¶  ró  rô  r2   c              3   óP   "  € T F  qP                  R 4      R,          x € K  	  R# 5i)rÊ   Nr  r¢   )r  Úitems   & r#   r  Ú-ShellFileOperations.search.<locals>.<genexpr>°  s   é € ÐKÁ
¸§
¡
¨3£°× 3Ò 3Ã
ùs   ‚$&z[Skipped macOS protected folders during broad search to avoid an unattended privacy prompt: z@. Search a protected folder directly when access is intentional.>   Úmodifiedr‡   )r   r   r¤  Ú_path_exists_proberÞ   rà   Ú_try_multi_path_searchÚ_path_not_found_resultÚ_dispatch_searchÚ_macos_search_exclusionsrÀ   r  Úwarning)rC   ru   r;   rv   rw   r=   r<   rx   ry   rz   r<  Úexists_probeÚmultirç   Ú
exclusionsr%  s   &&&&&&&&&&      r#   r}   ÚShellFileOperations.search�  sc  € ô 4°FÓB‰ˆØ�WÔ Ð.GÔ!GÜØ3°E±9ð =4ð 4ô6ð 6ð × Ñ  Ó&ˆØ×'Ñ'¨Ó-ˆØ—|‘|ˆØ�?�?ˆ?Ü e§o¡oÔ6Ð6Ø˜<Ô'¨K¸|Ô,KÜÐ)ZÐ[_ÐZ`ð alð (lô nð nà˜,Ô&à×/Ñ/Ø˜v°%ÀÐW\ó^ˆEàÒ Ø�Ø×.Ñ.¨tÓ4Ð4Ø×&Ñ& w°fÈØ'2¸UóDˆà×2Ñ2°4Ó8ˆ
ß˜fŸlŸl˜lØ—i‘iÑKÁ
ÓKÓKˆGð1Ø18°	ð :>ð>ð ŒNð ˆr%   )rÍ   rÏ   rÎ   rÆ   rË   r�   )NNN)rw  r  )T)rå  i    r   ))u   â€¯r  )ô   Â r  )u   â€™r­  )u   â€˜r­  r‚   rƒ   )Hrˆ   r‰   rŠ   r‹   rŒ   rÑ   ré   rò   rû   r  r  r  Ústaticmethodr%  r.  rO  rG  rF  r+  rm  r{  rƒ  r”  r¤  rú   rµ  rÄ  rÉ  rÖ  rÛ  rî  rõ  rü  r  r!  r  r  r)  rD   r:  r½  r2  r^  r5  r6  r9  r3  r:  r¢  rƒ  r„  rL   rÔ  rj   rq   r]  Úcompilerå  rè  rï  rö  r  rþ  r  rT   r7  r@  r^   re   r}   r�   rŽ   r�   s   @r#   rÄ   rÄ   Ï   s  ø‡ € ñ÷
Dò 
D÷Vò V÷@
(ð 
(÷Mð M÷Zð Z÷ð ÷0ð 0ð8 ÷Xó ðX÷7ò 7÷$2ð 2ðh ÷0ó ð0÷
ð ð: ÷ó ðð ÷ó ð÷6ò ÷Eð E÷Mò M÷ ð ÷>7ò 7÷07ð 7÷:6ð :6÷xKò K÷?ð ?ð ÷Oó ðO÷!ð !÷<hò h÷Að Að$ (ÐØÐ÷ð ÷
ò 
÷"P?ð P?÷dYPò YP÷v
Bð 
B÷oð o÷Xð Xðt ÷Zó ðZ÷1ð 1÷21ð 1÷"Að A÷"0Pð 0P÷d)?ð )?ðX€L÷ð ÷6$Fð $F÷LLð L÷6Wò W÷4&ð &÷Pð ð" ŸšÐ$CÓDÐ÷
ð 
ð ÷Dó ðD÷ 1ð 1÷(A,ð A,÷FJð J÷ ð ÷*?bò ?b÷F*ð *÷*ð ÷**^ò *^÷X6ð 6÷%÷ %ð %r%   rÄ   c                ó@   € V ^8„  d   Qh/ ^ \         9   d
   \        ;R&   # )r   r)   )Ú__conditional_annotations__r  )r"   s   "r#   r$   r$      s$   € ÷ ñ ÷Rò ”5ñ òSr%   ))s   ‰PNG

zPNG image data)s   ÿØÿzJPEG image data)s   GIF87aúGIF image data)s   GIF89arn  )s   RIFFz$RIFF container (WAV/AVI/WebP family))s   %PDF-zPDF document)s   PKz$ZIP archive (also docx/xlsx/jar/apk))s   PKzZIP archive (empty))s   ‹zgzip compressed data)s   BZhzbzip2 compressed data)s   ý7zXZ zxz compressed data)s   7z¼¯'z7-Zip archive)s   ELFzELF executable)s   MZzWindows PE executable)s   ÏúíþzMach-O executable (64-bit))s   Êþº¾z$Mach-O universal binary / Java class)s   SQLite format 3 zSQLite database)s   OggSzOgg container)s   fLaCz
FLAC audio)s   ID3zMP3 audio (ID3 tag))s      z$ISO media container (MP4/MOV family))s   BMzBMP image data)s   II* zTIFF image data (little-endian))s   MM *zTIFF image data (big-endian)>   ú.bmpú.gifú.icoú.jpgú.pngú.jpegú.webp)Grm  rŒ   r_  ra  r<  r]  r  rÓ  r`  r·   Úloggingr™   r   r   Úabcr   r   Útypingr   r   Úpathlibr   Útools.binary_extensionsr   Úagent.file_safetyr   Útools.file_operations_commonr	   r
   r   r   r   r   r   r   r   r   r   r   r   Útools.file_operations_lintr   r   r   Útools.file_operations_searchr   Útoolsr   r»  Ú	getLoggerrˆ   r7  r!   r   Ú_HOMEr)   r-   r6   r8   r‚  rê  rë  r4  rý  r  r›   r¤   r»   rÂ   rÄ   r$   )rm  s   @r#   Ú<module>r‚     sÿ   øðöó Û Û 	Û 	Û 
Û Û Û Û Û Û Û ß #ß !Ý å 8Ý 4÷Y÷ Y÷ Yõ Y÷ [Ñ ZÝ 4Ý 6à	×	Ò	˜8Ó	$€ñ 	ˆD�IŠI‹KÓ€ðÐ ó õ<	õ
Gô%+�Sô %+òV NÐ ð 0Ð ð
 (Ð à&Ð Ø'Ð Ø'Ð õ0õ)õ'õ$&ô f˜) [°.ö fr%   