Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
287 changes: 243 additions & 44 deletions hud/environment/file_tracker.py

Large diffs are not rendered by default.

75 changes: 0 additions & 75 deletions hud/environment/file_tracking.py

This file was deleted.

67 changes: 67 additions & 0 deletions hud/environment/tests/test_file_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

import base64
from typing import TYPE_CHECKING

from hud.environment.file_tracker import FileTracker
Expand Down Expand Up @@ -137,6 +138,72 @@ def test_vcs_config_files_are_redacted(tmp_path: Path) -> None:
assert "new-token@example.com" not in patch.patch


def test_capture_changed_deliverables_since_advanced_baseline(tmp_path: Path) -> None:
(tmp_path / "setup.xlsx").write_bytes(b"setup workbook")
tracker = FileTracker(tmp_path)
tracker.take_baseline()
tracker.advance_baseline()

(tmp_path / "analysis.py").write_text("print('tracked by diff')\n")
(tmp_path / "notes.txt").write_text("tracked by diff\n")
(tmp_path / "deliverable.xlsx").write_bytes(b"workbook bytes")
(tmp_path / "report.html").write_text("<html><body>report</body></html>\n")

payload = tracker.flush_changes()["capture"]

assert payload["files_changed"] == 4
assert payload["files_eligible"] == 2
assert payload["files_captured"] == 2
assert payload["files_skipped"] == 0
files = {file["path"]: file for file in payload["files"]}

xlsx = files["deliverable.xlsx"]
assert xlsx["status"] == "added"
assert (
xlsx["content_type"] == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
)
assert len(xlsx["content_hash"]) == 64
assert base64.b64decode(xlsx["file"]["data"]) == b"workbook bytes"
assert xlsx["file"]["type"] == "file"
assert xlsx["file"]["media_type"] == xlsx["content_type"]

html = files["report.html"]
assert html["status"] == "added"
assert html["content_type"] == "text/html"
assert base64.b64decode(html["file"]["data"]) == b"<html><body>report</body></html>\n"
assert html["file"]["media_type"] == "text/html"


def test_capture_skips_secret_shaped_files(tmp_path: Path) -> None:
(tmp_path / ".env.xlsx").write_bytes(b"API_KEY=before")
tracker = FileTracker(tmp_path)
tracker.take_baseline()

(tmp_path / ".env.xlsx").write_bytes(b"API_KEY=after")
payload = tracker.flush_changes()["capture"]

assert payload["files_changed"] == 1
assert payload["files_eligible"] == 0
assert payload["files_captured"] == 0
assert payload["files"] == []


def test_capture_marks_cap_skips_as_truncated(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setattr(FileTracker, "_MAX_CAPTURE_FILE_BYTES", 4)
tracker = FileTracker(tmp_path)
tracker.take_baseline()

(tmp_path / "large.pdf").write_bytes(b"12345")
payload = tracker.flush_changes()["capture"]

assert payload["files_eligible"] == 1
assert payload["files_captured"] == 0
assert payload["files_skipped"] == 1
assert payload["truncated"] is True


def test_per_file_diff_cap_emits_a_placeholder(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
Expand Down
13 changes: 11 additions & 2 deletions hud/environment/tests/test_file_tracking.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
from __future__ import annotations

import asyncio
import base64
from typing import TYPE_CHECKING, Any

from hud.environment.file_tracker import FileTracker
from hud.environment.file_tracking import serve_file_tracking
from hud.environment.file_tracker import FileTracker, serve_file_tracking
from hud.environment.utils import read_frame, send_frame

if TYPE_CHECKING:
Expand Down Expand Up @@ -59,6 +59,15 @@ async def test_diff_snapshot_advance_roundtrip(tmp_path: Path) -> None:
(tmp_path / "b.txt").write_text("z\n")
await _call(reader, writer, "advance")
assert (await _call(reader, writer, "diff"))["files_changed"] == 0

# flush() returns the trailing diff plus bounded changed deliverables.
(tmp_path / "report.xlsx").write_bytes(b"spreadsheet")
flush = await _call(reader, writer, "flush")
assert flush["diff"]["files_changed"] == 1
capture = flush["capture"]
assert capture["files_captured"] == 1
assert capture["files"][0]["path"] == "report.xlsx"
assert base64.b64decode(capture["files"][0]["file"]["data"]) == b"spreadsheet"
finally:
writer.close()
await writer.wait_closed()
Expand Down
3 changes: 1 addition & 2 deletions hud/environment/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,7 @@ async def start(self) -> None:

async def _start_file_tracking(self) -> None:
"""Take the baseline snapshot and bind the filetracking/1 server."""
from .file_tracker import FileTracker
from .file_tracking import serve_file_tracking
from .file_tracker import FileTracker, serve_file_tracking

tracker = FileTracker(self.root)
# The baseline walk is CPU-bound; keep it off the event loop.
Expand Down
Loading
Loading