mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
fix(photon): support immutable install trees for the sidecar (NS-606)
The Photon iMessage sidecar needs node_modules under plugins/platforms/photon/sidecar/, but hosted/managed images keep the whole install tree under an immutable /opt/hermes — every install and self-heal path (setup CLI, stale-deps reinstall, cold install) died on EROFS, and hosted users have no shell to work around it. Three-layer fix, mirroring the WhatsApp bridge resolver pattern: 1. Bake the deps into the image. The Dockerfile now runs npm ci for the sidecar in the layer-cached dependency stage (deterministic installs from the committed lockfile; the postinstall spectrum-ts patch runs at build time). Hosted happy path needs no runtime install at all. 2. New sidecar_paths.resolve_sidecar_dir() decides where the sidecar runs from: PHOTON_SIDECAR_DIR override > writable source dir (dev installs, unchanged) > read-only dir with baked fresh deps (managed image) > mirror to $HERMES_HOME/photon/sidecar (writable data volume) when deps are missing or stale in a read-only tree. The mirror refreshes changed source files on image updates while keeping node_modules, so the existing lockfile-staleness self-heal works there. 3. connect() can now cold-install: _start_sidecar() runs the bounded npm ci bootstrap when node_modules is missing instead of raising immediately, and check_requirements() reports available when a self-install is possible (npm present + writable resolved dir) so the gateway actually creates the adapter on hosted instances. A failed bootstrap still raises the actionable error, which connect() surfaces as the retryable SIDECAR_FAILED fatal state on the dashboard. Tests: resolver decision table (env override, in-place, mirror, refresh, fail-open), cold-install lifecycle paths, and a Dockerfile contract test guarding the baked-deps + no-chown invariants. Fixes NS-606.
This commit is contained in:
parent
a65494ed00
commit
0dfd5546fc
9 changed files with 472 additions and 10 deletions
|
|
@ -109,3 +109,25 @@ def test_dockerfile_redirects_lazy_installs_to_durable_target() -> None:
|
|||
"lazy-packages must be in the per-boot chown subdir list so it stays "
|
||||
"hermes-owned"
|
||||
)
|
||||
|
||||
|
||||
def test_dockerfile_bakes_photon_sidecar_deps() -> None:
|
||||
"""The Photon sidecar's node_modules must be baked at build time (NS-606).
|
||||
|
||||
The install tree is immutable at runtime, so a lazy `npm ci` on first
|
||||
connect would hit EROFS. Baking the deps (from the committed lockfile,
|
||||
which also runs the spectrum-ts postinstall patch) makes the hosted
|
||||
happy path install-free. Guards the contract between the Dockerfile
|
||||
and plugins/platforms/photon/sidecar_paths.resolve_sidecar_dir, which
|
||||
runs in place only when the baked deps exist and match the lockfile.
|
||||
"""
|
||||
text = _dockerfile_text()
|
||||
|
||||
assert "plugins/platforms/photon/sidecar/package-lock.json" in text
|
||||
assert re.search(
|
||||
r"RUN cd plugins/platforms/photon/sidecar && \\\n\s+npm ci", text
|
||||
), "sidecar deps must be installed with `npm ci` (deterministic, runs postinstall patch)"
|
||||
# Immutability contract: never chown the sidecar tree to the runtime user.
|
||||
assert not re.search(
|
||||
r"chown\s+-R\s+hermes:hermes\s+/opt/hermes/plugins", text
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue