fix: normalize named profile base homes#1689
Conversation
ReviewReading the diff at What the PR does
def _unwrap_profile_home_to_base(home: Path) -> Path:
"""Return the base Hermes home when *home* is already a named profile dir."""
if home.parent.name == 'profiles':
return home.parent.parent
return homeBefore this PR, # (origin/master)
base_override = os.getenv('HERMES_BASE_HOME', '').strip()
if base_override:
return Path(base_override).expanduser() # ← no unwrap, doubled when set to profile-home…which is exactly the gap @nesquena-hermes flagged: "the unwrap logic only runs on the The PR also collapses def _resolve_profile_home_for_name(name: str) -> Path:
if not name or _is_root_profile(name):
return _DEFAULT_HERMES_HOME
if not _PROFILE_ID_RE.fullmatch(name):
return _DEFAULT_HERMES_HOME
return _resolve_named_profile_home(name)This matches @nesquena-hermes's prescription almost exactly: "a shared One small drift note: Tests
The second test is the security-critical one — without the unwrap on VerdictLGTM. The fix is exactly what the umbrella issue asked for, the helper unification is the right shape, and the two regression tests target the precise reproductions the maintainer identified. The dropped |
4daa238
10 PRs (3 surfaces additions, 7 fixes): - nesquena#1644 model picker chip + group count (@bergeouss, closes nesquena#1425) - nesquena#1684 update network failures UX (@Michaelyklam, closes nesquena#1321) - nesquena#1685 Codex spark models (@Michaelyklam, closes nesquena#1680) - nesquena#1689 normalize profile base homes (@Michaelyklam, refs nesquena#749) - nesquena#1693 adaptive title refresh deadlock (@ai-ag2026) - nesquena#1701 normalize update banner URL (@Michaelyklam, closes nesquena#1691) - nesquena#1702 workspace double-click rename (@Michaelyklam, closes nesquena#1698) - nesquena#1703 cache invalidation on auth-store drift (@Michaelyklam, closes nesquena#1699) - nesquena#1704 markdown fence lengths (@Michaelyklam, closes nesquena#1696) - nesquena#1706 multi-image paste fix (@Michaelyklam, closes nesquena#1697) Tests: 4477 → 4503 (+26). Opus: SHIP, 7/7 verification clean. Co-authored-by: Michael Lam <Michaelyklam1@gmail.com> Co-authored-by: ai-ag2026 <noreply@github.com> Co-authored-by: bergeouss <noreply@github.com>
|
Closed by the v0.51.4 release in PR #1707 (merged at 4daa238, deployed to production). Live on production: https://github.com/nesquena/hermes-webui/releases/tag/v0.51.4 🚀 |
Thinking Path
HERMES_BASE_HOME=/base/profiles/foowhile the browser sendshermes_profile=foo._resolve_base_hermes_home()unwrappedHERMES_HOME=/base/profiles/foobut trustedHERMES_BASE_HOMEas already being the base, so later helpers appendedprofiles/fooagain.profiles/foo/profiles/foopath without redesigning the broader profile UX umbrella.What Changed
_unwrap_profile_home_to_base()soHERMES_BASE_HOME=/base/profiles/<name>is normalized to/base, matching the existingHERMES_HOMEprofile-subdir behavior._resolve_profile_home_for_name()and made bothget_active_hermes_home()andget_hermes_home_for_profile()delegate to it.fooresolving to/base/profiles/foo, not/base/profiles/foo/profiles/foo, even when the doubled path exists;api.models._get_profile_home('foo')andget_profile_runtime_env()reading the intended profile home/config;barresolving to the sibling/base/profiles/bar, not the pinnedfoodirectory orfoo/profiles/bar.Why It Matters
A dedicated WebUI process per named profile is a useful isolation deployment shape. Before this fix, that setup could make chat/model startup read a nested empty profile directory and report misleading provider/config failures even though the intended profile was configured correctly. This keeps the runtime path model consistent across active profile, per-request profile, model/session startup, and profile runtime env loading.
Verification
Result:
Full-suite note:
UI media:
Risks / Follow-ups
HERMES_BASE_HOME=/base/profiles/fooas a profile-home input that should be unwrapped to/base; that matches the existingHERMES_HOMEbehavior and keeps non-matching profile cookies on sibling paths.Model Used
AI assisted.
gpt-5.5