mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-09-05 18:51:53 +03:00
fix(tui): preserve draft scope until first message
This commit is contained in:
@@ -1217,7 +1217,6 @@ class WebSocketChannel(BaseChannel):
|
||||
if session_mentions:
|
||||
metadata["session_mentions"] = session_mentions
|
||||
metadata[WORKSPACE_SCOPE_METADATA_KEY] = scope.metadata()
|
||||
self._workspaces.persist_scope(cid, scope)
|
||||
is_webui = metadata.get("webui") is True
|
||||
queued_owner = None
|
||||
if is_webui and not is_user_shell and builtin_command_starts_agent_turn(content):
|
||||
@@ -1272,6 +1271,7 @@ class WebSocketChannel(BaseChannel):
|
||||
else False
|
||||
),
|
||||
)
|
||||
self._workspaces.persist_scope(cid, scope)
|
||||
accepted = True
|
||||
finally:
|
||||
if not accepted and queued_owner is not None:
|
||||
|
||||
@@ -1563,6 +1563,49 @@ async def test_new_chat_without_message_does_not_create_session(
|
||||
assert sessions.list_sessions() == []
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_failed_first_message_does_not_persist_draft_session(
|
||||
bus: MagicMock,
|
||||
tmp_path,
|
||||
) -> None:
|
||||
sessions = SessionManager(tmp_path / "sessions")
|
||||
channel = WebSocketChannel(
|
||||
{"enabled": True, "allowFrom": ["*"], "host": "127.0.0.1"},
|
||||
bus,
|
||||
gateway=_basic_handler(bus, session_manager=sessions, workspace_path=tmp_path),
|
||||
)
|
||||
conn = AsyncMock()
|
||||
conn.remote_address = ("127.0.0.1", 50123)
|
||||
|
||||
await channel._dispatch_envelope(
|
||||
conn,
|
||||
"tui-client",
|
||||
{
|
||||
"type": "new_chat",
|
||||
"workspace_scope": {
|
||||
"project_path": str(tmp_path),
|
||||
"access_mode": "full",
|
||||
},
|
||||
},
|
||||
)
|
||||
chat_id = json.loads(conn.send.await_args_list[0].args[0])["chat_id"]
|
||||
bus.publish_inbound.side_effect = RuntimeError("queue unavailable")
|
||||
|
||||
with pytest.raises(RuntimeError, match="queue unavailable"):
|
||||
await channel._dispatch_envelope(
|
||||
conn,
|
||||
"tui-client",
|
||||
{
|
||||
"type": "message",
|
||||
"chat_id": chat_id,
|
||||
"content": "hello",
|
||||
"webui": True,
|
||||
},
|
||||
)
|
||||
|
||||
assert sessions.list_sessions() == []
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_workspace_scope_change_invalidates_other_attached_clients(
|
||||
bus: MagicMock,
|
||||
|
||||
@@ -336,12 +336,12 @@ class WebUIWorkspaceController:
|
||||
|
||||
def persist_scope(self, chat_id: str, scope: WorkspaceScope) -> None:
|
||||
session_key = f"websocket:{chat_id}"
|
||||
self._draft_scopes.pop(session_key, None)
|
||||
if self._sessions is not None:
|
||||
session = self._sessions.get_or_create(session_key)
|
||||
session.metadata["webui"] = True
|
||||
session.metadata[WORKSPACE_SCOPE_METADATA_KEY] = scope.metadata()
|
||||
self._sessions.save(session)
|
||||
self._draft_scopes.pop(session_key, None)
|
||||
|
||||
def stage_scope(self, chat_id: str, scope: WorkspaceScope) -> None:
|
||||
"""Keep a new chat's scope transient until its first accepted message."""
|
||||
|
||||
Reference in New Issue
Block a user