({
currentSessionId,
onSelectSession,
projectPath,
workingDirectory,
isCurrentSessionThinking = false,
onQuickCreateRef,
}: SessionManagerProps)
| 99 | } |
| 100 | |
| 101 | export function SessionManager({ |
| 102 | currentSessionId, |
| 103 | onSelectSession, |
| 104 | projectPath, |
| 105 | workingDirectory, |
| 106 | isCurrentSessionThinking = false, |
| 107 | onQuickCreateRef, |
| 108 | }: SessionManagerProps) { |
| 109 | const shortcuts = useKeyboardShortcutsConfig(); |
| 110 | const queryClient = useQueryClient(); |
| 111 | const [activeTab, setActiveTab] = useState<'active' | 'archived'>('active'); |
| 112 | const [editingSessionId, setEditingSessionId] = useState<string | null>(null); |
| 113 | const [editingName, setEditingName] = useState(''); |
| 114 | const [isCreating, setIsCreating] = useState(false); |
| 115 | const [newSessionName, setNewSessionName] = useState(''); |
| 116 | const [runningSessions, setRunningSessions] = useState<Set<string>>(new Set()); |
| 117 | const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); |
| 118 | const [sessionToDelete, setSessionToDelete] = useState<SessionListItem | null>(null); |
| 119 | const [isDeleteAllArchivedDialogOpen, setIsDeleteAllArchivedDialogOpen] = useState(false); |
| 120 | |
| 121 | // Use React Query for sessions list - always include archived, filter client-side |
| 122 | const { data: sessions = [], refetch: refetchSessions } = useSessions(true); |
| 123 | |
| 124 | // Ref to track if we've done the initial running sessions check |
| 125 | const hasCheckedInitialRef = useRef(false); |
| 126 | |
| 127 | // Check running state for all sessions |
| 128 | const checkRunningSessions = useCallback(async (sessionList: SessionListItem[]) => { |
| 129 | const api = getElectronAPI(); |
| 130 | if (!api?.agent) return; |
| 131 | |
| 132 | const runningIds = new Set<string>(); |
| 133 | |
| 134 | // Check each session's running state |
| 135 | for (const session of sessionList) { |
| 136 | try { |
| 137 | const result = await api.agent.getHistory(session.id); |
| 138 | if (result.success && result.isRunning) { |
| 139 | runningIds.add(session.id); |
| 140 | } |
| 141 | } catch (err) { |
| 142 | // Ignore errors for individual session checks |
| 143 | logger.warn(`Failed to check running state for ${session.id}:`, err); |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | setRunningSessions(runningIds); |
| 148 | }, []); |
| 149 | |
| 150 | // Helper to invalidate sessions cache and refetch |
| 151 | const invalidateSessions = useCallback(async () => { |
| 152 | await queryClient.invalidateQueries({ queryKey: queryKeys.sessions.all(true) }); |
| 153 | // Also check running state after invalidation |
| 154 | const result = await refetchSessions(); |
| 155 | if (result.data) { |
| 156 | await checkRunningSessions(result.data); |
| 157 | } |
| 158 | return result; |
nothing calls this directly
no test coverage detected