§
    øžyj   ã                  ó¶   — d Z ddlmZ ddlZddlZddlZddlZddlmZ ddl	m
Z
  ej        e¦  «        Z ee¦  «        j        dz  ZdZdd„ZeZdd„Zddd„ZdS )uæ  
Resolve where the Photon sidecar runs from and where its Node deps live.

The sidecar source ships inside the installed plugin tree
(``plugins/platforms/photon/sidecar/``). On dev/source installs that tree is
writable and everything â€” ``npm ci``, the spectrum patch, the sidecar itself â€”
happens in place. Hosted/managed images instead keep the whole install tree
under an immutable ``/opt/hermes`` (read-only for the hermes user), which
broke every install/self-heal path with EROFS (NS-606).

Resolution order (mirrors ``resolve_whatsapp_bridge_dir`` for the Baileys
bridge, which hit the same wall):

1. ``PHOTON_SIDECAR_DIR`` env override â€” operator escape hatch, used as-is.
2. Source dir writable â†’ run in place (dev installs, unchanged behavior).
3. Source dir read-only but ``node_modules`` is baked and current â†’ run in
   place. This is the managed-image happy path: the Dockerfile bakes the
   sidecar deps with ``npm ci`` at build time (deterministic installs,
   NS-559), so no runtime install is ever needed.
4. Source dir read-only and deps missing or stale â†’ mirror the sidecar
   source files to ``$HERMES_HOME/photon/sidecar`` (the durable data volume,
   e.g. ``/opt/data`` on hosted) and return that. The caller's normal
   install/self-heal machinery then works there because it is writable.

The mirror is refreshed on every resolve: when an image update changes a
sidecar source file, the changed file is re-copied (content compare, not
mtime) while ``node_modules`` is left in place â€” the adapter's existing
lockfile-vs-install-marker staleness check then triggers the ``npm ci``
self-heal inside the mirror.

This module is import-light on purpose: both ``adapter.py`` (gateway) and
``cli.py`` (``hermes photon ...``) use it.
é    )ÚannotationsN)ÚPath)ÚOptionalÚsidecar)z	index.mjszpackage.jsonúpackage-lock.jsonz$patch-spectrum-mixed-attachments.mjsÚpathr   ÚreturnÚboolc                ó„   — | dz  }	 |                      ¦   «          |                     ¦   «          dS # t          $ r Y dS w xY w)zêTrue when we can create files in ``path`` (probe-based, not stat).

    A stat-mode check lies on containers (root-squash, read-only bind
    mounts), so probe with a real create+unlink like the WhatsApp bridge
    resolver does.
    z.hermes-write-probeTF)ÚtouchÚunlinkÚOSError)r   Úprobes     úL/home/ragecks/.hermes/hermes-agent/plugins/platforms/photon/sidecar_paths.pyÚdir_writabler   ;   sU   € ð Ð(Ñ(€EðØ�Š‰ŒˆØ�Š‰ŒˆØˆtøÝð ð ð Øˆuˆuðøøøs   ‡(1 ±
?¾?Úsidecar_dirc                ó¨   — | dz  }| dz  dz  }	 |                      ¦   «         j        |                      ¦   «         j        k    S # t          $ r Y dS w xY w)u@  True when the committed lockfile postdates npm's install marker.

    Same signal as ``adapter._sidecar_deps_stale`` â€” duplicated here (three
    lines) rather than imported so this module stays import-light for the
    CLI. Returns False on any stat failure so an odd filesystem never forces
    the mirror path.
    r   Únode_modulesz.package-lock.jsonF)ÚstatÚst_mtimer   )r   ÚlockfileÚmarkers      r   Ú_lock_newer_than_installr   O   sg   € ð Ð0Ñ0€HØ˜>Ñ)Ð,@Ñ@€FðØ�}Š}‰ŒÔ'¨&¯+ª+©-¬-Ô*@Ò@Ð@øÝð ð ð Øˆuˆuðøøøs   �3A Á
AÁAÚ
source_dirúOptional[Path]c                óò  — | �t          | ¦  «        nt          }t          j        d¦  «        }|rt          |¦  «        S t	          |¦  «        r|S |dz                       ¦   «         rt          |¦  «        s|S ddlm}  |¦   «         dz  dz  }	 | 	                    dd¬	¦  «         t          D ]•}||z  }|                     ¦   «         sŒ||z  }|                     ¦   «         r1t          j        t          |¦  «        t          |¦  «        d
¬¦  «        s/t          j        t          |¦  «        t          |¦  «        ¦  «         Œ–|S # t           $ r(}t"                               d||¦  «         |cY d}~S d}~ww xY w)zûReturn the directory the sidecar should run from (see module doc).

    ``source_dir`` defaults to the installed plugin tree; tests and callers
    that monkeypatch the adapter's ``_SIDECAR_DIR`` pass it through so the
    override keeps working.
    NÚPHOTON_SIDECAR_DIRr   r   )Úget_hermes_homeÚphotonr   T)ÚparentsÚexist_okF)Úshallowu¥   [photon] install tree is read-only and mirroring the sidecar to %s failed (%s) â€” falling back to the read-only source dir; dependency installs will not be possible)r   ÚSOURCE_SIDECAR_DIRÚosÚgetenvÚ_dir_writableÚexistsr   Úhermes_constantsr   ÚmkdirÚ_MIRROR_FILESÚfilecmpÚcmpÚstrÚshutilÚcopy2r   ÚloggerÚwarning)	r   ÚsourceÚoverrider   ÚmirrorÚnameÚsrcÚdstÚexcs	            r   Úresolve_sidecar_dirr9   _   sª  € ð ",Ð!7�T�*ÑÔÐÕ=O€FåŒyÐ-Ñ.Ô.€HØð Ý�H‰~Œ~Ðå�VÑÔð Øˆð
 	�Ñ×'Ò'Ñ)Ô)ð Õ2JÈ6Ñ2RÔ2Rð Øˆð
 1Ð0Ð0Ð0Ð0Ð0àˆ_ÑÔ Ñ)¨IÑ5€FðØ�Š˜T¨DˆÑ1Ô1Ð1Ý!ð 	1ð 	1ˆDØ˜4‘-ˆCØ—:’:‘<”<ð ØØ˜4‘-ˆCØ—:’:‘<”<ð 1¥w¤{µ3°s±8´8½SÀ¹X¼XÈuÐ'UÑ'UÔ'Uð 1Ý”�S ™XœX¥s¨3¡x¤xÑ0Ô0Ð0øØˆøÝð ð ð Ý�Šð7ð Øñ	
ô 	
ð 	
ð ˆˆˆˆˆˆøøøøðøøøs   ÂB5E Å
E6ÅE1Å+E6Å1E6)r   r   r	   r
   )r   r   r	   r
   )N)r   r   r	   r   )Ú__doc__Ú
__future__r   r+   Úloggingr$   r.   Úpathlibr   Útypingr   Ú	getLoggerÚ__name__r0   Ú__file__Úparentr#   r*   r   r&   r   r9   © ó    r   ú<module>rE      sí   ðð ð  ðD #Ð "Ð "Ð "Ð "Ð "à €€€Ø €€€Ø 	€	€	€	Ø €€€Ø Ð Ð Ð Ð Ð Ø Ð Ð Ð Ð Ð à	ˆÔ	˜8Ñ	$Ô	$€à�T˜(‘^”^Ô*¨YÑ6Ð ð
€ðð ð ð ð" €ðð ð ð ð .ð .ð .ð .ð .ð .ð .rD   