feat: mount skills directory into remote backends (Modal, Docker)#3890
feat: mount skills directory into remote backends (Modal, Docker)#3890
Conversation
3a18eca to
0219cbf
Compare
|
0219cbf to
bce4fa6
Compare
|
bce4fa6 to
8c9f28c
Compare
|
8c9f28c to
2dc1cfc
Compare
|
Skills with scripts/, templates/, and references/ subdirectories need those files available inside sandboxed execution environments. Previously the skills directory was missing entirely from remote backends. Live sync — files stay current as credentials refresh and skills update: - Docker/Singularity: bind mounts are inherently live (host changes visible immediately) - Modal: _sync_files() runs before each command with mtime+size caching, pushing only changed credential and skill files (~13μs no-op overhead) - SSH: rsync --safe-links before each command (naturally incremental) - Daytona: _upload_if_changed() with mtime+size caching before each command Security — symlink filtering: - Docker/Singularity: sanitized temp copy when symlinks detected - Modal/Daytona: iter_skills_files() skips symlinks - SSH: rsync --safe-links skips symlinks pointing outside source tree - Temp dir cleanup via atexit + reuse across calls Non-root user support: - SSH: detects remote home via echo $HOME, syncs to $HOME/.hermes/ - Daytona: detects sandbox home before sync, uploads to $HOME/.hermes/ - Docker/Modal/Singularity: run as root, /root/.hermes/ is correct Also: - credential_files.py: fix name/path key fallback in required_credential_files - Singularity, SSH, Daytona: gained credential file support - 14 tests covering symlink filtering, name/path fallback, iter_skills_files
2dc1cfc to
534ec87
Compare
|
…ousResearch#3890) Skills with scripts/, templates/, and references/ subdirectories need those files available inside sandboxed execution environments. Previously the skills directory was missing entirely from remote backends. Live sync — files stay current as credentials refresh and skills update: - Docker/Singularity: bind mounts are inherently live (host changes visible immediately) - Modal: _sync_files() runs before each command with mtime+size caching, pushing only changed credential and skill files (~13μs no-op overhead) - SSH: rsync --safe-links before each command (naturally incremental) - Daytona: _upload_if_changed() with mtime+size caching before each command Security — symlink filtering: - Docker/Singularity: sanitized temp copy when symlinks detected - Modal/Daytona: iter_skills_files() skips symlinks - SSH: rsync --safe-links skips symlinks pointing outside source tree - Temp dir cleanup via atexit + reuse across calls Non-root user support: - SSH: detects remote home via echo $HOME, syncs to $HOME/.hermes/ - Daytona: detects sandbox home before sync, uploads to $HOME/.hermes/ - Docker/Modal/Singularity: run as root, /root/.hermes/ is correct Also: - credential_files.py: fix name/path key fallback in required_credential_files - Singularity, SSH, Daytona: gained credential file support - 14 tests covering symlink filtering, name/path fallback, iter_skills_files
Summary
Skills with
scripts/,templates/, andreferences/subdirectories need those files available inside sandboxed execution environments. Previously only individual credential files were mounted — the skills directory itself was completely absent from Modal/Docker sandboxes, meaning skill scripts couldn't be executed.Reported by ilovescience (Tanishq) who uses Modal as a terminal backend —
~/.hermes/skills/didn't exist at all in the sandbox.Changes
tools/credential_files.pyget_skills_directory_mount()— returns$HERMES_HOME/skills/mount infotools/credential_files.pyname/pathkey fallback — skills usingnameinrequired_credential_fileswere silently skippedtools/environments/modal.pyMount.from_local_dir()at sandbox creationtools/environments/docker.pytests/tools/test_credential_files.pyHow it works
The skills tree is mounted read-only at
/root/.hermes/skills/inside the container. This means:python /root/.hermes/skills/.../scripts/setup.py)Tests