fix(webui): assign readable session handles

This commit is contained in:
chengyongru
2026-08-19 01:15:56 +08:00
committed by chengyongru
parent 251a1ccd40
commit 9e046815bc
20 changed files with 637 additions and 123 deletions
@@ -48,7 +48,7 @@ from nanobot.security.workspace_access import WORKSPACE_SCOPE_METADATA_KEY
from nanobot.session import webui_turns as wth
from nanobot.session.manager import SessionManager
from nanobot.session.model_selection import SESSION_MODEL_PRESET_METADATA_KEY
from nanobot.session.session_handles import session_handle_for_key
from nanobot.session.session_handles import session_handle_for_name
from nanobot.webui.gateway_services import GatewayServices, build_gateway_services
from nanobot.webui.http_utils import (
http_error as _http_error,
@@ -2027,7 +2027,7 @@ async def test_send_projects_external_user_input_to_existing_wire_event() -> Non
event=UserInputEvent(
content="hello from another session",
created_at_ms=1234,
provenance={"name": "mira-deadbeef00"},
provenance={"name": "luma"},
),
)
)
@@ -2039,7 +2039,7 @@ async def test_send_projects_external_user_input_to_existing_wire_event() -> Non
"text": "hello from another session",
"created_at_ms": 1234,
"starts_turn": False,
"provenance": {"name": "mira-deadbeef00"},
"provenance": {"name": "luma"},
}
@@ -4982,6 +4982,14 @@ def test_sessions_list_includes_active_run_started_at(monkeypatch) -> None:
},
]
monkeypatch.setattr(ws_http_module, "list_webui_sessions", lambda _session_manager: sessions)
handle = session_handle_for_name("websocket:chat-1", "luma")
monkeypatch.setattr(
ws_http_module,
"SessionHandleResolver",
lambda _session_manager: SimpleNamespace(
list_all_by_key=lambda: {handle.session_key: handle}
),
)
channel = WebSocketChannel(
{"enabled": True, "allowFrom": ["*"]},
bus,
@@ -5011,7 +5019,7 @@ def test_sessions_list_includes_active_run_started_at(monkeypatch) -> None:
"preview": "work",
"model_preset": "fast",
"run_started_at": 1_700_000_000.0,
"handle": session_handle_for_key("websocket:chat-1").public_payload(),
"handle": handle.public_payload(),
}
]
@@ -22,7 +22,7 @@ from nanobot.channels.websocket.runtime import (
from nanobot.runtime_context import RUNTIME_CONTEXT_INPUT_META
from nanobot.session import webui_turns as wth
from nanobot.session.manager import SessionManager
from nanobot.session.session_handles import session_handle_for_key
from nanobot.session.session_handles import SessionHandleResolver
from nanobot.webui.gateway_services import build_gateway_services
@@ -258,8 +258,10 @@ async def test_webui_message_forwards_verified_session_mentions(tmp_path) -> Non
channel._handle_message.assert_awaited_once()
metadata = channel._handle_message.call_args.kwargs["metadata"]
handle = SessionHandleResolver(manager).handle_for_session("websocket:pricing")
assert handle is not None
assert metadata["session_mentions"] == [{
**session_handle_for_key("websocket:pricing").public_payload(),
**handle.public_payload(),
"session_key": "websocket:pricing",
"title": "Pricing",
}]
@@ -23,7 +23,7 @@ from nanobot.optional_features import InstallResult
from nanobot.security.workspace_access import WORKSPACE_SCOPE_METADATA_KEY
from nanobot.session.keys import UNIFIED_SESSION_KEY
from nanobot.session.manager import Session, SessionManager
from nanobot.session.session_handles import session_handle_for_key
from nanobot.session.session_handles import SessionHandleResolver
from nanobot.triggers.local_store import LocalTriggerStore
from nanobot.webui.gateway_services import GatewayServices, build_gateway_services
@@ -2213,10 +2213,6 @@ async def test_sessions_list_only_returns_websocket_sessions_by_default(
}
sm.save(scoped)
def fail_metadata_read(_key: str) -> None:
raise AssertionError("the session list must use its own index metadata")
monkeypatch.setattr(sm, "read_session_metadata", fail_metadata_read)
channel = _ch(bus, session_manager=sm, workspace_path=tmp_path, port=29906)
server_task = asyncio.create_task(channel.start())
try:
@@ -2233,12 +2229,16 @@ async def test_sessions_list_only_returns_websocket_sessions_by_default(
# Slack / Lark rows would be non-resumable from the browser.
assert keys == {"websocket:alpha", "websocket:beta"}
rows = {row["key"]: row for row in sessions}
assert rows["websocket:alpha"]["handle"] == session_handle_for_key(
handles = {
handle.session_key: handle
for handle in SessionHandleResolver(sm).list_all()
}
assert rows["websocket:alpha"]["handle"] == handles[
"websocket:alpha"
).public_payload()
assert rows["websocket:beta"]["handle"] == session_handle_for_key(
].public_payload()
assert rows["websocket:beta"]["handle"] == handles[
"websocket:beta"
).public_payload()
].public_payload()
assert rows["websocket:beta"]["workspace_scope"]["project_path"] == str(
project.resolve()
)