fix: deduplicate idle sessions and refresh session data on transitions
Multiple claude processes in the same CWD share one sessionFile via findActiveJsonl, causing duplicate idle entries. Now deduplicates by project+sessionFile key. Also refreshes session data on busy→idle transitions so the parser fix takes effect immediately. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -267,14 +267,17 @@ export interface IdleSessionInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getIdleSessions(projects: Project[]): IdleSessionInfo[] {
|
export function getIdleSessions(projects: Project[]): IdleSessionInfo[] {
|
||||||
const idle: IdleSessionInfo[] = []
|
// Deduplicate by project+sessionFile — multiple processes in same CWD share one sessionFile
|
||||||
|
const seen = new Map<string, IdleSessionInfo>()
|
||||||
for (const project of projects) {
|
for (const project of projects) {
|
||||||
const sessions = sessionsByPath.get(project.path)
|
const sessions = sessionsByPath.get(project.path)
|
||||||
if (!sessions) continue
|
if (!sessions) continue
|
||||||
for (const s of sessions) {
|
for (const s of sessions) {
|
||||||
if (s.busy) continue
|
if (s.busy) continue
|
||||||
if (!s.lastActivityMs) continue
|
if (!s.lastActivityMs) continue
|
||||||
// Find matching session info for title/prompt
|
const dedupeKey = `${project.path}:${s.sessionFile || s.pid}`
|
||||||
|
const existing = seen.get(dedupeKey)
|
||||||
|
if (existing && existing.idleSinceMs >= s.lastActivityMs) continue
|
||||||
let title = ""
|
let title = ""
|
||||||
let lastPrompt = ""
|
let lastPrompt = ""
|
||||||
let lastResponse = ""
|
let lastResponse = ""
|
||||||
@@ -288,7 +291,7 @@ export function getIdleSessions(projects: Project[]): IdleSessionInfo[] {
|
|||||||
lastResponse = match.lastAssistantMsg
|
lastResponse = match.lastAssistantMsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
idle.push({
|
seen.set(dedupeKey, {
|
||||||
projectPath: project.path,
|
projectPath: project.path,
|
||||||
projectName: project.name,
|
projectName: project.name,
|
||||||
tty: s.tty,
|
tty: s.tty,
|
||||||
@@ -299,6 +302,7 @@ export function getIdleSessions(projects: Project[]): IdleSessionInfo[] {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const idle = Array.from(seen.values())
|
||||||
idle.sort((a, b) => b.idleSinceMs - a.idleSinceMs)
|
idle.sort((a, b) => b.idleSinceMs - a.idleSinceMs)
|
||||||
return idle
|
return idle
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -812,14 +812,14 @@ async function main() {
|
|||||||
} else {
|
} else {
|
||||||
const sessions = await detectActiveSessions()
|
const sessions = await detectActiveSessions()
|
||||||
const changed = updateProjectSessions(projects, sessions)
|
const changed = updateProjectSessions(projects, sessions)
|
||||||
// Eagerly load session data for active projects (needed for idle panel)
|
const transitioned = checkTransitions(projects, prevBusySnapshot)
|
||||||
|
// Eagerly load/refresh session data for active projects (needed for idle panel)
|
||||||
for (const p of projects) {
|
for (const p of projects) {
|
||||||
if (p.activeSessions > 0 && !p.sessions) {
|
if (p.activeSessions > 0 && (!p.sessions || transitioned.length > 0)) {
|
||||||
p.sessions = await loadSessions(p.path)
|
p.sessions = await loadSessions(p.path)
|
||||||
p.sessionCount = p.sessions.length
|
p.sessionCount = p.sessions.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const transitioned = checkTransitions(projects, prevBusySnapshot)
|
|
||||||
prevBusySnapshot = snapshotBusy(projects)
|
prevBusySnapshot = snapshotBusy(projects)
|
||||||
if (transitioned.length > 0) {
|
if (transitioned.length > 0) {
|
||||||
playDoneSound()
|
playDoneSound()
|
||||||
|
|||||||
Reference in New Issue
Block a user