7141ccff62
* fix: resolve pre-commit check failures - Change RuntimeError to TypeError for type validation in report/writer.py - Update pyupgrade to v3.21.2 for Python 3.14 compatibility * chore: add pytest test infrastructure Mirror the layout introduced on feature/438-token_budget: pytest + pytest-asyncio dev deps, asyncio_mode auto, a tests.* mypy override, and pytest in the mypy pre-commit hook deps so the tests/ package type-checks. * feat: add --mount and large-target pre-flight for local repos (#492) Large local targets were copied into the sandbox file-by-file via the SDK LocalDir entry, which stalls on big repos and could leave /workspace empty. - --mount <path> bind-mounts a host directory read-only at /workspace/<subdir> instead of copying it, bypassing the per-file stream. - A size pre-flight (STRIX_MAX_LOCAL_COPY_MB, default 1024) fails fast with a clear message suggesting --mount when a non-mounted local target is too big. * fix: reject empty --mount paths An empty or whitespace-only --mount value resolves to the current working directory and would silently bind-mount it into the sandbox. Reject it. * fix: dedupe local targets so a dir is never both copied and mounted If the same directory is passed via --target and --mount (or as duplicate values), it previously produced two targets — copied AND bind-mounted, and the copied one could trip the size pre-flight. Dedupe by resolved path, preferring the bind mount. * fix: treat non-positive STRIX_MAX_LOCAL_COPY_MB as disabled Previously a value of 0 (or negative) made every local target count as oversized, aborting all local scans. Now <= 0 disables the pre-flight. * fix: log unreadable subtrees during size pre-flight os.walk silently swallowed directory-listing errors, so a permission-denied subtree could make a large repo under-count and slip past the pre-flight. Surface such omissions via an onerror warning. * docs: document --mount and STRIX_MAX_LOCAL_COPY_MB Add CLI reference + example for --mount, document the size pre-flight env var, note the read-only-is-not-a-hard-boundary caveat and that remote repos are not size-checked, and clarify the backends docstring on when bind mounts apply. * Update strix/interface/main.py * Update strix/runtime/docker_client.py ---------
68 lines
1.9 KiB
Python
68 lines
1.9 KiB
Python
"""Tests for build_session_entries: splitting copied vs bind-mounted sources."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
from agents.sandbox.entries import LocalDir
|
|
|
|
from strix.runtime.session_manager import build_session_entries
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
from pathlib import Path
|
|
|
|
|
|
def _source(subdir: str, path: str, *, mount: bool = False) -> dict[str, Any]:
|
|
return {"source_path": path, "workspace_subdir": subdir, "mount": mount}
|
|
|
|
|
|
def test_copied_source_becomes_localdir_entry(tmp_path: Path) -> None:
|
|
entries, bind_mounts = build_session_entries([_source("repo", str(tmp_path))])
|
|
|
|
assert bind_mounts == []
|
|
assert isinstance(entries["repo"], LocalDir)
|
|
assert entries["repo"].src == tmp_path.resolve()
|
|
|
|
|
|
def test_mounted_source_becomes_bind_mount(tmp_path: Path) -> None:
|
|
entries, bind_mounts = build_session_entries([_source("repo", str(tmp_path), mount=True)])
|
|
|
|
assert entries == {}
|
|
assert bind_mounts == [
|
|
{
|
|
"source": str(tmp_path.resolve()),
|
|
"target": "/workspace/repo",
|
|
"read_only": True,
|
|
}
|
|
]
|
|
|
|
|
|
def test_mixed_sources_split_correctly(tmp_path: Path) -> None:
|
|
copied = tmp_path / "copied"
|
|
mounted = tmp_path / "mounted"
|
|
copied.mkdir()
|
|
mounted.mkdir()
|
|
|
|
entries, bind_mounts = build_session_entries(
|
|
[
|
|
_source("copied", str(copied)),
|
|
_source("mounted", str(mounted), mount=True),
|
|
]
|
|
)
|
|
|
|
assert list(entries) == ["copied"]
|
|
assert isinstance(entries["copied"], LocalDir)
|
|
assert [m["target"] for m in bind_mounts] == ["/workspace/mounted"]
|
|
|
|
|
|
def test_incomplete_sources_are_skipped() -> None:
|
|
entries, bind_mounts = build_session_entries(
|
|
[
|
|
{"source_path": "", "workspace_subdir": "x"},
|
|
{"source_path": "/p", "workspace_subdir": ""},
|
|
]
|
|
)
|
|
assert entries == {}
|
|
assert bind_mounts == []
|