Ë
    ãß²j6  ã                   óX  — U d Z ddlZddlZddlZddlZddlmZmZmZ ddl	m
Z
 ddddd	d
œZ eh d£«      ZddddœZdededefd„Zdedeeef   fd„Zdedeeef   fd„Zdedeeef   fd„Zdedeeef   fd„ZeeeeedœZeeeegeeef   f   f   ed<    eh d£«      Z G d„ d«      Zy)zÍSyntax-lint and LSP-diagnostics tier for ``tools.file_operations``.

``ShellFileOperations`` inherits ``LintMixin``; module constants and in-process
linters are pure functions importable from this module.
é    N)ÚCallableÚDictÚOptional)Ú
LintResultz python -m py_compile {file} 2>&1znode --check {file} 2>&1znpx tsc --noEmit {file} 2>&1zgo vet {file} 2>&1zrustfmt --check {file} 2>&1)ú.pyz.jsú.tsú.goú.rs>   r	   r
   r   )z/this is not the tsc command you are looking forz%could not determine executable to runznot found in npm registry)zno input filename givenzerror: not a workspace)zcannot find packagezgo: cannot find main module)ÚnpxÚrustfmtÚgoÚbase_cmdÚoutputÚreturnc                 ó|   ‡— t         j                  | «      }|sy|j                  «       Št        ˆfd„|D «       «      S )zgTrue iff ``output`` from ``base_cmd`` (first word of the linter cmd) says the tool itself couldn't run.Fc              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­w©N© )Ú.0ÚpÚlowers     €ú?/home/ubuntu/.hermes/hermes-agent/tools/file_operations_lint.pyú	<genexpr>z._looks_like_linter_unusable.<locals>.<genexpr>8   s   øè ø€ Ò,˜aˆq�EŒzÑ,ùs   ƒ)Ú_LINTER_UNUSABLE_PATTERNSÚgetr   Úany)r   r   Úpatternsr   s      @r   Ú_looks_like_linter_unusabler   2   s5   ø€ ä(×,Ñ,¨XÓ6€HÙØØ�L‰L‹N€EÜÓ, 8Ô,Ó,Ð,ó    Úcontentc           	      ó"  — 	 t        j                  | «       y# t         j                  $ r6}dd|j                  › d|j                  › d|j
                  › d�fcY d}~S d}~wt        $ r&}dt        |«      j                  › d|› �fcY d}~S d}~ww xY w)	z:In-process JSON syntax check. Returns (ok, error_message).©TÚ FzJSONDecodeError: ú (line ú	, column ú)Nú: )	ÚjsonÚloadsÚJSONDecodeErrorÚmsgÚlinenoÚcolnoÚ	ExceptionÚtypeÚ__name__©r    Úes     r   Ú_lint_json_inprocr3   ;   s…   € ð1Ü�
‰
�7ÔØøÜ×Ñò VØÐ)¨!¯%©%¨°¸¿¹°zÀÈ1Ï7É7È)ÐSTÐUÐUÕUûÜò 1Øœ˜a›×)Ñ)Ð*¨"¨Q¨CÐ0Ð0Õ0ûð1ús,   ‚ ˜B«+AÁBÁBÁ(B	ÂBÂ	Bc                 óú   — 	 ddl }	 |j                  | «      D ]  }Œ y# t        $ r Y yw xY w# |j                  $ r}dd|› �fcY d}~S d}~wt        $ r&}dt        |«      j                  › d|› �fcY d}~S d}~ww xY w)zîIn-process YAML syntax check; ``__SKIP__`` when PyYAML is missing. Syntax-only
    (``yaml.parse``), NOT ``safe_load``: loading rejects valid multi-doc streams and
    app tags (``!Sub``, ``!vault``), and this is a fail-closed WRITE gate.r   N)TÚ__SKIP__r"   FzYAMLError: r'   )ÚyamlÚImportErrorÚparseÚ	YAMLErrorr.   r/   r0   )r    Ú_yamlÚ_eventr2   s       r   Ú_lint_yaml_inprocr<   F   s’   € ð Ûð1Ø—k‘k 'Ó*ò 	ˆFØð	àøô ò  Ùð ûð �?‰?ò (Ø˜ A 3Ð'Ð'Õ'ûÜò 1Øœ˜a›×)Ñ)Ð*¨"¨Q¨CÐ0Ð0Õ0ûð1ús8   ‚ ‡- ž	*©*­A:¼AÁA:ÁA:ÁA5Á/A:Á5A:c                 ó”   — 	 t        j                  | «       y# t        $ r&}dt        |«      j                  › d|› �fcY d}~S d}~ww xY w)z.In-process TOML syntax check (stdlib tomllib).r"   Fr'   N)Útomllibr)   r.   r/   r0   r1   s     r   Ú_lint_toml_inprocr?   X   sG   € ð1Ü�‰�gÔØøÜò 1Øœ˜a›×)Ñ)Ð*¨"¨Q¨CÐ0Ð0Õ0ûð1ús   ‚ ˜	A¡A¼AÁAc                 ó\  — 	 t        j                  | «       y# t        $ r]}|j                  rd|j                  › d|j                  › d�nd}dt        |«      j                  › d|j                  › |› �fcY d}~S d}~wt        $ r&}dt        |«      j                  › d|› �fcY d}~S d}~ww xY w)	zQIn-process Python syntax check via ast.parse (py_compile's scope, no subprocess).r"   r$   r%   r&   r#   Fr'   N)	Úastr8   ÚSyntaxErrorr,   Úoffsetr/   r0   r+   r.   )r    r2   Úlocs      r   Ú_lint_python_inprocrE   a   s�   € ð1Ü�	‰	�'ÔØøÜò :Ø:;¿(º(�˜Ÿ™�z ¨1¯8©8¨*°AÑ6ÈˆØœ˜a›×)Ñ)Ð*¨"¨Q¯U©U¨G°C°5Ð9Ð9Õ9ûÜò 1Øœ˜a›×)Ñ)Ð*¨"¨Q¨CÐ0Ð0Õ0ûð1ús-   ‚ ˜	B+¡AA9Á3B+Á9B+ÂB&Â B+Â&B+)r   ú.jsonú.yamlú.ymlú.tomlÚLINTERS_INPROC>   rH   rF   rI   rG   c            	       óâ   — e Zd ZdZddedee   defd„Z	 ddedee   dee   defd	„Zde	fd
„Z
d„ Zdede	fd„Zdede	fd„Zdedefd„Zdede	fd„Zdeddfd„Zdddœdedee   dee   defd„Zy)Ú	LintMixinz«Post-write syntax lint + LSP diagnostics. Requires ``_exec``,
    ``_has_command``, ``_escape_shell_arg``, ``_escape_native_tool_arg`` and
    ``env`` from the host class.NÚpathr    r   c                 ó¸  — t         j                  j                  |«      d   j                  «       }t        j                  |«      }|�‰|€P| j                  d| j                  |«      › d�«      }|j                  dk7  rt        dd|› d�¬	«      S |j                  } ||«      \  }}|d
k(  rt        dd|› d�¬	«      S t        ||rd¬«      S |¬«      S |t        vrt        dd|› d�¬	«      S |dk(  r| j                  |«      rt        dd¬	«      S |t        v r"| j                  |«      rt        dd|› d�¬	«      S t        |   }|j                  «       d   }	| j!                  |	«      st        d|	› d�¬	«      S | j                  |j#                  d| j%                  |«      «      d¬«      }
|
j                  dk7  rut'        |	|
j                  «      r_ddlm}  ||
j                  «      j-                  «       }t/        d„ |j1                  «       D «       |dd «      }t        d|	› d|dd › �¬	«      S t        |
j                  dk(  |
j                  j-                  «       ¬«      S )zŒSyntax-check ``path``: in-process linter when one matches the
        extension (``content`` avoids a re-read), else the shell linter table.é   Nzcat z 2>/dev/nullr   TzFailed to read z	 for lint)ÚskippedÚmessager5   zNo linter available for z (missing dependency)r#   ©Úsuccessr   zNo linter for z filesr   u±   Project tsconfig.json detected â€” per-file tsc skipped (single-file tsc can't resolve project aliases/globals; use the LSP tier or `tsc -p tsconfig.json` for real diagnostics).zLSP server handles u    â€” shell linter skippedz not availablez{file}é   )Útimeout)Ú
strip_ansic              3   ó^   K  — | ]%  }|j                  «       sŒ|j                  «       –— Œ' y ­wr   )Ústrip)r   Úlns     r   r   z(LintMixin._check_lint.<locals>.<genexpr>¨   s   è ø€ ÒW¨bÈBÏHÉHÍJ˜rŸx™xŸzÑWùs   ‚-˜-éx   z not usable: éÈ   )ÚosrM   Úsplitextr   rJ   r   Ú_execÚ_escape_shell_argÚ	exit_coder   ÚstdoutÚLINTERSÚ_has_ancestor_tsconfigÚ_SHELL_LINTER_LSP_REDUNDANTÚ_lsp_will_handleÚsplitÚ_has_commandÚreplaceÚ_escape_native_tool_argr   Útools.ansi_striprV   rX   ÚnextÚ
splitlines)ÚselfrM   r    ÚextÚinprocÚread_resultÚokÚerrÚ
linter_cmdr   ÚresultrV   ÚcleanedÚ
first_lines                 r   Ú_check_lintzLintMixin._check_lint‚   s^  € ô �g‰g×Ñ˜tÓ$ QÑ'×-Ñ-Ó/ˆÜ×#Ñ# CÓ(ˆØÐØˆØ"Ÿj™j¨4°×0FÑ0FÀtÓ0LÐ/MÈ\Ð)ZÓ[�Ø×(Ñ(¨AÒ-Ü%¨d¸oÈdÈVÐS\Ð<]Ô^Ð^Ø%×,Ñ,�Ù˜W“o‰GˆB�Ø�jÒ Ü!¨$Ð:RÐSVÐRWÐWlÐ8mÔnÐnÜ b±r°ÔCÐC¸sÔCÐCØ”gÑÜ d°nÀSÀEÈÐ4PÔQÐQð �%Š<˜D×7Ñ7¸Ô=Ü dð ôð ð Ô-Ñ-°$×2GÑ2GÈÔ2MÜ dÐ6IÈ#ÈÐNgÐ4hÔiÐiÜ˜S‘\ˆ
Ø×#Ñ#Ó% aÑ(ˆØ× Ñ  Ô*Ü d°x°jÀÐ4OÔPÐPà—‘˜J×.Ñ.¨x¸×9UÑ9UÐVZÓ9[Ó\Ðfh�ÓiˆØ×Ñ˜qÒ Ô%@ÀÈ6Ï=É=Ô%YÝ3Ù  §¡Ó/×5Ñ5Ó7ˆGäÑW°G×4FÑ4FÓ4HÔWÐY`ÐaeÐbeÐYfÓgˆJÜ d°x°jÀÈjÐY]ÐZ]ÐN^ÐM_Ð4`ÔaÐaÜ &×"2Ñ"2°aÑ"7ÀÇÁ×@SÑ@SÓ@UÔVÐVr   Úpre_contentÚpost_contentc                 óz  — | j                  ||¬«      }|j                  s|j                  s|€|S | j                  ||¬«      }|j                  s|j                  s|j                  s|S |j                  j	                  «       D �ch c]#  }|j                  «       sŒ|j                  «       ’Œ% }}|j                  j	                  «       D �cg c](  }|j                  «       sŒ|j                  «       |vsŒ'|‘Œ* }}|st        d|j                  d¬«      S t        dddj                  |«      z   ¬«      S c c}w c c}w )uí   Post-write lint; when it fails and ``pre_content`` is known, report only
        errors this edit introduced (pre-existing lines filtered out). Semantic
        (LSP) diagnostics are a separate channel â€” see ``_maybe_lsp_diagnostics``.)r    Fu^   Pre-existing lint errors â€” this edit didn't introduce new ones but the file is still broken.)rS   r   rQ   zLNew lint errors introduced by this edit (pre-existing errors filtered out):
Ú
rR   )rw   rS   rP   r   rl   rX   r   Újoin)	rm   rM   rx   ry   ÚpostÚprerY   Ú	pre_linesÚ
post_liness	            r   Ú_check_lint_deltazLintMixin._check_lint_delta¬   s  € ð
 ×Ñ ¨lÐÓ;ˆØ�<Š<˜4Ÿ<š<¨;Ð+>ØˆKØ×Ñ˜t¨[ÐÓ9ˆØ�;Š;˜#Ÿ+š+¨S¯ZªZØˆKð +.¯*©*×*?Ñ*?Ó*AÖP BÀRÇXÁXÅZ�R—X‘X•ZÐPˆ	ÐPØ#'§;¡;×#9Ñ#9Ó#;Öj˜R¸r¿x¹x½zÈbÏhÉhËjÐ`iÒNi’bÐjˆ
ÐjÙÜ e°D·K±KØpôsð sä %ð4Ø6:·i±iÀ
Ó6KñLôð 	ùò QùÚjs   ÂD3ÂD3ÃD8Ã!D8Ã4D8c                 óf   — t        | dd«      }|€y	 ddlm} t	        ||«      S # t        $ r Y yw xY w)z…True iff wired to a local backend. LSP servers run on the host and
        can't see files inside Docker/Modal/SSH/Daytona sandboxes.ÚenvNFr   )ÚLocalEnvironment)ÚgetattrÚtools.environments.localr„   r.   Ú
isinstance)rm   rƒ   r„   s      r   Ú_lsp_local_onlyzLintMixin._lsp_local_onlyÃ   sF   € ô �d˜E 4Ó(ˆØˆ;Øð	ÝAô ˜#Ð/Ó0Ð0øô ò 	Ùð	ús   ’$ ¤	0¯0c                 ó^   — | j                  «       sy	 ddlm}  |«       S # t        $ r Y yw xY w)z…The active LSPService, or None on a non-local backend / any failure.
        LSP is an enrichment layer and must never break a write.Nr   )Úget_service)rˆ   Ú	agent.lsprŠ   r.   )rm   rŠ   s     r   Ú_lsp_servicezLintMixin._lsp_serviceÏ   s5   € ð ×#Ñ#Ô%Øð	Ý-Ù“=Ð øÜò 	Ùð	ús   “   	,«,rn   c                 ó¤   ‡— ‰sy	 | j                  «       }|�|j                  ‰«      S ddlm} t        ˆfd„|D «       «      S # t        $ r Y yw xY w)zÐTrue iff the active service (config-declared servers included) or, without one,
        the static registry claims ``ext``. Decides whether pre-write content is worth
        capturing for the line-shift map.Fr   )ÚSERVERSc              3   óV   •K  — | ]   }‰j                  «       |j                  v –— Œ" y ­wr   )r   Ú
extensions)r   Úsrvrn   s     €r   r   z3LintMixin._lsp_handles_extension.<locals>.<genexpr>ç   s    øè ø€ ÒD°S�3—9‘9“; #§.¡.Ô0ÑDùs   ƒ&))rŒ   Úhandles_extensionÚagent.lsp.serversrŽ   r.   r   )rm   rn   ÚsvcrŽ   s    `  r   Ú_lsp_handles_extensionz LintMixin._lsp_handles_extensionÚ   s^   ø€ ñ Øð	Ø×#Ñ#Ó%ˆCØˆØ×,Ñ,¨SÓ1Ð1Ý1ô ÓD¸GÔDÓDÐDøô ò 	Ùð	ús   †"A ©A Á	AÁAc                 ó  — | j                  «       sy	 t        j                  j                  t        j                  j	                  |«      «      }t        j                  j                  t        j                  j                  |d«      «      set        j                  j                  |«      }||k(  ry|}t        j                  j                  t        j                  j                  |d«      «      sŒey# t        $ r Y yw xY w)uû   True iff a tsconfig.json exists in ``path``'s directory or any ancestor.
        Host-side walk, local backend only: on a remote backend this answers False so
        the shell linter still runs â€” never suppress lint on a probe that couldn't answer.Fztsconfig.jsonT)rˆ   r\   rM   ÚdirnameÚabspathÚisfiler|   r.   )rm   rM   ÚdÚparents       r   rc   z LintMixin._has_ancestor_tsconfigé   s¯   € ð ×#Ñ#Ô%Øð		Ü—‘—‘¤§¡§¡°Ó 5Ó6ˆAÜ—g‘g—n‘n¤R§W¡W§\¡\°!°_Ó%EÔFÜŸ™Ÿ™¨Ó+�Ø˜Q’;Ø Ø�ô	 —g‘g—n‘n¤R§W¡W§\¡\°!°_Ó%EÕFð
 øÜò 	Ùð	ús   “BC2 Â1?C2 Ã2	C>Ã=C>Úmethodc                 ór   — | j                  «       }|€|S 	  t        ||«      |«      S # t        $ r |cY S w xY w)z‰``svc.<method>(path)`` on the active service; ``default`` when there is
        no service or the call raises (LSP never breaks a write).)rŒ   r…   r.   )rm   rœ   rM   Údefaultr”   s        r   Ú	_lsp_callzLintMixin._lsp_callú   sI   € ð ×ÑÓ!ˆØˆ;ØˆNð	Ø'”7˜3 Ó'¨Ó-Ð-øÜò 	ØŠNð	ús   –( ¨6µ6c                 ó:   — t        | j                  d|d«      «      S )uÉ   True iff the LSP service is active AND ``enabled_for(path)`` (workspace
        detection, disabled-server set, broken-pair short-circuit). Any failure â†’
        False so the shell linter still runs.Úenabled_forF)ÚboolrŸ   ©rm   rM   s     r   re   zLintMixin._lsp_will_handle  s   € ô �D—N‘N =°$¸Ó>Ó?Ð?r   c                 ó*   — | j                  d|d«       y)zWCapture pre-edit LSP diagnostics so the post-write delta is correct. Silent on failure.Úsnapshot_baselineN)rŸ   r£   s     r   Ú_snapshot_lsp_baselinez LintMixin._snapshot_lsp_baseline  s   € à�‰Ð*¨D°$Õ7r   )rx   ry   c                óP  — | j                  «       }|�| j                  |«      syd}|�|�||k7  r	 ddlm}  |||«      }	 |j                  |d|¬«      }|sy	 ddlm}m}	  |||«      }
|
r |	d|
z   «      S dS # t        $ r d}Y ŒFw xY w# t        $ r Y yw xY w# t        $ r Y yw xY w)	a/  Formatted LSP diagnostics introduced by this edit, or "" when LSP is
        unavailable/disabled/clean. With both pre and post content a line-shift map
        remaps baseline diagnostics into post-edit coordinates; otherwise every
        pre-existing diagnostic below an inserted line would look new.Nr#   r   )Úbuild_line_shiftT)ÚdeltaÚ
line_shift)Úreport_for_fileÚtruncatez)LSP diagnostics introduced by this edit:
)	rŒ   re   Úagent.lsp.range_shiftr¨   r.   Úget_diagnostics_syncÚagent.lsp.reporterr«   r¬   )rm   rM   rx   ry   r”   rª   r¨   Údiagnosticsr«   r¬   Úblocks              r   Ú_maybe_lsp_diagnosticsz LintMixin._maybe_lsp_diagnostics  sá   € ð ×ÑÓ!ˆØˆ;˜d×3Ñ3°DÔ9ØØˆ
ØÐ" |Ð'?ÀKÐS_ÒD_ð"ÝBÙ-¨k¸<ÓH�
ð	Ø×2Ñ2°4¸tÐPZÐ2Ó[ˆKñ Øð	ßDÙ# D¨+Ó6ˆEÙUZ‘8ÐHÈ5ÑPÓQÐbÐ`bÐbøô ò "Ø!’
ð"ûô ò 	Ùð	ûô ò 	Ùð	ús;   ±A9 ÁB
 ÁB Á7B Á9BÂBÂ
	BÂBÂ	B%Â$B%r   )r0   Ú
__module__Ú__qualname__Ú__doc__Ústrr   r   rw   r�   r¢   rˆ   rŒ   r•   rc   rŸ   re   r¦   r²   r   r   r   rL   rL   }   s  „ ñ$ñ(W ð (W¨h°s©mð (WÀzó (WðV 9=ñ cð ¸À¹ð Ø(0°©ðØAKóð.
1 ó 
1ò	ðE¨#ð E°$ó Eð¨3ð °4ó ð"	 ð 	¨3ó 	ð@ Sð @¨Tó @ð8¨3ð 8°4ó 8ð QUØ=Aò¨3ð ÀÈÁð Ø-5°c©]ðØFIôr   rL   )rµ   rA   r(   r\   r>   Útypingr   r   r   Útools.file_operations_commonr   rb   Ú	frozensetrd   r   r¶   r¢   r   Útupler3   r<   r?   rE   rJ   Ú__annotations__Ú_FAIL_CLOSED_INPROC_EXTSrL   r   r   r   ú<module>r½      sA  ðòó Û Û 	Û ß +Ñ +å 3ð
 .Ø%Ø)ØØ(ñ€ñ (Ò(=Ó>Ð ð
ð
ðñÐ ð"-¨#ð -°sð -¸tó -ð1˜sð 1 u¨T°3¨YÑ'7ó 1ð1˜sð 1 u¨T°3¨YÑ'7ó 1ð$1˜sð 1 u¨T°3¨YÑ'7ó 1ð	1 ð 	1¨¨t°S¨yÑ)9ó 	1ð ØØØØñ@€��S˜( C 5¨%°°c°	Ñ*:Ð#:Ñ;Ð;Ñ<ó ñ %Ò%HÓIÐ ÷mò mr   