fix(frontend/builder): always clear messages on flowID change to keep action state consistent

When navigating back to a cached session, appliedActionKeys was reset to empty
but messages were preserved. This caused previously applied actions to reappear
as unapplied in the UI, allowing them to be re-applied and creating duplicate
undo entries. Clearing messages unconditionally on navigation ensures the
displayed action buttons always reflect the actual applied state.
This commit is contained in:
majdyz
2026-04-10 02:03:56 +07:00
parent 31cb6a2f58
commit d49f2518a2
2 changed files with 38 additions and 5 deletions

View File

@@ -359,6 +359,39 @@ describe("useBuilderChatPanel flowID reset", () => {
expect(result.current.sessionError).toBe(false);
});
it("always clears messages on flowID change even when a cached session exists (prevents applied/unapplied mismatch)", async () => {
mockPostV2CreateSession.mockResolvedValue({
status: 200,
data: { id: "sess-cached" },
});
mockFlowID = "flow-1";
const { result, rerender } = renderHook(() => useBuilderChatPanel());
await openAndFlush(() => result.current.handleToggle());
expect(result.current.sessionId).toBe("sess-cached");
// Simulate chat messages from the first session
mockChatMessages = [
{
id: "msg-1",
role: "assistant",
parts: [{ type: "text", text: "Hello from session 1" }],
},
];
mockSetMessages.mockClear();
// Navigate away and back to the same graph — cached session should be restored
// but messages must be cleared to stay in sync with the reset appliedActionKeys
mockFlowID = "flow-2";
rerender();
mockFlowID = "flow-1";
rerender();
// setMessages([]) must be called unconditionally regardless of cached session
expect(mockSetMessages).toHaveBeenCalledWith([]);
});
});
describe("useBuilderChatPanel apply does not trigger cache refetch", () => {

View File

@@ -122,8 +122,10 @@ export function useBuilderChatPanel({
const setEdges = useEdgeStore((s) => s.setEdges);
// When the user navigates to a different graph: restore the cached session for
// that graph (preserving conversation history) and reset per-session UI state.
// Messages are only cleared when there is no prior session for the new graph.
// that graph (preserving the backend session) and reset all per-session UI state.
// Messages are always cleared on navigation — appliedActionKeys cannot be persisted
// so restoring messages while resetting action state would show previously applied
// actions as unapplied, allowing them to be re-applied and creating duplicate undo entries.
useEffect(() => {
const cachedSessionId = flowID
? (graphSessionCache.get(flowID) ?? null)
@@ -136,9 +138,7 @@ export function useBuilderChatPanel({
isCreatingSessionRef.current = false;
processedToolCallsRef.current = new Set();
hasSentSeedMessageRef.current = false;
if (!cachedSessionId) {
setMessages([]);
}
setMessages([]);
// setMessages is a stable function from useChat; excluding from deps is safe.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [flowID]);