Port from PrimeIntellect-ai/prime-agent#628: resolve symlink aliases in ACP cwd comparison

macOS reports editor workspaces as /var/... while sessions are stored
under /private/var/... (same for /tmp vs /private/tmp), so the lexical
normpath comparison in _normalize_cwd_for_compare treated them as
different directories and ACP history filters silently dropped a
workspace's own sessions.

Canonicalize with os.path.realpath; nonexistent paths (e.g.
WSL-translated Windows drives on a Linux host) keep the previous
lexical behavior since realpath(strict=False) is lexical for them.
This commit is contained in:
Teknium 2026-08-06 17:21:31 -07:00
parent 0957277f2f
commit 4d8181fd84
No known key found for this signature in database
2 changed files with 60 additions and 1 deletions

View File

@ -56,7 +56,18 @@ def _normalize_cwd_for_compare(cwd: str | None) -> str:
elif re.match(r"^/mnt/[A-Za-z]/", expanded):
expanded = f"/mnt/{expanded[5].lower()}/{expanded[7:]}"
return os.path.normpath(expanded)
# Resolve symlink aliases so equivalent spellings of the same directory
# compare equal — macOS reports editor workspaces as ``/var/...`` while
# sessions get stored under ``/private/var/...`` (and ``/tmp`` vs
# ``/private/tmp``), which made ACP history filters silently drop a
# workspace's own sessions. ``os.path.realpath`` is lexical for missing
# paths (strict=False), so cwds that don't exist on this host — e.g.
# WSL-translated Windows drives — keep the previous normpath behavior.
# Ported from PrimeIntellect-ai/prime-agent#628.
try:
return os.path.realpath(expanded)
except OSError:
return os.path.normpath(expanded)
def _build_session_title(title: Any, preview: Any, cwd: str | None) -> str:

View File

@ -158,6 +158,54 @@ class TestWslCwdTranslation:
# ---------------------------------------------------------------------------
class TestSymlinkAliasNormalization:
"""Ported from PrimeIntellect-ai/prime-agent#628 — symlink aliases of the
same directory (macOS ``/var`` vs ``/private/var``, ``/tmp`` vs
``/private/tmp``) must compare equal, or ACP history filters silently drop
a workspace's own sessions."""
def test_symlink_alias_compares_equal(self, tmp_path):
real = tmp_path / "real"
real.mkdir()
alias = tmp_path / "alias"
alias.symlink_to(real)
assert acp_session._normalize_cwd_for_compare(
str(alias)
) == acp_session._normalize_cwd_for_compare(str(real))
def test_distinct_dirs_still_compare_different(self, tmp_path):
a = tmp_path / "a"
b = tmp_path / "b"
a.mkdir()
b.mkdir()
assert acp_session._normalize_cwd_for_compare(
str(a)
) != acp_session._normalize_cwd_for_compare(str(b))
def test_missing_path_keeps_lexical_normalization(self):
# realpath(strict=False) is lexical for nonexistent paths, so cwds
# that don't exist on this host (e.g. WSL-translated drives) behave
# exactly as the old normpath comparison did.
assert acp_session._normalize_cwd_for_compare(
"/nonexistent-hermes-test/x/../y"
) == "/nonexistent-hermes-test/y"
def test_list_sessions_matches_symlink_alias_cwd(self, manager, tmp_path):
real = tmp_path / "proj"
real.mkdir()
alias = tmp_path / "link"
alias.symlink_to(real)
state = manager.create_session(cwd=str(real))
state.history.append({"role": "user", "content": "hello"})
listed = manager.list_sessions(cwd=str(alias))
assert [s["session_id"] for s in listed] == [state.session_id]
# ---------------------------------------------------------------------------
# list / cleanup
# ---------------------------------------------------------------------------
class TestListAndCleanup:
def test_list_sessions_empty(self, manager):
assert manager.list_sessions() == []