fix(status): render the session profile home

Let the shared status field builder accept an explicit owning home and have the
multiplexed TUI/Desktop session.status path pass its session profile_home.
Unscoped CLI/gateway callers keep the historical process-home fallback.

Add focused coverage for a secondary-profile session and for the launch-profile
fallback.

Fixes #124500.
This commit is contained in:
JoaoMarcos44
2026-09-26 19:10:42 -03:00
committed by brooklyn!
parent 7d6da01e98
commit 2a977be999
3 changed files with 81 additions and 1 deletions

View File

@@ -13,6 +13,7 @@ They now all call :func:`build_status_fields`; a surface only adds its own heade
from __future__ import annotations
from datetime import datetime
from pathlib import Path
from typing import Any
STATUS_STAMP = "%Y-%m-%d %H:%M"
@@ -69,6 +70,7 @@ def build_status_fields(
created_fallback: datetime | None = None,
tokens: int | None = None,
agent_running: bool = False,
home: str | Path | None = None,
) -> dict[str, Any]:
"""Common ``/status`` facts, pre-formatted for display.
@@ -76,6 +78,8 @@ def build_status_fields(
(CLI ``self.model``, TUI metadata mirror, gateway's resolved route) and are also what a
surface passes when it has no live agent. ``created`` / ``last_activity`` override the
``meta`` row scan for surfaces whose session store is authoritative (gateway SessionEntry).
``home`` is an explicit owning-profile path for multiplexed surfaces; omitted callers keep
the process/current-profile lookup.
"""
from hermes_constants import display_hermes_home
@@ -89,7 +93,7 @@ def build_status_fields(
row_title = meta.get("title") if title is None else title
return {
"session_id": str(session_id or ""),
"path": display_hermes_home(),
"path": display_hermes_home(Path(home) if home else None),
"title": (row_title or "").strip(),
"model": getattr(agent, "model", None) or model or "",
"provider": getattr(agent, "provider", None) or provider or "",

View File

@@ -0,0 +1,75 @@
"""Profile-owned /status path rendering for multiplexed TUI/Desktop sessions (#124500)."""
import threading
from tui_gateway import server
def _session(profile_home=None):
row = {
"session_key": "status-row",
"history": [],
"history_lock": threading.Lock(),
"running": False,
"agent": None,
"created_at": 1.0,
"last_active": 1.0,
}
if profile_home is not None:
row["profile_home"] = str(profile_home)
return row
def test_session_status_path_uses_owning_profile_home(monkeypatch, tmp_path):
launch_home = tmp_path / "profiles" / "launch"
profile_home = tmp_path / "profiles" / "ember"
launch_home.mkdir(parents=True)
profile_home.mkdir(parents=True)
monkeypatch.setenv("HERMES_HOME", str(launch_home))
class LaunchDB:
def get_session(self, _key):
raise AssertionError("secondary-profile status must not read the launch DB")
class ProfileDB:
def __init__(self, db_path=None):
assert str(db_path) == str(profile_home / "state.db")
def get_session(self, key):
return {"id": key, "title": "owned", "started_at": 1}
def close(self):
pass
server._sessions["status-profile-home"] = _session(profile_home)
monkeypatch.setattr(server, "_get_db", lambda: LaunchDB())
monkeypatch.setattr("hermes_state_registry.acquire", ProfileDB)
try:
resp = server.handle_request(
{"id": "1", "method": "session.status", "params": {"session_id": "status-profile-home"}}
)
output = resp["result"]["output"]
assert f"Path: {profile_home}" in output
assert f"Path: {launch_home}" not in output
finally:
server._sessions.pop("status-profile-home", None)
def test_session_status_path_without_profile_home_keeps_launch_home(monkeypatch, tmp_path):
launch_home = tmp_path / "launch"
launch_home.mkdir()
monkeypatch.setenv("HERMES_HOME", str(launch_home))
class LaunchDB:
def get_session(self, key):
return {"id": key, "title": "launch", "started_at": 1}
server._sessions["status-launch-home"] = _session()
monkeypatch.setattr(server, "_get_db", lambda: LaunchDB())
try:
resp = server.handle_request(
{"id": "1", "method": "session.status", "params": {"session_id": "status-launch-home"}}
)
assert f"Path: {launch_home}" in resp["result"]["output"]
finally:
server._sessions.pop("status-launch-home", None)

View File

@@ -1843,6 +1843,7 @@ def _(rid, params: dict, session: dict) -> dict:
model=mirror.get("model") or getattr(live_agent, "model", None),
provider=mirror.get("provider") or getattr(live_agent, "provider", None),
tokens=_session_usage_snapshot(session).get("total"), agent_running=bool(session.get("running")),
home=session.get("profile_home"),
)
project = _project_info_for_cwd(_display_session_cwd(session))
lines = [