fix(ChatTrigger Node): Keep session ID when load previous session is on (#22150)

This commit is contained in:
Michael Drury 2025-11-24 08:41:20 +00:00 committed by GitHub
parent 31715c8a6e
commit ca84de8d56
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 110 additions and 8 deletions

View File

@ -311,7 +311,53 @@ describe('ChatPlugin', () => {
expect(sessionId).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
expect(chatStore.messages.value).toHaveLength(0);
expect(chatStore.currentSessionId.value).toBeNull();
expect(chatStore.currentSessionId.value).toBe(sessionId);
// eslint-disable-next-line @typescript-eslint/unbound-method
expect(window.localStorage.setItem).toHaveBeenCalledWith(localStorageSessionIdKey, sessionId);
});
it('should preserve manually set sessionId when no messages exist', async () => {
const manualSessionId = '5123f177-df4b-4c0b-b2a1-645432140313';
(window.localStorage.getItem as ReturnType<typeof vi.fn>).mockReturnValueOnce(
manualSessionId,
);
vi.mocked(api.loadPreviousSession).mockResolvedValueOnce({ data: [] });
const sessionId = await chatStore.loadPreviousSession?.();
expect(sessionId).toBe(manualSessionId);
expect(chatStore.currentSessionId.value).toBe(manualSessionId);
expect(chatStore.messages.value).toHaveLength(0);
// localStorage.setItem should not be called since sessionId already existed
// eslint-disable-next-line @typescript-eslint/unbound-method
expect(window.localStorage.setItem).not.toHaveBeenCalled();
});
it('should preserve manually set sessionId when messages exist', async () => {
const manualSessionId = '5123f177-df4b-4c0b-b2a1-645432140313';
(window.localStorage.getItem as ReturnType<typeof vi.fn>).mockReturnValueOnce(
manualSessionId,
);
const mockMessages: LoadPreviousSessionResponse = {
data: [
{
id: ['user', 'uuid-1'],
kwargs: { content: 'Hello', additional_kwargs: {} },
lc: 1,
type: 'HumanMessage',
},
],
};
vi.mocked(api.loadPreviousSession).mockResolvedValueOnce(mockMessages);
const sessionId = await chatStore.loadPreviousSession?.();
expect(sessionId).toBe(manualSessionId);
expect(chatStore.currentSessionId.value).toBe(manualSessionId);
expect(chatStore.messages.value).toHaveLength(1);
// localStorage.setItem should not be called since sessionId already existed
// eslint-disable-next-line @typescript-eslint/unbound-method
expect(window.localStorage.setItem).not.toHaveBeenCalled();
});
it('should skip loading if loadPreviousSession is false', async () => {
@ -324,7 +370,9 @@ describe('ChatPlugin', () => {
expect(api.loadPreviousSession).not.toHaveBeenCalled();
});
it('should start a new session', async () => {
it('should start a new session when localStorage is empty', async () => {
(window.localStorage.getItem as ReturnType<typeof vi.fn>).mockReturnValueOnce(null);
await chatStore.startNewSession?.();
expect(chatStore.currentSessionId.value).toMatch(
@ -336,6 +384,45 @@ describe('ChatPlugin', () => {
chatStore.currentSessionId.value,
);
});
it('should preserve existing sessionId when starting new session with loadPreviousSession enabled', async () => {
const existingSessionId = '5123f177-df4b-4c0b-b2a1-645432140313';
mockOptions.loadPreviousSession = true;
chatStore = setupChatStore(mockOptions);
(window.localStorage.getItem as ReturnType<typeof vi.fn>).mockReturnValueOnce(
existingSessionId,
);
await chatStore.startNewSession?.();
expect(chatStore.currentSessionId.value).toBe(existingSessionId);
// localStorage.setItem should not be called since sessionId already exists
// eslint-disable-next-line @typescript-eslint/unbound-method
expect(window.localStorage.setItem).not.toHaveBeenCalled();
});
it('should generate new sessionId when loadPreviousSession is disabled', async () => {
const existingSessionId = '5123f177-df4b-4c0b-b2a1-645432140313';
mockOptions.loadPreviousSession = false;
chatStore = setupChatStore(mockOptions);
(window.localStorage.getItem as ReturnType<typeof vi.fn>).mockReturnValueOnce(
existingSessionId,
);
await chatStore.startNewSession?.();
// Should generate new UUID, not preserve existing one
expect(chatStore.currentSessionId.value).not.toBe(existingSessionId);
expect(chatStore.currentSessionId.value).toMatch(
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
);
// localStorage.setItem should be called with new sessionId
// eslint-disable-next-line @typescript-eslint/unbound-method
expect(window.localStorage.setItem).toHaveBeenCalledWith(
localStorageSessionIdKey,
chatStore.currentSessionId.value,
);
});
});
describe('initial messages', () => {

View File

@ -259,7 +259,14 @@ export const ChatPlugin: Plugin<ChatOptions> = {
return;
}
const sessionId = localStorage.getItem(localStorageSessionIdKey) ?? uuidv4();
const existingSessionId = localStorage.getItem(localStorageSessionIdKey);
const sessionId = existingSessionId ?? uuidv4();
// Save to localStorage if it was newly generated
if (!existingSessionId) {
localStorage.setItem(localStorageSessionIdKey, sessionId);
}
const previousMessagesResponse = await api.loadPreviousSession(sessionId, options);
messages.value = (previousMessagesResponse?.data || []).map((message, index) => ({
@ -268,18 +275,26 @@ export const ChatPlugin: Plugin<ChatOptions> = {
sender: message.id.includes('HumanMessage') ? 'user' : 'bot',
}));
if (messages.value.length) {
currentSessionId.value = sessionId;
}
// Always set currentSessionId to preserve manually set sessionIds
currentSessionId.value = sessionId;
return sessionId;
}
// eslint-disable-next-line @typescript-eslint/require-await
async function startNewSession() {
currentSessionId.value = uuidv4();
const existingSessionId = localStorage.getItem(localStorageSessionIdKey);
localStorage.setItem(localStorageSessionIdKey, currentSessionId.value);
// Only preserve existing sessionId if loadPreviousSession is enabled
// When loadPreviousSession is false, always generate a new session
if (existingSessionId && options.loadPreviousSession) {
// Preserve existing sessionId (e.g., manually set by user)
currentSessionId.value = existingSessionId;
} else {
// Generate new UUID and save to localStorage
currentSessionId.value = uuidv4();
localStorage.setItem(localStorageSessionIdKey, currentSessionId.value);
}
}
const chatStore = {