fix(copilot): make chat history non-interfering (#869)

* Add basic personalizatoin

* Make chat history non-interfering

* Always personalize
This commit is contained in:
Siddharth Ganesan
2025-08-04 18:25:43 -07:00
committed by GitHub
parent b613010a26
commit 6ab9fa76a1
3 changed files with 71 additions and 29 deletions

View File

@@ -244,7 +244,7 @@ export async function POST(req: NextRequest) {
stream: stream,
streamToolCalls: true,
mode: mode,
...(createNewChat && session?.user?.name && { userName: session.user.name }),
...(session?.user?.name && { userName: session.user.name }),
}),
})

View File

@@ -90,7 +90,12 @@ export function Panel() {
// Load chats for the current workflow - let the store handle caching
if (activeWorkflowId) {
await loadChats(forceRefresh)
validateCurrentChat()
// Only validate current chat if we're not actively streaming
// This prevents clearing the current conversation during a stream
if (!isSendingMessage) {
validateCurrentChat()
}
// Mark this workflow as loaded for the legacy ref
lastLoadedWorkflowRef.current = activeWorkflowId
@@ -106,6 +111,7 @@ export function Panel() {
loadChats,
validateCurrentChat,
isLoadingChats,
isSendingMessage,
]
)
@@ -121,9 +127,10 @@ export function Panel() {
// Open dropdown immediately for better UX
setIsHistoryDropdownOpen(open)
// If opening, ensure data is loaded but don't force refresh unless needed
if (open && activeWorkflowId) {
// Only load if we don't have fresh chats for this workflow
// If opening and there's an active stream, don't do any data loading at all
// Just show what's already loaded to avoid any interference
if (open && activeWorkflowId && !isSendingMessage) {
// Only load if we don't have fresh chats for this workflow AND we're not streaming
if (!areChatsFresh(activeWorkflowId)) {
// Don't await - let it load in background while dropdown is already open
ensureCopilotDataLoaded(false).catch((error) => {
@@ -131,8 +138,13 @@ export function Panel() {
})
}
}
// If streaming, just log that we're showing cached data
if (open && isSendingMessage) {
console.log('Chat history opened during stream - showing cached data only')
}
},
[ensureCopilotDataLoaded, activeWorkflowId, areChatsFresh]
[ensureCopilotDataLoaded, activeWorkflowId, areChatsFresh, isSendingMessage]
)
// Group chats by day
@@ -412,7 +424,11 @@ export function Panel() {
<div
key={chat.id}
onClick={() => {
selectChat(chat)
// Only call selectChat if it's a different chat
// This prevents aborting streams when clicking the currently active chat
if (currentChat?.id !== chat.id) {
selectChat(chat)
}
setIsHistoryDropdownOpen(false)
}}
className={`group mx-1 flex h-8 cursor-pointer items-center rounded-lg px-2 py-1.5 text-left transition-colors ${

View File

@@ -1597,13 +1597,30 @@ export const useCopilotStore = create<CopilotStore>()(
(chat: CopilotChat) => chat.id === currentChat.id
)
if (updatedCurrentChat) {
set({
currentChat: updatedCurrentChat,
messages: ensureToolCallDisplayNames(updatedCurrentChat.messages || []),
})
logger.info(
`Preserved current chat selection: ${updatedCurrentChat.title || 'Untitled'} (${updatedCurrentChat.messages?.length || 0} messages)`
)
const { isSendingMessage } = get()
// If we're currently streaming, preserve the current messages state
// to avoid overwriting streaming content with stale database state
if (isSendingMessage) {
set({
currentChat: {
...updatedCurrentChat,
messages: get().messages, // Preserve current streaming messages
},
})
logger.info(
`Preserved current chat and streaming messages during active stream: ${updatedCurrentChat.title || 'Untitled'}`
)
} else {
// Safe to update messages when not streaming
set({
currentChat: updatedCurrentChat,
messages: ensureToolCallDisplayNames(updatedCurrentChat.messages || []),
})
logger.info(
`Updated current chat with latest database state: ${updatedCurrentChat.title || 'Untitled'} (${updatedCurrentChat.messages?.length || 0} messages)`
)
}
// Load checkpoints for the preserved chat
try {
@@ -1614,22 +1631,31 @@ export const useCopilotStore = create<CopilotStore>()(
}
} else {
// Only auto-select most recent chat if no current chat or current chat is stale
const mostRecentChat = data.chats[0]
set({
currentChat: mostRecentChat,
messages: ensureToolCallDisplayNames(mostRecentChat.messages || []),
})
logger.info(
`Auto-selected most recent chat for workflow ${workflowId}: ${mostRecentChat.title || 'Untitled'}`
)
// But don't auto-select during streaming to avoid disrupting the conversation
const { isSendingMessage } = get()
// Load checkpoints for the auto-selected chat
try {
await get().loadMessageCheckpoints(mostRecentChat.id)
} catch (checkpointError) {
logger.error(
'Failed to load checkpoints for auto-selected chat:',
checkpointError
if (!isSendingMessage) {
const mostRecentChat = data.chats[0]
set({
currentChat: mostRecentChat,
messages: ensureToolCallDisplayNames(mostRecentChat.messages || []),
})
logger.info(
`Auto-selected most recent chat for workflow ${workflowId}: ${mostRecentChat.title || 'Untitled'}`
)
// Load checkpoints for the auto-selected chat
try {
await get().loadMessageCheckpoints(mostRecentChat.id)
} catch (checkpointError) {
logger.error(
'Failed to load checkpoints for auto-selected chat:',
checkpointError
)
}
} else {
logger.info(
`Skipped auto-selecting chat during active stream for workflow ${workflowId}`
)
}
}