refactor(session): simplify cross-session flow

This commit is contained in:
Xubin Ren
2026-08-04 12:14:51 +08:00
parent 62d34b5eb7
commit d8aeb0eb2c
12 changed files with 282 additions and 574 deletions
+25 -60
View File
@@ -18,11 +18,22 @@ def _save_session(manager: SessionManager, key: str, title: str) -> None:
manager.save(session)
def test_normalize_session_mentions_keeps_existing_distinct_targets(tmp_path) -> None:
def test_normalize_session_mentions_keeps_only_authorized_distinct_targets(
tmp_path,
monkeypatch,
) -> None:
manager = SessionManager(tmp_path)
_save_session(manager, "websocket:current", "Current")
_save_session(manager, "websocket:pricing", "Authoritative title")
_save_session(manager, "websocket:other", "Other")
_save_session(manager, "websocket:street", "Straße")
_save_session(manager, "websocket:upper", "STRASSE")
_save_session(manager, "telegram:private", "Private")
monkeypatch.setattr(
manager,
"list_sessions",
lambda: (_ for _ in ()).throw(AssertionError("full scan")),
)
mentions = WebuiSessionAccess(manager).normalize_mentions(
[
@@ -36,15 +47,22 @@ def test_normalize_session_mentions_keeps_existing_distinct_targets(tmp_path) ->
{"name": "current", "session_key": "websocket:current"},
{"name": "bad name", "session_key": "websocket:pricing"},
{"name": "missing", "session_key": "websocket:missing"},
{"name": "Straße", "session_key": "websocket:street"},
{"name": "STRASSE", "session_key": "websocket:upper"},
{"name": "private", "session_key": "telegram:private"},
],
SessionAccessScope("websocket:current", "websocket:"),
SessionAccessScope("websocket:current"),
)
assert mentions == [{
"name": "pricing",
"session_key": "websocket:pricing",
"title": "Authoritative title",
}]
assert mentions == [
{
"name": "pricing",
"session_key": "websocket:pricing",
"title": "Authoritative title",
},
{"name": "Straße", "session_key": "websocket:street", "title": "Straße"},
{"name": "STRASSE", "session_key": "websocket:upper", "title": "STRASSE"},
]
def test_session_mention_context_treats_titles_as_data() -> None:
@@ -62,58 +80,6 @@ def test_session_mention_context_treats_titles_as_data() -> None:
assert json.loads(block.content.splitlines()[2])[0]["session_key"] == "websocket:history"
def test_normalize_session_mentions_matches_browser_lowercase_rules(tmp_path) -> None:
manager = SessionManager(tmp_path)
_save_session(manager, "websocket:street", "Straße")
_save_session(manager, "websocket:upper", "STRASSE")
mentions = WebuiSessionAccess(manager).normalize_mentions(
[
{"name": "Straße", "session_key": "websocket:street"},
{"name": "STRASSE", "session_key": "websocket:upper"},
],
SessionAccessScope("websocket:current", "websocket:"),
)
assert [mention["session_key"] for mention in mentions] == [
"websocket:street",
"websocket:upper",
]
def test_normalize_session_mentions_rejects_other_session_scopes(tmp_path) -> None:
manager = SessionManager(tmp_path)
_save_session(manager, "websocket:visible", "Visible")
_save_session(manager, "telegram:private", "Private")
mentions = WebuiSessionAccess(manager).normalize_mentions(
[
{"name": "visible", "session_key": "websocket:visible"},
{"name": "private", "session_key": "telegram:private"},
],
SessionAccessScope("websocket:current", "websocket:"),
)
assert [mention["session_key"] for mention in mentions] == ["websocket:visible"]
def test_normalize_session_mentions_uses_exact_metadata_reads(tmp_path, monkeypatch) -> None:
manager = SessionManager(tmp_path)
_save_session(manager, "websocket:visible", "Visible")
monkeypatch.setattr(
manager,
"list_sessions",
lambda: (_ for _ in ()).throw(AssertionError("full scan")),
)
mentions = WebuiSessionAccess(manager).normalize_mentions(
[{"name": "visible", "session_key": "websocket:visible"}],
SessionAccessScope("websocket:current", "websocket:"),
)
assert [mention["session_key"] for mention in mentions] == ["websocket:visible"]
def test_restricted_scope_rejects_sessions_from_other_projects(tmp_path) -> None:
manager = SessionManager(tmp_path)
project_a = tmp_path / "a"
@@ -133,7 +99,6 @@ def test_restricted_scope_rejects_sessions_from_other_projects(tmp_path) -> None
access = WebuiSessionAccess(manager)
scope = SessionAccessScope(
"websocket:current",
"websocket:",
project_path=project_a,
restrict_to_workspace=True,
)