Skip to content

Commit 6ab9fa7

Browse files
authored
fix(copilot): make chat history non-interfering (#869)
* Add basic personalizatoin * Make chat history non-interfering * Always personalize
1 parent b613010 commit 6ab9fa7

File tree

3 files changed

+71
-29
lines changed

3 files changed

+71
-29
lines changed

apps/sim/app/api/copilot/chat/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ export async function POST(req: NextRequest) {
244244
stream: stream,
245245
streamToolCalls: true,
246246
mode: mode,
247-
...(createNewChat && session?.user?.name && { userName: session.user.name }),
247+
...(session?.user?.name && { userName: session.user.name }),
248248
}),
249249
})
250250

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/panel.tsx

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,12 @@ export function Panel() {
9090
// Load chats for the current workflow - let the store handle caching
9191
if (activeWorkflowId) {
9292
await loadChats(forceRefresh)
93-
validateCurrentChat()
93+
94+
// Only validate current chat if we're not actively streaming
95+
// This prevents clearing the current conversation during a stream
96+
if (!isSendingMessage) {
97+
validateCurrentChat()
98+
}
9499

95100
// Mark this workflow as loaded for the legacy ref
96101
lastLoadedWorkflowRef.current = activeWorkflowId
@@ -106,6 +111,7 @@ export function Panel() {
106111
loadChats,
107112
validateCurrentChat,
108113
isLoadingChats,
114+
isSendingMessage,
109115
]
110116
)
111117

@@ -121,18 +127,24 @@ export function Panel() {
121127
// Open dropdown immediately for better UX
122128
setIsHistoryDropdownOpen(open)
123129

124-
// If opening, ensure data is loaded but don't force refresh unless needed
125-
if (open && activeWorkflowId) {
126-
// Only load if we don't have fresh chats for this workflow
130+
// If opening and there's an active stream, don't do any data loading at all
131+
// Just show what's already loaded to avoid any interference
132+
if (open && activeWorkflowId && !isSendingMessage) {
133+
// Only load if we don't have fresh chats for this workflow AND we're not streaming
127134
if (!areChatsFresh(activeWorkflowId)) {
128135
// Don't await - let it load in background while dropdown is already open
129136
ensureCopilotDataLoaded(false).catch((error) => {
130137
console.error('Failed to load chat history:', error)
131138
})
132139
}
133140
}
141+
142+
// If streaming, just log that we're showing cached data
143+
if (open && isSendingMessage) {
144+
console.log('Chat history opened during stream - showing cached data only')
145+
}
134146
},
135-
[ensureCopilotDataLoaded, activeWorkflowId, areChatsFresh]
147+
[ensureCopilotDataLoaded, activeWorkflowId, areChatsFresh, isSendingMessage]
136148
)
137149

138150
// Group chats by day
@@ -412,7 +424,11 @@ export function Panel() {
412424
<div
413425
key={chat.id}
414426
onClick={() => {
415-
selectChat(chat)
427+
// Only call selectChat if it's a different chat
428+
// This prevents aborting streams when clicking the currently active chat
429+
if (currentChat?.id !== chat.id) {
430+
selectChat(chat)
431+
}
416432
setIsHistoryDropdownOpen(false)
417433
}}
418434
className={`group mx-1 flex h-8 cursor-pointer items-center rounded-lg px-2 py-1.5 text-left transition-colors ${

apps/sim/stores/copilot/store.ts

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,13 +1597,30 @@ export const useCopilotStore = create<CopilotStore>()(
15971597
(chat: CopilotChat) => chat.id === currentChat.id
15981598
)
15991599
if (updatedCurrentChat) {
1600-
set({
1601-
currentChat: updatedCurrentChat,
1602-
messages: ensureToolCallDisplayNames(updatedCurrentChat.messages || []),
1603-
})
1604-
logger.info(
1605-
`Preserved current chat selection: ${updatedCurrentChat.title || 'Untitled'} (${updatedCurrentChat.messages?.length || 0} messages)`
1606-
)
1600+
const { isSendingMessage } = get()
1601+
1602+
// If we're currently streaming, preserve the current messages state
1603+
// to avoid overwriting streaming content with stale database state
1604+
if (isSendingMessage) {
1605+
set({
1606+
currentChat: {
1607+
...updatedCurrentChat,
1608+
messages: get().messages, // Preserve current streaming messages
1609+
},
1610+
})
1611+
logger.info(
1612+
`Preserved current chat and streaming messages during active stream: ${updatedCurrentChat.title || 'Untitled'}`
1613+
)
1614+
} else {
1615+
// Safe to update messages when not streaming
1616+
set({
1617+
currentChat: updatedCurrentChat,
1618+
messages: ensureToolCallDisplayNames(updatedCurrentChat.messages || []),
1619+
})
1620+
logger.info(
1621+
`Updated current chat with latest database state: ${updatedCurrentChat.title || 'Untitled'} (${updatedCurrentChat.messages?.length || 0} messages)`
1622+
)
1623+
}
16071624

16081625
// Load checkpoints for the preserved chat
16091626
try {
@@ -1614,22 +1631,31 @@ export const useCopilotStore = create<CopilotStore>()(
16141631
}
16151632
} else {
16161633
// Only auto-select most recent chat if no current chat or current chat is stale
1617-
const mostRecentChat = data.chats[0]
1618-
set({
1619-
currentChat: mostRecentChat,
1620-
messages: ensureToolCallDisplayNames(mostRecentChat.messages || []),
1621-
})
1622-
logger.info(
1623-
`Auto-selected most recent chat for workflow ${workflowId}: ${mostRecentChat.title || 'Untitled'}`
1624-
)
1634+
// But don't auto-select during streaming to avoid disrupting the conversation
1635+
const { isSendingMessage } = get()
16251636

1626-
// Load checkpoints for the auto-selected chat
1627-
try {
1628-
await get().loadMessageCheckpoints(mostRecentChat.id)
1629-
} catch (checkpointError) {
1630-
logger.error(
1631-
'Failed to load checkpoints for auto-selected chat:',
1632-
checkpointError
1637+
if (!isSendingMessage) {
1638+
const mostRecentChat = data.chats[0]
1639+
set({
1640+
currentChat: mostRecentChat,
1641+
messages: ensureToolCallDisplayNames(mostRecentChat.messages || []),
1642+
})
1643+
logger.info(
1644+
`Auto-selected most recent chat for workflow ${workflowId}: ${mostRecentChat.title || 'Untitled'}`
1645+
)
1646+
1647+
// Load checkpoints for the auto-selected chat
1648+
try {
1649+
await get().loadMessageCheckpoints(mostRecentChat.id)
1650+
} catch (checkpointError) {
1651+
logger.error(
1652+
'Failed to load checkpoints for auto-selected chat:',
1653+
checkpointError
1654+
)
1655+
}
1656+
} else {
1657+
logger.info(
1658+
`Skipped auto-selecting chat during active stream for workflow ${workflowId}`
16331659
)
16341660
}
16351661
}

0 commit comments

Comments
 (0)