diff --git a/server/modules/projects/services/project-management.service.ts b/server/modules/projects/services/project-management.service.ts index 674418cc..913c2fa3 100644 --- a/server/modules/projects/services/project-management.service.ts +++ b/server/modules/projects/services/project-management.service.ts @@ -30,10 +30,6 @@ type ProjectApiView = { isArchived: boolean; isStarred: boolean; sessions: []; - cursorSessions: []; - codexSessions: []; - geminiSessions: []; - opencodeSessions: []; sessionMeta: { hasMore: false; total: 0; @@ -82,10 +78,6 @@ function mapProjectRowToApiView(projectRow: ProjectRepositoryRow): ProjectApiVie isArchived: Boolean(projectRow.isArchived), isStarred: Boolean(projectRow.isStarred), sessions: [], - cursorSessions: [], - codexSessions: [], - geminiSessions: [], - opencodeSessions: [], sessionMeta: { hasMore: false, total: 0, diff --git a/server/modules/projects/services/projects-with-sessions-fetch.service.ts b/server/modules/projects/services/projects-with-sessions-fetch.service.ts index 81d66ddf..296ec594 100644 --- a/server/modules/projects/services/projects-with-sessions-fetch.service.ts +++ b/server/modules/projects/services/projects-with-sessions-fetch.service.ts @@ -9,13 +9,12 @@ import { AppError } from '@/shared/utils.js'; type SessionSummary = { id: string; + provider: string; summary: string; messageCount: number; lastActivity: string; }; -type SessionsByProvider = Record<'claude' | 'cursor' | 'codex' | 'gemini' | 'opencode', SessionSummary[]>; - type SessionRepositoryRow = { provider: string; session_id: string; @@ -31,10 +30,6 @@ export type ProjectListItem = { fullPath: string; isStarred: boolean; sessions: SessionSummary[]; - cursorSessions: SessionSummary[]; - codexSessions: SessionSummary[]; - geminiSessions: SessionSummary[]; - opencodeSessions: SessionSummary[]; sessionMeta: { hasMore: boolean; total: number; @@ -64,7 +59,7 @@ type SessionPaginationOptions = { }; type ProjectSessionsPageResult = { - sessionsByProvider: SessionsByProvider; + sessions: SessionSummary[]; total: number; hasMore: boolean; }; @@ -72,10 +67,6 @@ type ProjectSessionsPageResult = { export type ProjectSessionsPageApiView = { projectId: string; sessions: SessionSummary[]; - cursorSessions: SessionSummary[]; - codexSessions: SessionSummary[]; - geminiSessions: SessionSummary[]; - opencodeSessions: SessionSummary[]; sessionMeta: { hasMore: boolean; total: number; @@ -129,39 +120,18 @@ function normalizeSessionPagination(options: SessionPaginationOptions = {}): { l function mapSessionRowToSummary(row: SessionRepositoryRow): SessionSummary { return { id: row.session_id, + provider: row.provider, summary: row.custom_name || '', messageCount: 0, lastActivity: row.updated_at ?? row.created_at ?? new Date().toISOString(), }; } -function bucketSessionRowsByProvider(rows: SessionRepositoryRow[]): SessionsByProvider { - const byProvider: SessionsByProvider = { - claude: [], - cursor: [], - codex: [], - gemini: [], - opencode: [], - }; - - for (const row of rows) { - const provider = row.provider as keyof SessionsByProvider; - const bucket = byProvider[provider]; - if (!bucket) { - continue; - } - - bucket.push(mapSessionRowToSummary(row)); - } - - return byProvider; -} - function readProjectSessionsIncludingArchived(projectPath: string): ProjectSessionsPageResult { const rows = sessionsDb.getSessionsByProjectPathIncludingArchived(projectPath) as SessionRepositoryRow[]; return { - sessionsByProvider: bucketSessionRowsByProvider(rows), + sessions: rows.map(mapSessionRowToSummary), total: rows.length, hasMore: false, }; @@ -183,7 +153,7 @@ function readProjectSessionsPageByPath( const total = sessionsDb.countSessionsByProjectPath(projectPath); return { - sessionsByProvider: bucketSessionRowsByProvider(rows), + sessions: rows.map(mapSessionRowToSummary), total, hasMore: pagination.offset + rows.length < total, }; @@ -205,7 +175,7 @@ function broadcastProgress(progress: ProgressUpdate) { } /** - * Reads all projects from DB and returns provider-bucketed session summaries. + * Reads all projects from DB and returns normalized session summaries. */ export async function getProjectsWithSessions( options: GetProjectsWithSessionsOptions = {} @@ -253,11 +223,7 @@ export async function getProjectsWithSessions( displayName, fullPath: projectPath, isStarred: Boolean(row.isStarred), - sessions: sessionsPage.sessionsByProvider.claude, - cursorSessions: sessionsPage.sessionsByProvider.cursor, - codexSessions: sessionsPage.sessionsByProvider.codex, - geminiSessions: sessionsPage.sessionsByProvider.gemini, - opencodeSessions: sessionsPage.sessionsByProvider.opencode, + sessions: sessionsPage.sessions, sessionMeta: { hasMore: sessionsPage.hasMore, total: sessionsPage.total, @@ -310,11 +276,7 @@ export async function getArchivedProjectsWithSessions( fullPath: row.project_path, isStarred: Boolean(row.isStarred), isArchived: true, - sessions: sessionsPage.sessionsByProvider.claude, - cursorSessions: sessionsPage.sessionsByProvider.cursor, - codexSessions: sessionsPage.sessionsByProvider.codex, - geminiSessions: sessionsPage.sessionsByProvider.gemini, - opencodeSessions: sessionsPage.sessionsByProvider.opencode, + sessions: sessionsPage.sessions, sessionMeta: { hasMore: sessionsPage.hasMore, total: sessionsPage.total, @@ -343,11 +305,7 @@ export async function getProjectSessionsPage( const sessionsPage = readProjectSessionsPageByPath(projectRow.project_path, options); return { projectId: projectRow.project_id, - sessions: sessionsPage.sessionsByProvider.claude, - cursorSessions: sessionsPage.sessionsByProvider.cursor, - codexSessions: sessionsPage.sessionsByProvider.codex, - geminiSessions: sessionsPage.sessionsByProvider.gemini, - opencodeSessions: sessionsPage.sessionsByProvider.opencode, + sessions: sessionsPage.sessions, sessionMeta: { hasMore: sessionsPage.hasMore, total: sessionsPage.total, diff --git a/src/components/command-palette/sources/useSessionsSource.ts b/src/components/command-palette/sources/useSessionsSource.ts index 3623c798..ec045b26 100644 --- a/src/components/command-palette/sources/useSessionsSource.ts +++ b/src/components/command-palette/sources/useSessionsSource.ts @@ -11,10 +11,6 @@ export type SessionResult = { interface SessionsResponse { sessions?: ProjectSession[]; - cursorSessions?: ProjectSession[]; - codexSessions?: ProjectSession[]; - geminiSessions?: ProjectSession[]; - opencodeSessions?: ProjectSession[]; } export function useSessionsSource(projectId: string | undefined, enabled: boolean) { @@ -29,17 +25,10 @@ export function useSessionsSource(projectId: string | undefined, enabled: boolea ); }, parse: (data) => { - const all: ProjectSession[] = [ - ...(data.sessions ?? []), - ...(data.cursorSessions ?? []), - ...(data.codexSessions ?? []), - ...(data.geminiSessions ?? []), - ...(data.opencodeSessions ?? []), - ]; - return all.map((s) => ({ + return (data.sessions ?? []).map((s) => ({ id: s.id, label: (s.title || s.summary || s.name || s.id) as string, - provider: s.__provider, + provider: (s.__provider || s.provider) as LLMProvider | undefined, })); }, }); diff --git a/src/components/sidebar/hooks/useSidebarController.ts b/src/components/sidebar/hooks/useSidebarController.ts index a7d539e0..4d907a8b 100644 --- a/src/components/sidebar/hooks/useSidebarController.ts +++ b/src/components/sidebar/hooks/useSidebarController.ts @@ -594,16 +594,7 @@ export function useSidebarController({ return sortedProjects.reduce((acc, project) => { const sessions = (project.sessions ?? []).filter((session) => activeSessionIds.has(String(session.id))); - const cursorSessions = (project.cursorSessions ?? []).filter((session) => activeSessionIds.has(String(session.id))); - const codexSessions = (project.codexSessions ?? []).filter((session) => activeSessionIds.has(String(session.id))); - const geminiSessions = (project.geminiSessions ?? []).filter((session) => activeSessionIds.has(String(session.id))); - const opencodeSessions = (project.opencodeSessions ?? []).filter((session) => activeSessionIds.has(String(session.id))); - const runningCount = - sessions.length - + cursorSessions.length - + codexSessions.length - + geminiSessions.length - + opencodeSessions.length; + const runningCount = sessions.length; if (runningCount === 0) { return acc; @@ -612,10 +603,6 @@ export function useSidebarController({ acc.push({ ...project, sessions, - cursorSessions, - codexSessions, - geminiSessions, - opencodeSessions, sessionMeta: { ...project.sessionMeta, total: runningCount, diff --git a/src/components/sidebar/types/types.ts b/src/components/sidebar/types/types.ts index 3e049b3d..672fdd34 100644 --- a/src/components/sidebar/types/types.ts +++ b/src/components/sidebar/types/types.ts @@ -61,10 +61,6 @@ export type SidebarProps = { }; export type SessionViewModel = { - isCursorSession: boolean; - isCodexSession: boolean; - isGeminiSession: boolean; - isOpenCodeSession: boolean; isActive: boolean; sessionName: string; sessionTime: string; diff --git a/src/components/sidebar/utils/utils.ts b/src/components/sidebar/utils/utils.ts index 57e28b1d..23010915 100644 --- a/src/components/sidebar/utils/utils.ts +++ b/src/components/sidebar/utils/utils.ts @@ -1,6 +1,6 @@ import type { TFunction } from 'i18next'; -import type { Project } from '../../../types/app'; +import type { LLMProvider, Project, ProjectSession } from '../../../types/app'; import type { ProjectSortOrder, SettingsProject, SessionViewModel, SessionWithProvider } from '../types/types'; export const readProjectSortOrder = (): ProjectSortOrder => { @@ -61,6 +61,13 @@ const getUpdatedTimestamp = (session: SessionWithProvider): string => { return String(session.lastActivity || ''); }; +const getSessionProvider = (session: ProjectSession): LLMProvider => { + const provider = session.__provider ?? session.provider; + return typeof provider === 'string' && provider.trim() + ? provider as LLMProvider + : 'claude'; +}; + export const getSessionDate = (session: SessionWithProvider): Date => { return new Date(getUpdatedTimestamp(session) || getCreatedTimestamp(session) || 0); }; @@ -82,10 +89,6 @@ export const createSessionViewModel = ( const diffInMinutes = Math.floor((currentTime.getTime() - sessionDate.getTime()) / (1000 * 60)); return { - isCursorSession: session.__provider === 'cursor', - isCodexSession: session.__provider === 'codex', - isGeminiSession: session.__provider === 'gemini', - isOpenCodeSession: session.__provider === 'opencode', isActive: diffInMinutes < 10, sessionName: getSessionName(session, t), sessionTime: getSessionTime(session), @@ -94,32 +97,10 @@ export const createSessionViewModel = ( }; export const getAllSessions = (project: Project): SessionWithProvider[] => { - const claudeSessions = [...(project.sessions || [])].map((session) => ({ + return (project.sessions || []).map((session) => ({ ...session, - __provider: 'claude' as const, - })); - - const cursorSessions = (project.cursorSessions || []).map((session) => ({ - ...session, - __provider: 'cursor' as const, - })); - - const codexSessions = (project.codexSessions || []).map((session) => ({ - ...session, - __provider: 'codex' as const, - })); - - const geminiSessions = (project.geminiSessions || []).map((session) => ({ - ...session, - __provider: 'gemini' as const, - })); - - const opencodeSessions = (project.opencodeSessions || []).map((session) => ({ - ...session, - __provider: 'opencode' as const, - })); - - return [...claudeSessions, ...cursorSessions, ...codexSessions, ...geminiSessions, ...opencodeSessions].sort( + __provider: getSessionProvider(session), + })).sort( (a, b) => getSessionDate(b).getTime() - getSessionDate(a).getTime(), ); }; diff --git a/src/components/sidebar/view/subcomponents/SidebarSessionItem.tsx b/src/components/sidebar/view/subcomponents/SidebarSessionItem.tsx index faeb76fe..c55d8ed3 100644 --- a/src/components/sidebar/view/subcomponents/SidebarSessionItem.tsx +++ b/src/components/sidebar/view/subcomponents/SidebarSessionItem.tsx @@ -179,7 +179,7 @@ export default function SidebarSessionItem({ - {!isProcessing && !sessionView.isCursorSession && ( + {!isProcessing && ( - {!isProcessing && !sessionView.isCursorSession && ( + {!isProcessing && (