* fix(vision): mount images/ upload dir into sandboxes and permit host read (#69575) Desktop, clipboard, and PDF uploads land in the flat top-level HERMES_HOME/images/ dir, but Docker sandboxes only mounted the cache/ subtree and the vision resolver only permitted host reads from the media caches. So vision_analyze on any desktop-app upload failed under a Docker backend with "not reachable inside the sandbox". - Add ("images", "images") to _CACHE_DIRS so the uploads dir is bind-mounted into sandbox containers through the existing profile-scoped cache-mount and reverse-mapping mechanism. - Add home/"images" to _media_cache_roots() so the non-local host-read allowlist permits reading uploads directly from the host filesystem. - Cover the mount entry, the container path mapping, and the Docker-mode resolver read for a profile-scoped upload. Co-authored-by: JonthanaHanh <92574114+JonthanaHanh@users.noreply.github.com> Co-authored-by: webtecnica <75556242+webtecnica@users.noreply.github.com> * fix(tui_gateway): write image uploads under the session's profile home (#69575) The attach RPCs (image.attach_bytes, clipboard.paste, pdf.attach) wrote uploads to the gateway's module-cached launch home via _hermes_home/"images". Those RPCs run before prompt.submit installs the session's profile HERMES_HOME override, so in a multi-profile / root-gateway deployment the file landed in the launch home while the sandbox mount and the vision host-read allowlist both resolve the session profile's images/ at run time — the agent could never see the upload it was handed. Add _session_images_dir(session), which anchors the write on the session's stored profile_home when present (matching the mount/read scope) and falls back to the launch home otherwise. Route both write sites through it, keeping per-profile isolation. Co-authored-by: webtecnica <75556242+webtecnica@users.noreply.github.com> --------- Co-authored-by: JonthanaHanh <92574114+JonthanaHanh@users.noreply.github.com> Co-authored-by: webtecnica <75556242+webtecnica@users.noreply.github.com>
This commit is contained in:
@@ -362,6 +362,39 @@ class TestCacheDirectoryMounts:
|
||||
|
||||
assert get_cache_directory_mounts() == []
|
||||
|
||||
def test_images_upload_dir_is_mounted(self, tmp_path, monkeypatch):
|
||||
"""The flat top-level ``images/`` upload dir is mounted (#69575).
|
||||
|
||||
Desktop / clipboard / PDF uploads land in ``HERMES_HOME/images``, not
|
||||
under ``cache/``. Without this entry vision_analyze on a desktop upload
|
||||
fails because the file is not reachable inside the sandbox.
|
||||
"""
|
||||
hermes_home = tmp_path / ".hermes"
|
||||
(hermes_home / "images").mkdir(parents=True)
|
||||
monkeypatch.setenv("HERMES_HOME", str(hermes_home))
|
||||
|
||||
mounts = get_cache_directory_mounts()
|
||||
by_container = {m["container_path"]: m["host_path"] for m in mounts}
|
||||
assert "/root/.hermes/images" in by_container
|
||||
assert by_container["/root/.hermes/images"] == str(hermes_home / "images")
|
||||
|
||||
def test_images_upload_file_maps_into_container(self, tmp_path, monkeypatch):
|
||||
"""A concrete upload under ``images/`` maps to its container path.
|
||||
|
||||
This is the reverse mapping vision uses to translate a container-visible
|
||||
path back to the host mount; it must recognise the ``images/`` dir.
|
||||
"""
|
||||
hermes_home = tmp_path / ".hermes"
|
||||
(hermes_home / "images").mkdir(parents=True)
|
||||
upload = hermes_home / "images" / "upload_20260722_181019_1.png"
|
||||
upload.write_bytes(bytes.fromhex("89504e470d0a1a0a"))
|
||||
monkeypatch.setenv("HERMES_HOME", str(hermes_home))
|
||||
|
||||
assert (
|
||||
map_cache_path_to_container(str(upload))
|
||||
== "/root/.hermes/images/upload_20260722_181019_1.png"
|
||||
)
|
||||
|
||||
|
||||
class TestMapCachePathToContainer:
|
||||
"""Tests for map_cache_path_to_container() — the backend-agnostic mapper."""
|
||||
|
||||
Reference in New Issue
Block a user