Skip to content

Commit 97445f9

Browse files
committed
Route queued messages back to the originating session
sendMessage always read the active session id from the store, so a queued message (or a deferred /compact) fired from a `result` event would land on whichever session the user was viewing at fire time, not the one that produced the event. Switching sessions mid-turn caused the queued message to be sent to the wrong conversation. sendMessage now accepts an optional targetSessionId; the three event-driven call sites (queued message after result, immediate auto-compact, deferred auto-compact) pass the originating sid explicitly. The user-typed path keeps reading activeSessionId.
1 parent 5811047 commit 97445f9

2 files changed

Lines changed: 15 additions & 12 deletions

File tree

src/renderer/src/components/Chat.tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export default function Chat({
7676
const [searchQuery, setSearchQuery] = useState('')
7777
const [activeMatchIndex, setActiveMatchIndex] = useState(0)
7878
const dragCounterRef = useRef(0)
79-
const sendMessageRef = useRef<((text: string, images?: ImageAttachment[], files?: FileAttachment[]) => Promise<void>) | null>(null)
79+
const sendMessageRef = useRef<((text: string, images?: ImageAttachment[], files?: FileAttachment[], targetSessionId?: string) => Promise<void>) | null>(null)
8080
// After 401, holds the prompt to re-send once /login succeeds, keyed by session id
8181
const pendingAuthRetryRef = useRef<Map<string, { text: string; images?: ImageAttachment[]; files?: FileAttachment[] }>>(new Map())
8282
// Extended thinking state: tracks when Claude is actively reasoning
@@ -409,7 +409,7 @@ export default function Chat({
409409
} else {
410410
useSessionsStore.getState().setAutoCompacted(sid, true)
411411
addMessage(sid, { id: Date.now().toString(), role: 'assistant', text: 'Context approaching limit — auto-compacting…' })
412-
setTimeout(() => sendMessageRef.current?.('/compact'), 150)
412+
setTimeout(() => sendMessageRef.current?.('/compact', undefined, undefined, sid), 150)
413413
}
414414
}
415415
}
@@ -591,7 +591,7 @@ export default function Chat({
591591
// Auto-send queued message
592592
const queued = useSessionsStore.getState().clearQueuedMessage(sid)
593593
if (queued && !event.is_error && sendMessageRef.current) {
594-
setTimeout(() => sendMessageRef.current?.(queued.text, queued.images, queued.files), 100)
594+
setTimeout(() => sendMessageRef.current?.(queued.text, queued.images, queued.files, sid), 100)
595595
}
596596

597597
// Deferred auto-compaction (was busy when threshold was hit)
@@ -600,7 +600,7 @@ export default function Chat({
600600
useSessionsStore.getState().setPendingAutoCompact(sid, false)
601601
useSessionsStore.getState().setAutoCompacted(sid, true)
602602
addMessage(sid, { id: Date.now().toString(), role: 'assistant', text: 'Context approaching limit — auto-compacting…' })
603-
setTimeout(() => sendMessageRef.current?.('/compact'), 150)
603+
setTimeout(() => sendMessageRef.current?.('/compact', undefined, undefined, sid), 150)
604604
}
605605
}
606606

@@ -738,10 +738,13 @@ export default function Chat({
738738
handlePermissionRespond(true)
739739
}, [permissionQueue, activeSessionId, updateSettings, handlePermissionRespond])
740740

741-
const sendMessage = useCallback(async (text: string, images?: ImageAttachment[], files?: FileAttachment[]): Promise<void> => {
742-
const currentActiveId = useSessionsStore.getState().activeSessionId
741+
const sendMessage = useCallback(async (text: string, images?: ImageAttachment[], files?: FileAttachment[], targetSessionId?: string): Promise<void> => {
742+
// Background events (queued message after result, deferred auto-compact) pass
743+
// targetSessionId so they route to the session that produced the event, not
744+
// whichever session the user is currently viewing.
745+
const routedSid = targetSessionId ?? useSessionsStore.getState().activeSessionId
743746
const hasAttachments = (images?.length ?? 0) > 0 || (files?.length ?? 0) > 0
744-
if ((!text.trim() && !hasAttachments) || (currentActiveId && loadingSessions.has(currentActiveId))) return
747+
if ((!text.trim() && !hasAttachments) || (routedSid && loadingSessions.has(routedSid))) return
745748

746749
let prompt = text.trim()
747750

@@ -752,9 +755,7 @@ export default function Chat({
752755
const slashName = prompt.slice(1).split(/\s/)[0]
753756
const builtInNames = new Set(BUILT_IN_COMMANDS.map((c) => c.name.slice(1).split(/\s/)[0]))
754757
if (!builtInNames.has(slashName)) {
755-
const session = useSessionsStore.getState().sessions.find(
756-
(s) => s.id === useSessionsStore.getState().activeSessionId
757-
)
758+
const session = useSessionsStore.getState().sessions.find((s) => s.id === routedSid)
758759
const skillCwd = session?.cwd ?? localStorage.getItem('cwd') ?? defaultCwd
759760
try {
760761
const skills = await window.api.skills.list(skillCwd)
@@ -770,7 +771,7 @@ export default function Chat({
770771

771772
pendingToolsRef.current.clear()
772773

773-
let sid = useSessionsStore.getState().activeSessionId
774+
let sid = routedSid
774775
if (!sid) {
775776
sid = useSessionsStore.getState().createSession(localStorage.getItem('cwd') ?? defaultCwd)
776777
}

src/renderer/src/data/releaseNotes.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ export const RELEASE_NOTES: ReleaseNote[] = [
88
{
99
version: 'next',
1010
date: '',
11-
notes: []
11+
notes: [
12+
'Fix: queued messages now stay with their original session if you switch sessions before the previous turn finishes'
13+
]
1214
},
1315
{
1416
version: '0.27.0',

0 commit comments

Comments
 (0)