mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-09-04 02:01:48 +03:00
fix(webui): delete unpersisted pane sessions (#5624)
Co-authored-by: chengyongru <chengyongru.ai@gmail.com>
This commit is contained in:
@@ -257,11 +257,14 @@ export function useSessions(): {
|
||||
|
||||
const deleteChat = useCallback(
|
||||
async (key: string, options?: { deleteAutomations?: boolean }) => {
|
||||
const optimistic = optimisticKeysRef.current.has(key);
|
||||
const result = await apiDeleteSession(client, key, options);
|
||||
if (!result.deleted) return result;
|
||||
if (result.blocked_by_automations || (!result.deleted && !optimistic)) return result;
|
||||
optimisticKeysRef.current.delete(key);
|
||||
setSessions((prev) => prev.filter((s) => s.key !== key));
|
||||
return result;
|
||||
// The gateway may have restarted and forgotten an unpersisted chat's
|
||||
// draft scope, but removing that optimistic session is still a deletion.
|
||||
return result.deleted ? result : { ...result, deleted: true };
|
||||
},
|
||||
[client],
|
||||
);
|
||||
|
||||
@@ -124,6 +124,59 @@ describe("useSessions", () => {
|
||||
expect(result.current.sessions.map((s) => s.key)).toEqual(["websocket:chat-b"]);
|
||||
});
|
||||
|
||||
it("removes an optimistic chat when the gateway no longer has its draft", async () => {
|
||||
vi.mocked(api.listSessions).mockResolvedValue([]);
|
||||
vi.mocked(api.deleteSession).mockResolvedValue({ deleted: false });
|
||||
const client = fakeClient();
|
||||
client.newChat.mockResolvedValue("chat-empty");
|
||||
|
||||
const { result } = renderHook(() => useSessions(), {
|
||||
wrapper: wrap(client),
|
||||
});
|
||||
|
||||
await waitFor(() => expect(result.current.loading).toBe(false));
|
||||
await act(async () => {
|
||||
await result.current.createChat();
|
||||
});
|
||||
expect(result.current.sessions.map((s) => s.key)).toEqual(["websocket:chat-empty"]);
|
||||
|
||||
let deleteResult: Awaited<ReturnType<typeof result.current.deleteChat>> | undefined;
|
||||
await act(async () => {
|
||||
deleteResult = await result.current.deleteChat("websocket:chat-empty");
|
||||
});
|
||||
|
||||
expect(deleteResult?.deleted).toBe(true);
|
||||
expect(result.current.sessions).toEqual([]);
|
||||
});
|
||||
|
||||
it("keeps an optimistic chat when delete is blocked by bound automations", async () => {
|
||||
vi.mocked(api.listSessions).mockResolvedValue([]);
|
||||
vi.mocked(api.deleteSession).mockResolvedValue({
|
||||
deleted: false,
|
||||
blocked_by_automations: true,
|
||||
automations: [],
|
||||
});
|
||||
const client = fakeClient();
|
||||
client.newChat.mockResolvedValue("chat-empty");
|
||||
|
||||
const { result } = renderHook(() => useSessions(), {
|
||||
wrapper: wrap(client),
|
||||
});
|
||||
|
||||
await waitFor(() => expect(result.current.loading).toBe(false));
|
||||
await act(async () => {
|
||||
await result.current.createChat();
|
||||
});
|
||||
|
||||
let deleteResult: Awaited<ReturnType<typeof result.current.deleteChat>> | undefined;
|
||||
await act(async () => {
|
||||
deleteResult = await result.current.deleteChat("websocket:chat-empty");
|
||||
});
|
||||
|
||||
expect(deleteResult?.blocked_by_automations).toBe(true);
|
||||
expect(result.current.sessions.map((s) => s.key)).toEqual(["websocket:chat-empty"]);
|
||||
});
|
||||
|
||||
it("keeps a session when delete is blocked by bound automations", async () => {
|
||||
vi.mocked(api.listSessions).mockResolvedValue([
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user